879 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			879 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* 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.StringTokenizer;
 | ||
| 
 | ||
| import org.torproject.android.service.ITorService;
 | ||
| import org.torproject.android.service.ITorServiceCallback;
 | ||
| import org.torproject.android.service.TorServiceUtils;
 | ||
| import org.torproject.android.service.TorTransProxy;
 | ||
| import org.torproject.android.service.TorServiceConstants;
 | ||
| 
 | ||
| import android.app.Activity;
 | ||
| import android.app.AlertDialog;
 | ||
| import android.app.ProgressDialog;
 | ||
| import android.content.ComponentName;
 | ||
| import android.content.Context;
 | ||
| import android.content.DialogInterface;
 | ||
| import android.content.Intent;
 | ||
| import android.content.ServiceConnection;
 | ||
| import android.content.SharedPreferences;
 | ||
| import android.net.Uri;
 | ||
| import android.os.Bundle;
 | ||
| import android.os.Handler;
 | ||
| import android.os.IBinder;
 | ||
| import android.os.Message;
 | ||
| import android.os.RemoteException;
 | ||
| import android.preference.PreferenceManager;
 | ||
| import android.util.Log;
 | ||
| import android.view.KeyEvent;
 | ||
| import android.view.LayoutInflater;
 | ||
| import android.view.Menu;
 | ||
| import android.view.MenuItem;
 | ||
| import android.view.View;
 | ||
| import android.view.ViewGroup;
 | ||
| import android.view.View.OnClickListener;
 | ||
| import android.widget.ArrayAdapter;
 | ||
| import android.widget.CheckBox;
 | ||
| import android.widget.CompoundButton;
 | ||
| import android.widget.ImageView;
 | ||
| import android.widget.ListAdapter;
 | ||
| import android.widget.ListView;
 | ||
| import android.widget.TextView;
 | ||
| import android.widget.Toast;
 | ||
| import android.widget.CompoundButton.OnCheckedChangeListener;
 | ||
| 
 | ||
| public class Orbot extends Activity implements OnClickListener, TorConstants, OnCheckedChangeListener
 | ||
| {
 | ||
| 	
 | ||
| 	/* Useful UI bits */
 | ||
| 	private TextView txtMessageLog = null; //the full screen log view of Tor control messages
 | ||
| 	private TextView lblStatus = null; //the main text display widget
 | ||
| 	private ImageView imgStatus = null; //the main touchable image for activating Orbot
 | ||
| 	private ProgressDialog progressDialog;
 | ||
| 	private ListView listApps;
 | ||
| 	private boolean showingSettings = false;
 | ||
| 	
 | ||
| 	/* Some tracking bits */
 | ||
| 	private int torStatus = STATUS_READY; //latest status reported from the tor service
 | ||
| 	private int currentView = 0; //the currently displayed UI view
 | ||
| 	private StringBuffer logBuffer = new StringBuffer(); //the output of the service log messages
 | ||
| 	
 | ||
| 	/* Tor Service interaction */
 | ||
| 		/* The primary interface we will be calling on the service. */
 | ||
|     ITorService mService = null;
 | ||
| 	
 | ||
|     /** Called when the activity is first created. */
 | ||
|     @Override
 | ||
|     public void onCreate(Bundle savedInstanceState) {
 | ||
|         super.onCreate(savedInstanceState);
 | ||
| 
 | ||
|     	setTheme(android.R.style.Theme_Black_NoTitleBar);
 | ||
|     	//setTitle(getString(R.string.app_name) + ' ' + getString(R.string.app_version));
 | ||
|         showMain();
 | ||
| 
 | ||
|     }
 | ||
|     
 | ||
|    /*
 | ||
|     * Create the UI Options Menu (non-Javadoc)
 | ||
|     * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
 | ||
|     */
 | ||
|     public boolean onCreateOptionsMenu(Menu menu) {
 | ||
|         super.onCreateOptionsMenu(menu);
 | ||
|         
 | ||
|         MenuItem mItem = null;
 | ||
|         
 | ||
|         /*
 | ||
|         
 | ||
|         mItem = menu.add(0, 1, Menu.NONE, getString(R.string.menu_home));
 | ||
|         mItem.setIcon(R.drawable.ic_menu_home);
 | ||
| 
 | ||
|         mItem = menu.add(0, 2, Menu.NONE, getString(R.string.menu_browse));
 | ||
|         mItem.setIcon(R.drawable.ic_menu_goto);
 | ||
|         */
 | ||
| 
 | ||
|         
 | ||
|         mItem = menu.add(0, 4, Menu.NONE, getString(R.string.menu_settings));
 | ||
|         mItem.setIcon(R.drawable.ic_menu_register);
 | ||
|        
 | ||
|        
 | ||
|     	mItem = menu.add(0, 5, Menu.NONE, getString(R.string.menu_apps));
 | ||
|     	mItem.setIcon(R.drawable.ic_menu_goto);
 | ||
|     	
 | ||
|     	 if (!TorServiceUtils.hasRoot())
 | ||
|          {
 | ||
|     		 mItem.setEnabled(false);
 | ||
|     		 
 | ||
|          }
 | ||
|         	
 | ||
|         mItem =  menu.add(0,6, Menu.NONE, getString(R.string.menu_log));
 | ||
|         mItem.setIcon(R.drawable.ic_menu_reports);
 | ||
|         
 | ||
|         mItem = menu.add(0, 3, Menu.NONE, getString(R.string.menu_info));
 | ||
|         mItem.setIcon(R.drawable.ic_menu_about);
 | ||
|        
 | ||
| 
 | ||
|       
 | ||
|         return true;
 | ||
|     }
 | ||
|     
 | ||
|     /* When a menu item is selected launch the appropriate view or activity
 | ||
|      * (non-Javadoc)
 | ||
| 	 * @see android.app.Activity#onMenuItemSelected(int, android.view.MenuItem)
 | ||
| 	 */
 | ||
| 	@Override
 | ||
| 	public boolean onMenuItemSelected(int featureId, MenuItem item) {
 | ||
| 		
 | ||
| 		super.onMenuItemSelected(featureId, item);
 | ||
| 		
 | ||
| 		if (item.getItemId() == 1)
 | ||
| 		{
 | ||
| 			this.showMain();
 | ||
| 		}
 | ||
| 		else if (item.getItemId() == 4)
 | ||
| 		{
 | ||
| 			this.showSettings();
 | ||
| 		}
 | ||
| 		else if (item.getItemId() == 6)
 | ||
| 		{
 | ||
| 			this.showMessageLog();
 | ||
| 		}
 | ||
| 		else if (item.getItemId() == 2)
 | ||
| 		{
 | ||
| 			openBrowser(URL_TOR_CHECK);
 | ||
| 		}
 | ||
| 		else if (item.getItemId() == 3)
 | ||
| 		{
 | ||
| 			showHelp();
 | ||
| 		}
 | ||
| 		else if (item.getItemId() == 5)
 | ||
| 		{
 | ||
| 			showApps();
 | ||
| 		}
 | ||
| 		
 | ||
|         return true;
 | ||
| 	}
 | ||
| 	
 | ||
| 	/* Return to the main view when the back key is pressed
 | ||
| 	 * (non-Javadoc)
 | ||
| 	 * @see android.app.Activity#onKeyDown(int, android.view.KeyEvent)
 | ||
| 	 */
 | ||
| 	public boolean onKeyDown(int keyCode, KeyEvent event){
 | ||
| 		
 | ||
| 		if(keyCode==KeyEvent.KEYCODE_BACK){
 | ||
| 
 | ||
| 			if(currentView != R.layout.layout_main){
 | ||
| 					
 | ||
| 					showMain ();
 | ||
| 					return true;
 | ||
| 			}
 | ||
| 			else{
 | ||
| 				return super.onKeyDown(keyCode, event);
 | ||
| 			}
 | ||
| 		}
 | ||
| 	
 | ||
| 		return super.onKeyDown(keyCode, event);
 | ||
| 		
 | ||
| 	}
 | ||
|  
 | ||
|     /* (non-Javadoc)
 | ||
| 	 * @see android.app.Activity#onPause()
 | ||
| 	 */
 | ||
| 	@Override
 | ||
| 	protected void onPause() {
 | ||
| 		super.onPause();
 | ||
| 		
 | ||
| 
 | ||
| 	}
 | ||
| 
 | ||
| 	/* (non-Javadoc)
 | ||
| 	 * @see android.app.Activity#onResume()
 | ||
| 	 */
 | ||
| 	@Override
 | ||
| 	protected void onResume() {
 | ||
| 		super.onResume();
 | ||
| 		
 | ||
| 		updateStatus (""); //update the status, which checks the service status
 | ||
| 		
 | ||
| 		if (showingSettings)
 | ||
| 		{
 | ||
| 			
 | ||
| 			showingSettings = false;
 | ||
| 			processSettings();
 | ||
| 		
 | ||
| 		}
 | ||
| 		
 | ||
| 		
 | ||
| 		
 | ||
| 	}
 | ||
| 
 | ||
| 	/* (non-Javadoc)
 | ||
| 	 * @see android.app.Activity#onStart()
 | ||
| 	 */
 | ||
| 	@Override
 | ||
| 	protected void onStart() {
 | ||
| 		super.onStart();
 | ||
| 		
 | ||
| 		//if Tor binary is not running, then start the service up
 | ||
| 		startService(new Intent(INTENT_TOR_SERVICE));
 | ||
| 		bindService ();
 | ||
| 		
 | ||
| 		updateStatus ("");
 | ||
| 		
 | ||
| 	}
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 	/* (non-Javadoc)
 | ||
| 	 * @see android.app.Activity#onStop()
 | ||
| 	 */
 | ||
| 	@Override
 | ||
| 	protected void onStop() {
 | ||
| 		super.onStop();
 | ||
| 		
 | ||
| 		TorServiceUtils.saveAppSettings(this);
 | ||
| 		
 | ||
| 		unbindService();
 | ||
| 	}
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 	/*
 | ||
| 	 * Show the main form UI
 | ||
| 	 */
 | ||
| 	private void showMain ()
 | ||
|     {
 | ||
| 		bindService(); //connect the UI activity to the remote service
 | ||
| 		
 | ||
| 		if (currentView == R.layout.layout_apps)
 | ||
| 		{
 | ||
| 			if (hasRoot)
 | ||
| 			{
 | ||
| 				
 | ||
| 				TorServiceUtils.saveAppSettings(this);
 | ||
| 				
 | ||
| 				if (enableTransparentProxy)
 | ||
| 				{
 | ||
| 					TorTransProxy.purgeNatIptables();
 | ||
| 					TorTransProxy.setDNSProxying();
 | ||
| 					TorTransProxy.setTransparentProxying(this, TorServiceUtils.getApps(this));
 | ||
| 				}
 | ||
| 				
 | ||
| 				
 | ||
| 			}
 | ||
| 		}
 | ||
| 		
 | ||
| 		currentView = R.layout.layout_main;
 | ||
| 		setContentView(currentView);
 | ||
| 		
 | ||
| 		//add touch listeners for the image and the text label
 | ||
|     	findViewById(R.id.imgStatus).setOnClickListener(this); 
 | ||
|     	findViewById(R.id.lblStatus).setOnClickListener(this);
 | ||
|     	
 | ||
|     	lblStatus = (TextView)findViewById(R.id.lblStatus);
 | ||
|     	imgStatus = (ImageView)findViewById(R.id.imgStatus);
 | ||
|     	
 | ||
|     	updateStatus("");
 | ||
|     }
 | ||
| 	
 | ||
| 	/*
 | ||
| 	 * Launch the system activity for Uri viewing with the provided url
 | ||
| 	 */
 | ||
| 	private void openBrowser(String url)
 | ||
| 	{
 | ||
| 		startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
 | ||
| 		
 | ||
| 	}
 | ||
| 	
 | ||
| 	private void loadApps ()
 | ||
| 	{
 | ||
|         final TorifiedApp[] apps = TorServiceUtils.getApps(this);
 | ||
|         
 | ||
|         Arrays.sort(apps, new Comparator<TorifiedApp>() {
 | ||
| 			@Override
 | ||
| 			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) {
 | ||
|         	@Override
 | ||
|         	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.box = (CheckBox) convertView.findViewById(R.id.itemcheck);
 | ||
|        				entry.text = (TextView) convertView.findViewById(R.id.itemtext);
 | ||
|        				convertView.setTag(entry);
 | ||
|        				entry.box.setOnCheckedChangeListener(Orbot.this);
 | ||
|         		} else {
 | ||
|         			// Convert an existing view
 | ||
|         			entry = (ListEntry) convertView.getTag();
 | ||
|         		}
 | ||
|         		final TorifiedApp app = apps[position];
 | ||
|         		entry.text.setText(app.getName());
 | ||
|         		final CheckBox box = entry.box;
 | ||
|         		box.setTag(app);
 | ||
|         		box.setChecked(app.isTorified());
 | ||
|        			return convertView;
 | ||
|         	}
 | ||
|         };
 | ||
|         this.listApps.setAdapter(adapter);
 | ||
| 		   
 | ||
| 	}
 | ||
| 	
 | ||
| 	/**
 | ||
| 	 * Called an application is check/unchecked
 | ||
| 	 */
 | ||
| 	@Override
 | ||
| 	public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
 | ||
| 		final TorifiedApp app = (TorifiedApp) buttonView.getTag();
 | ||
| 		if (app != null) {
 | ||
| 			app.setTorified(isChecked);
 | ||
| 		}
 | ||
| 		
 | ||
| 		TorServiceUtils.saveAppSettings(this);
 | ||
| 
 | ||
| 	}
 | ||
| 	
 | ||
| 	private static class ListEntry {
 | ||
| 		private CheckBox box;
 | ||
| 		private TextView text;
 | ||
| 	}
 | ||
| 	/*
 | ||
| 	 * Show the about view - a popup dialog
 | ||
| 	 */
 | ||
| 	private void showAbout ()
 | ||
| 	{
 | ||
| 		
 | ||
| 		LayoutInflater li = LayoutInflater.from(this);
 | ||
|         View view = li.inflate(R.layout.layout_about, null); 
 | ||
|         TextView versionName = (TextView)view.findViewById(R.id.versionName);
 | ||
|         versionName.setText(R.string.app_version);    
 | ||
|         
 | ||
| 		new AlertDialog.Builder(this)
 | ||
|         .setTitle(getString(R.string.menu_info))
 | ||
|         .setView(view)
 | ||
|         .setNeutralButton(getString(R.string.button_help), new DialogInterface.OnClickListener() {
 | ||
|                 public void onClick(DialogInterface dialog, int whichButton) {
 | ||
|                       showHelp();
 | ||
|                 }
 | ||
|         })
 | ||
|         .setNegativeButton(getString(R.string.button_close), new DialogInterface.OnClickListener() {
 | ||
|                 public void onClick(DialogInterface dialog, int whichButton) {
 | ||
|                     //    Log.d(TAG, "Close pressed");
 | ||
|                 }
 | ||
|         })
 | ||
|         .show();
 | ||
| 	}
 | ||
| 	
 | ||
| 	/*
 | ||
| 	 * Show the help view - a popup dialog
 | ||
| 	 */
 | ||
| 	private void showHelp ()
 | ||
| 	{
 | ||
| 		
 | ||
| 		LayoutInflater li = LayoutInflater.from(this);
 | ||
|         View view = li.inflate(R.layout.layout_help, null); 
 | ||
|         
 | ||
| 		new AlertDialog.Builder(this)
 | ||
|         .setTitle(getString(R.string.menu_info))
 | ||
|         .setView(view)
 | ||
|         .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 showApps ()
 | ||
| 	{
 | ||
| 		currentView = R.layout.layout_apps;
 | ||
| 		setContentView(currentView);
 | ||
| 	
 | ||
| 		listApps = (ListView)findViewById(R.id.applistview);
 | ||
| 		
 | ||
| 		loadApps();
 | ||
| 		
 | ||
| 	}
 | ||
| 	/*
 | ||
| 	 * Show the message log UI
 | ||
| 	 */
 | ||
| 	private void showMessageLog ()
 | ||
| 	{
 | ||
| 		currentView = R.layout.layout_log;
 | ||
| 		setContentView(currentView);
 | ||
| 		
 | ||
| 		txtMessageLog = (TextView)findViewById(R.id.messageLog);
 | ||
|     	txtMessageLog.setText(logBuffer.toString());
 | ||
| 		
 | ||
| 	}
 | ||
| 	
 | ||
| 		    
 | ||
|     
 | ||
| 	
 | ||
|     /*
 | ||
|      * Load the basic settings application to display torrc
 | ||
|      */
 | ||
| 	private void showSettings ()
 | ||
| 	{
 | ||
| 		
 | ||
| 		showingSettings = true;
 | ||
| 		startActivity(new Intent(this, SettingsPreferences.class));
 | ||
| 
 | ||
| 		
 | ||
| 	}
 | ||
| 	
 | ||
| 	/*
 | ||
| 	 * Read in the Preferences and write then to the .torrc file
 | ||
| 	 */
 | ||
| 
 | ||
| 	private void processSettings ()
 | ||
| 	{
 | ||
| 		StringBuffer torrcText = new StringBuffer();
 | ||
| 		
 | ||
| 		torrcText.append(TorConstants.TORRC_DEFAULT);
 | ||
| 		
 | ||
| 		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
 | ||
| 		
 | ||
| 		boolean useBridges = prefs.getBoolean(PREF_BRIDGES_ENABLED, false);
 | ||
| 		
 | ||
| 		boolean autoUpdateBridges = prefs.getBoolean(PREF_BRIDGES_UPDATED, false);
 | ||
| 
 | ||
|         boolean becomeRelay = prefs.getBoolean(PREF_OR, false);
 | ||
| 
 | ||
|         boolean fascistFirewall = prefs.getBoolean(PREF_FASCIST_FIREWALL,false);
 | ||
| 
 | ||
| 		enableTransparentProxy = prefs.getBoolean(PREF_TRANSPARENT, false);
 | ||
| 		
 | ||
| 		if (hasRoot)
 | ||
| 		{
 | ||
| 			if (enableTransparentProxy)
 | ||
| 			{
 | ||
| 				TorTransProxy.setDNSProxying();
 | ||
| 				TorTransProxy.setTransparentProxying(this, TorServiceUtils.getApps(this));
 | ||
| 			}
 | ||
| 			else
 | ||
| 			{
 | ||
| 				TorTransProxy.purgeNatIptables();
 | ||
| 			}
 | ||
| 			
 | ||
| 		}
 | ||
| 		String bridgeList = prefs.getString(PREF_BRIDGES_LIST,"");
 | ||
| 
 | ||
| 		if (useBridges)
 | ||
| 		{
 | ||
| 			torrcText.append("UseBridges 1");
 | ||
| 			torrcText.append('\n');		
 | ||
| 
 | ||
| 			torrcText.append("UpdateBridgesFromAuthority ");
 | ||
| 			
 | ||
| 			if (autoUpdateBridges)
 | ||
| 				torrcText.append("1");
 | ||
| 			else
 | ||
| 				torrcText.append("0");
 | ||
| 			
 | ||
| 			torrcText.append('\n');		
 | ||
| 			
 | ||
| 			String bridgeDelim = "\n";
 | ||
| 			
 | ||
| 			if (bridgeList.indexOf(",") != -1)
 | ||
| 			{
 | ||
| 				bridgeDelim = ",";
 | ||
| 			}
 | ||
| 			
 | ||
| 			StringTokenizer st = new StringTokenizer(bridgeList,bridgeDelim);
 | ||
| 			while (st.hasMoreTokens())
 | ||
| 			{
 | ||
| 				torrcText.append("bridge ");
 | ||
| 				torrcText.append(st.nextToken());
 | ||
| 				torrcText.append('\n');		
 | ||
| 
 | ||
| 			}
 | ||
| 		}
 | ||
| 		else
 | ||
| 		{
 | ||
| 			torrcText.append("UseBridges 0");
 | ||
| 		}
 | ||
| 
 | ||
|         try
 | ||
|         {
 | ||
|             if (fascistFirewall)
 | ||
|             {
 | ||
|                 String fascistFirewallPorts =
 | ||
|                     prefs.getString(PREF_FASCIST_FIREWALL_PORTS, "80,443");
 | ||
| 
 | ||
|                 torrcText.append("FascistFirewall 1");
 | ||
|                 torrcText.append('\n');
 | ||
|                 torrcText.append("FirewallPorts ");
 | ||
|                 // We should verify this and someday, the Exception will matter :-)
 | ||
|                 torrcText.append(fascistFirewallPorts);
 | ||
|                 torrcText.append('\n');
 | ||
|             }
 | ||
|         }
 | ||
|         catch (Exception e)
 | ||
|         {
 | ||
|             Toast.makeText(this, "Your FascistFirewall settings caused an exception!",
 | ||
|                            Toast.LENGTH_LONG).show();
 | ||
|         }
 | ||
| 
 | ||
|         try
 | ||
|         {
 | ||
|             if (becomeRelay && !useBridges && !fascistFirewall)
 | ||
|             {
 | ||
|                 int ORPort =  Integer.parseInt(prefs.getString(PREF_OR_PORT, "9001"));
 | ||
|                 String nickname = prefs.getString(PREF_OR_NICKNAME, "Orbot");
 | ||
| 
 | ||
|                 torrcText.append("ORPort ");
 | ||
|                 torrcText.append(ORPort);
 | ||
|                 torrcText.append('\n');
 | ||
| 
 | ||
|                 torrcText.append("Nickname ");
 | ||
|                 torrcText.append(nickname);
 | ||
|                 torrcText.append('\n');
 | ||
| 
 | ||
|                 torrcText.append("ExitPolicy reject *:*");
 | ||
|                 torrcText.append('\n');
 | ||
|             }
 | ||
|         }
 | ||
|         catch (Exception e)
 | ||
|         {
 | ||
|             Toast.makeText(this, "Your relay settings caused an exception!", Toast.LENGTH_LONG).show();
 | ||
|         }
 | ||
| 
 | ||
| 		Utils.saveTextFile(TorServiceConstants.TORRC_INSTALL_PATH, torrcText.toString());
 | ||
| 	}
 | ||
| 	
 | ||
| 	
 | ||
|     /*
 | ||
|      * Set the state of the running/not running graphic and label
 | ||
|      */
 | ||
|     public void updateStatus (String torServiceMsg)
 | ||
|     {
 | ||
|     	try
 | ||
|     	{
 | ||
|     		
 | ||
|     		if (mService != null)
 | ||
|     			torStatus = mService.getStatus();
 | ||
| 	    	
 | ||
| 
 | ||
| 	    	if (imgStatus != null)
 | ||
| 	    	{
 | ||
| 	    		
 | ||
| 		    	if (torStatus == STATUS_ON)
 | ||
| 		    	{
 | ||
| 		    		imgStatus.setImageResource(R.drawable.toron);
 | ||
| 		    	
 | ||
| 		    		lblStatus.setText(getString(R.string.status_activated));
 | ||
| 		    		
 | ||
| 		    		if (progressDialog != null)
 | ||
| 		    		{
 | ||
| 		    			
 | ||
| 		    			progressDialog.cancel();
 | ||
| 		    			progressDialog.hide();
 | ||
| 		    			progressDialog = null;
 | ||
| 		    		}
 | ||
| 		    		
 | ||
| 		    		if (torServiceMsg != null && torServiceMsg.length()>0)
 | ||
| 		    			Toast.makeText(this, torServiceMsg, Toast.LENGTH_LONG).show();
 | ||
| 		    		
 | ||
| 		    	
 | ||
| 		    	}
 | ||
| 		    	else if (torStatus == STATUS_CONNECTING)
 | ||
| 		    	{
 | ||
| 		    		
 | ||
| 		    		imgStatus.setImageResource(R.drawable.torstarting);
 | ||
| 		    		lblStatus.setText(getString(R.string.status_starting_up));
 | ||
| 		    		
 | ||
| 		    		if (progressDialog == null)
 | ||
| 		    		{
 | ||
| 			    		progressDialog = new ProgressDialog(this);
 | ||
| 			    		progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
 | ||
| 			    		progressDialog.setCancelable(true);
 | ||
| 			    		progressDialog.setMessage(getString(R.string.status_starting_up));
 | ||
| 			    		progressDialog.show();
 | ||
| 			    		
 | ||
| 			    		progressDialog.setProgress(10);
 | ||
| 
 | ||
| 		    		}
 | ||
| 		    			
 | ||
| 	    			progressDialog.setMessage(torServiceMsg);
 | ||
| 	    			
 | ||
| 	    			int idx = torServiceMsg.indexOf("%");
 | ||
| 	    			
 | ||
| 	    			if (idx != -1)
 | ||
| 	    			{	
 | ||
| 	    				String pComp = torServiceMsg.substring(idx-2,idx).trim();
 | ||
| 	    				int ipComp = Integer.parseInt(pComp);
 | ||
| 	    				progressDialog.setProgress(ipComp);
 | ||
| 	    			}
 | ||
| 		    			
 | ||
| 		    	}
 | ||
| 		    	else if (torStatus == STATUS_OFF)
 | ||
| 		    	{
 | ||
| 		    		imgStatus.setImageResource(R.drawable.torstopping);
 | ||
| 		    		lblStatus.setText(getString(R.string.status_shutting_down));
 | ||
| 		    		
 | ||
| 		    		if (torServiceMsg != null && torServiceMsg.length()>0)
 | ||
| 		    			Toast.makeText(this, torServiceMsg, Toast.LENGTH_LONG).show();
 | ||
| 		    		
 | ||
| 		    	
 | ||
| 		    		
 | ||
| 		    	}
 | ||
| 		    	else
 | ||
| 		    	{
 | ||
| 
 | ||
| 		    		if (torServiceMsg != null && torServiceMsg.length()>0)
 | ||
| 		    			Toast.makeText(this, torServiceMsg, Toast.LENGTH_LONG).show();
 | ||
| 		    		
 | ||
| 		    	
 | ||
| 		    		if (progressDialog != null)
 | ||
| 		    		{
 | ||
| 		    			
 | ||
| 		    			progressDialog.cancel();
 | ||
| 		    			progressDialog.hide();
 | ||
| 		    			progressDialog = null;
 | ||
| 		    		}
 | ||
| 		    		
 | ||
| 		    		
 | ||
| 		    		imgStatus.setImageResource(R.drawable.toroff);
 | ||
| 		    		lblStatus.setText(getString(R.string.status_disabled));
 | ||
| 		    		
 | ||
| 		    	}
 | ||
| 	    	}
 | ||
| 		    	
 | ||
|     	}
 | ||
|     	catch (RemoteException e)
 | ||
|     	{
 | ||
|     		e.printStackTrace();
 | ||
|     	}
 | ||
|     	
 | ||
|         
 | ||
|     }
 | ||
|   
 | ||
|     /*
 | ||
|      * (non-Javadoc)
 | ||
|      * @see android.view.View.OnClickListener#onClick(android.view.View)
 | ||
|      */
 | ||
| 	public void onClick(View view) {
 | ||
| 		
 | ||
| 		// the start button
 | ||
| 		if (view.getId()==R.id.imgStatus || view.getId()==R.id.lblStatus)
 | ||
| 		{
 | ||
| 			try
 | ||
| 			{
 | ||
| 				
 | ||
| 				if (mService == null)
 | ||
| 				{
 | ||
| 				
 | ||
| 				}
 | ||
| 				else if (mService.getStatus() == STATUS_READY)
 | ||
| 				{
 | ||
| 					
 | ||
| 					mService.setProfile(PROFILE_ON); //this means turn on
 | ||
| 					
 | ||
| 					imgStatus.setImageResource(R.drawable.torstarting);
 | ||
| 		    		lblStatus.setText(getString(R.string.status_starting_up));
 | ||
| 		    		
 | ||
| 					Message msg = mHandler.obtainMessage(ENABLE_TOR_MSG);
 | ||
| 		        	mHandler.sendMessage(msg);
 | ||
| 		        	
 | ||
| 		        	updateStatus("");
 | ||
| 					
 | ||
| 				}
 | ||
| 				else
 | ||
| 				{
 | ||
| 					
 | ||
| 					mService.setProfile(PROFILE_ONDEMAND);	//these means turn off
 | ||
| 					
 | ||
| 					Message msg = mHandler.obtainMessage(DISABLE_TOR_MSG);
 | ||
| 		        	mHandler.sendMessage(msg);
 | ||
| 		        	
 | ||
| 		        	updateStatus("");
 | ||
| 					
 | ||
| 				}
 | ||
| 				
 | ||
| 			}
 | ||
| 			catch (Exception e)
 | ||
| 			{
 | ||
| 				Log.i(TAG,"error onclick",e);
 | ||
| 			}
 | ||
| 			
 | ||
| 		}
 | ||
| 		
 | ||
| 		
 | ||
| 	}
 | ||
| 	
 | ||
| 	private void doTorSetup (boolean enabled)
 | ||
| 	{
 | ||
| 		if (enabled)
 | ||
| 		{
 | ||
| 			processSettings();
 | ||
| 			
 | ||
| 	
 | ||
| 			if (hasRoot && enableTransparentProxy)
 | ||
| 			{
 | ||
| 				
 | ||
| 				TorTransProxy.setDNSProxying();
 | ||
| 				TorTransProxy.setTransparentProxying(this,TorServiceUtils.getApps(this));
 | ||
| 			}
 | ||
| 		}
 | ||
| 		else
 | ||
| 		{
 | ||
| 			if (hasRoot && enableTransparentProxy)
 | ||
| 			{
 | ||
| 				TorTransProxy.purgeNatIptables();
 | ||
| 				//TorRoot.setDNSProxying(false);
 | ||
| 				//TorRoot.setTransparentProxying(this,false);
 | ||
| 			}
 | ||
| 		}
 | ||
| 	}
 | ||
| 	
 | ||
|     /**
 | ||
|      * This implementation is used to receive callbacks from the remote
 | ||
|      * service.
 | ||
|      */
 | ||
|     private ITorServiceCallback mCallback = new ITorServiceCallback.Stub() {
 | ||
|         /**
 | ||
|          * This is called by the remote service regularly to tell us about
 | ||
|          * new values.  Note that IPC calls are dispatched through a thread
 | ||
|          * pool running in each process, so the code executing here will
 | ||
|          * NOT be running in our main thread like most other things -- so,
 | ||
|          * to update the UI, we need to use a Handler to hop over there.
 | ||
|          */
 | ||
|         public void statusChanged(String value) {
 | ||
|            
 | ||
|         	Message msg = mHandler.obtainMessage(BUMP_MSG);
 | ||
|         	msg.getData().putString(HANDLER_TOR_MSG, value);
 | ||
|         	mHandler.sendMessage(msg);
 | ||
|         }
 | ||
|     };
 | ||
|     
 | ||
|     private static final int BUMP_MSG = 1;
 | ||
|     
 | ||
|     private static final int ENABLE_TOR_MSG = 2;
 | ||
|     private static final int DISABLE_TOR_MSG = 3;
 | ||
|     	
 | ||
|     private Handler mHandler = new Handler() {
 | ||
|         @Override public void handleMessage(Message msg) {
 | ||
|             switch (msg.what) {
 | ||
|                 case BUMP_MSG:
 | ||
| 
 | ||
|                 	String torServiceMsg = (String)msg.getData().getString(HANDLER_TOR_MSG);
 | ||
|                 	
 | ||
|                 	logBuffer.append(torServiceMsg);
 | ||
|                 	logBuffer.append('\n');
 | ||
|                 	
 | ||
|                 	updateStatus(torServiceMsg);
 | ||
|                 	
 | ||
|                     break;
 | ||
|                 case ENABLE_TOR_MSG:
 | ||
|                 	
 | ||
|                 	doTorSetup(true);
 | ||
|                 	break;
 | ||
|                 case DISABLE_TOR_MSG:
 | ||
|                 	
 | ||
|                 	doTorSetup(false);
 | ||
|                 	break;
 | ||
|                 		
 | ||
|                 default:
 | ||
|                     super.handleMessage(msg);
 | ||
|             }
 | ||
|         }
 | ||
|         
 | ||
|     };
 | ||
| 
 | ||
|     
 | ||
|     /**
 | ||
|      * Class for interacting with the main interface of the service.
 | ||
|      */
 | ||
|     private ServiceConnection mConnection = new ServiceConnection() {
 | ||
|         public void onServiceConnected(ComponentName className,
 | ||
|                 IBinder service) {
 | ||
|             // This is called when the connection with the service has been
 | ||
|             // established, giving us the service object we can use to
 | ||
|             // interact with the service.  We are communicating with our
 | ||
|             // service through an IDL interface, so get a client-side
 | ||
|             // representation of that from the raw service object.
 | ||
|             mService = ITorService.Stub.asInterface(service);
 | ||
|        
 | ||
|             updateStatus ("");
 | ||
|             
 | ||
|             // We want to monitor the service for as long as we are
 | ||
|             // connected to it.
 | ||
|             try {
 | ||
|                 mService.registerCallback(mCallback);
 | ||
|             } catch (RemoteException e) {
 | ||
|                 // In this case the service has crashed before we could even
 | ||
|                 // do anything with it; we can count on soon being
 | ||
|                 // disconnected (and then reconnected if it can be restarted)
 | ||
|                 // so there is no need to do anything here.
 | ||
|             }
 | ||
|             
 | ||
|           
 | ||
|         }
 | ||
| 
 | ||
|         public void onServiceDisconnected(ComponentName className) {
 | ||
|             // This is called when the connection with the service has been
 | ||
|             // unexpectedly disconnected -- that is, its process crashed.
 | ||
|             mService = null;
 | ||
|           
 | ||
|         }
 | ||
|     };
 | ||
|     
 | ||
|     boolean mIsBound = false;
 | ||
|     boolean hasRoot = false;
 | ||
|     boolean enableTransparentProxy = false;
 | ||
|     
 | ||
|     private void bindService ()
 | ||
|     {
 | ||
|     	 bindService(new Intent(ITorService.class.getName()),
 | ||
|                  mConnection, Context.BIND_AUTO_CREATE);
 | ||
|     	 
 | ||
|     	 mIsBound = true;
 | ||
|     
 | ||
|     	 hasRoot = TorTransProxy.hasRootAccess();
 | ||
| 
 | ||
|     	
 | ||
|     }
 | ||
|     
 | ||
|     private void unbindService ()
 | ||
|     {
 | ||
|     	if (mIsBound) {
 | ||
|             // If we have received the service, and hence registered with
 | ||
|             // it, then now is the time to unregister.
 | ||
|             if (mService != null) {
 | ||
|                 try {
 | ||
|                     mService.unregisterCallback(mCallback);
 | ||
|                 } catch (RemoteException e) {
 | ||
|                     // There is nothing special we need to do if the service
 | ||
|                     // has crashed.
 | ||
|                 }
 | ||
|             }
 | ||
|             
 | ||
|             // Detach our existing connection.
 | ||
|             unbindService(mConnection);
 | ||
|             mIsBound = false;
 | ||
|         }
 | ||
|     }
 | ||
| 	
 | ||
| }
 |