1 /*
2  *  Copyright (C) 2013-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
8 
9 #include "ProfilesOperations.h"
10 
11 #include "GUIPassword.h"
12 #include "ServiceBroker.h"
13 #include "guilib/LocalizeStrings.h"
14 #include "messaging/ApplicationMessenger.h"
15 #include "profiles/ProfileManager.h"
16 #include "settings/SettingsComponent.h"
17 #include "utils/Digest.h"
18 #include "utils/Variant.h"
19 
20 using namespace JSONRPC;
21 using namespace KODI::MESSAGING;
22 using KODI::UTILITY::CDigest;
23 
GetProfiles(const std::string & method,ITransportLayer * transport,IClient * client,const CVariant & parameterObject,CVariant & result)24 JSONRPC_STATUS CProfilesOperations::GetProfiles(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
25 {
26   const std::shared_ptr<CProfileManager> profileManager = CServiceBroker::GetSettingsComponent()->GetProfileManager();
27 
28   CFileItemList listItems;
29 
30   for (unsigned int i = 0; i < profileManager->GetNumberOfProfiles(); ++i)
31   {
32     const CProfile *profile = profileManager->GetProfile(i);
33     CFileItemPtr item(new CFileItem(profile->getName()));
34     item->SetArt("thumb", profile->getThumb());
35     listItems.Add(item);
36   }
37 
38   HandleFileItemList("profileid", false, "profiles", listItems, parameterObject, result);
39 
40   for (CVariant::const_iterator_array propertyiter = parameterObject["properties"].begin_array(); propertyiter != parameterObject["properties"].end_array(); ++propertyiter)
41   {
42     if (propertyiter->isString() &&
43         propertyiter->asString() == "lockmode")
44     {
45       for (CVariant::iterator_array profileiter = result["profiles"].begin_array(); profileiter != result["profiles"].end_array(); ++profileiter)
46       {
47         std::string profilename = (*profileiter)["label"].asString();
48         int index = profileManager->GetProfileIndex(profilename);
49         const CProfile *profile = profileManager->GetProfile(index);
50         LockType locktype = LOCK_MODE_UNKNOWN;
51         if (index == 0)
52           locktype = profileManager->GetMasterProfile().getLockMode();
53         else
54           locktype = profile->getLockMode();
55         (*profileiter)["lockmode"] = locktype;
56       }
57       break;
58     }
59   }
60   return OK;
61 }
62 
GetCurrentProfile(const std::string & method,ITransportLayer * transport,IClient * client,const CVariant & parameterObject,CVariant & result)63 JSONRPC_STATUS CProfilesOperations::GetCurrentProfile(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
64 {
65   const std::shared_ptr<CProfileManager> profileManager = CServiceBroker::GetSettingsComponent()->GetProfileManager();
66 
67   const CProfile& currentProfile = profileManager->GetCurrentProfile();
68   CVariant profileVariant = CVariant(CVariant::VariantTypeObject);
69   profileVariant["label"] = currentProfile.getName();
70   for (CVariant::const_iterator_array propertyiter = parameterObject["properties"].begin_array(); propertyiter != parameterObject["properties"].end_array(); ++propertyiter)
71   {
72     if (propertyiter->isString())
73     {
74       if (propertyiter->asString() == "lockmode")
75         profileVariant["lockmode"] = currentProfile.getLockMode();
76       else if (propertyiter->asString() == "thumbnail")
77         profileVariant["thumbnail"] = currentProfile.getThumb();
78     }
79   }
80 
81   result = profileVariant;
82 
83   return OK;
84 }
85 
LoadProfile(const std::string & method,ITransportLayer * transport,IClient * client,const CVariant & parameterObject,CVariant & result)86 JSONRPC_STATUS CProfilesOperations::LoadProfile(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
87 {
88   const std::shared_ptr<CProfileManager> profileManager = CServiceBroker::GetSettingsComponent()->GetProfileManager();
89 
90   std::string profilename = parameterObject["profile"].asString();
91   int index = profileManager->GetProfileIndex(profilename);
92 
93   if (index < 0)
94     return InvalidParams;
95 
96   // get the profile
97   const CProfile *profile = profileManager->GetProfile(index);
98   if (profile == NULL)
99     return InvalidParams;
100 
101   bool bPrompt = parameterObject["prompt"].asBoolean();
102   bool bCanceled = false;
103   bool bLoadProfile = false;
104 
105   // if the profile does not require a password or
106   // the user is prompted and provides the correct password
107   // we can load the requested profile
108   if (profile->getLockMode() == LOCK_MODE_EVERYONE ||
109      (bPrompt && g_passwordManager.IsProfileLockUnlocked(index, bCanceled, bPrompt)))
110     bLoadProfile = true;
111   else if (!bCanceled)  // Password needed and user provided it
112   {
113     const CVariant &passwordObject = parameterObject["password"];
114     const std::string& strToVerify = profile->getLockCode();
115     std::string password = passwordObject["value"].asString();
116 
117     // Create password hash from the provided password if md5 is not used
118     std::string md5pword2;
119     std::string encryption = passwordObject["encryption"].asString();
120     if (encryption == "none")
121       md5pword2 = CDigest::Calculate(CDigest::Type::MD5, password);
122     else if (encryption == "md5")
123       md5pword2 = password;
124 
125     // Verify provided password
126     if (StringUtils::EqualsNoCase(strToVerify, md5pword2))
127       bLoadProfile = true;
128   }
129 
130   if (bLoadProfile)
131   {
132     CApplicationMessenger::GetInstance().PostMsg(TMSG_LOADPROFILE, index);
133     return ACK;
134   }
135   return InvalidParams;
136 }
137