xref: /haiku/src/preferences/screensaver/PasswordWindow.cpp (revision f8da8f3477d3c18142e59d17d05a545982faa5a8)
1 /*
2  * Copyright 2003-2013 Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Jérôme Duval, jerome.duval@free.fr
7  *		Julun, host.haiku@gmx.de
8  *		Michael Phipps
9  *		John Scipione, jscipione@gmail.com
10  */
11 
12 
13 #include "PasswordWindow.h"
14 
15 #include <Alert.h>
16 #include <Box.h>
17 #include <Button.h>
18 #include <Catalog.h>
19 #include <ControlLook.h>
20 #include <LayoutBuilder.h>
21 #include <LayoutItem.h>
22 #include <RadioButton.h>
23 #include <Screen.h>
24 #include <Size.h>
25 #include <TextControl.h>
26 
27 #include <ctype.h>
28 
29 #include "ScreenSaverSettings.h"
30 
31 
32 #undef B_TRANSLATION_CONTEXT
33 #define B_TRANSLATION_CONTEXT "ScreenSaver"
34 
35 
36 static const uint32 kPasswordTextWidth = 12;
37 
38 static const uint32 kMsgDone = 'done';
39 static const uint32 kMsgPasswordTypeChanged = 'pwtp';
40 
41 
42 PasswordWindow::PasswordWindow(ScreenSaverSettings& settings)
43 	:
44 	BWindow(BRect(100, 100, 300, 200), B_TRANSLATE("Password Window"),
45 		B_MODAL_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, B_NOT_RESIZABLE
46 			| B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS),
47 	fSettings(settings)
48 {
49 	_Setup();
50 	Update();
51 }
52 
53 
54 void
55 PasswordWindow::_Setup()
56 {
57 	float spacing = be_control_look->DefaultItemSpacing();
58 
59 	BView* topView = new BView("topView", B_WILL_DRAW);
60 	topView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
61 	topView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED));
62 
63 	BBox* networkBox = new BBox("networkBox");
64 	networkBox->SetBorder(B_NO_BORDER);
65 
66 	fUseNetwork = new BRadioButton("useNetwork",
67 		B_TRANSLATE("Use network password"),
68 		new BMessage(kMsgPasswordTypeChanged));
69 	networkBox->SetLabel(fUseNetwork);
70 
71 	BBox* customBox = new BBox("customBox");
72 
73 	fUseCustom = new BRadioButton("useCustom",
74 		B_TRANSLATE("Use custom password"),
75 		new BMessage(kMsgPasswordTypeChanged));
76 	customBox->SetLabel(fUseCustom);
77 
78 	fPasswordControl = new BTextControl("passwordTextView",
79 		B_TRANSLATE("Password:"), B_EMPTY_STRING, NULL);
80 	fPasswordControl->TextView()->HideTyping(true);
81 	fPasswordControl->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
82 
83 	BLayoutItem* passwordTextView
84 		= fPasswordControl->CreateTextViewLayoutItem();
85 	passwordTextView->SetExplicitMinSize(BSize(spacing * kPasswordTextWidth,
86 		B_SIZE_UNSET));
87 
88 	fConfirmControl = new BTextControl("confirmTextView",
89 		B_TRANSLATE("Confirm password:"), B_EMPTY_STRING, NULL);
90 	fConfirmControl->SetExplicitMinSize(BSize(spacing * kPasswordTextWidth,
91 		B_SIZE_UNSET));
92 	fConfirmControl->TextView()->HideTyping(true);
93 	fConfirmControl->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
94 
95 	BLayoutItem* confirmTextView = fConfirmControl->CreateTextViewLayoutItem();
96 	confirmTextView->SetExplicitMinSize(BSize(spacing * kPasswordTextWidth,
97 		B_SIZE_UNSET));
98 
99 	customBox->AddChild(BLayoutBuilder::Group<>(B_VERTICAL)
100 		.SetInsets(B_USE_SMALL_SPACING)
101 		.AddGrid(B_USE_DEFAULT_SPACING, B_USE_SMALL_SPACING)
102 			.Add(fPasswordControl->CreateLabelLayoutItem(), 0, 0)
103 			.Add(passwordTextView, 1, 0)
104 			.Add(fConfirmControl->CreateLabelLayoutItem(), 0, 1)
105 			.Add(confirmTextView, 1, 1)
106 			.End()
107 		.View());
108 
109 	BButton* doneButton = new BButton("done", B_TRANSLATE("Done"),
110 		new BMessage(kMsgDone));
111 
112 	BButton* cancelButton = new BButton("cancel", B_TRANSLATE("Cancel"),
113 		new BMessage(B_CANCEL));
114 
115 	BLayoutBuilder::Group<>(topView, B_VERTICAL, 0)
116 		.SetInsets(B_USE_DEFAULT_SPACING)
117 		.Add(networkBox)
118 		.Add(customBox)
119 		.AddStrut(B_USE_DEFAULT_SPACING)
120 		.AddGroup(B_HORIZONTAL)
121 			.AddGlue()
122 			.Add(cancelButton)
123 			.Add(doneButton)
124 			.End()
125 		.End();
126 
127 	doneButton->MakeDefault(true);
128 
129 	SetLayout(new BGroupLayout(B_VERTICAL));
130 	GetLayout()->AddView(topView);
131 }
132 
133 
134 void
135 PasswordWindow::Update()
136 {
137 	if (fSettings.IsNetworkPassword())
138 		fUseNetwork->SetValue(B_CONTROL_ON);
139 	else
140 		fUseCustom->SetValue(B_CONTROL_ON);
141 
142 	bool useNetPassword = (fUseCustom->Value() > 0);
143 	fConfirmControl->SetEnabled(useNetPassword);
144 	fPasswordControl->SetEnabled(useNetPassword);
145 }
146 
147 
148 char*
149 PasswordWindow::_SanitizeSalt(const char* password)
150 {
151 	char* salt;
152 
153 	uint8 length = strlen(password);
154 
155 	if (length < 2)
156 		salt = new char[3];
157 	else
158 		salt = new char[length + 1];
159 
160 	uint8 i = 0;
161 	uint8 j = 0;
162 	for (; i < length; i++) {
163 		if (isalnum(password[i]) || password[i] == '.' || password[i] == '/') {
164 			salt[j] = password[i];
165 			j++;
166 		}
167 	}
168 
169 	/*
170 	 *	We need to pad the salt.
171 	 */
172 	while (j < 2) {
173 		salt[j] = '.';
174 		j++;
175 	}
176 
177 	salt[j] = '\0';
178 
179 	return salt;
180 }
181 
182 
183 void
184 PasswordWindow::MessageReceived(BMessage* message)
185 {
186 	switch (message->what) {
187 		case kMsgDone:
188 			fSettings.SetLockMethod(fUseCustom->Value() ? "custom" : "network");
189 			if (fUseCustom->Value()) {
190 				if (strcmp(fPasswordControl->Text(), fConfirmControl->Text())
191 						!= 0) {
192 					BAlert* alert = new BAlert("noMatch",
193 						B_TRANSLATE("Passwords don't match. Please try again."),
194 						B_TRANSLATE("OK"));
195 					alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
196 					alert->Go();
197 					break;
198 				}
199 				const char* salt = _SanitizeSalt(fPasswordControl->Text());
200 				fSettings.SetPassword(crypt(fPasswordControl->Text(), salt));
201 				delete[] salt;
202 			} else
203 				fSettings.SetPassword("");
204 
205 			fPasswordControl->SetText("");
206 			fConfirmControl->SetText("");
207 			fSettings.Save();
208 			Hide();
209 			break;
210 
211 		case B_CANCEL:
212 			fPasswordControl->SetText("");
213 			fConfirmControl->SetText("");
214 			Hide();
215 			break;
216 
217 		case kMsgPasswordTypeChanged:
218 			fSettings.SetLockMethod(fUseCustom->Value() > 0 ? "custom" : "network");
219 			Update();
220 			break;
221 
222 		default:
223 			BWindow::MessageReceived(message);
224  	}
225 }
226