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