Some progress on hacking the webview

This commit is contained in:
octospacc 2023-02-15 00:13:36 +01:00
parent a1caff328d
commit 7fb71c27a7
12 changed files with 210 additions and 51 deletions

4
.gitignore vendored
View File

@ -1 +1,5 @@
.gradle/*
.idea/*
local.properties
app/build/*
build/*

View File

@ -8,22 +8,16 @@ BleedingEdge:
interruptible: true
stage: build
script: |
mkdir -p ./AndroidSdk
cd ./AndroidSdk
StartDir="$(pwd)"
mkdir -p ../AndroidSdk
cd ../AndroidSdk
wget -O BuildTools.zip https://dl.google.com/android/repository/build-tools_r30.0.3-linux.zip
wget -O Platform.zip https://dl.google.com/android/repository/platform-30_r03.zip
yes A | unzip BuildTools.zip || true
yes A | unzip Platform.zip || true
cd ..
cd "$StartDir"
mv ./app/src/main ./main
cd ./main
mv ./java ./src
mv ../tools/tiny-android-template/* ./
echo "${SecEncodedKeystore}" | base64 --decode > ./Keystore.jks
perl ./link.pl
bash ./make.sh
sh ./tools/Build.sh
artifacts:
paths:
- main/app.apk
- build/app.apk

View File

@ -9,7 +9,7 @@ android {
minSdkVersion 1
targetSdkVersion 29
versionCode 1
versionName "1.0.0"
versionName "1.0.1"
}
buildTypes {
release {
@ -20,5 +20,5 @@ android {
}
dependencies {
//compile fileTree(dir: 'libs', include: ['*.jar'])
compile fileTree(dir: 'libs', include: ['*.jar'])
}

View File

@ -2,8 +2,8 @@
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="org.eu.octt.browserocto"
android:versionCode="0"
android:versionName="0">
android:versionCode="1"
android:versionName="1.0.1">
<uses-sdk android:minSdkVersion="1" android:targetSdkVersion="30"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>

View File

@ -48,10 +48,9 @@ public class MainActivity extends Activity {
};
private Intent MakeIntBrowse(String Url, Boolean Cache) {
Intent IntBrowse = new Intent(getApplicationContext(), WebWindowActivity.class);
Intent IntBrowse = new Intent(getApplicationContext(), WebWindowActivity.class)
// To get unlimited activities in general but only 1 per site, set only FLAG_ACTIVITY_NEW_DOCUMENT and put site URL in intent.setData
// NOTE: This only gives a good UX on Android >= 7, for the lower versions we need to implement things differently
IntBrowse
.setAction(Intent.ACTION_OPEN_DOCUMENT)
.setData(Uri.parse(Url))
.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT /*| Intent.FLAG_ACTIVITY_MULTIPLE_TASK*/)
@ -84,50 +83,61 @@ public class MainActivity extends Activity {
};
private final void CreateShortcutFallback(String Url, String Name) {
Intent IntExt = new Intent();
IntExt.putExtra(Intent.EXTRA_SHORTCUT_INTENT, MakeIntBrowse(Url, true));
IntExt.putExtra(Intent.EXTRA_SHORTCUT_NAME, Name);
IntExt.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(getApplicationContext(), R.drawable.ic_launcher));
IntExt.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
//IntExt.putExtra("duplicate", false); //may it's already there so don't duplicate
Intent IntExt = new Intent()
.putExtra(Intent.EXTRA_SHORTCUT_INTENT, MakeIntBrowse(Url, true))
.putExtra(Intent.EXTRA_SHORTCUT_NAME, Name)
.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(getApplicationContext(), R.drawable.ic_launcher))
.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
//.putExtra("duplicate", false); //may it's already there so don't duplicate
getApplicationContext().sendBroadcast(IntExt);
};
private void ShowShortcutDial(String Url) {
final AlertDialog.Builder Dial = new AlertDialog.Builder(this);
final String Url_ = Url;
final View v = getLayoutInflater().inflate(R.layout.dialmakeshortcut, null);
Dial.setView(v);
final View DialView = getLayoutInflater().inflate(R.layout.dialmakeshortcut, null);
Dial.setView(DialView);
final EditText EditName = v.findViewById(R.id.EditName);
//final EditText EditIcon = v.findViewById(R.id.EditIcon);
final EditText EditName = DialView.findViewById(R.id.EditName);
//final EditText EditIcon = DialView.findViewById(R.id.EditIcon);
Dial.setTitle("Create Home Shortcut");
//Dial.setCancelable(false);
Dial.setCancelable(false);
// https://stackoverflow.com/a/15619098
//Dial.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
// @Override
// public void onClick(DialogInterface Dial, int w) {
// // Do nothing here because we override this button later to change the behavior.
// // However, we still need this because of quirks on older versions of Android.
// };
//});
Dial.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface Dial, int w) {
Dial.dismiss();
};
});
//Dial.show();
// TODO: FIX it seems we just broke this with our crap idea of hacking the dialog cancellation
Dial.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface d, int w) {
public void onClick(DialogInterface Dial, int w) {
final String Name = EditName.getText().toString();
//String IconUrl = EditIcon.getText().toString();
if (!Name.equals("")) {
CreateShortcut(Url_, Name);
Dial.dismiss();
} else
if (Name.equals("")) {
_Util.ToastMsg("Name can't be empty!", getApplicationContext());
};
};
});
Dial.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface d, int w) {
};
});
Dial.show();
};

View File

@ -5,26 +5,98 @@ import android.content.*;
import android.os.*;
import android.webkit.*;
import android.widget.*;
import android.util.*;
import java.io.*;
import java.net.*;
public class WebWindowActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.webwindow);
Bundle Extra = getIntent().getExtras();
LinearLayout LayMain = findViewById(R.id.LayMain);
WebView Web0 = findViewById(R.id.Web0);
Web0.setWebViewClient(new WebViewClient());
//Web0.setWebViewClient(new WebViewClient());
Web0.setWebViewClient(new WebViewClient() {
// https://gist.github.com/kmerrell42/b4ff31733c562a3262ee9a42f5704a89
@Override
public WebResourceResponse shouldInterceptRequest(WebView v, String Url) {
return HandleRequest(Url);
}
@Override
public WebResourceResponse shouldInterceptRequest(WebView v, WebResourceRequest Req) {
return HandleRequest(Req.getUrl().toString());
}
private WebResourceResponse HandleRequest(String Url) {
//Thread thread = new Thread(new Runnable() {
// @Override
// public void run() {
try {
//URL url;
//HttpURLConnection Connection = null;
URL Url_ = new URL(Url);
HttpURLConnection Connection = (HttpURLConnection)Url_.openConnection();
String ContentType = Connection.getContentType();
String ContentEncoding = null;
if (ContentType != null) {
ContentType = ContentType.split("\\;")[0];
ContentEncoding = ContentType.split("\\=")[1];
}
InputStream In = new BufferedInputStream(Connection.getInputStream());
return new WebResourceResponse(ContentType, ContentEncoding, In);
} catch (Exception Ex) {
Log.e("browserocto/Log", "", Ex);
};
// };//});
return null;
};
});
Web0.getSettings().setJavaScriptEnabled(true);
Web0.getSettings().setDomStorageEnabled(true);
Web0.getSettings().setCacheMode(WhichCacheMode(Extra.getBoolean("Cache")));
// This is apparently not working like I want (force caching of all site resources in spite of bad Cache-Control HTTP headers)
//webView.getSettings().setAppCacheMaxSize(1024*1024*8);
//webView.getSettings().setAppCachePath("/data/data/" + getPackageName() + "/cache");
//webView.getSettings().setAllowFileAccess(true);
//webView.getSettings().setAppCacheEnabled(true);
Web0.loadUrl(Extra.getString("Url"));
_Util.ToastMsg(Extra.getString("Url"), getApplicationContext());
_Util.ToastMsg(Extra.getString("Url"), this);
// Thread thread = new Thread(new Runnable() {
// @Override
// public void run() {
// URL url;
// HttpURLConnection urlConnection = null;
// try {
// url = new URL("http://www.android.com/");
// urlConnection = (HttpURLConnection) url.openConnection();
// InputStream in = new BufferedInputStream(urlConnection.getInputStream());
// runOnUiThread(new Runnable() {
// @Override
// public void run() {
// try {
// _Util.ToastMsg(_Util.StreamToString(in), getApplicationContext());
// } catch (Exception Ex) {
// Log.e("browserocto/Log", "", Ex);
// };
// };
// });
// } catch (Exception Ex) {
// Log.e("browserocto/Log", "", Ex);
// } finally {
// urlConnection.disconnect();
// };
// };
// });
// thread.start();
};
public int WhichCacheMode(boolean Opt) {
if (Opt) {
return WebSettings.LOAD_CACHE_ELSE_NETWORK;

View File

@ -3,20 +3,56 @@ package org.eu.octt.browserocto;
import android.app.*;
import android.content.*;
import android.widget.*;
import java.io.*;
public class _Util extends Activity {
public static boolean StartsWithOneOf(String Check, String[] With) {
for (int i=0; i<With.length; i++) {
if (Check.startsWith(With[i])) {
return true;
};
};
return false;
};
public static boolean EqualsOneOf(String Check, String[] With) {
for (int i=0; i<With.length; i++) {
if (Check.equals(With[i])) {
return true;
};
};
return false;
};
public static void ToastMsg(String Msg, Context c) {
Toast.makeText(c, Msg, Toast.LENGTH_SHORT).show();
};
public static boolean IsUrlValid(String Url) {
Url = Url.toLowerCase();
if (
(Url.startsWith("file://") || Url.startsWith("http://") || Url.startsWith("https://"))
&& !(Url.equals("file://") || Url.equals("http://") || Url.equals("https://"))
) {
Url = Url.trim().toLowerCase();
String[] Prefixes = {"file://", "http://", "https://", "data:", "javascript:"};
if (StartsWithOneOf(Url, Prefixes) && !EqualsOneOf(Url, Prefixes)) {
return true;
};
return false;
};
// https://stackoverflow.com/a/5713929
public static String StreamToString(InputStream is) throws IOException {
if (is != null) {
Writer writer = new StringWriter();
char[] buffer = new char[1024];
try {
Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
int n;
while ((n = reader.read(buffer)) != -1) {
writer.write(buffer, 0, n);
};
} finally {
is.close();
};
return writer.toString();
};
return "";
};
};

View File

@ -38,6 +38,7 @@
</LinearLayout>
<!-- TODO: Make this be CheckBox on Android < ICS because Switch doesn't exist -->
<Switch
android:layout_width="wrap_content"
android:layout_height="wrap_content"

11
tools/Build.sh Executable file
View File

@ -0,0 +1,11 @@
#!/bin/sh
rm -rf ./build || true
cp -r ./app/src/main ./build
cd ./build
mv ./java ./src
cp -r ../tools/tiny-android-template/* ./
echo "${SecEncodedKeystore}" | base64 --decode > ./Keystore.jks
perl ./link.pl
bash ./make.sh

6
tools/DevBuild.sh Executable file
View File

@ -0,0 +1,6 @@
#!/bin/sh
export SecEncodedKeystore="$(cat ../Test.jks | base64 -w0)"
export SecKeystorePassword="123456"
sh ./tools/Build.sh

View File

@ -7,7 +7,7 @@ API_LEVEL_MIN="1"
ANDROID_VERSION="11"
NDK_VERSION="r23-beta4"
TARGET_ARCHES=( "arm64-v8a" )
SDK_DIR="../AndroidSdk"
SDK_DIR="../../AndroidSdk"
KOTLIN_LIB_DIR="/usr/share/kotlin/lib"
REPO="https://dl.google.com/dl/android/maven2"

View File

@ -0,0 +1,25 @@
#!/bin/bash
source includes.sh
MF=`cat AndroidManifest.xml`
TERM="package=[\'\"]([a-z0-9.]+)"
if [[ "$MF" =~ $TERM ]]
then
package="${BASH_REMATCH[1]}"
activity=".MainActivity"
TERM="<activity([^>]+)"
if [[ "$MF" =~ $TERM ]]; then
tag="${BASH_REMATCH[1]}"
TERM="[\'\"]([^\'\"]+)"
[[ "$tag" =~ $TERM ]] && activity="${BASH_REMATCH[1]}"
fi
$CMD_ADB install -r -t app.apk && \
$CMD_ADB shell am start -n $package/$activity
else
echo Could not find a suitable package name inside AndroidManifest.xml
exit
fi