diff --git a/build.xml b/build.xml
index 3eee3f9d3..7436b45ff 100644
--- a/build.xml
+++ b/build.xml
@@ -810,7 +810,8 @@
bundle-plugin-googletalkaccregwizz,bundle-argdelegation-service,
bundle-argdelegation,bundle-zrtp4j,
bundle-filehistory,bundle-metahistory,bundle-metahistory-slick,
- bundle-facebook,bundle-plugin-facebookaccregwizz"/>
+ bundle-facebook,bundle-plugin-facebookaccregwizz,
+ bundle-bouncycastle,bundle-plugin-otr"/>
@@ -2025,11 +2026,17 @@ org.apache.http.util"/>
-
+
+
@@ -2059,6 +2066,37 @@ org.apache.http.util"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -2068,6 +2106,4 @@ org.apache.http.util"/>
prefix="net/java/sip/communicator/slick/metahistory"/>
-
-
diff --git a/lib/felix.client.run.properties b/lib/felix.client.run.properties
index 94ca43481..5aa139e48 100644
--- a/lib/felix.client.run.properties
+++ b/lib/felix.client.run.properties
@@ -50,7 +50,14 @@ org.osgi.framework.system.packages.extra= org.osgi.framework; version=1.3.0, \
javax.crypto; \
javax.crypto.spec; \
javax.crypto.interfaces; \
- sun.awt.shell;
+ sun.awt.shell; \
+ java.io; \
+ java.math; \
+ java.nio; \
+ java.security; \
+ java.security.interfaces; \
+ java.security.spec;
+
felix.auto.start.10= \
reference:file:lib/bundle/org.apache.felix.bundlerepository-1.0.0.jar
@@ -83,6 +90,7 @@ felix.auto.start.45= \
reference:file:sc-bundles/branding.jar
felix.auto.start.49= \
+ reference:file:sc-bundles/bouncycastle.jar \
reference:file:sc-bundles/zrtp4j.jar \
reference:file:sc-bundles/protocol.jar \
reference:file:lib/bundle/httpcore.jar
@@ -157,6 +165,7 @@ felix.auto.start.67= \
reference:file:sc-bundles/keybindingChooser.jar \
reference:file:sc-bundles/generalconfig.jar \
reference:file:sc-bundles/dictaccregwizz.jar \
+ reference:file:sc-bundles/otr.jar \
reference:file:sc-bundles/facebookaccregwizz.jar
#level 68 is for profiler, don't use it or change the build.xml file accordingly
diff --git a/lib/felix.unit.test.properties b/lib/felix.unit.test.properties
index adb589474..75c97d599 100644
--- a/lib/felix.unit.test.properties
+++ b/lib/felix.unit.test.properties
@@ -49,7 +49,13 @@ org.osgi.framework.system.packages.extra= org.osgi.framework; ; version=1.3.0, \
javax.crypto; \
javax.crypto.spec; \
javax.crypto.interfaces; \
- sun.awt.shell;
+ sun.awt.shell; \
+ java.io; \
+ java.math; \
+ java.nio; \
+ java.security; \
+ java.security.interfaces; \
+ java.security.spec;
#
@@ -88,6 +94,7 @@ felix.auto.start.4= \
reference:file:sc-bundles/netaddr.jar
felix.auto.start.5= \
+ reference:file:sc-bundles/bouncycastle.jar \
reference:file:sc-bundles/zrtp4j.jar \
reference:file:sc-bundles/protocol.jar \
reference:file:lib/bundle/httpcore.jar
diff --git a/lib/installer-exclude/lcrypto-jdk16-143.jar b/lib/installer-exclude/lcrypto-jdk16-143.jar
new file mode 100755
index 000000000..1153ea9a8
Binary files /dev/null and b/lib/installer-exclude/lcrypto-jdk16-143.jar differ
diff --git a/lib/installer-exclude/otr4j.jar b/lib/installer-exclude/otr4j.jar
new file mode 100755
index 000000000..52ee97e85
Binary files /dev/null and b/lib/installer-exclude/otr4j.jar differ
diff --git a/lib/installer-exclude/zrtp4j-light.jar b/lib/installer-exclude/zrtp4j-light.jar
index ef162243a..455218709 100755
Binary files a/lib/installer-exclude/zrtp4j-light.jar and b/lib/installer-exclude/zrtp4j-light.jar differ
diff --git a/resources/images/images.properties b/resources/images/images.properties
index 0ec8e45c9..ae1223b4d 100644
--- a/resources/images/images.properties
+++ b/resources/images/images.properties
@@ -407,3 +407,7 @@ plugin.notificationconfig.FOLDER_ICON=resources/images/plugin/notificationconfig
# media configuration form
plugin.mediaconfig.PLUGIN_ICON=resources/images/impl/media/media.png
+
+# otr plugin icons
+plugin.otr.ENCRYPTED_ICON=resources/images/plugin/otr/encrypted.png
+plugin.otr.DECRYPTED_ICON=resources/images/plugin/otr/decrypted.png
\ No newline at end of file
diff --git a/src/net/java/sip/communicator/impl/protocol/icq/OperationSetBasicInstantMessagingIcqImpl.java b/src/net/java/sip/communicator/impl/protocol/icq/OperationSetBasicInstantMessagingIcqImpl.java
index d9dd612a5..b77482e3a 100644
--- a/src/net/java/sip/communicator/impl/protocol/icq/OperationSetBasicInstantMessagingIcqImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/icq/OperationSetBasicInstantMessagingIcqImpl.java
@@ -169,6 +169,27 @@ public void sendInstantMessage(Contact to, Message message)
else
messageContent = message.getContent();
+ MessageDeliveredEvent msgDeliveryPendingEvt = new MessageDeliveredEvent(
+ message, to, System.currentTimeMillis());
+
+ OperationSetInstantMessageTransformIcqImpl messageTransform =
+ (OperationSetInstantMessageTransformIcqImpl)icqProvider.getOperationSet(OperationSetInstantMessageTransform.class);
+
+ for (Map.Entry> entry : messageTransform.transformLayers
+ .entrySet())
+ {
+ for (Iterator iterator = entry.getValue().iterator(); iterator
+ .hasNext();)
+ {
+ TransformLayer transformLayer = (TransformLayer) iterator.next();
+ if (msgDeliveryPendingEvt != null)
+ msgDeliveryPendingEvt = transformLayer.messageDeliveryPending(msgDeliveryPendingEvt);
+ }
+ }
+
+ if (msgDeliveryPendingEvt == null)
+ return;
+
if (to.getPresenceStatus().isOnline())
{
//do not add the conversation listener in here. we'll add it
@@ -178,10 +199,23 @@ public void sendInstantMessage(Contact to, Message message)
else
imConversation.sendMessage(new SimpleMessage(messageContent), true);
- MessageDeliveredEvent msgDeliveredEvt
- = new MessageDeliveredEvent(message, to, System.currentTimeMillis());
+ MessageDeliveredEvent msgDeliveredEvt = new MessageDeliveredEvent(
+ message, to, System.currentTimeMillis());
- fireMessageEvent(msgDeliveredEvt);
+ for (Map.Entry> entry : messageTransform.transformLayers
+ .entrySet())
+ {
+ for (Iterator iterator = entry.getValue().iterator(); iterator
+ .hasNext();)
+ {
+ TransformLayer transformLayer = (TransformLayer) iterator.next();
+ if (msgDeliveredEvt != null)
+ msgDeliveredEvt = transformLayer.messageDelivered(msgDeliveredEvt);
+ }
+ }
+
+ if (msgDeliveredEvt != null)
+ fireMessageEvent(msgDeliveredEvt);
}
@@ -258,9 +292,28 @@ public void handleResponse(SnacResponseEvent evt)
createMessage(offlineMsgCmd.getContents()),
sourceContact,
msgDate);
- logger.debug("fire msg received for : " +
- offlineMsgCmd.getContents());
- fireMessageEvent(msgReceivedEvt);
+
+ OperationSetInstantMessageTransformIcqImpl messageTransform =
+ (OperationSetInstantMessageTransformIcqImpl)icqProvider.getOperationSet(OperationSetInstantMessageTransform.class);
+
+ for (Map.Entry> entry : messageTransform.transformLayers
+ .entrySet())
+ {
+ for (Iterator iterator = entry.getValue().iterator(); iterator
+ .hasNext();)
+ {
+ TransformLayer transformLayer = (TransformLayer) iterator.next();
+ if (msgReceivedEvt != null)
+ msgReceivedEvt = transformLayer.messageReceived(msgReceivedEvt);
+ }
+ }
+
+ if (msgReceivedEvt != null)
+ {
+ logger.debug("fire msg received for : " +
+ offlineMsgCmd.getContents());
+ fireMessageEvent(msgReceivedEvt);
+ }
}
else if (snac instanceof OfflineMsgDoneCmd)
{
@@ -527,11 +580,30 @@ public void gotMessage(Conversation conversation, MessageInfo minfo)
msgDate = current;
- MessageReceivedEvent msgReceivedEvt
- = new MessageReceivedEvent(
- newMessage, sourceContact , msgDate );
+ MessageReceivedEvent msgReceivedEvt =
+ new MessageReceivedEvent(newMessage, sourceContact, msgDate);
- fireMessageEvent(msgReceivedEvt);
+ OperationSetInstantMessageTransformIcqImpl messageTransform =
+ (OperationSetInstantMessageTransformIcqImpl)icqProvider.getOperationSet(OperationSetInstantMessageTransform.class);
+
+ for (Map.Entry> entry : messageTransform.transformLayers
+ .entrySet())
+ {
+ for (Iterator iterator = entry.getValue().iterator(); iterator
+ .hasNext();)
+ {
+ TransformLayer transformLayer = (TransformLayer) iterator.next();
+ if (msgReceivedEvt != null)
+ msgReceivedEvt = transformLayer.messageReceived(msgReceivedEvt);
+ }
+ }
+
+ if (msgReceivedEvt != null)
+ {
+ logger.debug("fire msg received for : " +
+ newMessage);
+ fireMessageEvent(msgReceivedEvt);
+ }
}
public void sentOtherEvent(Conversation conversation,
diff --git a/src/net/java/sip/communicator/impl/protocol/icq/OperationSetInstantMessageTransformIcqImpl.java b/src/net/java/sip/communicator/impl/protocol/icq/OperationSetInstantMessageTransformIcqImpl.java
new file mode 100644
index 000000000..43e2821e6
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/protocol/icq/OperationSetInstantMessageTransformIcqImpl.java
@@ -0,0 +1,62 @@
+package net.java.sip.communicator.impl.protocol.icq;
+
+import java.util.*;
+import net.java.sip.communicator.service.protocol.*;
+
+public class OperationSetInstantMessageTransformIcqImpl
+ implements OperationSetInstantMessageTransform
+{
+ public final Map> transformLayers =
+ new Hashtable>();
+
+ private final int defaultPriority = 1;
+
+ @Override
+ public void addTransformLayer(TransformLayer transformLayer)
+ {
+ this.addTransformLayer(defaultPriority, transformLayer);
+ }
+
+ @Override
+ public void addTransformLayer(int priority, TransformLayer transformLayer)
+ {
+ synchronized (transformLayers)
+ {
+ if (!transformLayers.containsKey(defaultPriority))
+ transformLayers.put(defaultPriority,
+ new Vector());
+
+ transformLayers.get(defaultPriority).add(transformLayer);
+ }
+ }
+
+ @Override
+ public boolean containsLayer(TransformLayer layer)
+ {
+ synchronized (transformLayers)
+ {
+ for (Map.Entry> entry : transformLayers
+ .entrySet())
+ {
+ if (entry.getValue().contains(layer))
+ return true;
+ }
+
+ }
+ return false;
+ }
+
+ @Override
+ public void removeTransformLayer(TransformLayer transformLayer)
+ {
+ synchronized (transformLayers)
+ {
+ for (Map.Entry> entry : transformLayers
+ .entrySet())
+ {
+ entry.getValue().remove(transformLayer);
+ }
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/net/java/sip/communicator/impl/protocol/icq/ProtocolProviderServiceIcqImpl.java b/src/net/java/sip/communicator/impl/protocol/icq/ProtocolProviderServiceIcqImpl.java
index 0a35392a0..a172eff75 100644
--- a/src/net/java/sip/communicator/impl/protocol/icq/ProtocolProviderServiceIcqImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/icq/ProtocolProviderServiceIcqImpl.java
@@ -455,6 +455,9 @@ protected void initialize(String screenname,
if(IcqAccountID.isAIM(accountID.getAccountProperties()))
USING_ICQ = false;
+ supportedOperationSets.put(OperationSetInstantMessageTransform.class.getName(),
+ new OperationSetInstantMessageTransformIcqImpl());
+
//initialize the presence operationset
OperationSetPersistentPresence persistentPresence =
new OperationSetPersistentPresenceIcqImpl(this, screenname);
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicInstantMessagingJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicInstantMessagingJabberImpl.java
index 2d401f88c..259f829b4 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicInstantMessagingJabberImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicInstantMessagingJabberImpl.java
@@ -195,7 +195,29 @@ public void processMessage(
org.jivesoftware.smack.packet.Message msg =
new org.jivesoftware.smack.packet.Message();
- String content = message.getContent();
+ MessageDeliveredEvent msgDeliveryPendingEvt
+ = new MessageDeliveredEvent(
+ message, to, System.currentTimeMillis());
+
+ OperationSetInstantMessageTransformJabberImpl messageTransform =
+ (OperationSetInstantMessageTransformJabberImpl)jabberProvider.getOperationSet(OperationSetInstantMessageTransform.class);
+
+ for (Map.Entry> entry : messageTransform.transformLayers
+ .entrySet())
+ {
+ for (Iterator iterator = entry.getValue().iterator(); iterator
+ .hasNext();)
+ {
+ TransformLayer transformLayer = (TransformLayer) iterator.next();
+ if (msgDeliveryPendingEvt != null)
+ msgDeliveryPendingEvt = transformLayer.messageDeliveryPending(msgDeliveryPendingEvt);
+ }
+ }
+
+ if (msgDeliveryPendingEvt == null)
+ return;
+
+ String content = msgDeliveryPendingEvt.getSourceMessage().getContent();
if(message.getContentType().equals(HTML_MIME_TYPE))
{
@@ -220,14 +242,27 @@ public void processMessage(
MessageEventManager.
addNotificationsRequests(msg, true, false, false, true);
-
+
chat.sendMessage(msg);
-
+
MessageDeliveredEvent msgDeliveredEvt
= new MessageDeliveredEvent(
message, to, System.currentTimeMillis());
- fireMessageEvent(msgDeliveredEvt);
+ for (Map.Entry> entry : messageTransform.transformLayers
+ .entrySet())
+ {
+ for (Iterator iterator = entry.getValue().iterator(); iterator
+ .hasNext();)
+ {
+ TransformLayer transformLayer = (TransformLayer) iterator.next();
+ if (msgDeliveredEvt != null)
+ msgDeliveredEvt = transformLayer.messageDelivered(msgDeliveredEvt);
+ }
+ }
+
+ if (msgDeliveredEvt != null)
+ fireMessageEvent(msgDeliveredEvt);
}
catch (XMPPException ex)
{
@@ -392,7 +427,24 @@ public void processPacket(Packet packet)
new MessageDeliveryFailedEvent(newMessage,
sourceContact,
errorResultCode);
- fireMessageEvent(ev);
+
+ OperationSetInstantMessageTransformJabberImpl messageTransform =
+ (OperationSetInstantMessageTransformJabberImpl)jabberProvider.getOperationSet(OperationSetInstantMessageTransform.class);
+
+ for (Map.Entry> entry : messageTransform.transformLayers
+ .entrySet())
+ {
+ for (Iterator iterator = entry.getValue().iterator(); iterator
+ .hasNext();)
+ {
+ TransformLayer transformLayer = (TransformLayer) iterator.next();
+ if (ev != null)
+ ev = transformLayer.messageDeliveryFailed(ev);
+ }
+ }
+
+ if (ev != null)
+ fireMessageEvent(ev);
return;
}
@@ -411,7 +463,23 @@ public void processPacket(Packet packet)
= new MessageReceivedEvent(
newMessage, sourceContact , System.currentTimeMillis() );
- fireMessageEvent(msgReceivedEvt);
+ OperationSetInstantMessageTransformJabberImpl messageTransform =
+ (OperationSetInstantMessageTransformJabberImpl)jabberProvider.getOperationSet(OperationSetInstantMessageTransform.class);
+
+ for (Map.Entry> entry : messageTransform.transformLayers
+ .entrySet())
+ {
+ for (Iterator iterator = entry.getValue().iterator(); iterator
+ .hasNext();)
+ {
+ TransformLayer transformLayer = (TransformLayer) iterator.next();
+ if (msgReceivedEvt != null)
+ msgReceivedEvt = transformLayer.messageReceived(msgReceivedEvt);
+ }
+ }
+
+ if (msgReceivedEvt != null)
+ fireMessageEvent(msgReceivedEvt);
}
}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetInstantMessageTransformJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetInstantMessageTransformJabberImpl.java
new file mode 100644
index 000000000..02f60e02e
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetInstantMessageTransformJabberImpl.java
@@ -0,0 +1,62 @@
+package net.java.sip.communicator.impl.protocol.jabber;
+
+import java.util.*;
+import net.java.sip.communicator.service.protocol.*;
+
+public class OperationSetInstantMessageTransformJabberImpl
+ implements OperationSetInstantMessageTransform
+{
+ public final Map> transformLayers =
+ new Hashtable>();
+
+ private final int defaultPriority = 1;
+
+ @Override
+ public void addTransformLayer(TransformLayer transformLayer)
+ {
+ this.addTransformLayer(defaultPriority, transformLayer);
+ }
+
+ @Override
+ public void addTransformLayer(int priority, TransformLayer transformLayer)
+ {
+ synchronized (transformLayers)
+ {
+ if (!transformLayers.containsKey(defaultPriority))
+ transformLayers.put(defaultPriority,
+ new Vector());
+
+ transformLayers.get(defaultPriority).add(transformLayer);
+ }
+ }
+
+ @Override
+ public boolean containsLayer(TransformLayer layer)
+ {
+ synchronized (transformLayers)
+ {
+ for (Map.Entry> entry : transformLayers
+ .entrySet())
+ {
+ if (entry.getValue().contains(layer))
+ return true;
+ }
+
+ }
+ return false;
+ }
+
+ @Override
+ public void removeTransformLayer(TransformLayer transformLayer)
+ {
+ synchronized (transformLayers)
+ {
+ for (Map.Entry> entry : transformLayers
+ .entrySet())
+ {
+ entry.getValue().remove(transformLayer);
+ }
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java
index 13df3e73a..6cdb119c8 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java
@@ -642,6 +642,13 @@ protected void initialize(String screenname,
OperationSetFileTransfer.class.getName(),
fileTransfer);
+ OperationSetInstantMessageTransform messageTransform
+ = new OperationSetInstantMessageTransformJabberImpl();
+
+ supportedOperationSets.put(
+ OperationSetInstantMessageTransform.class.getName(),
+ messageTransform);
+
// Include features we're supporting in plus of the four that
// included by smack itself:
// http://jabber.org/protocol/si/profile/file-transfer
diff --git a/src/net/java/sip/communicator/impl/protocol/msn/OperationSetBasicInstantMessagingMsnImpl.java b/src/net/java/sip/communicator/impl/protocol/msn/OperationSetBasicInstantMessagingMsnImpl.java
index 08b929cc0..9698bdfd0 100644
--- a/src/net/java/sip/communicator/impl/protocol/msn/OperationSetBasicInstantMessagingMsnImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/msn/OperationSetBasicInstantMessagingMsnImpl.java
@@ -7,6 +7,7 @@
package net.java.sip.communicator.impl.protocol.msn;
import java.text.*;
+import java.util.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
@@ -116,15 +117,51 @@ public void sendInstantMessage(Contact to, Message message)
"The specified contact is not an MSN contact."
+ to);
+ MessageDeliveredEvent msgDeliveryPendingEvt
+ = new MessageDeliveredEvent(
+ message, to, System.currentTimeMillis());
+
+ OperationSetInstantMessageTransformMsnImpl messageTransform =
+ (OperationSetInstantMessageTransformMsnImpl)msnProvider.getOperationSet(OperationSetInstantMessageTransform.class);
+
+ for (Map.Entry> entry : messageTransform.transformLayers
+ .entrySet())
+ {
+ for (Iterator iterator = entry.getValue().iterator(); iterator
+ .hasNext();)
+ {
+ TransformLayer transformLayer = (TransformLayer) iterator.next();
+ if (msgDeliveryPendingEvt != null)
+ msgDeliveryPendingEvt = transformLayer.messageDeliveryPending(msgDeliveryPendingEvt);
+ }
+ }
+
+ if (msgDeliveryPendingEvt == null)
+ return;
+
msnProvider.getMessenger().
sendText(
((ContactMsnImpl)to).getSourceContact().getEmail(),
- message.getContent()
+ msgDeliveryPendingEvt.getSourceMessage().getContent()
);
MessageDeliveredEvent msgDeliveredEvt
= new MessageDeliveredEvent(message, to, System.currentTimeMillis());
- fireMessageEvent(msgDeliveredEvt);
+
+ for (Map.Entry> entry : messageTransform.transformLayers
+ .entrySet())
+ {
+ for (Iterator iterator = entry.getValue().iterator(); iterator
+ .hasNext();)
+ {
+ TransformLayer transformLayer = (TransformLayer) iterator.next();
+ if (msgDeliveredEvt != null)
+ msgDeliveredEvt = transformLayer.messageDelivered(msgDeliveredEvt);
+ }
+ }
+
+ if (msgDeliveredEvt != null)
+ fireMessageEvent(msgDeliveredEvt);
}
/**
@@ -206,8 +243,24 @@ public void instantMessageReceived(MsnSwitchboard switchboard,
MessageReceivedEvent msgReceivedEvt
= new MessageReceivedEvent(
newMessage, sourceContact , System.currentTimeMillis() );
-
- fireMessageEvent(msgReceivedEvt);
+
+ OperationSetInstantMessageTransformMsnImpl messageTransform =
+ (OperationSetInstantMessageTransformMsnImpl)msnProvider.getOperationSet(OperationSetInstantMessageTransform.class);
+
+ for (Map.Entry> entry : messageTransform.transformLayers
+ .entrySet())
+ {
+ for (Iterator iterator = entry.getValue().iterator(); iterator
+ .hasNext();)
+ {
+ TransformLayer transformLayer = (TransformLayer) iterator.next();
+ if (msgReceivedEvt != null)
+ msgReceivedEvt = transformLayer.messageReceived(msgReceivedEvt);
+ }
+ }
+
+ if (msgReceivedEvt != null)
+ fireMessageEvent(msgReceivedEvt);
}
/**
diff --git a/src/net/java/sip/communicator/impl/protocol/msn/OperationSetInstantMessageTransformMsnImpl.java b/src/net/java/sip/communicator/impl/protocol/msn/OperationSetInstantMessageTransformMsnImpl.java
new file mode 100644
index 000000000..b66797173
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/protocol/msn/OperationSetInstantMessageTransformMsnImpl.java
@@ -0,0 +1,62 @@
+package net.java.sip.communicator.impl.protocol.msn;
+
+import java.util.*;
+import net.java.sip.communicator.service.protocol.*;
+
+public class OperationSetInstantMessageTransformMsnImpl
+ implements OperationSetInstantMessageTransform
+{
+ public final Map> transformLayers =
+ new Hashtable>();
+
+ private final int defaultPriority = 1;
+
+ @Override
+ public void addTransformLayer(TransformLayer transformLayer)
+ {
+ this.addTransformLayer(defaultPriority, transformLayer);
+ }
+
+ @Override
+ public void addTransformLayer(int priority, TransformLayer transformLayer)
+ {
+ synchronized (transformLayers)
+ {
+ if (!transformLayers.containsKey(defaultPriority))
+ transformLayers.put(defaultPriority,
+ new Vector());
+
+ transformLayers.get(defaultPriority).add(transformLayer);
+ }
+ }
+
+ @Override
+ public boolean containsLayer(TransformLayer layer)
+ {
+ synchronized (transformLayers)
+ {
+ for (Map.Entry> entry : transformLayers
+ .entrySet())
+ {
+ if (entry.getValue().contains(layer))
+ return true;
+ }
+
+ }
+ return false;
+ }
+
+ @Override
+ public void removeTransformLayer(TransformLayer transformLayer)
+ {
+ synchronized (transformLayers)
+ {
+ for (Map.Entry> entry : transformLayers
+ .entrySet())
+ {
+ entry.getValue().remove(transformLayer);
+ }
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/net/java/sip/communicator/impl/protocol/msn/ProtocolProviderServiceMsnImpl.java b/src/net/java/sip/communicator/impl/protocol/msn/ProtocolProviderServiceMsnImpl.java
index 984d37398..f98ea8d66 100644
--- a/src/net/java/sip/communicator/impl/protocol/msn/ProtocolProviderServiceMsnImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/msn/ProtocolProviderServiceMsnImpl.java
@@ -261,9 +261,12 @@ protected void initialize(String screenname,
{
this.accountID = accountID;
+ supportedOperationSets.put(OperationSetInstantMessageTransform.class.getName(),
+ new OperationSetInstantMessageTransformMsnImpl());
+
//initialize the presence operationset
persistentPresence = new OperationSetPersistentPresenceMsnImpl(this);
-
+
supportedOperationSets.put(
OperationSetPersistentPresence.class.getName(),
persistentPresence);
diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetBasicInstantMessagingYahooImpl.java b/src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetBasicInstantMessagingYahooImpl.java
index b92a8abd1..f21567525 100644
--- a/src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetBasicInstantMessagingYahooImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetBasicInstantMessagingYahooImpl.java
@@ -142,7 +142,30 @@ public void sendInstantMessage(Contact to, Message message)
{
String toUserID = ((ContactYahooImpl) to).getID();
- byte[] msgBytesToBeSent = message.getContent().trim().getBytes();
+ MessageDeliveredEvent msgDeliveryPendingEvt
+ = new MessageDeliveredEvent(
+ message, to, System.currentTimeMillis());
+
+ OperationSetInstantMessageTransformYahooImpl messageTransform =
+ (OperationSetInstantMessageTransformYahooImpl)yahooProvider.getOperationSet(OperationSetInstantMessageTransform.class);
+
+ for (Map.Entry> entry : messageTransform.transformLayers
+ .entrySet())
+ {
+ for (Iterator iterator = entry.getValue().iterator(); iterator
+ .hasNext();)
+ {
+ TransformLayer transformLayer = (TransformLayer) iterator.next();
+ if (msgDeliveryPendingEvt != null)
+ msgDeliveryPendingEvt = transformLayer.messageDeliveryPending(msgDeliveryPendingEvt);
+ }
+ }
+
+ if (msgDeliveryPendingEvt == null)
+ return;
+
+ byte[] msgBytesToBeSent = msgDeliveryPendingEvt.getSourceMessage().
+ getContent().trim().getBytes();
// split the message in parts with max allowed length
// and send them all
@@ -173,10 +196,23 @@ public void sendInstantMessage(Contact to, Message message)
}
MessageDeliveredEvent msgDeliveredEvt
- = new MessageDeliveredEvent(
- message, to, System.currentTimeMillis());
-
- fireMessageEvent(msgDeliveredEvt);
+ = new MessageDeliveredEvent(
+ message, to, System.currentTimeMillis());
+
+ for (Map.Entry> entry : messageTransform.transformLayers
+ .entrySet())
+ {
+ for (Iterator iterator = entry.getValue().iterator(); iterator
+ .hasNext();)
+ {
+ TransformLayer transformLayer = (TransformLayer) iterator.next();
+ if (msgDeliveredEvt != null)
+ msgDeliveredEvt = transformLayer.messageDelivered(msgDeliveredEvt);
+ }
+ }
+
+ if (msgDeliveredEvt != null)
+ fireMessageEvent(msgDeliveredEvt);
}
while(msgBytesToBeSent.length > MAX_MESSAGE_LENGTH);
}
@@ -188,7 +224,24 @@ public void sendInstantMessage(Contact to, Message message)
message,
to,
MessageDeliveryFailedEvent.NETWORK_FAILURE);
- fireMessageEvent(evt);
+
+ OperationSetInstantMessageTransformYahooImpl messageTransform =
+ (OperationSetInstantMessageTransformYahooImpl)yahooProvider.getOperationSet(OperationSetInstantMessageTransform.class);
+
+ for (Map.Entry> entry : messageTransform.transformLayers
+ .entrySet())
+ {
+ for (Iterator iterator = entry.getValue().iterator(); iterator
+ .hasNext();)
+ {
+ TransformLayer transformLayer = (TransformLayer) iterator.next();
+ if (evt != null)
+ evt = transformLayer.messageDeliveryFailed(evt);
+ }
+ }
+
+ if (evt != null)
+ fireMessageEvent(evt);
return;
}
}
@@ -430,11 +483,27 @@ private void handleNewMessage(SessionEvent ev)
.createVolatileContact(ev.getFrom());
}
- MessageReceivedEvent msgReceivedEvt
- = new MessageReceivedEvent(
- newMessage, sourceContact , System.currentTimeMillis() );
-
- fireMessageEvent(msgReceivedEvt);
+ MessageReceivedEvent msgReceivedEvt
+ = new MessageReceivedEvent(
+ newMessage, sourceContact , System.currentTimeMillis() );
+
+ OperationSetInstantMessageTransformYahooImpl messageTransform =
+ (OperationSetInstantMessageTransformYahooImpl)yahooProvider.getOperationSet(OperationSetInstantMessageTransform.class);
+
+ for (Map.Entry> entry : messageTransform.transformLayers
+ .entrySet())
+ {
+ for (Iterator iterator = entry.getValue().iterator(); iterator
+ .hasNext();)
+ {
+ TransformLayer transformLayer = (TransformLayer) iterator.next();
+ if (msgReceivedEvt != null)
+ msgReceivedEvt = transformLayer.messageReceived(msgReceivedEvt);
+ }
+ }
+
+ if (msgReceivedEvt != null)
+ fireMessageEvent(msgReceivedEvt);
}
}
diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetInstantMessageTransformYahooImpl.java b/src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetInstantMessageTransformYahooImpl.java
new file mode 100644
index 000000000..7117c8239
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetInstantMessageTransformYahooImpl.java
@@ -0,0 +1,62 @@
+package net.java.sip.communicator.impl.protocol.yahoo;
+
+import java.util.*;
+import net.java.sip.communicator.service.protocol.*;
+
+public class OperationSetInstantMessageTransformYahooImpl
+ implements OperationSetInstantMessageTransform
+{
+ public final Map> transformLayers =
+ new Hashtable>();
+
+ private final int defaultPriority = 1;
+
+ @Override
+ public void addTransformLayer(TransformLayer transformLayer)
+ {
+ this.addTransformLayer(defaultPriority, transformLayer);
+ }
+
+ @Override
+ public void addTransformLayer(int priority, TransformLayer transformLayer)
+ {
+ synchronized (transformLayers)
+ {
+ if (!transformLayers.containsKey(defaultPriority))
+ transformLayers.put(defaultPriority,
+ new Vector());
+
+ transformLayers.get(defaultPriority).add(transformLayer);
+ }
+ }
+
+ @Override
+ public boolean containsLayer(TransformLayer layer)
+ {
+ synchronized (transformLayers)
+ {
+ for (Map.Entry> entry : transformLayers
+ .entrySet())
+ {
+ if (entry.getValue().contains(layer))
+ return true;
+ }
+
+ }
+ return false;
+ }
+
+ @Override
+ public void removeTransformLayer(TransformLayer transformLayer)
+ {
+ synchronized (transformLayers)
+ {
+ for (Map.Entry> entry : transformLayers
+ .entrySet())
+ {
+ entry.getValue().remove(transformLayer);
+ }
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/ProtocolProviderServiceYahooImpl.java b/src/net/java/sip/communicator/impl/protocol/yahoo/ProtocolProviderServiceYahooImpl.java
index 45baf65dc..a2e9a3a4b 100644
--- a/src/net/java/sip/communicator/impl/protocol/yahoo/ProtocolProviderServiceYahooImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/yahoo/ProtocolProviderServiceYahooImpl.java
@@ -318,6 +318,10 @@ protected void initialize(String screenname,
{
this.accountID = accountID;
+ supportedOperationSets.put(
+ OperationSetInstantMessageTransform.class.getName(),
+ new OperationSetInstantMessageTransformYahooImpl());
+
//initialize the presence operationset
persistentPresence = new OperationSetPersistentPresenceYahooImpl(this);
diff --git a/src/net/java/sip/communicator/plugin/otr/OtrActivator.java b/src/net/java/sip/communicator/plugin/otr/OtrActivator.java
new file mode 100644
index 000000000..a60612c2c
--- /dev/null
+++ b/src/net/java/sip/communicator/plugin/otr/OtrActivator.java
@@ -0,0 +1,159 @@
+package net.java.sip.communicator.plugin.otr;
+
+import java.util.*;
+
+import net.java.sip.communicator.service.gui.*;
+import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.service.resources.*;
+import net.java.sip.communicator.util.*;
+
+import org.osgi.framework.*;
+
+public class OtrActivator
+ implements BundleActivator, ServiceListener
+{
+
+ private BundleContext bundleContext = null;
+
+ private OtrTransformLayer transformLayer = new OtrTransformLayer();
+
+ private static Logger logger = Logger.getLogger(OtrActivator.class);
+
+ @Override
+ public void start(BundleContext bc) throws Exception
+ {
+ this.bundleContext = bc;
+ bc.addServiceListener(this);
+
+ ServiceReference[] protocolProviderRefs = null;
+ try
+ {
+ protocolProviderRefs =
+ bc.getServiceReferences(
+ ProtocolProviderService.class.getName(), null);
+ }
+ catch (InvalidSyntaxException ex)
+ {
+ logger.error("Error while retrieving service refs", ex);
+ return;
+ }
+
+ if (protocolProviderRefs != null)
+ {
+ logger.debug("Found " + protocolProviderRefs.length
+ + " already installed providers.");
+ for (int i = 0; i < protocolProviderRefs.length; i++)
+ {
+ ProtocolProviderService provider =
+ (ProtocolProviderService) bc
+ .getService(protocolProviderRefs[i]);
+
+ this.handleProviderAdded(provider);
+ }
+ }
+
+ Hashtable containerFilter =
+ new Hashtable();
+ containerFilter.put(Container.CONTAINER_ID,
+ Container.CONTAINER_CONTACT_RIGHT_BUTTON_MENU.getID());
+
+ bundleContext.registerService(PluginComponent.class.getName(),
+ new OtrMenu(ResourceManagementServiceUtils
+ .getService(bc)), containerFilter);
+ }
+
+ private void handleProviderAdded(ProtocolProviderService provider)
+ {
+ OperationSetInstantMessageTransform opSetMessageTransform =
+ (OperationSetInstantMessageTransform) provider
+ .getOperationSet(OperationSetInstantMessageTransform.class);
+
+ if (opSetMessageTransform != null)
+ {
+ opSetMessageTransform.addTransformLayer(transformLayer);
+ }
+ else
+ {
+ logger.trace("Service did not have a transform op. set.");
+ }
+
+ }
+
+ @Override
+ public void stop(BundleContext bc) throws Exception
+ {
+ // start listening for newly register or removed protocol providers
+ bc.removeServiceListener(this);
+
+ ServiceReference[] protocolProviderRefs = null;
+ try
+ {
+ protocolProviderRefs =
+ bc.getServiceReferences(
+ ProtocolProviderService.class.getName(), null);
+ }
+ catch (InvalidSyntaxException ex)
+ {
+ // this shouldn't happen since we're providing no parameter string
+ // but let's log just in case.
+ logger.error("Error while retrieving service refs", ex);
+ return;
+ }
+
+ // in case we found any
+ if (protocolProviderRefs != null)
+ {
+ for (int i = 0; i < protocolProviderRefs.length; i++)
+ {
+ ProtocolProviderService provider =
+ (ProtocolProviderService) bc
+ .getService(protocolProviderRefs[i]);
+
+ this.handleProviderRemoved(provider);
+ }
+ }
+ }
+
+ private void handleProviderRemoved(ProtocolProviderService provider)
+ {
+ // check whether the provider has a basic im operation set
+ OperationSetInstantMessageTransform opSetMessageTransform =
+ (OperationSetInstantMessageTransform) provider
+ .getOperationSet(OperationSetInstantMessageTransform.class);
+
+ if (opSetMessageTransform != null)
+ {
+ opSetMessageTransform.removeTransformLayer(transformLayer);
+ }
+ }
+
+ @Override
+ public void serviceChanged(ServiceEvent serviceEvent)
+ {
+ Object sService =
+ bundleContext.getService(serviceEvent.getServiceReference());
+
+ logger.trace("Received a service event for: "
+ + sService.getClass().getName());
+
+ // we don't care if the source service is not a protocol provider
+ if (!(sService instanceof ProtocolProviderService))
+ {
+ return;
+ }
+
+ logger.debug("Service is a protocol provider.");
+ if (serviceEvent.getType() == ServiceEvent.REGISTERED)
+ {
+ logger.debug("Handling registration of a new Protocol Provider.");
+
+ this.handleProviderAdded((ProtocolProviderService) sService);
+ }
+ else if (serviceEvent.getType() == ServiceEvent.UNREGISTERING)
+ {
+ this.handleProviderRemoved((ProtocolProviderService) sService);
+ }
+
+ }
+
+}
diff --git a/src/net/java/sip/communicator/plugin/otr/OtrMenu.java b/src/net/java/sip/communicator/plugin/otr/OtrMenu.java
new file mode 100644
index 000000000..0ddaa79a1
--- /dev/null
+++ b/src/net/java/sip/communicator/plugin/otr/OtrMenu.java
@@ -0,0 +1,93 @@
+package net.java.sip.communicator.plugin.otr;
+
+import java.awt.Component;
+import java.awt.event.*;
+
+import javax.swing.*;
+
+import net.java.sip.communicator.service.contactlist.*;
+import net.java.sip.communicator.service.gui.*;
+import net.java.sip.communicator.service.resources.*;
+
+@SuppressWarnings("serial")
+public class OtrMenu
+ extends JMenu
+ implements PluginComponent, ActionListener
+{
+ private static final String imageID = "plugin.otr.DECRYPTED_ICON";
+
+ private ResourceManagementService resourceService;
+
+ public OtrMenu(ResourceManagementService resourceService)
+ {
+ super("Encryption");
+ this.setToolTipText("Options for OTR Encryption");
+
+ if (resourceService != null)
+ this.setIcon(resourceService.getImage(imageID));
+
+ // TODO Internationalize Strings...
+ JMenuItem mitmStartOtr = new JMenuItem("Start Private Conversation");
+ JMenuItem mitmEndOtr = new JMenuItem("End Private Conversation");
+ JMenuItem mitmRefreshOtr =
+ new JMenuItem("Refresh Private Conversation");
+ JMenuItem mitmAuthenticateBuddy = new JMenuItem("Authenticate Buddy");
+ JMenuItem mitmWhatsThis = new JMenuItem("What's this?");
+
+ // Shown if we don't have an OTR session.
+ this.add(mitmStartOtr);
+ // Shown if we have an OTR session.
+ this.add(mitmEndOtr);
+ this.add(mitmRefreshOtr);
+ this.add(mitmAuthenticateBuddy);
+ this.add(mitmWhatsThis);
+ }
+
+ @Override
+ public String getConstraints()
+ {
+ return null;
+ }
+
+ public Component getComponent()
+ {
+ return this;
+ }
+
+ @Override
+ public Container getContainer()
+ {
+ return Container.CONTAINER_CONTACT_RIGHT_BUTTON_MENU;
+ }
+
+ @Override
+ public int getPositionIndex()
+ {
+ return -1;
+ }
+
+ @Override
+ public boolean isNativeComponent()
+ {
+ return false;
+ }
+
+ private MetaContact metaContact;
+
+ @Override
+ public void setCurrentContact(MetaContact metaContact)
+ {
+ this.metaContact = metaContact;
+ }
+
+ @Override
+ public void setCurrentContactGroup(MetaContactGroup metaGroup)
+ {
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ }
+
+}
\ No newline at end of file
diff --git a/src/net/java/sip/communicator/plugin/otr/OtrTransformLayer.java b/src/net/java/sip/communicator/plugin/otr/OtrTransformLayer.java
new file mode 100644
index 000000000..3cd39bb3f
--- /dev/null
+++ b/src/net/java/sip/communicator/plugin/otr/OtrTransformLayer.java
@@ -0,0 +1,201 @@
+package net.java.sip.communicator.plugin.otr;
+
+import java.security.*;
+import java.util.*;
+
+import net.java.otr4j.*;
+import net.java.otr4j.message.MessageConstants;
+import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.service.protocol.event.*;
+import net.java.sip.communicator.util.*;
+
+public class OtrTransformLayer
+ implements TransformLayer
+{
+ private static Logger logger = Logger.getLogger(TransformLayer.class);
+
+ private UserState us = new UserState(new OTR4jListener()
+ {
+ @Override
+ public void showWarning(String warn)
+ {
+ logger.warn(warn);
+ }
+
+ @Override
+ public void showError(String err)
+ {
+ logger.error(err);
+ }
+
+ @Override
+ public void injectMessage(String messageText, String account,
+ String user, String protocol)
+ {
+ Contact contact = getContact(account, user, protocol);
+ OperationSetBasicInstantMessaging imOpSet =
+ (OperationSetBasicInstantMessaging) contact
+ .getProtocolProvider().getOperationSet(
+ OperationSetBasicInstantMessaging.class);
+
+ Message message = imOpSet.createMessage(messageText);
+ imOpSet.sendInstantMessage(contact, message);
+ }
+
+ @Override
+ public int getPolicy(ConnContext arg0)
+ {
+ return PolicyConstants.ALLOW_V2;
+ }
+
+ @Override
+ public KeyPair getKeyPair(String arg0, String arg1)
+ throws NoSuchAlgorithmException
+ {
+ try
+ {
+ return CryptoUtils.generateDsaKeyPair();
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+ });
+
+ private List contacts = new Vector();
+
+ private Contact getContact(String account, String user, String protocol)
+ {
+ for (Contact c : contacts)
+ {
+ String cuser = c.getAddress();
+ ProtocolProviderService cprotoProvider = c.getProtocolProvider();
+ String caccount = cprotoProvider.getAccountID().toString();
+ String cprotocol = cprotoProvider.getProtocolName();
+
+ if (user.equals(cuser) && account.equals(caccount)
+ && protocol.equals(cprotocol))
+ return c;
+ }
+ return null;
+ }
+
+ private void addContact(Contact contact)
+ {
+ if (contact == null)
+ return;
+
+ String user = contact.getAddress();
+ ProtocolProviderService protoProvider = contact.getProtocolProvider();
+ String account = protoProvider.getAccountID().toString();
+ String protocol = protoProvider.getProtocolName();
+
+ for (Contact c : contacts)
+ {
+ String cuser = c.getAddress();
+ ProtocolProviderService cprotoProvider = c.getProtocolProvider();
+ String caccount = cprotoProvider.getAccountID().toString();
+ String cprotocol = cprotoProvider.getProtocolName();
+
+ if (user.equals(cuser) && account.equals(caccount)
+ && protocol.equals(cprotocol))
+ return;
+ }
+
+ contacts.add(contact);
+ }
+
+ @Override
+ public MessageDeliveredEvent messageDelivered(MessageDeliveredEvent evt)
+ {
+ if (evt.getSourceMessage().getContent().contains(MessageConstants.BASE_HEAD))
+ return null;
+ else
+ return evt;
+ }
+
+ @Override
+ public MessageDeliveryFailedEvent messageDeliveryFailed(
+ MessageDeliveryFailedEvent evt)
+ {
+ return evt;
+ }
+
+ @Override
+ public MessageDeliveredEvent messageDeliveryPending(
+ MessageDeliveredEvent evt)
+ {
+ Contact contact = evt.getDestinationContact();
+ addContact(contact);
+ String user = contact.getAddress();
+
+ ProtocolProviderService protoProvider = contact.getProtocolProvider();
+ String account = protoProvider.getAccountID().toString();
+ String protocol = protoProvider.getProtocolName();
+
+ Message msg = evt.getSourceMessage();
+ String msgContent = msg.getContent();
+
+ OperationSetBasicInstantMessaging imOpSet =
+ (OperationSetBasicInstantMessaging) contact.getProtocolProvider()
+ .getOperationSet(OperationSetBasicInstantMessaging.class);
+
+ String processedMessageContent =
+ us.handleSendingMessage(user, account, protocol, msgContent);
+
+ if (processedMessageContent == null
+ || processedMessageContent.length() < 1)
+ return null;
+
+ if (processedMessageContent.equals(msgContent))
+ return evt;
+
+ Message processedMessage =
+ imOpSet.createMessage(processedMessageContent);
+
+ MessageDeliveredEvent processedEvent =
+ new MessageDeliveredEvent(processedMessage, contact, evt
+ .getTimestamp());
+
+ return processedEvent;
+ }
+
+ @Override
+ public MessageReceivedEvent messageReceived(MessageReceivedEvent evt)
+ {
+ Contact contact = evt.getSourceContact();
+ addContact(contact);
+ String user = contact.getAddress();
+
+ ProtocolProviderService protoProvider = contact.getProtocolProvider();
+ String account = protoProvider.getAccountID().toString();
+ String protocol = protoProvider.getProtocolName();
+
+ Message msg = evt.getSourceMessage();
+ String msgContent = msg.getContent();
+
+ OperationSetBasicInstantMessaging imOpSet =
+ (OperationSetBasicInstantMessaging) contact.getProtocolProvider()
+ .getOperationSet(OperationSetBasicInstantMessaging.class);
+
+ String processedMessageContent =
+ us.handleReceivingMessage(user, account, protocol, msgContent);
+
+ if (processedMessageContent == null
+ || processedMessageContent.length() < 1)
+ return null;
+
+ if (processedMessageContent.equals(msgContent))
+ return evt;
+
+ Message processedMessage =
+ imOpSet.createMessage(processedMessageContent);
+
+ MessageReceivedEvent processedEvent =
+ new MessageReceivedEvent(processedMessage, contact, evt
+ .getTimestamp());
+
+ return processedEvent;
+ }
+}
diff --git a/src/net/java/sip/communicator/plugin/otr/otr.manifest.mf b/src/net/java/sip/communicator/plugin/otr/otr.manifest.mf
new file mode 100644
index 000000000..14960f990
--- /dev/null
+++ b/src/net/java/sip/communicator/plugin/otr/otr.manifest.mf
@@ -0,0 +1,25 @@
+Bundle-Activator: net.java.sip.communicator.plugin.otr.OtrActivator
+Bundle-Name: OTR (Off-the-Record) Messaging
+Bundle-Description: Support for secure, Off The Record messaging in SIP Communicator
+Bundle-Vendor: sip-communicator.org
+Bundle-Version: 0.0.1
+System-Bundle: yes
+Import-Package: org.osgi.framework,
+ net.java.sip.communicator.util,
+ net.java.sip.communicator.service.gui,
+ net.java.sip.communicator.service.protocol,
+ net.java.sip.communicator.service.protocol.event,
+ net.java.sip.communicator.service.contactlist,
+ net.java.sip.communicator.service.resources,
+ javax.swing,
+ javax.crypto,
+ javax.crypto.interfaces,
+ javax.crypto.spec,
+ org.bouncycastle.crypto,
+ org.bouncycastle.crypto.generators,
+ org.bouncycastle.crypto.params,
+ org.bouncycastle.crypto.signers,
+ org.bouncycastle.crypto.engines,
+ org.bouncycastle.crypto.modes,
+ org.bouncycastle.util,
+ org.bouncycastle.util.encoders
\ No newline at end of file
diff --git a/src/net/java/sip/communicator/service/protocol/OperationSetInstantMessageTransform.java b/src/net/java/sip/communicator/service/protocol/OperationSetInstantMessageTransform.java
index 2ab9c1a20..460cbd6ad 100644
--- a/src/net/java/sip/communicator/service/protocol/OperationSetInstantMessageTransform.java
+++ b/src/net/java/sip/communicator/service/protocol/OperationSetInstantMessageTransform.java
@@ -23,6 +23,7 @@
*
*/
public interface OperationSetInstantMessageTransform
+ extends OperationSet
{
/**
* Adds a transformation layer to this protocol provider using a default