made otr a little bit more solid when there is no presence subscription

iNPUTmice created

Change summary

res/values/strings.xml                                         |  1 
src/eu/siacs/conversations/crypto/OtrEngine.java               | 35 ++-
src/eu/siacs/conversations/entities/Account.java               |  7 
src/eu/siacs/conversations/entities/Conversation.java          | 15 
src/eu/siacs/conversations/parser/MessageParser.java           |  9 
src/eu/siacs/conversations/services/XmppConnectionService.java | 10 
src/eu/siacs/conversations/ui/EditAccountActivity.java         |  2 
src/eu/siacs/conversations/ui/XmppActivity.java                |  1 
src/eu/siacs/conversations/ui/adapter/MessageAdapter.java      |  5 
9 files changed, 56 insertions(+), 29 deletions(-)

Detailed changes

res/values/strings.xml πŸ”—

@@ -244,5 +244,6 @@
     <string name="missing_presence_updates">Missing presence updates from contact</string>
     <string name="request_presence_updates">Please request presence updates from your contact first.\n\n<small>This will be used to determine what client(s) your contact is using.</small></string>
     <string name="request_now">Request now</string>
+    <string name="unable_to_decrypt_otr_message">Unable to decrypt OTR message</string>
 
 </resources>

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

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();
 	}
 

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;
 	}

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;
 		}
 	}

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 {

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);

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);

src/eu/siacs/conversations/ui/adapter/MessageAdapter.java πŸ”—

@@ -495,6 +495,11 @@ public class MessageAdapter extends ArrayAdapter<Message> {
 				}
 			} 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);
 			}