Started working on the IMAP add-on itself.
* Renamed imap_config.cpp to ConfigView.cpp, IMAPFolderConfig.(h|cpp) to FolderConfigWindow.(h|cpp). * Got the latter to build. * Added Settings class to simplify and unify the BMessage based settings access. * Removed the InboundProtocol[Thread] implementation from the build for now.
This commit is contained in:
@@ -1,48 +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.
|
||||
*/
|
||||
#ifndef SERVER_CONNECTION_H
|
||||
#define SERVER_CONNECTION_H
|
||||
|
||||
|
||||
#include "SupportDefs.h"
|
||||
|
||||
|
||||
namespace BPrivate {
|
||||
|
||||
|
||||
class AbstractConnection;
|
||||
|
||||
|
||||
class ServerConnection {
|
||||
public:
|
||||
ServerConnection();
|
||||
~ServerConnection();
|
||||
|
||||
status_t ConnectSSL(const char* server,
|
||||
uint32 port = 993);
|
||||
|
||||
status_t ConnectSocket(const char* server,
|
||||
uint32 port = 143);
|
||||
status_t Disconnect();
|
||||
|
||||
status_t WaitForData(bigtime_t timeout);
|
||||
|
||||
ssize_t Read(char* buffer, uint32 length);
|
||||
ssize_t Write(const char* buffer, uint32 length);
|
||||
|
||||
private:
|
||||
AbstractConnection* fConnection;
|
||||
};
|
||||
|
||||
|
||||
} // namespace BPrivate
|
||||
|
||||
|
||||
using BPrivate::ServerConnection;
|
||||
|
||||
|
||||
#endif // SERVER_CONNECTION_H
|
||||
+12
-12
@@ -18,7 +18,7 @@
|
||||
#include <ProtocolConfigView.h>
|
||||
#include <MailPrivate.h>
|
||||
|
||||
#include "IMAPFolderConfig.h"
|
||||
#include "FolderConfigWindow.h"
|
||||
|
||||
|
||||
#undef B_TRANSLATION_CONTEXT
|
||||
@@ -28,11 +28,11 @@
|
||||
const uint32 kMsgOpenIMAPFolder = '&OIF';
|
||||
|
||||
|
||||
class IMAPConfig : public BMailProtocolConfigView {
|
||||
class ConfigView : public BMailProtocolConfigView {
|
||||
public:
|
||||
IMAPConfig(MailAddonSettings& settings,
|
||||
ConfigView(MailAddonSettings& settings,
|
||||
BMailAccountSettings& accountSettings);
|
||||
virtual ~IMAPConfig();
|
||||
virtual ~ConfigView();
|
||||
virtual status_t Archive(BMessage *into, bool deep = true) const;
|
||||
virtual void GetPreferredSize(float *width, float *height);
|
||||
|
||||
@@ -40,13 +40,13 @@ public:
|
||||
virtual void AttachedToWindow();
|
||||
|
||||
private:
|
||||
BMailFileConfigView* fFileView;
|
||||
BMailFileConfigView* fFileView;
|
||||
BButton* fIMAPFolderButton;
|
||||
MailAddonSettings& fAddonSettings;
|
||||
};
|
||||
|
||||
|
||||
IMAPConfig::IMAPConfig(MailAddonSettings& settings,
|
||||
ConfigView::ConfigView(MailAddonSettings& settings,
|
||||
BMailAccountSettings& accountSettings)
|
||||
:
|
||||
BMailProtocolConfigView(B_MAIL_PROTOCOL_HAS_USERNAME
|
||||
@@ -93,13 +93,13 @@ IMAPConfig::IMAPConfig(MailAddonSettings& settings,
|
||||
}
|
||||
|
||||
|
||||
IMAPConfig::~IMAPConfig()
|
||||
ConfigView::~ConfigView()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
IMAPConfig::Archive(BMessage *into, bool deep) const
|
||||
ConfigView::Archive(BMessage *into, bool deep) const
|
||||
{
|
||||
fFileView->Archive(into, deep);
|
||||
return BMailProtocolConfigView::Archive(into, deep);
|
||||
@@ -107,7 +107,7 @@ IMAPConfig::Archive(BMessage *into, bool deep) const
|
||||
|
||||
|
||||
void
|
||||
IMAPConfig::GetPreferredSize(float *width, float *height)
|
||||
ConfigView::GetPreferredSize(float *width, float *height)
|
||||
{
|
||||
BMailProtocolConfigView::GetPreferredSize(width,height);
|
||||
*height -= 20;
|
||||
@@ -115,7 +115,7 @@ IMAPConfig::GetPreferredSize(float *width, float *height)
|
||||
|
||||
|
||||
void
|
||||
IMAPConfig::MessageReceived(BMessage* message)
|
||||
ConfigView::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case kMsgOpenIMAPFolder:
|
||||
@@ -135,7 +135,7 @@ IMAPConfig::MessageReceived(BMessage* message)
|
||||
|
||||
|
||||
void
|
||||
IMAPConfig::AttachedToWindow()
|
||||
ConfigView::AttachedToWindow()
|
||||
{
|
||||
fIMAPFolderButton->SetTarget(this);
|
||||
}
|
||||
@@ -148,5 +148,5 @@ BView*
|
||||
instantiate_config_panel(MailAddonSettings& settings,
|
||||
BMailAccountSettings& accountSettings)
|
||||
{
|
||||
return new IMAPConfig(settings, accountSettings);
|
||||
return new ConfigView(settings, accountSettings);
|
||||
}
|
||||
+17
-32
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "IMAPFolderConfig.h"
|
||||
#include "FolderConfigWindow.h"
|
||||
|
||||
#include <Catalog.h>
|
||||
#include <ControlLook.h>
|
||||
@@ -17,7 +17,7 @@
|
||||
#include <ALMGroup.h>
|
||||
#include <StringForSize.h>
|
||||
|
||||
#include <crypt.h>
|
||||
#include "Settings.h"
|
||||
|
||||
|
||||
#undef B_TRANSLATION_CONTEXT
|
||||
@@ -311,30 +311,15 @@ FolderConfigWindow::_LoadFolders()
|
||||
B_TRANSLATE("Fetching IMAP folders, have patience..."));
|
||||
status->Show();
|
||||
|
||||
BString server;
|
||||
fSettings.FindString("server", &server);
|
||||
int32 ssl;
|
||||
fSettings.FindInt32("flavor", &ssl);
|
||||
bool useSSL = false;
|
||||
if (ssl == 1)
|
||||
useSSL = true;
|
||||
fProtocol.Connect(fSettings.ServerAddress(), fSettings.Username(),
|
||||
fSettings.Password(), fSettings.UseSSL());
|
||||
|
||||
BString username;
|
||||
fSettings.FindString("username", &username);
|
||||
|
||||
BString password;
|
||||
char* passwd = get_passwd(&fSettings, "cpasswd");
|
||||
if (passwd != NULL) {
|
||||
password = passwd;
|
||||
delete[] passwd;
|
||||
}
|
||||
|
||||
fProtocol.Connect(server, username, password, useSSL);
|
||||
// TODO: don't get all of them at once, but retrieve them level by level
|
||||
fFolderList.clear();
|
||||
fProtocol.GetFolders(fFolderList);
|
||||
for (unsigned int i = 0; i < fFolderList.size(); i++) {
|
||||
FolderInfo& info = fFolderList[i];
|
||||
CheckBoxItem* item = new CheckBoxItem(info.folder, info.subscribed);
|
||||
for (size_t i = 0; i < fFolderList.size(); i++) {
|
||||
IMAP::FolderEntry& entry = fFolderList[i];
|
||||
CheckBoxItem* item = new CheckBoxItem(entry.folder, entry.subscribed);
|
||||
fFolderListView->AddItem(item);
|
||||
item->SetListView(fFolderListView);
|
||||
}
|
||||
@@ -358,10 +343,10 @@ void
|
||||
FolderConfigWindow::_ApplyChanges()
|
||||
{
|
||||
bool haveChanges = false;
|
||||
for (unsigned int i = 0; i < fFolderList.size(); i++) {
|
||||
FolderInfo& info = fFolderList[i];
|
||||
for (size_t i = 0; i < fFolderList.size(); i++) {
|
||||
IMAP::FolderEntry& entry = fFolderList[i];
|
||||
CheckBoxItem* item = (CheckBoxItem*)fFolderListView->ItemAt(i);
|
||||
if ((info.subscribed != item->Checked())) {
|
||||
if (entry.subscribed != item->Checked()) {
|
||||
haveChanges = true;
|
||||
break;
|
||||
}
|
||||
@@ -373,13 +358,13 @@ FolderConfigWindow::_ApplyChanges()
|
||||
"IMAP folders, have patience..."));
|
||||
status->Show();
|
||||
|
||||
for (unsigned int i = 0; i < fFolderList.size(); i++) {
|
||||
FolderInfo& info = fFolderList[i];
|
||||
for (size_t i = 0; i < fFolderList.size(); i++) {
|
||||
IMAP::FolderEntry& entry = fFolderList[i];
|
||||
CheckBoxItem* item = (CheckBoxItem*)fFolderListView->ItemAt(i);
|
||||
if (info.subscribed && !item->Checked())
|
||||
fProtocol.UnsubscribeFolder(info.folder);
|
||||
else if (!info.subscribed && item->Checked())
|
||||
fProtocol.SubscribeFolder(info.folder);
|
||||
if (entry.subscribed && !item->Checked())
|
||||
fProtocol.UnsubscribeFolder(entry.folder);
|
||||
else if (!entry.subscribed && item->Checked())
|
||||
fProtocol.SubscribeFolder(entry.folder);
|
||||
}
|
||||
|
||||
status->PostMessage(B_QUIT_REQUESTED);
|
||||
+6
-4
@@ -3,8 +3,8 @@
|
||||
* Copyright 2011, Clemens Zeidler <haiku@clemens-zeidler.de>
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef IMAP_FOLDER_CONFIG_H
|
||||
#define IMAP_FOLDER_CONFIG_H
|
||||
#ifndef FOLDER_CONFIG_WINDOW_H
|
||||
#define FOLDER_CONFIG_WINDOW_H
|
||||
|
||||
|
||||
#include <Button.h>
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <MailSettings.h>
|
||||
|
||||
#include "Protocol.h"
|
||||
#include "Settings.h"
|
||||
|
||||
|
||||
class FolderConfigWindow : public BWindow {
|
||||
@@ -28,14 +29,15 @@ private:
|
||||
void _LoadFolders();
|
||||
void _ApplyChanges();
|
||||
|
||||
private:
|
||||
const Settings fSettings;
|
||||
IMAP::Protocol fProtocol;
|
||||
BListView* fFolderListView;
|
||||
BButton* fApplyButton;
|
||||
const BMessage fSettings;
|
||||
IMAP::FolderList fFolderList;
|
||||
|
||||
BStringView* fQuotaView;
|
||||
};
|
||||
|
||||
|
||||
#endif //IMAP_FOLDER_CONFIG_H
|
||||
#endif // FOLDER_CONFIG_WINDOW_H
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright 2011, Haiku, Inc. All rights reserved.
|
||||
* Copyright 2011, Clemens Zeidler <[email protected]>
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef IMAP_H
|
||||
#define IMAP_H
|
||||
|
||||
|
||||
#include "MailProtocol.h"
|
||||
|
||||
#include <Handler.h>
|
||||
#include <Locker.h>
|
||||
#include <Message.h>
|
||||
|
||||
#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
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2011, Axel Dörfler, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "IMAPConnectionWorker.h"
|
||||
|
||||
|
||||
IMAPConnectionWorker::IMAPConnectionWorker(IMAP::Protocol& protocol,
|
||||
StringList& mailboxes)
|
||||
:
|
||||
fProtocol(protocol)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
IMAPConnectionWorker::~IMAPConnectionWorker()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
IMAPConnectionWorker::Start(bool usePush)
|
||||
{
|
||||
fThread = spawn_thread(&_Worker, "imap connection worker",
|
||||
B_NORMAL_PRIORITY, this);
|
||||
if (fThread < 0)
|
||||
return fThread;
|
||||
|
||||
resume_thread(fThread);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
IMAPConnectionWorker::Stop()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
IMAPConnectionWorker::_Worker()
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ status_t
|
||||
IMAPConnectionWorker::_Worker(void* self)
|
||||
{
|
||||
return ((IMAPConnectionWorker*)self)->_Worker();
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2011, Axel Dörfler, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef IMAP_CONNECTION_WORKER_H
|
||||
#define IMAP_CONNECTION_WORKER_H
|
||||
|
||||
|
||||
#include <Locker.h>
|
||||
#include <String.h>
|
||||
|
||||
#include "Protocol.h"
|
||||
|
||||
|
||||
class IMAPConnectionWorker {
|
||||
public:
|
||||
IMAPConnectionWorker(IMAP::Protocol& protocol,
|
||||
StringList& mailboxes);
|
||||
virtual ~IMAPConnectionWorker();
|
||||
|
||||
status_t Start(bool usePush);
|
||||
void Stop();
|
||||
|
||||
private:
|
||||
status_t _Worker();
|
||||
static status_t _Worker(void* self);
|
||||
|
||||
private:
|
||||
IMAP::Protocol& fProtocol;
|
||||
BString fIdleBox;
|
||||
StringList fOtherBoxes;
|
||||
|
||||
BLocker fLocker;
|
||||
thread_id fThread;
|
||||
};
|
||||
|
||||
|
||||
#endif // IMAP_CONNECTION_WORKER_H
|
||||
@@ -16,14 +16,16 @@ UseLibraryHeaders linprog alm ;
|
||||
SubDirHdrs [ FDirName $(HAIKU_TOP) headers os add-ons mail_daemon ] ;
|
||||
|
||||
local sources =
|
||||
imap_config.cpp
|
||||
IMAPInboundProtocol.cpp
|
||||
IMAPRootInboundProtocol.cpp
|
||||
IMAPFolderConfig.cpp
|
||||
# IMAPInboundProtocol.cpp
|
||||
# IMAPRootInboundProtocol.cpp
|
||||
ConfigView.cpp
|
||||
FolderConfigWindow.cpp
|
||||
IMAPConnectionWorker.cpp
|
||||
Settings.cpp
|
||||
|
||||
# imap_lib
|
||||
Commands.cpp
|
||||
Protocol.cpp
|
||||
IMAPStorage.cpp
|
||||
Response.cpp
|
||||
;
|
||||
|
||||
@@ -40,12 +42,11 @@ Addon IMAP
|
||||
:
|
||||
$(sources)
|
||||
:
|
||||
be libmail.so localestub $(TARGET_NETWORK_LIBS) libalm.so
|
||||
libshared.a [ TargetLibsupc++ ] [ TargetLibstdc++ ]
|
||||
be libmail.so localestub $(TARGET_NETWORK_LIBS) libbnetapi.so
|
||||
libalm.so libshared.a [ TargetLibsupc++ ] [ TargetLibstdc++ ]
|
||||
;
|
||||
|
||||
SEARCH on [ FGristFiles Commands.cpp IMAPMailbox.cpp
|
||||
IMAPProtocol.cpp IMAPStorage.cpp Response.cpp ]
|
||||
SEARCH on [ FGristFiles Commands.cpp Protocol.cpp Response.cpp ]
|
||||
= [ FDirName $(HAIKU_TOP) src add-ons mail_daemon inbound_protocols imap
|
||||
imap_lib ] ;
|
||||
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2011, Axel Dörfler, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "Settings.h"
|
||||
|
||||
#include <crypt.h>
|
||||
|
||||
|
||||
Settings::Settings(const BMessage& archive)
|
||||
:
|
||||
fMessage(archive)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Settings::~Settings()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BNetworkAddress
|
||||
Settings::ServerAddress() const
|
||||
{
|
||||
return BNetworkAddress(Server(), Port());
|
||||
}
|
||||
|
||||
|
||||
BString
|
||||
Settings::Server() const
|
||||
{
|
||||
BString server;
|
||||
if (fMessage.FindString("server", &server) == B_OK)
|
||||
return server;
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
uint16
|
||||
Settings::Port() const
|
||||
{
|
||||
int32 port;
|
||||
if (fMessage.FindInt32("port", &port) == B_OK)
|
||||
return port;
|
||||
|
||||
return UseSSL() ? 993 : 143;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Settings::UseSSL() const
|
||||
{
|
||||
int32 flavor;
|
||||
if (fMessage.FindInt32("flavor", &flavor) == B_OK)
|
||||
return flavor == 1;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
BString
|
||||
Settings::Username() const
|
||||
{
|
||||
BString username;
|
||||
if (fMessage.FindString("username", &username) == B_OK)
|
||||
return username;
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
BString
|
||||
Settings::Password() const
|
||||
{
|
||||
BString password;
|
||||
char* passwd = get_passwd(&fMessage, "cpasswd");
|
||||
if (passwd != NULL) {
|
||||
password = passwd;
|
||||
delete[] passwd;
|
||||
return password;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2011, Axel Dörfler, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef SETTINGS_H
|
||||
#define SETTINGS_H
|
||||
|
||||
|
||||
#include <Message.h>
|
||||
#include <NetworkAddress.h>
|
||||
|
||||
|
||||
class Settings {
|
||||
public:
|
||||
Settings(const BMessage& archive);
|
||||
~Settings();
|
||||
|
||||
BNetworkAddress ServerAddress() const;
|
||||
|
||||
BString Server() const;
|
||||
uint16 Port() const;
|
||||
bool UseSSL() const;
|
||||
|
||||
BString Username() const;
|
||||
BString Password() const;
|
||||
|
||||
private:
|
||||
const BMessage& fMessage;
|
||||
};
|
||||
|
||||
|
||||
#endif // SETTINGS_H
|
||||
@@ -628,18 +628,33 @@ FlagsHandler::HandleUntagged(const BString& response)
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
ListCommand::ListCommand(const char* prefix, bool subscribedOnly)
|
||||
:
|
||||
fPrefix(prefix),
|
||||
fSubscribedOnly(subscribedOnly)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BString
|
||||
ListCommand::CommandString()
|
||||
{
|
||||
fFolders.clear();
|
||||
return "LIST \"\" \"*\"";
|
||||
BString command = _Command();
|
||||
command += " \"\" \"";
|
||||
if (fPrefix != NULL)
|
||||
command << fPrefix << "%";
|
||||
else
|
||||
command += "*";
|
||||
command += "\"";
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ListCommand::HandleUntagged(Response& response)
|
||||
{
|
||||
if (response.IsCommand("LIST") && response.IsStringAt(3)) {
|
||||
if (response.IsCommand(_Command()) && response.IsStringAt(3)) {
|
||||
fFolders.push_back(response.StringAt(3));
|
||||
return true;
|
||||
}
|
||||
@@ -655,33 +670,10 @@ ListCommand::FolderList()
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
BString
|
||||
ListSubscribedCommand::CommandString()
|
||||
const char*
|
||||
ListCommand::_Command() const
|
||||
{
|
||||
fFolders.clear();
|
||||
return "LSUB \"\" \"*\"";
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ListSubscribedCommand::HandleUntagged(Response& response)
|
||||
{
|
||||
if (response.IsCommand("LSUB") && response.IsStringAt(3)) {
|
||||
fFolders.push_back(response.StringAt(3));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const StringList&
|
||||
ListSubscribedCommand::FolderList()
|
||||
{
|
||||
return fFolders;
|
||||
return fSubscribedOnly ? "LSUB" : "LIST";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -246,25 +246,21 @@ public:
|
||||
|
||||
class ListCommand : public Command, public Handler {
|
||||
public:
|
||||
ListCommand(const char* prefix,
|
||||
bool subscribedOnly);
|
||||
|
||||
BString CommandString();
|
||||
bool HandleUntagged(Response& response);
|
||||
|
||||
const StringList& FolderList();
|
||||
|
||||
private:
|
||||
StringList fFolders;
|
||||
};
|
||||
|
||||
|
||||
class ListSubscribedCommand : public Command, public Handler {
|
||||
public:
|
||||
BString CommandString();
|
||||
bool HandleUntagged(Response& response);
|
||||
|
||||
const StringList& FolderList();
|
||||
const char* _Command() const;
|
||||
|
||||
private:
|
||||
const char* fPrefix;
|
||||
StringList fFolders;
|
||||
bool fSubscribedOnly;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -123,16 +123,16 @@ Protocol::GetFolders(FolderList& folders)
|
||||
return status;
|
||||
|
||||
for (unsigned int i = 0; i < allFolders.size(); i++) {
|
||||
FolderInfo info;
|
||||
info.folder = allFolders[i];
|
||||
FolderEntry entry;
|
||||
entry.folder = allFolders[i];
|
||||
for (unsigned int a = 0; a < subscribedFolders.size(); a++) {
|
||||
if (allFolders[i] == subscribedFolders[a]
|
||||
|| allFolders[i].ICompare("INBOX") == 0) {
|
||||
info.subscribed = true;
|
||||
entry.subscribed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
folders.push_back(info);
|
||||
folders.push_back(entry);
|
||||
}
|
||||
|
||||
// you could be subscribed to a folder which not exist currently, add them:
|
||||
@@ -147,10 +147,10 @@ Protocol::GetFolders(FolderList& folders)
|
||||
if (isInlist)
|
||||
continue;
|
||||
|
||||
FolderInfo info;
|
||||
info.folder = subscribedFolders[a];
|
||||
info.subscribed = true;
|
||||
folders.push_back(info);
|
||||
FolderEntry entry;
|
||||
entry.folder = subscribedFolders[a];
|
||||
entry.subscribed = true;
|
||||
folders.push_back(entry);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
@@ -344,8 +344,11 @@ Protocol::_Disconnect()
|
||||
{
|
||||
fOngoingCommands.clear();
|
||||
fIsConnected = false;
|
||||
delete fBufferedSocket;
|
||||
fBufferedSocket = NULL;
|
||||
delete fSocket;
|
||||
fSocket = NULL;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -353,12 +356,12 @@ Protocol::_Disconnect()
|
||||
status_t
|
||||
Protocol::_GetAllFolders(StringList& folders)
|
||||
{
|
||||
ListCommand listCommand;
|
||||
status_t status = ProcessCommand(listCommand);
|
||||
ListCommand command(NULL, false);
|
||||
status_t status = ProcessCommand(command);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
folders = listCommand.FolderList();
|
||||
folders = command.FolderList();
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -366,12 +369,12 @@ Protocol::_GetAllFolders(StringList& folders)
|
||||
status_t
|
||||
Protocol::_GetSubscribedFolders(StringList& folders)
|
||||
{
|
||||
ListSubscribedCommand listSubscribedCommand;
|
||||
status_t status = ProcessCommand(listSubscribedCommand);
|
||||
ListCommand command(NULL, true);
|
||||
status_t status = ProcessCommand(command);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
folders = listSubscribedCommand.FolderList();
|
||||
folders = command.FolderList();
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,9 +36,9 @@ typedef BObjectList<Handler> HandlerList;
|
||||
typedef std::map<int32, Command*> CommandIDMap;
|
||||
|
||||
|
||||
class FolderInfo {
|
||||
class FolderEntry {
|
||||
public:
|
||||
FolderInfo()
|
||||
FolderEntry()
|
||||
:
|
||||
subscribed(false)
|
||||
{
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
BString folder;
|
||||
bool subscribed;
|
||||
};
|
||||
typedef std::vector<FolderInfo> FolderList;
|
||||
typedef std::vector<FolderEntry> FolderList;
|
||||
|
||||
|
||||
class Protocol {
|
||||
|
||||
@@ -31,7 +31,6 @@ local sources =
|
||||
NodeMessage.cpp
|
||||
numailkit.cpp
|
||||
ProtocolConfigView.cpp
|
||||
ServerConnection.cpp
|
||||
;
|
||||
|
||||
|
||||
|
||||
@@ -1,410 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2011, Haiku, Inc. All rights reserved.
|
||||
* Copyright 2010, Clemens Zeidler <haiku@clemens-zeidler.de>
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "ServerConnection.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/poll.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef USE_SSL
|
||||
# include <openssl/ssl.h>
|
||||
# include <openssl/rand.h>
|
||||
#endif
|
||||
|
||||
#include <Autolock.h>
|
||||
#include <Locker.h>
|
||||
#include <NetworkAddress.h>
|
||||
|
||||
|
||||
#define DEBUG_SERVER_CONNECTION
|
||||
#ifdef DEBUG_SERVER_CONNECTION
|
||||
# include <stdio.h>
|
||||
# define TRACE(x...) printf(x)
|
||||
#else
|
||||
# define TRACE(x...) ;
|
||||
#endif
|
||||
|
||||
|
||||
namespace BPrivate {
|
||||
|
||||
|
||||
class AbstractConnection {
|
||||
public:
|
||||
virtual ~AbstractConnection();
|
||||
|
||||
virtual status_t Connect(const char* server, uint32 port) = 0;
|
||||
virtual status_t Disconnect() = 0;
|
||||
|
||||
virtual status_t WaitForData(bigtime_t timeout) = 0;
|
||||
|
||||
virtual ssize_t Read(char* buffer, uint32 length) = 0;
|
||||
virtual ssize_t Write(const char* buffer, uint32 length) = 0;
|
||||
};
|
||||
|
||||
|
||||
class SocketConnection : public AbstractConnection {
|
||||
public:
|
||||
SocketConnection();
|
||||
|
||||
status_t Connect(const char* server, uint32 port);
|
||||
status_t Disconnect();
|
||||
|
||||
status_t WaitForData(bigtime_t timeout);
|
||||
|
||||
ssize_t Read(char* buffer, uint32 length);
|
||||
ssize_t Write(const char* buffer, uint32 length);
|
||||
|
||||
protected:
|
||||
int fSocket;
|
||||
};
|
||||
|
||||
|
||||
#ifdef USE_SSL
|
||||
|
||||
|
||||
class InitSSL {
|
||||
public:
|
||||
InitSSL()
|
||||
{
|
||||
if (SSL_library_init() != 1) {
|
||||
fInit = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// use combination of more or less random this pointer and system time
|
||||
int64 seed = (int64)this + system_time();
|
||||
RAND_seed(&seed, sizeof(seed));
|
||||
|
||||
fInit = true;
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
status_t InitCheck()
|
||||
{
|
||||
return fInit ? B_OK : B_ERROR;
|
||||
}
|
||||
|
||||
private:
|
||||
bool fInit;
|
||||
};
|
||||
|
||||
|
||||
class SSLConnection : public SocketConnection {
|
||||
public:
|
||||
SSLConnection();
|
||||
|
||||
status_t Connect(const char* server, uint32 port);
|
||||
status_t Disconnect();
|
||||
|
||||
status_t WaitForData(bigtime_t timeout);
|
||||
|
||||
ssize_t Read(char* buffer, uint32 length);
|
||||
ssize_t Write(const char* buffer, uint32 length);
|
||||
|
||||
private:
|
||||
SSL_CTX* fCTX;
|
||||
SSL* fSSL;
|
||||
BIO* fBIO;
|
||||
};
|
||||
|
||||
|
||||
static InitSSL gInitSSL;
|
||||
|
||||
|
||||
#endif // USE_SSL
|
||||
|
||||
|
||||
AbstractConnection::~AbstractConnection()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
ServerConnection::ServerConnection()
|
||||
:
|
||||
fConnection(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ServerConnection::~ServerConnection()
|
||||
{
|
||||
if (fConnection != NULL)
|
||||
fConnection->Disconnect();
|
||||
delete fConnection;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ServerConnection::ConnectSSL(const char* server, uint32 port)
|
||||
{
|
||||
#ifdef USE_SSL
|
||||
delete fConnection;
|
||||
fConnection = new SSLConnection;
|
||||
return fConnection->Connect(server, port);
|
||||
#else
|
||||
return B_ERROR;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ServerConnection::ConnectSocket(const char* server, uint32 port)
|
||||
{
|
||||
delete fConnection;
|
||||
fConnection = new SocketConnection;
|
||||
return fConnection->Connect(server, port);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ServerConnection::Disconnect()
|
||||
{
|
||||
if (fConnection == NULL)
|
||||
return B_ERROR;
|
||||
return fConnection->Disconnect();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ServerConnection::WaitForData(bigtime_t timeout)
|
||||
{
|
||||
if (fConnection == NULL)
|
||||
return B_ERROR;
|
||||
return fConnection->WaitForData(timeout);
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
ServerConnection::Read(char* buffer, uint32 nBytes)
|
||||
{
|
||||
if (fConnection == NULL)
|
||||
return B_ERROR;
|
||||
return fConnection->Read(buffer, nBytes);
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
ServerConnection::Write(const char* buffer, uint32 nBytes)
|
||||
{
|
||||
if (fConnection == NULL)
|
||||
return B_ERROR;
|
||||
return fConnection->Write(buffer, nBytes);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
SocketConnection::SocketConnection()
|
||||
:
|
||||
fSocket(-1)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
SocketConnection::Connect(const char* server, uint32 port)
|
||||
{
|
||||
if (fSocket >= 0)
|
||||
Disconnect();
|
||||
|
||||
TRACE("SocketConnection to server %s:%i\n", server, (int)port);
|
||||
|
||||
BNetworkAddress address;
|
||||
status_t status = address.SetTo(server, port);
|
||||
if (status != B_OK) {
|
||||
TRACE("%s: Address Error: %s\n", __func__, strerror(status));
|
||||
return status;
|
||||
}
|
||||
|
||||
TRACE("Server resolves to %s\n", address.ToString().String());
|
||||
|
||||
fSocket = socket(address.Family(), SOCK_STREAM, 0);
|
||||
if (fSocket < 0) {
|
||||
TRACE("%s: Socket Error: %s\n", __func__, strerror(errno));
|
||||
return errno;
|
||||
}
|
||||
|
||||
int result = connect(fSocket, address, address.Length());
|
||||
if (result < 0) {
|
||||
TRACE("%s: Connect Error: %s\n", __func__, strerror(errno));
|
||||
close(fSocket);
|
||||
return errno;
|
||||
}
|
||||
|
||||
TRACE("SocketConnection: connected\n");
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
SocketConnection::Disconnect()
|
||||
{
|
||||
close(fSocket);
|
||||
fSocket = -1;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
SocketConnection::WaitForData(bigtime_t timeout)
|
||||
{
|
||||
struct pollfd entry;
|
||||
entry.fd = fSocket;
|
||||
entry.events = POLLIN;
|
||||
|
||||
int timeoutMillis = -1;
|
||||
if (timeout > 0)
|
||||
timeoutMillis = timeout / 1000;
|
||||
|
||||
int result = poll(&entry, 1, timeoutMillis);
|
||||
if (result == 0)
|
||||
return B_TIMED_OUT;
|
||||
if (result < 0)
|
||||
return errno;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
SocketConnection::Read(char* buffer, uint32 length)
|
||||
{
|
||||
ssize_t bytesReceived = recv(fSocket, buffer, length, 0);
|
||||
if (bytesReceived < 0)
|
||||
return errno;
|
||||
|
||||
return bytesReceived;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
SocketConnection::Write(const char* buffer, uint32 length)
|
||||
{
|
||||
ssize_t bytesWritten = send(fSocket, buffer, length, 0);
|
||||
if (bytesWritten < 0)
|
||||
return errno;
|
||||
|
||||
return bytesWritten;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
#ifdef USE_SSL
|
||||
|
||||
|
||||
SSLConnection::SSLConnection()
|
||||
:
|
||||
fCTX(NULL),
|
||||
fSSL(NULL),
|
||||
fBIO(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
SSLConnection::Connect(const char* server, uint32 port)
|
||||
{
|
||||
if (fSSL != NULL)
|
||||
Disconnect();
|
||||
|
||||
if (gInitSSL.InitCheck() != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
status_t status = SocketConnection::Connect(server, port);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
fCTX = SSL_CTX_new(SSLv23_method());
|
||||
fSSL = SSL_new(fCTX);
|
||||
fBIO = BIO_new_socket(fSocket, BIO_NOCLOSE);
|
||||
SSL_set_bio(fSSL, fBIO, fBIO);
|
||||
|
||||
if (SSL_connect(fSSL) <= 0) {
|
||||
TRACE("SSLConnection can't connect\n");
|
||||
SocketConnection::Disconnect();
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
TRACE("SSLConnection connected\n");
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
SSLConnection::Disconnect()
|
||||
{
|
||||
TRACE("SSLConnection::Disconnect()\n");
|
||||
|
||||
if (fSSL)
|
||||
SSL_shutdown(fSSL);
|
||||
if (fCTX)
|
||||
SSL_CTX_free(fCTX);
|
||||
if (fBIO)
|
||||
BIO_free(fBIO);
|
||||
|
||||
fSSL = NULL;
|
||||
fCTX = NULL;
|
||||
fBIO = NULL;
|
||||
return SocketConnection::Disconnect();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
SSLConnection::WaitForData(bigtime_t timeout)
|
||||
{
|
||||
if (fSSL == NULL)
|
||||
return B_NO_INIT;
|
||||
if (SSL_pending(fSSL) > 0)
|
||||
return B_OK;
|
||||
|
||||
return SocketConnection::WaitForData(timeout);
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
SSLConnection::Read(char* buffer, uint32 length)
|
||||
{
|
||||
if (fSSL == NULL)
|
||||
return B_NO_INIT;
|
||||
|
||||
int bytesRead = SSL_read(fSSL, buffer, length);
|
||||
if (bytesRead > 0)
|
||||
return bytesRead;
|
||||
|
||||
// TODO: translate SSL error codes!
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
SSLConnection::Write(const char* buffer, uint32 length)
|
||||
{
|
||||
if (fSSL == NULL)
|
||||
return B_NO_INIT;
|
||||
|
||||
int bytesWritten = SSL_write(fSSL, buffer, length);
|
||||
if (bytesWritten > 0)
|
||||
return bytesWritten;
|
||||
|
||||
// TODO: translate SSL error codes!
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
#endif // USE_SSL
|
||||
|
||||
|
||||
} // namespace BPrivate
|
||||
Reference in New Issue
Block a user