Merge branch 'master' of git://git.torproject.org/n8fr8/orbot

Conflicts:
	AUTHORS
	AndroidManifest.xml
This commit is contained in:
Sathyanarayanan Gunasekaran 2011-07-25 21:57:58 -04:00
commit 34ce45398f
51 changed files with 1742 additions and 770 deletions

View File

@ -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">
@ -29,7 +29,11 @@
</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
View File

@ -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

View File

@ -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

90
WALKTHROUGH Normal file
View File

@ -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

BIN
res/drawable/proxymob.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
res/drawable/warning.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>
</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>

View File

@ -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>
</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>

View File

@ -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>

Binary file not shown.

BIN
res/raw/toraa Normal file

Binary file not shown.

BIN
res/raw/torab Normal file

Binary file not shown.

BIN
res/raw/torac Normal file

Binary file not shown.

BIN
res/raw/torad Normal file

Binary file not shown.

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

9
res/values/theme.xml Normal file
View File

@ -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>

View File

@ -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"

View File

@ -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();
}
}

View File

@ -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);
}
});
}
}

View File

@ -1,9 +1,11 @@
/* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */
/* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - https://guardianproject.info */
/* See LICENSE for licensing information */
package org.torproject.android;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@ -24,6 +26,7 @@ import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@ -46,40 +49,53 @@ import android.widget.TextView;
public class Orbot extends Activity implements OnLongClickListener, TorConstants
{
/* Useful UI bits */
private TextView lblStatus = null; //the main text display widget
private ImageView imgStatus = null; //the main touchable image for activating Orbot
private ProgressDialog progressDialog;
private MenuItem mItemOnOff = null;
/* Useful UI bits */
// so this is probably pretty obvious, here, but also an area
// which we might see quite a bit of change+complexity was the main screen
// UI gets new features
private TextView lblStatus = null; //the main text display widget
private ImageView imgStatus = null; //the main touchable image for activating Orbot
private ProgressDialog progressDialog; //the spinning progress dialog that shows up now and then
private MenuItem mItemOnOff = null; //the menu item which we toggle based on Orbot state
/* Some tracking bits */
private int torStatus = STATUS_READY; //latest status reported from the tor service
/* Some tracking bits */
private int torStatus = STATUS_READY; //latest status reported from the tor service
// this is a value we get passed back from the TorService
/* Tor Service interaction */
/* The primary interface we will be calling on the service. */
ITorService mService = null;
private boolean autoStartOnBind = false;
/* Tor Service interaction */
/* The primary interface we will be calling on the service. */
ITorService mService = null; //interface to remote TorService
private boolean autoStartOnBind = false; //controls whether service starts when class binds to it
SharedPreferences prefs;
SharedPreferences prefs; //what the user really wants!
/** Called when the activity is first created. */
/**
* When the Orbot activity is created, we call startService
* to ensure the Tor remote service is running. However, it may
* already be running, and this should not create more than one instnace
*/
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//if Tor binary is not running, then start the service up
startService(new Intent(INTENT_TOR_SERVICE));
//might want to look at whether we need to call this every time
//or whether binding to the service is enough
startService(new Intent(INTENT_TOR_SERVICE));
//something to play with on the UI branch
setTheme(android.R.style.Theme_Black_NoTitleBar);
setTheme(android.R.style.Theme_Black_NoTitleBar);
prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs = PreferenceManager.getDefaultSharedPreferences(this);
//same here - layout_main has been cleaned up since 1.0.5.2 a bit (removed table as you recmnd)
//but ther eis more to be done
setContentView(R.layout.layout_main);
setContentView(R.layout.layout_main);
lblStatus = (TextView)findViewById(R.id.lblStatus);
lblStatus.setOnLongClickListener(this);
imgStatus = (ImageView)findViewById(R.id.imgStatus);
imgStatus.setOnLongClickListener(this);
//obvious? -yep got everything so far
lblStatus = (TextView)findViewById(R.id.lblStatus);
lblStatus.setOnLongClickListener(this);
imgStatus = (ImageView)findViewById(R.id.imgStatus);
imgStatus.setOnLongClickListener(this);
@ -119,130 +135,150 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
private void showAbout ()
{
{
LayoutInflater li = LayoutInflater.from(this);
View view = li.inflate(R.layout.layout_about, null);
LayoutInflater li = LayoutInflater.from(this);
View view = li.inflate(R.layout.layout_about, null);
TextView versionName = (TextView)view.findViewById(R.id.versionName);
versionName.setText(R.string.app_version);
String version = "";
new AlertDialog.Builder(this)
.setTitle(getString(R.string.button_about))
.setView(view)
.show();
}
try {
version = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
} catch (NameNotFoundException e) {
version = "Version Not Found";
}
TextView versionName = (TextView)view.findViewById(R.id.versionName);
versionName.setText(version);
new AlertDialog.Builder(this)
.setTitle(getString(R.string.button_about))
.setView(view)
.show();
}
/* When a menu item is selected launch the appropriate view or activity
* (non-Javadoc)
* @see android.app.Activity#onMenuItemSelected(int, android.view.MenuItem)
*/
public boolean onMenuItemSelected(int featureId, MenuItem item) {
* @see android.app.Activity#onMenuItemSelected(int, android.view.MenuItem)
*/
public boolean onMenuItemSelected(int featureId, MenuItem item) {
super.onMenuItemSelected(featureId, item);
super.onMenuItemSelected(featureId, item);
if (item.getItemId() == 1)
{
if (item.getItemId() == 1)
{
try
{
try
{
if (mService == null)
{
if (mService == null)
{
}
else if (mService.getStatus() == STATUS_READY)
{
if (mItemOnOff != null)
mItemOnOff.setTitle(R.string.menu_stop);
startTor();
}
else if (mService.getStatus() == STATUS_READY)
{
if (mItemOnOff != null)
mItemOnOff.setTitle(R.string.menu_stop);
startTor();
}
else
{
if (mItemOnOff != null)
mItemOnOff.setTitle(R.string.menu_start);
stopTor();
}
else
{
if (mItemOnOff != null)
mItemOnOff.setTitle(R.string.menu_start);
stopTor();
}
}
}
catch (RemoteException re)
{
Log.w(TAG, "Unable to start/top Tor from menu UI", re);
}
}
else if (item.getItemId() == 4)
{
showSettings();
}
else if (item.getItemId() == 3)
{
showHelp();
}
else if (item.getItemId() == 7)
{
doTorCheck();
}
else if (item.getItemId() == 8)
{
//exit app
doExit();
}
catch (RemoteException re)
{
Log.w(TAG, "Unable to start/top Tor from menu UI", re);
}
}
else if (item.getItemId() == 4)
{
showSettings();
}
else if (item.getItemId() == 3)
{
showHelp();
}
else if (item.getItemId() == 7)
{
doTorCheck();
}
else if (item.getItemId() == 8)
{
//exit app
doExit();
}
else if (item.getItemId() == 6)
{
showAbout();
}
else if (item.getItemId() == 6)
{
showAbout();
}
}
return true;
}
}
private void doExit ()
{
try {
/**
* This is our attempt to REALLY exit Orbot, and stop the background service
* However, Android doesn't like people "quitting" apps, and/or our code may not
* be quite right b/c no matter what we do, it seems like the TorService still exists
**/
private void doExit ()
{
try {
stopTor();
//one of the confusing things about all of this code is the multiple
//places where things like "stopTor" are called, both in the Activity and the Service
//not something to tackle in your first iteration, but i thin we can talk about fixing
//terminology but also making sure there are clear distinctions in control
stopTor();
stopService(new Intent(ITorService.class.getName()));
//perhaps this should be referenced as INTENT_TOR_SERVICE as in startService
stopService(new Intent(ITorService.class.getName()));
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.cancelAll();
//clears all notifications from the status bar
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.cancelAll();
} catch (RemoteException e) {
Log.w(TAG, e);
}
} catch (RemoteException e) {
Log.w(TAG, e);
}
finish();
finish();
}
}
/* Return to the main view when the back key is pressed
* (non-Javadoc)
* @see android.app.Activity#onKeyDown(int, android.view.KeyEvent)
*/
/*
public boolean onKeyDown(int keyCode, KeyEvent event){
/* Return to the main view when the back key is pressed
* (non-Javadoc)
* @see android.app.Activity#onKeyDown(int, android.view.KeyEvent)
*/
/*
public boolean onKeyDown(int keyCode, KeyEvent event){
if(keyCode==KeyEvent.KEYCODE_BACK){
//yeah this should probably go away now :) - or not
if(keyCode==KeyEvent.KEYCODE_BACK){
if(currentView != R.layout.layout_main){
if(currentView != R.layout.layout_main){
showMain ();
return true;
}
else{
return super.onKeyDown(keyCode, event);
}
}
showMain ();
return true;
}
else{
return super.onKeyDown(keyCode, event);
}
}
return super.onKeyDown(keyCode, event);
return super.onKeyDown(keyCode, event);
}*/
}*/
/* (non-Javadoc)
* @see android.app.Activity#onPause()
@ -408,7 +444,7 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
pEdit.commit();
new WizardHelper(this).showWizard();
startActivityForResult(new Intent(getBaseContext(), LotsaText.class), 1);
}
@ -454,227 +490,258 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
private void showHelp ()
{
new WizardHelper(this).showWizard();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
Editor pEdit = prefs.edit();
pEdit.putBoolean("wizardscreen1",true);
pEdit.commit();
startActivityForResult(new Intent(getBaseContext(), LotsaText.class), 1);
}
/*
* Load the basic settings application to display torrc
*/
private void showSettings ()
{
private void showSettings ()
{
startActivityForResult(new Intent(this, SettingsPreferences.class), 1);
}
startActivityForResult(new Intent(this, SettingsPreferences.class), 1);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1 && resultCode == 1010 && mService != null)
{
new ProcessSettingsAsyncTask().execute(mService);
}
}
//if we get a response from an activity we launched (like from line 527 where we launch the Settings/Prefs screen)
//and the resultCode matches our arbitrary 1010 value, AND Tor is running
//then update the preferences in an async background task
if (requestCode == 1 && resultCode == 1010 && mService != null)
{
new ProcessSettingsAsyncTask().execute(mService);
}
}
AlertDialog aDialog = null;
AlertDialog aDialog = null;
private void showAlert(String title, String msg, boolean button)
{
try
{
if (aDialog != null && aDialog.isShowing())
aDialog.dismiss();
}
catch (Exception e){} //swallow any errors
//general alert dialog for mostly Tor warning messages
//sometimes this can go haywire or crazy with too many error
//messages from Tor, and the user cannot stop or exit Orbot
//so need to ensure repeated error messages are not spamming this method
private void showAlert(String title, String msg, boolean button)
{
try
{
if (aDialog != null && aDialog.isShowing())
aDialog.dismiss();
}
catch (Exception e){} //swallow any errors
if (button)
{
aDialog = new AlertDialog.Builder(this)
.setIcon(R.drawable.icon)
.setTitle(title)
.setMessage(msg)
.setPositiveButton(android.R.string.ok, null)
.show();
}
else
{
aDialog = new AlertDialog.Builder(this)
.setIcon(R.drawable.icon)
.setTitle(title)
.setMessage(msg)
.show();
}
if (button)
{
aDialog = new AlertDialog.Builder(this)
.setIcon(R.drawable.icon)
.setTitle(title)
.setMessage(msg)
.setPositiveButton(android.R.string.ok, null)
.show();
}
else
{
aDialog = new AlertDialog.Builder(this)
.setIcon(R.drawable.icon)
.setTitle(title)
.setMessage(msg)
.show();
}
aDialog.setCanceledOnTouchOutside(true);
}
aDialog.setCanceledOnTouchOutside(true);
}
/*
* Set the state of the running/not running graphic and label
* this all needs to be looked at w/ the shift to progressDialog
*/
public void updateStatus (String torServiceMsg)
{
try
{
try
{
//if the serivce is bound, query it for the curren status value (int)
if (mService != null)
torStatus = mService.getStatus();
if (mService != null)
torStatus = mService.getStatus();
//now update the layout_main UI based on the status
if (imgStatus != null)
{
if (imgStatus != null)
{
if (torStatus == STATUS_ON)
{
imgStatus.setImageResource(R.drawable.toron);
if (torStatus == STATUS_ON)
{
imgStatus.setImageResource(R.drawable.toron);
hideProgressDialog();
hideProgressDialog();
String lblMsg = getString(R.string.status_activated);
//+ "\n" + torServiceMsg;
String lblMsg = getString(R.string.status_activated);
//+ "\n" + torServiceMsg;
lblStatus.setText(lblMsg);
lblStatus.setText(lblMsg);
if (torServiceMsg.length() > 0)
showAlert("Update", torServiceMsg, false);
if (torServiceMsg.length() > 0)
showAlert("Update", torServiceMsg, false);
boolean showFirstTime = prefs.getBoolean("connect_first_time",true);
boolean showFirstTime = prefs.getBoolean("connect_first_time",true);
if (showFirstTime)
{
if (showFirstTime)
{
Editor pEdit = prefs.edit();
Editor pEdit = prefs.edit();
pEdit.putBoolean("connect_first_time",false);
pEdit.putBoolean("connect_first_time",false);
pEdit.commit();
pEdit.commit();
showAlert(getString(R.string.status_activated),getString(R.string.connect_first_time),true);
showAlert(getString(R.string.status_activated),getString(R.string.connect_first_time),true);
}
}
if (mItemOnOff != null)
mItemOnOff.setTitle(R.string.menu_stop);
if (mItemOnOff != null)
mItemOnOff.setTitle(R.string.menu_stop);
}
else if (torStatus == STATUS_CONNECTING)
{
}
else if (torStatus == STATUS_CONNECTING)
{
imgStatus.setImageResource(R.drawable.torstarting);
imgStatus.setImageResource(R.drawable.torstarting);
if (progressDialog != null)
progressDialog.setMessage(torServiceMsg);
if (progressDialog != null)
progressDialog.setMessage(torServiceMsg);
if (mItemOnOff != null)
mItemOnOff.setTitle(R.string.menu_stop);
if (mItemOnOff != null)
mItemOnOff.setTitle(R.string.menu_stop);
}
else if (torStatus == STATUS_OFF)
{
imgStatus.setImageResource(R.drawable.toroff);
}
else if (torStatus == STATUS_OFF)
{
imgStatus.setImageResource(R.drawable.toroff);
hideProgressDialog();
hideProgressDialog();
lblStatus.setText(getString(R.string.status_shutting_down));
lblStatus.setText(getString(R.string.status_shutting_down));
if (mItemOnOff != null)
mItemOnOff.setTitle(R.string.menu_start);
}
else
{
if (mItemOnOff != null)
mItemOnOff.setTitle(R.string.menu_start);
}
else
{
hideProgressDialog();
hideProgressDialog();
imgStatus.setImageResource(R.drawable.toroff);
lblStatus.setText(getString(R.string.status_disabled) + "\n" + getString(R.string.press_to_start));
imgStatus.setImageResource(R.drawable.toroff);
lblStatus.setText(getString(R.string.status_disabled) + "\n" + getString(R.string.press_to_start));
if (mItemOnOff != null)
mItemOnOff.setTitle(R.string.menu_start);
if (mItemOnOff != null)
mItemOnOff.setTitle(R.string.menu_start);
}
}
}
}
}
catch (RemoteException e)
{
Log.e(TAG,"remote exception updating status",e);
}
}
catch (RemoteException e)
{
Log.e(TAG,"remote exception updating status",e);
}
}
// guess what? this start's Tor! actually no it just requests via the local ITorService to the remote TorService instance
// to start Tor
private void startTor () throws RemoteException
{
// here we bind AGAIN - at some point i think we had to bind multiple times just in case
// but i would love to clarify, clean this up
bindService();
bindService();
// this is a bit of a strange/old/borrowed code/design i used to change the service state
// not sure it really makes sense when what we want to say is just "startTor"
mService.setProfile(TorServiceConstants.PROFILE_ON); //this means turn on
mService.setProfile(TorServiceConstants.PROFILE_ON); //this means turn on
//here we update the UI which is a bit sloppy and mixed up code wise
//might be best to just call updateStatus() instead of directly manipulating UI in this method - yep makes sense
imgStatus.setImageResource(R.drawable.torstarting);
lblStatus.setText(getString(R.string.status_starting_up));
imgStatus.setImageResource(R.drawable.torstarting);
lblStatus.setText(getString(R.string.status_starting_up));
Message msg = mHandler.obtainMessage(TorServiceConstants.ENABLE_TOR_MSG);
mHandler.sendMessage(msg);
//we send a message here to the progressDialog i believe, but we can clarify that shortly
Message msg = mHandler.obtainMessage(TorServiceConstants.ENABLE_TOR_MSG);
mHandler.sendMessage(msg);
}
//now we stop Tor! amazing!
private void stopTor () throws RemoteException
{
if (mService != null)
{
mService.setProfile(TorServiceConstants.PROFILE_OFF);
Message msg = mHandler.obtainMessage(TorServiceConstants.DISABLE_TOR_MSG);
mHandler.sendMessage(msg);
}
//if the service is bound, then turn it off, using the same "PROFILE_" technique
if (mService != null)
{
mService.setProfile(TorServiceConstants.PROFILE_OFF);
//again this is related to the progress dialog or some other threaded UI object
Message msg = mHandler.obtainMessage(TorServiceConstants.DISABLE_TOR_MSG);
mHandler.sendMessage(msg);
}
}
/*
/*
* (non-Javadoc)
* @see android.view.View.OnClickListener#onClick(android.view.View)
*/
public boolean onLongClick(View view) {
public boolean onLongClick(View view) {
try
{
try
{
if (mService == null)
{
if (mService == null)
{
}
else if (mService.getStatus() == STATUS_READY)
{
}
else if (mService.getStatus() == STATUS_READY)
{
createProgressDialog(getString(R.string.status_starting_up));
createProgressDialog(getString(R.string.status_starting_up));
startTor();
}
else
{
startTor();
}
else
{
stopTor();
stopTor();
}
}
}
catch (Exception e)
{
Log.d(TAG,"error onclick",e);
}
}
catch (Exception e)
{
Log.d(TAG,"error onclick",e);
}
return true;
}
return true;
}
/**
* This implementation is used to receive callbacks from the remote
* service.
*
* If we have this setup probably, we shouldn't have to poll or query status
* to the service, as it should send it as it changes or when we bind/unbind to it
* from this activity
*/
private ITorServiceCallback mCallback = new ITorServiceCallback.Stub() {
/**
@ -684,32 +751,37 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
* NOT be running in our main thread like most other things -- so,
* to update the UI, we need to use a Handler to hop over there.
*/
//receive a new string vaule end-user displayable message from the ITorService
public void statusChanged(String value) {
Message msg = mHandler.obtainMessage(TorServiceConstants.STATUS_MSG);
msg.getData().putString(HANDLER_TOR_MSG, value);
mHandler.sendMessage(msg);
//pass it off to the progressDialog
Message msg = mHandler.obtainMessage(TorServiceConstants.STATUS_MSG);
msg.getData().putString(HANDLER_TOR_MSG, value);
mHandler.sendMessage(msg);
}
@Override
public void logMessage(String value) throws RemoteException {
@Override //this was when we displayed the log in the main Activity; can prob take this out now
public void logMessage(String value) throws RemoteException {
Message msg = mHandler.obtainMessage(TorServiceConstants.LOG_MSG);
msg.getData().putString(HANDLER_TOR_MSG, value);
mHandler.sendMessage(msg);
Message msg = mHandler.obtainMessage(TorServiceConstants.LOG_MSG);
msg.getData().putString(HANDLER_TOR_MSG, value);
mHandler.sendMessage(msg);
}
}
};
// this is what takes messages or values from the callback threads or other non-mainUI threads
//and passes them back into the main UI thread for display to the user
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case TorServiceConstants.STATUS_MSG:
String torServiceMsg = (String)msg.getData().getString(HANDLER_TOR_MSG);
String torServiceMsg = (String)msg.getData().getString(HANDLER_TOR_MSG);
updateStatus(torServiceMsg);
updateStatus(torServiceMsg);
break;
case TorServiceConstants.LOG_MSG:
@ -719,14 +791,14 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
case TorServiceConstants.ENABLE_TOR_MSG:
updateStatus((String)msg.getData().getString(HANDLER_TOR_MSG));
updateStatus((String)msg.getData().getString(HANDLER_TOR_MSG));
break;
break;
case TorServiceConstants.DISABLE_TOR_MSG:
updateStatus((String)msg.getData().getString(HANDLER_TOR_MSG));
updateStatus((String)msg.getData().getString(HANDLER_TOR_MSG));
break;
break;
default:
super.handleMessage(msg);
@ -741,6 +813,10 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
/**
* Class for interacting with the main interface of the service.
*/
// this is the connection that gets called back when a successfull bind occurs
// we should use this to activity monitor unbind so that we don't have to call
// bindService() a million times
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
@ -756,13 +832,14 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
try {
mService.registerCallback(mCallback);
//again with the update status?!? :P
updateStatus("");
if (autoStartOnBind)
{
autoStartOnBind = false;
autoStartOnBind = false;
startTor();
startTor();
}
@ -771,7 +848,7 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
// do anything with it; we can count on soon being
// disconnected (and then reconnected if it can be restarted)
// so there is no need to do anything here.
Log.d(TAG,"error registering callback to service",e);
Log.d(TAG,"error registering callback to service",e);
}
@ -789,20 +866,26 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
}
};
//should move this up with all the other class variables
boolean mIsBound = false;
//this is where we bind!
private void bindService ()
{
bindService(new Intent(ITorService.class.getName()),
//since its auto create, we prob don't ever need to call startService
//also we should again be consistent with using either iTorService.class.getName()
//or the variable constant
bindService(new Intent(ITorService.class.getName()),
mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
mIsBound = true;
}
//unbind removes the callback, and unbinds the service
private void unbindService ()
{
if (mIsBound) {
if (mIsBound) {
// If we have received the service, and hence registered with
// it, then now is the time to unregister.
if (mService != null) {
@ -813,7 +896,10 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
// There is nothing special we need to do if the service
// has crashed.
}
}
}
//maybe needs this?
mService = null;
// Detach our existing connection.
unbindService(mConnection);
@ -824,22 +910,22 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
private void createProgressDialog (String msg)
{
if (progressDialog != null && progressDialog.isShowing())
return;
if (progressDialog != null && progressDialog.isShowing())
return;
progressDialog = ProgressDialog.show(Orbot.this, "", msg);
progressDialog.setCancelable(true);
progressDialog = ProgressDialog.show(Orbot.this, "", msg);
progressDialog.setCancelable(true);
}
private void hideProgressDialog ()
{
if (progressDialog != null && progressDialog.isShowing())
{
progressDialog.dismiss();
if (progressDialog != null && progressDialog.isShowing())
{
progressDialog.dismiss();
}
}
}

View File

@ -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);
}
});
}
}

View File

@ -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

View File

@ -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();
}
}

View File

@ -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) {
}
}

View File

@ -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 {
}
});
*/
}

View File

@ -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);
}
}

View File

@ -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);
}
/**

View File

@ -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);
ZipEntry zipen = zip.getEntry(ASSETS_BASE + TOR_BINARY_ASSET_KEY);
streamToFile(zip.getInputStream(zipen),installPath + TOR_BINARY_ASSET_KEY);
is = context.getResources().openRawResource(R.raw.torab);
streamToFile(is,installFolder, TOR_BINARY_ASSET_KEY, true);
zipen = zip.getEntry(ASSETS_BASE + TORRC_ASSET_KEY);
streamToFile(zip.getInputStream(zipen),installPath + TORRC_ASSET_KEY);
is = context.getResources().openRawResource(R.raw.torac);
streamToFile(is,installFolder, TOR_BINARY_ASSET_KEY, true);
zipen = zip.getEntry(ASSETS_BASE + PRIVOXY_ASSET_KEY);
streamToFile(zip.getInputStream(zipen),installPath + PRIVOXY_ASSET_KEY);
is = context.getResources().openRawResource(R.raw.torad);
streamToFile(is,installFolder, TOR_BINARY_ASSET_KEY, true);
zipen = zip.getEntry(ASSETS_BASE + PRIVOXYCONFIG_ASSET_KEY);
streamToFile(zip.getInputStream(zipen),installPath + PRIVOXYCONFIG_ASSET_KEY);
is = context.getResources().openRawResource(R.raw.torrc);
streamToFile(is,installFolder, TORRC_ASSET_KEY, false);
zipen = zip.getEntry(ASSETS_BASE + PRIVOXYCONFIG_ASSET_KEY);
streamToFile(zip.getInputStream(zipen),installPath + PRIVOXYCONFIG_ASSET_KEY);
is = context.getResources().openRawResource(R.raw.privoxy);
streamToFile(is,installFolder, PRIVOXY_ASSET_KEY, false);
zip.close();
Log.d(TAG,"SUCCESS: unzipped tor, privoxy, iptables binaries from apk");
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(folder, targetFilename);
File outFile = new File(targetFilename);
FileOutputStream stmOut = new FileOutputStream(outFile, append);
try {
outFile.createNewFile();
stmOut = new FileOutputStream(outFile);
}
catch (java.io.IOException e)
while ((bytecount = stm.read(buffer)) > 0)
{
Log.d(TAG,"Error opening output file " + targetFilename,e);
return;
}
try
{
while ((bytecount = stm.read(buffer)) > 0)
{
stmOut.write(buffer, 0, bytecount);
}
stmOut.close();
stmOut.write(buffer, 0, bytecount);
}
catch (java.io.IOException e)
stmOut.close();
{
Log.d(TAG,"Error writing output file '" + targetFilename + "': " + e.toString());
return;
}
return true;
}

View File

@ -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,12 +584,23 @@ 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,12 +1291,9 @@ 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", "");
//boolean enableTransparentProxy = prefs.getBoolean(TorConstants.PREF_TRANSPARENT, false);
String entranceNodes = prefs.getString("pref_entrance_nodes", null);
String exitNodes = prefs.getString("pref_exit_nodes", null);
String excludeNodes = prefs.getString("pref_exclude_nodes", null);
if (currentStatus == STATUS_ON)
{
@ -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","");

View File

@ -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)

View File

@ -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");
String[] hwinterfaces = {"usb0","wl0.1"};
script.append(ipTablesPath);
script.append(" -I FORWARD");
script.append(" -j ACCEPT");
script.append(" || exit\n");
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(" -P FORWARD DROP");
script.append(" || exit\n");
*/
script.append(ipTablesPath);
script.append(" -t nat -I POSTROUTING -j MASQUERADE");
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