From 0e5a0a07fd32d185d2d4c43df9494fafcace9208 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Sat, 6 Sep 2014 18:21:31 +0200 Subject: [PATCH] made otr a little bit more solid when there is no presence subscription --- res/values/strings.xml | 1 + .../siacs/conversations/crypto/OtrEngine.java | 35 ++++++++++++++----- .../siacs/conversations/entities/Account.java | 7 ++-- .../conversations/entities/Conversation.java | 15 ++++---- .../conversations/parser/MessageParser.java | 9 +++-- .../services/XmppConnectionService.java | 10 +++--- .../conversations/ui/EditAccountActivity.java | 2 +- .../siacs/conversations/ui/XmppActivity.java | 1 - .../ui/adapter/MessageAdapter.java | 5 +++ 9 files changed, 56 insertions(+), 29 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 5e8d4f550..0d5a75d52 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -244,5 +244,6 @@ Missing presence updates from contact Please request presence updates from your contact first.\n\nThis will be used to determine what client(s) your contact is using. Request now + Unable to decrypt OTR message \ No newline at end of file diff --git a/src/eu/siacs/conversations/crypto/OtrEngine.java b/src/eu/siacs/conversations/crypto/OtrEngine.java index 0ef112c63..b23b31fe2 100644 --- a/src/eu/siacs/conversations/crypto/OtrEngine.java +++ b/src/eu/siacs/conversations/crypto/OtrEngine.java @@ -19,7 +19,10 @@ import android.util.Log; import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.entities.Conversation; +import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.persistance.DatabaseBackend; +import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.xmpp.stanzas.MessagePacket; import net.java.otr4j.OtrEngineHost; @@ -28,21 +31,24 @@ import net.java.otr4j.OtrPolicy; import net.java.otr4j.OtrPolicyImpl; import net.java.otr4j.session.InstanceTag; import net.java.otr4j.session.SessionID; +import net.java.otr4j.session.SessionImpl; +import net.java.otr4j.session.SessionStatus; public class OtrEngine implements OtrEngineHost { private Account account; private OtrPolicy otrPolicy; private KeyPair keyPair; - private Context context; + private XmppConnectionService mXmppConnectionService; - public OtrEngine(Context context, Account account) { + public OtrEngine(XmppConnectionService service, Account account) { this.account = account; this.otrPolicy = new OtrPolicyImpl(); this.otrPolicy.setAllowV1(false); this.otrPolicy.setAllowV2(true); this.otrPolicy.setAllowV3(true); this.keyPair = loadKey(account.getKeys()); + this.mXmppConnectionService = service; } private KeyPair loadKey(JSONObject keys) { @@ -102,14 +108,12 @@ public class OtrEngine implements OtrEngineHost { @Override public void finishedSessionMessage(SessionID arg0, String arg1) throws OtrException { - // TODO Auto-generated method stub } @Override public String getFallbackMessage(SessionID arg0) { - // TODO Auto-generated method stub - return null; + return "I would like to start a private (OTR encrypted) conversation but your client doesn’t seem to support that"; } @Override @@ -133,7 +137,7 @@ public class OtrEngine implements OtrEngineHost { kg = KeyPairGenerator.getInstance("DSA"); this.keyPair = kg.genKeyPair(); this.saveKey(); - DatabaseBackend.getInstance(context).updateAccount(account); + mXmppConnectionService.databaseBackend.updateAccount(account); } catch (NoSuchAlgorithmException e) { Log.d(Config.LOGTAG, "error generating key pair " + e.getMessage()); @@ -171,9 +175,22 @@ public class OtrEngine implements OtrEngineHost { } @Override - public void messageFromAnotherInstanceReceived(SessionID arg0) { - // TODO Auto-generated method stub - + public void messageFromAnotherInstanceReceived(SessionID id) { + String jid = id.getAccountID(); + Conversation conversation = mXmppConnectionService + .findOrCreateConversation(account, jid, false); + Message error = new Message(conversation, null, Message.ENCRYPTION_OTR); + conversation.getMessages().add(error); + error.setStatus(Message.STATUS_RECEPTION_FAILED); + mXmppConnectionService.databaseBackend.createMessage(error); + SessionImpl session = conversation.getOtrSession(); + if (session != null + && session.getSessionStatus() != SessionStatus.ENCRYPTED) { + try { + session.startSession(); + } catch (OtrException e) { + } + } } @Override diff --git a/src/eu/siacs/conversations/entities/Account.java b/src/eu/siacs/conversations/entities/Account.java index 272cf3797..eacd172c6 100644 --- a/src/eu/siacs/conversations/entities/Account.java +++ b/src/eu/siacs/conversations/entities/Account.java @@ -14,6 +14,7 @@ import org.json.JSONObject; import eu.siacs.conversations.R; import eu.siacs.conversations.crypto.OtrEngine; import eu.siacs.conversations.persistance.FileBackend; +import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.xmpp.XmppConnection; import android.content.ContentValues; @@ -230,7 +231,7 @@ public class Account extends AbstractEntity { cursor.getString(cursor.getColumnIndex(AVATAR))); } - public OtrEngine getOtrEngine(Context context) { + public OtrEngine getOtrEngine(XmppConnectionService context) { if (otrEngine == null) { otrEngine = new OtrEngine(context, this); } @@ -283,8 +284,8 @@ public class Account extends AbstractEntity { this.rosterVersion = version; } - public String getOtrFingerprint(Context applicationContext) { - this.getOtrEngine(applicationContext); + public String getOtrFingerprint(XmppConnectionService service) { + this.getOtrEngine(service); return this.getOtrFingerprint(); } diff --git a/src/eu/siacs/conversations/entities/Conversation.java b/src/eu/siacs/conversations/entities/Conversation.java index 2097b2a45..9f7ba3aaa 100644 --- a/src/eu/siacs/conversations/entities/Conversation.java +++ b/src/eu/siacs/conversations/entities/Conversation.java @@ -4,6 +4,7 @@ import java.security.interfaces.DSAPublicKey; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; +import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.utils.UIHelper; import net.java.otr4j.OtrException; @@ -43,7 +44,7 @@ public class Conversation extends AbstractEntity { private int status; private long created; private int mode; - + private long mutedTill = 0; private String nextPresence; @@ -223,15 +224,15 @@ public class Conversation extends AbstractEntity { this.mode = mode; } - public SessionImpl startOtrSession(Context context, String presence, - boolean sendStart) { + public SessionImpl startOtrSession(XmppConnectionService service, + String presence, boolean sendStart) { if (this.otrSession != null) { return this.otrSession; } else { - SessionID sessionId = new SessionID(this.getContactJid(), presence, - "xmpp"); + SessionID sessionId = new SessionID( + this.getContactJid().split("/")[0], presence, "xmpp"); this.otrSession = new SessionImpl(sessionId, getAccount() - .getOtrEngine(context)); + .getOtrEngine(service)); try { if (sendStart) { this.otrSession.startSession(); @@ -425,7 +426,7 @@ public class Conversation extends AbstractEntity { public void setMutedTill(long mutedTill) { this.mutedTill = mutedTill; } - + public boolean isMuted() { return SystemClock.elapsedRealtime() < this.mutedTill; } diff --git a/src/eu/siacs/conversations/parser/MessageParser.java b/src/eu/siacs/conversations/parser/MessageParser.java index 0f95627d3..938ccc167 100644 --- a/src/eu/siacs/conversations/parser/MessageParser.java +++ b/src/eu/siacs/conversations/parser/MessageParser.java @@ -71,10 +71,13 @@ public class MessageParser extends AbstractParser implements } updateLastseen(packet, account, true); String body = packet.getBody(); + if (body.matches("^\\?OTRv\\d*\\?")) { + conversation.resetOtrSession(); + } if (!conversation.hasValidOtrSession()) { if (properlyAddressed) { conversation.startOtrSession( - mXmppConnectionService.getApplicationContext(), + mXmppConnectionService, presence, false); } else { return null; @@ -86,7 +89,7 @@ public class MessageParser extends AbstractParser implements conversation.endOtrIfNeeded(); if (properlyAddressed) { conversation.startOtrSession( - mXmppConnectionService.getApplicationContext(), + mXmppConnectionService, presence, false); } else { return null; @@ -125,7 +128,7 @@ public class MessageParser extends AbstractParser implements if (receivedId != null) { mXmppConnectionService.replyWithNotAcceptable(account, packet); } - conversation.endOtrIfNeeded(); + conversation.resetOtrSession(); return null; } } diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java index 9e1717514..da7ffb4dd 100644 --- a/src/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/eu/siacs/conversations/services/XmppConnectionService.java @@ -516,7 +516,7 @@ public class XmppConnectionService extends Service { if (message.getEncryption() == Message.ENCRYPTION_OTR) { if (!conv.hasValidOtrSession() && (message.getPresence() != null)) { - conv.startOtrSession(getApplicationContext(), + conv.startOtrSession(this, message.getPresence(), true); message.setStatus(Message.STATUS_WAITING); } else if (conv.hasValidOtrSession() @@ -536,7 +536,7 @@ public class XmppConnectionService extends Service { if (message.getEncryption() == Message.ENCRYPTION_OTR) { if (!conv.hasValidOtrSession() && (message.getPresence() != null)) { - conv.startOtrSession(getApplicationContext(), + conv.startOtrSession(this, message.getPresence(), true); message.setStatus(Message.STATUS_WAITING); } else if (conv.hasValidOtrSession() @@ -577,7 +577,7 @@ public class XmppConnectionService extends Service { .getUserID()); } else if (!conv.hasValidOtrSession() && message.getPresence() != null) { - conv.startOtrSession(getApplicationContext(), + conv.startOtrSession(this, message.getPresence(), false); } } @@ -617,13 +617,13 @@ public class XmppConnectionService extends Service { if ((message.getPresence() != null) && (presences.has(message.getPresence()))) { message.getConversation().startOtrSession( - getApplicationContext(), message.getPresence(), + this, message.getPresence(), true); } else { if (presences.size() == 1) { String presence = presences.asStringArray()[0]; message.getConversation().startOtrSession( - getApplicationContext(), presence, true); + this, presence, true); } } } else { diff --git a/src/eu/siacs/conversations/ui/EditAccountActivity.java b/src/eu/siacs/conversations/ui/EditAccountActivity.java index 6cee8386c..bc9461159 100644 --- a/src/eu/siacs/conversations/ui/EditAccountActivity.java +++ b/src/eu/siacs/conversations/ui/EditAccountActivity.java @@ -325,7 +325,7 @@ public class EditAccountActivity extends XmppActivity { this.mServerInfoPep.setText(R.string.server_info_unavailable); } String fingerprint = this.mAccount - .getOtrFingerprint(getApplicationContext()); + .getOtrFingerprint(xmppConnectionService); if (fingerprint != null) { this.mOtrFingerprintHeadline.setVisibility(View.VISIBLE); this.mOtrFingerprint.setVisibility(View.VISIBLE); diff --git a/src/eu/siacs/conversations/ui/XmppActivity.java b/src/eu/siacs/conversations/ui/XmppActivity.java index 7d903e864..6ff83357b 100644 --- a/src/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/eu/siacs/conversations/ui/XmppActivity.java @@ -377,7 +377,6 @@ public abstract class XmppActivity extends Activity { Toast toast = Toast.makeText(this, R.string.missing_presence_updates, Toast.LENGTH_LONG); - toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0); toast.show(); } conversation.setNextPresence(null); diff --git a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java index ccf25a334..074e38fbb 100644 --- a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -495,6 +495,11 @@ public class MessageAdapter extends ArrayAdapter { } } else if (item.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) { displayDecryptionFailed(viewHolder); + } else if (item.getEncryption() == Message.ENCRYPTION_OTR + && item.getStatus() == Message.STATUS_RECEPTION_FAILED + && item.getType() == Message.TYPE_TEXT) { + displayInfoMessage(viewHolder, + R.string.unable_to_decrypt_otr_message); } else { displayTextMessage(viewHolder, item); }