Class Command.

Inherits EventHandler. Inherited by Acl, Append, Authenticate, Capability, Check, Compress, Copy, Create, Delete, Enable, Expunge, Fetch, GenUrlauth, GetQuota, Id, Idle, Listext, Login, Logout, Namespace, Noop, Notify, Rename, ResetKey, Search, Select, SetQuota, SetQuotaRoot, StartTLS, Status, Store, Subscribe, Unselect, Unsubscribe and UrlFetch.

The Command class represents a single IMAP command.

Subclasses implement each command (e.g. Noop implements Noop), this class provides the overall framework.

It contains convenience functions to parse the various arguments, such as atom(), astring(), set and so on, as well as utility functions for the Command subclasses and, naturally, some functions that are tightly bound with the Commands, viz:

setGroup() and group() provide the IMAP class with information about which Commands can be executed concurrently.

setState() and state() decribe a command's state, which is either Blocked (waiting until IMAP permits executing this command), Executing (Command subclass working), Finished (done, but no response sent) or Retired (done, responses sent).

respond(), emitResponses(), error() and ok() all help sending responses to the IMAP client. respond() is mostly used for untagged responses, error() for tagged NO/BAD responses. If neither respond() nor error() is called, a tagged OK is sent by default when emitResponses() is called at the end of processing. Finally, ok() returns false if anything has happened to warrant NO/BAD, and true if everything is still OK.

Command::Command( IMAP * i )

Constructs a simple Command and ties it to i. create() doesn't need this, but maybe, just maybe, there is a world beyond create().

Command::Command()

Constructs a simple Command, entirely empty.

Reimplements EventHandler::EventHandler().

EString Command::astring()

Parses an IMAP astring and returns that string. In case of error, astring() calls error() appropriately and returns an empty string.

EString Command::atom()

Parses an IMAP atom and returns it as a string. Calls error() and turns an empty string in case of error.

void Command::checkUntaggedResponses()

Checks that everything we waitFor() has been sent.

static Command * Command::create( IMAP * imap, const EString & tag, const EString & name, ImapParser * args )

This static function creates an instance of the right subclass of Command, depending on name and the state of imap.

args is a pointer to the ImapParser object for the command; it is expected to point to the first character after the command's tag and name, so that it may be used to parse any arguments. Command assumes ownership of args, which must be non-zero.

If name is not a valid command, create() return a null pointer.

EString Command::digits( uint min, uint max )

Parses from min to max digits and returns them in string form. If fewer than min digits are available, error() is called.

void Command::emitResponses()

Dumps all responses issued during the command's parsing and execution to the write buffer. This may turn out to be insufficient, but for the moment it guarantees that each command's untagged responses and final tagged response come together.

void Command::end()

Asserts that the end of parsing has been reached. If the IMAP client has supplied more text, that text is a parse error and results in a BAD response.

void Command::error( Error e, const EString & t )

Sets the command's status code to be e and the attendant debugging message to be t, provided no status code has been set yet.

Only the first call to error() has any effect, and only if it's before the call to emitResponses(); subsequent calls are ignored entirely.

t should not be CRLF-terminated.

void Command::execute()

This virtual function is responsible for executing the command, as appopriate, and setting state() to Finished when it is. It is called by IMAP after parse() finishes, and only if parse() succeeds.

If state() is still Executing after a call to execute(), IMAP will call it again later.

Reimplements EventHandler::execute().

void Command::finish()

Sets this Command's state to ::Finished and emit any queued responses as soon as possible.

EString Command::flag()

Parses a flag name and returns it as a string, or calls error() if no valid flag name was present. The return value may contain both upper and lower case letters.

const EString Command::following() const

This private utility function returns a const string of no more than 15 characters containing the first unparsed bits of input.

uint Command::group() const

Returns the command group of this Command. Commands in group 0 may only be executed singly, commands in other groups may be executed concurrently with other commands in the same group.

The initial value is 0. setGroup() defines the available groups.

IMAP * Command::imap() const

Returns a pointer to the IMAP session to which this command belongs.

EString Command::imapQuoted( Mailbox * m, Mailbox * r )

Returns the name of m in the right format for sending to the client. The result is relative to r (if it is supplied), encoded using mUTF-7 if necessary, quoted appropriately, etc.

If r is null (this is the default), a user is logged in, and the mailbox is within the user's own namespace, then the result may be relative or absolute, depending on whether the client seems to prefer relative or absolute mailbox names.

static EString Command::imapQuoted( const EString & s, const QuoteMode mode )

This helper returns s, quoted such that an IMAP client will recover s. The quoted string fits the IMAP productions astring, nstring or string, depending on mode. The default is string.

We avoid using the escape characters and unusual atoms. "\"" is a legal one-character string. But we're easy on the poor client parser, and we make life easy for ourselves too.

EString Command::letters( uint min, uint max )

Parses from min to max letters and returns them in string form. If fewer than min letters are available, error() is called.

EString Command::listChars()

Parses one or more consecutive list-chars (ATOM-CHAR/list-wildcards/ resp-specials) and returns them as a EString. Calls error() and returns an empty string in case of error.

UString Command::listMailbox()

Parses and returns a list-mailbox. This is the same as an atom(), except that the three additional characters %, * and ] are accepted. The return value has been mutf-7 decoded.

EString Command::literal()

Parses an IMAP literal and returns the relevant string. Returns an empty string in case of error.

Mailbox * Command::mailbox()

Parses a mailbox name and returns a pointer to the relevant mailbox, which is guaranteed to be either a real mailbox or a view.

In case of error, mailbox() returns a null pointer and calls error() appropriately.

MailboxGroup * Command::mailboxGroup()

Guesses whether this command is part of a client loop processing group of mailboxes, and returns a pointer to the mailbox group if that seems to be the case. Returns a null pointer if not.

UString Command::mailboxName()

Parse a mailbox name and returns either it or the fully qualified name of the same name. Returns an empty string and calls error() in case there is a parse problem.

uint Command::msn()

Parses a single MSN and returns the accompanying UID.

EString Command::name() const

Returns the name of this command, e.g. 'uid fetch', in lower case.

char Command::nextChar()

Returns the next, unparsed character, without consuming it. Returns 0 in case of error, but does not emit any error messages.

void Command::nil()

Checks that the atom "nil" is next at the parse position, and steps past.

EString Command::nstring()

Parses an IMAP nstring and returns that string. If the nstring is NIL, an empty string is returned and error() is called.

uint Command::number()

Parses a single number and returns it.

uint Command::nzNumber()

Parses a single nzNumber and returns it.

bool Command::ok() const

Returns true if there haven't been any errors so far during parsing or execution of this command.

Calling error() makes this function return false.

void Command::parse()

This virtual function is responsible for parsing the entire command. It may not return any value; instead, it may set an error by calling error(). It may also not do any database lookups or other "slow" work.

If this function (or a reimplementation) is called and does not call error() or set the command's state, IMAP changes the state to Executing afterwards.

The default implementation is suitable for argumentless commands such as logout, capability and starttls.

ImapParser * Command::parser() const

Returns a pointer to the ImapParser object that was set by setParser() (usually by create()).

bool Command::permitted()

Returns true if this command is permitted to proceed, and false if it either must abort due to lack of rights or wait until Permissions has fetched more information.

If permitted() denies permission, it also sets a suitable error message.

bool Command::present( const EString & s )

Checks whether the next characters in the input match s. If so, present() steps past the matching characters and returns true. If not, it returns false without changing the input.

Note that the match is completely case insensitive.

EString Command::quoted()

Parses an IMAP quoted string and return the relevant string. In case of error an empty string is returned.

Note that any character can be quoted. IMAP properly allows only the quote character and the backslash to be quoted. In this respect, we deviate from the standard.

void Command::read()

This virtual function is responsible for reading from the IMAP stream and eventually releasing a reservation. Most subclasses will not need to implement this; only those that call IMAP::reserve() to the IMAP input stream do.

void Command::require( const EString & s )

Verifies that the next characters in the input match s (case insensitively), and removes whatever matches. If input isn't as required, require() calls error().

void Command::requireRight( Mailbox * m, Permissions::Right r )

Notes that this command requires r on m. execute() should proceed only if and when permitted() is true.

void Command::respond( const EString & r )

Adds r to the list of strings to be sent to the client. Neither the leading star-space nor the trailing CRLF should be included in r.

ImapSession * Command::session()

Returns a pointer to the Session for this Command. The Session is the one that applied when the Command started running. If there isn't one, then session() logs an error and throws an exception (which in turn closes the IMAP connection).

If the returned Session isn't active any longer, then ImapResponse will make sure the command's results aren't displayed.

IntegerSet Command::set( bool parseMsns )

Parses an IMAP set and returns the corresponding IntegerSet object. The set always contains UIDs; this function creates an UID set even if parseMsns is true.

void Command::setAllowedState( IMAP::State s ) const

Records that this Command may be executed in state s. The default is none, or what create() set.

void Command::setGroup( uint g )

Sets this command to belong to group g. If g is 0, the command must be executed singly. If g is nonzero, IMAP may try to execute this command concurrently with any other commands whose group is g.

The groups are (subject to later change):

0) Most commands. All commands which change state() or expunge messages must be here.

1) UID SEARCH and UID FETCH.

2) FETCH and SEARCH.

3) STORE and UID STORE. (Note that for this group to work, the server cannot emit side-effect expunges during UID STORE processing.) This group exists because a fetch after a store could otherwise fetch old data.

4) STATUS, LIST. Perhaps other read-only commands that look at mailboxes.

The initial value is 0.

void Command::setParser( ImapParser * p )

Instructs this command to parse itself using p. Most commands expect that nextChar() will return the space after the command name, before the first argument.

void Command::setRespTextCode( const EString & s )

Remembers that when the time comes to send a tagged OK, s should be sent as resp-text-code. s should not contain [], emitResponses() adds those itself.

void Command::setState( State s )

Sets the state of this command to s. The state is always one of three values, Blocked, Executing and Finished. The initial value is Executing. execute() must set it to Finished when done.

The Blocked state means that execute() cannot be called until all currently executing commands have finished. parse() and read() both may be called.

The Executing state means that execute() should be called (again).

The Finished state means that the command is done. IMAP rechecks the state after calling execute.

void Command::setTransaction( Transaction * t )

Records that this Command uses t for its database work.

void Command::shrink( IntegerSet * set )

Shrinks set by removing expunged and nonexistent UIDs. Quiet: Does not emit any kind of error or response.

void Command::space()

Checks that a single space is next at the parse position, and steps past it if all is ok.

This command accepts more than one space, and gives a warning. This is to tolerate broken clients, while giving client authors a strong hint.

State Command::state() const

Returns the state of this command, which may be Blocked, Executing or Finished. See setState().

void Command::step( uint n )

Steps past n characters of the unparsed arguments.

EString Command::string()

Parses an IMAP string and returns it. If there is none, error() is called appropriately.

EString Command::tag() const

Returns the tag of this command. Useful for logging.

Transaction * Command::transaction() const

Returns this Command's Transaction, if any was set using setTransaction(). Returns a null pointer if not.

bool Command::usesMsn() const

Returns true if this command has parsed at least one MSN, and false if it has not (ie. it returns false before parse()).

void Command::waitFor( ImapResponse * response )

Make sure that this command's tagged OK is not sent until response has been sent.

Command::~Command()

Destroys the object and frees any allocated resources.

Reimplements EventHandler::~EventHandler().

This web page based on source code belonging to The Archiveopteryx Developers. All rights reserved.