1package eu.siacs.conversations.ui;
2
3import android.app.AlertDialog;
4import android.app.AlertDialog.Builder;
5import android.app.PendingIntent;
6import android.content.DialogInterface;
7import android.content.Intent;
8import android.graphics.Bitmap;
9import android.os.Bundle;
10import android.text.Editable;
11import android.text.TextWatcher;
12import android.view.Menu;
13import android.view.MenuItem;
14import android.view.View;
15import android.view.View.OnClickListener;
16import android.widget.AutoCompleteTextView;
17import android.widget.Button;
18import android.widget.CheckBox;
19import android.widget.CompoundButton;
20import android.widget.CompoundButton.OnCheckedChangeListener;
21import android.widget.EditText;
22import android.widget.ImageButton;
23import android.widget.ImageView;
24import android.widget.LinearLayout;
25import android.widget.RelativeLayout;
26import android.widget.TableLayout;
27import android.widget.TextView;
28import android.widget.Toast;
29
30import java.util.Set;
31
32import eu.siacs.conversations.Config;
33import eu.siacs.conversations.R;
34import eu.siacs.conversations.crypto.axolotl.AxolotlService;
35import eu.siacs.conversations.entities.Account;
36import eu.siacs.conversations.services.XmppConnectionService.OnCaptchaRequested;
37import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate;
38import eu.siacs.conversations.ui.adapter.KnownHostsAdapter;
39import eu.siacs.conversations.utils.CryptoHelper;
40import eu.siacs.conversations.utils.UIHelper;
41import eu.siacs.conversations.xmpp.OnKeyStatusUpdated;
42import eu.siacs.conversations.xmpp.XmppConnection.Features;
43import eu.siacs.conversations.xmpp.forms.Data;
44import eu.siacs.conversations.xmpp.jid.InvalidJidException;
45import eu.siacs.conversations.xmpp.jid.Jid;
46import eu.siacs.conversations.xmpp.pep.Avatar;
47
48public class EditAccountActivity extends XmppActivity implements OnAccountUpdate,
49 OnKeyStatusUpdated, OnCaptchaRequested {
50
51 private AutoCompleteTextView mAccountJid;
52 private EditText mPassword;
53 private EditText mPasswordConfirm;
54 private CheckBox mRegisterNew;
55 private Button mCancelButton;
56 private Button mSaveButton;
57 private TableLayout mMoreTable;
58
59 private LinearLayout mStats;
60 private TextView mServerInfoSm;
61 private TextView mServerInfoRosterVersion;
62 private TextView mServerInfoCarbons;
63 private TextView mServerInfoMam;
64 private TextView mServerInfoCSI;
65 private TextView mServerInfoBlocking;
66 private TextView mServerInfoPep;
67 private TextView mServerInfoHttpUpload;
68 private TextView mSessionEst;
69 private TextView mOtrFingerprint;
70 private TextView mAxolotlFingerprint;
71 private TextView mAccountJidLabel;
72 private ImageView mAvatar;
73 private RelativeLayout mOtrFingerprintBox;
74 private RelativeLayout mAxolotlFingerprintBox;
75 private ImageButton mOtrFingerprintToClipboardButton;
76 private ImageButton mAxolotlFingerprintToClipboardButton;
77 private ImageButton mRegenerateAxolotlKeyButton;
78 private LinearLayout keys;
79 private LinearLayout keysCard;
80 private AlertDialog mCaptchaDialog = null;
81
82 private Jid jidToEdit;
83 private boolean mInitMode = false;
84 private Account mAccount;
85 private String messageFingerprint;
86
87 private boolean mFetchingAvatar = false;
88
89 private final OnClickListener mSaveButtonClickListener = new OnClickListener() {
90
91 @Override
92 public void onClick(final View v) {
93 if (mInitMode && mAccount != null) {
94 mAccount.setOption(Account.OPTION_DISABLED, false);
95 }
96 if (mAccount != null && mAccount.getStatus() == Account.State.DISABLED && !accountInfoEdited()) {
97 mAccount.setOption(Account.OPTION_DISABLED, false);
98 xmppConnectionService.updateAccount(mAccount);
99 return;
100 }
101 final boolean registerNewAccount = mRegisterNew.isChecked() && !Config.DISALLOW_REGISTRATION_IN_UI;
102 if (Config.DOMAIN_LOCK != null && mAccountJid.getText().toString().contains("@")) {
103 mAccountJid.setError(getString(R.string.invalid_username));
104 mAccountJid.requestFocus();
105 return;
106 }
107 final Jid jid;
108 try {
109 if (Config.DOMAIN_LOCK != null) {
110 jid = Jid.fromParts(mAccountJid.getText().toString(),Config.DOMAIN_LOCK,null);
111 } else {
112 jid = Jid.fromString(mAccountJid.getText().toString());
113 }
114 } catch (final InvalidJidException e) {
115 if (Config.DOMAIN_LOCK != null) {
116 mAccountJid.setError(getString(R.string.invalid_username));
117 } else {
118 mAccountJid.setError(getString(R.string.invalid_jid));
119 }
120 mAccountJid.requestFocus();
121 return;
122 }
123 if (jid.isDomainJid()) {
124 if (Config.DOMAIN_LOCK != null) {
125 mAccountJid.setError(getString(R.string.invalid_username));
126 } else {
127 mAccountJid.setError(getString(R.string.invalid_jid));
128 }
129 mAccountJid.requestFocus();
130 return;
131 }
132 final String password = mPassword.getText().toString();
133 final String passwordConfirm = mPasswordConfirm.getText().toString();
134 if (registerNewAccount) {
135 if (!password.equals(passwordConfirm)) {
136 mPasswordConfirm.setError(getString(R.string.passwords_do_not_match));
137 mPasswordConfirm.requestFocus();
138 return;
139 }
140 }
141 if (mAccount != null) {
142 mAccount.setJid(jid);
143 mAccountJid.setError(null);
144 mPasswordConfirm.setError(null);
145 mAccount.setPassword(password);
146 mAccount.setOption(Account.OPTION_REGISTER, registerNewAccount);
147 xmppConnectionService.updateAccount(mAccount);
148 } else {
149 if (xmppConnectionService.findAccountByJid(jid) != null) {
150 mAccountJid.setError(getString(R.string.account_already_exists));
151 mAccountJid.requestFocus();
152 return;
153 }
154 mAccount = new Account(jid.toBareJid(), password);
155 mAccount.setOption(Account.OPTION_USETLS, true);
156 mAccount.setOption(Account.OPTION_USECOMPRESSION, true);
157 mAccount.setOption(Account.OPTION_REGISTER, registerNewAccount);
158 xmppConnectionService.createAccount(mAccount);
159 }
160 if (!mAccount.isOptionSet(Account.OPTION_DISABLED)
161 && !registerNewAccount
162 && !mInitMode) {
163 finish();
164 } else {
165 updateSaveButton();
166 updateAccountInformation(true);
167 }
168
169 }
170 };
171 private final OnClickListener mCancelButtonClickListener = new OnClickListener() {
172
173 @Override
174 public void onClick(final View v) {
175 finish();
176 }
177 };
178
179 public void refreshUiReal() {
180 invalidateOptionsMenu();
181 if (mAccount != null
182 && mAccount.getStatus() != Account.State.ONLINE
183 && mFetchingAvatar) {
184 startActivity(new Intent(getApplicationContext(),
185 ManageAccountActivity.class));
186 finish();
187 } else if (mInitMode && mAccount != null && mAccount.getStatus() == Account.State.ONLINE) {
188 if (!mFetchingAvatar) {
189 mFetchingAvatar = true;
190 xmppConnectionService.checkForAvatar(mAccount, mAvatarFetchCallback);
191 }
192 } else {
193 updateSaveButton();
194 }
195 if (mAccount != null) {
196 updateAccountInformation(false);
197 }
198 }
199
200 @Override
201 public void onAccountUpdate() {
202 refreshUi();
203 }
204 private final UiCallback<Avatar> mAvatarFetchCallback = new UiCallback<Avatar>() {
205
206 @Override
207 public void userInputRequried(final PendingIntent pi, final Avatar avatar) {
208 finishInitialSetup(avatar);
209 }
210
211 @Override
212 public void success(final Avatar avatar) {
213 finishInitialSetup(avatar);
214 }
215
216 @Override
217 public void error(final int errorCode, final Avatar avatar) {
218 finishInitialSetup(avatar);
219 }
220 };
221 private final TextWatcher mTextWatcher = new TextWatcher() {
222
223 @Override
224 public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
225 updateSaveButton();
226 }
227
228 @Override
229 public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
230 }
231
232 @Override
233 public void afterTextChanged(final Editable s) {
234
235 }
236 };
237
238 private final OnClickListener mAvatarClickListener = new OnClickListener() {
239 @Override
240 public void onClick(final View view) {
241 if (mAccount != null) {
242 final Intent intent = new Intent(getApplicationContext(), PublishProfilePictureActivity.class);
243 intent.putExtra("account", mAccount.getJid().toBareJid().toString());
244 startActivity(intent);
245 }
246 }
247 };
248
249 protected void finishInitialSetup(final Avatar avatar) {
250 runOnUiThread(new Runnable() {
251
252 @Override
253 public void run() {
254 final Intent intent;
255 if (avatar != null) {
256 intent = new Intent(getApplicationContext(),
257 StartConversationActivity.class);
258 if (xmppConnectionService != null && xmppConnectionService.getAccounts().size() == 1) {
259 intent.putExtra("init", true);
260 }
261 } else {
262 intent = new Intent(getApplicationContext(),
263 PublishProfilePictureActivity.class);
264 intent.putExtra("account", mAccount.getJid().toBareJid().toString());
265 intent.putExtra("setup", true);
266 }
267 startActivity(intent);
268 finish();
269 }
270 });
271 }
272
273 protected void updateSaveButton() {
274 if (accountInfoEdited() && !mInitMode) {
275 this.mSaveButton.setText(R.string.save);
276 this.mSaveButton.setEnabled(true);
277 this.mSaveButton.setTextColor(getPrimaryTextColor());
278 } else if (mAccount != null && (mAccount.getStatus() == Account.State.CONNECTING || mFetchingAvatar)) {
279 this.mSaveButton.setEnabled(false);
280 this.mSaveButton.setTextColor(getSecondaryTextColor());
281 this.mSaveButton.setText(R.string.account_status_connecting);
282 } else if (mAccount != null && mAccount.getStatus() == Account.State.DISABLED && !mInitMode) {
283 this.mSaveButton.setEnabled(true);
284 this.mSaveButton.setTextColor(getPrimaryTextColor());
285 this.mSaveButton.setText(R.string.enable);
286 } else {
287 this.mSaveButton.setEnabled(true);
288 this.mSaveButton.setTextColor(getPrimaryTextColor());
289 if (!mInitMode) {
290 if (mAccount != null && mAccount.isOnlineAndConnected()) {
291 this.mSaveButton.setText(R.string.save);
292 if (!accountInfoEdited()) {
293 this.mSaveButton.setEnabled(false);
294 this.mSaveButton.setTextColor(getSecondaryTextColor());
295 }
296 } else {
297 this.mSaveButton.setText(R.string.connect);
298 }
299 } else {
300 this.mSaveButton.setText(R.string.next);
301 }
302 }
303 }
304
305 protected boolean accountInfoEdited() {
306 if (this.mAccount == null) {
307 return false;
308 }
309 final String unmodified;
310 if (Config.DOMAIN_LOCK != null) {
311 unmodified = this.mAccount.getJid().getLocalpart();
312 } else {
313 unmodified = this.mAccount.getJid().toBareJid().toString();
314 }
315 return !unmodified.equals(this.mAccountJid.getText().toString()) ||
316 !this.mAccount.getPassword().equals(this.mPassword.getText().toString());
317 }
318
319 @Override
320 protected String getShareableUri() {
321 if (mAccount!=null) {
322 return mAccount.getShareableUri();
323 } else {
324 return "";
325 }
326 }
327
328 @Override
329 protected void onCreate(final Bundle savedInstanceState) {
330 super.onCreate(savedInstanceState);
331 setContentView(R.layout.activity_edit_account);
332 this.mAccountJid = (AutoCompleteTextView) findViewById(R.id.account_jid);
333 this.mAccountJid.addTextChangedListener(this.mTextWatcher);
334 this.mAccountJidLabel = (TextView) findViewById(R.id.account_jid_label);
335 if (Config.DOMAIN_LOCK != null) {
336 this.mAccountJidLabel.setText(R.string.username);
337 this.mAccountJid.setHint(R.string.username_hint);
338 }
339 this.mPassword = (EditText) findViewById(R.id.account_password);
340 this.mPassword.addTextChangedListener(this.mTextWatcher);
341 this.mPasswordConfirm = (EditText) findViewById(R.id.account_password_confirm);
342 this.mAvatar = (ImageView) findViewById(R.id.avater);
343 this.mAvatar.setOnClickListener(this.mAvatarClickListener);
344 this.mRegisterNew = (CheckBox) findViewById(R.id.account_register_new);
345 this.mStats = (LinearLayout) findViewById(R.id.stats);
346 this.mSessionEst = (TextView) findViewById(R.id.session_est);
347 this.mServerInfoRosterVersion = (TextView) findViewById(R.id.server_info_roster_version);
348 this.mServerInfoCarbons = (TextView) findViewById(R.id.server_info_carbons);
349 this.mServerInfoMam = (TextView) findViewById(R.id.server_info_mam);
350 this.mServerInfoCSI = (TextView) findViewById(R.id.server_info_csi);
351 this.mServerInfoBlocking = (TextView) findViewById(R.id.server_info_blocking);
352 this.mServerInfoSm = (TextView) findViewById(R.id.server_info_sm);
353 this.mServerInfoPep = (TextView) findViewById(R.id.server_info_pep);
354 this.mServerInfoHttpUpload = (TextView) findViewById(R.id.server_info_http_upload);
355 this.mOtrFingerprint = (TextView) findViewById(R.id.otr_fingerprint);
356 this.mOtrFingerprintBox = (RelativeLayout) findViewById(R.id.otr_fingerprint_box);
357 this.mOtrFingerprintToClipboardButton = (ImageButton) findViewById(R.id.action_copy_to_clipboard);
358 this.mAxolotlFingerprint = (TextView) findViewById(R.id.axolotl_fingerprint);
359 this.mAxolotlFingerprintBox = (RelativeLayout) findViewById(R.id.axolotl_fingerprint_box);
360 this.mAxolotlFingerprintToClipboardButton = (ImageButton) findViewById(R.id.action_copy_axolotl_to_clipboard);
361 this.mRegenerateAxolotlKeyButton = (ImageButton) findViewById(R.id.action_regenerate_axolotl_key);
362 this.keysCard = (LinearLayout) findViewById(R.id.other_device_keys_card);
363 this.keys = (LinearLayout) findViewById(R.id.other_device_keys);
364 this.mSaveButton = (Button) findViewById(R.id.save_button);
365 this.mCancelButton = (Button) findViewById(R.id.cancel_button);
366 this.mSaveButton.setOnClickListener(this.mSaveButtonClickListener);
367 this.mCancelButton.setOnClickListener(this.mCancelButtonClickListener);
368 this.mMoreTable = (TableLayout) findViewById(R.id.server_info_more);
369 final OnCheckedChangeListener OnCheckedShowConfirmPassword = new OnCheckedChangeListener() {
370 @Override
371 public void onCheckedChanged(final CompoundButton buttonView,
372 final boolean isChecked) {
373 if (isChecked) {
374 mPasswordConfirm.setVisibility(View.VISIBLE);
375 } else {
376 mPasswordConfirm.setVisibility(View.GONE);
377 }
378 updateSaveButton();
379 }
380 };
381 this.mRegisterNew.setOnCheckedChangeListener(OnCheckedShowConfirmPassword);
382 if (Config.DISALLOW_REGISTRATION_IN_UI) {
383 this.mRegisterNew.setVisibility(View.GONE);
384 }
385 }
386
387 @Override
388 public boolean onCreateOptionsMenu(final Menu menu) {
389 super.onCreateOptionsMenu(menu);
390 getMenuInflater().inflate(R.menu.editaccount, menu);
391 final MenuItem showQrCode = menu.findItem(R.id.action_show_qr_code);
392 final MenuItem showBlocklist = menu.findItem(R.id.action_show_block_list);
393 final MenuItem showMoreInfo = menu.findItem(R.id.action_server_info_show_more);
394 final MenuItem changePassword = menu.findItem(R.id.action_change_password_on_server);
395 final MenuItem clearDevices = menu.findItem(R.id.action_clear_devices);
396 if (mAccount != null && mAccount.isOnlineAndConnected()) {
397 if (!mAccount.getXmppConnection().getFeatures().blocking()) {
398 showBlocklist.setVisible(false);
399 }
400 if (!mAccount.getXmppConnection().getFeatures().register()) {
401 changePassword.setVisible(false);
402 }
403 Set<Integer> otherDevices = mAccount.getAxolotlService().getOwnDeviceIds();
404 if (otherDevices == null || otherDevices.isEmpty()) {
405 clearDevices.setVisible(false);
406 }
407 } else {
408 showQrCode.setVisible(false);
409 showBlocklist.setVisible(false);
410 showMoreInfo.setVisible(false);
411 changePassword.setVisible(false);
412 clearDevices.setVisible(false);
413 }
414 return true;
415 }
416
417 @Override
418 protected void onStart() {
419 super.onStart();
420 if (getIntent() != null) {
421 try {
422 this.jidToEdit = Jid.fromString(getIntent().getStringExtra("jid"));
423 } catch (final InvalidJidException | NullPointerException ignored) {
424 this.jidToEdit = null;
425 }
426 this.mInitMode = getIntent().getBooleanExtra("init", false) || this.jidToEdit == null;
427 this.messageFingerprint = getIntent().getStringExtra("fingerprint");
428 if (!mInitMode) {
429 this.mRegisterNew.setVisibility(View.GONE);
430 if (getActionBar() != null) {
431 getActionBar().setTitle(getString(R.string.account_details));
432 }
433 } else {
434 this.mAvatar.setVisibility(View.GONE);
435 if (getActionBar() != null) {
436 getActionBar().setTitle(R.string.action_add_account);
437 }
438 }
439 }
440 }
441
442 @Override
443 protected void onBackendConnected() {
444 if (this.jidToEdit != null) {
445 this.mAccount = xmppConnectionService.findAccountByJid(jidToEdit);
446 if (this.mAccount != null) {
447 if (this.mAccount.getPrivateKeyAlias() != null) {
448 this.mPassword.setHint(R.string.authenticate_with_certificate);
449 if (this.mInitMode) {
450 this.mPassword.requestFocus();
451 }
452 } updateAccountInformation(true);
453 }
454 } else if (this.xmppConnectionService.getAccounts().size() == 0) {
455 if (getActionBar() != null) {
456 getActionBar().setDisplayHomeAsUpEnabled(false);
457 getActionBar().setDisplayShowHomeEnabled(false);
458 getActionBar().setHomeButtonEnabled(false);
459 }
460 this.mCancelButton.setEnabled(false);
461 this.mCancelButton.setTextColor(getSecondaryTextColor());
462 }
463 if (Config.DOMAIN_LOCK == null) {
464 final KnownHostsAdapter mKnownHostsAdapter = new KnownHostsAdapter(this,
465 android.R.layout.simple_list_item_1,
466 xmppConnectionService.getKnownHosts());
467 this.mAccountJid.setAdapter(mKnownHostsAdapter);
468 }
469 updateSaveButton();
470 }
471
472 @Override
473 public boolean onOptionsItemSelected(final MenuItem item) {
474 switch (item.getItemId()) {
475 case R.id.action_show_block_list:
476 final Intent showBlocklistIntent = new Intent(this, BlocklistActivity.class);
477 showBlocklistIntent.putExtra("account", mAccount.getJid().toString());
478 startActivity(showBlocklistIntent);
479 break;
480 case R.id.action_server_info_show_more:
481 mMoreTable.setVisibility(item.isChecked() ? View.GONE : View.VISIBLE);
482 item.setChecked(!item.isChecked());
483 break;
484 case R.id.action_change_password_on_server:
485 final Intent changePasswordIntent = new Intent(this, ChangePasswordActivity.class);
486 changePasswordIntent.putExtra("account", mAccount.getJid().toString());
487 startActivity(changePasswordIntent);
488 break;
489 case R.id.action_clear_devices:
490 showWipePepDialog();
491 break;
492 }
493 return super.onOptionsItemSelected(item);
494 }
495
496 private void updateAccountInformation(boolean init) {
497 if (init) {
498 if (Config.DOMAIN_LOCK != null) {
499 this.mAccountJid.setText(this.mAccount.getJid().getLocalpart());
500 } else {
501 this.mAccountJid.setText(this.mAccount.getJid().toBareJid().toString());
502 }
503 this.mPassword.setText(this.mAccount.getPassword());
504 }
505 if (!mInitMode) {
506 this.mAvatar.setVisibility(View.VISIBLE);
507 this.mAvatar.setImageBitmap(avatarService().get(this.mAccount, getPixel(72)));
508 }
509 if (this.mAccount.isOptionSet(Account.OPTION_REGISTER)) {
510 this.mRegisterNew.setVisibility(View.VISIBLE);
511 this.mRegisterNew.setChecked(true);
512 this.mPasswordConfirm.setText(this.mAccount.getPassword());
513 } else {
514 this.mRegisterNew.setVisibility(View.GONE);
515 this.mRegisterNew.setChecked(false);
516 }
517 if (this.mAccount.isOnlineAndConnected() && !this.mFetchingAvatar) {
518 this.mStats.setVisibility(View.VISIBLE);
519 this.mSessionEst.setText(UIHelper.readableTimeDifferenceFull(this, this.mAccount.getXmppConnection()
520 .getLastSessionEstablished()));
521 Features features = this.mAccount.getXmppConnection().getFeatures();
522 if (features.rosterVersioning()) {
523 this.mServerInfoRosterVersion.setText(R.string.server_info_available);
524 } else {
525 this.mServerInfoRosterVersion.setText(R.string.server_info_unavailable);
526 }
527 if (features.carbons()) {
528 this.mServerInfoCarbons.setText(R.string.server_info_available);
529 } else {
530 this.mServerInfoCarbons
531 .setText(R.string.server_info_unavailable);
532 }
533 if (features.mam()) {
534 this.mServerInfoMam.setText(R.string.server_info_available);
535 } else {
536 this.mServerInfoMam.setText(R.string.server_info_unavailable);
537 }
538 if (features.csi()) {
539 this.mServerInfoCSI.setText(R.string.server_info_available);
540 } else {
541 this.mServerInfoCSI.setText(R.string.server_info_unavailable);
542 }
543 if (features.blocking()) {
544 this.mServerInfoBlocking.setText(R.string.server_info_available);
545 } else {
546 this.mServerInfoBlocking.setText(R.string.server_info_unavailable);
547 }
548 if (features.sm()) {
549 this.mServerInfoSm.setText(R.string.server_info_available);
550 } else {
551 this.mServerInfoSm.setText(R.string.server_info_unavailable);
552 }
553 if (features.pep()) {
554 AxolotlService axolotlService = this.mAccount.getAxolotlService();
555 if (axolotlService != null && axolotlService.isPepBroken()) {
556 this.mServerInfoPep.setText(R.string.server_info_broken);
557 } else {
558 this.mServerInfoPep.setText(R.string.server_info_available);
559 }
560 } else {
561 this.mServerInfoPep.setText(R.string.server_info_unavailable);
562 }
563 if (features.httpUpload()) {
564 this.mServerInfoHttpUpload.setText(R.string.server_info_available);
565 } else {
566 this.mServerInfoHttpUpload.setText(R.string.server_info_unavailable);
567 }
568 final String otrFingerprint = this.mAccount.getOtrFingerprint();
569 if (otrFingerprint != null) {
570 this.mOtrFingerprintBox.setVisibility(View.VISIBLE);
571 this.mOtrFingerprint.setText(CryptoHelper.prettifyFingerprint(otrFingerprint));
572 this.mOtrFingerprintToClipboardButton
573 .setVisibility(View.VISIBLE);
574 this.mOtrFingerprintToClipboardButton
575 .setOnClickListener(new View.OnClickListener() {
576
577 @Override
578 public void onClick(final View v) {
579
580 if (copyTextToClipboard(otrFingerprint, R.string.otr_fingerprint)) {
581 Toast.makeText(
582 EditAccountActivity.this,
583 R.string.toast_message_otr_fingerprint,
584 Toast.LENGTH_SHORT).show();
585 }
586 }
587 });
588 } else {
589 this.mOtrFingerprintBox.setVisibility(View.GONE);
590 }
591 final String axolotlFingerprint = this.mAccount.getAxolotlService().getOwnFingerprint();
592 if (axolotlFingerprint != null) {
593 this.mAxolotlFingerprintBox.setVisibility(View.VISIBLE);
594 this.mAxolotlFingerprint.setText(CryptoHelper.prettifyFingerprint(axolotlFingerprint));
595 this.mAxolotlFingerprintToClipboardButton
596 .setVisibility(View.VISIBLE);
597 this.mAxolotlFingerprintToClipboardButton
598 .setOnClickListener(new View.OnClickListener() {
599
600 @Override
601 public void onClick(final View v) {
602
603 if (copyTextToClipboard(axolotlFingerprint, R.string.omemo_fingerprint)) {
604 Toast.makeText(
605 EditAccountActivity.this,
606 R.string.toast_message_omemo_fingerprint,
607 Toast.LENGTH_SHORT).show();
608 }
609 }
610 });
611 if (Config.SHOW_REGENERATE_AXOLOTL_KEYS_BUTTON) {
612 this.mRegenerateAxolotlKeyButton
613 .setVisibility(View.VISIBLE);
614 this.mRegenerateAxolotlKeyButton
615 .setOnClickListener(new View.OnClickListener() {
616
617 @Override
618 public void onClick(final View v) {
619 showRegenerateAxolotlKeyDialog();
620 }
621 });
622 }
623 } else {
624 this.mAxolotlFingerprintBox.setVisibility(View.GONE);
625 }
626 final String ownFingerprint = mAccount.getAxolotlService().getOwnFingerprint();
627 boolean hasKeys = false;
628 keys.removeAllViews();
629 for (final String fingerprint : mAccount.getAxolotlService().getFingerprintsForOwnSessions()) {
630 if(ownFingerprint.equals(fingerprint)) {
631 continue;
632 }
633 boolean highlight = fingerprint.equals(messageFingerprint);
634 hasKeys |= addFingerprintRow(keys, mAccount, fingerprint, highlight);
635 }
636 if (hasKeys) {
637 keysCard.setVisibility(View.VISIBLE);
638 } else {
639 keysCard.setVisibility(View.GONE);
640 }
641 } else {
642 if (this.mAccount.errorStatus()) {
643 this.mAccountJid.setError(getString(this.mAccount.getStatus().getReadableId()));
644 if (init || !accountInfoEdited()) {
645 this.mAccountJid.requestFocus();
646 }
647 } else {
648 this.mAccountJid.setError(null);
649 }
650 this.mStats.setVisibility(View.GONE);
651 }
652 }
653
654 public void showRegenerateAxolotlKeyDialog() {
655 Builder builder = new Builder(this);
656 builder.setTitle("Regenerate Key");
657 builder.setIconAttribute(android.R.attr.alertDialogIcon);
658 builder.setMessage("Are you sure you want to regenerate your Identity Key? (This will also wipe all established sessions and contact Identity Keys)");
659 builder.setNegativeButton(getString(R.string.cancel), null);
660 builder.setPositiveButton("Yes",
661 new DialogInterface.OnClickListener() {
662 @Override
663 public void onClick(DialogInterface dialog, int which) {
664 mAccount.getAxolotlService().regenerateKeys();
665 }
666 });
667 builder.create().show();
668 }
669
670 public void showWipePepDialog() {
671 Builder builder = new Builder(this);
672 builder.setTitle(getString(R.string.clear_other_devices));
673 builder.setIconAttribute(android.R.attr.alertDialogIcon);
674 builder.setMessage(getString(R.string.clear_other_devices_desc));
675 builder.setNegativeButton(getString(R.string.cancel), null);
676 builder.setPositiveButton(getString(R.string.accept),
677 new DialogInterface.OnClickListener() {
678 @Override
679 public void onClick(DialogInterface dialog, int which) {
680 mAccount.getAxolotlService().wipeOtherPepDevices();
681 }
682 });
683 builder.create().show();
684 }
685
686 @Override
687 public void onKeyStatusUpdated() {
688 refreshUi();
689 }
690
691 @Override
692 public void onCaptchaRequested(final Account account, final String id, final Data data,
693 final Bitmap captcha) {
694 final AlertDialog.Builder builder = new AlertDialog.Builder(this);
695 final ImageView view = new ImageView(this);
696 final LinearLayout layout = new LinearLayout(this);
697 final EditText input = new EditText(this);
698
699 view.setImageBitmap(captcha);
700 view.setScaleType(ImageView.ScaleType.FIT_CENTER);
701
702 input.setHint(getString(R.string.captcha_hint));
703
704 layout.setOrientation(LinearLayout.VERTICAL);
705 layout.addView(view);
706 layout.addView(input);
707
708 builder.setTitle(getString(R.string.captcha_required));
709 builder.setView(layout);
710
711 builder.setPositiveButton(getString(R.string.ok),
712 new DialogInterface.OnClickListener() {
713 @Override
714 public void onClick(DialogInterface dialog, int which) {
715 String rc = input.getText().toString();
716 data.put("username", account.getUsername());
717 data.put("password", account.getPassword());
718 data.put("ocr", rc);
719 data.submit();
720
721 if (xmppConnectionServiceBound) {
722 xmppConnectionService.sendCreateAccountWithCaptchaPacket(
723 account, id, data);
724 }
725 }
726 });
727 builder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
728 @Override
729 public void onClick(DialogInterface dialog, int which) {
730 if (xmppConnectionService != null) {
731 xmppConnectionService.sendCreateAccountWithCaptchaPacket(account, null, null);
732 }
733 }
734 });
735
736 builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
737 @Override
738 public void onCancel(DialogInterface dialog) {
739 if (xmppConnectionService != null) {
740 xmppConnectionService.sendCreateAccountWithCaptchaPacket(account, null, null);
741 }
742 }
743 });
744
745 runOnUiThread(new Runnable() {
746 @Override
747 public void run() {
748 if ((mCaptchaDialog != null) && mCaptchaDialog.isShowing()) {
749 mCaptchaDialog.dismiss();
750 }
751 mCaptchaDialog = builder.create();
752 mCaptchaDialog.show();
753 }
754 });
755 }
756}