1 /* 2 * Copyright 2007-2011, Haiku, Inc. All rights reserved. 3 * Copyright 2011, Clemens Zeidler <haiku@clemens-zeidler.de> 4 * Distributed under the terms of the MIT License. 5 */ 6 #include "AutoConfigView.h" 7 8 #include <Catalog.h> 9 #include <Directory.h> 10 #include <Entry.h> 11 #include <FindDirectory.h> 12 #include <Message.h> 13 #include <MenuItem.h> 14 #include <Path.h> 15 #include <PopUpMenu.h> 16 #include <String.h> 17 #include <Window.h> 18 19 #include <MailSettings.h> 20 21 22 #undef B_TRANSLATE_CONTEXT 23 #define B_TRANSLATE_CONTEXT "E-Mail" 24 25 26 AutoConfigView::AutoConfigView(BRect rect, AutoConfig &config) 27 : 28 BBox(rect), 29 fAutoConfig(config) 30 { 31 int32 stepSize = 30; 32 int32 divider = 100; 33 BPoint topLeft(20, 20); 34 BPoint rightDown(rect.Width() - 20, 20 + stepSize); 35 36 // protocol view 37 topLeft.y += stepSize; 38 rightDown.y += stepSize; 39 fInProtocolsField = SetupProtocolView(BRect(topLeft, rightDown)); 40 if (fInProtocolsField) 41 AddChild(fInProtocolsField); 42 43 // search for smtp ref 44 GetSMTPAddonRef(&fSMTPAddonRef); 45 46 // email view 47 topLeft.y += stepSize; 48 rightDown.y += stepSize; 49 fEmailView = new BTextControl(BRect(topLeft, rightDown), "email", 50 "E-mail address:", "", new BMessage(kEMailChangedMsg)); 51 fEmailView->SetDivider(divider); 52 AddChild(fEmailView); 53 54 // login name view 55 topLeft.y += stepSize; 56 rightDown.y += stepSize; 57 fLoginNameView = new BTextControl(BRect(topLeft, rightDown), 58 "login", "Login name:", "", NULL); 59 fLoginNameView->SetDivider(divider); 60 AddChild(fLoginNameView); 61 62 // password view 63 topLeft.y += stepSize; 64 rightDown.y += stepSize; 65 fPasswordView = new BTextControl(BRect(topLeft, rightDown), "password", 66 "Password:", "", NULL); 67 fPasswordView->SetDivider(divider); 68 fPasswordView->TextView()->HideTyping(true); 69 AddChild(fPasswordView); 70 71 // account view 72 topLeft.y += stepSize; 73 rightDown.y += stepSize; 74 fAccountNameView = new BTextControl(BRect(topLeft, rightDown), "account", 75 "Account name:", "", NULL); 76 fAccountNameView->SetDivider(divider); 77 AddChild(fAccountNameView); 78 79 // name view 80 topLeft.y += stepSize; 81 rightDown.y += stepSize; 82 fNameView = new BTextControl(BRect(topLeft, rightDown), "name", 83 "Real name:", "", NULL); 84 AddChild(fNameView); 85 fNameView->SetDivider(divider); 86 } 87 88 89 void 90 AutoConfigView::AttachedToWindow() 91 { 92 fEmailView->SetTarget(this); 93 fEmailView->MakeFocus(true); 94 } 95 96 97 void 98 AutoConfigView::MessageReceived(BMessage *msg) 99 { 100 BString text, login; 101 switch (msg->what) 102 { 103 case kEMailChangedMsg: 104 { 105 text = fLoginNameView->Text(); 106 if (text == "") 107 ProposeUsername(); 108 fLoginNameView->MakeFocus(); 109 fLoginNameView->TextView()->SelectAll(); 110 111 text = fAccountNameView->Text(); 112 if (text == "") 113 fAccountNameView->SetText(fEmailView->Text()); 114 break; 115 } 116 default: 117 BView::MessageReceived(msg); 118 break; 119 } 120 } 121 122 123 bool 124 AutoConfigView::GetBasicAccountInfo(account_info &info) 125 { 126 status_t status = B_OK; 127 128 BString inboundProtocolName = ""; 129 BMenuItem* item = fInProtocolsField->Menu()->FindMarked(); 130 if (item) { 131 inboundProtocolName = item->Label(); 132 item->Message()->FindRef("protocol", &(info.inboundProtocol)); 133 } 134 else 135 status = B_ERROR; 136 137 if (inboundProtocolName.FindFirst("IMAP") >= 0) 138 info.inboundType = IMAP; 139 else 140 info.inboundType = POP; 141 142 info.outboundProtocol = fSMTPAddonRef; 143 info.name = fNameView->Text(); 144 info.accountName = fAccountNameView->Text(); 145 info.email = fEmailView->Text(); 146 info.loginName = fLoginNameView->Text(); 147 info.password = fPasswordView->Text(); 148 149 return status; 150 } 151 152 153 BMenuField* 154 AutoConfigView::SetupProtocolView(BRect rect) 155 { 156 BPopUpMenu *menu = new BPopUpMenu(B_TRANSLATE("Choose Protocol")); 157 158 for (int i = 0; i < 2; i++) { 159 BPath path; 160 status_t status = find_directory((i == 0) ? B_USER_ADDONS_DIRECTORY : 161 B_BEOS_ADDONS_DIRECTORY, &path); 162 if (status != B_OK) 163 return NULL; 164 165 path.Append("mail_daemon"); 166 path.Append("inbound_protocols"); 167 168 BDirectory dir(path.Path()); 169 entry_ref protocolRef; 170 while (dir.GetNextRef(&protocolRef) == B_OK) 171 { 172 char name[B_FILE_NAME_LENGTH]; 173 BEntry entry(&protocolRef); 174 entry.GetName(name); 175 176 BMenuItem *item; 177 BMessage *msg = new BMessage(kProtokollChangedMsg); 178 menu->AddItem(item = new BMenuItem(name, msg)); 179 msg->AddRef("protocol", &protocolRef); 180 181 item->SetMarked(true); 182 } 183 } 184 185 // make imap default protocol if existing 186 BMenuItem* imapItem = menu->FindItem("IMAP"); 187 if (imapItem) 188 imapItem->SetMarked(true); 189 190 BMenuField *protocolsMenuField = new BMenuField(rect, NULL, NULL, menu); 191 protocolsMenuField->ResizeToPreferred(); 192 return protocolsMenuField; 193 } 194 195 196 status_t 197 AutoConfigView::GetSMTPAddonRef(entry_ref *ref) 198 { 199 for (int i = 0; i < 2; i++) { 200 BPath path; 201 status_t status = find_directory((i == 0) ? B_USER_ADDONS_DIRECTORY : 202 B_BEOS_ADDONS_DIRECTORY, &path); 203 if (status != B_OK) 204 { 205 return B_ERROR; 206 } 207 208 path.Append("mail_daemon"); 209 path.Append("outbound_protocols"); 210 211 BDirectory dir(path.Path()); 212 213 while (dir.GetNextRef(ref) == B_OK) 214 { 215 return B_OK; 216 } 217 } 218 219 return B_ERROR; 220 } 221 222 223 BString 224 AutoConfigView::ExtractLocalPart(const char* email) 225 { 226 BString emailS(email); 227 BString localPart; 228 int32 at = emailS.FindLast("@"); 229 emailS.CopyInto(localPart, 0, at); 230 return localPart; 231 } 232 233 234 void 235 AutoConfigView::ProposeUsername() 236 { 237 const char* email = fEmailView->Text(); 238 provider_info info; 239 status_t status = fAutoConfig.GetInfoFromMailAddress(email, &info); 240 if (status == B_OK) { 241 BString localPart = ExtractLocalPart(email); 242 switch (info.username_pattern) { 243 case 0: 244 // username is the mail address 245 fLoginNameView->SetText(email); 246 break; 247 case 1: 248 // username is the local-part 249 fLoginNameView->SetText(localPart.String()); 250 break; 251 case 2: 252 // do nothing 253 break; 254 } 255 } 256 else { 257 fLoginNameView->SetText(email); 258 } 259 } 260 261 262 bool 263 AutoConfigView::IsValidMailAddress(BString email) 264 { 265 int32 atPos = email.FindFirst("@"); 266 if (atPos < 0) 267 return false; 268 BString provider; 269 email.CopyInto(provider, atPos + 1, email.Length() - atPos); 270 if (provider.FindLast(".") < 0) 271 return false; 272 return true; 273 } 274 275 276 ServerSettingsView::ServerSettingsView(BRect rect, const account_info &info) 277 : BView(rect, NULL,B_FOLLOW_ALL,0), 278 fInboundAccount(true), 279 fOutboundAccount(true), 280 fInboundAuthMenu(NULL), 281 fOutboundAuthMenu(NULL), 282 fInboundEncrItemStart(NULL), 283 fOutboundEncrItemStart(NULL), 284 fImageId(-1) 285 { 286 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 287 288 int32 divider = 120; 289 290 fInboundAccount = true; 291 fOutboundAccount = true; 292 293 // inbound 294 BRect boxRect = Bounds(); 295 boxRect.bottom /= 2; 296 boxRect.bottom -= 5; 297 298 BBox *box = new BBox(boxRect); 299 box->SetLabel(B_TRANSLATE("Inbound")); 300 AddChild(box); 301 302 BString serverName; 303 if (info.inboundType == IMAP) 304 serverName = info.providerInfo.imap_server; 305 else 306 serverName = info.providerInfo.pop_server; 307 308 fInboundNameView = new BTextControl(BRect(10, 20, rect.Width() - 20, 35), 309 "inbound", "Server Name:", serverName.String(), 310 new BMessage(kServerChangedMsg)); 311 fInboundNameView->SetDivider(divider); 312 313 box->AddChild(fInboundNameView); 314 315 GetAuthEncrMenu(info.inboundProtocol, &fInboundAuthMenu, 316 &fInboundEncryptionMenu); 317 if (fInboundAuthMenu) { 318 int authID = info.providerInfo.authentification_pop; 319 if (info.inboundType == POP) 320 fInboundAuthMenu->Menu()->ItemAt(authID)->SetMarked(true); 321 fInboundAuthItemStart = fInboundAuthMenu->Menu()->FindMarked(); 322 box->AddChild(fInboundAuthMenu); 323 fInboundAuthMenu->SetDivider(divider); 324 fInboundAuthMenu->MoveTo(10, 50); 325 } 326 if (fInboundEncryptionMenu) { 327 BMenuItem *item = NULL; 328 if (info.inboundType == POP) { 329 item = fInboundEncryptionMenu->Menu() 330 ->ItemAt(info.providerInfo.ssl_pop); 331 if (item) 332 item->SetMarked(true); 333 fInboundEncryptionMenu->MoveTo(10, 80); 334 } 335 if (info.inboundType == IMAP) { 336 item = fInboundEncryptionMenu->Menu()->ItemAt( 337 info.providerInfo.ssl_imap); 338 if (item) 339 item->SetMarked(true); 340 fInboundEncryptionMenu->MoveTo(10, 50); 341 } 342 fInboundEncrItemStart = fInboundEncryptionMenu->Menu()->FindMarked(); 343 box->AddChild(fInboundEncryptionMenu); 344 fInboundEncryptionMenu->SetDivider(divider); 345 } 346 347 if (!fInboundAccount) { 348 fInboundNameView->SetEnabled(false); 349 if (fInboundAuthMenu) 350 fInboundAuthMenu->SetEnabled(false); 351 } 352 353 // outbound 354 boxRect = Bounds(); 355 boxRect.top = boxRect.bottom / 2; 356 boxRect.top += 5; 357 358 box = new BBox(boxRect); 359 box->SetLabel(B_TRANSLATE("Outbound")); 360 AddChild(box); 361 362 serverName = info.providerInfo.smtp_server; 363 fOutboundNameView = new BTextControl(BRect(10, 20, rect.Width() - 20, 30), 364 "outbound", B_TRANSLATE("Server name:"), serverName.String(), 365 new BMessage(kServerChangedMsg)); 366 fOutboundNameView->SetDivider(divider); 367 368 box->AddChild(fOutboundNameView); 369 370 GetAuthEncrMenu(info.outboundProtocol, &fOutboundAuthMenu, 371 &fOutboundEncryptionMenu); 372 if (fOutboundAuthMenu) { 373 BMenuItem *item = fOutboundAuthMenu->Menu()->ItemAt( 374 info.providerInfo.authentification_smtp); 375 if (item) 376 item->SetMarked(true); 377 fOutboundAuthItemStart = item; 378 box->AddChild(fOutboundAuthMenu); 379 fOutboundAuthMenu->SetDivider(divider); 380 fOutboundAuthMenu->MoveTo(10, 50); 381 } 382 if (fOutboundEncryptionMenu) { 383 BMenuItem *item = fOutboundEncryptionMenu->Menu()->ItemAt( 384 info.providerInfo.ssl_smtp); 385 if (item) 386 item->SetMarked(true); 387 fOutboundEncrItemStart = item; 388 box->AddChild(fOutboundEncryptionMenu); 389 fOutboundEncryptionMenu->SetDivider(divider); 390 fOutboundEncryptionMenu->MoveTo(10, 80); 391 } 392 393 if (!fOutboundAccount) { 394 fOutboundNameView->SetEnabled(false); 395 if (fOutboundAuthMenu) 396 fOutboundAuthMenu->SetEnabled(false); 397 } 398 399 } 400 401 402 ServerSettingsView::~ServerSettingsView() 403 { 404 RemoveChild(fInboundAuthMenu); 405 RemoveChild(fInboundEncryptionMenu); 406 delete fInboundAuthMenu; 407 delete fInboundEncryptionMenu; 408 unload_add_on(fImageId); 409 } 410 411 412 void 413 ServerSettingsView::GetServerInfo(account_info &info) 414 { 415 if (info.inboundType == IMAP) { 416 info.providerInfo.imap_server = fInboundNameView->Text(); 417 if (fInboundEncryptionMenu) { 418 BMenuItem* item = fInboundEncryptionMenu->Menu()->FindMarked(); 419 if (item) 420 info.providerInfo.ssl_imap = fInboundEncryptionMenu->Menu() 421 ->IndexOf(item); 422 } 423 } else { 424 info.providerInfo.pop_server = fInboundNameView->Text(); 425 BMenuItem* item = NULL; 426 if (fInboundAuthMenu) { 427 item = fInboundAuthMenu->Menu()->FindMarked(); 428 if (item) 429 info.providerInfo.authentification_pop = fInboundAuthMenu 430 ->Menu() 431 ->IndexOf(item); 432 } 433 if (fInboundEncryptionMenu) { 434 item = fInboundEncryptionMenu->Menu()->FindMarked(); 435 if (item) 436 info.providerInfo.ssl_pop = fInboundEncryptionMenu->Menu() 437 ->IndexOf(item); 438 } 439 } 440 info.providerInfo.smtp_server = fOutboundNameView->Text(); 441 BMenuItem* item = NULL; 442 if (fOutboundAuthMenu) { 443 item = fOutboundAuthMenu->Menu()->FindMarked(); 444 if (item) 445 info.providerInfo.authentification_smtp = fOutboundAuthMenu->Menu() 446 ->IndexOf(item); 447 } 448 449 if (fOutboundEncryptionMenu) { 450 item = fOutboundEncryptionMenu->Menu()->FindMarked(); 451 if (item) 452 info.providerInfo.ssl_smtp = fOutboundEncryptionMenu->Menu() 453 ->IndexOf(item); 454 } 455 DetectMenuChanges(); 456 } 457 458 459 void 460 ServerSettingsView::DetectMenuChanges() 461 { 462 bool changed = false; 463 if (fInboundAuthMenu) { 464 BMenuItem *item = fInboundAuthMenu->Menu()->FindMarked(); 465 if (fInboundAuthItemStart != item) 466 changed = true; 467 } 468 if (fInboundEncryptionMenu) { 469 BMenuItem *item = fInboundEncryptionMenu->Menu()->FindMarked(); 470 if (fInboundEncrItemStart != item) 471 changed = true; 472 } 473 if (fOutboundAuthMenu) { 474 BMenuItem *item = fOutboundAuthMenu->Menu()->FindMarked(); 475 if (fOutboundAuthItemStart != item) 476 changed = true; 477 } 478 if (fOutboundEncryptionMenu) { 479 BMenuItem *item = fOutboundEncryptionMenu->Menu()->FindMarked(); 480 if (fOutboundEncrItemStart != item) 481 changed = true; 482 } 483 if (changed) { 484 BMessage msg(kServerChangedMsg); 485 BMessenger messenger(NULL, Window()->Looper()); 486 messenger.SendMessage(&msg); 487 } 488 } 489 490 491 void 492 ServerSettingsView::GetAuthEncrMenu(entry_ref protocol, 493 BMenuField **authField, BMenuField **sslField) 494 { 495 BMailAccountSettings dummySettings; 496 BView *view = CreateConfigView(protocol, dummySettings.InboundSettings(), 497 dummySettings, &fImageId); 498 499 *authField = (BMenuField *)(view->FindView("auth_method")); 500 *sslField = (BMenuField *)(view->FindView("flavor")); 501 502 view->RemoveChild(*authField); 503 view->RemoveChild(*sslField); 504 delete view; 505 } 506