package im.ricochet.androidod; import android.content.Intent; import android.content.SharedPreferences; import android.os.AsyncTask; import android.os.StrictMode; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ProgressBar; import android.widget.TextView; import goRicochetMobile.GoRicochetMobile; import od.Od; public class ConnectActivity extends AppCompatActivity { private static final int ONION_ADDRESS_LENGTH = 16; public static final String PREFERNCE_FILE = "im.ricochet.PREFERENCE_FILE"; private static final String TAG = "InitActivity"; private static final String PRIVATE_KEY_KEY = "privateKey"; private static final String CONNECT_TO_ADDRESS_KEY = "connectToAddress"; private static final String RICOCHET_ADDRESS_PREFIX = "ricochet:"; Button regenButton; Button connectButton; ProgressBar connectSpinner; ProgressBar regenIdentSpinner; TextView connectStatusText; TextView regenIdentStatusText; TextView idetityText; EditText addressText; SharedPreferences prefs; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(im.ricochet.androidod.R.layout.activity_connect); connectStatusText = (TextView)findViewById(R.id.connectStatusTextView); regenIdentStatusText = (TextView)findViewById(R.id.regenIdentStatusText); idetityText = (TextView)findViewById(R.id.identityTextView); regenButton = (Button)findViewById(R.id.regenIdentButton); connectButton = (Button)findViewById(R.id.connectButton); connectSpinner = (ProgressBar)findViewById(R.id.connectProgressBar); regenIdentSpinner = (ProgressBar)findViewById(R.id.regenIdentProgressBar); addressText = (EditText)findViewById(R.id.addressText); prefs = getSharedPreferences(PREFERNCE_FILE, MODE_PRIVATE); regenButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { RegenIdentTask regenIdentTask = new RegenIdentTask(); regenIdentTask.execute(); } }); connectButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { ConnectTask connectTask = new ConnectTask(); String connectToAddr = addressText.getText().toString().replaceFirst(RICOCHET_ADDRESS_PREFIX, ""); String privateKey = prefs.getString(PRIVATE_KEY_KEY, ""); connectTask.execute(privateKey, connectToAddr); } }); addressText.addTextChangedListener(new TextWatcher(){ @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { validateOnionAddress(); } @Override public void afterTextChanged(Editable s) { } }); String privateKey = prefs.getString(PRIVATE_KEY_KEY, ""); Log.i(TAG, "Private key loaded:\n"+privateKey); if (privateKey.equals("")) { Log.i(TAG, "Generating pricate key"); RegenIdentTask regenIdentTask = new RegenIdentTask(); regenIdentTask.execute(); } else { Log.i(TAG, "Setting identity, Enabling regen"); setIdentity(privateKey); Button regenButton = (Button)findViewById(R.id.regenIdentButton); regenButton.setEnabled(true); } String connectToAddress = prefs.getString(CONNECT_TO_ADDRESS_KEY, RICOCHET_ADDRESS_PREFIX); addressText.setText(connectToAddress); validateOnionAddress(); } private class ConnectTask extends AsyncTask { @Override protected void onPreExecute() { Log.i(TAG, "ConnectTask.onPreExecute()"); regenButton.setEnabled(false); connectButton.setEnabled(false); connectStatusText.setText("Connecting to Onion server..."); connectSpinner.setVisibility(View.VISIBLE); } @Override // execute(privateKey, connectToAddr) // return string of exception if failed public String doInBackground(String... params) { Log.i(TAG, "ConntectTask.doInBackground()"); String privateKey = params[0]; String connectToAddr = params[1].replaceFirst(RICOCHET_ADDRESS_PREFIX, ""); try { Od.odClientConnect(privateKey, connectToAddr); return ""; } catch (Exception e) { Log.e(TAG, e.toString()); return e.toString(); } } @Override protected void onPostExecute(String exception) { Log.i(TAG, "ConnectTask.onPostExecute(): " ); connectSpinner.setVisibility(View.INVISIBLE); if (exception != "") { connectStatusText.setText("ERROR connecting: " + exception); connectButton.setEnabled(true); regenButton.setEnabled(true); } else { connectStatusText.setText("Connected!"); Intent i = new Intent(getApplicationContext(), RemoteActivity.class); // i,putExtra("key", "val") startActivity(i); } } } private void setIdentity(String privateKey) { Log.i(TAG, "setIdentity()"); String addr = GoRicochetMobile.getOnionAddress(privateKey); Log.i(TAG, "setIdentity(): addr: '" + addr + "'"); idetityText.setText("ricochet:" + addr); } private void validateOnionAddress() { String address = addressText.getText().toString(); if (address.startsWith(RICOCHET_ADDRESS_PREFIX) && address.length() == ONION_ADDRESS_LENGTH + RICOCHET_ADDRESS_PREFIX.length()) { SharedPreferences.Editor prefsEditor = prefs.edit(); prefsEditor.putString(CONNECT_TO_ADDRESS_KEY, address); prefsEditor.commit(); connectButton.setEnabled(true); } else { connectButton.setEnabled(false); } } private class RegenIdentTask extends AsyncTask { @Override protected void onPreExecute() { Log.i(TAG, "RegenIdentTask.onPreExecute()"); regenButton.setEnabled(false); connectButton.setEnabled(false); regenIdentStatusText.setText("Generating new identity..."); regenIdentSpinner.setVisibility(View.VISIBLE); } @Override public String doInBackground(Void... voids) { Log.i(TAG, "RegenIdentTask.doInBackground()"); String privateKey; try { privateKey = GoRicochetMobile.generatePrivateKey(); SharedPreferences.Editor prefsEditor = prefs.edit(); prefsEditor.putString(PRIVATE_KEY_KEY, privateKey); prefsEditor.commit(); return privateKey; } catch (Exception e) { Log.e(TAG, e.toString()); return null; } } @Override protected void onPostExecute(String privateKey) { Log.i(TAG, "RegenIdentTask.onPostExecute(): " + privateKey); regenIdentSpinner.setVisibility(View.INVISIBLE); regenButton.setEnabled(true); validateOnionAddress(); if (privateKey == null) { regenIdentStatusText.setText("ERROR: unable to generate new identity"); } else { regenIdentStatusText.setText(""); setIdentity(privateKey); } } } /********** TESTING by standing up an echobot ************/ private void echoBot(String privateKey) { // Test echobot Log.i(TAG, "Setting thread policy perms"); StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); Log.i(TAG, "Starting Echo Bot"); new EchoBot(privateKey).execute(); } private class EchoBot extends AsyncTask { String privateKey; public EchoBot(String privateKey) { this.privateKey = privateKey; } @Override public Void doInBackground(Void... voids) { GoRicochetMobile.echoBot(privateKey); return null; } } }