xbmc/xbmc/guilib/GUIKeyboardFactory.cpp

240 lines
9.1 KiB
C++

/*
* Copyright (C) 2005-2018 Team Kodi
* This file is part of Kodi - https://kodi.tv
*
* SPDX-License-Identifier: GPL-2.0-or-later
* See LICENSES/README.md for more information.
*/
#include "ServiceBroker.h"
#include "GUIComponent.h"
#include "messaging/ApplicationMessenger.h"
#include "LocalizeStrings.h"
#include "GUIKeyboardFactory.h"
#include "GUIUserMessages.h"
#include "GUIWindowManager.h"
#include "messaging/helpers/DialogOKHelper.h"
#include "settings/Settings.h"
#include "settings/SettingsComponent.h"
#include "utils/Digest.h"
#include "utils/StringUtils.h"
#include "utils/Variant.h"
#include "dialogs/GUIDialogKeyboardGeneric.h"
#if defined(TARGET_DARWIN_EMBEDDED)
#include "dialogs/GUIDialogKeyboardTouch.h"
#include "platform/darwin/ios-common/DarwinEmbedKeyboard.h"
#endif
using namespace KODI::MESSAGING;
using KODI::UTILITY::CDigest;
CGUIKeyboard *CGUIKeyboardFactory::g_activeKeyboard = NULL;
FILTERING CGUIKeyboardFactory::m_filtering = FILTERING_NONE;
CGUIKeyboardFactory::CGUIKeyboardFactory(void) = default;
CGUIKeyboardFactory::~CGUIKeyboardFactory(void) = default;
void CGUIKeyboardFactory::keyTypedCB(CGUIKeyboard *ref, const std::string &typedString)
{
if(ref)
{
// send our search message in safe way (only the active window needs it)
CGUIMessage message(GUI_MSG_NOTIFY_ALL, ref->GetWindowId(), 0);
switch(m_filtering)
{
case FILTERING_SEARCH:
message.SetParam1(GUI_MSG_SEARCH_UPDATE);
message.SetStringParam(typedString);
CServiceBroker::GetAppMessenger()->SendGUIMessage(
message, CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow());
break;
case FILTERING_CURRENT:
message.SetParam1(GUI_MSG_FILTER_ITEMS);
message.SetStringParam(typedString);
CServiceBroker::GetAppMessenger()->SendGUIMessage(message);
break;
case FILTERING_NONE:
break;
}
ref->resetAutoCloseTimer();
}
}
bool CGUIKeyboardFactory::SendTextToActiveKeyboard(const std::string &aTextString, bool closeKeyboard /* = false */)
{
if (!g_activeKeyboard)
return false;
return g_activeKeyboard->SetTextToKeyboard(aTextString, closeKeyboard);
}
// Show keyboard with initial value (aTextString) and replace with result string.
// Returns: true - successful display and input (empty result may return true or false depending on parameter)
// false - unsuccessful display of the keyboard or cancelled editing
bool CGUIKeyboardFactory::ShowAndGetInput(std::string& aTextString,
const CVariant& heading,
bool allowEmptyResult,
bool hiddenInput /* = false */,
unsigned int autoCloseMs /* = 0 */)
{
bool confirmed = false;
//heading can be a string or a localization id
std::string headingStr;
if (heading.isString())
headingStr = heading.asString();
else if (heading.isInteger() && heading.asInteger())
headingStr = g_localizeStrings.Get((uint32_t)heading.asInteger());
bool useKodiKeyboard = true;
#if defined(TARGET_DARWIN_EMBEDDED)
#if defined(TARGET_DARWIN_TVOS)
useKodiKeyboard = CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
CSettings::SETTING_INPUT_TVOSUSEKODIKEYBOARD);
#else
useKodiKeyboard = CDarwinEmbedKeyboard::hasExternalKeyboard();
#endif // defined(TARGET_DARWIN_TVOS)
#endif
auto& winManager = CServiceBroker::GetGUI()->GetWindowManager();
CGUIKeyboard* kb = nullptr;
if (useKodiKeyboard)
kb = winManager.GetWindow<CGUIDialogKeyboardGeneric>(WINDOW_DIALOG_KEYBOARD);
#if defined(TARGET_DARWIN_EMBEDDED)
else
kb = winManager.GetWindow<CGUIDialogKeyboardTouch>(WINDOW_DIALOG_KEYBOARD_TOUCH);
#endif // defined(TARGET_DARWIN_EMBEDDED)
if (kb)
{
g_activeKeyboard = kb;
kb->startAutoCloseTimer(autoCloseMs);
confirmed = kb->ShowAndGetInput(keyTypedCB, aTextString, aTextString, headingStr, hiddenInput);
g_activeKeyboard = NULL;
}
if (confirmed)
{
if (!allowEmptyResult && aTextString.empty())
confirmed = false;
}
return confirmed;
}
bool CGUIKeyboardFactory::ShowAndGetInput(std::string& aTextString, bool allowEmptyResult, unsigned int autoCloseMs /* = 0 */)
{
return ShowAndGetInput(aTextString, CVariant{""}, allowEmptyResult, false, autoCloseMs);
}
// Shows keyboard and prompts for a password.
// Differs from ShowAndVerifyNewPassword() in that no second verification is necessary.
bool CGUIKeyboardFactory::ShowAndGetNewPassword(std::string& newPassword,
const CVariant& heading,
bool allowEmpty,
unsigned int autoCloseMs /* = 0 */)
{
return ShowAndGetInput(newPassword, heading, allowEmpty, true, autoCloseMs);
}
// Shows keyboard and prompts for a password.
// Differs from ShowAndVerifyNewPassword() in that no second verification is necessary.
bool CGUIKeyboardFactory::ShowAndGetNewPassword(std::string& newPassword, unsigned int autoCloseMs /* = 0 */)
{
return ShowAndGetNewPassword(newPassword, 12340, false, autoCloseMs);
}
bool CGUIKeyboardFactory::ShowAndGetFilter(std::string &filter, bool searching, unsigned int autoCloseMs /* = 0 */)
{
m_filtering = searching ? FILTERING_SEARCH : FILTERING_CURRENT;
bool ret = ShowAndGetInput(filter, searching ? 16017 : 16028, true, false, autoCloseMs);
m_filtering = FILTERING_NONE;
return ret;
}
// \brief Show keyboard twice to get and confirm a user-entered password string.
// \param newPassword Overwritten with user input if return=true.
// \param heading Heading to display
// \param allowEmpty Whether a blank password is valid or not.
// \return true if successful display and user input entry/re-entry. false if unsuccessful display, no user input, or canceled editing.
bool CGUIKeyboardFactory::ShowAndVerifyNewPassword(std::string& newPassword,
const CVariant& heading,
bool allowEmpty,
unsigned int autoCloseMs /* = 0 */)
{
// Prompt user for password input
std::string userInput;
if (!ShowAndGetInput(userInput, heading, allowEmpty, true, autoCloseMs))
{ // user cancelled, or invalid input
return false;
}
// success - verify the password
std::string checkInput;
if (!ShowAndGetInput(checkInput, 12341, allowEmpty, true, autoCloseMs))
{ // user cancelled, or invalid input
return false;
}
// check the password
if (checkInput == userInput)
{
newPassword = CDigest::Calculate(CDigest::Type::MD5, userInput);
return true;
}
HELPERS::ShowOKDialogText(CVariant{12341}, CVariant{12344});
return false;
}
// \brief Show keyboard twice to get and confirm a user-entered password string.
// \param strNewPassword Overwritten with user input if return=true.
// \return true if successful display and user input entry/re-entry. false if unsuccessful display, no user input, or canceled editing.
bool CGUIKeyboardFactory::ShowAndVerifyNewPassword(std::string& newPassword, unsigned int autoCloseMs /* = 0 */)
{
const std::string& heading = g_localizeStrings.Get(12340);
return ShowAndVerifyNewPassword(newPassword, heading, false, autoCloseMs);
}
// \brief Show keyboard and verify user input against strPassword.
// \param strPassword Value to compare against user input.
// \param dlgHeading String shown on dialog title. Converts to localized string if contains a positive integer.
// \param iRetries If greater than 0, shows "Incorrect password, %d retries left" on dialog line 2, else line 2 is blank.
// \return 0 if successful display and user input. 1 if unsuccessful input. -1 if no user input or canceled editing.
int CGUIKeyboardFactory::ShowAndVerifyPassword(std::string& strPassword, const std::string& strHeading, int iRetries, unsigned int autoCloseMs /* = 0 */)
{
std::string strHeadingTemp;
if (1 > iRetries && !strHeading.empty())
strHeadingTemp = strHeading;
else
strHeadingTemp =
StringUtils::Format("{} - {} {}", g_localizeStrings.Get(12326),
CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(
CSettings::SETTING_MASTERLOCK_MAXRETRIES) -
iRetries,
g_localizeStrings.Get(12343));
std::string strUserInput;
//! @todo GUI Setting to enable disable this feature y/n?
if (!ShowAndGetInput(strUserInput, strHeadingTemp, false, true, autoCloseMs)) //bool hiddenInput = false/true ?
return -1; // user canceled out
if (!strPassword.empty())
{
std::string md5pword2 = CDigest::Calculate(CDigest::Type::MD5, strUserInput);
if (StringUtils::EqualsNoCase(strPassword, md5pword2))
return 0; // user entered correct password
else return 1; // user must have entered an incorrect password
}
else
{
if (!strUserInput.empty())
{
strPassword = CDigest::Calculate(CDigest::Type::MD5, strUserInput);
return 0; // user entered correct password
}
else return 1;
}
}