big checkin for 0.0.8-beta-280710a build with new start wizard, improved ctrlport handling, and root config
svn:r22697
|
@ -25,6 +25,7 @@
|
|||
|
||||
<activity android:name=".SettingsPreferences" android:label="@string/app_name"/>
|
||||
<activity android:name=".AppManager" android:label="@string/app_name"/>
|
||||
<activity android:name=".WizardActivity" android:label="@string/app_name"/>
|
||||
|
||||
<service android:name=".service.TorService" android:process=":remote" android:debuggable="false">
|
||||
<intent-filter>
|
||||
|
|
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 120 KiB |
After Width: | Height: | Size: 459 B |
After Width: | Height: | Size: 1.6 KiB |
|
@ -11,13 +11,28 @@
|
|||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
<TextView android:text="@string/wizard_details"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="15px"
|
||||
android:paddingLeft="15px"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#00ff00" />
|
||||
<TextView android:text="@string/wizard_details_msg"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:autoLink="web"
|
||||
android:textColorLink="#ffffff"
|
||||
android:paddingLeft="15px"
|
||||
android:textColor="#ffffff" />
|
||||
|
||||
<TextView android:text="Version: "
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="15px"
|
||||
android:paddingLeft="15px"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#ffffff" />
|
||||
android:textColor="#00ff00" />
|
||||
<TextView android:text="- Unknown -"
|
||||
android:id="@+id/versionName"
|
||||
android:layout_width="fill_parent"
|
||||
|
@ -25,13 +40,13 @@
|
|||
android:paddingLeft="15px"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:textColor="#ffffff" />
|
||||
<TextView android:text="Project-Home: "
|
||||
<TextView android:text="Project Home(s): "
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="15px"
|
||||
android:paddingLeft="15px"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#ffffff" />
|
||||
android:textColor="#00ff00" />
|
||||
<TextView android:text="https://www.torproject.org/docs/android\nhttps://guardianproject.info/apps/orbot/"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -45,7 +60,7 @@
|
|||
android:paddingTop="15px"
|
||||
android:paddingLeft="15px"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#ffffff" />
|
||||
android:textColor="#00ff00" />
|
||||
<TextView android:text="The Tor License"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -64,7 +79,7 @@
|
|||
android:paddingTop="15px"
|
||||
android:paddingLeft="15px"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#ffffff" />
|
||||
android:textColor="#00ff00" />
|
||||
<TextView android:text="Tor v0.2.2.13: https://www.torproject.org"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<ScrollView android:id="@+id/helpscrollview"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
<TextView android:text=""
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="#ffffff" />
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</LinearLayout>
|
||||
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<ScrollView android:id="@+id/helpscrollview"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:padding="3px">
|
||||
<TextView android:text="@string/wizard_configure_msg" android:textColor="#ffffff" android:id="@+id/WizardRootTextView01" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
|
||||
|
||||
|
||||
<CheckBox android:layout_marginTop="20px" android:text="@string/wizard_configure_all" android:id="@+id/WizardRootCheckBox01" android:layout_width="wrap_content" android:layout_height="wrap_content"></CheckBox>
|
||||
<TextView android:text=" or " android:textColor="#ffffff" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
|
||||
|
||||
<Button android:text="@string/wizard_configure_select_apps" android:id="@+id/WizardRootButton01" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</LinearLayout>
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<ScrollView android:id="@+id/helpscrollview"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:padding="3px">
|
||||
|
||||
|
||||
<TextView android:text="@string/wizard_permissions_msg_stock" android:textColor="#ffffff" android:id="@+id/TextView01" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
|
||||
|
||||
<Button android:text="@string/wizard_permission_enable_root" android:layout_marginTop="10px" android:id="@+id/WizardRootButtonEnable" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||
|
||||
|
||||
|
||||
<TextView android:text="@string/wizard_permissions_no_root" android:layout_marginTop="10px" android:textColor="#ffffff" android:id="@+id/TextView01" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
|
||||
|
||||
<CheckBox android:text="@string/wizard_permissions_consent" android:id="@+id/CheckBoxConsent" android:layout_width="wrap_content" android:layout_height="wrap_content"></CheckBox>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</LinearLayout>
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<ScrollView android:id="@+id/helpscrollview"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:padding="3px">
|
||||
|
||||
<TextView android:text="@string/wizard_tips_msg" android:textColor="#ffffff" android:id="@+id/TextView01" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
|
||||
|
||||
<Button android:text="@string/wizard_tips_otrchat" android:layout_marginTop="10px" android:id="@+id/WizardRootButtonInstallOtrchat" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||
|
||||
<Button android:text="@string/wizard_tips_orweb" android:layout_marginTop="10px" android:id="@+id/WizardRootButtonInstallOrweb" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</LinearLayout>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<ScrollView android:id="@+id/helpscrollview"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:padding="3px">
|
||||
<TextView android:text="@string/wizard_welcome_msg" android:textColor="#ffffff" android:id="@+id/WizardRootTextView01" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
|
||||
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</LinearLayout>
|
||||
|
|
@ -58,10 +58,52 @@ and all DNS requests. This includes the built-in Browser, Gmail, YouTube and Map
|
|||
<string name="pref_trans_proxy_summary">Automatic Torifying of Apps</string>
|
||||
|
||||
<string name="pref_transparent_all_title">Tor Everything</string>
|
||||
<string name="pref_transparent_all_summary">Send traffic for all apps through Tor</string>
|
||||
<string name="pref_transparent_all_summary">Proxy traffic for all apps through Tor</string>
|
||||
|
||||
<string name="status_install_success">Tor binaries successfully installed!</string>
|
||||
<string name="status_install_fail">The Tor binary files were unable to be installed. Please check the log and notify tor-assistants@torproject.org</string>
|
||||
|
||||
<string name="title_error">Application Error</string>
|
||||
|
||||
<string name="wizard_title">Welcome to Orbot</string>
|
||||
|
||||
<string name="wizard_btn_tell_me_more">About Orbot</string>
|
||||
<string name="btn_next">Next</string>
|
||||
<string name="btn_back">Back</string>
|
||||
<string name="btn_finish">Finish</string>
|
||||
|
||||
|
||||
<!-- Welcome Wizard strings (DJH) -->
|
||||
<string name="wizard_welcome_msg">Orbot brings Tor to Android. Tor is free software and an open network that helps you defend against a form of network surveillance that threatens personal freedom and privacy, confidential business activities and relationships, and state security known as traffic analysis.\n\n*WARNING:* Simply installing Orbot will _not_ magically anonymize your mobile traffic! This wizard will help you get started.</string>
|
||||
<string name="wizard_details">Some Orbot Details</string>
|
||||
<string name="wizard_details_msg">Orbot is an open-source application that contains Tor, LibEvent and Privoxy. It provides a local HTTP proxy (8118) and a SOCKS proxy (9050) into the Tor network. Orbot also has the ability, on rooted device, to send all internet traffic through Tor.</string>
|
||||
<string name="wizard_permissions_root">Grant Permissions</string>
|
||||
<string name="wizard_permissions_stock">Permissions Warning</string>
|
||||
<string name="wizard_premissions_msg_root">Excellent! We\'ve detected that you have root permissions enabled for Orbot. We will use this power wisely.</string>
|
||||
<string name="wizard_permissions_msg_stock">We\'ve detected that you do not have root permissions enabled. Your application data usage will NOT be transparently routed through Tor without root access. </string>
|
||||
|
||||
<string name="wizard_permissions_no_root">If you choose to continue WITHOUT root, you must use apps that know how to talk to Tor.</string>
|
||||
<string name="wizard_permissions_consent">I understand and would like to continue without root</string>
|
||||
|
||||
<string name="wizard_permission_enable_root">Attempt to enable root access</string>
|
||||
<string name="wizard_configure">Configure Torification</string>
|
||||
<string name="wizard_configure_msg">Orbot gives you the option to route all application traffic through Tor OR to choose your applications individually.</string>
|
||||
<string name="wizard_configure_all">Proxy All Apps Through Tor</string>
|
||||
<string name="wizard_configure_select_apps">Select Individual Apps for Tor</string>
|
||||
|
||||
|
||||
<string name="wizard_tips_tricks">Orbot-enabled Apps</string>
|
||||
<string name="wizard_tips_msg">We encourage you to download & use apps that know how to connect directly to Orbot. Click on the buttons below to install.</string>
|
||||
<string name="wizard_tips_otrchat">OtrChat - From the Orbot dev team, a secure Instant Messaging client for Android.</string>
|
||||
<string name="wizard_tips_orweb">OrWeb (Android 1.x Only) - From the Orbot dev team, a web browser designed to work with Tor.</string>
|
||||
|
||||
<string name="wizard_final">Orbot is ready!</string>
|
||||
<string name="wizard_final_msg">Hundreds of thousands of people around the world use Tor for a wide variety of reasons: journalists and bloggers, human rights workers, law enforcement officers, soldiers, corporations, citizens of repressive regimes, and just ordinary citizens... and now you are ready to, as well!</string>
|
||||
|
||||
<string name="otrchat_apk_url">https://github.com/downloads/guardianproject/OtRChat/OtRChat-0.0.1-alpha-build6a.apk</string>
|
||||
<string name="orweb_apk_url">http://github.com/downloads/guardianproject/Orweb/Orweb-0.0.1c.apk.apk</string>
|
||||
|
||||
<!-- END Welcome Wizard strings (DJH) -->
|
||||
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -0,0 +1,263 @@
|
|||
/* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
package org.torproject.android;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.Editor;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
|
||||
public class AppManager extends Activity implements OnCheckedChangeListener, OnClickListener, TorConstants {
|
||||
|
||||
private static TorifiedApp[] apps = null;
|
||||
|
||||
private ListView listApps;
|
||||
|
||||
private AppManager mAppManager;
|
||||
|
||||
|
||||
private boolean appsLoaded = false;
|
||||
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
this.setContentView(R.layout.layout_apps);
|
||||
|
||||
mAppManager = this;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
listApps = (ListView)findViewById(R.id.applistview);
|
||||
|
||||
if (!appsLoaded)
|
||||
loadApps();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void loadApps ()
|
||||
{
|
||||
final TorifiedApp[] apps = getApps(this);
|
||||
|
||||
Arrays.sort(apps, new Comparator<TorifiedApp>() {
|
||||
public int compare(TorifiedApp o1, TorifiedApp o2) {
|
||||
if (o1.isTorified() == o2.isTorified()) return o1.getName().compareTo(o2.getName());
|
||||
if (o1.isTorified()) return -1;
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
|
||||
final LayoutInflater inflater = getLayoutInflater();
|
||||
|
||||
final ListAdapter adapter = new ArrayAdapter<TorifiedApp>(this,R.layout.layout_apps_item,R.id.itemtext,apps) {
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
ListEntry entry;
|
||||
if (convertView == null) {
|
||||
// Inflate a new view
|
||||
convertView = inflater.inflate(R.layout.layout_apps_item, parent, false);
|
||||
entry = new ListEntry();
|
||||
entry.icon = (ImageView) convertView.findViewById(R.id.itemicon);
|
||||
entry.box = (CheckBox) convertView.findViewById(R.id.itemcheck);
|
||||
entry.text = (TextView) convertView.findViewById(R.id.itemtext);
|
||||
|
||||
entry.text.setOnClickListener(mAppManager);
|
||||
entry.text.setOnClickListener(mAppManager);
|
||||
|
||||
convertView.setTag(entry);
|
||||
|
||||
entry.box.setOnCheckedChangeListener(mAppManager);
|
||||
} else {
|
||||
// Convert an existing view
|
||||
entry = (ListEntry) convertView.getTag();
|
||||
}
|
||||
|
||||
|
||||
final TorifiedApp app = apps[position];
|
||||
|
||||
|
||||
entry.icon.setImageDrawable(app.getIcon());
|
||||
entry.text.setText(app.getName());
|
||||
|
||||
final CheckBox box = entry.box;
|
||||
box.setTag(app);
|
||||
box.setChecked(app.isTorified());
|
||||
|
||||
entry.text.setTag(box);
|
||||
entry.icon.setTag(box);
|
||||
|
||||
return convertView;
|
||||
}
|
||||
};
|
||||
|
||||
listApps.setAdapter(adapter);
|
||||
|
||||
appsLoaded = true;
|
||||
|
||||
}
|
||||
|
||||
private static class ListEntry {
|
||||
private CheckBox box;
|
||||
private TextView text;
|
||||
private ImageView icon;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see android.app.Activity#onStop()
|
||||
*/
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
|
||||
//Log.i(getClass().getName(),"Exiting Preferences");
|
||||
}
|
||||
|
||||
|
||||
public static TorifiedApp[] getApps (Context context)
|
||||
{
|
||||
if (apps != null)
|
||||
return apps;
|
||||
|
||||
final SharedPreferences prefs = context.getSharedPreferences(PREFS_KEY, 0);
|
||||
|
||||
String tordAppString = prefs.getString(PREFS_KEY_TORIFIED, "");
|
||||
String[] tordApps;
|
||||
|
||||
StringTokenizer st = new StringTokenizer(tordAppString,"|");
|
||||
tordApps = new String[st.countTokens()];
|
||||
int tordIdx = 0;
|
||||
while (st.hasMoreTokens())
|
||||
{
|
||||
tordApps[tordIdx++] = st.nextToken();
|
||||
}
|
||||
|
||||
Arrays.sort(tordApps);
|
||||
|
||||
//else load the apps up
|
||||
PackageManager pMgr = context.getPackageManager();
|
||||
|
||||
List<ApplicationInfo> lAppInfo = pMgr.getInstalledApplications(0);
|
||||
|
||||
Iterator<ApplicationInfo> itAppInfo = lAppInfo.iterator();
|
||||
|
||||
apps = new TorifiedApp[lAppInfo.size()];
|
||||
|
||||
ApplicationInfo aInfo = null;
|
||||
|
||||
int appIdx = 0;
|
||||
|
||||
while (itAppInfo.hasNext())
|
||||
{
|
||||
aInfo = itAppInfo.next();
|
||||
|
||||
apps[appIdx] = new TorifiedApp();
|
||||
|
||||
apps[appIdx].setEnabled(aInfo.enabled);
|
||||
apps[appIdx].setUid(aInfo.uid);
|
||||
apps[appIdx].setUsername(pMgr.getNameForUid(apps[appIdx].getUid()));
|
||||
apps[appIdx].setProcname(aInfo.processName);
|
||||
apps[appIdx].setName(pMgr.getApplicationLabel(aInfo).toString());
|
||||
apps[appIdx].setIcon(pMgr.getApplicationIcon(aInfo));
|
||||
|
||||
// check if this application is allowed
|
||||
if (Arrays.binarySearch(tordApps, apps[appIdx].getUsername()) >= 0) {
|
||||
apps[appIdx].setTorified(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
apps[appIdx].setTorified(false);
|
||||
}
|
||||
|
||||
appIdx++;
|
||||
}
|
||||
|
||||
return apps;
|
||||
}
|
||||
|
||||
|
||||
public static void saveAppSettings (Context context)
|
||||
{
|
||||
if (apps == null)
|
||||
return;
|
||||
|
||||
final SharedPreferences prefs = context.getSharedPreferences(PREFS_KEY, 0);
|
||||
|
||||
StringBuilder tordApps = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < apps.length; i++)
|
||||
{
|
||||
if (apps[i].isTorified())
|
||||
{
|
||||
tordApps.append(apps[i].getUsername());
|
||||
tordApps.append("|");
|
||||
}
|
||||
}
|
||||
|
||||
Editor edit = prefs.edit();
|
||||
edit.putString(PREFS_KEY_TORIFIED, tordApps.toString());
|
||||
edit.commit();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called an application is check/unchecked
|
||||
*/
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
final TorifiedApp app = (TorifiedApp) buttonView.getTag();
|
||||
if (app != null) {
|
||||
app.setTorified(isChecked);
|
||||
}
|
||||
|
||||
saveAppSettings(this);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
CheckBox cbox = (CheckBox)v.getTag();
|
||||
|
||||
final TorifiedApp app = (TorifiedApp)cbox.getTag();
|
||||
if (app != null) {
|
||||
app.setTorified(!app.isTorified());
|
||||
cbox.setChecked(app.isTorified());
|
||||
}
|
||||
|
||||
saveAppSettings(this);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package org.torproject.android;
|
||||
|
||||
|
||||
//list view with add/remove hidden services - user is prompted for port
|
||||
|
||||
public class HiddenServiceManager {
|
||||
|
||||
}
|
||||
/*
|
||||
*
|
||||
* ## Once you have configured a hidden service, you can look at the
|
||||
## contents of the file ".../hidden_service/hostname" for the address
|
||||
## to tell people.
|
||||
##
|
||||
## HiddenServicePort x y:z says to redirect requests on port x to the
|
||||
## address y:z.
|
||||
|
||||
#HiddenServiceDir @LOCALSTATEDIR@/lib/tor/hidden_service/
|
||||
#HiddenServicePort 80 127.0.0.1:80
|
||||
|
||||
#HiddenServiceDir @LOCALSTATEDIR@/lib/tor/other_hidden_service/
|
||||
#HiddenServicePort 80 127.0.0.1:80
|
||||
#HiddenServicePort 22 127.0.0.1:22
|
||||
*/
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package org.torproject.android;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
public class OnBootReceiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Intent serviceIntent = new Intent();
|
||||
serviceIntent.setAction("org.torproject.android.service.TorService");
|
||||
context.startService(serviceIntent);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -19,6 +19,7 @@ import android.content.DialogInterface;
|
|||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.Editor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
|
@ -35,7 +36,10 @@ import android.view.View;
|
|||
import android.view.View.OnClickListener;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
|
@ -58,10 +62,14 @@ public class Orbot extends Activity implements OnClickListener, TorConstants
|
|||
/* The primary interface we will be calling on the service. */
|
||||
ITorService mService = null;
|
||||
|
||||
Orbot mOrbot = null;
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mOrbot = this;
|
||||
|
||||
setTheme(android.R.style.Theme_Black_NoTitleBar);
|
||||
//setTitle(getString(R.string.app_name) + ' ' + getString(R.string.app_version));
|
||||
showMain();
|
||||
|
@ -244,10 +252,8 @@ public class Orbot extends Activity implements OnClickListener, TorConstants
|
|||
|
||||
|
||||
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
|
||||
mNotificationManager.cancelAll();
|
||||
|
||||
|
||||
if (mService != null)
|
||||
{
|
||||
try {
|
||||
|
@ -258,6 +264,23 @@ public class Orbot extends Activity implements OnClickListener, TorConstants
|
|||
}
|
||||
}
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mOrbot);
|
||||
|
||||
boolean showWizard = prefs.getBoolean("show_wizard",true);
|
||||
|
||||
if (showWizard)
|
||||
{
|
||||
|
||||
Editor pEdit = prefs.edit();
|
||||
|
||||
pEdit.putBoolean("show_wizard",false);
|
||||
|
||||
pEdit.commit();
|
||||
|
||||
showHelp();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -272,7 +295,7 @@ public class Orbot extends Activity implements OnClickListener, TorConstants
|
|||
|
||||
//updateStatus ("");
|
||||
|
||||
hasRoot = TorTransProxy.hasRootAccess();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -297,7 +320,6 @@ public class Orbot extends Activity implements OnClickListener, TorConstants
|
|||
{
|
||||
bindService(); //connect the UI activity to the remote service
|
||||
|
||||
|
||||
currentView = R.layout.layout_main;
|
||||
setContentView(currentView);
|
||||
|
||||
|
@ -358,64 +380,7 @@ public class Orbot extends Activity implements OnClickListener, TorConstants
|
|||
private void showHelp ()
|
||||
{
|
||||
|
||||
LayoutInflater li = LayoutInflater.from(this);
|
||||
View view = li.inflate(R.layout.layout_help, null);
|
||||
|
||||
StringBuilder msg = new StringBuilder();
|
||||
msg.append(getString(R.string.help_text_1));
|
||||
msg.append("\n\n");
|
||||
|
||||
if (hasRoot)
|
||||
{
|
||||
msg.append("Your device is ROOTED. Please enable the 'Transparent Proxying' setting to select which apps to send through Tor.");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
msg.append("Your device is NOT rooted.\n");
|
||||
|
||||
msg.append(getString(R.string.help_text_5));
|
||||
|
||||
msg.append("\n\n");
|
||||
|
||||
msg.append(getString(R.string.not_anonymous_yet));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
msg.append(getString(R.string.help_text_2));
|
||||
msg.append("\n\n");
|
||||
msg.append(getString(R.string.help_text_3));
|
||||
msg.append("\n\n");
|
||||
msg.append(getString(R.string.help_text_4));
|
||||
msg.append("\n\n");
|
||||
msg.append(getString(R.string.help_text_5));
|
||||
msg.append("\n\n");
|
||||
*/
|
||||
|
||||
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle(getString(R.string.menu_info))
|
||||
.setMessage(msg.toString())
|
||||
.setNeutralButton(getString(R.string.button_about), new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int whichButton) {
|
||||
|
||||
showAbout();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(getString(R.string.button_close), new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int whichButton) {
|
||||
// Log.d(TAG, "Close pressed");
|
||||
}
|
||||
})
|
||||
.show();
|
||||
}
|
||||
|
||||
private void showHelpWizard ()
|
||||
{
|
||||
|
||||
//sshowAlert("Configure",getString(R.string.not_anonymous_yet));
|
||||
|
||||
new WizardHelper(this).showWizard();
|
||||
}
|
||||
|
||||
|
||||
|
@ -447,6 +412,8 @@ public class Orbot extends Activity implements OnClickListener, TorConstants
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Read in the Preferences and write then to the .torrc file
|
||||
*/
|
||||
|
@ -611,17 +578,8 @@ public class Orbot extends Activity implements OnClickListener, TorConstants
|
|||
return;
|
||||
}
|
||||
|
||||
mService.updateConfiguration("UseBridges", "1", false);
|
||||
|
||||
if (autoUpdateBridges)
|
||||
{
|
||||
mService.updateConfiguration("UpdateBridgesFromAuthority", "1", false);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
mService.updateConfiguration("UpdateBridgesFromAuthority", "0", false);
|
||||
}
|
||||
mService.updateConfiguration("UseBridges", "1", false);
|
||||
|
||||
String bridgeDelim = "\n";
|
||||
|
||||
|
@ -637,6 +595,9 @@ public class Orbot extends Activity implements OnClickListener, TorConstants
|
|||
mService.updateConfiguration("bridge", st.nextToken(), false);
|
||||
|
||||
}
|
||||
|
||||
mService.updateConfiguration("UpdateBridgesFromAuthority", "0", false);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -721,7 +682,7 @@ public class Orbot extends Activity implements OnClickListener, TorConstants
|
|||
|
||||
lblStatus.setText(getString(R.string.status_activated));
|
||||
|
||||
showHelpWizard ();
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
@ -998,7 +959,6 @@ public class Orbot extends Activity implements OnClickListener, TorConstants
|
|||
};
|
||||
|
||||
boolean mIsBound = false;
|
||||
boolean hasRoot = false;
|
||||
|
||||
private void bindService ()
|
||||
{
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
package org.torproject.android;
|
||||
|
||||
import org.torproject.android.service.TorServiceUtils;
|
||||
import org.torproject.android.service.TorTransProxy;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
@ -28,7 +29,7 @@ public class SettingsPreferences
|
|||
super.onCreate(savedInstanceState);
|
||||
addPreferencesFromResource(R.xml.preferences);
|
||||
|
||||
hasRoot = TorServiceUtils.hasRoot();
|
||||
hasRoot = TorTransProxy.hasRootAccess();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,8 @@ public interface TorConstants {
|
|||
public final static String PREF_REACHABLE_ADDRESSES = "pref_reachable_addresses";
|
||||
public final static String PREF_REACHABLE_ADDRESSES_PORTS = "pref_reachable_addresses_ports";
|
||||
public final static String PREF_TRANSPARENT = "pref_transparent";
|
||||
public final static String PREF_TRANSPARENT_ALL = "pref_transparent_all";
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
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","this is nathan's 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) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,371 @@
|
|||
package org.torproject.android;
|
||||
|
||||
import org.torproject.android.service.TorTransProxy;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
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.preference.PreferenceManager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.TextView;
|
||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class WizardHelper implements TorConstants {
|
||||
|
||||
private Context context;
|
||||
private Dialog currentDialog;
|
||||
|
||||
public WizardHelper (Context context)
|
||||
{
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
|
||||
public void showWizard ()
|
||||
{
|
||||
showWizardStep1();
|
||||
}
|
||||
|
||||
public void showWizardStep1()
|
||||
{
|
||||
|
||||
|
||||
String title = context.getString(R.string.wizard_title);
|
||||
|
||||
LayoutInflater li = LayoutInflater.from(context);
|
||||
View view = li.inflate(R.layout.layout_wizard_welcome, null);
|
||||
|
||||
|
||||
showCustomDialog(title, view,context.getString(R.string.btn_next),context.getString(R.string.wizard_btn_tell_me_more),new DialogInterface.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
|
||||
if (which == DialogInterface.BUTTON_NEUTRAL)
|
||||
{
|
||||
|
||||
showWizardStep2();
|
||||
}
|
||||
else if (which == DialogInterface.BUTTON_POSITIVE)
|
||||
{
|
||||
showAbout();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void showWizardStep2()
|
||||
{
|
||||
|
||||
String title = null;
|
||||
String msg = null;
|
||||
|
||||
|
||||
title = context.getString(R.string.wizard_permissions_root);
|
||||
msg = context.getString(R.string.wizard_premissions_msg_root);
|
||||
|
||||
|
||||
title = context.getString(R.string.wizard_permissions_stock);
|
||||
|
||||
LayoutInflater li = LayoutInflater.from(context);
|
||||
View view = li.inflate(R.layout.layout_wizard_stock, null);
|
||||
|
||||
Button btn1 = (Button)view.findViewById(R.id.WizardRootButtonEnable);
|
||||
|
||||
btn1.setOnClickListener(new OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
|
||||
|
||||
boolean hasRoot = TorTransProxy.hasRootAccess();
|
||||
|
||||
if (hasRoot)
|
||||
{
|
||||
currentDialog.dismiss();
|
||||
showWizardStep2Root();
|
||||
}
|
||||
else
|
||||
{
|
||||
Toast.makeText(context, "Unable to get root access", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
showCustomDialog(title, view,context.getString(R.string.btn_next),context.getString(R.string.btn_back),new DialogInterface.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
|
||||
if (which == DialogInterface.BUTTON_NEUTRAL)
|
||||
{
|
||||
showWizardTipsAndTricks();
|
||||
}
|
||||
else if (which == DialogInterface.BUTTON_POSITIVE)
|
||||
{
|
||||
showWizardStep1();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void showWizardStep2Root()
|
||||
{
|
||||
|
||||
String title = null;
|
||||
String msg = null;
|
||||
|
||||
|
||||
|
||||
title = context.getString(R.string.wizard_permissions_root);
|
||||
msg = context.getString(R.string.wizard_premissions_msg_root);
|
||||
|
||||
|
||||
|
||||
showDialog(title, msg,context.getString(R.string.btn_next),context.getString(R.string.btn_back),new DialogInterface.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
|
||||
if (which == DialogInterface.BUTTON_NEUTRAL)
|
||||
{
|
||||
showWizardRootConfigureTorification();
|
||||
}
|
||||
else if (which == DialogInterface.BUTTON_POSITIVE)
|
||||
{
|
||||
showWizardStep1();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void showWizardTipsAndTricks()
|
||||
{
|
||||
|
||||
String title = context.getString(R.string.wizard_tips_tricks);
|
||||
|
||||
LayoutInflater li = LayoutInflater.from(context);
|
||||
View view = li.inflate(R.layout.layout_wizard_tips, null);
|
||||
|
||||
Button btn1 = (Button)view.findViewById(R.id.WizardRootButtonInstallOtrchat);
|
||||
|
||||
btn1.setOnClickListener(new OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
|
||||
String url = context.getString(R.string.otrchat_apk_url);
|
||||
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
Button btn2 = (Button)view.findViewById(R.id.WizardRootButtonInstallOrweb);
|
||||
|
||||
btn2.setOnClickListener(new OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
|
||||
String url = context.getString(R.string.orweb_apk_url);
|
||||
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
showCustomDialog(title, view,context.getString(R.string.btn_next),context.getString(R.string.btn_back),new DialogInterface.OnClickListener() {
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
|
||||
if (which == DialogInterface.BUTTON_NEUTRAL)
|
||||
{
|
||||
showWizardFinal();
|
||||
|
||||
}
|
||||
else if (which == DialogInterface.BUTTON_POSITIVE)
|
||||
{
|
||||
showWizardStep2();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void showWizardRootConfigureTorification()
|
||||
{
|
||||
|
||||
LayoutInflater li = LayoutInflater.from(context);
|
||||
View view = li.inflate(R.layout.layout_wizard_root, null);
|
||||
|
||||
CheckBox cb1 = (CheckBox)view.findViewById(R.id.WizardRootCheckBox01);
|
||||
Button btn1 = (Button)view.findViewById(R.id.WizardRootButton01);
|
||||
|
||||
cb1.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 btn1 = (Button)buttonView.getParent().findViewById(R.id.WizardRootButton01);
|
||||
//btn1.setEnabled(!isChecked);
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
btn1.setOnClickListener(new OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
Editor pEdit = prefs.edit();
|
||||
pEdit.putBoolean(PREF_TRANSPARENT, true);
|
||||
pEdit.putBoolean(PREF_TRANSPARENT_ALL, false);
|
||||
pEdit.commit();
|
||||
|
||||
context.startActivity(new Intent(context, AppManager.class));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
showCustomDialog(context.getString(R.string.wizard_configure),view,context.getString(R.string.btn_next),context.getString(R.string.btn_back),new DialogInterface.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
|
||||
dialog.dismiss();
|
||||
|
||||
if (which == DialogInterface.BUTTON_NEUTRAL)
|
||||
{
|
||||
showWizardTipsAndTricks();
|
||||
|
||||
}
|
||||
else if (which == DialogInterface.BUTTON_POSITIVE)
|
||||
{
|
||||
showWizardStep2();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void showWizardFinal ()
|
||||
{
|
||||
String title = null;
|
||||
String msg = null;
|
||||
|
||||
|
||||
title = context.getString(R.string.wizard_final);
|
||||
msg = context.getString(R.string.wizard_final_msg);
|
||||
|
||||
new AlertDialog.Builder(context)
|
||||
.setIcon(R.drawable.icon)
|
||||
.setTitle(title)
|
||||
.setPositiveButton(R.string.button_close, null)
|
||||
.setMessage(msg)
|
||||
.show();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void showDialog (String title, String msg, String button1, String button2, DialogInterface.OnClickListener ocListener)
|
||||
{
|
||||
|
||||
// dialog.setContentView(R.layout.custom_dialog);
|
||||
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context)
|
||||
.setIcon(R.drawable.icon)
|
||||
.setTitle(title)
|
||||
.setMessage(msg)
|
||||
.setNeutralButton(button1, ocListener)
|
||||
.setPositiveButton(button2, ocListener);
|
||||
|
||||
|
||||
currentDialog = builder.show();
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void showCustomDialog (String title, View view, String button1, String button2, DialogInterface.OnClickListener ocListener)
|
||||
{
|
||||
|
||||
currentDialog = new AlertDialog.Builder(context)
|
||||
.setIcon(R.drawable.icon)
|
||||
.setTitle(title)
|
||||
.setView(view)
|
||||
.setNeutralButton(button1, ocListener)
|
||||
.setPositiveButton(button2, ocListener)
|
||||
.show();
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void showAbout ()
|
||||
{
|
||||
|
||||
LayoutInflater li = LayoutInflater.from(context);
|
||||
View view = li.inflate(R.layout.layout_about, null);
|
||||
TextView versionName = (TextView)view.findViewById(R.id.versionName);
|
||||
versionName.setText(R.string.app_version);
|
||||
|
||||
new AlertDialog.Builder(context)
|
||||
.setTitle(context.getString(R.string.button_about))
|
||||
.setView(view)
|
||||
.setNeutralButton(context.getString(R.string.btn_back), new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int whichButton) {
|
||||
showWizard();
|
||||
}
|
||||
})
|
||||
.show();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -49,7 +49,6 @@ public class TorService extends Service implements TorServiceConstants, Runnable
|
|||
|
||||
private ArrayList<String> configBuffer = null;
|
||||
|
||||
private boolean hasRoot = false;
|
||||
|
||||
private String appHome = null;
|
||||
private String torBinaryPath = null;
|
||||
|
@ -61,8 +60,6 @@ public class TorService extends Service implements TorServiceConstants, Runnable
|
|||
|
||||
Log.i(TAG,"TorService: onCreate");
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -223,15 +220,25 @@ public class TorService extends Service implements TorServiceConstants, Runnable
|
|||
|
||||
sendCallbackMessage("Web proxy shutdown");
|
||||
|
||||
killTorProcess ();
|
||||
try
|
||||
{
|
||||
killTorProcess ();
|
||||
|
||||
currentStatus = STATUS_READY;
|
||||
currentStatus = STATUS_READY;
|
||||
|
||||
|
||||
showToolbarNotification (getString(R.string.status_disabled),R.drawable.tornotificationoff);
|
||||
sendCallbackMessage(getString(R.string.status_disabled));
|
||||
showToolbarNotification (getString(R.string.status_disabled),R.drawable.tornotificationoff);
|
||||
sendCallbackMessage(getString(R.string.status_disabled));
|
||||
|
||||
setupTransProxy(false);
|
||||
setupTransProxy(false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.i(TAG, "An error occured stopping Tor",e);
|
||||
logNotice("An error occured stopping Tor: " + e.getMessage());
|
||||
sendCallbackMessage("Something bad happened. Check the log");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -257,7 +264,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
|
|||
}
|
||||
}
|
||||
|
||||
private void killTorProcess ()
|
||||
private void killTorProcess () throws Exception
|
||||
{
|
||||
|
||||
if (conn != null)
|
||||
|
@ -318,6 +325,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
|
|||
|
||||
String APK_EXT = ".apk";
|
||||
|
||||
int MAX_TRIES = 10;
|
||||
|
||||
String buildPath = apkBase + TOR_APP_USERNAME + APK_EXT;
|
||||
Log.i(TAG, "Checking APK location: " + buildPath);
|
||||
|
@ -327,7 +335,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
|
|||
if (fileApk.exists())
|
||||
return fileApk.getAbsolutePath();
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
for (int i = 0; i < MAX_TRIES; i++)
|
||||
{
|
||||
buildPath = apkBase + TOR_APP_USERNAME + '-' + i + APK_EXT;
|
||||
fileApk = new File(buildPath);
|
||||
|
@ -338,10 +346,33 @@ public class TorService extends Service implements TorServiceConstants, Runnable
|
|||
return fileApk.getAbsolutePath();
|
||||
}
|
||||
|
||||
String apkBaseExt = "/mnt/asec/" + TOR_APP_USERNAME;
|
||||
String pkgFile = "/pkg.apk";
|
||||
|
||||
buildPath = apkBaseExt + pkgFile;
|
||||
fileApk = new File(buildPath);
|
||||
|
||||
Log.i(TAG, "Checking external storage APK location: " + buildPath);
|
||||
|
||||
if (fileApk.exists())
|
||||
return fileApk.getAbsolutePath();
|
||||
|
||||
for (int i = 0; i < MAX_TRIES; i++)
|
||||
{
|
||||
buildPath = apkBaseExt + '-' + i + pkgFile;
|
||||
fileApk = new File(buildPath);
|
||||
|
||||
Log.i(TAG, "Checking external storage APK location: " + buildPath);
|
||||
|
||||
if (fileApk.exists())
|
||||
return fileApk.getAbsolutePath();
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean checkTorBinaries ()
|
||||
private boolean checkTorBinaries () throws Exception
|
||||
{
|
||||
//android.os.Debug.waitForDebugger();
|
||||
|
||||
|
@ -366,8 +397,8 @@ public class TorService extends Service implements TorServiceConstants, Runnable
|
|||
return false;
|
||||
}
|
||||
|
||||
torBinaryPath = appHome + '/' + TOR_BINARY_ASSET_KEY;
|
||||
privoxyPath = appHome + '/' + PRIVOXY_ASSET_KEY;
|
||||
torBinaryPath = appHome + TOR_BINARY_ASSET_KEY;
|
||||
privoxyPath = appHome + PRIVOXY_ASSET_KEY;
|
||||
|
||||
boolean torBinaryExists = new File(torBinaryPath).exists();
|
||||
boolean privoxyBinaryExists = new File(privoxyPath).exists();
|
||||
|
@ -401,15 +432,22 @@ public class TorService extends Service implements TorServiceConstants, Runnable
|
|||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
logNotice("Found Tor binary: " + torBinaryPath);
|
||||
|
||||
logNotice("Found prvoxy binary: " + privoxyPath);
|
||||
|
||||
}
|
||||
|
||||
StringBuilder log = new StringBuilder ();
|
||||
|
||||
logNotice("Setting permission on Tor binary");
|
||||
logNotice("(re)Setting permission on Tor binary");
|
||||
String[] cmd1 = {SHELL_CMD_CHMOD + ' ' + CHMOD_EXE_VALUE + ' ' + torBinaryPath};
|
||||
TorServiceUtils.doShellCommand(cmd1, log, false, true);
|
||||
|
||||
logNotice("Setting permission on Privoxy binary");
|
||||
logNotice("(re)Setting permission on Privoxy binary");
|
||||
String[] cmd2 = {SHELL_CMD_CHMOD + ' ' + CHMOD_EXE_VALUE + ' ' + privoxyPath};
|
||||
TorServiceUtils.doShellCommand(cmd2, log, false, true);
|
||||
|
||||
|
@ -525,6 +563,9 @@ public class TorService extends Service implements TorServiceConstants, Runnable
|
|||
|
||||
private void runPrivoxyShellCmd () throws Exception
|
||||
{
|
||||
|
||||
Log.i(TAG,"Starting privoxy process");
|
||||
|
||||
int privoxyProcId = TorServiceUtils.findProcessId(privoxyPath);
|
||||
|
||||
StringBuilder log = null;
|
||||
|
@ -538,9 +579,9 @@ public class TorService extends Service implements TorServiceConstants, Runnable
|
|||
String privoxyConfigPath = appHome + PRIVOXYCONFIG_ASSET_KEY;
|
||||
|
||||
String[] cmds =
|
||||
{ privoxyPath + " " + privoxyConfigPath };
|
||||
{ privoxyPath + " " + privoxyConfigPath + " &" };
|
||||
|
||||
logNotice (cmds[0]);
|
||||
logNotice (cmds[0]);
|
||||
|
||||
TorServiceUtils.doShellCommand(cmds, log, false, true);
|
||||
|
||||
|
@ -845,13 +886,19 @@ public class TorService extends Service implements TorServiceConstants, Runnable
|
|||
|
||||
if (appHome == null)
|
||||
{
|
||||
checkTorBinaries();
|
||||
try
|
||||
{
|
||||
checkTorBinaries();
|
||||
|
||||
findExistingProc ();
|
||||
findExistingProc ();
|
||||
|
||||
_torInstance = this;
|
||||
|
||||
hasRoot = TorServiceUtils.hasRoot();
|
||||
_torInstance = this;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.i(TAG,"Unable to check for Tor binaries",e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (ITorService.class.getName().equals(intent.getAction())) {
|
||||
|
@ -1037,15 +1084,27 @@ public class TorService extends Service implements TorServiceConstants, Runnable
|
|||
|
||||
logNotice ("Transparent Proxying: " + enableTransparentProxy);
|
||||
|
||||
boolean hasRoot = TorTransProxy.hasRootAccess();
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
|
||||
|
||||
|
||||
if (hasRoot && enableTransparentProxy)
|
||||
{
|
||||
|
||||
TorTransProxy.setDNSProxying();
|
||||
TorTransProxy.setTransparentProxyingByApp(this,AppManager.getApps(this),transProxyAll);
|
||||
try
|
||||
{
|
||||
TorTransProxy.setDNSProxying();
|
||||
boolean success = TorTransProxy.setTransparentProxyingByApp(this,AppManager.getApps(this),transProxyAll);
|
||||
|
||||
logNotice ("TorTransProxy enabled: " + success);
|
||||
|
||||
} catch (Exception e) {
|
||||
logNotice("WARNING: Error configuring transparenty proxying: " + e.getMessage());
|
||||
|
||||
Log.w(TAG, "error refreshing iptables: err=" + e.getMessage(), e);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
|
|
|
@ -123,26 +123,16 @@ public class TorServiceUtils implements TorServiceConstants {
|
|||
}
|
||||
|
||||
|
||||
public static boolean hasRoot ()
|
||||
public static int doShellCommand(String[] cmds, StringBuilder log, boolean runAsRoot, boolean waitFor) throws Exception
|
||||
{
|
||||
String[] cmds = {"exit 0"};
|
||||
|
||||
int code = doShellCommand(cmds,null,true, true);
|
||||
|
||||
return (code == 0);
|
||||
}
|
||||
|
||||
public static int doShellCommand(String[] cmds, StringBuilder log, boolean isRoot, boolean waitFor)
|
||||
{
|
||||
Log.i(TAG,"executing shell cmds: " + cmds[0] + "; isRoot=" + isRoot);
|
||||
Log.i(TAG,"executing shell cmds: " + cmds[0] + "; runAsRoot=" + runAsRoot);
|
||||
|
||||
|
||||
Process proc = null;
|
||||
int exitCode = -1;
|
||||
|
||||
try {
|
||||
|
||||
if (isRoot)
|
||||
if (runAsRoot)
|
||||
proc = Runtime.getRuntime().exec("su");
|
||||
else
|
||||
proc = Runtime.getRuntime().exec("sh");
|
||||
|
@ -163,10 +153,7 @@ public class TorServiceUtils implements TorServiceConstants {
|
|||
if (waitFor)
|
||||
{
|
||||
|
||||
exitCode = proc.waitFor();
|
||||
log.append("process exit code: ");
|
||||
log.append(exitCode);
|
||||
log.append("\n");
|
||||
|
||||
|
||||
final char buf[] = new char[10];
|
||||
|
||||
|
@ -183,12 +170,15 @@ public class TorServiceUtils implements TorServiceConstants {
|
|||
while ((read=reader.read(buf)) != -1) {
|
||||
if (log != null) log.append(buf, 0, read);
|
||||
}
|
||||
|
||||
exitCode = proc.waitFor();
|
||||
log.append("process exit code: ");
|
||||
log.append(exitCode);
|
||||
log.append("\n");
|
||||
|
||||
Log.i(TAG,"command process exit value: " + exitCode);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Error executing shell cmd: " + e.getMessage());
|
||||
}
|
||||
|
||||
|
||||
return exitCode;
|
||||
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
package org.torproject.android.service;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.torproject.android.TorifiedApp;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.util.Log;
|
||||
|
||||
public class TorTransProxy {
|
||||
|
@ -23,29 +18,35 @@ public class TorTransProxy {
|
|||
private final static String IPTABLES_ADD = " -A ";
|
||||
|
||||
//private final static String IPTABLES_DELETE = " -D "; //not deleting manually anymore - just calling a system wide flush of iptables rules
|
||||
private final static String IPTABLES_DROP_ALL = " -j DROP ";
|
||||
private static boolean hasRoot = false;
|
||||
// private final static String IPTABLES_DROP_ALL = " -j DROP ";
|
||||
|
||||
/**
|
||||
* Check if we have root access
|
||||
* @return boolean true if we have root
|
||||
*/
|
||||
public static boolean hasRootAccess() {
|
||||
if (hasRoot) return true;
|
||||
|
||||
|
||||
StringBuilder log = new StringBuilder();
|
||||
|
||||
try {
|
||||
|
||||
// Run an empty script just to check root access
|
||||
String[] cmd = {"exit 0"};
|
||||
if (TorServiceUtils.doShellCommand(cmd, null, true, true) == 0) {
|
||||
hasRoot = true;
|
||||
String[] cmd = {"whoami"};
|
||||
int exitCode = TorServiceUtils.doShellCommand(cmd, log, true, true);
|
||||
if (exitCode == 0) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG,"Error checking for root access: " + e.getMessage() ,e);
|
||||
}
|
||||
Log.w(TAG, "Could not acquire root access.");
|
||||
Log.w(TAG, "Could not acquire root access: " + log.toString());
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int setDNSProxying ()
|
||||
public static int setDNSProxying () throws Exception
|
||||
{
|
||||
|
||||
final StringBuilder log = new StringBuilder();
|
||||
|
@ -93,7 +94,8 @@ public class TorTransProxy {
|
|||
}
|
||||
}
|
||||
|
||||
public static boolean setTransparentProxyingByApp(Context context, TorifiedApp[] apps, boolean forceAll) {
|
||||
public static boolean setTransparentProxyingByApp(Context context, TorifiedApp[] apps, boolean forceAll) throws Exception
|
||||
{
|
||||
|
||||
String command = null;
|
||||
|
||||
|
@ -104,9 +106,6 @@ public class TorTransProxy {
|
|||
StringBuilder res = new StringBuilder();
|
||||
int code = -1;
|
||||
|
||||
try {
|
||||
|
||||
|
||||
for (int i = 0; i < apps.length; i++)
|
||||
{
|
||||
if (forceAll || apps[i].isTorified())
|
||||
|
@ -147,9 +146,7 @@ public class TorTransProxy {
|
|||
String msg = res.toString();
|
||||
Log.e(TAG, msg);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "error refreshing iptables: err=" + code + "; resp=" + res.toString(), e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|