hrev47960 adds 2 changesets to branch 'master' old head: c6e3208e3e78ba2be90e74b129f00e1f3f1a4bc9 new head: 6f9eb8d1bb1fd9d9a93b3afda0be7578ca322caa overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=6f9eb8d+%5Ec6e3208 ---------------------------------------------------------------------------- fa09af9: HaikuDepot/RatePackageWindow: Output in error code paths 6f9eb8d: HaikuDepot: Validate input before creating account Provide error or info alert when fields are invalid, suggest providing an email, but allow to ignore the warning. [ Stephan Aßmus <superstippi@xxxxxx> ] ---------------------------------------------------------------------------- 4 files changed, 162 insertions(+), 5 deletions(-) src/apps/haikudepot/ui/RatePackageWindow.cpp | 16 ++- src/apps/haikudepot/ui/UserLoginWindow.cpp | 144 ++++++++++++++++++++++- src/apps/haikudepot/ui/UserLoginWindow.h | 2 + src/kits/interface/TextControl.cpp | 5 + ############################################################################ Commit: fa09af9a8f2426e03e944d2a91078536a89f97db URL: http://cgit.haiku-os.org/haiku/commit/?id=fa09af9 Author: Stephan Aßmus <superstippi@xxxxxx> Date: Sat Oct 4 10:31:12 2014 UTC HaikuDepot/RatePackageWindow: Output in error code paths ---------------------------------------------------------------------------- diff --git a/src/apps/haikudepot/ui/RatePackageWindow.cpp b/src/apps/haikudepot/ui/RatePackageWindow.cpp index 729e930..346b739 100644 --- a/src/apps/haikudepot/ui/RatePackageWindow.cpp +++ b/src/apps/haikudepot/ui/RatePackageWindow.cpp @@ -387,8 +387,10 @@ RatePackageWindow::_QueryRatingThreadEntry(void* data) void RatePackageWindow::_QueryRatingThread() { - if (!Lock()) + if (!Lock()) { + fprintf(stderr, "rating query: Failed to lock window\n"); return; + } PackageInfoRef package(fPackage); @@ -399,6 +401,7 @@ RatePackageWindow::_QueryRatingThread() locker.Unlock(); if (package.Get() == NULL) { + fprintf(stderr, "rating query: No package\n"); _SetWorkerThread(-1); return; } @@ -458,6 +461,11 @@ RatePackageWindow::_QueryRatingThread() fSendButton->SetLabel(B_TRANSLATE("Update")); Unlock(); + } else { + fprintf(stderr, "rating query: Failed response: %s\n", + strerror(status)); + if (!info.IsEmpty()) + info.PrintToStream(); } _SetWorkerThread(-1); @@ -476,8 +484,10 @@ RatePackageWindow::_SendRatingThreadEntry(void* data) void RatePackageWindow::_SendRatingThread() { - if (!Lock()) + if (!Lock()) { + fprintf(stderr, "upload rating: Failed to lock window\n"); return; + } BString package = fPackage->Title(); BString architecture = fPackage->Architecture(); @@ -551,6 +561,8 @@ RatePackageWindow::_SendRatingThread() fprintf(stderr, B_TRANSLATE("Failed to create or update rating: %s\n"), error.String()); + if (!info.IsEmpty()) + info.PrintToStream(); _SetWorkerThread(-1); } else { ############################################################################ Revision: hrev47960 Commit: 6f9eb8d1bb1fd9d9a93b3afda0be7578ca322caa URL: http://cgit.haiku-os.org/haiku/commit/?id=6f9eb8d Author: Stephan Aßmus <superstippi@xxxxxx> Date: Sat Oct 4 11:31:58 2014 UTC HaikuDepot: Validate input before creating account Provide error or info alert when fields are invalid, suggest providing an email, but allow to ignore the warning. ---------------------------------------------------------------------------- diff --git a/src/apps/haikudepot/ui/UserLoginWindow.cpp b/src/apps/haikudepot/ui/UserLoginWindow.cpp index f2598e5..25624b8 100644 --- a/src/apps/haikudepot/ui/UserLoginWindow.cpp +++ b/src/apps/haikudepot/ui/UserLoginWindow.cpp @@ -19,6 +19,7 @@ #include <PopUpMenu.h> #include <TabView.h> #include <TextControl.h> +#include <UnicodeChar.h> #include "BitmapView.h" #include "Model.h" @@ -33,6 +34,7 @@ enum { MSG_SEND = 'send', MSG_TAB_SELECTED = 'tbsl', MSG_CAPTCHA_OBTAINED = 'cpob', + MSG_VALIDATE_FIELDS = 'vldt', MSG_LANGUAGE_SELECTED = 'lngs', }; @@ -92,12 +94,13 @@ UserLoginWindow::UserLoginWindow(BWindow* parent, BRect frame, Model& model) fPasswordField = new BTextControl(B_TRANSLATE("Pass phrase:"), "", NULL); fPasswordField->TextView()->HideTyping(true); - fNewUsernameField = new BTextControl(B_TRANSLATE("User name:"), "", NULL); - fNewPasswordField = new BTextControl(B_TRANSLATE("Pass phrase:"), "", + fNewUsernameField = new BTextControl(B_TRANSLATE("User name:"), "", NULL); + fNewPasswordField = new BTextControl(B_TRANSLATE("Pass phrase:"), "", + new BMessage(MSG_VALIDATE_FIELDS)); fNewPasswordField->TextView()->HideTyping(true); fRepeatPasswordField = new BTextControl(B_TRANSLATE("Repeat pass phrase:"), - "", NULL); + "", new BMessage(MSG_VALIDATE_FIELDS)); fRepeatPasswordField->TextView()->HideTyping(true); // Construct languages popup @@ -118,6 +121,19 @@ UserLoginWindow::UserLoginWindow(BWindow* parent, BRect frame, Model& model) fCaptchaView = new BitmapView("captcha view"); fCaptchaResultField = new BTextControl("", "", NULL); + // Setup modification messages on all text fields to trigger validation + // of input + fNewUsernameField->SetModificationMessage( + new BMessage(MSG_VALIDATE_FIELDS)); + fNewPasswordField->SetModificationMessage( + new BMessage(MSG_VALIDATE_FIELDS)); + fRepeatPasswordField->SetModificationMessage( + new BMessage(MSG_VALIDATE_FIELDS)); + fEmailField->SetModificationMessage( + new BMessage(MSG_VALIDATE_FIELDS)); + fCaptchaResultField->SetModificationMessage( + new BMessage(MSG_VALIDATE_FIELDS)); + fTabView = new TabView(BMessenger(this), BMessage(MSG_TAB_SELECTED)); @@ -182,6 +198,10 @@ void UserLoginWindow::MessageReceived(BMessage* message) { switch (message->what) { + case MSG_VALIDATE_FIELDS: + _ValidateCreateAccountFields(); + break; + case MSG_SEND: switch (fMode) { case LOGIN: @@ -220,6 +240,7 @@ UserLoginWindow::MessageReceived(BMessage* message) } else { fCaptchaView->SetBitmap(NULL); } + fCaptchaResultField->SetText(""); break; case MSG_LANGUAGE_SELECTED: @@ -262,6 +283,7 @@ UserLoginWindow::_SetMode(Mode mode) if (fCaptchaToken.IsEmpty()) _RequestCaptcha(); fNewUsernameField->MakeFocus(); + _ValidateCreateAccountFields(); break; default: break; @@ -269,6 +291,119 @@ UserLoginWindow::_SetMode(Mode mode) } +static int32 +count_digits(const BString& string) +{ + int32 digits = 0; + const char* c = string.String(); + for (int32 i = 0; i < string.CountChars(); i++) { + uint32 unicodeChar = BUnicodeChar::FromUTF8(&c); + if (BUnicodeChar::IsDigit(unicodeChar)) + digits++; + } + return digits; +} + + +static int32 +count_upper_case_letters(const BString& string) +{ + int32 upperCaseLetters = 0; + const char* c = string.String(); + for (int32 i = 0; i < string.CountChars(); i++) { + uint32 unicodeChar = BUnicodeChar::FromUTF8(&c); + if (BUnicodeChar::IsUpper(unicodeChar)) + upperCaseLetters++; + } + return upperCaseLetters; +} + + +bool +UserLoginWindow::_ValidateCreateAccountFields(bool alertProblems) +{ + BString nickName(fNewUsernameField->Text()); + BString password1(fNewPasswordField->Text()); + BString password2(fRepeatPasswordField->Text()); + BString email(fEmailField->Text()); + BString captcha(fCaptchaResultField->Text()); + + // TODO: Use the same validation as the web-serivce + bool validUserName = nickName.Length() >= 3; + fNewUsernameField->MarkAsInvalid(validUserName); + + bool validPassword = password1.Length() >= 8 + && count_digits(password1) >= 2 + && count_upper_case_letters(password1) >= 2; + fNewPasswordField->MarkAsInvalid(!validPassword); + fRepeatPasswordField->MarkAsInvalid(password1 != password2); + + bool validCaptcha = captcha.Length() > 0; + fCaptchaResultField->MarkAsInvalid(!validCaptcha); + + bool valid = validUserName && validPassword && password1 == password2 + && validCaptcha; + if (valid && email.Length() > 0) + return true; + + if (alertProblems) { + BString message; + alert_type alertType; + const char* okLabel = B_TRANSLATE("OK"); + const char* cancelLabel = NULL; + if (!valid) { + message = B_TRANSLATE("There are problems in the form:\n\n"); + alertType = B_WARNING_ALERT; + } else { + alertType = B_IDEA_ALERT; + okLabel = B_TRANSLATE("Ignore"); + cancelLabel = B_TRANSLATE("Cancel"); + } + + if (!validUserName) { + message << B_TRANSLATE( + "The user name needs to be at least " + "3 letters long.") << "\n\n"; + } + if (!validPassword) { + message << B_TRANSLATE( + "The password is too weak or invalid. " + "Please use at least 8 characters with " + "at least 2 numbers and 2 upper-case " + "letters.") << "\n\n"; + } + if (password1 != password2) { + message << B_TRANSLATE( + "The passwords do not match.") << "\n\n"; + } + if (email.Length() == 0) { + message << B_TRANSLATE( + "If you do not provide an email address, " + "you will not be able to reset your password " + "if you forget it.") << "\n\n"; + } + if (!validCaptcha) { + message << B_TRANSLATE( + "The captcha puzzle needs to be solved.") << "\n\n"; + } + + BAlert* alert = new(std::nothrow) BAlert( + B_TRANSLATE("Input validation"), + message, + okLabel, cancelLabel, NULL, + B_WIDTH_AS_USUAL, alertType); + + if (alert != NULL) { + int32 choice = alert->Go(); + if (choice == 1) + return false; + } + } + + return valid; +} + + void UserLoginWindow::_Login() { @@ -287,6 +422,9 @@ UserLoginWindow::_Login() void UserLoginWindow::_CreateAccount() { + if (!_ValidateCreateAccountFields(true)) + return; + BAutolock locker(&fLock); if (fWorkerThread >= 0) diff --git a/src/apps/haikudepot/ui/UserLoginWindow.h b/src/apps/haikudepot/ui/UserLoginWindow.h index 6d1540b..6d529e7 100644 --- a/src/apps/haikudepot/ui/UserLoginWindow.h +++ b/src/apps/haikudepot/ui/UserLoginWindow.h @@ -40,6 +40,8 @@ private: }; void _SetMode(Mode mode); + bool _ValidateCreateAccountFields( + bool alertProblems = false); void _Login(); void _CreateAccount(); void _RequestCaptcha(); diff --git a/src/kits/interface/TextControl.cpp b/src/kits/interface/TextControl.cpp index caabbbe..fac0166 100644 --- a/src/kits/interface/TextControl.cpp +++ b/src/kits/interface/TextControl.cpp @@ -336,10 +336,15 @@ BTextControl::Text() const void BTextControl::MarkAsInvalid(bool invalid) { + uint32 look = fLook; + if (invalid) fLook |= BControlLook::B_INVALID; else fLook &= ~BControlLook::B_INVALID; + + if (look != fLook) + Invalidate(); }