diff --git a/tor-android-binary/src/main/java/org/torproject/android/binary/NativeLoader.java b/tor-android-binary/src/main/java/org/torproject/android/binary/NativeLoader.java new file mode 100644 index 00000000..2c316c34 --- /dev/null +++ b/tor-android-binary/src/main/java/org/torproject/android/binary/NativeLoader.java @@ -0,0 +1,175 @@ + +package org.torproject.android.binary; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.os.Build; +import android.util.Log; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +public class NativeLoader { + + private final static int LIB_VERSION = 1; + private final static String LIB_NAME = "tor"; + private final static String LIB_SO_NAME = "tor.so"; + private final static String LOCALE_LIB_SO_NAME = "tor.so"; + + private static volatile boolean nativeLoaded = false; + + private final static String TAG = "TorNativeLoader"; + + private static File getNativeLibraryDir(Context context) { + File f = null; + if (context != null) { + try { + f = new File((String)ApplicationInfo.class.getField("nativeLibraryDir").get(context.getApplicationInfo())); + } catch (Throwable th) { + th.printStackTrace(); + } + } + if (f == null) { + f = new File(context.getApplicationInfo().dataDir, "lib"); + } + if (f != null && f.isDirectory()) { + return f; + } + return null; + } + + private static boolean loadFromZip(Context context, File destLocalFile, String folder) { + + + ZipFile zipFile = null; + InputStream stream = null; + try { + zipFile = new ZipFile(context.getApplicationInfo().sourceDir); + ZipEntry entry = zipFile.getEntry("lib/" + folder + "/" + LIB_SO_NAME); + if (entry == null) { + throw new Exception("Unable to find file in apk:" + "lib/" + folder + "/" + LIB_NAME); + } + stream = zipFile.getInputStream(entry); + + OutputStream out = new FileOutputStream(destLocalFile); + byte[] buf = new byte[4096]; + int len; + while ((len = stream.read(buf)) > 0) { + Thread.yield(); + out.write(buf, 0, len); + } + out.close(); + + if (Build.VERSION.SDK_INT >= 9) { + destLocalFile.setReadable(true, false); + destLocalFile.setExecutable(true, false); + destLocalFile.setWritable(true); + } + + try { + // System.load(destLocalFile.getAbsolutePath()); + nativeLoaded = true; + } catch (Error e) { + Log.e(TAG, e.getMessage()); + } + return true; + } catch (Exception e) { + Log.e(TAG, e.getMessage()); + } finally { + if (stream != null) { + try { + stream.close(); + } catch (Exception e) { + Log.e(TAG, e.getMessage()); + } + } + if (zipFile != null) { + try { + zipFile.close(); + } catch (Exception e) { + Log.e(TAG, e.getMessage()); + } + } + } + return false; + } + + public static synchronized boolean initNativeLibs(Context context, File destLocalFile) { + if (nativeLoaded) { + return nativeLoaded; + } + + try { + String folder = null; + + try { + /** + if (Build.CPU_ABI.equalsIgnoreCase("armeabi-v7a")) { + folder = "armeabi-v7a"; + } else + **/ + if (Build.CPU_ABI.startsWith("armeabi")) { + folder = "armeabi"; + } else if (Build.CPU_ABI.equalsIgnoreCase("x86")) { + folder = "x86"; + } else if (Build.CPU_ABI.equalsIgnoreCase("mips")) { + folder = "mips"; + } else { + folder = "armeabi"; + //FileLog.e("tmessages", "Unsupported arch: " + Build.CPU_ABI); + } + } catch (Exception e) { + // FileLog.e("tmessages", e); + Log.e(TAG, e.getMessage()); + folder = "armeabi"; + } + + + String javaArch = System.getProperty("os.arch"); + if (javaArch != null && javaArch.contains("686")) { + folder = "x86"; + } + + if (destLocalFile != null && destLocalFile.exists()) { + try { + // System.load(destLocalFile.getAbsolutePath()); + nativeLoaded = true; + return nativeLoaded; + } catch (Error e) { + Log.e(TAG, e.getMessage()); + } + destLocalFile.delete(); + } + + + if (loadFromZip(context, destLocalFile, folder)) { + return true; + } + + /* + folder = "x86"; + destLocalFile = new File(context.getFilesDir().getAbsolutePath() + "/libtmessages86.so"); + if (!loadFromZip(context, destLocalFile, folder)) { + destLocalFile = new File(context.getFilesDir().getAbsolutePath() + "/libtmessagesarm.so"); + folder = "armeabi"; + loadFromZip(context, destLocalFile, folder); + } + */ + } catch (Throwable e) { + e.printStackTrace(); + } + + try { + // System.loadLibrary(LIB_NAME); + nativeLoaded = true; + } catch (Error e) { + Log.e(TAG, e.getMessage()); + } + + return nativeLoaded; + } +} diff --git a/tor-android-binary/src/main/java/org/torproject/android/binary/TorResourceInstaller.java b/tor-android-binary/src/main/java/org/torproject/android/binary/TorResourceInstaller.java index 1f78e832..7a44f125 100644 --- a/tor-android-binary/src/main/java/org/torproject/android/binary/TorResourceInstaller.java +++ b/tor-android-binary/src/main/java/org/torproject/android/binary/TorResourceInstaller.java @@ -34,7 +34,7 @@ public class TorResourceInstaller implements TorServiceConstants { this.context = context; } - public void deleteDirectory(File file) { + private void deleteDirectory(File file) { if( file.exists() ) { if (file.isDirectory()) { File[] files = file.listFiles(); @@ -58,21 +58,39 @@ public class TorResourceInstaller implements TorServiceConstants { */ public boolean installResources () throws IOException, TimeoutException { + File fileTorLocalFile = new File(installFolder, TOR_ASSET_KEY); deleteDirectory(installFolder); installFolder.mkdirs(); + installGeoIP(); assetToFile(COMMON_ASSET_KEY + TORRC_ASSET_KEY, TORRC_ASSET_KEY, false, false); - InputStream is = new FileInputStream(new File(getNativeLibraryDir(context),TOR_ASSET_KEY + ".so")); - File outFile = new File(installFolder, TOR_ASSET_KEY); - streamToFile(is,outFile, false, true); - setExecutable(outFile); + File fileNativeDir = new File(getNativeLibraryDir(context)); + Log.d(TAG,"listing native files"); + listf(fileNativeDir.getAbsolutePath()); - installGeoIP(); - - return true; + File fileNativeBin = new File(getNativeLibraryDir(context),TOR_ASSET_KEY + ".so"); + if (!fileNativeBin.exists()) + { + if (getNativeLibraryDir(context).endsWith("arm")) { + fileNativeBin = new File(getNativeLibraryDir(context)+"eabi", TOR_ASSET_KEY + ".so"); + } + } + + if (fileNativeBin.exists()) { + InputStream is = new FileInputStream(fileNativeBin); + streamToFile(is, fileTorLocalFile, false, true); + setExecutable(fileTorLocalFile); + + return fileTorLocalFile.exists() && fileTorLocalFile.canExecute(); + } + else + { + //let's try another approach + return NativeLoader.initNativeLibs(context,fileTorLocalFile); + } } @@ -131,7 +149,7 @@ public class TorResourceInstaller implements TorServiceConstants { /* * Write the inputstream contents to the file */ - public static boolean streamToFile(InputStream stm, File outFile, boolean append, boolean zip) throws IOException + private static boolean streamToFile(InputStream stm, File outFile, boolean append, boolean zip) throws IOException { byte[] buffer = new byte[FILE_WRITE_BUFFER_SIZE]; @@ -176,4 +194,22 @@ public class TorResourceInstaller implements TorServiceConstants { fileBin.setWritable(true, true); } + private static File[] listf(String directoryName) { + + // .............list file + File directory = new File(directoryName); + + // get all the files from a directory + File[] fList = directory.listFiles(); + + for (File file : fList) { + if (file.isFile()) { + Log.d(TAG,file.getAbsolutePath()); + } else if (file.isDirectory()) { + listf(file.getAbsolutePath()); + } + } + + return fList; + } }