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