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