From 184619e6257232f484e4e10a64ee29a53c278a42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Thu, 3 Dec 2015 21:30:37 +0100 Subject: [PATCH] IMAP: removed superfluous files from the old implementation. --- .../mail_daemon/inbound_protocols/imap/IMAP.h | 143 ---- .../imap/IMAPInboundProtocol.cpp | 615 ------------------ .../imap/IMAPInboundProtocol.h | 143 ---- .../imap/IMAPRootInboundProtocol.cpp | 185 ------ .../imap/IMAPRootInboundProtocol.h | 51 -- .../imap/imap_lib/IMAPMailbox.cpp | 304 --------- .../imap/imap_lib/IMAPMailbox.h | 98 --- .../imap/imap_lib/IMAPStorage.cpp | 513 --------------- .../imap/imap_lib/IMAPStorage.h | 102 --- 9 files changed, 2154 deletions(-) delete mode 100644 src/add-ons/mail_daemon/inbound_protocols/imap/IMAP.h delete mode 100644 src/add-ons/mail_daemon/inbound_protocols/imap/IMAPInboundProtocol.cpp delete mode 100644 src/add-ons/mail_daemon/inbound_protocols/imap/IMAPInboundProtocol.h delete mode 100644 src/add-ons/mail_daemon/inbound_protocols/imap/IMAPRootInboundProtocol.cpp delete mode 100644 src/add-ons/mail_daemon/inbound_protocols/imap/IMAPRootInboundProtocol.h delete mode 100644 src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/IMAPMailbox.cpp delete mode 100644 src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/IMAPMailbox.h delete mode 100644 src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/IMAPStorage.cpp delete mode 100644 src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/IMAPStorage.h diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAP.h b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAP.h deleted file mode 100644 index 2a1eadd0d4..0000000000 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAP.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2011, Haiku, Inc. All rights reserved. - * Copyright 2011, Clemens Zeidler - * Distributed under the terms of the MIT License. - */ -#ifndef IMAP_H -#define IMAP_H - - -#include "MailProtocol.h" - -#include -#include -#include - -#include "MailSettings.h" - -#include "Protocol.h" -#include "IMAPStorage.h" - - -class DispatcherIMAPListener : public IMAPMailboxListener { -public: - DispatcherIMAPListener(MailProtocol& protocol, - IMAPStorage& storage); - - bool Lock(); - void Unlock(); - - void HeaderFetched(int32 uid, BPositionIO* data, - bool bodyIsComming); - void BodyFetched(int32 uid, BPositionIO* data); - - void NewMessagesToFetch(int32 nMessages); - void FetchEnd(); -private: - MailProtocol& fProtocol; - IMAPStorage& fStorage; -}; - - -class IMAPInboundProtocol; - - -/*! Just wait for a IDLE (watching) IMAP response in this thread. */ -class IMAPMailboxThread { -public: - IMAPMailboxThread(IMAPInboundProtocol& protocol, - IMAPMailbox& mailbox); - ~IMAPMailboxThread(); - - bool IsWatching(); - status_t SyncAndStartWatchingMailbox(); - status_t StopWatchingMailbox(); - -private: - static status_t _WatchThreadFunction(void* data); - void _Watch(); - -private: - IMAPInboundProtocol& fProtocol; - IMAPMailbox& fIMAPMailbox; - - BLocker fLock; - bool fIsWatching; - - thread_id fThread; - sem_id fWatchSyncSem; -}; - - -class IMAPInboundProtocol; - - -class MailboxWatcher : public BHandler { -public: - MailboxWatcher(IMAPInboundProtocol* protocol); - ~MailboxWatcher(); - - void StartWatching(const char* mailboxDir); - void MessageReceived(BMessage* message); -private: - node_ref fWatchDir; - IMAPInboundProtocol* fProtocol; -}; - - -class IMAPInboundProtocol : public InboundProtocol { -public: - IMAPInboundProtocol( - BMailAccountSettings* settings, - const char* mailbox); - virtual ~IMAPInboundProtocol(); - - //! thread safe interface - virtual status_t Connect(const char* server, - const char* username, const char* password, - bool useSSL = true, int32 port = -1); - virtual status_t Disconnect(); - status_t Reconnect(); - bool IsConnected(); - - virtual void SetStopNow(); - - void AddedToLooper(); - void UpdateSettings(const BMessage& settings); - - bool InterestingEntry(const entry_ref& ref); - - virtual status_t SyncMessages(); - virtual status_t FetchBody(const entry_ref& ref); - virtual status_t MarkMessageAsRead(const entry_ref& ref, - read_flags flag = B_READ); - - virtual status_t DeleteMessage(const entry_ref& ref); - virtual status_t AppendMessage(const entry_ref& ref); - - virtual status_t DeleteMessage(node_ref& node); - //! these should be thread save - virtual void FileRenamed(const entry_ref& from, - const entry_ref& to); - virtual void FileDeleted(const node_ref& node); - -protected: - BString fServer; - BString fUsername; - BString fPassword; - bool fUseSSL; - bool fIsConnected; - - BString fMailboxName; - BPath fMailboxPath; - - IMAPStorage fStorage; - IMAPMailbox fIMAPMailbox; - DispatcherIMAPListener fDispatcherIMAPListener; - - MailboxWatcher* fINBOXWatcher; - IMAPMailboxThread* fIMAPMailboxThread; -}; - - -#endif // IMAP_H diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPInboundProtocol.cpp b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPInboundProtocol.cpp deleted file mode 100644 index 2aa44fad79..0000000000 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPInboundProtocol.cpp +++ /dev/null @@ -1,615 +0,0 @@ -/* - * Copyright 2011, Haiku, Inc. All rights reserved. - * Copyright 2011, Clemens Zeidler - * Distributed under the terms of the MIT License. - */ - - -#include "IMAPInboundProtocol.h" - -#include - -#include -#include -#include -#include - -#include - - -const uint32 kMsgStartWatching = '&StW'; - - -DispatcherIMAPListener::DispatcherIMAPListener(MailProtocol& protocol, - IMAPStorage& storage) - : - fProtocol(protocol), - fStorage(storage) -{ -} - - -void -DispatcherIMAPListener::HeaderFetched(int32 uid, BPositionIO* data, - bool bodyIsComing) -{ - BFile* file = dynamic_cast(data); - if (file == NULL) - return; - entry_ref ref; - if (!fStorage.UIDToRef(uid, ref)) - return; - - fProtocol.NotifyHeaderFetched(ref, file); - - if (!bodyIsComing) - fProtocol.ReportProgress(0, 1); -} - - -void -DispatcherIMAPListener::BodyFetched(int32 uid, BPositionIO* data) -{ - BFile* file = dynamic_cast(data); - if (file == NULL) - return; - entry_ref ref; - if (!fStorage.UIDToRef(uid, ref)) - return; - fProtocol.NotifyBodyFetched(ref, file); - - fProtocol.ReportProgress(0, 1); -} - - -void -DispatcherIMAPListener::NewMessagesToFetch(int32 nMessages) -{ - fProtocol.NotifyNewMessagesToFetch(nMessages); -} - - -void -DispatcherIMAPListener::FetchEnd() -{ - fProtocol.ReportProgress(0, 1); -} - - -// #pragma mark - - - -IMAPMailboxThread::IMAPMailboxThread(IMAPInboundProtocol& protocol, - IMAPMailbox& mailbox) - : - fProtocol(protocol), - fIMAPMailbox(mailbox), - - fIsWatching(false), - fThread(-1) -{ - fWatchSyncSem = create_sem(0, "watch sync sem"); -} - - -IMAPMailboxThread::~IMAPMailboxThread() -{ - delete_sem(fWatchSyncSem); -} - - -bool -IMAPMailboxThread::IsWatching() -{ - BAutolock _(fLock); - return fIsWatching; -} - - -status_t -IMAPMailboxThread::SyncAndStartWatchingMailbox() -{ - if (!fProtocol.IsConnected()) - return B_ERROR; - - if (fIMAPMailbox.SupportWatching()) { - BAutolock autolock(fLock); - if (fIsWatching) - return B_OK; - fThread = spawn_thread(_WatchThreadFunction, "IMAPMailboxThread", - B_LOW_PRIORITY, this); - if (resume_thread(fThread) != B_OK) { - fThread = -1; - return B_ERROR; - } - acquire_sem(fWatchSyncSem); - fIsWatching = true; - } else { - status_t status = fIMAPMailbox.CheckMailbox(); - // if we lost connection reconnect and try again - if (status != B_OK) - status = fProtocol.Reconnect(); - if (status != B_OK) - return status; - status = fIMAPMailbox.CheckMailbox(); - if (status != B_OK) - return status; - } - - return B_OK; -} - - -status_t -IMAPMailboxThread::StopWatchingMailbox() -{ - status_t status = fIMAPMailbox.StopWatchingMailbox(); - if (status != B_OK) - return status; - - // wait till watching stopped - status_t exitCode; - return wait_for_thread(fThread, &exitCode); -} - - -/*static*/ status_t -IMAPMailboxThread::_WatchThreadFunction(void* data) -{ - ((IMAPMailboxThread*)data)->_Watch(); - return B_OK; -} - - - -void -IMAPMailboxThread::_Watch() -{ - status_t status = fIMAPMailbox.StartWatchingMailbox(fWatchSyncSem); - if (status != B_OK) - fProtocol.Disconnect(); - - fLock.Lock(); - fIsWatching = false; - fLock.Unlock(); - - fThread = -1; -} - - -// #pragma mark - - - -MailboxWatcher::MailboxWatcher(IMAPInboundProtocol* protocol) - : - fProtocol(protocol) -{ -} - - -MailboxWatcher::~MailboxWatcher() -{ - stop_watching(this); -} - - -void -MailboxWatcher::StartWatching(const char* mailboxDir) -{ - create_directory(mailboxDir, 0755); - - BDirectory dir(mailboxDir); - dir.GetNodeRef(&fWatchDir); - watch_node(&fWatchDir, B_WATCH_DIRECTORY, this); -} - - -void -MailboxWatcher::MessageReceived(BMessage* message) -{ - int32 opcode; - entry_ref ref; - node_ref nref; - const char* name; - switch (message->what) { - case B_NODE_MONITOR: - if (message->FindInt32("opcode", &opcode) != B_OK) - break; - switch (opcode) { - case B_ENTRY_CREATED: - break; - message->FindInt32("device", &ref.device); - message->FindInt64("directory", &ref.directory); - message->FindString("name", &name); - ref.set_name(name); - - fProtocol->AppendMessage(ref); - break; - - case B_ENTRY_REMOVED: - message->FindInt32("device", &nref.device); - message->FindInt64("node", &nref.node); - - fProtocol->DeleteMessage(nref); - break; - - case B_ENTRY_MOVED: - { - break; - entry_ref from; - entry_ref to; - ino_t toDirectory = -1; - ino_t fromDirectory = -2; - message->FindInt64("to directory", &toDirectory); - message->FindInt64("from directory", &fromDirectory); - if (toDirectory != fromDirectory) - break; - message->FindInt32("device", &to.device); - message->FindInt64("directory", &to.directory); - message->FindString("name", &name); - to.set_name(name); - - from.device = to.device; - from.directory = to.directory; - from.set_name(message->FindString("from name")); - fProtocol->Looper()->TriggerFileRenamed(from, to); - break; - - if (fWatchDir.node == toDirectory) { - // append - message->FindInt32("device", &ref.device); - ref.directory = toDirectory; - message->FindString("name", &name); - ref.set_name(name); - fProtocol->AppendMessage(ref); - } else { - // delete - message->FindInt32("device", &nref.device); - message->FindInt64("node", &nref.node); - fProtocol->DeleteMessage(nref); - } - break; - } - } - - default: - BHandler::MessageReceived(message); - } -} - - -// #pragma mark - - - -IMAPInboundProtocol::IMAPInboundProtocol(BMailAccountSettings* settings, - const char* mailbox) - : - InboundProtocol(settings), - - fIsConnected(false), - fMailboxName(mailbox), - fIMAPMailbox(fStorage), - fDispatcherIMAPListener(*this, fStorage), - fINBOXWatcher(NULL) -{ - const BMessage& settingsMsg = fAccountSettings.InboundSettings().Settings(); - int32 bodyLimit = 0; - if (settingsMsg.HasInt32("partial_download_limit")) - bodyLimit = settingsMsg.FindInt32("partial_download_limit"); - - BString tempString; - if (settingsMsg.FindString("destination", &tempString) != B_OK) { - tempString = "/boot/home/mail/"; - tempString += settings->Name(); - } - fMailboxPath.SetTo(tempString); - fMailboxPath.Append(fMailboxName); - fStorage.SetTo(fMailboxPath.Path()); - - fIMAPMailbox.SetListener(&fDispatcherIMAPListener); - fIMAPMailbox.SetFetchBodyLimit(bodyLimit); - - fIMAPMailboxThread = new IMAPMailboxThread(*this, fIMAPMailbox); - - // set watch directory - fINBOXWatcher = new MailboxWatcher(this); - AddHandler(fINBOXWatcher); -} - - -IMAPInboundProtocol::~IMAPInboundProtocol() -{ - fIMAPMailboxThread->StopWatchingMailbox(); - - RemoveHandler(fINBOXWatcher); - delete fINBOXWatcher; - - delete fIMAPMailboxThread; -} - - -status_t -IMAPInboundProtocol::Connect(const char* server, const char* username, - const char* password, bool useSSL, int32 port) -{ - if (fIsConnected) - return B_OK; - - BString statusMessage; - - statusMessage = "Connect to: "; - statusMessage += username; - SetTotalItems(5); - ReportProgress(0, 1, statusMessage); - - status_t status = fIMAPMailbox.Connect(server, username, password, useSSL, - port); - if (status != B_OK) { - if (fIMAPMailbox.CommandError().CountChars() > 0) { - // This was a IMAP error - statusMessage = "Failed to login: "; - statusMessage += fIMAPMailbox.CommandError(); - } else { - // Probably a connection error - statusMessage = "Connection error: "; - statusMessage += strerror(status); - } - ShowError(statusMessage); - ResetProgress(); - return status; - } - - ReportProgress(0, 1, "Load database"); - - fStorage.StartReadDatabase(); - status = fIMAPMailbox.SelectMailbox(fMailboxName); - if (status != B_OK) { - fStorage.WaitForDatabaseRead(); - statusMessage = "Failed to select mailbox ("; - statusMessage += fMailboxName; - statusMessage += "): "; - statusMessage += fIMAPMailbox.CommandError(); - ShowError(statusMessage); - ResetProgress(); - return status; - } - - ReportProgress(0, 1, "Fetch message list"); - status = fIMAPMailbox.Sync(); - if (status != B_OK) { - fStorage.WaitForDatabaseRead(); - ShowError("Failed to sync mailbox"); - ResetProgress(); - return status; - } - - ReportProgress(0, 1, "Read local message list"); - status = fStorage.WaitForDatabaseRead(); - if (status != B_OK) { - ShowError("Can't read database"); - ResetProgress(); - return status; - } - - ReportProgress(0, 1, "Sync mailbox"); - - IMAPMailboxSync mailboxSync; - status = mailboxSync.Sync(fStorage, fIMAPMailbox); - - ResetProgress(); - - if (status == B_OK) - fIsConnected = true; - else - Disconnect(); - return status; -} - - -status_t -IMAPInboundProtocol::Disconnect() -{ - fIsConnected = false; - return fIMAPMailbox.Disconnect(); -} - - -status_t -IMAPInboundProtocol::Reconnect() -{ - Disconnect(); - return Connect(fServer, fUsername, fPassword, fUseSSL, -1); -} - - -bool -IMAPInboundProtocol::IsConnected() -{ - if (!fIsConnected) - return false; - if (fIMAPMailbox.IsConnected()) - return true; - - Disconnect(); - return false; -} - - -void -IMAPInboundProtocol::SetStopNow() -{ - fIMAPMailbox.SetStopNow(); -} - - -void -IMAPInboundProtocol::AddedToLooper() -{ - fINBOXWatcher->StartWatching(fMailboxPath.Path()); - - const BMessage& settingsMsg = fAccountSettings.InboundSettings().Settings(); - UpdateSettings(settingsMsg); -} - - -void -IMAPInboundProtocol::UpdateSettings(const BMessage& settings) -{ - settings.FindString("server", &fServer); - int32 ssl; - settings.FindInt32("flavor", &ssl); - if (ssl == 1) - fUseSSL = true; - else - fUseSSL = false; - settings.FindString("username", &fUsername); - - char* passwd = get_passwd(&settings, "cpasswd"); - if (passwd) { - fPassword = passwd; - delete[] passwd; - } - - SyncMessages(); -} - - -bool -IMAPInboundProtocol::InterestingEntry(const entry_ref& ref) -{ - BEntry entry(&ref); - return BDirectory(fMailboxPath.Path()).Contains(&entry, B_FILE_NODE); -} - - -status_t -IMAPInboundProtocol::SyncMessages() -{ - if (!IsConnected()) - Connect(fServer, fUsername, fPassword, fUseSSL); - - return fIMAPMailboxThread->SyncAndStartWatchingMailbox(); -} - - -status_t -IMAPInboundProtocol::FetchBody(const entry_ref& ref) -{ - if (!IsConnected()) - Connect(fServer, fUsername, fPassword, fUseSSL); - - fIMAPMailboxThread->StopWatchingMailbox(); - int32 uid = fStorage.RefToUID(ref); - - ResetProgress("Fetch body"); - SetTotalItems(1); - - status_t status = fIMAPMailbox.FetchBody(fIMAPMailbox.UIDToMessageNumber( - uid)); - - ResetProgress(); - - fIMAPMailboxThread->SyncAndStartWatchingMailbox(); - return status; -} - - -status_t -IMAPInboundProtocol::MarkMessageAsRead(const entry_ref& ref, read_flags flag) -{ - if (!IsConnected()) - Connect(fServer, fUsername, fPassword, fUseSSL); - - fIMAPMailboxThread->StopWatchingMailbox(); - int32 uid = fStorage.RefToUID(ref); - int32 flags = fStorage.GetFlags(uid); - if (flag == B_READ) - flags |= kSeen; - else - flags &= ~kSeen; - status_t status = fIMAPMailbox.SetFlags( - fIMAPMailbox.UIDToMessageNumber(uid), flags); - fIMAPMailboxThread->SyncAndStartWatchingMailbox(); - if (status != B_OK) - return status; - return InboundProtocol::MarkMessageAsRead(ref, flag); -} - - -status_t -IMAPInboundProtocol::DeleteMessage(const entry_ref& ref) -{ - if (!IsConnected()) - Connect(fServer, fUsername, fPassword, fUseSSL); - - fIMAPMailboxThread->StopWatchingMailbox(); - - int32 uid = fStorage.RefToUID(ref); - status_t status = fIMAPMailbox.DeleteMessage(uid, false); - - fIMAPMailboxThread->SyncAndStartWatchingMailbox(); - return status; -} - - -void -IMAPInboundProtocol::FileRenamed(const entry_ref& from, const entry_ref& to) -{ - fStorage.FileRenamed(from, to); -} - - -void -IMAPInboundProtocol::FileDeleted(const node_ref& node) -{ - //TODO -} - - -status_t -IMAPInboundProtocol::AppendMessage(const entry_ref& ref) -{ - if (!IsConnected()) - Connect(fServer, fUsername, fPassword, fUseSSL); - - fIMAPMailboxThread->StopWatchingMailbox(); - BFile file(&ref, B_READ_ONLY); - off_t size; - file.GetSize(&size); - - // check if file is already known - int32 uid = -1; - file.ReadAttr("MAIL:unique_id", B_INT32_TYPE, 0, &uid, sizeof(int32)); - if (fStorage.HasFile(uid)) { - fIMAPMailboxThread->SyncAndStartWatchingMailbox(); - return B_BAD_VALUE; - } - - int32 flags = 0; - file.ReadAttr("MAIL:server_flags", B_INT32_TYPE, 0, &flags, sizeof(int32)); - - status_t status = fIMAPMailbox.AppendMessage(file, size, flags); - fIMAPMailboxThread->SyncAndStartWatchingMailbox(); - return status; -} - - -status_t -IMAPInboundProtocol::DeleteMessage(node_ref& node) -{ - if (!IsConnected()) - Connect(fServer, fUsername, fPassword, fUseSSL); - - fIMAPMailboxThread->StopWatchingMailbox(); - StorageMailEntry* entry = fStorage.GetEntryForRef(node); - if (entry == NULL) { - fIMAPMailboxThread->SyncAndStartWatchingMailbox(); - return B_BAD_VALUE; - } - - int32 uid = entry->uid; - status_t status = fIMAPMailbox.DeleteMessage(uid, false); - - fIMAPMailboxThread->SyncAndStartWatchingMailbox(); - return status; -} diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPInboundProtocol.h b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPInboundProtocol.h deleted file mode 100644 index 9b3eda7db3..0000000000 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPInboundProtocol.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2011, Haiku, Inc. All rights reserved. - * Copyright 2011, Clemens Zeidler - * Distributed under the terms of the MIT License. - */ -#ifndef IMAP_INBOUND_PROTOCOL_H -#define IMAP_INBOUND_PROTOCOL_H - - -#include "MailProtocol.h" - -#include -#include -#include - -#include "MailSettings.h" - -#include "Protocol.h" -#include "IMAPStorage.h" - - -class DispatcherIMAPListener : public IMAPMailboxListener { -public: - DispatcherIMAPListener(MailProtocol& protocol, - IMAPStorage& storage); - - bool Lock(); - void Unlock(); - - void HeaderFetched(int32 uid, BPositionIO* data, - bool bodyIsComming); - void BodyFetched(int32 uid, BPositionIO* data); - - void NewMessagesToFetch(int32 nMessages); - void FetchEnd(); -private: - MailProtocol& fProtocol; - IMAPStorage& fStorage; -}; - - -class IMAPInboundProtocol; - - -/*! Just wait for a IDLE (watching) IMAP response in this thread. */ -class IMAPMailboxThread { -public: - IMAPMailboxThread(IMAPInboundProtocol& protocol, - IMAPMailbox& mailbox); - ~IMAPMailboxThread(); - - bool IsWatching(); - status_t SyncAndStartWatchingMailbox(); - status_t StopWatchingMailbox(); - -private: - static status_t _WatchThreadFunction(void* data); - void _Watch(); - -private: - IMAPInboundProtocol& fProtocol; - IMAPMailbox& fIMAPMailbox; - - BLocker fLock; - bool fIsWatching; - - thread_id fThread; - sem_id fWatchSyncSem; -}; - - -class IMAPInboundProtocol; - - -class MailboxWatcher : public BHandler { -public: - MailboxWatcher(IMAPInboundProtocol* protocol); - ~MailboxWatcher(); - - void StartWatching(const char* mailboxDir); - void MessageReceived(BMessage* message); -private: - node_ref fWatchDir; - IMAPInboundProtocol* fProtocol; -}; - - -class IMAPInboundProtocol : public InboundProtocol { -public: - IMAPInboundProtocol( - BMailAccountSettings* settings, - const char* mailbox); - virtual ~IMAPInboundProtocol(); - - //! thread safe interface - virtual status_t Connect(const char* server, - const char* username, const char* password, - bool useSSL = true, int32 port = -1); - virtual status_t Disconnect(); - status_t Reconnect(); - bool IsConnected(); - - virtual void SetStopNow(); - - void AddedToLooper(); - void UpdateSettings(const BMessage& settings); - - bool InterestingEntry(const entry_ref& ref); - - virtual status_t SyncMessages(); - virtual status_t FetchBody(const entry_ref& ref); - virtual status_t MarkMessageAsRead(const entry_ref& ref, - read_flags flag = B_READ); - - virtual status_t DeleteMessage(const entry_ref& ref); - virtual status_t AppendMessage(const entry_ref& ref); - - virtual status_t DeleteMessage(node_ref& node); - //! these should be thread save - virtual void FileRenamed(const entry_ref& from, - const entry_ref& to); - virtual void FileDeleted(const node_ref& node); - -protected: - BString fServer; - BString fUsername; - BString fPassword; - bool fUseSSL; - bool fIsConnected; - - BString fMailboxName; - BPath fMailboxPath; - - IMAPStorage fStorage; - IMAPMailbox fIMAPMailbox; - DispatcherIMAPListener fDispatcherIMAPListener; - - MailboxWatcher* fINBOXWatcher; - IMAPMailboxThread* fIMAPMailboxThread; -}; - - -#endif // IMAP_INBOUND_PROTOCOL_H diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPRootInboundProtocol.cpp b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPRootInboundProtocol.cpp deleted file mode 100644 index 544d927cf5..0000000000 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPRootInboundProtocol.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright 2011, Haiku, Inc. All rights reserved. - * Copyright 2011, Clemens Zeidler - * Distributed under the terms of the MIT License. - */ - - -#include "IMAPRootInboundProtocol.h" - -#include - - -IMAPRootInboundProtocol::IMAPRootInboundProtocol(BMailAccountSettings* settings) - : - IMAPInboundProtocol(settings, "INBOX") -{ -} - - -IMAPRootInboundProtocol::~IMAPRootInboundProtocol() -{ - _ShutdownChilds(); -} - - -status_t -IMAPRootInboundProtocol::Connect(const char* server, const char* username, - const char* password, bool useSSL, int32 port) -{ - status_t status = IMAPInboundProtocol::Connect(server, username, password, - useSSL, port); - if (status != B_OK) - return status; - - FolderList folders; - fIMAPMailbox.GetFolders(folders); - for (unsigned int i = 0; i < folders.size(); i++) { - if (!folders[i].subscribed || folders[i].folder == "INBOX") - continue; - - IMAPInboundProtocol* inboundProtocol = new IMAPInboundProtocol( - &fAccountSettings, folders[i].folder); - inboundProtocol->SetMailNotifier(fMailNotifier->Clone()); - - InboundProtocolThread* inboundThread = new InboundProtocolThread( - inboundProtocol); - inboundThread->Run(); - - fProtocolThreadList.AddItem(inboundThread); - } - return status; -} - - -status_t -IMAPRootInboundProtocol::Disconnect() -{ - status_t status = IMAPInboundProtocol::Disconnect(); - _ShutdownChilds(); - return status; -} - - -void -IMAPRootInboundProtocol::SetStopNow() -{ - for (int32 i = 0; i < fProtocolThreadList.CountItems(); i++) - fProtocolThreadList.ItemAt(i)->SetStopNow(); - IMAPInboundProtocol::SetStopNow(); -} - - -status_t -IMAPRootInboundProtocol::SyncMessages() -{ - for (int32 i = 0; i < fProtocolThreadList.CountItems(); i++) - fProtocolThreadList.ItemAt(i)->SyncMessages(); - return IMAPInboundProtocol::SyncMessages(); -} - - -status_t -IMAPRootInboundProtocol::FetchBody(const entry_ref& ref) -{ - if (InterestingEntry(ref)) - return IMAPInboundProtocol::FetchBody(ref); - InboundProtocolThread* thread = _FindThreadFor(ref); - if (!thread) - return B_BAD_VALUE; - thread->FetchBody(ref); - return B_OK; -} - - -status_t -IMAPRootInboundProtocol::MarkMessageAsRead(const entry_ref& ref, - read_flags flag) -{ - if (InterestingEntry(ref)) - return IMAPInboundProtocol::MarkMessageAsRead(ref, flag); - InboundProtocolThread* thread = _FindThreadFor(ref); - if (!thread) - return B_BAD_VALUE; - thread->MarkMessageAsRead(ref, flag); - return B_OK; -} - - -status_t -IMAPRootInboundProtocol::DeleteMessage(const entry_ref& ref) -{ - if (InterestingEntry(ref)) - return IMAPInboundProtocol::DeleteMessage(ref); - InboundProtocolThread* thread = _FindThreadFor(ref); - if (!thread) - return B_BAD_VALUE; - thread->DeleteMessage(ref); - return B_OK; -} - - -status_t -IMAPRootInboundProtocol::AppendMessage(const entry_ref& ref) -{ - if (InterestingEntry(ref)) - return IMAPInboundProtocol::AppendMessage(ref); - InboundProtocolThread* thread = _FindThreadFor(ref); - if (!thread) - return B_BAD_VALUE; - thread->AppendMessage(ref); - return B_OK; -} - - -status_t -IMAPRootInboundProtocol::DeleteMessage(node_ref& node) -{ - status_t status = IMAPInboundProtocol::DeleteMessage(node); - if (status == B_OK) - return status; - for (int32 i = 0; i < fProtocolThreadList.CountItems(); i++) - fProtocolThreadList.ItemAt(i)->TriggerFileDeleted(node); - return B_OK; -} - - -void -IMAPRootInboundProtocol::_ShutdownChilds() -{ - BMessage reply; - for (int32 i = 0; i < fProtocolThreadList.CountItems(); i++) { - InboundProtocolThread* thread = fProtocolThreadList.ItemAt(i); - MailProtocol* protocol = thread->Protocol(); - - thread->SetStopNow(); - BMessenger(thread).SendMessage(B_QUIT_REQUESTED, &reply); - - delete protocol; - } - fProtocolThreadList.MakeEmpty(); -} - - -InboundProtocolThread* -IMAPRootInboundProtocol::_FindThreadFor(const entry_ref& ref) -{ - for (int32 i = 0; i < fProtocolThreadList.CountItems(); i++) { - InboundProtocolThread* thread = fProtocolThreadList.ItemAt(i); - IMAPInboundProtocol* protocol - = (IMAPInboundProtocol*)thread->Protocol(); - if (protocol->InterestingEntry(ref)) - return thread; - } - return NULL; -} - - -// #pragma mark - - - -InboundProtocol* -instantiate_inbound_protocol(BMailAccountSettings* settings) -{ - return new IMAPRootInboundProtocol(settings); -} diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPRootInboundProtocol.h b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPRootInboundProtocol.h deleted file mode 100644 index 29e77a25d8..0000000000 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPRootInboundProtocol.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2011, Haiku, Inc. All rights reserved. - * Copyright 2011, Clemens Zeidler - * Distributed under the terms of the MIT License. - */ -#ifndef IMAP_ROOT_INBOUND_PROTOCOL_H -#define IMAP_ROOT_INBOUND_PROTOCOL_H - - -#include "IMAPInboundProtocol.h" - -#include "MailAddon.h" - - -typedef BObjectList ProtocolThreadList; - - -/*! Hold the main INBOX mailbox and manage all the other other mailboxes. */ -class IMAPRootInboundProtocol : public IMAPInboundProtocol { -public: - IMAPRootInboundProtocol( - BMailAccountSettings* settings); - ~IMAPRootInboundProtocol(); - - //! thread safe interface - status_t Connect(const char* server, - const char* username, const char* password, - bool useSSL = true, int32 port = -1); - status_t Disconnect(); - - void SetStopNow(); - - status_t SyncMessages(); - status_t FetchBody(const entry_ref& ref); - status_t MarkMessageAsRead(const entry_ref& ref, - read_flags flag = B_READ); - - status_t DeleteMessage(const entry_ref& ref); - status_t AppendMessage(const entry_ref& ref); - - status_t DeleteMessage(node_ref& node); - -private: - void _ShutdownChilds(); - InboundProtocolThread* _FindThreadFor(const entry_ref& ref); - - ProtocolThreadList fProtocolThreadList; -}; - - -#endif // IMAP_ROOT_INBOUND_PROTOCOL_H diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/IMAPMailbox.cpp b/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/IMAPMailbox.cpp deleted file mode 100644 index 96f80f4d02..0000000000 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/IMAPMailbox.cpp +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright 2011, Haiku, Inc. All rights reserved. - * Copyright 2011, Clemens Zeidler - * Distributed under the terms of the MIT License. - */ - - -#include "IMAPMailbox.h" - -#include "IMAPHandler.h" -#include "IMAPStorage.h" - - -#define DEBUG_IMAP_MAILBOX -#ifdef DEBUG_IMAP_MAILBOX -# include -# define TRACE(x...) printf(x) -#else -# define TRACE(x...) ; -#endif - - -MinMessage::MinMessage() -{ - uid = 0; - flags = 0; -} - - -// #pragma mark - - - -IMAPMailbox::IMAPMailbox(IMAPStorage& storage) - : - fStorage(storage), - - fMailboxSelectHandler(*this), - fExistsHandler(*this), - fExpungeHandler(*this), - fFlagsHandler(*this), - - fWatching(0), - - fFetchBodyLimit(0) -{ - fIMAPMailboxListener = &fNULLListener; -} - - -IMAPMailbox::~IMAPMailbox() -{ - Disconnect(); -} - - -void -IMAPMailbox::SetListener(IMAPMailboxListener* listener) -{ - if (listener == NULL) - fIMAPMailboxListener = &fNULLListener; - else - fIMAPMailboxListener = listener; -} - - -BString -IMAPMailbox::Mailbox() -{ - return fSelectedMailbox; -} - - -status_t -IMAPMailbox::Sync() -{ - TRACE("Sync\n"); - if (fMailboxSelectHandler.NextUID() <= 1) - return B_OK; - - _InstallUnsolicitedHandler(false); - - fMessageList.clear(); - FetchMessageListCommand fetchMessageListCommand(*this, &fMessageList, - fMailboxSelectHandler.NextUID()); - status_t status = ProcessCommand(&fetchMessageListCommand); - if (status != B_OK) - return status; - - _InstallUnsolicitedHandler(true); - return B_OK; -} - - -bool -IMAPMailbox::SupportWatching() -{ - if (fCapabilityHandler.Capabilities().FindFirst("IDLE") < 0) - return false; - return true; -} - - -status_t -IMAPMailbox::StartWatchingMailbox(sem_id startedSem) -{ - atomic_set(&fWatching, 1); - - bool firstIDLE = true; - // refresh every 29 min - bigtime_t timeout = 1000 * 1000 * 60 * 29; // 29 min - status_t status; - while (true) { - int32 commandID = NextCommandID(); - TRACE("IDLE ...\n"); - status = SendCommand("IDLE", commandID); - if (firstIDLE) { - release_sem(startedSem); - firstIDLE = false; - } - if (status != B_OK) - break; - - status = HandleResponse(commandID, timeout, false); - ProcessAfterQuacks(kIMAP4ClientTimeout); - - if (atomic_get(&fWatching) == 0) - break; - - if (status == B_TIMED_OUT) { - TRACE("Renew IDLE connection.\n"); - status = SendRawCommand("DONE"); - if (status != B_OK) - break; - // handle IDLE response and more - status = ProcessCommand("NOOP"); - if (status != B_OK) - break; - else - continue; - } - if (status != B_OK) - break; - } - - atomic_set(&fWatching, 0); - return status; -} - - - -status_t -IMAPMailbox::StopWatchingMailbox() -{ - if (atomic_get(&fWatching) == 0) - return B_OK; - atomic_set(&fWatching, 0); - return SendRawCommand("DONE"); -} - - -status_t -IMAPMailbox::CheckMailbox() -{ - return ProcessCommand("NOOP"); -} - - -status_t -IMAPMailbox::FetchMinMessage(int32 messageNumber, BPositionIO** data) -{ - if (messageNumber <= 0) - return B_BAD_VALUE; - FetchMinMessageCommand fetchMinMessageCommand(*this, messageNumber, - &fMessageList, data); - return ProcessCommand(&fetchMinMessageCommand); -} - - -status_t -IMAPMailbox::FetchBody(int32 messageNumber, BPositionIO* data) -{ - if (data == NULL || messageNumber <= 0) { - delete data; - return B_BAD_VALUE; - } - - FetchBodyCommand fetchBodyCommand(*this, messageNumber, data); - status_t status = ProcessCommand(&fetchBodyCommand); - - return status; -} - - -void -IMAPMailbox::SetFetchBodyLimit(int32 limit) -{ - fFetchBodyLimit = limit; -} - - -status_t -IMAPMailbox::FetchMessage(int32 messageNumber) -{ - return FetchMessages(messageNumber, -1); -} - - -status_t -IMAPMailbox::FetchMessages(int32 firstMessage, int32 lastMessage) -{ - FetchMessageCommand fetchCommand(*this, firstMessage, lastMessage, - fFetchBodyLimit); - return ProcessCommand(&fetchCommand); -} - - -status_t -IMAPMailbox::FetchBody(int32 messageNumber) -{ - if (fStorage.IsBodyFetched(MessageNumberToUID(messageNumber))) - return B_BAD_VALUE; - - BPositionIO* file; - status_t status = fStorage.OpenMessage(MessageNumberToUID(messageNumber), - &file); - if (status != B_OK) - return status; - - // fetch command deletes the file - status = FetchBody(messageNumber, file); - return status; -} - - -status_t -IMAPMailbox::SetFlags(int32 messageNumber, int32 flags) -{ - if (messageNumber <= 0) - return B_BAD_VALUE; - - SetFlagsCommand setFlagsCommand(*this, messageNumber, flags); - return ProcessCommand(&setFlagsCommand); -} - - -status_t -IMAPMailbox::AppendMessage(BPositionIO& message, off_t size, int32 flags, - time_t time) -{ - AppendCommand appendCommand(*this, message, size, flags, time); - return ProcessCommand(&appendCommand); -} - - -int32 -IMAPMailbox::UIDToMessageNumber(int32 uid) -{ - for (unsigned int i = 0; i < fMessageList.size(); i++) { - if (fMessageList[i].uid == uid) - return i + 1; - } - return -1; -} - - -int32 -IMAPMailbox::MessageNumberToUID(int32 messageNumber) -{ - int32 index = messageNumber - 1; - if (index < 0 || index >= (int32)fMessageList.size()) - return -1; - return fMessageList[index].uid; -} - - -status_t -IMAPMailbox::DeleteMessage(int32 uid, bool permanently) -{ - int32 flags = fStorage.GetFlags(uid); - flags |= kDeleted; - status_t status = SetFlags(UIDToMessageNumber(uid), flags); - - if (!permanently || status != B_OK) - return status; - - // delete permanently by invoking expunge - ExpungeCommmand expungeCommand(*this); - return ProcessCommand(&expungeCommand); -} - - -void -IMAPMailbox::_InstallUnsolicitedHandler(bool install) -{ - if (install) { - fHandlerList.AddItem(&fFlagsHandler, 0); - fHandlerList.AddItem(&fExpungeHandler, 0); - fHandlerList.AddItem(&fExistsHandler, 0); - } else { - fHandlerList.RemoveItem(&fFlagsHandler); - fHandlerList.RemoveItem(&fExpungeHandler); - fHandlerList.RemoveItem(&fExistsHandler); - } -} diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/IMAPMailbox.h b/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/IMAPMailbox.h deleted file mode 100644 index afb6e1c9f1..0000000000 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/IMAPMailbox.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2010, Haiku Inc. All Rights Reserved. - * Copyright 2010 Clemens Zeidler. All rights reserved. - * - * Distributed under the terms of the MIT License. - */ -#ifndef IMAP_MAILBOX_H -#define IMAP_MAILBOX_H - - -#include - -#include "IMAPHandler.h" -#include "IMAPProtocol.h" - - -class IMAPMailboxListener { -public: - virtual ~IMAPMailboxListener() {} - - virtual void HeaderFetched(int32 uid, BPositionIO* data, - bool bodyIsComing) {} - virtual void BodyFetched(int32 uid, BPositionIO* data) {} - - virtual void NewMessagesToFetch(int32 nMessages) {} - virtual void FetchEnd() {} -}; - - -class IMAPStorage; - - -class IMAPMailbox : public IMAP::Protocol { -public: - IMAPMailbox(IMAPStorage& storage); - ~IMAPMailbox(); - - void SetListener(IMAPMailboxListener* listener); - IMAPMailboxListener& Listener() { return *fIMAPMailboxListener; } - - /*! Select mailbox and sync with the storage. */ - BString Mailbox(); - status_t Sync(); - - bool SupportWatching(); - status_t StartWatchingMailbox(sem_id startedSem = -1); - status_t StopWatchingMailbox(); - - status_t CheckMailbox(); - - //! Low level fetch functions. - status_t FetchMinMessage(int32 messageNumber, - BPositionIO** data = NULL); - status_t FetchBody(int32 messageNumber, - BPositionIO* data); - - void SetFetchBodyLimit(int32 limit); - int32 FetchBodyLimit() { return fFetchBodyLimit; } - status_t FetchMessage(int32 messageNumber); - status_t FetchMessages(int32 firstMessage, - int32 lastMessage); - status_t FetchBody(int32 messageNumber); - - status_t SetFlags(int32 messageNumber, int32 flags); - status_t AppendMessage(BPositionIO& message, off_t size, - int32 flags = 0, time_t time = -1); - - int32 GetCurrentMessageCount() - { return fMessageList.size(); } - const IMAP::MinMessageList& GetMessageList() { return fMessageList; } - IMAPStorage& GetStorage() { return fStorage; } - - int32 UIDToMessageNumber(int32 uid); - int32 MessageNumberToUID(int32 messageNumber); - - status_t DeleteMessage(int32 uid, bool permanently); -private: - void _InstallUnsolicitedHandler(bool install); - - IMAP::MinMessageList fMessageList; - - IMAPStorage& fStorage; - IMAPMailboxListener* fIMAPMailboxListener; - IMAPMailboxListener fNULLListener; - - IMAP::ExistsHandler fExistsHandler; - IMAP::ExpungeHandler fExpungeHandler; -// FlagsHandler fFlagsHandler; - - int32 fWatching; - - BString fSelectedMailbox; - - int32 fFetchBodyLimit; -}; - - -#endif // IMAP_MAILBOX_H diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/IMAPStorage.cpp b/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/IMAPStorage.cpp deleted file mode 100644 index a2444e3f7e..0000000000 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/IMAPStorage.cpp +++ /dev/null @@ -1,513 +0,0 @@ -/* - * Copyright 2010-2011, Haiku Inc. All Rights Reserved. - * Copyright 2010 Clemens Zeidler. All rights reserved. - * - * Distributed under the terms of the MIT License. - */ - - -#include "IMAPStorage.h" - -#include - -#include -#include -#include -#include - -#include - -#include "IMAPMailbox.h" - - -#define DEBUG_IMAP_STORAGE -#ifdef DEBUG_IMAP_STORAGE -# include -# define TRACE(x...) printf(x) -#else -# define TRACE(x...) /* nothing */ -#endif - - -status_t -IMAPMailboxSync::Sync(IMAPStorage& storage, IMAPMailbox& mailbox) -{ - const MailEntryMap& files = storage.GetFiles(); - const MinMessageList& messages = mailbox.GetMessageList(); - - for (MailEntryMap::const_iterator it = files.begin(); it != files.end(); - it++) { - const StorageMailEntry& mailEntry = (*it).second; - bool found = false; - for (unsigned int a = 0; a < messages.size(); a++) { - const MinMessage& minMessage = messages[a]; - if (mailEntry.uid == minMessage.uid) { - found = true; - if (mailEntry.flags != minMessage.flags) - storage.SetFlags(mailEntry.uid, minMessage.flags); - break; - } - } - if (!found) - storage.DeleteMessage(mailEntry.uid); - } - - for (unsigned int i = 0; i < messages.size(); i++) { - const MinMessage& minMessage = messages[i]; - bool found = false; - for (MailEntryMap::const_iterator it = files.begin(); it != files.end(); - it++) { - const StorageMailEntry& mailEntry = (*it).second; - - if (mailEntry.uid == minMessage.uid) { - found = true; - break; - } - } - if (!found) - fToFetchList.push_back(i + 1); - } - - mailbox.Listener().NewMessagesToFetch(fToFetchList.size()); - - // fetch headers in big bunches if possible - int32 fetchCount = 0; - int32 start = -1; - int32 end = -1; - int32 lastId = -1; - for (unsigned int i = 0; i < fToFetchList.size(); i++) { - if (mailbox.StopNow()) - return B_ERROR; - - int32 current = fToFetchList[i]; - fetchCount++; - - if (start < 0) { - start = current; - lastId = current; - continue; - } - if (current - 1 == lastId) { - end = current; - lastId = current; - // limit to a fix number to make it interruptable see StopNow() - if (fetchCount < 250) - continue; - } - - fetchCount = 0; - mailbox.FetchMessages(start, end); - start = -1; - end = -1; - } - if (start > 0) - mailbox.FetchMessages(start, end); - - return B_OK; -} - - -// #pragma mark - - - -IMAPStorage::IMAPStorage() -{ - fLoadDatabaseLock = create_sem(1, "sync lock"); -} - - -IMAPStorage::~IMAPStorage() -{ - delete_sem(fLoadDatabaseLock); -} - - -void -IMAPStorage::SetTo(const char* dir) -{ - fMailboxPath.SetTo(dir); -} - - -status_t -IMAPStorage::StartReadDatabase() -{ - status_t status = create_directory(fMailboxPath.Path(), 0755); - if (status != B_OK) - return status; - - thread_id id = spawn_thread(_ReadFilesThreadFunction, "read mailbox", - B_LOW_PRIORITY, this); - if (id < 0) - return id; - - // will be unlocked from thread - acquire_sem(fLoadDatabaseLock); - status = resume_thread(id); - if (status != B_OK) - release_sem(fLoadDatabaseLock); - return status; -} - - -status_t -IMAPStorage::WaitForDatabaseRead() -{ - // just wait for thread - if (acquire_sem(fLoadDatabaseLock) != B_OK) - return B_ERROR; - release_sem(fLoadDatabaseLock); - return B_OK; -} - - -status_t -IMAPStorage::AddNewMessage(int32 uid, int32 flags, BPositionIO** file) -{ - if (file != NULL) - *file = NULL; - // TODO: make sure there is not a valid mail with this name - BString fileName = "Downloading file... uid: "; - fileName << uid; - - BPath filePath = fMailboxPath; - filePath.Append(fileName); - TRACE("AddNewMessage %s\n", filePath.Path()); - BFile* newFile = new BFile(filePath.Path(), B_READ_WRITE | B_CREATE_FILE - | B_ERASE_FILE); - if (newFile == NULL) - return B_NO_MEMORY; - - StorageMailEntry storageEntry; - storageEntry.uid = uid; - storageEntry.flags = flags; - storageEntry.fileName = fileName; - newFile->GetNodeRef(&storageEntry.nodeRef); - - if (_WriteUniqueID(*newFile, uid) != B_OK) { - delete newFile; - return B_ERROR; - } - - status_t status = _WriteFlags(flags, *newFile); - if (status != B_OK) { - delete newFile; - return status; - } - - if (file) - *file = newFile; - else - delete newFile; - fMailEntryMap[uid] = storageEntry; - return B_OK; -} - - -status_t -IMAPStorage::OpenMessage(int32 uid, BPositionIO** file) -{ - *file = NULL; - - MailEntryMap::const_iterator it = fMailEntryMap.find(uid); - if (it == fMailEntryMap.end()) - return B_BAD_VALUE; - - const StorageMailEntry& storageEntry = (*it).second; - BPath filePath = fMailboxPath; - filePath.Append(storageEntry.fileName); - BFile* ourFile = new BFile(filePath.Path(), B_READ_WRITE); - if (!ourFile) - return B_NO_MEMORY; - status_t status = ourFile->InitCheck(); - if (status != B_OK) { - delete *file; - return status; - } - *file = ourFile; - return B_OK; -} - - -status_t -IMAPStorage::DeleteMessage(int32 uid) -{ - MailEntryMap::iterator it = fMailEntryMap.find(uid); - if (it == fMailEntryMap.end()) - return B_ENTRY_NOT_FOUND; - const StorageMailEntry& storageEntry = (*it).second; - - BPath filePath = fMailboxPath; - filePath.Append(storageEntry.fileName); - BEntry entry(filePath.Path()); - TRACE("IMAPStorage::DeleteMessage %s, %" B_PRId32 "\n", filePath.Path(), uid); - - status_t status = entry.Remove(); - if (status != B_OK) - return status; - fMailEntryMap.erase(it); - return B_OK; -} - - -status_t -IMAPStorage::SetFlags(int32 uid, int32 flags) -{ - MailEntryMap::iterator it = fMailEntryMap.find(uid); - if (it == fMailEntryMap.end()) - return B_ENTRY_NOT_FOUND; - StorageMailEntry& entry = (*it).second; - - BPath filePath = fMailboxPath; - filePath.Append(entry.fileName); - BNode node(filePath.Path()); - - status_t status = _WriteFlags(flags, node); - if (status != B_OK) - return status; - - entry.flags = flags; - return B_OK; -} - - -int32 -IMAPStorage::GetFlags(int32 uid) -{ - MailEntryMap::const_iterator it = fMailEntryMap.find(uid); - if (it == fMailEntryMap.end()) - return -1; - const StorageMailEntry& entry = (*it).second; - return entry.flags; -} - - -status_t -IMAPStorage::SetFileName(int32 uid, const BString& name) -{ - MailEntryMap::iterator it = fMailEntryMap.find(uid); - if (it == fMailEntryMap.end()) - return -1; - StorageMailEntry& storageEntry = (*it).second; - BPath filePath = fMailboxPath; - filePath.Append(storageEntry.fileName); - BEntry entry(filePath.Path()); - status_t status = entry.Rename(name); - if (status != B_OK) - return status; - storageEntry.fileName = name; - return B_OK; -} - - -status_t -IMAPStorage::FileRenamed(const entry_ref& from, const entry_ref& to) -{ - int32 uid = RefToUID(from); - if (uid < 0) - return B_BAD_VALUE; - fMailEntryMap[uid].fileName = to.name; - return B_OK; -} - - -bool -IMAPStorage::HasFile(int32 uid) -{ - MailEntryMap::const_iterator it = fMailEntryMap.find(uid); - if (it == fMailEntryMap.end()) - return false; - return true; -} - - -status_t -IMAPStorage::SetCompleteMessageSize(int32 uid, int32 size) -{ - MailEntryMap::iterator it = fMailEntryMap.find(uid); - if (it == fMailEntryMap.end()) - return false; - StorageMailEntry& storageEntry = (*it).second; - BPath filePath = fMailboxPath; - filePath.Append(storageEntry.fileName); - BNode node(filePath.Path()); - - if (node.WriteAttr("MAIL:size", B_INT32_TYPE, 0, &size, sizeof(int32)) < 0) - return B_ERROR; - return B_OK; -} - - -StorageMailEntry* -IMAPStorage::GetEntryForRef(const node_ref& ref) -{ - for (MailEntryMap::iterator it = fMailEntryMap.begin(); - it != fMailEntryMap.end(); it++) { - StorageMailEntry& mailEntry = (*it).second; - if (mailEntry.nodeRef == ref) - return &mailEntry; - } - return NULL; -} - - -bool -IMAPStorage::IsBodyFetched(int32 uid) -{ - MailEntryMap::iterator it = fMailEntryMap.find(uid); - if (it == fMailEntryMap.end()) - return false; - StorageMailEntry& storageEntry = (*it).second; - BPath filePath = fMailboxPath; - filePath.Append(storageEntry.fileName); - BNode node(filePath.Path()); - - char buffer[B_MIME_TYPE_LENGTH]; - BNodeInfo info(&node); - info.GetType(buffer); - - return strcmp(buffer, B_MAIL_TYPE) == 0; -} - - -int32 -IMAPStorage::RefToUID(const entry_ref& ref) -{ - for (MailEntryMap::iterator it = fMailEntryMap.begin(); - it != fMailEntryMap.end(); it++) { - StorageMailEntry& mailEntry = (*it).second; - if (mailEntry.fileName == ref.name) - return mailEntry.uid; - } - - // not found try to fix internal name - BDirectory dir(fMailboxPath.Path()); - if (!dir.Contains(ref.name)) - return -1; - - BNode node(&ref); - int32 uid; - if (ReadUniqueID(node, uid) != B_OK) - return -1; - - MailEntryMap::iterator it = fMailEntryMap.find(uid); - if (it == fMailEntryMap.end()) - return -1; - it->second.fileName = ref.name; - - return uid; -} - - -bool -IMAPStorage::UIDToRef(int32 uid, entry_ref& ref) -{ - MailEntryMap::iterator it = fMailEntryMap.find(uid); - if (it == fMailEntryMap.end()) - return false; - - StorageMailEntry& mailEntry = (*it).second; - BPath filePath = fMailboxPath; - filePath.Append(mailEntry.fileName); - - BEntry entry(filePath.Path()); - if (entry.GetRef(&ref) == B_OK) - return true; - return false; -} - - -status_t -IMAPStorage::_ReadFilesThreadFunction(void* data) -{ - IMAPStorage* storage = (IMAPStorage*)data; - return storage->_ReadFiles(); -} - - -status_t -IMAPStorage::_ReadFiles() -{ - fMailEntryMap.clear(); - - BDirectory directory(fMailboxPath.Path()); - - entry_ref ref; - while (directory.GetNextRef(&ref) != B_ENTRY_NOT_FOUND) { - BNode node(&ref); - if (node.InitCheck() != B_OK || !node.IsFile()) - continue; - - char buffer[B_MIME_TYPE_LENGTH]; - BNodeInfo info(&node); - info.GetType(buffer); - - // maybe interrupted downloads ignore them - if (strcmp(buffer, "text/x-partial-email") != 0 - && strcmp(buffer, B_MAIL_TYPE) != 0) - continue; - - StorageMailEntry entry; - entry.fileName = ref.name; - if (ReadUniqueID(node, entry.uid) != B_OK) { - TRACE("IMAPStorage::_ReadFilesThread() failed to read uid %s\n", - ref.name); - continue; - } - - if (node.ReadAttr("MAIL:server_flags", B_INT32_TYPE, 0, &entry.flags, - sizeof(int32)) != sizeof(int32)) - continue; - - node.GetNodeRef(&entry.nodeRef); - - fMailEntryMap[entry.uid] = entry; - } - - release_sem(fLoadDatabaseLock); - return B_OK; -} - - -status_t -IMAPStorage::_WriteFlags(int32 flags, BNode& node) -{ - if ((flags & kSeen) != 0) - write_read_attr(node, B_READ); - else - write_read_attr(node, B_UNREAD); - - ssize_t writen = node.WriteAttr("MAIL:server_flags", B_INT32_TYPE, 0, - &flags, sizeof(int32)); - if (writen != sizeof(int32)) - return writen; - - return B_OK; -} - - -status_t -IMAPStorage::ReadUniqueID(BNode& node, int32& uid) -{ - const uint32 kMaxUniqueLength = 32; - char uidString[kMaxUniqueLength]; - memset(uidString, 0, kMaxUniqueLength); - if (node.ReadAttr("MAIL:unique_id", B_STRING_TYPE, 0, uidString, - kMaxUniqueLength) < 0) - return B_ERROR; - uid = atoi(uidString); - return B_OK; -} - - -status_t -IMAPStorage::_WriteUniqueID(BNode& node, int32 uid) -{ - BString uidString; - uidString << uid; - ssize_t written = node.WriteAttr("MAIL:unique_id", B_STRING_TYPE, 0, - uidString.String(), uidString.Length()); - if (written < 0) - return written; - return B_OK; -} diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/IMAPStorage.h b/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/IMAPStorage.h deleted file mode 100644 index 8f63a2a182..0000000000 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/IMAPStorage.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2010, Haiku Inc. All Rights Reserved. - * Copyright 2010 Clemens Zeidler. All rights reserved. - * - * Distributed under the terms of the MIT License. - */ -#ifndef IMAP_STORAGE_H -#define IMAP_STORAGE_H - - -#include -#include - -#include -#include -#include -#include - - -struct StorageMailEntry { - int32 uid; - int32 flags; - node_ref nodeRef; - BString fileName; -}; - - -typedef std::map MailEntryMap; - - -class IMAPStorage { -public: - enum MessageState { - kHeaderDownloaded = 0x01, - kBodyDownloaded = 0x02 - }; - - IMAPStorage(); - ~IMAPStorage(); - - void SetTo(const char* dir); - - status_t StartReadDatabase(); - status_t WaitForDatabaseRead(); - - status_t AddNewMessage(int32 uid, int32 flags, - BPositionIO** file = NULL); - status_t OpenMessage(int32 uid, BPositionIO** file); - - /*! Remove the message from the storage. */ - status_t DeleteMessage(int32 uid); - - status_t SetFlags(int32 uid, int32 flags); - int32 GetFlags(int32 uid); - - status_t SetFileName(int32 uid, const BString& name); - status_t FileRenamed(const entry_ref& from, - const entry_ref& to); - - const MailEntryMap& GetFiles() { return fMailEntryMap; } - bool HasFile(int32 uid); - - status_t SetCompleteMessageSize(int32 uid, int32 size); - - bool IsBodyFetched(int32 uid); - - StorageMailEntry* GetEntryForRef(const node_ref& ref); - int32 RefToUID(const entry_ref& ref); - bool UIDToRef(int32 uid, entry_ref& ref); - - status_t ReadUniqueID(BNode& node, int32& uid); - -private: - static status_t _ReadFilesThreadFunction(void* data); - status_t _ReadFiles(); - - status_t _WriteFlags(int32 flags, BNode& node); - status_t _WriteUniqueID(BNode& node, int32 uid); - -private: - BPath fMailboxPath; - - sem_id fLoadDatabaseLock; - MailEntryMap fMailEntryMap; -}; - - -class IMAPMailbox; -typedef std::vector MessageNumberList; - -class IMAPMailboxSync { -public: - status_t Sync(IMAPStorage& storage, - IMAPMailbox& mailbox); - const MessageNumberList& ToFetchList() { return fToFetchList; } - -private: - MessageNumberList fToFetchList; -}; - - -#endif // IMAP_STORAGE_H