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"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <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.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <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" <activity android:name=".Orbot"
android:theme="@android:style/Theme.NoTitleBar"> android:theme="@android:style/Theme.NoTitleBar">
@ -29,6 +29,10 @@
</intent-filter> </intent-filter>
</activity> </activity>
<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=".SettingsPreferences" android:label="@string/app_name"/>
<activity android:name=".AppManager" android:label="@string/app_name"/> <activity android:name=".AppManager" android:label="@string/app_name"/>
<activity android:name=".WizardActivity" 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 export APP_SDK=~/Documents/projects/android/android-sdk-linux_x86-1.5_r3/tools
cd ../Orbot/ cd ../Orbot/
cp $DROID_ROOT/external/privoxy/privoxy-3.0.12-stable/privoxy assets/privoxy 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 . $APP_SDK/android update project --name Orbot --target 3 --path .
ant release 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/ 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 1.0.5
- added exit node and "StrictExitNode" preference - added exit node and "StrictExitNode" preference
- fixed tor binary installation issue related to max resource size and compression - 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:layout_height="fill_parent"
android:stretchColumns="1"> android:stretchColumns="1">
<TableRow> <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> <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> <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/itemcheck" ></CheckBox>
</TableRow> </TableRow>
</TableLayout> </TableLayout>

View File

@ -33,11 +33,17 @@
android:layout_toLeftOf="@+id/radioModeImage" android:layout_toLeftOf="@+id/radioModeImage"
android:textColor="#cccccc" /> android:textColor="#cccccc" />
</RelativeLayout> </RelativeLayout>
<RelativeLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center_vertical"
>
<ImageView <ImageView
android:id="@+id/imgStatus" android:id="@+id/imgStatus"
android:layout_margin="5dip" android:layout_margin="15dip"
android:layout_width="320dip" android:layout_width="fill_parent"
android:layout_height="320dip" android:layout_height="320dip"
android:src="@drawable/toroff" android:src="@drawable/toroff"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
@ -45,14 +51,14 @@
<TextView android:id="@+id/lblStatus" <TextView android:id="@+id/lblStatus"
android:text="@string/press_to_start" android:text="@string/press_to_start"
android:layout_gravity="center_horizontal" android:gravity="center_horizontal"
android:textStyle="bold" android:textStyle="bold"
android:layout_width="wrap_content" android:layout_width="fill_parent"
android:layout_height="30dip" android:layout_height="60dip"
android:textColor="#ffffff" android:textColor="#ffffff"
android:layout_below="@id/imgStatus"
/> />
</RelativeLayout>
</LinearLayout> </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"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:orientation="vertical"
android:layout_width="fill_parent" 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" <ScrollView android:id="@+id/helpscrollview"
android:orientation="vertical" android:orientation="vertical"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent"> android:layout_height="fill_parent"
<LinearLayout android:layout_span="3">
<LinearLayout
android:background="#575757"
android:orientation="vertical" android:orientation="vertical"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:padding="3px"> 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> <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>
<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:layout_height="wrap_content"
<TextView android:text=" or " android:textColor="#ffffff" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView> android:text="@string/wizard_transproxy_hint"
android:layout_width="wrap_content"
<Button android:text="@string/wizard_configure_select_apps" android:id="@+id/WizardRootButton01" android:layout_width="wrap_content" android:layout_height="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> </LinearLayout>
</ScrollView> </ScrollView>
</TableRow>
<TableRow android:background="#000000" android:layout_marginTop="10dip" android:paddingTop="10dip" android:id="@+id/TableRow01" android:textColor="#00ff00" android:layout_width="fill_parent" android:layout_height="30px">
<Button android:text="Back" android:id="@+id/btnWizard1" android:layout_weight="1" android:layout_width="fill_parent" android:layout_height="wrap_content"></Button>
<Button android:text="Next" android:id="@+id/btnWizard2" android:layout_weight="1" android:layout_width="fill_parent" android:layout_height="wrap_content"></Button>
</TableRow>
</TableLayout>
</LinearLayout> </LinearLayout>

View File

@ -1,29 +1,63 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:orientation="vertical"
android:layout_width="fill_parent" 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" <ScrollView android:id="@+id/helpscrollview"
android:orientation="vertical" android:orientation="vertical"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent"> android:layout_height="fill_parent"
<LinearLayout android:layout_span="3">
<LinearLayout
android:background="#575757"
android:orientation="vertical" android:orientation="vertical"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="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_proxymob" android:layout_marginTop="10px" android:drawableLeft="@drawable/proxymob" android:id="@+id/WizardRootButtonInstallProxyMob" 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"/>
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>
</TableRow>
<TableRow android:background="#000000" android:layout_marginTop="10dip" android:paddingTop="10dip" android:id="@+id/TableRow01" android:textColor="#00ff00" android:layout_width="fill_parent" android:layout_height="30px">
<Button android:text="Back" android:id="@+id/btnWizard1" android:layout_weight="1" android:layout_width="fill_parent" android:layout_height="wrap_content"></Button>
<Button android:text="Next" android:id="@+id/btnWizard2" android:layout_weight="1" android:layout_width="fill_parent" android:layout_height="wrap_content"></Button>
</TableRow>
</TableLayout>
</LinearLayout> </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 RelayBandwidthBurst 20 KBytes
UseBridges 0 UseBridges 0
AutomapHostsOnResolve 1 AutomapHostsOnResolve 1
TransListenAddress 0.0.0.0
TransPort 9040 TransPort 9040
DNSListenAddress 0.0.0.0
DNSPort 5400 DNSPort 5400

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">اوربوت (Orbot)</string> <string name="app_name">اوربوت (Orbot)</string>
<string name="app_version">1.0.5</string>
<string name="internal_web_url">http://orbot/</string> <string name="internal_web_url">http://orbot/</string>
<string name="default_web_url">http://check.torproject.org</string> <string name="default_web_url">http://check.torproject.org</string>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">Orbot</string> <string name="app_name">Orbot</string>
<string name="app_version">1.0.5</string>
<string name="internal_web_url">http://orbot/</string> <string name="internal_web_url">http://orbot/</string>
<string name="default_web_url">http://check.torproject.org</string> <string name="default_web_url">http://check.torproject.org</string>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">Orbot</string> <string name="app_name">Orbot</string>
<string name="app_version">1.0.5</string>
<string name="internal_web_url">http://orbot/</string> <string name="internal_web_url">http://orbot/</string>
<string name="default_web_url">http://check.torproject.org</string> <string name="default_web_url">http://check.torproject.org</string>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">Orbot</string> <string name="app_name">Orbot</string>
<string name="app_version">1.0.5</string>
<string name="internal_web_url">http://orbot/</string> <string name="internal_web_url">http://orbot/</string>
<string name="default_web_url">http://check.torproject.org</string> <string name="default_web_url">http://check.torproject.org</string>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">اوربات</string> <string name="app_name">اوربات</string>
<string name="app_version">1.0.5</string>
<string name="internal_web_url">http://orbot/</string> <string name="internal_web_url">http://orbot/</string>
<string name="default_web_url">http://check.torproject.org</string> <string name="default_web_url">http://check.torproject.org</string>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">Орбот</string> <string name="app_name">Орбот</string>
<string name="app_version">1.0.5</string>
<string name="internal_web_url">http://orbot/</string> <string name="internal_web_url">http://orbot/</string>
<string name="default_web_url">http://check.torproject.org</string> <string name="default_web_url">http://check.torproject.org</string>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">Orbot</string> <string name="app_name">Orbot</string>
<string name="app_version">1.0.5</string>
<string name="internal_web_url">http://orbot/</string> <string name="internal_web_url">http://orbot/</string>
<string name="default_web_url">http://check.torproject.org</string> <string name="default_web_url">http://check.torproject.org</string>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">Orbot</string> <string name="app_name">Orbot</string>
<string name="app_version">1.0.5</string>
<string name="internal_web_url">http://orbot/</string> <string name="internal_web_url">http://orbot/</string>
<string name="default_web_url">http://check.torproject.org</string> <string name="default_web_url">http://check.torproject.org</string>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">Orbot</string> <string name="app_name">Orbot</string>
<string name="app_version">1.0.5</string>
<string name="internal_web_url">http://orbot/</string> <string name="internal_web_url">http://orbot/</string>
<string name="default_web_url">http://check.torproject.org</string> <string name="default_web_url">http://check.torproject.org</string>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">Orbot</string> <string name="app_name">Orbot</string>
<string name="app_version">1.0.5</string>
<string name="internal_web_url">http://orbot/</string> <string name="internal_web_url">http://orbot/</string>
<string name="default_web_url">http://check.torproject.org</string> <string name="default_web_url">http://check.torproject.org</string>
<string name="secure_default_web_url">https://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"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">Orbot</string> <string name="app_name">Orbot</string>
<string name="app_version">1.0.5</string>
<string name="internal_web_url">http://orbot/</string> <string name="internal_web_url">http://orbot/</string>
<string name="default_web_url">http://check.torproject.org</string> <string name="default_web_url">http://check.torproject.org</string>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">Orbot</string> <string name="app_name">Orbot</string>
<string name="app_version">1.0.5</string>
<string name="internal_web_url">http://orbot/</string> <string name="internal_web_url">http://orbot/</string>
<string name="default_web_url">http://check.torproject.org</string> <string name="default_web_url">http://check.torproject.org</string>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">Orbot</string> <string name="app_name">Orbot</string>
<string name="app_version">1.0.5</string>
<string name="internal_web_url">http://orbot/</string> <string name="internal_web_url">http://orbot/</string>
<string name="default_web_url">http://check.torproject.org</string> <string name="default_web_url">http://check.torproject.org</string>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">Orbot</string> <string name="app_name">Orbot</string>
<string name="app_version">1.0.5</string>
<string name="internal_web_url">http://orbot/</string> <string name="internal_web_url">http://orbot/</string>
<string name="default_web_url">http://check.torproject.org</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_general_group">General</string>
<string name="pref_start_boot_title">Start Orbot on Boot</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> <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> </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 <Preference
android:defaultValue="" android:defaultValue=""
android:key="pref_transparent_app_list" android:key="pref_transparent_app_list"
android:title="Select Apps" android:title="@string/pref_select_apps"
android:summary="Choose Apps to Route Through Tor" android:summary="@string/pref_select_apps_summary"
android:enabled="true"/> 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>
<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" <EditTextPreference android:key="pref_entrance_nodes"
android:title="Entrance Nodes" android:title="@string/pref_entrance_node"
android:summary="Fingerprints, nicks, countries and addresses for the first hop" android:summary="@string/pref_entrance_node_summary"
android:dialogTitle="Enter Entrance Nodes" android:dialogTitle="@string/pref_entrance_node_dialog"
/> />
<EditTextPreference android:key="pref_exit_nodes" <EditTextPreference android:key="pref_exit_nodes"
android:title="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:title="Use Bridges" android:key="pref_bridges_enabled"
android:summary="Enable alternate entrance nodes into the Tor Network"></CheckBoxPreference> 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" <EditTextPreference android:key="pref_bridges_list"
android:title="Bridges" 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 */ /* See LICENSE for licensing information */
package org.torproject.android; package org.torproject.android;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -24,6 +26,7 @@ import android.content.Intent;
import android.content.ServiceConnection; import android.content.ServiceConnection;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor; import android.content.SharedPreferences.Editor;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
@ -47,35 +50,48 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
{ {
/* Useful UI bits */ /* 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 TextView lblStatus = null; //the main text display widget
private ImageView imgStatus = null; //the main touchable image for activating Orbot private ImageView imgStatus = null; //the main touchable image for activating Orbot
private ProgressDialog progressDialog; private ProgressDialog progressDialog; //the spinning progress dialog that shows up now and then
private MenuItem mItemOnOff = null; private MenuItem mItemOnOff = null; //the menu item which we toggle based on Orbot state
/* Some tracking bits */ /* Some tracking bits */
private int torStatus = STATUS_READY; //latest status reported from the tor service 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 */ /* Tor Service interaction */
/* The primary interface we will be calling on the service. */ /* The primary interface we will be calling on the service. */
ITorService mService = null; ITorService mService = null; //interface to remote TorService
private boolean autoStartOnBind = false; 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) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
//if Tor binary is not running, then start the service up //if Tor binary is not running, then start the service up
//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)); 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);
//obvious? -yep got everything so far
lblStatus = (TextView)findViewById(R.id.lblStatus); lblStatus = (TextView)findViewById(R.id.lblStatus);
lblStatus.setOnLongClickListener(this); lblStatus.setOnLongClickListener(this);
imgStatus = (ImageView)findViewById(R.id.imgStatus); imgStatus = (ImageView)findViewById(R.id.imgStatus);
@ -124,8 +140,16 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
LayoutInflater li = LayoutInflater.from(this); LayoutInflater li = LayoutInflater.from(this);
View view = li.inflate(R.layout.layout_about, null); View view = li.inflate(R.layout.layout_about, null);
String version = "";
try {
version = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
} catch (NameNotFoundException e) {
version = "Version Not Found";
}
TextView versionName = (TextView)view.findViewById(R.id.versionName); TextView versionName = (TextView)view.findViewById(R.id.versionName);
versionName.setText(R.string.app_version); versionName.setText(version);
new AlertDialog.Builder(this) new AlertDialog.Builder(this)
.setTitle(getString(R.string.button_about)) .setTitle(getString(R.string.button_about))
@ -201,14 +225,25 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
return true; return true;
} }
/**
* 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 () private void doExit ()
{ {
try { try {
//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(); stopTor();
//perhaps this should be referenced as INTENT_TOR_SERVICE as in startService
stopService(new Intent(ITorService.class.getName())); stopService(new Intent(ITorService.class.getName()));
//clears all notifications from the status bar
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.cancelAll(); mNotificationManager.cancelAll();
@ -228,6 +263,7 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
/* /*
public boolean onKeyDown(int keyCode, KeyEvent event){ public boolean onKeyDown(int keyCode, KeyEvent event){
//yeah this should probably go away now :) - or not
if(keyCode==KeyEvent.KEYCODE_BACK){ if(keyCode==KeyEvent.KEYCODE_BACK){
if(currentView != R.layout.layout_main){ if(currentView != R.layout.layout_main){
@ -408,7 +444,7 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
pEdit.commit(); pEdit.commit();
new WizardHelper(this).showWizard(); startActivityForResult(new Intent(getBaseContext(), LotsaText.class), 1);
} }
@ -454,7 +490,12 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
private void showHelp () 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);
} }
@ -472,6 +513,9 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
//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) if (requestCode == 1 && resultCode == 1010 && mService != null)
{ {
new ProcessSettingsAsyncTask().execute(mService); new ProcessSettingsAsyncTask().execute(mService);
@ -480,6 +524,10 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
AlertDialog aDialog = null; AlertDialog aDialog = null;
//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) private void showAlert(String title, String msg, boolean button)
{ {
try try
@ -511,15 +559,17 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
} }
/* /*
* Set the state of the running/not running graphic and label * 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) public void updateStatus (String torServiceMsg)
{ {
try try
{ {
//if the serivce is bound, query it for the curren status value (int)
if (mService != null) if (mService != null)
torStatus = mService.getStatus(); torStatus = mService.getStatus();
//now update the layout_main UI based on the status
if (imgStatus != null) if (imgStatus != null)
{ {
@ -605,16 +655,25 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
} }
// 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 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); imgStatus.setImageResource(R.drawable.torstarting);
lblStatus.setText(getString(R.string.status_starting_up)); lblStatus.setText(getString(R.string.status_starting_up));
//we send a message here to the progressDialog i believe, but we can clarify that shortly
Message msg = mHandler.obtainMessage(TorServiceConstants.ENABLE_TOR_MSG); Message msg = mHandler.obtainMessage(TorServiceConstants.ENABLE_TOR_MSG);
mHandler.sendMessage(msg); mHandler.sendMessage(msg);
@ -622,11 +681,15 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
} }
//now we stop Tor! amazing!
private void stopTor () throws RemoteException private void stopTor () throws RemoteException
{ {
//if the service is bound, then turn it off, using the same "PROFILE_" technique
if (mService != null) if (mService != null)
{ {
mService.setProfile(TorServiceConstants.PROFILE_OFF); 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); Message msg = mHandler.obtainMessage(TorServiceConstants.DISABLE_TOR_MSG);
mHandler.sendMessage(msg); mHandler.sendMessage(msg);
} }
@ -675,6 +738,10 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
/** /**
* This implementation is used to receive callbacks from the remote * This implementation is used to receive callbacks from the remote
* service. * 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() { private ITorServiceCallback mCallback = new ITorServiceCallback.Stub() {
/** /**
@ -684,14 +751,17 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
* NOT be running in our main thread like most other things -- so, * 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. * 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) { public void statusChanged(String value) {
//pass it off to the progressDialog
Message msg = mHandler.obtainMessage(TorServiceConstants.STATUS_MSG); Message msg = mHandler.obtainMessage(TorServiceConstants.STATUS_MSG);
msg.getData().putString(HANDLER_TOR_MSG, value); msg.getData().putString(HANDLER_TOR_MSG, value);
mHandler.sendMessage(msg); mHandler.sendMessage(msg);
} }
@Override @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 { public void logMessage(String value) throws RemoteException {
Message msg = mHandler.obtainMessage(TorServiceConstants.LOG_MSG); Message msg = mHandler.obtainMessage(TorServiceConstants.LOG_MSG);
@ -702,6 +772,8 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
}; };
// 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() { private Handler mHandler = new Handler() {
public void handleMessage(Message msg) { public void handleMessage(Message msg) {
switch (msg.what) { switch (msg.what) {
@ -741,6 +813,10 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
/** /**
* Class for interacting with the main interface of the service. * 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() { private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, public void onServiceConnected(ComponentName className,
IBinder service) { IBinder service) {
@ -756,6 +832,7 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
try { try {
mService.registerCallback(mCallback); mService.registerCallback(mCallback);
//again with the update status?!? :P
updateStatus(""); updateStatus("");
if (autoStartOnBind) if (autoStartOnBind)
@ -789,10 +866,15 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
} }
}; };
//should move this up with all the other class variables
boolean mIsBound = false; boolean mIsBound = false;
//this is where we bind!
private void bindService () private void bindService ()
{ {
//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()), bindService(new Intent(ITorService.class.getName()),
mConnection, Context.BIND_AUTO_CREATE); mConnection, Context.BIND_AUTO_CREATE);
@ -800,6 +882,7 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
} }
//unbind removes the callback, and unbinds the service
private void unbindService () private void unbindService ()
{ {
if (mIsBound) { if (mIsBound) {
@ -815,6 +898,9 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants
} }
} }
//maybe needs this?
mService = null;
// Detach our existing connection. // Detach our existing connection.
unbindService(mConnection); unbindService(mConnection);
mIsBound = false; mIsBound = false;

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 boolean hasRoot = false;
private final static int HIDDEN_SERVICE_PREF_IDX = 6;
protected void onCreate(Bundle savedInstanceState) protected void onCreate(Bundle savedInstanceState)
{ {
super.onCreate(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); prefHiddenServices.setOnPreferenceClickListener(this);
((PreferenceCategory)this.getPreferenceScreen().getPreference(hiddenGroupIdx)).getPreference(1).setEnabled(prefHiddenServices.isChecked()); ((PreferenceCategory)this.getPreferenceScreen().getPreference(HIDDEN_SERVICE_PREF_IDX)).getPreference(1).setEnabled(prefHiddenServices.isChecked());
((PreferenceCategory)this.getPreferenceScreen().getPreference(hiddenGroupIdx)).getPreference(2).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) else if (preference == prefHiddenServices)
{ {
((PreferenceCategory)this.getPreferenceScreen().getPreference(5)).getPreference(1).setEnabled(prefHiddenServices.isChecked()); ((PreferenceCategory)this.getPreferenceScreen().getPreference(HIDDEN_SERVICE_PREF_IDX)).getPreference(1).setEnabled(prefHiddenServices.isChecked());
((PreferenceCategory)this.getPreferenceScreen().getPreference(5)).getPreference(2).setEnabled(prefHiddenServices.isChecked()); ((PreferenceCategory)this.getPreferenceScreen().getPreference(HIDDEN_SERVICE_PREF_IDX)).getPreference(2).setEnabled(prefHiddenServices.isChecked());
} }
else 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); LayoutInflater li = LayoutInflater.from(context);
View view = li.inflate(R.layout.layout_wizard_tips, null); 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() { 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() { 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() { btn3.setOnClickListener(new OnClickListener() {
@ -277,7 +277,7 @@ public class WizardHelper implements TorConstants {
public void showWizardRootConfigureTorification() public void showWizardRootConfigureTorification()
{ {
/*
LayoutInflater li = LayoutInflater.from(context); LayoutInflater li = LayoutInflater.from(context);
View view = li.inflate(R.layout.layout_wizard_root, null); 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. * Contains shared programming interfaces.
* All iptables "communication" is handled by this class. * All iptables "communication" is handled by this class.
*/ */
public final class Api { public final class IptablesManager {
/** application version string */ /** application version string */
public static final String VERSION = "1.5.1-dev"; public static final String VERSION = "1.5.1-dev";
/** special application UID used to indicate "any application" */ /** special application UID used to indicate "any application" */
@ -861,8 +861,8 @@ public final class Api {
return; return;
} }
/* notify */ /* notify */
final Intent message = new Intent(Api.STATUS_CHANGED_MSG); final Intent message = new Intent(IptablesManager.STATUS_CHANGED_MSG);
message.putExtra(Api.STATUS_EXTRA, enabled); message.putExtra(IptablesManager.STATUS_EXTRA, enabled);
ctx.sendBroadcast(message); ctx.sendBroadcast(message);
} }
/** /**

View File

@ -20,138 +20,75 @@ import android.util.Log;
public class TorBinaryInstaller implements TorServiceConstants { public class TorBinaryInstaller implements TorServiceConstants {
String installPath; File installFolder;
String apkPath;
Context context; Context context;
public TorBinaryInstaller (Context context, String installPath, String apkPath) public TorBinaryInstaller (Context context, File installFolder)
{ {
this.installPath = installPath; this.installFolder = installFolder;
this.apkPath = apkPath;
this.context = context; 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 * 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 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); is = context.getResources().openRawResource(R.raw.torab);
streamToFile(zip.getInputStream(zipen),installPath + TOR_BINARY_ASSET_KEY); streamToFile(is,installFolder, TOR_BINARY_ASSET_KEY, true);
zipen = zip.getEntry(ASSETS_BASE + TORRC_ASSET_KEY); is = context.getResources().openRawResource(R.raw.torac);
streamToFile(zip.getInputStream(zipen),installPath + TORRC_ASSET_KEY); streamToFile(is,installFolder, TOR_BINARY_ASSET_KEY, true);
zipen = zip.getEntry(ASSETS_BASE + PRIVOXY_ASSET_KEY); is = context.getResources().openRawResource(R.raw.torad);
streamToFile(zip.getInputStream(zipen),installPath + PRIVOXY_ASSET_KEY); streamToFile(is,installFolder, TOR_BINARY_ASSET_KEY, true);
zipen = zip.getEntry(ASSETS_BASE + PRIVOXYCONFIG_ASSET_KEY); is = context.getResources().openRawResource(R.raw.torrc);
streamToFile(zip.getInputStream(zipen),installPath + PRIVOXYCONFIG_ASSET_KEY); streamToFile(is,installFolder, TORRC_ASSET_KEY, false);
zipen = zip.getEntry(ASSETS_BASE + PRIVOXYCONFIG_ASSET_KEY); is = context.getResources().openRawResource(R.raw.privoxy);
streamToFile(zip.getInputStream(zipen),installPath + PRIVOXYCONFIG_ASSET_KEY); streamToFile(is,installFolder, PRIVOXY_ASSET_KEY, false);
is = context.getResources().openRawResource(R.raw.privoxy_config);
zip.close(); streamToFile(is,installFolder, PRIVOXYCONFIG_ASSET_KEY, false);
Log.d(TAG,"SUCCESS: unzipped tor, privoxy, iptables binaries from apk");
} }
catch (IOException ioe) 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 * 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]; byte[] buffer = new byte[FILE_WRITE_BUFFER_SIZE];
int bytecount; 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)
{
Log.d(TAG,"Error opening output file " + targetFilename,e);
return;
}
try
{
while ((bytecount = stm.read(buffer)) > 0) while ((bytecount = stm.read(buffer)) > 0)
@ -163,17 +100,8 @@ public class TorBinaryInstaller implements TorServiceConstants {
stmOut.close(); stmOut.close();
}
catch (java.io.IOException e) return true;
{
Log.d(TAG,"Error writing output file '" + targetFilename + "': " + e.toString());
return;
}
} }

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 */ /* See LICENSE for licensing information */
package org.torproject.android.service; package org.torproject.android.service;
@ -60,16 +60,13 @@ public class TorService extends Service implements TorServiceConstants, Runnable
private ArrayList<String> resetBuffer = null; private ArrayList<String> resetBuffer = null;
private String appHome; // private String appHome;
private String appBinHome; private File appBinHome;
private String appDataHome; private File appDataHome;
private String torBinaryPath; private String torBinaryPath;
private String privoxyPath; private String privoxyPath;
private boolean hasRoot = false;
/** Called when the activity is first created. */ /** Called when the activity is first created. */
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
@ -416,43 +413,37 @@ public class TorService extends Service implements TorServiceConstants, Runnable
private boolean checkTorBinaries () throws Exception private boolean checkTorBinaries () throws Exception
{ {
//android.os.Debug.waitForDebugger();
//check and install iptables //check and install iptables
Api.assertBinaries(this, true); IptablesManager.assertBinaries(this, true);
File fileInstall = getDir("",0);
String subBinPath = "bin/";
appHome = fileInstall.getAbsolutePath(); appBinHome = getDir("bin",0);
appBinHome = appHome + subBinPath; appDataHome = getCacheDir();
appDataHome = getCacheDir().getAbsolutePath() + '/';
logNotice( "appHome=" + appHome); // 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"); logNotice( "checking Tor binaries");
boolean torBinaryExists = new File(torBinaryPath).exists(); if (!(fileTor.exists() && filePrivoxy.exists()))
boolean privoxyBinaryExists = new File(privoxyPath).exists();
if (!(torBinaryExists && privoxyBinaryExists))
{ {
killTorProcess (); killTorProcess ();
TorBinaryInstaller installer = new TorBinaryInstaller(this, appBinHome, appBinHome); TorBinaryInstaller installer = new TorBinaryInstaller(this, appBinHome);
installer.start(true); boolean success = installer.installFromRaw();
torBinaryExists = new File(torBinaryPath).exists(); if (success)
privoxyBinaryExists = new File(privoxyPath).exists();
if (torBinaryExists && privoxyBinaryExists)
{ {
logNotice(getString(R.string.status_install_success)); logNotice(getString(R.string.status_install_success));
showToolbarNotification(getString(R.string.status_install_success), NOTIFY_ID, R.drawable.tornotification); showToolbarNotification(getString(R.string.status_install_success), NOTIFY_ID, R.drawable.tornotification);
torBinaryPath = fileTor.getAbsolutePath();
privoxyPath = filePrivoxy.getAbsolutePath();
} }
else else
{ {
@ -470,6 +461,9 @@ public class TorService extends Service implements TorServiceConstants, Runnable
logNotice("Found Tor binary: " + torBinaryPath); logNotice("Found Tor binary: " + torBinaryPath);
logNotice("Found Privoxy binary: " + privoxyPath); logNotice("Found Privoxy binary: " + privoxyPath);
torBinaryPath = fileTor.getAbsolutePath();
privoxyPath = filePrivoxy.getAbsolutePath();
} }
StringBuilder log = new StringBuilder (); StringBuilder log = new StringBuilder ();
@ -545,6 +539,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
boolean enableTransparentProxy = prefs.getBoolean("pref_transparent", false); boolean enableTransparentProxy = prefs.getBoolean("pref_transparent", false);
boolean transProxyAll = prefs.getBoolean("pref_transparent_all", false); boolean transProxyAll = prefs.getBoolean("pref_transparent_all", false);
boolean transProxyPortFallback = prefs.getBoolean("pref_transparent_port_fallback", false); boolean transProxyPortFallback = prefs.getBoolean("pref_transparent_port_fallback", false);
boolean transProxyTethering = prefs.getBoolean("pref_transparent_tethering", false);
TorService.logMessage ("Transparent Proxying: " + enableTransparentProxy); 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..."); showAlert("Status", "Setting up app-based transparent proxying...");
code = TorTransProxy.setTransparentProxyingByApp(this,AppManager.getApps(this)); code = TorTransProxy.setTransparentProxyingByApp(this,AppManager.getApps(this));
} }
} }
TorService.logMessage ("TorTransProxy resp code: " + code); TorService.logMessage ("TorTransProxy resp code: " + code);
@ -588,12 +584,23 @@ public class TorService extends Service implements TorServiceConstants, Runnable
if (code == 0) if (code == 0)
{ {
showAlert("Status", "Transparent proxying ENABLED"); showAlert("Status", "Transparent proxying ENABLED");
if (transProxyTethering)
{
showAlert("Status", "TransProxy enabled for Tethering!");
TorTransProxy.enableTetheringRules(this);
}
} }
else else
{ {
showAlert("Status", "WARNING: error starting transparent proxying!"); showAlert("Status", "WARNING: error starting transparent proxying!");
} }
return true; return true;
} }
@ -618,9 +625,9 @@ public class TorService extends Service implements TorServiceConstants, Runnable
StringBuilder log = new StringBuilder(); 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 runAsRootFalse = false;
boolean waitForProcess = false; boolean waitForProcess = false;
@ -688,7 +695,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
{ {
log = new StringBuilder(); log = new StringBuilder();
String privoxyConfigPath = appBinHome + PRIVOXYCONFIG_ASSET_KEY; String privoxyConfigPath = new File(appBinHome, PRIVOXYCONFIG_ASSET_KEY).getAbsolutePath();
String[] cmds = String[] cmds =
{ privoxyPath + " " + privoxyConfigPath + " &" }; { privoxyPath + " " + privoxyConfigPath + " &" };
@ -753,7 +760,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
logNotice( "SUCCESS connected to control port"); 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); File fileCookie = new File(torAuthCookie);
@ -1137,18 +1144,12 @@ public class TorService extends Service implements TorServiceConstants, Runnable
if (value == null || value.length() == 0) if (value == null || value.length() == 0)
{ {
resetBuffer.add(name); 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 else
{
configBuffer.add(name + ' ' + value); configBuffer.add(name + ' ' + value);
}
return false; return false;
} }
@ -1290,12 +1291,9 @@ public class TorService extends Service implements TorServiceConstants, Runnable
boolean enableHiddenServices = prefs.getBoolean("pref_hs_enable", false); boolean enableHiddenServices = prefs.getBoolean("pref_hs_enable", false);
boolean enableStrictNodes = prefs.getBoolean("pref_strict_nodes", false); boolean enableStrictNodes = prefs.getBoolean("pref_strict_nodes", false);
String entranceNodes = prefs.getString("pref_entrance_nodes", ""); String entranceNodes = prefs.getString("pref_entrance_nodes", null);
String exitNodes = prefs.getString("pref_exit_nodes", ""); String exitNodes = prefs.getString("pref_exit_nodes", null);
String excludeNodes = prefs.getString("pref_exclude_nodes", ""); String excludeNodes = prefs.getString("pref_exclude_nodes", null);
//boolean enableTransparentProxy = prefs.getBoolean(TorConstants.PREF_TRANSPARENT, false);
if (currentStatus == STATUS_ON) 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("ExitNodes", exitNodes, false);
mBinder.updateConfiguration("ExcludeNodes", excludeNodes, false); mBinder.updateConfiguration("ExcludeNodes", excludeNodes, false);
mBinder.updateConfiguration("StrictExitNodes", enableStrictNodes ? "1" : "0", false); mBinder.updateConfiguration("StrictNodes", enableStrictNodes ? "1" : "0", false);
if (useBridges) if (useBridges)
{ {
@ -1407,7 +1405,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
if (enableHiddenServices) if (enableHiddenServices)
{ {
mBinder.updateConfiguration("HiddenServiceDir",appDataHome, false); mBinder.updateConfiguration("HiddenServiceDir",appDataHome.getAbsolutePath(), false);
String hsPorts = prefs.getString("pref_hs_ports",""); String hsPorts = prefs.getString("pref_hs_ports","");

View File

@ -17,9 +17,11 @@ public class TorServiceUtils implements TorServiceConstants {
* Check if we have root access * Check if we have root access
* @return boolean true if we have root * @return boolean true if we have root
*/ */
/*
public static boolean checkRootAccess() { public static boolean checkRootAccess() {
StringBuilder log = new StringBuilder(); StringBuilder log = new StringBuilder();
try { try {
@ -45,7 +47,40 @@ public class TorServiceUtils implements TorServiceConstants {
TorService.logMessage("Could not acquire root permissions"); TorService.logMessage("Could not acquire root permissions");
return false; 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) public static int findProcessId(String command)

View File

@ -313,14 +313,12 @@ public class TorTransProxy implements TorServiceConstants {
return code; return code;
} }
public static int enableWifiHotspotRules (Context context) throws Exception public static int enableTetheringRules (Context context) throws Exception
{ {
boolean runRoot = true; boolean runRoot = true;
boolean waitFor = true; boolean waitFor = true;
//redirectDNSResolvConf(); //not working yet
String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath(); String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
StringBuilder script = new StringBuilder(); StringBuilder script = new StringBuilder();
@ -328,25 +326,24 @@ public class TorTransProxy implements TorServiceConstants {
StringBuilder res = new StringBuilder(); StringBuilder res = new StringBuilder();
int code = -1; int code = -1;
String[] hwinterfaces = {"usb0","wl0.1"};
for (int i = 0; i < hwinterfaces.length; i++)
{
script.append(ipTablesPath); script.append(ipTablesPath);
script.append(" -I FORWARD"); script.append(" -t nat -A PREROUTING -i ");
script.append(" -m state --state ESTABLISHED,RELATED -j ACCEPT"); 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(" || exit\n");
script.append(ipTablesPath); script.append(ipTablesPath);
script.append(" -I FORWARD"); script.append(" -t nat -A PREROUTING -i ");
script.append(" -j ACCEPT"); script.append(hwinterfaces[i]);
script.append(" || exit\n"); script.append(" -p tcp -j REDIRECT --to-ports ");
script.append(TOR_TRANSPROXY_PORT);
/*
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(" || exit\n");
}
String[] cmdAdd = {script.toString()}; String[] cmdAdd = {script.toString()};
@ -374,8 +371,6 @@ public class TorTransProxy implements TorServiceConstants {
purgeIptables(context); purgeIptables(context);
enableWifiHotspotRules(context);
int torUid = context.getApplicationInfo().uid; int torUid = context.getApplicationInfo().uid;
// Set up port redirection // Set up port redirection