diff --git a/lib/installer-exclude/irc-api-1.0-sources.jar b/lib/installer-exclude/irc-api-1.0-sources.jar index ca6388bd6..70b7393b0 100644 Binary files a/lib/installer-exclude/irc-api-1.0-sources.jar and b/lib/installer-exclude/irc-api-1.0-sources.jar differ diff --git a/lib/installer-exclude/irc-api-1.0.jar b/lib/installer-exclude/irc-api-1.0.jar index db98348bf..b97ac133b 100644 Binary files a/lib/installer-exclude/irc-api-1.0.jar and b/lib/installer-exclude/irc-api-1.0.jar differ diff --git a/src/net/java/sip/communicator/impl/protocol/irc/IrcActivator.java b/src/net/java/sip/communicator/impl/protocol/irc/IrcActivator.java index fc867f5e8..b69d4a2f0 100644 --- a/src/net/java/sip/communicator/impl/protocol/irc/IrcActivator.java +++ b/src/net/java/sip/communicator/impl/protocol/irc/IrcActivator.java @@ -8,6 +8,7 @@ import java.util.*; +import net.java.sip.communicator.service.certificate.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.service.resources.*; import net.java.sip.communicator.util.*; @@ -37,10 +38,15 @@ public class IrcActivator /** * The currently valid bundle context. */ - public static BundleContext bundleContext = null; + private static BundleContext bundleContext = null; private static ResourceManagementService resourceService; + /** + * Certificate Service instance. + */ + private static CertificateService certiticateService; + /** * Called when this bundle is started. In here we'll export the * IRC ProtocolProviderFactory implementation so that it could be @@ -112,4 +118,33 @@ public static ResourceManagementService getResources() = ResourceManagementServiceUtils.getService(bundleContext); return resourceService; } + + /** + * Bundle Context + * + * @return returns bundle context + */ + public static BundleContext getBundleContext() + { + return bundleContext; + } + /** + * Return the certificate verification service impl. + * + * @return the CertificateVerification service. + */ + public static CertificateService getCertificateVerificationService() + { + if(certiticateService == null) + { + ServiceReference guiVerifyReference + = IrcActivator.getBundleContext().getServiceReference( + CertificateService.class.getName()); + if(guiVerifyReference != null) + certiticateService = (CertificateService) + IrcActivator.getBundleContext().getService( + guiVerifyReference); + } + return certiticateService; + } } 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 6a3076cc9..b3e5e6bce 100644 --- a/src/net/java/sip/communicator/impl/protocol/irc/IrcStack.java +++ b/src/net/java/sip/communicator/impl/protocol/irc/IrcStack.java @@ -7,9 +7,13 @@ package net.java.sip.communicator.impl.protocol.irc; import java.io.*; +import java.security.*; import java.util.*; +import javax.net.ssl.*; + import net.java.sip.communicator.impl.protocol.irc.ModeParser.ModeEntry; +import net.java.sip.communicator.service.certificate.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.service.protocol.event.*; import net.java.sip.communicator.util.*; @@ -61,7 +65,7 @@ public class IrcStack * Connection state of a successful IRC connection. */ private IIRCState connectionState; - + /** * The cached channel list. * @@ -133,20 +137,16 @@ public void connect(String host, int port, String password, this.joined.clear(); this.irc = new IRCApiImpl(true); - // FIXME Currently, the secure connection is created by - // explicitly creating an SSLContext for 'SSL'. According - // to Ingo (in a mailing list conversation) it is better to - // use the CertificateService for this. This should be - // implemented in the irc-api library, though. - this.params.setServer(new IRCServer(host, port, password, - secureConnection)); synchronized (this.irc) { + this.params.setServer(new IRCServer(host, port, password, + secureConnection)); + this.params.setCustomContext(getCustomSSLContext(host)); this.irc.addListener(new ServerListener()); connectSynchronized(); } } - + /** * Perform synchronized connect operation. * @@ -195,7 +195,7 @@ public void onFailure(Exception e) .trace("Waiting for the connection to be established ..."); result.wait(); } - + this.connectionState = result.getValue(); // TODO Implement connection timeout and a way to recognize that // the timeout occurred. @@ -232,6 +232,30 @@ public void onFailure(Exception e) } } + /** + * Create a custom SSL context for this particular server. + * + * @return returns a customized SSL context or null if one cannot + * be created. + */ + private SSLContext getCustomSSLContext(String hostname) + { + SSLContext context = null; + try + { + CertificateService cs = + IrcActivator.getCertificateVerificationService(); + X509TrustManager tm = + cs.getTrustManager(hostname); + context = cs.getSSLContext(tm); + } + catch (GeneralSecurityException e) + { + LOGGER.error("failed to create custom SSL context", e); + } + return context; + } + /** * Disconnect from the IRC server */ @@ -239,8 +263,8 @@ public void disconnect() { if (this.connectionState == null && this.irc == null) return; - - synchronized(this.joined) + + synchronized (this.joined) { // Leave all joined channels. for (ChatRoomIrcImpl channel : this.joined.values()) @@ -248,7 +272,7 @@ public void disconnect() leave(channel); } } - synchronized(this.irc) + synchronized (this.irc) { // Disconnect and clean up this.irc.disconnect(); @@ -575,7 +599,7 @@ public void onFailure(Exception e) .trace("Finished waiting for join operation for channel '" + chatroom.getIdentifier() + "' to complete."); // TODO How to handle 480 (+j): Channel throttle exceeded? - + Exception e = joinSignal.getException(); if (e != null) { @@ -666,10 +690,12 @@ public void command(ChatRoomIrcImpl chatroom, String command) int endOfNick = command.indexOf(' '); if (endOfNick == -1) { - throw new IllegalArgumentException("Invalid private message format. Message was not sent."); + throw new IllegalArgumentException( + "Invalid private message format. " + + "Message was not sent."); } - target = command.substring(0, endOfNick); - command = command.substring(endOfNick+1); + target = command.substring(0, endOfNick); + command = command.substring(endOfNick + 1); } else { @@ -703,12 +729,12 @@ private static ChatRoomMemberRole convertMemberMode(char modeSymbol) } /** - * A listener for server-level messages (any messages that are related to the - * server, the connection, that are not related to any chatroom in + * A listener for server-level messages (any messages that are related to + * the server, the connection, that are not related to any chatroom in * particular) or that are personal message from user to local user. */ private class ServerListener - extends VariousMessageListenerAdapter + extends VariousMessageListenerAdapter { /** * Print out server notices for debugging purposes and for simply @@ -744,10 +770,9 @@ public void onServerNumericMessage(ServerNumericMessage msg) @Override public void onError(ErrorMessage msg) { - LOGGER.debug("ERROR: " + msg.getSource() + ": " - + msg.getText()); + LOGGER.debug("ERROR: " + msg.getSource() + ": " + msg.getText()); } - + /** * Upon receiving a private message from a user, deliver that to a * private chat room and create one if it does not exist. We can ignore @@ -780,8 +805,8 @@ public void onUserPrivMessage(UserPrivMsg msg) * @param user the source user * @param text the message */ - private void deliverReceivedMessageToPrivateChat(ChatRoomIrcImpl chatroom, - String user, String text) + private void deliverReceivedMessageToPrivateChat( + ChatRoomIrcImpl chatroom, String user, String text) { ChatRoomMember member = chatroom.getChatRoomMember(user); MessageIrcImpl message = @@ -813,7 +838,7 @@ private ChatRoomIrcImpl initiatePrivateChatRoom(String user) return chatroom; } } - + /** * A chat room listener. * @@ -924,9 +949,10 @@ public void onChannelPart(ChanPartMessage msg) } catch (NullPointerException e) { - System.err - .println("This should not have happened. Please report this as it is a bug."); - e.printStackTrace(); + LOGGER + .warn( + "This should not have happened. Please report this as it is a bug.", + e); } } } @@ -959,8 +985,7 @@ public void onChannelKick(ChannelKick msg) { ChatRoomMember kicker = this.chatroom.getChatRoomMember(user); - this.chatroom.fireMemberPresenceEvent(kickedMember, - kicker, + this.chatroom.fireMemberPresenceEvent(kickedMember, kicker, ChatRoomMemberPresenceChangeEvent.MEMBER_KICKED, msg.getText()); } @@ -1214,9 +1239,9 @@ sourceMember, new Date(), ChatRoomMessageReceivedEvent.SYSTEM_MESSAGE_RECEIVED); break; case UNKNOWN: - LOGGER.info("Unknown mode: " - + (mode.isAdded() ? "+" : "-") + mode.getParams()[0] - + ". Original mode string: '" + msg.getModeStr() + "'"); + LOGGER.info("Unknown mode: " + (mode.isAdded() ? "+" : "-") + + mode.getParams()[0] + ". Original mode string: '" + + msg.getModeStr() + "'"); break; default: LOGGER.info("Unsupported mode '" @@ -1395,16 +1420,43 @@ private static class ServerParameters implements IServerParameters { + /** + * Nick name. + */ private String nick; + /** + * Alternative nick names. + */ private List alternativeNicks = new ArrayList(); + /** + * Real name. + */ private String real; + /** + * Ident. + */ private String ident; + /** + * IRC server. + */ private IRCServer server; + + /** + * Custom SSL Context. + */ + private SSLContext sslContext = null; + /** + * Construct ServerParameters instance. + * @param nickName nick name + * @param realName real name + * @param ident ident + * @param server IRC server instance + */ private ServerParameters(String nickName, String realName, String ident, IRCServer server) { @@ -1415,54 +1467,128 @@ private ServerParameters(String nickName, String realName, this.server = server; } + /** + * Get nick name. + * + * @return returns nick name + */ @Override public String getNickname() { return this.nick; } + /** + * Set new nick name. + * + * @param nick nick name + */ public void setNickname(String nick) { this.nick = checkNick(nick); } - + + /** + * Verify nick name. + * + * @param nick nick name + * @return returns nick name + * @throws IllegalArgumentException throws + * IllegalArgumentException if an invalid nick name + * is provided. + */ private String checkNick(String nick) { if (nick == null) - throw new IllegalArgumentException("a nick name must be provided"); - if (nick.startsWith("#")) - throw new IllegalArgumentException("the nick name must not start with '#' since this is reserved for IRC channels"); + throw new IllegalArgumentException( + "a nick name must be provided"); + if (nick.startsWith("#")) + throw new IllegalArgumentException( + "the nick name must not start with '#' " + + "since this is reserved for IRC channels"); return nick; } + /** + * Get alternative nick names. + * + * @return returns list of alternatives + */ @Override public List getAlternativeNicknames() { return this.alternativeNicks; } + /** + * Get ident string. + * + * @return returns ident + */ @Override public String getIdent() { return this.ident; } + /** + * Get real name + * + * @return returns real name + */ @Override public String getRealname() { return this.real; } + /** + * Get server + * + * @return returns server instance + */ @Override public IRCServer getServer() { return this.server; } + /** + * Set server instance. + * + * @param server IRC server instance + */ public void setServer(IRCServer server) { + if (server == null) + throw new IllegalArgumentException("server cannot be null"); + this.server = server; } + + /** + * Get the SSL Context. + * + * Returns the custom SSLContext or null in case there is no + * custom implementation. + * + * @return returns the SSLContext or null + */ + @Override + public SSLContext getCustomContext() + { + return this.sslContext; + } + + /** + * Set custom SSLContext. + * + * @param context the custom SSLContext + */ + public void setCustomContext(SSLContext context) + { + this.sslContext = context; + } } /** diff --git a/src/net/java/sip/communicator/impl/protocol/irc/ProtocolProviderFactoryIrcImpl.java b/src/net/java/sip/communicator/impl/protocol/irc/ProtocolProviderFactoryIrcImpl.java index fafe1394e..b0b9393c3 100644 --- a/src/net/java/sip/communicator/impl/protocol/irc/ProtocolProviderFactoryIrcImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/irc/ProtocolProviderFactoryIrcImpl.java @@ -24,7 +24,7 @@ public class ProtocolProviderFactoryIrcImpl { public ProtocolProviderFactoryIrcImpl() { - super(IrcActivator.bundleContext, ProtocolNames.IRC); + super(IrcActivator.getBundleContext(), ProtocolNames.IRC); } /** @@ -42,7 +42,7 @@ public ProtocolProviderFactoryIrcImpl() public AccountID installAccount( String userIDStr, Map accountProperties) { - BundleContext context = IrcActivator.bundleContext; + BundleContext context = IrcActivator.getBundleContext(); if (context == null) throw new NullPointerException( diff --git a/src/net/java/sip/communicator/impl/protocol/irc/ProtocolProviderServiceIrcImpl.java b/src/net/java/sip/communicator/impl/protocol/irc/ProtocolProviderServiceIrcImpl.java index b3e4d7fda..5524419e3 100644 --- a/src/net/java/sip/communicator/impl/protocol/irc/ProtocolProviderServiceIrcImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/irc/ProtocolProviderServiceIrcImpl.java @@ -6,6 +6,7 @@ */ package net.java.sip.communicator.impl.protocol.irc; +import net.java.sip.communicator.service.certificate.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.service.protocol.event.*; import net.java.sip.communicator.util.*; @@ -25,7 +26,7 @@ public class ProtocolProviderServiceIrcImpl /** * The irc server. */ - private IrcStack ircStack; + private IrcStack ircStack = null; /** * The id of the account that this protocol provider represents. @@ -150,6 +151,7 @@ public RegistrationState getRegistrationState() { return currentRegistrationState; } + /** * Starts the registration process. 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 391100899..bf48200b9 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 @@ -9,6 +9,7 @@ Import-Package: org.osgi.framework, org.jitsi.service.resources, net.java.sip.communicator.service.resources, net.java.sip.communicator.util, + net.java.sip.communicator.service.certificate, net.java.sip.communicator.service.protocol, net.java.sip.communicator.service.protocol.event, org.slf4j,