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