xref: /haiku/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Commands.cpp (revision 3a469b95bebf6f7e2f48d0e8b5f7955385350517)
137d26ae5SAxel Dörfler /*
281805393SAxel Dörfler  * Copyright 2011-2016, Haiku, Inc. All rights reserved.
337d26ae5SAxel Dörfler  * Copyright 2011, Clemens Zeidler <haiku@clemens-zeidler.de>
437d26ae5SAxel Dörfler  * Distributed under the terms of the MIT License.
537d26ae5SAxel Dörfler  */
637d26ae5SAxel Dörfler 
737d26ae5SAxel Dörfler 
837d26ae5SAxel Dörfler #include "Commands.h"
937d26ae5SAxel Dörfler 
1037d26ae5SAxel Dörfler #include <stdlib.h>
1137d26ae5SAxel Dörfler 
1237d26ae5SAxel Dörfler #include <AutoDeleter.h>
1337d26ae5SAxel Dörfler 
1437d26ae5SAxel Dörfler 
1537d26ae5SAxel Dörfler #define DEBUG_IMAP_HANDLER
1637d26ae5SAxel Dörfler #ifdef DEBUG_IMAP_HANDLER
1737d26ae5SAxel Dörfler #	include <stdio.h>
1837d26ae5SAxel Dörfler #	define TRACE(x...) printf(x)
1937d26ae5SAxel Dörfler #else
2037d26ae5SAxel Dörfler #	define TRACE(x...) ;
2137d26ae5SAxel Dörfler #endif
2237d26ae5SAxel Dörfler 
2337d26ae5SAxel Dörfler 
2437d26ae5SAxel Dörfler using namespace BPrivate;
2537d26ae5SAxel Dörfler 
2637d26ae5SAxel Dörfler 
2746019292SAxel Dörfler /*!	Maximum size of commands to the server (soft limit) */
2846019292SAxel Dörfler const size_t kMaxCommandLength = 2048;
2946019292SAxel Dörfler 
3046019292SAxel Dörfler 
31db0a4f2cSAxel Dörfler static void
PutFlag(BString & string,const char * flag)32db0a4f2cSAxel Dörfler PutFlag(BString& string, const char* flag)
33db0a4f2cSAxel Dörfler {
34db0a4f2cSAxel Dörfler 	if (!string.IsEmpty())
35db0a4f2cSAxel Dörfler 		string += " ";
36db0a4f2cSAxel Dörfler 	string += flag;
37db0a4f2cSAxel Dörfler }
38db0a4f2cSAxel Dörfler 
39db0a4f2cSAxel Dörfler 
40db0a4f2cSAxel Dörfler static BString
GenerateFlagString(uint32 flags)41db0a4f2cSAxel Dörfler GenerateFlagString(uint32 flags)
42db0a4f2cSAxel Dörfler {
43db0a4f2cSAxel Dörfler 	BString string;
44db0a4f2cSAxel Dörfler 
45db0a4f2cSAxel Dörfler 	if ((flags & IMAP::kSeen) != 0)
46db0a4f2cSAxel Dörfler 		PutFlag(string, "\\Seen");
47db0a4f2cSAxel Dörfler 	if ((flags & IMAP::kAnswered) != 0)
48db0a4f2cSAxel Dörfler 		PutFlag(string, "\\Answered");
49db0a4f2cSAxel Dörfler 	if ((flags & IMAP::kFlagged) != 0)
50db0a4f2cSAxel Dörfler 		PutFlag(string, "\\Flagged");
51db0a4f2cSAxel Dörfler 	if ((flags & IMAP::kDeleted) != 0)
52db0a4f2cSAxel Dörfler 		PutFlag(string, "\\Deleted");
53db0a4f2cSAxel Dörfler 	if ((flags & IMAP::kDraft) != 0)
54db0a4f2cSAxel Dörfler 		PutFlag(string, "\\Draft");
55db0a4f2cSAxel Dörfler 
56db0a4f2cSAxel Dörfler 	return string;
57db0a4f2cSAxel Dörfler }
58db0a4f2cSAxel Dörfler 
59db0a4f2cSAxel Dörfler 
60db0a4f2cSAxel Dörfler static uint32
ParseFlags(IMAP::ArgumentList & list)61db0a4f2cSAxel Dörfler ParseFlags(IMAP::ArgumentList& list)
62db0a4f2cSAxel Dörfler {
63db0a4f2cSAxel Dörfler 	uint32 flags = 0;
64db0a4f2cSAxel Dörfler 	for (int32 i = 0; i < list.CountItems(); i++) {
65db0a4f2cSAxel Dörfler 		if (list.EqualsAt(i, "\\Seen"))
66db0a4f2cSAxel Dörfler 			flags |= IMAP::kSeen;
67db0a4f2cSAxel Dörfler 		else if (list.EqualsAt(i, "\\Answered"))
68db0a4f2cSAxel Dörfler 			flags |= IMAP::kAnswered;
69db0a4f2cSAxel Dörfler 		else if (list.EqualsAt(i, "\\Flagged"))
70db0a4f2cSAxel Dörfler 			flags |= IMAP::kFlagged;
71db0a4f2cSAxel Dörfler 		else if (list.EqualsAt(i, "\\Deleted"))
72db0a4f2cSAxel Dörfler 			flags |= IMAP::kDeleted;
73db0a4f2cSAxel Dörfler 		else if (list.EqualsAt(i, "\\Draft"))
74db0a4f2cSAxel Dörfler 			flags |= IMAP::kDraft;
75db0a4f2cSAxel Dörfler 	}
76db0a4f2cSAxel Dörfler 	return flags;
77db0a4f2cSAxel Dörfler }
78db0a4f2cSAxel Dörfler 
79db0a4f2cSAxel Dörfler 
80db0a4f2cSAxel Dörfler // #pragma mark -
81db0a4f2cSAxel Dörfler 
82db0a4f2cSAxel Dörfler 
8337d26ae5SAxel Dörfler namespace IMAP {
8437d26ae5SAxel Dörfler 
8537d26ae5SAxel Dörfler 
Handler()8637d26ae5SAxel Dörfler Handler::Handler()
8737d26ae5SAxel Dörfler {
8837d26ae5SAxel Dörfler }
8937d26ae5SAxel Dörfler 
9037d26ae5SAxel Dörfler 
~Handler()9137d26ae5SAxel Dörfler Handler::~Handler()
9237d26ae5SAxel Dörfler {
9337d26ae5SAxel Dörfler }
9437d26ae5SAxel Dörfler 
9537d26ae5SAxel Dörfler 
9637d26ae5SAxel Dörfler // #pragma mark -
9737d26ae5SAxel Dörfler 
9837d26ae5SAxel Dörfler 
~Command()9937d26ae5SAxel Dörfler Command::~Command()
10037d26ae5SAxel Dörfler {
10137d26ae5SAxel Dörfler }
10237d26ae5SAxel Dörfler 
10337d26ae5SAxel Dörfler 
10437d26ae5SAxel Dörfler status_t
HandleTagged(Response & response)10537d26ae5SAxel Dörfler Command::HandleTagged(Response& response)
10637d26ae5SAxel Dörfler {
10737d26ae5SAxel Dörfler 	if (response.StringAt(0) == "OK")
10837d26ae5SAxel Dörfler 		return B_OK;
10937d26ae5SAxel Dörfler 	if (response.StringAt(0) == "BAD")
11037d26ae5SAxel Dörfler 		return B_BAD_VALUE;
11137d26ae5SAxel Dörfler 	if (response.StringAt(0) == "NO")
11237d26ae5SAxel Dörfler 		return B_NOT_ALLOWED;
11337d26ae5SAxel Dörfler 
11437d26ae5SAxel Dörfler 	return B_ERROR;
11537d26ae5SAxel Dörfler }
11637d26ae5SAxel Dörfler 
11737d26ae5SAxel Dörfler 
11837d26ae5SAxel Dörfler // #pragma mark -
11937d26ae5SAxel Dörfler 
120db0a4f2cSAxel Dörfler #if 0
12137d26ae5SAxel Dörfler HandlerListener::~HandlerListener()
12237d26ae5SAxel Dörfler {
12337d26ae5SAxel Dörfler }
12437d26ae5SAxel Dörfler 
12537d26ae5SAxel Dörfler 
12637d26ae5SAxel Dörfler void
12737d26ae5SAxel Dörfler HandlerListener::ExpungeReceived(int32 number)
12837d26ae5SAxel Dörfler {
12937d26ae5SAxel Dörfler }
13037d26ae5SAxel Dörfler 
13137d26ae5SAxel Dörfler 
13237d26ae5SAxel Dörfler void
13337d26ae5SAxel Dörfler HandlerListener::ExistsReceived(int32 number)
13437d26ae5SAxel Dörfler {
13537d26ae5SAxel Dörfler }
136db0a4f2cSAxel Dörfler #endif
13737d26ae5SAxel Dörfler 
13837d26ae5SAxel Dörfler // #pragma mark -
13937d26ae5SAxel Dörfler 
14037d26ae5SAxel Dörfler 
RawCommand(const BString & command)14137d26ae5SAxel Dörfler RawCommand::RawCommand(const BString& command)
14237d26ae5SAxel Dörfler 	:
14337d26ae5SAxel Dörfler 	fCommand(command)
14437d26ae5SAxel Dörfler {
14537d26ae5SAxel Dörfler }
14637d26ae5SAxel Dörfler 
14737d26ae5SAxel Dörfler 
14837d26ae5SAxel Dörfler BString
CommandString()14937d26ae5SAxel Dörfler RawCommand::CommandString()
15037d26ae5SAxel Dörfler {
15137d26ae5SAxel Dörfler 	return fCommand;
15237d26ae5SAxel Dörfler }
15337d26ae5SAxel Dörfler 
15437d26ae5SAxel Dörfler 
15537d26ae5SAxel Dörfler // #pragma mark -
15637d26ae5SAxel Dörfler 
15737d26ae5SAxel Dörfler 
LoginCommand(const char * user,const char * password)15837d26ae5SAxel Dörfler LoginCommand::LoginCommand(const char* user, const char* password)
15937d26ae5SAxel Dörfler 	:
16037d26ae5SAxel Dörfler 	fUser(user),
16137d26ae5SAxel Dörfler 	fPassword(password)
16237d26ae5SAxel Dörfler {
16337d26ae5SAxel Dörfler }
16437d26ae5SAxel Dörfler 
16537d26ae5SAxel Dörfler 
16637d26ae5SAxel Dörfler BString
CommandString()16737d26ae5SAxel Dörfler LoginCommand::CommandString()
16837d26ae5SAxel Dörfler {
16937d26ae5SAxel Dörfler 	BString command = "LOGIN ";
17037d26ae5SAxel Dörfler 	command << "\"" << fUser << "\" " << "\"" << fPassword << "\"";
17137d26ae5SAxel Dörfler 
17237d26ae5SAxel Dörfler 	return command;
17337d26ae5SAxel Dörfler }
17437d26ae5SAxel Dörfler 
17537d26ae5SAxel Dörfler 
17637d26ae5SAxel Dörfler bool
HandleUntagged(Response & response)17737d26ae5SAxel Dörfler LoginCommand::HandleUntagged(Response& response)
17837d26ae5SAxel Dörfler {
17937d26ae5SAxel Dörfler 	if (!response.EqualsAt(0, "OK") || !response.IsListAt(1, '['))
18037d26ae5SAxel Dörfler 		return false;
18137d26ae5SAxel Dörfler 
18237d26ae5SAxel Dörfler 	// TODO: we only support capabilities at the moment
18337d26ae5SAxel Dörfler 	ArgumentList& list = response.ListAt(1);
18437d26ae5SAxel Dörfler 	if (!list.EqualsAt(0, "CAPABILITY"))
18537d26ae5SAxel Dörfler 		return false;
18637d26ae5SAxel Dörfler 
18737d26ae5SAxel Dörfler 	fCapabilities.MakeEmpty();
18837d26ae5SAxel Dörfler 	while (list.CountItems() > 1)
18937d26ae5SAxel Dörfler 		fCapabilities.AddItem(list.RemoveItemAt(1));
19037d26ae5SAxel Dörfler 
19137d26ae5SAxel Dörfler 	TRACE("CAPABILITY: %s\n", fCapabilities.ToString().String());
19237d26ae5SAxel Dörfler 	return true;
19337d26ae5SAxel Dörfler }
19437d26ae5SAxel Dörfler 
19537d26ae5SAxel Dörfler 
19637d26ae5SAxel Dörfler // #pragma mark -
19737d26ae5SAxel Dörfler 
19837d26ae5SAxel Dörfler 
SelectCommand()19937d26ae5SAxel Dörfler SelectCommand::SelectCommand()
20037d26ae5SAxel Dörfler 	:
20137d26ae5SAxel Dörfler 	fNextUID(0),
20237d26ae5SAxel Dörfler 	fUIDValidity(0)
20337d26ae5SAxel Dörfler {
20437d26ae5SAxel Dörfler }
20537d26ae5SAxel Dörfler 
20637d26ae5SAxel Dörfler 
SelectCommand(const char * name)20737d26ae5SAxel Dörfler SelectCommand::SelectCommand(const char* name)
20837d26ae5SAxel Dörfler 	:
20937d26ae5SAxel Dörfler 	fNextUID(0),
21037d26ae5SAxel Dörfler 	fUIDValidity(0)
21137d26ae5SAxel Dörfler {
212a4bdd26dSAxel Dörfler 	SetTo(name);
21337d26ae5SAxel Dörfler }
21437d26ae5SAxel Dörfler 
21537d26ae5SAxel Dörfler 
21637d26ae5SAxel Dörfler BString
CommandString()21737d26ae5SAxel Dörfler SelectCommand::CommandString()
21837d26ae5SAxel Dörfler {
21937d26ae5SAxel Dörfler 	if (fMailboxName == "")
22037d26ae5SAxel Dörfler 		return "";
22137d26ae5SAxel Dörfler 
22237d26ae5SAxel Dörfler 	BString command = "SELECT \"";
22337d26ae5SAxel Dörfler 	command += fMailboxName;
22437d26ae5SAxel Dörfler 	command += "\"";
22537d26ae5SAxel Dörfler 	return command;
22637d26ae5SAxel Dörfler }
22737d26ae5SAxel Dörfler 
22837d26ae5SAxel Dörfler 
22937d26ae5SAxel Dörfler bool
HandleUntagged(Response & response)23037d26ae5SAxel Dörfler SelectCommand::HandleUntagged(Response& response)
23137d26ae5SAxel Dörfler {
23237d26ae5SAxel Dörfler 	if (response.EqualsAt(0, "OK") && response.IsListAt(1, '[')) {
23337d26ae5SAxel Dörfler 		const ArgumentList& arguments = response.ListAt(1);
23437d26ae5SAxel Dörfler 		if (arguments.EqualsAt(0, "UIDVALIDITY")
23537d26ae5SAxel Dörfler 			&& arguments.IsNumberAt(1)) {
23637d26ae5SAxel Dörfler 			fUIDValidity = arguments.NumberAt(1);
23737d26ae5SAxel Dörfler 			return true;
23837d26ae5SAxel Dörfler 		} else if (arguments.EqualsAt(0, "UIDNEXT")
23937d26ae5SAxel Dörfler 			&& arguments.IsNumberAt(1)) {
24037d26ae5SAxel Dörfler 			fNextUID = arguments.NumberAt(1);
24137d26ae5SAxel Dörfler 			return true;
24237d26ae5SAxel Dörfler 		}
24337d26ae5SAxel Dörfler 	}
24437d26ae5SAxel Dörfler 
24537d26ae5SAxel Dörfler 	return false;
24637d26ae5SAxel Dörfler }
24737d26ae5SAxel Dörfler 
24837d26ae5SAxel Dörfler 
249a4bdd26dSAxel Dörfler void
SetTo(const char * mailboxName)250a4bdd26dSAxel Dörfler SelectCommand::SetTo(const char* mailboxName)
251a4bdd26dSAxel Dörfler {
252a4bdd26dSAxel Dörfler 	RFC3501Encoding encoding;
253a4bdd26dSAxel Dörfler 	fMailboxName = encoding.Encode(mailboxName);
254a4bdd26dSAxel Dörfler }
255a4bdd26dSAxel Dörfler 
256a4bdd26dSAxel Dörfler 
25737d26ae5SAxel Dörfler // #pragma mark -
25837d26ae5SAxel Dörfler 
25937d26ae5SAxel Dörfler 
26037d26ae5SAxel Dörfler BString
CommandString()26137d26ae5SAxel Dörfler CapabilityHandler::CommandString()
26237d26ae5SAxel Dörfler {
26337d26ae5SAxel Dörfler 	return "CAPABILITY";
26437d26ae5SAxel Dörfler }
26537d26ae5SAxel Dörfler 
26637d26ae5SAxel Dörfler 
26737d26ae5SAxel Dörfler bool
HandleUntagged(Response & response)26837d26ae5SAxel Dörfler CapabilityHandler::HandleUntagged(Response& response)
26937d26ae5SAxel Dörfler {
27037d26ae5SAxel Dörfler 	if (!response.IsCommand("CAPABILITY"))
27137d26ae5SAxel Dörfler 		return false;
27237d26ae5SAxel Dörfler 
27337d26ae5SAxel Dörfler 	fCapabilities.MakeEmpty();
27437d26ae5SAxel Dörfler 	while (response.CountItems() > 1)
27537d26ae5SAxel Dörfler 		fCapabilities.AddItem(response.RemoveItemAt(1));
27637d26ae5SAxel Dörfler 
27737d26ae5SAxel Dörfler 	TRACE("CAPABILITY: %s\n", fCapabilities.ToString().String());
27837d26ae5SAxel Dörfler 	return true;
27937d26ae5SAxel Dörfler }
28037d26ae5SAxel Dörfler 
28137d26ae5SAxel Dörfler 
28237d26ae5SAxel Dörfler // #pragma mark -
28337d26ae5SAxel Dörfler 
28437d26ae5SAxel Dörfler 
FetchMessageEntriesCommand(MessageEntryList & entries,uint32 from,uint32 to,bool uids)28537d26ae5SAxel Dörfler FetchMessageEntriesCommand::FetchMessageEntriesCommand(
286c1f779e3SAxel Dörfler 	MessageEntryList& entries, uint32 from, uint32 to, bool uids)
28737d26ae5SAxel Dörfler 	:
28837d26ae5SAxel Dörfler 	fEntries(entries),
28937d26ae5SAxel Dörfler 	fFrom(from),
290c1f779e3SAxel Dörfler 	fTo(to),
291c1f779e3SAxel Dörfler 	fUIDs(uids)
29237d26ae5SAxel Dörfler {
29337d26ae5SAxel Dörfler }
29437d26ae5SAxel Dörfler 
29537d26ae5SAxel Dörfler 
29637d26ae5SAxel Dörfler BString
CommandString()29737d26ae5SAxel Dörfler FetchMessageEntriesCommand::CommandString()
29837d26ae5SAxel Dörfler {
299c1f779e3SAxel Dörfler 	BString command = fUIDs ? "UID FETCH " : "FETCH ";
30046019292SAxel Dörfler 	command << fFrom;
30146019292SAxel Dörfler 	if (fFrom != fTo)
30246019292SAxel Dörfler 		command << ":" << fTo;
30346019292SAxel Dörfler 
30446019292SAxel Dörfler 	command << " (FLAGS RFC822.SIZE";
305c1f779e3SAxel Dörfler 	if (!fUIDs)
306c1f779e3SAxel Dörfler 		command << " UID";
307c1f779e3SAxel Dörfler 	command << ")";
30837d26ae5SAxel Dörfler 
30937d26ae5SAxel Dörfler 	return command;
31037d26ae5SAxel Dörfler }
31137d26ae5SAxel Dörfler 
31237d26ae5SAxel Dörfler 
31337d26ae5SAxel Dörfler bool
HandleUntagged(Response & response)31437d26ae5SAxel Dörfler FetchMessageEntriesCommand::HandleUntagged(Response& response)
31537d26ae5SAxel Dörfler {
31637d26ae5SAxel Dörfler 	if (!response.EqualsAt(1, "FETCH") || !response.IsListAt(2))
31737d26ae5SAxel Dörfler 		return false;
31837d26ae5SAxel Dörfler 
31937d26ae5SAxel Dörfler 	MessageEntry entry;
32037d26ae5SAxel Dörfler 
32137d26ae5SAxel Dörfler 	ArgumentList& list = response.ListAt(2);
32237d26ae5SAxel Dörfler 	for (int32 i = 0; i < list.CountItems(); i += 2) {
32337d26ae5SAxel Dörfler 		if (list.EqualsAt(i, "UID") && list.IsNumberAt(i + 1))
32437d26ae5SAxel Dörfler 			entry.uid = list.NumberAt(i + 1);
325db0a4f2cSAxel Dörfler 		else if (list.EqualsAt(i, "RFC822.SIZE") && list.IsNumberAt(i + 1))
326db0a4f2cSAxel Dörfler 			entry.size = list.NumberAt(i + 1);
32737d26ae5SAxel Dörfler 		else if (list.EqualsAt(i, "FLAGS") && list.IsListAt(i + 1)) {
32837d26ae5SAxel Dörfler 			// Parse flags
32937d26ae5SAxel Dörfler 			ArgumentList& flags = list.ListAt(i + 1);
330db0a4f2cSAxel Dörfler 			entry.flags = ParseFlags(flags);
33137d26ae5SAxel Dörfler 		}
33237d26ae5SAxel Dörfler 	}
33337d26ae5SAxel Dörfler 
33437d26ae5SAxel Dörfler 	if (entry.uid == 0)
33537d26ae5SAxel Dörfler 		return false;
33637d26ae5SAxel Dörfler 
33737d26ae5SAxel Dörfler 	fEntries.push_back(entry);
33837d26ae5SAxel Dörfler 	return true;
33937d26ae5SAxel Dörfler }
34037d26ae5SAxel Dörfler 
34137d26ae5SAxel Dörfler 
34237d26ae5SAxel Dörfler // #pragma mark -
34337d26ae5SAxel Dörfler 
34437d26ae5SAxel Dörfler 
FetchCommand(uint32 from,uint32 to,uint32 flags)3453302df14SAxel Dörfler FetchCommand::FetchCommand(uint32 from, uint32 to, uint32 flags)
34637d26ae5SAxel Dörfler 	:
3473302df14SAxel Dörfler 	fFlags(flags)
34837d26ae5SAxel Dörfler {
34946019292SAxel Dörfler 	fSequence << from;
35046019292SAxel Dörfler 	if (from != to)
35146019292SAxel Dörfler 		fSequence << ":" << to;
35246019292SAxel Dörfler }
35346019292SAxel Dörfler 
35446019292SAxel Dörfler 
35546019292SAxel Dörfler /*!	Builds the sequence from the passed in UID list, and takes \a max entries
35646019292SAxel Dörfler 	at maximum. If the sequence gets too large, it might fetch less entries
35746019292SAxel Dörfler 	than specified. The fetched UIDs will be removed from the \uids list.
35846019292SAxel Dörfler */
FetchCommand(MessageUIDList & uids,size_t max,uint32 flags)35946019292SAxel Dörfler FetchCommand::FetchCommand(MessageUIDList& uids, size_t max, uint32 flags)
36046019292SAxel Dörfler 	:
36146019292SAxel Dörfler 	fFlags(flags)
36246019292SAxel Dörfler {
36346019292SAxel Dörfler 	// Build sequence string
36446019292SAxel Dörfler 	max = std::min(max, uids.size());
36546019292SAxel Dörfler 
36646019292SAxel Dörfler 	size_t index = 0;
36746019292SAxel Dörfler 	while (index < max && (size_t)fSequence.Length() < kMaxCommandLength) {
36846019292SAxel Dörfler 		// Get start of range
36946019292SAxel Dörfler 		uint32 first = uids[index++];
37046019292SAxel Dörfler 		uint32 last = first;
37146019292SAxel Dörfler 		if (!fSequence.IsEmpty())
37246019292SAxel Dörfler 			fSequence += ",";
37346019292SAxel Dörfler 		fSequence << first;
37446019292SAxel Dörfler 
37546019292SAxel Dörfler 		for (; index < max; index++) {
37646019292SAxel Dörfler 			uint32 uid = uids[index];
37746019292SAxel Dörfler 			if (uid != last + 1)
37846019292SAxel Dörfler 				break;
37946019292SAxel Dörfler 
38046019292SAxel Dörfler 			last = uid;
38146019292SAxel Dörfler 		}
38246019292SAxel Dörfler 
38346019292SAxel Dörfler 		if (last != first)
38446019292SAxel Dörfler 			fSequence << ":" << last;
38546019292SAxel Dörfler 	}
38646019292SAxel Dörfler 
38746019292SAxel Dörfler 	uids.erase(uids.begin(), uids.begin() + index);
38837d26ae5SAxel Dörfler }
38937d26ae5SAxel Dörfler 
39037d26ae5SAxel Dörfler 
391db0a4f2cSAxel Dörfler void
SetListener(FetchListener * listener)392db0a4f2cSAxel Dörfler FetchCommand::SetListener(FetchListener* listener)
39337d26ae5SAxel Dörfler {
394db0a4f2cSAxel Dörfler 	fListener = listener;
39537d26ae5SAxel Dörfler }
39637d26ae5SAxel Dörfler 
39737d26ae5SAxel Dörfler 
39837d26ae5SAxel Dörfler BString
CommandString()399db0a4f2cSAxel Dörfler FetchCommand::CommandString()
40037d26ae5SAxel Dörfler {
401db0a4f2cSAxel Dörfler 	BString command = "UID FETCH ";
40246019292SAxel Dörfler 	command += fSequence;
40337d26ae5SAxel Dörfler 
404db0a4f2cSAxel Dörfler 	command += " (UID ";
4053302df14SAxel Dörfler 	if ((fFlags & kFetchFlags) != 0)
4063302df14SAxel Dörfler 		command += "FLAGS ";
4073302df14SAxel Dörfler 	switch (fFlags & kFetchAll) {
408db0a4f2cSAxel Dörfler 		case kFetchHeader:
409db0a4f2cSAxel Dörfler 			command += "RFC822.HEADER";
41037d26ae5SAxel Dörfler 			break;
411db0a4f2cSAxel Dörfler 		case kFetchBody:
412db0a4f2cSAxel Dörfler 			command += "BODY.PEEK[TEXT]";
413db0a4f2cSAxel Dörfler 			break;
414db0a4f2cSAxel Dörfler 		case kFetchAll:
415db0a4f2cSAxel Dörfler 			command += "BODY.PEEK[]";
416db0a4f2cSAxel Dörfler 			break;
41737d26ae5SAxel Dörfler 	}
418db0a4f2cSAxel Dörfler 	command += ")";
41937d26ae5SAxel Dörfler 
42037d26ae5SAxel Dörfler 	return command;
42137d26ae5SAxel Dörfler }
42237d26ae5SAxel Dörfler 
42337d26ae5SAxel Dörfler 
42437d26ae5SAxel Dörfler bool
HandleUntagged(Response & response)425db0a4f2cSAxel Dörfler FetchCommand::HandleUntagged(Response& response)
42637d26ae5SAxel Dörfler {
427db0a4f2cSAxel Dörfler 	if (!response.EqualsAt(1, "FETCH") || !response.IsListAt(2))
42837d26ae5SAxel Dörfler 		return false;
42937d26ae5SAxel Dörfler 
4303302df14SAxel Dörfler 	ArgumentList& list = response.ListAt(2);
4313302df14SAxel Dörfler 	uint32 uid = 0;
4323302df14SAxel Dörfler 	uint32 flags = 0;
4333302df14SAxel Dörfler 
4343302df14SAxel Dörfler 	for (int32 i = 0; i < list.CountItems(); i += 2) {
4353302df14SAxel Dörfler 		if (list.EqualsAt(i, "UID") && list.IsNumberAt(i + 1))
4363302df14SAxel Dörfler 			uid = list.NumberAt(i + 1);
4373302df14SAxel Dörfler 		else if (list.EqualsAt(i, "FLAGS") && list.IsListAt(i + 1)) {
4383302df14SAxel Dörfler 			// Parse flags
4393302df14SAxel Dörfler 			ArgumentList& flagList = list.ListAt(i + 1);
4403302df14SAxel Dörfler 			flags = ParseFlags(flagList);
4413302df14SAxel Dörfler 		}
4423302df14SAxel Dörfler 	}
4433302df14SAxel Dörfler 
4443302df14SAxel Dörfler 	if (fListener != NULL)
4453302df14SAxel Dörfler 		fListener->FetchedData(fFlags, uid, flags);
44637d26ae5SAxel Dörfler 	return true;
44737d26ae5SAxel Dörfler }
44837d26ae5SAxel Dörfler 
44937d26ae5SAxel Dörfler 
45037d26ae5SAxel Dörfler bool
HandleLiteral(Response & response,ArgumentList & arguments,BDataIO & stream,size_t & length)4513302df14SAxel Dörfler FetchCommand::HandleLiteral(Response& response, ArgumentList& arguments,
452eba458b9SAxel Dörfler 	BDataIO& stream, size_t& length)
45337d26ae5SAxel Dörfler {
454db0a4f2cSAxel Dörfler 	if (fListener == NULL || !response.EqualsAt(1, "FETCH")
455db0a4f2cSAxel Dörfler 		|| !response.IsListAt(2))
45637d26ae5SAxel Dörfler 		return false;
45737d26ae5SAxel Dörfler 
4583302df14SAxel Dörfler 	return fListener->FetchData(fFlags, stream, length);
45937d26ae5SAxel Dörfler }
46037d26ae5SAxel Dörfler 
46137d26ae5SAxel Dörfler 
46237d26ae5SAxel Dörfler // #pragma mark -
46337d26ae5SAxel Dörfler 
46437d26ae5SAxel Dörfler 
SetFlagsCommand(uint32 uid,uint32 flags)465db0a4f2cSAxel Dörfler SetFlagsCommand::SetFlagsCommand(uint32 uid, uint32 flags)
46637d26ae5SAxel Dörfler 	:
467db0a4f2cSAxel Dörfler 	fUID(uid),
46837d26ae5SAxel Dörfler 	fFlags(flags)
46937d26ae5SAxel Dörfler {
47037d26ae5SAxel Dörfler }
47137d26ae5SAxel Dörfler 
47237d26ae5SAxel Dörfler 
47337d26ae5SAxel Dörfler BString
CommandString()47437d26ae5SAxel Dörfler SetFlagsCommand::CommandString()
47537d26ae5SAxel Dörfler {
47681805393SAxel Dörfler 	BString command = "UID STORE ";
477db0a4f2cSAxel Dörfler 	command << fUID << " FLAGS (" << GenerateFlagString(fFlags) << ")";
478db0a4f2cSAxel Dörfler 
47937d26ae5SAxel Dörfler 	return command;
48037d26ae5SAxel Dörfler }
48137d26ae5SAxel Dörfler 
48237d26ae5SAxel Dörfler 
48337d26ae5SAxel Dörfler bool
HandleUntagged(Response & response)484db0a4f2cSAxel Dörfler SetFlagsCommand::HandleUntagged(Response& response)
48537d26ae5SAxel Dörfler {
486db0a4f2cSAxel Dörfler 	// We're not that interested in the outcome, apparently
487db0a4f2cSAxel Dörfler 	return response.EqualsAt(1, "FETCH");
48837d26ae5SAxel Dörfler }
48937d26ae5SAxel Dörfler 
49037d26ae5SAxel Dörfler 
49137d26ae5SAxel Dörfler // #pragma mark -
49237d26ae5SAxel Dörfler 
49337d26ae5SAxel Dörfler 
494db0a4f2cSAxel Dörfler #if 0
49537d26ae5SAxel Dörfler AppendCommand::AppendCommand(IMAPMailbox& mailbox, BPositionIO& message,
49637d26ae5SAxel Dörfler 	off_t size, int32 flags, time_t time)
49737d26ae5SAxel Dörfler 	:
49837d26ae5SAxel Dörfler 	IMAPMailboxCommand(mailbox),
49937d26ae5SAxel Dörfler 
50037d26ae5SAxel Dörfler 	fMessageData(message),
50137d26ae5SAxel Dörfler 	fDataSize(size),
50237d26ae5SAxel Dörfler 	fFlags(flags),
50337d26ae5SAxel Dörfler 	fTime(time)
50437d26ae5SAxel Dörfler {
50537d26ae5SAxel Dörfler }
50637d26ae5SAxel Dörfler 
50737d26ae5SAxel Dörfler 
50837d26ae5SAxel Dörfler BString
50937d26ae5SAxel Dörfler AppendCommand::CommandString()
51037d26ae5SAxel Dörfler {
51137d26ae5SAxel Dörfler 	BString command = "APPEND ";
51237d26ae5SAxel Dörfler 	command << fIMAPMailbox.Mailbox();
51337d26ae5SAxel Dörfler 	command += " (";
51437d26ae5SAxel Dörfler 	command += SetFlagsCommand::GenerateFlagList(fFlags);
51537d26ae5SAxel Dörfler 	command += ")";
51637d26ae5SAxel Dörfler 	command += " {";
51737d26ae5SAxel Dörfler 	command << fDataSize;
51837d26ae5SAxel Dörfler 	command += "}";
51937d26ae5SAxel Dörfler 	return command;
52037d26ae5SAxel Dörfler }
52137d26ae5SAxel Dörfler 
52237d26ae5SAxel Dörfler 
52337d26ae5SAxel Dörfler bool
52437d26ae5SAxel Dörfler AppendCommand::HandleUntagged(const BString& response)
52537d26ae5SAxel Dörfler {
52637d26ae5SAxel Dörfler 	if (response.FindFirst("+") != 0)
52737d26ae5SAxel Dörfler 		return false;
52837d26ae5SAxel Dörfler 	fMessageData.Seek(0, SEEK_SET);
52937d26ae5SAxel Dörfler 
53037d26ae5SAxel Dörfler 	const int32 kBunchSize = 1024; // 1Kb
53137d26ae5SAxel Dörfler 	char buffer[kBunchSize];
53237d26ae5SAxel Dörfler 
53337d26ae5SAxel Dörfler 	int32 writeSize = fDataSize;
53437d26ae5SAxel Dörfler 	while (writeSize > 0) {
53537d26ae5SAxel Dörfler 		int32 bunchSize = writeSize < kBunchSize ? writeSize : kBunchSize;
53637d26ae5SAxel Dörfler 		fMessageData.Read(buffer, bunchSize);
53737d26ae5SAxel Dörfler 		int nWritten = fIMAPMailbox.SendRawData(buffer, bunchSize);
53837d26ae5SAxel Dörfler 		if (nWritten < 0)
53937d26ae5SAxel Dörfler 			return false;
54037d26ae5SAxel Dörfler 		writeSize -= nWritten;
54137d26ae5SAxel Dörfler 		TRACE("%i\n", (int)writeSize);
54237d26ae5SAxel Dörfler 	}
54337d26ae5SAxel Dörfler 
54437d26ae5SAxel Dörfler 	fIMAPMailbox.SendRawData(CRLF, strlen(CRLF));
54537d26ae5SAxel Dörfler 	return true;
54637d26ae5SAxel Dörfler }
54737d26ae5SAxel Dörfler #endif
54837d26ae5SAxel Dörfler 
54937d26ae5SAxel Dörfler 
55037d26ae5SAxel Dörfler // #pragma mark -
55137d26ae5SAxel Dörfler 
55237d26ae5SAxel Dörfler 
ExistsHandler()55337d26ae5SAxel Dörfler ExistsHandler::ExistsHandler()
55437d26ae5SAxel Dörfler {
55537d26ae5SAxel Dörfler }
55637d26ae5SAxel Dörfler 
55737d26ae5SAxel Dörfler 
5587993ddfaSAxel Dörfler void
SetListener(ExistsListener * listener)5597993ddfaSAxel Dörfler ExistsHandler::SetListener(ExistsListener* listener)
5607993ddfaSAxel Dörfler {
5617993ddfaSAxel Dörfler 	fListener = listener;
5627993ddfaSAxel Dörfler }
5637993ddfaSAxel Dörfler 
5647993ddfaSAxel Dörfler 
56537d26ae5SAxel Dörfler bool
HandleUntagged(Response & response)56637d26ae5SAxel Dörfler ExistsHandler::HandleUntagged(Response& response)
56737d26ae5SAxel Dörfler {
568229c7773SAxel Dörfler 	if (!response.EqualsAt(1, "EXISTS") || !response.IsNumberAt(0))
56937d26ae5SAxel Dörfler 		return false;
57037d26ae5SAxel Dörfler 
57146019292SAxel Dörfler 	uint32 count = response.NumberAt(0);
57237d26ae5SAxel Dörfler 
5737993ddfaSAxel Dörfler 	if (fListener != NULL)
57446019292SAxel Dörfler 		fListener->MessageExistsReceived(count);
57537d26ae5SAxel Dörfler 
57637d26ae5SAxel Dörfler 	return true;
57737d26ae5SAxel Dörfler }
57837d26ae5SAxel Dörfler 
57937d26ae5SAxel Dörfler 
58037d26ae5SAxel Dörfler // #pragma mark -
58137d26ae5SAxel Dörfler 
58237d26ae5SAxel Dörfler 
ExpungeCommand()58337d26ae5SAxel Dörfler ExpungeCommand::ExpungeCommand()
58437d26ae5SAxel Dörfler {
58537d26ae5SAxel Dörfler }
58637d26ae5SAxel Dörfler 
58737d26ae5SAxel Dörfler 
58837d26ae5SAxel Dörfler BString
CommandString()58937d26ae5SAxel Dörfler ExpungeCommand::CommandString()
59037d26ae5SAxel Dörfler {
59137d26ae5SAxel Dörfler 	return "EXPUNGE";
59237d26ae5SAxel Dörfler }
59337d26ae5SAxel Dörfler 
59437d26ae5SAxel Dörfler 
59537d26ae5SAxel Dörfler // #pragma mark -
59637d26ae5SAxel Dörfler 
59737d26ae5SAxel Dörfler 
ExpungeHandler()59837d26ae5SAxel Dörfler ExpungeHandler::ExpungeHandler()
59937d26ae5SAxel Dörfler {
60037d26ae5SAxel Dörfler }
60137d26ae5SAxel Dörfler 
60237d26ae5SAxel Dörfler 
603229c7773SAxel Dörfler void
SetListener(ExpungeListener * listener)604229c7773SAxel Dörfler ExpungeHandler::SetListener(ExpungeListener* listener)
605229c7773SAxel Dörfler {
606229c7773SAxel Dörfler 	fListener = listener;
607229c7773SAxel Dörfler }
608229c7773SAxel Dörfler 
609229c7773SAxel Dörfler 
61037d26ae5SAxel Dörfler bool
HandleUntagged(Response & response)61137d26ae5SAxel Dörfler ExpungeHandler::HandleUntagged(Response& response)
61237d26ae5SAxel Dörfler {
613229c7773SAxel Dörfler 	if (!response.EqualsAt(1, "EXPUNGE") || !response.IsNumberAt(0))
61437d26ae5SAxel Dörfler 		return false;
61537d26ae5SAxel Dörfler 
61646019292SAxel Dörfler 	uint32 index = response.NumberAt(0);
61737d26ae5SAxel Dörfler 
618229c7773SAxel Dörfler 	if (fListener != NULL)
619229c7773SAxel Dörfler 		fListener->MessageExpungeReceived(index);
62037d26ae5SAxel Dörfler 
62137d26ae5SAxel Dörfler 	return true;
62237d26ae5SAxel Dörfler }
62337d26ae5SAxel Dörfler 
62437d26ae5SAxel Dörfler 
62537d26ae5SAxel Dörfler // #pragma mark -
62637d26ae5SAxel Dörfler 
62737d26ae5SAxel Dörfler 
62837d26ae5SAxel Dörfler #if 0
62937d26ae5SAxel Dörfler FlagsHandler::FlagsHandler(IMAPMailbox& mailbox)
63037d26ae5SAxel Dörfler 	:
63137d26ae5SAxel Dörfler 	IMAPMailboxCommand(mailbox)
63237d26ae5SAxel Dörfler {
63337d26ae5SAxel Dörfler }
63437d26ae5SAxel Dörfler 
63537d26ae5SAxel Dörfler 
63637d26ae5SAxel Dörfler bool
63737d26ae5SAxel Dörfler FlagsHandler::HandleUntagged(const BString& response)
63837d26ae5SAxel Dörfler {
63937d26ae5SAxel Dörfler 	if (response.FindFirst("FETCH") < 0)
64037d26ae5SAxel Dörfler 		return false;
64137d26ae5SAxel Dörfler 
64237d26ae5SAxel Dörfler 	int32 fetch = 0;
64337d26ae5SAxel Dörfler 	if (!IMAPParser::ExtractUntagedFromLeft(response, "FETCH", fetch))
64437d26ae5SAxel Dörfler 		return false;
64537d26ae5SAxel Dörfler 
64637d26ae5SAxel Dörfler 	int32 flags = FetchMinMessageCommand::ExtractFlags(response);
64737d26ae5SAxel Dörfler 	int32 uid = fIMAPMailbox.MessageNumberToUID(fetch);
64837d26ae5SAxel Dörfler 	fStorage.SetFlags(uid, flags);
64937d26ae5SAxel Dörfler 	TRACE("FlagsHandler id %i flags %i\n", (int)fetch, (int)flags);
65037d26ae5SAxel Dörfler 	fIMAPMailbox.SendRawCommand("DONE");
65137d26ae5SAxel Dörfler 
65237d26ae5SAxel Dörfler 	return true;
65337d26ae5SAxel Dörfler }
65437d26ae5SAxel Dörfler #endif
65537d26ae5SAxel Dörfler 
65637d26ae5SAxel Dörfler 
65737d26ae5SAxel Dörfler // #pragma mark -
65837d26ae5SAxel Dörfler 
65937d26ae5SAxel Dörfler 
ListCommand(const char * prefix,bool subscribedOnly)6609192d4dcSAxel Dörfler ListCommand::ListCommand(const char* prefix, bool subscribedOnly)
6619192d4dcSAxel Dörfler 	:
6629192d4dcSAxel Dörfler 	fPrefix(prefix),
6639192d4dcSAxel Dörfler 	fSubscribedOnly(subscribedOnly)
6649192d4dcSAxel Dörfler {
6659192d4dcSAxel Dörfler }
6669192d4dcSAxel Dörfler 
6679192d4dcSAxel Dörfler 
66837d26ae5SAxel Dörfler BString
CommandString()66937d26ae5SAxel Dörfler ListCommand::CommandString()
67037d26ae5SAxel Dörfler {
6719192d4dcSAxel Dörfler 	BString command = _Command();
6729192d4dcSAxel Dörfler 	command += " \"\" \"";
6739192d4dcSAxel Dörfler 	if (fPrefix != NULL)
674fe262847SAxel Dörfler 		command << fEncoding.Encode(fPrefix) << "%";
6759192d4dcSAxel Dörfler 	else
6769192d4dcSAxel Dörfler 		command += "*";
6779192d4dcSAxel Dörfler 	command += "\"";
6789192d4dcSAxel Dörfler 
6799192d4dcSAxel Dörfler 	return command;
68037d26ae5SAxel Dörfler }
68137d26ae5SAxel Dörfler 
68237d26ae5SAxel Dörfler 
68337d26ae5SAxel Dörfler bool
HandleUntagged(Response & response)68437d26ae5SAxel Dörfler ListCommand::HandleUntagged(Response& response)
68537d26ae5SAxel Dörfler {
686a4bdd26dSAxel Dörfler 	if (response.IsCommand(_Command()) && response.IsStringAt(2)
687a4bdd26dSAxel Dörfler 		&& response.IsStringAt(3)) {
688a4bdd26dSAxel Dörfler 		fSeparator = response.StringAt(2);
689a4bdd26dSAxel Dörfler 
690*7d6cefebSAxel Dörfler 		if (response.IsListAt(1)) {
691*7d6cefebSAxel Dörfler 			// We're not supposed to select \Noselect mailboxes,
692*7d6cefebSAxel Dörfler 			// so we'll just hide them
693*7d6cefebSAxel Dörfler 			ArgumentList& attributes = response.ListAt(1);
694*7d6cefebSAxel Dörfler 			if (attributes.Contains("\\Noselect"))
695*7d6cefebSAxel Dörfler 				return true;
696*7d6cefebSAxel Dörfler 		}
697*7d6cefebSAxel Dörfler 
698fe262847SAxel Dörfler 		BString folder = response.StringAt(3);
699a4bdd26dSAxel Dörfler 		if (folder == "")
700a4bdd26dSAxel Dörfler 			return true;
701a4bdd26dSAxel Dörfler 
702fe262847SAxel Dörfler 		try {
703a4bdd26dSAxel Dörfler 			folder = fEncoding.Decode(folder);
704a4bdd26dSAxel Dörfler 			// The folder INBOX is always case insensitive
705a4bdd26dSAxel Dörfler 			if (folder.ICompare("INBOX") == 0)
706a4bdd26dSAxel Dörfler 				folder = "Inbox";
70729871039SAxel Dörfler 			fFolders.Add(folder);
708fe262847SAxel Dörfler 		} catch (ParseException& exception) {
709fe262847SAxel Dörfler 			// Decoding failed, just add the plain text
710fe262847SAxel Dörfler 			fprintf(stderr, "Decoding \"%s\" failed: %s\n", folder.String(),
711fe262847SAxel Dörfler 				exception.Message());
71229871039SAxel Dörfler 			fFolders.Add(folder);
713fe262847SAxel Dörfler 		}
71437d26ae5SAxel Dörfler 		return true;
71537d26ae5SAxel Dörfler 	}
71637d26ae5SAxel Dörfler 
71737d26ae5SAxel Dörfler 	return false;
71837d26ae5SAxel Dörfler }
71937d26ae5SAxel Dörfler 
72037d26ae5SAxel Dörfler 
72129871039SAxel Dörfler const BStringList&
FolderList()72237d26ae5SAxel Dörfler ListCommand::FolderList()
72337d26ae5SAxel Dörfler {
72437d26ae5SAxel Dörfler 	return fFolders;
72537d26ae5SAxel Dörfler }
72637d26ae5SAxel Dörfler 
72737d26ae5SAxel Dörfler 
7289192d4dcSAxel Dörfler const char*
_Command() const7299192d4dcSAxel Dörfler ListCommand::_Command() const
73037d26ae5SAxel Dörfler {
7319192d4dcSAxel Dörfler 	return fSubscribedOnly ? "LSUB" : "LIST";
73237d26ae5SAxel Dörfler }
73337d26ae5SAxel Dörfler 
73437d26ae5SAxel Dörfler 
73537d26ae5SAxel Dörfler // #pragma mark -
73637d26ae5SAxel Dörfler 
73737d26ae5SAxel Dörfler 
SubscribeCommand(const char * mailboxName)73837d26ae5SAxel Dörfler SubscribeCommand::SubscribeCommand(const char* mailboxName)
73937d26ae5SAxel Dörfler 	:
74037d26ae5SAxel Dörfler 	fMailboxName(mailboxName)
74137d26ae5SAxel Dörfler {
74237d26ae5SAxel Dörfler }
74337d26ae5SAxel Dörfler 
74437d26ae5SAxel Dörfler 
74537d26ae5SAxel Dörfler BString
CommandString()74637d26ae5SAxel Dörfler SubscribeCommand::CommandString()
74737d26ae5SAxel Dörfler {
74837d26ae5SAxel Dörfler 	BString command = "SUBSCRIBE \"";
74937d26ae5SAxel Dörfler 	command += fMailboxName;
75037d26ae5SAxel Dörfler 	command += "\"";
75137d26ae5SAxel Dörfler 	return command;
75237d26ae5SAxel Dörfler }
75337d26ae5SAxel Dörfler 
75437d26ae5SAxel Dörfler 
75537d26ae5SAxel Dörfler // #pragma mark -
75637d26ae5SAxel Dörfler 
75737d26ae5SAxel Dörfler 
UnsubscribeCommand(const char * mailboxName)75837d26ae5SAxel Dörfler UnsubscribeCommand::UnsubscribeCommand(const char* mailboxName)
75937d26ae5SAxel Dörfler 	:
76037d26ae5SAxel Dörfler 	fMailboxName(mailboxName)
76137d26ae5SAxel Dörfler {
76237d26ae5SAxel Dörfler }
76337d26ae5SAxel Dörfler 
76437d26ae5SAxel Dörfler 
76537d26ae5SAxel Dörfler BString
CommandString()76637d26ae5SAxel Dörfler UnsubscribeCommand::CommandString()
76737d26ae5SAxel Dörfler {
76837d26ae5SAxel Dörfler 	BString command = "UNSUBSCRIBE \"";
76937d26ae5SAxel Dörfler 	command += fMailboxName;
77037d26ae5SAxel Dörfler 	command += "\"";
77137d26ae5SAxel Dörfler 	return command;
77237d26ae5SAxel Dörfler }
77337d26ae5SAxel Dörfler 
77437d26ae5SAxel Dörfler 
77537d26ae5SAxel Dörfler // #pragma mark -
77637d26ae5SAxel Dörfler 
77737d26ae5SAxel Dörfler 
GetQuotaCommand(const char * mailboxName)77837d26ae5SAxel Dörfler GetQuotaCommand::GetQuotaCommand(const char* mailboxName)
77937d26ae5SAxel Dörfler 	:
78037d26ae5SAxel Dörfler 	fMailboxName(mailboxName),
78137d26ae5SAxel Dörfler 	fUsedStorage(0),
78237d26ae5SAxel Dörfler 	fTotalStorage(0)
78337d26ae5SAxel Dörfler {
78437d26ae5SAxel Dörfler }
78537d26ae5SAxel Dörfler 
78637d26ae5SAxel Dörfler 
78737d26ae5SAxel Dörfler BString
CommandString()78837d26ae5SAxel Dörfler GetQuotaCommand::CommandString()
78937d26ae5SAxel Dörfler {
790cc3aa99cSAxel Dörfler 	BString command = "GETQUOTAROOT \"";
79137d26ae5SAxel Dörfler 	command += fMailboxName;
79237d26ae5SAxel Dörfler 	command += "\"";
79337d26ae5SAxel Dörfler 	return command;
79437d26ae5SAxel Dörfler }
79537d26ae5SAxel Dörfler 
79637d26ae5SAxel Dörfler 
79737d26ae5SAxel Dörfler bool
HandleUntagged(Response & response)79837d26ae5SAxel Dörfler GetQuotaCommand::HandleUntagged(Response& response)
79937d26ae5SAxel Dörfler {
800cc3aa99cSAxel Dörfler 	if (!response.IsCommand("QUOTA") || !response.IsListAt(2))
80137d26ae5SAxel Dörfler 		return false;
80237d26ae5SAxel Dörfler 
803cc3aa99cSAxel Dörfler 	const ArgumentList& arguments = response.ListAt(2);
804cc3aa99cSAxel Dörfler 	if (!arguments.EqualsAt(0, "STORAGE"))
805cc3aa99cSAxel Dörfler 		return false;
806cc3aa99cSAxel Dörfler 
807cc3aa99cSAxel Dörfler 	fUsedStorage = (uint64)arguments.NumberAt(1) * 1024;
808cc3aa99cSAxel Dörfler 	fTotalStorage = (uint64)arguments.NumberAt(2) * 1024;
80937d26ae5SAxel Dörfler 
81037d26ae5SAxel Dörfler 	return true;
81137d26ae5SAxel Dörfler }
81237d26ae5SAxel Dörfler 
81337d26ae5SAxel Dörfler 
81437d26ae5SAxel Dörfler uint64
UsedStorage()81537d26ae5SAxel Dörfler GetQuotaCommand::UsedStorage()
81637d26ae5SAxel Dörfler {
81737d26ae5SAxel Dörfler 	return fUsedStorage;
81837d26ae5SAxel Dörfler }
81937d26ae5SAxel Dörfler 
82037d26ae5SAxel Dörfler 
82137d26ae5SAxel Dörfler uint64
TotalStorage()82237d26ae5SAxel Dörfler GetQuotaCommand::TotalStorage()
82337d26ae5SAxel Dörfler {
82437d26ae5SAxel Dörfler 	return fTotalStorage;
82537d26ae5SAxel Dörfler }
82637d26ae5SAxel Dörfler 
82737d26ae5SAxel Dörfler 
82837d26ae5SAxel Dörfler }	// namespace
829