mirror of
https://github.com/igniterealtime/Spark.git
synced 2025-12-01 12:27:58 +00:00
SPARK-884 merged otr plugin branch 0.2 beta into trunk
git-svn-id: http://svn.igniterealtime.org/svn/repos/spark/trunk@12465 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
@ -386,6 +386,10 @@
|
||||
<subant target="">
|
||||
<fileset dir="./src/plugins/translator/" includes="*/build.xml" />
|
||||
</subant>
|
||||
|
||||
<subant target="">
|
||||
<fileset dir="./src/plugins/otr/" includes="*/build.xml" />
|
||||
</subant>
|
||||
|
||||
<copy todir="${plugins}">
|
||||
<fileset dir="${commercial.plugin.dir}">
|
||||
|
||||
97
src/plugins/otr/build/build.xml
Normal file
97
src/plugins/otr/build/build.xml
Normal file
@ -0,0 +1,97 @@
|
||||
<project name="otrplug" default="jar" basedir="..">
|
||||
|
||||
<property name="plug.dir" value="${basedir}"/>
|
||||
<property name="plug.lib.dir" value="${plug.dir}/build/lib"/>
|
||||
<property name="plug.lib.dist.dir" value="${plug.lib.dir}/dist"/>
|
||||
|
||||
<property name="spark.home" value="${basedir}/../../.."/>
|
||||
<property name="spark.target" value="${basedir}/../../../target"/>
|
||||
<property name="spark.build" value="${basedir}/../../../target/build"/>
|
||||
|
||||
<property name="classes.dir" value="${spark.target}/plugins-dev/otrplug/classes"/>
|
||||
<property name="src.dir" value="${plug.dir}/src/java"/>
|
||||
<property name="resources.dir" location="${plug.dir}/src/resources"/>
|
||||
|
||||
<property name="target.dir" value="${spark.target}/plugins/otrplug"/>
|
||||
<property name="target.lib.dir" value="${target.dir}/lib"/>
|
||||
<property name="jar.file" value="${target.dir}/lib/plugin-classes.jar"/>
|
||||
|
||||
<path id="lib.classpath">
|
||||
<fileset dir="${plug.lib.dir}" includes="**/*.jar, **/*.zip"/>
|
||||
<fileset dir="${plug.lib.dist.dir}" includes="**/*.jar, **/*.zip"/>
|
||||
<fileset dir="${spark.home}/target/build/lib/" includes="**/*.jar, **/*.zip"/>
|
||||
<fileset dir="${spark.home}/target/build/lib/windows" includes="**/*.jar"/>
|
||||
</path>
|
||||
|
||||
<target name="clean" description="Cleans all build related output">
|
||||
<delete file="${jar.file}"/>
|
||||
<delete dir="${classes.dir}"/>
|
||||
<delete dir="${target.dir}"/>
|
||||
</target>
|
||||
|
||||
<target name="compile" description="Compiles plugin source">
|
||||
<mkdir dir="${classes.dir}"/>
|
||||
<javac srcdir="${src.dir}"
|
||||
destdir="${classes.dir}"
|
||||
classpathref="lib.classpath"
|
||||
source="1.6"
|
||||
debug="true"
|
||||
target="1.6"/>
|
||||
<copy todir="${classes.dir}">
|
||||
<fileset dir="${src.dir}" includes="**/*.png"/>
|
||||
<fileset dir="${src.dir}" includes="**/*.gif"/>
|
||||
<fileset dir="${src.dir}" includes="**/*.jpg"/>
|
||||
<fileset dir="${src.dir}" includes="**/*.jpeg"/>
|
||||
<fileset dir="${src.dir}" includes="**/*.wav"/>
|
||||
<fileset dir="${src.dir}" includes="**/*.properties"/>
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<target name="jar" depends="clean,compile,resources" description="Makes a plugin jar">
|
||||
<mkdir dir="${target.dir}"/>
|
||||
<mkdir dir="${target.lib.dir}"/>
|
||||
|
||||
<copy todir="${target.lib.dir}">
|
||||
<fileset file="${plug.lib.dist.dir}/*.*"/>
|
||||
</copy>
|
||||
|
||||
<copy todir="${target.dir}">
|
||||
<fileset file="${plug.dir}/plugin.xml"/>
|
||||
</copy>
|
||||
|
||||
<jar basedir="${classes.dir}" file="${jar.file}" update="false"/>
|
||||
|
||||
<zip zipfile="${spark.build}/plugins/otrplug.jar" basedir="${target.dir}"/>
|
||||
|
||||
<copy todir="${spark.home}/src/commercial">
|
||||
<fileset file="${spark.build}/plugins/otrplug.jar"/>
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<!-- resources =================================================================================== -->
|
||||
<target name="resources">
|
||||
<copy todir="${classes.dir}">
|
||||
<fileset dir="${resources.dir}">
|
||||
<include name="**/*"/>
|
||||
</fileset>
|
||||
<fileset dir="${src.dir}">
|
||||
<include name="**/*.properties"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
|
||||
<property name="pluginsstuff" value="${basedir}\..\..\..\target\build\plugins"/>
|
||||
|
||||
<target name="copy" depends="jar">
|
||||
|
||||
<echo message="${pluginsstuff}"/>
|
||||
|
||||
<copy todir="${pluginsstuff}">
|
||||
<fileset file="${spark.build}/plugins/otrplug.jar"/>
|
||||
</copy>
|
||||
|
||||
</target>
|
||||
|
||||
|
||||
</project>
|
||||
BIN
src/plugins/otr/build/lib/dist/bcprov-jdk16-146.jar
vendored
Normal file
BIN
src/plugins/otr/build/lib/dist/bcprov-jdk16-146.jar
vendored
Normal file
Binary file not shown.
BIN
src/plugins/otr/build/lib/dist/otr4j-0.9.jar
vendored
Normal file
BIN
src/plugins/otr/build/lib/dist/otr4j-0.9.jar
vendored
Normal file
Binary file not shown.
16
src/plugins/otr/how-to-build.txt
Normal file
16
src/plugins/otr/how-to-build.txt
Normal file
@ -0,0 +1,16 @@
|
||||
Building a Sparkplug
|
||||
|
||||
To easily build a Sparkplug, we have added a simple ANT script to create a deployed plug. To create, do the following:
|
||||
|
||||
1) Copy your java source files to the src directory.
|
||||
2) Place any dependencies (besides Spark) into the lib directory.
|
||||
3) Update the plugin.xml file to represent your plugin.
|
||||
4) Go to the build directory, and type ant jar to build your plugin or
|
||||
.... type "ant run" to build and deploy your plugin directly to Spark and
|
||||
have Spark startup to test your plugin right away.
|
||||
|
||||
Your new plugin will be called myplugin.jar.
|
||||
|
||||
If you wish to deploy your plugin later, just copy your new myplugin.jar to the plugins directory of your Sparkplug distro kit.
|
||||
|
||||
Enjoy!
|
||||
13
src/plugins/otr/plugin.xml
Normal file
13
src/plugins/otr/plugin.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<!-- Define your plugins -->
|
||||
<plugin>
|
||||
<name>OTR Plugin</name>
|
||||
<version>0.2 Beta </version>
|
||||
<author>Holger Bergunde</author>
|
||||
<homePage>http://www.stytrix.de</homePage>
|
||||
<email>holger@bergunde.de</email>
|
||||
<description>Adds OTR support to Spark</description>
|
||||
<minSparkVersion>2.6.0</minSparkVersion>
|
||||
<java>1.6.0_01</java>
|
||||
<class>org.jivesoftware.spark.otrplug.OTRPlugin</class>
|
||||
<os>Windows,Linux,Mac</os>
|
||||
</plugin>
|
||||
@ -0,0 +1,160 @@
|
||||
package org.jivesoftware.spark.otrplug;
|
||||
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.Icon;
|
||||
|
||||
import net.java.otr4j.session.SessionID;
|
||||
|
||||
import org.jivesoftware.smack.packet.Presence;
|
||||
import org.jivesoftware.spark.ChatManager;
|
||||
import org.jivesoftware.spark.SparkManager;
|
||||
|
||||
import org.jivesoftware.spark.otrplug.impl.MyOtrKeyManager;
|
||||
import org.jivesoftware.spark.otrplug.impl.OTRSession;
|
||||
import org.jivesoftware.spark.otrplug.util.OTRProperties;
|
||||
import org.jivesoftware.spark.ui.ChatRoom;
|
||||
import org.jivesoftware.spark.ui.ChatRoomListenerAdapter;
|
||||
import org.jivesoftware.spark.ui.ContactItem;
|
||||
import org.jivesoftware.spark.ui.ContactItemHandler;
|
||||
import org.jivesoftware.spark.ui.rooms.ChatRoomImpl;
|
||||
|
||||
|
||||
|
||||
|
||||
public class OTRManager extends ChatRoomListenerAdapter implements ContactItemHandler {
|
||||
|
||||
private static OTRManager singleton;
|
||||
private static Object LOCK = new Object();
|
||||
private Map<String, OTRSession> _activeSessions = new HashMap<String,OTRSession>();
|
||||
final ChatManager chatManager = SparkManager.getChatManager();
|
||||
private static MyOtrKeyManager _keyManager;
|
||||
|
||||
|
||||
private OTRManager()
|
||||
{
|
||||
chatManager.addChatRoomListener(this);
|
||||
chatManager.addContactItemHandler(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void chatRoomOpened(ChatRoom room) {
|
||||
super.chatRoomOpened(room);
|
||||
if (room instanceof ChatRoomImpl) {
|
||||
createOTRSession((ChatRoomImpl) room, ((ChatRoomImpl) room).getParticipantJID());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chatRoomClosed(ChatRoom room) {
|
||||
super.chatRoomClosed(room);
|
||||
if (OTRProperties.getInstance().getOTRCloseOnChatClose()) {
|
||||
if (room instanceof ChatRoomImpl) {
|
||||
ChatRoomImpl myroom = (ChatRoomImpl) room;
|
||||
if (_activeSessions.containsKey(myroom.getParticipantJID())) {
|
||||
OTRSession searchedSession = _activeSessions.get(myroom.getParticipantJID());
|
||||
searchedSession.stopSession();
|
||||
_activeSessions.remove(myroom.getParticipantJID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static OTRManager getInstance() {
|
||||
// Synchronize on LOCK to ensure that we don't end up creating
|
||||
// two singletons.
|
||||
synchronized (LOCK) {
|
||||
if (null == singleton) {
|
||||
OTRManager controller = new OTRManager();
|
||||
singleton = controller;
|
||||
try {
|
||||
_keyManager = new MyOtrKeyManager(SparkManager.getUserDirectory().getPath()+"/otrkey.priv");
|
||||
//we should generate a local keyprint if there is no avaiable
|
||||
String key = _keyManager.getLocalFingerprint(new SessionID(SparkManager.getConnection().getUser(), "none", "Scytale"));
|
||||
if (key == null)
|
||||
{
|
||||
_keyManager.generateLocalKeyPair(new SessionID(SparkManager.getConnection().getUser(), "none", "Scytale"));
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
return controller;
|
||||
}
|
||||
}
|
||||
return singleton;
|
||||
}
|
||||
|
||||
public void startOtrWithUser(String jid)
|
||||
{
|
||||
if (_activeSessions.containsKey(jid))
|
||||
{
|
||||
_activeSessions.get(jid).startSession();
|
||||
}
|
||||
}
|
||||
|
||||
private void createOTRSession(ChatRoomImpl chatroom, String jid)
|
||||
{
|
||||
if (!_activeSessions.containsKey(jid))
|
||||
{
|
||||
_activeSessions.put(jid, startOTRSession(chatroom, jid));
|
||||
} else {
|
||||
_activeSessions.get(jid).updateChatRoom(chatroom);
|
||||
}
|
||||
}
|
||||
|
||||
public MyOtrKeyManager getKeyManager()
|
||||
{
|
||||
return _keyManager;
|
||||
}
|
||||
|
||||
private OTRSession startOTRSession(ChatRoomImpl chatroom, String jid)
|
||||
{
|
||||
return new OTRSession(chatroom, SparkManager.getConnection().getUser(), jid);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean handlePresence(ContactItem item, Presence presence) {
|
||||
if (OTRProperties.getInstance().getOTRCloseOnDisc())
|
||||
{
|
||||
if (!presence.isAvailable() && _activeSessions.containsKey(item.getJID()))
|
||||
{
|
||||
_activeSessions.get(item.getJID()).stopSession();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Icon getIcon(String jid) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Icon getTabIcon(Presence presence) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean handleDoubleClick(ContactItem item) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
package org.jivesoftware.spark.otrplug;
|
||||
|
||||
import org.jivesoftware.spark.SparkManager;
|
||||
import org.jivesoftware.spark.otrplug.pref.OTRPreferences;
|
||||
import org.jivesoftware.spark.plugin.Plugin;
|
||||
import org.jivesoftware.spark.preference.Preference;
|
||||
|
||||
|
||||
|
||||
public class OTRPlugin implements Plugin{
|
||||
|
||||
OTRManager _manager;
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
//Create OTRManager singleton
|
||||
|
||||
_manager = OTRManager.getInstance();
|
||||
|
||||
// The following will add an Entry into the Spark Preferences Window
|
||||
Preference mypreference = new OTRPreferences();
|
||||
SparkManager.getPreferenceManager().addPreference(mypreference);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canShutDown() {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uninstall() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,298 @@
|
||||
package org.jivesoftware.spark.otrplug.impl;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.bouncycastle.util.encoders.Base64;
|
||||
|
||||
import net.java.otr4j.OtrKeyManager;
|
||||
import net.java.otr4j.OtrKeyManagerListener;
|
||||
import net.java.otr4j.OtrKeyManagerStore;
|
||||
import net.java.otr4j.crypto.OtrCryptoEngineImpl;
|
||||
import net.java.otr4j.crypto.OtrCryptoException;
|
||||
import net.java.otr4j.session.SessionID;
|
||||
|
||||
public class MyOtrKeyManager implements OtrKeyManager {
|
||||
|
||||
private OtrKeyManagerStore store;
|
||||
|
||||
public MyOtrKeyManager(OtrKeyManagerStore store) {
|
||||
this.store = store;
|
||||
}
|
||||
|
||||
class DefaultPropertiesStore implements OtrKeyManagerStore {
|
||||
private final Properties properties = new Properties();
|
||||
private String filepath;
|
||||
|
||||
public DefaultPropertiesStore(String filepath) throws IOException {
|
||||
if (filepath == null || filepath.length() < 1)
|
||||
throw new IllegalArgumentException();
|
||||
this.filepath = filepath;
|
||||
properties.clear();
|
||||
|
||||
InputStream in = new BufferedInputStream(new FileInputStream(getConfigurationFile()));
|
||||
try {
|
||||
properties.load(in);
|
||||
} finally {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
|
||||
private File getConfigurationFile() throws IOException {
|
||||
File configFile = new File(filepath);
|
||||
if (!configFile.exists())
|
||||
configFile.createNewFile();
|
||||
return configFile;
|
||||
}
|
||||
|
||||
public void setProperty(String id, boolean value) {
|
||||
properties.setProperty(id, "true");
|
||||
try {
|
||||
this.store();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void store() throws FileNotFoundException, IOException {
|
||||
OutputStream out = new FileOutputStream(getConfigurationFile());
|
||||
properties.store(out, null);
|
||||
out.close();
|
||||
}
|
||||
|
||||
public void setProperty(String id, byte[] value) {
|
||||
properties.setProperty(id, new String(Base64.encode(value)));
|
||||
try {
|
||||
this.store();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void removeProperty(String id) {
|
||||
properties.remove(id);
|
||||
try {
|
||||
this.store();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getPropertyBytes(String id) {
|
||||
String value = properties.getProperty(id);
|
||||
if (value == null)
|
||||
return null;
|
||||
return Base64.decode(value);
|
||||
}
|
||||
|
||||
public boolean getPropertyBoolean(String id, boolean defaultValue) {
|
||||
try {
|
||||
return Boolean.valueOf(properties.get(id).toString());
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public MyOtrKeyManager(String filepath) throws IOException {
|
||||
this.store = new DefaultPropertiesStore(filepath);
|
||||
}
|
||||
|
||||
private List<OtrKeyManagerListener> listeners = new Vector<OtrKeyManagerListener>();
|
||||
|
||||
public void addListener(OtrKeyManagerListener l) {
|
||||
synchronized (listeners) {
|
||||
if (!listeners.contains(l))
|
||||
listeners.add(l);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeListener(OtrKeyManagerListener l) {
|
||||
synchronized (listeners) {
|
||||
listeners.remove(l);
|
||||
}
|
||||
}
|
||||
|
||||
public void generateLocalKeyPair(SessionID sessionID) {
|
||||
if (sessionID == null)
|
||||
return;
|
||||
|
||||
String accountID = sessionID.getAccountID();
|
||||
KeyPair keyPair;
|
||||
try {
|
||||
keyPair = KeyPairGenerator.getInstance("DSA").genKeyPair();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
// Store Public Key.
|
||||
PublicKey pubKey = keyPair.getPublic();
|
||||
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(pubKey.getEncoded());
|
||||
|
||||
this.store.setProperty(accountID + ".publicKey", x509EncodedKeySpec.getEncoded());
|
||||
|
||||
// Store Private Key.
|
||||
PrivateKey privKey = keyPair.getPrivate();
|
||||
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privKey.getEncoded());
|
||||
|
||||
this.store.setProperty(accountID + ".privateKey", pkcs8EncodedKeySpec.getEncoded());
|
||||
}
|
||||
|
||||
public String getLocalFingerprint(SessionID sessionID) {
|
||||
KeyPair keyPair = loadLocalKeyPair(sessionID);
|
||||
|
||||
if (keyPair == null)
|
||||
return null;
|
||||
|
||||
PublicKey pubKey = keyPair.getPublic();
|
||||
|
||||
try {
|
||||
return new OtrCryptoEngineImpl().getFingerprint(pubKey);
|
||||
} catch (OtrCryptoException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String getRemoteFingerprint(SessionID sessionID) {
|
||||
PublicKey remotePublicKey = loadRemotePublicKey(sessionID);
|
||||
if (remotePublicKey == null)
|
||||
return null;
|
||||
try {
|
||||
return new OtrCryptoEngineImpl().getFingerprint(remotePublicKey);
|
||||
} catch (OtrCryptoException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isVerified(SessionID sessionID) {
|
||||
if (sessionID == null)
|
||||
return false;
|
||||
|
||||
return this.store.getPropertyBoolean(sessionID.getUserID() + ".publicKey.verified", false);
|
||||
}
|
||||
|
||||
public KeyPair loadLocalKeyPair(SessionID sessionID) {
|
||||
if (sessionID == null)
|
||||
return null;
|
||||
|
||||
String accountID = sessionID.getAccountID();
|
||||
// Load Private Key.
|
||||
byte[] b64PrivKey = this.store.getPropertyBytes(accountID + ".privateKey");
|
||||
if (b64PrivKey == null)
|
||||
return null;
|
||||
|
||||
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(b64PrivKey);
|
||||
|
||||
// Load Public Key.
|
||||
byte[] b64PubKey = this.store.getPropertyBytes(accountID + ".publicKey");
|
||||
if (b64PubKey == null)
|
||||
return null;
|
||||
|
||||
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(b64PubKey);
|
||||
|
||||
PublicKey publicKey;
|
||||
PrivateKey privateKey;
|
||||
|
||||
// Generate KeyPair.
|
||||
KeyFactory keyFactory;
|
||||
try {
|
||||
keyFactory = KeyFactory.getInstance("DSA");
|
||||
publicKey = keyFactory.generatePublic(publicKeySpec);
|
||||
privateKey = keyFactory.generatePrivate(privateKeySpec);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
} catch (InvalidKeySpecException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
return new KeyPair(publicKey, privateKey);
|
||||
}
|
||||
|
||||
public PublicKey loadRemotePublicKey(SessionID sessionID) {
|
||||
if (sessionID == null)
|
||||
return null;
|
||||
|
||||
String userID = sessionID.getUserID();
|
||||
|
||||
byte[] b64PubKey = this.store.getPropertyBytes(userID + ".publicKey");
|
||||
if (b64PubKey == null)
|
||||
return null;
|
||||
|
||||
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(b64PubKey);
|
||||
|
||||
// Generate KeyPair.
|
||||
KeyFactory keyFactory;
|
||||
try {
|
||||
keyFactory = KeyFactory.getInstance("DSA");
|
||||
return keyFactory.generatePublic(publicKeySpec);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
} catch (InvalidKeySpecException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void savePublicKey(SessionID sessionID, PublicKey pubKey) {
|
||||
if (sessionID == null)
|
||||
return;
|
||||
|
||||
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(pubKey.getEncoded());
|
||||
|
||||
String userID = sessionID.getUserID();
|
||||
this.store.setProperty(userID + ".publicKey", x509EncodedKeySpec.getEncoded());
|
||||
|
||||
this.store.removeProperty(userID + ".publicKey.verified");
|
||||
}
|
||||
|
||||
public void unverify(SessionID sessionID) {
|
||||
if (sessionID == null)
|
||||
return;
|
||||
|
||||
if (!isVerified(sessionID))
|
||||
return;
|
||||
|
||||
this.store.removeProperty(sessionID.getUserID() + ".publicKey.verified");
|
||||
for (OtrKeyManagerListener l : listeners)
|
||||
l.verificationStatusChanged(sessionID);
|
||||
|
||||
}
|
||||
|
||||
public void verify(SessionID sessionID) {
|
||||
if (sessionID == null)
|
||||
return;
|
||||
|
||||
if (this.isVerified(sessionID))
|
||||
return;
|
||||
|
||||
this.store.setProperty(sessionID.getUserID() + ".publicKey.verified", true);
|
||||
|
||||
for (OtrKeyManagerListener l : listeners)
|
||||
l.verificationStatusChanged(sessionID);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
package org.jivesoftware.spark.otrplug.impl;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.security.KeyPair;
|
||||
|
||||
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
import org.jivesoftware.spark.SparkManager;
|
||||
import org.jivesoftware.spark.otrplug.OTRManager;
|
||||
import org.jivesoftware.spark.ui.rooms.ChatRoomImpl;
|
||||
|
||||
import net.java.otr4j.OtrEngineHost;
|
||||
import net.java.otr4j.OtrPolicy;
|
||||
import net.java.otr4j.session.SessionID;
|
||||
|
||||
public class OTREngineHost implements OtrEngineHost {
|
||||
|
||||
private ChatRoomImpl _chatRoom;
|
||||
private OtrPolicy _policy;
|
||||
public OTREngineHost(OtrPolicy policy, ChatRoomImpl chatroom)
|
||||
{
|
||||
_policy = policy;
|
||||
_chatRoom = chatroom;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyPair getKeyPair(SessionID arg0) {
|
||||
return OTRManager.getInstance().getKeyManager().loadLocalKeyPair(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OtrPolicy getSessionPolicy(SessionID arg0) {
|
||||
return _policy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectMessage(SessionID arg0, String arg1) {
|
||||
Message injection = new Message();
|
||||
injection.setType(Message.Type.chat);
|
||||
injection.setTo(_chatRoom.getParticipantJID());
|
||||
injection.setFrom(SparkManager.getSessionManager().getJID());
|
||||
String threadID = StringUtils.randomString(6);
|
||||
injection.setThread(threadID);
|
||||
injection.setBody(arg1);
|
||||
SparkManager.getConnection().sendPacket(injection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showError(SessionID arg0, String arg1) {
|
||||
_chatRoom.getTranscriptWindow().insertNotificationMessage(arg1, Color.red);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showWarning(SessionID arg0, String arg1) {
|
||||
_chatRoom.getTranscriptWindow().insertNotificationMessage(arg1, Color.red);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,201 @@
|
||||
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 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;
|
||||
|
||||
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 = new ChatRoomButton();
|
||||
private OTRConnectionPanel _conPanel;
|
||||
private boolean _OtrEnabled = false;
|
||||
|
||||
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();
|
||||
_OtrEnabled = OTRProperties.getInstance().getIsOTREnabled();
|
||||
}
|
||||
|
||||
public void updateChatRoom(ChatRoomImpl chatroom) {
|
||||
_OtrEnabled = OTRProperties.getInstance().getIsOTREnabled();
|
||||
_chatRoom = chatroom;
|
||||
setUpMessageListener();
|
||||
createButton();
|
||||
}
|
||||
|
||||
private void setUpMessageListener() {
|
||||
|
||||
_conPanel = new OTRConnectionPanel(_chatRoom);
|
||||
|
||||
|
||||
_chatRoom.addMessageEventListener(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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
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"));
|
||||
_chatRoom.getTranscriptWindow().insertNotificationMessage("From now on, your conversation is encrypted", Color.gray);
|
||||
} else {
|
||||
otricon = new ImageIcon(cl.getResource("otr_off.png"));
|
||||
}
|
||||
|
||||
_otrButton.setIcon(otricon);
|
||||
|
||||
_otrButton.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (_engine.getSessionStatus(_mySession).equals(SessionStatus.ENCRYPTED)) {
|
||||
stopSession();
|
||||
} else {
|
||||
startSession();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
_chatRoom.getToolBar().addChatRoomButton(_otrButton);
|
||||
_engine.addOtrEngineListener(new OtrEngineListener() {
|
||||
|
||||
@Override
|
||||
public void sessionStatusChanged(SessionID arg0) {
|
||||
if (_engine.getSessionStatus(_mySession).equals(SessionStatus.ENCRYPTED)) {
|
||||
_conPanel.sucessfullyCon();
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void startSession() {
|
||||
_conPanel.tryToStart();
|
||||
_engine.startSession(_mySession);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,87 @@
|
||||
package org.jivesoftware.spark.otrplug.pref;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
|
||||
import javax.swing.event.TableModelListener;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
|
||||
import org.jivesoftware.spark.otrplug.util.OTRResources;
|
||||
|
||||
|
||||
public class OTRKeyTable extends JPanel {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -2922785387942547350L;
|
||||
private JTable _table;
|
||||
private DefaultTableModel _tableModel;
|
||||
|
||||
public OTRKeyTable() {
|
||||
|
||||
final String[] header = { OTRResources.getString("otr.table.jid"), OTRResources.getString("otr.table.public.key"), OTRResources.getString("otr.key.verified") };
|
||||
|
||||
_tableModel = new MyTableModel(header);
|
||||
_table = new JTable(_tableModel);
|
||||
_table.getTableHeader().setReorderingAllowed(false);
|
||||
|
||||
this.setLayout(new BorderLayout());
|
||||
this.add(new JScrollPane(_table), BorderLayout.CENTER);
|
||||
|
||||
}
|
||||
|
||||
class MyTableModel extends DefaultTableModel {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -2930577433474767242L;
|
||||
|
||||
public MyTableModel(String[] headers) {
|
||||
super(headers, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCellEditable(int row, int column) {
|
||||
if (column == 2)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getColumnClass(int columnIndex) {
|
||||
if (columnIndex == 2) {
|
||||
return Boolean.class;
|
||||
} else
|
||||
return String.class;
|
||||
}
|
||||
}
|
||||
|
||||
public void addTableChangeListener(TableModelListener listener) {
|
||||
_tableModel.addTableModelListener(listener);
|
||||
}
|
||||
|
||||
public void addEntry(String jid, String hash, boolean verified) {
|
||||
Vector<Object> data = new Vector<Object>(3);
|
||||
|
||||
data.add(jid);
|
||||
data.add(hash);
|
||||
data.add(verified);
|
||||
|
||||
_tableModel.addRow(data);
|
||||
}
|
||||
|
||||
public Object getValueAt(int row, int col) {
|
||||
return _tableModel.getValueAt(row, col);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,198 @@
|
||||
package org.jivesoftware.spark.otrplug.pref;
|
||||
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.event.TableModelEvent;
|
||||
import javax.swing.event.TableModelListener;
|
||||
|
||||
import net.java.otr4j.session.SessionID;
|
||||
|
||||
import org.jivesoftware.smack.RosterEntry;
|
||||
import org.jivesoftware.spark.SparkManager;
|
||||
|
||||
import org.jivesoftware.spark.otrplug.OTRManager;
|
||||
import org.jivesoftware.spark.otrplug.impl.MyOtrKeyManager;
|
||||
import org.jivesoftware.spark.otrplug.util.OTRProperties;
|
||||
import org.jivesoftware.spark.otrplug.util.OTRResources;
|
||||
|
||||
public class OTRPrefPanel extends JPanel {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -7125162190413040003L;
|
||||
private OTRManager _manager;
|
||||
private JCheckBox _enableOTR;
|
||||
private JCheckBox _closeSessionOff;
|
||||
private JCheckBox _closeSessionOnWindowClose;
|
||||
private JLabel _currentKeyLabel;
|
||||
private JButton _renewPrivateKey;
|
||||
private OTRKeyTable _keytable;
|
||||
private JTextField _privateKey;
|
||||
private MyOtrKeyManager _keyManager;
|
||||
private OTRProperties _properties;
|
||||
|
||||
public OTRPrefPanel() {
|
||||
|
||||
_manager = OTRManager.getInstance();
|
||||
_keyManager = _manager.getKeyManager();
|
||||
_properties = OTRProperties.getInstance();
|
||||
setLayout(new GridBagLayout());
|
||||
init();
|
||||
buildGUI();
|
||||
OtrEnableSwitch();
|
||||
}
|
||||
|
||||
private void OtrEnableSwitch() {
|
||||
if (!_enableOTR.isSelected())
|
||||
{
|
||||
_closeSessionOff.setEnabled(false);
|
||||
_closeSessionOnWindowClose.setEnabled(false);
|
||||
_renewPrivateKey.setEnabled(false);
|
||||
_keytable.setEnabled(false);
|
||||
} else {
|
||||
_closeSessionOff.setEnabled(true);
|
||||
_closeSessionOnWindowClose.setEnabled(true);
|
||||
_renewPrivateKey.setEnabled(true);
|
||||
_keytable.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void init() {
|
||||
|
||||
_enableOTR = new JCheckBox();
|
||||
_enableOTR.setText(OTRResources.getString("otr.enable"));
|
||||
_enableOTR.setSelected(_properties.getIsOTREnabled());
|
||||
|
||||
_enableOTR.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
OtrEnableSwitch();
|
||||
}
|
||||
});
|
||||
|
||||
_closeSessionOff = new JCheckBox();
|
||||
_closeSessionOff.setText(OTRResources.getString("otr.close.session.on.contact.off"));
|
||||
_closeSessionOff.setSelected(_properties.getOTRCloseOnDisc());
|
||||
|
||||
_closeSessionOnWindowClose = new JCheckBox();
|
||||
_closeSessionOnWindowClose.setText(OTRResources.getString("otr.close.session.on.window.close"));
|
||||
_closeSessionOnWindowClose.setSelected(_properties.getOTRCloseOnChatClose());
|
||||
|
||||
_currentKeyLabel = new JLabel();
|
||||
_currentKeyLabel.setText(OTRResources.getString("current.priv.key"));
|
||||
|
||||
_renewPrivateKey = new JButton();
|
||||
_renewPrivateKey.setText(OTRResources.getString("renew.current.key"));
|
||||
_renewPrivateKey.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
SessionID mySession = new SessionID(SparkManager.getConnection().getUser(), "no one", "Scytale");
|
||||
_manager.getKeyManager().generateLocalKeyPair(mySession);
|
||||
_privateKey.setText(getCurrentLocalKey());
|
||||
}
|
||||
});
|
||||
|
||||
_privateKey = new JTextField();
|
||||
_privateKey.setEditable(false);
|
||||
_privateKey.setText(getCurrentLocalKey());
|
||||
|
||||
_keytable = new OTRKeyTable();
|
||||
|
||||
loadRemoteKeys();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void loadRemoteKeys() {
|
||||
|
||||
for (RosterEntry entry : SparkManager.getConnection().getRoster().getEntries()) {
|
||||
SessionID curSession = new SessionID(SparkManager.getConnection().getUser(), entry.getUser(), "Scytale");
|
||||
String remoteKey = _keyManager.getRemoteFingerprint(curSession);
|
||||
if (remoteKey != null) {
|
||||
boolean isVerified = _keyManager.isVerified(curSession);
|
||||
_keytable.addEntry(entry.getUser(), remoteKey, isVerified);
|
||||
}
|
||||
}
|
||||
|
||||
_keytable.addTableChangeListener(new TableModelListener() {
|
||||
|
||||
@Override
|
||||
public void tableChanged(TableModelEvent e) {
|
||||
int col = e.getColumn();
|
||||
int row = e.getFirstRow();
|
||||
|
||||
if (col == 2) {
|
||||
boolean selection = (Boolean) _keytable.getValueAt(row, col);
|
||||
String JID = (String)_keytable.getValueAt(row, 0);
|
||||
SessionID curSelectedSession = new SessionID(SparkManager.getConnection().getUser(), JID, "Scytale");
|
||||
if (!selection) {
|
||||
_keyManager.verify(curSelectedSession);
|
||||
} else
|
||||
{
|
||||
_keyManager.unverify(curSelectedSession);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void buildGUI() {
|
||||
this.setBorder(BorderFactory.createTitledBorder(OTRResources.getString("otr.settings")));
|
||||
this.add(_enableOTR, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
|
||||
this.add(_closeSessionOff, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(10, 0, 0, 0), 0, 0));
|
||||
this.add(_closeSessionOnWindowClose, new GridBagConstraints(0, 2, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
|
||||
this.add(_currentKeyLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 5, 0, 0), 0, 0));
|
||||
this.add(_privateKey, new GridBagConstraints(1, 3, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(10, 0, 0, 5), 0, 0));
|
||||
this.add(_renewPrivateKey, new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHEAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 5), 0, 0));
|
||||
this.add(_keytable, new GridBagConstraints(0, 5, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(20, 5, 10, 5), 0, 0));
|
||||
}
|
||||
|
||||
|
||||
private String getCurrentLocalKey() {
|
||||
SessionID mySession = new SessionID(SparkManager.getConnection().getUser(), "no one", "Scytale");
|
||||
String myKey = _keyManager.getLocalFingerprint(mySession);
|
||||
return myKey;
|
||||
}
|
||||
|
||||
public JComponent getGUI() {
|
||||
_keytable = new OTRKeyTable();
|
||||
loadRemoteKeys();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public boolean isOTREnabled()
|
||||
{
|
||||
return _enableOTR.isSelected();
|
||||
}
|
||||
|
||||
public boolean isCloseOnDisc()
|
||||
{
|
||||
return _closeSessionOff.isSelected();
|
||||
}
|
||||
public boolean isCloseOnChatClose()
|
||||
{
|
||||
return _closeSessionOnWindowClose.isSelected();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
package org.jivesoftware.spark.otrplug.pref;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
|
||||
|
||||
import org.jivesoftware.spark.otrplug.util.OTRProperties;
|
||||
import org.jivesoftware.spark.otrplug.util.OTRResources;
|
||||
import org.jivesoftware.spark.preference.Preference;
|
||||
|
||||
public class OTRPreferences implements Preference {
|
||||
|
||||
private OTRPrefPanel pref = new OTRPrefPanel();
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return OTRResources.getString("otr.title");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
return OTRResources.getIcon("otr_pref.png");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTooltip() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getListName() {
|
||||
|
||||
return OTRResources.getString("otr.list.entry");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNamespace() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getGUI() {
|
||||
pref = new OTRPrefPanel();
|
||||
return pref.getGUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commit() {
|
||||
OTRProperties.getInstance().setIsOTREnabled(pref.isOTREnabled());
|
||||
OTRProperties.getInstance().setOTRCloseOnChatClose(pref.isCloseOnChatClose());
|
||||
OTRProperties.getInstance().setOTRCloseOnDisc(pref.isCloseOnDisc());
|
||||
OTRProperties.getInstance().save();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDataValid() {
|
||||
// TODO Auto-generated method stub
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorMessage() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getData() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,141 @@
|
||||
package org.jivesoftware.spark.otrplug.ui;
|
||||
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.text.BadLocationException;
|
||||
import javax.swing.text.Style;
|
||||
import javax.swing.text.StyleConstants;
|
||||
import javax.swing.text.StyledDocument;
|
||||
|
||||
import org.jivesoftware.resource.SparkRes;
|
||||
import org.jivesoftware.spark.otrplug.OTRManager;
|
||||
import org.jivesoftware.spark.otrplug.util.OTRResources;
|
||||
import org.jivesoftware.spark.ui.TranscriptWindow;
|
||||
import org.jivesoftware.spark.ui.rooms.ChatRoomImpl;
|
||||
|
||||
public class OTRConnectionPanel {
|
||||
|
||||
private ChatRoomImpl _chatRoom;
|
||||
private JLabel _label;
|
||||
private ImageIcon _icon;
|
||||
private JPanel _conPanel;
|
||||
private int _i;
|
||||
private StyledDocument _doc;
|
||||
private TranscriptWindow _transcriptWindow;
|
||||
private JButton _retry;
|
||||
private boolean _succesfull = false;
|
||||
private boolean _waiting = false;
|
||||
|
||||
public OTRConnectionPanel(ChatRoomImpl chatroom) {
|
||||
_chatRoom = chatroom;
|
||||
_transcriptWindow = _chatRoom.getTranscriptWindow();
|
||||
_doc = _transcriptWindow.getStyledDocument();
|
||||
_retry = new JButton(OTRResources.getString("otr.retry"));
|
||||
_retry.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
OTRManager.getInstance().startOtrWithUser(_chatRoom.getParticipantJID());
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
_retry.setVisible(false);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void tryToStart() {
|
||||
if (!_succesfull && !_waiting) {
|
||||
renewPanel();
|
||||
_icon.setImage(SparkRes.getImageIcon(SparkRes.BUSY_IMAGE).getImage());
|
||||
|
||||
|
||||
_conPanel.setVisible(true);
|
||||
|
||||
_i = 10;
|
||||
_label.setText(OTRResources.getString("otr.try.to.connect.for.seconds",_i));
|
||||
|
||||
Timer t = new Timer();
|
||||
TimerTask task = new TimerTask() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
if (_i != 0 && !_succesfull) {
|
||||
_waiting = true;
|
||||
_label.setText(OTRResources.getString("otr.try.to.connect.for.seconds",_i));
|
||||
decI();
|
||||
} else if (!_succesfull) {
|
||||
_waiting = true;
|
||||
_icon.setImage(SparkRes.getImageIcon(SparkRes.SMALL_DELETE).getImage());
|
||||
_label.setText(OTRResources.getString("otr.failed.to.establish",_i));
|
||||
_retry.setVisible(true);
|
||||
|
||||
this.cancel();
|
||||
} else {
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
};
|
||||
t.scheduleAtFixedRate(task, 0, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
private void renewPanel() {
|
||||
_conPanel = new JPanel(new GridBagLayout());
|
||||
_label = new JLabel();
|
||||
_icon = new ImageIcon();
|
||||
|
||||
_conPanel.add(new JLabel(_icon), new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 10, 0, 0), 0, 0));
|
||||
_conPanel.add(_label, new GridBagConstraints(1, 0, 1, 1, 0.7, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 15, 0, 0), 0, 0));
|
||||
_conPanel.add(_retry,new GridBagConstraints(2, 0, 1, 1, 2.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 10, 0, 0), 0, 0));
|
||||
|
||||
Style style = _doc.addStyle("OTRStyle", null);
|
||||
StyleConstants.setComponent(style, _conPanel);
|
||||
|
||||
try {
|
||||
_doc.insertString(_doc.getLength(), "ignored text", style);
|
||||
_doc.insertString(_doc.getLength(), "\n", null);
|
||||
} catch (BadLocationException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void connectionClosed() {
|
||||
if (_succesfull) {
|
||||
renewPanel();
|
||||
_succesfull = false;
|
||||
_label.setText(OTRResources.getString("otr.disconnected"));
|
||||
_icon.setImage(SparkRes.getImageIcon(SparkRes.SMALL_STOP).getImage());
|
||||
_conPanel.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void decI() {
|
||||
--_i;
|
||||
}
|
||||
|
||||
public void sucessfullyCon() {
|
||||
if(!_waiting)
|
||||
renewPanel();
|
||||
_retry.setVisible(false);
|
||||
_conPanel.setVisible(true);
|
||||
_succesfull = true;
|
||||
_waiting = false;
|
||||
_icon.setImage(SparkRes.getImageIcon(SparkRes.SMALL_CHECK).getImage());
|
||||
_label.setText(OTRResources.getString("otr.successfull"));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,119 @@
|
||||
|
||||
package org.jivesoftware.spark.otrplug.util;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
import org.jivesoftware.spark.SparkManager;
|
||||
|
||||
/**
|
||||
* RoarProperties file stuff
|
||||
*
|
||||
* @author wolf.posdorfer
|
||||
*
|
||||
*/
|
||||
public class OTRProperties {
|
||||
private Properties props;
|
||||
private File configFile;
|
||||
|
||||
private static final Object LOCK = new Object();
|
||||
private static OTRProperties instance = null;
|
||||
|
||||
/**
|
||||
* returns the Instance of this Properties file
|
||||
* @return
|
||||
*/
|
||||
public static OTRProperties getInstance() {
|
||||
synchronized (LOCK) {
|
||||
if (instance == null) {
|
||||
instance = new OTRProperties();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
private OTRProperties() {
|
||||
this.props = new Properties();
|
||||
|
||||
try {
|
||||
props.load(new FileInputStream(getConfigFile()));
|
||||
} catch (IOException e) {
|
||||
// Can't load ConfigFile
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private File getConfigFile() {
|
||||
if (configFile == null)
|
||||
configFile = new File(SparkManager.getUserDirectory(), "otr.properties");
|
||||
|
||||
return configFile;
|
||||
}
|
||||
|
||||
public void save() {
|
||||
try {
|
||||
props.store(new FileOutputStream(getConfigFile()),
|
||||
"Storing OTRPlugin properties");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getIsOTREnabled()
|
||||
{
|
||||
return getBoolean("isOTREnabeld", true);
|
||||
}
|
||||
|
||||
public void setIsOTREnabled(boolean enabled)
|
||||
{
|
||||
setBoolean("isOTREnabeld", enabled);
|
||||
}
|
||||
|
||||
public boolean getOTRCloseOnDisc()
|
||||
{
|
||||
return getBoolean("OTRCloseOnDisc", true);
|
||||
}
|
||||
|
||||
public void setOTRCloseOnDisc(boolean enabled)
|
||||
{
|
||||
setBoolean("OTRCloseOnDisc", enabled);
|
||||
}
|
||||
|
||||
public boolean getOTRCloseOnChatClose()
|
||||
{
|
||||
return getBoolean("OTRCloseOnChatClose", false);
|
||||
}
|
||||
|
||||
public void setOTRCloseOnChatClose(boolean enabled)
|
||||
{
|
||||
setBoolean("OTRCloseOnChatClose", enabled);
|
||||
}
|
||||
|
||||
// ===============================================================================
|
||||
// ===============================================================================
|
||||
// ===============================================================================
|
||||
private boolean getBoolean(String property, boolean defaultValue) {
|
||||
return Boolean.parseBoolean(props.getProperty(property,
|
||||
Boolean.toString(defaultValue)));
|
||||
}
|
||||
|
||||
private void setBoolean(String property, boolean value) {
|
||||
props.setProperty(property, Boolean.toString(value));
|
||||
}
|
||||
|
||||
private int getInt(String property) {
|
||||
return Integer.parseInt(props.getProperty(property, "0"));
|
||||
}
|
||||
|
||||
private void setInt(String property, int integer) {
|
||||
props.setProperty(property, "" + integer);
|
||||
}
|
||||
|
||||
public String getProperty(String property) {
|
||||
return props.getProperty(property);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
package org.jivesoftware.spark.otrplug.util;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.PropertyResourceBundle;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
|
||||
import org.jivesoftware.spark.util.log.Log;
|
||||
|
||||
public class OTRResources {
|
||||
|
||||
private static PropertyResourceBundle prb;
|
||||
|
||||
static ClassLoader cl = OTRResources.class.getClassLoader();
|
||||
|
||||
static {
|
||||
prb = (PropertyResourceBundle) ResourceBundle.getBundle("i18n/otrplugin_i18n");
|
||||
}
|
||||
|
||||
public static final String getString(String propertyName) {
|
||||
try {
|
||||
return prb.getString(propertyName);
|
||||
} catch (Exception e) {
|
||||
Log.error(e);
|
||||
return propertyName;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static ImageIcon getIcon(String fileName)
|
||||
{
|
||||
final ClassLoader cl = OTRResources.class.getClassLoader();
|
||||
ImageIcon icon = new ImageIcon(cl.getResource(fileName));
|
||||
return icon;
|
||||
}
|
||||
|
||||
|
||||
public static String getString(String propertyName, Object... obj) {
|
||||
String str = prb.getString(propertyName);
|
||||
if (str == null) {
|
||||
return propertyName;
|
||||
}
|
||||
|
||||
|
||||
return MessageFormat.format(str, obj);
|
||||
}
|
||||
|
||||
}
|
||||
30
src/plugins/otr/src/resources/i18n/otrplugin_i18n.properties
Normal file
30
src/plugins/otr/src/resources/i18n/otrplugin_i18n.properties
Normal file
@ -0,0 +1,30 @@
|
||||
|
||||
# OTR language file
|
||||
|
||||
otr.title = Off-the-Record Messaging
|
||||
otr.list.entry = OTR Messaging
|
||||
otr.settings = OTR Settings
|
||||
otr.enable = OTR Enabled
|
||||
current.priv.key = Current private key:
|
||||
renew.current.key = Generate a new key
|
||||
otr.close.session.on.window.close = Close OTR session when chat window is closed
|
||||
otr.close.session.on.contact.off = Close OTR session when contact went offline
|
||||
otr.key.not.verified.title = Key not verified
|
||||
otr.question.verify = Verify?
|
||||
otr.key.not.verified.text = Following key is not verified!
|
||||
otr.start.session.with = OTR encrypted Session with {0}
|
||||
|
||||
otr.not.enabled = You recieved an OTR request. You should enable OTR in preferences.
|
||||
|
||||
#Table Columns
|
||||
otr.table.jid = User's JID
|
||||
otr.table.public.key = Public key
|
||||
otr.key.verified = Verified
|
||||
|
||||
|
||||
#OTR Panel in Chat
|
||||
otr.retry = Retry
|
||||
otr.try.to.connect.for.seconds = Trying to establish an OTR session. {0}s remaining...
|
||||
otr.failed.to.establish = Failed to establish OTR session. Timeout.
|
||||
otr.successfull = OTR successfully establish. Messages will be encrypted.
|
||||
otr.disconnected = OTR session closed. Messages are no longer encrypted.
|
||||
@ -0,0 +1,30 @@
|
||||
|
||||
# OTR language file
|
||||
|
||||
otr.title = Off-the-Record Nachrichten Verschl<68>sselung
|
||||
otr.list.entry = OTR Verschl<68>sselung
|
||||
otr.settings = OTR Einstellungen
|
||||
otr.enable = OTR Aktivieren
|
||||
current.priv.key = Aktueller privater Schl<68>ssel:
|
||||
renew.current.key = Neuen Schl<68>ssel generieren
|
||||
otr.close.session.on.window.close = OTR Sitzung schlie<69>en, wenn Chatfenster geschlossen wird
|
||||
otr.close.session.on.contact.off = OTR Sitzung schlie<69>en, wenn Kontakt sich abmeldet
|
||||
otr.key.not.verified.title = Schl<EFBFBD>ssel nicht beglaubigt
|
||||
otr.question.verify = Beglaubigen?
|
||||
otr.key.not.verified.text = Folgender Schl<68>ssel ist nicht beglaubigt:
|
||||
otr.start.session.with = OTR Sitzung mit {0}
|
||||
|
||||
otr.not.enabled = Sie haben eine OTR Anfrage empfagen. Sie sollten OTR in den Einstellungen aktivieren.
|
||||
|
||||
#Table Columns
|
||||
otr.table.jid = Kontakt
|
||||
otr.table.public.key = <EFBFBD>ffentlicher Schl<68>ssel
|
||||
otr.key.verified = Beglaubigt
|
||||
|
||||
|
||||
#OTR Panel in Chat
|
||||
otr.retry = Wiederholen
|
||||
otr.try.to.connect.for.seconds = Versuche eine OTR Sitzung aufzubauen. {0}s verbleibend...
|
||||
otr.failed.to.establish = Fehler beim erstellen der Sitzung. Zeit abgelaufen.
|
||||
otr.successfull = Sitzung erfolgreich erstellt. Nachrichten werden jetzt verschl<68>sselt.
|
||||
otr.disconnected = Sitzung geschlossen. Nachrichten sind ab jetzt nicht mehr verschl<68>sselt!
|
||||
BIN
src/plugins/otr/src/resources/otr_off.png
Normal file
BIN
src/plugins/otr/src/resources/otr_off.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
BIN
src/plugins/otr/src/resources/otr_on.png
Normal file
BIN
src/plugins/otr/src/resources/otr_on.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
BIN
src/plugins/otr/src/resources/otr_pref.png
Normal file
BIN
src/plugins/otr/src/resources/otr_pref.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
Reference in New Issue
Block a user