Files
wxWidgets/src/common/secretstore.cpp
Vadim Zeitlin 2fffbde096 Change wxSecretStore API to allow retrieving the username
The old API didn't make any sense for the most common case when both the
user name and password need to be stored, as it required providing the
user name as input, which couldn't work (but somehow this went
unnoticed for more than a year...).

Fix this by returning the username, and not only the password, from
Load() instead of taking it as parameter and removing this parameter
from Delete() as well.

Also improve the documentation, notably include a simple example of
using this class.

Notice that this is a backwards-incompatible change, but the old API was
really badly broken and didn't appear in 3.1.0 yet, so the breakage is
both unavoidable and, hopefully, shouldn't affect much code.
Nevertheless, a special wxHAS_SECRETSTORE_LOAD_USERNAME symbol is added
to allow testing for it if necessary.
2017-07-17 18:26:20 +02:00

234 lines
5.9 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// Name: src/common/secretstore.cpp
// Purpose: Common parts of wxSecretStore implementation.
// Author: Vadim Zeitlin
// Created: 2016-05-27
// Copyright: (c) 2016 Vadim Zeitlin <vadim@wxwidgets.org>
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// for compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#if wxUSE_SECRETSTORE
#include "wx/secretstore.h"
#include "wx/log.h"
#include "wx/translation.h"
#include "wx/private/secretstore.h"
#include <string.h>
// ============================================================================
// wxSecretValue implementation
// ============================================================================
// ----------------------------------------------------------------------------
// Memory management
// ----------------------------------------------------------------------------
wxSecretValue::wxSecretValue(const wxSecretValue& other)
: m_impl(other.m_impl)
{
if ( m_impl )
m_impl->IncRef();
}
wxSecretValue& wxSecretValue::operator=(const wxSecretValue& other)
{
// This code is written to be safe in case of self-assignment.
wxSecretValueImpl* const impl = other.m_impl;
if ( impl )
impl->IncRef();
if ( m_impl )
m_impl->DecRef();
m_impl = impl;
return *this;
}
wxSecretValue::~wxSecretValue()
{
if ( m_impl )
m_impl->DecRef();
}
// ----------------------------------------------------------------------------
// Comparison
// ----------------------------------------------------------------------------
bool wxSecretValue::operator==(const wxSecretValue& other) const
{
// Two empty secrets are equal but no other secret is equal to the empty
// one (even the zero-length one).
if ( !m_impl )
return !other.m_impl;
wxSecretValueImpl* const impl = other.m_impl;
if ( !impl )
return false;
// Here both objects are not empty, so we can compare them.
return m_impl->GetSize() == impl->GetSize() &&
memcmp(m_impl->GetData(), impl->GetData(), m_impl->GetSize()) == 0;
}
// ----------------------------------------------------------------------------
// Methods forwarded to wxSecretValueImpl
// ----------------------------------------------------------------------------
size_t wxSecretValue::GetSize() const
{
return m_impl ? m_impl->GetSize() : (size_t)0;
}
const void *wxSecretValue::GetData() const
{
return m_impl ? m_impl->GetData() : NULL;
}
wxString wxSecretValue::GetAsString(const wxMBConv& conv) const
{
if ( !m_impl )
return wxString();
return wxString
(
static_cast<const char*>(m_impl->GetData()),
conv,
m_impl->GetSize()
);
}
#ifndef __WINDOWS__
/* static */
void wxSecretValue::Wipe(size_t size, void *data)
{
// memset_s() is not present under non-MSW systems anyhow and there doesn't
// seem to be any other way to portably ensure that the memory is really
// cleared, so just do it in this obvious way.
memset(data, 0, size);
}
#endif // __WINDOWS__
/* static */
void wxSecretValue::WipeString(wxString& str)
{
for ( wxString::iterator it = str.begin(); it != str.end(); ++it )
*it = '*';
}
// ============================================================================
// wxSecretStore implementation
// ============================================================================
// ----------------------------------------------------------------------------
// Memory management
// ----------------------------------------------------------------------------
wxSecretStore::wxSecretStore(const wxSecretStore& other)
: m_impl(other.m_impl)
{
if ( m_impl )
m_impl->IncRef();
}
wxSecretStore::~wxSecretStore()
{
if ( m_impl )
m_impl->DecRef();
}
// ----------------------------------------------------------------------------
// Methods forwarded to wxSecretStoreImpl
// ----------------------------------------------------------------------------
bool
wxSecretStore::Save(const wxString& service,
const wxString& user,
const wxSecretValue& secret)
{
if ( !m_impl )
return false;
if ( !secret.m_impl )
return false;
wxString err;
if ( !m_impl->Save(service, user, *secret.m_impl, err) )
{
wxLogError(_("Saving password for \"%s\" failed: %s."),
service, err);
return false;
}
return true;
}
bool
wxSecretStore::Load(const wxString& service,
wxString& user,
wxSecretValue& secret) const
{
if ( !m_impl )
return false;
wxString err;
wxSecretValueImpl* secretImpl = NULL;
if ( !m_impl->Load(service, &user, &secretImpl, err) )
{
if ( !err.empty() )
{
wxLogError(_("Reading password for \"%s\" failed: %s."),
service, err);
}
return false;
}
secret = wxSecretValue(secretImpl);
return true;
}
bool
wxSecretStore::Delete(const wxString& service)
{
if ( !m_impl )
return false;
wxString err;
if ( !m_impl->Delete(service, err) )
{
if ( !err.empty() )
{
wxLogError(_("Deleting password for \"%s\" failed: %s."),
service, err);
}
return false;
}
return true;
}
#endif // wxUSE_SECRETSTORE