improved OTR verification part one
This commit is contained in:
parent
b71740f0d4
commit
3833e6dfef
|
@ -34,7 +34,7 @@ import net.java.otr4j.crypto.OtrCryptoException;
|
||||||
import net.java.otr4j.session.InstanceTag;
|
import net.java.otr4j.session.InstanceTag;
|
||||||
import net.java.otr4j.session.SessionID;
|
import net.java.otr4j.session.SessionID;
|
||||||
|
|
||||||
public class OtrEngine implements OtrEngineHost {
|
public class OtrEngine extends OtrCryptoEngineImpl implements OtrEngineHost {
|
||||||
|
|
||||||
private Account account;
|
private Account account;
|
||||||
private OtrPolicy otrPolicy;
|
private OtrPolicy otrPolicy;
|
||||||
|
@ -258,10 +258,10 @@ public class OtrEngine implements OtrEngineHost {
|
||||||
Conversation conversation = this.mXmppConnectionService.find(this.account,jid);
|
Conversation conversation = this.mXmppConnectionService.find(this.account,jid);
|
||||||
if (conversation!=null) {
|
if (conversation!=null) {
|
||||||
if (approved) {
|
if (approved) {
|
||||||
conversation.getContact().addOtrFingerprint(CryptoHelper.prettifyFingerprint(fingerprint));
|
conversation.getContact().addOtrFingerprint(fingerprint);
|
||||||
}
|
}
|
||||||
conversation.smp().hint = null;
|
conversation.smp().hint = null;
|
||||||
conversation.smp().status = Conversation.Smp.STATUS_FINISHED;
|
conversation.smp().status = Conversation.Smp.STATUS_VERIFIED;
|
||||||
mXmppConnectionService.updateConversationUi();
|
mXmppConnectionService.updateConversationUi();
|
||||||
mXmppConnectionService.syncRosterToDisk(conversation.getAccount());
|
mXmppConnectionService.syncRosterToDisk(conversation.getAccount());
|
||||||
}
|
}
|
||||||
|
|
|
@ -453,7 +453,7 @@ public class Contact implements ListItem, Blockable {
|
||||||
public String getShareableUri() {
|
public String getShareableUri() {
|
||||||
if (getOtrFingerprints().size() >= 1) {
|
if (getOtrFingerprints().size() >= 1) {
|
||||||
String otr = getOtrFingerprints().get(0);
|
String otr = getOtrFingerprints().get(0);
|
||||||
return "xmpp:" + getJid().toBareJid().toString() + "?otr-fingerprint=" + otr.replace(" ", "");
|
return "xmpp:" + getJid().toBareJid().toString() + "?otr-fingerprint=" + otr;
|
||||||
} else {
|
} else {
|
||||||
return "xmpp:" + getJid().toBareJid().toString();
|
return "xmpp:" + getJid().toBareJid().toString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -436,30 +436,29 @@ public class Conversation extends AbstractEntity implements Blockable {
|
||||||
return this.otrSession != null;
|
return this.otrSession != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getOtrFingerprint() {
|
public synchronized String getOtrFingerprint() {
|
||||||
if (this.otrFingerprint == null) {
|
if (this.otrFingerprint == null) {
|
||||||
try {
|
try {
|
||||||
if (getOtrSession() == null) {
|
if (getOtrSession() == null || getOtrSession().getSessionStatus() != SessionStatus.ENCRYPTED) {
|
||||||
return "";
|
return null;
|
||||||
}
|
}
|
||||||
DSAPublicKey remotePubKey = (DSAPublicKey) getOtrSession()
|
DSAPublicKey remotePubKey = (DSAPublicKey) getOtrSession().getRemotePublicKey();
|
||||||
.getRemotePublicKey();
|
this.otrFingerprint = getAccount().getOtrEngine().getFingerprint(remotePubKey);
|
||||||
StringBuilder builder = new StringBuilder(
|
|
||||||
new OtrCryptoEngineImpl().getFingerprint(remotePubKey));
|
|
||||||
builder.insert(8, " ");
|
|
||||||
builder.insert(17, " ");
|
|
||||||
builder.insert(26, " ");
|
|
||||||
builder.insert(35, " ");
|
|
||||||
this.otrFingerprint = builder.toString();
|
|
||||||
} catch (final OtrCryptoException | UnsupportedOperationException ignored) {
|
} catch (final OtrCryptoException | UnsupportedOperationException ignored) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.otrFingerprint;
|
return this.otrFingerprint;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void verifyOtrFingerprint() {
|
public boolean verifyOtrFingerprint() {
|
||||||
getContact().addOtrFingerprint(getOtrFingerprint());
|
final String fingerprint = getOtrFingerprint();
|
||||||
|
if (fingerprint != null) {
|
||||||
|
getContact().addOtrFingerprint(fingerprint);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOtrFingerprintVerified() {
|
public boolean isOtrFingerprintVerified() {
|
||||||
|
@ -708,7 +707,7 @@ public class Conversation extends AbstractEntity implements Blockable {
|
||||||
public static final int STATUS_CONTACT_REQUESTED = 1;
|
public static final int STATUS_CONTACT_REQUESTED = 1;
|
||||||
public static final int STATUS_WE_REQUESTED = 2;
|
public static final int STATUS_WE_REQUESTED = 2;
|
||||||
public static final int STATUS_FAILED = 3;
|
public static final int STATUS_FAILED = 3;
|
||||||
public static final int STATUS_FINISHED = 4;
|
public static final int STATUS_VERIFIED = 4;
|
||||||
|
|
||||||
public String secret = null;
|
public String secret = null;
|
||||||
public String hint = null;
|
public String hint = null;
|
||||||
|
|
|
@ -22,7 +22,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
||||||
private static DatabaseBackend instance = null;
|
private static DatabaseBackend instance = null;
|
||||||
|
|
||||||
private static final String DATABASE_NAME = "history";
|
private static final String DATABASE_NAME = "history";
|
||||||
private static final int DATABASE_VERSION = 12;
|
private static final int DATABASE_VERSION = 13;
|
||||||
|
|
||||||
private static String CREATE_CONTATCS_STATEMENT = "create table "
|
private static String CREATE_CONTATCS_STATEMENT = "create table "
|
||||||
+ Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, "
|
+ Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, "
|
||||||
|
@ -126,6 +126,10 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
||||||
db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN "
|
db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN "
|
||||||
+ Message.SERVER_MSG_ID + " TEXT");
|
+ Message.SERVER_MSG_ID + " TEXT");
|
||||||
}
|
}
|
||||||
|
if (oldVersion < 13 && newVersion >= 13) {
|
||||||
|
db.execSQL("delete from "+Contact.TABLENAME);
|
||||||
|
db.execSQL("update "+Account.TABLENAME+" set "+Account.ROSTERVERSION+" = NULL");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized DatabaseBackend getInstance(Context context) {
|
public static synchronized DatabaseBackend getInstance(Context context) {
|
||||||
|
|
|
@ -37,6 +37,7 @@ import eu.siacs.conversations.entities.Contact;
|
||||||
import eu.siacs.conversations.entities.ListItem;
|
import eu.siacs.conversations.entities.ListItem;
|
||||||
import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate;
|
import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate;
|
||||||
import eu.siacs.conversations.services.XmppConnectionService.OnRosterUpdate;
|
import eu.siacs.conversations.services.XmppConnectionService.OnRosterUpdate;
|
||||||
|
import eu.siacs.conversations.utils.CryptoHelper;
|
||||||
import eu.siacs.conversations.utils.UIHelper;
|
import eu.siacs.conversations.utils.UIHelper;
|
||||||
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
|
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
|
||||||
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
|
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
|
||||||
|
@ -315,7 +316,7 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd
|
||||||
.findViewById(R.id.button_remove);
|
.findViewById(R.id.button_remove);
|
||||||
remove.setVisibility(View.VISIBLE);
|
remove.setVisibility(View.VISIBLE);
|
||||||
keyType.setText("OTR Fingerprint");
|
keyType.setText("OTR Fingerprint");
|
||||||
key.setText(otrFingerprint);
|
key.setText(CryptoHelper.prettifyFingerprint(otrFingerprint));
|
||||||
keys.addView(view);
|
keys.addView(view);
|
||||||
remove.setOnClickListener(new OnClickListener() {
|
remove.setOnClickListener(new OnClickListener() {
|
||||||
|
|
||||||
|
@ -396,8 +397,7 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
if (contact.deleteOtrFingerprint(fingerprint)) {
|
if (contact.deleteOtrFingerprint(fingerprint)) {
|
||||||
populateView();
|
populateView();
|
||||||
xmppConnectionService.syncRosterToDisk(contact
|
xmppConnectionService.syncRosterToDisk(contact.getAccount());
|
||||||
.getAccount());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,8 @@ import android.widget.PopupMenu;
|
||||||
import android.widget.PopupMenu.OnMenuItemClickListener;
|
import android.widget.PopupMenu.OnMenuItemClickListener;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import net.java.otr4j.session.SessionStatus;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -555,6 +557,41 @@ public class ConversationActivity extends XmppActivity
|
||||||
attachFilePopup.show();
|
attachFilePopup.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void verifyOtrSessionDialog(final Conversation conversation, View view) {
|
||||||
|
if (!conversation.hasValidOtrSession() || conversation.getOtrSession().getSessionStatus() != SessionStatus.ENCRYPTED) {
|
||||||
|
Toast.makeText(this, R.string.otr_session_not_started, Toast.LENGTH_LONG).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (view == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PopupMenu popup = new PopupMenu(this, view);
|
||||||
|
popup.inflate(R.menu.verification_choices);
|
||||||
|
popup.setOnMenuItemClickListener(new OnMenuItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemClick(MenuItem menuItem) {
|
||||||
|
Intent intent = new Intent(ConversationActivity.this, VerifyOTRActivity.class);
|
||||||
|
intent.setAction(VerifyOTRActivity.ACTION_VERIFY_CONTACT);
|
||||||
|
intent.putExtra("contact", conversation.getContact().getJid().toBareJid().toString());
|
||||||
|
intent.putExtra("account", conversation.getAccount().getJid().toBareJid().toString());
|
||||||
|
switch (menuItem.getItemId()) {
|
||||||
|
case R.id.scan_fingerprint:
|
||||||
|
intent.putExtra("mode",VerifyOTRActivity.MODE_SCAN_FINGERPRINT);
|
||||||
|
break;
|
||||||
|
case R.id.ask_question:
|
||||||
|
intent.putExtra("mode",VerifyOTRActivity.MODE_ASK_QUESTION);
|
||||||
|
break;
|
||||||
|
case R.id.manual_verification:
|
||||||
|
intent.putExtra("mode",VerifyOTRActivity.MODE_MANUAL_VERIFICATION);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
startActivity(intent);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
popup.show();
|
||||||
|
}
|
||||||
|
|
||||||
protected void selectEncryptionDialog(final Conversation conversation) {
|
protected void selectEncryptionDialog(final Conversation conversation) {
|
||||||
View menuItemView = findViewById(R.id.action_security);
|
View menuItemView = findViewById(R.id.action_security);
|
||||||
if (menuItemView == null) {
|
if (menuItemView == null) {
|
||||||
|
|
|
@ -204,13 +204,7 @@ public class ConversationFragment extends Fragment {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
if (conversation.getOtrFingerprint() != null) {
|
activity.verifyOtrSessionDialog(conversation,v);
|
||||||
Intent intent = new Intent(getActivity(), VerifyOTRActivity.class);
|
|
||||||
intent.setAction(VerifyOTRActivity.ACTION_VERIFY_CONTACT);
|
|
||||||
intent.putExtra("contact", conversation.getContact().getJid().toBareJid().toString());
|
|
||||||
intent.putExtra("account", conversation.getAccount().getJid().toBareJid().toString());
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private ConcurrentLinkedQueue<Message> mEncryptedMessages = new ConcurrentLinkedQueue<>();
|
private ConcurrentLinkedQueue<Message> mEncryptedMessages = new ConcurrentLinkedQueue<>();
|
||||||
|
@ -796,7 +790,17 @@ public class ConversationFragment extends Fragment {
|
||||||
|
|
||||||
protected void makeFingerprintWarning() {
|
protected void makeFingerprintWarning() {
|
||||||
if (conversation.smpRequested()) {
|
if (conversation.smpRequested()) {
|
||||||
showSnackbar(R.string.smp_requested, R.string.verify, clickToVerify);
|
showSnackbar(R.string.smp_requested, R.string.verify, new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
Intent intent = new Intent(activity, VerifyOTRActivity.class);
|
||||||
|
intent.setAction(VerifyOTRActivity.ACTION_VERIFY_CONTACT);
|
||||||
|
intent.putExtra("contact", conversation.getContact().getJid().toBareJid().toString());
|
||||||
|
intent.putExtra("account", conversation.getAccount().getJid().toBareJid().toString());
|
||||||
|
intent.putExtra("mode",VerifyOTRActivity.MODE_ANSWER_QUESTION);
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
} else if (conversation.hasValidOtrSession() && (conversation.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED)
|
} else if (conversation.hasValidOtrSession() && (conversation.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED)
|
||||||
&& (!conversation.isOtrFingerprintVerified())) {
|
&& (!conversation.isOtrFingerprintVerified())) {
|
||||||
showSnackbar(R.string.unknown_otr_fingerprint, R.string.verify, clickToVerify);
|
showSnackbar(R.string.unknown_otr_fingerprint, R.string.verify, clickToVerify);
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
package eu.siacs.conversations.ui;
|
package eu.siacs.conversations.ui;
|
||||||
|
|
||||||
|
import android.app.ActionBar;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.Menu;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
@ -32,59 +33,58 @@ import eu.siacs.conversations.xmpp.jid.Jid;
|
||||||
public class VerifyOTRActivity extends XmppActivity implements XmppConnectionService.OnConversationUpdate {
|
public class VerifyOTRActivity extends XmppActivity implements XmppConnectionService.OnConversationUpdate {
|
||||||
|
|
||||||
public static final String ACTION_VERIFY_CONTACT = "verify_contact";
|
public static final String ACTION_VERIFY_CONTACT = "verify_contact";
|
||||||
|
public static final int MODE_SCAN_FINGERPRINT = - 0x0502;
|
||||||
|
public static final int MODE_ASK_QUESTION = 0x0503;
|
||||||
|
public static final int MODE_ANSWER_QUESTION = 0x0504;
|
||||||
|
public static final int MODE_MANUAL_VERIFICATION = 0x0505;
|
||||||
|
|
||||||
private RelativeLayout mVerificationAreaOne;
|
private LinearLayout mManualVerificationArea;
|
||||||
private RelativeLayout mVerificationAreaTwo;
|
private LinearLayout mSmpVerificationArea;
|
||||||
private TextView mErrorNoSession;
|
|
||||||
private TextView mRemoteJid;
|
|
||||||
private TextView mRemoteFingerprint;
|
private TextView mRemoteFingerprint;
|
||||||
private TextView mYourFingerprint;
|
private TextView mYourFingerprint;
|
||||||
private EditText mSharedSecretHint;
|
private TextView mVerificationExplain;
|
||||||
private EditText mSharedSecretSecret;
|
|
||||||
private Button mButtonScanQrCode;
|
|
||||||
private Button mButtonShowQrCode;
|
|
||||||
private Button mButtonSharedSecretPositive;
|
|
||||||
private Button mButtonSharedSecretNegative;
|
|
||||||
private TextView mStatusMessage;
|
private TextView mStatusMessage;
|
||||||
|
private TextView mSharedSecretHint;
|
||||||
|
private EditText mSharedSecretHintEditable;
|
||||||
|
private EditText mSharedSecretSecret;
|
||||||
|
private Button mLeftButton;
|
||||||
|
private Button mRightButton;
|
||||||
private Account mAccount;
|
private Account mAccount;
|
||||||
private Conversation mConversation;
|
private Conversation mConversation;
|
||||||
|
private int mode = MODE_MANUAL_VERIFICATION;
|
||||||
|
private XmppUri mPendingUri = null;
|
||||||
|
|
||||||
private DialogInterface.OnClickListener mVerifyFingerprintListener = new DialogInterface.OnClickListener() {
|
private DialogInterface.OnClickListener mVerifyFingerprintListener = new DialogInterface.OnClickListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialogInterface, int click) {
|
public void onClick(DialogInterface dialogInterface, int click) {
|
||||||
mConversation.verifyOtrFingerprint();
|
mConversation.verifyOtrFingerprint();
|
||||||
updateView();
|
|
||||||
xmppConnectionService.syncRosterToDisk(mConversation.getAccount());
|
xmppConnectionService.syncRosterToDisk(mConversation.getAccount());
|
||||||
|
Toast.makeText(VerifyOTRActivity.this,R.string.verified,Toast.LENGTH_SHORT).show();
|
||||||
|
finish();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private View.OnClickListener mShowQrCodeListener = new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(final View view) {
|
|
||||||
showQrCode();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private View.OnClickListener mScanQrCodeListener = new View.OnClickListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
new IntentIntegrator(VerifyOTRActivity.this).initiateScan();
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
private View.OnClickListener mCreateSharedSecretListener = new View.OnClickListener() {
|
private View.OnClickListener mCreateSharedSecretListener = new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(final View view) {
|
public void onClick(final View view) {
|
||||||
if (isAccountOnline()) {
|
if (isAccountOnline()) {
|
||||||
final String question = mSharedSecretHint.getText().toString();
|
final String question = mSharedSecretHintEditable.getText().toString();
|
||||||
final String secret = mSharedSecretSecret.getText().toString();
|
final String secret = mSharedSecretSecret.getText().toString();
|
||||||
|
if (question.trim().isEmpty()) {
|
||||||
|
mSharedSecretHintEditable.requestFocus();
|
||||||
|
mSharedSecretHintEditable.setError(getString(R.string.shared_secret_hint_should_not_be_empty));
|
||||||
|
} else if (secret.trim().isEmpty()) {
|
||||||
|
mSharedSecretSecret.requestFocus();
|
||||||
|
mSharedSecretSecret.setError(getString(R.string.shared_secret_can_not_be_empty));
|
||||||
|
} else {
|
||||||
|
mSharedSecretSecret.setError(null);
|
||||||
|
mSharedSecretHintEditable.setError(null);
|
||||||
initSmp(question, secret);
|
initSmp(question, secret);
|
||||||
updateView();
|
updateView();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
private View.OnClickListener mCancelSharedSecretListener = new View.OnClickListener() {
|
private View.OnClickListener mCancelSharedSecretListener = new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -100,7 +100,7 @@ public class VerifyOTRActivity extends XmppActivity implements XmppConnectionSer
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
if (isAccountOnline()) {
|
if (isAccountOnline()) {
|
||||||
final String question = mSharedSecretHint.getText().toString();
|
final String question = mSharedSecretHintEditable.getText().toString();
|
||||||
final String secret = mSharedSecretSecret.getText().toString();
|
final String secret = mSharedSecretSecret.getText().toString();
|
||||||
respondSmp(question, secret);
|
respondSmp(question, secret);
|
||||||
updateView();
|
updateView();
|
||||||
|
@ -124,14 +124,14 @@ public class VerifyOTRActivity extends XmppActivity implements XmppConnectionSer
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private XmppUri mPendingUri = null;
|
|
||||||
|
|
||||||
protected boolean initSmp(final String question, final String secret) {
|
protected boolean initSmp(final String question, final String secret) {
|
||||||
final Session session = mConversation.getOtrSession();
|
final Session session = mConversation.getOtrSession();
|
||||||
if (session!=null) {
|
if (session!=null) {
|
||||||
try {
|
try {
|
||||||
session.initSmp(question, secret);
|
session.initSmp(question, secret);
|
||||||
mConversation.smp().status = Conversation.Smp.STATUS_WE_REQUESTED;
|
mConversation.smp().status = Conversation.Smp.STATUS_WE_REQUESTED;
|
||||||
|
mConversation.smp().secret = secret;
|
||||||
|
mConversation.smp().hint = question;
|
||||||
return true;
|
return true;
|
||||||
} catch (OtrException e) {
|
} catch (OtrException e) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -172,15 +172,17 @@ public class VerifyOTRActivity extends XmppActivity implements XmppConnectionSer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void verifyWithUri(XmppUri uri) {
|
protected boolean verifyWithUri(XmppUri uri) {
|
||||||
Contact contact = mConversation.getContact();
|
Contact contact = mConversation.getContact();
|
||||||
if (this.mConversation.getContact().getJid().equals(uri.getJid()) && uri.getFingerprint() != null) {
|
if (this.mConversation.getContact().getJid().equals(uri.getJid()) && uri.getFingerprint() != null) {
|
||||||
contact.addOtrFingerprint(uri.getFingerprint());
|
contact.addOtrFingerprint(uri.getFingerprint());
|
||||||
Toast.makeText(this,R.string.verified,Toast.LENGTH_SHORT).show();
|
Toast.makeText(this,R.string.verified,Toast.LENGTH_SHORT).show();
|
||||||
updateView();
|
updateView();
|
||||||
xmppConnectionService.syncRosterToDisk(contact.getAccount());
|
xmppConnectionService.syncRosterToDisk(contact.getAccount());
|
||||||
|
return true;
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this,R.string.could_not_verify_fingerprint,Toast.LENGTH_SHORT).show();
|
Toast.makeText(this,R.string.could_not_verify_fingerprint,Toast.LENGTH_SHORT).show();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,7 +196,7 @@ public class VerifyOTRActivity extends XmppActivity implements XmppConnectionSer
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean handleIntent(Intent intent) {
|
protected boolean handleIntent(Intent intent) {
|
||||||
if (intent.getAction().equals(ACTION_VERIFY_CONTACT)) {
|
if (intent != null && intent.getAction().equals(ACTION_VERIFY_CONTACT)) {
|
||||||
try {
|
try {
|
||||||
this.mAccount = this.xmppConnectionService.findAccountByJid(Jid.fromString(intent.getExtras().getString("account")));
|
this.mAccount = this.xmppConnectionService.findAccountByJid(Jid.fromString(intent.getExtras().getString("account")));
|
||||||
} catch (final InvalidJidException ignored) {
|
} catch (final InvalidJidException ignored) {
|
||||||
|
@ -208,6 +210,11 @@ public class VerifyOTRActivity extends XmppActivity implements XmppConnectionSer
|
||||||
} catch (final InvalidJidException ignored) {
|
} catch (final InvalidJidException ignored) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
this.mode = intent.getIntExtra("mode", MODE_MANUAL_VERIFICATION);
|
||||||
|
if (this.mode == MODE_SCAN_FINGERPRINT) {
|
||||||
|
new IntentIntegrator(this).initiateScan();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
@ -223,9 +230,12 @@ public class VerifyOTRActivity extends XmppActivity implements XmppConnectionSer
|
||||||
XmppUri uri = new XmppUri(data);
|
XmppUri uri = new XmppUri(data);
|
||||||
if (xmppConnectionServiceBound) {
|
if (xmppConnectionServiceBound) {
|
||||||
verifyWithUri(uri);
|
verifyWithUri(uri);
|
||||||
|
finish();
|
||||||
} else {
|
} else {
|
||||||
this.mPendingUri = uri;
|
this.mPendingUri = uri;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
super.onActivityResult(requestCode, requestCode, intent);
|
super.onActivityResult(requestCode, requestCode, intent);
|
||||||
|
@ -234,84 +244,139 @@ public class VerifyOTRActivity extends XmppActivity implements XmppConnectionSer
|
||||||
@Override
|
@Override
|
||||||
protected void onBackendConnected() {
|
protected void onBackendConnected() {
|
||||||
if (handleIntent(getIntent())) {
|
if (handleIntent(getIntent())) {
|
||||||
if (mPendingUri!=null) {
|
updateView();
|
||||||
|
} else if (mPendingUri!=null) {
|
||||||
verifyWithUri(mPendingUri);
|
verifyWithUri(mPendingUri);
|
||||||
|
finish();
|
||||||
mPendingUri = null;
|
mPendingUri = null;
|
||||||
}
|
}
|
||||||
updateView();
|
setIntent(null);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void updateView() {
|
protected void updateView() {
|
||||||
if (this.mConversation.hasValidOtrSession()) {
|
if (this.mConversation.hasValidOtrSession()) {
|
||||||
|
final ActionBar actionBar = getActionBar();
|
||||||
|
this.mVerificationExplain.setText(R.string.no_otr_session_found);
|
||||||
invalidateOptionsMenu();
|
invalidateOptionsMenu();
|
||||||
this.mVerificationAreaOne.setVisibility(View.VISIBLE);
|
switch(this.mode) {
|
||||||
this.mVerificationAreaTwo.setVisibility(View.VISIBLE);
|
case MODE_ASK_QUESTION:
|
||||||
this.mErrorNoSession.setVisibility(View.GONE);
|
if (actionBar != null ) {
|
||||||
|
actionBar.setTitle(R.string.ask_question);
|
||||||
|
}
|
||||||
|
this.updateViewAskQuestion();
|
||||||
|
break;
|
||||||
|
case MODE_ANSWER_QUESTION:
|
||||||
|
if (actionBar != null ) {
|
||||||
|
actionBar.setTitle(R.string.smp_requested);
|
||||||
|
}
|
||||||
|
this.updateViewAnswerQuestion();
|
||||||
|
break;
|
||||||
|
case MODE_MANUAL_VERIFICATION:
|
||||||
|
default:
|
||||||
|
if (actionBar != null ) {
|
||||||
|
actionBar.setTitle(R.string.manually_verify);
|
||||||
|
}
|
||||||
|
this.updateViewManualVerification();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.mManualVerificationArea.setVisibility(View.GONE);
|
||||||
|
this.mSmpVerificationArea.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateViewManualVerification() {
|
||||||
|
this.mVerificationExplain.setText(R.string.manual_verification_explanation);
|
||||||
|
this.mManualVerificationArea.setVisibility(View.VISIBLE);
|
||||||
|
this.mSmpVerificationArea.setVisibility(View.GONE);
|
||||||
this.mYourFingerprint.setText(CryptoHelper.prettifyFingerprint(this.mAccount.getOtrFingerprint()));
|
this.mYourFingerprint.setText(CryptoHelper.prettifyFingerprint(this.mAccount.getOtrFingerprint()));
|
||||||
this.mRemoteFingerprint.setText(this.mConversation.getOtrFingerprint());
|
this.mRemoteFingerprint.setText(CryptoHelper.prettifyFingerprint(this.mConversation.getOtrFingerprint()));
|
||||||
this.mRemoteJid.setText(this.mConversation.getContact().getJid().toBareJid().toString());
|
if (this.mConversation.isOtrFingerprintVerified()) {
|
||||||
Conversation.Smp smp = mConversation.smp();
|
deactivateButton(this.mRightButton,R.string.verified);
|
||||||
Session session = mConversation.getOtrSession();
|
activateButton(this.mLeftButton,R.string.cancel,this.mFinishListener);
|
||||||
if (mConversation.isOtrFingerprintVerified()) {
|
|
||||||
deactivateButton(mButtonScanQrCode, R.string.verified);
|
|
||||||
} else {
|
} else {
|
||||||
activateButton(mButtonScanQrCode, R.string.scan_qr_code, mScanQrCodeListener);
|
activateButton(this.mLeftButton,R.string.cancel,this.mFinishListener);
|
||||||
|
activateButton(this.mRightButton,R.string.verify, new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
showManuallyVerifyDialog();
|
||||||
}
|
}
|
||||||
if (smp.status == Conversation.Smp.STATUS_NONE) {
|
});
|
||||||
activateButton(mButtonSharedSecretPositive, R.string.create, mCreateSharedSecretListener);
|
}
|
||||||
deactivateButton(mButtonSharedSecretNegative, R.string.cancel);
|
}
|
||||||
this.mSharedSecretHint.setFocusableInTouchMode(true);
|
|
||||||
this.mSharedSecretSecret.setFocusableInTouchMode(true);
|
protected void updateViewAskQuestion() {
|
||||||
|
this.mManualVerificationArea.setVisibility(View.GONE);
|
||||||
|
this.mSmpVerificationArea.setVisibility(View.VISIBLE);
|
||||||
|
this.mVerificationExplain.setText(R.string.smp_explain_question);
|
||||||
|
final int smpStatus = this.mConversation.smp().status;
|
||||||
|
switch (smpStatus) {
|
||||||
|
case Conversation.Smp.STATUS_WE_REQUESTED:
|
||||||
|
this.mStatusMessage.setVisibility(View.GONE);
|
||||||
|
this.mSharedSecretHintEditable.setVisibility(View.VISIBLE);
|
||||||
|
this.mSharedSecretSecret.setVisibility(View.VISIBLE);
|
||||||
|
this.mSharedSecretHintEditable.setText(this.mConversation.smp().hint);
|
||||||
|
this.mSharedSecretSecret.setText(this.mConversation.smp().secret);
|
||||||
|
this.activateButton(this.mLeftButton, R.string.cancel, this.mCancelSharedSecretListener);
|
||||||
|
this.deactivateButton(this.mRightButton, R.string.in_progress);
|
||||||
|
break;
|
||||||
|
case Conversation.Smp.STATUS_FAILED:
|
||||||
|
this.mStatusMessage.setVisibility(View.GONE);
|
||||||
|
this.mSharedSecretHintEditable.setVisibility(View.VISIBLE);
|
||||||
|
this.mSharedSecretSecret.setVisibility(View.VISIBLE);
|
||||||
|
this.mSharedSecretSecret.requestFocus();
|
||||||
|
this.mSharedSecretSecret.setError(getString(R.string.secrets_do_not_match));
|
||||||
|
this.deactivateButton(this.mLeftButton, R.string.cancel);
|
||||||
|
this.activateButton(this.mRightButton, R.string.try_again, this.mRetrySharedSecretListener);
|
||||||
|
break;
|
||||||
|
case Conversation.Smp.STATUS_VERIFIED:
|
||||||
|
this.mSharedSecretHintEditable.setText("");
|
||||||
|
this.mSharedSecretHintEditable.setVisibility(View.GONE);
|
||||||
this.mSharedSecretSecret.setText("");
|
this.mSharedSecretSecret.setText("");
|
||||||
this.mSharedSecretHint.setText("");
|
|
||||||
this.mSharedSecretHint.setVisibility(View.VISIBLE);
|
|
||||||
this.mSharedSecretSecret.setVisibility(View.VISIBLE);
|
|
||||||
this.mStatusMessage.setVisibility(View.GONE);
|
|
||||||
} else if (smp.status == Conversation.Smp.STATUS_CONTACT_REQUESTED) {
|
|
||||||
this.mSharedSecretHint.setFocusable(false);
|
|
||||||
this.mSharedSecretHint.setText(smp.hint);
|
|
||||||
this.mSharedSecretSecret.setFocusableInTouchMode(true);
|
|
||||||
this.mSharedSecretHint.setVisibility(View.VISIBLE);
|
|
||||||
this.mSharedSecretSecret.setVisibility(View.VISIBLE);
|
|
||||||
this.mStatusMessage.setVisibility(View.GONE);
|
|
||||||
deactivateButton(mButtonSharedSecretNegative, R.string.cancel);
|
|
||||||
activateButton(mButtonSharedSecretPositive, R.string.respond, mRespondSharedSecretListener);
|
|
||||||
} else if (smp.status == Conversation.Smp.STATUS_FAILED) {
|
|
||||||
activateButton(mButtonSharedSecretNegative, R.string.cancel, mFinishListener);
|
|
||||||
activateButton(mButtonSharedSecretPositive, R.string.try_again, mRetrySharedSecretListener);
|
|
||||||
this.mSharedSecretHint.setVisibility(View.GONE);
|
|
||||||
this.mSharedSecretSecret.setVisibility(View.GONE);
|
this.mSharedSecretSecret.setVisibility(View.GONE);
|
||||||
this.mStatusMessage.setVisibility(View.VISIBLE);
|
this.mStatusMessage.setVisibility(View.VISIBLE);
|
||||||
this.mStatusMessage.setText(R.string.secrets_do_not_match);
|
this.deactivateButton(this.mLeftButton, R.string.cancel);
|
||||||
this.mStatusMessage.setTextColor(getWarningTextColor());
|
this.activateButton(this.mRightButton, R.string.finish, this.mFinishListener);
|
||||||
} else if (smp.status == Conversation.Smp.STATUS_FINISHED) {
|
break;
|
||||||
this.mSharedSecretHint.setText("");
|
default:
|
||||||
|
this.mStatusMessage.setVisibility(View.GONE);
|
||||||
|
this.mSharedSecretHintEditable.setVisibility(View.VISIBLE);
|
||||||
|
this.mSharedSecretSecret.setVisibility(View.VISIBLE);
|
||||||
|
this.activateButton(this.mLeftButton,R.string.cancel,this.mFinishListener);
|
||||||
|
this.activateButton(this.mRightButton, R.string.ask_question, this.mCreateSharedSecretListener);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateViewAnswerQuestion() {
|
||||||
|
this.mManualVerificationArea.setVisibility(View.GONE);
|
||||||
|
this.mSmpVerificationArea.setVisibility(View.VISIBLE);
|
||||||
|
this.mVerificationExplain.setText(R.string.smp_explain_answer);
|
||||||
|
this.mSharedSecretHintEditable.setVisibility(View.GONE);
|
||||||
|
this.mSharedSecretHint.setVisibility(View.VISIBLE);
|
||||||
|
this.deactivateButton(this.mLeftButton, R.string.cancel);
|
||||||
|
final int smpStatus = this.mConversation.smp().status;
|
||||||
|
switch (smpStatus) {
|
||||||
|
case Conversation.Smp.STATUS_CONTACT_REQUESTED:
|
||||||
|
this.mStatusMessage.setVisibility(View.GONE);
|
||||||
|
this.mSharedSecretHint.setText(this.mConversation.smp().hint);
|
||||||
|
this.activateButton(this.mRightButton,R.string.respond,this.mRespondSharedSecretListener);
|
||||||
|
break;
|
||||||
|
case Conversation.Smp.STATUS_VERIFIED:
|
||||||
|
this.mSharedSecretHintEditable.setText("");
|
||||||
|
this.mSharedSecretHintEditable.setVisibility(View.GONE);
|
||||||
this.mSharedSecretHint.setVisibility(View.GONE);
|
this.mSharedSecretHint.setVisibility(View.GONE);
|
||||||
this.mSharedSecretSecret.setText("");
|
this.mSharedSecretSecret.setText("");
|
||||||
this.mSharedSecretSecret.setVisibility(View.GONE);
|
this.mSharedSecretSecret.setVisibility(View.GONE);
|
||||||
this.mStatusMessage.setVisibility(View.VISIBLE);
|
this.mStatusMessage.setVisibility(View.VISIBLE);
|
||||||
this.mStatusMessage.setTextColor(getPrimaryColor());
|
this.activateButton(this.mRightButton, R.string.finish, this.mFinishListener);
|
||||||
deactivateButton(mButtonSharedSecretNegative, R.string.cancel);
|
break;
|
||||||
if (mConversation.isOtrFingerprintVerified()) {
|
case Conversation.Smp.STATUS_FAILED:
|
||||||
activateButton(mButtonSharedSecretPositive, R.string.finish, mFinishListener);
|
default:
|
||||||
this.mStatusMessage.setText(R.string.verified);
|
this.mSharedSecretSecret.requestFocus();
|
||||||
} else {
|
this.mSharedSecretSecret.setError(getString(R.string.secrets_do_not_match));
|
||||||
activateButton(mButtonSharedSecretPositive,R.string.reset,mRetrySharedSecretListener);
|
this.activateButton(this.mRightButton,R.string.finish,this.mFinishListener);
|
||||||
this.mStatusMessage.setText(R.string.secret_accepted);
|
break;
|
||||||
}
|
|
||||||
} else if (session != null && session.isSmpInProgress()) {
|
|
||||||
deactivateButton(mButtonSharedSecretPositive, R.string.in_progress);
|
|
||||||
activateButton(mButtonSharedSecretNegative, R.string.cancel, mCancelSharedSecretListener);
|
|
||||||
this.mSharedSecretHint.setVisibility(View.VISIBLE);
|
|
||||||
this.mSharedSecretSecret.setVisibility(View.VISIBLE);
|
|
||||||
this.mSharedSecretHint.setFocusable(false);
|
|
||||||
this.mSharedSecretSecret.setFocusable(false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.mVerificationAreaOne.setVisibility(View.GONE);
|
|
||||||
this.mVerificationAreaTwo.setVisibility(View.GONE);
|
|
||||||
this.mErrorNoSession.setVisibility(View.VISIBLE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,39 +399,16 @@ public class VerifyOTRActivity extends XmppActivity implements XmppConnectionSer
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_verify_otr);
|
setContentView(R.layout.activity_verify_otr);
|
||||||
this.mRemoteFingerprint = (TextView) findViewById(R.id.remote_fingerprint);
|
this.mRemoteFingerprint = (TextView) findViewById(R.id.remote_fingerprint);
|
||||||
this.mRemoteJid = (TextView) findViewById(R.id.remote_jid);
|
|
||||||
this.mYourFingerprint = (TextView) findViewById(R.id.your_fingerprint);
|
this.mYourFingerprint = (TextView) findViewById(R.id.your_fingerprint);
|
||||||
this.mButtonSharedSecretNegative = (Button) findViewById(R.id.button_shared_secret_negative);
|
this.mLeftButton = (Button) findViewById(R.id.left_button);
|
||||||
this.mButtonSharedSecretPositive = (Button) findViewById(R.id.button_shared_secret_positive);
|
this.mRightButton = (Button) findViewById(R.id.right_button);
|
||||||
this.mButtonScanQrCode = (Button) findViewById(R.id.button_scan_qr_code);
|
this.mVerificationExplain = (TextView) findViewById(R.id.verification_explanation);
|
||||||
this.mButtonShowQrCode = (Button) findViewById(R.id.button_show_qr_code);
|
this.mStatusMessage = (TextView) findViewById(R.id.status_message);
|
||||||
this.mButtonShowQrCode.setOnClickListener(this.mShowQrCodeListener);
|
|
||||||
this.mSharedSecretSecret = (EditText) findViewById(R.id.shared_secret_secret);
|
this.mSharedSecretSecret = (EditText) findViewById(R.id.shared_secret_secret);
|
||||||
this.mSharedSecretHint = (EditText) findViewById(R.id.shared_secret_hint);
|
this.mSharedSecretHintEditable = (EditText) findViewById(R.id.shared_secret_hint_editable);
|
||||||
this.mStatusMessage= (TextView) findViewById(R.id.status_message);
|
this.mSharedSecretHint = (TextView) findViewById(R.id.shared_secret_hint);
|
||||||
this.mVerificationAreaOne = (RelativeLayout) findViewById(R.id.verification_area_one);
|
this.mManualVerificationArea = (LinearLayout) findViewById(R.id.manual_verification_area);
|
||||||
this.mVerificationAreaTwo = (RelativeLayout) findViewById(R.id.verification_area_two);
|
this.mSmpVerificationArea = (LinearLayout) findViewById(R.id.smp_verification_area);
|
||||||
this.mErrorNoSession = (TextView) findViewById(R.id.error_no_session);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
|
||||||
getMenuInflater().inflate(R.menu.verify_otr, menu);
|
|
||||||
if (mConversation != null && mConversation.isOtrFingerprintVerified()) {
|
|
||||||
MenuItem manuallyVerifyItem = menu.findItem(R.id.manually_verify);
|
|
||||||
manuallyVerifyItem.setVisible(false);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem menuItem) {
|
|
||||||
if (menuItem.getItemId() == R.id.manually_verify) {
|
|
||||||
showManuallyVerifyDialog();
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return super.onOptionsItemSelected(menuItem);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showManuallyVerifyDialog() {
|
private void showManuallyVerifyDialog() {
|
||||||
|
|
|
@ -53,7 +53,7 @@ public class XmppUri {
|
||||||
final String NEEDLE = "otr-fingerprint=";
|
final String NEEDLE = "otr-fingerprint=";
|
||||||
int index = query.indexOf(NEEDLE);
|
int index = query.indexOf(NEEDLE);
|
||||||
if (index >= 0 && query.length() >= (NEEDLE.length() + index + 40)) {
|
if (index >= 0 && query.length() >= (NEEDLE.length() + index + 40)) {
|
||||||
return CryptoHelper.prettifyFingerprint(query.substring(index + NEEDLE.length(), index + NEEDLE.length() + 40));
|
return query.substring(index + NEEDLE.length(), index + NEEDLE.length() + 40);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -576,8 +576,8 @@ public class XmppConnection implements Runnable {
|
||||||
auth.setAttribute("xmlns", "urn:ietf:params:xml:ns:xmpp-sasl");
|
auth.setAttribute("xmlns", "urn:ietf:params:xml:ns:xmpp-sasl");
|
||||||
if (mechanisms.contains("SCRAM-SHA-1")) {
|
if (mechanisms.contains("SCRAM-SHA-1")) {
|
||||||
saslMechanism = new ScramSha1(tagWriter, account, mXmppConnectionService.getRNG());
|
saslMechanism = new ScramSha1(tagWriter, account, mXmppConnectionService.getRNG());
|
||||||
} else if (mechanisms.contains("DIGEST-MD5")) {
|
//} else if (mechanisms.contains("DIGEST-MD5")) {
|
||||||
saslMechanism = new DigestMd5(tagWriter, account, mXmppConnectionService.getRNG());
|
// saslMechanism = new DigestMd5(tagWriter, account, mXmppConnectionService.getRNG());
|
||||||
} else if (mechanisms.contains("PLAIN")) {
|
} else if (mechanisms.contains("PLAIN")) {
|
||||||
saslMechanism = new Plain(tagWriter, account);
|
saslMechanism = new Plain(tagWriter, account);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,189 +1,147 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/primarybackground">
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="fill_parent"
|
android:layout_height="fill_parent"
|
||||||
android:background="@color/secondarybackground">
|
android:layout_above="@+id/button_bar">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/error_no_session"
|
android:id="@+id/verification_explanation"
|
||||||
android:layout_margin="16dp"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"/>
|
||||||
android:text="@string/no_otr_session_found"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:textColor="@color/primarytext"
|
|
||||||
android:textSize="?attr/TextSizeBody"
|
|
||||||
/>
|
|
||||||
<RelativeLayout
|
|
||||||
android:id="@+id/verification_area_one"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="fill_parent"
|
|
||||||
android:background="@drawable/infocard_border"
|
|
||||||
android:layout_margin="8dp">
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/fingerprint_area"
|
android:id="@+id/manual_verification_area"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="16dp"
|
|
||||||
android:orientation="vertical">
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/remote_jid"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textColor="@color/primarytext"
|
|
||||||
android:textSize="?attr/TextSizeHeadline"/>
|
|
||||||
<TextView
|
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
android:id="@+id/your_fingerprint"
|
android:id="@+id/your_fingerprint"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textColor="@color/primarytext"
|
android:textColor="@color/primarytext"
|
||||||
android:textSize="?attr/TextSizeBody"
|
android:textSize="?attr/TextSizeBody"
|
||||||
android:typeface="monospace" />
|
android:typeface="monospace"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/your_fingerprint"
|
||||||
android:textColor="@color/secondarytext"
|
android:textColor="@color/secondarytext"
|
||||||
android:textSize="?attr/TextSizeInfo"
|
android:textSize="?attr/TextSizeInfo"/>
|
||||||
android:text="@string/your_fingerprint"/>
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:id="@+id/remote_fingerprint"
|
android:id="@+id/remote_fingerprint"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
android:textColor="@color/primarytext"
|
android:textColor="@color/primarytext"
|
||||||
android:textSize="?attr/TextSizeBody"
|
android:textSize="?attr/TextSizeBody"
|
||||||
android:typeface="monospace" />
|
android:typeface="monospace"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="20dp"
|
||||||
|
android:text="@string/remote_fingerprint"
|
||||||
android:textColor="@color/secondarytext"
|
android:textColor="@color/secondarytext"
|
||||||
android:textSize="?attr/TextSizeInfo"
|
android:textSize="?attr/TextSizeInfo"/>
|
||||||
android:text="@string/remote_fingerprint"/>
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_below="@+id/fingerprint_area"
|
android:id="@+id/smp_verification_area"
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentBottom="true"
|
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_alignParentRight="true" >
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/button_show_qr_code"
|
|
||||||
style="?android:attr/borderlessButtonStyle"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/show_qr_code"/>
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:layout_width="1dp"
|
|
||||||
android:layout_height="fill_parent"
|
|
||||||
android:layout_marginBottom="7dp"
|
|
||||||
android:layout_marginTop="7dp"
|
|
||||||
android:background="@color/divider" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/button_scan_qr_code"
|
|
||||||
style="?android:attr/borderlessButtonStyle"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/scan_qr_code"
|
|
||||||
android:textColor="@color/primarytext" />
|
|
||||||
</LinearLayout>
|
|
||||||
</RelativeLayout>
|
|
||||||
<RelativeLayout
|
|
||||||
android:id="@+id/verification_area_two"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="8dp"
|
|
||||||
android:background="@drawable/infocard_border">
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="fill_parent"
|
android:layout_height="fill_parent"
|
||||||
android:orientation="vertical"
|
android:layout_marginTop="16dp"
|
||||||
android:id="@+id/shared_secret_box"
|
android:orientation="vertical">
|
||||||
android:padding="16dp">
|
|
||||||
<TextView
|
|
||||||
android:text="@string/smp"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textColor="@color/primarytext"
|
|
||||||
android:textSize="?attr/TextSizeHeadline"
|
|
||||||
android:layout_marginBottom="16dp"
|
|
||||||
/>
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/status_message"
|
android:id="@+id/status_message"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/verified"
|
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:text="@string/verified"
|
||||||
|
android:textColor="@color/primarytext"
|
||||||
android:textSize="?attr/TextSizeHeadline"
|
android:textSize="?attr/TextSizeHeadline"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:visibility="gone"/>
|
android:visibility="gone"/>
|
||||||
<EditText
|
|
||||||
|
<TextView
|
||||||
android:id="@+id/shared_secret_hint"
|
android:id="@+id/shared_secret_hint"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:textColor="@color/primarytext"
|
||||||
|
android:textSize="?attr/TextSizeBody"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/shared_secret_hint_editable"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:inputType="textAutoComplete"
|
android:layout_marginBottom="8dp"
|
||||||
android:hint="@string/shared_secret_hint"
|
android:hint="@string/shared_secret_hint"
|
||||||
|
android:inputType="textAutoComplete"
|
||||||
android:textColor="@color/primarytext"
|
android:textColor="@color/primarytext"
|
||||||
android:textColorHint="@color/secondarytext"
|
android:textColorHint="@color/secondarytext"
|
||||||
android:textSize="?attr/TextSizeBody"
|
android:textSize="?attr/TextSizeBody"/>
|
||||||
android:layout_marginBottom="8dp"/>
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/shared_secret_secret"
|
android:id="@+id/shared_secret"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
android:hint="@string/shared_secret_secret"
|
android:hint="@string/shared_secret_secret"
|
||||||
android:inputType="textPassword"
|
android:inputType="textPassword"
|
||||||
android:textColor="@color/primarytext"
|
android:textColor="@color/primarytext"
|
||||||
android:textColorHint="@color/secondarytext"
|
android:textColorHint="@color/secondarytext"
|
||||||
android:textSize="?attr/TextSizeBody" />
|
android:textSize="?attr/TextSizeBody"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_below="@+id/shared_secret_box"
|
|
||||||
android:id="@+id/button_bar"
|
android:id="@+id/button_bar"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_alignParentRight="true" >
|
android:layout_alignParentRight="true">
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/button_shared_secret_negative"
|
android:id="@+id/left_button"
|
||||||
style="?android:attr/borderlessButtonStyle"
|
style="?android:attr/borderlessButtonStyle"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"/>
|
||||||
android:enabled="false"
|
|
||||||
android:text="@string/cancel"
|
|
||||||
android:textColor="@color/secondarytext"/>
|
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="1dp"
|
android:layout_width="1dp"
|
||||||
android:layout_height="fill_parent"
|
android:layout_height="fill_parent"
|
||||||
android:layout_marginBottom="7dp"
|
android:layout_marginBottom="7dp"
|
||||||
android:layout_marginTop="7dp"
|
android:layout_marginTop="7dp"
|
||||||
android:background="@color/divider" />
|
android:background="@color/divider"/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/button_shared_secret_positive"
|
android:id="@+id/right_button"
|
||||||
style="?android:attr/borderlessButtonStyle"
|
style="?android:attr/borderlessButtonStyle"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"/>
|
||||||
android:text="@string/create"
|
|
||||||
android:textColor="@color/primarytext" />
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</RelativeLayout>
|
|
||||||
</LinearLayout>
|
</RelativeLayout>
|
||||||
</ScrollView>
|
|
|
@ -392,4 +392,11 @@
|
||||||
<string name="updating">Updating…</string>
|
<string name="updating">Updating…</string>
|
||||||
<string name="password_changed">Password changed!</string>
|
<string name="password_changed">Password changed!</string>
|
||||||
<string name="could_not_change_password">Could not change password</string>
|
<string name="could_not_change_password">Could not change password</string>
|
||||||
|
<string name="otr_session_not_started">Send a message to start an encrypted chat</string>
|
||||||
|
<string name="ask_question">Ask question</string>
|
||||||
|
<string name="smp_explain_question">If you and your contact have a secret in common that no one else knows (like an inside joke or simply what you had for lunch the last time you met) you can use that secret to verify each other\'s fingerprints.\n\nYou provide a hint or a question for your contact who will respond with a case-sensitive answer.</string>
|
||||||
|
<string name="smp_explain_answer">Your contact would like to verify your fingerprint by challenging you with a shared secret. Your contact provided the following hint or question for that secret.</string>
|
||||||
|
<string name="shared_secret_hint_should_not_be_empty">Your hint should not be empty</string>
|
||||||
|
<string name="shared_secret_can_not_be_empty">Your shared secret can not be empty</string>
|
||||||
|
<string name="manual_verification_explanation">Carefully compare the fingerprints shown below with the fingerprints of your contact.\nYou can use a trusted communication channel like an encrypted e-mail or a telephone call channel to exchange those.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in New Issue