diff options
Diffstat (limited to 'src')
14 files changed, 552 insertions, 284 deletions
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 b4e08e7..5ef2532 100644 --- a/src/net/java/sip/communicator/impl/protocol/icq/OperationSetBasicInstantMessagingIcqImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/icq/OperationSetBasicInstantMessagingIcqImpl.java @@ -172,29 +172,35 @@ public class OperationSetBasicInstantMessagingIcqImpl MessageDeliveredEvent msgDeliveryPendingEvt = new MessageDeliveredEvent(message, to); - msgDeliveryPendingEvt = this.messageDeliveryPendingTransform(msgDeliveryPendingEvt); - - if (msgDeliveryPendingEvt == null) + MessageDeliveredEvent[] msgDeliveryPendingEvts = this.messageDeliveryPendingTransform(msgDeliveryPendingEvt); + if (msgDeliveryPendingEvts == null || msgDeliveryPendingEvts.length == 0) return; - String transformedContent = msgDeliveryPendingEvt.getSourceMessage().getContent(); - - if (to.getPresenceStatus().isOnline()) + for (MessageDeliveredEvent pendingEvt : msgDeliveryPendingEvts) { - //do not add the conversation listener in here. we'll add it - //inside the icbm listener - imConversation.sendMessage(new SimpleMessage(transformedContent)); - } - else - imConversation.sendMessage(new SimpleMessage(transformedContent), true); + String transformedContent = + pendingEvt.getSourceMessage().getContent(); - MessageDeliveredEvent msgDeliveredEvt - = new MessageDeliveredEvent(message, to); + if (to.getPresenceStatus().isOnline()) + { + // do not add the conversation listener in here. we'll add it + // inside the icbm listener + imConversation + .sendMessage(new SimpleMessage(transformedContent)); + } + else + imConversation.sendMessage( + new SimpleMessage(transformedContent), true); - // msgDeliveredEvt = this.messageDeliveredTransform(msgDeliveredEvt); + MessageDeliveredEvent msgDeliveredEvt = + new MessageDeliveredEvent(message, to); - if (msgDeliveredEvt != null) - fireMessageEvent(msgDeliveredEvt); + // msgDeliveredEvt = + // this.messageDeliveredTransform(msgDeliveredEvt); + + if (msgDeliveredEvt != null) + fireMessageEvent(msgDeliveredEvt); + } } /** diff --git a/src/net/java/sip/communicator/impl/protocol/irc/IrcStack.java b/src/net/java/sip/communicator/impl/protocol/irc/IrcStack.java index b819131..22aab66 100644 --- a/src/net/java/sip/communicator/impl/protocol/irc/IrcStack.java +++ b/src/net/java/sip/communicator/impl/protocol/irc/IrcStack.java @@ -152,6 +152,12 @@ public class IrcStack private PresenceManager presence = null; /** + * The local user's identity as it will be used in server-client + * communication for sent messages. + */ + private Identity identity; + + /** * The cached channel list. * * Contained inside a simple container object in order to lock the container @@ -253,6 +259,8 @@ public class IrcStack connectSynchronized(); + queryIdentity(); + // TODO Read IRC network capabilities based on RPL_ISUPPORT (005) // replies if available. This information should be available in // irc-api if possible. @@ -363,6 +371,27 @@ public class IrcStack } /** + * Issue WHOIS query to discover identity as seen by the server. + */ + private void queryIdentity() + { + this.session.get().rawMessage( + "WHOIS " + this.connectionState.getNickname()); + } + + /** + * Get the current identity string, based on nick, user and host of local + * user. + * + * @return returns identity string + */ + public String getIdentityString() + { + final String currentNick = this.connectionState.getNickname(); + return this.identity.getIdentityString(currentNick); + } + + /** * Create a custom SSL context for this particular server. * * @param hostname host name of the host we are connecting to such that we @@ -1022,16 +1051,12 @@ public class IrcStack { final IRCApi irc = this.session.get(); irc.message(target, message.getContent()); - IrcStack.this.provider.getBasicInstantMessaging() - .fireMessageDelivered(message, contact); LOGGER.trace("Message delivered to server successfully."); } catch (RuntimeException e) { - IrcStack.this.provider.getBasicInstantMessaging() - .fireMessageDeliveryFailed(message, contact, - MessageDeliveryFailedEvent.NETWORK_FAILURE); LOGGER.trace("Failed to deliver message: " + e.getMessage(), e); + throw e; } } @@ -1185,6 +1210,11 @@ public class IrcStack */ private static final int RPL_LISTEND = IRCServerNumerics.CHANNEL_NICKS_END_OF_LIST; + + /** + * Reply for WHOIS query. + */ + private static final int IRC_RPL_WHOISUSER = 311; /** * IRCApi instance. @@ -1359,6 +1389,29 @@ public class IrcStack .fireMessageReceived(awayMessage, awayUser); break; + case IRC_RPL_WHOISUSER: + final String whoismsg = msg.getText(); + final int endNickIndex = whoismsg.indexOf(' '); + final String nick = whoismsg.substring(0, endNickIndex); + if (!IrcStack.this.connectionState.getNickname().equals(nick)) + { + // We need WHOIS info on ourselves to discover our identity + // on the IRC server. So skip other WHOIS replies. + return; + } + final int endUserIndex = + whoismsg.indexOf(' ', endNickIndex + 1); + final int endHostIndex = + whoismsg.indexOf(' ', endUserIndex + 1); + final String user = + whoismsg.substring(endNickIndex + 1, endUserIndex); + final String host = + whoismsg.substring(endUserIndex + 1, endHostIndex); + LOGGER.debug(String.format("Current identity: %s!%s@%s", + IrcStack.this.connectionState.getNickname(), user, host)); + IrcStack.this.identity = new IrcStack.Identity(user, host); + break; + default: if (LOGGER.isTraceEnabled()) { @@ -2592,4 +2645,49 @@ public class IrcStack LOGGER.debug("Old channel list cache has been cleared."); } } + + /** + * Storage container for identity components. + * + * IRC identity components user and host are stored. The nick name component + * isn't stored, because it changes too frequently. When getting the + * identity string, the nick name component is provided at calling time. + * + * @author Danny van Heumen + */ + private static final class Identity + { + /** + * User name. + */ + private final String user; + + /** + * Host name. + */ + private final String host; + + /** + * Constructor. + * + * @param user user + * @param host host + */ + private Identity(final String user, final String host) + { + this.user = user; + this.host = host; + } + + /** + * Get identity string. + * + * @param currentNick the current nick + * @return returns identity string + */ + public String getIdentityString(final String currentNick) + { + return String.format("%s!%s@%s", currentNick, this.user, this.host); + } + } } diff --git a/src/net/java/sip/communicator/impl/protocol/irc/OperationSetBasicInstantMessagingIrcImpl.java b/src/net/java/sip/communicator/impl/protocol/irc/OperationSetBasicInstantMessagingIrcImpl.java index 09a0b79..6130263 100644 --- a/src/net/java/sip/communicator/impl/protocol/irc/OperationSetBasicInstantMessagingIrcImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/irc/OperationSetBasicInstantMessagingIrcImpl.java @@ -6,6 +6,8 @@ package net.java.sip.communicator.impl.protocol.irc; import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.event.*; +import net.java.sip.communicator.util.*; /** * Implementation of Basic Instant Messaging as utilized for IRC private @@ -17,6 +19,11 @@ public class OperationSetBasicInstantMessagingIrcImpl extends AbstractOperationSetBasicInstantMessaging { /** + * Logger. + */ + private static final Logger LOGGER = Logger.getLogger(OperationSetBasicInstantMessagingIrcImpl.class); + + /** * IRC protocol provider service. */ private final ProtocolProviderServiceIrcImpl provider; @@ -59,28 +66,74 @@ public class OperationSetBasicInstantMessagingIrcImpl * Send instant message. * * @param to contact to send message to - * @param message message to send + * @param original message to send * @throws IllegalStateException in case of bad internal state * @throws IllegalArgumentException in case invalid arguments have been * passed */ @Override - public void sendInstantMessage(final Contact to, final Message message) + public void sendInstantMessage(final Contact to, final Message original) throws IllegalStateException, IllegalArgumentException { + if (!(original instanceof MessageIrcImpl)) + { + LOGGER.error("Invalid class of Message implementation received. " + + "Not sending message."); + return; + } + // OTR seems to be compatible with the command syntax (starts with '/') // and there were no other obvious problems so we decided to implement // IRC command support for IM infrastructure too. - if (message instanceof MessageIrcImpl - && ((MessageIrcImpl) message).isCommand()) + final MessageDeliveredEvent[] msgDeliveryPendingEvts = + messageDeliveryPendingTransform(new MessageDeliveredEvent(original, + to)); + + try { - this.provider.getIrcStack().command(to, (MessageIrcImpl) message); + for (MessageDeliveredEvent event : msgDeliveryPendingEvts) + { + if (event == null) + { + return; + } + + String transformedContent = + event.getSourceMessage().getContent(); + + // FIXME how to handle HTML content? + + // Note: can't set subject since it leaks information while + // message content actually gets encoded. + MessageIrcImpl message = this.createMessage(transformedContent, + original.getContentType(), original.getEncoding(), ""); + + try + { + if (message.isCommand()) + { + this.provider.getIrcStack().command(to, message); + } + else + { + this.provider.getIrcStack().message(to, message); + } + } + catch (RuntimeException e) + { + LOGGER.debug("Failed to deliver (raw) message: " + message); + throw e; + } + } + fireMessageDelivered(original, to); } - else + catch (RuntimeException e) { - this.provider.getIrcStack().message(to, message); + LOGGER.warn("Failed to deliver message: " + original, e); + fireMessageDeliveryFailed(original, to, + MessageDeliveryFailedEvent.NETWORK_FAILURE); } } diff --git a/src/net/java/sip/communicator/impl/protocol/irc/irc.provider.manifest.mf b/src/net/java/sip/communicator/impl/protocol/irc/irc.provider.manifest.mf index a28001a..2de13b0 100644 --- a/src/net/java/sip/communicator/impl/protocol/irc/irc.provider.manifest.mf +++ b/src/net/java/sip/communicator/impl/protocol/irc/irc.provider.manifest.mf @@ -3,7 +3,8 @@ Bundle-Name: Irc Protocol Provider Bundle-Description: A bundle providing support for the Irc protocol. Bundle-Vendor: jitsi.org Bundle-Version: 0.0.1 -Bundle-SymbolicName: net.java.sip.communicator.protocol.irc +Bundle-SymbolicName: net.java.sip.communicator.impl.protocol.irc +Export-Package: net.java.sip.communicator.impl.protocol.irc Import-Package: org.osgi.framework, org.jitsi.service.configuration, org.jitsi.service.resources, 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 0b53ccb..486d49f 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicInstantMessagingJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicInstantMessagingJabberImpl.java @@ -442,62 +442,60 @@ public class OperationSetBasicInstantMessagingJabberImpl MessageDeliveredEvent msgDeliveryPendingEvt = new MessageDeliveredEvent(message, to, toResource); - msgDeliveryPendingEvt - = messageDeliveryPendingTransform(msgDeliveryPendingEvt); + MessageDeliveredEvent[] transformedEvents = messageDeliveryPendingTransform(msgDeliveryPendingEvt); - if (msgDeliveryPendingEvt == null) + if (transformedEvents == null || transformedEvents.length == 0) return null; - String content = msgDeliveryPendingEvt - .getSourceMessage().getContent(); - - if(message.getContentType().equals(HTML_MIME_TYPE)) + for (MessageDeliveredEvent event : transformedEvents) { - msg.setBody(Html2Text.extractText(content)); + String content = event.getSourceMessage().getContent(); - // Check if the other user supports XHTML messages - // make sure we use our discovery manager as it caches calls - if(jabberProvider.isFeatureListSupported( - toJID, - HTML_NAMESPACE)) + if (message.getContentType().equals(HTML_MIME_TYPE)) { - // Add the XHTML text to the message - XHTMLManager.addBody(msg, - OPEN_BODY_TAG + content + CLOSE_BODY_TAG); - } - } - else - { - // this is plain text so keep it as it is. - msg.setBody(content); - } + msg.setBody(Html2Text.extractText(content)); - //msg.addExtension(new Version()); + // Check if the other user supports XHTML messages + // make sure we use our discovery manager as it caches calls + if (jabberProvider + .isFeatureListSupported(toJID, HTML_NAMESPACE)) + { + // Add the XHTML text to the message + XHTMLManager.addBody(msg, OPEN_BODY_TAG + content + + CLOSE_BODY_TAG); + } + } + else + { + // this is plain text so keep it as it is. + msg.setBody(content); + } - if(msgDeliveryPendingEvt.isMessageEncrypted()) - { - msg.addExtension(new CarbonPacketExtension.PrivateExtension()); - } + // msg.addExtension(new Version()); - MessageEventManager. - addNotificationsRequests(msg, true, false, false, true); + if (event.isMessageEncrypted()) + { + msg.addExtension(new CarbonPacketExtension.PrivateExtension()); + } - String threadID = getThreadIDForAddress(toJID); - if(threadID == null) - threadID = nextThreadID(); + MessageEventManager.addNotificationsRequests(msg, true, false, + false, true); - msg.setThread(threadID); - msg.setType(org.jivesoftware.smack.packet.Message.Type.chat); - msg.setFrom(jabberProvider.getConnection().getUser()); + String threadID = getThreadIDForAddress(toJID); + if (threadID == null) + threadID = nextThreadID(); - jabberProvider.getConnection().sendPacket(msg); + msg.setThread(threadID); + msg.setType(org.jivesoftware.smack.packet.Message.Type.chat); + msg.setFrom(jabberProvider.getConnection().getUser()); - putJidForAddress(toJID, threadID); + jabberProvider.getConnection().sendPacket(msg); - MessageDeliveredEvent msgDeliveredEvt - = new MessageDeliveredEvent(message, to, toResource); + putJidForAddress(toJID, threadID); + } - // msgDeliveredEvt = messageDeliveredTransform(msgDeliveredEvt); + MessageDeliveredEvent msgDeliveredEvt = + new MessageDeliveredEvent(message, to, toResource); return msgDeliveredEvt; } @@ -1119,6 +1117,7 @@ public class OperationSetBasicInstantMessagingJabberImpl ? "service.gui.NEW_GMAIL_MANY_FOOTER" : "service.gui.NEW_GMAIL_FOOTER"; + // FIXME Escape HTML! String newMailHeader = JabberActivator.getResources().getI18NString( resourceHeaderKey, new String[] 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 e614586..e09d9c1 100644 --- a/src/net/java/sip/communicator/impl/protocol/msn/OperationSetBasicInstantMessagingMsnImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/msn/OperationSetBasicInstantMessagingMsnImpl.java @@ -113,7 +113,7 @@ public class OperationSetBasicInstantMessagingMsnImpl * @throws java.lang.IllegalArgumentException if <tt>to</tt> is not an * instance of ContactImpl. */ - public void sendInstantMessage(final Contact to, Message message) + public void sendInstantMessage(final Contact to, final Message message) throws IllegalStateException, IllegalArgumentException { assertConnected(); @@ -123,29 +123,30 @@ public class OperationSetBasicInstantMessagingMsnImpl "The specified contact is not an MSN contact." + to); - final MessageDeliveredEvent msgDeliveryPendingEvt - = messageDeliveryPendingTransform( - new MessageDeliveredEvent(message, to)); + MessageDeliveredEvent[] transformedEvents = messageDeliveryPendingTransform( + new MessageDeliveredEvent(message, to)); - if (msgDeliveryPendingEvt == null) + if (transformedEvents == null || transformedEvents.length == 0) return; - MessageDeliveredEvent msgDeliveredEvt - = new MessageDeliveredEvent(message, to); + MessageDeliveredEvent msgDeliveredEvt = + new MessageDeliveredEvent(message, to); fireMessageEvent(msgDeliveredEvt); - // send message in separate thread so we won't block ui if - // it takes time. - if(senderThread == null) + // send message in separate thread so we won't block ui if it takes + // time. + if (senderThread == null) { senderThread = new SenderThread(); senderThread.start(); } - senderThread.sendMessage( - (ContactMsnImpl)to, - msgDeliveryPendingEvt.getSourceMessage().getContent()); + for (MessageDeliveredEvent event : transformedEvents) + { + senderThread.sendMessage((ContactMsnImpl) to, event + .getSourceMessage().getContent()); + } } /** @@ -323,6 +324,7 @@ public class OperationSetBasicInstantMessagingMsnImpl logger.warn("Failed to decode the subject of a new e-mail", ex); } + // FIXME Escape HTML! String messageFrom = message.getFrom(); Message newMailMessage = new MessageMsnImpl( MessageFormat.format( diff --git a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicInstantMessagingSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicInstantMessagingSipImpl.java index 3b40ba8..2e0534a 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicInstantMessagingSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicInstantMessagingSipImpl.java @@ -214,53 +214,44 @@ public class OperationSetBasicInstantMessagingSipImpl } // create the message - Request mes; - try - { - Message transformedMessage = transformSIPMessage(to, message); - mes = createMessageRequest(to, transformedMessage); - } - catch (OperationFailedException ex) + Message[] transformedMessages = transformSIPMessage(to, message); + for (Message msg : transformedMessages) { - logger.error( - "Failed to create the message." - , ex); + Request mes; + try + { + mes = createMessageRequest(to, msg); + } + catch (OperationFailedException ex) + { + logger.error("Failed to create the message.", ex); - fireMessageDeliveryFailed( - message, - to, - MessageDeliveryFailedEvent.INTERNAL_ERROR); - return; - } + fireMessageDeliveryFailed(message, to, + MessageDeliveryFailedEvent.INTERNAL_ERROR); + continue; + } - try - { - sendMessageRequest(mes, to, message); - } - catch(TransactionUnavailableException ex) - { - logger.error( - "Failed to create messageTransaction.\n" - + "This is most probably a network connection error." - , ex); + try + { + sendMessageRequest(mes, to, message); + } + catch (TransactionUnavailableException ex) + { + logger.error("Failed to create messageTransaction.\n" + + "This is most probably a network connection error.", ex); - fireMessageDeliveryFailed( - message, - to, - MessageDeliveryFailedEvent.NETWORK_FAILURE); - return; - } - catch(SipException ex) - { - logger.error( - "Failed to send the message." - , ex); + fireMessageDeliveryFailed(message, to, + MessageDeliveryFailedEvent.NETWORK_FAILURE); + continue; + } + catch (SipException ex) + { + logger.error("Failed to send the message.", ex); - fireMessageDeliveryFailed( - message, - to, - MessageDeliveryFailedEvent.INTERNAL_ERROR); - return; + fireMessageDeliveryFailed(message, to, + MessageDeliveryFailedEvent.INTERNAL_ERROR); + continue; + } } } @@ -482,28 +473,36 @@ public class OperationSetBasicInstantMessagingSipImpl * * @return The new transformed <tt>Message</tt> */ - private Message transformSIPMessage(Contact to, Message message) + private Message[] transformSIPMessage(final Contact to, + final Message message) { MessageDeliveredEvent msgDeliveryPendingEvt = new MessageDeliveredEvent(message, to); - msgDeliveryPendingEvt - = messageDeliveryPendingTransform(msgDeliveryPendingEvt); + MessageDeliveredEvent[] msgDeliveryPendingEvts = + messageDeliveryPendingTransform(msgDeliveryPendingEvt); - if (msgDeliveryPendingEvt == null) - return null; - - String content = msgDeliveryPendingEvt.getSourceMessage().getContent(); + if (msgDeliveryPendingEvts == null + || msgDeliveryPendingEvts.length == 0) + { + return new Message[0]; + } OperationSetBasicInstantMessaging opSetBasicIM = (OperationSetBasicInstantMessaging) sipProvider .getSupportedOperationSets().get( OperationSetBasicInstantMessaging.class.getName()); - Message transformedMesssage = - opSetBasicIM.createMessage(content, message.getContentType(), - message.getEncoding(), message.getSubject()); - - return transformedMesssage; + Message[] transformedMessages = + new Message[msgDeliveryPendingEvts.length]; + for (int i = 0; i < msgDeliveryPendingEvts.length; i++) + { + MessageDeliveredEvent event = msgDeliveryPendingEvts[i]; + String content = event.getSourceMessage().getContent(); + transformedMessages[i] = + opSetBasicIM.createMessage(content, message.getContentType(), + message.getEncoding(), message.getSubject()); + } + return transformedMessages; } /** 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 ab9ba26..eb53d4a 100644 --- a/src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetBasicInstantMessagingYahooImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetBasicInstantMessagingYahooImpl.java @@ -150,56 +150,55 @@ public class OperationSetBasicInstantMessagingYahooImpl { String toUserID = ((ContactYahooImpl) to).getID(); - MessageDeliveredEvent msgDeliveryPendingEvt - = new MessageDeliveredEvent( - message, to, new Date()); + MessageDeliveredEvent msgDeliveryPendingEvt = + new MessageDeliveredEvent(message, to, new Date()); - msgDeliveryPendingEvt = messageDeliveryPendingTransform(msgDeliveryPendingEvt); + MessageDeliveredEvent[] msgDeliveryPendingEvts = messageDeliveryPendingTransform(msgDeliveryPendingEvt); - if (msgDeliveryPendingEvt == null) + if (msgDeliveryPendingEvts == null || msgDeliveryPendingEvts.length == 0) return; - byte[] msgBytesToBeSent = msgDeliveryPendingEvt.getSourceMessage(). - getContent().trim().getBytes("UTF-8"); - - // split the message in parts with max allowed length - // and send them all - do + for (MessageDeliveredEvent event : msgDeliveryPendingEvts) { - if(msgBytesToBeSent.length > MAX_MESSAGE_LENGTH) - { - byte[] tmp1 = new byte[MAX_MESSAGE_LENGTH]; - System.arraycopy(msgBytesToBeSent, - 0, tmp1, 0, MAX_MESSAGE_LENGTH); - - byte[] tmp2 = - new byte[msgBytesToBeSent.length - MAX_MESSAGE_LENGTH]; - System.arraycopy(msgBytesToBeSent, - MAX_MESSAGE_LENGTH, tmp2, 0, tmp2.length); + byte[] msgBytesToBeSent = + event.getSourceMessage().getContent().trim() + .getBytes("UTF-8"); - msgBytesToBeSent = tmp2; - - yahooProvider.getYahooSession().sendMessage( - toUserID, - new String(tmp1, "UTF-8")); - } - else + // split the message in parts with max allowed length + // and send them all + do { - yahooProvider.getYahooSession().sendMessage( - toUserID, - new String(msgBytesToBeSent, "UTF-8")); + if (msgBytesToBeSent.length > MAX_MESSAGE_LENGTH) + { + byte[] tmp1 = new byte[MAX_MESSAGE_LENGTH]; + System.arraycopy(msgBytesToBeSent, 0, tmp1, 0, + MAX_MESSAGE_LENGTH); + + byte[] tmp2 = + new byte[msgBytesToBeSent.length + - MAX_MESSAGE_LENGTH]; + System.arraycopy(msgBytesToBeSent, MAX_MESSAGE_LENGTH, + tmp2, 0, tmp2.length); + + msgBytesToBeSent = tmp2; + + yahooProvider.getYahooSession().sendMessage(toUserID, + new String(tmp1, "UTF-8")); + } + else + { + yahooProvider.getYahooSession().sendMessage(toUserID, + new String(msgBytesToBeSent, "UTF-8")); + } + + MessageDeliveredEvent msgDeliveredEvt = + new MessageDeliveredEvent(message, to, new Date()); + + if (msgDeliveredEvt != null) + fireMessageEvent(msgDeliveredEvt); } - - MessageDeliveredEvent msgDeliveredEvt - = new MessageDeliveredEvent( - message, to, new Date()); - - // msgDeliveredEvt = messageDeliveredTransform(msgDeliveredEvt); - - if (msgDeliveredEvt != null) - fireMessageEvent(msgDeliveredEvt); + while (msgBytesToBeSent.length > MAX_MESSAGE_LENGTH); } - while(msgBytesToBeSent.length > MAX_MESSAGE_LENGTH); } catch (IOException ex) { @@ -210,8 +209,6 @@ public class OperationSetBasicInstantMessagingYahooImpl to, MessageDeliveryFailedEvent.NETWORK_FAILURE); - // evt = messageDeliveryFailedTransform(evt); - if (evt != null) fireMessageEvent(evt); } @@ -374,6 +371,7 @@ public class OperationSetBasicInstantMessagingYahooImpl + yahooMailLogon + "\">" + yahooMailLogon + "</a>"; + // FIXME Escape HTML! String newMail = YahooActivator.getResources().getI18NString( "service.gui.NEW_MAIL", new String[]{ev.getFrom(), diff --git a/src/net/java/sip/communicator/plugin/otr/OtrTransformLayer.java b/src/net/java/sip/communicator/plugin/otr/OtrTransformLayer.java index f447de0..7c94eac 100644 --- a/src/net/java/sip/communicator/plugin/otr/OtrTransformLayer.java +++ b/src/net/java/sip/communicator/plugin/otr/OtrTransformLayer.java @@ -61,7 +61,7 @@ public class OtrTransformLayer /* * Implements TransformLayer#messageDeliveryPending(MessageDeliveredEvent). */ - public MessageDeliveredEvent messageDeliveryPending( + public MessageDeliveredEvent[] messageDeliveryPending( MessageDeliveredEvent evt) { Contact contact = evt.getDestinationContact(); @@ -76,47 +76,57 @@ public class OtrTransformLayer if (!policy.getEnableManual() && sessionStatus != ScSessionStatus.ENCRYPTED && sessionStatus != ScSessionStatus.FINISHED) - return evt; + return new MessageDeliveredEvent[] {evt}; // If this is a message otr4j injected earlier, return the event as is. if (OtrActivator.scOtrEngine.isMessageUIDInjected(evt .getSourceMessage().getMessageUID())) - return evt; + return new MessageDeliveredEvent[] {evt}; // Process the outgoing message. String msgContent = evt.getSourceMessage().getContent(); - String processedMessageContent = + String[] processedMessageContent = OtrActivator.scOtrEngine.transformSending(otrContact, msgContent); if (processedMessageContent == null - || processedMessageContent.length() < 1) - return null; - - if (processedMessageContent.equals(msgContent)) - return evt; - - // Forge a new message based on the new contents. - OperationSetBasicInstantMessaging imOpSet = - contact.getProtocolProvider().getOperationSet( - OperationSetBasicInstantMessaging.class); - Message processedMessage = - imOpSet.createMessage( - processedMessageContent, - evt.getSourceMessage().getContentType(), - evt.getSourceMessage().getEncoding(), - evt.getSourceMessage().getSubject()); + || processedMessageContent.length <= 0 + || processedMessageContent[0].length() < 1) + return new MessageDeliveredEvent[0]; - // Create a new event and return. - MessageDeliveredEvent processedEvent = - new MessageDeliveredEvent(processedMessage, contact, evt - .getTimestamp()); + if (processedMessageContent.length == 1 + && processedMessageContent[0].equals(msgContent)) + return new MessageDeliveredEvent[] {evt}; - if(processedMessage.getContent().contains(SerializationConstants.HEAD)) + final MessageDeliveredEvent[] processedEvents = + new MessageDeliveredEvent[processedMessageContent.length]; + for (int i = 0; i < processedMessageContent.length; i++) { - processedEvent.setMessageEncrypted(true); + final String fragmentContent = processedMessageContent[i]; + // Forge a new message based on the new contents. + OperationSetBasicInstantMessaging imOpSet = + contact.getProtocolProvider().getOperationSet( + OperationSetBasicInstantMessaging.class); + Message processedMessage = + imOpSet.createMessage(fragmentContent, evt + .getSourceMessage().getContentType(), evt + .getSourceMessage().getEncoding(), evt.getSourceMessage() + .getSubject()); + + // Create a new event and return. + final MessageDeliveredEvent processedEvent = + new MessageDeliveredEvent(processedMessage, contact, + evt.getTimestamp()); + + if (processedMessage.getContent().contains( + SerializationConstants.HEAD)) + { + processedEvent.setMessageEncrypted(true); + } + + processedEvents[i] = processedEvent; } - return processedEvent; + return processedEvents; } /* diff --git a/src/net/java/sip/communicator/plugin/otr/ScOtrEngine.java b/src/net/java/sip/communicator/plugin/otr/ScOtrEngine.java index f9ee909..5bd9688 100644 --- a/src/net/java/sip/communicator/plugin/otr/ScOtrEngine.java +++ b/src/net/java/sip/communicator/plugin/otr/ScOtrEngine.java @@ -70,7 +70,7 @@ public interface ScOtrEngine * @param content the original message content. * @return the transformed message content. */ - public abstract String transformSending(OtrContact contact, String content); + public abstract String[] transformSending(OtrContact contact, String content); /** * Transforms an incoming message. diff --git a/src/net/java/sip/communicator/plugin/otr/ScOtrEngineImpl.java b/src/net/java/sip/communicator/plugin/otr/ScOtrEngineImpl.java index a06b61d..f14c2ec 100644 --- a/src/net/java/sip/communicator/plugin/otr/ScOtrEngineImpl.java +++ b/src/net/java/sip/communicator/plugin/otr/ScOtrEngineImpl.java @@ -14,6 +14,7 @@ import java.util.concurrent.*; import net.java.otr4j.*;
import net.java.otr4j.crypto.*;
import net.java.otr4j.session.*;
+import net.java.sip.communicator.impl.protocol.irc.*;
import net.java.sip.communicator.plugin.otr.OtrContactManager.OtrContact;
import net.java.sip.communicator.plugin.otr.authdialog.*;
import net.java.sip.communicator.service.browserlauncher.*;
@@ -420,6 +421,44 @@ public class ScOtrEngineImpl message,
OperationSetBasicInstantMessaging.HTML_MIME_TYPE);
}
+
+ /**
+ * Provide fragmenter instructions according to the Instant Messaging
+ * transport channel of the contact's protocol.
+ */
+ @Override
+ public FragmenterInstructions getFragmenterInstructions(
+ final SessionID sessionID)
+ {
+ final OtrContact otrContact = getOtrContact(sessionID);
+ // FIXME Change this into querying an Operation Set that provides
+ // Instant Message medium/transport information that we can use to
+ // determine fragmentation parameters.
+ if (ProtocolNames.IRC.equals(otrContact.contact
+ .getProtocolProvider().getProtocolName()))
+ {
+ // :<nick>!<user>@<host> PRIVMSG <targetnick> :<message>
+ //
+ // Example:
+ // :ircotrtest!~ircotrtes@77-175-185-165.FTTH.ispfabriek.nl
+ // PRIVMSG test12345abc :
+ final String identity =
+ ((ProtocolProviderServiceIrcImpl) otrContact.contact
+ .getProtocolProvider()).getIrcStack()
+ .getIdentityString();
+ final int size =
+ 510 - (":" + identity + " PRIVMSG "
+ + otrContact.contact.getAddress() + " :").length();
+ return new FragmenterInstructions(
+ FragmenterInstructions.UNLIMITED, size);
+ }
+ else
+ {
+ return new FragmenterInstructions(
+ FragmenterInstructions.UNLIMITED,
+ FragmenterInstructions.UNLIMITED);
+ }
+ }
}
/**
@@ -510,11 +549,11 @@ public class ScOtrEngineImpl private final OtrEngineHost otrEngineHost = new ScOtrEngineHost();
- private final OtrEngine otrEngine;
+ private final OtrSessionManager otrEngine;
public ScOtrEngineImpl()
{
- otrEngine = new OtrEngineImpl(otrEngineHost);
+ otrEngine = new OtrSessionManagerImpl(otrEngineHost);
// Clears the map after previous instance
// This is required because of OSGi restarts in the same VM on Android
@@ -539,13 +578,13 @@ public class ScOtrEngineImpl ScSessionStatus scSessionStatus = getSessionStatus(otrContact);
String message = "";
- switch (otrEngine.getSessionStatus(sessionID))
+ final Session session = otrEngine.getSession(sessionID);
+ switch (session.getSessionStatus())
{
case ENCRYPTED:
scSessionStatus = ScSessionStatus.ENCRYPTED;
scSessionStatusMap.put(sessionID, scSessionStatus);
- PublicKey remotePubKey =
- otrEngine.getRemotePublicKey(sessionID);
+ PublicKey remotePubKey = session.getRemotePublicKey();
String remoteFingerprint = null;
try
@@ -790,7 +829,7 @@ public class ScOtrEngineImpl {
setSessionStatus(otrContact, ScSessionStatus.PLAINTEXT);
- otrEngine.endSession(sessionID);
+ otrEngine.getSession(sessionID).endSession();
}
catch (OtrException e)
{
@@ -926,7 +965,7 @@ public class ScOtrEngineImpl public ScSessionStatus getSessionStatus(OtrContact contact)
{
SessionID sessionID = getSessionID(contact);
- SessionStatus sessionStatus = otrEngine.getSessionStatus(sessionID);
+ SessionStatus sessionStatus = otrEngine.getSession(sessionID).getSessionStatus();
ScSessionStatus scSessionStatus = null;
if (!scSessionStatusMap.containsKey(sessionID))
{
@@ -976,7 +1015,7 @@ public class ScOtrEngineImpl SessionID sessionID = getSessionID(otrContact);
try
{
- otrEngine.refreshSession(sessionID);
+ otrEngine.getSession(sessionID).refreshSession();
}
catch (OtrException e)
{
@@ -1112,7 +1151,7 @@ public class ScOtrEngineImpl try
{
- otrEngine.startSession(sessionID);
+ otrEngine.getSession(sessionID).startSession();
}
catch (OtrException e)
{
@@ -1127,7 +1166,7 @@ public class ScOtrEngineImpl SessionID sessionID = getSessionID(otrContact);
try
{
- return otrEngine.transformReceiving(sessionID, msgText);
+ return otrEngine.getSession(sessionID).transformReceiving(msgText);
}
catch (OtrException e)
{
@@ -1138,12 +1177,12 @@ public class ScOtrEngineImpl }
@Override
- public String transformSending(OtrContact otrContact, String msgText)
+ public String[] transformSending(OtrContact otrContact, String msgText)
{
SessionID sessionID = getSessionID(otrContact);
try
{
- return otrEngine.transformSending(sessionID, msgText);
+ return otrEngine.getSession(sessionID).transformSending(msgText);
}
catch (OtrException e)
{
@@ -1280,6 +1319,6 @@ public class ScOtrEngineImpl SessionID sessionID = getSessionID(contact);
- return otrEngine.getOutgoingSession(sessionID);
+ return otrEngine.getSession(sessionID).getOutgoingInstance();
}
}
diff --git a/src/net/java/sip/communicator/plugin/otr/otr.manifest.mf b/src/net/java/sip/communicator/plugin/otr/otr.manifest.mf index 07807d4..0dbc565 100644 --- a/src/net/java/sip/communicator/plugin/otr/otr.manifest.mf +++ b/src/net/java/sip/communicator/plugin/otr/otr.manifest.mf @@ -33,4 +33,5 @@ Import-Package: org.osgi.framework, org.bouncycastle.crypto.modes,
org.bouncycastle.util,
org.bouncycastle.util.encoders,
- net.java.sip.communicator.service.msghistory
+ net.java.sip.communicator.service.msghistory,
+ net.java.sip.communicator.impl.protocol.irc
diff --git a/src/net/java/sip/communicator/service/protocol/AbstractOperationSetBasicInstantMessaging.java b/src/net/java/sip/communicator/service/protocol/AbstractOperationSetBasicInstantMessaging.java index d3c42eb..28ab995 100644 --- a/src/net/java/sip/communicator/service/protocol/AbstractOperationSetBasicInstantMessaging.java +++ b/src/net/java/sip/communicator/service/protocol/AbstractOperationSetBasicInstantMessaging.java @@ -205,38 +205,41 @@ public abstract class AbstractOperationSetBasicInstantMessaging } // Transform the event. - try + EventObject[] events = messageTransform(evt, eventType); + for (EventObject event : events) { - evt = messageTransform(evt, eventType); - if (evt == null) - return; - - for (MessageListener listener : listeners) + try { - switch (eventType) + if (event == null) + return; + + for (MessageListener listener : listeners) { - case MessageDelivered: - listener.messageDelivered((MessageDeliveredEvent) evt); - break; - case MessageDeliveryFailed: - listener.messageDeliveryFailed( - (MessageDeliveryFailedEvent)evt); - break; - case MessageReceived: - listener.messageReceived((MessageReceivedEvent) evt); - break; - default: - /* - * We either have nothing to do or we do not know what to - * do. Anyway, we'll silence the compiler. - */ - break; + switch (eventType) + { + case MessageDelivered: + listener.messageDelivered((MessageDeliveredEvent) event); + break; + case MessageDeliveryFailed: + listener + .messageDeliveryFailed((MessageDeliveryFailedEvent) event); + break; + case MessageReceived: + listener.messageReceived((MessageReceivedEvent) event); + break; + default: + /* + * We either have nothing to do or we do not know what + * to do. Anyway, we'll silence the compiler. + */ + break; + } } } - } - catch (Throwable e) - { - logger.error("Error delivering message", e); + catch (Throwable e) + { + logger.error("Error delivering message", e); + } } } @@ -268,18 +271,44 @@ public abstract class AbstractOperationSetBasicInstantMessaging } } - public MessageDeliveredEvent messageDeliveryPendingTransform( - MessageDeliveredEvent evt) + /** + * Messages pending delivery to be transformed. + * + * @param evt the message delivery event + * @return returns message delivery events + */ + public MessageDeliveredEvent[] messageDeliveryPendingTransform( + final MessageDeliveredEvent evt) { - return (MessageDeliveredEvent) messageTransform( + EventObject[] transformed = messageTransform( evt, MessageEventType.MessageDeliveryPending); - } - private EventObject messageTransform( EventObject evt, - MessageEventType eventType){ + final int size = transformed.length; + MessageDeliveredEvent[] events = + new MessageDeliveredEvent[size]; + System.arraycopy(transformed, 0, events, 0, size); + return events; + } + /** + * Transform provided source event by processing transform layers in + * sequence. + * + * @param evt the source event to transform + * @param eventType the event type of the source event + * @return returns the resulting (transformed) events, if any. (I.e. an + * array of 0 or more size containing events.) + */ + private EventObject[] messageTransform(final EventObject evt, + final MessageEventType eventType) + { + if (evt == null) + { + return new EventObject[0]; + } ProtocolProviderService protocolProvider; - switch (eventType){ + switch (eventType) + { case MessageDelivered: protocolProvider = ((MessageDeliveredEvent) evt) @@ -301,7 +330,7 @@ public abstract class AbstractOperationSetBasicInstantMessaging .getSourceContact().getProtocolProvider(); break; default: - return evt; + return new EventObject[] {evt}; } OperationSetInstantMessageTransformImpl opSetMessageTransform @@ -309,49 +338,81 @@ public abstract class AbstractOperationSetBasicInstantMessaging .getOperationSet(OperationSetInstantMessageTransform.class); if (opSetMessageTransform == null) - return evt; - + return new EventObject[] {evt}; + + // 'current' contains the events that need to be transformed. It should + // not contain null values. + final LinkedList<EventObject> current = new LinkedList<EventObject>(); + // Add source event as start of transformation. + current.add(evt); + // 'next' contains the resulting events after transformation in the + // current iteration. It should not contain null values. + final LinkedList<EventObject> next = new LinkedList<EventObject>(); for (Map.Entry<Integer, Vector<TransformLayer>> entry : opSetMessageTransform.transformLayers.entrySet()) { for (TransformLayer transformLayer : entry.getValue()) { - if (evt != null){ - switch (eventType){ + next.clear(); + while (!current.isEmpty()) + { + final EventObject event = current.remove(); + switch (eventType) + { case MessageDelivered: - evt - = transformLayer - .messageDelivered((MessageDeliveredEvent)evt); + MessageDeliveredEvent transformedDelivered = + transformLayer.messageDelivered( + (MessageDeliveredEvent) event); + if (transformedDelivered != null) + { + next.add(transformedDelivered); + } break; case MessageDeliveryPending: - evt - = transformLayer - .messageDeliveryPending( - (MessageDeliveredEvent)evt); + MessageDeliveredEvent[] evts = transformLayer + .messageDeliveryPending( + (MessageDeliveredEvent) event); + for (MessageDeliveredEvent mde : evts) + { + if (mde != null) + { + next.add(mde); + } + } break; case MessageDeliveryFailed: - evt - = transformLayer - .messageDeliveryFailed( - (MessageDeliveryFailedEvent)evt); + MessageDeliveryFailedEvent transformedDeliveryFailed = + transformLayer.messageDeliveryFailed( + (MessageDeliveryFailedEvent) event); + if (transformedDeliveryFailed != null) + { + next.add(transformedDeliveryFailed); + } break; case MessageReceived: - evt - = transformLayer - .messageReceived((MessageReceivedEvent)evt); + MessageReceivedEvent transformedReceived = + transformLayer + .messageReceived((MessageReceivedEvent) event); + if (transformedReceived != null) + { + next.add(transformedReceived); + } break; default: + next.add(event); /* - * We either have nothing to do or we do not know what - * to do. Anyway, we'll silence the compiler. + * We either have nothing to do or we do not know + * what to do. Anyway, we'll silence the compiler. */ break; } } + // Set events for next round of transformations. + current.addAll(next); } } - return evt; + return current.toArray(new EventObject[current.size()]); } /** diff --git a/src/net/java/sip/communicator/service/protocol/TransformLayer.java b/src/net/java/sip/communicator/service/protocol/TransformLayer.java index fb48f6c..f9615bd 100644 --- a/src/net/java/sip/communicator/service/protocol/TransformLayer.java +++ b/src/net/java/sip/communicator/service/protocol/TransformLayer.java @@ -61,12 +61,13 @@ public interface TransformLayer * @param evt the MessageDeliveredEvent containing the id of the message * that has caused the event. * - * @return an instance of a (possibly new) <tt>MessageDeliveredEvent</tt> - * instance containing the transformed message or <tt>null</tt> if the - * <tt>TransportLayer</tt> has determined that this message event should not - * be delivered to the upper layers. + * @return a number of instances of (possibly new) + * <tt>MessageDeliveredEvent</tt> instances containing the transformed + * message(s) or an empty array if the <tt>TransportLayer</tt> has + * determined that there are no message event that should be delivered to + * the upper layers. */ - public MessageDeliveredEvent messageDeliveryPending(MessageDeliveredEvent evt); + public MessageDeliveredEvent[] messageDeliveryPending(MessageDeliveredEvent evt); /** * Called when the underlying implementation has received an indication |