# HG changeset patch # User Nikita Kozlov # Date 1302975833 -7200 # Node ID ab30d289a86c6a02b6a3198abde3281bd30ba6da # Parent 9443da4a7fb74034c2a0a29689d15cfe43230551 adding a keystore for otr, adding buttons which display fingerprints diff -r 9443da4a7fb7 -r ab30d289a86c res/menu/chat.xml --- a/res/menu/chat.xml Fri Apr 15 23:58:06 2011 +0200 +++ b/res/menu/chat.xml Sat Apr 16 19:43:53 2011 +0200 @@ -13,4 +13,8 @@ android:title="@string/chat_menu_listen_otr_session" /> + + diff -r 9443da4a7fb7 -r ab30d289a86c res/values/strings.xml --- a/res/values/strings.xml Fri Apr 15 23:58:06 2011 +0200 +++ b/res/values/strings.xml Sat Apr 16 19:43:53 2011 +0200 @@ -274,6 +274,8 @@ Start OTR session Listen for OTR session Stop OTR session + OTR local key + OTR remote key Opened chats Close this chat No more active chats @@ -284,6 +286,8 @@ PLAINTEXT ENCRYPTED FINISHED + Verify remote fingerprint %s ? + Local fingerprint %s Available Available to chat diff -r 9443da4a7fb7 -r ab30d289a86c src/com/beem/project/beem/otr/BeemOtrManager.java --- a/src/com/beem/project/beem/otr/BeemOtrManager.java Fri Apr 15 23:58:06 2011 +0200 +++ b/src/com/beem/project/beem/otr/BeemOtrManager.java Sat Apr 16 19:43:53 2011 +0200 @@ -1,9 +1,33 @@ +/* + BEEM is a videoconference application on the Android Platform. + + Copyright (C) 2009-2011 by Frederic-Charles Barthelery, + Nikita Kozlov, + Vincent Veronis. + + This file is part of BEEM. + + BEEM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + BEEM 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 BEEM. If not, see . + + Please send bug reports with examples or suggestions to + contact@beem-project.com or http://www.beem-project.com/ + + */ package com.beem.project.beem.otr; import java.io.IOException; import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.NoSuchAlgorithmException; import java.util.HashMap; import java.util.Map; @@ -11,113 +35,142 @@ import net.java.otr4j.OtrEngineHost; import net.java.otr4j.OtrEngineImpl; import net.java.otr4j.OtrEngineListener; +import net.java.otr4j.OtrException; import net.java.otr4j.OtrKeyManagerImpl; import net.java.otr4j.OtrPolicy; import net.java.otr4j.OtrPolicyImpl; import net.java.otr4j.session.SessionID; +import net.java.otr4j.session.SessionStatus; +import android.os.RemoteException; import android.util.Log; import com.beem.project.beem.service.ChatAdapter; - +/** + * BeemOtrManager. + */ public class BeemOtrManager implements OtrEngineHost { - private static final String TAG = "BeemOtrEngineHostImpl"; - private static BeemOtrManager INSTANCE; + private static final String TAG = "BeemOtrEngineHostImpl"; + private static BeemOtrManager INSTANCE; + //We will have a global policy for Beem as long as we won't need to modify the policy per chat. + private static final OtrPolicy mGlobalPolicy = new OtrPolicyImpl(OtrPolicy.ALLOW_V2 | OtrPolicy.ERROR_START_AKE); + - private OtrEngine mOtrEngine; - private OtrKeyManagerImpl mOtrKeyManager; + private OtrEngine mOtrEngine; + private OtrKeyManagerImpl mOtrKeyManager; + + //Map of chat, needed because of the message injection + private final Map mChats = new HashMap(); - //Map of chat, needed because of the message injection - private final Map mChats = new HashMap(); + /** + * Private constructor prevents instantiation from other classes. + */ + private BeemOtrManager() { + mOtrEngine = new OtrEngineImpl(this); + mOtrEngine.addOtrEngineListener(new BeemOtrListener()); + try { + mOtrKeyManager = new OtrKeyManagerImpl("/sdcard/beem.keystore"); + } catch (IOException e) { + e.printStackTrace(); + } + } - //We will have a global policy for Beem as long as we won't need to modify the policy per chat. - private static final OtrPolicy mGlobalPolicy = new OtrPolicyImpl(OtrPolicy.ALLOW_V2 | OtrPolicy.ERROR_START_AKE); - + /** + * getOtrManager. + * @return OtrEngine + */ + public OtrEngine getOtrManager() { + return mOtrEngine; + } - private Map mKeys = new HashMap(); - - public OtrEngine getOtrManager() { - return mOtrEngine; - } + /** + * BeemOtrManager.getInstance. + * @return BeemOtrManager + */ + public static BeemOtrManager getInstance() { + if (INSTANCE == null) + INSTANCE = new BeemOtrManager(); + return INSTANCE; + } - // Private constructor prevents instantiation from other classes - private BeemOtrManager() { - mOtrEngine = new OtrEngineImpl(this);; - mOtrEngine.addOtrEngineListener(new BeemOtrListener()); - try { - mOtrKeyManager = new OtrKeyManagerImpl("/sdcard/beem.keystore"); - } catch (IOException e) { - e.printStackTrace(); - } - } + /** + * We must call addChat before stating a new otr session because we will need the chat instance for message injection. + * @param sessionID the otr sessionID. + * @param chat instance. + */ + public void addChat(final SessionID sessionID, final ChatAdapter chat) { + mChats.put(sessionID, chat); + Log.d(TAG, "adding new OTR session " + sessionID); + } + + /** + * We must remove the chat from the map after we ended the corresponding otr session. + * @param sessionID the otr sessionID to remove. + */ + public void removeChat(final SessionID sessionID) { + mChats.remove(sessionID); + } + + public String getRemoteFingerprint(final SessionID sessionID) { + return mOtrKeyManager.getRemoteFingerprint(sessionID); + } + + public String getLocalFingerprint(final SessionID sessionID) { + return mOtrKeyManager.getLocalFingerprint(sessionID); + } - public static BeemOtrManager getInstance() { - if (INSTANCE == null) - INSTANCE = new BeemOtrManager(); - return INSTANCE; - } + @Override + public void injectMessage(SessionID sessionID, String msg) { + ChatAdapter chat = mChats.get(sessionID); + chat.sendMessage(msg); + } + + @Override + public void showWarning(SessionID sessionID, String warning) { + Log.d(TAG, "Warning for " + sessionID + " : " + warning); + } + + @Override + public void showError(SessionID sessionID, String error) { + Log.d(TAG, "Error for " + sessionID + " : " + error); + } - /* - * We must call addChat before stating a new otr session because we will need the chat instance for message injection - */ - public void addChat(final SessionID sessionID, final ChatAdapter chat) { - mChats.put(sessionID, chat); - } + @Override + public OtrPolicy getSessionPolicy(SessionID sessionID) { + return mGlobalPolicy; + } + + @Override + public KeyPair getKeyPair(SessionID sessionID) { + KeyPair kp = mOtrKeyManager.loadLocalKeyPair(sessionID); - /* - * We must remove the chat from the map after we ended the corresponding otr session. - */ - public void removeChat(final SessionID sessionID) { - mChats.remove(sessionID); - } + if(kp != null) + return kp; + + mOtrKeyManager.generateLocalKeyPair(sessionID); + return mOtrKeyManager.loadLocalKeyPair(sessionID); + } + + /** + * BeemOtrListener. + */ + private class BeemOtrListener implements OtrEngineListener { @Override - public void injectMessage(SessionID sessionID, String msg) { - ChatAdapter chat = mChats.get(sessionID); - chat.sendMessage(msg); - } - - @Override - public void showWarning(SessionID sessionID, String warning) { - Log.d(TAG, "Warning for "+sessionID + " : "+warning); - } - - @Override - public void showError(SessionID sessionID, String error) { - Log.d(TAG, "Error for "+sessionID + " : "+error); - } - - @Override - public OtrPolicy getSessionPolicy(SessionID sessionID) { - return mGlobalPolicy; + public void sessionStatusChanged(final SessionID sessionID) { + Log.d(TAG, "OTR Status changed for " + sessionID + " : " + mOtrEngine.getSessionStatus(sessionID)); + if (mOtrKeyManager.loadRemotePublicKey(sessionID) == null) { + mOtrKeyManager.savePublicKey(sessionID, mOtrEngine.getRemotePublicKey(sessionID)); + } + mChats.get(sessionID).otrStateChanged(mOtrEngine.getSessionStatus(sessionID).toString()); + if(mOtrEngine.getSessionStatus(sessionID) == SessionStatus.FINISHED) { + try { + mChats.get(sessionID).localEndOtrSession(); + } catch (OtrException e) { + e.printStackTrace(); + } + } } - - @Override - public KeyPair getKeyPair(SessionID sessionID) { - KeyPair key = mKeys.get(sessionID); - - if (key == null) { - KeyPairGenerator kg; - try { - kg = KeyPairGenerator.getInstance("DSA"); - key = kg.genKeyPair(); - mKeys.put(sessionID, key); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - return null; - } - } - - return key; - } - - private class BeemOtrListener implements OtrEngineListener { - - @Override - public void sessionStatusChanged(final SessionID sessionID) { - Log.d(TAG, "OTR Status changed for " + sessionID + " : " + mOtrEngine.getSessionStatus(sessionID)); - mChats.get(sessionID).otrStateChanged(mOtrEngine.getSessionStatus(sessionID).toString()); - } - } + } } diff -r 9443da4a7fb7 -r ab30d289a86c src/com/beem/project/beem/service/ChatAdapter.java --- a/src/com/beem/project/beem/service/ChatAdapter.java Fri Apr 15 23:58:06 2011 +0200 +++ b/src/com/beem/project/beem/service/ChatAdapter.java Sat Apr 16 19:43:53 2011 +0200 @@ -58,11 +58,11 @@ import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smackx.ChatState; import org.jivesoftware.smackx.ChatStateListener; -import org.jivesoftware.smackx.ChatState; import android.os.Environment; import android.os.RemoteCallbackList; import android.os.RemoteException; +import android.util.AndroidException; import android.util.Log; import com.beem.project.beem.otr.BeemOtrManager; @@ -74,19 +74,19 @@ * @author darisk */ public class ChatAdapter extends IChat.Stub { - private static final int HISTORY_MAX_SIZE = 50; - private static final String TAG = "ChatAdapter"; - private static final String PROTOCOL = "XMPP"; + private static final int HISTORY_MAX_SIZE = 50; + private static final String TAG = "ChatAdapter"; + private static final String PROTOCOL = "XMPP"; - private final Chat mAdaptee; - private final Contact mParticipant; - private String mState; - private boolean mIsOpen; - private final List mMessages; - private final RemoteCallbackList mRemoteListeners = new RemoteCallbackList(); - private final MsgListener mMsgListener = new MsgListener(); - private SessionID mOtrSessionId; - private boolean mIsHistory; + private final Chat mAdaptee; + private final Contact mParticipant; + private String mState; + private boolean mIsOpen; + private final List mMessages; + private final RemoteCallbackList mRemoteListeners = new RemoteCallbackList(); + private final MsgListener mMsgListener = new MsgListener(); + private SessionID mOtrSessionId; + private boolean mIsHistory; private File mHistoryPath; private String mAccountUser; @@ -119,15 +119,15 @@ send.setTo(message.getTo()); Log.w(TAG, "message to " + message.getTo()); - if (mOtrSessionId != null) { - String body; - try { - body = BeemOtrManager.getInstance().getOtrManager().transformSending(mOtrSessionId, msgBody); - msgBody = body; - } catch (OtrException e) { - e.printStackTrace(); - } - } + if (mOtrSessionId != null) { + String body; + try { + body = BeemOtrManager.getInstance().getOtrManager().transformSending(mOtrSessionId, msgBody); + msgBody = body; + } catch (OtrException e) { + e.printStackTrace(); + } + } send.setBody(msgBody); send.setThread(message.getThread()); @@ -148,17 +148,17 @@ /** * send message. - * @param msg + * @param msg to send. */ - public void sendMessage(String msg) { - Message msgToSend = new Message(mParticipant.getJIDWithRes(), Message.MSG_TYPE_CHAT); - msgToSend.setBody(msg); - try { - sendMessage(msgToSend); - } catch (RemoteException e) { - e.printStackTrace(); - } + public void sendMessage(String msg) { + Message msgToSend = new Message(mParticipant.getJIDWithRes(), Message.MSG_TYPE_CHAT); + msgToSend.setBody(msg); + try { + sendMessage(msgToSend); + } catch (RemoteException e) { + e.printStackTrace(); } + } /** * {@inheritDoc} @@ -250,16 +250,16 @@ */ public void saveHistory(Message msg, String contactName) { File path = getHistoryPath(); - File filepath; - if (contactName.equals(msg.getFrom())) - filepath = new File(path, StringUtils.parseBareAddress(contactName)); - else - filepath = new File(path, StringUtils.parseBareAddress(msg.getTo())); - path.mkdirs(); + File filepath; + if (contactName.equals(msg.getFrom())) + filepath = new File(path, StringUtils.parseBareAddress(contactName)); + else + filepath = new File(path, StringUtils.parseBareAddress(msg.getTo())); + path.mkdirs(); try { FileWriter file = new FileWriter(filepath, true); String log = msg.getTimestamp() + " " + contactName + " " + msg.getBody() - + System.getProperty("line.separator"); + + System.getProperty("line.separator"); file.write(log); file.close(); } catch (IOException e) { @@ -324,121 +324,142 @@ */ public MsgListener() { } - @Override - public void processMessage(Chat chat, org.jivesoftware.smack.packet.Message message) { - Message msg = new Message(message); - Log.d(TAG, "new msg " + msg.getBody()); - - if (mOtrSessionId != null) { - String body; - try { - body = BeemOtrManager.getInstance().getOtrManager().transformReceiving(mOtrSessionId, msg.getBody()); - msg.setBody(body); - } catch (OtrException e) { - e.printStackTrace(); - } - } + @Override + public void processMessage(Chat chat, org.jivesoftware.smack.packet.Message message) { + Message msg = new Message(message); + Log.d(TAG, "new msg " + msg.getBody()); - //TODO add que les message pas de type errors - ChatAdapter.this.addMessage(msg); - final int n = mRemoteListeners.beginBroadcast(); - for (int i = 0; i < n; i++) { - IMessageListener listener = mRemoteListeners.getBroadcastItem(i); - try { - if (listener != null) - listener.processMessage(ChatAdapter.this, msg); - } catch (RemoteException e) { - Log.w(TAG, "Error while diffusing message to listener", e); - } - } - mRemoteListeners.finishBroadcast(); + if (mOtrSessionId != null) { + String body; + try { + body = BeemOtrManager.getInstance().getOtrManager().transformReceiving(mOtrSessionId, msg.getBody()); + msg.setBody(body); + } catch (OtrException e) { + e.printStackTrace(); } + } - /** - * {@inheritDoc} - */ - @Override - public void stateChanged(Chat chat, ChatState state) { - mState = state.name(); - final int n = mRemoteListeners.beginBroadcast(); - - for (int i = 0; i < n; i++) { - IMessageListener listener = mRemoteListeners.getBroadcastItem(i); - try { - listener.stateChanged(ChatAdapter.this); - } catch (RemoteException e) { - Log.w(TAG, e.getMessage()); - } - } - mRemoteListeners.finishBroadcast(); + //TODO add que les message pas de type errors + ChatAdapter.this.addMessage(msg); + final int n = mRemoteListeners.beginBroadcast(); + for (int i = 0; i < n; i++) { + IMessageListener listener = mRemoteListeners.getBroadcastItem(i); + try { + if (listener != null) + listener.processMessage(ChatAdapter.this, msg); + } catch (RemoteException e) { + Log.w(TAG, "Error while diffusing message to listener", e); } - - + } + mRemoteListeners.finishBroadcast(); } + /** - * This method is executed when the otr session status change. - * @param otrState the new state of otr session. + * {@inheritDoc} */ - public void otrStateChanged(final String otrState) { - final int n = mRemoteListeners.beginBroadcast(); + @Override + public void stateChanged(Chat chat, ChatState state) { + mState = state.name(); + final int n = mRemoteListeners.beginBroadcast(); - if ("FINISHED".equals(otrState)) { - BeemOtrManager.getInstance().removeChat(mOtrSessionId); - mOtrSessionId = null; + for (int i = 0; i < n; i++) { + IMessageListener listener = mRemoteListeners.getBroadcastItem(i); + try { + listener.stateChanged(ChatAdapter.this); + } catch (RemoteException e) { + Log.w(TAG, e.getMessage()); } - for (int i = 0; i < n; i++) { - IMessageListener listener = mRemoteListeners.getBroadcastItem(i); - try { - listener.otrStateChanged(otrState); - } catch (RemoteException e) { - Log.w(TAG, e.getMessage()); - } - } - mRemoteListeners.finishBroadcast(); + } + mRemoteListeners.finishBroadcast(); } - @Override - public void startOtrSession() throws RemoteException { - if (mOtrSessionId != null) - return ; + } + /** + * This method is executed when the otr session status change. + * @param otrState the new state of otr session. + */ + public void otrStateChanged(final String otrState) { + final int n = mRemoteListeners.beginBroadcast(); - mOtrSessionId = new SessionID(mParticipant.getJIDWithRes(), mParticipant.getJID(), PROTOCOL); - try { - BeemOtrManager.getInstance().addChat(mOtrSessionId, this); - BeemOtrManager.getInstance().getOtrManager().startSession(mOtrSessionId); - } catch (OtrException e) { - mOtrSessionId = null; - e.printStackTrace(); - throw new RemoteException(); - } + for (int i = 0; i < n; i++) { + IMessageListener listener = mRemoteListeners.getBroadcastItem(i); + try { + listener.otrStateChanged(otrState); + } catch (RemoteException e) { + Log.w(TAG, e.getMessage()); + } } + mRemoteListeners.finishBroadcast(); + } - @Override - public void endOtrSession() throws RemoteException { - if (mOtrSessionId == null) - return; + + @Override + public void startOtrSession() throws RemoteException { + if (mOtrSessionId != null) + return; + + mOtrSessionId = new SessionID(mParticipant.getJIDWithRes(), mParticipant.getJID(), PROTOCOL); + try { + BeemOtrManager.getInstance().addChat(mOtrSessionId, this); + BeemOtrManager.getInstance().getOtrManager().startSession(mOtrSessionId); + } catch (OtrException e) { + mOtrSessionId = null; + e.printStackTrace(); + throw new RemoteException(); + } + } - try { - BeemOtrManager.getInstance().getOtrManager().endSession(mOtrSessionId); - } catch (OtrException e) { - e.printStackTrace(); - throw new RemoteException(); - } - BeemOtrManager.getInstance().removeChat(mOtrSessionId); - mOtrSessionId = null; + @Override + public void endOtrSession() throws RemoteException { + try { + localEndOtrSession(); + } catch (OtrException e) { + e.printStackTrace(); + throw new RemoteException(); } + } + + /** + * end an Otr session. + * @return false if something bad happened. + */ + public boolean localEndOtrSession() throws OtrException { + if (mOtrSessionId == null) + return true; + + BeemOtrManager.getInstance().getOtrManager().endSession(mOtrSessionId); + BeemOtrManager.getInstance().removeChat(mOtrSessionId); + mOtrSessionId = null; + return true; + } - @Override - public void listenOtrSession() throws RemoteException { - if (mOtrSessionId != null) - return; + @Override + public void listenOtrSession() throws RemoteException { + if (mOtrSessionId != null) + return; + + mOtrSessionId = new SessionID(mParticipant.getJIDWithRes(), mParticipant.getJID(), PROTOCOL); + BeemOtrManager.getInstance().addChat(mOtrSessionId, this); + //OtrEngineImpl will make a call to "this.getSession(sessionID)" which will instantiate our session. + BeemOtrManager.getInstance().getOtrManager().getSessionStatus(mOtrSessionId); + + } - mOtrSessionId = new SessionID(mParticipant.getJIDWithRes(), mParticipant.getJID(), PROTOCOL); - BeemOtrManager.getInstance().addChat(mOtrSessionId, this); - //OtrEngineImpl will make a call to "this.getSession(sessionID)" which will instantiate our session. - BeemOtrManager.getInstance().getOtrManager().getSessionStatus(mOtrSessionId); + @Override + public String getLocalOtrFingerprint() throws RemoteException { + if (mOtrSessionId == null) + return null; + + return BeemOtrManager.getInstance().getLocalFingerprint(mOtrSessionId); + } - } + @Override + public String getRemoteOtrFingerprint() throws RemoteException { + if (mOtrSessionId == null) + return null; + + return BeemOtrManager.getInstance().getRemoteFingerprint(mOtrSessionId); + } } diff -r 9443da4a7fb7 -r ab30d289a86c src/com/beem/project/beem/service/aidl/IChat.aidl --- a/src/com/beem/project/beem/service/aidl/IChat.aidl Fri Apr 15 23:58:06 2011 +0200 +++ b/src/com/beem/project/beem/service/aidl/IChat.aidl Sat Apr 16 19:43:53 2011 +0200 @@ -100,5 +100,17 @@ * Listen for an incoming OTR session. */ void listenOtrSession(); + + /** + * get local OTR key fingerprints. + */ + String getLocalOtrFingerprint(); + + + /** + * get remote OTR key fingerprints. + */ + String getRemoteOtrFingerprint(); + } diff -r 9443da4a7fb7 -r ab30d289a86c src/com/beem/project/beem/ui/Chat.java --- a/src/com/beem/project/beem/ui/Chat.java Fri Apr 15 23:58:06 2011 +0200 +++ b/src/com/beem/project/beem/ui/Chat.java Sat Apr 16 19:43:53 2011 +0200 @@ -43,14 +43,14 @@ */ package com.beem.project.beem.ui; +import java.io.IOException; +import java.io.InputStream; import java.text.DateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.io.InputStream; -import java.io.IOException; import org.jivesoftware.smack.packet.Presence.Mode; import org.jivesoftware.smack.util.StringUtils; @@ -62,11 +62,11 @@ import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.SharedPreferences; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.LayerDrawable; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.LayerDrawable; import android.net.Uri; import android.os.Bundle; import android.os.Handler; @@ -84,7 +84,6 @@ import android.view.ViewGroup; import android.view.View.OnClickListener; import android.view.View.OnKeyListener; -import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.EditText; @@ -92,7 +91,6 @@ import android.widget.ListView; import android.widget.TextView; - import com.beem.project.beem.R; import com.beem.project.beem.providers.AvatarProvider; import com.beem.project.beem.service.Contact; @@ -106,6 +104,7 @@ import com.beem.project.beem.service.aidl.IRoster; import com.beem.project.beem.service.aidl.IXmppFacade; import com.beem.project.beem.ui.dialogs.builders.ChatList; +import com.beem.project.beem.ui.dialogs.builders.DisplayOtrFingerprint; import com.beem.project.beem.utils.BeemBroadcastReceiver; import com.beem.project.beem.utils.Status; @@ -176,8 +175,8 @@ mContactChatState = (TextView) findViewById(R.id.chat_contact_chat_state); mContactStatusIcon = (ImageView) findViewById(R.id.chat_contact_status_icon); mAvatarStatusDrawable = (LayerDrawable) mContactStatusIcon.getDrawable(); - mContactOtrState = (TextView) findViewById(R.id.chat_contact_otr_state); - mAvatarStatusDrawable.setLayerInset(1, 36, 36, 0, 0); + mContactOtrState = (TextView) findViewById(R.id.chat_contact_otr_state); + mAvatarStatusDrawable.setLayerInset(1, 36, 36, 0, 0); } else { setContentView(R.layout.chat_compact); } @@ -308,11 +307,10 @@ Log.e(TAG, e.getMessage()); } this.finish(); - this.finish(); break; case R.id.chat_menu_start_otr_session: try { - Log.d(TAG, "opened otr chats = " + mChat + " for "+mContact); + Log.d(TAG, "opened otr chats = " + mChat + " for " + mContact); if (mChat == null) { mChat = mChatManager.createChat(mContact, mMessageListener); if (mChat != null) { @@ -321,12 +319,12 @@ } mChat.startOtrSession(); } catch (RemoteException e) { - Log.e(TAG, e.getMessage()); + Log.e(TAG, "start otr chats failed " + mChat , e); } break; case R.id.chat_menu_listen_otr_session: try { - Log.d(TAG, "listen otr chats = " + mChat + " for "+mContact); + Log.d(TAG, "listen otr chats = " + mChat + " for " + mContact); if (mChat == null) { mChat = mChatManager.createChat(mContact, mMessageListener); if (mChat != null) { @@ -335,12 +333,12 @@ } mChat.listenOtrSession(); } catch (RemoteException e) { - Log.e(TAG, e.getMessage()); + Log.e(TAG, "listen for otr chats failed " + mChat , e); } break; case R.id.chat_menu_stop_otr_session: try { - Log.d(TAG, "close otr chats = " + mChat + " for "+mContact); + Log.d(TAG, "close otr chats = " + mChat + " for " + mContact); if (mChat == null) { mChat = mChatManager.createChat(mContact, mMessageListener); if (mChat != null) { @@ -349,7 +347,39 @@ } mChat.endOtrSession(); } catch (RemoteException e) { - Log.e(TAG, e.getMessage()); + Log.e(TAG, "close otr chats failed " + mChat , e); + } + break; + case R.id.chat_menu_otr_local_key: + try { + if (mChat == null) { + mChat = mChatManager.createChat(mContact, mMessageListener); + if (mChat != null) { + mChat.setOpen(true); + } + } + String fk = mChat.getLocalOtrFingerprint(); + Log.d(TAG, "otr chats = " + mChat + " for " + mContact + " fk " + fk); + Dialog otrDialog = new DisplayOtrFingerprint(this, fk, true).create(); + otrDialog.show(); + } catch (RemoteException e) { + Log.e(TAG, "getting local otr key failed " + mChat , e); + } + break; + case R.id.chat_menu_otr_remote_key: + try { + if (mChat == null) { + mChat = mChatManager.createChat(mContact, mMessageListener); + if (mChat != null) { + mChat.setOpen(true); + } + } + String fk = mChat.getRemoteOtrFingerprint(); + Log.d(TAG, "otr chats = " + mChat + " for " + mContact + " fk " + fk); + Dialog otrDialog = new DisplayOtrFingerprint(this, fk, false).create(); + otrDialog.show(); + } catch (RemoteException e) { + Log.e(TAG, "getting remote otr key failed " + mChat , e); } break; default: @@ -689,7 +719,7 @@ try { try { in = getContentResolver().openInputStream(uri); - avatarDrawable = Drawable.createFromStream(in, avatarId); + avatarDrawable = Drawable.createFromStream(in, avatarId); } finally { if (in != null) in.close(); @@ -772,7 +802,7 @@ View sv; if (convertView == null) { LayoutInflater inflater = Chat.this.getLayoutInflater(); - sv = inflater.inflate(R.layout.chat_msg_row, null); + sv = inflater.inflate(R.layout.chat_msg_row, null); } else { sv = convertView; } diff -r 9443da4a7fb7 -r ab30d289a86c src/net/java/otr4j/OtrKeyManagerImpl.java --- a/src/net/java/otr4j/OtrKeyManagerImpl.java Fri Apr 15 23:58:06 2011 +0200 +++ b/src/net/java/otr4j/OtrKeyManagerImpl.java Sat Apr 16 19:43:53 2011 +0200 @@ -92,6 +92,8 @@ public byte[] getPropertyBytes(String id) { String value = properties.getProperty(id); + if (value == null) + return null; return Base64.decode(value); }