[cstdstring] demise Format, replacing with StringUtils::Format
[vuplus_xbmc] / xbmc / dialogs / GUIDialogGamepad.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "GUIDialogGamepad.h"
22 #include "utils/md5.h"
23 #include "utils/StringUtils.h"
24 #include "guilib/GUIAudioManager.h"
25 #include "guilib/GUIWindowManager.h"
26 #include "GUIDialogOK.h"
27 #include "utils/StringUtils.h"
28 #include "guilib/Key.h"
29 #include "guilib/LocalizeStrings.h"
30
31 CGUIDialogGamepad::CGUIDialogGamepad(void)
32     : CGUIDialogBoxBase(WINDOW_DIALOG_GAMEPAD, "DialogGamepad.xml")
33 {
34   m_bCanceled = false;
35   m_strUserInput = "";
36   m_strPassword = "";
37   m_iRetries = 0;
38   m_bUserInputCleanup = true;
39 }
40
41 CGUIDialogGamepad::~CGUIDialogGamepad(void)
42 {}
43
44 bool CGUIDialogGamepad::OnAction(const CAction &action)
45 {
46   if ((action.GetButtonCode() >= KEY_BUTTON_A &&
47        action.GetButtonCode() <= KEY_BUTTON_RIGHT_TRIGGER) ||
48       (action.GetButtonCode() >= KEY_BUTTON_DPAD_UP &&
49        action.GetButtonCode() <= KEY_BUTTON_DPAD_RIGHT) ||
50       (action.GetID() >= ACTION_MOVE_LEFT &&
51        action.GetID() <= ACTION_MOVE_DOWN) ||
52       action.GetID() == ACTION_PLAYER_PLAY
53      )
54   {
55     switch (action.GetButtonCode())
56     {
57     case KEY_BUTTON_A : m_strUserInput += "A"; break;
58     case KEY_BUTTON_B : m_strUserInput += "B"; break;
59     case KEY_BUTTON_X : m_strUserInput += "X"; break;
60     case KEY_BUTTON_Y : m_strUserInput += "Y"; break;
61     case KEY_BUTTON_BLACK : m_strUserInput += "K"; break;
62     case KEY_BUTTON_WHITE : m_strUserInput += "W"; break;
63     case KEY_BUTTON_LEFT_TRIGGER : m_strUserInput += "("; break;
64     case KEY_BUTTON_RIGHT_TRIGGER : m_strUserInput += ")"; break;
65     case KEY_BUTTON_DPAD_UP : m_strUserInput += "U"; break;
66     case KEY_BUTTON_DPAD_DOWN : m_strUserInput += "D"; break;
67     case KEY_BUTTON_DPAD_LEFT : m_strUserInput += "L"; break;
68     case KEY_BUTTON_DPAD_RIGHT : m_strUserInput += "R"; break;
69     default:
70       switch (action.GetID())
71       {
72         case ACTION_MOVE_LEFT:   m_strUserInput += "L"; break;
73         case ACTION_MOVE_RIGHT:  m_strUserInput += "R"; break;
74         case ACTION_MOVE_UP:     m_strUserInput += "U"; break;
75         case ACTION_MOVE_DOWN:   m_strUserInput += "D"; break;
76         case ACTION_PLAYER_PLAY: m_strUserInput += "P"; break;
77         default:
78           return true;
79       }
80       break;
81     }
82
83     CStdString strHiddenInput(m_strUserInput);
84     for (int i = 0; i < (int)strHiddenInput.size(); i++)
85     {
86       strHiddenInput[i] = m_cHideInputChar;
87     }
88     SetLine(2, strHiddenInput);
89     return true;
90   }
91   else if (action.GetButtonCode() == KEY_BUTTON_BACK || action.GetID() == ACTION_PREVIOUS_MENU || action.GetID() == ACTION_NAV_BACK)
92   {
93     m_bConfirmed = false;
94     m_bCanceled = true;
95     m_strUserInput = "";
96     m_bHideInputChars = true;
97     Close();
98     return true;
99   }
100   else if (action.GetButtonCode() == KEY_BUTTON_START || action.GetID() == ACTION_SELECT_ITEM)
101   {
102     m_bConfirmed = false;
103     m_bCanceled = false;
104
105     CStdString md5pword2;
106     XBMC::XBMC_MD5 md5state;
107     md5state.append(m_strUserInput);
108     md5state.getDigest(md5pword2);
109
110     if (!m_strPassword.Equals(md5pword2))
111     {
112       // incorrect password entered
113       m_iRetries--;
114
115       // don't clean up if the calling code wants the bad user input
116       if (m_bUserInputCleanup)
117         m_strUserInput = "";
118       else
119         m_bUserInputCleanup = true;
120
121       m_bHideInputChars = true;
122       Close();
123       return true;
124     }
125
126     // correct password entered
127     m_bConfirmed = true;
128     m_iRetries = 0;
129     m_strUserInput = "";
130     m_bHideInputChars = true;
131     Close();
132     return true;
133   }
134   else if (action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9)
135   {
136     return true; // unhandled
137   }
138   else
139   {
140     return CGUIDialog::OnAction(action);
141   }
142 }
143
144 bool CGUIDialogGamepad::OnMessage(CGUIMessage& message)
145 {
146   switch ( message.GetMessage() )
147   {
148   case GUI_MSG_WINDOW_INIT:
149     {
150       m_bConfirmed = false;
151       m_bCanceled = false;
152       m_cHideInputChar = g_localizeStrings.Get(12322).c_str()[0];
153       CGUIDialog::OnMessage(message);
154       return true;
155     }
156     break;
157
158   case GUI_MSG_CLICKED:
159     {
160       m_bConfirmed = false;
161       m_bCanceled = false;
162     }
163     break;
164   }
165   return CGUIDialogBoxBase::OnMessage(message);
166 }
167
168 // \brief Show gamepad keypad and replace aTextString with user input.
169 // \param aTextString String to preload into the keyboard accumulator. Overwritten with user input if return=true.
170 // \param dlgHeading String shown on dialog title. Converts to localized string if contains a positive integer.
171 // \param bHideUserInput Masks user input as asterisks if set as true.  Currently not yet implemented.
172 // \return true if successful display and user input. false if unsucessful display, no user input, or canceled editing.
173 bool CGUIDialogGamepad::ShowAndGetInput(CStdString& aTextString, const CStdString &dlgHeading, bool bHideUserInput)
174 {
175   // Prompt user for input
176   CStdString strUserInput = "";
177   if (ShowAndVerifyInput(strUserInput, dlgHeading, aTextString, "", "", true, bHideUserInput))
178   {
179     // user entry was blank
180     return false;
181   }
182
183   if (strUserInput.IsEmpty())
184     // user canceled out
185     return false;
186
187
188   // We should have a string to return
189   aTextString = strUserInput;
190   return true;
191 }
192
193 // \brief Show gamepad keypad twice to get and confirm a user-entered password string.
194 // \param strNewPassword String to preload into the keyboard accumulator. Overwritten with user input if return=true.
195 // \return true if successful display and user input entry/re-entry. false if unsucessful display, no user input, or canceled editing.
196 bool CGUIDialogGamepad::ShowAndVerifyNewPassword(CStdString& strNewPassword)
197 {
198   // Prompt user for password input
199   CStdString strUserInput = "";
200   if (ShowAndVerifyInput(strUserInput, "12340", "12330", "12331", "", true, true))
201   {
202     // TODO: Show error to user saying the password entry was blank
203     CGUIDialogOK::ShowAndGetInput(12357, 12358, 0, 0); // Password is empty/blank
204     return false;
205   }
206
207   if (strUserInput.IsEmpty())
208     // user canceled out
209     return false;
210
211   // Prompt again for password input, this time sending previous input as the password to verify
212   if (!ShowAndVerifyInput(strUserInput, "12341", "12330", "12331", "", false, true))
213   {
214     // TODO: Show error to user saying the password re-entry failed
215     CGUIDialogOK::ShowAndGetInput(12357, 12344, 0, 0); // Password do not match
216     return false;
217   }
218
219   // password entry and re-entry succeeded
220   strNewPassword = strUserInput;
221   return true;
222 }
223
224 // \brief Show gamepad keypad and verify user input against strPassword.
225 // \param strPassword Value to compare against user input.
226 // \param dlgHeading String shown on dialog title. Converts to localized string if contains a positive integer.
227 // \param iRetries If greater than 0, shows "Incorrect password, %d retries left" on dialog line 2, else line 2 is blank.
228 // \return 0 if successful display and user input. 1 if unsucessful input. -1 if no user input or canceled editing.
229 int CGUIDialogGamepad::ShowAndVerifyPassword(CStdString& strPassword, const CStdString& dlgHeading, int iRetries)
230 {
231   CStdString strLine2 = "";
232   if (0 < iRetries)
233   {
234     // Show a string telling user they have iRetries retries left
235     strLine2 = StringUtils::Format("%s %i %s", g_localizeStrings.Get(12342).c_str(), iRetries, g_localizeStrings.Get(12343).c_str());
236   }
237
238   // make a copy of strPassword to prevent from overwriting it later
239   CStdString strPassTemp = strPassword;
240   if (ShowAndVerifyInput(strPassTemp, dlgHeading, g_localizeStrings.Get(12330), g_localizeStrings.Get(12331), strLine2, true, true))
241   {
242     // user entered correct password
243     return 0;
244   }
245
246   if (strPassTemp.IsEmpty())
247     // user canceled out
248     return -1;
249
250   // user must have entered an incorrect password
251   return 1;
252 }
253
254 // \brief Show gamepad keypad and verify user input against strToVerify.
255 // \param strToVerify Value to compare against user input.
256 // \param dlgHeading String shown on dialog title. Converts to localized string if contains a positive integer.
257 // \param dlgLine0 String shown on dialog line 0. Converts to localized string if contains a positive integer.
258 // \param dlgLine1 String shown on dialog line 1. Converts to localized string if contains a positive integer.
259 // \param dlgLine2 String shown on dialog line 2. Converts to localized string if contains a positive integer.
260 // \param bGetUserInput If set as true and return=true, strToVerify is overwritten with user input string.
261 // \param bHideInputChars Masks user input as asterisks if set as true.  Currently not yet implemented.
262 // \return true if successful display and user input. false if unsucessful display, no user input, or canceled editing.
263 bool CGUIDialogGamepad::ShowAndVerifyInput(CStdString& strToVerify, const CStdString& dlgHeading,
264     const CStdString& dlgLine0, const CStdString& dlgLine1,
265     const CStdString& dlgLine2, bool bGetUserInput, bool bHideInputChars)
266 {
267   // Prompt user for password input
268   CGUIDialogGamepad *pDialog = (CGUIDialogGamepad *)g_windowManager.GetWindow(WINDOW_DIALOG_GAMEPAD);
269   pDialog->m_strPassword = strToVerify;
270   pDialog->m_bUserInputCleanup = !bGetUserInput;
271   pDialog->m_bHideInputChars = bHideInputChars;
272
273   // HACK: This won't work if the label specified is actually a positive numeric value, but that's very unlikely
274   if (!StringUtils::IsNaturalNumber(dlgHeading))
275     pDialog->SetHeading( dlgHeading );
276   else
277     pDialog->SetHeading( atoi(dlgHeading.c_str()) );
278
279   if (!StringUtils::IsNaturalNumber(dlgLine0))
280     pDialog->SetLine( 0, dlgLine0 );
281   else
282     pDialog->SetLine( 0, atoi(dlgLine0.c_str()) );
283
284   if (!StringUtils::IsNaturalNumber(dlgLine1))
285     pDialog->SetLine( 1, dlgLine1 );
286   else
287     pDialog->SetLine( 1, atoi(dlgLine1.c_str()) );
288
289   if (!StringUtils::IsNaturalNumber(dlgLine2))
290     pDialog->SetLine( 2, dlgLine2 );
291   else
292     pDialog->SetLine( 2, atoi(dlgLine2.c_str()) );
293
294   g_audioManager.Enable(false); // dont do sounds during pwd input
295   pDialog->DoModal();
296   g_audioManager.Enable(true);
297
298   if (bGetUserInput && !pDialog->IsCanceled())
299   {
300     XBMC::XBMC_MD5 md5state;
301     md5state.append(pDialog->m_strUserInput);
302     md5state.getDigest(strToVerify);
303     strToVerify.ToLower();
304     pDialog->m_strUserInput = "";
305   }
306
307   if (!pDialog->IsConfirmed() || pDialog->IsCanceled())
308   {
309     // user canceled out or entered an incorrect password
310     return false;
311   }
312
313   // user entered correct password
314   return true;
315 }
316
317 bool CGUIDialogGamepad::IsCanceled() const
318 {
319   return m_bCanceled;
320 }
321