修复 打包后ui脚本无法运行的问题

修复 打包后模块无法运行的问题
This commit is contained in:
hyb1996
2018-12-12 14:18:03 +08:00
parent c460425656
commit 05813499bc
33 changed files with 548 additions and 91 deletions

View File

@@ -31,7 +31,7 @@
android:name=".App" android:name=".App"
android:allowBackup="false" android:allowBackup="false"
android:icon="@drawable/autojs_material" android:icon="@drawable/autojs_material"
android:label="@string/_app_name" android:label="@string/app_name"
android:largeHeap="true" android:largeHeap="true"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme" android:theme="@style/AppTheme"
@@ -45,7 +45,7 @@
<activity <activity
android:name=".ui.splash.SplashActivity" android:name=".ui.splash.SplashActivity"
android:hardwareAccelerated="true" android:hardwareAccelerated="true"
android:label="@string/_app_name" android:label="@string/app_name"
android:theme="@style/AppTheme.Splash"> android:theme="@style/AppTheme.Splash">
<intent-filter> <intent-filter>
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER"/>
@@ -56,7 +56,7 @@
<activity <activity
android:name=".ui.main.MainActivity_" android:name=".ui.main.MainActivity_"
android:hardwareAccelerated="true" android:hardwareAccelerated="true"
android:label="@string/_app_name" android:label="@string/app_name"
android:launchMode="singleTask" android:launchMode="singleTask"
android:theme="@style/AppTheme.FullScreen"> android:theme="@style/AppTheme.FullScreen">
</activity> </activity>
@@ -164,7 +164,7 @@
android:name=".external.tasker.PluginActivity" android:name=".external.tasker.PluginActivity"
android:exported="true" android:exported="true"
android:icon="@drawable/ic_android_eat_js" android:icon="@drawable/ic_android_eat_js"
android:label="@string/_app_name" android:label="@string/app_name"
android:targetActivity=".external.tasker.TaskPrefEditActivity_" android:targetActivity=".external.tasker.TaskPrefEditActivity_"
tools:ignore="ExportedActivity"> tools:ignore="ExportedActivity">
<intent-filter> <intent-filter>
@@ -277,7 +277,7 @@
</activity> </activity>
<service <service
android:name="com.stardust.notification.NotificationListenerService" android:name="com.stardust.notification.NotificationListenerService"
android:label="@string/_app_name" android:label="@string/app_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"> android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter> <intent-filter>
<action android:name="android.service.notification.NotificationListenerService"/> <action android:name="android.service.notification.NotificationListenerService"/>

View File

@@ -9,6 +9,8 @@ import com.stardust.autojs.apkbuilder.ManifestEditor;
import com.stardust.autojs.apkbuilder.util.StreamUtils; import com.stardust.autojs.apkbuilder.util.StreamUtils;
import com.stardust.autojs.project.BuildInfo; import com.stardust.autojs.project.BuildInfo;
import com.stardust.autojs.project.ProjectConfig; import com.stardust.autojs.project.ProjectConfig;
import com.stardust.autojs.script.EncryptedScriptFileHeader;
import com.stardust.autojs.script.JavaScriptFileSource;
import com.stardust.pio.PFiles; import com.stardust.pio.PFiles;
import com.stardust.util.AdvancedEncryptionStandard; import com.stardust.util.AdvancedEncryptionStandard;
import com.stardust.util.MD5; import com.stardust.util.MD5;
@@ -198,12 +200,16 @@ public class ApkBuilder {
} }
private void encrypt(File toDir, File file) throws IOException { private void encrypt(File toDir, File file) throws IOException {
PFiles.writeBytes(new File(toDir, file.getName()).getPath(), encrypt(file)); FileOutputStream fos = new FileOutputStream(new File(toDir, file.getName()));
EncryptedScriptFileHeader.INSTANCE.writeHeader(fos, (short) new JavaScriptFileSource(file).getExecutionMode());
encrypt(fos, file);
} }
private byte[] encrypt(File file) throws IOException { private void encrypt(FileOutputStream fos, File file) throws IOException {
try { try {
return new AdvancedEncryptionStandard(mKey.getBytes(), mInitVector).encrypt(PFiles.readBytes(file.getPath())); byte[] bytes = new AdvancedEncryptionStandard(mKey.getBytes(), mInitVector).encrypt(PFiles.readBytes(file.getPath()));
fos.write(bytes);
fos.close();
} catch (Exception e) { } catch (Exception e) {
throw new IOException(e); throw new IOException(e);
} }
@@ -212,7 +218,7 @@ public class ApkBuilder {
public ApkBuilder replaceFile(String relativePath, String newFilePath) throws IOException { public ApkBuilder replaceFile(String relativePath, String newFilePath) throws IOException {
if (newFilePath.endsWith(".js")) { if (newFilePath.endsWith(".js")) {
PFiles.writeBytes(new File(mWorkspacePath, relativePath).getPath(), encrypt(new File(newFilePath))); encrypt(new FileOutputStream(new File(mWorkspacePath, relativePath)), new File(newFilePath));
} else { } else {
StreamUtils.write(new FileInputStream(newFilePath), new FileOutputStream(new File(mWorkspacePath, relativePath))); StreamUtils.write(new FileInputStream(newFilePath), new FileOutputStream(new File(mWorkspacePath, relativePath)));
} }

View File

@@ -5,6 +5,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import com.stardust.pio.UncheckedIOException; import com.stardust.pio.UncheckedIOException;
import org.autojs.autojs.BuildConfig; import org.autojs.autojs.BuildConfig;
import com.stardust.util.DeveloperUtils; import com.stardust.util.DeveloperUtils;
@@ -20,6 +21,7 @@ public class ApkBuilderPluginHelper {
private static final String PLUGIN_PACKAGE_NAME = "org.autojs.apkbuilderplugin"; private static final String PLUGIN_PACKAGE_NAME = "org.autojs.apkbuilderplugin";
private static final String TEMPLATE_APK_PATH = "template.apk"; private static final String TEMPLATE_APK_PATH = "template.apk";
private static final boolean DEBUG_APK_PLUGIN = false;
public static boolean isPluginAvailable(Context context) { public static boolean isPluginAvailable(Context context) {
return DeveloperUtils.checkSignature(context, PLUGIN_PACKAGE_NAME); return DeveloperUtils.checkSignature(context, PLUGIN_PACKAGE_NAME);
@@ -27,9 +29,9 @@ public class ApkBuilderPluginHelper {
public static InputStream openTemplateApk(Context context) { public static InputStream openTemplateApk(Context context) {
try { try {
//if (BuildConfig.DEBUG) { if (DEBUG_APK_PLUGIN && BuildConfig.DEBUG) {
// return context.getAssets().open(TEMPLATE_APK_PATH); return context.getAssets().open(TEMPLATE_APK_PATH);
//} }
return context.getPackageManager().getResourcesForApplication(PLUGIN_PACKAGE_NAME) return context.getPackageManager().getResourcesForApplication(PLUGIN_PACKAGE_NAME)
.getAssets().open(TEMPLATE_APK_PATH); .getAssets().open(TEMPLATE_APK_PATH);
} catch (IOException e) { } catch (IOException e) {

View File

@@ -28,7 +28,6 @@ public class ScriptIntents {
public static final String EXTRA_KEY_LOOP_INTERVAL = "interval"; public static final String EXTRA_KEY_LOOP_INTERVAL = "interval";
public static final String EXTRA_KEY_DELAY = "delay"; public static final String EXTRA_KEY_DELAY = "delay";
public static boolean isTaskerBundleValid(Bundle bundle) { public static boolean isTaskerBundleValid(Bundle bundle) {
return bundle.containsKey(ScriptIntents.EXTRA_KEY_PATH) || bundle.containsKey(EXTRA_KEY_PRE_EXECUTE_SCRIPT); return bundle.containsKey(ScriptIntents.EXTRA_KEY_PATH) || bundle.containsKey(EXTRA_KEY_PRE_EXECUTE_SCRIPT);
} }

View File

@@ -6,7 +6,6 @@ import android.text.TextUtils;
import com.stardust.app.GlobalAppContext; import com.stardust.app.GlobalAppContext;
import org.autojs.autojs.Pref; import org.autojs.autojs.Pref;
import org.autojs.autojs.App;
import org.autojs.autojs.R; import org.autojs.autojs.R;
import com.stardust.autojs.core.accessibility.AccessibilityService; import com.stardust.autojs.core.accessibility.AccessibilityService;
@@ -36,12 +35,12 @@ public class AccessibilityServiceTool {
public static void goToAccessibilitySetting() { public static void goToAccessibilitySetting() {
Context context = GlobalAppContext.get(); Context context = GlobalAppContext.get();
if (Pref.isFirstGoToAccessibilitySetting()) { if (Pref.isFirstGoToAccessibilitySetting()) {
GlobalAppContext.toast(context.getString(R.string.text_please_choose) + context.getString(R.string._app_name)); GlobalAppContext.toast(context.getString(R.string.text_please_choose) + context.getString(R.string.app_name));
} }
try { try {
AccessibilityServiceUtils.INSTANCE.goToAccessibilitySetting(context); AccessibilityServiceUtils.INSTANCE.goToAccessibilitySetting(context);
} catch (ActivityNotFoundException e) { } catch (ActivityNotFoundException e) {
GlobalAppContext.toast(context.getString(R.string.go_to_accessibility_settings) + context.getString(R.string._app_name)); GlobalAppContext.toast(context.getString(R.string.go_to_accessibility_settings) + context.getString(R.string.app_name));
} }
} }

View File

@@ -158,7 +158,7 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
private void setUpToolbar() { private void setUpToolbar() {
Toolbar toolbar = $(R.id.toolbar); Toolbar toolbar = $(R.id.toolbar);
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
toolbar.setTitle(R.string._app_name); toolbar.setTitle(R.string.app_name);
ActionBarDrawerToggle drawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.text_drawer_open, ActionBarDrawerToggle drawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.text_drawer_open,
R.string.text_drawer_close); R.string.text_drawer_close);
drawerToggle.syncState(); drawerToggle.syncState();

View File

@@ -26,7 +26,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
android:theme="@style/ToolBarStyle" android:theme="@style/ToolBarStyle"
android:title="@string/_app_name" android:title="@string/app_name"
app:layout_scrollFlags="scroll|enterAlways" app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/AppTheme.PopupOverlay"/> app:popupTheme="@style/AppTheme.PopupOverlay"/>

View File

@@ -19,7 +19,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
app:popupTheme="@style/AppTheme.PopupOverlay" app:popupTheme="@style/AppTheme.PopupOverlay"
app:title="@string/_app_name"> app:title="@string/app_name">
</com.stardust.theme.widget.ThemeColorToolbar> </com.stardust.theme.widget.ThemeColorToolbar>

View File

@@ -17,7 +17,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:theme="@style/ToolBarStyle" android:theme="@style/ToolBarStyle"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
android:title="@string/_app_name" android:title="@string/app_name"
app:layout_scrollFlags="scroll|enterAlways" app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/AppTheme.PopupOverlay"/> app:popupTheme="@style/AppTheme.PopupOverlay"/>

View File

@@ -19,7 +19,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
app:popupTheme="@style/AppTheme.PopupOverlay" app:popupTheme="@style/AppTheme.PopupOverlay"
app:title="@string/_app_name"> app:title="@string/app_name">
</com.stardust.theme.widget.ThemeColorToolbar> </com.stardust.theme.widget.ThemeColorToolbar>

View File

@@ -19,7 +19,7 @@
android:theme="@style/ToolBarStyle" android:theme="@style/ToolBarStyle"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary" android:background="?attr/colorPrimary"
android:title="@string/_app_name" android:title="@string/app_name"
app:popupTheme="@style/AppTheme.PopupOverlay"> app:popupTheme="@style/AppTheme.PopupOverlay">
<LinearLayout <LinearLayout

View File

@@ -51,7 +51,7 @@
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:gravity="center" android:gravity="center"
android:minHeight="60dp" android:minHeight="60dp"
android:text="@string/_app_name" android:text="@string/app_name"
android:textColor="@android:color/primary_text_light"/> android:textColor="@android:color/primary_text_light"/>
</LinearLayout> </LinearLayout>

View File

@@ -17,7 +17,7 @@
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
android:theme="@style/ToolBarStyle" android:theme="@style/ToolBarStyle"
android:background="?attr/colorPrimary" android:background="?attr/colorPrimary"
android:title="@string/_app_name" android:title="@string/app_name"
app:popupTheme="@style/AppTheme.PopupOverlay"> app:popupTheme="@style/AppTheme.PopupOverlay">
<FrameLayout <FrameLayout

View File

@@ -1,5 +1,5 @@
<resources> <resources>
<string name="_app_name">Auto.js</string> <string name="app_name">Auto.js</string>
<string name="text_accessibility_service_description">Required by the script automatic operation (click, long press, slide, etc.).</string> <string name="text_accessibility_service_description">Required by the script automatic operation (click, long press, slide, etc.).</string>
<string name="text_new_file">New File</string> <string name="text_new_file">New File</string>
<string name="text_create_fail">Creation failed</string> <string name="text_create_fail">Creation failed</string>

View File

@@ -1,11 +1,11 @@
<resources> <resources>
<string name="_app_name">Auto.js</string> <string name="app_name">Auto.js</string>
<string name="text_new_file">新建文件</string> <string name="text_new_file">新建文件</string>
<string name="text_create_fail">创建失败</string> <string name="text_create_fail">创建失败</string>
<string name="text_please_input_name">请输入名称</string> <string name="text_please_input_name">请输入名称</string>
<string name="text_name">名称</string> <string name="text_name">名称</string>
<string name="text_go_to_setting">去设置</string> <string name="text_go_to_setting">去设置</string>
<string name="explain_accessibility_permission">软件需要打开\"无障碍服务\"才能运行,请在随后的设置中选择\"AutoJs\"并开启服务。\n您也可以稍后在侧拉菜单中设置。</string> <string name="explain_accessibility_permission">软件需要打开\"无障碍服务\"才能运行,请在随后的设置中选择\"Auto.js\"并开启服务。\n您也可以稍后在侧拉菜单中设置。</string>
<string name="text_cancel">取消</string> <string name="text_cancel">取消</string>
<string name="text_path_is_empty">路径为空</string> <string name="text_path_is_empty">路径为空</string>
<string name="text_file_not_exists">文件不存在</string> <string name="text_file_not_exists">文件不存在</string>
@@ -27,7 +27,7 @@
<string name="text_about">关于</string> <string name="text_about">关于</string>
<string name="text_licenses">开放源代码许可</string> <string name="text_licenses">开放源代码许可</string>
<string name="text_do_not_remind_again">不再提示</string> <string name="text_do_not_remind_again">不再提示</string>
<string name="copyright">Copyright©2016 All right reserves.</string> <string name="copyright">Copyright©2018-2019 All right reserves.</string>
<string name="developer">星尘幻影</string> <string name="developer">星尘幻影</string>
<string name="qq" translatable="false">2732014414</string> <string name="qq" translatable="false">2732014414</string>
<string name="email" translatable="false">hybbbb1996@gmail.com</string> <string name="email" translatable="false">hybbbb1996@gmail.com</string>
@@ -35,7 +35,7 @@
<string name="text_already_copy_to_clip">已复制到剪贴板</string> <string name="text_already_copy_to_clip">已复制到剪贴板</string>
<string name="donate_developer">打赏作者</string> <string name="donate_developer">打赏作者</string>
<string name="my_github">https://github.com/hyb1996/NoRootScriptDroid</string> <string name="my_github">https://github.com/hyb1996/NoRootScriptDroid</string>
<string name="share_app">[AutoJs]下载地址http://www.coolapk.com/apk/org.autojs.autojs </string> <string name="share_app">[Auto.js]下载地址http://www.coolapk.com/apk/org.autojs.autojs </string>
<string name="text_floating_window">悬浮窗</string> <string name="text_floating_window">悬浮窗</string>
<string name="text_error_report">错误报告</string> <string name="text_error_report">错误报告</string>
<string name="text_press_again_to_exit">再按一次退出程序</string> <string name="text_press_again_to_exit">再按一次退出程序</string>
@@ -99,7 +99,7 @@
<string name="text_import_succeed">导入成功</string> <string name="text_import_succeed">导入成功</string>
<string name="text_current_activity">当前活动:</string> <string name="text_current_activity">当前活动:</string>
<string name="text_current_package">当前应用包名:</string> <string name="text_current_package">当前应用包名:</string>
<string name="go_to_accessibility_settings"><![CDATA[请打开设置->无障碍服务->AutoJs并开启]]></string> <string name="go_to_accessibility_settings"><![CDATA[请打开设置->无障碍服务->Auto.js并开启]]></string>
<string name="text_script_running">脚本运行</string> <string name="text_script_running">脚本运行</string>
<string name="key_use_volume_control_running">key_use_volume_control_running</string> <string name="key_use_volume_control_running">key_use_volume_control_running</string>
<string name="text_use_volume_to_stop_running">音量上键停止所有脚本</string> <string name="text_use_volume_to_stop_running">音量上键停止所有脚本</string>

View File

@@ -32,7 +32,7 @@
<service <service
android:name="com.stardust.autojs.core.accessibility.AccessibilityService" android:name="com.stardust.autojs.core.accessibility.AccessibilityService"
android:label="@string/_app_name" android:label="@string/app_name"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"> android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter> <intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService"/> <action android:name="android.accessibilityservice.AccessibilityService"/>

View File

@@ -5,15 +5,12 @@ import android.view.View;
import com.stardust.autojs.BuildConfig; import com.stardust.autojs.BuildConfig;
import com.stardust.autojs.core.ui.ViewExtras; import com.stardust.autojs.core.ui.ViewExtras;
import com.stardust.autojs.rhino.NativeJavaObjectWithPrototype; import com.stardust.autojs.engine.module.AssetAndUrlModuleSourceProvider;
import com.stardust.autojs.rhino.RhinoAndroidHelper; import com.stardust.autojs.rhino.RhinoAndroidHelper;
import com.stardust.autojs.rhino.TokenStream;
import com.stardust.autojs.rhino.TopLevelScope; import com.stardust.autojs.rhino.TopLevelScope;
import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.autojs.runtime.ScriptRuntime;
import com.stardust.autojs.script.JavaScriptSource; import com.stardust.autojs.script.JavaScriptSource;
import com.stardust.autojs.script.StringScriptSource;
import com.stardust.automator.UiObjectCollection; import com.stardust.automator.UiObjectCollection;
import com.stardust.pio.PFiles;
import com.stardust.pio.UncheckedIOException; import com.stardust.pio.UncheckedIOException;
import org.mozilla.javascript.Context; import org.mozilla.javascript.Context;

View File

@@ -0,0 +1,14 @@
package com.stardust.autojs.engine.encryption
import com.stardust.util.AdvancedEncryptionStandard
object ScriptEncryption {
private var mKey = ""
private var mInitVector = ""
fun decrypt(bytes: ByteArray, start: Int = 0, end: Int = bytes.size): ByteArray {
return AdvancedEncryptionStandard(mKey.toByteArray(), mInitVector).decrypt(bytes, start, end)
}
}

View File

@@ -1,20 +1,21 @@
package com.stardust.autojs.engine; package com.stardust.autojs.engine.module;
import android.content.res.AssetManager; import android.content.res.AssetManager;
import android.net.Uri;
import org.mozilla.javascript.Scriptable; import com.stardust.autojs.engine.encryption.ScriptEncryption;
import com.stardust.autojs.script.EncryptedScriptFileHeader;
import org.mozilla.javascript.commonjs.module.provider.ModuleSource; import org.mozilla.javascript.commonjs.module.provider.ModuleSource;
import org.mozilla.javascript.commonjs.module.provider.UrlModuleSourceProvider;
import java.io.File; import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.util.Arrays; import java.net.URLConnection;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
@@ -49,4 +50,17 @@ public class AssetAndUrlModuleSourceProvider extends UrlModuleSourceProvider {
return super.loadFromPrivilegedLocations(moduleId, validator); return super.loadFromPrivilegedLocations(moduleId, validator);
} }
} }
@Override
protected Reader getReader(URLConnection urlConnection) throws IOException {
InputStream stream = urlConnection.getInputStream();
byte[] bytes = new byte[stream.available()];
stream.read(bytes);
stream.close();
if (EncryptedScriptFileHeader.INSTANCE.isValidFile(bytes)) {
byte[] clearText = ScriptEncryption.INSTANCE.decrypt(bytes, EncryptedScriptFileHeader.BLOCK_SIZE, bytes.length);
return new InputStreamReader(new ByteArrayInputStream(clearText));
}
return new InputStreamReader(new ByteArrayInputStream(bytes));
}
} }

View File

@@ -0,0 +1,364 @@
package com.stardust.autojs.engine.module;
import org.mozilla.javascript.commonjs.module.provider.DefaultUrlConnectionExpiryCalculator;
import org.mozilla.javascript.commonjs.module.provider.ModuleSource;
import org.mozilla.javascript.commonjs.module.provider.ModuleSourceProviderBase;
import org.mozilla.javascript.commonjs.module.provider.ParsedContentType;
import org.mozilla.javascript.commonjs.module.provider.UrlConnectionExpiryCalculator;
import org.mozilla.javascript.commonjs.module.provider.UrlConnectionSecurityDomainProvider;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.Serializable;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Iterator;
import java.util.List;
/**
* A URL-based script provider that can load modules against a set of base
* privileged and fallback URIs. It is deliberately not named "URI provider"
* but a "URL provider" since it actually only works against those URIs that
* are URLs (and the JRE has a protocol handler for them). It creates cache
* validators that are suitable for use with both file: and http: URL
* protocols. Specifically, it is able to use both last-modified timestamps and
* ETags for cache revalidation, and follows the HTTP cache expiry calculation
* model, and allows for fallback heuristic expiry calculation when no server
* specified expiry is provided.
*
* @author Attila Szegedi
* @version $Id: UrlModuleSourceProvider.java,v 1.4 2011/04/07 20:26:12 hannes%helma.at Exp $
*/
public class UrlModuleSourceProvider extends ModuleSourceProviderBase {
private static final long serialVersionUID = 1L;
private final Iterable<URI> privilegedUris;
private final Iterable<URI> fallbackUris;
private final UrlConnectionSecurityDomainProvider
urlConnectionSecurityDomainProvider;
private final UrlConnectionExpiryCalculator urlConnectionExpiryCalculator;
/**
* Creates a new module script provider that loads modules against a set of
* privileged and fallback URIs. It will use a fixed default cache expiry
* of 60 seconds, and provide no security domain objects for the resource.
*
* @param privilegedUris an iterable providing the privileged URIs. Can be
* null if no privileged URIs are used.
* @param fallbackUris an iterable providing the fallback URIs. Can be
* null if no fallback URIs are used.
*/
public UrlModuleSourceProvider(Iterable<URI> privilegedUris,
Iterable<URI> fallbackUris) {
this(privilegedUris, fallbackUris,
new DefaultUrlConnectionExpiryCalculator(), null);
}
/**
* Creates a new module script provider that loads modules against a set of
* privileged and fallback URIs. It will use the specified heuristic cache
* expiry calculator and security domain provider.
*
* @param privilegedUris an iterable providing the privileged URIs. Can be
* null if no privileged URIs are used.
* @param fallbackUris an iterable providing the fallback URIs. Can be
* null if no fallback URIs are used.
* @param urlConnectionExpiryCalculator the calculator object for heuristic
* calculation of the resource expiry, used when no expiry is provided by
* the server of the resource. Can be null, in which case the maximum age
* of cached entries without validation will be zero.
* @param urlConnectionSecurityDomainProvider object that provides security
* domain objects for the loaded sources. Can be null, in which case the
* loaded sources will have no security domain associated with them.
*/
public UrlModuleSourceProvider(Iterable<URI> privilegedUris,
Iterable<URI> fallbackUris,
UrlConnectionExpiryCalculator urlConnectionExpiryCalculator,
UrlConnectionSecurityDomainProvider urlConnectionSecurityDomainProvider) {
this.privilegedUris = privilegedUris;
this.fallbackUris = fallbackUris;
this.urlConnectionExpiryCalculator = urlConnectionExpiryCalculator;
this.urlConnectionSecurityDomainProvider =
urlConnectionSecurityDomainProvider;
}
@Override
protected ModuleSource loadFromPrivilegedLocations(
String moduleId, Object validator)
throws IOException, URISyntaxException {
return loadFromPathList(moduleId, validator, privilegedUris);
}
@Override
protected ModuleSource loadFromFallbackLocations(
String moduleId, Object validator)
throws IOException, URISyntaxException {
return loadFromPathList(moduleId, validator, fallbackUris);
}
private ModuleSource loadFromPathList(String moduleId,
Object validator, Iterable<URI> paths)
throws IOException, URISyntaxException {
if (paths == null) {
return null;
}
for (URI path : paths) {
final ModuleSource moduleSource = loadFromUri(
path.resolve(moduleId), path, validator);
if (moduleSource != null) {
return moduleSource;
}
}
return null;
}
@Override
protected ModuleSource loadFromUri(URI uri, URI base, Object validator)
throws IOException, URISyntaxException {
// We expect modules to have a ".js" file name extension ...
URI fullUri = new URI(uri + ".js");
ModuleSource source = loadFromActualUri(fullUri, base, validator);
// ... but for compatibility we support modules without extension,
// or ids with explicit extension.
return source != null ?
source : loadFromActualUri(uri, base, validator);
}
protected ModuleSource loadFromActualUri(URI uri, URI base, Object validator)
throws IOException {
final URL url = new URL(base == null ? null : base.toURL(), uri.toString());
final long request_time = System.currentTimeMillis();
final URLConnection urlConnection = openUrlConnection(url);
final URLValidator applicableValidator;
if (validator instanceof URLValidator) {
final URLValidator uriValidator = ((URLValidator) validator);
applicableValidator = uriValidator.appliesTo(uri) ? uriValidator :
null;
} else {
applicableValidator = null;
}
if (applicableValidator != null) {
applicableValidator.applyConditionals(urlConnection);
}
try {
urlConnection.connect();
if (applicableValidator != null &&
applicableValidator.updateValidator(urlConnection,
request_time, urlConnectionExpiryCalculator)) {
close(urlConnection);
return NOT_MODIFIED;
}
return new ModuleSource(getReader(urlConnection),
getSecurityDomain(urlConnection), uri, base,
new URLValidator(uri, urlConnection, request_time,
urlConnectionExpiryCalculator));
} catch (FileNotFoundException e) {
return null;
} catch (RuntimeException e) {
close(urlConnection);
throw e;
} catch (IOException e) {
close(urlConnection);
throw e;
}
}
protected Reader getReader(URLConnection urlConnection)
throws IOException {
return new InputStreamReader(urlConnection.getInputStream(),
getCharacterEncoding(urlConnection));
}
protected String getCharacterEncoding(URLConnection urlConnection) {
final ParsedContentType pct = new ParsedContentType(
urlConnection.getContentType());
final String encoding = pct.getEncoding();
if (encoding != null) {
return encoding;
}
final String contentType = pct.getContentType();
if (contentType != null && contentType.startsWith("text/")) {
return "8859_1";
}
return "utf-8";
}
protected Object getSecurityDomain(URLConnection urlConnection) {
return urlConnectionSecurityDomainProvider == null ? null :
urlConnectionSecurityDomainProvider.getSecurityDomain(
urlConnection);
}
private void close(URLConnection urlConnection) {
try {
urlConnection.getInputStream().close();
} catch (IOException e) {
onFailedClosingUrlConnection(urlConnection, e);
}
}
/**
* Override if you want to get notified if the URL connection fails to
* close. Does nothing by default.
*
* @param urlConnection the connection
* @param cause the cause it failed to close.
*/
protected void onFailedClosingUrlConnection(URLConnection urlConnection,
IOException cause) {
}
/**
* Can be overridden in subclasses to customize the URL connection opening
* process. By default, just calls {@link URL#openConnection()}.
*
* @param url the URL
* @return a connection to the URL.
* @throws IOException if an I/O error occurs.
*/
protected URLConnection openUrlConnection(URL url) throws IOException {
return url.openConnection();
}
@Override
protected boolean entityNeedsRevalidation(Object validator) {
return !(validator instanceof URLValidator)
|| ((URLValidator) validator).entityNeedsRevalidation();
}
private static class URLValidator implements Serializable {
private static final long serialVersionUID = 1L;
private final URI uri;
private final long lastModified;
private final String entityTags;
private long expiry;
public URLValidator(URI uri, URLConnection urlConnection,
long request_time, UrlConnectionExpiryCalculator
urlConnectionExpiryCalculator) {
this.uri = uri;
this.lastModified = urlConnection.getLastModified();
this.entityTags = getEntityTags(urlConnection);
expiry = calculateExpiry(urlConnection, request_time,
urlConnectionExpiryCalculator);
}
boolean updateValidator(URLConnection urlConnection, long request_time,
UrlConnectionExpiryCalculator urlConnectionExpiryCalculator)
throws IOException {
boolean isResourceChanged = isResourceChanged(urlConnection);
if (!isResourceChanged) {
expiry = calculateExpiry(urlConnection, request_time,
urlConnectionExpiryCalculator);
}
return isResourceChanged;
}
private boolean isResourceChanged(URLConnection urlConnection)
throws IOException {
if (urlConnection instanceof HttpURLConnection) {
return ((HttpURLConnection) urlConnection).getResponseCode() ==
HttpURLConnection.HTTP_NOT_MODIFIED;
}
return lastModified != urlConnection.getLastModified();
}
private long calculateExpiry(URLConnection urlConnection,
long request_time, UrlConnectionExpiryCalculator
urlConnectionExpiryCalculator) {
if ("no-cache".equals(urlConnection.getHeaderField("Pragma"))) {
return 0L;
}
final String cacheControl = urlConnection.getHeaderField(
"Cache-Control");
if (cacheControl != null) {
if (cacheControl.indexOf("no-cache") != -1) {
return 0L;
}
final int max_age = getMaxAge(cacheControl);
if (-1 != max_age) {
final long response_time = System.currentTimeMillis();
final long apparent_age = Math.max(0, response_time -
urlConnection.getDate());
final long corrected_received_age = Math.max(apparent_age,
urlConnection.getHeaderFieldInt("Age", 0) * 1000L);
final long response_delay = response_time - request_time;
final long corrected_initial_age = corrected_received_age +
response_delay;
final long creation_time = response_time -
corrected_initial_age;
return max_age * 1000L + creation_time;
}
}
final long explicitExpiry = urlConnection.getHeaderFieldDate(
"Expires", -1L);
if (explicitExpiry != -1L) {
return explicitExpiry;
}
return urlConnectionExpiryCalculator == null ? 0L :
urlConnectionExpiryCalculator.calculateExpiry(urlConnection);
}
private int getMaxAge(String cacheControl) {
final int maxAgeIndex = cacheControl.indexOf("max-age");
if (maxAgeIndex == -1) {
return -1;
}
final int eq = cacheControl.indexOf('=', maxAgeIndex + 7);
if (eq == -1) {
return -1;
}
final int comma = cacheControl.indexOf(',', eq + 1);
final String strAge;
if (comma == -1) {
strAge = cacheControl.substring(eq + 1);
} else {
strAge = cacheControl.substring(eq + 1, comma);
}
try {
return Integer.parseInt(strAge);
} catch (NumberFormatException e) {
return -1;
}
}
private String getEntityTags(URLConnection urlConnection) {
final List<String> etags = urlConnection.getHeaderFields().get("ETag");
if (etags == null || etags.isEmpty()) {
return null;
}
final StringBuilder b = new StringBuilder();
final Iterator<String> it = etags.iterator();
b.append(it.next());
while (it.hasNext()) {
b.append(", ").append(it.next());
}
return b.toString();
}
boolean appliesTo(URI uri) {
return this.uri.equals(uri);
}
void applyConditionals(URLConnection urlConnection) {
if (lastModified != 0L) {
urlConnection.setIfModifiedSince(lastModified);
}
if (entityTags != null && entityTags.length() > 0) {
urlConnection.addRequestProperty("If-None-Match", entityTags);
}
}
boolean entityNeedsRevalidation() {
return System.currentTimeMillis() > expiry;
}
}
}

View File

@@ -12,7 +12,9 @@ data class ExecutionConfig(var workingDirectory: String = "",
var intentFlags: Int = 0, var intentFlags: Int = 0,
var delay: Long = 0, var delay: Long = 0,
var interval: Long = 0, var interval: Long = 0,
var loopTimes: Int = 1) : Parcelable { var loopTimes: Int = 1,
var uiMode: Boolean = false,
var features: Int = 0) : Parcelable {
private val mArguments = HashMap<String, Any>() private val mArguments = HashMap<String, Any>()
@@ -79,13 +81,16 @@ data class ExecutionConfig(var workingDirectory: String = "",
companion object CREATOR : Parcelable.Creator<ExecutionConfig> { companion object CREATOR : Parcelable.Creator<ExecutionConfig> {
@JvmStatic @JvmStatic
val tag = "execution.config" val tag = "execution.config"
@JvmStatic @JvmStatic
val default: ExecutionConfig val default: ExecutionConfig
get() = ExecutionConfig() get() = ExecutionConfig()
@JvmStatic
val featureContinuation = 1
override fun createFromParcel(parcel: Parcel): ExecutionConfig { override fun createFromParcel(parcel: Parcel): ExecutionConfig {
return ExecutionConfig(parcel) return ExecutionConfig(parcel)
} }

View File

@@ -118,8 +118,8 @@ public class ScriptExecuteActivity extends AppCompatActivity {
private void prepare() { private void prepare() {
mScriptEngine.put("activity", this); mScriptEngine.put("activity", this);
mScriptEngine.setTag("activity", this); mScriptEngine.setTag("activity", this);
mScriptEngine.setTag(ScriptEngine.TAG_ENV_PATH, mScriptExecution.getConfig().getWorkingDirectory()); mScriptEngine.setTag(ScriptEngine.TAG_ENV_PATH, mScriptExecution.getConfig().getPath());
mScriptEngine.setTag(ScriptEngine.TAG_WORKING_DIRECTORY, mScriptExecution.getConfig().getPath()); mScriptEngine.setTag(ScriptEngine.TAG_WORKING_DIRECTORY, mScriptExecution.getConfig().getWorkingDirectory());
mScriptEngine.init(); mScriptEngine.init();
} }

View File

@@ -0,0 +1,47 @@
package com.stardust.autojs.script
import java.io.File
import java.io.FileInputStream
import java.io.OutputStream
object EncryptedScriptFileHeader {
const val FLAG_INVALID_FILE: Short = Short.MIN_VALUE
const val FLAG_EXECUTION_MODE_UI: Short = 0x0001
const val FLAG_EXECUTION_MODE_AUTO: Short = 0x0002
const val BLOCK_SIZE = 8
private val BLOCK = byteArrayOf(0x77, 0x01, 0x17, 0x7F, 0x12, 0x12)
fun getHeaderFlags(file: File): Short {
val fis = FileInputStream(file)
val bytes = ByteArray(BLOCK_SIZE)
if (fis.read(bytes) < BLOCK_SIZE) {
return FLAG_INVALID_FILE
}
if (!isValidFile(bytes)) {
return FLAG_INVALID_FILE
}
return (bytes[BLOCK.size].toShort() * 256 + bytes[BLOCK.size + 1]).toShort()
}
fun isValidFile(bytes: ByteArray): Boolean {
for (i in 0 until BLOCK.size) {
if (bytes[i] != BLOCK[i]) {
return false
}
}
return true
}
fun writeHeader(os: OutputStream, flags: Short = 0) {
os.write(BLOCK)
val byte6 = flags / 256
val byte7 = flags % 256
os.write(byte6)
os.write(byte7)
}
}

View File

@@ -43,6 +43,15 @@ public class JavaScriptFileSource extends JavaScriptSource {
return mScript; return mScript;
} }
@Override
protected int parseExecutionMode() {
short flags = EncryptedScriptFileHeader.INSTANCE.getHeaderFlags(mFile);
if (flags == EncryptedScriptFileHeader.FLAG_INVALID_FILE) {
return super.parseExecutionMode();
}
return flags;
}
@Override @Override
public Reader getScriptReader() { public Reader getScriptReader() {
try { try {

View File

@@ -1,10 +1,15 @@
package com.stardust.autojs.script; package com.stardust.autojs.script;
import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.stardust.autojs.rhino.TokenStream;
import com.stardust.util.MapBuilder; import com.stardust.util.MapBuilder;
import org.mozilla.javascript.Token;
import java.io.Reader; import java.io.Reader;
import java.io.StringReader; import java.io.StringReader;
import java.util.Map; import java.util.Map;
@@ -23,11 +28,13 @@ public abstract class JavaScriptSource extends ScriptSource {
public static final int EXECUTION_MODE_UI = 0x00000001; public static final int EXECUTION_MODE_UI = 0x00000001;
public static final int EXECUTION_MODE_AUTO = 0x00000002; public static final int EXECUTION_MODE_AUTO = 0x00000002;
private static final String LOG_TAG = "JavaScriptSource";
private static final Map<String, Integer> EXECUTION_MODES = new MapBuilder<String, Integer>() private static final Map<String, Integer> EXECUTION_MODES = new MapBuilder<String, Integer>()
.put("ui", EXECUTION_MODE_UI) .put("ui", EXECUTION_MODE_UI)
.put("auto", EXECUTION_MODE_AUTO) .put("auto", EXECUTION_MODE_AUTO)
.build(); .build();
private static final int EXECUTION_MODE_STRING_MAX_LENGTH = 7; private static final int PARSING_MAX_TOKEN = 300;
private int mExecutionMode = -1; private int mExecutionMode = -1;
@@ -57,20 +64,35 @@ public abstract class JavaScriptSource extends ScriptSource {
public int getExecutionMode() { public int getExecutionMode() {
if (mExecutionMode == -1) { if (mExecutionMode == -1) {
mExecutionMode = parseExecutionMode(getScript()); mExecutionMode = parseExecutionMode();
} }
return mExecutionMode; return mExecutionMode;
} }
private int parseExecutionMode(String script) { protected int parseExecutionMode() {
if (script == null || script.length() == 0) String script = getScript();
return EXECUTION_MODE_NORMAL; TokenStream ts = new TokenStream(new StringReader(script), null, 1);
if(script.charAt(0) == '"'){ int token;
int i = script.lastIndexOf("\";", EXECUTION_MODE_STRING_MAX_LENGTH + 2); int count = 0;
if (i >= 0){ try {
String modeString = script.substring(1, i); while (count <= PARSING_MAX_TOKEN && (token = ts.getToken()) != Token.EOF) {
return parseExecutionMode(modeString.split(" ")); count++;
if (token == Token.EOL || token == Token.COMMENT) {
continue;
}
if (token == Token.STRING && ts.getTokenLength() > 2) {
String tokenString = script.substring(ts.getTokenBeg() + 1, ts.getTokenEnd() - 1);
if (ts.getToken() != Token.SEMI) {
break;
}
Log.d(LOG_TAG, "string = " + tokenString);
return parseExecutionMode(tokenString.split(" "));
}
break;
} }
} catch (Exception e) {
e.printStackTrace();
return EXECUTION_MODE_NORMAL;
} }
return EXECUTION_MODE_NORMAL; return EXECUTION_MODE_NORMAL;

View File

@@ -1,10 +1,9 @@
package com.stardust.autojs.script; package com.stardust.autojs.script;
import android.content.Context; import android.content.Context;
import android.util.Log;
import android.view.View; import android.view.View;
import com.stardust.autojs.engine.AssetAndUrlModuleSourceProvider; import com.stardust.autojs.engine.module.AssetAndUrlModuleSourceProvider;
import com.stardust.pio.PFiles; import com.stardust.pio.PFiles;
import com.stardust.pio.UncheckedIOException; import com.stardust.pio.UncheckedIOException;
@@ -18,7 +17,6 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Collections; import java.util.Collections;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;

View File

@@ -1,5 +1,5 @@
<resources> <resources>
<string name="app_name">AutoJs</string> <string name="app_name">Auto.js</string>
<string name="text_error">Error:</string> <string name="text_error">Error:</string>
<string name="text_start_running">Script Running</string> <string name="text_start_running">Script Running</string>
<string name="text_path_is_empty">Path is empty</string> <string name="text_path_is_empty">Path is empty</string>
@@ -13,7 +13,6 @@
<string name="text_console">Console</string> <string name="text_console">Console</string>
<string name="text_no_floating_window_permission">No drawing overlay permission</string> <string name="text_no_floating_window_permission">No drawing overlay permission</string>
<string name="text_accessibility_service_description">Auto.js</string> <string name="text_accessibility_service_description">Auto.js</string>
<string name="_app_name">AutoJs</string>
<string name="text_should_enable_key_observing">Key observing is disabled, please enable in settings</string> <string name="text_should_enable_key_observing">Key observing is disabled, please enable in settings</string>
<string name="no_write_settings_permissin">No writing settings permission</string> <string name="no_write_settings_permissin">No writing settings permission</string>
<string name="exception_notification_service_disabled">通知服务未运行,请重新启用通知权限</string> <string name="exception_notification_service_disabled">通知服务未运行,请重新启用通知权限</string>

View File

@@ -1,5 +1,5 @@
<resources> <resources>
<string name="app_name">AutoJs</string> <string name="app_name">Auto.js</string>
<string name="text_error">错误:</string> <string name="text_error">错误:</string>
<string name="text_start_running">开始运行</string> <string name="text_start_running">开始运行</string>
<string name="text_path_is_empty">路径为空</string> <string name="text_path_is_empty">路径为空</string>
@@ -13,7 +13,6 @@
<string name="text_console">控制台</string> <string name="text_console">控制台</string>
<string name="text_no_floating_window_permission">没有悬浮窗权限</string> <string name="text_no_floating_window_permission">没有悬浮窗权限</string>
<string name="text_accessibility_service_description">使脚本自动操作(点击、长按、滑动等)所需,若关闭则只能执行不涉及自动操作的脚本。</string> <string name="text_accessibility_service_description">使脚本自动操作(点击、长按、滑动等)所需,若关闭则只能执行不涉及自动操作的脚本。</string>
<string name="_app_name">AutoJs</string>
<string name="text_should_enable_key_observing">按键监听未启用,请在软件设置中开启</string> <string name="text_should_enable_key_observing">按键监听未启用,请在软件设置中开启</string>
<string name="text_should_enable_gesture_observing">手势监听未启用,请在软件设置中开启</string> <string name="text_should_enable_gesture_observing">手势监听未启用,请在软件设置中开启</string>
<string name="no_write_settings_permissin">沒有修改系統设置权限</string> <string name="no_write_settings_permissin">沒有修改系統设置权限</string>

View File

@@ -31,7 +31,7 @@ class AdvancedEncryptionStandard(private val key: ByteArray, private val initVec
val ivParameterSpec = IvParameterSpec(initVector.toByteArray()) val ivParameterSpec = IvParameterSpec(initVector.toByteArray())
val cipher = Cipher.getInstance(FULL_ALGORITHM) val cipher = Cipher.getInstance(FULL_ALGORITHM)
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec) cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec)
return cipher.doFinal(cipherText, start, end) return cipher.doFinal(cipherText, start, end - start)
} }
companion object { companion object {

View File

@@ -23,8 +23,6 @@ import java.lang.IllegalStateException
*/ */
class AutoJs private constructor(application: Application) : com.stardust.autojs.AutoJs(application) { class AutoJs private constructor(application: Application) : com.stardust.autojs.AutoJs(application) {
private var mKey = ""
private var mInitVector = ""
init { init {
scriptEngineService.registerGlobalScriptExecutionListener(ScriptExecutionGlobalListener()) scriptEngineService.registerGlobalScriptExecutionListener(ScriptExecutionGlobalListener())
@@ -85,7 +83,6 @@ class AutoJs private constructor(application: Application) : com.stardust.autojs
super.initScriptEngineManager() super.initScriptEngineManager()
scriptEngineManager.registerEngine(JavaScriptSource.ENGINE) { scriptEngineManager.registerEngine(JavaScriptSource.ENGINE) {
val engine = XJavaScriptEngine(application) val engine = XJavaScriptEngine(application)
engine.setKey(mKey, mInitVector)
engine.runtime = createRuntime() engine.runtime = createRuntime()
engine engine
} }
@@ -98,11 +95,6 @@ class AutoJs private constructor(application: Application) : com.stardust.autojs
return runtime return runtime
} }
fun setKey(key: String, vet: String) {
mKey = key
mInitVector = vet
}
companion object { companion object {
@SuppressLint("StaticFieldLeak") @SuppressLint("StaticFieldLeak")

View File

@@ -20,7 +20,7 @@ class ScriptExecutionGlobalListener : ScriptExecutionListener {
} }
private fun onFinish(execution: ScriptExecution) { private fun onFinish(execution: ScriptExecution) {
val millis = execution.engine.getTag(ENGINE_TAG_START_TIME) as Long ?: return val millis = execution.engine.getTag(ENGINE_TAG_START_TIME) as Long? ?: return
val seconds = (System.currentTimeMillis() - millis) / 1000.0 val seconds = (System.currentTimeMillis() - millis) / 1000.0
AutoJs.instance.scriptEngineService.globalConsole AutoJs.instance.scriptEngineService.globalConsole
.verbose(GlobalAppContext.getString(R.string.text_execution_finished), execution.source.toString(), seconds) .verbose(GlobalAppContext.getString(R.string.text_execution_finished), execution.source.toString(), seconds)

View File

@@ -2,20 +2,17 @@ package com.stardust.auojs.inrt.autojs
import android.content.Context import android.content.Context
import com.stardust.autojs.engine.LoopBasedJavaScriptEngine import com.stardust.autojs.engine.LoopBasedJavaScriptEngine
import com.stardust.autojs.engine.encryption.ScriptEncryption
import com.stardust.autojs.script.EncryptedScriptFileHeader
import com.stardust.autojs.script.JavaScriptFileSource import com.stardust.autojs.script.JavaScriptFileSource
import com.stardust.autojs.script.ScriptSource import com.stardust.autojs.script.ScriptSource
import com.stardust.autojs.script.StringScriptSource import com.stardust.autojs.script.StringScriptSource
import com.stardust.pio.PFiles import com.stardust.pio.PFiles
import com.stardust.util.AdvancedEncryptionStandard
import java.io.File import java.io.File
import java.lang.Exception
import java.lang.IllegalStateException
import java.security.GeneralSecurityException import java.security.GeneralSecurityException
class XJavaScriptEngine(context: Context) : LoopBasedJavaScriptEngine(context) { class XJavaScriptEngine(context: Context) : LoopBasedJavaScriptEngine(context) {
private var mKey = ""
private var mInitVector = ""
override fun execute(source: ScriptSource, callback: ExecuteCallback?) { override fun execute(source: ScriptSource, callback: ExecuteCallback?) {
if (source is JavaScriptFileSource) { if (source is JavaScriptFileSource) {
@@ -32,17 +29,10 @@ class XJavaScriptEngine(context: Context) : LoopBasedJavaScriptEngine(context) {
private fun execute(file: File) { private fun execute(file: File) {
val bytes = PFiles.readBytes(file.path) val bytes = PFiles.readBytes(file.path)
try { try {
val source = AdvancedEncryptionStandard(mKey.toByteArray(), mInitVector).decrypt(bytes) super.execute(StringScriptSource(file.name, String(ScriptEncryption.decrypt(bytes, EncryptedScriptFileHeader.BLOCK_SIZE))))
super.execute(StringScriptSource(file.name, String(source)))
} catch (e: GeneralSecurityException) { } catch (e: GeneralSecurityException) {
e.printStackTrace() e.printStackTrace()
} }
} }
fun setKey(key: String, initVector: String) {
mKey = key
mInitVector = initVector
}
} }

View File

@@ -11,6 +11,7 @@ import com.stardust.auojs.inrt.BuildConfig
import com.stardust.auojs.inrt.LogActivity import com.stardust.auojs.inrt.LogActivity
import com.stardust.auojs.inrt.Pref import com.stardust.auojs.inrt.Pref
import com.stardust.auojs.inrt.autojs.AutoJs import com.stardust.auojs.inrt.autojs.AutoJs
import com.stardust.autojs.engine.encryption.ScriptEncryption
import com.stardust.autojs.execution.ExecutionConfig import com.stardust.autojs.execution.ExecutionConfig
import com.stardust.autojs.execution.ScriptExecution import com.stardust.autojs.execution.ScriptExecution
import com.stardust.autojs.project.ProjectConfig import com.stardust.autojs.project.ProjectConfig
@@ -101,12 +102,12 @@ open class AssetsProjectLauncher(private val mAssetsProjectDir: String, private
val key = MD5.md5(projectConfig.packageName + projectConfig.versionName + projectConfig.mainScriptFile) val key = MD5.md5(projectConfig.packageName + projectConfig.versionName + projectConfig.mainScriptFile)
val vec = MD5.md5(projectConfig.buildInfo.buildId + projectConfig.name).substring(0, 16) val vec = MD5.md5(projectConfig.buildInfo.buildId + projectConfig.name).substring(0, 16)
try { try {
val fieldKey = AutoJs::class.java.getDeclaredField("mKey") val fieldKey = ScriptEncryption::class.java.getDeclaredField("mKey")
fieldKey.isAccessible = true fieldKey.isAccessible = true
fieldKey.set(AutoJs.instance, key) fieldKey.set(null, key)
val fieldVector = AutoJs::class.java.getDeclaredField("mInitVector") val fieldVector = ScriptEncryption::class.java.getDeclaredField("mInitVector")
fieldVector.isAccessible = true fieldVector.isAccessible = true
fieldVector.set(AutoJs.instance, vec) fieldVector.set(null, vec)
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
} }