VerifyOTRActivity.java

  1package eu.siacs.conversations.ui;
  2
  3import android.content.Intent;
  4import android.os.Bundle;
  5import android.view.View;
  6import android.widget.Button;
  7import android.widget.EditText;
  8import android.widget.RelativeLayout;
  9import android.widget.TextView;
 10import android.widget.Toast;
 11
 12import net.java.otr4j.OtrException;
 13import net.java.otr4j.session.Session;
 14
 15import eu.siacs.conversations.R;
 16import eu.siacs.conversations.entities.Account;
 17import eu.siacs.conversations.entities.Conversation;
 18import eu.siacs.conversations.services.XmppConnectionService;
 19import eu.siacs.conversations.xmpp.jid.InvalidJidException;
 20import eu.siacs.conversations.xmpp.jid.Jid;
 21
 22public class VerifyOTRActivity extends XmppActivity implements XmppConnectionService.OnConversationUpdate {
 23
 24	public static final String ACTION_VERIFY_CONTACT = "verify_contact";
 25
 26	private RelativeLayout mVerificationAreaOne;
 27	private RelativeLayout mVerificationAreaTwo;
 28	private TextView mErrorNoSession;
 29	private TextView mRemoteJid;
 30	private TextView mRemoteFingerprint;
 31	private TextView mYourFingerprint;
 32	private EditText mSharedSecretHint;
 33	private EditText mSharedSecretSecret;
 34	private Button mButtonVerifyFingerprint;
 35	private Button mButtonSharedSecretPositive;
 36	private Button mButtonSharedSecretNegative;
 37	private TextView mStatusMessage;
 38	private Account mAccount;
 39	private Conversation mConversation;
 40
 41	private View.OnClickListener mVerifyFingerprintListener = new View.OnClickListener() {
 42
 43		@Override
 44		public void onClick(View view) {
 45			mConversation.verifyOtrFingerprint();
 46			finish();
 47		}
 48	};
 49
 50	private View.OnClickListener mCreateSharedSecretListener = new View.OnClickListener() {
 51		@Override
 52		public void onClick(final View view) {
 53			if (isAccountOnline()) {
 54				final String question = mSharedSecretHint.getText().toString();
 55				final String secret = mSharedSecretSecret.getText().toString();
 56				initSmp(question, secret);
 57				updateView();
 58			}
 59		}
 60	};
 61	private View.OnClickListener mCancelSharedSecretListener = new View.OnClickListener() {
 62		@Override
 63		public void onClick(View view) {
 64			if (isAccountOnline()) {
 65				abortSmp();
 66				updateView();
 67			}
 68		}
 69	};
 70	private View.OnClickListener mRespondSharedSecretListener = new View.OnClickListener() {
 71
 72		@Override
 73		public void onClick(View view) {
 74			if (isAccountOnline()) {
 75				final String question = mSharedSecretHint.getText().toString();
 76				final String secret = mSharedSecretSecret.getText().toString();
 77				respondSmp(question, secret);
 78				updateView();
 79			}
 80		}
 81	};
 82	private View.OnClickListener mRetrySharedSecretListener = new View.OnClickListener() {
 83		@Override
 84		public void onClick(View view) {
 85			mConversation.smp().status = Conversation.Smp.STATUS_NONE;
 86			mConversation.smp().hint = null;
 87			mConversation.smp().secret = null;
 88			updateView();
 89		}
 90	};
 91	private View.OnClickListener mFinishListener = new View.OnClickListener() {
 92		@Override
 93		public void onClick(View view) {
 94			mConversation.smp().status = Conversation.Smp.STATUS_NONE;
 95			finish();
 96		}
 97	};
 98
 99	protected boolean initSmp(final String question, final String secret) {
100		final Session session = mConversation.getOtrSession();
101		if (session!=null) {
102			try {
103				session.initSmp(question, secret);
104				mConversation.smp().status = Conversation.Smp.STATUS_WE_REQUESTED;
105				return true;
106			} catch (OtrException e) {
107				return false;
108			}
109		} else {
110			return false;
111		}
112	}
113
114	protected boolean abortSmp() {
115		final Session session = mConversation.getOtrSession();
116		if (session!=null) {
117			try {
118				session.abortSmp();
119				mConversation.smp().status = Conversation.Smp.STATUS_NONE;
120				mConversation.smp().hint = null;
121				mConversation.smp().secret = null;
122				return true;
123			} catch (OtrException e) {
124				return false;
125			}
126		} else {
127			return false;
128		}
129	}
130
131	protected boolean respondSmp(final String question, final String secret) {
132		final Session session = mConversation.getOtrSession();
133		if (session!=null) {
134			try {
135				session.respondSmp(question,secret);
136				return true;
137			} catch (OtrException e) {
138				return false;
139			}
140		} else {
141			return false;
142		}
143	}
144
145	protected boolean isAccountOnline() {
146		if (this.mAccount.getStatus() != Account.STATUS_ONLINE) {
147			Toast.makeText(this,R.string.not_connected_try_again,Toast.LENGTH_SHORT).show();
148			return false;
149		} else {
150			return true;
151		}
152	}
153
154	protected boolean handleIntent(Intent intent) {
155		if (intent.getAction().equals(ACTION_VERIFY_CONTACT)) {
156			try {
157				this.mAccount = this.xmppConnectionService.findAccountByJid(Jid.fromString(intent.getExtras().getString("account")));
158			} catch (final InvalidJidException ignored) {
159				return false;
160			}
161			try {
162				this.mConversation = this.xmppConnectionService.find(this.mAccount,Jid.fromString(intent.getExtras().getString("contact")));
163				if (this.mConversation == null) {
164					return false;
165				}
166			} catch (final InvalidJidException ignored) {
167				return false;
168			}
169			return true;
170		} else {
171			return false;
172		}
173	}
174
175	@Override
176	protected void onBackendConnected() {
177		if (handleIntent(getIntent())) {
178			updateView();
179		}
180	}
181
182	protected void updateView() {
183		if (this.mConversation.hasValidOtrSession()) {
184			this.mVerificationAreaOne.setVisibility(View.VISIBLE);
185			this.mVerificationAreaTwo.setVisibility(View.VISIBLE);
186			this.mErrorNoSession.setVisibility(View.GONE);
187			this.mYourFingerprint.setText(this.mAccount.getOtrFingerprint(xmppConnectionService));
188			this.mRemoteFingerprint.setText(this.mConversation.getOtrFingerprint());
189			this.mRemoteJid.setText(this.mConversation.getContact().getJid().toBareJid().toString());
190			Conversation.Smp smp = mConversation.smp();
191			Session session = mConversation.getOtrSession();
192			if (mConversation.isOtrFingerprintVerified()) {
193				deactivateButton(mButtonVerifyFingerprint, R.string.verified);
194			} else {
195				activateButton(mButtonVerifyFingerprint, R.string.verify, mVerifyFingerprintListener);
196			}
197			if (smp.status == Conversation.Smp.STATUS_NONE) {
198				activateButton(mButtonSharedSecretPositive, R.string.create, mCreateSharedSecretListener);
199				deactivateButton(mButtonSharedSecretNegative, R.string.cancel);
200				this.mSharedSecretHint.setFocusableInTouchMode(true);
201				this.mSharedSecretSecret.setFocusableInTouchMode(true);
202				this.mSharedSecretSecret.setText("");
203				this.mSharedSecretHint.setText("");
204				this.mSharedSecretHint.setVisibility(View.VISIBLE);
205				this.mSharedSecretSecret.setVisibility(View.VISIBLE);
206				this.mStatusMessage.setVisibility(View.GONE);
207			} else if (smp.status == Conversation.Smp.STATUS_CONTACT_REQUESTED) {
208				this.mSharedSecretHint.setFocusable(false);
209				this.mSharedSecretHint.setText(smp.hint);
210				this.mSharedSecretSecret.setFocusableInTouchMode(true);
211				this.mSharedSecretHint.setVisibility(View.VISIBLE);
212				this.mSharedSecretSecret.setVisibility(View.VISIBLE);
213				this.mStatusMessage.setVisibility(View.GONE);
214				deactivateButton(mButtonSharedSecretNegative, R.string.cancel);
215				activateButton(mButtonSharedSecretPositive, R.string.respond, mRespondSharedSecretListener);
216			} else if (smp.status == Conversation.Smp.STATUS_FAILED) {
217				activateButton(mButtonSharedSecretNegative, R.string.cancel, mFinishListener);
218				activateButton(mButtonSharedSecretPositive, R.string.try_again, mRetrySharedSecretListener);
219				this.mSharedSecretHint.setVisibility(View.GONE);
220				this.mSharedSecretSecret.setVisibility(View.GONE);
221				this.mStatusMessage.setVisibility(View.VISIBLE);
222				this.mStatusMessage.setText(R.string.secrets_do_not_match);
223				this.mStatusMessage.setTextColor(getWarningTextColor());
224			} else if (smp.status == Conversation.Smp.STATUS_VERIFIED) {
225				this.mSharedSecretHint.setVisibility(View.GONE);
226				this.mSharedSecretSecret.setVisibility(View.GONE);
227				this.mStatusMessage.setVisibility(View.VISIBLE);
228				this.mStatusMessage.setText(R.string.verified);
229				this.mStatusMessage.setTextColor(getPrimaryColor());
230				deactivateButton(mButtonSharedSecretNegative, R.string.cancel);
231				activateButton(mButtonSharedSecretPositive, R.string.finish, mFinishListener);
232			} else if (session != null && session.isSmpInProgress()) {
233				deactivateButton(mButtonSharedSecretPositive, R.string.in_progress);
234				activateButton(mButtonSharedSecretNegative, R.string.cancel, mCancelSharedSecretListener);
235				this.mSharedSecretHint.setVisibility(View.VISIBLE);
236				this.mSharedSecretSecret.setVisibility(View.VISIBLE);
237				this.mSharedSecretHint.setFocusable(false);
238				this.mSharedSecretSecret.setFocusable(false);
239			}
240		} else {
241			this.mVerificationAreaOne.setVisibility(View.GONE);
242			this.mVerificationAreaTwo.setVisibility(View.GONE);
243			this.mErrorNoSession.setVisibility(View.VISIBLE);
244		}
245	}
246
247	protected void activateButton(Button button, int text, View.OnClickListener listener) {
248		button.setEnabled(true);
249		button.setTextColor(getPrimaryTextColor());
250		button.setText(text);
251		button.setOnClickListener(listener);
252	}
253
254	protected void deactivateButton(Button button, int text) {
255		button.setEnabled(false);
256		button.setTextColor(getSecondaryTextColor());
257		button.setText(text);
258		button.setOnClickListener(null);
259	}
260
261	@Override
262	protected void onCreate(Bundle savedInstanceState) {
263		super.onCreate(savedInstanceState);
264		setContentView(R.layout.activity_verify_otr);
265		this.mRemoteFingerprint = (TextView) findViewById(R.id.remote_fingerprint);
266		this.mRemoteJid = (TextView) findViewById(R.id.remote_jid);
267		this.mYourFingerprint = (TextView) findViewById(R.id.your_fingerprint);
268		this.mButtonSharedSecretNegative = (Button) findViewById(R.id.button_shared_secret_negative);
269		this.mButtonSharedSecretPositive = (Button) findViewById(R.id.button_shared_secret_positive);
270		this.mButtonVerifyFingerprint = (Button) findViewById(R.id.button_verify_fingerprint);
271		this.mSharedSecretSecret = (EditText) findViewById(R.id.shared_secret_secret);
272		this.mSharedSecretHint = (EditText) findViewById(R.id.shared_secret_hint);
273		this.mStatusMessage= (TextView) findViewById(R.id.status_message);
274		this.mVerificationAreaOne = (RelativeLayout) findViewById(R.id.verification_area_one);
275		this.mVerificationAreaTwo = (RelativeLayout) findViewById(R.id.verification_area_two);
276		this.mErrorNoSession = (TextView) findViewById(R.id.error_no_session);
277	}
278
279	@Override
280	protected String getShareableUri() {
281		if (mAccount!=null) {
282			return "xmpp:"+mAccount.getJid().toBareJid();
283		} else {
284			return "";
285		}
286	}
287
288	public void onConversationUpdate() {
289		runOnUiThread(new Runnable() {
290			@Override
291			public void run() {
292				updateView();
293			}
294		});
295	}
296}