Merge branch 'master' of git://git.torproject.org/n8fr8/orbot
Conflicts: AUTHORS AndroidManifest.xml
This commit is contained in:
commit
34ce45398f
|
@ -1,11 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.torproject.android" android:versionName="0.2.2.25-orbot-alpha-1.0.5.2" android:versionCode="14">
|
||||
package="org.torproject.android" android:versionName="0.2.3.1-orbot-alpha-1.0.5.3" android:versionCode="16">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||
|
||||
<application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="false">
|
||||
<application android:theme="@style/DefaultTheme" android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="false">
|
||||
|
||||
<activity android:name=".Orbot"
|
||||
android:theme="@android:style/Theme.NoTitleBar">
|
||||
|
@ -28,8 +28,12 @@
|
|||
<action android:name="org.torproject.android.START_TOR" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".SettingsPreferences" android:label="@string/app_name"/>
|
||||
|
||||
<activity android:name=".LotsaText"/>
|
||||
<activity android:name=".Permissions"/>
|
||||
<activity android:name=".TipsAndTricks"/>
|
||||
<activity android:name=".ConfigureTransProxy"/>
|
||||
<activity android:name=".SettingsPreferences" android:label="@string/app_name"/>
|
||||
<activity android:name=".AppManager" android:label="@string/app_name"/>
|
||||
<activity android:name=".WizardActivity" android:label="@string/app_name"/>
|
||||
|
||||
|
|
8
BUILD
8
BUILD
|
@ -124,7 +124,13 @@ Finally, we'll make a proper Android package with ant and the Android App SDK:
|
|||
export APP_SDK=~/Documents/projects/android/android-sdk-linux_x86-1.5_r3/tools
|
||||
cd ../Orbot/
|
||||
cp $DROID_ROOT/external/privoxy/privoxy-3.0.12-stable/privoxy assets/privoxy
|
||||
cp $DROID_ROOT/external/tor/tor/src/or/tor assets/tor
|
||||
|
||||
Now you need to split and copy the tor binary into res/raw. We split it into < 1M chunks
|
||||
because some Android devices don't like resources larger than 1M.
|
||||
|
||||
split --bytes=1m $DROID_ROOT/external/tor/tor/src/or/tor res/raw/tor
|
||||
|
||||
Now build the Android app
|
||||
$APP_SDK/android update project --name Orbot --target 3 --path .
|
||||
ant release
|
||||
|
||||
|
|
|
@ -1,5 +1,14 @@
|
|||
NOTE: Specific #s below correspond to Trac tickets logged and maintained at https://trac.torproject.org/projects/tor/
|
||||
|
||||
1.0.5.3
|
||||
- added auto-tor of wireless and usb tethering
|
||||
- integrated new setup wizard
|
||||
- moved large tor binary into split multiple 1M segments to fix for devices with 1M resource limit
|
||||
|
||||
1.0.5.1/.2
|
||||
- small updates to layout of main screen to fit smaller screens
|
||||
- fixed preference setting of EntryNode torrc value
|
||||
|
||||
1.0.5
|
||||
- added exit node and "StrictExitNode" preference
|
||||
- fixed tor binary installation issue related to max resource size and compression
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
|
||||
.
|
||||
└── org
|
||||
└── torproject
|
||||
└── android
|
||||
├── AppManager.java
|
||||
//this is what helps us track the app-by-app torification
|
||||
//and gets the app name, icon, etc for display - we have some problems here
|
||||
//in normalizing the icon on the list label
|
||||
//some of this code came originally from DroidWall project (yay open source)
|
||||
|
||||
├── boot
|
||||
│ └── OnbootBroadcastReceiver.java
|
||||
//i think this is a dup now and should be removed
|
||||
|
||||
├── HiddenServiceManager.java
|
||||
//empty! but at some point i thought it would be good to aggregate HS functions here
|
||||
|
||||
├── OnBootReceiver.java
|
||||
//this is the class registered in AndroidManifest.xml to handle Onboot events
|
||||
//to start Orbot/Tor when the device boots if the user has elected to do so - what kind of permissions does this require?
|
||||
// <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||
// BTW, this shows up as a fairly unintrusive type perm request now in Android / in older versions (1.6 and earlier)
|
||||
// it was reported "as read / monitor phone state" and paranoid Tor-types didn't like the idea of it
|
||||
// in 1.6+ it has a much better UX in terms of having a more granular permisions around boot since it is a very
|
||||
// common request - ah , that's awesome, i think i remember seeing sth of this sorts when i was going through the guardianproject mailing list. iirc this is something ioerror wanted
|
||||
|
||||
|
||||
├── Orbot.java
|
||||
//our wonderful main activity!
|
||||
|
||||
├── ProcessSettingsAsyncTask.java
|
||||
//this was just added in 1.0.5.x, but it was meant to help stop the UI blocking while processing settings and prefs
|
||||
//it uses the AsyncTask feature of Android, which seems to work pretty well
|
||||
//for this type of non-time critical function you just want to happen in the background at some point soon-ish
|
||||
|
||||
├── SettingsPreferences.java
|
||||
// Settings activity that loads the res/xml/preferences.xml resource up
|
||||
// has some custom event handlng, onActivityResult callback result code's as well
|
||||
// basically meant to tell Orbot activity if critical settings have been modified and whether
|
||||
// those new settings should be applied (like iptables/transproxy changes)
|
||||
|
||||
├── TorConstants.java
|
||||
// globals! well, constants! but yeah, just a place to put values we use a lot
|
||||
|
||||
├── TorifiedApp.java
|
||||
// object to store a single app's metadata for display in UI and for transproxy process
|
||||
|
||||
├── Utils.java
|
||||
// random methods that can be useful, a.k.a. another place to put stuff
|
||||
|
||||
├── WizardActivity.java
|
||||
// our original attempt at wizard activity that didn't get far
|
||||
|
||||
└── WizardHelper.java
|
||||
// the helper class that manages the dialog based wizard
|
||||
|
||||
├── service //okay the Service subpackage!
|
||||
|
||||
│ ├── Api.java
|
||||
//this is more code taken from DroidWall, that needs to be cleaned up and paired down to just what we need it for
|
||||
//this is related to 1.0.5.x changes with how we bundle and install our C binaries (tor, privoxy and iptables)
|
||||
|
||||
│ ├── ITorService.aidl
|
||||
// the android remote interface definition file;
|
||||
// this is the remote interface which the Orbot activity gets a reference to
|
||||
// and that in the TorService is instantiated as the "binder"
|
||||
|
||||
│ ├── ITorServiceCallback.aidl
|
||||
// this is the callback interface that the Orbot activity instantiates, and passes
|
||||
// to the ITorService; reverse of ITorService in a sense
|
||||
|
||||
│ ├── TorBinaryInstaller.java
|
||||
// this handles installation of binaries; uses Api.java; // tied into Wizard as well
|
||||
|
||||
│ ├── TorServiceConstants.java
|
||||
// reusable constants for just the Service package
|
||||
|
||||
│ ├── TorService.java
|
||||
// the main might powerful service class; Orbot and TorService are the front and backends of this whole app
|
||||
// should run as a remote service, but the manifest doesn't seem to indicate that at the moment
|
||||
|
||||
│ ├── TorServiceUtils.java
|
||||
//utility methods for the service; specificaly check for root and tools for finding processID of background binaries
|
||||
|
||||
│ └── TorTransProxy.java
|
||||
// all the code for iptables transproxying management
|
||||
|
||||
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 9.0 KiB |
Binary file not shown.
Before Width: | Height: | Size: 8.6 KiB |
Binary file not shown.
Before Width: | Height: | Size: 4.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
|
@ -5,12 +5,13 @@
|
|||
android:layout_height="fill_parent"
|
||||
android:stretchColumns="1">
|
||||
<TableRow>
|
||||
<ImageView android:id="@+id/itemicon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="3dip"></ImageView>
|
||||
<ImageView android:id="@+id/itemicon" android:layout_width="50dip" android:layout_height="50dip" android:padding="3dip"></ImageView>
|
||||
|
||||
<TextView android:layout_height="wrap_content" android:id="@+id/itemtext" android:text="uid:packages" android:textSize="18sp" android:padding="3dip"></TextView>
|
||||
|
||||
<CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/itemcheck" ></CheckBox>
|
||||
|
||||
</TableRow>
|
||||
|
||||
</TableLayout>
|
||||
|
||||
|
|
|
@ -33,11 +33,17 @@
|
|||
android:layout_toLeftOf="@+id/radioModeImage"
|
||||
android:textColor="#cccccc" />
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_gravity="center_vertical"
|
||||
|
||||
>
|
||||
<ImageView
|
||||
android:id="@+id/imgStatus"
|
||||
android:layout_margin="5dip"
|
||||
android:layout_width="320dip"
|
||||
android:layout_margin="15dip"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="320dip"
|
||||
android:src="@drawable/toroff"
|
||||
android:layout_gravity="center_horizontal"
|
||||
|
@ -45,14 +51,14 @@
|
|||
|
||||
<TextView android:id="@+id/lblStatus"
|
||||
android:text="@string/press_to_start"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:gravity="center_horizontal"
|
||||
android:textStyle="bold"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="30dip"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="60dip"
|
||||
android:textColor="#ffffff"
|
||||
android:layout_below="@id/imgStatus"
|
||||
/>
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/relativeLayout1"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:background="#000000">
|
||||
|
||||
<TextView android:textSize="10pt"
|
||||
android:textColor="#FFFFFF"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/WizardTextTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:fadingEdge="vertical"
|
||||
android:text="TITLE"
|
||||
android:singleLine="true"
|
||||
android:padding="20px" android:layout_centerInParent="true">
|
||||
</TextView>
|
||||
</RelativeLayout>
|
||||
<TableLayout android:id="@+id/TableLayout01" android:stretchColumns="*" android:layout_height="fill_parent" android:layout_width="wrap_content">
|
||||
|
||||
<TableRow android:layout_margin="10dip" android:id="@+id/TableRow01" android:layout_weight="1" android:layout_width="fill_parent" android:layout_height="fill_parent">
|
||||
|
||||
|
||||
<ScrollView android:id="@+id/helpscrollview"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_span="3"
|
||||
>
|
||||
<LinearLayout android:background="#575757" android:layout_width="wrap_content" android:id="@+id/linearLayout1" android:layout_height="wrap_content" android:orientation="vertical">
|
||||
<TextView android:layout_width="wrap_content" android:textColor="#ffffff" android:layout_height="wrap_content" android:textSize="8pt" android:id="@+id/WizardTextBody1" android:text="this is sample text this is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample text" android:padding="20dip"></TextView>
|
||||
<Button android:layout_width="wrap_content" android:visibility="gone" android:layout_height="wrap_content" android:gravity="center" android:text="Grant Permission" android:id="@+id/grantPermissions" android:layout_gravity="center"></Button>
|
||||
<TextView android:layout_width="wrap_content" android:visibility="gone" android:textColor="#ffffff" android:layout_height="wrap_content" android:textSize="8pt" android:id="@+id/WizardTextBody2" android:text="this is sample text this is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample text" android:padding="20dip"></TextView>
|
||||
<CheckBox android:id="@+id/checkBox" android:layout_gravity="center" android:text="@string/wizard_permissions_consent" android:layout_height="wrap_content" android:layout_width="wrap_content" android:gravity="center" android:visibility="visible"></CheckBox>
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
</TableRow>
|
||||
<TableRow android:background="#000000" android:layout_marginTop="10dip" android:paddingTop="10dip" android:id="@+id/TableRow01" android:textColor="#00ff00" android:layout_width="fill_parent" android:layout_height="30px">
|
||||
<Button android:text="Back" android:id="@+id/btnWizard1" android:layout_weight="1" android:layout_width="fill_parent" android:layout_height="wrap_content"></Button>
|
||||
<Button android:text="Next" android:id="@+id/btnWizard2" android:layout_weight="1" android:layout_width="fill_parent" android:layout_height="wrap_content"></Button>
|
||||
</TableRow>
|
||||
</TableLayout>
|
||||
</LinearLayout>
|
||||
|
||||
|
|
@ -1,29 +1,69 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="fill_parent">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/relativeLayout1"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:background="#000000">
|
||||
<TextView android:textSize="10pt"
|
||||
android:textColor="#FFFFFF"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/WizardTextTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:fadingEdge="vertical"
|
||||
android:text="TITLE"
|
||||
android:singleLine="true"
|
||||
android:padding="20px" android:layout_centerInParent="true">
|
||||
</TextView>
|
||||
</RelativeLayout>
|
||||
<TableLayout android:id="@+id/TableLayout01" android:stretchColumns="*" android:layout_height="fill_parent" android:layout_width="wrap_content">
|
||||
|
||||
<TableRow android:layout_margin="10dip" android:id="@+id/TableRow01" android:layout_weight="1" android:layout_width="fill_parent" android:layout_height="fill_parent">
|
||||
|
||||
|
||||
<ScrollView android:id="@+id/helpscrollview"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
<LinearLayout
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_span="3">
|
||||
|
||||
<LinearLayout
|
||||
android:background="#575757"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:padding="3px">
|
||||
<TextView android:text="@string/wizard_configure_msg" android:textColor="#ffffff" android:id="@+id/WizardRootTextView01" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
|
||||
|
||||
|
||||
<CheckBox android:layout_marginTop="20px" android:text="@string/wizard_configure_all" android:id="@+id/WizardRootCheckBox01" android:layout_width="wrap_content" android:layout_height="wrap_content"></CheckBox>
|
||||
<TextView android:text=" or " android:textColor="#ffffff" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
|
||||
|
||||
<Button android:text="@string/wizard_configure_select_apps" android:id="@+id/WizardRootButton01" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||
<TextView android:text="@string/wizard_transproxy_msg" android:layout_width="wrap_content" android:textColor="#ffffff" android:layout_height="wrap_content" android:textSize="8pt" android:id="@+id/WizardTextBody1" android:padding="20dip"></TextView>
|
||||
<RadioGroup android:id="@+id/radioGroup" android:layout_height="wrap_content" android:layout_width="wrap_content" android:paddingLeft="15dip">
|
||||
<RadioButton android:text="@string/wizard_configure_all" android:id="@+id/radio0" android:layout_height="wrap_content" android:layout_width="wrap_content"></RadioButton>
|
||||
<TextView android:layout_height="wrap_content"
|
||||
android:text="@string/wizard_transproxy_hint"
|
||||
android:layout_width="wrap_content"
|
||||
android:textSize="15sp"
|
||||
android:paddingBottom="10dip" android:paddingRight="20dip">
|
||||
</TextView>
|
||||
<RadioButton android:text="@string/wizard_configure_select_apps" android:id="@+id/radio1" android:layout_height="wrap_content" android:layout_width="wrap_content"></RadioButton>
|
||||
<RadioButton android:text="@string/wizard_transproxy_none" android:id="@+id/radio2" android:layout_height="wrap_content" android:layout_width="wrap_content"></RadioButton>
|
||||
</RadioGroup>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</ScrollView>
|
||||
|
||||
</TableRow>
|
||||
<TableRow android:background="#000000" android:layout_marginTop="10dip" android:paddingTop="10dip" android:id="@+id/TableRow01" android:textColor="#00ff00" android:layout_width="fill_parent" android:layout_height="30px">
|
||||
<Button android:text="Back" android:id="@+id/btnWizard1" android:layout_weight="1" android:layout_width="fill_parent" android:layout_height="wrap_content"></Button>
|
||||
<Button android:text="Next" android:id="@+id/btnWizard2" android:layout_weight="1" android:layout_width="fill_parent" android:layout_height="wrap_content"></Button>
|
||||
</TableRow>
|
||||
</TableLayout>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,29 +1,63 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="fill_parent">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/relativeLayout1"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:background="#000000">
|
||||
<TextView android:textSize="10pt"
|
||||
android:textColor="#FFFFFF"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/WizardTextTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:fadingEdge="vertical"
|
||||
android:text="TITLE"
|
||||
android:singleLine="true"
|
||||
android:padding="20px" android:layout_centerInParent="true">
|
||||
</TextView>
|
||||
</RelativeLayout>
|
||||
<TableLayout android:id="@+id/TableLayout01" android:stretchColumns="*" android:layout_height="fill_parent" android:layout_width="wrap_content">
|
||||
|
||||
<TableRow android:layout_margin="10dip" android:id="@+id/TableRow01" android:layout_weight="1" android:layout_width="fill_parent" android:layout_height="fill_parent">
|
||||
|
||||
|
||||
<ScrollView android:id="@+id/helpscrollview"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
<LinearLayout
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_span="3">
|
||||
|
||||
<LinearLayout
|
||||
android:background="#575757"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:padding="3px">
|
||||
android:paddingRight="20dip"
|
||||
>
|
||||
|
||||
<TextView android:text="@string/wizard_tips_msg" android:layout_gravity="left" android:textColor="#ffffff" android:id="@+id/TextView01" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
|
||||
<TextView android:text="@string/wizard_tips_msg" android:layout_width="wrap_content" android:textColor="#ffffff" android:layout_height="wrap_content" android:textSize="8pt" android:id="@+id/WizardTextBody1" android:padding="20dip"></TextView>
|
||||
<Button android:text="@string/wizard_tips_gibberbot" android:layout_gravity="left" android:drawableLeft="@drawable/ic_launcher_gibberbot" android:layout_marginTop="10px" android:id="@+id/WizardRootButtonInstallGibberbot" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||
|
||||
<Button android:text="@string/wizard_tips_otrchat" android:layout_gravity="left" android:drawableLeft="@drawable/ic_launcher_gibberbot" android:layout_marginTop="10px" android:id="@+id/WizardRootButtonInstallOtrchat" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||
<Button android:text="@string/wizard_tips_firefox" android:layout_gravity="left" android:drawableLeft="@drawable/icon_firefox" android:layout_marginTop="10px" android:id="@+id/WizardRootButtonInstallFirefox" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||
|
||||
<Button android:text="@string/wizard_tips_orweb" android:drawableLeft="@drawable/icon_orweb" android:layout_marginTop="10px" android:id="@+id/WizardRootButtonInstallOrweb" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||
|
||||
<Button android:text="@string/wizard_tips_proxy" android:layout_marginTop="10px" android:id="@+id/WizardRootButtonProxyHelp" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||
<Button android:text="@string/wizard_tips_proxymob" android:layout_marginTop="10px" android:drawableLeft="@drawable/proxymob" android:id="@+id/WizardRootButtonInstallProxyMob" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</ScrollView>
|
||||
|
||||
</TableRow>
|
||||
<TableRow android:background="#000000" android:layout_marginTop="10dip" android:paddingTop="10dip" android:id="@+id/TableRow01" android:textColor="#00ff00" android:layout_width="fill_parent" android:layout_height="30px">
|
||||
<Button android:text="Back" android:id="@+id/btnWizard1" android:layout_weight="1" android:layout_width="fill_parent" android:layout_height="wrap_content"></Button>
|
||||
<Button android:text="Next" android:id="@+id/btnWizard2" android:layout_weight="1" android:layout_width="fill_parent" android:layout_height="wrap_content"></Button>
|
||||
</TableRow>
|
||||
</TableLayout>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/relativeLayout1"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:background="#000000"
|
||||
>
|
||||
<ImageView
|
||||
android:src="@drawable/warning"
|
||||
android:id="@+id/orbot_image"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:paddingLeft="20px" android:layout_marginLeft="10dip" android:layout_marginTop="8dip">
|
||||
</ImageView>
|
||||
<TextView
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="10pt"
|
||||
android:layout_toRightOf="@id/orbot_image"
|
||||
android:layout_alignParentTop="true"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/WizardTextTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:fadingEdge="vertical"
|
||||
android:text="TITLE"
|
||||
android:singleLine="true"
|
||||
|
||||
|
||||
|
||||
android:layout_centerInParent="true"
|
||||
android:paddingLeft="5px"
|
||||
android:padding="20px"
|
||||
>
|
||||
</TextView>
|
||||
</RelativeLayout>
|
||||
<TableLayout android:id="@+id/TableLayout01" android:stretchColumns="*" android:layout_height="fill_parent" android:layout_width="wrap_content" >
|
||||
|
||||
<TableRow android:id="@+id/TableRow01" android:layout_weight="1" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_margin="10dip">
|
||||
|
||||
|
||||
<ScrollView android:id="@+id/helpscrollview"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_span="3">
|
||||
|
||||
<TextView android:background="#575757" android:text="this is sample text this is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample textthis is sample text" android:textColor="#ffffff" android:id="@+id/WizardTextBody" android:textSize="8pt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="20dip"></TextView>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
</TableRow>
|
||||
<TableRow android:background="#000000" android:id="@+id/TableRow01" android:textColor="#00ff00" android:layout_width="fill_parent" android:layout_height="30px" android:layout_marginTop="10dip" android:paddingTop="10dip">
|
||||
<Button android:text="Back" android:id="@+id/btnWizard1" android:layout_weight="1" android:layout_width="fill_parent" android:layout_height="wrap_content"></Button>
|
||||
<Button android:text="Next" android:id="@+id/btnWizard2" android:layout_weight="1" android:layout_width="fill_parent" android:layout_height="wrap_content"></Button>
|
||||
</TableRow>
|
||||
</TableLayout>
|
||||
</LinearLayout>
|
||||
|
||||
|
BIN
res/raw/tor
BIN
res/raw/tor
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -7,5 +7,8 @@ RelayBandwidthRate 20 KBytes
|
|||
RelayBandwidthBurst 20 KBytes
|
||||
UseBridges 0
|
||||
AutomapHostsOnResolve 1
|
||||
TransListenAddress 0.0.0.0
|
||||
TransPort 9040
|
||||
DNSListenAddress 0.0.0.0
|
||||
DNSPort 5400
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">اوربوت (Orbot)</string>
|
||||
<string name="app_version">1.0.5</string>
|
||||
|
||||
<string name="internal_web_url">http://orbot/</string>
|
||||
<string name="default_web_url">http://check.torproject.org</string>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Orbot</string>
|
||||
<string name="app_version">1.0.5</string>
|
||||
|
||||
<string name="internal_web_url">http://orbot/</string>
|
||||
<string name="default_web_url">http://check.torproject.org</string>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Orbot</string>
|
||||
<string name="app_version">1.0.5</string>
|
||||
|
||||
<string name="internal_web_url">http://orbot/</string>
|
||||
<string name="default_web_url">http://check.torproject.org</string>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Orbot</string>
|
||||
<string name="app_version">1.0.5</string>
|
||||
|
||||
<string name="internal_web_url">http://orbot/</string>
|
||||
<string name="default_web_url">http://check.torproject.org</string>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">اوربات</string>
|
||||
<string name="app_version">1.0.5</string>
|
||||
|
||||
<string name="internal_web_url">http://orbot/</string>
|
||||
<string name="default_web_url">http://check.torproject.org</string>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Орбот</string>
|
||||
<string name="app_version">1.0.5</string>
|
||||
|
||||
<string name="internal_web_url">http://orbot/</string>
|
||||
<string name="default_web_url">http://check.torproject.org</string>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Orbot</string>
|
||||
<string name="app_version">1.0.5</string>
|
||||
|
||||
<string name="internal_web_url">http://orbot/</string>
|
||||
<string name="default_web_url">http://check.torproject.org</string>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Orbot</string>
|
||||
<string name="app_version">1.0.5</string>
|
||||
|
||||
<string name="internal_web_url">http://orbot/</string>
|
||||
<string name="default_web_url">http://check.torproject.org</string>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Orbot</string>
|
||||
<string name="app_version">1.0.5</string>
|
||||
|
||||
<string name="internal_web_url">http://orbot/</string>
|
||||
<string name="default_web_url">http://check.torproject.org</string>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Orbot</string>
|
||||
<string name="app_version">1.0.5</string>
|
||||
<string name="internal_web_url">http://orbot/</string>
|
||||
<string name="default_web_url">http://check.torproject.org</string>
|
||||
<string name="secure_default_web_url">https://check.torproject.org</string>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Orbot</string>
|
||||
<string name="app_version">1.0.5</string>
|
||||
|
||||
<string name="internal_web_url">http://orbot/</string>
|
||||
<string name="default_web_url">http://check.torproject.org</string>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Orbot</string>
|
||||
<string name="app_version">1.0.5</string>
|
||||
|
||||
<string name="internal_web_url">http://orbot/</string>
|
||||
<string name="default_web_url">http://check.torproject.org</string>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Orbot</string>
|
||||
<string name="app_version">1.0.5</string>
|
||||
|
||||
<string name="internal_web_url">http://orbot/</string>
|
||||
<string name="default_web_url">http://check.torproject.org</string>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Orbot</string>
|
||||
<string name="app_version">1.0.5</string>
|
||||
|
||||
<string name="internal_web_url">http://orbot/</string>
|
||||
<string name="default_web_url">http://check.torproject.org</string>
|
||||
|
@ -130,5 +129,42 @@
|
|||
<string name="pref_general_group">General</string>
|
||||
<string name="pref_start_boot_title">Start Orbot on Boot</string>
|
||||
<string name="pref_start_boot_summary">Automatically start Orbot and connect Tor when your Android device boots</string>
|
||||
|
||||
<!-- New Wizard Strings -->
|
||||
<!-- Title Screen -->
|
||||
<string name="wizard_title_msg">Orbot brings Tor to Android \n\nTor helps you defend against a form of network surveillance that threatens privacy, confidential business activity and relationships, and state security known as traffic analysis</string>
|
||||
<!-- Warning screen -->
|
||||
<string name="wizard_warning_title">Warning</string>
|
||||
<string name="wizard_warning_msg">Simply installing Orbot will not automatically anonymize your mobile traffic.\n\nPlease follow the following steps to get started</string>
|
||||
<!-- Permissions screen -->
|
||||
<string name="wizard_permissions_title">Permissions</string>
|
||||
<string name="wizard_permissions_root_msg1">Orbot has detected that you have root permissions enabled. To enable \'Transparent Proxying\', please grant superuser privileges to Orbot</string>
|
||||
<string name="wizard_permissions_root_msg2">If you choose to continue without providing superuser privileges, make sure to use apps made to work with orbot</string>
|
||||
<string name="wizard_permissions_msg">Orbot has detected that you do not have root permissions.\nTransparent Proxying is not possible without superuser privileges.\nMake sure to use apps that have been configured to work with Orbot</string>
|
||||
<!-- TipsAndTricks screen -->
|
||||
<string name="wizard_tips_title">Orbot configured Apps</string>
|
||||
<string name="wizard_tips_gibberbot">Gibberbot - Secure instant messaging client for Android</string>
|
||||
<string name="wizard_tips_firefox">Firefox - Android browser - To be used along with ProxyMob Add-on </string>
|
||||
<string name="wizard_tips_proxymob">ProxyMob - Simple Firefox Add-on for setting HTTP, SOCKS and SSL proxy settings</string>
|
||||
<string name="gibberbot_apk_url">https://market.android.com/details?id=info.guardianproject.otr.app.im</string>
|
||||
<string name="firefox_apk_url">https://market.android.com/details?id=org.mozilla.firefox</string>
|
||||
<string name="proxymob_url">https://addons.mozilla.org/mobile/downloads/latest/251558/type:attachment/addon-251558-latest.xpi?src=addon-detail</string>
|
||||
<!-- Transparent Proxy screen -->
|
||||
<string name="wizard_transproxy_title">Transparent Proxy</string>
|
||||
<string name="wizard_transproxy_msg">Transparent Proxying allows you to redirect client requests without any special configuration or knowledge at the client.</string>
|
||||
<string name="wizard_transproxy_hint">(Check this box if you have no idea what we are talking about)</string>
|
||||
<string name="wizard_transproxy_none">None</string>
|
||||
|
||||
<string name="pref_transparent_tethering_title">Tor Tethering</string>
|
||||
<string name="pref_transparent_tethering_summary">Enable Tor Transparent Proxying for Wifi and USB Tethered Devices</string>
|
||||
|
||||
|
||||
<string name="pref_select_apps">Select Apps</string>
|
||||
<string name="pref_select_apps_summary">Choose Apps to Route Through Tor</string>
|
||||
|
||||
<string name="pref_node_configuration">Node Configuration</string>
|
||||
<string name="pref_node_configuration_summary">These are advanced settings that can reduce your anonymity</string>
|
||||
|
||||
<string name="pref_entrance_node">Entrance Nodes</string>
|
||||
<string name="pref_entrance_node_summary">Fingerprints, nicks, countries and addresses for the first hop</string>
|
||||
<string name="pref_entrance_node_dialog">Enter Entrance Nodes</string>
|
||||
</resources>
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<resources>
|
||||
<color name="custom_theme_color">#333</color>
|
||||
<style name="DefaultTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<item name="android:windowBackground">@drawable/bgtitanium</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
</style>
|
||||
</resources>
|
|
@ -35,18 +35,27 @@ android:title="@string/pref_transparent_all_title"/>
|
|||
<Preference
|
||||
android:defaultValue=""
|
||||
android:key="pref_transparent_app_list"
|
||||
android:title="Select Apps"
|
||||
android:summary="Choose Apps to Route Through Tor"
|
||||
android:title="@string/pref_select_apps"
|
||||
android:summary="@string/pref_select_apps_summary"
|
||||
android:enabled="true"/>
|
||||
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:key="pref_transparent_tethering"
|
||||
android:summary="@string/pref_transparent_tethering_summary"
|
||||
android:enabled="true"
|
||||
android:title="@string/pref_transparent_tethering_title"/>
|
||||
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory android:title="Node Configuration" android:summary="These are advanced settings that can reduce your anonymity">
|
||||
<PreferenceCategory android:title="@string/pref_node_configuration"
|
||||
android:summary="@string/pref_node_configuration_summary">
|
||||
|
||||
<EditTextPreference android:key="pref_entrance_nodes"
|
||||
android:title="Entrance Nodes"
|
||||
android:summary="Fingerprints, nicks, countries and addresses for the first hop"
|
||||
android:dialogTitle="Enter Entrance Nodes"
|
||||
android:title="@string/pref_entrance_node"
|
||||
android:summary="@string/pref_entrance_node_summary"
|
||||
android:dialogTitle="@string/pref_entrance_node_dialog"
|
||||
/>
|
||||
<EditTextPreference android:key="pref_exit_nodes"
|
||||
android:title="Exit Nodes"
|
||||
|
@ -70,11 +79,6 @@ android:summary="Use *only* these specified nodes"/>
|
|||
android:title="Use Bridges" android:key="pref_bridges_enabled"
|
||||
android:summary="Enable alternate entrance nodes into the Tor Network"></CheckBoxPreference>
|
||||
|
||||
<!-- 5/8/2010 NF: Arma says this doesn't actually work, so commenting out for now
|
||||
<CheckBoxPreference android:defaultValue="false"
|
||||
android:title="Update from Authority" android:key="pref_bridges_update"
|
||||
android:summary="Modify bridge list automatically"></CheckBoxPreference>
|
||||
-->
|
||||
|
||||
<EditTextPreference android:key="pref_bridges_list"
|
||||
android:title="Bridges"
|
||||
|
|
|
@ -0,0 +1,183 @@
|
|||
package org.torproject.android;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.Editor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.RadioGroup;
|
||||
import android.widget.TextView;
|
||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class ConfigureTransProxy extends Activity implements TorConstants {
|
||||
|
||||
private Context context;
|
||||
private int flag = 0;
|
||||
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
context = this;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
|
||||
super.onStart();
|
||||
setContentView(R.layout.layout_wizard_root);
|
||||
|
||||
stepSix();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void stepSix(){
|
||||
|
||||
String title = context.getString(R.string.wizard_transproxy_title);
|
||||
TextView txtTitle = ((TextView)findViewById(R.id.WizardTextTitle));
|
||||
txtTitle.setText(title);
|
||||
|
||||
Button back = ((Button)findViewById(R.id.btnWizard1));
|
||||
Button next = ((Button)findViewById(R.id.btnWizard2));
|
||||
next.setEnabled(false);
|
||||
|
||||
back.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
startActivityForResult(new Intent(getBaseContext(), Permissions.class), 1);
|
||||
}
|
||||
});
|
||||
|
||||
next.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
//Dirty flag variable - improve logic
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if( flag == 1 )
|
||||
context.startActivity(new Intent(context, AppManager.class));
|
||||
|
||||
else
|
||||
showWizardFinal();
|
||||
}
|
||||
});
|
||||
|
||||
RadioGroup mRadioGroup = (RadioGroup)findViewById(R.id.radioGroup);
|
||||
mRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener (){
|
||||
|
||||
|
||||
@Override
|
||||
public void onCheckedChanged(RadioGroup group, int checkedId){
|
||||
Button next = ((Button)findViewById(R.id.btnWizard2));
|
||||
next.setEnabled(true);
|
||||
next.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
showWizardFinal();
|
||||
}
|
||||
});
|
||||
|
||||
RadioButton rb0 = (RadioButton)findViewById(R.id.radio0);
|
||||
RadioButton rb1 = (RadioButton)findViewById(R.id.radio1);
|
||||
RadioButton rb2 = (RadioButton)findViewById(R.id.radio2);
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
Editor pEdit = prefs.edit();
|
||||
pEdit.putBoolean(PREF_TRANSPARENT, rb0.isChecked());
|
||||
pEdit.putBoolean(PREF_TRANSPARENT_ALL, rb0.isChecked());
|
||||
pEdit.commit();
|
||||
|
||||
if(rb0.isChecked())
|
||||
{
|
||||
pEdit.putString("radiobutton","rb0");
|
||||
pEdit.commit();
|
||||
}
|
||||
|
||||
else if(rb1.isChecked())
|
||||
{
|
||||
flag = 1;
|
||||
|
||||
pEdit.putBoolean(PREF_TRANSPARENT, true);
|
||||
pEdit.putBoolean(PREF_TRANSPARENT_ALL, false);
|
||||
pEdit.putString("radiobutton","rb1");
|
||||
pEdit.commit();
|
||||
|
||||
next.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
context.startActivity(new Intent(context, AppManager.class));
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
else if(rb2.isChecked())
|
||||
{
|
||||
pEdit.putString("radiobutton", "rb2");
|
||||
pEdit.commit();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void showWizardFinal ()
|
||||
{
|
||||
String title = null;
|
||||
String msg = null;
|
||||
|
||||
|
||||
title = context.getString(R.string.wizard_final);
|
||||
msg = context.getString(R.string.wizard_final_msg);
|
||||
|
||||
DialogInterface.OnClickListener ocListener = new DialogInterface.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
context.startActivity(new Intent(context, Orbot.class));
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
new AlertDialog.Builder(context)
|
||||
.setIcon(R.drawable.icon)
|
||||
.setTitle(title)
|
||||
.setPositiveButton(R.string.button_close, ocListener)
|
||||
.setMessage(msg)
|
||||
.show();
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
package org.torproject.android;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.Editor;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class LotsaText extends Activity implements TorConstants{
|
||||
|
||||
private Context context;
|
||||
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
context = this;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
|
||||
super.onStart();
|
||||
setContentView(R.layout.scrollingtext_buttons_view);
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
boolean wizardScreen1 = prefs.getBoolean("wizardscreen1",true);
|
||||
if(wizardScreen1)
|
||||
stepOne();
|
||||
else
|
||||
stepTwo();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void stepOne() {
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
Editor pEdit = prefs.edit();
|
||||
pEdit.putBoolean("wizardscreen1",true);
|
||||
pEdit.commit();
|
||||
|
||||
String title = context.getString(R.string.wizard_title);
|
||||
String msg = context.getString(R.string.wizard_title_msg);
|
||||
|
||||
TextView txtTitle = ((TextView)findViewById(R.id.WizardTextTitle));
|
||||
txtTitle.setText(title);
|
||||
|
||||
TextView txtBody = ((TextView)findViewById(R.id.WizardTextBody));
|
||||
txtBody.setText(msg);
|
||||
|
||||
Button btn1 = ((Button)findViewById(R.id.btnWizard1));
|
||||
Button btn2 = ((Button)findViewById(R.id.btnWizard2));
|
||||
ImageView img = (ImageView) findViewById(R.id.orbot_image);
|
||||
|
||||
btn1.setVisibility(Button.INVISIBLE);
|
||||
img.setImageResource(R.drawable.tor);
|
||||
|
||||
btn2.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
stepTwo();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void stepTwo() {
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
Editor pEdit = prefs.edit();
|
||||
pEdit.putBoolean("wizardscreen1",false);
|
||||
pEdit.commit();
|
||||
|
||||
setContentView(R.layout.scrollingtext_buttons_view);
|
||||
String title = context.getString(R.string.wizard_warning_title);
|
||||
String msg = context.getString(R.string.wizard_warning_msg);
|
||||
|
||||
TextView txtTitle = ((TextView)findViewById(R.id.WizardTextTitle));
|
||||
txtTitle.setText(title);
|
||||
|
||||
TextView txtBody = ((TextView)findViewById(R.id.WizardTextBody));
|
||||
txtBody.setText(msg);
|
||||
|
||||
Button btn1 = ((Button)findViewById(R.id.btnWizard1));
|
||||
Button btn2 = ((Button)findViewById(R.id.btnWizard2));
|
||||
ImageView img = (ImageView) findViewById(R.id.orbot_image);
|
||||
|
||||
btn1.setVisibility(Button.VISIBLE);
|
||||
img.setImageResource(R.drawable.warning);
|
||||
|
||||
btn1.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
stepOne();
|
||||
}
|
||||
});
|
||||
|
||||
btn2.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
startActivityForResult(new Intent(getBaseContext(), Permissions.class), 1);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,229 @@
|
|||
package org.torproject.android;
|
||||
|
||||
import org.torproject.android.service.TorService;
|
||||
import org.torproject.android.service.TorServiceUtils;
|
||||
import org.torproject.android.service.TorTransProxy;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.Editor;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class Permissions extends Activity implements TorConstants {
|
||||
|
||||
private Context context;
|
||||
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
context = this;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
|
||||
super.onStart();
|
||||
setContentView(R.layout.layout_wizard_permissions);
|
||||
|
||||
stepThree();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void stepThree(){
|
||||
|
||||
boolean hasRoot = TorServiceUtils.checkRootAccess();
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
Editor pEdit = prefs.edit();
|
||||
pEdit.putBoolean("has_root",hasRoot);
|
||||
pEdit.commit();
|
||||
|
||||
if (hasRoot)
|
||||
{
|
||||
stepFourRoot();
|
||||
}
|
||||
else
|
||||
{
|
||||
stepFour();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void stepFourRoot(){
|
||||
|
||||
String title = context.getString(R.string.wizard_permissions_title);
|
||||
String msg1 = context.getString(R.string.wizard_permissions_root_msg1);
|
||||
String msg2 = context.getString(R.string.wizard_permissions_root_msg2);
|
||||
|
||||
TextView txtTitle = ((TextView)findViewById(R.id.WizardTextTitle));
|
||||
txtTitle.setText(title);
|
||||
|
||||
TextView txtBody1 = ((TextView)findViewById(R.id.WizardTextBody1));
|
||||
txtBody1.setText(msg1);
|
||||
|
||||
|
||||
TextView txtBody2 = ((TextView)findViewById(R.id.WizardTextBody2));
|
||||
txtBody2.setText(msg2);
|
||||
txtBody2.setVisibility(TextView.VISIBLE);
|
||||
|
||||
Button grantPermissions = ((Button)findViewById(R.id.grantPermissions));
|
||||
grantPermissions.setVisibility(Button.VISIBLE);
|
||||
|
||||
Button back = ((Button)findViewById(R.id.btnWizard1));
|
||||
Button next = ((Button)findViewById(R.id.btnWizard2));
|
||||
next.setEnabled(false);
|
||||
|
||||
CheckBox consent = (CheckBox)findViewById(R.id.checkBox);
|
||||
consent.setVisibility(CheckBox.VISIBLE);
|
||||
|
||||
consent.setOnCheckedChangeListener(new OnCheckedChangeListener (){
|
||||
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView,
|
||||
boolean isChecked) {
|
||||
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
Editor pEdit = prefs.edit();
|
||||
|
||||
pEdit.putBoolean(PREF_TRANSPARENT, !isChecked);
|
||||
pEdit.putBoolean(PREF_TRANSPARENT_ALL, !isChecked);
|
||||
|
||||
pEdit.commit();
|
||||
|
||||
Button next = ((Button)findViewById(R.id.btnWizard2));
|
||||
if(isChecked)
|
||||
next.setEnabled(true);
|
||||
else
|
||||
next.setEnabled(false);
|
||||
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
grantPermissions.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
//Check and Install iptables - TorTransProxy.testOwnerModule(this)
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
boolean hasRoot = prefs.getBoolean("has_root",false);
|
||||
|
||||
if (hasRoot)
|
||||
{
|
||||
try {
|
||||
int resp = TorTransProxy.testOwnerModule(context);
|
||||
|
||||
if (resp < 0)
|
||||
{
|
||||
hasRoot = false;
|
||||
Toast.makeText(context, "ERROR: IPTables OWNER module not available", Toast.LENGTH_LONG).show();
|
||||
|
||||
Log.i(TorService.TAG,"ERROR: IPTables OWNER module not available");
|
||||
stepFour();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
hasRoot = false;
|
||||
Log.d(TorService.TAG,"ERROR: IPTables OWNER module not available",e);
|
||||
}
|
||||
}
|
||||
|
||||
startActivityForResult(new Intent(getBaseContext(), ConfigureTransProxy.class), 1);
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
back.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
startActivityForResult(new Intent(getBaseContext(), LotsaText.class), 1);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
next.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
startActivityForResult(new Intent(getBaseContext(), TipsAndTricks.class), 1);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void stepFour(){
|
||||
|
||||
Toast.makeText(context, "NON ROOT FUNC", Toast.LENGTH_SHORT).show();
|
||||
String title = context.getString(R.string.wizard_permissions_title);
|
||||
String msg = context.getString(R.string.wizard_permissions_msg);
|
||||
|
||||
TextView txtTitle = ((TextView)findViewById(R.id.WizardTextTitle));
|
||||
txtTitle.setText(title);
|
||||
|
||||
TextView txtBody = ((TextView)findViewById(R.id.WizardTextBody1));
|
||||
txtBody.setText(msg);
|
||||
|
||||
Button btn1 = ((Button)findViewById(R.id.btnWizard1));
|
||||
Button btn2 = ((Button)findViewById(R.id.btnWizard2));
|
||||
btn2.setEnabled(true);
|
||||
|
||||
|
||||
TextView txtBody2 = ((TextView)findViewById(R.id.WizardTextBody2));
|
||||
txtBody2.setVisibility(TextView.GONE);
|
||||
|
||||
Button grantPermissions = ((Button)findViewById(R.id.grantPermissions));
|
||||
grantPermissions.setVisibility(Button.GONE);
|
||||
|
||||
|
||||
CheckBox consent = (CheckBox)findViewById(R.id.checkBox);
|
||||
consent.setVisibility(CheckBox.GONE);
|
||||
|
||||
btn1.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
startActivityForResult(new Intent(getBaseContext(), LotsaText.class), 1);
|
||||
}
|
||||
});
|
||||
|
||||
btn2.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
startActivityForResult(new Intent(getBaseContext(), TipsAndTricks.class), 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -28,6 +28,9 @@ public class SettingsPreferences
|
|||
|
||||
private boolean hasRoot = false;
|
||||
|
||||
|
||||
private final static int HIDDEN_SERVICE_PREF_IDX = 6;
|
||||
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
@ -77,12 +80,11 @@ public class SettingsPreferences
|
|||
|
||||
}
|
||||
|
||||
int hiddenGroupIdx = 6;
|
||||
|
||||
prefHiddenServices = ((CheckBoxPreference)((PreferenceCategory)this.getPreferenceScreen().getPreference(hiddenGroupIdx)).getPreference(0));
|
||||
prefHiddenServices = ((CheckBoxPreference)((PreferenceCategory)this.getPreferenceScreen().getPreference(HIDDEN_SERVICE_PREF_IDX)).getPreference(0));
|
||||
prefHiddenServices.setOnPreferenceClickListener(this);
|
||||
((PreferenceCategory)this.getPreferenceScreen().getPreference(hiddenGroupIdx)).getPreference(1).setEnabled(prefHiddenServices.isChecked());
|
||||
((PreferenceCategory)this.getPreferenceScreen().getPreference(hiddenGroupIdx)).getPreference(2).setEnabled(prefHiddenServices.isChecked());
|
||||
((PreferenceCategory)this.getPreferenceScreen().getPreference(HIDDEN_SERVICE_PREF_IDX)).getPreference(1).setEnabled(prefHiddenServices.isChecked());
|
||||
((PreferenceCategory)this.getPreferenceScreen().getPreference(HIDDEN_SERVICE_PREF_IDX)).getPreference(2).setEnabled(prefHiddenServices.isChecked());
|
||||
|
||||
|
||||
};
|
||||
|
@ -113,8 +115,8 @@ public class SettingsPreferences
|
|||
else if (preference == prefHiddenServices)
|
||||
{
|
||||
|
||||
((PreferenceCategory)this.getPreferenceScreen().getPreference(5)).getPreference(1).setEnabled(prefHiddenServices.isChecked());
|
||||
((PreferenceCategory)this.getPreferenceScreen().getPreference(5)).getPreference(2).setEnabled(prefHiddenServices.isChecked());
|
||||
((PreferenceCategory)this.getPreferenceScreen().getPreference(HIDDEN_SERVICE_PREF_IDX)).getPreference(1).setEnabled(prefHiddenServices.isChecked());
|
||||
((PreferenceCategory)this.getPreferenceScreen().getPreference(HIDDEN_SERVICE_PREF_IDX)).getPreference(2).setEnabled(prefHiddenServices.isChecked());
|
||||
|
||||
}
|
||||
else
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
package org.torproject.android;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class TipsAndTricks extends Activity implements TorConstants {
|
||||
|
||||
private Context context;
|
||||
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
context = this;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
|
||||
super.onStart();
|
||||
setContentView(R.layout.layout_wizard_tips);
|
||||
|
||||
stepFive();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void stepFive(){
|
||||
|
||||
String title = context.getString(R.string.wizard_tips_title);
|
||||
TextView txtTitle = ((TextView)findViewById(R.id.WizardTextTitle));
|
||||
txtTitle.setText(title);
|
||||
|
||||
Button btn1 = (Button)findViewById(R.id.WizardRootButtonInstallGibberbot);
|
||||
|
||||
btn1.setOnClickListener(new OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
|
||||
String url = context.getString(R.string.gibberbot_apk_url);
|
||||
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
Button btn2 = (Button)findViewById(R.id.WizardRootButtonInstallFirefox);
|
||||
|
||||
btn2.setOnClickListener(new OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
|
||||
String url = context.getString(R.string.firefox_apk_url);
|
||||
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
Button btn3 = (Button)findViewById(R.id.WizardRootButtonInstallProxyMob);
|
||||
|
||||
btn3.setOnClickListener(new OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
|
||||
String url = context.getString(R.string.proxymob_url);
|
||||
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
|
||||
}
|
||||
});
|
||||
|
||||
Button back = ((Button)findViewById(R.id.btnWizard1));
|
||||
Button next = ((Button)findViewById(R.id.btnWizard2));
|
||||
|
||||
back.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
startActivityForResult(new Intent(getBaseContext(), Permissions.class), 1);
|
||||
}
|
||||
});
|
||||
|
||||
next.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
showWizardFinal();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void showWizardFinal ()
|
||||
{
|
||||
String title = null;
|
||||
String msg = null;
|
||||
|
||||
|
||||
title = context.getString(R.string.wizard_final);
|
||||
msg = context.getString(R.string.wizard_final_msg);
|
||||
|
||||
DialogInterface.OnClickListener ocListener = new DialogInterface.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
context.startActivity(new Intent(context, Orbot.class));
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
new AlertDialog.Builder(context)
|
||||
.setIcon(R.drawable.icon)
|
||||
.setTitle(title)
|
||||
.setPositiveButton(R.string.button_close, ocListener)
|
||||
.setMessage(msg)
|
||||
.show();
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
package org.torproject.android;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
||||
public class WizardActivity extends Activity implements OnClickListener
|
||||
{
|
||||
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
|
||||
this.setContentView(R.layout.layout_help);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
|
||||
super.onStart();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
showStep1();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void showStep1()
|
||||
{
|
||||
showDialog("Test","","foo","bar",this);
|
||||
}
|
||||
|
||||
private void showDialog (String title, String msg, String button1, String button2, OnClickListener ocListener)
|
||||
{
|
||||
|
||||
new AlertDialog.Builder(this)
|
||||
.setInverseBackgroundForced(true)
|
||||
.setTitle(title)
|
||||
.setMessage(msg)
|
||||
.setNeutralButton(button1, ocListener)
|
||||
.setNegativeButton(button2, ocListener)
|
||||
.show();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface arg0, int arg1) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -215,7 +215,7 @@ public class WizardHelper implements TorConstants {
|
|||
LayoutInflater li = LayoutInflater.from(context);
|
||||
View view = li.inflate(R.layout.layout_wizard_tips, null);
|
||||
|
||||
Button btn1 = (Button)view.findViewById(R.id.WizardRootButtonInstallOtrchat);
|
||||
Button btn1 = (Button)view.findViewById(R.id.WizardRootButtonInstallGibberbot);
|
||||
|
||||
btn1.setOnClickListener(new OnClickListener() {
|
||||
|
||||
|
@ -228,7 +228,7 @@ public class WizardHelper implements TorConstants {
|
|||
}
|
||||
});
|
||||
|
||||
Button btn2 = (Button)view.findViewById(R.id.WizardRootButtonInstallOrweb);
|
||||
Button btn2 = (Button)view.findViewById(R.id.WizardRootButtonInstallFirefox);
|
||||
|
||||
btn2.setOnClickListener(new OnClickListener() {
|
||||
|
||||
|
@ -241,7 +241,7 @@ public class WizardHelper implements TorConstants {
|
|||
}
|
||||
});
|
||||
|
||||
Button btn3 = (Button)view.findViewById(R.id.WizardRootButtonProxyHelp);
|
||||
Button btn3 = (Button)view.findViewById(R.id.WizardRootButtonInstallProxyMob);
|
||||
|
||||
btn3.setOnClickListener(new OnClickListener() {
|
||||
|
||||
|
@ -277,7 +277,7 @@ public class WizardHelper implements TorConstants {
|
|||
|
||||
public void showWizardRootConfigureTorification()
|
||||
{
|
||||
|
||||
/*
|
||||
LayoutInflater li = LayoutInflater.from(context);
|
||||
View view = li.inflate(R.layout.layout_wizard_root, null);
|
||||
|
||||
|
@ -347,7 +347,7 @@ public class WizardHelper implements TorConstants {
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
package org.torproject.android.boot;
|
||||
|
||||
import org.torproject.android.service.ITorService;
|
||||
import org.torproject.android.service.TorService;
|
||||
import org.torproject.android.service.TorServiceConstants;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
|
||||
public class OnbootBroadcastReceiver extends BroadcastReceiver implements TorServiceConstants {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
|
||||
Log.d(TAG, "received on boot notification");
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
boolean startOnBoot = prefs.getBoolean("pref_start_boot",true);
|
||||
|
||||
Log.d(TAG, "startOnBoot:" + startOnBoot);
|
||||
|
||||
if (startOnBoot)
|
||||
{
|
||||
Intent serviceIntent = new Intent(context,TorService.class);
|
||||
serviceIntent.setAction("onboot");
|
||||
context.startService(serviceIntent);
|
||||
}
|
||||
|
||||
//bindService(new Intent(ITorService.class.getName()),
|
||||
// mConnection, Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
}
|
|
@ -55,7 +55,7 @@ import android.widget.Toast;
|
|||
* Contains shared programming interfaces.
|
||||
* All iptables "communication" is handled by this class.
|
||||
*/
|
||||
public final class Api {
|
||||
public final class IptablesManager {
|
||||
/** application version string */
|
||||
public static final String VERSION = "1.5.1-dev";
|
||||
/** special application UID used to indicate "any application" */
|
||||
|
@ -861,8 +861,8 @@ public final class Api {
|
|||
return;
|
||||
}
|
||||
/* notify */
|
||||
final Intent message = new Intent(Api.STATUS_CHANGED_MSG);
|
||||
message.putExtra(Api.STATUS_EXTRA, enabled);
|
||||
final Intent message = new Intent(IptablesManager.STATUS_CHANGED_MSG);
|
||||
message.putExtra(IptablesManager.STATUS_EXTRA, enabled);
|
||||
ctx.sendBroadcast(message);
|
||||
}
|
||||
/**
|
|
@ -20,160 +20,88 @@ import android.util.Log;
|
|||
public class TorBinaryInstaller implements TorServiceConstants {
|
||||
|
||||
|
||||
String installPath;
|
||||
String apkPath;
|
||||
File installFolder;
|
||||
Context context;
|
||||
|
||||
public TorBinaryInstaller (Context context, String installPath, String apkPath)
|
||||
public TorBinaryInstaller (Context context, File installFolder)
|
||||
{
|
||||
this.installPath = installPath;
|
||||
this.apkPath = apkPath;
|
||||
this.installFolder = installFolder;
|
||||
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the binary installation if the file doesn't exist or is forced
|
||||
*/
|
||||
public void start (boolean force)
|
||||
{
|
||||
|
||||
boolean torBinaryExists = new File(installPath + TOR_BINARY_ASSET_KEY).exists();
|
||||
Log.d(TAG,"Tor binary exists=" + torBinaryExists);
|
||||
|
||||
boolean privoxyBinaryExists = new File(installPath + PRIVOXY_ASSET_KEY).exists();
|
||||
Log.d(TAG,"Privoxy binary exists=" + privoxyBinaryExists);
|
||||
|
||||
if (!(torBinaryExists && privoxyBinaryExists) || force)
|
||||
installFromRaw ();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
/*
|
||||
* Extract the Tor binary from the APK file using ZIP
|
||||
*/
|
||||
private void installFromRaw ()
|
||||
public boolean installFromRaw ()
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
|
||||
InputStream is = context.getResources().openRawResource(R.raw.tor);
|
||||
streamToFile(is,installPath + TOR_BINARY_ASSET_KEY);
|
||||
|
||||
|
||||
is = context.getResources().openRawResource(R.raw.torrc);
|
||||
streamToFile(is,installPath + TORRC_ASSET_KEY);
|
||||
|
||||
is = context.getResources().openRawResource(R.raw.privoxy);
|
||||
streamToFile(is,installPath + PRIVOXY_ASSET_KEY);
|
||||
|
||||
is = context.getResources().openRawResource(R.raw.privoxy_config);
|
||||
streamToFile(is,installPath + PRIVOXYCONFIG_ASSET_KEY);
|
||||
|
||||
|
||||
|
||||
Log.d(TAG,"SUCCESS: installed tor, privoxy binaries from raw");
|
||||
|
||||
|
||||
}
|
||||
/*
|
||||
* Extract the Tor binary from the APK file using ZIP
|
||||
*/
|
||||
private void installFromZip ()
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
InputStream is;
|
||||
|
||||
ZipFile zip = new ZipFile(apkPath);
|
||||
is = context.getResources().openRawResource(R.raw.toraa);
|
||||
streamToFile(is,installFolder, TOR_BINARY_ASSET_KEY, false);
|
||||
|
||||
is = context.getResources().openRawResource(R.raw.torab);
|
||||
streamToFile(is,installFolder, TOR_BINARY_ASSET_KEY, true);
|
||||
|
||||
is = context.getResources().openRawResource(R.raw.torac);
|
||||
streamToFile(is,installFolder, TOR_BINARY_ASSET_KEY, true);
|
||||
|
||||
is = context.getResources().openRawResource(R.raw.torad);
|
||||
streamToFile(is,installFolder, TOR_BINARY_ASSET_KEY, true);
|
||||
|
||||
is = context.getResources().openRawResource(R.raw.torrc);
|
||||
streamToFile(is,installFolder, TORRC_ASSET_KEY, false);
|
||||
|
||||
ZipEntry zipen = zip.getEntry(ASSETS_BASE + TOR_BINARY_ASSET_KEY);
|
||||
streamToFile(zip.getInputStream(zipen),installPath + TOR_BINARY_ASSET_KEY);
|
||||
|
||||
zipen = zip.getEntry(ASSETS_BASE + TORRC_ASSET_KEY);
|
||||
streamToFile(zip.getInputStream(zipen),installPath + TORRC_ASSET_KEY);
|
||||
|
||||
zipen = zip.getEntry(ASSETS_BASE + PRIVOXY_ASSET_KEY);
|
||||
streamToFile(zip.getInputStream(zipen),installPath + PRIVOXY_ASSET_KEY);
|
||||
|
||||
zipen = zip.getEntry(ASSETS_BASE + PRIVOXYCONFIG_ASSET_KEY);
|
||||
streamToFile(zip.getInputStream(zipen),installPath + PRIVOXYCONFIG_ASSET_KEY);
|
||||
|
||||
zipen = zip.getEntry(ASSETS_BASE + PRIVOXYCONFIG_ASSET_KEY);
|
||||
streamToFile(zip.getInputStream(zipen),installPath + PRIVOXYCONFIG_ASSET_KEY);
|
||||
|
||||
|
||||
zip.close();
|
||||
|
||||
Log.d(TAG,"SUCCESS: unzipped tor, privoxy, iptables binaries from apk");
|
||||
is = context.getResources().openRawResource(R.raw.privoxy);
|
||||
streamToFile(is,installFolder, PRIVOXY_ASSET_KEY, false);
|
||||
|
||||
is = context.getResources().openRawResource(R.raw.privoxy_config);
|
||||
streamToFile(is,installFolder, PRIVOXYCONFIG_ASSET_KEY, false);
|
||||
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
Log.d(TAG,"FAIL: unable to unzip binaries from apk",ioe);
|
||||
|
||||
Log.e(TAG, "unable to install tor binaries from raw", ioe);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write the inputstream contents to the file
|
||||
*/
|
||||
private static void streamToFile(InputStream stm, String targetFilename)
|
||||
private static boolean streamToFile(InputStream stm, File folder, String targetFilename, boolean append) throws IOException
|
||||
|
||||
{
|
||||
|
||||
FileOutputStream stmOut = null;
|
||||
|
||||
byte[] buffer = new byte[FILE_WRITE_BUFFER_SIZE];
|
||||
|
||||
int bytecount;
|
||||
|
||||
|
||||
File outFile = new File(targetFilename);
|
||||
File outFile = new File(folder, targetFilename);
|
||||
|
||||
FileOutputStream stmOut = new FileOutputStream(outFile, append);
|
||||
|
||||
while ((bytecount = stm.read(buffer)) > 0)
|
||||
|
||||
{
|
||||
|
||||
stmOut.write(buffer, 0, bytecount);
|
||||
|
||||
}
|
||||
|
||||
stmOut.close();
|
||||
|
||||
|
||||
try {
|
||||
outFile.createNewFile();
|
||||
|
||||
stmOut = new FileOutputStream(outFile);
|
||||
}
|
||||
|
||||
catch (java.io.IOException e)
|
||||
|
||||
{
|
||||
|
||||
Log.d(TAG,"Error opening output file " + targetFilename,e);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
try
|
||||
|
||||
{
|
||||
|
||||
while ((bytecount = stm.read(buffer)) > 0)
|
||||
|
||||
{
|
||||
|
||||
stmOut.write(buffer, 0, bytecount);
|
||||
|
||||
}
|
||||
|
||||
stmOut.close();
|
||||
|
||||
}
|
||||
|
||||
catch (java.io.IOException e)
|
||||
|
||||
{
|
||||
|
||||
Log.d(TAG,"Error writing output file '" + targetFilename + "': " + e.toString());
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */
|
||||
/* Copyright (c) 2009-2011, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */
|
||||
/* See LICENSE for licensing information */
|
||||
package org.torproject.android.service;
|
||||
|
||||
|
@ -60,16 +60,13 @@ public class TorService extends Service implements TorServiceConstants, Runnable
|
|||
private ArrayList<String> resetBuffer = null;
|
||||
|
||||
|
||||
private String appHome;
|
||||
private String appBinHome;
|
||||
private String appDataHome;
|
||||
// private String appHome;
|
||||
private File appBinHome;
|
||||
private File appDataHome;
|
||||
|
||||
private String torBinaryPath;
|
||||
private String privoxyPath;
|
||||
|
||||
|
||||
private boolean hasRoot = false;
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
@ -416,43 +413,37 @@ public class TorService extends Service implements TorServiceConstants, Runnable
|
|||
|
||||
private boolean checkTorBinaries () throws Exception
|
||||
{
|
||||
//android.os.Debug.waitForDebugger();
|
||||
|
||||
//check and install iptables
|
||||
Api.assertBinaries(this, true);
|
||||
IptablesManager.assertBinaries(this, true);
|
||||
|
||||
File fileInstall = getDir("",0);
|
||||
String subBinPath = "bin/";
|
||||
|
||||
appHome = fileInstall.getAbsolutePath();
|
||||
appBinHome = appHome + subBinPath;
|
||||
appDataHome = getCacheDir().getAbsolutePath() + '/';
|
||||
logNotice( "appHome=" + appHome);
|
||||
appBinHome = getDir("bin",0);
|
||||
appDataHome = getCacheDir();
|
||||
|
||||
// logNotice( "appHome=" + appHome);
|
||||
|
||||
File fileTor = new File(appBinHome, TOR_BINARY_ASSET_KEY);
|
||||
File filePrivoxy = new File(appBinHome, PRIVOXY_ASSET_KEY);
|
||||
|
||||
|
||||
torBinaryPath = appBinHome + TOR_BINARY_ASSET_KEY;
|
||||
privoxyPath = appBinHome + PRIVOXY_ASSET_KEY;
|
||||
|
||||
logNotice( "checking Tor binaries");
|
||||
|
||||
boolean torBinaryExists = new File(torBinaryPath).exists();
|
||||
boolean privoxyBinaryExists = new File(privoxyPath).exists();
|
||||
|
||||
if (!(torBinaryExists && privoxyBinaryExists))
|
||||
if (!(fileTor.exists() && filePrivoxy.exists()))
|
||||
{
|
||||
killTorProcess ();
|
||||
|
||||
TorBinaryInstaller installer = new TorBinaryInstaller(this, appBinHome, appBinHome);
|
||||
installer.start(true);
|
||||
TorBinaryInstaller installer = new TorBinaryInstaller(this, appBinHome);
|
||||
boolean success = installer.installFromRaw();
|
||||
|
||||
torBinaryExists = new File(torBinaryPath).exists();
|
||||
privoxyBinaryExists = new File(privoxyPath).exists();
|
||||
|
||||
if (torBinaryExists && privoxyBinaryExists)
|
||||
if (success)
|
||||
{
|
||||
logNotice(getString(R.string.status_install_success));
|
||||
|
||||
showToolbarNotification(getString(R.string.status_install_success), NOTIFY_ID, R.drawable.tornotification);
|
||||
|
||||
|
||||
torBinaryPath = fileTor.getAbsolutePath();
|
||||
privoxyPath = filePrivoxy.getAbsolutePath();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -470,6 +461,9 @@ public class TorService extends Service implements TorServiceConstants, Runnable
|
|||
logNotice("Found Tor binary: " + torBinaryPath);
|
||||
logNotice("Found Privoxy binary: " + privoxyPath);
|
||||
|
||||
|
||||
torBinaryPath = fileTor.getAbsolutePath();
|
||||
privoxyPath = filePrivoxy.getAbsolutePath();
|
||||
}
|
||||
|
||||
StringBuilder log = new StringBuilder ();
|
||||
|
@ -545,6 +539,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
|
|||
boolean enableTransparentProxy = prefs.getBoolean("pref_transparent", false);
|
||||
boolean transProxyAll = prefs.getBoolean("pref_transparent_all", false);
|
||||
boolean transProxyPortFallback = prefs.getBoolean("pref_transparent_port_fallback", false);
|
||||
boolean transProxyTethering = prefs.getBoolean("pref_transparent_tethering", false);
|
||||
|
||||
TorService.logMessage ("Transparent Proxying: " + enableTransparentProxy);
|
||||
|
||||
|
@ -581,6 +576,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
|
|||
showAlert("Status", "Setting up app-based transparent proxying...");
|
||||
code = TorTransProxy.setTransparentProxyingByApp(this,AppManager.getApps(this));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TorService.logMessage ("TorTransProxy resp code: " + code);
|
||||
|
@ -588,11 +584,22 @@ public class TorService extends Service implements TorServiceConstants, Runnable
|
|||
if (code == 0)
|
||||
{
|
||||
showAlert("Status", "Transparent proxying ENABLED");
|
||||
|
||||
|
||||
|
||||
if (transProxyTethering)
|
||||
{
|
||||
showAlert("Status", "TransProxy enabled for Tethering!");
|
||||
|
||||
TorTransProxy.enableTetheringRules(this);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
showAlert("Status", "WARNING: error starting transparent proxying!");
|
||||
}
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
|
@ -618,9 +625,9 @@ public class TorService extends Service implements TorServiceConstants, Runnable
|
|||
|
||||
StringBuilder log = new StringBuilder();
|
||||
|
||||
String torrcPath = appBinHome + TORRC_ASSET_KEY;
|
||||
String torrcPath = new File(appBinHome, TORRC_ASSET_KEY).getAbsolutePath();
|
||||
|
||||
String[] torCmd = {torBinaryPath + " DataDirectory " + appDataHome + " -f " + torrcPath + " || exit\n"};
|
||||
String[] torCmd = {torBinaryPath + " DataDirectory " + appDataHome.getAbsolutePath() + " -f " + torrcPath + " || exit\n"};
|
||||
|
||||
boolean runAsRootFalse = false;
|
||||
boolean waitForProcess = false;
|
||||
|
@ -688,7 +695,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
|
|||
{
|
||||
log = new StringBuilder();
|
||||
|
||||
String privoxyConfigPath = appBinHome + PRIVOXYCONFIG_ASSET_KEY;
|
||||
String privoxyConfigPath = new File(appBinHome, PRIVOXYCONFIG_ASSET_KEY).getAbsolutePath();
|
||||
|
||||
String[] cmds =
|
||||
{ privoxyPath + " " + privoxyConfigPath + " &" };
|
||||
|
@ -753,7 +760,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
|
|||
|
||||
logNotice( "SUCCESS connected to control port");
|
||||
|
||||
String torAuthCookie = appDataHome + TOR_CONTROL_COOKIE;
|
||||
String torAuthCookie = new File(appDataHome, TOR_CONTROL_COOKIE).getAbsolutePath();
|
||||
|
||||
File fileCookie = new File(torAuthCookie);
|
||||
|
||||
|
@ -1137,18 +1144,12 @@ public class TorService extends Service implements TorServiceConstants, Runnable
|
|||
if (value == null || value.length() == 0)
|
||||
{
|
||||
resetBuffer.add(name);
|
||||
/*
|
||||
if (conn != null)
|
||||
{
|
||||
try {
|
||||
conn.resetConf(Arrays.asList(new String[]{name}));
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, "Unable to reset conf",e);
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
configBuffer.add(name + ' ' + value);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -1290,13 +1291,10 @@ public class TorService extends Service implements TorServiceConstants, Runnable
|
|||
boolean enableHiddenServices = prefs.getBoolean("pref_hs_enable", false);
|
||||
|
||||
boolean enableStrictNodes = prefs.getBoolean("pref_strict_nodes", false);
|
||||
String entranceNodes = prefs.getString("pref_entrance_nodes", "");
|
||||
String exitNodes = prefs.getString("pref_exit_nodes", "");
|
||||
String excludeNodes = prefs.getString("pref_exclude_nodes", "");
|
||||
String entranceNodes = prefs.getString("pref_entrance_nodes", null);
|
||||
String exitNodes = prefs.getString("pref_exit_nodes", null);
|
||||
String excludeNodes = prefs.getString("pref_exclude_nodes", null);
|
||||
|
||||
|
||||
//boolean enableTransparentProxy = prefs.getBoolean(TorConstants.PREF_TRANSPARENT, false);
|
||||
|
||||
if (currentStatus == STATUS_ON)
|
||||
{
|
||||
//reset iptables rules in active mode
|
||||
|
@ -1311,10 +1309,10 @@ public class TorService extends Service implements TorServiceConstants, Runnable
|
|||
}
|
||||
}
|
||||
|
||||
mBinder.updateConfiguration("EntranceNodes", entranceNodes, false);
|
||||
mBinder.updateConfiguration("EntryNodes", entranceNodes, false);
|
||||
mBinder.updateConfiguration("ExitNodes", exitNodes, false);
|
||||
mBinder.updateConfiguration("ExcludeNodes", excludeNodes, false);
|
||||
mBinder.updateConfiguration("StrictExitNodes", enableStrictNodes ? "1" : "0", false);
|
||||
mBinder.updateConfiguration("StrictNodes", enableStrictNodes ? "1" : "0", false);
|
||||
|
||||
if (useBridges)
|
||||
{
|
||||
|
@ -1407,7 +1405,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
|
|||
|
||||
if (enableHiddenServices)
|
||||
{
|
||||
mBinder.updateConfiguration("HiddenServiceDir",appDataHome, false);
|
||||
mBinder.updateConfiguration("HiddenServiceDir",appDataHome.getAbsolutePath(), false);
|
||||
|
||||
String hsPorts = prefs.getString("pref_hs_ports","");
|
||||
|
||||
|
|
|
@ -17,7 +17,9 @@ public class TorServiceUtils implements TorServiceConstants {
|
|||
* Check if we have root access
|
||||
* @return boolean true if we have root
|
||||
*/
|
||||
public static boolean checkRootAccess() {
|
||||
/*
|
||||
public static boolean checkRootAccess() {
|
||||
|
||||
|
||||
|
||||
StringBuilder log = new StringBuilder();
|
||||
|
@ -45,7 +47,40 @@ public class TorServiceUtils implements TorServiceConstants {
|
|||
TorService.logMessage("Could not acquire root permissions");
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
public static boolean checkRootAccess(){
|
||||
|
||||
StringBuilder log = new StringBuilder();
|
||||
|
||||
try {
|
||||
|
||||
// Check if Superuser.apk exists
|
||||
File file = new File("/system/app/Superuser.apk");
|
||||
|
||||
//Check for 'su' binary
|
||||
String[] cmd = {"which su"};
|
||||
int exitCode = TorServiceUtils.doShellCommand(cmd, log, false, true);
|
||||
|
||||
if (file.exists() && exitCode == 0) {
|
||||
TorService.logMessage("Can acquire root permissions");
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
//this means that there is no root to be had (normally) so we won't log anything
|
||||
TorService.logException("Error checking for root access",e);
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
TorService.logException("Error checking for root access",e);
|
||||
//this means that there is no root to be had (normally)
|
||||
}
|
||||
|
||||
TorService.logMessage("Could not acquire root permissions");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public static int findProcessId(String command)
|
||||
|
|
|
@ -313,14 +313,12 @@ public class TorTransProxy implements TorServiceConstants {
|
|||
return code;
|
||||
}
|
||||
|
||||
public static int enableWifiHotspotRules (Context context) throws Exception
|
||||
public static int enableTetheringRules (Context context) throws Exception
|
||||
{
|
||||
|
||||
boolean runRoot = true;
|
||||
boolean waitFor = true;
|
||||
|
||||
//redirectDNSResolvConf(); //not working yet
|
||||
|
||||
String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
|
||||
|
||||
StringBuilder script = new StringBuilder();
|
||||
|
@ -328,25 +326,24 @@ public class TorTransProxy implements TorServiceConstants {
|
|||
StringBuilder res = new StringBuilder();
|
||||
int code = -1;
|
||||
|
||||
script.append(ipTablesPath);
|
||||
script.append(" -I FORWARD");
|
||||
script.append(" -m state --state ESTABLISHED,RELATED -j ACCEPT");
|
||||
script.append(" || exit\n");
|
||||
|
||||
script.append(ipTablesPath);
|
||||
script.append(" -I FORWARD");
|
||||
script.append(" -j ACCEPT");
|
||||
script.append(" || exit\n");
|
||||
|
||||
/*
|
||||
script.append(ipTablesPath);
|
||||
script.append(" -P FORWARD DROP");
|
||||
script.append(" || exit\n");
|
||||
*/
|
||||
|
||||
script.append(ipTablesPath);
|
||||
script.append(" -t nat -I POSTROUTING -j MASQUERADE");
|
||||
script.append(" || exit\n");
|
||||
String[] hwinterfaces = {"usb0","wl0.1"};
|
||||
|
||||
for (int i = 0; i < hwinterfaces.length; i++)
|
||||
{
|
||||
script.append(ipTablesPath);
|
||||
script.append(" -t nat -A PREROUTING -i ");
|
||||
script.append(hwinterfaces[i]);
|
||||
script.append(" -p udp --dport 53 -j REDIRECT --to-ports ");
|
||||
script.append(TOR_DNS_PORT);
|
||||
script.append(" || exit\n");
|
||||
|
||||
script.append(ipTablesPath);
|
||||
script.append(" -t nat -A PREROUTING -i ");
|
||||
script.append(hwinterfaces[i]);
|
||||
script.append(" -p tcp -j REDIRECT --to-ports ");
|
||||
script.append(TOR_TRANSPROXY_PORT);
|
||||
script.append(" || exit\n");
|
||||
}
|
||||
|
||||
String[] cmdAdd = {script.toString()};
|
||||
|
||||
|
@ -374,8 +371,6 @@ public class TorTransProxy implements TorServiceConstants {
|
|||
|
||||
purgeIptables(context);
|
||||
|
||||
enableWifiHotspotRules(context);
|
||||
|
||||
int torUid = context.getApplicationInfo().uid;
|
||||
|
||||
// Set up port redirection
|
||||
|
|
Loading…
Reference in New Issue