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