/*
* Copyright (C) 2005-2013 Team XBMC
* http://xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XBMC; see the file COPYING. If not, see
* .
*
*/
#include "PasswordManager.h"
#include "profiles/ProfilesManager.h"
#include "profiles/dialogs/GUIDialogLockSettings.h"
#include "URL.h"
#include "utils/XMLUtils.h"
#include "threads/SingleLock.h"
#include "utils/log.h"
#include "filesystem/File.h"
using namespace std;
CPasswordManager &CPasswordManager::GetInstance()
{
static CPasswordManager sPasswordManager;
return sPasswordManager;
}
CPasswordManager::CPasswordManager()
{
m_loaded = false;
}
bool CPasswordManager::AuthenticateURL(CURL &url)
{
CSingleLock lock(m_critSection);
if (!m_loaded)
Load();
CStdString lookup(GetLookupPath(url));
map::const_iterator it = m_temporaryCache.find(lookup);
if (it == m_temporaryCache.end())
{ // second step, try something that doesn't quite match
it = m_temporaryCache.find(GetServerLookup(lookup));
}
if (it != m_temporaryCache.end())
{
CURL auth(it->second);
url.SetPassword(auth.GetPassWord());
url.SetUserName(auth.GetUserName());
return true;
}
return false;
}
bool CPasswordManager::PromptToAuthenticateURL(CURL &url)
{
CSingleLock lock(m_critSection);
std::string passcode;
std::string username = url.GetUserName();
bool saveDetails = false;
if (!CGUIDialogLockSettings::ShowAndGetUserAndPassword(username, passcode, url.GetWithoutUserDetails(), &saveDetails))
return false;
url.SetPassword(passcode);
url.SetUserName(username);
// save the information for later
SaveAuthenticatedURL(url, saveDetails);
return true;
}
void CPasswordManager::SaveAuthenticatedURL(const CURL &url, bool saveToProfile)
{
// don't store/save authenticated url if it doesn't contain username
if (url.GetUserName().empty())
return;
CSingleLock lock(m_critSection);
CStdString path = GetLookupPath(url);
CStdString authenticatedPath = url.Get();
if (!m_loaded)
Load();
if (saveToProfile)
{ // write to some random XML file...
m_permanentCache[path] = authenticatedPath;
Save();
}
// save for both this path and more generally the server as a whole.
m_temporaryCache[path] = authenticatedPath;
m_temporaryCache[GetServerLookup(path)] = authenticatedPath;
}
void CPasswordManager::Clear()
{
m_temporaryCache.clear();
m_permanentCache.clear();
m_loaded = false;
}
void CPasswordManager::Load()
{
Clear();
CStdString passwordsFile = CProfilesManager::Get().GetUserDataItem("passwords.xml");
if (XFILE::CFile::Exists(passwordsFile))
{
CXBMCTinyXML doc;
if (!doc.LoadFile(passwordsFile))
{
CLog::Log(LOGERROR, "%s - Unable to load: %s, Line %d\n%s",
__FUNCTION__, passwordsFile.c_str(), doc.ErrorRow(), doc.ErrorDesc());
return;
}
const TiXmlElement *root = doc.RootElement();
if (root->ValueStr() != "passwords")
return;
// read in our passwords
const TiXmlElement *path = root->FirstChildElement("path");
while (path)
{
CStdString from, to;
if (XMLUtils::GetPath(path, "from", from) && XMLUtils::GetPath(path, "to", to))
{
m_permanentCache[from] = to;
m_temporaryCache[from] = to;
m_temporaryCache[GetServerLookup(from)] = to;
}
path = path->NextSiblingElement("path");
}
}
m_loaded = true;
}
void CPasswordManager::Save() const
{
if (m_permanentCache.empty())
return;
CXBMCTinyXML doc;
TiXmlElement rootElement("passwords");
TiXmlNode *root = doc.InsertEndChild(rootElement);
if (!root)
return;
for (map::const_iterator i = m_permanentCache.begin(); i != m_permanentCache.end(); ++i)
{
TiXmlElement pathElement("path");
TiXmlNode *path = root->InsertEndChild(pathElement);
XMLUtils::SetPath(path, "from", i->first);
XMLUtils::SetPath(path, "to", i->second);
}
doc.SaveFile(CProfilesManager::Get().GetUserDataItem("passwords.xml"));
}
CStdString CPasswordManager::GetLookupPath(const CURL &url) const
{
return "smb://" + url.GetHostName() + "/" + url.GetShareName();
}
CStdString CPasswordManager::GetServerLookup(const CStdString &path) const
{
CURL url(path);
return "smb://" + url.GetHostName() + "/";
}