xref: /haiku/src/preferences/screensaver/PasswordWindow.cpp (revision 922e7ba1f3228e6f28db69b0ded8f86eb32dea17)
1 /*
2  * Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Michael Phipps
7  *		Jérôme Duval, jerome.duval@free.fr
8  *		Julun <host.haiku@gmx.de>
9  */
10 
11 #include "PasswordWindow.h"
12 
13 
14 #include <Alert.h>
15 #include <Box.h>
16 #include <Button.h>
17 #include <Catalog.h>
18 #include <RadioButton.h>
19 #include <Screen.h>
20 #include <TextControl.h>
21 
22 #include <ctype.h>
23 
24 #undef B_TRANSLATE_CONTEXT
25 #define B_TRANSLATE_CONTEXT "ScreenSaver"
26 
27 const uint32 kMsgDone = 'done';
28 const uint32 kMsgPasswordTypeChanged = 'pwtp';
29 
30 
31 PasswordWindow::PasswordWindow(ScreenSaverSettings& settings)
32 	: BWindow(BRect(100, 100, 380, 249), B_TRANSLATE("Password Window"),
33 		B_MODAL_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, B_ASYNCHRONOUS_CONTROLS
34 			| B_NOT_RESIZABLE),
35 	fSettings(settings)
36 {
37 	_Setup();
38 	Update();
39 
40 	BRect screenFrame = BScreen(B_MAIN_SCREEN_ID).Frame();
41 	BPoint point;
42 	point.x = (screenFrame.Width() - Bounds().Width()) / 2;
43 	point.y = (screenFrame.Height() - Bounds().Height()) / 2;
44 
45 	if (screenFrame.Contains(point))
46 		MoveTo(point);
47 }
48 
49 
50 void
51 PasswordWindow::_Setup()
52 {
53 	BRect bounds = Bounds();
54 	BView* topView = new BView(bounds, "topView", B_FOLLOW_ALL, B_WILL_DRAW);
55 	topView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
56 	AddChild(topView);
57 
58 	bounds.InsetBy(10.0, 10.0);
59 	fUseNetwork = new BRadioButton(bounds, "useNetwork",
60 		B_TRANSLATE("Use network password"),
61 		new BMessage(kMsgPasswordTypeChanged), B_FOLLOW_NONE);
62 	topView->AddChild(fUseNetwork);
63 	fUseNetwork->ResizeToPreferred();
64 	fUseNetwork->MoveBy(10.0, 0.0);
65 
66 	bounds.OffsetBy(0.0, fUseNetwork->Bounds().Height());
67 	BBox *customBox = new BBox(bounds, "customBox", B_FOLLOW_NONE);
68 	topView->AddChild(customBox);
69 
70 	fUseCustom = new BRadioButton(BRect(), "useCustom",
71 		B_TRANSLATE("Use custom password"),
72 		new BMessage(kMsgPasswordTypeChanged), B_FOLLOW_NONE);
73 	customBox->SetLabel(fUseCustom);
74 	fUseCustom->ResizeToPreferred();
75 
76 	fPasswordControl = new BTextControl(bounds, "passwordControl",
77 		B_TRANSLATE("Password:"),
78 		NULL, B_FOLLOW_NONE);
79 	customBox->AddChild(fPasswordControl);
80 	fPasswordControl->ResizeToPreferred();
81 	fPasswordControl->TextView()->HideTyping(true);
82 	fPasswordControl->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
83 
84 	bounds.OffsetBy(0.0, fPasswordControl->Bounds().Height() + 5.0);
85 	fConfirmControl = new BTextControl(bounds, "confirmControl",
86 		B_TRANSLATE("Confirm password:"),
87 		"VeryLongPasswordPossible",
88 		B_FOLLOW_NONE);
89 	customBox->AddChild(fConfirmControl);
90 	fConfirmControl->TextView()->HideTyping(true);
91 	fConfirmControl->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
92 
93 	float width, height;
94 	fConfirmControl->GetPreferredSize(&width, &height);
95 	fPasswordControl->ResizeTo(width, height);
96 	fConfirmControl->ResizeTo(width, height);
97 
98 	float divider = be_plain_font->StringWidth(B_TRANSLATE("Confirm password:"))
99 		+ 5.0;
100 	fConfirmControl->SetDivider(divider);
101 	fPasswordControl->SetDivider(divider);
102 
103 	customBox->ResizeTo(fConfirmControl->Frame().right + 10.0,
104 		fConfirmControl->Frame().bottom + 10.0);
105 
106 	BButton* button = new BButton(BRect(), "done", B_TRANSLATE("Done"),
107 		new BMessage(kMsgDone));
108 	topView->AddChild(button);
109 	button->ResizeToPreferred();
110 
111 	BRect frame = customBox->Frame();
112 	button->MoveTo(frame.right - button->Bounds().Width(), frame.bottom + 10.0);
113 
114 	frame = button->Frame();
115 	button->MakeDefault(true);
116 
117 	button = new BButton(frame, "cancel", B_TRANSLATE("Cancel"),
118 		new BMessage(B_CANCEL));
119 	topView->AddChild(button);
120 	button->ResizeToPreferred();
121 	button->MoveBy(-(button->Bounds().Width() + 10.0), 0.0);
122 
123 	ResizeTo(customBox->Frame().right + 10.0, frame.bottom + 10.0);
124 }
125 
126 
127 void
128 PasswordWindow::Update()
129 {
130 	if (fSettings.IsNetworkPassword())
131 		fUseNetwork->SetValue(B_CONTROL_ON);
132 	else
133 		fUseCustom->SetValue(B_CONTROL_ON);
134 
135 	bool useNetPassword = (fUseCustom->Value() > 0);
136 	fConfirmControl->SetEnabled(useNetPassword);
137 	fPasswordControl->SetEnabled(useNetPassword);
138 }
139 
140 
141 char *
142 PasswordWindow::_SanitizeSalt(const char *password)
143 {
144 	char *salt;
145 
146 	uint8 length = strlen(password);
147 
148 	if (length < 2)
149 		salt = new char[3];
150 	else
151 		salt = new char[length + 1];
152 
153 	uint8 i = 0;
154 	uint8 j = 0;
155 	for (; i < length; i++) {
156 		if (isalnum(password[i]) || password[i] == '.' || password[i] == '/') {
157 			salt[j] = password[i];
158 			j++;
159 		}
160 	}
161 
162 	/*
163 	 *	We need to pad the salt.
164 	 */
165 	while (j < 2) {
166 		salt[j] = '.';
167 		j++;
168 	}
169 
170 	salt[j] = '\0';
171 
172 	return salt;
173 }
174 
175 
176 void
177 PasswordWindow::MessageReceived(BMessage *message)
178 {
179 	switch (message->what) {
180 		case kMsgDone:
181 			fSettings.SetLockMethod(fUseCustom->Value() ? "custom" : "network");
182 			if (fUseCustom->Value()) {
183 				if (strcmp(fPasswordControl->Text(), fConfirmControl->Text())) {
184 					BAlert *alert = new BAlert("noMatch",
185 						B_TRANSLATE("Passwords don't match. Please try again."),
186 						B_TRANSLATE("OK"));
187 					alert->Go();
188 					break;
189 				}
190 				const char *salt = _SanitizeSalt(fPasswordControl->Text());
191 				fSettings.SetPassword(crypt(fPasswordControl->Text(), salt));
192 				delete[] salt;
193 			} else {
194 				fSettings.SetPassword("");
195 			}
196 			fPasswordControl->SetText("");
197 			fConfirmControl->SetText("");
198 			fSettings.Save();
199 			Hide();
200 			break;
201 
202 	case B_CANCEL:
203 		fPasswordControl->SetText("");
204 		fConfirmControl->SetText("");
205 		Hide();
206 		break;
207 
208 	case kMsgPasswordTypeChanged:
209 		fSettings.SetLockMethod(fUseCustom->Value() > 0 ? "custom" : "network");
210 		Update();
211 		break;
212 
213 	default:
214 		BWindow::MessageReceived(message);
215 		break;
216  	}
217 }
218