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