MailProtocol.cpp revision 549949b2
10c7f804cSAxel Dörfler/*
2549949b2SAxel Dörfler * Copyright 2011-2013, Haiku, Inc. All rights reserved.
30c7f804cSAxel Dörfler * Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved.
40c7f804cSAxel Dörfler */
5f7215ac8SNathan Whitehorn
6f7215ac8SNathan Whitehorn
7715bf3d1SAxel Dörfler//#include <assert.h>
8dfc6cf01SPhilippe Houdoin#include <stdio.h>
9dfc6cf01SPhilippe Houdoin#include <stdlib.h>
10715bf3d1SAxel Dörfler
11715bf3d1SAxel Dörfler#include <fs_attr.h>
12dfc6cf01SPhilippe Houdoin
13f7215ac8SNathan Whitehorn#include <Alert.h>
14dfc6cf01SPhilippe Houdoin#include <Directory.h>
15dfc6cf01SPhilippe Houdoin#include <FindDirectory.h>
16f7215ac8SNathan Whitehorn#include <E-mail.h>
17715bf3d1SAxel Dörfler#include <Locker.h>
18dfc6cf01SPhilippe Houdoin#include <Node.h>
19f7215ac8SNathan Whitehorn#include <NodeInfo.h>
20f7215ac8SNathan Whitehorn#include <NodeMonitor.h>
21dfc6cf01SPhilippe Houdoin#include <Path.h>
22715bf3d1SAxel Dörfler#include <Query.h>
231af4fa4bSClemens Zeidler#include <Roster.h>
24dfc6cf01SPhilippe Houdoin#include <String.h>
25dfc6cf01SPhilippe Houdoin#include <StringList.h>
26dfc6cf01SPhilippe Houdoin#include <VolumeRoster.h>
27f7215ac8SNathan Whitehorn
28715bf3d1SAxel Dörfler#include <MailFilter.h>
29b8d2bbd6SClemens Zeidler#include <MailDaemon.h>
30f7215ac8SNathan Whitehorn#include <MailProtocol.h>
311af4fa4bSClemens Zeidler#include <MailSettings.h>
32dfc6cf01SPhilippe Houdoin
33715bf3d1SAxel Dörfler#include <mail_util.h>
34146357b5SAxel Dörfler#include <MailPrivate.h>
35715bf3d1SAxel Dörfler
361af4fa4bSClemens Zeidler#include "HaikuMailFormatFilter.h"
37f7215ac8SNathan Whitehorn
38dfc6cf01SPhilippe Houdoin
39146357b5SAxel Dörflerusing namespace BPrivate;
40f7215ac8SNathan Whitehorn
41f7215ac8SNathan Whitehorn
420c7f804cSAxel Dörflerconst uint32 kMsgDeleteMessage = '&DeM';
430c7f804cSAxel Dörflerconst uint32 kMsgAppendMessage = '&ApM';
440c7f804cSAxel Dörfler
450c7f804cSAxel Dörflerconst uint32 kMsgSendMessage = '&SeM';
460c7f804cSAxel Dörfler
470c7f804cSAxel Dörfler
48715bf3d1SAxel DörflerBMailProtocol::BMailProtocol(const BMailAccountSettings& settings)
491af4fa4bSClemens Zeidler	:
50715bf3d1SAxel Dörfler	fAccountSettings(settings),
51715bf3d1SAxel Dörfler	fMailNotifier(NULL)
52f7215ac8SNathan Whitehorn{
53715bf3d1SAxel Dörfler	AddFilter(new HaikuMailFormatFilter(*this, settings));
54f7215ac8SNathan Whitehorn}
55f7215ac8SNathan Whitehorn
56f7215ac8SNathan Whitehorn
57715bf3d1SAxel DörflerBMailProtocol::~BMailProtocol()
581af4fa4bSClemens Zeidler{
59715bf3d1SAxel Dörfler	delete fMailNotifier;
60eb9b1980SIngo Weinhold
61715bf3d1SAxel Dörfler	for (int i = 0; i < fFilterList.CountItems(); i++)
62715bf3d1SAxel Dörfler		delete fFilterList.ItemAt(i);
63dfc6cf01SPhilippe Houdoin
64146357b5SAxel Dörfler	std::map<entry_ref, image_id>::iterator it = fFilterImages.begin();
65715bf3d1SAxel Dörfler	for (; it != fFilterImages.end(); it++)
66715bf3d1SAxel Dörfler		unload_add_on(it->second);
671af4fa4bSClemens Zeidler}
68f7215ac8SNathan Whitehorn
69f7215ac8SNathan Whitehorn
70715bf3d1SAxel Dörflerconst BMailAccountSettings&
71715bf3d1SAxel DörflerBMailProtocol::AccountSettings() const
721af4fa4bSClemens Zeidler{
73715bf3d1SAxel Dörfler	return fAccountSettings;
741af4fa4bSClemens Zeidler}
75dfc6cf01SPhilippe Houdoin
76f7215ac8SNathan Whitehorn
771af4fa4bSClemens Zeidlervoid
78715bf3d1SAxel DörflerBMailProtocol::SetMailNotifier(BMailNotifier* mailNotifier)
791af4fa4bSClemens Zeidler{
80715bf3d1SAxel Dörfler	delete fMailNotifier;
81715bf3d1SAxel Dörfler	fMailNotifier = mailNotifier;
821af4fa4bSClemens Zeidler}
83f7215ac8SNathan Whitehorn
84dfc6cf01SPhilippe Houdoin
85715bf3d1SAxel DörflerBMailNotifier*
86715bf3d1SAxel DörflerBMailProtocol::MailNotifier() const
871af4fa4bSClemens Zeidler{
88715bf3d1SAxel Dörfler	return fMailNotifier;
891af4fa4bSClemens Zeidler}
90dfc6cf01SPhilippe Houdoin
91eb9b1980SIngo Weinhold
92715bf3d1SAxel Dörflerbool
93715bf3d1SAxel DörflerBMailProtocol::AddFilter(BMailFilter* filter)
94f7215ac8SNathan Whitehorn{
95715bf3d1SAxel Dörfler	BLocker locker(this);
96715bf3d1SAxel Dörfler	return fFilterList.AddItem(filter);
971af4fa4bSClemens Zeidler}
981af4fa4bSClemens Zeidler
99dfc6cf01SPhilippe Houdoin
100715bf3d1SAxel Dörflerint32
101715bf3d1SAxel DörflerBMailProtocol::CountFilter() const
1021af4fa4bSClemens Zeidler{
103715bf3d1SAxel Dörfler	BLocker locker(this);
104715bf3d1SAxel Dörfler	return fFilterList.CountItems();
1051af4fa4bSClemens Zeidler}
1061af4fa4bSClemens Zeidler
1071af4fa4bSClemens Zeidler
108715bf3d1SAxel DörflerBMailFilter*
109715bf3d1SAxel DörflerBMailProtocol::FilterAt(int32 index) const
1101af4fa4bSClemens Zeidler{
111715bf3d1SAxel Dörfler	BLocker locker(this);
112715bf3d1SAxel Dörfler	return fFilterList.ItemAt(index);
1131af4fa4bSClemens Zeidler}
1141af4fa4bSClemens Zeidler
1151af4fa4bSClemens Zeidler
116715bf3d1SAxel DörflerBMailFilter*
117715bf3d1SAxel DörflerBMailProtocol::RemoveFilter(int32 index)
1181af4fa4bSClemens Zeidler{
119715bf3d1SAxel Dörfler	BLocker locker(this);
120715bf3d1SAxel Dörfler	return fFilterList.RemoveItemAt(index);
1211af4fa4bSClemens Zeidler}
1221af4fa4bSClemens Zeidler
1231af4fa4bSClemens Zeidler
124715bf3d1SAxel Dörflerbool
125715bf3d1SAxel DörflerBMailProtocol::RemoveFilter(BMailFilter* filter)
1261af4fa4bSClemens Zeidler{
127715bf3d1SAxel Dörfler	BLocker locker(this);
128715bf3d1SAxel Dörfler	return fFilterList.RemoveItem(filter);
1291af4fa4bSClemens Zeidler}
1301af4fa4bSClemens Zeidler
1311af4fa4bSClemens Zeidler
132715bf3d1SAxel Dörflervoid
133715bf3d1SAxel DörflerBMailProtocol::MessageReceived(BMessage* message)
1341af4fa4bSClemens Zeidler{
135549949b2SAxel Dörfler	BLooper::MessageReceived(message);
1361af4fa4bSClemens Zeidler}
1371af4fa4bSClemens Zeidler
1381af4fa4bSClemens Zeidler
139715bf3d1SAxel Dörflerstatus_t
140715bf3d1SAxel DörflerBMailProtocol::MoveMessage(const entry_ref& ref, BDirectory& dir)
1411af4fa4bSClemens Zeidler{
142715bf3d1SAxel Dörfler	BEntry entry(&ref);
143715bf3d1SAxel Dörfler	return entry.MoveTo(&dir);
1441af4fa4bSClemens Zeidler}
1451af4fa4bSClemens Zeidler
1461af4fa4bSClemens Zeidler
147715bf3d1SAxel Dörflerstatus_t
148715bf3d1SAxel DörflerBMailProtocol::DeleteMessage(const entry_ref& ref)
1491af4fa4bSClemens Zeidler{
150715bf3d1SAxel Dörfler	BEntry entry(&ref);
151715bf3d1SAxel Dörfler	return entry.Remove();
1521af4fa4bSClemens Zeidler}
1531af4fa4bSClemens Zeidler
1541af4fa4bSClemens Zeidler
1551af4fa4bSClemens Zeidlervoid
156715bf3d1SAxel DörflerBMailProtocol::ShowError(const char* error)
1571af4fa4bSClemens Zeidler{
158715bf3d1SAxel Dörfler	if (MailNotifier() != NULL)
159715bf3d1SAxel Dörfler		MailNotifier()->ShowError(error);
1601af4fa4bSClemens Zeidler}
1611af4fa4bSClemens Zeidler
1621af4fa4bSClemens Zeidler
1631af4fa4bSClemens Zeidlervoid
164715bf3d1SAxel DörflerBMailProtocol::ShowMessage(const char* message)
1651af4fa4bSClemens Zeidler{
166715bf3d1SAxel Dörfler	if (MailNotifier() != NULL)
167715bf3d1SAxel Dörfler		MailNotifier()->ShowMessage(message);
1681af4fa4bSClemens Zeidler}
1691af4fa4bSClemens Zeidler
1701af4fa4bSClemens Zeidler
1711af4fa4bSClemens Zeidlervoid
172715bf3d1SAxel DörflerBMailProtocol::SetTotalItems(uint32 items)
1731af4fa4bSClemens Zeidler{
174715bf3d1SAxel Dörfler	if (MailNotifier() != NULL)
175715bf3d1SAxel Dörfler		MailNotifier()->SetTotalItems(items);
1761af4fa4bSClemens Zeidler}
1771af4fa4bSClemens Zeidler
1781af4fa4bSClemens Zeidler
179715bf3d1SAxel Dörflervoid
180715bf3d1SAxel DörflerBMailProtocol::SetTotalItemsSize(uint64 size)
1811af4fa4bSClemens Zeidler{
182715bf3d1SAxel Dörfler	if (MailNotifier() != NULL)
183715bf3d1SAxel Dörfler		MailNotifier()->SetTotalItemsSize(size);
1841af4fa4bSClemens Zeidler}
1851af4fa4bSClemens Zeidler
1861af4fa4bSClemens Zeidler
187715bf3d1SAxel Dörflervoid
188715bf3d1SAxel DörflerBMailProtocol::ReportProgress(uint32 messages, uint64 bytes,
189715bf3d1SAxel Dörfler	const char* message)
1901af4fa4bSClemens Zeidler{
191715bf3d1SAxel Dörfler	if (MailNotifier() != NULL)
192715bf3d1SAxel Dörfler		MailNotifier()->ReportProgress(messages, bytes, message);
1931af4fa4bSClemens Zeidler}
1941af4fa4bSClemens Zeidler
1951af4fa4bSClemens Zeidler
196715bf3d1SAxel Dörflervoid
197715bf3d1SAxel DörflerBMailProtocol::ResetProgress(const char* message)
1981af4fa4bSClemens Zeidler{
199715bf3d1SAxel Dörfler	if (MailNotifier() != NULL)
200715bf3d1SAxel Dörfler		MailNotifier()->ResetProgress(message);
2011af4fa4bSClemens Zeidler}
2021af4fa4bSClemens Zeidler
2031af4fa4bSClemens Zeidler
2041af4fa4bSClemens Zeidlervoid
205715bf3d1SAxel DörflerBMailProtocol::NotifyNewMessagesToFetch(int32 count)
2061af4fa4bSClemens Zeidler{
2071af4fa4bSClemens Zeidler	ResetProgress();
208715bf3d1SAxel Dörfler	SetTotalItems(count);
2091af4fa4bSClemens Zeidler}
2101af4fa4bSClemens Zeidler
2111af4fa4bSClemens Zeidler
212549949b2SAxel DörflerBMailFilterAction
213549949b2SAxel DörflerBMailProtocol::ProcessHeaderFetched(entry_ref& ref, BFile& data)
2141af4fa4bSClemens Zeidler{
215549949b2SAxel Dörfler	entry_ref outRef = ref;
216549949b2SAxel Dörfler
217549949b2SAxel Dörfler	for (int i = 0; i < fFilterList.CountItems(); i++) {
218549949b2SAxel Dörfler		BMailFilterAction action = fFilterList.ItemAt(i)->HeaderFetched(outRef,
219549949b2SAxel Dörfler			data);
220549949b2SAxel Dörfler		if (action == B_DELETE_MAIL_ACTION) {
221549949b2SAxel Dörfler			// We have to delete the message
222549949b2SAxel Dörfler			BEntry entry(&ref);
223549949b2SAxel Dörfler			status_t status = entry.Remove();
224549949b2SAxel Dörfler			if (status != B_OK) {
225549949b2SAxel Dörfler				fprintf(stderr, "BMailProtocol::NotifyHeaderFetched(): could "
226549949b2SAxel Dörfler					"not delete mail: %s\n", strerror(status));
227549949b2SAxel Dörfler			}
228549949b2SAxel Dörfler			return B_DELETE_MAIL_ACTION;
229549949b2SAxel Dörfler		}
230549949b2SAxel Dörfler	}
231549949b2SAxel Dörfler
232549949b2SAxel Dörfler	if (ref == outRef)
233549949b2SAxel Dörfler		return B_NO_MAIL_ACTION;
234549949b2SAxel Dörfler
235549949b2SAxel Dörfler	// We have to rename the file
236549949b2SAxel Dörfler	node_ref newParentRef;
237549949b2SAxel Dörfler	newParentRef.device = outRef.device;
238549949b2SAxel Dörfler	newParentRef.node = outRef.directory;
239549949b2SAxel Dörfler
240549949b2SAxel Dörfler	BDirectory newParent(&newParentRef);
241549949b2SAxel Dörfler	status_t status = newParent.InitCheck();
242549949b2SAxel Dörfler	BString workerName;
243549949b2SAxel Dörfler	if (status == B_OK) {
244549949b2SAxel Dörfler		int32 uniqueNumber = 1;
245549949b2SAxel Dörfler		do {
246549949b2SAxel Dörfler			workerName = outRef.name;
247549949b2SAxel Dörfler			if (uniqueNumber > 1)
248549949b2SAxel Dörfler				workerName << "_" << ++uniqueNumber;
249549949b2SAxel Dörfler
250549949b2SAxel Dörfler			// TODO: support copying to another device!
251549949b2SAxel Dörfler			BEntry entry(&ref);
252549949b2SAxel Dörfler			status = entry.Rename(workerName);
253549949b2SAxel Dörfler		} while (status == B_FILE_EXISTS);
254549949b2SAxel Dörfler	}
255549949b2SAxel Dörfler
256549949b2SAxel Dörfler	if (status != B_OK) {
257549949b2SAxel Dörfler		fprintf(stderr, "BMailProtocol::NotifyHeaderFetched(): could not "
258549949b2SAxel Dörfler			"rename mail (%s)! (should be: %s)\n", strerror(status),
259549949b2SAxel Dörfler			workerName.String());
260549949b2SAxel Dörfler	}
261549949b2SAxel Dörfler
262549949b2SAxel Dörfler	ref = outRef;
263549949b2SAxel Dörfler	ref.set_name(workerName.String());
264549949b2SAxel Dörfler
265549949b2SAxel Dörfler	return B_MOVE_MAIL_ACTION;
2661af4fa4bSClemens Zeidler}
2671af4fa4bSClemens Zeidler
2681af4fa4bSClemens Zeidler
2691af4fa4bSClemens Zeidlervoid
270549949b2SAxel DörflerBMailProtocol::NotifyBodyFetched(const entry_ref& ref, BFile& data)
2711af4fa4bSClemens Zeidler{
2721af4fa4bSClemens Zeidler	for (int i = 0; i < fFilterList.CountItems(); i++)
2731af4fa4bSClemens Zeidler		fFilterList.ItemAt(i)->BodyFetched(ref, data);
2741af4fa4bSClemens Zeidler}
2751af4fa4bSClemens Zeidler
2761af4fa4bSClemens Zeidler
2771af4fa4bSClemens Zeidlervoid
278549949b2SAxel DörflerBMailProtocol::NotifyMessageReadyToSend(const entry_ref& ref, BFile& data)
2791af4fa4bSClemens Zeidler{
2801af4fa4bSClemens Zeidler	for (int i = 0; i < fFilterList.CountItems(); i++)
2811af4fa4bSClemens Zeidler		fFilterList.ItemAt(i)->MessageReadyToSend(ref, data);
2821af4fa4bSClemens Zeidler}
2831af4fa4bSClemens Zeidler
2841af4fa4bSClemens Zeidler
2851af4fa4bSClemens Zeidlervoid
286549949b2SAxel DörflerBMailProtocol::NotifyMessageSent(const entry_ref& ref, BFile& data)
2871af4fa4bSClemens Zeidler{
2881af4fa4bSClemens Zeidler	for (int i = 0; i < fFilterList.CountItems(); i++)
2891af4fa4bSClemens Zeidler		fFilterList.ItemAt(i)->MessageSent(ref, data);
2901af4fa4bSClemens Zeidler}
2911af4fa4bSClemens Zeidler
2921af4fa4bSClemens Zeidler
2931af4fa4bSClemens Zeidlervoid
294715bf3d1SAxel DörflerBMailProtocol::LoadFilters(const BMailProtocolSettings& settings)
2951af4fa4bSClemens Zeidler{
2961af4fa4bSClemens Zeidler	for (int i = 0; i < settings.CountFilterSettings(); i++) {
297715bf3d1SAxel Dörfler		BMailAddOnSettings* filterSettings = settings.FilterSettingsAt(i);
298ca3341c7SAxel Dörfler		BMailFilter* filter = _LoadFilter(*filterSettings);
299715bf3d1SAxel Dörfler		if (filter != NULL)
300715bf3d1SAxel Dörfler			AddFilter(filter);
301f7215ac8SNathan Whitehorn	}
302f7215ac8SNathan Whitehorn}
303f7215ac8SNathan Whitehorn
304f7215ac8SNathan Whitehorn
305715bf3d1SAxel DörflerBMailFilter*
306ca3341c7SAxel DörflerBMailProtocol::_LoadFilter(const BMailAddOnSettings& settings)
3071af4fa4bSClemens Zeidler{
308ca3341c7SAxel Dörfler	const entry_ref& ref = settings.AddOnRef();
309146357b5SAxel Dörfler	std::map<entry_ref, image_id>::iterator it = fFilterImages.find(ref);
3101af4fa4bSClemens Zeidler	image_id image;
3111af4fa4bSClemens Zeidler	if (it != fFilterImages.end())
3121af4fa4bSClemens Zeidler		image = it->second;
3131af4fa4bSClemens Zeidler	else {
314