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