1 /* 2 * Copyright 2011-2012, Haiku, Inc. All rights reserved. 3 * Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved. 4 */ 5 6 7 //#include <assert.h> 8 #include <stdio.h> 9 #include <stdlib.h> 10 11 #include <fs_attr.h> 12 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> 27 28 #include <MailFilter.h> 29 #include <MailDaemon.h> 30 #include <MailProtocol.h> 31 #include <MailSettings.h> 32 33 #include <mail_util.h> 34 #include <MailPrivate.h> 35 36 #include "HaikuMailFormatFilter.h" 37 38 39 using namespace BPrivate; 40 41 42 const uint32 kMsgDeleteMessage = '&DeM'; 43 const uint32 kMsgAppendMessage = '&ApM'; 44 45 const uint32 kMsgMoveFile = '&MoF'; 46 const uint32 kMsgDeleteFile = '&DeF'; 47 const uint32 kMsgFileRenamed = '&FiR'; 48 const uint32 kMsgFileDeleted = '&FDe'; 49 const uint32 kMsgInit = '&Ini'; 50 51 const uint32 kMsgSendMessage = '&SeM'; 52 53 54 BMailProtocol::BMailProtocol(const BMailAccountSettings& settings) 55 : 56 fAccountSettings(settings), 57 fMailNotifier(NULL) 58 { 59 AddFilter(new HaikuMailFormatFilter(*this, settings)); 60 } 61 62 63 BMailProtocol::~BMailProtocol() 64 { 65 delete fMailNotifier; 66 67 for (int i = 0; i < fFilterList.CountItems(); i++) 68 delete fFilterList.ItemAt(i); 69 70 std::map<entry_ref, image_id>::iterator it = fFilterImages.begin(); 71 for (; it != fFilterImages.end(); it++) 72 unload_add_on(it->second); 73 } 74 75 76 const BMailAccountSettings& 77 BMailProtocol::AccountSettings() const 78 { 79 return fAccountSettings; 80 } 81 82 83 void 84 BMailProtocol::SetMailNotifier(BMailNotifier* mailNotifier) 85 { 86 delete fMailNotifier; 87 fMailNotifier = mailNotifier; 88 } 89 90 91 BMailNotifier* 92 BMailProtocol::MailNotifier() const 93 { 94 return fMailNotifier; 95 } 96 97 98 bool 99 BMailProtocol::AddFilter(BMailFilter* filter) 100 { 101 BLocker locker(this); 102 return fFilterList.AddItem(filter); 103 } 104 105 106 int32 107 BMailProtocol::CountFilter() const 108 { 109 BLocker locker(this); 110 return fFilterList.CountItems(); 111 } 112 113 114 BMailFilter* 115 BMailProtocol::FilterAt(int32 index) const 116 { 117 BLocker locker(this); 118 return fFilterList.ItemAt(index); 119 } 120 121 122 BMailFilter* 123 BMailProtocol::RemoveFilter(int32 index) 124 { 125 BLocker locker(this); 126 return fFilterList.RemoveItemAt(index); 127 } 128 129 130 bool 131 BMailProtocol::RemoveFilter(BMailFilter* filter) 132 { 133 BLocker locker(this); 134 return fFilterList.RemoveItem(filter); 135 } 136 137 138 void 139 BMailProtocol::MessageReceived(BMessage* message) 140 { 141 switch (message->what) { 142 case kMsgMoveFile: 143 { 144 entry_ref file; 145 message->FindRef("file", &file); 146 entry_ref dir; 147 message->FindRef("directory", &dir); 148 BDirectory directory(&dir); 149 MoveMessage(file, directory); 150 break; 151 } 152 153 case kMsgDeleteFile: 154 { 155 entry_ref file; 156 message->FindRef("file", &file); 157 DeleteMessage(file); 158 break; 159 } 160 161 case kMsgFileRenamed: 162 { 163 entry_ref from; 164 message->FindRef("from", &from); 165 entry_ref to; 166 message->FindRef("to", &to); 167 FileRenamed(from, to); 168 break; 169 } 170 171 case kMsgFileDeleted: 172 { 173 node_ref node; 174 message->FindInt32("device",&node.device); 175 message->FindInt64("node", &node.node); 176 FileDeleted(node); 177 break; 178 } 179 180 default: 181 BLooper::MessageReceived(message); 182 } 183 } 184 185 186 status_t 187 BMailProtocol::MoveMessage(const entry_ref& ref, BDirectory& dir) 188 { 189 BEntry entry(&ref); 190 return entry.MoveTo(&dir); 191 } 192 193 194 status_t 195 BMailProtocol::DeleteMessage(const entry_ref& ref) 196 { 197 BEntry entry(&ref); 198 return entry.Remove(); 199 } 200 201 202 void 203 BMailProtocol::FileRenamed(const entry_ref& from, const entry_ref& to) 204 { 205 } 206 207 208 void 209 BMailProtocol::FileDeleted(const node_ref& node) 210 { 211 } 212 213 214 void 215 BMailProtocol::ShowError(const char* error) 216 { 217 if (MailNotifier() != NULL) 218 MailNotifier()->ShowError(error); 219 } 220 221 222 void 223 BMailProtocol::ShowMessage(const char* message) 224 { 225 if (MailNotifier() != NULL) 226 MailNotifier()->ShowMessage(message); 227 } 228 229 230 void 231 BMailProtocol::SetTotalItems(uint32 items) 232 { 233 if (MailNotifier() != NULL) 234 MailNotifier()->SetTotalItems(items); 235 } 236 237 238 void 239 BMailProtocol::SetTotalItemsSize(uint64 size) 240 { 241 if (MailNotifier() != NULL) 242 MailNotifier()->SetTotalItemsSize(size); 243 } 244 245 246 void 247 BMailProtocol::ReportProgress(uint32 messages, uint64 bytes, 248 const char* message) 249 { 250 if (MailNotifier() != NULL) 251 MailNotifier()->ReportProgress(messages, bytes, message); 252 } 253 254 255 void 256 BMailProtocol::ResetProgress(const char* message) 257 { 258 if (MailNotifier() != NULL) 259 MailNotifier()->ResetProgress(message); 260 } 261 262 263 void 264 BMailProtocol::NotifyNewMessagesToFetch(int32 count) 265 { 266 ResetProgress(); 267 SetTotalItems(count); 268 } 269 270 271 void 272 BMailProtocol::NotifyHeaderFetched(const entry_ref& ref, BFile* data) 273 { 274 for (int i = 0; i < fFilterList.CountItems(); i++) 275 fFilterList.ItemAt(i)->HeaderFetched(ref, data); 276 } 277 278 279 void 280 BMailProtocol::NotifyBodyFetched(const entry_ref& ref, BFile* data) 281 { 282 for (int i = 0; i < fFilterList.CountItems(); i++) 283 fFilterList.ItemAt(i)->BodyFetched(ref, data); 284 } 285 286 287 void 288 BMailProtocol::NotifyMessageReadyToSend(const entry_ref& ref, BFile* data) 289 { 290 for (int i = 0; i < fFilterList.CountItems(); i++) 291 fFilterList.ItemAt(i)->MessageReadyToSend(ref, data); 292 } 293 294 295 void 296 BMailProtocol::NotifyMessageSent(const entry_ref& ref, BFile* data) 297 { 298 for (int i = 0; i < fFilterList.CountItems(); i++) 299 fFilterList.ItemAt(i)->MessageSent(ref, data); 300 } 301 302 303 void 304 BMailProtocol::LoadFilters(const BMailProtocolSettings& settings) 305 { 306 for (int i = 0; i < settings.CountFilterSettings(); i++) { 307 BMailAddOnSettings* filterSettings = settings.FilterSettingsAt(i); 308 BMailFilter* filter = _LoadFilter(*filterSettings); 309 if (filter != NULL) 310 AddFilter(filter); 311 } 312 } 313 314 315 BMailFilter* 316 BMailProtocol::_LoadFilter(const BMailAddOnSettings& settings) 317 { 318 const entry_ref& ref = settings.AddOnRef(); 319 std::map<entry_ref, image_id>::iterator it = fFilterImages.find(ref); 320 image_id image; 321 if (it != fFilterImages.end()) 322 image = it->second; 323 else { 324 BEntry entry(&ref); 325 BPath path(&entry); 326 image = load_add_on(path.Path()); 327 } 328 if (image < 0) 329 return NULL; 330 331 BMailFilter* (*instantiateFilter)(BMailProtocol& protocol, 332 const BMailAddOnSettings& settings); 333 if (get_image_symbol(image, "instantiate_filter", B_SYMBOL_TYPE_TEXT, 334 (void**)&instantiateFilter) != B_OK) { 335 unload_add_on(image); 336 return NULL; 337 } 338 339 fFilterImages[ref] = image; 340 return instantiateFilter(*this, settings); 341 } 342 343 344 // #pragma mark - 345 346 347 BInboundMailProtocol::BInboundMailProtocol(const BMailAccountSettings& settings) 348 : 349 BMailProtocol(settings) 350 { 351 LoadFilters(fAccountSettings.InboundSettings()); 352 } 353 354 355 BInboundMailProtocol::~BInboundMailProtocol() 356 { 357 } 358 359 360 void 361 BInboundMailProtocol::MessageReceived(BMessage* message) 362 { 363 switch (message->what) { 364 case kMsgSyncMessages: 365 { 366 NotiyMailboxSynchronized(SyncMessages()); 367 break; 368 } 369 370 case kMsgFetchBody: 371 { 372 entry_ref ref; 373 message->FindRef("ref", &ref); 374 status_t status = FetchBody(ref); 375 376 BMessenger target; 377 if (message->FindMessenger("target", &target) != B_OK) 378 break; 379 380 BMessage message(B_MAIL_BODY_FETCHED); 381 message.AddInt32("status", status); 382 message.AddRef("ref", &ref); 383 target.SendMessage(&message); 384 break; 385 } 386 387 case kMsgMarkMessageAsRead: 388 { 389 entry_ref ref; 390 message->FindRef("ref", &ref); 391 read_flags read = (read_flags)message->FindInt32("read"); 392 MarkMessageAsRead(ref, read); 393 break; 394 } 395 396 case kMsgDeleteMessage: 397 { 398 entry_ref ref; 399 message->FindRef("ref", &ref); 400 DeleteMessage(ref); 401 break; 402 } 403 404 case kMsgAppendMessage: 405 { 406 entry_ref ref; 407 message->FindRef("ref", &ref); 408 AppendMessage(ref); 409 break; 410 } 411 412 default: 413 BMailProtocol::MessageReceived(message); 414 break; 415 } 416 } 417 418 419 status_t 420 BInboundMailProtocol::MarkMessageAsRead(const entry_ref& ref, read_flags flag) 421 { 422 BNode node(&ref); 423 return write_read_attr(node, flag); 424 } 425 426 427 status_t 428 BInboundMailProtocol::AppendMessage(const entry_ref& ref) 429 { 430 return B_OK; 431 } 432 433 434 void 435 BInboundMailProtocol::NotiyMailboxSynchronized(status_t status) 436 { 437 for (int32 i = 0; i < CountFilter(); i++) 438 FilterAt(i)->MailboxSynchronized(status); 439 } 440 441 442 // #pragma mark - 443 444 445 BOutboundMailProtocol::BOutboundMailProtocol( 446 const BMailAccountSettings& settings) 447 : 448 BMailProtocol(settings) 449 { 450 LoadFilters(fAccountSettings.OutboundSettings()); 451 } 452 453 454 BOutboundMailProtocol::~BOutboundMailProtocol() 455 { 456 } 457 458 459 void 460 BOutboundMailProtocol::MessageReceived(BMessage* message) 461 { 462 switch (message->what) { 463 case kMsgSendMessage: 464 SendMessages(*message, message->FindInt64("bytes")); 465 break; 466 467 default: 468 BMailProtocol::MessageReceived(message); 469 } 470 } 471