VerifyOTRActivity.java

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