* Ordered methods in the order of their declaration.

* Minor coding style cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42945 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2011-10-29 11:32:55 +00:00
parent cdffe7e544
commit d396412d0b
2 changed files with 424 additions and 424 deletions

View File

@ -35,7 +35,21 @@
#define B_TRANSLATE_CONTEXT "MailDaemon"
void
struct send_mails_info {
send_mails_info()
{
totalSize = 0;
}
vector<entry_ref> files;
off_t totalSize;
};
// #pragma mark -
static void
makeIndices()
{
const char* stringIndices[] = {
@ -67,7 +81,7 @@ makeIndices()
}
void
static void
addAttribute(BMessage& msg, const char* name, const char* publicName,
int32 type = B_STRING_TYPE, bool viewable = true, bool editable = false,
int32 width = 200)
@ -212,6 +226,406 @@ MailDaemonApp::RefsReceived(BMessage* message)
}
void
MailDaemonApp::MessageReceived(BMessage* msg)
{
switch (msg->what) {
case 'moto':
if (fSettingsFile.CheckOnlyIfPPPUp()) {
// TODO: check whether internet is up and running!
}
// supposed to fall through
case kMsgCheckAndSend: // check & send messages
msg->what = kMsgSendMessages;
PostMessage(msg);
// supposed to fall trough
case kMsgCheckMessage: // check messages
GetNewMessages(msg);
break;
case kMsgSendMessages: // send messages
SendPendingMessages(msg);
break;
case kMsgSettingsUpdated:
fSettingsFile.Reload();
_UpdateAutoCheck(fSettingsFile.AutoCheckInterval());
fMailStatusWindow->SetShowCriterion(fSettingsFile.ShowStatusWindow());
break;
case kMsgAccountsChanged:
_ReloadAccounts(msg);
break;
case kMsgSetStatusWindowMode: // when to show the status window
{
int32 mode;
if (msg->FindInt32("ShowStatusWindow", &mode) == B_OK)
fMailStatusWindow->SetShowCriterion(mode);
break;
}
case kMsgMarkMessageAsRead:
{
int32 account = msg->FindInt32("account");
entry_ref ref;
if (msg->FindRef("ref", &ref) != B_OK)
break;
read_flags read = (read_flags)msg->FindInt32("read");
AccountMap::iterator it = fAccounts.find(account);
if (it == fAccounts.end())
break;
InboundProtocolThread* inboundThread = it->second.inboundThread;
inboundThread->MarkMessageAsRead(ref, read);
break;
}
case kMsgFetchBody:
RefsReceived(msg);
break;
case 'lkch': // status window look changed
case 'wsch': // workspace changed
fMailStatusWindow->PostMessage(msg);
break;
case 'stwg': // Status window gone
{
BMessage reply('mnuc');
reply.AddInt32("num_new_messages", fNewMessages);
while ((msg = fFetchDoneRespondents.RemoveItemAt(0))) {
msg->SendReply(&reply);
delete msg;
}
if (fAlertString != B_EMPTY_STRING) {
fAlertString.Truncate(fAlertString.Length() - 1);
BAlert* alert = new BAlert(B_TRANSLATE("New Messages"),
fAlertString.String(), "OK", NULL, NULL, B_WIDTH_AS_USUAL);
alert->SetFeel(B_NORMAL_WINDOW_FEEL);
alert->Go(NULL);
fAlertString = B_EMPTY_STRING;
}
if (fCentralBeep) {
system_beep("New E-mail");
fCentralBeep = false;
}
break;
}
case 'mcbp':
if (fNewMessages > 0)
fCentralBeep = true;
break;
case kMsgCountNewMessages: // Number of new messages
{
BMessage reply('mnuc'); // Mail New message Count
if (msg->FindBool("wait_for_fetch_done")) {
fFetchDoneRespondents.AddItem(DetachCurrentMessage());
break;
}
reply.AddInt32("num_new_messages", fNewMessages);
msg->SendReply(&reply);
break;
}
case 'mblk': // Mail Blink
if (fNewMessages > 0)
fLEDAnimation->Start();
break;
case 'enda': // End Auto Check
delete fAutoCheckRunner;
fAutoCheckRunner = NULL;
break;
case 'numg':
{
int32 numMessages = msg->FindInt32("num_messages");
BString numString;
if (numMessages > 1)
fAlertString << B_TRANSLATE("%num new messages for %name\n");
else
fAlertString << B_TRANSLATE("%num new message for %name\n");
numString << numMessages;
fAlertString.ReplaceFirst("%num", numString);
fAlertString.ReplaceFirst("%name", msg->FindString("name"));
break;
}
case B_QUERY_UPDATE:
{
int32 what;
msg->FindInt32("opcode", &what);
switch (what) {
case B_ENTRY_CREATED:
fNewMessages++;
break;
case B_ENTRY_REMOVED:
fNewMessages--;
break;
}
BString string, numString;
if (fNewMessages > 0) {
if (fNewMessages != 1)
string << B_TRANSLATE("%num new messages.");
else
string << B_TRANSLATE("%num new message.");
numString << fNewMessages;
string.ReplaceFirst("%num", numString);
}
else
string << B_TRANSLATE("No new messages.");
fMailStatusWindow->SetDefaultMessage(string.String());
break;
}
default:
BApplication::MessageReceived(msg);
break;
}
}
void
MailDaemonApp::Pulse()
{
bigtime_t idle = idle_time();
if (fLEDAnimation->IsRunning() && idle < 100000)
fLEDAnimation->Stop();
}
bool
MailDaemonApp::QuitRequested()
{
RemoveDeskbarIcon();
return true;
}
void
MailDaemonApp::InstallDeskbarIcon()
{
BDeskbar deskbar;
if (!deskbar.HasItem("mail_daemon")) {
BRoster roster;
entry_ref ref;
status_t status = roster.FindApp("application/x-vnd.Be-POST", &ref);
if (status < B_OK) {
fprintf(stderr, "Can't find application to tell deskbar: %s\n",
strerror(status));
return;
}
status = deskbar.AddItem(&ref);
if (status < B_OK) {
fprintf(stderr, "Can't add deskbar replicant: %s\n", strerror(status));
return;
}
}
}
void
MailDaemonApp::RemoveDeskbarIcon()
{
BDeskbar deskbar;
if (deskbar.HasItem("mail_daemon"))
deskbar.RemoveItem("mail_daemon");
}
void
MailDaemonApp::GetNewMessages(BMessage* msg)
{
int32 account = -1;
if (msg->FindInt32("account", &account) == B_OK && account >= 0) {
InboundProtocolThread* protocol = _FindInboundProtocol(account);
if (!protocol)
return;
protocol->SyncMessages();
return;
}
// else check all accounts
AccountMap::const_iterator it = fAccounts.begin();
for (; it != fAccounts.end(); it++) {
InboundProtocolThread* protocol = it->second.inboundThread;
if (!protocol)
continue;
protocol->SyncMessages();
}
}
void
MailDaemonApp::SendPendingMessages(BMessage* msg)
{
BVolumeRoster roster;
BVolume volume;
map<int32, send_mails_info> messages;
int32 account = -1;
if (msg->FindInt32("account", &account) != B_OK)
account = -1;
if (!msg->HasString("message_path")) {
while (roster.GetNextVolume(&volume) == B_OK) {
BQuery query;
query.SetVolume(&volume);
query.PushAttr(B_MAIL_ATTR_FLAGS);
query.PushInt32(B_MAIL_PENDING);
query.PushOp(B_EQ);
query.PushAttr(B_MAIL_ATTR_FLAGS);
query.PushInt32(B_MAIL_PENDING | B_MAIL_SAVE);
query.PushOp(B_EQ);
if (account >= 0) {
query.PushAttr(B_MAIL_ATTR_ACCOUNT_ID);
query.PushInt32(account);
query.PushOp(B_EQ);
query.PushOp(B_AND);
}
query.PushOp(B_OR);
query.Fetch();
BEntry entry;
while (query.GetNextEntry(&entry) == B_OK) {
if (_IsEntryInTrash(entry))
continue;
BNode node;
while (node.SetTo(&entry) == B_BUSY)
snooze(1000);
if (!_IsPending(node))
continue;
int32 messageAccount;
if (node.ReadAttr(B_MAIL_ATTR_ACCOUNT_ID, B_INT32_TYPE, 0,
&messageAccount, sizeof(int32)) < 0)
messageAccount = -1;
off_t size = 0;
node.GetSize(&size);
entry_ref ref;
entry.GetRef(&ref);
messages[messageAccount].files.push_back(ref);
messages[messageAccount].totalSize += size;
}
}
} else {
const char* path;
if (msg->FindString("message_path", &path) != B_OK)
return;
off_t size = 0;
if (BNode(path).GetSize(&size) != B_OK)
return;
BEntry entry(path);
entry_ref ref;
entry.GetRef(&ref);
messages[account].files.push_back(ref);
messages[account].totalSize += size;
}
map<int32, send_mails_info>::iterator iter = messages.begin();
for (; iter != messages.end(); iter++) {
OutboundProtocolThread* protocolThread = _FindOutboundProtocol(
iter->first);
if (!protocolThread)
continue;
send_mails_info& info = iter->second;
if (info.files.size() == 0)
continue;
MailProtocol* protocol = protocolThread->Protocol();
protocolThread->Lock();
protocol->SetTotalItems(info.files.size());
protocol->SetTotalItemsSize(info.totalSize);
protocolThread->Unlock();
protocolThread->SendMessages(iter->second.files, info.totalSize);
}
}
void
MailDaemonApp::MakeMimeTypes(bool remakeMIMETypes)
{
// Add MIME database entries for the e-mail file types we handle. Either
// do a full rebuild from nothing, or just add on the new attributes that
// we support which the regular BeOS mail daemon didn't have.
const uint8 kNTypes = 2;
const char* types[kNTypes] = {"text/x-email", "text/x-partial-email"};
for (size_t i = 0; i < kNTypes; i++) {
BMessage info;
BMimeType mime(types[i]);
if (mime.InitCheck() != B_OK) {
fputs("could not init mime type.\n", stderr);
return;
}
if (!mime.IsInstalled() || remakeMIMETypes) {
// install the full mime type
mime.Delete();
mime.Install();
// Set up the list of e-mail related attributes that Tracker will
// let you display in columns for e-mail messages.
addAttribute(info, B_MAIL_ATTR_NAME, "Name");
addAttribute(info, B_MAIL_ATTR_SUBJECT, "Subject");
addAttribute(info, B_MAIL_ATTR_TO, "To");
addAttribute(info, B_MAIL_ATTR_CC, "Cc");
addAttribute(info, B_MAIL_ATTR_FROM, "From");
addAttribute(info, B_MAIL_ATTR_REPLY, "Reply To");
addAttribute(info, B_MAIL_ATTR_STATUS, "Status");
addAttribute(info, B_MAIL_ATTR_PRIORITY, "Priority", B_STRING_TYPE,
true, true, 40);
addAttribute(info, B_MAIL_ATTR_WHEN, "When", B_TIME_TYPE, true,
false, 150);
addAttribute(info, B_MAIL_ATTR_THREAD, "Thread");
addAttribute(info, B_MAIL_ATTR_ACCOUNT, "Account", B_STRING_TYPE,
true, false, 100);
addAttribute(info, B_MAIL_ATTR_READ, "Read", B_INT32_TYPE,
true, false, 70);
mime.SetAttrInfo(&info);
if (i == 0) {
mime.SetShortDescription("E-mail");
mime.SetLongDescription("Electronic Mail Message");
mime.SetPreferredApp("application/x-vnd.Be-MAIL");
} else {
mime.SetShortDescription("Partial E-mail");
mime.SetLongDescription("A Partially Downloaded E-mail");
mime.SetPreferredApp("application/x-vnd.Be-MAIL");
}
}
}
}
void
MailDaemonApp::_InitAccounts()
{
@ -400,423 +814,9 @@ MailDaemonApp::_UpdateAutoCheck(bigtime_t interval)
}
void
MailDaemonApp::MessageReceived(BMessage* msg)
{
switch (msg->what) {
case 'moto':
if (fSettingsFile.CheckOnlyIfPPPUp()) {
// TODO: check whether internet is up and running!
}
// supposed to fall through
case kMsgCheckAndSend: // check & send messages
msg->what = kMsgSendMessages;
PostMessage(msg);
// supposed to fall trough
case kMsgCheckMessage: // check messages
GetNewMessages(msg);
break;
case kMsgSendMessages: // send messages
SendPendingMessages(msg);
break;
case kMsgSettingsUpdated:
fSettingsFile.Reload();
_UpdateAutoCheck(fSettingsFile.AutoCheckInterval());
fMailStatusWindow->SetShowCriterion(fSettingsFile.ShowStatusWindow());
break;
case kMsgAccountsChanged:
_ReloadAccounts(msg);
break;
case kMsgSetStatusWindowMode: // when to show the status window
{
int32 mode;
if (msg->FindInt32("ShowStatusWindow", &mode) == B_OK)
fMailStatusWindow->SetShowCriterion(mode);
break;
}
case kMsgMarkMessageAsRead:
{
int32 account = msg->FindInt32("account");
entry_ref ref;
if (msg->FindRef("ref", &ref) != B_OK)
break;
read_flags read = (read_flags)msg->FindInt32("read");
AccountMap::iterator it = fAccounts.find(account);
if (it == fAccounts.end())
break;
InboundProtocolThread* inboundThread = it->second.inboundThread;
inboundThread->MarkMessageAsRead(ref, read);
break;
}
case kMsgFetchBody:
RefsReceived(msg);
break;
case 'lkch': // status window look changed
case 'wsch': // workspace changed
fMailStatusWindow->PostMessage(msg);
break;
case 'stwg': // Status window gone
{
BMessage reply('mnuc');
reply.AddInt32("num_new_messages", fNewMessages);
while ((msg = fFetchDoneRespondents.RemoveItemAt(0))) {
msg->SendReply(&reply);
delete msg;
}
if (fAlertString != B_EMPTY_STRING) {
fAlertString.Truncate(fAlertString.Length() - 1);
BAlert* alert = new BAlert(B_TRANSLATE("New Messages"),
fAlertString.String(), "OK", NULL, NULL, B_WIDTH_AS_USUAL);
alert->SetFeel(B_NORMAL_WINDOW_FEEL);
alert->Go(NULL);
fAlertString = B_EMPTY_STRING;
}
if (fCentralBeep) {
system_beep("New E-mail");
fCentralBeep = false;
}
break;
}
case 'mcbp':
if (fNewMessages > 0)
fCentralBeep = true;
break;
case kMsgCountNewMessages: // Number of new messages
{
BMessage reply('mnuc'); // Mail New message Count
if (msg->FindBool("wait_for_fetch_done")) {
fFetchDoneRespondents.AddItem(DetachCurrentMessage());
break;
}
reply.AddInt32("num_new_messages", fNewMessages);
msg->SendReply(&reply);
break;
}
case 'mblk': // Mail Blink
if (fNewMessages > 0)
fLEDAnimation->Start();
break;
case 'enda': // End Auto Check
delete fAutoCheckRunner;
fAutoCheckRunner = NULL;
break;
case 'numg':
{
int32 numMessages = msg->FindInt32("num_messages");
BString numString;
if (numMessages > 1)
fAlertString << B_TRANSLATE("%num new messages for %name\n");
else
fAlertString << B_TRANSLATE("%num new message for %name\n");
numString << numMessages;
fAlertString.ReplaceFirst("%num", numString);
fAlertString.ReplaceFirst("%name", msg->FindString("name"));
break;
}
case B_QUERY_UPDATE:
{
int32 what;
msg->FindInt32("opcode", &what);
switch (what) {
case B_ENTRY_CREATED:
fNewMessages++;
break;
case B_ENTRY_REMOVED:
fNewMessages--;
break;
}
BString string, numString;
if (fNewMessages > 0) {
if (fNewMessages != 1)
string << B_TRANSLATE("%num new messages.");
else
string << B_TRANSLATE("%num new message.");
numString << fNewMessages;
string.ReplaceFirst("%num", numString);
}
else
string << B_TRANSLATE("No new messages.");
fMailStatusWindow->SetDefaultMessage(string.String());
break;
}
default:
BApplication::MessageReceived(msg);
break;
}
}
void
MailDaemonApp::InstallDeskbarIcon()
{
BDeskbar deskbar;
if (!deskbar.HasItem("mail_daemon")) {
BRoster roster;
entry_ref ref;
status_t status = roster.FindApp("application/x-vnd.Be-POST", &ref);
if (status < B_OK) {
fprintf(stderr, "Can't find application to tell deskbar: %s\n",
strerror(status));
return;
}
status = deskbar.AddItem(&ref);
if (status < B_OK) {
fprintf(stderr, "Can't add deskbar replicant: %s\n", strerror(status));
return;
}
}
}
void
MailDaemonApp::RemoveDeskbarIcon()
{
BDeskbar deskbar;
if (deskbar.HasItem("mail_daemon"))
deskbar.RemoveItem("mail_daemon");
}
bool
MailDaemonApp::QuitRequested()
{
RemoveDeskbarIcon();
return true;
}
void
MailDaemonApp::GetNewMessages(BMessage* msg)
{
int32 account = -1;
if (msg->FindInt32("account", &account) == B_OK && account >= 0) {
InboundProtocolThread* protocol = _FindInboundProtocol(account);
if (!protocol)
return;
protocol->SyncMessages();
return;
}
// else check all accounts
AccountMap::const_iterator it = fAccounts.begin();
for (; it != fAccounts.end(); it++) {
InboundProtocolThread* protocol = it->second.inboundThread;
if (!protocol)
continue;
protocol->SyncMessages();
}
}
void
MailDaemonApp::MakeMimeTypes(bool remakeMIMETypes)
{
// Add MIME database entries for the e-mail file types we handle. Either
// do a full rebuild from nothing, or just add on the new attributes that
// we support which the regular BeOS mail daemon didn't have.
const uint8 kNTypes = 2;
const char* types[kNTypes] = {"text/x-email", "text/x-partial-email"};
for (size_t i = 0; i < kNTypes; i++) {
BMessage info;
BMimeType mime(types[i]);
if (mime.InitCheck() != B_OK) {
fputs("could not init mime type.\n", stderr);
return;
}
if (!mime.IsInstalled() || remakeMIMETypes) {
// install the full mime type
mime.Delete();
mime.Install();
// Set up the list of e-mail related attributes that Tracker will
// let you display in columns for e-mail messages.
addAttribute(info, B_MAIL_ATTR_NAME, "Name");
addAttribute(info, B_MAIL_ATTR_SUBJECT, "Subject");
addAttribute(info, B_MAIL_ATTR_TO, "To");
addAttribute(info, B_MAIL_ATTR_CC, "Cc");
addAttribute(info, B_MAIL_ATTR_FROM, "From");
addAttribute(info, B_MAIL_ATTR_REPLY, "Reply To");
addAttribute(info, B_MAIL_ATTR_STATUS, "Status");
addAttribute(info, B_MAIL_ATTR_PRIORITY, "Priority", B_STRING_TYPE,
true, true, 40);
addAttribute(info, B_MAIL_ATTR_WHEN, "When", B_TIME_TYPE, true,
false, 150);
addAttribute(info, B_MAIL_ATTR_THREAD, "Thread");
addAttribute(info, B_MAIL_ATTR_ACCOUNT, "Account", B_STRING_TYPE,
true, false, 100);
addAttribute(info, B_MAIL_ATTR_READ, "Read", B_INT32_TYPE,
true, false, 70);
mime.SetAttrInfo(&info);
if (i == 0) {
mime.SetShortDescription("E-mail");
mime.SetLongDescription("Electronic Mail Message");
mime.SetPreferredApp("application/x-vnd.Be-MAIL");
} else {
mime.SetShortDescription("Partial E-mail");
mime.SetLongDescription("A Partially Downloaded E-mail");
mime.SetPreferredApp("application/x-vnd.Be-MAIL");
}
}
}
}
struct send_mails_info {
send_mails_info()
{
totalSize = 0;
}
vector<entry_ref> files;
off_t totalSize;
};
void
MailDaemonApp::SendPendingMessages(BMessage* msg)
{
BVolumeRoster roster;
BVolume volume;
map<int32, send_mails_info> messages;
int32 account = -1;
if (msg->FindInt32("account", &account) != B_OK)
account = -1;
if (!msg->HasString("message_path")) {
while (roster.GetNextVolume(&volume) == B_OK) {
BQuery query;
query.SetVolume(&volume);
query.PushAttr(B_MAIL_ATTR_FLAGS);
query.PushInt32(B_MAIL_PENDING);
query.PushOp(B_EQ);
query.PushAttr(B_MAIL_ATTR_FLAGS);
query.PushInt32(B_MAIL_PENDING | B_MAIL_SAVE);
query.PushOp(B_EQ);
if (account >= 0) {
query.PushAttr(B_MAIL_ATTR_ACCOUNT_ID);
query.PushInt32(account);
query.PushOp(B_EQ);
query.PushOp(B_AND);
}
query.PushOp(B_OR);
query.Fetch();
BEntry entry;
while (query.GetNextEntry(&entry) == B_OK) {
if (_IsEntryInTrash(entry))
continue;
BNode node;
while (node.SetTo(&entry) == B_BUSY)
snooze(1000);
if (!_IsPending(node))
continue;
int32 messageAccount;
if (node.ReadAttr(B_MAIL_ATTR_ACCOUNT_ID, B_INT32_TYPE, 0,
&messageAccount, sizeof(int32)) < 0)
messageAccount = -1;
off_t size = 0;
node.GetSize(&size);
entry_ref ref;
entry.GetRef(&ref);
messages[messageAccount].files.push_back(ref);
messages[messageAccount].totalSize += size;
}
}
} else {
const char* path;
if (msg->FindString("message_path", &path) != B_OK)
return;
off_t size = 0;
if (BNode(path).GetSize(&size) != B_OK)
return;
BEntry entry(path);
entry_ref ref;
entry.GetRef(&ref);
messages[account].files.push_back(ref);
messages[account].totalSize += size;
}
map<int32, send_mails_info>::iterator iter = messages.begin();
for (; iter != messages.end(); iter++) {
OutboundProtocolThread* protocolThread = _FindOutboundProtocol(
iter->first);
if (!protocolThread)
continue;
send_mails_info& info = iter->second;
if (info.files.size() == 0)
continue;
MailProtocol* protocol = protocolThread->Protocol();
protocolThread->Lock();
protocol->SetTotalItems(info.files.size());
protocol->SetTotalItemsSize(info.totalSize);
protocolThread->Unlock();
protocolThread->SendMessages(iter->second.files, info.totalSize);
}
}
void
MailDaemonApp::Pulse()
{
bigtime_t idle = idle_time();
if (fLEDAnimation->IsRunning() && idle < 100000)
fLEDAnimation->Stop();
}
/*! Work-around for a broken index that contains out-of-date information.
*/
/* static */
bool
/*static*/ bool
MailDaemonApp::_IsPending(BNode& node)
{
int32 flags;
@ -828,8 +828,7 @@ MailDaemonApp::_IsPending(BNode& node)
}
/* static */
bool
/*static*/ bool
MailDaemonApp::_IsEntryInTrash(BEntry& entry)
{
entry_ref ref;

View File

@ -50,18 +50,18 @@ public:
MailDaemonApp();
virtual ~MailDaemonApp();
virtual void MessageReceived(BMessage* message);
virtual void ReadyToRun();
virtual void RefsReceived(BMessage* message);
virtual void MessageReceived(BMessage* message);
virtual void Pulse();
virtual bool QuitRequested();
virtual void ReadyToRun();
void InstallDeskbarIcon();
void RemoveDeskbarIcon();
void SendPendingMessages(BMessage* message);
void GetNewMessages(BMessage* message);
void SendPendingMessages(BMessage* message);
void MakeMimeTypes(bool remakeMIMETypes = false);
@ -82,6 +82,7 @@ private:
OutboundProtocolThread* _FindOutboundProtocol(int32 account);
void _UpdateAutoCheck(bigtime_t interval);
static bool _IsPending(BNode& node);
static bool _IsEntryInTrash(BEntry& entry);