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,18 +578,9 @@ 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); | ||||
| 			} | ||||
| 				 | ||||
| 			String bridgeDelim = "\n"; | ||||
| 			 | ||||
| 			if (bridgeList.indexOf(",") != -1) | ||||
|  | @ -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; | ||||
|  | @ -62,8 +61,6 @@ public class TorService extends Service implements TorServiceConstants, Runnable | |||
|     	Log.i(TAG,"TorService: onCreate"); | ||||
| 
 | ||||
|        | ||||
| 
 | ||||
|        | ||||
|     } | ||||
|      | ||||
|      | ||||
|  | @ -223,6 +220,8 @@ public class TorService extends Service implements TorServiceConstants, Runnable | |||
|     		 | ||||
|     	sendCallbackMessage("Web proxy shutdown"); | ||||
|     	 | ||||
|     	try | ||||
|     	{	 | ||||
|     		killTorProcess (); | ||||
| 				 | ||||
|     		currentStatus = STATUS_READY; | ||||
|  | @ -233,6 +232,14 @@ public class TorService extends Service implements TorServiceConstants, Runnable | |||
| 
 | ||||
|     		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,7 +579,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable | |||
|     			String privoxyConfigPath = appHome + PRIVOXYCONFIG_ASSET_KEY; | ||||
|     			 | ||||
|     			String[] cmds =  | ||||
|     			{ privoxyPath + " " + privoxyConfigPath }; | ||||
|     			{ privoxyPath + " " + privoxyConfigPath + " &" }; | ||||
|     			 | ||||
|     			logNotice (cmds[0]);  | ||||
|     			 | ||||
|  | @ -844,14 +885,20 @@ public class TorService extends Service implements TorServiceConstants, Runnable | |||
|         // the Intent. | ||||
|          | ||||
|     	if (appHome == null) | ||||
|     	{ | ||||
|     		try | ||||
|     		{ | ||||
|     			checkTorBinaries(); | ||||
|         	 | ||||
|     			findExistingProc (); | ||||
|         	 | ||||
|     			_torInstance = this; | ||||
| 
 | ||||
|         	hasRoot = TorServiceUtils.hasRoot(); | ||||
|     		} | ||||
|     		catch (Exception e) | ||||
|     		{ | ||||
|     			Log.i(TAG,"Unable to check for Tor binaries",e); | ||||
|     			return null; | ||||
|     		} | ||||
|     	} | ||||
|     	 | ||||
|     	if (ITorService.class.getName().equals(intent.getAction())) { | ||||
|  | @ -1037,6 +1084,8 @@ public class TorService extends Service implements TorServiceConstants, Runnable | |||
| 	 | ||||
|     	logNotice ("Transparent Proxying: " + enableTransparentProxy); | ||||
|     	 | ||||
|     	boolean hasRoot = TorTransProxy.hasRootAccess(); | ||||
| 
 | ||||
| 		if (enabled) | ||||
| 		{ | ||||
| 		 | ||||
|  | @ -1044,8 +1093,18 @@ public class TorService extends Service implements TorServiceConstants, Runnable | |||
| 			if (hasRoot && enableTransparentProxy) | ||||
| 			{ | ||||
| 				 | ||||
| 				try | ||||
| 				{ | ||||
| 					TorTransProxy.setDNSProxying(); | ||||
| 				TorTransProxy.setTransparentProxyingByApp(this,AppManager.getApps(this),transProxyAll); | ||||
| 					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; | ||||
|     }	 | ||||
| 	 | ||||
|  |  | |||