package info.blockchain.wallet.ui; import java.io.DataOutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.security.SecureRandom; import java.util.HashMap; import piuk.blockchain.android.Constants; import piuk.blockchain.android.MyRemoteWallet; import piuk.blockchain.android.MyWallet; import piuk.blockchain.android.WalletApplication; import piuk.blockchain.android.SuccessCallback; import piuk.blockchain.android.R; import piuk.blockchain.android.ui.dialogs.RequestForgotPasswordDialog; import piuk.blockchain.android.util.ConnectivityStatus; import piuk.blockchain.android.util.WalletUtils; import info.blockchain.api.ExchangeRates; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.preference.PreferenceManager; import android.provider.Settings; import android.app.Activity; import android.support.v4.app.FragmentActivity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.content.pm.ActivityInfo; import android.graphics.Color; import android.graphics.Typeface; import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.style.RelativeSizeSpan; import android.view.Menu; import android.view.MotionEvent; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.view.View.OnTouchListener; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import android.support.v4.content.LocalBroadcastManager; import org.apache.commons.io.IOUtils; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import org.spongycastle.util.encoders.Hex; public class PinEntryActivity extends FragmentActivity { String userEntered = ""; final int PIN_LENGTH = 4; boolean keyPadLockedFlag = false; Context context = null; TextView titleView = null; TextView pinBox0 = null; TextView pinBox1 = null; TextView pinBox2 = null; TextView pinBox3 = null; TextView[] pinBoxArray = null; TextView statusView = null; Button button0 = null; Button button1 = null; Button button2 = null; Button button3 = null; Button button4 = null; Button button5 = null; Button button6 = null; Button button7 = null; Button button8 = null; Button button9 = null; Button buttonForgot = null; Button buttonDeleteBack = null; private boolean validating = true; private boolean creating = false; private String userInput = null; private static final String WebROOT = "https://" + Constants.BLOCKCHAIN_DOMAIN + "/pin-store"; public static final int PBKDF2Iterations = 2000; public String strUri = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); context = this; userEntered = ""; requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); if(!DeviceUtil.getInstance(this).isSmallScreen()) { setContentView(R.layout.activity_pin_entry); } else { setContentView(R.layout.activity_pin_entry_small); } setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); String action = getIntent().getAction(); String scheme = getIntent().getScheme(); if(action != null && Intent.ACTION_VIEW.equals(action) && scheme.equals("bitcoin")) { strUri = getIntent().getData().toString(); } Bundle extras = getIntent().getExtras(); if(extras != null) { if(extras.getString("N") != null && extras.getString("N").equals("1")) { validating = false; creating = true; ((TextView)findViewById(R.id.titleBox)).setText(R.string.create_pin); Toast.makeText(this, R.string.create_pin, Toast.LENGTH_LONG).show(); } else if(extras.getString("N") != null && extras.getString("N").length() == 4) { validating = false; creating = true; userInput = extras.getString("N"); ((TextView)findViewById(R.id.titleBox)).setText(R.string.confirm_pin); Toast.makeText(this, R.string.confirm_pin, Toast.LENGTH_LONG).show(); } else if(extras.getString("S") != null && extras.getString("S").equals("1")) { validating = false; ((TextView)findViewById(R.id.titleBox)).setText(R.string.create_pin); Toast.makeText(this, R.string.create_pin, Toast.LENGTH_LONG).show(); } else if(extras.getString("S") != null && extras.getString("S").length() == 4) { validating = false; userInput = extras.getString("S"); ((TextView)findViewById(R.id.titleBox)).setText(R.string.confirm_pin); Toast.makeText(this, R.string.confirm_pin, Toast.LENGTH_LONG).show(); } else { validating = true; } } Typeface typeface = Typeface.createFromAsset(getAssets(), "Roboto-Regular.ttf"); buttonForgot = (Button) findViewById(R.id.buttonForgot); buttonForgot.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { requestPassword(); } }); buttonForgot.setTypeface(typeface); buttonDeleteBack = (Button) findViewById(R.id.buttonDeleteBack); buttonDeleteBack.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if(keyPadLockedFlag == true) { return; } if(userEntered.length() > 0) { for (int i = 0; i < pinBoxArray.length; i++) pinBoxArray[i].setText(""); userEntered = ""; } } }); titleView = (TextView)findViewById(R.id.titleBox); titleView.setTypeface(typeface); pinBox0 = (TextView)findViewById(R.id.pinBox0); pinBox1 = (TextView)findViewById(R.id.pinBox1); pinBox2 = (TextView)findViewById(R.id.pinBox2); pinBox3 = (TextView)findViewById(R.id.pinBox3); pinBoxArray = new TextView[PIN_LENGTH]; pinBoxArray[0] = pinBox0; pinBoxArray[1] = pinBox1; pinBoxArray[2] = pinBox2; pinBoxArray[3] = pinBox3; statusView = (TextView) findViewById(R.id.statusMessage); statusView.setTypeface(typeface); View.OnClickListener pinButtonHandler = new View.OnClickListener() { public void onClick(View v) { if(keyPadLockedFlag == true) { return; } Button pressedButton = (Button)v; if(userEntered.length() < PIN_LENGTH) { userEntered = userEntered + pressedButton.getText().toString().substring(0, 1); // Log.v("PinView", "User entered=" + userEntered); // Update pin boxes pinBoxArray[userEntered.length() - 1].setText("8"); if(userEntered.length() == PIN_LENGTH) { if(validating) { if(userEntered.equals("0000")) { Toast.makeText(PinEntryActivity.this, R.string.zero_pin, Toast.LENGTH_SHORT).show(); return; } validatePIN(userEntered); } else { if(userInput != null) { if(userInput.equals("0000")) { Toast.makeText(PinEntryActivity.this, R.string.zero_pin, Toast.LENGTH_SHORT).show(); Intent intent = new Intent(PinEntryActivity.this, PinEntryActivity.class); intent.putExtra("N", "1"); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); return; } if(userInput.equals(userEntered)) { new Thread(new Runnable(){ @Override public void run() { Looper.prepare(); final WalletApplication application = (WalletApplication) getApplication(); Editor edit = PreferenceManager.getDefaultSharedPreferences(PinEntryActivity.this).edit(); // // Save PIN // try { byte[] bytes = new byte[16]; SecureRandom random = new SecureRandom(); random.nextBytes(bytes); final String key = new String(Hex.encode(bytes), "UTF-8"); random.nextBytes(bytes); final String value = new String(Hex.encode(bytes), "UTF-8"); // final JSONObject response = piuk.blockchain.android.ui.PinEntryActivity.apiStoreKey(key, value, userInput); final JSONObject response = apiStoreKey(key, value, userInput); if (response.get("success") != null) { edit.putString("pin_kookup_key", key); edit.putString("encrypted_password", MyWallet.encrypt(application.getRemoteWallet().getTemporyPassword(), value, PBKDF2Iterations)); if (!edit.commit()) { throw new Exception("Error Saving Preferences"); } else { TimeOutUtil.getInstance().updatePin(); Toast.makeText(PinEntryActivity.this, "PIN saved", Toast.LENGTH_SHORT).show(); Intent intent = new Intent(PinEntryActivity.this, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } } else { Toast.makeText(application, response.toString(), Toast.LENGTH_LONG).show(); Toast.makeText(PinEntryActivity.this, "PIN saved", Toast.LENGTH_SHORT).show(); Intent intent = new Intent(PinEntryActivity.this, MainActivity.class); String navigateTo = getIntent().getStringExtra("navigateTo"); intent.putExtra("navigateTo", navigateTo); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } } catch (Exception e) { Toast.makeText(application, e.toString(), Toast.LENGTH_LONG).show(); e.printStackTrace(); } // // // Looper.loop(); } }).start(); } else { Toast.makeText(PinEntryActivity.this, "Start over", Toast.LENGTH_SHORT).show(); if(creating) { Intent intent = new Intent(PinEntryActivity.this, PinEntryActivity.class); intent.putExtra("N", "1"); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } else { Intent intent = new Intent(PinEntryActivity.this, PinEntryActivity.class); intent.putExtra("S", "1"); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } } } else { if(creating) { Intent intent = new Intent(PinEntryActivity.this, PinEntryActivity.class); intent.putExtra("N", userEntered); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } else { Intent intent = new Intent(PinEntryActivity.this, PinEntryActivity.class); intent.putExtra("S", userEntered); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } } } } } else { //Roll over pinBoxArray[0].setText(""); pinBoxArray[1].setText(""); pinBoxArray[2].setText(""); pinBoxArray[3].setText(""); userEntered = ""; statusView.setText(""); userEntered = userEntered + pressedButton.getText().toString().substring(0, 1); // Log.v("PinView", "User entered=" + userEntered); //Update pin boxes pinBoxArray[userEntered.length() - 1].setText("8"); if(userEntered.equals("0000")) { Toast.makeText(PinEntryActivity.this, R.string.zero_pin, Toast.LENGTH_SHORT).show(); return; } validatePIN(userEntered); } } }; button0 = (Button)findViewById(R.id.button0); button0.setTypeface(typeface); button0.setOnClickListener(pinButtonHandler); button1 = (Button)findViewById(R.id.button1); button1.setTypeface(typeface); button1.setOnClickListener(pinButtonHandler); SpannableStringBuilder cs = null; float sz = 0.6f; button2 = (Button)findViewById(R.id.button2); button2.setTypeface(typeface); button2.setOnClickListener(pinButtonHandler); cs = new SpannableStringBuilder("2 ABC"); cs.setSpan(new RelativeSizeSpan(sz), 2, cs.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); button2.setText(cs); button3 = (Button)findViewById(R.id.button3); button3.setTypeface(typeface); button3.setOnClickListener(pinButtonHandler); cs = new SpannableStringBuilder("3 DEF"); cs.setSpan(new RelativeSizeSpan(sz), 2, cs.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); button3.setText(cs); button4 = (Button)findViewById(R.id.button4); button4.setTypeface(typeface); button4.setOnClickListener(pinButtonHandler); cs = new SpannableStringBuilder("4 GHI"); cs.setSpan(new RelativeSizeSpan(sz), 2, cs.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); button4.setText(cs); button5 = (Button)findViewById(R.id.button5); button5.setTypeface(typeface); button5.setOnClickListener(pinButtonHandler); cs = new SpannableStringBuilder("5 JKL"); cs.setSpan(new RelativeSizeSpan(sz), 2, cs.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); button5.setText(cs); button6 = (Button)findViewById(R.id.button6); button6.setTypeface(typeface); button6.setOnClickListener(pinButtonHandler); cs = new SpannableStringBuilder("6 MNO"); cs.setSpan(new RelativeSizeSpan(sz), 2, cs.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); button6.setText(cs); button7 = (Button)findViewById(R.id.button7); button7.setTypeface(typeface); button7.setOnClickListener(pinButtonHandler); cs = new SpannableStringBuilder("7 PQRS"); cs.setSpan(new RelativeSizeSpan(sz), 2, cs.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); button7.setText(cs); button8 = (Button)findViewById(R.id.button8); button8.setTypeface(typeface); button8.setOnClickListener(pinButtonHandler); cs = new SpannableStringBuilder("8 TUV"); cs.setSpan(new RelativeSizeSpan(sz), 2, cs.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); button8.setText(cs); button9 = (Button)findViewById(R.id.button9); button9.setTypeface(typeface); button9.setOnClickListener(pinButtonHandler); cs = new SpannableStringBuilder("9 WXYZ"); cs.setSpan(new RelativeSizeSpan(sz), 2, cs.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); button9.setText(cs); buttonDeleteBack = (Button)findViewById(R.id.buttonDeleteBack); buttonDeleteBack.setTypeface(typeface); final int colorOff = 0xff333333; final int colorOn = 0xff1a87c6; button0.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case android.view.MotionEvent.ACTION_DOWN: case android.view.MotionEvent.ACTION_MOVE: button0.setBackgroundColor(colorOn); break; case android.view.MotionEvent.ACTION_UP: case android.view.MotionEvent.ACTION_CANCEL: button0.setBackgroundColor(colorOff); break; } return false; } }); button1.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case android.view.MotionEvent.ACTION_DOWN: case android.view.MotionEvent.ACTION_MOVE: button1.setBackgroundColor(colorOn); break; case android.view.MotionEvent.ACTION_UP: case android.view.MotionEvent.ACTION_CANCEL: button1.setBackgroundColor(colorOff); break; } return false; } }); button2.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case android.view.MotionEvent.ACTION_DOWN: case android.view.MotionEvent.ACTION_MOVE: button2.setBackgroundColor(colorOn); break; case android.view.MotionEvent.ACTION_UP: case android.view.MotionEvent.ACTION_CANCEL: button2.setBackgroundColor(colorOff); break; } return false; } }); button3.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case android.view.MotionEvent.ACTION_DOWN: case android.view.MotionEvent.ACTION_MOVE: button3.setBackgroundColor(colorOn); break; case android.view.MotionEvent.ACTION_UP: case android.view.MotionEvent.ACTION_CANCEL: button3.setBackgroundColor(colorOff); break; } return false; } }); button4.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case android.view.MotionEvent.ACTION_DOWN: case android.view.MotionEvent.ACTION_MOVE: button4.setBackgroundColor(colorOn); break; case android.view.MotionEvent.ACTION_UP: case android.view.MotionEvent.ACTION_CANCEL: button4.setBackgroundColor(colorOff); break; } return false; } }); button5.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case android.view.MotionEvent.ACTION_DOWN: case android.view.MotionEvent.ACTION_MOVE: button5.setBackgroundColor(colorOn); break; case android.view.MotionEvent.ACTION_UP: case android.view.MotionEvent.ACTION_CANCEL: button5.setBackgroundColor(colorOff); break; } return false; } }); button6.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case android.view.MotionEvent.ACTION_DOWN: case android.view.MotionEvent.ACTION_MOVE: button6.setBackgroundColor(colorOn); break; case android.view.MotionEvent.ACTION_UP: case android.view.MotionEvent.ACTION_CANCEL: button6.setBackgroundColor(colorOff); break; } return false; } }); button7.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case android.view.MotionEvent.ACTION_DOWN: case android.view.MotionEvent.ACTION_MOVE: button7.setBackgroundColor(colorOn); break; case android.view.MotionEvent.ACTION_UP: case android.view.MotionEvent.ACTION_CANCEL: button7.setBackgroundColor(colorOff); break; } return false; } }); button8.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case android.view.MotionEvent.ACTION_DOWN: case android.view.MotionEvent.ACTION_MOVE: button8.setBackgroundColor(colorOn); break; case android.view.MotionEvent.ACTION_UP: case android.view.MotionEvent.ACTION_CANCEL: button8.setBackgroundColor(colorOff); break; } return false; } }); button9.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case android.view.MotionEvent.ACTION_DOWN: case android.view.MotionEvent.ACTION_MOVE: button9.setBackgroundColor(colorOn); break; case android.view.MotionEvent.ACTION_UP: case android.view.MotionEvent.ACTION_CANCEL: button9.setBackgroundColor(colorOff); break; } return false; } }); buttonDeleteBack.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case android.view.MotionEvent.ACTION_DOWN: case android.view.MotionEvent.ACTION_MOVE: buttonDeleteBack.setBackgroundColor(colorOn); break; case android.view.MotionEvent.ACTION_UP: case android.view.MotionEvent.ACTION_CANCEL: buttonDeleteBack.setBackgroundColor(colorOff); break; } return false; } }); buttonForgot.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case android.view.MotionEvent.ACTION_DOWN: case android.view.MotionEvent.ACTION_MOVE: buttonForgot.setBackgroundColor(colorOn); break; case android.view.MotionEvent.ACTION_UP: case android.view.MotionEvent.ACTION_CANCEL: buttonForgot.setBackgroundColor(colorOff); break; } return false; } }); if(ConnectivityStatus.hasConnectivity(this)) { ExchangeRates fxRates = new ExchangeRates(); DownloadFXRatesTask task = new DownloadFXRatesTask(context, fxRates); task.execute(new String[] { fxRates.getUrl() }); String[] currencies = CurrencyExchange.getInstance(this).getBlockchainCurrencies(); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(PinEntryActivity.this); String strFiatCode = prefs.getString("ccurrency", "USD"); OtherCurrencyExchange.getInstance(PinEntryActivity.this, currencies, strFiatCode); } else { final AlertDialog.Builder builder = new AlertDialog.Builder(this); final String message = getString(R.string.check_connectivity_exit); builder.setMessage(message) .setCancelable(false) .setPositiveButton(R.string.dialog_continue, new DialogInterface.OnClickListener() { public void onClick(DialogInterface d, int id) { d.dismiss(); Intent intent = new Intent(PinEntryActivity.this, PinEntryActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } }); builder.create().show(); } final WalletApplication application = (WalletApplication)PinEntryActivity.this.getApplication(); if (application.getGUID() == null && !creating) { Intent intent = new Intent(PinEntryActivity.this, SetupActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } } @Override public void onBackPressed() { //App not allowed to go back to Parent activity until correct pin entered. return; //super.onBackPressed(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. //getMenuInflater().inflate(R.menu.activity_pin_entry_view, menu); return true; } private class LockKeyPadOperation extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... params) { for(int i = 0; i < 2; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return "Executed"; } @Override protected void onPostExecute(String result) { statusView.setText(""); //Roll over pinBoxArray[0].setText(""); pinBoxArray[1].setText(""); pinBoxArray[2].setText(""); pinBoxArray[3].setText(""); userEntered = ""; keyPadLockedFlag = false; } @Override protected void onPreExecute() { } @Override protected void onProgressUpdate(Void... values) { } } public static void clearPrefValues(WalletApplication application) throws Exception { Editor editor = PreferenceManager.getDefaultSharedPreferences(application).edit(); editor.remove("pin_kookup_key"); editor.remove("encrypted_password"); editor.putBoolean("verified", false); if (!editor.commit()) { throw new Exception("Error Saving Preferences"); } } public void validatePIN(final String PIN) { final WalletApplication application = (WalletApplication)PinEntryActivity.this.getApplication(); final Handler handler = new Handler(); final Activity activity = this; ProgressUtil.getInstance(PinEntryActivity.this).show(); new Thread(new Runnable() { public void run() { Looper.prepare(); String pin_lookup_key = PreferenceManager.getDefaultSharedPreferences(application).getString("pin_kookup_key", null); String encrypted_password = PreferenceManager.getDefaultSharedPreferences(application).getString("encrypted_password", null); try { final JSONObject response = apiGetValue(pin_lookup_key, PIN); String decryptionKey = (String) response.get("success"); if (decryptionKey != null) { application.setTemporyPIN(PIN); application.didEncounterFatalPINServerError = false; String password = MyWallet.decrypt(encrypted_password, decryptionKey, piuk.blockchain.android.ui.PinEntryActivity.PBKDF2Iterations); application.checkIfWalletHasUpdatedAndFetchTransactions(password, new SuccessCallback() { @Override public void onSuccess() { handler.post(new Runnable() { public void run() { TimeOutUtil.getInstance().updatePin(); Editor edit = PreferenceManager.getDefaultSharedPreferences(PinEntryActivity.this).edit(); edit.putBoolean("verified", true); edit.commit(); ProgressUtil.getInstance(PinEntryActivity.this).close(); BlockchainUtil.getInstance(PinEntryActivity.this); Intent intent = new Intent(PinEntryActivity.this, MainActivity.class); String navigateTo = getIntent().getStringExtra("navigateTo"); intent.putExtra("navigateTo", navigateTo); intent.putExtra("verified", true); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); if(strUri != null) { intent.putExtra("INTENT_URI", strUri); } startActivity(intent); } }); } @Override public void onFail() { handler.post(new Runnable() { public void run() { Toast.makeText(PinEntryActivity.this, piuk.blockchain.android.R.string.toast_wallet_decryption_failed, Toast.LENGTH_LONG).show(); ProgressUtil.getInstance(PinEntryActivity.this).close(); } }); } }); } else if (response.get("error") != null) { Toast.makeText(PinEntryActivity.this, response.get("error").toString(), Toast.LENGTH_SHORT).show(); application.didEncounterFatalPINServerError = false; ProgressUtil.getInstance(PinEntryActivity.this).close(); //"code" == 2 means the PIN is incorrect if (!response.containsKey("code") || ((Number)response.get("code")).intValue() != 2) { clearPrefValues(application); throw new Exception("Fatal PIN Server Error"); } else { //Restart in "validating" mode handler.post(new Runnable() { public void run() { Toast.makeText(PinEntryActivity.this, (String)response.get("error"), Toast.LENGTH_SHORT).show(); Intent starterIntent = getIntent(); finish(); startActivity(starterIntent); } }); } } else { ProgressUtil.getInstance(PinEntryActivity.this).close(); throw new Exception("Unknown Error"); } } catch (final Exception e) { e.printStackTrace(); ProgressUtil.getInstance(PinEntryActivity.this).close(); application.didEncounterFatalPINServerError = true; handler.post(new Runnable() { public void run() { try { AlertDialog.Builder builder = new AlertDialog.Builder(activity); builder.setCancelable(false); builder.setMessage(piuk.blockchain.android.R.string.pin_server_error_description); builder.setTitle(piuk.blockchain.android.R.string.pin_server_error); builder.setPositiveButton(piuk.blockchain.android.R.string.try_again, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { Toast.makeText(PinEntryActivity.this, "Starting over", Toast.LENGTH_SHORT).show(); Intent intent = new Intent(PinEntryActivity.this, PinEntryActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } }); builder.setNegativeButton(piuk.blockchain.android.R.string.pin_server_error_enter_password_manually, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.dismiss(); requestPassword(); } }); AlertDialog dialog = builder.create(); // ProgressUtil.getInstance(PinEntryActivity.this).close(); dialog.show(); } catch (Exception e) { e.printStackTrace(); } } }); } Looper.loop(); } }).start(); } @Override protected void onResume() { super.onResume(); final WalletApplication application = (WalletApplication) getApplication(); application.setIsPassedPinScreen(false); } public static String postURL(String request, String urlParameters) throws Exception { String error = null; for (int ii = 0; ii < WalletUtils.DefaultRequestRetry; ++ii) { URL url = new URL(request); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); try { connection.setDoOutput(true); connection.setDoInput(true); connection.setInstanceFollowRedirects(false); connection.setRequestMethod("POST"); connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); connection.setRequestProperty("charset", "utf-8"); connection.setRequestProperty("Accept", "application/json"); connection.setRequestProperty("Content-Length", "" + Integer.toString(urlParameters.getBytes().length)); connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36"); connection.setUseCaches (false); connection.setConnectTimeout(WalletUtils.DefaultRequestTimeout); connection.setReadTimeout(WalletUtils.DefaultRequestTimeout); connection.connect(); DataOutputStream wr = new DataOutputStream(connection.getOutputStream ()); wr.writeBytes(urlParameters); wr.flush(); wr.close(); connection.setInstanceFollowRedirects(false); System.out.println("Response Code " + connection.getResponseCode() ); //connection.getRequestProperties().get("Content-Type").equals("application/json") if (connection.getResponseCode() == 200) return IOUtils.toString(connection.getInputStream(), "UTF-8"); else if (connection.getResponseCode() == 500) return IOUtils.toString(connection.getErrorStream(), "UTF-8"); else error = IOUtils.toString(connection.getErrorStream(), "UTF-8"); Thread.sleep(5000); } finally { connection.disconnect(); } } throw new Exception("Invalid Response " + error); } public static JSONObject apiGetValue(String key, String pin) throws Exception { StringBuilder args = new StringBuilder(); args.append("key=" + key); args.append("&pin=" + pin); args.append("&method=get"); String response = postURL(WebROOT, args.toString()); if (response == null || response.length() == 0) throw new Exception("Invalid Server Response"); try { return (JSONObject) new JSONParser().parse(response); } catch (ParseException e) { throw new Exception("Invalid Server Response"); } } public static JSONObject apiStoreKey(String key, String value, String pin) throws Exception { StringBuilder args = new StringBuilder(); args.append("key=" + key); args.append("&value=" + value); args.append("&pin=" + pin); args.append("&method=put"); String response = postURL(WebROOT, args.toString()); if (response == null || response.length() == 0) throw new Exception("Invalid Server Response"); try { return (JSONObject) new JSONParser().parse(response); } catch (ParseException e) { throw new Exception("Invalid Server Response"); } } public void requestPassword() { RequestForgotPasswordDialog.show(getSupportFragmentManager(), new SuccessCallback() { public void onSuccess() { Toast.makeText(PinEntryActivity.this, R.string.password_correct, Toast.LENGTH_LONG).show(); new AlertDialog.Builder(PinEntryActivity.this) .setTitle(R.string.app_name) .setMessage(R.string.confirm_new_pin_creation) .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { // @Override public void onClick(DialogInterface dialog, int which) { Intent starterIntent = getIntent(); starterIntent.putExtra("N", "1"); finish(); startActivity(starterIntent); } }).show(); } public void onFail() { Toast.makeText(PinEntryActivity.this, piuk.blockchain.android.R.string.password_incorrect, Toast.LENGTH_LONG).show(); Intent intent = new Intent(PinEntryActivity.this, PinEntryActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } }); } }