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