[droid] splash: adjust progressbar color
[vuplus_xbmc] / xbmc / GUIPassword.cpp
1 /*
2  *      Copyright (C) 2005-2012 Team XBMC
3  *      http://www.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 "GUIPassword.h"
22 #include "GUIUserMessages.h"
23 #include "ApplicationMessenger.h"
24 #include "dialogs/GUIDialogGamepad.h"
25 #include "guilib/GUIKeyboardFactory.h"
26 #include "dialogs/GUIDialogNumeric.h"
27 #include "dialogs/GUIDialogOK.h"
28 #include "settings/GUIDialogLockSettings.h"
29 #include "settings/GUIDialogProfileSettings.h"
30 #include "Util.h"
31 #include "settings/Settings.h"
32 #include "settings/GUISettings.h"
33 #include "guilib/GUIWindowManager.h"
34 #include "FileItem.h"
35 #include "guilib/LocalizeStrings.h"
36 #include "utils/log.h"
37
38 CGUIPassword::CGUIPassword(void)
39 {
40   iMasterLockRetriesLeft = -1;
41   bMasterUser = false;
42 }
43 CGUIPassword::~CGUIPassword(void)
44 {}
45
46 bool CGUIPassword::IsItemUnlocked(CFileItem* pItem, const CStdString &strType)
47 {
48   // \brief Tests if the user is allowed to access the share folder
49   // \param pItem The share folder item to access
50   // \param strType The type of share being accessed, e.g. "music", "video", etc. See CSettings::UpdateSources()
51   // \return If access is granted, returns \e true
52   if (g_settings.GetMasterProfile().getLockMode() == LOCK_MODE_EVERYONE)
53     return true;
54
55   while (pItem->m_iHasLock > 1)
56   {
57     CStdString strLockCode = pItem->m_strLockCode;
58     CStdString strLabel = pItem->GetLabel();
59     int iResult = 0;  // init to user succeeded state, doing this to optimize switch statement below
60     char buffer[33]; // holds 32 places plus sign character
61     if(g_passwordManager.bMasterUser)// Check if we are the MasterUser!
62     {
63       iResult = 0;
64     }
65     else
66     {
67       if (0 != g_guiSettings.GetInt("masterlock.maxretries") && pItem->m_iBadPwdCount >= g_guiSettings.GetInt("masterlock.maxretries"))
68       { // user previously exhausted all retries, show access denied error
69         CGUIDialogOK::ShowAndGetInput(12345, 12346, 0, 0);
70         return false;
71       }
72       // show the appropriate lock dialog
73       CStdString strHeading = "";
74       if (pItem->m_bIsFolder)
75         strHeading = g_localizeStrings.Get(12325);
76       else
77         strHeading = g_localizeStrings.Get(12348);
78
79       iResult = VerifyPassword(pItem->m_iLockMode, strLockCode, strHeading);
80     }
81     switch (iResult)
82     {
83     case -1:
84       { // user canceled out
85         return false;
86         break;
87       }
88     case 0:
89       {
90         // password entry succeeded
91         pItem->m_iBadPwdCount = 0;
92         pItem->m_iHasLock = 1;
93         g_passwordManager.LockSource(strType,strLabel,false);
94         sprintf(buffer,"%i",pItem->m_iBadPwdCount);
95         g_settings.UpdateSource(strType, strLabel, "badpwdcount", buffer);
96         g_settings.SaveSources();
97         break;
98       }
99     case 1:
100       {
101         // password entry failed
102         if (0 != g_guiSettings.GetInt("masterlock.maxretries"))
103           pItem->m_iBadPwdCount++;
104         sprintf(buffer,"%i",pItem->m_iBadPwdCount);
105         g_settings.UpdateSource(strType, strLabel, "badpwdcount", buffer);
106         g_settings.SaveSources();
107         break;
108       }
109     default:
110       {
111         // this should never happen, but if it does, do nothing
112         return false;
113         break;
114       }
115     }
116   }
117   return true;
118 }
119
120 bool CGUIPassword::CheckStartUpLock()
121 {
122   // prompt user for mastercode if the mastercode was set b4 or by xml
123   int iVerifyPasswordResult = -1;
124   CStdString strHeader = g_localizeStrings.Get(20075);
125   if (iMasterLockRetriesLeft == -1)
126     iMasterLockRetriesLeft = g_guiSettings.GetInt("masterlock.maxretries");
127   if (g_passwordManager.iMasterLockRetriesLeft == 0) g_passwordManager.iMasterLockRetriesLeft = 1;
128   CStdString strPassword = g_settings.GetMasterProfile().getLockCode();
129   if (g_settings.GetMasterProfile().getLockMode() == 0)
130     iVerifyPasswordResult = 0;
131   else
132   {
133     for (int i=1; i <= g_passwordManager.iMasterLockRetriesLeft; i++)
134     {
135       iVerifyPasswordResult = VerifyPassword(g_settings.GetMasterProfile().getLockMode(), strPassword, strHeader);
136       if (iVerifyPasswordResult != 0 )
137       {
138         CStdString strLabel,strLabel1;
139         strLabel1 = g_localizeStrings.Get(12343);
140         int iLeft = g_passwordManager.iMasterLockRetriesLeft-i;
141         strLabel.Format("%i %s",iLeft,strLabel1.c_str());
142
143         // PopUp OK and Display: MasterLock mode has changed but no no Mastercode has been set!
144         CGUIDialogOK::ShowAndGetInput(20076, 12367, 12368, strLabel);
145       }
146       else
147         i=g_passwordManager.iMasterLockRetriesLeft;
148     }
149   }
150
151   if (iVerifyPasswordResult == 0)
152   {
153     g_passwordManager.iMasterLockRetriesLeft = g_guiSettings.GetInt("masterlock.maxretries");
154     return true;  // OK The MasterCode Accepted! XBMC Can Run!
155   }
156   else
157   {
158     CApplicationMessenger::Get().Shutdown(); // Turn off the box
159     return false;
160   }
161 }
162
163 bool CGUIPassword::SetMasterLockMode(bool bDetails)
164 {
165   CProfile* profile = g_settings.GetProfile(0);
166   if (profile)
167   {
168     CProfile::CLock locks = profile->GetLocks();
169     if (CGUIDialogLockSettings::ShowAndGetLock(locks, 12360, true, bDetails))
170     {
171       profile->SetLocks(locks);
172       return true;
173     }
174   }
175   return false;
176 }
177
178 bool CGUIPassword::IsProfileLockUnlocked(int iProfile)
179 {
180   bool bDummy;
181   return IsProfileLockUnlocked(iProfile,bDummy,true);
182 }
183
184 bool CGUIPassword::IsProfileLockUnlocked(int iProfile, bool& bCanceled, bool prompt)
185 {
186   if (g_passwordManager.bMasterUser)
187     return true;
188   int iProfileToCheck=iProfile;
189   if (iProfile == -1)
190     iProfileToCheck = g_settings.GetCurrentProfileIndex();
191   if (iProfileToCheck == 0)
192     return IsMasterLockUnlocked(prompt,bCanceled);
193   else
194   {
195     CProfile *profile = g_settings.GetProfile(iProfileToCheck);
196     if (!profile)
197       return false;
198
199     if (!prompt)
200       return (profile->getLockMode() == LOCK_MODE_EVERYONE);
201
202     if (profile->getDate().IsEmpty() &&
203        (g_settings.GetMasterProfile().getLockMode() == LOCK_MODE_EVERYONE ||
204         profile->getLockMode() == LOCK_MODE_EVERYONE))
205     {
206       // user hasn't set a password and this is the first time they've used this account
207       // so prompt for password/settings
208       if (CGUIDialogProfileSettings::ShowForProfile(iProfileToCheck, true))
209         return true;
210     }
211     else
212        if (g_settings.GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE)
213         return CheckLock(profile->getLockMode(),profile->getLockCode(),20095,bCanceled);
214   }
215
216   return true;
217 }
218
219 bool CGUIPassword::IsMasterLockUnlocked(bool bPromptUser)
220 {
221   bool bDummy;
222   return IsMasterLockUnlocked(bPromptUser,bDummy);
223 }
224
225 bool CGUIPassword::IsMasterLockUnlocked(bool bPromptUser, bool& bCanceled)
226 {
227   bCanceled = false;
228   if (iMasterLockRetriesLeft == -1)
229     iMasterLockRetriesLeft = g_guiSettings.GetInt("masterlock.maxretries");
230   if ((LOCK_MODE_EVERYONE < g_settings.GetMasterProfile().getLockMode() && !bMasterUser) && !bPromptUser)
231     // not unlocked, but calling code doesn't want to prompt user
232     return false;
233
234   if (g_passwordManager.bMasterUser || g_settings.GetMasterProfile().getLockMode() == LOCK_MODE_EVERYONE)
235     return true;
236
237   if (iMasterLockRetriesLeft == 0)
238   {
239     UpdateMasterLockRetryCount(false);
240     return false;
241   }
242
243   // no, unlock since we are allowed to prompt
244   int iVerifyPasswordResult = -1;
245   CStdString strHeading = g_localizeStrings.Get(20075);
246   CStdString strPassword = g_settings.GetMasterProfile().getLockCode();
247   iVerifyPasswordResult = VerifyPassword(g_settings.GetMasterProfile().getLockMode(), strPassword, strHeading);
248   if (1 == iVerifyPasswordResult)
249     UpdateMasterLockRetryCount(false);
250
251   if (0 != iVerifyPasswordResult)
252   {
253     bCanceled = true;
254     return false;
255   }
256
257   // user successfully entered mastercode
258   UpdateMasterLockRetryCount(true);
259   return true;
260 }
261
262 void CGUIPassword::UpdateMasterLockRetryCount(bool bResetCount)
263 {
264   // \brief Updates Master Lock status.
265   // \param bResetCount masterlock retry counter is zeroed if true, or incremented and displays an Access Denied dialog if false.
266   if (!bResetCount)
267   {
268     // Bad mastercode entered
269     if (0 < g_guiSettings.GetInt("masterlock.maxretries"))
270     {
271       // We're keeping track of how many bad passwords are entered
272       if (1 < g_passwordManager.iMasterLockRetriesLeft)
273       {
274         // user still has at least one retry after decrementing
275         g_passwordManager.iMasterLockRetriesLeft--;
276       }
277       else
278       {
279         // user has run out of retry attempts
280         g_passwordManager.iMasterLockRetriesLeft = 0;
281         // Tell the user they ran out of retry attempts
282         CGUIDialogOK::ShowAndGetInput(12345, 12346, 0, 0);
283         return ;
284       }
285     }
286     CStdString dlgLine1 = "";
287     if (0 < g_passwordManager.iMasterLockRetriesLeft)
288       dlgLine1.Format("%d %s", g_passwordManager.iMasterLockRetriesLeft, g_localizeStrings.Get(12343));
289     CGUIDialogOK::ShowAndGetInput(20075, 12345, dlgLine1, 0);
290   }
291   else
292     g_passwordManager.iMasterLockRetriesLeft = g_guiSettings.GetInt("masterlock.maxretries"); // user entered correct mastercode, reset retries to max allowed
293 }
294
295 bool CGUIPassword::CheckLock(LockType btnType, const CStdString& strPassword, int iHeading)
296 {
297   bool bDummy;
298   return CheckLock(btnType,strPassword,iHeading,bDummy);
299 }
300
301 bool CGUIPassword::CheckLock(LockType btnType, const CStdString& strPassword, int iHeading, bool& bCanceled)
302 {
303   bCanceled = false;
304   if (btnType == LOCK_MODE_EVERYONE || strPassword.Equals("-")        ||
305       g_settings.GetMasterProfile().getLockMode() == LOCK_MODE_EVERYONE || g_passwordManager.bMasterUser)
306     return true;
307
308   int iVerifyPasswordResult = -1;
309   CStdString strHeading = g_localizeStrings.Get(iHeading);
310   iVerifyPasswordResult = VerifyPassword(btnType, strPassword, strHeading);
311
312   if (iVerifyPasswordResult == -1)
313     bCanceled = true;
314
315   return (iVerifyPasswordResult==0);
316 }
317
318 bool CGUIPassword::CheckMenuLock(int iWindowID)
319 {
320   bool bCheckPW         = false;
321   int iSwitch = iWindowID;
322
323   // check if a settings subcategory was called from other than settings window
324   if (iWindowID >= WINDOW_SCREEN_CALIBRATION && iWindowID <= WINDOW_SETTINGS_APPEARANCE)
325   {
326     int iCWindowID = g_windowManager.GetActiveWindow();
327     if (iCWindowID != WINDOW_SETTINGS_MENU && (iCWindowID < WINDOW_SCREEN_CALIBRATION || iCWindowID > WINDOW_SETTINGS_APPEARANCE))
328       iSwitch = WINDOW_SETTINGS_MENU;
329   }
330
331   if (iWindowID == WINDOW_MUSIC_FILES)
332     if (g_windowManager.GetActiveWindow() == WINDOW_MUSIC_NAV)
333       iSwitch = WINDOW_HOME;
334
335   if (iWindowID == WINDOW_MUSIC_NAV)
336     if (g_windowManager.GetActiveWindow() == WINDOW_HOME)
337       iSwitch = WINDOW_MUSIC_FILES;
338
339   if (iWindowID == WINDOW_VIDEO_NAV)
340     if (g_windowManager.GetActiveWindow() == WINDOW_HOME)
341       iSwitch = WINDOW_VIDEO_FILES;
342
343   if (iWindowID == WINDOW_VIDEO_FILES)
344     if (g_windowManager.GetActiveWindow() == WINDOW_VIDEO_NAV)
345       iSwitch = WINDOW_HOME;
346
347   switch (iSwitch)
348   {
349     case WINDOW_SETTINGS_MENU:  // Settings
350       bCheckPW = g_settings.GetCurrentProfile().settingsLocked();
351       break;
352     case WINDOW_ADDON_BROWSER:  // Addons
353       bCheckPW = g_settings.GetCurrentProfile().addonmanagerLocked();
354       break;
355     case WINDOW_FILES:          // Files
356       bCheckPW = g_settings.GetCurrentProfile().filesLocked();
357       break;
358     case WINDOW_PROGRAMS:       // Programs
359       bCheckPW = g_settings.GetCurrentProfile().programsLocked();
360       break;
361     case WINDOW_MUSIC_FILES:    // Music
362       bCheckPW = g_settings.GetCurrentProfile().musicLocked();
363       break;
364     case WINDOW_VIDEO_FILES:    // Video
365       bCheckPW = g_settings.GetCurrentProfile().videoLocked();
366       break;
367     case WINDOW_PICTURES:       // Pictures
368       bCheckPW = g_settings.GetCurrentProfile().picturesLocked();
369       break;
370     case WINDOW_SETTINGS_PROFILES:
371       bCheckPW = true;
372       break;
373     default:
374       bCheckPW = false;
375       break;
376   }
377   if (bCheckPW)
378     return IsMasterLockUnlocked(true); //Now let's check the PW if we need!
379   else
380     return true;
381 }
382
383 bool CGUIPassword::LockSource(const CStdString& strType, const CStdString& strName, bool bState)
384 {
385   VECSOURCES* pShares = g_settings.GetSourcesFromType(strType);
386   bool bResult = false;
387   for (IVECSOURCES it=pShares->begin();it != pShares->end();++it)
388   {
389     if (it->strName == strName)
390     {
391       if (it->m_iHasLock > 0)
392       {
393         it->m_iHasLock = bState?2:1;
394         bResult = true;
395       }
396       break;
397     }
398   }
399   CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_UPDATE_SOURCES);
400   g_windowManager.SendThreadMessage(msg);
401
402   return bResult;
403 }
404
405 void CGUIPassword::LockSources(bool lock)
406 {
407   // lock or unlock all sources (those with locks)
408   const char* strType[5] = {"programs","music","video","pictures","files"};
409   for (int i=0;i<5;++i)
410   {
411     VECSOURCES *shares = g_settings.GetSourcesFromType(strType[i]);
412     for (IVECSOURCES it=shares->begin();it != shares->end();++it)
413       if (it->m_iLockMode != LOCK_MODE_EVERYONE)
414         it->m_iHasLock = lock ? 2 : 1;
415   }
416   CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_UPDATE_SOURCES);
417   g_windowManager.SendThreadMessage(msg);
418 }
419
420 void CGUIPassword::RemoveSourceLocks()
421 {
422   // remove lock from all sources
423   const char* strType[5] = {"programs","music","video","pictures","files"};
424   for (int i=0;i<5;++i)
425   {
426     VECSOURCES *shares = g_settings.GetSourcesFromType(strType[i]);
427     for (IVECSOURCES it=shares->begin();it != shares->end();++it)
428       if (it->m_iLockMode != LOCK_MODE_EVERYONE) // remove old info
429       {
430         it->m_iHasLock = 0;
431         it->m_iLockMode = LOCK_MODE_EVERYONE;
432         g_settings.UpdateSource(strType[i],it->strName,"lockmode","0"); // removes locks from xml
433       }
434   }
435   g_settings.SaveSources();
436   CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0, GUI_MSG_UPDATE_SOURCES);
437   g_windowManager.SendThreadMessage(msg);
438 }
439
440 bool CGUIPassword::IsDatabasePathUnlocked(const CStdString& strPath, VECSOURCES& vecSources)
441 {
442   if (g_passwordManager.bMasterUser || g_settings.GetMasterProfile().getLockMode() == LOCK_MODE_EVERYONE)
443     return true;
444
445   // try to find the best matching source
446   bool bName = false;
447   int iIndex = CUtil::GetMatchingSource(strPath, vecSources, bName);
448
449   if (iIndex > -1 && iIndex < (int)vecSources.size())
450     if (vecSources[iIndex].m_iHasLock < 2)
451       return true;
452
453   return false;
454 }
455
456 int CGUIPassword::VerifyPassword(LockType btnType, const CStdString& strPassword, const CStdString& strHeading)
457 {
458   int iVerifyPasswordResult;
459   switch (btnType)
460   {
461   case LOCK_MODE_NUMERIC:
462     iVerifyPasswordResult = CGUIDialogNumeric::ShowAndVerifyPassword(const_cast<CStdString&>(strPassword), strHeading, 0);
463     break;
464   case LOCK_MODE_GAMEPAD:
465     iVerifyPasswordResult = CGUIDialogGamepad::ShowAndVerifyPassword(const_cast<CStdString&>(strPassword), strHeading, 0);
466     break;
467   case LOCK_MODE_QWERTY:
468     iVerifyPasswordResult = CGUIKeyboardFactory::ShowAndVerifyPassword(const_cast<CStdString&>(strPassword), strHeading, 0);
469     break;
470   default:   // must not be supported, treat as unlocked
471     iVerifyPasswordResult = 0;
472     break;
473   }
474
475   return iVerifyPasswordResult;
476 }
477