1 /* 2 * Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved. 3 * Copyright 2004-2011, Haiku Inc. All rights reserved. 4 * 5 * Distributed under the terms of the MIT License. 6 */ 7 8 9 //! The mail daemon's settings 10 11 12 #include <MailSettings.h> 13 14 #include <stdio.h> 15 #include <string.h> 16 #include <stdlib.h> 17 18 #include <Directory.h> 19 #include <Entry.h> 20 #include <File.h> 21 #include <FindDirectory.h> 22 #include <Message.h> 23 #include <Messenger.h> 24 #include <Path.h> 25 #include <String.h> 26 #include <Window.h> 27 28 #include <MailPrivate.h> 29 30 31 // #pragma mark - BMailSettings 32 33 34 BMailSettings::BMailSettings() 35 { 36 Reload(); 37 } 38 39 40 BMailSettings::~BMailSettings() 41 { 42 } 43 44 45 status_t 46 BMailSettings::InitCheck() const 47 { 48 return B_OK; 49 } 50 51 52 status_t 53 BMailSettings::Save(bigtime_t /*timeout*/) 54 { 55 status_t ret; 56 // 57 // Find chain-saving directory 58 // 59 60 BPath path; 61 ret = find_directory(B_USER_SETTINGS_DIRECTORY, &path); 62 if (ret != B_OK) { 63 fprintf(stderr, "Couldn't find user settings directory: %s\n", 64 strerror(ret)); 65 return ret; 66 } 67 68 path.Append("Mail"); 69 70 status_t result = BPrivate::WriteMessageFile(fData, path, 71 "new_mail_daemon"); 72 if (result < B_OK) 73 return result; 74 75 BMessenger("application/x-vnd.Be-POST").SendMessage('mrrs'); 76 77 return B_OK; 78 } 79 80 81 status_t 82 BMailSettings::Reload() 83 { 84 status_t ret; 85 86 BPath path; 87 ret = find_directory(B_USER_SETTINGS_DIRECTORY, &path); 88 if (ret != B_OK) { 89 fprintf(stderr, "Couldn't find user settings directory: %s\n", 90 strerror(ret)); 91 return ret; 92 } 93 94 path.Append("Mail/new_mail_daemon"); 95 96 // open 97 BFile settings(path.Path(),B_READ_ONLY); 98 ret = settings.InitCheck(); 99 if (ret != B_OK) { 100 fprintf(stderr, "Couldn't open settings file '%s': %s\n", 101 path.Path(), strerror(ret)); 102 return ret; 103 } 104 105 // read settings 106 BMessage tmp; 107 ret = tmp.Unflatten(&settings); 108 if (ret != B_OK) { 109 fprintf(stderr, "Couldn't read settings from '%s': %s\n", 110 path.Path(), strerror(ret)); 111 return ret; 112 } 113 114 // clobber old settings 115 fData = tmp; 116 return B_OK; 117 } 118 119 120 // # pragma mark - Global settings 121 122 123 int32 124 BMailSettings::WindowFollowsCorner() 125 { 126 return fData.FindInt32("WindowFollowsCorner"); 127 } 128 129 130 void 131 BMailSettings::SetWindowFollowsCorner(int32 whichCorner) 132 { 133 if (fData.ReplaceInt32("WindowFollowsCorner", whichCorner) != B_OK) 134 fData.AddInt32("WindowFollowsCorner", whichCorner); 135 } 136 137 138 uint32 139 BMailSettings::ShowStatusWindow() 140 { 141 int32 showStatusWindow; 142 if (fData.FindInt32("ShowStatusWindow", &showStatusWindow) != B_OK) { 143 // show during send and receive 144 return 2; 145 } 146 147 return showStatusWindow; 148 } 149 150 151 void 152 BMailSettings::SetShowStatusWindow(uint32 mode) 153 { 154 if (fData.ReplaceInt32("ShowStatusWindow", mode) != B_OK) 155 fData.AddInt32("ShowStatusWindow", mode); 156 } 157 158 159 bool 160 BMailSettings::DaemonAutoStarts() 161 { 162 return fData.FindBool("DaemonAutoStarts"); 163 } 164 165 166 void 167 BMailSettings::SetDaemonAutoStarts(bool startIt) 168 { 169 if (fData.ReplaceBool("DaemonAutoStarts", startIt) != B_OK) 170 fData.AddBool("DaemonAutoStarts", startIt); 171 } 172 173 174 BRect 175 BMailSettings::ConfigWindowFrame() 176 { 177 return fData.FindRect("ConfigWindowFrame"); 178 } 179 180 181 void 182 BMailSettings::SetConfigWindowFrame(BRect frame) 183 { 184 if (fData.ReplaceRect("ConfigWindowFrame", frame) != B_OK) 185 fData.AddRect("ConfigWindowFrame", frame); 186 } 187 188 189 BRect 190 BMailSettings::StatusWindowFrame() 191 { 192 BRect frame; 193 if (fData.FindRect("StatusWindowFrame", &frame) != B_OK) 194 return BRect(100, 100, 200, 120); 195 196 return frame; 197 } 198 199 200 void 201 BMailSettings::SetStatusWindowFrame(BRect frame) 202 { 203 if (fData.ReplaceRect("StatusWindowFrame", frame) != B_OK) 204 fData.AddRect("StatusWindowFrame", frame); 205 } 206 207 208 int32 209 BMailSettings::StatusWindowWorkspaces() 210 { 211 uint32 workspaces; 212 if (fData.FindInt32("StatusWindowWorkSpace", (int32*)&workspaces) != B_OK) 213 return B_ALL_WORKSPACES; 214 215 return workspaces; 216 } 217 218 219 void 220 BMailSettings::SetStatusWindowWorkspaces(int32 workspace) 221 { 222 if (fData.ReplaceInt32("StatusWindowWorkSpace", workspace) != B_OK) 223 fData.AddInt32("StatusWindowWorkSpace", workspace); 224 225 BMessage msg('wsch'); 226 msg.AddInt32("StatusWindowWorkSpace",workspace); 227 BMessenger("application/x-vnd.Be-POST").SendMessage(&msg); 228 } 229 230 231 int32 232 BMailSettings::StatusWindowLook() 233 { 234 return fData.FindInt32("StatusWindowLook"); 235 } 236 237 238 void 239 BMailSettings::SetStatusWindowLook(int32 look) 240 { 241 if (fData.ReplaceInt32("StatusWindowLook", look) != B_OK) 242 fData.AddInt32("StatusWindowLook", look); 243 244 BMessage msg('lkch'); 245 msg.AddInt32("StatusWindowLook", look); 246 BMessenger("application/x-vnd.Be-POST").SendMessage(&msg); 247 } 248 249 250 bigtime_t 251 BMailSettings::AutoCheckInterval() 252 { 253 bigtime_t value; 254 if (fData.FindInt64("AutoCheckInterval", &value) != B_OK) { 255 // every 5 min 256 return 5 * 60 * 1000 * 1000; 257 } 258 return value; 259 } 260 261 262 void 263 BMailSettings::SetAutoCheckInterval(bigtime_t interval) 264 { 265 if (fData.ReplaceInt64("AutoCheckInterval", interval) != B_OK) 266 fData.AddInt64("AutoCheckInterval", interval); 267 } 268 269 270 bool 271 BMailSettings::CheckOnlyIfPPPUp() 272 { 273 return fData.FindBool("CheckOnlyIfPPPUp"); 274 } 275 276 277 void 278 BMailSettings::SetCheckOnlyIfPPPUp(bool yes) 279 { 280 if (fData.ReplaceBool("CheckOnlyIfPPPUp", yes)) 281 fData.AddBool("CheckOnlyIfPPPUp", yes); 282 } 283 284 285 bool 286 BMailSettings::SendOnlyIfPPPUp() 287 { 288 return fData.FindBool("SendOnlyIfPPPUp"); 289 } 290 291 292 void 293 BMailSettings::SetSendOnlyIfPPPUp(bool yes) 294 { 295 if (fData.ReplaceBool("SendOnlyIfPPPUp", yes)) 296 fData.AddBool("SendOnlyIfPPPUp", yes); 297 } 298 299 300 int32 301 BMailSettings::DefaultOutboundAccount() 302 { 303 return fData.FindInt32("DefaultOutboundAccount"); 304 } 305 306 307 void 308 BMailSettings::SetDefaultOutboundAccount(int32 to) 309 { 310 if (fData.ReplaceInt32("DefaultOutboundAccount", to) != B_OK) 311 fData.AddInt32("DefaultOutboundAccount", to); 312 } 313 314 315 // #pragma mark - 316 317 318 BMailAccounts::BMailAccounts() 319 { 320 BPath path; 321 status_t status = AccountsPath(path); 322 if (status != B_OK) 323 return; 324 325 BDirectory dir(path.Path()); 326 if (dir.InitCheck() != B_OK) 327 return; 328 329 std::vector<time_t> creationTimeList; 330 BEntry entry; 331 while (dir.GetNextEntry(&entry) != B_ENTRY_NOT_FOUND) { 332 BNode node(&entry); 333 time_t creationTime; 334 if (node.GetCreationTime(&creationTime) != B_OK) 335 continue; 336 337 BMailAccountSettings* account = new BMailAccountSettings(entry); 338 if (account->InitCheck() != B_OK) { 339 delete account; 340 continue; 341 } 342 343 // sort by creation time 344 int insertIndex = -1; 345 for (unsigned int i = 0; i < creationTimeList.size(); i++) { 346 if (creationTimeList[i] > creationTime) { 347 insertIndex = i; 348 break; 349 } 350 } 351 if (insertIndex < 0) { 352 fAccounts.AddItem(account); 353 creationTimeList.push_back(creationTime); 354 } else { 355 fAccounts.AddItem(account, insertIndex); 356 creationTimeList.insert(creationTimeList.begin() + insertIndex, 357 creationTime); 358 } 359 } 360 } 361 362 363 status_t 364 BMailAccounts::AccountsPath(BPath& path) 365 { 366 status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path); 367 if (status != B_OK) 368 return status; 369 return path.Append("Mail/accounts"); 370 } 371 372 373 BMailAccounts::~BMailAccounts() 374 { 375 for (int i = 0; i < fAccounts.CountItems(); i++) 376 delete fAccounts.ItemAt(i); 377 } 378 379 380 int32 381 BMailAccounts::CountAccounts() 382 { 383 return fAccounts.CountItems(); 384 } 385 386 387 BMailAccountSettings* 388 BMailAccounts::AccountAt(int32 index) 389 { 390 return fAccounts.ItemAt(index); 391 } 392 393 394 BMailAccountSettings* 395 BMailAccounts::AccountByID(int32 id) 396 { 397 for (int i = 0; i < fAccounts.CountItems(); i++) { 398 BMailAccountSettings* account = fAccounts.ItemAt(i); 399 if (account->AccountID() == id) 400 return account; 401 } 402 return NULL; 403 } 404 405 406 BMailAccountSettings* 407 BMailAccounts::AccountByName(const char* name) 408 { 409 for (int i = 0; i < fAccounts.CountItems(); i++) { 410 BMailAccountSettings* account = fAccounts.ItemAt(i); 411 if (strcmp(account->Name(), name) == 0) 412 return account; 413 } 414 return NULL; 415 } 416 417 418 // #pragma mark - 419 420 421 AddonSettings::AddonSettings() 422 : 423 fModified(false) 424 { 425 } 426 427 428 bool 429 AddonSettings::Load(const BMessage& message) 430 { 431 const char* addonPath = NULL; 432 if (message.FindString("add-on path", &addonPath) != B_OK 433 || get_ref_for_path(addonPath, &fAddonRef) != B_OK 434 || message.FindMessage("settings", &fSettings) != B_OK) 435 return false; 436 437 fModified = false; 438 return true; 439 } 440 441 442 bool 443 AddonSettings::Save(BMessage& message) 444 { 445 BPath path(&fAddonRef); 446 message.AddString("add-on path", path.Path()); 447 message.AddMessage("settings", &fSettings); 448 fModified = false; 449 return true; 450 } 451 452 453 void 454 AddonSettings::SetAddonRef(const entry_ref& ref) 455 { 456 fAddonRef = ref; 457 } 458 459 460 const entry_ref& 461 AddonSettings::AddonRef() const 462 { 463 return fAddonRef; 464 } 465 466 467 const BMessage& 468 AddonSettings::Settings() const 469 { 470 return fSettings; 471 } 472 473 474 BMessage& 475 AddonSettings::EditSettings() 476 { 477 fModified = true; 478 return fSettings; 479 } 480 481 482 bool 483 AddonSettings::HasBeenModified() 484 { 485 return fModified; 486 } 487 488 489 // #pragma mark - 490 491 492 bool 493 MailAddonSettings::Load(const BMessage& message) 494 { 495 if (!AddonSettings::Load(message)) 496 return false; 497 498 type_code typeFound; 499 int32 countFound; 500 message.GetInfo("filters", &typeFound, &countFound); 501 if (typeFound != B_MESSAGE_TYPE) 502 return false; 503 504 for (int i = 0; i < countFound; i++) { 505 int32 index = AddFilterSettings(); 506 AddonSettings& filterSettings = fFiltersSettings[index]; 507 BMessage filterMessage; 508 message.FindMessage("filters", i, &filterMessage); 509 if (!filterSettings.Load(filterMessage)) 510 RemoveFilterSettings(index); 511 } 512 return true; 513 } 514 515 516 bool 517 MailAddonSettings::Save(BMessage& message) 518 { 519 if (!AddonSettings::Save(message)) 520 return false; 521 522 for (int i = 0; i < CountFilterSettings(); i++) { 523 BMessage filter; 524 AddonSettings& filterSettings = fFiltersSettings[i]; 525 filterSettings.Save(filter); 526 message.AddMessage("filters", &filter); 527 } 528 return true; 529 } 530 531 532 int32 533 MailAddonSettings::CountFilterSettings() 534 { 535 return fFiltersSettings.size(); 536 } 537 538 539 int32 540 MailAddonSettings::AddFilterSettings(const entry_ref* ref) 541 { 542 AddonSettings filterSettings; 543 if (ref != NULL) 544 filterSettings.SetAddonRef(*ref); 545 fFiltersSettings.push_back(filterSettings); 546 return fFiltersSettings.size() - 1; 547 } 548 549 550 bool 551 MailAddonSettings::RemoveFilterSettings(int32 index) 552 { 553 fFiltersSettings.erase(fFiltersSettings.begin() + index); 554 return true; 555 } 556 557 558 bool 559 MailAddonSettings::MoveFilterSettings(int32 from, int32 to) 560 { 561 if (from < 0 || from >= (int32)fFiltersSettings.size() || to < 0 562 || to >= (int32)fFiltersSettings.size()) 563 return false; 564 AddonSettings fromSettings = fFiltersSettings[from]; 565 fFiltersSettings.erase(fFiltersSettings.begin() + from); 566 if (to == (int32)fFiltersSettings.size()) 567 fFiltersSettings.push_back(fromSettings); 568 else { 569 std::vector<AddonSettings>::iterator it = fFiltersSettings.begin() + to; 570 fFiltersSettings.insert(it, fromSettings); 571 } 572 return true; 573 } 574 575 576 AddonSettings* 577 MailAddonSettings::FilterSettingsAt(int32 index) 578 { 579 if (index < 0 || index >= (int32)fFiltersSettings.size()) 580 return NULL; 581 return &fFiltersSettings[index]; 582 } 583 584 585 bool 586 MailAddonSettings::HasBeenModified() 587 { 588 if (AddonSettings::HasBeenModified()) 589 return true; 590 for (unsigned int i = 0; i < fFiltersSettings.size(); i++) { 591 if (fFiltersSettings[i].HasBeenModified()) 592 return true; 593 } 594 return false; 595 } 596 597 598 // #pragma mark - 599 600 601 BMailAccountSettings::BMailAccountSettings() 602 : 603 fStatus(B_OK), 604 fInboundEnabled(true), 605 fOutboundEnabled(true), 606 fModified(true) 607 { 608 fAccountID = real_time_clock(); 609 } 610 611 612 BMailAccountSettings::BMailAccountSettings(BEntry account) 613 : 614 fAccountFile(account), 615 fModified(false) 616 { 617 fStatus = Reload(); 618 } 619 620 621 BMailAccountSettings::~BMailAccountSettings() 622 { 623 624 } 625 626 627 void 628 BMailAccountSettings::SetAccountID(int32 id) 629 { 630 fModified = true; 631 fAccountID = id; 632 } 633 634 635 int32 636 BMailAccountSettings::AccountID() 637 { 638 return fAccountID; 639 } 640 641 642 void 643 BMailAccountSettings::SetName(const char* name) 644 { 645 fModified = true; 646 fAccountName = name; 647 } 648 649 650 const char* 651 BMailAccountSettings::Name() const 652 { 653 return fAccountName; 654 } 655 656 657 void 658 BMailAccountSettings::SetRealName(const char* realName) 659 { 660 fModified = true; 661 fRealName = realName; 662 } 663 664 665 const char* 666 BMailAccountSettings::RealName() const 667 { 668 return fRealName; 669 } 670 671 672 void 673 BMailAccountSettings::SetReturnAddress(const char* returnAddress) 674 { 675 fModified = true; 676 fReturnAdress = returnAddress; 677 } 678 679 680 const char* 681 BMailAccountSettings::ReturnAddress() const 682 { 683 return fReturnAdress; 684 } 685 686 687 bool 688 BMailAccountSettings::SetInboundAddon(const char* name) 689 { 690 BPath path; 691 status_t status = find_directory(B_BEOS_ADDONS_DIRECTORY, &path); 692 if (status != B_OK) 693 return false; 694 path.Append("mail_daemon"); 695 path.Append("inbound_protocols"); 696 path.Append(name); 697 entry_ref ref; 698 get_ref_for_path(path.Path(), &ref); 699 fInboundSettings.SetAddonRef(ref); 700 701 fModified = true; 702 return true; 703 } 704 705 706 bool 707 BMailAccountSettings::SetOutboundAddon(const char* name) 708 { 709 BPath path; 710 status_t status = find_directory(B_BEOS_ADDONS_DIRECTORY, &path); 711 if (status != B_OK) 712 return false; 713 path.Append("mail_daemon"); 714 path.Append("outbound_protocols"); 715 path.Append(name); 716 entry_ref ref; 717 get_ref_for_path(path.Path(), &ref); 718 fOutboundSettings.SetAddonRef(ref); 719 720 fModified = true; 721 return true; 722 } 723 724 725 const entry_ref& 726 BMailAccountSettings::InboundPath() const 727 { 728 return fInboundSettings.AddonRef(); 729 } 730 731 732 const entry_ref& 733 BMailAccountSettings::OutboundPath() const 734 { 735 return fOutboundSettings.AddonRef(); 736 } 737 738 739 MailAddonSettings& 740 BMailAccountSettings::InboundSettings() 741 { 742 return fInboundSettings; 743 } 744 745 746 MailAddonSettings& 747 BMailAccountSettings::OutboundSettings() 748 { 749 return fOutboundSettings; 750 } 751 752 753 bool 754 BMailAccountSettings::HasInbound() 755 { 756 return BEntry(&fInboundSettings.AddonRef()).Exists(); 757 } 758 759 760 bool 761 BMailAccountSettings::HasOutbound() 762 { 763 return BEntry(&fOutboundSettings.AddonRef()).Exists(); 764 } 765 766 767 void 768 BMailAccountSettings::SetInboundEnabled(bool enabled) 769 { 770 fInboundEnabled = enabled; 771 fModified = true; 772 } 773 774 775 bool 776 BMailAccountSettings::IsInboundEnabled() const 777 { 778 return fInboundEnabled; 779 } 780 781 782 void 783 BMailAccountSettings::SetOutboundEnabled(bool enabled) 784 { 785 fOutboundEnabled = enabled; 786 fModified = true; 787 } 788 789 790 bool 791 BMailAccountSettings::IsOutboundEnabled() const 792 { 793 return fOutboundEnabled; 794 } 795 796 797 status_t 798 BMailAccountSettings::Reload() 799 { 800 BFile file(&fAccountFile, B_READ_ONLY); 801 status_t status = file.InitCheck(); 802 if (status != B_OK) 803 return status; 804 BMessage settings; 805 settings.Unflatten(&file); 806 807 int32 id; 808 if (settings.FindInt32("id", &id) == B_OK) 809 fAccountID = id; 810 settings.FindString("name", &fAccountName); 811 settings.FindString("real_name", &fRealName); 812 settings.FindString("return_address", &fReturnAdress); 813 814 BMessage inboundSettings; 815 settings.FindMessage("inbound", &inboundSettings); 816 fInboundSettings.Load(inboundSettings); 817 BMessage outboundSettings; 818 settings.FindMessage("outbound", &outboundSettings); 819 fOutboundSettings.Load(outboundSettings); 820 821 if (settings.FindBool("inbound_enabled", &fInboundEnabled) != B_OK) 822 fInboundEnabled = true; 823 if (settings.FindBool("outbound_enabled", &fOutboundEnabled) != B_OK) 824 fOutboundEnabled = true; 825 826 fModified = false; 827 return B_OK; 828 } 829 830 831 status_t 832 BMailAccountSettings::Save() 833 { 834 fModified = false; 835 836 BMessage settings; 837 settings.AddInt32("id", fAccountID); 838 settings.AddString("name", fAccountName); 839 settings.AddString("real_name", fRealName); 840 settings.AddString("return_address", fReturnAdress); 841 842 BMessage inboundSettings; 843 fInboundSettings.Save(inboundSettings); 844 settings.AddMessage("inbound", &inboundSettings); 845 BMessage outboundSettings; 846 fOutboundSettings.Save(outboundSettings); 847 settings.AddMessage("outbound", &outboundSettings); 848 849 settings.AddBool("inbound_enabled", fInboundEnabled); 850 settings.AddBool("outbound_enabled", fOutboundEnabled); 851 852 status_t status = _CreateAccountFilePath(); 853 if (status != B_OK) 854 return status; 855 856 BFile file(&fAccountFile, B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); 857 status = file.InitCheck(); 858 if (status != B_OK) 859 return status; 860 return settings.Flatten(&file); 861 } 862 863 864 status_t 865 BMailAccountSettings::Delete() 866 { 867 return fAccountFile.Remove(); 868 } 869 870 871 bool 872 BMailAccountSettings::HasBeenModified() 873 { 874 if (fInboundSettings.HasBeenModified()) 875 return true; 876 if (fOutboundSettings.HasBeenModified()) 877 return true; 878 return fModified; 879 } 880 881 882 const BEntry& 883 BMailAccountSettings::AccountFile() 884 { 885 return fAccountFile; 886 } 887 888 889 status_t 890 BMailAccountSettings::_CreateAccountFilePath() 891 { 892 BPath path; 893 status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path); 894 if (status != B_OK) 895 return status; 896 path.Append("Mail/accounts"); 897 create_directory(path.Path(), 777); 898 899 if (fAccountFile.InitCheck() == B_OK) 900 return B_OK; 901 902 BString fileName = fAccountName; 903 if (fileName == "") 904 fileName << fAccountID; 905 for (int i = 0; ; i++) { 906 BString testFileName = fileName; 907 if (i != 0) { 908 testFileName += "_"; 909 testFileName << i; 910 } 911 BPath testPath(path); 912 testPath.Append(testFileName); 913 BEntry testEntry(testPath.Path()); 914 if (!testEntry.Exists()) { 915 fileName = testFileName; 916 break; 917 } 918 } 919 920 path.Append(fileName); 921 return fAccountFile.SetTo(path.Path()); 922 } 923