Author: norman Date: Fri Jan 6 17:42:12 2012 New Revision: 1228299 URL: http://svn.apache.org/viewvc?rev=1228299&view=rev Log: Make sure we correctly handle non existing message numbers. Also adding more test cases for this.
Added: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/MessageMetaDataUtils.java Modified: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/DeleCmdHandler.java james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/ListCmdHandler.java james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/RetrCmdHandler.java james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/TopCmdHandler.java james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UidlCmdHandler.java james/protocols/trunk/pop3/src/test/java/org/apache/james/protocols/pop3/POP3ServerTest.java Modified: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/DeleCmdHandler.java URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/DeleCmdHandler.java?rev=1228299&r1=1228298&r2=1228299&view=diff ============================================================================== --- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/DeleCmdHandler.java (original) +++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/DeleCmdHandler.java Fri Jan 6 17:42:12 2012 @@ -55,10 +55,14 @@ public class DeleCmdHandler implements C return SYNTAX_ERROR; } try { - List<MessageMetaData> uidList = (List<MessageMetaData>) session.getAttachment(POP3Session.UID_LIST, State.Transaction); + MessageMetaData meta = MessageMetaDataUtils.getMetaData(session, num); + if (meta == null) { + StringBuilder responseBuffer = new StringBuilder(64).append("Message (").append(num).append(") does not exist."); + return new POP3Response(POP3Response.ERR_RESPONSE, responseBuffer.toString()); + } List<Long> deletedUidList = (List<Long>) session.getAttachment(POP3Session.DELETED_UID_LIST, State.Transaction); - Long uid = uidList.get(num - 1).getUid(); + Long uid = meta.getUid(); if (deletedUidList.contains(uid)) { StringBuilder responseBuffer = new StringBuilder(64).append("Message (").append(num).append(") already deleted."); Modified: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/ListCmdHandler.java URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/ListCmdHandler.java?rev=1228299&r1=1228298&r2=1228299&view=diff ============================================================================== --- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/ListCmdHandler.java (original) +++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/ListCmdHandler.java Fri Jan 6 17:42:12 2012 @@ -87,7 +87,13 @@ public class ListCmdHandler implements C int num = 0; try { num = Integer.parseInt(parameters); - MessageMetaData data = uidList.get(num - 1); + + MessageMetaData data = MessageMetaDataUtils.getMetaData(session, num); + if (data == null) { + StringBuilder responseBuffer = new StringBuilder(64).append("Message (").append(num).append(") does not exist."); + return new POP3Response(POP3Response.ERR_RESPONSE, responseBuffer.toString()); + } + if (deletedUidList.contains(data.getUid()) == false) { StringBuilder responseBuffer = new StringBuilder(64).append(num).append(" ").append(data.getSize()); Added: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/MessageMetaDataUtils.java URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/MessageMetaDataUtils.java?rev=1228299&view=auto ============================================================================== --- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/MessageMetaDataUtils.java (added) +++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/MessageMetaDataUtils.java Fri Jan 6 17:42:12 2012 @@ -0,0 +1,47 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.protocols.pop3.core; + +import java.util.List; + +import org.apache.james.protocols.api.ProtocolSession.State; +import org.apache.james.protocols.pop3.POP3Session; +import org.apache.james.protocols.pop3.mailbox.MessageMetaData; + +public class MessageMetaDataUtils { + + /** + * Returns the {@link MessageMetaData} for the given message number or <code>null</code> if it can not be + * found. + * + * @param session + * @param number + * @return data + */ + public static MessageMetaData getMetaData(POP3Session session, int number) { + @SuppressWarnings("unchecked") + List<MessageMetaData> uidList = (List<MessageMetaData>) session.getAttachment(POP3Session.UID_LIST, State.Transaction); + if (uidList == null || number > uidList.size()) { + return null; + } else { + return uidList.get(number -1); + } + } +} Modified: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/RetrCmdHandler.java URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/RetrCmdHandler.java?rev=1228299&r1=1228298&r2=1228299&view=diff ============================================================================== --- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/RetrCmdHandler.java (original) +++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/RetrCmdHandler.java Fri Jan 6 17:42:12 2012 @@ -60,10 +60,16 @@ public class RetrCmdHandler implements C return SYNTAX_ERROR; } try { - List<MessageMetaData> uidList = (List<MessageMetaData>) session.getAttachment(POP3Session.UID_LIST, State.Transaction); + MessageMetaData data = MessageMetaDataUtils.getMetaData(session, num); + + if (data == null) { + StringBuilder responseBuffer = new StringBuilder(64).append("Message (").append(num).append(") does not exist."); + response = new POP3Response(POP3Response.ERR_RESPONSE, responseBuffer.toString()); + return response; + } List<Long> deletedUidList = (List<Long>) session.getAttachment(POP3Session.DELETED_UID_LIST, State.Transaction); - Long uid = uidList.get(num - 1).getUid(); + Long uid = data.getUid(); if (deletedUidList.contains(uid) == false) { InputStream content = session.getUserMailbox().getMessage(uid); Modified: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/TopCmdHandler.java URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/TopCmdHandler.java?rev=1228299&r1=1228298&r2=1228299&view=diff ============================================================================== --- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/TopCmdHandler.java (original) +++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/TopCmdHandler.java Fri Jan 6 17:42:12 2012 @@ -79,10 +79,16 @@ public class TopCmdHandler extends RetrC return SYNTAX_ERROR; } try { - List<MessageMetaData> uidList = (List<MessageMetaData>) session.getAttachment(POP3Session.UID_LIST, State.Transaction); + + MessageMetaData data = MessageMetaDataUtils.getMetaData(session, num); + if (data == null) { + StringBuilder responseBuffer = new StringBuilder(64).append("Message (").append(num).append(") does not exist."); + return new POP3Response(POP3Response.ERR_RESPONSE, responseBuffer.toString()); + } + List<Long> deletedUidList = (List<Long>) session.getAttachment(POP3Session.DELETED_UID_LIST, State.Transaction); - Long uid = uidList.get(num - 1).getUid(); + Long uid = data.getUid(); if (deletedUidList.contains(uid) == false) { InputStream body = new CountingBodyInputStream(new ExtraDotInputStream(new CRLFTerminatedInputStream(session.getUserMailbox().getMessageBody(uid))), lines); Modified: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UidlCmdHandler.java URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UidlCmdHandler.java?rev=1228299&r1=1228298&r2=1228299&view=diff ============================================================================== --- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UidlCmdHandler.java (original) +++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UidlCmdHandler.java Fri Jan 6 17:42:12 2012 @@ -70,7 +70,14 @@ public class UidlCmdHandler implements C int num = 0; try { num = Integer.parseInt(parameters); - Long uid = uidList.get(num - 1).getUid(); + + MessageMetaData data = MessageMetaDataUtils.getMetaData(session, num); + if (data == null) { + StringBuilder responseBuffer = new StringBuilder(64).append("Message (").append(num).append(") does not exist."); + return new POP3Response(POP3Response.ERR_RESPONSE, responseBuffer.toString()); + } + long uid = data.getUid(); + if (deletedUidList.contains(uid) == false) { // construct unique UIDL. See JAMES-1264 StringBuilder responseBuffer = new StringBuilder(64).append(num).append(" ").append(identifier).append("-").append(uid); Modified: james/protocols/trunk/pop3/src/test/java/org/apache/james/protocols/pop3/POP3ServerTest.java URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/test/java/org/apache/james/protocols/pop3/POP3ServerTest.java?rev=1228299&r1=1228298&r2=1228299&view=diff ============================================================================== --- james/protocols/trunk/pop3/src/test/java/org/apache/james/protocols/pop3/POP3ServerTest.java (original) +++ james/protocols/trunk/pop3/src/test/java/org/apache/james/protocols/pop3/POP3ServerTest.java Fri Jan 6 17:42:12 2012 @@ -20,11 +20,15 @@ package org.apache.james.protocols.pop3; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.io.Reader; import java.io.SequenceInputStream; import java.net.InetSocketAddress; import java.util.ArrayList; @@ -45,6 +49,9 @@ import org.junit.Test; public class POP3ServerTest { + private static final Message MESSAGE1 = new Message("Subject: test\r\nX-Header: value\r\n", "My Body\r\n"); + private static final Message MESSAGE2 = new Message("Subject: test2\r\nX-Header: value2\r\n", "My Body with a DOT.\r\n.\r\n"); + private POP3Protocol createProtocol(MailboxFactory factory) throws WiringException { return new POP3Protocol(new POP3ProtocolHandlerChain(factory), new POP3Configuration(), new MockLogger()); } @@ -105,6 +112,391 @@ public class POP3ServerTest { } } + + @Test + public void testInboxWithMessages() throws Exception { + InetSocketAddress address = new InetSocketAddress("127.0.0.1", TestUtils.getFreePort()); + + NettyServer server = null; + try { + String identifier = "id"; + MockMailboxFactory factory = new MockMailboxFactory(); + + factory.add("valid", new MockMailbox(identifier, MESSAGE1, MESSAGE2)); + server = new NettyServer(createProtocol(factory)); + server.setListenAddresses(address); + server.bind(); + + POP3Client client = new POP3Client(); + client.connect(address.getAddress().getHostAddress(), address.getPort()); + + assertTrue(client.login("valid", "valid")); + POP3MessageInfo[] info = client.listMessages(); + assertEquals(2, info.length); + assertEquals((int) MESSAGE1.meta.getSize(), info[0].size); + assertEquals((int) MESSAGE2.meta.getSize(), info[1].size); + assertEquals(1, info[0].number); + assertEquals(2, info[1].number); + + POP3MessageInfo mInfo = client.listMessage(1); + assertEquals((int) MESSAGE1.meta.getSize(), mInfo.size); + assertEquals(1, mInfo.number); + + // try to retrieve message that not exist + mInfo = client.listMessage(10); + assertNull(mInfo); + + info = client.listUniqueIdentifiers(); + assertEquals(2, info.length); + assertEquals(identifier + "-" + MESSAGE1.meta.getUid(), info[0].identifier); + assertEquals(identifier + "-" + MESSAGE2.meta.getUid(), info[1].identifier); + assertEquals(1, info[0].number); + assertEquals(2, info[1].number); + + mInfo = client.listUniqueIdentifier(1); + assertEquals(identifier + "-" + MESSAGE1.meta.getUid(), mInfo.identifier); + assertEquals(1, mInfo.number); + + // try to retrieve message that not exist + mInfo = client.listUniqueIdentifier(10); + assertNull(mInfo); + + assertTrue(client.logout()); + + } finally { + if (server != null) { + server.unbind(); + } + } + + } + + @Test + public void testRetr() throws Exception { + InetSocketAddress address = new InetSocketAddress("127.0.0.1", TestUtils.getFreePort()); + + NettyServer server = null; + try { + String identifier = "id"; + MockMailboxFactory factory = new MockMailboxFactory(); + + factory.add("valid", new MockMailbox(identifier, MESSAGE1, MESSAGE2)); + server = new NettyServer(createProtocol(factory)); + server.setListenAddresses(address); + server.bind(); + + POP3Client client = new POP3Client(); + client.connect(address.getAddress().getHostAddress(), address.getPort()); + + assertTrue(client.login("valid", "valid")); + Reader reader = client.retrieveMessage(1); + assertNotNull(reader); + checkMessage(MESSAGE1, reader); + reader.close(); + + // does not exist + reader = client.retrieveMessage(10); + assertNull(reader); + + + // delete and check for the message again, should now be deleted + assertTrue(client.deleteMessage(1)); + reader = client.retrieveMessage(1); + assertNull(reader); + + + assertTrue(client.logout()); + + } finally { + if (server != null) { + server.unbind(); + } + } + + } + + @Test + public void testTop() throws Exception { + InetSocketAddress address = new InetSocketAddress("127.0.0.1", TestUtils.getFreePort()); + + NettyServer server = null; + try { + String identifier = "id"; + MockMailboxFactory factory = new MockMailboxFactory(); + + factory.add("valid", new MockMailbox(identifier, MESSAGE1, MESSAGE2)); + server = new NettyServer(createProtocol(factory)); + server.setListenAddresses(address); + server.bind(); + + POP3Client client = new POP3Client(); + client.connect(address.getAddress().getHostAddress(), address.getPort()); + + assertTrue(client.login("valid", "valid")); + Reader reader = client.retrieveMessageTop(1, 1000); + assertNotNull(reader); + checkMessage(MESSAGE1, reader); + reader.close(); + + reader = client.retrieveMessageTop(2, 1); + assertNotNull(reader); + checkMessage(MESSAGE2, reader,1); + reader.close(); + + // does not exist + reader = client.retrieveMessageTop(10,100); + assertNull(reader); + + // delete and check for the message again, should now be deleted + assertTrue(client.deleteMessage(1)); + reader = client.retrieveMessageTop(1, 1000); + assertNull(reader); + + assertTrue(client.logout()); + + } finally { + if (server != null) { + server.unbind(); + } + } + + } + + @Test + public void testDele() throws Exception { + InetSocketAddress address = new InetSocketAddress("127.0.0.1", TestUtils.getFreePort()); + + NettyServer server = null; + try { + String identifier = "id"; + MockMailboxFactory factory = new MockMailboxFactory(); + + factory.add("valid", new MockMailbox(identifier, MESSAGE1, MESSAGE2)); + server = new NettyServer(createProtocol(factory)); + server.setListenAddresses(address); + server.bind(); + + POP3Client client = new POP3Client(); + client.connect(address.getAddress().getHostAddress(), address.getPort()); + + assertTrue(client.login("valid", "valid")); + POP3MessageInfo[] info = client.listMessages(); + assertEquals(2, info.length); + + assertTrue(client.deleteMessage(1)); + info = client.listMessages(); + assertEquals(1, info.length); + + + assertFalse(client.deleteMessage(1)); + info = client.listMessages(); + assertEquals(1, info.length); + + + assertTrue(client.deleteMessage(2)); + info = client.listMessages(); + assertEquals(0, info.length); + + // logout so the messages get expunged + assertTrue(client.logout()); + + client.connect(address.getAddress().getHostAddress(), address.getPort()); + + assertTrue(client.login("valid", "valid")); + info = client.listMessages(); + assertEquals(0, info.length); + + assertTrue(client.logout()); + + } finally { + if (server != null) { + server.unbind(); + } + } + + } + + @Test + public void testNoop() throws Exception { + InetSocketAddress address = new InetSocketAddress("127.0.0.1", TestUtils.getFreePort()); + + NettyServer server = null; + try { + String identifier = "id"; + MockMailboxFactory factory = new MockMailboxFactory(); + + factory.add("valid", new MockMailbox(identifier)); + server = new NettyServer(createProtocol(factory)); + server.setListenAddresses(address); + server.bind(); + + POP3Client client = new POP3Client(); + client.connect(address.getAddress().getHostAddress(), address.getPort()); + + assertTrue(client.login("valid", "valid")); + assertTrue(client.noop()); + assertTrue(client.logout()); + + } finally { + if (server != null) { + server.unbind(); + } + } + + } + + @Test + public void testRset() throws Exception { + InetSocketAddress address = new InetSocketAddress("127.0.0.1", TestUtils.getFreePort()); + + NettyServer server = null; + try { + String identifier = "id"; + MockMailboxFactory factory = new MockMailboxFactory(); + + factory.add("valid", new MockMailbox(identifier, MESSAGE1)); + server = new NettyServer(createProtocol(factory)); + server.setListenAddresses(address); + server.bind(); + + POP3Client client = new POP3Client(); + client.connect(address.getAddress().getHostAddress(), address.getPort()); + + assertTrue(client.login("valid", "valid")); + assertEquals(1, client.listMessages().length); + assertTrue(client.deleteMessage(1)); + assertEquals(0, client.listMessages().length); + + // call RSET. After this the deleted mark should be removed again + assertTrue(client.reset()); + assertEquals(1, client.listMessages().length); + + assertTrue(client.logout()); + + } finally { + if (server != null) { + server.unbind(); + } + } + + } + + @Test + public void testStat() throws Exception { + InetSocketAddress address = new InetSocketAddress("127.0.0.1", TestUtils.getFreePort()); + + NettyServer server = null; + try { + String identifier = "id"; + MockMailboxFactory factory = new MockMailboxFactory(); + + factory.add("valid", new MockMailbox(identifier, MESSAGE1, MESSAGE2)); + server = new NettyServer(createProtocol(factory)); + server.setListenAddresses(address); + server.bind(); + + POP3Client client = new POP3Client(); + client.connect(address.getAddress().getHostAddress(), address.getPort()); + + assertTrue(client.login("valid", "valid")); + POP3MessageInfo info = client.status(); + assertEquals((int)(MESSAGE1.meta.getSize() + MESSAGE2.meta.getSize()), info.size); + assertEquals(2, info.number); + + assertTrue(client.logout()); + + } finally { + if (server != null) { + server.unbind(); + } + } + + } + @Test + public void testDifferentStates() throws Exception { + InetSocketAddress address = new InetSocketAddress("127.0.0.1", TestUtils.getFreePort()); + + NettyServer server = null; + try { + String identifier = "id"; + MockMailboxFactory factory = new MockMailboxFactory(); + + factory.add("valid", new MockMailbox(identifier, MESSAGE1, MESSAGE2)); + server = new NettyServer(createProtocol(factory)); + server.setListenAddresses(address); + server.bind(); + + POP3Client client = new POP3Client(); + + client.connect(address.getAddress().getHostAddress(), address.getPort()); + assertNull(client.listMessages()); + assertNull(client.listUniqueIdentifiers()); + assertFalse(client.deleteMessage(1)); + assertNull(client.retrieveMessage(1)); + assertNull(client.retrieveMessageTop(1, 10)); + assertNull(client.status()); + assertFalse(client.reset()); + client.logout(); + + client.connect(address.getAddress().getHostAddress(), address.getPort()); + + assertTrue(client.login("valid", "valid")); + assertNotNull(client.listMessages()); + assertNotNull(client.listUniqueIdentifiers()); + Reader reader = client.retrieveMessage(1); + assertNotNull(reader); + reader.close(); + assertNotNull(client.status()); + reader = client.retrieveMessageTop(1, 1); + assertNotNull(reader); + reader.close(); + assertTrue(client.deleteMessage(1)); + assertTrue(client.reset()); + + assertTrue(client.logout()); + + } finally { + if (server != null) { + server.unbind(); + } + } + + } + private void checkMessage(Message message, Reader reader) throws IOException { + int read = 0; + int i = -1; + String content = message.toString(); + while ((i = reader.read()) != -1) { + assertEquals(content.charAt(read++), (char)i); + } + assertEquals(content.length(), read); + } + + private void checkMessage(Message message, Reader reader, int lines) throws IOException { + int read = 0; + String headers = message.headers + "\r\n"; + + while (read < headers.length()) { + assertEquals(headers.charAt(read++), reader.read()); + } + assertEquals(headers.length(), read); + + BufferedReader bufReader = new BufferedReader(reader); + String line = null; + int linesRead = 0; + String parts[] = message.body.split("\r\n"); + while ((line = bufReader.readLine()) != null) { + assertEquals(parts[linesRead++], line); + + if (linesRead == lines) { + break; + } + } + + assertEquals(lines, linesRead); + + } + private final class MockMailboxFactory implements MailboxFactory { private final Map<String, Mailbox> mailboxes = new HashMap<String, Mailbox>(); @@ -193,5 +585,9 @@ public class POP3ServerTest { this.meta = new MessageMetaData(UIDS.incrementAndGet(), headers.length() + body.length() + 2); } + public String toString() { + return headers + "\r\n" + body; + } + } } --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org