修复 打包后ui脚本无法运行的问题
修复 打包后模块无法运行的问题
This commit is contained in:
@@ -32,7 +32,7 @@
|
||||
|
||||
<service
|
||||
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">
|
||||
<intent-filter>
|
||||
<action android:name="android.accessibilityservice.AccessibilityService"/>
|
||||
|
||||
@@ -5,15 +5,12 @@ import android.view.View;
|
||||
|
||||
import com.stardust.autojs.BuildConfig;
|
||||
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.TokenStream;
|
||||
import com.stardust.autojs.rhino.TopLevelScope;
|
||||
import com.stardust.autojs.runtime.ScriptRuntime;
|
||||
import com.stardust.autojs.script.JavaScriptSource;
|
||||
import com.stardust.autojs.script.StringScriptSource;
|
||||
import com.stardust.automator.UiObjectCollection;
|
||||
import com.stardust.pio.PFiles;
|
||||
import com.stardust.pio.UncheckedIOException;
|
||||
|
||||
import org.mozilla.javascript.Context;
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,20 +1,21 @@
|
||||
package com.stardust.autojs.engine;
|
||||
package com.stardust.autojs.engine.module;
|
||||
|
||||
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.UrlModuleSourceProvider;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.net.URLConnection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -49,4 +50,17 @@ public class AssetAndUrlModuleSourceProvider extends UrlModuleSourceProvider {
|
||||
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));
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,9 @@ data class ExecutionConfig(var workingDirectory: String = "",
|
||||
var intentFlags: Int = 0,
|
||||
var delay: 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>()
|
||||
@@ -79,13 +81,16 @@ data class ExecutionConfig(var workingDirectory: String = "",
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<ExecutionConfig> {
|
||||
|
||||
@JvmStatic
|
||||
val tag = "execution.config"
|
||||
@JvmStatic
|
||||
val tag = "execution.config"
|
||||
|
||||
@JvmStatic
|
||||
val default: ExecutionConfig
|
||||
get() = ExecutionConfig()
|
||||
|
||||
@JvmStatic
|
||||
val featureContinuation = 1
|
||||
|
||||
override fun createFromParcel(parcel: Parcel): ExecutionConfig {
|
||||
return ExecutionConfig(parcel)
|
||||
}
|
||||
|
||||
@@ -118,8 +118,8 @@ public class ScriptExecuteActivity extends AppCompatActivity {
|
||||
private void prepare() {
|
||||
mScriptEngine.put("activity", this);
|
||||
mScriptEngine.setTag("activity", this);
|
||||
mScriptEngine.setTag(ScriptEngine.TAG_ENV_PATH, mScriptExecution.getConfig().getWorkingDirectory());
|
||||
mScriptEngine.setTag(ScriptEngine.TAG_WORKING_DIRECTORY, mScriptExecution.getConfig().getPath());
|
||||
mScriptEngine.setTag(ScriptEngine.TAG_ENV_PATH, mScriptExecution.getConfig().getPath());
|
||||
mScriptEngine.setTag(ScriptEngine.TAG_WORKING_DIRECTORY, mScriptExecution.getConfig().getWorkingDirectory());
|
||||
mScriptEngine.init();
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -43,6 +43,15 @@ public class JavaScriptFileSource extends JavaScriptSource {
|
||||
return mScript;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int parseExecutionMode() {
|
||||
short flags = EncryptedScriptFileHeader.INSTANCE.getHeaderFlags(mFile);
|
||||
if (flags == EncryptedScriptFileHeader.FLAG_INVALID_FILE) {
|
||||
return super.parseExecutionMode();
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Reader getScriptReader() {
|
||||
try {
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
package com.stardust.autojs.script;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.stardust.autojs.rhino.TokenStream;
|
||||
import com.stardust.util.MapBuilder;
|
||||
|
||||
import org.mozilla.javascript.Token;
|
||||
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
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_AUTO = 0x00000002;
|
||||
|
||||
private static final String LOG_TAG = "JavaScriptSource";
|
||||
|
||||
private static final Map<String, Integer> EXECUTION_MODES = new MapBuilder<String, Integer>()
|
||||
.put("ui", EXECUTION_MODE_UI)
|
||||
.put("auto", EXECUTION_MODE_AUTO)
|
||||
.build();
|
||||
private static final int EXECUTION_MODE_STRING_MAX_LENGTH = 7;
|
||||
private static final int PARSING_MAX_TOKEN = 300;
|
||||
|
||||
private int mExecutionMode = -1;
|
||||
|
||||
@@ -57,20 +64,35 @@ public abstract class JavaScriptSource extends ScriptSource {
|
||||
|
||||
public int getExecutionMode() {
|
||||
if (mExecutionMode == -1) {
|
||||
mExecutionMode = parseExecutionMode(getScript());
|
||||
mExecutionMode = parseExecutionMode();
|
||||
}
|
||||
return mExecutionMode;
|
||||
}
|
||||
|
||||
private int parseExecutionMode(String script) {
|
||||
if (script == null || script.length() == 0)
|
||||
return EXECUTION_MODE_NORMAL;
|
||||
if(script.charAt(0) == '"'){
|
||||
int i = script.lastIndexOf("\";", EXECUTION_MODE_STRING_MAX_LENGTH + 2);
|
||||
if (i >= 0){
|
||||
String modeString = script.substring(1, i);
|
||||
return parseExecutionMode(modeString.split(" "));
|
||||
protected int parseExecutionMode() {
|
||||
String script = getScript();
|
||||
TokenStream ts = new TokenStream(new StringReader(script), null, 1);
|
||||
int token;
|
||||
int count = 0;
|
||||
try {
|
||||
while (count <= PARSING_MAX_TOKEN && (token = ts.getToken()) != Token.EOF) {
|
||||
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;
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package com.stardust.autojs.script;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
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.UncheckedIOException;
|
||||
|
||||
@@ -18,7 +17,6 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<resources>
|
||||
<string name="app_name">AutoJs</string>
|
||||
<string name="app_name">Auto.js</string>
|
||||
<string name="text_error">Error:</string>
|
||||
<string name="text_start_running">Script Running</string>
|
||||
<string name="text_path_is_empty">Path is empty</string>
|
||||
@@ -13,7 +13,6 @@
|
||||
<string name="text_console">Console</string>
|
||||
<string name="text_no_floating_window_permission">No drawing overlay permission</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="no_write_settings_permissin">No writing settings permission</string>
|
||||
<string name="exception_notification_service_disabled">通知服务未运行,请重新启用通知权限</string>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<resources>
|
||||
<string name="app_name">AutoJs</string>
|
||||
<string name="app_name">Auto.js</string>
|
||||
<string name="text_error">错误:</string>
|
||||
<string name="text_start_running">开始运行</string>
|
||||
<string name="text_path_is_empty">路径为空</string>
|
||||
@@ -13,7 +13,6 @@
|
||||
<string name="text_console">控制台</string>
|
||||
<string name="text_no_floating_window_permission">没有悬浮窗权限</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_gesture_observing">手势监听未启用,请在软件设置中开启</string>
|
||||
<string name="no_write_settings_permissin">沒有修改系統设置权限</string>
|
||||
|
||||
Reference in New Issue
Block a user