import java.util.*; import java.util.zip.*; import java.util.List; import java.util.regex.*; import java.util.concurrent.*; import java.util.concurrent.atomic.*; import java.util.concurrent.locks.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.text.*; import javax.swing.table.*; import java.io.*; import java.net.*; import java.lang.reflect.*; import java.lang.ref.*; import java.lang.management.*; import java.security.*; import java.security.spec.*; import java.awt.*; import java.awt.event.*; import java.awt.image.*; import javax.imageio.*; import java.math.*; // stage 1 is the app itself import android.app.*; import android.graphics.*; import android.content.pm.ActivityInfo; import java.text.NumberFormat; import javax.net.ssl.*; import java.security.SecureRandom; import java.security.cert.X509Certificate; import java.text.SimpleDateFormat; import java.util.*; import java.util.zip.*; import java.util.List; import java.util.regex.*; import java.util.concurrent.*; import java.util.concurrent.atomic.*; import java.io.*; import java.net.*; import java.lang.reflect.*; import java.lang.ref.*; import java.lang.management.*; import java.security.*; import java.security.spec.*; import java.math.*; import android.widget.*; import android.view.*; import android.view.View; import android.view.Menu; import android.view.MenuItem; import android.widget.Button; import android.content.Context; import android.app.Activity; import android.view.KeyEvent; import android.view.inputmethod.*; import android.content.*; import android.text.*; class main { static String awarenessID = "#1004078"; //sS catProgramID = #1014854; static String catProgramID = "#1023372"; static boolean dontStartCat = false; static boolean bootIntoLog = false; static volatile Class x30; static volatile boolean x30loading, x30loadingFailed; static List programsStarted = new ArrayList(); static File defSnip, defargs; static volatile Class visibleProgram; static boolean dontSwitchToRunningProgram = false; static ReliableSingleThread snippetTitleFinder; static class Prog { String snippetID; Thread thread; } static class Lg { static int maxBufferLength = 2048; Activity context; ScrollView sv; TextView tv; EditText inputView; LinearLayout ll; StringBuffer buf = new StringBuffer(); Lg(Activity context) { this.context = context; sv = new ScrollView(context); tv = new TextView(context); tv.setText(buf.toString()); sv.addView(tv); sv.setLayoutParams(new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT, 1.0f)); inputView = new EditText(context); inputView.setInputType(InputType.TYPE_CLASS_TEXT); // turn off multiline inputView.setOnEditorActionListener(new TextView.OnEditorActionListener() { public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (actionId == EditorInfo.IME_ACTION_DONE)) { String line = inputView.getText().toString(); try { pout3.write((line + "\n").getBytes("UTF-8")); pout3.flush(); } catch (Exception e) {} inputView.selectAll(); } return false; } }); ll = new LinearLayout(context); ll.setOrientation(ll.VERTICAL); ll.addView(sv); ll.addView(inputView); } View getView() { return ll; } void shortenBuffer() { while (buf.length() > maxBufferLength) { String s = buf.toString(); int i = s.indexOf('\n'); if (i < 0) return; buf = new StringBuffer(s.substring(i+1)); } } UTF8Processor up = new UTF8Processor(); Lock lock = lock(); LineBuffer lineBuffer = new LineBuffer(new VF1() { public void get(String line) { try { if (startsWithOneOf(line, "[CDS]", "[socket]", "close [socket]")) return; if (eqOneOf(line, "tcp port:5000", "propertyValue:true")) return; print(line + "\n"); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (startsWithOneOf(line, \"[CDS]\", \"[socket]\", \"close [socket]\")) ret;\r\n i..."; }}); void receiveBytes(byte[] b) { Lock __0 = lock; lock(__0); try { lineBuffer.append(funnelBytesThroughUTF8Processor(up, b)); } finally { unlock(__0); } } // TODO: coalesce void print(final String s) { androidUI_noWait(new Runnable() { public void run() { try { buf.append(s); shortenBuffer(); tv.setText(buf.toString()); sv.post(new Runnable() { public void run() { // This method works but animates the scrolling // which looks weird on first load sv.fullScroll(View.FOCUS_DOWN); // This method works even better because there are no animations. //sv.scrollTo(0, sv.getBottom()); } }); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "buf.append(s);\r\n shortenBuffer();\r\n tv.setText(buf.toString());\r\n ..."; }}); } void clear() { buf.setLength(0); print(""); } void println(String s) { print(s + "\n"); } } public static String snippetToRun; static TextView statusView; public static View main(final Context _context) throws Exception { final Activity context = _context instanceof Activity ? (Activity) _context : null; visibleProgram = null; //System.out.println("676 context: " + _context); androidContext = _context; if (context == null) { // I guess this is for boot time execution if (snippetToRun != null) { new Thread() { public void run() { String[] a = { snippetToRun }; callx30(a); } }.start(); } return null; } statusView = aTextView(); preloadx30(); while (x30 == null && !x30loading && !x30loadingFailed) sleep(10); int nInjections = l(injections()); if (dontSwitchToRunningProgram) dontSwitchToRunningProgram = false; else if (nInjections > 0) { try { return getRunningProgramView(nInjections-1); } catch (Throwable __e) { _handleException(__e); }} prepareOptionsMenu(); String dsc = trim(loadTextFile(javaxDataDir("dont-start-cat"))); if (eq(dsc, "0")) dontStartCat = false; else if (eq(dsc, "1")) dontStartCat = true; if (!dontStartCat && (__javax == null || !isTrue(vm_generalMap_get("dontLoadCat")))) { //aHideTitleBar(); //waitForX30(); View view = aCatLoadingScreen(); startThread("Cat", new Runnable() { public void run() { try { waitForX30(); vm_generalMap_put("dontLoadCat", true); for (int i = 0; i < 2; i++) { if (i != 0) sleepSeconds(0.5); // User has already clicked "ADMIN" if (print("admin mode: ", androidIsAdminMode())) { showStartScreen(); return; } } if (!bootIntoLog) run_dontShowLog.set(true); main.run(context, catProgramID); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "waitForX30();\r\n vm_generalMap_put(\"dontLoadCat\", true);\r\n for (int ..."; }}); return view; } defSnip = new File(userHome(), ".javax/defsnip"); String id = loadTextFile(defSnip.getPath(), "636"); defargs = new File(userHome(), ".javax/defargs"); String arg = loadTextFile(defargs.getPath(), ""); ScrollView sv = new ScrollView(context); LinearLayout ll = new LinearLayout(context); ll.setOrientation(LinearLayout.VERTICAL); ll.addView(statusView); for (int i = 0; i < nInjections; i++) { final int _i = i; ll.addView(aButton("Back to running program " + (i+1), new Runnable() { public void run() { try { showRunningProgram(_i) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "showRunningProgram(_i)"; }})); } for (int i = 0; i < nInjections; i++) { final int _i = i; ll.addView(aButton("Kill running program " + (i+1), new Runnable() { public void run() { try { killRunningProgram(_i) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "killRunningProgram(_i)"; }})); } LinearLayout line1 = new LinearLayout(context); line1.addView(aTextView("Snippet ID:")); final EditText tv = aFontSize(24, new EditText(context)); // BAD - tv.setInputType(InputType.TYPE_NUMBER_FLAG_DECIMAL); tv.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_CLASS_NUMBER); tv.setText(id); line1.addView(tv); snippetTitleFinder = new ReliableSingleThread(new Runnable() { public void run() { try { String id = aGetText(tv); if (isSnippetID(id)) aSetText(statusView, snippetTitle(id)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "String id = aGetText(tv);\r\n if (isSnippetID(id))\r\n aSetText(statusVie..."; }}); aOnChange(tv, snippetTitleFinder); Button btnRun = new Button(context); btnRun.setText("Run"); line1.addView(btnRun); ll.addView(line1); final EditText tvArgs = aEditText(arg); ll.addView(aHorizontalLinearLayout( aTextView("Program arguments:"), tvArgs)); //LinearLayout line3 = new LinearLayout(context); //deleteDownloadedLibrary(#1101204); ll.addView(aImageButton("#1101205",/*aButton("Cat",*/ new Runnable() { public void run() { try { main.run(context, catProgramID); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "main.run(context, catProgramID);"; }})); /*ll.addView(aButton("Start Awareness [" + awarenessID + "]", r { saveDef(awarenessID, ""); main.run(context, awarenessID); }));*/ btnRun.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { hideKeyboard(context); String snippetID = tv.getText().toString(); String args = tvArgs.getText().toString(); runSnippet(context, snippetID, args); } }); // Show initial status for 1 second, then snippet title aLater(1000, snippetTitleFinder); sv.addView(ll); return sv; } static void saveDef(String snippetID, String args) { try { saveTextFile(defSnip.getPath(), snippetID); saveTextFile(defargs.getPath(), args); } catch (IOException e) { } } static Lg lg; static int systemInPipeSize = 4*1024; // 4 K static PipedInputStream pin3; static PipedOutputStream pout3; static ThreadLocal run_dontShowLog = new ThreadLocal(); public static void run(final Activity context, final String mainSnippet, final String... args) { boolean dontShowLog = isTrue(optParam(run_dontShowLog)); try { pin3 = new PipedInputStream(systemInPipeSize); pout3 = new PipedOutputStream(pin3); } catch (IOException e) {} lg = new Lg(context); OutputStream outputStream = new OutputStream() { public void write(int b) { lg.receiveBytes(new byte[] {(byte) b}); } @Override public void write(byte[] b, int off, int len) { lg.receiveBytes(subByteArray(b, off, len)); } }; PrintStream ps = new PrintStream(outputStream, true); System.setOut(ps); System.setErr(ps); System.setIn(pin3); Prog prog = new Prog(); prog.snippetID = mainSnippet; prog.thread = new Thread() { public void run() { try { String[] a = new String[args.length+1]; System.arraycopy(args, 0, a, 1, args.length); a[0] = mainSnippet; callx30(a); } catch (Throwable e) { System.out.println("Whoa!"); e.printStackTrace(); } } }; programsStarted.add(prog); prog.thread.start(); if (!dontShowLog) context.setContentView(lg.getView()); } static void setContentViewInUIThread(final View view) { androidUI(new Runnable() { public void run() { try { androidActivity().setContentView(view); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "androidActivity().setContentView(view);"; }}); } public static void hideKeyboard(Activity context) { View view = context.getCurrentFocus(); if (view != null) { InputMethodManager inputManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); inputManager.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); } } static void onActivityResult(int requestCode, int resultCode, Intent data) { /* TODO? if (x30.mainClass != null) x30.call(x30.mainClass, "onActivityResult", requestCode, resultCode, data);*/ } static void onPrepareOptionsPanel(View view, Menu menu) { /* TODO if (x30.mainClass != null) x30.call(x30.mainClass, "onPrepareOptionsPanel", view, menu);*/ } static boolean onOptionsItemSelected(MenuItem item) { /* TODO if (x30.mainClass != null) return (boolean) x30.call(x30.mainClass, "onOptionsItemSelected", item);*/ String s = str(item.getTitle()); print("Item title: " + quote(s)); if (eqOneOf(s, "Settings", "Tasks")) showStartScreen(); else if (eqic(s, "Show Console")) showConsole(); callOpt(visibleProgram, "onMenuCommand", s); return true; } static void waitForX30() { while (x30 == null) if (x30loadingFailed) throw fail("x30 load failed"); else sleep(10); // guess it's loading } static void callx30(String[] args) { waitForX30(); //print("Calling x30 " + join(" ", args)); try { set(x30, "androidContext", androidContext); ((ThreadLocal) get(x30, "onProgramLoad")).set(new VF1() { public void get(Object paa) { try { visibleProgram = (Class) getOpt(paa, "mainClass"); //print("Have visible program: " + visibleProgram); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "visibleProgram = (Class) getOpt(paa, 'mainClass);\r\n //print(\"Have visibl..."; }}); callMain(x30, args); List injections = injections(); //visibleProgram = (Class) getOpt(last(injections), 'mainClass); // TODO: imprecise if main program tempers with injections //print("Have " + l(injections) + " injections, visibleProgram=" + visibleProgram); //print("x30 done"); } catch (Throwable __e) { _handleException(__e); } } static void preloadx30() { { startThread(new Runnable() { public void run() { try { getx30(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "getx30();"; }}); } } static void getx30() { try { String status = ""; if (x30 != null) status = "Have x30."; else { Object dataStore = null; try { dataStore = Class.forName("de.tinybrain.javax_allperms.DataStore"); } catch (Throwable __e) { _handleException(__e); } if (dataStore != null) { x30 = __javax = (Class) call(dataStore, "get", "x30"); if (x30 != null) status = "Have x30 from data store."; } if (x30 == null) { x30loading = true; status("Loading x30..."); Class x30 = loadx30("#1004182"); callOpt(dataStore, "put", "x30", x30); main.x30 = __javax = x30; // use it ourselves vmGeneralMap_put("bootstrapper", mc()); status(status = "x30 loaded."); } setOpt(x30, "bootUpClass", main.class); } List injections = injections(); if (nempty(injections)) status += " " + n2(injections, "injection"); status(status); } catch (Throwable e) { status(getStackTrace(e)); printStackTrace(e); x30loadingFailed = true; } finally { x30loading = false; } } static List injections() { return (List) callOpt(x30, "getInjections"); } static void killRunningProgram(int i) { try { Object paa = get(injections(), i); if (paa == null) return; call(x30, "removeInjection", paa); showStartScreen(); } catch (Throwable e) { printStackTrace(e); status(str(e)); } } static void showStartScreen() { print("showStartScreen"); androidUI(new Runnable() { public void run() { try { dontSwitchToRunningProgram = true; androidActivity().setContentView(main(androidContext())); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "dontSwitchToRunningProgram = true;\r\n androidActivity().setContentView(main..."; }}); } static void showRunningProgram(int i) { View v = getRunningProgramView(i); if (v != null) setContentViewInUIThread(v); } static View getRunningProgramView(int i) { Object paa = get(injections(), i); if (paa == null) { status("No running program to show"); return null; } Class mainClass = (Class) (getOpt(paa, "mainClass")); View view = (View) (getOpt(mainClass, "androidShow_view")); if (view == null) //ret null with status("Program has no view to show"); view = lg.getView(); // show log instead print("Switched to program " + get(paa, "progID")); visibleProgram = mainClass; ViewGroup group = (ViewGroup) view.getParent(); if (group != null) group.removeView(view); return view; } static void status(String s) { aSetText(statusView, s); print(s); } static Class loadx30(String programID) { try { System.out.println("Program ID: " + programID); String url = tb_mainServer() + "/dexcompile.php?id=" + parseSnippetID(programID); status("Loading DEX: " + url); byte[] dexData = loadBinaryPage(url); status("Loaded something"); if (!isDex(dexData)) throw new RuntimeException("Dex generation error"); status("DEX loaded"); System.out.println("Dex loaded: " + dexData.length + "b"); File dexDir = makeAndroidTempDir(); File dexFile = new File(dexDir, System.currentTimeMillis() + ".dex"); File dexOutputDir = makeAndroidTempDir(); System.out.println("Saving dex to: " + dexDir.getAbsolutePath()); try { saveBinaryFile(dexFile.getPath(), dexData); } catch (Throwable e) { System.out.println("Whoa!"); throw new RuntimeException(e); } System.out.println("Getting parent class loader."); ClassLoader parentClassLoader = main.class.getClassLoader().getParent(); //System.out.println("Making DexClassLoader."); //DexClassLoader classLoader = new DexClassLoader(dexFile.getAbsolutePath(), dexOutputDir.getAbsolutePath(), null, // parentClassLoader); Class dcl = Class.forName("dalvik.system.DexClassLoader"); Object classLoader = dcl.getConstructors()[0].newInstance(dexFile.getAbsolutePath(), dexOutputDir.getAbsolutePath(), null, parentClassLoader); System.out.println("Loading main class."); Class theClass = (Class) call(classLoader, "loadClass", "x30"); System.out.println("Main class loaded."); try { set(theClass, "androidContext", androidContext); } catch (Throwable e) {} setVars(theClass, programID); hotwire_copyOver(theClass); return theClass; } catch (Exception __e) { throw rethrow(__e); } } static void setVars(Class theClass, String programID) { try { set(theClass, "programID", programID); } catch (Throwable e) {} try { set(theClass, "__javax", x30); } catch (Throwable e) {} } static String getConsoleOutput() { return lg.buf.toString(); } static void prepareOptionsMenu() { try { Menu menu = (Menu) (getOpt(androidActivity(), "optionsMenu")); if (menu == null) return; if (menu.size() < 2) { aRemoveItemFromMenu(menu, "Settings"); menu.add("Tasks"); menu.add("Show Console"); } } catch (Throwable __e) { _handleException(__e); } } // fix for when there is no x30 yet static void vmBus_send(String msg, Object... args) { try { Object arg = vmBus_wrapArgs(args); pcallFAll(vm_busListeners_live(), msg, arg); pcallFAll(vm_busListenersByMessage_live().get(msg), msg, arg); } catch (Throwable __e) { silentException(__e); } } static void showConsole() { visibleProgram = null; { androidUI(new Runnable() { public void run() { try { androidActivity().setContentView(lg.getView()); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "androidActivity().setContentView(lg.getView());"; }}); } } static void runSnippet(final Activity context, final String snippetID, final String args) { { androidUI(new Runnable() { public void run() { try { androidUnsetAdminMode(); String text = "Running: " + snippetID; Toast.makeText(context, text, 2000).show(); saveDef(snippetID, args); // TODO: quoted args main.run(context, snippetID, unnull(args).split(" +")); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "androidUnsetAdminMode();\r\n String text = \"Running: \" + snippetID;\r\n Toa..."; }}); } } static void lock(Lock lock) { try { ping(); if (lock == null) return; try { lock.lockInterruptibly(); } catch (InterruptedException e) { print("Locking interrupted! I probably deadlocked, oops."); printStackTrace(e); rethrow(e); } ping(); } catch (Exception __e) { throw rethrow(__e); } } static void lock(Lock lock, String msg) { print("Locking: " + msg); lock(lock); } static void lock(Lock lock, String msg, long timeout) { print("Locking: " + msg); lockOrFail(lock, timeout); } static ReentrantLock lock() { return fairLock(); } static boolean startsWithOneOf(String s, String... l) { for (String x : l) if (startsWith(s, x)) return true; return false; } static boolean eqOneOf(Object o, Object... l) { for (Object x : l) if (eq(o, x)) return true; return false; } static volatile StringBuffer local_log = new StringBuffer(); // not redirected static volatile Appendable print_log = local_log; // might be redirected, e.g. to main bot // in bytes - will cut to half that static volatile int print_log_max = 1024*1024; static volatile int local_log_max = 100*1024; static boolean print_silent = false; // total mute if set static Object print_byThread_lock = new Object(); static volatile ThreadLocal print_byThread; // special handling by thread - prefers F1 static volatile Object print_allThreads; static volatile Object print_preprocess; static void print() { print(""); } static A print(String s, A o) { print((endsWithLetterOrDigit(s) ? s + ": " : s) + o); return o; } // slightly overblown signature to return original object... static A print(A o) { ping_okInCleanUp(); if (print_silent) return o; String s = String.valueOf(o) + "\n"; print_noNewLine(s); return o; } static void print_noNewLine(String s) { print_raw(s); } static void print_raw(String s) { Appendable loc = local_log; Appendable buf = print_log; int loc_max = print_log_max; if (buf != loc && buf != null) { print_append(buf, s, print_log_max); loc_max = local_log_max; } if (loc != null) print_append(loc, s, loc_max); System.out.print(s); } static void print_autoRotate() { } static RuntimeException rethrow(Throwable t) { throw t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t); } static RuntimeException rethrow(String msg, Throwable t) { throw new RuntimeException(msg, t); } static String funnelBytesThroughUTF8Processor(UTF8Processor p, byte[] bytes) { StringBuilder input = new StringBuilder(); int n = l(bytes); for (int i = 0; i < n; i++) input.append(p.processByte(bytes[i])); return input.toString(); } static void unlock(Lock lock, String msg) { if (lock == null) return; print("Unlocking: " + msg); lock.unlock(); } static void unlock(Lock lock) { if (lock == null) return; lock.unlock(); } static void androidUI_noWait(final Object r) { androidActivity().runOnUiThread(toRunnable(r)); } static TextView aTextView(String text) { TextView tv = aTextView(); tv.setText(text); return tv; } static TextView aTextView() { return androidUI(new F0() { TextView get() { try { return new TextView(androidActivity()); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret new TextView(androidActivity());"; }}); } static volatile boolean sleep_noSleep = false; static void sleep(long ms) { ping(); if (ms < 0) return; // allow spin locks if (isAWTThread() && ms > 100) throw fail("Should not sleep on AWT thread"); try { Thread.sleep(ms); } catch (Exception e) { throw new RuntimeException(e); } } static void sleep() { try { if (sleep_noSleep) throw fail("nosleep"); print("Sleeping."); sleepQuietly(); } catch (Exception __e) { throw rethrow(__e); } } static int l(Object[] a) { return a == null ? 0 : a.length; } static int l(boolean[] a) { return a == null ? 0 : a.length; } static int l(byte[] a) { return a == null ? 0 : a.length; } static int l(short[] a) { return a == null ? 0 : a.length; } static int l(long[] a) { return a == null ? 0 : a.length; } static int l(int[] a) { return a == null ? 0 : a.length; } static int l(float[] a) { return a == null ? 0 : a.length; } static int l(double[] a) { return a == null ? 0 : a.length; } static int l(char[] a) { return a == null ? 0 : a.length; } static int l(Collection c) { return c == null ? 0 : c.size(); } static int l(Iterator i) { return iteratorCount_int_close(i); } // consumes the iterator && closes it if possible static int l(Map m) { return m == null ? 0 : m.size(); } static int l(CharSequence s) { return s == null ? 0 : s.length(); } static long l(File f) { return f == null ? 0 : f.length(); } static int l(Object o) { return o == null ? 0 : o instanceof String ? l((String) o) : o instanceof Map ? l((Map) o) : o instanceof Collection ? l((Collection) o) : o instanceof Object[] ? l((Object[]) o) : o instanceof boolean[] ? l((boolean[]) o) : o instanceof byte[] ? l((byte[]) o) : o instanceof char[] ? l((char[]) o) : o instanceof short[] ? l((short[]) o) : o instanceof int[] ? l((int[]) o) : o instanceof float[] ? l((float[]) o) : o instanceof double[] ? l((double[]) o) : o instanceof long[] ? l((long[]) o) : (Integer) call(o, "size"); } static volatile PersistableThrowable _handleException_lastException; static List _handleException_onException = synchroList(ll("printStackTrace2")); static void _handleException(Throwable e) { _handleException_lastException = persistableThrowable(e); Throwable e2 = innerException(e); if (e2.getClass() == RuntimeException.class && eq(e2.getMessage(), "Thread cancelled.") || e2 instanceof InterruptedException) return; for (Object f : cloneList(_handleException_onException)) try { callF(f, e); } catch (Throwable e3) { printStackTrace2(e3); // not using pcall here - it could lead to endless loops } } static String trim(String s) { return s == null ? null : s.trim(); } static String trim(StringBuilder buf) { return buf.toString().trim(); } static String trim(StringBuffer buf) { return buf.toString().trim(); } static String loadTextFile(String fileName) { return loadTextFile(fileName, null); } static String loadTextFile(File f, String defaultContents) { try { if (f == null || !f.exists()) return defaultContents; FileInputStream fileInputStream = new FileInputStream(f); InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8"); return loadTextFile(inputStreamReader); } catch (Exception __e) { throw rethrow(__e); } } public static String loadTextFile(File fileName) { return loadTextFile(fileName, null); } static String loadTextFile(String fileName, String defaultContents) { return fileName == null ? defaultContents : loadTextFile(newFile(fileName), defaultContents); } static String loadTextFile(Reader reader) throws IOException { StringBuilder builder = new StringBuilder(); try { char[] buffer = new char[1024]; int n; while (-1 != (n = reader.read(buffer))) builder.append(buffer, 0, n); } finally { reader.close(); } return str(builder); } static File javaxDataDir_dir; // can be set to work on different base dir static File javaxDataDir() { return javaxDataDir_dir != null ? javaxDataDir_dir : new File(userHome(), "JavaX-Data"); } static File javaxDataDir(String... subs) { return newFile(javaxDataDir(), subs); } static boolean eq(Object a, Object b) { return a == b || (a == null ? b == null : b != null && a.equals(b)); } static boolean isTrue(Object o) { if (o instanceof Boolean) return ((Boolean) o).booleanValue(); if (o == null) return false; if (o instanceof ThreadLocal) // TODO: remove this return isTrue(((ThreadLocal) o).get()); throw fail(getClassName(o)); } static Object vm_generalMap_get(Object key) { return vm_generalMap().get(key); } static View aCatLoadingScreen() { aPortraitMode(); final TextView tv = aCenteredTextView("ASSISTANT LOADING"); return aVerticalLinearLayout( aImageView("#1101167"), aFontSize(32, aSetForeground(aBlack(), tv)), aVerticalExpander(), aFontSize(32, aButton( //"No thanks, I'll do something else", "ADMIN", new Runnable() { public void run() { try { aDisable(heldInstance(Button.class)); aSetText(tv, ""); callOptMC("waitForX30"); androidGoAdminMode(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "aDisable(heldInstance(Button.class));\r\n aSetText(tv, \"\"..."; }})) ); } static Thread startThread(Object runnable) { return startThread(defaultThreadName(), runnable); } static Thread startThread(String name, Object runnable) { runnable = wrapAsActivity(runnable); return startThread(newThread(toRunnable(runnable), name)); } static Thread startThread(Thread t) { t.start(); return t; } static Object vm_generalMap_put(Object key, Object value) { return mapPutOrRemove(vm_generalMap(), key, value); } static void sleepSeconds(double s) { if (s > 0) sleep(round(s*1000)); } static boolean androidIsAdminMode() { return isTrue(vm_generalMap_get("admin-mode")); } static String _userHome; static String userHome() { if (_userHome == null) return actualUserHome(); return _userHome; } static File userHome(String path) { return new File(userDir(), path); } static Button aButton(String text, final Runnable action) { final Button b = aButton(text); if (action != null) b.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { AutoCloseable __1 = holdInstance(b); try { pcallF(action); } finally { _close(__1); }} }); return b; } static Button aButton(String text) { Button b = aButton(); b.setText(text); return b; } static Button aButton() { return androidUI(new F0