xref: /haiku/src/preferences/mail/AutoConfigView.cpp (revision d17092ceb18bf47a96dbaf8a1acf10e6e3070704)
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