xref: /haiku/src/kits/mail/ProtocolConfigView.cpp (revision 4bd0c1066b227cec4b79883bdef697c7a27f2e90)
1 /*
2  * Copyright 2011-2012, Haiku Inc. All Rights Reserved.
3  * Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
4  * Distributed under the terms of the MIT License.
5  */
6 
7 
8 //! The standard config view for all protocols.
9 
10 
11 #include "ProtocolConfigView.h"
12 
13 #include <stdio.h>
14 #include <stdlib.h>
15 
16 #include <Catalog.h>
17 #include <CheckBox.h>
18 #include <ControlLook.h>
19 #include <GridLayout.h>
20 #include <LayoutBuilder.h>
21 #include <MenuField.h>
22 #include <MenuItem.h>
23 #include <Message.h>
24 #include <PopUpMenu.h>
25 #include <String.h>
26 #include <TextControl.h>
27 
28 #include <crypt.h>
29 
30 
31 #undef B_TRANSLATION_CONTEXT
32 #define B_TRANSLATION_CONTEXT "ProtocolConfigView"
33 
34 
35 static const char* kPartialDownloadLimit = "partial_download_limit";
36 
37 static const uint32 kMsgLeaveOnServer = 'lmos';
38 static const uint32 kMsgNoPassword = 'none';
39 static const uint32 kMsgNeedPassword = 'some';
40 
41 
42 namespace BPrivate {
43 
44 
45 BodyDownloadConfigView::BodyDownloadConfigView()
46 	:
47 	BView("body_config", 0)
48 {
49 	fPartialBox = new BCheckBox("size_if", B_TRANSLATE(
50 		"Partially download messages larger than"), new BMessage('SIZF'));
51 
52 	fSizeControl = new BTextControl("size",
53 		B_TRANSLATE_COMMENT("KB", "kilo byte"), "", NULL);
54 	fSizeControl->SetExplicitMinSize(BSize(be_plain_font->StringWidth("0000"),
55 		B_SIZE_UNSET));
56 
57 	BLayoutBuilder::Group<>(this, B_HORIZONTAL,
58 			be_control_look->DefaultLabelSpacing())
59 		.Add(fPartialBox)
60 		.Add(fSizeControl->CreateTextViewLayoutItem())
61 		.Add(fSizeControl->CreateLabelLayoutItem());
62 }
63 
64 
65 void
66 BodyDownloadConfigView::SetTo(const BMailProtocolSettings& settings)
67 {
68 	int32 limit = settings.GetInt32(kPartialDownloadLimit, -1);
69 	if (limit < 0) {
70 		fPartialBox->SetValue(B_CONTROL_OFF);
71 		fSizeControl->SetText("0");
72 		fSizeControl->SetEnabled(false);
73 	} else {
74 		BString kb;
75 		kb << int32(limit / 1024);
76 		fSizeControl->SetText(kb);
77 		fPartialBox->SetValue(B_CONTROL_ON);
78 		fSizeControl->SetEnabled(true);
79 	}
80 }
81 
82 
83 status_t
84 BodyDownloadConfigView::SaveInto(BMailAddOnSettings& settings) const
85 {
86 	if (fPartialBox->Value() == B_CONTROL_ON) {
87 		settings.SetInt32(kPartialDownloadLimit,
88 			atoi(fSizeControl->Text()) * 1024);
89 	} else
90 		settings.RemoveName(kPartialDownloadLimit);
91 
92 	return B_OK;
93 }
94 
95 
96 void
97 BodyDownloadConfigView::MessageReceived(BMessage *msg)
98 {
99 	if (msg->what != 'SIZF')
100 		return BView::MessageReceived(msg);
101 	fSizeControl->SetEnabled(fPartialBox->Value());
102 }
103 
104 
105 void
106 BodyDownloadConfigView::AttachedToWindow()
107 {
108 	fPartialBox->SetTarget(this);
109 	fPartialBox->ResizeToPreferred();
110 }
111 
112 
113 // #pragma mark -
114 
115 
116 MailProtocolConfigView::MailProtocolConfigView(uint32 optionsMask)
117 	:
118 	BMailSettingsView("protocol_config_view"),
119 	fHostControl(NULL),
120 	fUserControl(NULL),
121 	fPasswordControl(NULL),
122 	fFlavorField(NULL),
123 	fAuthenticationField(NULL),
124 	fLeaveOnServerCheckBox(NULL),
125 	fRemoveFromServerCheckBox(NULL),
126 	fBodyDownloadConfig(NULL)
127 {
128 	SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
129 
130 	BGridLayout* layout = new BGridLayout(0.f);
131 	SetLayout(layout);
132 
133 	if ((optionsMask & B_MAIL_PROTOCOL_HAS_HOSTNAME) != 0) {
134 		fHostControl = _AddTextControl(layout, "host",
135 			B_TRANSLATE("Mail server:"));
136 	}
137 	if ((optionsMask & B_MAIL_PROTOCOL_HAS_USERNAME) != 0) {
138 		fUserControl = _AddTextControl(layout, "user",
139 			B_TRANSLATE("Username:"));
140 	}
141 
142 	if ((optionsMask & B_MAIL_PROTOCOL_HAS_PASSWORD) != 0) {
143 		fPasswordControl = _AddTextControl(layout, "pass",
144 			B_TRANSLATE("Password:"));
145 		fPasswordControl->TextView()->HideTyping(true);
146 	}
147 
148 	if ((optionsMask & B_MAIL_PROTOCOL_HAS_FLAVORS) != 0) {
149 		fFlavorField = _AddMenuField(layout, "flavor",
150 			B_TRANSLATE("Connection type:"));
151 	}
152 
153 	if ((optionsMask & B_MAIL_PROTOCOL_HAS_AUTH_METHODS) != 0) {
154 		fAuthenticationField = _AddMenuField(layout, "auth_method",
155 			B_TRANSLATE("Login type:"));
156 	}
157 
158 	if ((optionsMask & B_MAIL_PROTOCOL_CAN_LEAVE_MAIL_ON_SERVER) != 0) {
159 		fLeaveOnServerCheckBox = new BCheckBox("leave_mail_on_server",
160 			B_TRANSLATE("Leave mail on server"),
161 			new BMessage(kMsgLeaveOnServer));
162 		layout->AddView(fLeaveOnServerCheckBox, 0, layout->CountRows(), 2);
163 
164 		fRemoveFromServerCheckBox = new BCheckBox("delete_remote_when_local",
165 			B_TRANSLATE("Remove mail from server when deleted"), NULL);
166 		fRemoveFromServerCheckBox->SetEnabled(false);
167 		layout->AddView(fRemoveFromServerCheckBox, 0, layout->CountRows(), 2);
168 	}
169 
170 	if ((optionsMask & B_MAIL_PROTOCOL_PARTIAL_DOWNLOAD) != 0) {
171 		fBodyDownloadConfig = new BodyDownloadConfigView();
172 		layout->AddView(fBodyDownloadConfig, 0, layout->CountRows(), 2);
173 	}
174 }
175 
176 
177 MailProtocolConfigView::~MailProtocolConfigView()
178 {
179 }
180 
181 
182 void
183 MailProtocolConfigView::SetTo(const BMailProtocolSettings& settings)
184 {
185 	BString host = settings.FindString("server");
186 	if (settings.HasInt32("port"))
187 		host << ':' << settings.FindInt32("port");
188 
189 	if (fHostControl != NULL)
190 		fHostControl->SetText(host.String());
191 	if (fUserControl != NULL)
192 		fUserControl->SetText(settings.FindString("username"));
193 
194 	if (fPasswordControl != NULL) {
195 		char* password = get_passwd(&settings, "cpasswd");
196 		if (password != NULL) {
197 			fPasswordControl->SetText(password);
198 			delete[] password;
199 		} else
200 			fPasswordControl->SetText(settings.FindString("password"));
201 	}
202 
203 	if (settings.HasInt32("flavor") && fFlavorField != NULL) {
204 		if (BMenuItem* item = fFlavorField->Menu()->ItemAt(
205 				settings.FindInt32("flavor")))
206 			item->SetMarked(true);
207 	}
208 
209 	if (settings.HasInt32("auth_method") && fAuthenticationField != NULL) {
210 		if (BMenuItem* item = fAuthenticationField->Menu()->ItemAt(
211 				settings.FindInt32("auth_method"))) {
212 			item->SetMarked(true);
213 			_SetCredentialsEnabled(item->Command() != kMsgNoPassword);
214 		}
215 	}
216 
217 	if (fLeaveOnServerCheckBox != NULL) {
218 		fLeaveOnServerCheckBox->SetValue(settings.FindBool(
219 			"leave_mail_on_server") ? B_CONTROL_ON : B_CONTROL_OFF);
220 	}
221 
222 	if (fRemoveFromServerCheckBox != NULL) {
223 		fRemoveFromServerCheckBox->SetValue(settings.FindBool(
224 			"delete_remote_when_local") ? B_CONTROL_ON : B_CONTROL_OFF);
225 		fRemoveFromServerCheckBox->SetEnabled(
226 			settings.FindBool("leave_mail_on_server"));
227 	}
228 
229 	if (fBodyDownloadConfig != NULL)
230 		fBodyDownloadConfig->SetTo(settings);
231 }
232 
233 
234 void
235 MailProtocolConfigView::AddFlavor(const char* label)
236 {
237 	if (fFlavorField != NULL) {
238 		fFlavorField->Menu()->AddItem(new BMenuItem(label, NULL));
239 
240 		if (fFlavorField->Menu()->FindMarked() == NULL)
241 			fFlavorField->Menu()->ItemAt(0)->SetMarked(true);
242 	}
243 }
244 
245 
246 void
247 MailProtocolConfigView::AddAuthMethod(const char* label, bool needUserPassword)
248 {
249 	if (fAuthenticationField != NULL) {
250 		fAuthenticationField->Menu()->AddItem(new BMenuItem(label,
251 			new BMessage(needUserPassword
252 				? kMsgNeedPassword : kMsgNoPassword)));
253 
254 		if (fAuthenticationField->Menu()->FindMarked() == NULL) {
255 			BMenuItem* item = fAuthenticationField->Menu()->ItemAt(0);
256 			item->SetMarked(true);
257 			MessageReceived(item->Message());
258 		}
259 	}
260 }
261 
262 
263 BGridLayout*
264 MailProtocolConfigView::Layout() const
265 {
266 	return (BGridLayout*)BView::GetLayout();
267 }
268 
269 
270 status_t
271 MailProtocolConfigView::SaveInto(BMailAddOnSettings& settings) const
272 {
273 	if (fHostControl != NULL) {
274 		int32 port = -1;
275 		BString hostName = fHostControl->Text();
276 		if (hostName.FindFirst(':') > -1) {
277 			port = atol(hostName.String() + hostName.FindFirst(':') + 1);
278 			hostName.Truncate(hostName.FindFirst(':'));
279 		}
280 
281 		settings.SetString("server", hostName);
282 
283 		// since there is no need for the port option, remove it here
284 		if (port != -1)
285 			settings.SetInt32("port", port);
286 		else
287 			settings.RemoveName("port");
288 	} else {
289 		settings.RemoveName("server");
290 		settings.RemoveName("port");
291 	}
292 
293 	if (fUserControl != NULL)
294 		settings.SetString("username", fUserControl->Text());
295 	else
296 		settings.RemoveName("username");
297 
298 	// remove old unencrypted passwords
299 	settings.RemoveName("password");
300 
301 	if (fPasswordControl != NULL)
302 		set_passwd(&settings, "cpasswd", fPasswordControl->Text());
303 	else
304 		settings.RemoveName("cpasswd");
305 
306 	_StoreIndexOfMarked(settings, "flavor", fFlavorField);
307 	_StoreIndexOfMarked(settings, "auth_method", fAuthenticationField);
308 
309 	_StoreCheckBox(settings, "leave_mail_on_server", fLeaveOnServerCheckBox);
310 	_StoreCheckBox(settings, "delete_remote_when_local",
311 		fRemoveFromServerCheckBox);
312 
313 	if (fBodyDownloadConfig != NULL)
314 		return fBodyDownloadConfig->SaveInto(settings);
315 
316 	return B_OK;
317 }
318 
319 
320 void
321 MailProtocolConfigView::AttachedToWindow()
322 {
323 	if (fAuthenticationField != NULL)
324 		fAuthenticationField->Menu()->SetTargetForItems(this);
325 
326 	if (fLeaveOnServerCheckBox != NULL)
327 		fLeaveOnServerCheckBox->SetTarget(this);
328 }
329 
330 
331 void
332 MailProtocolConfigView::MessageReceived(BMessage* message)
333 {
334 	switch (message->what) {
335 		case kMsgNeedPassword:
336 			_SetCredentialsEnabled(true);
337 			break;
338 		case kMsgNoPassword:
339 			_SetCredentialsEnabled(false);
340 			break;
341 
342 		case kMsgLeaveOnServer:
343 			fRemoveFromServerCheckBox->SetEnabled(
344 				message->FindInt32("be:value") == B_CONTROL_ON);
345 			break;
346 	}
347 }
348 
349 
350 BTextControl*
351 MailProtocolConfigView::_AddTextControl(BGridLayout* layout, const char* name,
352 	const char* label)
353 {
354 	BTextControl* control = new BTextControl(name, label, "", NULL);
355 	control->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
356 
357 	int32 row = layout->CountRows();
358 	layout->AddItem(control->CreateLabelLayoutItem(), 0, row);
359 	layout->AddItem(control->CreateTextViewLayoutItem(), 1, row);
360 	return control;
361 }
362 
363 
364 BMenuField*
365 MailProtocolConfigView::_AddMenuField(BGridLayout* layout, const char* name,
366 	const char* label)
367 {
368 	BPopUpMenu* menu = new BPopUpMenu("");
369 	BMenuField* field = new BMenuField(name, label, menu);
370 	field->SetAlignment(B_ALIGN_RIGHT);
371 
372 	int32 row = layout->CountRows();
373 	layout->AddItem(field->CreateLabelLayoutItem(), 0, row);
374 	layout->AddItem(field->CreateMenuBarLayoutItem(), 1, row);
375 	return field;
376 }
377 
378 
379 void
380 MailProtocolConfigView::_StoreIndexOfMarked(BMessage& message, const char* name,
381 	BMenuField* field) const
382 {
383 	int32 index = -1;
384 	if (field != NULL && field->Menu() != NULL) {
385 		BMenuItem* item = field->Menu()->FindMarked();
386 		if (item != NULL)
387 			index = field->Menu()->IndexOf(item);
388 	}
389 	message.SetInt32(name, index);
390 }
391 
392 
393 void
394 MailProtocolConfigView::_StoreCheckBox(BMessage& message, const char* name,
395 	BCheckBox* checkBox) const
396 {
397 	bool value = checkBox != NULL && checkBox->Value() == B_CONTROL_ON;
398 	if (value)
399 		message.SetBool(name, value);
400 	else
401 		message.RemoveName(name);
402 }
403 
404 
405 void
406 MailProtocolConfigView::_SetCredentialsEnabled(bool enabled)
407 {
408 	if (fUserControl != NULL && fPasswordControl != NULL) {
409 		fUserControl->SetEnabled(enabled);
410 		fPasswordControl->SetEnabled(enabled);
411 	}
412 }
413 
414 
415 }	// namespace BPrivate
416