BPicture: Fix archive constructor.
[haiku.git] / src / kits / mail / MailProtocol.cpp
blob446e142fb678b422b001b4a46cc657add5366e86
1 /*
2 * Copyright 2011-2013, Haiku, Inc. All rights reserved.
3 * Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved.
4 */
7 //#include <assert.h>
8 #include <stdio.h>
9 #include <stdlib.h>
11 #include <fs_attr.h>
13 #include <Alert.h>
14 #include <Directory.h>
15 #include <FindDirectory.h>
16 #include <E-mail.h>
17 #include <Locker.h>
18 #include <Node.h>
19 #include <NodeInfo.h>
20 #include <NodeMonitor.h>
21 #include <Path.h>
22 #include <Query.h>
23 #include <Roster.h>
24 #include <String.h>
25 #include <StringList.h>
26 #include <VolumeRoster.h>
28 #include <MailFilter.h>
29 #include <MailDaemon.h>
30 #include <MailProtocol.h>
31 #include <MailSettings.h>
33 #include <mail_util.h>
34 #include <MailPrivate.h>
35 #include <NodeMessage.h>
37 #include "HaikuMailFormatFilter.h"
40 using namespace BPrivate;
43 const uint32 kMsgDeleteMessage = '&DeM';
44 const uint32 kMsgAppendMessage = '&ApM';
46 const uint32 kMsgSendMessage = '&SeM';
49 BMailProtocol::BMailProtocol(const BMailAccountSettings& settings)
51 fAccountSettings(settings),
52 fMailNotifier(NULL)
54 AddFilter(new HaikuMailFormatFilter(*this, settings));
58 BMailProtocol::~BMailProtocol()
60 delete fMailNotifier;
62 for (int i = 0; i < fFilterList.CountItems(); i++)
63 delete fFilterList.ItemAt(i);
65 std::map<entry_ref, image_id>::iterator it = fFilterImages.begin();
66 for (; it != fFilterImages.end(); it++)
67 unload_add_on(it->second);
71 const BMailAccountSettings&
72 BMailProtocol::AccountSettings() const
74 return fAccountSettings;
78 void
79 BMailProtocol::SetMailNotifier(BMailNotifier* mailNotifier)
81 delete fMailNotifier;
82 fMailNotifier = mailNotifier;
86 BMailNotifier*
87 BMailProtocol::MailNotifier() const
89 return fMailNotifier;
93 bool
94 BMailProtocol::AddFilter(BMailFilter* filter)
96 BLocker locker(this);
97 return fFilterList.AddItem(filter);
101 int32
102 BMailProtocol::CountFilter() const
104 BLocker locker(this);
105 return fFilterList.CountItems();
109 BMailFilter*
110 BMailProtocol::FilterAt(int32 index) const
112 BLocker locker(this);
113 return fFilterList.ItemAt(index);
117 BMailFilter*
118 BMailProtocol::RemoveFilter(int32 index)
120 BLocker locker(this);
121 return fFilterList.RemoveItemAt(index);
125 bool
126 BMailProtocol::RemoveFilter(BMailFilter* filter)
128 BLocker locker(this);
129 return fFilterList.RemoveItem(filter);
133 void
134 BMailProtocol::MessageReceived(BMessage* message)
136 BLooper::MessageReceived(message);
140 status_t
141 BMailProtocol::MoveMessage(const entry_ref& ref, BDirectory& dir)
143 BEntry entry(&ref);
144 return entry.MoveTo(&dir);
148 status_t
149 BMailProtocol::DeleteMessage(const entry_ref& ref)
151 BEntry entry(&ref);
152 return entry.Remove();
156 void
157 BMailProtocol::ShowError(const char* error)
159 if (MailNotifier() != NULL)
160 MailNotifier()->ShowError(error);
164 void
165 BMailProtocol::ShowMessage(const char* message)
167 if (MailNotifier() != NULL)
168 MailNotifier()->ShowMessage(message);
172 void
173 BMailProtocol::SetTotalItems(uint32 items)
175 if (MailNotifier() != NULL)
176 MailNotifier()->SetTotalItems(items);
180 void
181 BMailProtocol::SetTotalItemsSize(uint64 size)
183 if (MailNotifier() != NULL)
184 MailNotifier()->SetTotalItemsSize(size);
188 void
189 BMailProtocol::ReportProgress(uint32 messages, uint64 bytes,
190 const char* message)
192 if (MailNotifier() != NULL)
193 MailNotifier()->ReportProgress(messages, bytes, message);
197 void
198 BMailProtocol::ResetProgress(const char* message)
200 if (MailNotifier() != NULL)
201 MailNotifier()->ResetProgress(message);
205 void
206 BMailProtocol::NotifyNewMessagesToFetch(int32 count)
208 ResetProgress();
209 SetTotalItems(count);
213 BMailFilterAction
214 BMailProtocol::ProcessHeaderFetched(entry_ref& ref, BFile& file,
215 BMessage& attributes)
217 BMailFilterAction action = _ProcessHeaderFetched(ref, file, attributes);
218 if (action >= B_OK && action != B_DELETE_MAIL_ACTION)
219 file << attributes;
221 return action;
225 void
226 BMailProtocol::NotifyBodyFetched(const entry_ref& ref, BFile& file,
227 BMessage& attributes)
229 _NotifyBodyFetched(ref, file, attributes);
230 file << attributes;
234 BMailFilterAction
235 BMailProtocol::ProcessMessageFetched(entry_ref& ref, BFile& file,
236 BMessage& attributes)
238 BMailFilterAction action = _ProcessHeaderFetched(ref, file, attributes);
239 if (action >= B_OK && action != B_DELETE_MAIL_ACTION) {
240 _NotifyBodyFetched(ref, file, attributes);
241 file << attributes;
244 return action;
248 void
249 BMailProtocol::NotifyMessageReadyToSend(const entry_ref& ref, BFile& file)
251 for (int i = 0; i < fFilterList.CountItems(); i++)
252 fFilterList.ItemAt(i)->MessageReadyToSend(ref, file);
256 void
257 BMailProtocol::NotifyMessageSent(const entry_ref& ref, BFile& file)
259 for (int i = 0; i < fFilterList.CountItems(); i++)
260 fFilterList.ItemAt(i)->MessageSent(ref, file);
264 void
265 BMailProtocol::LoadFilters(const BMailProtocolSettings& settings)
267 for (int i = 0; i < settings.CountFilterSettings(); i++) {
268 BMailAddOnSettings* filterSettings = settings.FilterSettingsAt(i);
269 BMailFilter* filter = _LoadFilter(*filterSettings);
270 if (filter != NULL)
271 AddFilter(filter);
276 BMailFilter*
277 BMailProtocol::_LoadFilter(const BMailAddOnSettings& settings)
279 const entry_ref& ref = settings.AddOnRef();
280 std::map<entry_ref, image_id>::iterator it = fFilterImages.find(ref);
281 image_id image;
282 if (it != fFilterImages.end())
283 image = it->second;
284 else {
285 BEntry entry(&ref);
286 BPath path(&entry);
287 image = load_add_on(path.Path());
289 if (image < 0)
290 return NULL;
292 BMailFilter* (*instantiateFilter)(BMailProtocol& protocol,
293 const BMailAddOnSettings& settings);
294 if (get_image_symbol(image, "instantiate_filter", B_SYMBOL_TYPE_TEXT,
295 (void**)&instantiateFilter) != B_OK) {
296 unload_add_on(image);
297 return NULL;
300 fFilterImages[ref] = image;
301 return instantiateFilter(*this, settings);
305 BMailFilterAction
306 BMailProtocol::_ProcessHeaderFetched(entry_ref& ref, BFile& file,
307 BMessage& attributes)
309 entry_ref outRef = ref;
311 for (int i = 0; i < fFilterList.CountItems(); i++) {
312 BMailFilterAction action = fFilterList.ItemAt(i)->HeaderFetched(outRef,
313 file, attributes);
314 if (action == B_DELETE_MAIL_ACTION) {
315 // We have to delete the message
316 BEntry entry(&ref);
317 status_t status = entry.Remove();
318 if (status != B_OK) {
319 fprintf(stderr, "BMailProtocol::NotifyHeaderFetched(): could "
320 "not delete mail: %s\n", strerror(status));
322 return B_DELETE_MAIL_ACTION;
326 if (ref == outRef)
327 return B_NO_MAIL_ACTION;
329 // We have to rename the file
330 node_ref newParentRef;
331 newParentRef.device = outRef.device;
332 newParentRef.node = outRef.directory;
334 BDirectory newParent(&newParentRef);
335 status_t status = newParent.InitCheck();
336 BString workerName;
337 if (status == B_OK) {
338 int32 uniqueNumber = 1;
339 do {
340 workerName = outRef.name;
341 if (uniqueNumber > 1)
342 workerName << "_" << uniqueNumber;
344 // TODO: support copying to another device!
345 BEntry entry(&ref);
346 status = entry.Rename(workerName);
348 uniqueNumber++;
349 } while (status == B_FILE_EXISTS);
352 if (status != B_OK) {
353 fprintf(stderr, "BMailProtocol::NotifyHeaderFetched(): could not "
354 "rename mail (%s)! (should be: %s)\n", strerror(status),
355 workerName.String());
358 ref = outRef;
359 ref.set_name(workerName.String());
361 return B_MOVE_MAIL_ACTION;
365 void
366 BMailProtocol::_NotifyBodyFetched(const entry_ref& ref, BFile& file,
367 BMessage& attributes)
369 for (int i = 0; i < fFilterList.CountItems(); i++)
370 fFilterList.ItemAt(i)->BodyFetched(ref, file, attributes);
374 // #pragma mark -
377 BInboundMailProtocol::BInboundMailProtocol(const BMailAccountSettings& settings)
379 BMailProtocol(settings)
381 LoadFilters(fAccountSettings.InboundSettings());
385 BInboundMailProtocol::~BInboundMailProtocol()
390 void
391 BInboundMailProtocol::MessageReceived(BMessage* message)
393 switch (message->what) {
394 case kMsgSyncMessages:
396 NotiyMailboxSynchronized(SyncMessages());
397 break;
400 case kMsgFetchBody:
402 entry_ref ref;
403 message->FindRef("ref", &ref);
404 status_t status = FetchBody(ref);
406 BMessenger target;
407 if (message->FindMessenger("target", &target) != B_OK)
408 break;
410 BMessage message(B_MAIL_BODY_FETCHED);
411 message.AddInt32("status", status);
412 message.AddRef("ref", &ref);
413 target.SendMessage(&message);
414 break;
417 case kMsgMarkMessageAsRead:
419 entry_ref ref;
420 message->FindRef("ref", &ref);
421 read_flags read = (read_flags)message->FindInt32("read");
422 MarkMessageAsRead(ref, read);
423 break;
426 case kMsgDeleteMessage:
428 entry_ref ref;
429 message->FindRef("ref", &ref);
430 DeleteMessage(ref);
431 break;
434 case kMsgAppendMessage:
436 entry_ref ref;
437 message->FindRef("ref", &ref);
438 AppendMessage(ref);
439 break;
442 default:
443 BMailProtocol::MessageReceived(message);
444 break;
449 status_t
450 BInboundMailProtocol::MarkMessageAsRead(const entry_ref& ref, read_flags flag)
452 BNode node(&ref);
453 return write_read_attr(node, flag);
457 status_t
458 BInboundMailProtocol::AppendMessage(const entry_ref& ref)
460 return B_OK;
464 void
465 BInboundMailProtocol::NotiyMailboxSynchronized(status_t status)
467 for (int32 i = 0; i < CountFilter(); i++)
468 FilterAt(i)->MailboxSynchronized(status);
472 // #pragma mark -
475 BOutboundMailProtocol::BOutboundMailProtocol(
476 const BMailAccountSettings& settings)
478 BMailProtocol(settings)
480 LoadFilters(fAccountSettings.OutboundSettings());
484 BOutboundMailProtocol::~BOutboundMailProtocol()
489 void
490 BOutboundMailProtocol::MessageReceived(BMessage* message)
492 switch (message->what) {
493 case kMsgSendMessage:
494 SendMessages(*message, message->FindInt64("bytes"));
495 break;
497 default:
498 BMailProtocol::MessageReceived(message);