/** * Copyright (c) 2013, Redsolution LTD. All rights reserved. * * This file is part of Xabber project; you can redistribute it and/or * modify it under the terms of the GNU General Public License, Version 3. * * Xabber is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License, * along with this program. If not, see http://www.gnu.org/licenses/. */ package com.xabber.android.ui.activity; import android.app.AlertDialog; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.text.ClipboardManager; import android.view.View; import android.view.View.OnClickListener; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.TextView; import com.google.zxing.integration.android.IntentIntegrator; import com.google.zxing.integration.android.IntentResult; import com.xabber.android.R; import com.xabber.android.data.Application; import com.xabber.android.data.account.AccountManager; import com.xabber.android.data.account.listeners.OnAccountChangedListener; import com.xabber.android.data.entity.AccountJid; import com.xabber.android.data.entity.BaseEntity; import com.xabber.android.data.entity.UserJid; import com.xabber.android.data.extension.otr.OTRManager; import com.xabber.android.data.intent.AccountIntentBuilder; import com.xabber.android.data.intent.EntityIntentBuilder; import com.xabber.android.data.roster.AbstractContact; import com.xabber.android.data.roster.OnContactChangedListener; import com.xabber.android.data.roster.RosterContact; import com.xabber.android.data.roster.RosterManager; import com.xabber.android.ui.helper.ContactTitleActionBarInflater; import org.jxmpp.jid.BareJid; import java.util.Collection; public class FingerprintActivity extends ManagedActivity implements OnCheckedChangeListener, OnAccountChangedListener, OnContactChangedListener, OnClickListener { private static final String SAVED_REMOTE_FINGERPRINT = "com.xabber.android.ui.activity.FingerprintViewer.SAVED_REMOTE_FINGERPRINT"; private static final String SAVED_LOCAL_FINGERPRINT = "com.xabber.android.ui.activity.FingerprintViewer.SAVED_LOCAL_FINGERPRINT"; ContactTitleActionBarInflater contactTitleActionBarInflater; private AccountJid account; private UserJid user; private String remoteFingerprint; private String localFingerprint; /** * UI update is in progress. */ private boolean isUpdating; private CheckBox verifiedView; private View scanView; private View showView; private View copyView; /** * QR code scanner and generator. */ private IntentIntegrator integrator; public static Intent createIntent(Context context, AccountJid account, UserJid user) { return new EntityIntentBuilder(context, FingerprintActivity.class) .setAccount(account).setUser(user).build(); } private static AccountJid getAccount(Intent intent) { return AccountIntentBuilder.getAccount(intent); } private static UserJid getUser(Intent intent) { return EntityIntentBuilder.getUser(intent); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (isFinishing()) { return; } setContentView(R.layout.activity_fingerprint); integrator = new IntentIntegrator(this); Intent intent = getIntent(); account = getAccount(intent); user = getUser(intent); if (AccountManager.getInstance().getAccount(account) == null || user == null) { Application.getInstance().onError(R.string.ENTRY_IS_NOT_FOUND); finish(); return; } if (savedInstanceState != null) { remoteFingerprint = savedInstanceState.getString(SAVED_REMOTE_FINGERPRINT); localFingerprint = savedInstanceState.getString(SAVED_LOCAL_FINGERPRINT); } else { remoteFingerprint = OTRManager.getInstance().getRemoteFingerprint(account, user); localFingerprint = OTRManager.getInstance().getLocalFingerprint(account); } verifiedView = (CheckBox) findViewById(R.id.verified); verifiedView.setOnCheckedChangeListener(this); scanView = findViewById(R.id.scan); scanView.setOnClickListener(this); showView = findViewById(R.id.show); showView.setOnClickListener(this); copyView = findViewById(R.id.copy); copyView.setOnClickListener(this); isUpdating = false; contactTitleActionBarInflater = new ContactTitleActionBarInflater(this); contactTitleActionBarInflater.setUpActionBarView(); } @Override protected void onResume() { super.onResume(); Application.getInstance().addUIListener(OnAccountChangedListener.class, this); Application.getInstance().addUIListener(OnContactChangedListener.class, this); update(); } @Override protected void onPause() { super.onPause(); Application.getInstance().removeUIListener(OnAccountChangedListener.class, this); Application.getInstance().removeUIListener(OnContactChangedListener.class, this); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { isUpdating = true; super.onRestoreInstanceState(savedInstanceState); isUpdating = false; } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putString(SAVED_REMOTE_FINGERPRINT, remoteFingerprint); outState.putString(SAVED_LOCAL_FINGERPRINT, localFingerprint); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); IntentResult scanResult = IntentIntegrator.parseActivityResult( requestCode, resultCode, data); if (scanResult != null) { String code = scanResult.getContents(); boolean equals = code != null && code.equals(remoteFingerprint); verifiedView.setChecked(equals); int dialogMessageId; if (equals) { dialogMessageId = R.string.action_otr_smp_verified; } else { dialogMessageId = R.string.action_otr_smp_unverified; } new AlertDialog.Builder(this).setMessage(dialogMessageId) .setNeutralButton(android.R.string.ok, null).show(); } } @Override public void onContactsChanged(Collection<RosterContact> entities) { BareJid thisBareAddress = user.getBareJid(); for (BaseEntity entity : entities) { if (entity.equals(account, thisBareAddress)) { update(); break; } } } @Override public void onAccountsChanged(Collection<AccountJid> accounts) { if (accounts.contains(account)) { update(); } } @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { switch (buttonView.getId()) { case R.id.verified: if (!isUpdating) { OTRManager.getInstance().setVerify(account, user, remoteFingerprint, isChecked); } break; default: break; } } @Override public void onClick(View view) { switch (view.getId()) { case R.id.scan: integrator.initiateScan(IntentIntegrator.QR_CODE_TYPES); break; case R.id.show: integrator.shareText(localFingerprint); break; case R.id.copy: ((ClipboardManager) getSystemService(CLIPBOARD_SERVICE)) .setText(((TextView) findViewById(R.id.otr_local_fingerprint)).getText()); break; default: break; } } private void update() { isUpdating = true; AbstractContact abstractContact = RosterManager.getInstance().getBestContact(account, user); verifiedView.setChecked(OTRManager.getInstance().isVerified(account, user)); scanView.setEnabled(remoteFingerprint != null); verifiedView.setEnabled(remoteFingerprint != null); ((TextView) findViewById(R.id.otr_remote_fingerprint)).setText( remoteFingerprint == null ? getString(R.string.unknown) : showFingerprint(remoteFingerprint)); showView.setEnabled(localFingerprint != null); copyView.setEnabled(localFingerprint != null); ((TextView) findViewById(R.id.otr_local_fingerprint)).setText( localFingerprint == null ? getString(R.string.unknown) : showFingerprint(localFingerprint)); contactTitleActionBarInflater.update(abstractContact); isUpdating = false; } /** * @param fingerprint * @return Formatted fingerprint to be shown. */ private static String showFingerprint(String fingerprint) { if (fingerprint == null) return null; StringBuffer buffer = new StringBuffer(); for (int index = 0; index < fingerprint.length(); index++) { if (index > 0 && index % 2 == 0) buffer.append(':'); buffer.append(fingerprint.charAt(index)); } return buffer.toString().toUpperCase(); } }