String ctcpCommand = messageWords[0];
if (ctcpCommand.equalsIgnoreCase("DCC")) {
if (messageWords[1].equalsIgnoreCase("SEND")) {
- Optional<InetAddress> inetAddress = parseInetAddress(messageWords[3]);
- Optional<Integer> port = fromNullable(Ints.tryParse(messageWords[4]));
- long fileSize = fromNullable(Longs.tryParse(messageWords[5])).or(-1L);
- if (inetAddress.isPresent() && port.isPresent()) {
- eventBus.post(new DccSendReceived(connection, client, messageWords[2], inetAddress.get(), port.get(), fileSize));
- } else {
- logger.warn(format("Received malformed DCC SEND: “%s”", message));
- }
+ processDccSend(client, message, messageWords);
} else if (messageWords[1].equalsIgnoreCase("ACCEPT")) {
- Optional<Integer> port = fromNullable(Ints.tryParse(messageWords[3]));
- long position = (messageWords.length > 4) ? fromNullable(Longs.tryParse(messageWords[4])).or(-1L) : -1;
- if (port.isPresent()) {
- eventBus.post(new DccAcceptReceived(connection, client, messageWords[2], port.get(), position));
- } else {
- logger.warn(format("Received malformed DCC ACCEPT: “%s”", message));
- }
+ processDccAccept(client, message, messageWords);
}
}
}
+ private void processDccSend(Source client, String message,
+ String[] messageWords) {
+ Optional<DccSendInformation> dccSendInformation = parseDccSendInformation(messageWords);
+ if (dccSendInformation.isPresent()) {
+ eventBus.post(new DccSendReceived(connection, client,
+ dccSendInformation.get().filename,
+ dccSendInformation.get().internetAddress,
+ dccSendInformation.get().port,
+ dccSendInformation.get().size));
+ } else {
+ logger.warn(format("Received malformed DCC SEND: “%s”", message));
+ }
+ }
+
+ private Optional<DccSendInformation> parseDccSendInformation(String[] messageWords) {
+ if (messageWords.length <5) {
+ return absent();
+ }
+ Optional<InetAddress> internetAddress = parseInetAddress(messageWords[3]);
+ Optional<Integer> port = fromNullable(Ints.tryParse(messageWords[4]));
+ long fileSize = (messageWords.length > 5) ? fromNullable(Longs.tryParse(messageWords[5])).or(-1L) : -1;
+ if (!internetAddress.isPresent() || !port.isPresent()) {
+ return absent();
+ }
+ return of(new DccSendInformation(messageWords[2], internetAddress.get(), port.get(), fileSize));
+ }
+
+ private static class DccSendInformation {
+
+ private final String filename;
+ private final InetAddress internetAddress;
+ private final int port;
+ private final long size;
+
+ private DccSendInformation(String filename,
+ InetAddress internetAddress, int port, long size) {
+ this.filename = filename;
+ this.internetAddress = internetAddress;
+ this.port = port;
+ this.size = size;
+ }
+
+ }
+
private Optional<InetAddress> parseInetAddress(String ip) {
Long ipNumber = Longs.tryParse(ip);
if (ipNumber == null) {
}
}
+ private void processDccAccept(Source client, String message,
+ String[] messageWords) {
+ Optional<DccAcceptInformation> dccAcceptInformation = parseDccAcceptInformation(messageWords);
+ if (dccAcceptInformation.isPresent()) {
+ eventBus.post(new DccAcceptReceived(connection, client,
+ dccAcceptInformation.get().filename,
+ dccAcceptInformation.get().port,
+ dccAcceptInformation.get().position));
+ } else {
+ logger.warn(format("Received malformed DCC ACCEPT: “%s”", message));
+ }
+ }
+
+ private Optional<DccAcceptInformation> parseDccAcceptInformation(
+ String[] messageWords) {
+ if (messageWords.length < 4) {
+ return absent();
+ }
+ Optional<Integer> port = fromNullable(Ints.tryParse(messageWords[3]));
+ long position = (messageWords.length > 4) ? fromNullable(
+ Longs.tryParse(messageWords[4])).or(-1L) : -1;
+ if (!port.isPresent()) {
+ return absent();
+ }
+ return of(new DccAcceptInformation(messageWords[2], port.get(), position));
+ }
+
+ private static class DccAcceptInformation {
+
+ private final String filename;
+ private final int port;
+ private final long position;
+
+ private DccAcceptInformation(String filename, int port, long position) {
+ this.filename = filename;
+ this.port = port;
+ this.position = position;
+ }
+
+ }
+
}
--- /dev/null
+package net.pterodactylus.irc.connection;
+
+import static net.pterodactylus.irc.Source.parseSource;
+import static net.pterodactylus.irc.connection.Replies.createReply;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.mockito.ArgumentCaptor.forClass;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import net.pterodactylus.irc.Connection;
+import net.pterodactylus.irc.event.DccAcceptReceived;
+import net.pterodactylus.irc.event.DccSendReceived;
+
+import com.google.common.eventbus.EventBus;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+/**
+ * Unit test for {@link CtcpHandler}.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class CtcpHandlerTest {
+
+ private final EventBus eventBus = mock(EventBus.class);
+ private final Connection connection = mock(Connection.class);
+ private final CtcpHandler handler = new CtcpHandler(eventBus, connection);
+
+ @Test
+ public void handlerWillHandleCtcpMessagesSentAsNotice() {
+ assertThat(handler.willHandle(createReply("NOTICE", "\u0001ACTION\u0001")), is(true));
+ }
+
+ @Test
+ public void handlerWillHandleCtcpMessagesSentAsPrivmsg() {
+ assertThat(handler.willHandle(createReply("PRIVMSG", "\u0001ACTION\u0001")), is(true));
+ }
+
+ @Test
+ public void handlerWillNotHandleNormalMessages() {
+ assertThat(handler.willHandle(createReply("NOTICE", "ACTION")), is(false));
+ }
+
+ @Test
+ public void handlerWillNotHandleMalformedMessages() {
+ assertThat(handler.willHandle(createReply("NOTICE", "\u0001ACTION")), is(false));
+ }
+
+ @Test
+ public void dccSendCommandAsNoticeIsRecognizedCorrectly() {
+ dccSendCommandIsRecognizedCorrectly("NOTICE", "23456", 23456L);
+ }
+
+ private void dccSendCommandIsRecognizedCorrectly(String command,
+ Object sizeAsString, long expectedSize) {
+ handler.handleReply(createReply(parseSource("User!user@host"),
+ command,
+ "\u0001DCC SEND test.dat 2130706433 12345 " + sizeAsString + "\u0001"));
+ ArgumentCaptor<DccSendReceived> eventCaptor = forClass(
+ DccSendReceived.class);
+ verify(eventBus).post(eventCaptor.capture());
+ DccSendReceived dccSendReceived = eventCaptor.getValue();
+ assertThat(dccSendReceived.connection(), is(connection));
+ assertThat(dccSendReceived.filename(), is("test.dat"));
+ assertThat(dccSendReceived.inetAddress().getHostAddress(),
+ is("127.0.0.1"));
+ assertThat(dccSendReceived.port(), is(12345));
+ assertThat(dccSendReceived.filesize(), is(expectedSize));
+ assertThat(dccSendReceived.source().nick().get(), is("User"));
+ }
+
+ @Test
+ public void dccSendCommandAsPrivmsgIsRecognizedCorrectly() {
+ dccSendCommandIsRecognizedCorrectly("PRIVMSG", "23456", 23456L);
+ }
+
+ @Test
+ public void nonDccCommandDoesNotCauseEvent() {
+ handler.handleReply(createReply(parseSource("User!user@host"),
+ "NOTICE",
+ "\u0001FOO SEND test.dat 2130706433 12345 23456\u0001"));
+ verify(eventBus, never()).post(anyObject());
+ }
+
+ @Test
+ public void nonSendDccCommandDoesNotCauseEvent() {
+ handler.handleReply(createReply(parseSource("User!user@host"),
+ "NOTICE",
+ "\u0001DCC FOO test.dat 2130706433 12345 23456\u0001"));
+ verify(eventBus, never()).post(anyObject());
+ }
+
+ @Test
+ public void dccCommandWithoutPortNumberDoesNotCauseEvent() {
+ handler.handleReply(createReply(parseSource("User!user@host"),
+ "NOTICE",
+ "\u0001DCC SEND test.dat 2130706433\u0001"));
+ verify(eventBus, never()).post(anyObject());
+ }
+
+ @Test
+ public void dccCommandWithInvalidPortNumberDoesNotCauseEvent() {
+ handler.handleReply(createReply(parseSource("User!user@host"),
+ "NOTICE",
+ "\u0001DCC SEND test.dat 2130706433 abc\u0001"));
+ verify(eventBus, never()).post(anyObject());
+ }
+
+ @Test
+ public void dccCommandWithoutIpAddressDoesNotCauseEvent() {
+ handler.handleReply(createReply(parseSource("User!user@host"),
+ "NOTICE",
+ "\u0001DCC SEND test.dat\u0001"));
+ verify(eventBus, never()).post(anyObject());
+ }
+
+ @Test
+ public void dccCommandWithInvalidIpAddressDoesNotCauseEvent() {
+ handler.handleReply(createReply(parseSource("User!user@host"),
+ "NOTICE",
+ "\u0001DCC SEND test.dat abc abc\u0001"));
+ verify(eventBus, never()).post(anyObject());
+ }
+
+ @Test
+ public void dccCommandWithoutLengthIsRecognizedCorrectly() {
+ dccSendCommandIsRecognizedCorrectly("PRIVMSG", "", -1);
+ }
+
+ @Test
+ public void dccAcceptCommandIsRecognized() {
+ handler.handleReply(createReply(parseSource("User!user@host"),
+ "NOTICE",
+ "\u0001DCC ACCEPT test.dat 12345 23456\u0001"));
+ ArgumentCaptor<DccAcceptReceived> eventCaptor = forClass(
+ DccAcceptReceived.class);
+ verify(eventBus).post(eventCaptor.capture());
+ DccAcceptReceived dccAcceptReceived = eventCaptor.getValue();
+ assertThat(dccAcceptReceived.connection(), is(connection));
+ assertThat(dccAcceptReceived.filename(), is("test.dat"));
+ assertThat(dccAcceptReceived.port(), is(12345));
+ assertThat(dccAcceptReceived.position(), is(23456L));
+ assertThat(dccAcceptReceived.source().nick().get(), is("User"));
+ }
+
+ @Test
+ public void dccAcceptCommandWithoutParametersDoesNotCauseEvent() {
+ handler.handleReply(createReply(parseSource("User!user@host"),
+ "NOTICE",
+ "\u0001DCC ACCEPT\u0001"));
+ verify(eventBus,never()).post(anyObject());
+ }
+
+ @Test
+ public void dccAcceptCommandWithInvalidPortDoesNotCauseEvent() {
+ handler.handleReply(createReply(parseSource("User!user@host"),
+ "NOTICE",
+ "\u0001DCC ACCEPT test.dat abc\u0001"));
+ verify(eventBus,never()).post(anyObject());
+ }
+
+ @Test
+ public void dccAcceptCommandWithMissingPositionIsRecognized() {
+ handler.handleReply(createReply(parseSource("User!user@host"),
+ "NOTICE",
+ "\u0001DCC ACCEPT test.dat 12345\u0001"));
+ ArgumentCaptor<DccAcceptReceived> eventCaptor = forClass(
+ DccAcceptReceived.class);
+ verify(eventBus).post(eventCaptor.capture());
+ DccAcceptReceived dccAcceptReceived = eventCaptor.getValue();
+ assertThat(dccAcceptReceived.connection(), is(connection));
+ assertThat(dccAcceptReceived.filename(), is("test.dat"));
+ assertThat(dccAcceptReceived.port(), is(12345));
+ assertThat(dccAcceptReceived.position(), is(-1L));
+ assertThat(dccAcceptReceived.source().nick().get(), is("User"));
+ }
+
+}