xref: /haiku/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Protocol.cpp (revision e378617b62dcb9a1544717b5b8366c9ff4262803)
137d26ae5SAxel Dörfler /*
2f429e4f4SAxel Dörfler  * Copyright 2010-2016, Haiku Inc. All Rights Reserved.
337d26ae5SAxel Dörfler  * Copyright 2010 Clemens Zeidler. All rights reserved.
437d26ae5SAxel Dörfler  *
537d26ae5SAxel Dörfler  * Distributed under the terms of the MIT License.
637d26ae5SAxel Dörfler  */
737d26ae5SAxel Dörfler 
837d26ae5SAxel Dörfler 
937d26ae5SAxel Dörfler #include "Protocol.h"
1037d26ae5SAxel Dörfler 
1137d26ae5SAxel Dörfler #include "Commands.h"
1237d26ae5SAxel Dörfler 
1337d26ae5SAxel Dörfler 
1437d26ae5SAxel Dörfler #define DEBUG_IMAP_PROTOCOL
1537d26ae5SAxel Dörfler #ifdef DEBUG_IMAP_PROTOCOL
1637d26ae5SAxel Dörfler #	include <stdio.h>
1737d26ae5SAxel Dörfler #	define TRACE(...) printf(__VA_ARGS__)
1837d26ae5SAxel Dörfler #else
1937d26ae5SAxel Dörfler #	define TRACE(...) ;
2037d26ae5SAxel Dörfler #endif
2137d26ae5SAxel Dörfler 
2237d26ae5SAxel Dörfler 
2337d26ae5SAxel Dörfler namespace IMAP {
2437d26ae5SAxel Dörfler 
2537d26ae5SAxel Dörfler 
Protocol()2637d26ae5SAxel Dörfler Protocol::Protocol()
2737d26ae5SAxel Dörfler 	:
2837d26ae5SAxel Dörfler 	fSocket(NULL),
2937d26ae5SAxel Dörfler 	fBufferedSocket(NULL),
307993ddfaSAxel Dörfler 	fHandlerList(5, false),
3137d26ae5SAxel Dörfler 	fCommandID(0),
3237d26ae5SAxel Dörfler 	fIsConnected(false)
3337d26ae5SAxel Dörfler {
3437d26ae5SAxel Dörfler }
3537d26ae5SAxel Dörfler 
3637d26ae5SAxel Dörfler 
~Protocol()3737d26ae5SAxel Dörfler Protocol::~Protocol()
3837d26ae5SAxel Dörfler {
3937d26ae5SAxel Dörfler 	delete fSocket;
4037d26ae5SAxel Dörfler 	delete fBufferedSocket;
4137d26ae5SAxel Dörfler }
4237d26ae5SAxel Dörfler 
4337d26ae5SAxel Dörfler 
4437d26ae5SAxel Dörfler status_t
Connect(const BNetworkAddress & address,const char * username,const char * password,bool useSSL)4537d26ae5SAxel Dörfler Protocol::Connect(const BNetworkAddress& address, const char* username,
4637d26ae5SAxel Dörfler 	const char* password, bool useSSL)
4737d26ae5SAxel Dörfler {
4837d26ae5SAxel Dörfler 	TRACE("Connect\n");
4937d26ae5SAxel Dörfler 	if (useSSL)
5037d26ae5SAxel Dörfler 		fSocket = new(std::nothrow) BSecureSocket(address);
5137d26ae5SAxel Dörfler 	else
5237d26ae5SAxel Dörfler 		fSocket = new(std::nothrow) BSocket(address);
5337d26ae5SAxel Dörfler 
5437d26ae5SAxel Dörfler 	if (fSocket == NULL)
5537d26ae5SAxel Dörfler 		return B_NO_MEMORY;
5637d26ae5SAxel Dörfler 
5737d26ae5SAxel Dörfler 	status_t status = fSocket->InitCheck();
5837d26ae5SAxel Dörfler 	if (status != B_OK)
5937d26ae5SAxel Dörfler 		return status;
6037d26ae5SAxel Dörfler 
6137d26ae5SAxel Dörfler 	fBufferedSocket = new(std::nothrow) BBufferedDataIO(*fSocket, 32768, false,
6237d26ae5SAxel Dörfler 		true);
6337d26ae5SAxel Dörfler 	if (fBufferedSocket == NULL)
6437d26ae5SAxel Dörfler 		return B_NO_MEMORY;
6537d26ae5SAxel Dörfler 
6637d26ae5SAxel Dörfler 	TRACE("Login\n");
6737d26ae5SAxel Dörfler 
6837d26ae5SAxel Dörfler 	fIsConnected = true;
6937d26ae5SAxel Dörfler 
7037d26ae5SAxel Dörfler 	LoginCommand login(username, password);
7137d26ae5SAxel Dörfler 	status = ProcessCommand(login);
7237d26ae5SAxel Dörfler 	if (status != B_OK) {
7337d26ae5SAxel Dörfler 		_Disconnect();
7437d26ae5SAxel Dörfler 		return status;
7537d26ae5SAxel Dörfler 	}
7637d26ae5SAxel Dörfler 
7737d26ae5SAxel Dörfler 	_ParseCapabilities(login.Capabilities());
7817044801SAxel Dörfler 
7917044801SAxel Dörfler 	if (fCapabilities.IsEmpty()) {
8017044801SAxel Dörfler 		CapabilityHandler capabilityHandler;
8117044801SAxel Dörfler 		status = ProcessCommand(capabilityHandler);
8217044801SAxel Dörfler 		if (status != B_OK)
8317044801SAxel Dörfler 			return status;
8417044801SAxel Dörfler 
8517044801SAxel Dörfler 		_ParseCapabilities(capabilityHandler.Capabilities());
8617044801SAxel Dörfler 	}
8717044801SAxel Dörfler 
883302df14SAxel Dörfler 	if (Capabilities().Contains("ID")) {
893302df14SAxel Dörfler 		// Get the server's ID into our log
903302df14SAxel Dörfler 		class IDCommand : public IMAP::Command, public IMAP::Handler {
913302df14SAxel Dörfler 		public:
923302df14SAxel Dörfler 			BString CommandString()
933302df14SAxel Dörfler 			{
943302df14SAxel Dörfler 				return "ID NIL";
953302df14SAxel Dörfler 			}
963302df14SAxel Dörfler 
973302df14SAxel Dörfler 			bool HandleUntagged(IMAP::Response& response)
983302df14SAxel Dörfler 			{
993302df14SAxel Dörfler 				if (response.IsCommand("ID") && response.IsListAt(1)) {
1003302df14SAxel Dörfler 					puts("Server:");
1013302df14SAxel Dörfler 					ArgumentList& list = response.ListAt(1);
1023302df14SAxel Dörfler 					for (int32 i = 0; i < list.CountItems(); i += 2) {
1033302df14SAxel Dörfler 						printf("  %s: %s\n",
1043302df14SAxel Dörfler 							list.ItemAt(i)->ToString().String(),
1053302df14SAxel Dörfler 							list.ItemAt(i + 1)->ToString().String());
1063302df14SAxel Dörfler 					}
1073302df14SAxel Dörfler 					return true;
1083302df14SAxel Dörfler 				}
1093302df14SAxel Dörfler 
1103302df14SAxel Dörfler 				return false;
1113302df14SAxel Dörfler 			}
1123302df14SAxel Dörfler 		};
1133302df14SAxel Dörfler 		IDCommand idCommand;
1143302df14SAxel Dörfler 		ProcessCommand(idCommand);
1153302df14SAxel Dörfler 	}
11637d26ae5SAxel Dörfler 	return B_OK;
11737d26ae5SAxel Dörfler }
11837d26ae5SAxel Dörfler 
11937d26ae5SAxel Dörfler 
12037d26ae5SAxel Dörfler status_t
Disconnect()12137d26ae5SAxel Dörfler Protocol::Disconnect()
12237d26ae5SAxel Dörfler {
12337d26ae5SAxel Dörfler 	if (IsConnected()) {
12437d26ae5SAxel Dörfler 		RawCommand command("LOGOUT");
12537d26ae5SAxel Dörfler 		ProcessCommand(command);
12637d26ae5SAxel Dörfler 	}
12737d26ae5SAxel Dörfler 	return _Disconnect();
12837d26ae5SAxel Dörfler }
12937d26ae5SAxel Dörfler 
13037d26ae5SAxel Dörfler 
13137d26ae5SAxel Dörfler bool
IsConnected()13237d26ae5SAxel Dörfler Protocol::IsConnected()
13337d26ae5SAxel Dörfler {
13437d26ae5SAxel Dörfler 	return fIsConnected;
13537d26ae5SAxel Dörfler }
13637d26ae5SAxel Dörfler 
13737d26ae5SAxel Dörfler 
1387993ddfaSAxel Dörfler bool
AddHandler(Handler & handler)1397993ddfaSAxel Dörfler Protocol::AddHandler(Handler& handler)
1407993ddfaSAxel Dörfler {
1417993ddfaSAxel Dörfler 	return fHandlerList.AddItem(&handler);
1427993ddfaSAxel Dörfler }
1437993ddfaSAxel Dörfler 
1447993ddfaSAxel Dörfler 
1457993ddfaSAxel Dörfler void
RemoveHandler(Handler & handler)1467993ddfaSAxel Dörfler Protocol::RemoveHandler(Handler& handler)
1477993ddfaSAxel Dörfler {
1487993ddfaSAxel Dörfler 	fHandlerList.RemoveItem(&handler);
1497993ddfaSAxel Dörfler }
1507993ddfaSAxel Dörfler 
1517993ddfaSAxel Dörfler 
15237d26ae5SAxel Dörfler status_t
GetFolders(FolderList & folders,BString & separator)153a4bdd26dSAxel Dörfler Protocol::GetFolders(FolderList& folders, BString& separator)
15437d26ae5SAxel Dörfler {
15529871039SAxel Dörfler 	BStringList allFolders;
15637d26ae5SAxel Dörfler 	status_t status = _GetAllFolders(allFolders);
15737d26ae5SAxel Dörfler 	if (status != B_OK)
15837d26ae5SAxel Dörfler 		return status;
15937d26ae5SAxel Dörfler 
16029871039SAxel Dörfler 	BStringList subscribedFolders;
161a4bdd26dSAxel Dörfler 	status = GetSubscribedFolders(subscribedFolders, separator);
16237d26ae5SAxel Dörfler 	if (status != B_OK)
16337d26ae5SAxel Dörfler 		return status;
16437d26ae5SAxel Dörfler 
16529871039SAxel Dörfler 	for (int32 i = 0; i < allFolders.CountStrings(); i++) {
1669192d4dcSAxel Dörfler 		FolderEntry entry;
16729871039SAxel Dörfler 		entry.folder = allFolders.StringAt(i);
16829871039SAxel Dörfler 		for (int32 j = 0; j < subscribedFolders.CountStrings(); j++) {
169*e378617bSDave Thompson 			if (entry.folder == subscribedFolders.StringAt(j)) {
1709192d4dcSAxel Dörfler 				entry.subscribed = true;
17137d26ae5SAxel Dörfler 				break;
17237d26ae5SAxel Dörfler 			}
17337d26ae5SAxel Dörfler 		}
1749192d4dcSAxel Dörfler 		folders.push_back(entry);
17537d26ae5SAxel Dörfler 	}
17637d26ae5SAxel Dörfler 
17737d26ae5SAxel Dörfler 	// you could be subscribed to a folder which not exist currently, add them:
17829871039SAxel Dörfler 	for (int32 i = 0; i < subscribedFolders.CountStrings(); i++) {
17937d26ae5SAxel Dörfler 		bool isInlist = false;
18029871039SAxel Dörfler 		for (int32 j = 0; j < allFolders.CountStrings(); j++) {
18129871039SAxel Dörfler 			if (subscribedFolders.StringAt(i) == allFolders.StringAt(j)) {
18237d26ae5SAxel Dörfler 				isInlist = true;
18337d26ae5SAxel Dörfler 				break;
18437d26ae5SAxel Dörfler 			}
18537d26ae5SAxel Dörfler 		}
18637d26ae5SAxel Dörfler 		if (isInlist)
18737d26ae5SAxel Dörfler 			continue;
18837d26ae5SAxel Dörfler 
1899192d4dcSAxel Dörfler 		FolderEntry entry;
19029871039SAxel Dörfler 		entry.folder = subscribedFolders.StringAt(i);
1919192d4dcSAxel Dörfler 		entry.subscribed = true;
1929192d4dcSAxel Dörfler 		folders.push_back(entry);
19337d26ae5SAxel Dörfler 	}
19437d26ae5SAxel Dörfler 
19537d26ae5SAxel Dörfler 	return B_OK;
19637d26ae5SAxel Dörfler }
19737d26ae5SAxel Dörfler 
19837d26ae5SAxel Dörfler 
19937d26ae5SAxel Dörfler status_t
GetSubscribedFolders(BStringList & folders,BString & separator)20029871039SAxel Dörfler Protocol::GetSubscribedFolders(BStringList& folders, BString& separator)
201adbe8fc9SAxel Dörfler {
202adbe8fc9SAxel Dörfler 	ListCommand command(NULL, true);
203adbe8fc9SAxel Dörfler 	status_t status = ProcessCommand(command);
204adbe8fc9SAxel Dörfler 	if (status != B_OK)
205adbe8fc9SAxel Dörfler 		return status;
206adbe8fc9SAxel Dörfler 
207adbe8fc9SAxel Dörfler 	folders = command.FolderList();
208a4bdd26dSAxel Dörfler 	separator = command.Separator();
209adbe8fc9SAxel Dörfler 	return status;
210adbe8fc9SAxel Dörfler }
211adbe8fc9SAxel Dörfler 
212adbe8fc9SAxel Dörfler 
213adbe8fc9SAxel Dörfler status_t
SubscribeFolder(const char * folder)21437d26ae5SAxel Dörfler Protocol::SubscribeFolder(const char* folder)
21537d26ae5SAxel Dörfler {
21637d26ae5SAxel Dörfler 	SubscribeCommand command(folder);
21737d26ae5SAxel Dörfler 	return ProcessCommand(command);
21837d26ae5SAxel Dörfler }
21937d26ae5SAxel Dörfler 
22037d26ae5SAxel Dörfler 
22137d26ae5SAxel Dörfler status_t
UnsubscribeFolder(const char * folder)22237d26ae5SAxel Dörfler Protocol::UnsubscribeFolder(const char* folder)
22337d26ae5SAxel Dörfler {
22437d26ae5SAxel Dörfler 	UnsubscribeCommand command(folder);
22537d26ae5SAxel Dörfler 	return ProcessCommand(command);
22637d26ae5SAxel Dörfler }
22737d26ae5SAxel Dörfler 
22837d26ae5SAxel Dörfler 
22937d26ae5SAxel Dörfler status_t
GetQuota(uint64 & used,uint64 & total)23037d26ae5SAxel Dörfler Protocol::GetQuota(uint64& used, uint64& total)
23137d26ae5SAxel Dörfler {
23237d26ae5SAxel Dörfler 	if (!Capabilities().Contains("QUOTA"))
23337d26ae5SAxel Dörfler 		return B_ERROR;
23437d26ae5SAxel Dörfler 
23537d26ae5SAxel Dörfler 	GetQuotaCommand quotaCommand;
23637d26ae5SAxel Dörfler 	status_t status = ProcessCommand(quotaCommand);
23737d26ae5SAxel Dörfler 	if (status != B_OK)
23837d26ae5SAxel Dörfler 		return status;
23937d26ae5SAxel Dörfler 
24037d26ae5SAxel Dörfler 	used = quotaCommand.UsedStorage();
24137d26ae5SAxel Dörfler 	total = quotaCommand.TotalStorage();
24237d26ae5SAxel Dörfler 	return B_OK;
24337d26ae5SAxel Dörfler }
24437d26ae5SAxel Dörfler 
24537d26ae5SAxel Dörfler 
24637d26ae5SAxel Dörfler status_t
SendCommand(const char * command)24737d26ae5SAxel Dörfler Protocol::SendCommand(const char* command)
24837d26ae5SAxel Dörfler {
24937d26ae5SAxel Dörfler 	return SendCommand(0, command);
25037d26ae5SAxel Dörfler }
25137d26ae5SAxel Dörfler 
25237d26ae5SAxel Dörfler 
25337d26ae5SAxel Dörfler status_t
SendCommand(int32 id,const char * command)25437d26ae5SAxel Dörfler Protocol::SendCommand(int32 id, const char* command)
25537d26ae5SAxel Dörfler {
25637d26ae5SAxel Dörfler 	char buffer[2048];
25737d26ae5SAxel Dörfler 	int32 length;
258b9962ceaSJérôme Duval 	if (id > 0) {
259b9962ceaSJérôme Duval 		length = snprintf(buffer, sizeof(buffer), "A%.7" B_PRId32 " %s\r\n",
260b9962ceaSJérôme Duval 			id, command);
261b9962ceaSJérôme Duval 	} else
26237d26ae5SAxel Dörfler 		length = snprintf(buffer, sizeof(buffer), "%s\r\n", command);
26337d26ae5SAxel Dörfler 
264db0a4f2cSAxel Dörfler 	TRACE("C: %s", buffer);
265db0a4f2cSAxel Dörfler 
26637d26ae5SAxel Dörfler 	ssize_t bytesWritten = fSocket->Write(buffer, length);
26737d26ae5SAxel Dörfler 	if (bytesWritten < 0)
26837d26ae5SAxel Dörfler 		return bytesWritten;
26937d26ae5SAxel Dörfler 
27037d26ae5SAxel Dörfler 	return bytesWritten == length ? B_OK : B_ERROR;
27137d26ae5SAxel Dörfler }
27237d26ae5SAxel Dörfler 
27337d26ae5SAxel Dörfler 
274b9962ceaSJérôme Duval ssize_t
SendData(const char * buffer,uint32 length)27537d26ae5SAxel Dörfler Protocol::SendData(const char* buffer, uint32 length)
27637d26ae5SAxel Dörfler {
27737d26ae5SAxel Dörfler 	return fSocket->Write(buffer, length);
27837d26ae5SAxel Dörfler }
27937d26ae5SAxel Dörfler 
28037d26ae5SAxel Dörfler 
28137d26ae5SAxel Dörfler status_t
ProcessCommand(Command & command,bigtime_t timeout)28237d26ae5SAxel Dörfler Protocol::ProcessCommand(Command& command, bigtime_t timeout)
28337d26ae5SAxel Dörfler {
2847993ddfaSAxel Dörfler 	BString commandString = command.CommandString();
2857993ddfaSAxel Dörfler 	if (commandString.IsEmpty())
2867993ddfaSAxel Dörfler 		return B_BAD_VALUE;
28737d26ae5SAxel Dörfler 
2887993ddfaSAxel Dörfler 	Handler* handler = dynamic_cast<Handler*>(&command);
2897993ddfaSAxel Dörfler 	if (handler != NULL && !AddHandler(*handler))
2907993ddfaSAxel Dörfler 		return B_NO_MEMORY;
2917993ddfaSAxel Dörfler 
2927993ddfaSAxel Dörfler 	int32 commandID = NextCommandID();
2937993ddfaSAxel Dörfler 	status_t status = SendCommand(commandID, commandString.String());
2947993ddfaSAxel Dörfler 	if (status == B_OK) {
2957993ddfaSAxel Dörfler 		fOngoingCommands[commandID] = &command;
2967993ddfaSAxel Dörfler 		status = HandleResponse(&command, timeout);
2977993ddfaSAxel Dörfler 	}
2987993ddfaSAxel Dörfler 
2997993ddfaSAxel Dörfler 	if (handler != NULL)
3007993ddfaSAxel Dörfler 		RemoveHandler(*handler);
30137d26ae5SAxel Dörfler 
30237d26ae5SAxel Dörfler 	return status;
30337d26ae5SAxel Dörfler }
30437d26ae5SAxel Dörfler 
30537d26ae5SAxel Dörfler 
3067993ddfaSAxel Dörfler // #pragma mark - protected
3077993ddfaSAxel Dörfler 
3087993ddfaSAxel Dörfler 
30937d26ae5SAxel Dörfler status_t
HandleResponse(Command * command,bigtime_t timeout,bool disconnectOnTimeout)310077338a9SAxel Dörfler Protocol::HandleResponse(Command* command, bigtime_t timeout,
311077338a9SAxel Dörfler 	bool disconnectOnTimeout)
31237d26ae5SAxel Dörfler {
31337d26ae5SAxel Dörfler 	status_t commandStatus = B_OK;
314a5170470SAxel Dörfler 	IMAP::ResponseParser parser(*fBufferedSocket);
315077338a9SAxel Dörfler 	if (IMAP::LiteralHandler* literalHandler
316077338a9SAxel Dörfler 			= dynamic_cast<IMAP::LiteralHandler*>(command))
317077338a9SAxel Dörfler 		parser.SetLiteralHandler(literalHandler);
318077338a9SAxel Dörfler 
31937d26ae5SAxel Dörfler 	IMAP::Response response;
32037d26ae5SAxel Dörfler 
32137d26ae5SAxel Dörfler 	bool done = false;
32237d26ae5SAxel Dörfler 	while (!done) {
32337d26ae5SAxel Dörfler 		try {
32437d26ae5SAxel Dörfler 			status_t status = parser.NextResponse(response, timeout);
32537d26ae5SAxel Dörfler 			if (status != B_OK) {
32637d26ae5SAxel Dörfler 				// we might have lost the connection, clear the connection state
32737d26ae5SAxel Dörfler 				if (status != B_TIMED_OUT || disconnectOnTimeout)
32837d26ae5SAxel Dörfler 					_Disconnect();
32937d26ae5SAxel Dörfler 
33037d26ae5SAxel Dörfler 				return status;
33137d26ae5SAxel Dörfler 			}
33237d26ae5SAxel Dörfler 
33337d26ae5SAxel Dörfler 			if (response.IsUntagged() || response.IsContinuation()) {
33437d26ae5SAxel Dörfler 				bool handled = false;
3357993ddfaSAxel Dörfler 				for (int32 i = fHandlerList.CountItems(); i-- > 0;) {
33637d26ae5SAxel Dörfler 					if (fHandlerList.ItemAt(i)->HandleUntagged(response)) {
33737d26ae5SAxel Dörfler 						handled = true;
33837d26ae5SAxel Dörfler 						break;
33937d26ae5SAxel Dörfler 					}
34037d26ae5SAxel Dörfler 				}
34137d26ae5SAxel Dörfler 				if (!handled)
34237d26ae5SAxel Dörfler 					printf("Unhandled S: %s\n", response.ToString().String());
34337d26ae5SAxel Dörfler 			} else {
34437d26ae5SAxel Dörfler 				CommandIDMap::iterator found
34537d26ae5SAxel Dörfler 					= fOngoingCommands.find(response.Tag());
34637d26ae5SAxel Dörfler 				if (found != fOngoingCommands.end()) {
34737d26ae5SAxel Dörfler 					status_t status = found->second->HandleTagged(response);
34837d26ae5SAxel Dörfler 					if (status != B_OK)
34937d26ae5SAxel Dörfler 						commandStatus = status;
35037d26ae5SAxel Dörfler 
35137d26ae5SAxel Dörfler 					fOngoingCommands.erase(found);
35237d26ae5SAxel Dörfler 				} else
35337d26ae5SAxel Dörfler 					printf("Unknown tag S: %s\n", response.ToString().String());
35437d26ae5SAxel Dörfler 			}
355a5170470SAxel Dörfler 		} catch (ParseException& exception) {
35637d26ae5SAxel Dörfler 			printf("Error during parsing: %s\n", exception.Message());
357f429e4f4SAxel Dörfler 		} catch (StreamException& exception) {
358f429e4f4SAxel Dörfler 			return exception.Status();
35937d26ae5SAxel Dörfler 		}
36037d26ae5SAxel Dörfler 
36137d26ae5SAxel Dörfler 		if (fOngoingCommands.size() == 0)
36237d26ae5SAxel Dörfler 			done = true;
36337d26ae5SAxel Dörfler 	}
36437d26ae5SAxel Dörfler 
36537d26ae5SAxel Dörfler 	return commandStatus;
36637d26ae5SAxel Dörfler }
36737d26ae5SAxel Dörfler 
36837d26ae5SAxel Dörfler 
36937d26ae5SAxel Dörfler int32
NextCommandID()37037d26ae5SAxel Dörfler Protocol::NextCommandID()
37137d26ae5SAxel Dörfler {
37237d26ae5SAxel Dörfler 	fCommandID++;
37337d26ae5SAxel Dörfler 	return fCommandID;
37437d26ae5SAxel Dörfler }
37537d26ae5SAxel Dörfler 
37637d26ae5SAxel Dörfler 
3777993ddfaSAxel Dörfler // #pragma mark - private
37837d26ae5SAxel Dörfler 
37937d26ae5SAxel Dörfler 
38037d26ae5SAxel Dörfler status_t
_Disconnect()38137d26ae5SAxel Dörfler Protocol::_Disconnect()
38237d26ae5SAxel Dörfler {
38337d26ae5SAxel Dörfler 	fOngoingCommands.clear();
38437d26ae5SAxel Dörfler 	fIsConnected = false;
3859192d4dcSAxel Dörfler 	delete fBufferedSocket;
3869192d4dcSAxel Dörfler 	fBufferedSocket = NULL;
38737d26ae5SAxel Dörfler 	delete fSocket;
38837d26ae5SAxel Dörfler 	fSocket = NULL;
3899192d4dcSAxel Dörfler 
39037d26ae5SAxel Dörfler 	return B_OK;
39137d26ae5SAxel Dörfler }
39237d26ae5SAxel Dörfler 
39337d26ae5SAxel Dörfler 
39437d26ae5SAxel Dörfler status_t
_GetAllFolders(BStringList & folders)39529871039SAxel Dörfler Protocol::_GetAllFolders(BStringList& folders)
39637d26ae5SAxel Dörfler {
3979192d4dcSAxel Dörfler 	ListCommand command(NULL, false);
3989192d4dcSAxel Dörfler 	status_t status = ProcessCommand(command);
39937d26ae5SAxel Dörfler 	if (status != B_OK)
40037d26ae5SAxel Dörfler 		return status;
40137d26ae5SAxel Dörfler 
4029192d4dcSAxel Dörfler 	folders = command.FolderList();
40337d26ae5SAxel Dörfler 	return status;
40437d26ae5SAxel Dörfler }
40537d26ae5SAxel Dörfler 
40637d26ae5SAxel Dörfler 
40737d26ae5SAxel Dörfler void
_ParseCapabilities(const ArgumentList & arguments)40837d26ae5SAxel Dörfler Protocol::_ParseCapabilities(const ArgumentList& arguments)
40937d26ae5SAxel Dörfler {
41037d26ae5SAxel Dörfler 	fCapabilities.MakeEmpty();
41137d26ae5SAxel Dörfler 
41237d26ae5SAxel Dörfler 	for (int32 i = 0; i < arguments.CountItems(); i++) {
41337d26ae5SAxel Dörfler 		if (StringArgument* argument
41437d26ae5SAxel Dörfler 				= dynamic_cast<StringArgument*>(arguments.ItemAt(i)))
41537d26ae5SAxel Dörfler 			fCapabilities.AddItem(new StringArgument(*argument));
41637d26ae5SAxel Dörfler 	}
41737d26ae5SAxel Dörfler 
41837d26ae5SAxel Dörfler 	TRACE("capabilities: %s\n", fCapabilities.ToString().String());
41937d26ae5SAxel Dörfler }
42037d26ae5SAxel Dörfler 
42137d26ae5SAxel Dörfler 
42237d26ae5SAxel Dörfler }	// namespace IMAP
423