You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by jo...@apache.org on 2006/10/09 19:15:42 UTC
svn commit: r454432 [4/14] - in /james/server/sandbox/imap-integration: ./
lib/ src/java/ src/java/org/apache/james/imapserver/
src/java/org/apache/james/imapserver/commands/
src/java/org/apache/james/imapserver/debug/
src/java/org/apache/james/imapser...
Added: james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/ListCommand.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/ListCommand.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/ListCommand.java (added)
+++ james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/ListCommand.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,365 @@
+/***********************************************************************
+ * Copyright (c) 2000-2004 The Apache Software Foundation. *
+ * All rights reserved. *
+ * ------------------------------------------------------------------- *
+ * Licensed 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.imapserver.commands;
+
+import org.apache.james.imapserver.ImapRequestLineReader;
+import org.apache.james.imapserver.ImapResponse;
+import org.apache.james.imapserver.ImapSession;
+import org.apache.james.imapserver.ProtocolException;
+import org.apache.james.imapserver.store.MailboxException;
+import org.apache.james.mailboxmanager.ListResult;
+import org.apache.james.mailboxmanager.MailboxManagerException;
+import org.apache.james.mailboxmanager.impl.ListResultImpl;
+
+/**
+ * Handles processeing for the LIST imap command.
+ *
+ * @author Darrell DeBoer <da...@apache.org>
+ *
+ * @version $Revision: 109034 $
+ */
+class ListCommand extends AuthenticatedStateCommand
+{
+ public static final String NAME = "LIST";
+ public static final String ARGS = "<reference-name> <mailbox-name-with-wildcards>";
+
+ private ListCommandParser parser = new ListCommandParser();
+
+ /** @see CommandTemplate#doProcess */
+ protected void doProcess( ImapRequestLineReader request,
+ ImapResponse response,
+ ImapSession session )
+ throws ProtocolException, MailboxException
+ {
+ String referenceName = parser.mailbox( request );
+ String mailboxPattern = parser.listMailbox( request );
+ parser.endLine( request );
+
+ // Should the #user.userName section be removed from names returned?
+ boolean removeUserPrefix;
+
+ ListResult[] listResults;
+
+ String personalNamespace = USER_NAMESPACE + HIERARCHY_DELIMITER_CHAR +
+ session.getUser().getUserName();
+
+ if ( mailboxPattern.length() == 0 ) {
+ // An empty mailboxPattern signifies a request for the hierarchy delimiter
+ // and root name of the referenceName argument
+
+ String referenceRoot;
+ if ( referenceName.startsWith( NAMESPACE_PREFIX ) )
+ {
+ // A qualified reference name - get the first element,
+ // and don't remove the user prefix
+ removeUserPrefix = false;
+ int firstDelimiter = referenceName.indexOf( HIERARCHY_DELIMITER_CHAR );
+ if ( firstDelimiter == -1 ) {
+ referenceRoot = referenceName;
+ }
+ else {
+ referenceRoot = referenceName.substring(0, firstDelimiter );
+ }
+ }
+ else {
+ // A relative reference name - need to remove user prefix from results.
+ referenceRoot = "";
+ removeUserPrefix = true;
+
+ }
+
+ // Get the mailbox for the reference name.
+ listResults = new ListResult[1];
+ listResults[0]=new ListResultImpl(referenceRoot,HIERARCHY_DELIMITER);
+ }
+ else {
+
+ // If the mailboxPattern is fully qualified, ignore the
+ // reference name.
+ if ( mailboxPattern.charAt( 0 ) == NAMESPACE_PREFIX_CHAR ) {
+ referenceName="";
+ }
+
+ // If the search pattern is relative, need to remove user prefix from results.
+ removeUserPrefix = ( (referenceName+mailboxPattern).charAt(0) != NAMESPACE_PREFIX_CHAR );
+
+ if (removeUserPrefix) {
+ referenceName=personalNamespace+"."+referenceName;
+ }
+
+ listResults = doList( session, referenceName, mailboxPattern );
+ }
+
+
+ int prefixLength = personalNamespace.length();
+
+ for (int i = 0; i < listResults.length; i++) {
+ StringBuffer message = new StringBuffer( "(" );
+ String[] attrs=listResults[i].getAttributes();
+ for (int j = 0; j < attrs.length; j++) {
+ if (j > 0) {
+ message.append(' ');
+ }
+ message.append( attrs[j] );
+ }
+ message.append( ") \"" );
+ message.append( listResults[i].getHierarchyDelimiter() );
+ message.append( "\" " );
+
+ String mailboxName = listResults[i].getName();
+ if ( removeUserPrefix ) {
+ if ( mailboxName.length() <= prefixLength ) {
+ mailboxName = "";
+ }
+ else {
+ mailboxName = mailboxName.substring( prefixLength + 1 );
+ }
+ }
+
+ // TODO: need to check if the mailbox name needs quoting.
+ if ( mailboxName.length() == 0 ) {
+ message.append("\"\"");
+ }
+ else {
+ message.append( mailboxName );
+ }
+
+ response.commandResponse( this, message.toString() );
+ }
+
+ session.unsolicitedResponses( response, false );
+ response.commandComplete( this );
+ }
+
+ protected ListResult[] doList( ImapSession session, String base, String pattern ) throws MailboxException {
+ return doList( session, base, pattern, false);
+ }
+
+
+ protected ListResult[] doList( ImapSession session, String base, String pattern, boolean subscribed ) throws MailboxException
+ {
+ try {
+ return session.getMailboxManager().list(base,pattern,false);
+ } catch (MailboxManagerException e) {
+ throw new MailboxException(e);
+ }
+ }
+
+
+ /** @see ImapCommand#getName */
+ public String getName()
+ {
+ return NAME;
+ }
+
+ /** @see CommandTemplate#getArgSyntax */
+ public String getArgSyntax()
+ {
+ return ARGS;
+ }
+
+ private class ListCommandParser extends CommandParser
+ {
+ /**
+ * Reads an argument of type "list_mailbox" from the request, which is
+ * the second argument for a LIST or LSUB command. Valid values are a "string"
+ * argument, an "atom" with wildcard characters.
+ * @return An argument of type "list_mailbox"
+ */
+ public String listMailbox( ImapRequestLineReader request ) throws ProtocolException
+ {
+ char next = request.nextWordChar();
+ switch ( next ) {
+ case '"':
+ return consumeQuoted( request );
+ case '{':
+ return consumeLiteral( request );
+ default:
+ return consumeWord( request, new ListCharValidator() );
+ }
+ }
+
+ private class ListCharValidator extends ATOM_CHARValidator
+ {
+ public boolean isValid( char chr )
+ {
+ if ( isListWildcard( chr ) ) {
+ return true;
+ }
+ return super.isValid( chr );
+ }
+ }
+ }
+}
+
+/*
+6.3..8. LIST Command
+
+ Arguments: reference name
+ mailbox name with possible wildcards
+
+ Responses: untagged responses: LIST
+
+ Result: OK - list completed
+ NO - list failure: can't list that reference or name
+ BAD - command unknown or arguments invalid
+
+ The LIST command returns a subset of names from the complete set
+ of all names available to the client. Zero or more untagged LIST
+ replies are returned, containing the name attributes, hierarchy
+ delimiter, and name; see the description of the LIST reply for
+ more detail.
+
+ The LIST command SHOULD return its data quickly, without undue
+ delay. For example, it SHOULD NOT go to excess trouble to
+ calculate \Marked or \Unmarked status or perform other processing;
+ if each name requires 1 second of processing, then a list of 1200
+ names would take 20 minutes!
+
+ An empty ("" string) reference name argument indicates that the
+ mailbox name is interpreted as by SELECT. The returned mailbox
+ names MUST match the supplied mailbox name pattern. A non-empty
+ reference name argument is the name of a mailbox or a level of
+ mailbox hierarchy, and indicates a context in which the mailbox
+ name is interpreted in an implementation-defined manner.
+
+ An empty ("" string) mailbox name argument is a special request to
+ return the hierarchy delimiter and the root name of the name given
+ in the reference. The value returned as the root MAY be null if
+ the reference is non-rooted or is null. In all cases, the
+ hierarchy delimiter is returned. This permits a client to get the
+ hierarchy delimiter even when no mailboxes by that name currently
+ exist.
+
+ The reference and mailbox name arguments are interpreted, in an
+ implementation-dependent fashion, into a canonical form that
+ represents an unambiguous left-to-right hierarchy. The returned
+ mailbox names will be in the interpreted form.
+
+ Any part of the reference argument that is included in the
+ interpreted form SHOULD prefix the interpreted form. It SHOULD
+ also be in the same form as the reference name argument. This
+ rule permits the client to determine if the returned mailbox name
+ is in the context of the reference argument, or if something about
+ the mailbox argument overrode the reference argument. Without
+ this rule, the client would have to have knowledge of the server's
+ naming semantics including what characters are "breakouts" that
+ override a naming context.
+
+ For example, here are some examples of how references and mailbox
+ names might be interpreted on a UNIX-based server:
+
+ Reference Mailbox Name Interpretation
+ ------------ ------------ --------------
+ ~smith/Mail/ foo.* ~smith/Mail/foo.*
+ archive/ % archive/%
+ #news. comp.mail.* #news.comp.mail.*
+ ~smith/Mail/ /usr/doc/foo /usr/doc/foo
+ archive/ ~fred/Mail/* ~fred/Mail/*
+
+ The first three examples demonstrate interpretations in the
+ context of the reference argument. Note that "~smith/Mail" SHOULD
+ NOT be transformed into something like "/u2/users/smith/Mail", or
+ it would be impossible for the client to determine that the
+ interpretation was in the context of the reference.
+
+ The character "*" is a wildcard, and matches zero or more
+ characters at this position. The character "%" is similar to "*",
+ but it does not match a hierarchy delimiter. If the "%" wildcard
+ is the last character of a mailbox name argument, matching levels
+ of hierarchy are also returned. If these levels of hierarchy are
+ not also selectable mailboxes, they are returned with the
+ \Noselect mailbox name attribute (see the description of the LIST
+ response for more details).
+
+ Server implementations are permitted to "hide" otherwise
+ accessible mailboxes from the wildcard characters, by preventing
+ certain characters or names from matching a wildcard in certain
+ situations. For example, a UNIX-based server might restrict the
+ interpretation of "*" so that an initial "/" character does not
+ match.
+
+ The special name INBOX is included in the output from LIST, if
+ INBOX is supported by this server for this user and if the
+ uppercase string "INBOX" matches the interpreted reference and
+ mailbox name arguments with wildcards as described above. The
+ criteria for omitting INBOX is whether SELECT INBOX will return
+ failure; it is not relevant whether the user's real INBOX resides
+ on this or some other server.
+
+ Example: C: A101 LIST "" ""
+ S: * LIST (\Noselect) "/" ""
+ S: A101 OK LIST Completed
+ C: A102 LIST #news.comp.mail.misc ""
+ S: * LIST (\Noselect) "." #news.
+ S: A102 OK LIST Completed
+ C: A103 LIST /usr/staff/jones ""
+ S: * LIST (\Noselect) "/" /
+ S: A103 OK LIST Completed
+ C: A202 LIST ~/Mail/ %
+ S: * LIST (\Noselect) "/" ~/Mail/foo
+ S: * LIST () "/" ~/Mail/meetings
+ S: A202 OK LIST completed
+
+7.2.2. LIST Response
+
+ Contents: name attributes
+ hierarchy delimiter
+ name
+
+ The LIST response occurs as a result of a LIST command. It
+ returns a single name that matches the LIST specification. There
+ can be multiple LIST responses for a single LIST command.
+
+ Four name attributes are defined:
+
+ \Noinferiors It is not possible for any child levels of
+ hierarchy to exist under this name; no child levels
+ exist now and none can be created in the future.
+
+ \Noselect It is not possible to use this name as a selectable
+ mailbox.
+
+ \Marked The mailbox has been marked "interesting" by the
+ server; the mailbox probably contains messages that
+ have been added since the last time the mailbox was
+ selected.
+
+ \Unmarked The mailbox does not contain any additional
+ messages since the last time the mailbox was
+ selected.
+
+ If it is not feasible for the server to determine whether the
+ mailbox is "interesting" or not, or if the name is a \Noselect
+ name, the server SHOULD NOT send either \Marked or \Unmarked.
+
+ The hierarchy delimiter is a character used to delimit levels of
+ hierarchy in a mailbox name. A client can use it to create child
+ mailboxes, and to search higher or lower levels of naming
+ hierarchy. All children of a top-level hierarchy node MUST use
+ the same separator character. A NIL hierarchy delimiter means
+ that no hierarchy exists; the name is a "flat" name.
+
+ The name represents an unambiguous left-to-right hierarchy, and
+ MUST be valid for use as a reference in LIST and LSUB commands.
+ Unless \Noselect is indicated, the name MUST also be valid as an
+ argument for commands, such as SELECT, that accept mailbox
+ names.
+
+ Example: S: * LIST (\Noselect) "/" ~/Mail/foo
+*/
Added: james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/LoginCommand.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/LoginCommand.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/LoginCommand.java (added)
+++ james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/LoginCommand.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,90 @@
+/***********************************************************************
+ * Copyright (c) 2000-2004 The Apache Software Foundation. *
+ * All rights reserved. *
+ * ------------------------------------------------------------------- *
+ * Licensed 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.imapserver.commands;
+
+import org.apache.james.imapserver.ImapRequestLineReader;
+import org.apache.james.imapserver.ImapResponse;
+import org.apache.james.imapserver.ImapSession;
+import org.apache.james.imapserver.ProtocolException;
+import org.apache.james.services.User;
+
+
+/**
+ * Handles processeing for the LOGIN imap command.
+ *
+ * @author Darrell DeBoer <da...@apache.org>
+ *
+ * @version $Revision: 109034 $
+ */
+class LoginCommand extends NonAuthenticatedStateCommand
+{
+ public static final String NAME = "LOGIN";
+ public static final String ARGS = "<userid> <password>";
+
+ /** @see CommandTemplate#doProcess */
+ protected void doProcess( ImapRequestLineReader request,
+ ImapResponse response,
+ ImapSession session )
+ throws ProtocolException
+ {
+ String userid = parser.astring( request );
+ String password = parser.astring( request );
+ parser.endLine( request );
+
+ if ( session.getUsers().test( userid, password ) ) {
+ User user = session.getUsers().getUserByName( userid );
+ session.setAuthenticated( user );
+ response.commandComplete( this );
+
+ }
+ else {
+ response.commandFailed( this, "Invalid login/password" );
+ }
+ }
+
+ /** @see ImapCommand#getName */
+ public String getName()
+ {
+ return NAME;
+ }
+
+ /** @see CommandTemplate#getArgSyntax */
+ public String getArgSyntax()
+ {
+ return ARGS;
+ }
+}
+
+/*
+6.2.2. LOGIN Command
+
+ Arguments: user name
+ password
+
+ Responses: no specific responses for this command
+
+ Result: OK - login completed, now in authenticated state
+ NO - login failure: user name or password rejected
+ BAD - command unknown or arguments invalid
+
+ The LOGIN command identifies the client to the server and carries
+ the plaintext password authenticating this user.
+
+ Example: C: a001 LOGIN SMITH SESAME
+ S: a001 OK LOGIN completed
+*/
Added: james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/LogoutCommand.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/LogoutCommand.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/LogoutCommand.java (added)
+++ james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/LogoutCommand.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,82 @@
+/***********************************************************************
+ * Copyright (c) 2000-2004 The Apache Software Foundation. *
+ * All rights reserved. *
+ * ------------------------------------------------------------------- *
+ * Licensed 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.imapserver.commands;
+
+import org.apache.james.imapserver.ImapRequestLineReader;
+import org.apache.james.imapserver.ImapResponse;
+import org.apache.james.imapserver.ImapSession;
+import org.apache.james.imapserver.ProtocolException;
+
+/**
+ * Handles processeing for the LOGOUT imap command.
+ *
+ * @author Darrell DeBoer <da...@apache.org>
+ *
+ * @version $Revision: 109034 $
+ */
+class LogoutCommand extends CommandTemplate
+{
+ public static final String NAME = "LOGOUT";
+ public static final String ARGS = null;
+ public static final String BYE_MESSAGE = VERSION + SP + "Server logging out";
+
+ /** @see CommandTemplate#doProcess */
+ protected void doProcess( ImapRequestLineReader request,
+ ImapResponse response,
+ ImapSession session ) throws ProtocolException
+ {
+ parser.endLine( request );
+
+ response.byeResponse( BYE_MESSAGE );
+ response.commandComplete( this );
+ session.closeConnection();
+ }
+
+ /** @see ImapCommand#getName */
+ public String getName()
+ {
+ return NAME;
+ }
+
+ /** @see CommandTemplate#getArgSyntax */
+ public String getArgSyntax()
+ {
+ return ARGS;
+ }
+}
+
+/*
+6.1.3. LOGOUT Command
+
+ Arguments: none
+
+ Responses: REQUIRED untagged response: BYE
+
+ Result: OK - logout completed
+ BAD - command unknown or arguments invalid
+
+ The LOGOUT command informs the server that the client is done with
+ the connection. The server MUST send a BYE untagged response
+ before the (tagged) OK response, and then close the network
+ connection.
+
+ Example: C: A023 LOGOUT
+ S: * BYE IMAP4rev1 Server logging out
+ S: A023 OK LOGOUT completed
+ (Server and client then close the connection)
+*/
Added: james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/LsubCommand.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/LsubCommand.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/LsubCommand.java (added)
+++ james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/LsubCommand.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,44 @@
+/***********************************************************************
+ * Copyright (c) 2000-2004 The Apache Software Foundation. *
+ * All rights reserved. *
+ * ------------------------------------------------------------------- *
+ * Licensed 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.imapserver.commands;
+
+import org.apache.james.imapserver.ImapSession;
+import org.apache.james.imapserver.store.MailboxException;
+import org.apache.james.mailboxmanager.ListResult;
+
+/**
+ *
+ * @author Darrell DeBoer <da...@apache.org>
+ *
+ * @version $Revision: 109034 $
+ */
+class LsubCommand extends ListCommand
+{
+ public static final String NAME = "LSUB";
+
+ protected ListResult[] doList( ImapSession session, String base, String pattern ) throws MailboxException
+ {
+ return doList(session,base,pattern,true);
+ }
+
+ /** @see ImapCommand#getName */
+ public String getName()
+ {
+ return NAME;
+ }
+}
Added: james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/MsnRange.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/MsnRange.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/MsnRange.java (added)
+++ james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/MsnRange.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,50 @@
+/***********************************************************************
+ * Copyright (c) 2000-2004 The Apache Software Foundation. *
+ * All rights reserved. *
+ * ------------------------------------------------------------------- *
+ * Licensed 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.imapserver.commands;
+
+/**
+ * Represents a range of Message Sequence Numbers.
+ */
+public class MsnRange {
+
+ private int _lowVal;
+ private int _highVal;
+
+ public MsnRange(int singleVal) {
+ _lowVal = singleVal;
+ _highVal = singleVal;
+ }
+
+ public MsnRange(int lowVal, int highVal) {
+ _lowVal = lowVal;
+ _highVal = highVal;
+ }
+
+ public int getLowVal() {
+ return _lowVal;
+ }
+
+ public int getHighVal() {
+ return _highVal;
+ }
+
+ public boolean includes(int msn) {
+ return _lowVal <= msn && msn <= _highVal;
+ }
+
+}
Added: james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/NonAuthenticatedStateCommand.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/NonAuthenticatedStateCommand.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/NonAuthenticatedStateCommand.java (added)
+++ james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/NonAuthenticatedStateCommand.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,39 @@
+/***********************************************************************
+ * Copyright (c) 2000-2004 The Apache Software Foundation. *
+ * All rights reserved. *
+ * ------------------------------------------------------------------- *
+ * Licensed 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.imapserver.commands;
+
+import org.apache.james.imapserver.ImapSessionState;
+
+/**
+ * A base class for ImapCommands only valid in the NON_AUTHENTICATED state.
+ *
+ * @author Darrell DeBoer <da...@apache.org>
+ *
+ * @version $Revision: 109034 $
+ */
+abstract class NonAuthenticatedStateCommand extends CommandTemplate
+{
+
+ /**
+ * Ensure that state is {@link ImapSessionState#NON_AUTHENTICATED}.
+ */
+ public boolean validForState( ImapSessionState state )
+ {
+ return ( state == ImapSessionState.NON_AUTHENTICATED );
+ }
+}
Added: james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/NoopCommand.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/NoopCommand.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/NoopCommand.java (added)
+++ james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/NoopCommand.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,88 @@
+/***********************************************************************
+ * Copyright (c) 2000-2004 The Apache Software Foundation. *
+ * All rights reserved. *
+ * ------------------------------------------------------------------- *
+ * Licensed 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.imapserver.commands;
+
+import org.apache.james.imapserver.ImapRequestLineReader;
+import org.apache.james.imapserver.ImapResponse;
+import org.apache.james.imapserver.ImapSession;
+import org.apache.james.imapserver.ProtocolException;
+import org.apache.james.imapserver.store.MailboxException;
+
+/**
+ * Handles processeing for the NOOP imap command.
+ *
+ * @author Darrell DeBoer <da...@apache.org>
+ *
+ * @version $Revision: 109034 $
+ */
+class NoopCommand extends CommandTemplate
+{
+ public static final String NAME = "NOOP";
+ public static final String ARGS = null;
+
+ /** @see org.apache.james.imapserver.commands.CommandTemplate#doProcess */
+ protected void doProcess( ImapRequestLineReader request,
+ ImapResponse response,
+ ImapSession session ) throws ProtocolException, MailboxException
+ {
+ parser.endLine( request );
+ session.unsolicitedResponses( response, false );
+ response.commandComplete( this );
+ }
+
+ /** @see ImapCommand#getName */
+ public String getName()
+ {
+ return NAME;
+ }
+
+ /** @see CommandTemplate#getArgSyntax */
+ public String getArgSyntax()
+ {
+ return ARGS;
+ }
+}
+
+/*
+6.1.2. NOOP Command
+
+ Arguments: none
+
+ Responses: no specific responses for this command (but see below)
+
+ Result: OK - noop completed
+ BAD - command unknown or arguments invalid
+
+ The NOOP command always succeeds. It does nothing.
+
+ Since any command can return a status update as untagged data, the
+ NOOP command can be used as a periodic poll for new messages or
+ message status updates during a period of inactivity. The NOOP
+ command can also be used to reset any inactivity autologout timer
+ on the server.
+
+ Example: C: a002 NOOP
+ S: a002 OK NOOP completed
+ . . .
+ C: a047 NOOP
+ S: * 22 EXPUNGE
+ S: * 23 EXISTS
+ S: * 3 RECENT
+ S: * 14 FETCH (FLAGS (\Seen \Deleted))
+ S: a047 OK NOOP completed
+*/
Added: james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/RenameCommand.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/RenameCommand.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/RenameCommand.java (added)
+++ james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/RenameCommand.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,139 @@
+/***********************************************************************
+ * Copyright (c) 2000-2004 The Apache Software Foundation. *
+ * All rights reserved. *
+ * ------------------------------------------------------------------- *
+ * Licensed 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.imapserver.commands;
+
+import org.apache.james.imapserver.AuthorizationException;
+import org.apache.james.imapserver.ImapRequestLineReader;
+import org.apache.james.imapserver.ImapResponse;
+import org.apache.james.imapserver.ImapSession;
+import org.apache.james.imapserver.ProtocolException;
+import org.apache.james.imapserver.store.MailboxException;
+import org.apache.james.mailboxmanager.MailboxManagerException;
+
+/**
+ * Handles processeing for the RENAME imap command.
+ *
+ * @author Darrell DeBoer <da...@apache.org>
+ *
+ * @version $Revision: 109034 $
+ */
+class RenameCommand extends AuthenticatedStateCommand
+{
+ public static final String NAME = "RENAME";
+ public static final String ARGS = "existing-mailbox-name SPACE new-mailbox-name";
+
+ /** @see CommandTemplate#doProcess */
+ protected void doProcess( ImapRequestLineReader request,
+ ImapResponse response,
+ ImapSession session )
+ throws ProtocolException, MailboxException, AuthorizationException
+ {
+ String existingName = parser.mailbox( request );
+ String newName = parser.mailbox( request );
+ parser.endLine( request );
+
+ try {
+ existingName=session.buildFullName(existingName);
+ newName=session.buildFullName(newName);
+ session.getMailboxManager().renameMailbox( existingName, newName );
+ } catch (MailboxManagerException e) {
+ throw new MailboxException(e);
+ }
+
+ session.unsolicitedResponses( response , false );
+ response.commandComplete( this );
+ }
+
+ /** @see ImapCommand#getName */
+ public String getName()
+ {
+ return NAME;
+ }
+
+ /** @see CommandTemplate#getArgSyntax */
+ public String getArgSyntax()
+ {
+ return ARGS;
+ }
+
+}
+
+/*
+6.3.5. RENAME Command
+
+ Arguments: existing mailbox name
+ new mailbox name
+
+ Responses: no specific responses for this command
+
+ Result: OK - rename completed
+ NO - rename failure: can't rename mailbox with that name,
+ can't rename to mailbox with that name
+ BAD - command unknown or arguments invalid
+
+ The RENAME command changes the name of a mailbox. A tagged OK
+ response is returned only if the mailbox has been renamed. It is
+ an error to attempt to rename from a mailbox name that does not
+ exist or to a mailbox name that already exists. Any error in
+ renaming will return a tagged NO response.
+
+ If the name has inferior hierarchical names, then the inferior
+ hierarchical names MUST also be renamed. For example, a rename of
+ "foo" to "zap" will rename "foo/bar" (assuming "/" is the
+ hierarchy delimiter character) to "zap/bar".
+
+ The value of the highest-used unique identifier of the old mailbox
+ name MUST be preserved so that a new mailbox created with the same
+ name will not reuse the identifiers of the former incarnation,
+ UNLESS the new incarnation has a different unique identifier
+ validity value. See the description of the UID command for more
+ detail.
+
+ Renaming INBOX is permitted, and has special behavior. It moves
+ all messages in INBOX to a new mailbox with the given name,
+ leaving INBOX empty. If the server implementation supports
+ inferior hierarchical names of INBOX, these are unaffected by a
+ rename of INBOX.
+
+ Examples: C: A682 LIST "" *
+ S: * LIST () "/" blurdybloop
+ S: * LIST (\Noselect) "/" foo
+ S: * LIST () "/" foo/bar
+ S: A682 OK LIST completed
+ C: A683 RENAME blurdybloop sarasoop
+ S: A683 OK RENAME completed
+ C: A684 RENAME foo zowie
+ S: A684 OK RENAME Completed
+ C: A685 LIST "" *
+ S: * LIST () "/" sarasoop
+ S: * LIST (\Noselect) "/" zowie
+ S: * LIST () "/" zowie/bar
+ S: A685 OK LIST completed
+
+ C: Z432 LIST "" *
+ S: * LIST () "." INBOX
+ S: * LIST () "." INBOX.bar
+ S: Z432 OK LIST completed
+ C: Z433 RENAME INBOX old-mail
+ S: Z433 OK RENAME completed
+ C: Z434 LIST "" *
+ S: * LIST () "." INBOX
+ S: * LIST () "." INBOX.bar
+ S: * LIST () "." old-mail
+ S: Z434 OK LIST completed
+*/
Added: james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/SearchCommand.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/SearchCommand.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/SearchCommand.java (added)
+++ james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/SearchCommand.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,316 @@
+/***********************************************************************
+ * Copyright (c) 2000-2004 The Apache Software Foundation. *
+ * All rights reserved. *
+ * ------------------------------------------------------------------- *
+ * Licensed 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.imapserver.commands;
+
+import javax.mail.Message;
+import javax.mail.search.SearchTerm;
+
+import org.apache.james.imapserver.ImapRequestLineReader;
+import org.apache.james.imapserver.ImapResponse;
+import org.apache.james.imapserver.ImapSession;
+import org.apache.james.imapserver.ProtocolException;
+import org.apache.james.imapserver.store.MailboxException;
+import org.apache.james.mailboxmanager.MailboxManagerException;
+import org.apache.james.mailboxmanager.MessageResult;
+import org.apache.james.mailboxmanager.impl.GeneralMessageSetImpl;
+import org.apache.james.mailboxmanager.mailbox.ImapMailboxSession;
+
+/**
+ * Handles processeing for the SEARCH imap command.
+ *
+ * @author Darrell DeBoer <da...@apache.org>
+ *
+ * @version $Revision: 109034 $
+ */
+class SearchCommand extends SelectedStateCommand implements UidEnabledCommand
+{
+ public static final String NAME = "SEARCH";
+ public static final String ARGS = "<search term>";
+
+ private SearchCommandParser parser = new SearchCommandParser();
+
+ /** @see CommandTemplate#doProcess */
+ protected void doProcess( ImapRequestLineReader request,
+ ImapResponse response,
+ ImapSession session )
+ throws ProtocolException, MailboxException
+ {
+ doProcess( request, response, session, false );
+ }
+
+ public void doProcess( ImapRequestLineReader request,
+ ImapResponse response,
+ ImapSession session,
+ boolean useUids )
+ throws ProtocolException, MailboxException
+ {
+ // Parse the search term from the request
+ SearchTerm searchTerm = parser.searchTerm( request );
+ parser.endLine( request );
+
+ ImapMailboxSession mailbox = session.getSelected().getMailbox();
+ final int result;
+ if (useUids) {
+ result= MessageResult.UID;
+ } else {
+ result= MessageResult.MSN;
+ }
+ MessageResult[] messageResults;
+ try {
+ messageResults = mailbox.search(GeneralMessageSetImpl.all(),searchTerm, result);
+ } catch (MailboxManagerException e) {
+ throw new MailboxException(e);
+ }
+ StringBuffer idList = new StringBuffer();
+ for (int i = 0; i < messageResults.length; i++) {
+ if ( i > 0 ) {
+ idList.append( SP );
+ }
+ if ( useUids ) {
+ idList.append( messageResults[i].getUid());
+ } else {
+ idList.append( messageResults[i].getMsn());
+ }
+ }
+
+ response.commandResponse( this, idList.toString() );
+ boolean omitExpunged = (!useUids);
+ session.unsolicitedResponses( response, omitExpunged, useUids );
+ response.commandComplete( this );
+ }
+
+ /** @see ImapCommand#getName */
+ public String getName()
+ {
+ return NAME;
+ }
+
+ /** @see CommandTemplate#getArgSyntax */
+ public String getArgSyntax()
+ {
+ return ARGS;
+ }
+
+ private class SearchCommandParser extends CommandParser
+ {
+ /**
+ * Parses the request argument into a valid search term.
+ * Not yet implemented - all searches will return everything for now.
+ * TODO implement search
+ */
+ public SearchTerm searchTerm( ImapRequestLineReader request )
+ throws ProtocolException
+ {
+ // Dummy implementation
+ // Consume to the end of the line.
+ char next = request.nextChar();
+ while ( next != '\n' ) {
+ request.consume();
+ next = request.nextChar();
+ }
+
+ // Return a search term that matches everything.
+ return new SearchTerm()
+ {
+ private static final long serialVersionUID = 5290284637903768771L;
+
+ public boolean match( Message message )
+ {
+ return true;
+ }
+ };
+ }
+
+ }
+}
+/*
+6.4.4. SEARCH Command
+
+ Arguments: OPTIONAL [CHARSET] specification
+ searching criteria (one or more)
+
+ Responses: REQUIRED untagged response: SEARCH
+
+ Result: OK - search completed
+ NO - search error: can't search that [CHARSET] or
+ criteria
+ BAD - command unknown or arguments invalid
+
+ The SEARCH command searches the mailbox for messages that match
+ the given searching criteria. Searching criteria consist of one
+ or more search keys. The untagged SEARCH response from the server
+ contains a listing of message sequence numbers corresponding to
+ those messages that match the searching criteria.
+
+ When multiple keys are specified, the result is the intersection
+ (AND function) of all the messages that match those keys. For
+ example, the criteria DELETED FROM "SMITH" SINCE 1-Feb-1994 refers
+ to all deleted messages from Smith that were placed in the mailbox
+ since February 1, 1994. A search key can also be a parenthesized
+ list of one or more search keys (e.g. for use with the OR and NOT
+ keys).
+
+ Server implementations MAY exclude [MIME-IMB] body parts with
+ terminal content media types other than TEXT and MESSAGE from
+ consideration in SEARCH matching.
+
+ The OPTIONAL [CHARSET] specification consists of the word
+ "CHARSET" followed by a registered [CHARSET]. It indicates the
+ [CHARSET] of the strings that appear in the search criteria.
+ [MIME-IMB] content transfer encodings, and [MIME-HDRS] strings in
+ [RFC-822]/[MIME-IMB] headers, MUST be decoded before comparing
+ text in a [CHARSET] other than US-ASCII. US-ASCII MUST be
+ supported; other [CHARSET]s MAY be supported. If the server does
+ not support the specified [CHARSET], it MUST return a tagged NO
+ response (not a BAD).
+
+ In all search keys that use strings, a message matches the key if
+ the string is a substring of the field. The matching is case-
+ insensitive.
+
+ The defined search keys are as follows. Refer to the Formal
+ Syntax section for the precise syntactic definitions of the
+ arguments.
+
+ <message set> Messages with message sequence numbers
+ corresponding to the specified message sequence
+ number set
+
+ ALL All messages in the mailbox; the default initial
+ key for ANDing.
+
+ ANSWERED Messages with the \Answered flag set.
+
+ BCC <string> Messages that contain the specified string in the
+ envelope structure's BCC field.
+
+ BEFORE <date> Messages whose internal date is earlier than the
+ specified date.
+
+ BODY <string> Messages that contain the specified string in the
+ body of the message.
+
+ CC <string> Messages that contain the specified string in the
+ envelope structure's CC field.
+
+ DELETED Messages with the \Deleted flag set.
+
+ DRAFT Messages with the \Draft flag set.
+
+ FLAGGED Messages with the \Flagged flag set.
+
+ FROM <string> Messages that contain the specified string in the
+ envelope structure's FROM field.
+
+ HEADER <field-name> <string>
+ Messages that have a header with the specified
+ field-name (as defined in [RFC-822]) and that
+ contains the specified string in the [RFC-822]
+ field-body.
+
+ KEYWORD <flag> Messages with the specified keyword set.
+
+ LARGER <n> Messages with an [RFC-822] size larger than the
+ specified number of octets.
+
+ NEW Messages that have the \Recent flag set but not the
+ \Seen flag. This is functionally equivalent to
+ "(RECENT UNSEEN)".
+
+ NOT <search-key>
+ Messages that do not match the specified search
+ key.
+
+ OLD Messages that do not have the \Recent flag set.
+ This is functionally equivalent to "NOT RECENT" (as
+ opposed to "NOT NEW").
+
+ ON <date> Messages whose internal date is within the
+ specified date.
+
+ OR <search-key1> <search-key2>
+ Messages that match either search key.
+
+ RECENT Messages that have the \Recent flag set.
+
+ SEEN Messages that have the \Seen flag set.
+
+ SENTBEFORE <date>
+ Messages whose [RFC-822] Date: header is earlier
+ than the specified date.
+
+ SENTON <date> Messages whose [RFC-822] Date: header is within the
+ specified date.
+
+ SENTSINCE <date>
+ Messages whose [RFC-822] Date: header is within or
+ later than the specified date.
+
+ SINCE <date> Messages whose internal date is within or later
+ than the specified date.
+
+ SMALLER <n> Messages with an [RFC-822] size smaller than the
+ specified number of octets.
+
+ SUBJECT <string>
+ Messages that contain the specified string in the
+ envelope structure's SUBJECT field.
+
+ TEXT <string> Messages that contain the specified string in the
+ header or body of the message.
+
+ TO <string> Messages that contain the specified string in the
+ envelope structure's TO field.
+
+ UID <message set>
+ Messages with unique identifiers corresponding to
+ the specified unique identifier set.
+
+ UNANSWERED Messages that do not have the \Answered flag set.
+
+ UNDELETED Messages that do not have the \Deleted flag set.
+
+ UNDRAFT Messages that do not have the \Draft flag set.
+
+ UNFLAGGED Messages that do not have the \Flagged flag set.
+
+ UNKEYWORD <flag>
+ Messages that do not have the specified keyword
+ set.
+
+ UNSEEN Messages that do not have the \Seen flag set.
+
+ Example: C: A282 SEARCH FLAGGED SINCE 1-Feb-1994 NOT FROM "Smith"
+ S: * SEARCH 2 84 882
+ S: A282 OK SEARCH completed
+
+
+
+7.2.5. SEARCH Response
+
+ Contents: zero or more numbers
+
+ The SEARCH response occurs as a result of a SEARCH or UID SEARCH
+ command. The number(s) refer to those messages that match the
+ search criteria. For SEARCH, these are message sequence numbers;
+ for UID SEARCH, these are unique identifiers. Each number is
+ delimited by a space.
+
+ Example: S: * SEARCH 2 3 6
+
+*/
Added: james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/SelectCommand.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/SelectCommand.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/SelectCommand.java (added)
+++ james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/SelectCommand.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,189 @@
+/***********************************************************************
+ * Copyright (c) 2000-2004 The Apache Software Foundation. *
+ * All rights reserved. *
+ * ------------------------------------------------------------------- *
+ * Licensed 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.imapserver.commands;
+
+import org.apache.james.imapserver.ImapRequestLineReader;
+import org.apache.james.imapserver.ImapResponse;
+import org.apache.james.imapserver.ImapSession;
+import org.apache.james.imapserver.ProtocolException;
+import org.apache.james.imapserver.store.MailboxException;
+import org.apache.james.mailboxmanager.MailboxManagerException;
+import org.apache.james.mailboxmanager.MessageResult;
+import org.apache.james.mailboxmanager.mailbox.ImapMailboxSession;
+
+/**
+ * Handles processeing for the SELECT imap command.
+ *
+ * @author Darrell DeBoer <da...@apache.org>
+ *
+ * @version $Revision: 109034 $
+ */
+class SelectCommand extends AuthenticatedStateCommand
+{
+ public static final String NAME = "SELECT";
+ public static final String ARGS = "mailbox";
+
+ /** @see org.apache.james.imapserver.commands.CommandTemplate#doProcess */
+ protected void doProcess( ImapRequestLineReader request,
+ ImapResponse response,
+ ImapSession session )
+ throws ProtocolException, MailboxException
+ {
+ String mailboxName = parser.mailbox( request );
+ parser.endLine( request );
+
+ session.deselect();
+
+ final boolean isExamine = ( this instanceof ExamineCommand );
+
+ try {
+ mailboxName=session.buildFullName(mailboxName);
+ selectMailbox(mailboxName, session, isExamine);
+ ImapMailboxSession mailbox = session.getSelected().getMailbox();
+ response.flagsResponse(mailbox.getPermanentFlags());
+ final boolean resetRecent = !isExamine;
+ response.recentResponse(mailbox.getRecentCount(resetRecent));
+ response
+ .okResponse("UIDVALIDITY " + mailbox.getUidValidity(), null);
+
+ MessageResult firstUnseen = mailbox.getFirstUnseen(MessageResult.MSN);
+
+ response.existsResponse(mailbox.getMessageCount());
+
+ if (firstUnseen != null) {
+ response.okResponse("UNSEEN " + firstUnseen.getMsn(), "Message "
+ + firstUnseen.getMsn() + " is the first unseen");
+ } else {
+ response.okResponse(null, "No messages unseen");
+ }
+ response.permanentFlagsResponse(mailbox.getPermanentFlags());
+
+ if (!mailbox.isWriteable()) {
+ response.commandComplete(this, "READ-ONLY");
+ } else {
+ response.commandComplete(this, "READ-WRITE");
+ }
+ } catch (MailboxManagerException e) {
+ throw new MailboxException(e);
+ }
+ }
+
+ private boolean selectMailbox(String mailboxName, ImapSession session, boolean readOnly) throws MailboxException, MailboxManagerException {
+ ImapMailboxSession mailbox = session.getMailboxManager().getGenericImapMailboxSession(mailboxName);
+
+ if ( !mailbox.isSelectable() ) {
+ throw new MailboxException( "Nonselectable mailbox." );
+ }
+
+ session.setSelected( mailbox, readOnly );
+ return readOnly;
+ }
+
+ /** @see ImapCommand#getName */
+ public String getName()
+ {
+ return NAME;
+ }
+
+ /** @see CommandTemplate#getArgSyntax */
+ public String getArgSyntax()
+ {
+ return ARGS;
+ }
+}
+
+/*
+6.3.1. SELECT Command
+
+ Arguments: mailbox name
+
+ Responses: REQUIRED untagged responses: FLAGS, EXISTS, RECENT
+ OPTIONAL OK untagged responses: UNSEEN, PERMANENTFLAGS
+
+ Result: OK - select completed, now in selected state
+ NO - select failure, now in authenticated state: no
+ such mailbox, can't access mailbox
+ BAD - command unknown or arguments invalid
+
+ The SELECT command selects a mailbox so that messages in the
+ mailbox can be accessed. Before returning an OK to the client,
+ the server MUST send the following untagged data to the client:
+
+ FLAGS Defined flags in the mailbox. See the description
+ of the FLAGS response for more detail.
+
+ <n> EXISTS The number of messages in the mailbox. See the
+ description of the EXISTS response for more detail.
+
+ <n> RECENT The number of messages with the \Recent flag set.
+ See the description of the RECENT response for more
+ detail.
+
+ OK [UIDVALIDITY <n>]
+ The unique identifier validity value. See the
+ description of the UID command for more detail.
+
+ to define the initial state of the mailbox at the client.
+
+ The server SHOULD also send an UNSEEN response code in an OK
+ untagged response, indicating the message sequence number of the
+ first unseen message in the mailbox.
+
+ If the client can not change the permanent state of one or more of
+ the flags listed in the FLAGS untagged response, the server SHOULD
+ send a PERMANENTFLAGS response code in an OK untagged response,
+ listing the flags that the client can change permanently.
+
+ Only one mailbox can be selected at a time in a connection;
+ simultaneous access to multiple mailboxes requires multiple
+ connections. The SELECT command automatically deselects any
+ currently selected mailbox before attempting the new selection.
+ Consequently, if a mailbox is selected and a SELECT command that
+ fails is attempted, no mailbox is selected.
+
+
+
+
+Crispin Standards Track [Page 23]
+
+RFC 2060 IMAP4rev1 December 1996
+
+
+ If the client is permitted to modify the mailbox, the server
+ SHOULD prefix the text of the tagged OK response with the
+ "[READ-WRITE]" response code.
+
+ If the client is not permitted to modify the mailbox but is
+ permitted read access, the mailbox is selected as read-only, and
+ the server MUST prefix the text of the tagged OK response to
+ SELECT with the "[READ-ONLY]" response code. Read-only access
+ through SELECT differs from the EXAMINE command in that certain
+ read-only mailboxes MAY permit the change of permanent state on a
+ per-user (as opposed to global) basis. Netnews messages marked in
+ a server-based .newsrc file are an example of such per-user
+ permanent state that can be modified with read-only mailboxes.
+
+ Example: C: A142 SELECT INBOX
+ S: * 172 EXISTS
+ S: * 1 RECENT
+ S: * OK [UNSEEN 12] Message 12 is first unseen
+ S: * OK [UIDVALIDITY 3857529045] UIDs valid
+ S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
+ S: * OK [PERMANENTFLAGS (\Deleted \Seen \*)] Limited
+ S: A142 OK [READ-WRITE] SELECT completed
+*/
Added: james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/SelectedStateCommand.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/SelectedStateCommand.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/SelectedStateCommand.java (added)
+++ james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/SelectedStateCommand.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,49 @@
+/***********************************************************************
+ * Copyright (c) 2000-2004 The Apache Software Foundation. *
+ * All rights reserved. *
+ * ------------------------------------------------------------------- *
+ * Licensed 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.imapserver.commands;
+
+import org.apache.james.imapserver.ImapSessionState;
+
+/**
+ * A base class for ImapCommands only valid in the SELECTED state.
+ *
+ * @author Darrell DeBoer <da...@apache.org>
+ *
+ * @version $Revision: 109034 $
+ */
+abstract class SelectedStateCommand extends CommandTemplate
+{
+ /**
+ * Subclasses of this command are only valid in the
+ * {@link ImapSessionState#SELECTED} state.
+ */
+ public boolean validForState( ImapSessionState state )
+ {
+ return ( state == ImapSessionState.SELECTED );
+ }
+
+ protected boolean includes(IdRange[] idSet, long id) {
+ for (int i = 0; i < idSet.length; i++) {
+ IdRange idRange = idSet[i];
+ if (idRange.includes(id)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
Added: james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/StatusCommand.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/StatusCommand.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/StatusCommand.java (added)
+++ james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/StatusCommand.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,241 @@
+/***********************************************************************
+ * Copyright (c) 2000-2004 The Apache Software Foundation. *
+ * All rights reserved. *
+ * ------------------------------------------------------------------- *
+ * Licensed 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.imapserver.commands;
+
+import org.apache.james.imapserver.ImapRequestLineReader;
+import org.apache.james.imapserver.ImapResponse;
+import org.apache.james.imapserver.ImapSession;
+import org.apache.james.imapserver.ProtocolException;
+import org.apache.james.imapserver.store.MailboxException;
+import org.apache.james.mailboxmanager.MailboxManagerException;
+import org.apache.james.mailboxmanager.mailbox.ImapMailboxSession;
+
+/**
+ * Handles processeing for the STATUS imap command.
+ *
+ * @author Darrell DeBoer <da...@apache.org>
+ *
+ * @version $Revision: 109034 $
+ */
+class StatusCommand extends AuthenticatedStateCommand
+{
+ public static final String NAME = "STATUS";
+ public static final String ARGS = "<mailbox> ( <status-data-item>+ )";
+
+ private static final String MESSAGES = "MESSAGES";
+ private static final String RECENT = "RECENT";
+ private static final String UIDNEXT = "UIDNEXT";
+ private static final String UIDVALIDITY = "UIDVALIDITY";
+ private static final String UNSEEN = "UNSEEN";
+
+ private StatusCommandParser parser = new StatusCommandParser();
+
+ /** @see CommandTemplate#doProcess */
+ protected void doProcess( ImapRequestLineReader request,
+ ImapResponse response,
+ ImapSession session )
+ throws ProtocolException, MailboxException
+ {
+ String mailboxName = parser.mailbox( request );
+ StatusDataItems statusDataItems = parser.statusDataItems( request );
+ parser.endLine( request );
+
+ ImapMailboxSession mailbox = session.getSelected().getMailbox();
+
+ StringBuffer buffer = new StringBuffer( mailboxName );
+ buffer.append( SP );
+ buffer.append( "(" );
+ try {
+ if (statusDataItems.messages) {
+ buffer.append(MESSAGES);
+ buffer.append(SP);
+
+ buffer.append(mailbox.getMessageCount());
+
+ buffer.append(SP);
+ }
+
+ if (statusDataItems.recent) {
+ buffer.append(RECENT);
+ buffer.append(SP);
+ buffer.append(mailbox.getRecentCount(false));
+ buffer.append(SP);
+ }
+
+ if (statusDataItems.uidNext) {
+ buffer.append(UIDNEXT);
+ buffer.append(SP);
+ buffer.append(mailbox.getUidNext());
+ buffer.append(SP);
+ }
+
+ if (statusDataItems.uidValidity) {
+ buffer.append(UIDVALIDITY);
+ buffer.append(SP);
+ buffer.append(mailbox.getUidValidity());
+ buffer.append(SP);
+ }
+
+ if (statusDataItems.unseen) {
+ buffer.append(UNSEEN);
+ buffer.append(SP);
+ buffer.append(mailbox.getUnseenCount());
+ buffer.append(SP);
+ }
+ } catch (MailboxManagerException e) {
+ throw new MailboxException(e);
+ }
+ if ( buffer.charAt( buffer.length() - 1 ) == ' ' ) {
+ buffer.setLength( buffer.length() - 1 );
+ }
+ buffer.append(')');
+ response.commandResponse( this, buffer.toString());
+
+ session.unsolicitedResponses( response, false );
+ response.commandComplete( this );
+ }
+
+ /** @see ImapCommand#getName */
+ public String getName()
+ {
+ return NAME;
+ }
+
+ /** @see CommandTemplate#getArgSyntax */
+ public String getArgSyntax()
+ {
+ return ARGS;
+ }
+
+ private class StatusCommandParser extends CommandParser
+ {
+ StatusDataItems statusDataItems( ImapRequestLineReader request )
+ throws ProtocolException
+ {
+ StatusDataItems items = new StatusDataItems();
+
+ request.nextWordChar();
+ consumeChar( request, '(' );
+ CharacterValidator validator = new NoopCharValidator();
+ String nextWord = consumeWord( request, validator );
+ while ( ! nextWord.endsWith(")" ) ) {
+ addItem( nextWord, items );
+ nextWord = consumeWord( request, validator );
+ }
+ // Got the closing ")", may be attached to a word.
+ if ( nextWord.length() > 1 ) {
+ addItem( nextWord.substring(0, nextWord.length() - 1 ), items );
+ }
+
+ return items;
+ }
+
+ private void addItem( String nextWord, StatusDataItems items )
+ throws ProtocolException
+ {
+ if ( nextWord.equals( MESSAGES ) ) {
+ items.messages = true;
+ }
+ else if ( nextWord.equals( RECENT ) ) {
+ items.recent = true;
+ }
+ else if ( nextWord.equals( UIDNEXT ) ) {
+ items.uidNext = true;
+ }
+ else if ( nextWord.equals( UIDVALIDITY ) ) {
+ items.uidValidity = true;
+ }
+ else if ( nextWord.equals( UNSEEN ) ) {
+ items.unseen = true;
+ }
+ else {
+ throw new ProtocolException( "Unknown status item: '" + nextWord + "'" );
+ }
+ }
+ }
+
+ private class StatusDataItems
+ {
+ boolean messages;
+ boolean recent;
+ boolean uidNext;
+ boolean uidValidity;
+ boolean unseen;
+ }
+}
+/*
+6.3.10. STATUS Command
+
+ Arguments: mailbox name
+ status data item names
+
+ Responses: untagged responses: STATUS
+
+ Result: OK - status completed
+ NO - status failure: no status for that name
+ BAD - command unknown or arguments invalid
+
+ The STATUS command requests the status of the indicated mailbox.
+ It does not change the currently selected mailbox, nor does it
+ affect the state of any messages in the queried mailbox (in
+ particular, STATUS MUST NOT cause messages to lose the \Recent
+ flag).
+
+ The STATUS command provides an alternative to opening a second
+ IMAP4rev1 connection and doing an EXAMINE command on a mailbox to
+ query that mailbox's status without deselecting the current
+ mailbox in the first IMAP4rev1 connection.
+
+ Unlike the LIST command, the STATUS command is not guaranteed to
+ be fast in its response. In some implementations, the server is
+ obliged to open the mailbox read-only internally to obtain certain
+ status information. Also unlike the LIST command, the STATUS
+ command does not accept wildcards.
+
+ The currently defined status data items that can be requested are:
+
+ MESSAGES The number of messages in the mailbox.
+
+ RECENT The number of messages with the \Recent flag set.
+
+ UIDNEXT The next UID value that will be assigned to a new
+ message in the mailbox. It is guaranteed that this
+ value will not change unless new messages are added
+ to the mailbox; and that it will change when new
+ messages are added even if those new messages are
+ subsequently expunged.
+
+
+
+Crispin Standards Track [Page 33]
+
+RFC 2060 IMAP4rev1 December 1996
+
+
+ UIDVALIDITY The unique identifier validity value of the
+ mailbox.
+
+ UNSEEN The number of messages which do not have the \Seen
+ flag set.
+
+
+ Example: C: A042 STATUS blurdybloop (UIDNEXT MESSAGES)
+ S: * STATUS blurdybloop (MESSAGES 231 UIDNEXT 44292)
+ S: A042 OK STATUS completed
+
+*/
Added: james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/StoreCommand.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/StoreCommand.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/StoreCommand.java (added)
+++ james/server/sandbox/imap-integration/src/java/org/apache/james/imapserver/commands/StoreCommand.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,234 @@
+/***********************************************************************
+ * Copyright (c) 2000-2004 The Apache Software Foundation. *
+ * All rights reserved. *
+ * ------------------------------------------------------------------- *
+ * Licensed 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.imapserver.commands;
+
+import javax.mail.Flags;
+
+import org.apache.james.imapserver.ImapRequestLineReader;
+import org.apache.james.imapserver.ImapResponse;
+import org.apache.james.imapserver.ImapSession;
+import org.apache.james.imapserver.ProtocolException;
+import org.apache.james.imapserver.store.MailboxException;
+import org.apache.james.mailboxmanager.GeneralMessageSet;
+import org.apache.james.mailboxmanager.MailboxListener;
+import org.apache.james.mailboxmanager.MailboxManagerException;
+import org.apache.james.mailboxmanager.impl.GeneralMessageSetImpl;
+import org.apache.james.mailboxmanager.mailbox.ImapMailboxSession;
+
+/**
+ * Handles processeing for the STORE imap command.
+ *
+ * @author Darrell DeBoer <da...@apache.org>
+ *
+ * @version $Revision: 109034 $
+ */
+class StoreCommand extends SelectedStateCommand implements UidEnabledCommand
+{
+ public static final String NAME = "STORE";
+ public static final String ARGS = "<Message-set> ['+'|'-']FLAG[.SILENT] <flag-list>";
+
+ private final StoreCommandParser parser = new StoreCommandParser();
+
+ /** @see CommandTemplate#doProcess */
+ protected void doProcess( ImapRequestLineReader request,
+ ImapResponse response,
+ ImapSession session )
+ throws ProtocolException, MailboxException
+ {
+ doProcess( request, response, session , false );
+ }
+
+ public void doProcess( ImapRequestLineReader request,
+ ImapResponse response,
+ ImapSession session,
+ boolean useUids )
+ throws ProtocolException, MailboxException
+ {
+ IdRange[] idSet = parser.parseIdRange( request );
+ StoreDirective directive = parser.storeDirective( request );
+ Flags flags = parser.flagList( request );
+ parser.endLine( request );
+
+ ImapMailboxSession mailbox = session.getSelected().getMailbox();
+ MailboxListener silentListener = null;
+
+ final boolean replace;
+ final boolean value;
+ if (directive.getSign() < 0) {
+ value=false;
+ replace=false;
+ }
+ else if (directive.getSign() > 0) {
+ value=true;
+ replace=false;
+ }
+ else {
+ replace=true;
+ value=true;
+ }
+ try {
+ if (directive.isSilent()) {
+ silentListener = session.getSelected().getMailbox();
+ }
+ for (int i = 0; i < idSet.length; i++) {
+ final GeneralMessageSet messageSet = GeneralMessageSetImpl
+ .range(idSet[i].getLowVal(), idSet[i].getHighVal(),
+ useUids);
+
+ mailbox.setFlags(flags, value, replace, messageSet,
+ silentListener);
+ }
+ } catch (MailboxManagerException e) {
+ throw new MailboxException(e);
+ }
+ boolean omitExpunged = (!useUids);
+ session.unsolicitedResponses( response, omitExpunged , useUids);
+ response.commandComplete( this );
+ }
+
+
+ /** @see ImapCommand#getName */
+ public String getName()
+ {
+ return NAME;
+ }
+
+ /** @see CommandTemplate#getArgSyntax */
+ public String getArgSyntax()
+ {
+ return ARGS;
+ }
+
+ private class StoreCommandParser extends CommandParser
+ {
+ StoreDirective storeDirective( ImapRequestLineReader request ) throws ProtocolException
+ {
+ int sign = 0;
+ boolean silent = false;
+
+ char next = request.nextWordChar();
+ if ( next == '+' ) {
+ sign = 1;
+ request.consume();
+ }
+ else if ( next == '-' ) {
+ sign = -1;
+ request.consume();
+ }
+ else {
+ sign = 0;
+ }
+
+ String directive = consumeWord( request, new NoopCharValidator() );
+ if ( "FLAGS".equalsIgnoreCase( directive ) ) {
+ silent = false;
+ }
+ else if ( "FLAGS.SILENT".equalsIgnoreCase( directive ) ) {
+ silent = true;
+ }
+ else {
+ throw new ProtocolException( "Invalid Store Directive: '" + directive + "'" );
+ }
+ return new StoreDirective( sign, silent );
+ }
+ }
+
+ private class StoreDirective
+ {
+ private int sign;
+ private boolean silent;
+
+ public StoreDirective( int sign, boolean silent )
+ {
+ this.sign = sign;
+ this.silent = silent;
+ }
+
+ public int getSign()
+ {
+ return sign;
+ }
+
+ public boolean isSilent()
+ {
+ return silent;
+ }
+ }
+}
+/*
+6.4.6. STORE Command
+
+ Arguments: message set
+ message data item name
+ value for message data item
+
+ Responses: untagged responses: FETCH
+
+ Result: OK - store completed
+ NO - store error: can't store that data
+ BAD - command unknown or arguments invalid
+
+ The STORE command alters data associated with a message in the
+ mailbox. Normally, STORE will return the updated value of the
+ data with an untagged FETCH response. A suffix of ".SILENT" in
+ the data item name prevents the untagged FETCH, and the server
+ SHOULD assume that the client has determined the updated value
+ itself or does not care about the updated value.
+
+ Note: regardless of whether or not the ".SILENT" suffix was
+ used, the server SHOULD send an untagged FETCH response if a
+ change to a message's flags from an external source is
+ observed. The intent is that the status of the flags is
+ determinate without a race condition.
+
+ The currently defined data items that can be stored are:
+
+ FLAGS <flag list>
+ Replace the flags for the message with the
+ argument. The new value of the flags are returned
+ as if a FETCH of those flags was done.
+
+ FLAGS.SILENT <flag list>
+ Equivalent to FLAGS, but without returning a new
+ value.
+
+ +FLAGS <flag list>
+ Add the argument to the flags for the message. The
+ new value of the flags are returned as if a FETCH
+ of those flags was done.
+
+ +FLAGS.SILENT <flag list>
+ Equivalent to +FLAGS, but without returning a new
+ value.
+
+ -FLAGS <flag list>
+ Remove the argument from the flags for the message.
+ The new value of the flags are returned as if a
+ FETCH of those flags was done.
+
+ -FLAGS.SILENT <flag list>
+ Equivalent to -FLAGS, but without returning a new
+ value.
+
+ Example: C: A003 STORE 2:4 +FLAGS (\Deleted)
+ S: * 2 FETCH FLAGS (\Deleted \Seen)
+ S: * 3 FETCH FLAGS (\Deleted)
+ S: * 4 FETCH FLAGS (\Deleted \Flagged \Seen)
+ S: A003 OK STORE completed
+
+*/
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org