package mobi.acpm.inspeckage.webserver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Environment;
import android.security.KeyPairGeneratorSpec;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;
import android.text.Html;
import android.util.Log;
import org.java_websocket.util.Base64;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.net.ssl.KeyManagerFactory;
import javax.security.auth.x500.X500Principal;
import fi.iki.elonen.NanoHTTPD;
import mobi.acpm.inspeckage.Module;
import mobi.acpm.inspeckage.hooks.CryptoHook;
import mobi.acpm.inspeckage.hooks.FileSystemHook;
import mobi.acpm.inspeckage.hooks.HashHook;
import mobi.acpm.inspeckage.hooks.HttpHook;
import mobi.acpm.inspeckage.hooks.IPCHook;
import mobi.acpm.inspeckage.hooks.MiscHook;
import mobi.acpm.inspeckage.hooks.SQLiteHook;
import mobi.acpm.inspeckage.hooks.SerializationHook;
import mobi.acpm.inspeckage.hooks.SharedPrefsHook;
import mobi.acpm.inspeckage.hooks.UserHooks;
import mobi.acpm.inspeckage.hooks.WebViewHook;
import mobi.acpm.inspeckage.log.LogService;
import mobi.acpm.inspeckage.receivers.InspeckageWebReceiver;
import mobi.acpm.inspeckage.util.Config;
import mobi.acpm.inspeckage.util.FileUtil;
import mobi.acpm.inspeckage.util.PackageDetail;
import mobi.acpm.inspeckage.util.Util;
import static mobi.acpm.inspeckage.util.FileType.APP_STRUCT;
import static mobi.acpm.inspeckage.util.FileType.CRYPTO;
import static mobi.acpm.inspeckage.util.FileType.FILESYSTEM;
import static mobi.acpm.inspeckage.util.FileType.HASH;
import static mobi.acpm.inspeckage.util.FileType.HTTP;
import static mobi.acpm.inspeckage.util.FileType.IPC;
import static mobi.acpm.inspeckage.util.FileType.MISC;
import static mobi.acpm.inspeckage.util.FileType.PREFS;
import static mobi.acpm.inspeckage.util.FileType.SERIALIZATION;
import static mobi.acpm.inspeckage.util.FileType.SQLITE;
import static mobi.acpm.inspeckage.util.FileType.USERHOOKS;
import static mobi.acpm.inspeckage.util.FileType.WEBVIEW;
/**
* Created by acpm on 16/11/15.
*/
public class WebServer extends fi.iki.elonen.NanoHTTPD {
private Context mContext;
private SharedPreferences mPrefs;
private KeyStore keyStore;
public WebServer(String host, int port, Context context) throws IOException {
super(host,port);
mContext = context;
mPrefs = mContext.getSharedPreferences(Module.PREFS, mContext.MODE_WORLD_READABLE);
SharedPreferences.Editor editor = mPrefs.edit();
editor.putBoolean("fake_board_key",true);
editor.putBoolean("fake_bootloader_key",false);
editor.putBoolean("fake_brand_key",false);
editor.putBoolean("fake_cpu_abi_key",false);
editor.putBoolean("fake_cpu_abi2_key",false);
editor.putBoolean("fake_device_key",false);
editor.putBoolean("fake_display_key",false);
editor.putBoolean("fake_fingerprint_key",false);
editor.putBoolean("fake_hardware_key",false);
editor.putBoolean("fake_host_key",false);
editor.putBoolean("fake_id_key",false);
editor.putBoolean("fake_manufacturer_key",false);
editor.putBoolean("fake_model_key",false);
editor.putBoolean("fake_product_key",false);
editor.putBoolean("fake_radio_key",false);
editor.putBoolean("fake_tags_key",false);
editor.putBoolean("fake_time_key",false);
editor.putBoolean("fake_type_key",false);
editor.putBoolean("fake_user_key",false);
editor.putBoolean("fake_codename_key",false);
editor.putBoolean("fake_incremental_key",false);
editor.putBoolean("fake_release_key",false);
editor.putBoolean("fake_sdk_key",false);
editor.putBoolean("fake_sdk_int_key",false);
editor.apply();
try {
keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
Enumeration<String> aliases = keyStore.aliases();
List<String> keyAliases = new ArrayList<>();
while (aliases.hasMoreElements()) {
keyAliases.add(aliases.nextElement());
}
//use uuid as an alias, that way each installation has your own alias
if(mPrefs.getString(Config.KEYPAIR_ALIAS,"").equals("")) {
SharedPreferences.Editor edit = mPrefs.edit();
edit.putString(Config.KEYPAIR_ALIAS, UUID.randomUUID().toString());
edit.apply();
}
String alias = mPrefs.getString(Config.KEYPAIR_ALIAS,"");
boolean genNewKey = true;
for (String key : keyAliases) {
if(key.equals(alias)){
genNewKey = false;
}
}
if(genNewKey) {
KeyPair keyPair = generateKeys(alias);
keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
}
}
catch(Exception e) {
Log.e("Error",e.getMessage());
}
if(mPrefs.getBoolean(Config.SP_SWITCH_AUTH, false)) {
KeyManagerFactory keyManagerFactory = null;
try {
keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());//
keyManagerFactory.init(keyStore, "".toCharArray());
} catch (NoSuchAlgorithmException | UnrecoverableKeyException | KeyStoreException e) {
e.printStackTrace();
}
makeSecure(NanoHTTPD.makeSSLSocketFactory(keyStore, keyManagerFactory), null);
}
mContext.registerReceiver(new InspeckageWebReceiver(mContext), new IntentFilter("mobi.acpm.inspeckage.INSPECKAGE_WEB"));
start(10000);
}
public KeyPair generateKeys(String alias) {
KeyPair keyPair = null;
try {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA","AndroidKeyStore");
Calendar start = Calendar.getInstance();
Calendar end = Calendar.getInstance();
end.add(Calendar.YEAR, 1);
if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.M) {
KeyGenParameterSpec spec= new KeyGenParameterSpec.Builder(
alias,
KeyProperties.PURPOSE_SIGN|KeyProperties.PURPOSE_VERIFY)
.setCertificateSubject(new X500Principal("CN=Inspeckage, OU=ACPM, O=ACPM, C=BR"))
.setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
.setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1)
.setCertificateNotBefore(start.getTime())
.setCertificateNotAfter(end.getTime())
.setKeyValidityStart(start.getTime())
.setKeyValidityEnd(end.getTime())
.setKeySize(2048)
.setCertificateSerialNumber(BigInteger.valueOf(1))
.build();
keyGen.initialize(spec);
}else {
KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(mContext)
.setAlias(alias)
.setSubject(new X500Principal("CN=Inspeckage, OU=ACPM, O=ACPM, C=BR"))
.setSerialNumber(BigInteger.valueOf(12345))
.setStartDate(start.getTime())
.setEndDate(end.getTime())
.build();
keyGen.initialize(spec);
}
keyPair = keyGen.generateKeyPair();
} catch(GeneralSecurityException e) {
Log.d("Inspeckage_Exception: ",e.getMessage());
}
return keyPair;
}
private Response ok(String type, String html) {
return newFixedLengthResponse(Response.Status.OK, type, html);
}
private Response ok(String html) {
return newFixedLengthResponse(Response.Status.OK, NanoHTTPD.MIME_HTML, html);
}
@Override
public Response serve(IHTTPSession session) {
String uri = session.getUri();
if(mPrefs.getBoolean(Config.SP_SWITCH_AUTH, false)) {
Map<String, String> headers = session.getHeaders();
String authorization = headers.get("authorization");
String base64 = "";
if (authorization != null) {
base64 = authorization.substring(6);
}
boolean logged = false;
if (base64.equals(Base64.encodeBytes(mPrefs.getString(Config.SP_USER_PASS, "").getBytes()))) {
logged = true;
}
if (!logged) {
Response res = newFixedLengthResponse(Response.Status.UNAUTHORIZED, NanoHTTPD.MIME_HTML, "Denied!");
res.addHeader("WWW-Authenticate", "Basic realm=\"Server\"");
res.addHeader("Content-Length", "0");
return res;
}
}
//add ip and port to proxy fields
if (mPrefs.getString(Config.SP_PROXY_HOST, "").equals("")) {
String ip = session.getHeaders().get("http-client-ip");
if (ip != null && !ip.trim().equals("")) {
SharedPreferences.Editor edit = mPrefs.edit();
edit.putString(Config.SP_PROXY_HOST, ip);
edit.putString(Config.SP_PROXY_PORT, "4443");
edit.apply();
}
}
Map<String, String> parms = session.getParms();
String type = parms.get("type");
String html = new String();
if (uri.equals("/")) {
if (type != null) {
switch (type) {
case "startWS":
return startWS(parms);
case "stopWS":
return stopWS();
case "filetree":
return fileTreeHtml();
case "checkapp":
return checkApp();
case "downloadfile":
return downloadFile(parms);
case "screenshot":
return takeScreenshot();
case "setarp":
return setArp(parms);
case "downapk":
return downloadApk();
case "downall":
return downloadAll();
case "finishapp":
finishApp();
return ok("OK");
case "restartapp":
finishApp();
startApp();
return ok("OK");
case "startapp":
startApp();
return ok("OK");
case "start":
return startComponent(parms);
case "file":
html = fileHtml(parms);
break;
case Config.SP_EXPORTED:
html = spExported(parms);
break;
case "flagsec":
html = flagSecure(parms);
break;
case "proxy":
html = proxy(parms);
break;
case "switchproxy":
html = switchProxy(parms);
break;
case "sslunpinning":
html = sslUnpinning(parms);
break;
case "adduserhooks":
return addUserHooks(parms);
case "addparamreplaces":
return addUserReplaces(parms);
case "addreturnreplaces":
return addUserReturnReplaces(parms);
case "getuserhooks":
return getUserHooks();
case "getparamreplaces":
return getUserReplaces();
case "getreturnreplaces":
return getUserReturnReplaces();
case "getbuild":
return getBuild();
case "addbuild":
return addBuild(parms);
case "deleteLogs":
return clearHooksLog(parms);
case "enableTab":
html = tabsCheckbox(parms);
break;
case "clipboard":
return addToClipboard(parms);
}
} else {
html = setDefaultOptions();
}
} else if (uri.equals("/index.html")) {
html = FileUtil.readHtmlFile(mContext, uri);
} else if (uri.equals("/logcat.html")) {
html = FileUtil.readHtmlFile(mContext, uri);
html = html.replace("#ip_ws#", mPrefs.getString(Config.SP_SERVER_IP, "127.0.0.1"));
html = html.replace("#port_ws#", String.valueOf(mPrefs.getInt(Config.SP_WSOCKET_PORT, 8887)));
return ok(html);
} else if (uri.contains("/content/")) {
html = FileUtil.readHtmlFile(mContext, uri);
} else if (uri.equals("/struct")) {
String json = FileUtil.readFromFile(mPrefs, APP_STRUCT);//readHtmlFile(mContext, uri);
return ok("text/json", json);
} else {
String fname = FileUtil.readHtmlFile(mContext, uri);
if (uri.contains(".css")) {
return ok("text/css", fname);
}
if (uri.contains(".js")) {
return ok("text/javascript", fname);
}
if (uri.contains(".png")) {
try {
InputStream f = mContext.getAssets().open("HTMLFiles" + uri);
return newChunkedResponse(Response.Status.OK, "image/png", f);
//return new Response(Response.Status.OK, "image/png", f, f.available());
} catch (IOException e) {
e.printStackTrace();
}
}
if (uri.contains(".ico")) {
return ok("image/vnd.microsoft.icon", fname);
}
if (uri.contains(".eot")) {
return ok("application/vnd.ms-fontobject", fname);
}
if (uri.contains(".svg")) {
return ok("image/svg+xml", fname);
}
if (uri.contains(".ttf")) {
return ok("application/x-font-ttf", fname);
}
if (uri.contains(".woff")) {
return ok("application/font-woff", fname);
}
if (uri.contains(".woff2")) {
return ok("font/woff2", fname);
}
return ok(fname);
}
if (mPrefs.getBoolean(Config.SP_EXPORTED, false)) {
PackageDetail pd = new PackageDetail(mContext, mPrefs.getString(Config.SP_PACKAGE, ""));
SharedPreferences.Editor edit = mPrefs.edit();
edit.putString(Config.SP_EXP_ACTIVITIES, pd.getExportedActivities());
edit.putString(Config.SP_N_EXP_ACTIVITIES, pd.getNonExportedActivities());
edit.apply();
}
if (!mPrefs.getString(Config.SP_DATA_DIR_TREE, "").equals("")) {
html = html.replace("#filetree#", mPrefs.getString(Config.SP_DATA_DIR_TREE, ""));
}
String moduleEnable = "true";
if (!isModuleEnabled()) {
moduleEnable = "<font style=\"color:red; background:yellow;\">false</font>";
}
html = html.replace("#moduleEnable#", moduleEnable);
html = replaceHtmlVariables(html);
//Inspeckage version
PackageInfo pInfo;
try {
pInfo = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0);
String version = pInfo.versionName;
html = html.replace("#inspeckageVersion#", version);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return ok(html);
}
private String setDefaultOptions() {
SharedPreferences.Editor edit = mPrefs.edit();
edit.putBoolean(Config.SP_APP_IS_RUNNING, false);
edit.putString(Config.SP_DATA_DIR_TREE, "");
edit.apply();
isRunning();
fileTree();
return FileUtil.readHtmlFile(mContext, "/index.html");
}
private String tabsCheckbox(Map<String, String> parms) {
String tab = parms.get("tab");
if (tab != null) {
String state = parms.get("value");
SharedPreferences.Editor edit = mPrefs.edit();
switch (tab){
case "shared":
edit.putBoolean(Config.SP_TAB_ENABLE_SHAREDP, Boolean.valueOf(state));
break;
case "serialization":
edit.putBoolean(Config.SP_TAB_ENABLE_SERIALIZATION, Boolean.valueOf(state));
break;
case "crypto":
edit.putBoolean(Config.SP_TAB_ENABLE_CRYPTO, Boolean.valueOf(state));
break;
case "hash":
edit.putBoolean(Config.SP_TAB_ENABLE_HASH, Boolean.valueOf(state));
break;
case "sqlite":
edit.putBoolean(Config.SP_TAB_ENABLE_SQLITE, Boolean.valueOf(state));
break;
case "http":
edit.putBoolean(Config.SP_TAB_ENABLE_HTTP, Boolean.valueOf(state));
break;
case "filesystem":
edit.putBoolean(Config.SP_TAB_ENABLE_FS, Boolean.valueOf(state));
break;
case "misc":
edit.putBoolean(Config.SP_TAB_ENABLE_MISC, Boolean.valueOf(state));
break;
case "webview":
edit.putBoolean(Config.SP_TAB_ENABLE_WV, Boolean.valueOf(state));
break;
case "ipc":
edit.putBoolean(Config.SP_TAB_ENABLE_IPC, Boolean.valueOf(state));
break;
case "phooks":
edit.putBoolean(Config.SP_TAB_ENABLE_PHOOKS, Boolean.valueOf(state));
break;
}
edit.apply();
}
return "#tab_scheckbox#";
}
private String sslUnpinning(Map<String, String> parms) {
String ssl_switch = parms.get("sslswitch");
if (ssl_switch != null) {
SharedPreferences.Editor edit = mPrefs.edit();
edit.putBoolean(Config.SP_UNPINNING, Boolean.valueOf(ssl_switch));
edit.apply();
if (Boolean.valueOf(ssl_switch))
Util.showNotification(mContext, "Disable SSL");
}
return "#sslunpinning#";
}
private String switchProxy(Map<String, String> parms) {
String pswitch = parms.get("value");
if (pswitch != null) {
String host = mPrefs.getString(Config.SP_PROXY_HOST, "");
String port = mPrefs.getString(Config.SP_PROXY_PORT, "");
SharedPreferences.Editor edit = mPrefs.edit();
if (Boolean.valueOf(pswitch) && host.length() > 1 && port.length() > 0) {
edit.putBoolean(Config.SP_SWITCH_PROXY, true);
Util.showNotification(mContext, "Proxy Enable");
} else {
edit.putBoolean(Config.SP_SWITCH_PROXY, false);
}
edit.apply();
}
return "#proxy#";
}
private String proxy(Map<String, String> parms) {
String host = parms.get("host");
String port = parms.get("port");
if (host != null && port != null && Util.isInt(port)) {
SharedPreferences.Editor edit = mPrefs.edit();
edit.putString(Config.SP_PROXY_PORT, port);
edit.putString(Config.SP_PROXY_HOST, host);
edit.apply();
Util.showNotification(mContext, "Save Proxy: " + host + ":" + port);
}
return "#proxy#";
}
private String flagSecure(Map<String, String> parms) {
String fs_switch = parms.get("fsswitch");
if (fs_switch != null) {
SharedPreferences.Editor edit = mPrefs.edit();
edit.putBoolean(Config.SP_FLAG_SECURE, Boolean.valueOf(fs_switch));
edit.apply();
if (Boolean.valueOf(fs_switch))
Util.showNotification(mContext, "Disable all FLAG_SECURE");
}
return "#flags#";
}
private String spExported(Map<String, String> parms) {
String value = parms.get("value");
if (value != null) {
SharedPreferences.Editor edit = mPrefs.edit();
edit.putBoolean(Config.SP_EXPORTED, Boolean.valueOf(value));
edit.apply();
if (Boolean.valueOf(value))
Util.showNotification(mContext, "Export all activities");
}
return "#exported#";
}
private String fileHtml(Map<String, String> parms) {
String value = parms.get("value");
int count = 0;
String c = parms.get("count");
if (c == null || c.equals("")) {
c = "0";
}
count = Integer.valueOf(c);
if (value != null && !value.trim().equals("")) {
return hooksContent(value, count);
}
return "";
}
private Response startComponent(Map<String, String> parms) {
String component = parms.get("component");
if (component.equals("activity")) {
String activity = parms.get("activity");
String action = parms.get("action");
String category = parms.get("category");
String data_uri = parms.get("datauri");
String extra = parms.get("extra");
String flags = parms.get("flags");
String mimetype = parms.get("mimetype");
startActivity(activity, action, category, data_uri, extra, flags, mimetype);
} else if (component.equals("service")) {
} else if (component.equals("broadcast")) {
} else if (component.equals("provider")) {
String uri_provider = parms.get("uri");
return queryProvider(uri_provider);
}
return ok("");
}
private Response setArp(Map<String, String> parms) {
String ip = parms.get("ip");
String mac = parms.get("mac");
Util.setARPEntry(ip, mac);
Util.showNotification(mContext, "arp -s " + ip + " " + mac + "");
return ok("OK");
}
private Response addToClipboard(Map<String, String> parms) {
String value = parms.get("value");
Intent intent = new Intent("mobi.acpm.inspeckage.INSPECKAGE_WEB");
intent.putExtra("package", mPrefs.getString(Config.SP_PACKAGE, ""));
intent.putExtra("value", value);
intent.putExtra("action", "clipboard");
mContext.sendBroadcast(intent, null);
return ok("OK");
}
private Response downloadFile(Map<String, String> parms) {
String path = parms.get("value");
return downloadFileRoot(path);
}
private Response checkApp() {
String isRunning = "App is running: true";
if (!mPrefs.getBoolean(Config.SP_APP_IS_RUNNING, false)) {
isRunning = "App is running: <font style=\"color:red; background:yellow;\">false</font>";
}
return ok(isRunning);
}
private Response fileTreeHtml() {
String tree = mPrefs.getString(Config.SP_DATA_DIR_TREE, "");
if (tree.equals("")) {
tree = "<p class=\"text-danger\">The app is running?</p>";
}
return ok(tree);
}
private Response startWS(Map<String, String> parms) {
String selected = parms.get("selected");
Intent i = new Intent(mContext, LogService.class);
i.putExtra("filter",selected);
i.putExtra("port", mPrefs.getInt(Config.SP_WSOCKET_PORT, 8887));
mContext.startService(i);
return ok("OK");
}
private Response stopWS() {
mContext.stopService(new Intent(mContext, LogService.class));
return ok("OK");
}
private Response addUserHooks(Map<String, String> parms) {
String json = parms.get("jhooks");
SharedPreferences.Editor edit = mPrefs.edit();
edit.putString(Config.SP_USER_HOOKS, json);
edit.apply();
return ok("OK");
}
private Response addUserReplaces(Map<String, String> parms) {
String json = parms.get("data");
SharedPreferences.Editor edit = mPrefs.edit();
edit.putString(Config.SP_USER_REPLACES, json);
edit.apply();
return ok("OK");
}
private Response addUserReturnReplaces(Map<String, String> parms) {
String json = parms.get("data");
SharedPreferences.Editor edit = mPrefs.edit();
edit.putString(Config.SP_USER_RETURN_REPLACES, json);
edit.apply();
return ok("OK");
}
private Response getUserHooks() {
String json = mPrefs.getString(Config.SP_USER_HOOKS,"");
return ok("text/json", json);
}
private Response getUserReplaces() {
String json = mPrefs.getString(Config.SP_USER_REPLACES,"");
return ok("text/json", json);
}
private Response getUserReturnReplaces() {
String json = mPrefs.getString(Config.SP_USER_RETURN_REPLACES,"");
return ok("text/json", json);
}
private Response getBuild() {
String json = mPrefs.getString(Config.SP_BUILD_HOOKS,"");
json = json.replace("{\"buildItems\":[{","[{");
json = json.replace("\"}]}","\"}]");
return ok("text/json", json);
}
private Response addBuild(Map<String, String> parms) {
String json = parms.get("build");
json = "{\"buildItems\":"+json+"}";
SharedPreferences.Editor edit = mPrefs.edit();
edit.putString(Config.SP_BUILD_HOOKS, json);
edit.apply();
return ok("OK");
}
private Response clearHooksLog(Map<String, String> parms) {
String hook = parms.get("value");
String appPath = Environment.getExternalStorageDirectory().getAbsolutePath();
if (!mPrefs.getBoolean(Config.SP_HAS_W_PERMISSION, false)) {
appPath = mPrefs.getString(Config.SP_DATA_DIR, "");
}
String path = "";
switch (hook) {
case "userhooks":
path = Config.P_USERHOOKS;
break;
case "misc":
path = Config.P_MISC;
break;
case "webview":
path = Config.P_WEBVIEW;
break;
case "http":
path = Config.P_HTTP;
break;
case "fs":
path = Config.P_FILESYSTEM;
break;
case "ipc":
path = Config.P_IPC;
break;
case "sqlite":
path = Config.P_SQLITE;
break;
case "hash":
path = Config.P_HASH;
break;
case "crypto":
path = Config.P_CRYPTO;
break;
case "serialization":
path = Config.P_SERIALIZATION;
break;
case "prefs":
path = Config.P_PREFS;
break;
}
File root = new File(appPath + Config.P_ROOT + path);
FileUtil.deleteFile(root);
return ok("ok");
}
private String replaceHtmlVariables(String html) {
html = html.replace("#proxy#", htmlProxy());
html = html.replace("#flags#", flagSecureCheckbox());
html = html.replace("#sslunpinning#", SSLUnpinningCheckbox());
html = html.replace("#exported#", exportedCheckbox());
html = html.replace("#tab_scheckbox#", tabsCheckbox());
html = html.replace("#exported_act#", htmlExportedActivities());
html = html.replace("#activities_list#", htmlActivityList());
html = html.replace("#exported_provider#", htmlExportedProviders());
html = html.replace("#non_exported_provider#", htmlNonExportedProviders());
html = html.replace("#exported_services#", htmlExportedServices());
html = html.replace("#exported_broadcast#", htmlExportedBroadcasts());
html = html.replace("#appName#", mPrefs.getString(Config.SP_APP_NAME, "AppName"));
String icon = "<img src=\"data:image/png;base64, "+mPrefs.getString(Config.SP_APP_ICON_BASE64, "AppIcon")+"\" width=\"80\" height=\"80\" />";
html = html.replace("#appIcon#", icon);
html = html.replace("#appVersion#", mPrefs.getString(Config.SP_APP_VERSION, "Version"));
html = html.replace("#uid#", mPrefs.getString(Config.SP_UID, "uid"));
html = html.replace("#gids#", mPrefs.getString(Config.SP_GIDS, "GIDs"));
html = html.replace("#package#", mPrefs.getString(Config.SP_PACKAGE, "package"));
html = html.replace("#data_dir#", mPrefs.getString(Config.SP_DATA_DIR, "Data Path"));
html = html.replace("#isdebuggable#", mPrefs.getString(Config.SP_DEBUGGABLE, "?"));
html = html.replace("#allowbackup#", mPrefs.getString(Config.SP_ALLOW_BACKUP, "?"));
html = html.replace("#non_exported_act#", mPrefs.getString(Config.SP_N_EXP_ACTIVITIES, "Non Exported Activities").replace("\n", "</br>"));
html = html.replace("#non_exported_services#", mPrefs.getString(Config.SP_N_EXP_SERVICES, "Services").replace("\n", "</br>"));
html = html.replace("#non_exported_broadcast#", mPrefs.getString(Config.SP_N_EXP_BROADCAST, "Broadcast Receiver").replace("\n", "</br>"));
html = html.replace("#req_permissions#", mPrefs.getString(Config.SP_REQ_PERMISSIONS, "Permissions").replace("\n", "</br>"));
html = html.replace("#app_permissions#", mPrefs.getString(Config.SP_APP_PERMISSIONS, "Permissions").replace("\n", "</br>"));
html = html.replace("#shared_libraries#", mPrefs.getString(Config.SP_SHARED_LIB, "Shared Libraries").replace("\n", "</br>"));
return html;
}
//HTML
public String htmlNonExportedProviders() {
String act = mPrefs.getString(Config.SP_N_EXP_PROVIDER, "Non Exported Providers");
String[] providers = act.split("\n");
StringBuilder sb = new StringBuilder();
int i = 0;
for (String provider : providers) {
if (!provider.trim().equals("")) {
if (provider.contains("GRANT:")) {
String[] actInfo = provider.split("GRANT:");
String info = "<a data-toggle=\"collapse\" href=\"#collapsenprovider" + i + "\" aria-expanded=\"false\" aria-controls=\"collapsenprovider" + i + "\">" + actInfo[0] + "</a>" +
"<div class=\"collapse\" id=\"collapsenprovider" + i + "\"><div class=\"well\">Grant URI Permission: " + actInfo[1].replace("|", "</br>") + "</div></div>";
i++;
sb.append(info + "</br>");
} else {
sb.append(provider + "</br>");
}
}
}
return sb.toString();
}
public String htmlExportedProviders() {
String act = mPrefs.getString(Config.SP_EXP_PROVIDER, "Exported Providers");
String[] providers = act.split("\n");
StringBuilder sb = new StringBuilder();
int i = 0;
for (String provider : providers) {
if (!provider.trim().equals("")) {
if (provider.contains("GRANT:")) {
String[] actInfo = provider.split("GRANT:");
String info = "<a data-toggle=\"collapse\" href=\"#collapseprovider" + i + "\" aria-expanded=\"false\" aria-controls=\"collapseprovider" + i + "\">" + actInfo[0] + "</a>" +
"<div class=\"collapse\" id=\"collapseprovider" + i + "\"><div class=\"well\">Grant URI Permission: " + actInfo[1].replace("|", "</br>") + "</div></div>";
i++;
sb.append(info + "</br>");
} else {
sb.append(provider + "</br>");
}
}
}
return sb.toString();
}
public String htmlExportedBroadcasts() {
String act = mPrefs.getString(Config.SP_EXP_BROADCAST, "Exported Broadcasts");
String[] broadcasts = act.split("\n");
StringBuilder sb = new StringBuilder();
int i = 0;
for (String broadcast : broadcasts) {
if (!broadcast.trim().equals("")) {
if (broadcast.contains("PERM:")) {
String[] actInfo = broadcast.split("PERM:");
String info = "<a data-toggle=\"collapse\" href=\"#collapsebroadcast" + i + "\" aria-expanded=\"false\" aria-controls=\"collapsebroadcast" + i + "\">" + actInfo[0] + "</a>" +
"<div class=\"collapse\" id=\"collapsebroadcast" + i + "\"><div class=\"well\">PERMISSION: " + actInfo[1] + "</div></div></br>";
i++;
sb.append(info);
} else {
sb.append(broadcast + "</br>");
}
}
}
return sb.toString();
}
public String htmlExportedServices() {
String act = mPrefs.getString(Config.SP_EXP_SERVICES, "Exported Services");
String[] services = act.split("\n");
StringBuilder sb = new StringBuilder();
int i = 0;
for (String service : services) {
if (!service.trim().equals("")) {
if (service.contains("PERM:")) {
String[] actInfo = service.split("PERM:");
String info = "<a data-toggle=\"collapse\" href=\"#collapseservice" + i + "\" aria-expanded=\"false\" aria-controls=\"collapseservice" + i + "\">" + actInfo[0] + "</a>" +
"<div class=\"collapse\" id=\"collapseservice" + i + "\"><div class=\"well\">PERMISSION: " + actInfo[1] + "</div></div></br>";
i++;
sb.append(info);
} else {
sb.append(service + "</br>");
}
}
}
return sb.toString();
}
public String htmlExportedActivities() {
String act = mPrefs.getString(Config.SP_EXP_ACTIVITIES, "Exported Activities");
String[] activities = act.split("\n");
StringBuilder sb = new StringBuilder();
int i = 0;
for (String activity : activities) {
if (!activity.trim().equals("")) {
if (activity.contains("PERM:")) {
String[] actInfo = activity.split("PERM:");
String info = "<a data-toggle=\"collapse\" href=\"#collapseActivity" + i + "\" aria-expanded=\"false\" aria-controls=\"collapseActivity" + i + "\">" + actInfo[0] + "</a>" +
"<div class=\"collapse\" id=\"collapseActivity" + i + "\"><div class=\"well\">PERMISSION: " + actInfo[1] + "</div></div>";
i++;
sb.append(info + "</br>");
} else {
sb.append(activity + "</br>");
}
}
}
return sb.toString();
}
public String htmlActivityList() {
String act = mPrefs.getString(Config.SP_EXP_ACTIVITIES, "Exported Activities");
String[] activities = act.split("\n");
StringBuilder sb = new StringBuilder();
for (String activity : activities) {
if (!activity.trim().equals("")) {
if (activity.contains("PERM:")) {
String[] actInfo = activity.split("PERM:");
sb.append("<li><a href=\"#\" onclick=\"selectAct('" + actInfo[0].trim() + "');\">" + actInfo[0].trim() + "</a></li>");
} else {
sb.append("<li><a href=\"#\" onclick=\"selectAct('" + activity + "');\">" + activity + "</a></li>");
}
}
}
String nact = mPrefs.getString(Config.SP_N_EXP_ACTIVITIES, "N Exported Activities");
String[] nactivities = nact.split("\n");
if(nactivities.length > 0){
sb.append("<li role='separator' class='divider'></li>");
}
String disabled = "";
if(!mPrefs.getBoolean(Config.SP_APP_IS_RUNNING,false)){
disabled = "class='disabled'";
}
for (String activity : nactivities) {
if (!activity.trim().equals("")) {
if (activity.contains("PERM:")) {
String[] actInfo = activity.split("PERM:");
sb.append("<li "+disabled+"><a href=\"#\" onclick=\"selectAct('" + actInfo[0].trim() + "');\">N " + actInfo[0].trim() + "</a></li>");
} else {
sb.append("<li "+disabled+"><a href=\"#\" onclick=\"selectAct('" + activity + "');\">N " + activity + "</a></li>");
}
}
}
return sb.toString();
}
public String htmlProxy() {
//Proxy
String host = mPrefs.getString(Config.SP_PROXY_HOST, "");
String port = mPrefs.getString(Config.SP_PROXY_PORT, "");
Boolean sw = mPrefs.getBoolean(Config.SP_SWITCH_PROXY, false);
String flag_s = "<input type='checkbox' name='switch_proxy' data-size='mini' unchecked>";
if (sw) {
flag_s = "<input type='checkbox' name='switch_proxy' data-size='mini' checked>";
}
return "<input type='text' class='form-control input-sm' id='host' value='" + host + "' placeholder='192.168.1.337'>" +
"<input type='text' class='form-control input-sm' id='port' value='" + port + "' placeholder='8081'>" + flag_s;
}
public String htmlPrefsAccordion() {
Map<String, String> prefsFiles = FileUtil.readMultiFile(mPrefs, Config.PREFS_BKP);
String prefs_files = "";
int i = 0;
for (Map.Entry<String, String> e : prefsFiles.entrySet()) {
String k = e.getKey();
String v = e.getValue();
i++;
prefs_files += "<div class='panel panel-default'><div class='panel-heading' role='tab' id='heading" + i + "'>" +
"<h4 class='panel-title'><a role='button' data-toggle='collapse' data-parent='#accordion' href='#collapse" + i + "' " +
"aria-expanded='true' aria-controls='collapse" + i + "'> " + k + " </a> </h4> </div> <div id='collapse" + i + "' " +
"class='panel-collapse collapse in' role='tabpanel' aria-labelledby='heading" + i + "'> " +
"<div class='panel-body'><textarea rows='"+countLines(v)+"' style=\"border:none;width:100%\" readonly>" +v + "</textarea></div> </div> </div>";
}
return prefs_files;
}
private static int countLines(String str){
String[] lines = str.split("\r\n|\r|\n");
return lines.length+1;
}
//CONFIG
public String flagSecureCheckbox() {
String flag_s = "<input type='checkbox' name='flag_sec' data-size='mini' unchecked>";
boolean fs = mPrefs.getBoolean(Config.SP_FLAG_SECURE, false);
if (fs) {
flag_s = "<input type='checkbox' name='flag_sec' data-size='mini' checked>";
}
return flag_s;
}
public String SSLUnpinningCheckbox() {
String flag_s = "<input type='checkbox' name='ssl_uncheck' data-size='mini' unchecked>";
boolean fs = mPrefs.getBoolean(Config.SP_UNPINNING, false);
if (fs) {
flag_s = "<input type='checkbox' name='ssl_uncheck' data-size='mini' checked>";
}
return flag_s;
}
public String exportedCheckbox() {
String flag_s = "<input type='checkbox' name='exported' data-size='mini' unchecked>";
boolean fs = mPrefs.getBoolean(Config.SP_EXPORTED, false);
if (fs) {
flag_s = "<input type='checkbox' name='exported' data-size='mini' checked>";
}
return flag_s;
}
public String tabsCheckbox() {
String shared = "<input type='checkbox' name='shared' data-size='mini' checked> Shared Preferences</br>";
String serialization = "<input type='checkbox' name='serialization' data-size='mini' checked> Serialization</br>";
String crypto = "<input type='checkbox' name='crypto' data-size='mini' checked> Crypto</br>";
String hash = "<input type='checkbox' name='hash' data-size='mini' checked> Hash</br>";
String sqlite = "<input type='checkbox' name='sqlite' data-size='mini' checked> SQLite</br>";
String http = "<input type='checkbox' name='http' data-size='mini' checked> HTTP</br>";
String filesystem = "<input type='checkbox' name='filesystem' data-size='mini' checked> File System</br>";
String misc = "<input type='checkbox' name='misc' data-size='mini' checked> Misc.</br>";
String webview = "<input type='checkbox' name='webview' data-size='mini' checked> WebView</br>";
String ipc = "<input type='checkbox' name='ipc' data-size='mini' checked> IPC</br>";
String phooks = "<input type='checkbox' name='phooks' data-size='mini' checked> + Hooks</br>";
StringBuilder sb = new StringBuilder();
if (!mPrefs.getBoolean(Config.SP_TAB_ENABLE_SHAREDP, true)) {
shared = "<input type='checkbox' name='shared' data-size='mini' unchecked> Shared Preferences</br>";
}
if (!mPrefs.getBoolean(Config.SP_TAB_ENABLE_SERIALIZATION, true)) {
serialization = "<input type='checkbox' name='serialization' data-size='mini' unchecked> Serialization</br>";
}
if (!mPrefs.getBoolean(Config.SP_TAB_ENABLE_CRYPTO, true)) {
crypto = "<input type='checkbox' name='crypto' data-size='mini' unchecked> Crypto</br>";
}
if (!mPrefs.getBoolean(Config.SP_TAB_ENABLE_HASH, true)) {
hash = "<input type='checkbox' name='hash' data-size='mini' unchecked> Hash</br>";
}
if (!mPrefs.getBoolean(Config.SP_TAB_ENABLE_SQLITE, true)) {
sqlite = "<input type='checkbox' name='sqlite' data-size='mini' unchecked> SQLite</br>";
}
if (!mPrefs.getBoolean(Config.SP_TAB_ENABLE_HTTP, true)) {
http = "<input type='checkbox' name='http' data-size='mini' unchecked> HTTP</br>";
}
if (!mPrefs.getBoolean(Config.SP_TAB_ENABLE_FS, true)) {
filesystem = "<input type='checkbox' name='filesystem' data-size='mini' unchecked> File System</br>";
}
if (!mPrefs.getBoolean(Config.SP_TAB_ENABLE_MISC, true)) {
misc = "<input type='checkbox' name='misc' data-size='mini' unchecked> Misc.</br>";
}
if (!mPrefs.getBoolean(Config.SP_TAB_ENABLE_WV, true)) {
webview = "<input type='checkbox' name='webview' data-size='mini' unchecked> WebView</br>";
}
if (!mPrefs.getBoolean(Config.SP_TAB_ENABLE_IPC, true)) {
ipc = "<input type='checkbox' name='ipc' data-size='mini' unchecked> IPC</br>";
}
if (!mPrefs.getBoolean(Config.SP_TAB_ENABLE_PHOOKS, true)) {
phooks = "<input type='checkbox' name='phooks' data-size='mini' unchecked> + Hooks</br>";
}
return sb.append("<div class=\"col-md-6\" style=\"line-height:200%;\">").append(shared).append(serialization).append(crypto).append(hash).append(sqlite).append(http).append("</div><div class=\"col-md-6\" style=\"line-height:200%;\">")
.append(filesystem).append(misc).append(webview).append(ipc).append(phooks).append("</div>").toString();
}
//ACTIONS
public Response takeScreenshot() {
int time = (int) Calendar.getInstance().getTimeInMillis();
String fileName = String.valueOf(time) + ".png";
Util.takeScreenshot(fileName);
String sdcardPath = Environment.getExternalStorageDirectory().getAbsolutePath();
String absolutePath = sdcardPath + Config.P_ROOT + "/"+ fileName;
try {
FileInputStream f = new FileInputStream(absolutePath);
File file = new File(absolutePath);
Response res = newChunkedResponse(Response.Status.OK, "image/png", f);//new Response(Response.Status.OK, "image/png", f, (int) file.length());
res.addHeader("Content-Disposition", "attachment;filename=" + fileName);
return res;
} catch (FileNotFoundException e) {
//response with some alert
e.printStackTrace();
}
return null;
}
public Response downloadFileRoot(String path) {
String filename = path.substring(path.lastIndexOf("/") + 1);
String sdcardPath = Environment.getExternalStorageDirectory().getAbsolutePath();
if(new File(sdcardPath + Config.P_ROOT ).exists() && new File("/storage/emulated/legacy").exists()){
sdcardPath = "/storage/emulated/legacy";
}
String absolutePath = sdcardPath + Config.P_ROOT + "/" + filename;
Util.copyFileRoot(path, absolutePath);
try {
FileInputStream f = new FileInputStream(absolutePath);
File file = new File(absolutePath);
Response res = newChunkedResponse(Response.Status.OK, "application/octet-stream", f);//new Response(Response.Status.OK, "application/octet-stream", f, (int) file.length());
res.addHeader("Content-Disposition", "attachment;filename=" + filename);
file.delete();
return res;
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
public Response downloadAll() {
String sdcardPath = Environment.getExternalStorageDirectory().getAbsolutePath();
try {
int time = (int) Calendar.getInstance().getTimeInMillis();
String zipName = mPrefs.getString(Config.SP_PACKAGE, "") + "-" + String.valueOf(time) + ".zip";
String fullZipPath = sdcardPath + "/" + Config.P_ROOT + "/" + zipName;
String fullPath = mPrefs.getString(Config.SP_DATA_DIR, "") + Config.P_ROOT;
if (mPrefs.getBoolean(Config.SP_HAS_W_PERMISSION, false)) {
fullPath = sdcardPath + "/" + Config.P_ROOT+ "/"+ mPrefs.getString(Config.SP_PACKAGE,"");
}
FileUtil.zipFolder(fullPath, fullZipPath);
FileInputStream f = new FileInputStream(fullZipPath);
File file = new File(fullZipPath);
Response res = newChunkedResponse(Response.Status.OK, "application/zip", f);//new Response(Response.Status.OK, "application/zip", f, (int) file.length());
res.addHeader("Content-Disposition", "attachment;filename=" + file.getName());
return res;
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
public Response downloadApk() {
String absolutePath = mPrefs.getString(Config.SP_APK_DIR, "");
try {
FileInputStream f = new FileInputStream(absolutePath);
File file = new File(absolutePath);
Response res = newChunkedResponse(Response.Status.OK, "application/vnd.android.package-archive", f);//new Response(Response.Status.OK, "application/vnd.android.package-archive", f, (int) file.length());
String appName = mPrefs.getString(Config.SP_PACKAGE, "") + ".apk";
res.addHeader("Content-Disposition", "attachment;filename=" + appName);
return res;
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
public void startApp() {
PackageDetail pd = new PackageDetail(mContext, mPrefs.getString(Config.SP_PACKAGE, ""));
Intent i = pd.getLaunchIntent();
mContext.startActivity(i);
}
public void finishApp() {
Intent intent = new Intent("mobi.acpm.inspeckage.INSPECKAGE_FILTER");
intent.putExtra("package", mPrefs.getString(Config.SP_PACKAGE, ""));
intent.putExtra("action", "finish");
mContext.sendBroadcast(intent, null);
}
public void fileTree() {
Intent intent = new Intent("mobi.acpm.inspeckage.INSPECKAGE_FILTER");
intent.putExtra("package", mPrefs.getString(Config.SP_PACKAGE, ""));
intent.putExtra("action", "fileTree");
mContext.sendBroadcast(intent, null);
}
public void isRunning() {
Intent intent = new Intent("mobi.acpm.inspeckage.INSPECKAGE_FILTER");
intent.putExtra("package", mPrefs.getString(Config.SP_PACKAGE, ""));
intent.putExtra("action", "checkApp");
mContext.sendBroadcast(intent, null);
}
//COMPONENTS
public void startActivity(String activity, String action, String category, String data_uri, String extra, String flags, String mimetype) {
Intent intent = new Intent("mobi.acpm.inspeckage.INSPECKAGE_FILTER");
intent.putExtra("package", mPrefs.getString(Config.SP_PACKAGE, ""));
intent.putExtra("action", "startAct");
intent.putExtra("activity", activity);
intent.putExtra("intent_action", action);
intent.putExtra("data_uri", data_uri);
intent.putExtra("extra", extra);
intent.putExtra("flags", flags);
intent.putExtra("mimetype", mimetype);
intent.putExtra("category", category);
if(mPrefs.getBoolean(Config.SP_APP_IS_RUNNING,false)){
mContext.sendBroadcast(intent, null);
}else {
Intent i = new Intent();
i.setClassName(mPrefs.getString(Config.SP_PACKAGE, ""), activity);
//FLAGS
if(!flags.trim().equals("")) {
Field[] fields = Intent.class.getFields();
for (Field f : fields) {
try {
Object value = f.get(i);
if (flags.trim().contains(f.getName())) {
i.addFlags((int) value);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}else{
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
//DATA_URI
if(!data_uri.trim().equals("")){
Uri u = Uri.parse(data_uri);
i.setData(u);
}
if(!category.trim().equals("")){
i.addCategory(category);
}
if(!mimetype.trim().equals("")){
i.normalizeMimeType(mimetype);
}
if(!extra.trim().equals("")){
String[] extras = new String[]{extra};
if(extra.contains(";")){
extras = extra.split(";");
}
for(String e : extras){
String[] values = e.split(",");
if(values.length==3){
if(values[0].trim().toLowerCase().equals("string")){
i.putExtra(values[1],values[2]);
}
if(values[0].trim().toLowerCase().equals("boolean")){
i.putExtra(values[1],Boolean.valueOf(values[2]));
}
if(values[0].trim().toLowerCase().equals("int")){
i.putExtra(values[1], Integer.valueOf(values[2]));
}
if(values[0].trim().toLowerCase().equals("float")){
i.putExtra(values[1],Float.valueOf(values[2]));
}
if(values[0].trim().toLowerCase().equals("double")){
i.putExtra(values[1],Double.valueOf(values[2]));
}
}
}
}
mContext.startActivity(i);
}
}
public Response queryProvider(String uri) {
Intent intent = new Intent("mobi.acpm.inspeckage.INSPECKAGE_FILTER");
intent.putExtra("package", mPrefs.getString(Config.SP_PACKAGE, ""));
intent.putExtra("action", "query");
intent.putExtra("uri", uri);
mContext.sendBroadcast(intent, null);
return newFixedLengthResponse(Response.Status.OK, NanoHTTPD.MIME_HTML, "OK");
}
//HOOKS TABS
public String hooksContent(String type, int count) {
String html = "";
int countTmp = 0;
switch (type) {
case "serialization": {
html = FileUtil.readFromFile(mPrefs, SERIALIZATION).replace(SerializationHook.TAG, "");
if(!html.equals("")) {
String[] x = html.split("</br>");
for (int i = 0; i < x.length; i++) {
if ((i + 1) > count) {
countTmp = (i + 1);
} else {
countTmp = count;
}
if (x[i].length() > 170) {
String len170 = x[i].substring(0, 135);
String rest = x[i].substring(135);
x[i] = "<div class=\"collapse-group\"> <span class=\"label label-info\">" + (i + 1) + "</span> " + len170 +
"<div class=\"collapse\"><div class=\"breakWord\">" + rest + "</div></div><a class=\"a\" href=\"#\"> »</a></div>";
continue;
}
x[i] = "<span class=\"label label-info\">" + (i + 1) + "</span> " + x[i] + "</br>";
}
List<String> ls = Arrays.asList(x);
Collections.reverse(ls);
x = (String[]) ls.toArray();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < x.length; i++) {
if (i < 500)
sb.append(x[i]);
}
//need load from here for callapse work correctaly
String script = "<script>$(document).ready(function() {" +
"$('a').on('click', function(e) {" +
" e.preventDefault();" +
" var $this = $(this);" +
" var $collapse = $this.closest('.collapse-group').find('.collapse');" +
" $collapse.collapse('toggle');" +
" });" +
"});</script>";
sb.append(script);
if (count == -1) {
html = sb.toString();
} else {
html = "" + countTmp;
}
}
break;
}
case "fs": {
html = FileUtil.readFromFile(mPrefs, FILESYSTEM).replace(FileSystemHook.TAG, "");
if(!html.equals("")) {
String[] x = html.split("</br>");
for (int i = 0; i < x.length; i++) {
x[i] = "<span class=\"label label-info\">" + (i + 1) + "</span> " + x[i];
if ((i + 1) > count) {
countTmp = (i + 1);
} else {
countTmp = count;
}
}
List<String> ls = Arrays.asList(x);
Collections.reverse(ls);
x = (String[]) ls.toArray();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < x.length; i++) {
if (i < 500)
sb.append(x[i] + "</br>");
}
if (count == -1) {
html = sb.toString();
} else {
html = "" + countTmp;
}
}
break;
}
case "misc": {
html = FileUtil.readFromFile(mPrefs, MISC).replace(MiscHook.TAG, "");
if(!html.equals("")) {
String[] x = html.split("</br>");
for (int i = 0; i < x.length; i++) {
if (x[i].length() > 170) {
x[i] = "<div class=\"breakWord\"><span class=\"label label-info\"> " + (i + 1) + "</span> " + x[i] + "</div>";
} else {
x[i] = "<span class=\"label label-info\">" + (i + 1) + "</span> " + Html.escapeHtml(x[i]) + "</br>";
}
if ((i + 1) > count) {
countTmp = (i + 1);
} else {
countTmp = count;
}
}
List<String> ls = Arrays.asList(x);
Collections.reverse(ls);
x = (String[]) ls.toArray();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < x.length; i++) {
if (i < 500)
sb.append(x[i]);
}
if (count == -1) {
html = sb.toString();
} else {
html = "" + countTmp;
}
}
break;
}
case "http": {
html = FileUtil.readFromFile(mPrefs, HTTP).replace(HttpHook.TAG, "");
if(!html.equals("")) {
String[] x = html.split("</br>");
for (int i = 0; i < x.length; i++) {
if (x[i].length() > 170) {
x[i] = "<div class=\"breakWord\"><span class=\"label label-info\">" + (i + 1) + "</span> " + x[i] + "</div>";
} else {
String color = "label-info";
if (x[i].contains("Possible pinning")) {
color = "label-danger";
}
x[i] = "<span class=\"label " + color + "\">" + (i + 1) + "</span> " + Html.escapeHtml(x[i]) + "</br>";
}
if ((i + 1) > count) {
countTmp = (i + 1);
} else {
countTmp = count;
}
}
List<String> ls = Arrays.asList(x);
Collections.reverse(ls);
x = (String[]) ls.toArray();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < x.length; i++) {
if (i < 500)
sb.append(x[i]);
}
if (count == -1) {
html = sb.toString();
} else {
html = "" + countTmp;
}
}
break;
}
case "wv": {
html = FileUtil.readFromFile(mPrefs, WEBVIEW).replace(WebViewHook.TAG, "");
if(!html.equals("")) {
String[] x = html.split("</br>");
for (int i = 0; i < x.length; i++) {
if (x[i].contains("addJavascriptInterface(Object, ")) {
x[i] = "<a href=\"#\" role=\"button\" class=\"btn popovers\" data-toggle=\"popover\" " +
"title=\"\" data-content=\"" + "Injects the supplied Java object into this WebView. " +
"The object is injected into the JavaScript context of the main frame, " +
"using the supplied name. This allows the Java object's methods to " +
"be accessed from JavaScript. <a href='http://developer.android.com/intl/pt-br/reference/android/webkit/WebView.html#addJavascriptInterface(java.lang.Object, java.lang.String)' target='_blank' title='link'> read more.</a>\">" + x[i] + " </a>";
} else {
x[i] = x[i];
}
if ((i + 1) > count) {
countTmp = (i + 1);
} else {
countTmp = count;
}
}
List<String> ls = Arrays.asList(x);
Collections.reverse(ls);
x = (String[]) ls.toArray();
StringBuilder sb = new StringBuilder();
for (String aX : x) {
sb.append(aX + "</br>");
}
String script = "<script>$(document).ready(function() {" +
"$('[data-toggle=popover]').popover({html:true})" +
"});</script>";
sb.append(script);
if (count == -1) {
html = sb.toString();
} else {
html = "" + countTmp;
}
}
break;
}
case "ipc": {
html = FileUtil.readFromFile(mPrefs, IPC).replace(IPCHook.TAG, "");
if(!html.equals("")) {
String[] x = html.split("</br>");
for (int i = 0; i < x.length; i++) {
x[i] = "<span class=\"label label-default\">" + (i + 1) + "</span> " + x[i];
if ((i + 1) > count) {
countTmp = (i + 1);
} else {
countTmp = count;
}
}
List<String> ls = Arrays.asList(x);
Collections.reverse(ls);
x = (String[]) ls.toArray();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < x.length; i++) {
if (i < 500)
sb.append(x[i] + "</br>");
}
if (count == -1) {
html = sb.toString();
} else {
html = "" + countTmp;
}
}
break;
}
case "crypto": {
html = FileUtil.readFromFile(mPrefs, CRYPTO).replace(CryptoHook.TAG, "");
if(!html.equals("")) {
String[] x = html.split("</br>");
for (int i = 0; i < x.length; i++) {
if ((i + 1) > count) {
countTmp = (i + 1);
} else {
countTmp = count;
}
if (x[i].length() > 170) {
String len170 = x[i].substring(0, 135);
String rest = x[i].substring(135);
x[i] = "<div class=\"collapse-group\"> <span class=\"label label-info\">" + (i + 1) + "</span> " + len170 +
"<div class=\"collapse\"><p class=\"breakWord\">" + rest + "</p></div><a class=\"a\" href=\"#\"> »</a></div>";
continue;
}
x[i] = "<span class=\"label label-info\">" + (i + 1) + "</span> " + Html.escapeHtml(x[i]) + "</br>";
}
List<String> ls = Arrays.asList(x);
Collections.reverse(ls);
x = (String[]) ls.toArray();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < x.length; i++) {
if (i < 500)
sb.append(x[i]);
}
//need load from here for callapse work correctaly
String script = "<script>$(document).ready(function() {" +
"$('a').on('click', function(e) {" +
" e.preventDefault();" +
" var $this = $(this);" +
" var $collapse = $this.closest('.collapse-group').find('.collapse');" +
" $collapse.collapse('toggle');" +
" });" +
"});</script>";
sb.append(script);
if (count == -1) {
html = sb.toString();
} else {
html = "" + countTmp;
}
}
break;
}
case "prefs": {
html = FileUtil.readFromFile(mPrefs, PREFS).replace(SharedPrefsHook.TAG, "");
if(!html.equals("")) {
String[] x = html.split("</br>");
for (int i = 0; i < x.length; i++) {
String color = "danger";
if (x[i].contains("GET[")) {
color = "info";
} else if (x[i].contains("CONTAINS[")) {
color = "warning";
} else if (x[i].contains("PUT[")) {
color = "danger";
}
if (x[i].length() > 170) {
x[i] = "<tr><td><div class=\"breakWord\"><span class=\"label label-" + color + "\">" + (i + 1) + "</span> " + Html.escapeHtml(x[i]) + "</div></td></tr>";
} else {
x[i] = "<tr><td><span class=\"label label-" + color + "\">" + (i + 1) + "</span> " + Html.escapeHtml(x[i]) + "</br></td></tr>";
}
if ((i + 1) > count) {
countTmp = (i + 1);
} else {
countTmp = count;
}
}
List<String> ls = Arrays.asList(x);
Collections.reverse(ls);
x = (String[]) ls.toArray();
StringBuilder sb = new StringBuilder();
String tableBefore = "<table class=\"table\"><tbody>";
String tableAfter = "</tbody></table>";
//sb.append(tableBefore);
for (int i = 0; i < x.length; i++) {
if (i < 500)
sb.append(x[i]);
}
//sb.append(tableAfter);
if (count == -1) {
html = sb.toString();
} else {
html = "" + countTmp;
}
}
break;
}
case "hash": {
html = FileUtil.readFromFile(mPrefs, HASH).replace(HashHook.TAG, "");
if(!html.equals("")) {
String[] x = html.split("</br>");
for (int i = 0; i < x.length; i++) {
if ((i + 1) > count) {
countTmp = (i + 1);
} else {
countTmp = count;
}
if (x[i].length() > 170) {
String len170 = x[i].substring(0, 135);
String rest = x[i].substring(135);
x[i] = "<div class=\"collapse-group\"> <span class=\"label label-info\">" + (i + 1) + "</span> " + len170 +
"<div class=\"collapse\"><p class=\"breakWord\">" + rest + "</p></div><a class=\"a\" href=\"#\"> »</a></div>";
continue;
}
x[i] = "<span class=\"label label-info\">" + (i + 1) + "</span> " + Html.escapeHtml(x[i]) + "</br>";
}
List<String> ls = Arrays.asList(x);
Collections.reverse(ls);
x = (String[]) ls.toArray();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < x.length; i++) {
if (i < 500)
sb.append(x[i]);
}
//need load from here for callapse work correctaly
String script = "<script>$(document).ready(function() {" +
"$('a').on('click', function(e) {" +
" e.preventDefault();" +
" var $this = $(this);" +
" var $collapse = $this.closest('.collapse-group').find('.collapse');" +
" $collapse.collapse('toggle');" +
" });" +
"});</script>";
sb.append(script);
if (count == -1) {
html = sb.toString();
} else {
html = "" + countTmp;
}
}
break;
}
case "sqlite": {
html = FileUtil.readFromFile(mPrefs, SQLITE).replace(SQLiteHook.TAG, "");
if(!html.equals("")) {
String[] x = html.split("</br>");
for (int i = 0; i < x.length; i++) {
String color;
if (x[i].contains("INSERT INTO")) {
color = "label-info";
} else if (x[i].contains("UPDATE")) {
color = "label-warning";
} else if (x[i].contains("execSQL(")) {
color = "label-danger";
} else if (x[i].contains("SELECT")) {
color = "label-success";
x[i].replace("\n", "</br>");
} else {
color = "label-default";
}
if (x[i].length() > 170) {
x[i] = "<div class=\"breakWord\"><span class=\"label " + color + "\">" + (i + 1) + "</span> " + Html.escapeHtml(x[i]) + "</div>";
} else {
x[i] = "<span class=\"label " + color + "\">" + (i + 1) + "</span> " + Html.escapeHtml(x[i]) + "</br>";
}
if ((i + 1) > count) {
countTmp = (i + 1);
} else {
countTmp = count;
}
}
List<String> ls = Arrays.asList(x);
Collections.reverse(ls);
x = (String[]) ls.toArray();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < x.length; i++) {
if (i < 500)
sb.append(x[i]);
}
if (count == -1) {
html = sb.toString().replace("</br></br>", "</br>");
} else {
html = "" + countTmp;
}
}
break;
}
case "userhooks": {
html = FileUtil.readFromFile(mPrefs, USERHOOKS).replace(UserHooks.TAG, "");
if(!html.equals("")) {
String[] x = html.split("</br>");
for (int i = 0; i < x.length; i++) {
if (x[i].length() > 470) {
String len300 = x[i].substring(0, 400);
String rest = x[i].substring(400);
x[i] = "<div class=\"collapse-group\"> <div class=\"breakWord\"><span class=\"label label-default\">" + (i + 1) + "</span> " + len300 + "</div>" +
"<div class=\"collapse\"><p class=\"breakWord\">" + rest + "</p></div><a class=\"a\" href=\"#\"> »</a></div>";
} else {
x[i] = "<span class=\"label label-default\">" + (i + 1) + "</span> " + x[i];
}
if ((i + 1) > count) {
countTmp = (i + 1);
} else {
countTmp = count;
}
}
List<String> ls = Arrays.asList(x);
Collections.reverse(ls);
x = (String[]) ls.toArray();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < x.length; i++) {
if (i < 500)
sb.append(x[i] + "</br>");
}
//need load from here for callapse work correctaly
String script = "<script>$(document).ready(function() {" +
"$('a').on('click', function(e) {" +
" e.preventDefault();" +
" var $this = $(this);" +
" var $collapse = $this.closest('.collapse-group').find('.collapse');" +
" $collapse.collapse('toggle');" +
" });" +
"});</script>";
sb.append(script);
if (count == -1) {
html = sb.toString();
} else {
html = "" + countTmp;
}
}
break;
}
}
if (type.equals("pfiles")) {
html = htmlPrefsAccordion();
}
return html;
}
//TEST MODULE ENABLED
public static boolean isModuleEnabled() {
return false;
}
}