* 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:
parent
cdffe7e544
commit
d396412d0b
|
@ -35,7 +35,21 @@
|
||||||
#define B_TRANSLATE_CONTEXT "MailDaemon"
|
#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()
|
makeIndices()
|
||||||
{
|
{
|
||||||
const char* stringIndices[] = {
|
const char* stringIndices[] = {
|
||||||
|
@ -67,7 +81,7 @@ makeIndices()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
static void
|
||||||
addAttribute(BMessage& msg, const char* name, const char* publicName,
|
addAttribute(BMessage& msg, const char* name, const char* publicName,
|
||||||
int32 type = B_STRING_TYPE, bool viewable = true, bool editable = false,
|
int32 type = B_STRING_TYPE, bool viewable = true, bool editable = false,
|
||||||
int32 width = 200)
|
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
|
void
|
||||||
MailDaemonApp::_InitAccounts()
|
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.
|
/*! Work-around for a broken index that contains out-of-date information.
|
||||||
*/
|
*/
|
||||||
|
/*static*/ bool
|
||||||
/* static */
|
|
||||||
bool
|
|
||||||
MailDaemonApp::_IsPending(BNode& node)
|
MailDaemonApp::_IsPending(BNode& node)
|
||||||
{
|
{
|
||||||
int32 flags;
|
int32 flags;
|
||||||
|
@ -828,8 +828,7 @@ MailDaemonApp::_IsPending(BNode& node)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* static */
|
/*static*/ bool
|
||||||
bool
|
|
||||||
MailDaemonApp::_IsEntryInTrash(BEntry& entry)
|
MailDaemonApp::_IsEntryInTrash(BEntry& entry)
|
||||||
{
|
{
|
||||||
entry_ref ref;
|
entry_ref ref;
|
||||||
|
|
|
@ -50,18 +50,18 @@ public:
|
||||||
MailDaemonApp();
|
MailDaemonApp();
|
||||||
virtual ~MailDaemonApp();
|
virtual ~MailDaemonApp();
|
||||||
|
|
||||||
virtual void MessageReceived(BMessage* message);
|
virtual void ReadyToRun();
|
||||||
virtual void RefsReceived(BMessage* message);
|
virtual void RefsReceived(BMessage* message);
|
||||||
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
virtual void Pulse();
|
virtual void Pulse();
|
||||||
virtual bool QuitRequested();
|
virtual bool QuitRequested();
|
||||||
virtual void ReadyToRun();
|
|
||||||
|
|
||||||
void InstallDeskbarIcon();
|
void InstallDeskbarIcon();
|
||||||
void RemoveDeskbarIcon();
|
void RemoveDeskbarIcon();
|
||||||
|
|
||||||
void SendPendingMessages(BMessage* message);
|
|
||||||
void GetNewMessages(BMessage* message);
|
void GetNewMessages(BMessage* message);
|
||||||
|
void SendPendingMessages(BMessage* message);
|
||||||
|
|
||||||
void MakeMimeTypes(bool remakeMIMETypes = false);
|
void MakeMimeTypes(bool remakeMIMETypes = false);
|
||||||
|
|
||||||
|
@ -82,6 +82,7 @@ private:
|
||||||
OutboundProtocolThread* _FindOutboundProtocol(int32 account);
|
OutboundProtocolThread* _FindOutboundProtocol(int32 account);
|
||||||
|
|
||||||
void _UpdateAutoCheck(bigtime_t interval);
|
void _UpdateAutoCheck(bigtime_t interval);
|
||||||
|
|
||||||
static bool _IsPending(BNode& node);
|
static bool _IsPending(BNode& node);
|
||||||
static bool _IsEntryInTrash(BEntry& entry);
|
static bool _IsEntryInTrash(BEntry& entry);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue