Added: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/QuitCmdHandler.java URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/QuitCmdHandler.java?rev=1203562&view=auto ============================================================================== --- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/QuitCmdHandler.java (added) +++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/QuitCmdHandler.java Fri Nov 18 10:00:50 2011 @@ -0,0 +1,99 @@ +/**************************************************************** + * 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.ArrayList; +import java.util.Collection; +import java.util.List; + +import javax.annotation.Resource; +import javax.mail.Flags; + +import org.apache.james.mailbox.MessageManager; +import org.apache.james.mailbox.MailboxManager; +import org.apache.james.mailbox.MailboxSession; +import org.apache.james.mailbox.MessageRange; +import org.apache.james.mailbox.MailboxException; +import org.apache.james.pop3server.POP3Response; +import org.apache.james.pop3server.POP3Session; +import org.apache.james.protocols.api.Request; +import org.apache.james.protocols.api.Response; +import org.apache.james.protocols.api.handler.CommandHandler; + +/** + * Handles QUIT command + */ +public class QuitCmdHandler implements CommandHandler<POP3Session> { + private final static String COMMAND_NAME = "QUIT"; + protected MailboxManager mailboxManager; + + @Resource(name = "mailboxmanager") + public void setMailboxManager(MailboxManager manager) { + this.mailboxManager = manager; + } + + /** + * Handler method called upon receipt of a QUIT command. This method handles + * cleanup of the POP3Handler state. + */ + @SuppressWarnings("unchecked") + public Response onCommand(POP3Session session, Request request) { + POP3Response response = null; + if (session.getHandlerState() == POP3Session.AUTHENTICATION_READY || session.getHandlerState() == POP3Session.AUTHENTICATION_USERSET) { + response = new POP3Response(POP3Response.OK_RESPONSE, "Apache James POP3 Server signing off."); + response.setEndSession(true); + return response; + } + MailboxSession mailboxSession = (MailboxSession) session.getState().get(POP3Session.MAILBOX_SESSION); + + List<Long> toBeRemoved = (List<Long>) session.getState().get(POP3Session.DELETED_UID_LIST); + try { + MessageManager mailbox = session.getUserMailbox(); + + for (int i = 0; i < toBeRemoved.size(); i++) { + MessageRange range = MessageRange.one(toBeRemoved.get(i)); + mailbox.setFlags(new Flags(Flags.Flag.DELETED), true, false, range, mailboxSession); + mailbox.expunge(range, mailboxSession); + } + response = new POP3Response(POP3Response.OK_RESPONSE, "Apache James POP3 Server signing off."); + } catch (Exception ex) { + response = new POP3Response(POP3Response.ERR_RESPONSE, "Some deleted messages were not removed"); + session.getLogger().error("Some deleted messages were not removed", ex); + } + response.setEndSession(true); + try { + mailboxManager.logout(mailboxSession, false); + } catch (MailboxException e) { + // nothing todo on logout + } + + return response; + } + + /** + * @see org.apache.james.protocols.api.handler.CommandHandler#getImplCommands() + */ + public Collection<String> getImplCommands() { + List<String> commands = new ArrayList<String>(); + commands.add(COMMAND_NAME); + return commands; + } + +}
Added: 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=1203562&view=auto ============================================================================== --- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/RetrCmdHandler.java (added) +++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/RetrCmdHandler.java Fri Nov 18 10:00:50 2011 @@ -0,0 +1,134 @@ +/**************************************************************** + * 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.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Set; + +import org.apache.james.mailbox.Content; +import org.apache.james.mailbox.MailboxException; +import org.apache.james.mailbox.MailboxSession; +import org.apache.james.mailbox.MessageRange; +import org.apache.james.mailbox.MessageResult; +import org.apache.james.mailbox.MessageResult.FetchGroup; +import org.apache.james.pop3server.POP3Response; +import org.apache.james.pop3server.POP3Session; +import org.apache.james.pop3server.POP3StreamResponse; +import org.apache.james.protocols.api.Request; +import org.apache.james.protocols.api.Response; +import org.apache.james.protocols.api.handler.CommandHandler; + +/** + * Handles RETR command + */ +public class RetrCmdHandler implements CommandHandler<POP3Session> { + + private final static String COMMAND_NAME = "RETR"; + private final static FetchGroup GROUP = new FetchGroup() { + + @Override + public int content() { + return FULL_CONTENT; + } + + @Override + public Set<PartContentDescriptor> getPartContentDescriptors() { + return null; + } + + }; + /** + * Handler method called upon receipt of a RETR command. This command + * retrieves a particular mail message from the mailbox. + */ + @SuppressWarnings("unchecked") + public Response onCommand(POP3Session session, Request request) { + POP3Response response = null; + String parameters = request.getArgument(); + if (session.getHandlerState() == POP3Session.TRANSACTION) { + int num = 0; + try { + num = Integer.parseInt(parameters.trim()); + } catch (Exception e) { + response = new POP3Response(POP3Response.ERR_RESPONSE, "Usage: RETR [mail number]"); + return response; + } + try { + List<MessageMetaData> uidList = (List<MessageMetaData>) session.getState().get(POP3Session.UID_LIST); + List<Long> deletedUidList = (List<Long>) session.getState().get(POP3Session.DELETED_UID_LIST); + + MailboxSession mailboxSession = (MailboxSession) session.getState().get(POP3Session.MAILBOX_SESSION); + Long uid = uidList.get(num - 1).getUid(); + if (deletedUidList.contains(uid) == false) { + Iterator<MessageResult> results = session.getUserMailbox().getMessages(MessageRange.one(uid), GROUP, mailboxSession); + + if (results.hasNext()) { + MessageResult result = results.next(); + + Content content = result.getFullContent(); + InputStream in = new CRLFTerminatedInputStream(new ExtraDotInputStream(content.getInputStream())); + response = new POP3StreamResponse(POP3Response.OK_RESPONSE, "Message follows", in); + return response; + + + + } else { + StringBuilder responseBuffer = new StringBuilder(64).append("Message (").append(num).append(") does not exist."); + response = new POP3Response(POP3Response.ERR_RESPONSE, responseBuffer.toString()); + } + } else { + + StringBuilder responseBuffer = new StringBuilder(64).append("Message (").append(num).append(") already deleted."); + response = new POP3Response(POP3Response.ERR_RESPONSE, responseBuffer.toString()); + } + } catch (IOException ioe) { + response = new POP3Response(POP3Response.ERR_RESPONSE, "Error while retrieving message."); + } catch (MailboxException me) { + response = new POP3Response(POP3Response.ERR_RESPONSE, "Error while retrieving message."); + } catch (IndexOutOfBoundsException iob) { + StringBuilder responseBuffer = new StringBuilder(64).append("Message (").append(num).append(") does not exist."); + response = new POP3Response(POP3Response.ERR_RESPONSE, responseBuffer.toString()); + } catch (NoSuchElementException e) { + StringBuilder responseBuffer = new StringBuilder(64).append("Message (").append(num).append(") does not exist."); + response = new POP3Response(POP3Response.ERR_RESPONSE, responseBuffer.toString()); + } + } else { + response = new POP3Response(POP3Response.ERR_RESPONSE); + } + return response; + } + + + /** + * @see org.apache.james.protocols.api.handler.CommandHandler#getImplCommands() + */ + public Collection<String> getImplCommands() { + List<String> commands = new ArrayList<String>(); + commands.add(COMMAND_NAME); + return commands; + } + +} Added: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/RsetCmdHandler.java URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/RsetCmdHandler.java?rev=1203562&view=auto ============================================================================== --- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/RsetCmdHandler.java (added) +++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/RsetCmdHandler.java Fri Nov 18 10:00:50 2011 @@ -0,0 +1,110 @@ +/**************************************************************** + * 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.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.apache.james.mailbox.MailboxException; +import org.apache.james.mailbox.MailboxSession; +import org.apache.james.mailbox.MessageRange; +import org.apache.james.mailbox.MessageResult; +import org.apache.james.mailbox.MessageResult.FetchGroup; +import org.apache.james.pop3server.POP3Response; +import org.apache.james.pop3server.POP3Session; +import org.apache.james.protocols.api.Request; +import org.apache.james.protocols.api.Response; +import org.apache.james.protocols.api.handler.CommandHandler; + +/** + * Handles RSET command + */ +public class RsetCmdHandler implements CommandHandler<POP3Session> { + private final static String COMMAND_NAME = "RSET"; + + private final static FetchGroup GROUP = new FetchGroup() { + + @Override + public int content() { + return MINIMAL; + } + + @Override + public Set<PartContentDescriptor> getPartContentDescriptors() { + return null; + } + + }; + + /** + * Handler method called upon receipt of a RSET command. Calls stat() to + * reset the mailbox. + */ + public Response onCommand(POP3Session session, Request request) { + POP3Response response = null; + if (session.getHandlerState() == POP3Session.TRANSACTION) { + stat(session); + response = new POP3Response(POP3Response.OK_RESPONSE); + } else { + response = new POP3Response(POP3Response.ERR_RESPONSE); + } + return response; + } + + /** + * Implements a "stat". If the handler is currently in a transaction state, + * this amounts to a rollback of the mailbox contents to the beginning of + * the transaction. This method is also called when first entering the + * transaction state to initialize the handler copies of the user inbox. + */ + protected void stat(POP3Session session) { + try { + MailboxSession mailboxSession = (MailboxSession) session.getState().get(POP3Session.MAILBOX_SESSION); + + List<MessageMetaData> uids = new ArrayList<MessageMetaData>(); + Iterator<MessageResult> it = session.getUserMailbox().getMessages(MessageRange.all(), GROUP, mailboxSession); + while (it.hasNext()) { + MessageResult result = it.next(); + uids.add(new MessageMetaData(result.getUid(), result.getSize())); + + } + session.getState().put(POP3Session.UID_LIST, uids); + session.getState().put(POP3Session.DELETED_UID_LIST, new ArrayList<Long>()); + } catch (MailboxException e) { + // In the event of an exception being thrown there may or may not be + // anything in userMailbox + session.getLogger().error("Unable to STAT mail box ", e); + } + + } + + /** + * @see org.apache.james.protocols.api.handler.CommandHandler#getImplCommands() + */ + public Collection<String> getImplCommands() { + List<String> commands = new ArrayList<String>(); + commands.add(COMMAND_NAME); + return commands; + } + +} Added: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/StatCmdHandler.java URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/StatCmdHandler.java?rev=1203562&view=auto ============================================================================== --- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/StatCmdHandler.java (added) +++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/StatCmdHandler.java Fri Nov 18 10:00:50 2011 @@ -0,0 +1,80 @@ +/**************************************************************** + * 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.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.apache.james.pop3server.POP3Response; +import org.apache.james.pop3server.POP3Session; +import org.apache.james.protocols.api.Request; +import org.apache.james.protocols.api.Response; +import org.apache.james.protocols.api.handler.CommandHandler; + +/** + * Handles STAT command + */ +public class StatCmdHandler implements CommandHandler<POP3Session> { + private final static String COMMAND_NAME = "STAT"; + + /** + * Handler method called upon receipt of a STAT command. Returns the number + * of messages in the mailbox and its aggregate size. + */ + @SuppressWarnings("unchecked") + public Response onCommand(POP3Session session, Request request) { + POP3Response response = null; + if (session.getHandlerState() == POP3Session.TRANSACTION) { + + List<MessageMetaData> uidList = (List<MessageMetaData>) session.getState().get(POP3Session.UID_LIST); + List<Long> deletedUidList = (List<Long>) session.getState().get(POP3Session.DELETED_UID_LIST); + long size = 0; + int count = 0; + if (uidList.isEmpty() == false) { + List<MessageMetaData> validResults = new ArrayList<MessageMetaData>(); + for (int i = 0; i < uidList.size(); i++) { + MessageMetaData data = uidList.get(i); + if (deletedUidList.contains(data.getUid()) == false) { + size += data.getSize(); + count++; + validResults.add(data); + } + } + } + StringBuilder responseBuffer = new StringBuilder(32).append(count).append(" ").append(size); + response = new POP3Response(POP3Response.OK_RESPONSE, responseBuffer.toString()); + + } else { + response = new POP3Response(POP3Response.ERR_RESPONSE); + } + return response; + } + + /** + * @see org.apache.james.protocols.api.handler.CommandHandler#getImplCommands() + */ + public Collection<String> getImplCommands() { + List<String> commands = new ArrayList<String>(); + commands.add(COMMAND_NAME); + return commands; + } + +} Added: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/StlsCmdHandler.java URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/StlsCmdHandler.java?rev=1203562&view=auto ============================================================================== --- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/StlsCmdHandler.java (added) +++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/StlsCmdHandler.java Fri Nov 18 10:00:50 2011 @@ -0,0 +1,77 @@ +/**************************************************************** + * 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.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.apache.james.protocols.api.Request; +import org.apache.james.protocols.api.Response; +import org.apache.james.protocols.api.handler.CommandHandler; +import org.apache.james.protocols.pop3.POP3Response; +import org.apache.james.protocols.pop3.POP3Session; +import org.apache.james.protocols.pop3.StartTlsPop3Response; + +/** + * Handler which offer STARTTLS implementation for POP3. STARTTLS is started + * with the STSL command + */ +public class StlsCmdHandler implements CommandHandler<POP3Session>, CapaCapability { + public final static String COMMAND_NAME = "STLS"; + + /** + * @see CommandHandler#onCommand(org.apache.james.protocols.api.ProtocolSession, Request) + */ + public Response onCommand(POP3Session session, Request request) { + POP3Response response; + // check if starttls is supported, the state is the right one and it was + // not started before + if (session.isStartTLSSupported() && session.getHandlerState() == POP3Session.AUTHENTICATION_READY && session.isTLSStarted() == false) { + response = new StartTlsPop3Response(POP3Response.OK_RESPONSE, "Begin TLS negotiation"); + return response; + + } else { + response = new POP3Response(POP3Response.ERR_RESPONSE); + return response; + } + } + + /** + * @see org.apache.james.pop3server.core.CapaCapability#getImplementedCapabilities(org.apache.james.pop3server.POP3Session) + */ + public List<String> getImplementedCapabilities(POP3Session session) { + List<String> caps = new ArrayList<String>(); + if (session.isStartTLSSupported() && session.getHandlerState() == POP3Session.AUTHENTICATION_READY) { + caps.add(COMMAND_NAME); + return caps; + } + return caps; + } + + /** + * @see org.apache.james.protocols.api.handler.CommandHandler#getImplCommands() + */ + public Collection<String> getImplCommands() { + List<String> commands = new ArrayList<String>(); + commands.add(COMMAND_NAME); + return commands; + } +} Added: 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=1203562&view=auto ============================================================================== --- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/TopCmdHandler.java (added) +++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/TopCmdHandler.java Fri Nov 18 10:00:50 2011 @@ -0,0 +1,246 @@ +/**************************************************************** + * 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.io.ByteArrayInputStream; +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.SequenceInputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Set; + +import org.apache.james.mailbox.MailboxException; +import org.apache.james.mailbox.MailboxSession; +import org.apache.james.mailbox.MessageRange; +import org.apache.james.mailbox.MessageResult; +import org.apache.james.mailbox.MessageResult.FetchGroup; +import org.apache.james.pop3server.POP3Response; +import org.apache.james.pop3server.POP3Session; +import org.apache.james.pop3server.POP3StreamResponse; +import org.apache.james.protocols.api.Request; +import org.apache.james.protocols.api.Response; + +/** + * Handles TOP command + */ +public class TopCmdHandler extends RetrCmdHandler implements CapaCapability { + private final static String COMMAND_NAME = "TOP"; + private final static FetchGroup GROUP = new FetchGroup() { + + @Override + public int content() { + return BODY_CONTENT | HEADERS; + } + + @Override + public Set<PartContentDescriptor> getPartContentDescriptors() { + return null; + } + + }; + + /** + * Handler method called upon receipt of a TOP command. This command + * retrieves the top N lines of a specified message in the mailbox. + * + * The expected command format is TOP [mail message number] [number of lines + * to return] + */ + @SuppressWarnings("unchecked") + @Override + public Response onCommand(POP3Session session, Request request) { + POP3Response response = null; + String parameters = request.getArgument(); + if (parameters == null) { + response = new POP3Response(POP3Response.ERR_RESPONSE, "Usage: TOP [mail number] [Line number]"); + return response; + } + + String argument = ""; + String argument1 = ""; + int pos = parameters.indexOf(" "); + if (pos > 0) { + argument = parameters.substring(0, pos); + argument1 = parameters.substring(pos + 1); + } + + if (session.getHandlerState() == POP3Session.TRANSACTION) { + int num = 0; + int lines = -1; + try { + num = Integer.parseInt(argument); + lines = Integer.parseInt(argument1); + } catch (NumberFormatException nfe) { + response = new POP3Response(POP3Response.ERR_RESPONSE, "Usage: TOP [mail number] [Line number]"); + return response; + } + try { + List<MessageMetaData> uidList = (List<MessageMetaData>) session.getState().get(POP3Session.UID_LIST); + List<Long> deletedUidList = (List<Long>) session.getState().get(POP3Session.DELETED_UID_LIST); + + MailboxSession mailboxSession = (MailboxSession) session.getState().get(POP3Session.MAILBOX_SESSION); + Long uid = uidList.get(num - 1).getUid(); + if (deletedUidList.contains(uid) == false) { + + Iterator<MessageResult> results = session.getUserMailbox().getMessages(MessageRange.one(uid), GROUP, mailboxSession); + + if (results.hasNext()) { + MessageResult result = results.next(); + + InputStream headersIn = result.getHeaders().getInputStream(); + InputStream bodyIn = new CountingBodyInputStream(new ExtraDotInputStream(new CRLFTerminatedInputStream(result.getBody().getInputStream())), lines); + + // write body + InputStream in = new SequenceInputStream(Collections.enumeration(Arrays.asList(headersIn, new ByteArrayInputStream("\r\n".getBytes()), bodyIn))); + + response = new POP3StreamResponse(POP3Response.OK_RESPONSE, "Message follows", in); + return response; + + } else { + StringBuilder exceptionBuffer = new StringBuilder(64).append("Message (").append(num).append(") does not exist."); + response = new POP3Response(POP3Response.ERR_RESPONSE, exceptionBuffer.toString()); + } + + } else { + StringBuilder responseBuffer = new StringBuilder(64).append("Message (").append(num).append(") already deleted."); + response = new POP3Response(POP3Response.ERR_RESPONSE, responseBuffer.toString()); + } + } catch (IOException ioe) { + response = new POP3Response(POP3Response.ERR_RESPONSE, "Error while retrieving message."); + } catch (MailboxException me) { + response = new POP3Response(POP3Response.ERR_RESPONSE, "Error while retrieving message."); + } catch (IndexOutOfBoundsException iob) { + StringBuilder exceptionBuffer = new StringBuilder(64).append("Message (").append(num).append(") does not exist."); + response = new POP3Response(POP3Response.ERR_RESPONSE, exceptionBuffer.toString()); + } catch (NoSuchElementException iob) { + StringBuilder exceptionBuffer = new StringBuilder(64).append("Message (").append(num).append(") does not exist."); + response = new POP3Response(POP3Response.ERR_RESPONSE, exceptionBuffer.toString()); + } + } else { + response = new POP3Response(POP3Response.ERR_RESPONSE); + } + return response; + + } + + /** + * @see org.apache.james.pop3server.core.CapaCapability#getImplementedCapabilities(org.apache.james.pop3server.POP3Session) + */ + public List<String> getImplementedCapabilities(POP3Session session) { + List<String> caps = new ArrayList<String>(); + if (session.getHandlerState() == POP3Session.TRANSACTION) { + caps.add(COMMAND_NAME); + return caps; + } + return caps; + } + + /** + * @see org.apache.james.protocols.api.handler.CommandHandler#getImplCommands() + */ + public Collection<String> getImplCommands() { + List<String> commands = new ArrayList<String>(); + commands.add(COMMAND_NAME); + return commands; + } + + /** + * This {@link InputStream} implementation can be used to limit the body + * lines which will be read from the wrapped {@link InputStream} + */ + private final class CountingBodyInputStream extends FilterInputStream { + + private int count = 0; + private int limit = -1; + private int lastChar; + + /** + * + * @param in + * InputStream to read from + * @param limit + * the lines to read. -1 is used for no limits + */ + public CountingBodyInputStream(InputStream in, int limit) { + super(in); + this.limit = limit; + } + + @Override + public int read() throws IOException { + if (limit != -1) { + if (count <= limit) { + int a = in.read(); + + if (lastChar == '\r' && a == '\n') { + count++; + } + lastChar = a; + + return a; + } else { + return -1; + } + } else { + return in.read(); + } + + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + if (limit == -1) { + return in.read(b, off, len); + } else { + int i; + for (i = 0; i < len; i++) { + int a = read(); + if (i == 0 && a == -1) { + return -1; + } else { + if (a == -1) { + break; + } else { + b[off++] = (byte) a; + } + } + } + return i; + } + } + + @Override + public int read(byte[] b) throws IOException { + if (limit == -1) { + return in.read(b); + } else { + return read(b, 0, b.length); + } + } + + } +} Added: 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=1203562&view=auto ============================================================================== --- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UidlCmdHandler.java (added) +++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UidlCmdHandler.java Fri Nov 18 10:00:50 2011 @@ -0,0 +1,122 @@ +/**************************************************************** + * 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.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.apache.james.mailbox.MailboxException; +import org.apache.james.mailbox.MailboxSession; +import org.apache.james.mailbox.MessageManager.MetaData; +import org.apache.james.mailbox.MessageManager.MetaData.FetchGroup; +import org.apache.james.pop3server.POP3Response; +import org.apache.james.pop3server.POP3Session; +import org.apache.james.protocols.api.Request; +import org.apache.james.protocols.api.Response; +import org.apache.james.protocols.api.handler.CommandHandler; + +/** + * Handles UIDL command + */ +public class UidlCmdHandler implements CommandHandler<POP3Session>, CapaCapability { + private final static String COMMAND_NAME = "UIDL"; + + /** + * Handler method called upon receipt of a UIDL command. Returns a listing + * of message ids to the client. + */ + @SuppressWarnings("unchecked") + public Response onCommand(POP3Session session, Request request) { + POP3Response response = null; + String parameters = request.getArgument(); + if (session.getHandlerState() == POP3Session.TRANSACTION) { + List<MessageMetaData> uidList = (List<MessageMetaData>) session.getState().get(POP3Session.UID_LIST); + List<Long> deletedUidList = (List<Long>) session.getState().get(POP3Session.DELETED_UID_LIST); + MailboxSession mailboxSession = (MailboxSession) session.getState().get(POP3Session.MAILBOX_SESSION); + try { + MetaData mData = session.getUserMailbox().getMetaData(false, mailboxSession, FetchGroup.NO_COUNT); + long validity = mData.getUidValidity(); + if (parameters == null) { + response = new POP3Response(POP3Response.OK_RESPONSE, "unique-id listing follows"); + for (int i = 0; i < uidList.size(); i++) { + Long uid = uidList.get(i).getUid(); + if (deletedUidList.contains(uid) == false) { + // construct unique UIDL. See JAMES-1264 + StringBuilder responseBuffer = new StringBuilder(64).append(i + 1).append(" ").append(validity).append("-").append(uid); + response.appendLine(responseBuffer.toString()); + } + } + + response.appendLine("."); + } else { + int num = 0; + try { + num = Integer.parseInt(parameters); + Long uid = uidList.get(num - 1).getUid(); + if (deletedUidList.contains(uid) == false) { + // construct unique UIDL. See JAMES-1264 + StringBuilder responseBuffer = new StringBuilder(64).append(num).append(" ").append(validity).append("-").append(uid); + response = new POP3Response(POP3Response.OK_RESPONSE, responseBuffer.toString()); + + } else { + StringBuilder responseBuffer = new StringBuilder(64).append("Message (").append(num).append(") already deleted."); + response = new POP3Response(POP3Response.ERR_RESPONSE, responseBuffer.toString()); + } + } catch (IndexOutOfBoundsException npe) { + StringBuilder responseBuffer = new StringBuilder(64).append("Message (").append(num).append(") does not exist."); + response = new POP3Response(POP3Response.ERR_RESPONSE, responseBuffer.toString()); + } catch (NumberFormatException nfe) { + StringBuilder responseBuffer = new StringBuilder(64).append(parameters).append(" is not a valid number"); + response = new POP3Response(POP3Response.ERR_RESPONSE, responseBuffer.toString()); + } + } + } catch (MailboxException e) { + response = new POP3Response(POP3Response.ERR_RESPONSE); + return response; + } + + } else { + response = new POP3Response(POP3Response.ERR_RESPONSE); + } + return response; + } + + /** + * @see org.apache.james.pop3server.core.CapaCapability#getImplementedCapabilities(org.apache.james.pop3server.POP3Session) + */ + public List<String> getImplementedCapabilities(POP3Session session) { + List<String> caps = new ArrayList<String>(); + if (session.getHandlerState() == POP3Session.TRANSACTION) { + caps.add(COMMAND_NAME); + return caps; + } + return caps; + } + + /** + * @see org.apache.james.protocols.api.handler.CommandHandler#getImplCommands() + */ + public Collection<String> getImplCommands() { + List<String> commands = new ArrayList<String>(); + commands.add(COMMAND_NAME); + return commands; + } +} Added: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UnknownCmdHandler.java URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UnknownCmdHandler.java?rev=1203562&view=auto ============================================================================== --- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UnknownCmdHandler.java (added) +++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UnknownCmdHandler.java Fri Nov 18 10:00:50 2011 @@ -0,0 +1,58 @@ +/**************************************************************** + * 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.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.apache.james.protocols.api.Request; +import org.apache.james.protocols.api.Response; +import org.apache.james.protocols.api.handler.CommandHandler; +import org.apache.james.protocols.pop3.POP3Response; +import org.apache.james.protocols.pop3.POP3Session; + +/** + * Default command handler for handling unknown commands + */ +public class UnknownCmdHandler implements CommandHandler<POP3Session> { + /** + * The name of the command handled by the command handler + */ + public static final String COMMAND_NAME = "UNKNOWN"; + + /** + * Handler method called upon receipt of an unrecognized command. Returns an + * error response and logs the command. + */ + public Response onCommand(POP3Session session, Request request) { + return new POP3Response(POP3Response.ERR_RESPONSE); + } + + /** + * @see org.apache.james.protocols.api.handler.CommandHandler#getImplCommands() + */ + public Collection<String> getImplCommands() { + List<String> commands = new ArrayList<String>(); + commands.add(COMMAND_NAME); + return commands; + } + +} Added: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UserCmdHandler.java URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UserCmdHandler.java?rev=1203562&view=auto ============================================================================== --- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UserCmdHandler.java (added) +++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UserCmdHandler.java Fri Nov 18 10:00:50 2011 @@ -0,0 +1,73 @@ +/**************************************************************** + * 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.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.apache.james.pop3server.POP3Response; +import org.apache.james.pop3server.POP3Session; +import org.apache.james.protocols.api.Request; +import org.apache.james.protocols.api.Response; +import org.apache.james.protocols.api.handler.CommandHandler; + +/** + * Handles NOOP command + */ +public class UserCmdHandler implements CommandHandler<POP3Session>, CapaCapability { + + private final static String COMMAND_NAME = "USER"; + + /** + * Handler method called upon receipt of a USER command. Reads in the user + * id. + */ + public Response onCommand(POP3Session session, Request request) { + POP3Response response = null; + String parameters = request.getArgument(); + if (session.getHandlerState() == POP3Session.AUTHENTICATION_READY && parameters != null) { + session.setUser(parameters); + session.setHandlerState(POP3Session.AUTHENTICATION_USERSET); + response = new POP3Response(POP3Response.OK_RESPONSE); + } else { + response = new POP3Response(POP3Response.ERR_RESPONSE); + } + return response; + } + + /** + * @see org.apache.james.pop3server.core.CapaCapability#getImplementedCapabilities(org.apache.james.pop3server.POP3Session) + */ + public List<String> getImplementedCapabilities(POP3Session session) { + List<String> caps = new ArrayList<String>(); + caps.add(COMMAND_NAME); + return caps; + } + + /** + * @see org.apache.james.protocols.api.handler.CommandHandler#getImplCommands() + */ + public Collection<String> getImplCommands() { + List<String> commands = new ArrayList<String>(); + commands.add(COMMAND_NAME); + return commands; + } +} Added: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/WelcomeMessageHandler.java URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/WelcomeMessageHandler.java?rev=1203562&view=auto ============================================================================== --- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/WelcomeMessageHandler.java (added) +++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/WelcomeMessageHandler.java Fri Nov 18 10:00:50 2011 @@ -0,0 +1,46 @@ +/**************************************************************** + * 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 org.apache.james.protocols.api.Response; +import org.apache.james.protocols.api.handler.ConnectHandler; +import org.apache.james.protocols.pop3.POP3Response; +import org.apache.james.protocols.pop3.POP3Session; + +public class WelcomeMessageHandler implements ConnectHandler<POP3Session> { + /** POP3 Server identification string used in POP3 headers */ + private static final String softwaretype = "JAMES POP3 Server ";// + + // Constants.SOFTWARE_VERSION; + + /** + * @see org.apache.james.protocols.api.handler.ConnectHandler + * #onConnect(org.apache.james.pop3server.POP3Session) + */ + public Response onConnect(POP3Session session) { + StringBuilder responseBuffer = new StringBuilder(); + // Initially greet the connector + // Format is: Sat, 24 Jan 1998 13:16:09 -0500 + responseBuffer.append(session.getConfigurationData().getHelloName()).append(" POP3 server (").append(softwaretype).append(") ready "); + POP3Response response = new POP3Response(POP3Response.OK_RESPONSE, responseBuffer.toString()); + return response; + } + +} --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
