Reworked TrashMonitor to watch actual trash folder(s).
It was still monitoring /boot/home/Desktop/Trash folder, which don't exists anymore. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39803 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+156
-65
@@ -4,22 +4,24 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <String.h>
|
|
||||||
#include <Alert.h>
|
|
||||||
#include <Query.h>
|
|
||||||
#include <VolumeRoster.h>
|
|
||||||
#include <StringList.h>
|
|
||||||
#include <E-mail.h>
|
|
||||||
#include <NodeInfo.h>
|
|
||||||
#include <Directory.h>
|
|
||||||
#include <NodeMonitor.h>
|
|
||||||
#include <Node.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <fs_attr.h>
|
#include <fs_attr.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <Alert.h>
|
||||||
|
#include <Directory.h>
|
||||||
|
#include <FindDirectory.h>
|
||||||
|
#include <Query.h>
|
||||||
|
#include <E-mail.h>
|
||||||
|
#include <Node.h>
|
||||||
|
#include <NodeInfo.h>
|
||||||
|
#include <NodeMonitor.h>
|
||||||
|
#include <Path.h>
|
||||||
|
#include <String.h>
|
||||||
|
#include <StringList.h>
|
||||||
|
#include <VolumeRoster.h>
|
||||||
|
|
||||||
#include <MDRLanguage.h>
|
#include <MDRLanguage.h>
|
||||||
|
|
||||||
class BMailProtocol;
|
class BMailProtocol;
|
||||||
@@ -40,7 +42,7 @@ class ManifestAdder : public BMailChainCallback {
|
|||||||
(**uids_on_disk) += uid;
|
(**uids_on_disk) += uid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BStringList *manifest,**uids_on_disk;
|
BStringList *manifest,**uids_on_disk;
|
||||||
const char *uid;
|
const char *uid;
|
||||||
@@ -50,7 +52,7 @@ class MessageDeletion : public BMailChainCallback {
|
|||||||
public:
|
public:
|
||||||
MessageDeletion(BMailProtocol *home, const char *uid, BEntry *io_entry, bool delete_anyway);
|
MessageDeletion(BMailProtocol *home, const char *uid, BEntry *io_entry, bool delete_anyway);
|
||||||
virtual void Callback(status_t result);
|
virtual void Callback(status_t result);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BMailProtocol *us;
|
BMailProtocol *us;
|
||||||
bool always;
|
bool always;
|
||||||
@@ -76,6 +78,7 @@ BMailProtocol::error_alert(const char *process, status_t error)
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
|
||||||
class DeleteHandler : public BHandler {
|
class DeleteHandler : public BHandler {
|
||||||
public:
|
public:
|
||||||
DeleteHandler(BMailProtocol *a)
|
DeleteHandler(BMailProtocol *a)
|
||||||
@@ -96,64 +99,152 @@ class DeleteHandler : public BHandler {
|
|||||||
BMailProtocol *us;
|
BMailProtocol *us;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class TrashMonitor : public BHandler {
|
class TrashMonitor : public BHandler {
|
||||||
public:
|
public:
|
||||||
TrashMonitor(BMailProtocol *a, int32 chain_id)
|
TrashMonitor(BMailProtocol *a, int32 chain_id)
|
||||||
: us(a), trash("/boot/home/Desktop/Trash"), messages_for_us(0), id(chain_id)
|
: us(a), messages_for_us(0), id(chain_id)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~TrashMonitor()
|
||||||
|
{
|
||||||
|
stop_watching(this);
|
||||||
|
}
|
||||||
|
|
||||||
void MessageReceived(BMessage *msg)
|
void MessageReceived(BMessage *msg)
|
||||||
{
|
{
|
||||||
if (msg->what == 'INIT') {
|
if (msg->what == 'INIT') {
|
||||||
node_ref to_watch;
|
BVolumeRoster volumes;
|
||||||
trash.GetNodeRef(&to_watch);
|
BVolume volume;
|
||||||
watch_node(&to_watch,B_WATCH_DIRECTORY,this);
|
while (volumes.GetNextVolume(&volume) == B_OK) {
|
||||||
|
BPath trashPath;
|
||||||
|
if (find_directory(B_TRASH_DIRECTORY, &trashPath,
|
||||||
|
false, &volume) == B_OK) {
|
||||||
|
// watch this trash directory
|
||||||
|
BNode node(trashPath.Path());
|
||||||
|
node_ref to_watch;
|
||||||
|
node.GetNodeRef(&to_watch);
|
||||||
|
watch_node(&to_watch, B_WATCH_DIRECTORY, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Also watch for new volume
|
||||||
|
watch_node(NULL, B_WATCH_MOUNT, this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((msg->what == B_NODE_MONITOR) && (us->InitCheck() == B_OK)) {
|
|
||||||
int32 opcode;
|
if (msg->what != B_NODE_MONITOR || (us->InitCheck() != B_OK))
|
||||||
if (msg->FindInt32("opcode",&opcode) < B_OK)
|
return;
|
||||||
|
|
||||||
|
int32 opcode;
|
||||||
|
if (msg->FindInt32("opcode",&opcode) < B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (opcode == B_DEVICE_MOUNTED) {
|
||||||
|
dev_t device;
|
||||||
|
if (msg->FindInt32("new device", &device) != B_OK)
|
||||||
return;
|
return;
|
||||||
|
BVolume volume(device);
|
||||||
if (opcode == B_ENTRY_MOVED) {
|
BPath trashPath;
|
||||||
int64 node(msg->FindInt64("to directory"));
|
if (find_directory(B_TRASH_DIRECTORY, &trashPath,
|
||||||
dev_t device(msg->FindInt32("device"));
|
false, &volume) == B_OK) {
|
||||||
node_ref item_ref;
|
// watch also this new volume's trash directory
|
||||||
item_ref.node = node;
|
BNode node(trashPath.Path());
|
||||||
item_ref.device = device;
|
node_ref to_watch;
|
||||||
|
node.GetNodeRef(&to_watch);
|
||||||
BDirectory moved_to(&item_ref);
|
watch_node(&to_watch, B_WATCH_DIRECTORY, this);
|
||||||
|
|
||||||
BNode trash_item(&moved_to,msg->FindString("name"));
|
|
||||||
int32 chain;
|
|
||||||
if (trash_item.ReadAttr("MAIL:chain",B_INT32_TYPE,0,&chain,sizeof(chain)) < B_OK)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (chain == id)
|
|
||||||
messages_for_us += (moved_to == trash) ? 1 : -1;
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
if (messages_for_us < 0)
|
}
|
||||||
messages_for_us = 0; // Guard against weirdness
|
|
||||||
|
if (opcode == B_ENTRY_MOVED) {
|
||||||
if (trash.CountEntries() == 0) {
|
entry_ref entry;
|
||||||
if (messages_for_us > 0)
|
const char* name;
|
||||||
us->CheckForDeletedMessages();
|
msg->FindInt64("to directory", &entry.directory);
|
||||||
|
msg->FindInt32("device", &entry.device);
|
||||||
|
msg->FindString("name", &name);
|
||||||
|
entry.set_name(name);
|
||||||
|
|
||||||
|
BNode node(&entry);
|
||||||
|
int32 chain;
|
||||||
|
|
||||||
|
// check it's a mail
|
||||||
|
if (node.ReadAttr("MAIL:chain",B_INT32_TYPE,0,&chain,sizeof(chain)) < B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// check it's a mail for us
|
||||||
|
if (chain != id)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// check if it was moved to trash
|
||||||
|
bool moved_to_trash = false;
|
||||||
|
BPath trashPath;
|
||||||
|
BPath entryPath(&entry);
|
||||||
|
BVolumeRoster volumes;
|
||||||
|
BVolume volume;
|
||||||
|
while (volumes.GetNextVolume(&volume) == B_OK) {
|
||||||
|
BPath trashPath;
|
||||||
|
if (find_directory(B_TRASH_DIRECTORY, &trashPath,
|
||||||
|
false, &volume) != B_OK) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strncmp(entryPath.Path(), trashPath.Path(),
|
||||||
|
strlen(trashPath.Path())) == 0) {
|
||||||
|
moved_to_trash = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
messages_for_us += (moved_to_trash) ? 1 : -1;
|
||||||
|
if (messages_for_us < 0) {
|
||||||
|
// Guard against weirdness
|
||||||
messages_for_us = 0;
|
messages_for_us = 0;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opcode != B_ENTRY_REMOVED)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Check if this (trash) entry removal made one trash now empty
|
||||||
|
|
||||||
|
bool someTrashIsEmpty = false;
|
||||||
|
BVolumeRoster volumes;
|
||||||
|
BVolume volume;
|
||||||
|
while (volumes.GetNextVolume(&volume) == B_OK) {
|
||||||
|
BPath trashPath;
|
||||||
|
if (find_directory(B_TRASH_DIRECTORY, &trashPath,
|
||||||
|
false, &volume) != B_OK) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
BDirectory trash(trashPath.Path());
|
||||||
|
if (trash.CountEntries() == 0) {
|
||||||
|
someTrashIsEmpty = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (someTrashIsEmpty) {
|
||||||
|
// One trash is empty, check for deleted messages
|
||||||
|
if (messages_for_us > 0)
|
||||||
|
us->CheckForDeletedMessages();
|
||||||
|
|
||||||
|
messages_for_us = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BMailProtocol *us;
|
BMailProtocol *us;
|
||||||
BDirectory trash;
|
|
||||||
int32 messages_for_us;
|
int32 messages_for_us;
|
||||||
int32 id;
|
int32 id;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // unnamed namspace
|
} // unnamed namespace
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark BMailProtocol
|
||||||
|
|
||||||
|
|
||||||
BMailProtocol::BMailProtocol(BMessage *settings, BMailChainRunner *run)
|
BMailProtocol::BMailProtocol(BMessage *settings, BMailChainRunner *run)
|
||||||
: BMailFilter(settings),
|
: BMailFilter(settings),
|
||||||
@@ -163,17 +254,17 @@ BMailProtocol::BMailProtocol(BMessage *settings, BMailChainRunner *run)
|
|||||||
BMailProtocol::settings = settings;
|
BMailProtocol::settings = settings;
|
||||||
|
|
||||||
manifest = new BStringList;
|
manifest = new BStringList;
|
||||||
|
|
||||||
{
|
{
|
||||||
BString attr_name = "MAIL:";
|
BString attr_name = "MAIL:";
|
||||||
attr_name << runner->Chain()->ID() << ":manifest"; //--- In case someone puts multiple accounts in the same directory
|
attr_name << runner->Chain()->ID() << ":manifest"; //--- In case someone puts multiple accounts in the same directory
|
||||||
|
|
||||||
if (runner->Chain()->MetaData()->HasString("path")) {
|
if (runner->Chain()->MetaData()->HasString("path")) {
|
||||||
BNode node(runner->Chain()->MetaData()->FindString("path"));
|
BNode node(runner->Chain()->MetaData()->FindString("path"));
|
||||||
if (node.InitCheck() >= B_OK) {
|
if (node.InitCheck() >= B_OK) {
|
||||||
// We already have a directory so we can try to read metadata
|
// We already have a directory so we can try to read metadata
|
||||||
// from it. Note that it is normal for this directory not to
|
// from it. Note that it is normal for this directory not to
|
||||||
// be founf on the first run as it will be later created by
|
// be found on the first run as it will be later created by
|
||||||
// the INBOX system filter.
|
// the INBOX system filter.
|
||||||
attr_info info;
|
attr_info info;
|
||||||
if (node.GetAttrInfo(attr_name.String(),&info) < B_OK) {
|
if (node.GetAttrInfo(attr_name.String(),&info) < B_OK) {
|
||||||
@@ -190,14 +281,14 @@ BMailProtocol::BMailProtocol(BMessage *settings, BMailChainRunner *run)
|
|||||||
}
|
}
|
||||||
} else runner->ShowError("Error while reading account manifest: no destination directory exists.");
|
} else runner->ShowError("Error while reading account manifest: no destination directory exists.");
|
||||||
}
|
}
|
||||||
|
|
||||||
uids_on_disk = new BStringList;
|
uids_on_disk = new BStringList;
|
||||||
BVolumeRoster volumes;
|
BVolumeRoster volumes;
|
||||||
BVolume volume;
|
BVolume volume;
|
||||||
while (volumes.GetNextVolume(&volume) == B_OK) {
|
while (volumes.GetNextVolume(&volume) == B_OK) {
|
||||||
BQuery fido;
|
BQuery fido;
|
||||||
entry_ref entry;
|
entry_ref entry;
|
||||||
|
|
||||||
fido.SetVolume(&volume);
|
fido.SetVolume(&volume);
|
||||||
fido.PushAttr("MAIL:chain");
|
fido.PushAttr("MAIL:chain");
|
||||||
fido.PushInt32(settings->FindInt32("chain"));
|
fido.PushInt32(settings->FindInt32("chain"));
|
||||||
@@ -213,21 +304,21 @@ BMailProtocol::BMailProtocol(BMessage *settings, BMailChainRunner *run)
|
|||||||
fido.PushOp(B_AND);
|
fido.PushOp(B_AND);
|
||||||
}
|
}
|
||||||
fido.Fetch();
|
fido.Fetch();
|
||||||
|
|
||||||
BString uid;
|
BString uid;
|
||||||
while (fido.GetNextRef(&entry) == B_OK) {
|
while (fido.GetNextRef(&entry) == B_OK) {
|
||||||
BNode(&entry).ReadAttrString("MAIL:unique_id",&uid);
|
BNode(&entry).ReadAttrString("MAIL:unique_id",&uid);
|
||||||
uids_on_disk->AddItem(uid.String());
|
uids_on_disk->AddItem(uid.String());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(*manifest) |= (*uids_on_disk);
|
(*manifest) |= (*uids_on_disk);
|
||||||
|
|
||||||
if (!settings->FindBool("login_and_do_nothing_else_of_any_importance")) {
|
if (!settings->FindBool("login_and_do_nothing_else_of_any_importance")) {
|
||||||
DeleteHandler *h = new DeleteHandler(this);
|
DeleteHandler *h = new DeleteHandler(this);
|
||||||
runner->AddHandler(h);
|
runner->AddHandler(h);
|
||||||
runner->PostMessage('DELE',h);
|
runner->PostMessage('DELE',h);
|
||||||
|
|
||||||
trash_monitor = new TrashMonitor(this,runner->Chain()->ID());
|
trash_monitor = new TrashMonitor(this,runner->Chain()->ID());
|
||||||
runner->AddHandler(trash_monitor);
|
runner->AddHandler(trash_monitor);
|
||||||
runner->PostMessage('INIT',trash_monitor);
|
runner->PostMessage('INIT',trash_monitor);
|
||||||
@@ -269,7 +360,7 @@ BMailProtocol::~BMailProtocol()
|
|||||||
for (int32 i = 0; i < (a)->CountItems(); i++)\
|
for (int32 i = 0; i < (a)->CountItems(); i++)\
|
||||||
puts((a)->ItemAt(i)); \
|
puts((a)->ItemAt(i)); \
|
||||||
puts("Done\n");
|
puts("Done\n");
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BMailProtocol::ProcessMailMessage(BPositionIO **io_message, BEntry *io_entry,
|
BMailProtocol::ProcessMailMessage(BPositionIO **io_message, BEntry *io_entry,
|
||||||
BMessage *io_headers, BPath *io_folder, const char *io_uid)
|
BMessage *io_headers, BPath *io_folder, const char *io_uid)
|
||||||
@@ -278,7 +369,7 @@ BMailProtocol::ProcessMailMessage(BPositionIO **io_message, BEntry *io_entry,
|
|||||||
|
|
||||||
if (io_uid == NULL)
|
if (io_uid == NULL)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
error = GetMessage(io_uid, io_message, io_headers, io_folder);
|
error = GetMessage(io_uid, io_message, io_headers, io_folder);
|
||||||
if (error < B_OK) {
|
if (error < B_OK) {
|
||||||
if (error != B_MAIL_END_FETCH) {
|
if (error != B_MAIL_END_FETCH) {
|
||||||
@@ -306,16 +397,16 @@ void BMailProtocol::CheckForDeletedMessages() {
|
|||||||
|
|
||||||
if (((settings->FindBool("delete_remote_when_local")) || !(settings->FindBool("leave_mail_on_server"))) && (manifest->CountItems() > 0)) {
|
if (((settings->FindBool("delete_remote_when_local")) || !(settings->FindBool("leave_mail_on_server"))) && (manifest->CountItems() > 0)) {
|
||||||
BStringList to_delete;
|
BStringList to_delete;
|
||||||
|
|
||||||
if (uids_on_disk == NULL) {
|
if (uids_on_disk == NULL) {
|
||||||
BStringList query_contents;
|
BStringList query_contents;
|
||||||
BVolumeRoster volumes;
|
BVolumeRoster volumes;
|
||||||
BVolume volume;
|
BVolume volume;
|
||||||
|
|
||||||
while (volumes.GetNextVolume(&volume) == B_OK) {
|
while (volumes.GetNextVolume(&volume) == B_OK) {
|
||||||
BQuery fido;
|
BQuery fido;
|
||||||
entry_ref entry;
|
entry_ref entry;
|
||||||
|
|
||||||
fido.SetVolume(&volume);
|
fido.SetVolume(&volume);
|
||||||
fido.PushAttr("MAIL:chain");
|
fido.PushAttr("MAIL:chain");
|
||||||
fido.PushInt32(settings->FindInt32("chain"));
|
fido.PushInt32(settings->FindInt32("chain"));
|
||||||
@@ -325,24 +416,24 @@ void BMailProtocol::CheckForDeletedMessages() {
|
|||||||
fido.PushOp(B_EQ);
|
fido.PushOp(B_EQ);
|
||||||
fido.PushOp(B_OR);
|
fido.PushOp(B_OR);
|
||||||
fido.Fetch();
|
fido.Fetch();
|
||||||
|
|
||||||
BString uid;
|
BString uid;
|
||||||
while (fido.GetNextRef(&entry) == B_OK) {
|
while (fido.GetNextRef(&entry) == B_OK) {
|
||||||
BNode(&entry).ReadAttrString("MAIL:unique_id",&uid);
|
BNode(&entry).ReadAttrString("MAIL:unique_id",&uid);
|
||||||
query_contents.AddItem(uid.String());
|
query_contents.AddItem(uid.String());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
query_contents.NotHere(*manifest,&to_delete);
|
query_contents.NotHere(*manifest,&to_delete);
|
||||||
} else {
|
} else {
|
||||||
uids_on_disk->NotHere(*manifest,&to_delete);
|
uids_on_disk->NotHere(*manifest,&to_delete);
|
||||||
delete uids_on_disk;
|
delete uids_on_disk;
|
||||||
uids_on_disk = NULL;
|
uids_on_disk = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int32 i = 0; i < to_delete.CountItems(); i++)
|
for (int32 i = 0; i < to_delete.CountItems(); i++)
|
||||||
DeleteMessage(to_delete[i]);
|
DeleteMessage(to_delete[i]);
|
||||||
|
|
||||||
//*(unique_ids) -= to_delete; --- This line causes bad things to
|
//*(unique_ids) -= to_delete; --- This line causes bad things to
|
||||||
// happen (POP3 client uses the wrong indices to retrieve
|
// happen (POP3 client uses the wrong indices to retrieve
|
||||||
// messages). Without it, bad things don't happen.
|
// messages). Without it, bad things don't happen.
|
||||||
|
|||||||
Reference in New Issue
Block a user