Merge lp:~widelands-dev/widelands/bug-1827786-metaserver-login-box-clean-start into lp:widelands
- bug-1827786-metaserver-login-box-clean-start
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 9117 | ||||
Proposed branch: | lp:~widelands-dev/widelands/bug-1827786-metaserver-login-box-clean-start | ||||
Merge into: | lp:widelands | ||||
Prerequisite: | lp:~widelands-dev/widelands/bug-1825932-open-games-clean-start | ||||
Diff against target: |
662 lines (+258/-127) 9 files modified
src/network/internet_gaming.cc (+11/-0) src/network/internet_gaming.h (+2/-0) src/ui_basic/editbox.cc (+46/-18) src/ui_basic/editbox.h (+10/-0) src/ui_fsmenu/internet_lobby.cc (+3/-2) src/ui_fsmenu/multiplayer.cc (+39/-62) src/ui_fsmenu/multiplayer.h (+2/-2) src/wui/login_box.cc (+136/-38) src/wui/login_box.h (+9/-5) |
||||
To merge this branch: | bzr merge lp:~widelands-dev/widelands/bug-1827786-metaserver-login-box-clean-start | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
GunChleoc | Approve | ||
kaputtnik (community) | testing | Approve | |
Review via email: mp+367320@code.launchpad.net |
This proposal supersedes a proposal from 2019-05-12.
Commit message
redesigned login box
- renamed to Online game Settings
- limit the possible characters for usernames
- draw a red box around the input field for erroneous input
- tell user were to register their username
- clicking registered checkbox focuses password field
- remove check from registered_ clears password field
- password field is only accessible when checkbox is clicked
- when a password is set, ***** is shown on opening
- login box handles the settings instead of multiplayer
multiplayer login redesign
- only show login dialog when no name or invalid name is set
- Group of 2 buttons for Online Game & Settings
- renamed Internet game to Online game
- moved settings saving to login box
Description of the change
kaputtnik (franku) wrote : Posted in a previous version of this proposal | # |
Toni Förster (stonerl) wrote : Posted in a previous version of this proposal | # |
Your're right. Chnaged it.
bunnybot (widelandsofficial) wrote : Posted in a previous version of this proposal | # |
Continuous integration builds have changed state:
Travis build 4915. State: passed. Details: https:/
Appveyor build 4696. State: success. Details: https:/
GunChleoc (gunchleoc) : Posted in a previous version of this proposal | # |
Toni Förster (stonerl) wrote : Posted in a previous version of this proposal | # |
Will address the strings later. For the others see the diff comments.
bunnybot (widelandsofficial) wrote : Posted in a previous version of this proposal | # |
Continuous integration builds have changed state:
Travis build 4925. State: errored. Details: https:/
Appveyor build 4706. State: success. Details: https:/
kaputtnik (franku) wrote : Posted in a previous version of this proposal | # |
As talked on IRC: Can you try to remove the red border around the password editbox and instead show the string 'Password' and the corresponding editbox look sort of grayed out?
I think the text below can also be improved: "You need an account on the widelands website to use a registered account. Please visit ...."
GunChleoc (gunchleoc) wrote : Posted in a previous version of this proposal | # |
Changing editbox styles is implemented in https:/
GunChleoc (gunchleoc) wrote : Posted in a previous version of this proposal | # |
The changes string is missing a . after the %
I'll do some testing before I reply to the remaining diff comments.
Toni Förster (stonerl) wrote : Posted in a previous version of this proposal | # |
@kaputtnik
I addressed your comments. The only thing I can't do ATM is, greying out the password field.
Toni Förster (stonerl) wrote : Posted in a previous version of this proposal | # |
But I'm not confident whether we should grey the password field out as well. I would look too similar to an active edit box. Greying out the text "Password" and making the input box not editable should be sufficient, IMHO.
Toni Förster (stonerl) wrote : Posted in a previous version of this proposal | # |
This one gets replaced by the following one:
GunChleoc (gunchleoc) wrote : | # |
I have pushed a small tweak and added some more comments.
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 4956. State: passed. Details: https:/
Appveyor build 4737. State: success. Details: https:/
kaputtnik (franku) wrote : | # |
Looks good, imho. Graying out the 'Password' is sufficient :-)
The green arrow on the right of 'Internet Game' is always shown now? -> I tried to start widelands with a new homedir, and the green arrow was shown.
Don't forget to remove the 'red border' thing from the commit message please ;)
GunChleoc (gunchleoc) wrote : | # |
It does not solve comment #1 in the attached bug though:
> We should also add a password mode to the Editbox class that will show *** instead of the actual text.
So, either open a new bug before merging, or fix it in this branch.
Toni Förster (stonerl) wrote : | # |
Please test again it should address all issues. The only problem is that the caret does not move properly. Help is appreciated. :)
@Gun have a look at the diff comment, please.
Toni Förster (stonerl) wrote : | # |
Carets are also fixed.
Toni Förster (stonerl) wrote : | # |
I made the "show login dialog" button a proper button. kaputtnik has second thoughts, though.
here is a screenshot:
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 4976. State: errored. Details: https:/
Appveyor build 4757. State: success. Details: https:/
Toni Förster (stonerl) wrote : | # |
I could think of another option. We remove the button entirely. The login window is always shown for non registered users. When a user has entered a password, the dialog won't be shown as long as the password is valid.
GunChleoc (gunchleoc) wrote : | # |
That would not allow different players to use the same computer, because you can never log out when the password is correct.
I'd say revert the changes for now and let's think about having a logout button in the lobby.
Regarding the user name validation, this should be implemented in internet gaming somewhere, not in editbox. The editbox is a UI element and should not care about what a well-formed user name is. That way, you could also get rid of the remaining code duplication.
I have tested the password display and it's working fine :)
Toni Förster (stonerl) wrote : | # |
I have moved username validation to internet gaming.
I'm currently experimenting with a logout button stay tuned :=)
Toni Förster (stonerl) wrote : | # |
We have a logout button now :D
The login dialog will be shown only for non registered users. Registered users may log out from their account from within the lobby.
The additional login button from the Multiplayer menu is removed.
kaputtnik (franku) wrote : | # |
I am not convinced by this solution, it is confusing:
1. We have two places (views) which interact with the same thing now.
2. We have two buttons, 'Logout' and 'Back', in the lobby now, which do the same at first sight: Go back to the 'Multiplayer' view. How will a tooltip, if there were any, look to explain the buttons?
Having it like before is better, imho, although the small icon (button) to show the loginbox is visually disturbing. But better a visually disturbing thing than a confusing UI, especially because the Multiplayer view is mostly open for a short time.
Just my personal opinion :)
Toni Förster (stonerl) wrote : | # |
Well another solution would be:
We rename the back button to "Leave lobby"
Above the button we have a checkbox "Clear login data"
kaputtnik (franku) wrote : | # |
> We rename the back button to "Leave lobby"
> Above the button we have a checkbox "Clear login data"
"Leave lobby and clear login data" would be the correct explanation. But it's confusing anyway to have this in the lobby.
Maybe i am too nitpicking ;)
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 4988. State: passed. Details: https:/
Appveyor build 4769. State: success. Details: https:/
Toni Förster (stonerl) wrote : | # |
Hmm, I'm still uncertain. What about this?
https:/
I have to flesh out the details, though. Bu would this Screen look okay?
Toni Förster (stonerl) wrote : | # |
I gave it another run. The button is now called “Login settings” and sits in between the “LAN / Direct IP” ans “Back”.[1] The Title of the Login box has be renamed accordingly, also the “Login” button has been renamed to “Save”.[2]
The window opens automatically when no username or an invalid username is set or the wrong password has been entered. Otherwise, the user has to click the button. Clicking on “Save” in the box only closes the window but does not login automatically.
[1]https:/
[2]https:/
kaputtnik (franku) wrote : | # |
Ordering the buttons like here https:/
All the rest is fine for me :-)
GunChleoc (gunchleoc) wrote : | # |
How abut calling the "Back" button "Leave Lobby" rather than "Log Out"?
Toni Förster (stonerl) wrote : | # |
I renamed the back button
Reorder button on the multiplayer screen.
I took the liberty to rename “Internet game” because this is the common term nowadays (e.g. Wikipedia redirects form Internet game to Online game). I also renamed the settings button to “Online game Settings”
@Gun is it:
1. Online game settings
2. Online game Settings
2. Online Game Settings
I went for number 2.
GunChleoc (gunchleoc) wrote : | # |
Buttons use Title Case, so:
Online Game
Online Game Settings
kaputtnik (franku) wrote : | # |
Hm, there is some inconsistency and an assertion:
1. Start widelands
2. Set a wrong password -> No hint about wrong password -> Login dialog closes
3. Trying to get into the lobby shows now a warning -> Loginbox appear
4. Set a wrong password again -> now the warning appears immediately
5. Close dialog by pressing 'Cancel' (did not test right click to close it)
6. Try to enter the lobby -> Assertion:
widelands: /home/kaputtnik
If feasible the warning about wrong password should appear also in step 2.
I am fine with the wording though :-)
Toni Förster (stonerl) wrote : | # |
Can you give it another try?
kaputtnik (franku) wrote : | # |
Popup if wrong password is set works now. But i can still provoke the Assertion:
1. Open the settings
2. Enter a wrong password and close the popup
3. Click cancel
4. Try to connect with the metaserver (click on Online Game)
Running widelands with a new home directory does not show this error.
kaputtnik (franku) wrote : | # |
Setting a correct password and clicking on 'Save' connects immediately to the lobby and immediately disconnect again. One can see this in channel #widelands on IRC.
But the assert is gone now :-)
Toni Förster (stonerl) wrote : | # |
> Setting a correct password and clicking on 'Save' connects immediately to the
> lobby and immediately disconnect again. One can see this in channel #widelands
> on IRC.
>
That is currently the only way to check whether the password was correct or not.
Toni Förster (stonerl) wrote : | # |
Also, this needs to be resolved on the Metaserver side.
kaputtnik (franku) wrote : | # |
Ok, we may need to file a bug against the metaserver then.
This branch is ok for me now :-)
GunChleoc (gunchleoc) wrote : | # |
Code LGTM.
One tweak I'd like to see after testing:
Error message "The sent password was incorrect!" - call it "Wrong password" or "Wrong password, please try again." The user doesn't care about the technical detail that it was sent. This is coming from the metaserver, so I have opened a but over there. https:/
Preview Diff
1 | === modified file 'src/network/internet_gaming.cc' | |||
2 | --- src/network/internet_gaming.cc 2019-05-13 02:25:58 +0000 | |||
3 | +++ src/network/internet_gaming.cc 2019-05-23 17:11:42 +0000 | |||
4 | @@ -947,3 +947,14 @@ | |||
5 | 947 | ingame_system_chat_.push_back(c); | 947 | ingame_system_chat_.push_back(c); |
6 | 948 | } | 948 | } |
7 | 949 | } | 949 | } |
8 | 950 | |||
9 | 951 | /** | ||
10 | 952 | * Check for vaild username characters. | ||
11 | 953 | */ | ||
12 | 954 | bool InternetGaming::valid_username(std::string username) { | ||
13 | 955 | if (username.empty() || username.find_first_not_of("abcdefghijklmnopqrstuvwxyz" | ||
14 | 956 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890@.+-_") <= username.size()) { | ||
15 | 957 | return false; | ||
16 | 958 | } | ||
17 | 959 | return true; | ||
18 | 960 | } | ||
19 | 950 | 961 | ||
20 | === modified file 'src/network/internet_gaming.h' | |||
21 | --- src/network/internet_gaming.h 2019-05-11 22:02:09 +0000 | |||
22 | +++ src/network/internet_gaming.h 2019-05-23 17:11:42 +0000 | |||
23 | @@ -183,6 +183,8 @@ | |||
24 | 183 | bool system, | 183 | bool system, |
25 | 184 | const std::string& msg); | 184 | const std::string& msg); |
26 | 185 | 185 | ||
27 | 186 | bool valid_username(std::string); | ||
28 | 187 | |||
29 | 186 | private: | 188 | private: |
30 | 187 | InternetGaming(); | 189 | InternetGaming(); |
31 | 188 | 190 | ||
32 | 189 | 191 | ||
33 | === modified file 'src/ui_basic/editbox.cc' | |||
34 | --- src/ui_basic/editbox.cc 2019-05-13 02:25:58 +0000 | |||
35 | +++ src/ui_basic/editbox.cc 2019-05-23 17:11:42 +0000 | |||
36 | @@ -19,7 +19,9 @@ | |||
37 | 19 | 19 | ||
38 | 20 | #include "ui_basic/editbox.h" | 20 | #include "ui_basic/editbox.h" |
39 | 21 | 21 | ||
40 | 22 | #include <algorithm> | ||
41 | 22 | #include <limits> | 23 | #include <limits> |
42 | 24 | #include <string> | ||
43 | 23 | 25 | ||
44 | 24 | #include <SDL_keycode.h> | 26 | #include <SDL_keycode.h> |
45 | 25 | #include <boost/format.hpp> | 27 | #include <boost/format.hpp> |
46 | @@ -86,7 +88,8 @@ | |||
47 | 86 | m_(new EditBoxImpl), | 88 | m_(new EditBoxImpl), |
48 | 87 | history_active_(false), | 89 | history_active_(false), |
49 | 88 | history_position_(-1), | 90 | history_position_(-1), |
51 | 89 | warning_(false) { | 91 | password_(false), |
52 | 92 | warning_(false) { | ||
53 | 90 | set_thinks(false); | 93 | set_thinks(false); |
54 | 91 | 94 | ||
55 | 92 | m_->background_style = g_gr->styles().editbox_style(style); | 95 | m_->background_style = g_gr->styles().editbox_style(style); |
56 | @@ -388,7 +391,8 @@ | |||
57 | 388 | const int max_width = get_w() - 2 * kMarginX; | 391 | const int max_width = get_w() - 2 * kMarginX; |
58 | 389 | 392 | ||
59 | 390 | std::shared_ptr<const UI::RenderedText> rendered_text = | 393 | std::shared_ptr<const UI::RenderedText> rendered_text = |
61 | 391 | UI::g_fh->render(as_editorfont(m_->text, m_->fontsize)); | 394 | UI::g_fh->render(as_editorfont(m_->text, m_->fontsize)); |
62 | 395 | |||
63 | 392 | 396 | ||
64 | 393 | const int linewidth = rendered_text->width(); | 397 | const int linewidth = rendered_text->width(); |
65 | 394 | const int lineheight = m_->text.empty() ? text_height(m_->fontsize) : rendered_text->height(); | 398 | const int lineheight = m_->text.empty() ? text_height(m_->fontsize) : rendered_text->height(); |
66 | @@ -400,31 +404,44 @@ | |||
67 | 400 | UI::center_vertically(lineheight, &point); | 404 | UI::center_vertically(lineheight, &point); |
68 | 401 | 405 | ||
69 | 402 | // Crop to max_width while blitting | 406 | // Crop to max_width while blitting |
81 | 403 | if (max_width < linewidth) { | 407 | if (!password_) { |
82 | 404 | // Fix positioning for BiDi languages. | 408 | if (max_width < linewidth) { |
83 | 405 | if (UI::g_fh->fontset()->is_rtl()) { | 409 | // Fix positioning for BiDi languages. |
84 | 406 | point.x = 0.f; | 410 | if (UI::g_fh->fontset()->is_rtl()) { |
85 | 407 | } | 411 | point.x = 0.f; |
86 | 408 | // We want this always on, e.g. for mixed language savegame filenames | 412 | } |
87 | 409 | if (i18n::has_rtl_character(m_->text.c_str(), 100)) { // Restrict check for efficiency | 413 | // We want this always on, e.g. for mixed language savegame filenames |
88 | 410 | // TODO(GunChleoc): Arabic: Fix scrolloffset | 414 | if (i18n::has_rtl_character(m_->text.c_str(), 100)) { // Restrict check for efficiency |
78 | 411 | rendered_text->draw(dst, point, Recti(linewidth - max_width, 0, linewidth, lineheight)); | ||
79 | 412 | } else { | ||
80 | 413 | if (m_->align == UI::Align::kRight) { | ||
89 | 414 | // TODO(GunChleoc): Arabic: Fix scrolloffset | 415 | // TODO(GunChleoc): Arabic: Fix scrolloffset |
92 | 415 | rendered_text->draw( | 416 | rendered_text->draw(dst, point, Recti(linewidth - max_width, 0, linewidth, lineheight)); |
91 | 416 | dst, point, Recti(point.x + m_->scrolloffset + kMarginX, 0, max_width, lineheight)); | ||
93 | 417 | } else { | 417 | } else { |
95 | 418 | rendered_text->draw(dst, point, Recti(-m_->scrolloffset, 0, max_width, lineheight)); | 418 | if (m_->align == UI::Align::kRight) { |
96 | 419 | // TODO(GunChleoc): Arabic: Fix scrolloffset | ||
97 | 420 | rendered_text->draw( | ||
98 | 421 | dst, point, Recti(point.x + m_->scrolloffset + kMarginX, 0, max_width, lineheight)); | ||
99 | 422 | } else { | ||
100 | 423 | rendered_text->draw(dst, point, Recti(-m_->scrolloffset, 0, max_width, lineheight)); | ||
101 | 424 | } | ||
102 | 419 | } | 425 | } |
103 | 426 | } else { | ||
104 | 427 | rendered_text->draw(dst, point, Recti(0, 0, max_width, lineheight)); | ||
105 | 420 | } | 428 | } |
106 | 421 | } else { | 429 | } else { |
108 | 422 | rendered_text->draw(dst, point, Recti(0, 0, max_width, lineheight)); | 430 | std::shared_ptr<const UI::RenderedText> password_text = |
109 | 431 | UI::g_fh->render(as_editorfont(text_to_asterisk(), m_->fontsize)); | ||
110 | 432 | password_text->draw(dst, point, Recti(0, 0, max_width, lineheight)); | ||
111 | 423 | } | 433 | } |
112 | 424 | 434 | ||
113 | 425 | if (has_focus()) { | 435 | if (has_focus()) { |
114 | 426 | // Draw the caret | 436 | // Draw the caret |
116 | 427 | std::string line_to_caret = m_->text.substr(0, m_->caret); | 437 | std::string line_to_caret; |
117 | 438 | |||
118 | 439 | if (password_) { | ||
119 | 440 | line_to_caret = text_to_asterisk().substr(0, m_->caret); | ||
120 | 441 | } else { | ||
121 | 442 | line_to_caret = m_->text.substr(0, m_->caret); | ||
122 | 443 | } | ||
123 | 444 | |||
124 | 428 | // TODO(GunChleoc): Arabic: Fix cursor position for BIDI text. | 445 | // TODO(GunChleoc): Arabic: Fix cursor position for BIDI text. |
125 | 429 | int caret_x = text_width(line_to_caret, m_->fontsize); | 446 | int caret_x = text_width(line_to_caret, m_->fontsize); |
126 | 430 | 447 | ||
127 | @@ -471,4 +488,15 @@ | |||
128 | 471 | m_->scrolloffset = 0; | 488 | m_->scrolloffset = 0; |
129 | 472 | } | 489 | } |
130 | 473 | } | 490 | } |
131 | 491 | |||
132 | 492 | /** | ||
133 | 493 | * Return text as asterisks. | ||
134 | 494 | */ | ||
135 | 495 | std::string EditBox::text_to_asterisk() { | ||
136 | 496 | std::string asterisk; | ||
137 | 497 | for (int i = 0; i < int (m_->text.size()); i++) { | ||
138 | 498 | asterisk.append("*"); | ||
139 | 499 | } | ||
140 | 500 | return asterisk; | ||
141 | 501 | } | ||
142 | 474 | } // namespace UI | 502 | } // namespace UI |
143 | 475 | 503 | ||
144 | === modified file 'src/ui_basic/editbox.h' | |||
145 | --- src/ui_basic/editbox.h 2019-05-11 22:02:09 +0000 | |||
146 | +++ src/ui_basic/editbox.h 2019-05-23 17:11:42 +0000 | |||
147 | @@ -72,18 +72,28 @@ | |||
148 | 72 | 72 | ||
149 | 73 | void draw(RenderTarget&) override; | 73 | void draw(RenderTarget&) override; |
150 | 74 | 74 | ||
151 | 75 | void set_password(bool pass) { | ||
152 | 76 | password_ = pass; | ||
153 | 77 | } | ||
154 | 78 | |||
155 | 75 | void set_warning(bool warn) { | 79 | void set_warning(bool warn) { |
156 | 76 | warning_ = warn; | 80 | warning_ = warn; |
157 | 77 | } | 81 | } |
158 | 78 | 82 | ||
159 | 83 | bool is_password() { | ||
160 | 84 | return password_; | ||
161 | 85 | } | ||
162 | 86 | |||
163 | 79 | private: | 87 | private: |
164 | 80 | std::unique_ptr<EditBoxImpl> m_; | 88 | std::unique_ptr<EditBoxImpl> m_; |
165 | 81 | 89 | ||
166 | 82 | void check_caret(); | 90 | void check_caret(); |
167 | 91 | std::string text_to_asterisk(); | ||
168 | 83 | 92 | ||
169 | 84 | bool history_active_; | 93 | bool history_active_; |
170 | 85 | int16_t history_position_; | 94 | int16_t history_position_; |
171 | 86 | std::string history_[CHAT_HISTORY_SIZE]; | 95 | std::string history_[CHAT_HISTORY_SIZE]; |
172 | 96 | bool password_; | ||
173 | 87 | bool warning_; | 97 | bool warning_; |
174 | 88 | }; | 98 | }; |
175 | 89 | } // namespace UI | 99 | } // namespace UI |
176 | 90 | 100 | ||
177 | === modified file 'src/ui_fsmenu/internet_lobby.cc' | |||
178 | --- src/ui_fsmenu/internet_lobby.cc 2019-05-13 02:25:58 +0000 | |||
179 | +++ src/ui_fsmenu/internet_lobby.cc 2019-05-23 17:11:42 +0000 | |||
180 | @@ -78,7 +78,7 @@ | |||
181 | 78 | hostgame_(this, | 78 | hostgame_(this, |
182 | 79 | "host_game", | 79 | "host_game", |
183 | 80 | get_w() * 17 / 25, | 80 | get_w() * 17 / 25, |
185 | 81 | get_h() * 81 / 100, | 81 | get_h() * 73 / 100, |
186 | 82 | butw_, | 82 | butw_, |
187 | 83 | buth_, | 83 | buth_, |
188 | 84 | UI::ButtonStyle::kFsMenuSecondary, | 84 | UI::ButtonStyle::kFsMenuSecondary, |
189 | @@ -90,7 +90,7 @@ | |||
190 | 90 | butw_, | 90 | butw_, |
191 | 91 | buth_, | 91 | buth_, |
192 | 92 | UI::ButtonStyle::kFsMenuSecondary, | 92 | UI::ButtonStyle::kFsMenuSecondary, |
194 | 93 | _("Back")), | 93 | _("Leave Lobby")), |
195 | 94 | 94 | ||
196 | 95 | // Edit boxes | 95 | // Edit boxes |
197 | 96 | edit_servername_( | 96 | edit_servername_( |
198 | @@ -165,6 +165,7 @@ | |||
199 | 165 | 165 | ||
200 | 166 | // set focus to chat input | 166 | // set focus to chat input |
201 | 167 | chat.focus_edit(); | 167 | chat.focus_edit(); |
202 | 168 | |||
203 | 168 | } | 169 | } |
204 | 169 | 170 | ||
205 | 170 | void FullscreenMenuInternetLobby::layout() { | 171 | void FullscreenMenuInternetLobby::layout() { |
206 | 171 | 172 | ||
207 | === modified file 'src/ui_fsmenu/multiplayer.cc' | |||
208 | --- src/ui_fsmenu/multiplayer.cc 2019-05-11 18:50:30 +0000 | |||
209 | +++ src/ui_fsmenu/multiplayer.cc 2019-05-23 17:11:42 +0000 | |||
210 | @@ -21,7 +21,6 @@ | |||
211 | 21 | 21 | ||
212 | 22 | #include "base/i18n.h" | 22 | #include "base/i18n.h" |
213 | 23 | #include "graphic/text_constants.h" | 23 | #include "graphic/text_constants.h" |
214 | 24 | #include "network/crypto.h" | ||
215 | 25 | #include "network/internet_gaming.h" | 24 | #include "network/internet_gaming.h" |
216 | 26 | #include "profile/profile.h" | 25 | #include "profile/profile.h" |
217 | 27 | #include "random/random.h" | 26 | #include "random/random.h" |
218 | @@ -36,9 +35,10 @@ | |||
219 | 36 | 35 | ||
220 | 37 | // Buttons | 36 | // Buttons |
221 | 38 | metaserver( | 37 | metaserver( |
224 | 39 | &vbox_, "metaserver", 0, 0, butw_, buth_, UI::ButtonStyle::kFsMenuMenu, _("Internet game")), | 38 | &vbox_, "metaserver", 0, 0, butw_, buth_, UI::ButtonStyle::kFsMenuMenu, _("Online Game")), |
223 | 40 | showloginbox(nullptr), | ||
225 | 41 | lan(&vbox_, "lan", 0, 0, butw_, buth_, UI::ButtonStyle::kFsMenuMenu, _("LAN / Direct IP")), | 39 | lan(&vbox_, "lan", 0, 0, butw_, buth_, UI::ButtonStyle::kFsMenuMenu, _("LAN / Direct IP")), |
226 | 40 | showloginbox( | ||
227 | 41 | &vbox_, "lan", 0, 0, butw_, buth_, UI::ButtonStyle::kFsMenuMenu, _("Online Game Settings")), | ||
228 | 42 | back(&vbox_, "back", 0, 0, butw_, buth_, UI::ButtonStyle::kFsMenuMenu, _("Back")) { | 42 | back(&vbox_, "back", 0, 0, butw_, buth_, UI::ButtonStyle::kFsMenuMenu, _("Back")) { |
229 | 43 | metaserver.sigclicked.connect( | 43 | metaserver.sigclicked.connect( |
230 | 44 | boost::bind(&FullscreenMenuMultiPlayer::internet_login, boost::ref(*this))); | 44 | boost::bind(&FullscreenMenuMultiPlayer::internet_login, boost::ref(*this))); |
231 | @@ -47,6 +47,9 @@ | |||
232 | 47 | boost::bind(&FullscreenMenuMultiPlayer::end_modal<FullscreenMenuBase::MenuTarget>, | 47 | boost::bind(&FullscreenMenuMultiPlayer::end_modal<FullscreenMenuBase::MenuTarget>, |
233 | 48 | boost::ref(*this), FullscreenMenuBase::MenuTarget::kLan)); | 48 | boost::ref(*this), FullscreenMenuBase::MenuTarget::kLan)); |
234 | 49 | 49 | ||
235 | 50 | showloginbox.sigclicked.connect( | ||
236 | 51 | boost::bind(&FullscreenMenuMultiPlayer::show_internet_login, boost::ref(*this))); | ||
237 | 52 | |||
238 | 50 | back.sigclicked.connect( | 53 | back.sigclicked.connect( |
239 | 51 | boost::bind(&FullscreenMenuMultiPlayer::end_modal<FullscreenMenuBase::MenuTarget>, | 54 | boost::bind(&FullscreenMenuMultiPlayer::end_modal<FullscreenMenuBase::MenuTarget>, |
240 | 52 | boost::ref(*this), FullscreenMenuBase::MenuTarget::kBack)); | 55 | boost::ref(*this), FullscreenMenuBase::MenuTarget::kBack)); |
241 | @@ -54,73 +57,50 @@ | |||
242 | 54 | title.set_fontsize(fs_big()); | 57 | title.set_fontsize(fs_big()); |
243 | 55 | 58 | ||
244 | 56 | vbox_.add(&metaserver, UI::Box::Resizing::kFullSize); | 59 | vbox_.add(&metaserver, UI::Box::Resizing::kFullSize); |
245 | 60 | vbox_.add(&showloginbox, UI::Box::Resizing::kFullSize); | ||
246 | 61 | vbox_.add_inf_space(); | ||
247 | 57 | vbox_.add(&lan, UI::Box::Resizing::kFullSize); | 62 | vbox_.add(&lan, UI::Box::Resizing::kFullSize); |
248 | 58 | vbox_.add_inf_space(); | 63 | vbox_.add_inf_space(); |
249 | 64 | vbox_.add_inf_space(); | ||
250 | 65 | vbox_.add_inf_space(); | ||
251 | 59 | vbox_.add(&back, UI::Box::Resizing::kFullSize); | 66 | vbox_.add(&back, UI::Box::Resizing::kFullSize); |
252 | 60 | 67 | ||
262 | 61 | Section& s = g_options.pull_section("global"); | 68 | auto_log_ = false; |
254 | 62 | auto_log_ = s.get_bool("auto_log", false); | ||
255 | 63 | if (auto_log_) { | ||
256 | 64 | showloginbox = | ||
257 | 65 | new UI::Button(this, "login_dialog", 0, 0, 0, 0, UI::ButtonStyle::kFsMenuSecondary, | ||
258 | 66 | g_gr->images().get("images/ui_basic/continue.png"), _("Show login dialog")); | ||
259 | 67 | showloginbox->sigclicked.connect( | ||
260 | 68 | boost::bind(&FullscreenMenuMultiPlayer::show_internet_login, boost::ref(*this))); | ||
261 | 69 | } | ||
263 | 70 | layout(); | 69 | layout(); |
264 | 71 | } | 70 | } |
265 | 72 | 71 | ||
267 | 73 | /// called if the showloginbox button was pressed | 72 | /// called if the user is not registered |
268 | 74 | void FullscreenMenuMultiPlayer::show_internet_login() { | 73 | void FullscreenMenuMultiPlayer::show_internet_login() { |
271 | 75 | auto_log_ = false; | 74 | LoginBox lb(*this); |
272 | 76 | internet_login(); | 75 | if (lb.run<UI::Panel::Returncodes>() == UI::Panel::Returncodes::kOk && auto_log_) { |
273 | 76 | auto_log_ = false; | ||
274 | 77 | internet_login(); | ||
275 | 78 | } | ||
276 | 77 | } | 79 | } |
277 | 78 | 80 | ||
278 | 79 | /** | 81 | /** |
289 | 80 | * Called if "Internet" button was pressed. | 82 | * Called if "Online Game" button was pressed. |
290 | 81 | * | 83 | * |
291 | 82 | * IF autologin is not set, a LoginBox is shown and, if the user clicks on | 84 | * IF no nickname or a nickname with invalid characters is set, the Online Game Settings |
292 | 83 | * 'login' in it's menu, the data is read from the LoginBox and saved in 'this' | 85 | * are opened. |
293 | 84 | * so wlapplication can read it. | 86 | * |
294 | 85 | * | 87 | * IF at least a name is set, all data is read from the config file |
295 | 86 | * IF autologin is set, all data is read from the config file and saved. | 88 | * |
296 | 87 | * That data will be used for login to the metaserver. | 89 | * This fullscreen menu ends it's modality. |
287 | 88 | * | ||
288 | 89 | * In both cases this fullscreen menu ends it's modality. | ||
297 | 90 | */ | 90 | */ |
298 | 91 | void FullscreenMenuMultiPlayer::internet_login() { | 91 | void FullscreenMenuMultiPlayer::internet_login() { |
299 | 92 | Section& s = g_options.pull_section("global"); | 92 | Section& s = g_options.pull_section("global"); |
331 | 93 | if (auto_log_) { | 93 | |
332 | 94 | nickname_ = s.get_string("nickname", _("nobody")); | 94 | nickname_ = s.get_string("nickname", ""); |
333 | 95 | password_ = s.get_string("password_sha1", "nobody"); | 95 | password_ = s.get_string("password_sha1", "no_password_set"); |
334 | 96 | register_ = s.get_bool("registered", false); | 96 | register_ = s.get_bool("registered", false); |
335 | 97 | } else { | 97 | |
336 | 98 | LoginBox lb(*this); | 98 | // Checks can be done directly in editbox' by using valid_username(). |
337 | 99 | if (lb.run<UI::Panel::Returncodes>() == UI::Panel::Returncodes::kOk) { | 99 | // This is just to be on the safe side, in case the user changed the password in the config file. |
338 | 100 | nickname_ = lb.get_nickname(); | 100 | if (!InternetGaming::ref().valid_username(nickname_)) { |
339 | 101 | /// NOTE: The password is only stored (in memory and on disk) and transmitted (over the | 101 | auto_log_ = true; |
340 | 102 | /// network | 102 | show_internet_login(); |
341 | 103 | /// to the metaserver) as cryptographic hash. This does NOT mean that the password is | 103 | return; |
311 | 104 | /// stored | ||
312 | 105 | /// securely on the local disk. While the password should be secure while transmitted to | ||
313 | 106 | /// the | ||
314 | 107 | /// metaserver (no-one can use the transmitted data to log in as the user) this is not the | ||
315 | 108 | /// case | ||
316 | 109 | /// for local storage. The stored hash of the password makes it hard to look at the | ||
317 | 110 | /// configuration | ||
318 | 111 | /// file and figure out the plaintext password to, e.g., log in on the forum. However, the | ||
319 | 112 | /// stored hash can be copied to another system and used to log in as the user on the | ||
320 | 113 | /// metaserver. | ||
321 | 114 | // Further note: SHA-1 is considered broken and shouldn't be used anymore. But since the | ||
322 | 115 | // passwords on the server are protected by SHA-1 we have to use it here, too | ||
323 | 116 | password_ = crypto::sha1(lb.get_password()); | ||
324 | 117 | register_ = lb.registered(); | ||
325 | 118 | |||
326 | 119 | s.set_bool("registered", lb.registered()); | ||
327 | 120 | s.set_bool("auto_log", lb.set_automaticlog()); | ||
328 | 121 | } else { | ||
329 | 122 | return; | ||
330 | 123 | } | ||
342 | 124 | } | 104 | } |
343 | 125 | 105 | ||
344 | 126 | // Try to connect to the metaserver | 106 | // Try to connect to the metaserver |
345 | @@ -141,7 +121,8 @@ | |||
346 | 141 | 121 | ||
347 | 142 | // Reset InternetGaming and passwort and show internet login again | 122 | // Reset InternetGaming and passwort and show internet login again |
348 | 143 | InternetGaming::ref().reset(); | 123 | InternetGaming::ref().reset(); |
350 | 144 | s.set_string("password_sha1", ""); | 124 | s.set_string("password_sha1", "no_password_set"); |
351 | 125 | auto_log_ = true; | ||
352 | 145 | show_internet_login(); | 126 | show_internet_login(); |
353 | 146 | } | 127 | } |
354 | 147 | } | 128 | } |
355 | @@ -156,12 +137,8 @@ | |||
356 | 156 | 137 | ||
357 | 157 | title.set_pos(Vector2i(0, title_y_)); | 138 | title.set_pos(Vector2i(0, title_y_)); |
358 | 158 | 139 | ||
359 | 159 | metaserver.set_size(butw_, buth_); | ||
360 | 160 | if (showloginbox) { | ||
361 | 161 | showloginbox->set_pos(Vector2i(box_x_ + butw_ + padding_ / 2, box_y_)); | ||
362 | 162 | showloginbox->set_size(buth_, buth_); | ||
363 | 163 | } | ||
364 | 164 | metaserver.set_desired_size(butw_, buth_); | 140 | metaserver.set_desired_size(butw_, buth_); |
365 | 141 | showloginbox.set_desired_size(butw_, buth_); | ||
366 | 165 | lan.set_desired_size(butw_, buth_); | 142 | lan.set_desired_size(butw_, buth_); |
367 | 166 | back.set_desired_size(butw_, buth_); | 143 | back.set_desired_size(butw_, buth_); |
368 | 167 | 144 | ||
369 | 168 | 145 | ||
370 | === modified file 'src/ui_fsmenu/multiplayer.h' | |||
371 | --- src/ui_fsmenu/multiplayer.h 2019-05-11 18:50:30 +0000 | |||
372 | +++ src/ui_fsmenu/multiplayer.h 2019-05-23 17:11:42 +0000 | |||
373 | @@ -53,15 +53,15 @@ | |||
374 | 53 | 53 | ||
375 | 54 | UI::Textarea title; | 54 | UI::Textarea title; |
376 | 55 | UI::Button metaserver; | 55 | UI::Button metaserver; |
377 | 56 | UI::Button* showloginbox; | ||
378 | 57 | UI::Button lan; | 56 | UI::Button lan; |
379 | 57 | UI::Button showloginbox; | ||
380 | 58 | UI::Button back; | 58 | UI::Button back; |
381 | 59 | 59 | ||
382 | 60 | // Values from internet login window | 60 | // Values from internet login window |
383 | 61 | std::string nickname_; | 61 | std::string nickname_; |
384 | 62 | std::string password_; | 62 | std::string password_; |
385 | 63 | bool auto_log_; | ||
386 | 63 | bool register_; | 64 | bool register_; |
387 | 64 | bool auto_log_; | ||
388 | 65 | }; | 65 | }; |
389 | 66 | 66 | ||
390 | 67 | #endif // end of include guard: WL_UI_FSMENU_MULTIPLAYER_H | 67 | #endif // end of include guard: WL_UI_FSMENU_MULTIPLAYER_H |
391 | 68 | 68 | ||
392 | === modified file 'src/wui/login_box.cc' | |||
393 | --- src/wui/login_box.cc 2019-05-11 18:50:30 +0000 | |||
394 | +++ src/wui/login_box.cc 2019-05-23 17:11:42 +0000 | |||
395 | @@ -21,75 +21,89 @@ | |||
396 | 21 | 21 | ||
397 | 22 | #include "base/i18n.h" | 22 | #include "base/i18n.h" |
398 | 23 | #include "graphic/font_handler.h" | 23 | #include "graphic/font_handler.h" |
399 | 24 | #include "network/crypto.h" | ||
400 | 25 | #include "network/internet_gaming.h" | ||
401 | 24 | #include "profile/profile.h" | 26 | #include "profile/profile.h" |
402 | 25 | #include "ui_basic/button.h" | 27 | #include "ui_basic/button.h" |
403 | 26 | #include "ui_basic/messagebox.h" | 28 | #include "ui_basic/messagebox.h" |
404 | 27 | 29 | ||
405 | 28 | LoginBox::LoginBox(Panel& parent) | 30 | LoginBox::LoginBox(Panel& parent) |
407 | 29 | : Window(&parent, "login_box", 0, 0, 500, 220, _("Metaserver login")) { | 31 | : Window(&parent, "login_box", 0, 0, 500, 280, _("Online Game Settings")) { |
408 | 30 | center_to_parent(); | 32 | center_to_parent(); |
409 | 31 | 33 | ||
410 | 32 | int32_t margin = 10; | 34 | int32_t margin = 10; |
411 | 33 | 35 | ||
412 | 34 | ta_nickname = new UI::Textarea(this, margin, margin, _("Nickname:")); | 36 | ta_nickname = new UI::Textarea(this, margin, margin, _("Nickname:")); |
414 | 35 | ta_password = new UI::Textarea(this, margin, 40, _("Password:")); | 37 | ta_password = new UI::Textarea(this, margin, 70, _("Password:")); |
415 | 36 | eb_nickname = new UI::EditBox(this, 150, margin, 330, 20, 2, UI::PanelStyle::kWui); | 38 | eb_nickname = new UI::EditBox(this, 150, margin, 330, 20, 2, UI::PanelStyle::kWui); |
423 | 37 | eb_password = new UI::EditBox(this, 150, 40, 330, 20, 2, UI::PanelStyle::kWui); | 39 | eb_password = new UI::EditBox(this, 150, 70, 330, 20, 2, UI::PanelStyle::kWui); |
424 | 38 | 40 | ||
425 | 39 | pwd_warning = | 41 | cb_register = new UI::Checkbox(this, Vector2i(margin, 40), _("Log in to a registered account."), |
419 | 40 | new UI::MultilineTextarea(this, margin, 65, 505, 50, UI::PanelStyle::kWui, | ||
420 | 41 | _("WARNING: Password will be shown and saved readable!")); | ||
421 | 42 | |||
422 | 43 | cb_register = new UI::Checkbox(this, Vector2i(margin, 110), _("Log in to a registered account"), | ||
426 | 44 | "", get_inner_w() - 2 * margin); | 42 | "", get_inner_w() - 2 * margin); |
432 | 45 | cb_auto_log = new UI::Checkbox(this, Vector2i(margin, 135), | 43 | |
433 | 46 | _("Automatically use this login information from now on."), "", | 44 | register_account = new UI::MultilineTextarea(this, margin, 105, 470, 140, UI::PanelStyle::kWui, |
434 | 47 | get_inner_w() - 2 * margin); | 45 | (boost::format(_("In order to use a registered " |
435 | 48 | 46 | "account, you need an account on the widelands website. " | |
436 | 49 | UI::Button* loginbtn = new UI::Button( | 47 | "Please log in at %s and set an online " |
437 | 48 | "gaming password on your profile page.")) | ||
438 | 49 | % "\n\nhttps://widelands.org/accounts/register/\n\n").str()); | ||
439 | 50 | |||
440 | 51 | loginbtn = new UI::Button( | ||
441 | 50 | this, "login", | 52 | this, "login", |
442 | 51 | UI::g_fh->fontset()->is_rtl() ? (get_inner_w() / 2 - 200) / 2 : | 53 | UI::g_fh->fontset()->is_rtl() ? (get_inner_w() / 2 - 200) / 2 : |
443 | 52 | (get_inner_w() / 2 - 200) / 2 + get_inner_w() / 2, | 54 | (get_inner_w() / 2 - 200) / 2 + get_inner_w() / 2, |
447 | 53 | get_inner_h() - 20 - margin, 200, 20, UI::ButtonStyle::kWuiPrimary, _("Login")); | 55 | get_inner_h() - 20 - margin, 200, 20, UI::ButtonStyle::kWuiPrimary, _("Save")); |
448 | 54 | loginbtn->sigclicked.connect(boost::bind(&LoginBox::clicked_ok, boost::ref(*this))); | 56 | |
449 | 55 | UI::Button* cancelbtn = new UI::Button( | 57 | cancelbtn = new UI::Button( |
450 | 56 | this, "cancel", | 58 | this, "cancel", |
451 | 57 | UI::g_fh->fontset()->is_rtl() ? (get_inner_w() / 2 - 200) / 2 + get_inner_w() / 2 : | 59 | UI::g_fh->fontset()->is_rtl() ? (get_inner_w() / 2 - 200) / 2 + get_inner_w() / 2 : |
452 | 58 | (get_inner_w() / 2 - 200) / 2, | 60 | (get_inner_w() / 2 - 200) / 2, |
453 | 59 | loginbtn->get_y(), 200, 20, UI::ButtonStyle::kWuiSecondary, _("Cancel")); | 61 | loginbtn->get_y(), 200, 20, UI::ButtonStyle::kWuiSecondary, _("Cancel")); |
454 | 62 | |||
455 | 63 | loginbtn->sigclicked.connect(boost::bind(&LoginBox::clicked_ok, boost::ref(*this))); | ||
456 | 60 | cancelbtn->sigclicked.connect(boost::bind(&LoginBox::clicked_back, boost::ref(*this))); | 64 | cancelbtn->sigclicked.connect(boost::bind(&LoginBox::clicked_back, boost::ref(*this))); |
457 | 65 | eb_nickname->changed.connect(boost::bind(&LoginBox::change_playername, this)); | ||
458 | 66 | cb_register->clickedto.connect(boost::bind(&LoginBox::clicked_register, this)); | ||
459 | 61 | 67 | ||
460 | 62 | Section& s = g_options.pull_section("global"); | 68 | Section& s = g_options.pull_section("global"); |
461 | 63 | eb_nickname->set_text(s.get_string("nickname", _("nobody"))); | 69 | eb_nickname->set_text(s.get_string("nickname", _("nobody"))); |
462 | 64 | cb_register->set_state(s.get_bool("registered", false)); | 70 | cb_register->set_state(s.get_bool("registered", false)); |
463 | 71 | eb_password->set_password(true); | ||
464 | 72 | |||
465 | 73 | if (registered()) { | ||
466 | 74 | eb_password->set_text(s.get_string("password_sha1", "")); | ||
467 | 75 | loginbtn->set_enabled(false); | ||
468 | 76 | } else { | ||
469 | 77 | eb_password->set_can_focus(false); | ||
470 | 78 | ta_password->set_color(UI_FONT_CLR_DISABLED); | ||
471 | 79 | } | ||
472 | 80 | |||
473 | 65 | eb_nickname->focus(); | 81 | eb_nickname->focus(); |
474 | 82 | |||
475 | 83 | } | ||
476 | 84 | |||
477 | 85 | /// think function of the UI (main loop) | ||
478 | 86 | void LoginBox::think() { | ||
479 | 87 | verify_input(); | ||
480 | 66 | } | 88 | } |
481 | 67 | 89 | ||
482 | 68 | /** | 90 | /** |
483 | 69 | * called, if "login" is pressed. | 91 | * called, if "login" is pressed. |
484 | 70 | */ | 92 | */ |
485 | 71 | void LoginBox::clicked_ok() { | 93 | void LoginBox::clicked_ok() { |
507 | 72 | // Check if all needed input fields are valid | 94 | Section& s = g_options.pull_section("global"); |
508 | 73 | if (eb_nickname->text().empty()) { | 95 | if (cb_register->get_state()) { |
509 | 74 | UI::WLMessageBox mb( | 96 | if (check_password()) { |
510 | 75 | this, _("Empty Nickname"), _("Please enter a nickname!"), UI::WLMessageBox::MBoxType::kOk); | 97 | s.set_string("nickname", eb_nickname->text()); |
511 | 76 | mb.run<UI::Panel::Returncodes>(); | 98 | s.set_bool("registered", true); |
512 | 77 | return; | 99 | end_modal<UI::Panel::Returncodes>(UI::Panel::Returncodes::kOk); |
513 | 78 | } | 100 | } |
514 | 79 | if (eb_nickname->text().find(' ') <= eb_nickname->text().size()) { | 101 | } else { |
515 | 80 | UI::WLMessageBox mb(this, _("Space in Nickname"), | 102 | s.set_string("nickname", eb_nickname->text()); |
516 | 81 | _("Sorry, but spaces are not allowed in nicknames!"), | 103 | s.set_bool("registered", false); |
517 | 82 | UI::WLMessageBox::MBoxType::kOk); | 104 | s.set_string("password_sha1", ""); |
518 | 83 | mb.run<UI::Panel::Returncodes>(); | 105 | end_modal<UI::Panel::Returncodes>(UI::Panel::Returncodes::kOk); |
519 | 84 | return; | 106 | } |
499 | 85 | } | ||
500 | 86 | if (eb_password->text().empty() && cb_register->get_state()) { | ||
501 | 87 | UI::WLMessageBox mb(this, _("Empty Password"), _("Please enter your password!"), | ||
502 | 88 | UI::WLMessageBox::MBoxType::kOk); | ||
503 | 89 | mb.run<UI::Panel::Returncodes>(); | ||
504 | 90 | return; | ||
505 | 91 | } | ||
506 | 92 | end_modal<UI::Panel::Returncodes>(UI::Panel::Returncodes::kOk); | ||
520 | 93 | } | 107 | } |
521 | 94 | 108 | ||
522 | 95 | /// Called if "cancel" was pressed | 109 | /// Called if "cancel" was pressed |
523 | @@ -97,6 +111,13 @@ | |||
524 | 97 | end_modal<UI::Panel::Returncodes>(UI::Panel::Returncodes::kBack); | 111 | end_modal<UI::Panel::Returncodes>(UI::Panel::Returncodes::kBack); |
525 | 98 | } | 112 | } |
526 | 99 | 113 | ||
527 | 114 | /// Called when nickname was changed | ||
528 | 115 | void LoginBox::change_playername() { | ||
529 | 116 | cb_register->set_state(false); | ||
530 | 117 | eb_password->set_can_focus(false); | ||
531 | 118 | eb_password->set_text(""); | ||
532 | 119 | } | ||
533 | 120 | |||
534 | 100 | bool LoginBox::handle_key(bool down, SDL_Keysym code) { | 121 | bool LoginBox::handle_key(bool down, SDL_Keysym code) { |
535 | 101 | if (down) { | 122 | if (down) { |
536 | 102 | switch (code.sym) { | 123 | switch (code.sym) { |
537 | @@ -113,3 +134,80 @@ | |||
538 | 113 | } | 134 | } |
539 | 114 | return UI::Panel::handle_key(down, code); | 135 | return UI::Panel::handle_key(down, code); |
540 | 115 | } | 136 | } |
541 | 137 | |||
542 | 138 | void LoginBox::clicked_register() { | ||
543 | 139 | if (cb_register->get_state()) { | ||
544 | 140 | ta_password->set_color(UI_FONT_CLR_DISABLED); | ||
545 | 141 | eb_password->set_can_focus(false); | ||
546 | 142 | eb_password->set_text(""); | ||
547 | 143 | } else { | ||
548 | 144 | ta_password->set_color(UI_FONT_CLR_FG); | ||
549 | 145 | eb_password->set_can_focus(true); | ||
550 | 146 | } | ||
551 | 147 | } | ||
552 | 148 | |||
553 | 149 | void LoginBox::verify_input() { | ||
554 | 150 | // Check if all neccessary input fields are valid | ||
555 | 151 | loginbtn->set_enabled(true); | ||
556 | 152 | eb_nickname->set_tooltip(""); | ||
557 | 153 | eb_password->set_tooltip(""); | ||
558 | 154 | eb_nickname->set_warning(false); | ||
559 | 155 | |||
560 | 156 | if (eb_nickname->text().empty()) { | ||
561 | 157 | eb_nickname->set_warning(true); | ||
562 | 158 | eb_nickname->set_tooltip(_("Please enter a nickname!")); | ||
563 | 159 | loginbtn->set_enabled(false); | ||
564 | 160 | } else if (!InternetGaming::ref().valid_username(eb_nickname->text())) { | ||
565 | 161 | eb_nickname->set_warning(true); | ||
566 | 162 | eb_nickname->set_tooltip(_("Enter a valid nickname. This value may contain only " | ||
567 | 163 | "English letters, numbers, and @ . + - _ characters.")); | ||
568 | 164 | loginbtn->set_enabled(false); | ||
569 | 165 | } | ||
570 | 166 | |||
571 | 167 | if (eb_password->text().empty() && cb_register->get_state()) { | ||
572 | 168 | eb_password->set_tooltip(_("Please enter your password!")); | ||
573 | 169 | loginbtn->set_enabled(false); | ||
574 | 170 | eb_password->focus(); | ||
575 | 171 | } | ||
576 | 172 | |||
577 | 173 | Section& s = g_options.pull_section("global"); | ||
578 | 174 | if (eb_password->has_focus() && eb_password->text() == s.get_string("password_sha1", "")) { | ||
579 | 175 | eb_password->set_text(""); | ||
580 | 176 | } | ||
581 | 177 | |||
582 | 178 | if (cb_register->get_state() && eb_password->text() == s.get_string("password_sha1", "")) { | ||
583 | 179 | loginbtn->set_enabled(false); | ||
584 | 180 | } | ||
585 | 181 | } | ||
586 | 182 | |||
587 | 183 | /// Check password against metaserver | ||
588 | 184 | bool LoginBox::check_password() { | ||
589 | 185 | // Try to connect to the metaserver | ||
590 | 186 | Section& s = g_options.pull_section("global"); | ||
591 | 187 | const std::string& meta = s.get_string("metaserver", INTERNET_GAMING_METASERVER.c_str()); | ||
592 | 188 | uint32_t port = s.get_natural("metaserverport", kInternetGamingPort); | ||
593 | 189 | std::string password = crypto::sha1(eb_password->text()); | ||
594 | 190 | InternetGaming::ref().login(get_nickname(), password, true, meta, port); | ||
595 | 191 | |||
596 | 192 | if (!InternetGaming::ref().logged_in()) { | ||
597 | 193 | // something went wrong -> show the error message | ||
598 | 194 | // idealy it is about the wrong password | ||
599 | 195 | ChatMessage msg = InternetGaming::ref().get_messages().back(); | ||
600 | 196 | UI::WLMessageBox wmb(this, _("Error!"), msg.msg, UI::WLMessageBox::MBoxType::kOk); | ||
601 | 197 | wmb.run<UI::Panel::Returncodes>(); | ||
602 | 198 | InternetGaming::ref().reset(); | ||
603 | 199 | eb_password->set_text(""); | ||
604 | 200 | eb_password->focus(); | ||
605 | 201 | return false; | ||
606 | 202 | } | ||
607 | 203 | // NOTE: The password is only stored (in memory and on disk) and transmitted (over the network to the metaserver) as cryptographic hash. | ||
608 | 204 | // This does NOT mean that the password is stored securely on the local disk. | ||
609 | 205 | // While the password should be secure while transmitted to the metaserver (no-one can use the transmitted data to log in as the user) this is not the case for local storage. | ||
610 | 206 | // The stored hash of the password makes it hard to look at the configuration file and figure out the plaintext password to, e.g., log in on the forum. | ||
611 | 207 | // However, the stored hash can be copied to another system and used to log in as the user on the metaserver. | ||
612 | 208 | // Further note: SHA-1 is considered broken and shouldn't be used anymore. But since the | ||
613 | 209 | // passwords on the server are protected by SHA-1 we have to use it here, too | ||
614 | 210 | s.set_string("password_sha1", password); | ||
615 | 211 | InternetGaming::ref().logout(); | ||
616 | 212 | return true; | ||
617 | 213 | } | ||
618 | 116 | 214 | ||
619 | === modified file 'src/wui/login_box.h' | |||
620 | --- src/wui/login_box.h 2019-05-11 18:50:30 +0000 | |||
621 | +++ src/wui/login_box.h 2019-05-23 17:11:42 +0000 | |||
622 | @@ -29,6 +29,8 @@ | |||
623 | 29 | struct LoginBox : public UI::Window { | 29 | struct LoginBox : public UI::Window { |
624 | 30 | explicit LoginBox(UI::Panel&); | 30 | explicit LoginBox(UI::Panel&); |
625 | 31 | 31 | ||
626 | 32 | void think() override; | ||
627 | 33 | |||
628 | 32 | std::string get_nickname() { | 34 | std::string get_nickname() { |
629 | 33 | return eb_nickname->text(); | 35 | return eb_nickname->text(); |
630 | 34 | } | 36 | } |
631 | @@ -38,24 +40,26 @@ | |||
632 | 38 | bool registered() { | 40 | bool registered() { |
633 | 39 | return cb_register->get_state(); | 41 | return cb_register->get_state(); |
634 | 40 | } | 42 | } |
635 | 41 | bool set_automaticlog() { | ||
636 | 42 | return cb_auto_log->get_state(); | ||
637 | 43 | } | ||
638 | 44 | 43 | ||
639 | 45 | /// Handle keypresses | 44 | /// Handle keypresses |
640 | 46 | bool handle_key(bool down, SDL_Keysym code) override; | 45 | bool handle_key(bool down, SDL_Keysym code) override; |
641 | 47 | 46 | ||
642 | 48 | private: | 47 | private: |
643 | 48 | void change_playername(); | ||
644 | 49 | void clicked_back(); | 49 | void clicked_back(); |
645 | 50 | void clicked_ok(); | 50 | void clicked_ok(); |
646 | 51 | void clicked_register(); | ||
647 | 52 | void verify_input(); | ||
648 | 53 | bool check_password(); | ||
649 | 51 | 54 | ||
650 | 55 | UI::Button* loginbtn; | ||
651 | 56 | UI::Button* cancelbtn; | ||
652 | 52 | UI::EditBox* eb_nickname; | 57 | UI::EditBox* eb_nickname; |
653 | 53 | UI::EditBox* eb_password; | 58 | UI::EditBox* eb_password; |
654 | 54 | UI::Checkbox* cb_register; | 59 | UI::Checkbox* cb_register; |
655 | 55 | UI::Checkbox* cb_auto_log; | ||
656 | 56 | UI::Textarea* ta_nickname; | 60 | UI::Textarea* ta_nickname; |
657 | 57 | UI::Textarea* ta_password; | 61 | UI::Textarea* ta_password; |
659 | 58 | UI::MultilineTextarea* pwd_warning; | 62 | UI::MultilineTextarea* register_account; |
660 | 59 | }; | 63 | }; |
661 | 60 | 64 | ||
662 | 61 | #endif // end of include guard: WL_WUI_LOGIN_BOX_H | 65 | #endif // end of include guard: WL_WUI_LOGIN_BOX_H |
It would be good to have the registered checkbox above the password field. It would be a more logical ordering, imho.