diff --git a/src/plugins/otr/plugin.xml b/src/plugins/otr/plugin.xml
index d7182bb3..5d638f28 100644
--- a/src/plugins/otr/plugin.xml
+++ b/src/plugins/otr/plugin.xml
@@ -7,6 +7,7 @@
holger@bergunde.de
Adds OTR support to Spark
2.6.0
+ 1.6.0_1
org.jivesoftware.spark.otrplug.OTRPlugin
Windows,Linux,Mac
diff --git a/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/OTRManager.java b/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/OTRManager.java
index 7384fc6e..4b75f279 100644
--- a/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/OTRManager.java
+++ b/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/OTRManager.java
@@ -33,7 +33,8 @@ public class OTRManager extends ChatRoomListenerAdapter {
private MessageListenerHandler _msgListener;
private Map _activeSessions = new HashMap();
final ChatManager chatManager = SparkManager.getChatManager();
- private static OtrKeyManager _keyManager;
+ private static MyOtrKeyManager _keyManager;
+
private OTRManager()
{
@@ -81,7 +82,7 @@ public class OTRManager extends ChatRoomListenerAdapter {
}
}
- public OtrKeyManager getKeyManager()
+ public MyOtrKeyManager getKeyManager()
{
return _keyManager;
}
diff --git a/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/OTRProperties.java b/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/OTRProperties.java
new file mode 100644
index 00000000..f826a7ff
--- /dev/null
+++ b/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/OTRProperties.java
@@ -0,0 +1,139 @@
+
+package org.jivesoftware.spark.otrplug;
+
+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("isOTREnabled", true);
+ }
+
+ public void setIsOTREnabled(boolean enabled)
+ {
+ setBoolean("isOTREnabeld", 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);
+ }
+
+ private void setColor(String property, Color color) {
+ props.setProperty(property, convertColor(color));
+ }
+
+ private Color getColor(String property, Color defaultcolor) {
+ try {
+ return convertString(props.getProperty(property));
+ } catch (Exception e) {
+ return defaultcolor;
+ }
+
+ }
+
+ public String getProperty(String property) {
+ return props.getProperty(property);
+ }
+
+ /**
+ * Converts a {@link String} matching xxx,xxx,xxx to a {@link Color}
+ * where xxx is a number from 0 to 255
+ *
+ * @param s
+ * @return
+ */
+ public static Color convertString(String s) throws Exception {
+ String[] arr = s.split(",");
+ return new Color(Integer.parseInt(arr[0]), Integer.parseInt(arr[1]),
+ Integer.parseInt(arr[2]));
+
+ }
+
+ /**
+ * Converts a {@link Color} to a {@link String} in this format:
+ * xxx,xxx,xxx
+ * where xxx is a number from 0 to 255
+ *
+ * @param color
+ * @return
+ */
+ public static String convertColor(Color color) {
+ return color.getRed() + "," + color.getGreen() + "," + color.getBlue();
+ }
+
+ }
diff --git a/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/OTRResources.java b/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/OTRResources.java
new file mode 100644
index 00000000..e9ae2d85
--- /dev/null
+++ b/src/plugins/otr/src/java/org/jivesoftware/spark/otrplug/OTRResources.java
@@ -0,0 +1,27 @@
+package org.jivesoftware.spark.otrplug;
+
+import java.util.PropertyResourceBundle;
+import java.util.ResourceBundle;
+
+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;
+ }
+ }
+
+}
diff --git a/src/plugins/otr/src/java/org/jivesoftware/spark/ui/MyOtrKeyManager.java b/src/plugins/otr/src/java/org/jivesoftware/spark/ui/MyOtrKeyManager.java
index bfa8c4cd..6209a6c1 100644
--- a/src/plugins/otr/src/java/org/jivesoftware/spark/ui/MyOtrKeyManager.java
+++ b/src/plugins/otr/src/java/org/jivesoftware/spark/ui/MyOtrKeyManager.java
@@ -32,276 +32,264 @@ import net.java.otr4j.session.SessionID;
public class MyOtrKeyManager implements OtrKeyManager {
- private OtrKeyManagerStore store;
+ private OtrKeyManagerStore store;
- public MyOtrKeyManager(OtrKeyManagerStore store) {
- this.store = 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();
+ }
}
- 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);
-
- }
-
- 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;
- }
- }
+ private File getConfigurationFile() throws IOException {
+ File configFile = new File(filepath);
+ if (!configFile.exists())
+ configFile.createNewFile();
+ return configFile;
}
- public MyOtrKeyManager(String filepath) throws IOException {
- this.store = new DefaultPropertiesStore(filepath);
+ public void setProperty(String id, boolean value) {
+ properties.setProperty(id, "true");
+ try {
+ this.store();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
}
- private List listeners = new Vector();
-
- public void addListener(OtrKeyManagerListener l) {
- synchronized (listeners) {
- if (!listeners.contains(l))
- listeners.add(l);
- }
+ private void store() throws FileNotFoundException, IOException {
+ OutputStream out = new FileOutputStream(getConfigurationFile());
+ properties.store(out, null);
+ out.close();
}
- public void removeListener(OtrKeyManagerListener l) {
- synchronized (listeners) {
- listeners.remove(l);
- }
+ 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 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 removeProperty(String id) {
+ properties.remove(id);
}
- 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);
+ 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 listeners = new Vector();
+
+ 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);
+ }
+
}
diff --git a/src/plugins/otr/src/java/org/jivesoftware/spark/ui/OTRKeyTable.java b/src/plugins/otr/src/java/org/jivesoftware/spark/ui/OTRKeyTable.java
new file mode 100644
index 00000000..2c957fb7
--- /dev/null
+++ b/src/plugins/otr/src/java/org/jivesoftware/spark/ui/OTRKeyTable.java
@@ -0,0 +1,85 @@
+package org.jivesoftware.spark.ui;
+
+import java.awt.BorderLayout;
+
+import java.util.Vector;
+
+import javax.swing.JComponent;
+
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+
+import javax.swing.event.TableModelListener;
+import javax.swing.table.DefaultTableModel;
+
+import org.jivesoftware.spark.otrplug.OTRResources;
+
+public class OTRKeyTable extends JComponent {
+
+ /**
+ *
+ */
+ 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);
+
+ 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