package org.jivesoftware.spark.otrplug.impl; import java.awt.Color; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.security.PublicKey; import javax.swing.ImageIcon; import javax.swing.JOptionPane; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.spark.otrplug.OTRManager; import org.jivesoftware.spark.otrplug.ui.OTRConnectionPanel; import org.jivesoftware.spark.otrplug.util.OTRProperties; import org.jivesoftware.spark.otrplug.util.OTRResources; import org.jivesoftware.spark.ui.ChatRoomButton; import org.jivesoftware.spark.ui.MessageEventListener; import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; import org.jivesoftware.spark.util.UIComponentRegistry; import net.java.otr4j.OtrEngineHost; import net.java.otr4j.OtrEngineImpl; import net.java.otr4j.OtrEngineListener; import net.java.otr4j.OtrPolicy; import net.java.otr4j.OtrPolicyImpl; import net.java.otr4j.session.SessionID; import net.java.otr4j.session.SessionStatus; /** * OTRSession are unique for every conversation. It handles the otrEngine for * the chat and controls if the chat is encrypted or not. * * @author Bergunde Holger */ public class OTRSession { private ChatRoomImpl _chatRoom; private String _myJID; private String _remoteJID; private OtrEngineHost _otrEngineHost; private SessionID _mySession; private OtrEngineImpl _engine; private OTRManager _manager = OTRManager.getInstance(); final ChatRoomButton _otrButton = UIComponentRegistry.getButtonFactory().createOtrButton(); private OTRConnectionPanel _conPanel; private MessageEventListener _msgEvnt; private boolean _OtrEnabled = false; private OtrEngineListener _otrListener; /** * OTRSession Constructor * * @param chatroom * chat room related to this OTR session * @param myJID * my own JID * @param remoteJID * the JID of the participant */ public OTRSession(ChatRoomImpl chatroom, String myJID, String remoteJID) { _chatRoom = chatroom; _myJID = myJID; _remoteJID = remoteJID; _otrEngineHost = new OTREngineHost(new OtrPolicyImpl(OtrPolicy.ALLOW_V2 | OtrPolicy.ERROR_START_AKE), _chatRoom); _mySession = new SessionID(_myJID, _remoteJID, "Scytale"); _engine = new OtrEngineImpl(_otrEngineHost); setUpMessageListener(); createButton(); // Only initialize the actionListener once _otrButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (_engine.getSessionStatus(_mySession).equals(SessionStatus.ENCRYPTED)) { stopSession(); } else { startSession(); } } }); _otrButton.setToolTipText(OTRResources.getString("otr.chat.button.tooltip")); _OtrEnabled = OTRProperties.getInstance().getIsOTREnabled(); } /** * Maybe you want to update the chat room because it was reopend but the OTR * session is still alive. * * @param chatroom * the chat room related to this OTR session */ public void updateChatRoom(ChatRoomImpl chatroom) { _OtrEnabled = OTRProperties.getInstance().getIsOTREnabled(); _chatRoom = chatroom; setUpMessageListener(); createButton(); } private void setUpMessageListener() { _conPanel = new OTRConnectionPanel(_chatRoom); _chatRoom.removeMessageEventListener(_msgEvnt); _msgEvnt = new MessageEventListener() { @Override public void sendingMessage(Message message) { String oldmsg = message.getBody(); if (_engine.getSessionStatus(_mySession).equals(SessionStatus.ENCRYPTED)) { message.setBody(null); String mesg = _engine.transformSending(_mySession, oldmsg); message.setBody(mesg); } } @Override public void receivingMessage(Message message) { if (message.getBody() != null && _OtrEnabled) { String old = message.getBody(); message.setBody(null); String mesg = null; if (old.length() > 2) { mesg = _engine.transformReceiving(_mySession, old); } if (_engine.getSessionStatus(_mySession).equals(SessionStatus.ENCRYPTED)) { message.setBody(mesg); } else { if (old.length() > 3 && old.substring(0, 4).equals("?OTR")) { old = null; } message.setBody(old); } } else if (!_OtrEnabled) { String old = message.getBody(); message.setBody(null); if (old.length() > 3 && old.substring(0, 4).equals("?OTR")) { _chatRoom.getTranscriptWindow().insertNotificationMessage(OTRResources.getString("otr.not.enabled"), Color.gray); } else { message.setBody(old); } } } }; _chatRoom.addMessageEventListener(_msgEvnt); } private void createButton() { if (OTRProperties.getInstance().getIsOTREnabled()) { final ClassLoader cl = getClass().getClassLoader(); ImageIcon otricon = null; if (_engine.getSessionStatus(_mySession).equals(SessionStatus.ENCRYPTED)) { otricon = new ImageIcon(cl.getResource("otr_on.png")); _conPanel.successfullyCon(); } else { otricon = new ImageIcon(cl.getResource("otr_off.png")); } _otrButton.setIcon(otricon); _engine.removeOtrEngineListener(_otrListener); _chatRoom.getToolBar().addChatRoomButton(_otrButton); _otrListener = new OtrEngineListener() { @Override public void sessionStatusChanged(SessionID arg0) { if (_engine.getSessionStatus(_mySession).equals(SessionStatus.ENCRYPTED)) { _conPanel.successfullyCon(); String otrkey = _manager.getKeyManager().getRemoteFingerprint(_mySession); if (otrkey == null) { PublicKey pubkey = _engine.getRemotePublicKey(_mySession); _manager.getKeyManager().savePublicKey(_mySession, pubkey); otrkey = _manager.getKeyManager().getRemoteFingerprint(_mySession); } if (!OTRManager.getInstance().getKeyManager().isVerified(_mySession)) { final int n = JOptionPane.showConfirmDialog(_otrButton, OTRResources.getString("otr.start.session.with", _remoteJID) + "\n" + OTRResources.getString("otr.key.not.verified.text") + "\n" + otrkey + "\n" + OTRResources.getString("otr.question.verify"), OTRResources.getString("otr.key.not.verified.title"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); if (n == JOptionPane.YES_OPTION) { _manager.getKeyManager().verify(_mySession); } } _otrButton.setIcon(new ImageIcon(cl.getResource("otr_on.png"))); } else if (_engine.getSessionStatus(_mySession).equals(SessionStatus.FINISHED)) { _otrButton.setIcon(new ImageIcon(cl.getResource("otr_off.png"))); stopSession(); } else if (_engine.getSessionStatus(_mySession).equals(SessionStatus.PLAINTEXT)) { _otrButton.setIcon(new ImageIcon(cl.getResource("otr_off.png"))); stopSession(); } } }; _engine.addOtrEngineListener(_otrListener); } } /** * Start the OTR session manually from outside */ public void startSession() { _conPanel.tryToStart(); _engine.startSession(_mySession); } /** * Stop the OTR session manually from outside */ public void stopSession() { _conPanel.connectionClosed(); if (_engine.getSessionStatus(_mySession).equals(SessionStatus.ENCRYPTED)) { final ClassLoader cl = getClass().getClassLoader(); _otrButton.setIcon(new ImageIcon(cl.getResource("otr_off.png"))); _engine.endSession(_mySession); } } }