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_TRANSLATION_CONTEXT 25 #define B_TRANSLATION_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->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 188 alert->Go(); 189 break; 190 } 191 const char *salt = _SanitizeSalt(fPasswordControl->Text()); 192 fSettings.SetPassword(crypt(fPasswordControl->Text(), salt)); 193 delete[] salt; 194 } else { 195 fSettings.SetPassword(""); 196 } 197 fPasswordControl->SetText(""); 198 fConfirmControl->SetText(""); 199 fSettings.Save(); 200 Hide(); 201 break; 202 203 case B_CANCEL: 204 fPasswordControl->SetText(""); 205 fConfirmControl->SetText(""); 206 Hide(); 207 break; 208 209 case kMsgPasswordTypeChanged: 210 fSettings.SetLockMethod(fUseCustom->Value() > 0 ? "custom" : "network"); 211 Update(); 212 break; 213 214 default: 215 BWindow::MessageReceived(message); 216 break; 217 } 218 } 219