Merge branch 'secret-service-check'
Check if secret service can be used under Unix. See https://github.com/wxWidgets/wxWidgets/pull/1733
This commit is contained in:
@@ -78,6 +78,8 @@ private:
|
|||||||
class wxSecretStoreImpl : public wxRefCounter
|
class wxSecretStoreImpl : public wxRefCounter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
virtual bool IsOk(wxString* WXUNUSED(errmsg)) const { return true; }
|
||||||
|
|
||||||
virtual bool Save(const wxString& service,
|
virtual bool Save(const wxString& service,
|
||||||
const wxString& username,
|
const wxString& username,
|
||||||
const wxSecretValueImpl& password,
|
const wxSecretValueImpl& password,
|
||||||
|
@@ -126,8 +126,9 @@ public:
|
|||||||
~wxSecretStore();
|
~wxSecretStore();
|
||||||
|
|
||||||
|
|
||||||
// Check if this object is valid.
|
// Check if this object is valid, i.e. can be used, and optionally fill in
|
||||||
bool IsOk() const { return m_impl != NULL; }
|
// the provided error message string if it isn't.
|
||||||
|
bool IsOk(wxString* errmsg = NULL) const;
|
||||||
|
|
||||||
|
|
||||||
// Store a username/password combination.
|
// Store a username/password combination.
|
||||||
|
@@ -166,14 +166,16 @@ public:
|
|||||||
Example of storing credentials using this class:
|
Example of storing credentials using this class:
|
||||||
@code
|
@code
|
||||||
wxSecretStore store = wxSecretStore::GetDefault();
|
wxSecretStore store = wxSecretStore::GetDefault();
|
||||||
if ( store.IsOk() )
|
wxString errmsg;
|
||||||
|
if ( store.IsOk(&errmsg) )
|
||||||
{
|
{
|
||||||
if ( !store.Save("MyApp/MyService", username, password) )
|
if ( !store.Save("MyApp/MyService", username, password) )
|
||||||
wxLogWarning("Failed to save credentials to the system secret store.");
|
wxLogWarning("Failed to save credentials to the system secret store.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wxLogWarning("This system doesn't support storing passwords securely.");
|
wxLogWarning("This system doesn't support storing passwords securely "
|
||||||
|
"(%s).", errmsg);
|
||||||
}
|
}
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
@@ -201,13 +203,20 @@ public:
|
|||||||
Returns the default secrets collection to use.
|
Returns the default secrets collection to use.
|
||||||
|
|
||||||
Call IsOk() on the returned object to check if this method succeeded.
|
Call IsOk() on the returned object to check if this method succeeded.
|
||||||
|
|
||||||
|
Note that this method may show a dialog to the user under some
|
||||||
|
platforms, so it can take an arbitrarily long time to return.
|
||||||
*/
|
*/
|
||||||
static wxSecretStore GetDefault();
|
static wxSecretStore GetDefault();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Check if this object is valid.
|
Check if this object can actually be used.
|
||||||
|
|
||||||
|
@param errmsg If not @NULL, this parameter is filled with a
|
||||||
|
user-readable error message explaining why the secret store can't
|
||||||
|
be used (this argument is new since wxWidgets 3.1.4)
|
||||||
*/
|
*/
|
||||||
bool IsOk() const;
|
bool IsOk(wxString* errmsg = NULL) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Store a username/password combination.
|
Store a username/password combination.
|
||||||
|
@@ -196,9 +196,11 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
wxSecretStore store = wxSecretStore::GetDefault();
|
wxSecretStore store = wxSecretStore::GetDefault();
|
||||||
if ( !store.IsOk() )
|
wxString errmsg;
|
||||||
|
if ( !store.IsOk(&errmsg) )
|
||||||
{
|
{
|
||||||
wxFprintf(stderr, "Failed to create default secret store.\n");
|
wxFprintf(stderr, "Failed to create default secret store (%s)\n",
|
||||||
|
errmsg);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -162,6 +162,19 @@ wxSecretStore::~wxSecretStore()
|
|||||||
// Methods forwarded to wxSecretStoreImpl
|
// Methods forwarded to wxSecretStoreImpl
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool
|
||||||
|
wxSecretStore::IsOk(wxString* errmsg) const
|
||||||
|
{
|
||||||
|
if ( !m_impl )
|
||||||
|
{
|
||||||
|
if ( errmsg )
|
||||||
|
*errmsg = _("Not available for this platform");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_impl->IsOk(errmsg);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
wxSecretStore::Save(const wxString& service,
|
wxSecretStore::Save(const wxString& service,
|
||||||
const wxString& user,
|
const wxString& user,
|
||||||
|
@@ -119,6 +119,52 @@ private:
|
|||||||
SecretValue* const m_value;
|
SecretValue* const m_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Dummy implementation used when secret service is not available.
|
||||||
|
class wxSecretStoreNotAvailableImpl : public wxSecretStoreImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit wxSecretStoreNotAvailableImpl(const wxString& error)
|
||||||
|
: m_error(error)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool IsOk(wxString* errmsg) const wxOVERRIDE
|
||||||
|
{
|
||||||
|
if ( errmsg )
|
||||||
|
*errmsg = m_error;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool Save(const wxString& WXUNUSED(service),
|
||||||
|
const wxString& WXUNUSED(user),
|
||||||
|
const wxSecretValueImpl& WXUNUSED(secret),
|
||||||
|
wxString& errmsg) wxOVERRIDE
|
||||||
|
{
|
||||||
|
errmsg = m_error;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool Load(const wxString& WXUNUSED(service),
|
||||||
|
wxString* WXUNUSED(user),
|
||||||
|
wxSecretValueImpl** WXUNUSED(secret),
|
||||||
|
wxString& errmsg) const wxOVERRIDE
|
||||||
|
{
|
||||||
|
errmsg = m_error;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool Delete(const wxString& WXUNUSED(service),
|
||||||
|
wxString& errmsg) wxOVERRIDE
|
||||||
|
{
|
||||||
|
errmsg = m_error;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const wxString m_error;
|
||||||
|
};
|
||||||
|
|
||||||
// This implementation uses synchronous libsecret functions which is supposed
|
// This implementation uses synchronous libsecret functions which is supposed
|
||||||
// to be a bad idea, but doesn't seem to be a big deal in practice and as there
|
// to be a bad idea, but doesn't seem to be a big deal in practice and as there
|
||||||
// is no simple way to implement asynchronous API under the other platforms, it
|
// is no simple way to implement asynchronous API under the other platforms, it
|
||||||
@@ -127,6 +173,25 @@ private:
|
|||||||
class wxSecretStoreLibSecretImpl : public wxSecretStoreImpl
|
class wxSecretStoreLibSecretImpl : public wxSecretStoreImpl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static wxSecretStoreLibSecretImpl* Create(wxString& errmsg)
|
||||||
|
{
|
||||||
|
wxGtkError error;
|
||||||
|
SecretService* const service = secret_service_get_sync
|
||||||
|
(
|
||||||
|
SECRET_SERVICE_OPEN_SESSION,
|
||||||
|
NULL, // No cancellation
|
||||||
|
error.Out()
|
||||||
|
);
|
||||||
|
if ( !service )
|
||||||
|
{
|
||||||
|
errmsg = error.GetMessage();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This passes ownership of service to the new object.
|
||||||
|
return new wxSecretStoreLibSecretImpl(service);
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool Save(const wxString& service,
|
virtual bool Save(const wxString& service,
|
||||||
const wxString& user,
|
const wxString& user,
|
||||||
const wxSecretValueImpl& secret,
|
const wxSecretValueImpl& secret,
|
||||||
@@ -142,7 +207,7 @@ public:
|
|||||||
wxGtkError error;
|
wxGtkError error;
|
||||||
if ( !secret_service_store_sync
|
if ( !secret_service_store_sync
|
||||||
(
|
(
|
||||||
NULL, // Default service
|
m_service,
|
||||||
GetSchema(),
|
GetSchema(),
|
||||||
BuildAttributes(service, user),
|
BuildAttributes(service, user),
|
||||||
SECRET_COLLECTION_DEFAULT,
|
SECRET_COLLECTION_DEFAULT,
|
||||||
@@ -167,7 +232,7 @@ public:
|
|||||||
wxGtkError error;
|
wxGtkError error;
|
||||||
GList* const found = secret_service_search_sync
|
GList* const found = secret_service_search_sync
|
||||||
(
|
(
|
||||||
NULL, // Default service
|
m_service,
|
||||||
GetSchema(),
|
GetSchema(),
|
||||||
BuildAttributes(service),
|
BuildAttributes(service),
|
||||||
static_cast<SecretSearchFlags>
|
static_cast<SecretSearchFlags>
|
||||||
@@ -209,8 +274,9 @@ public:
|
|||||||
wxString& errmsg) wxOVERRIDE
|
wxString& errmsg) wxOVERRIDE
|
||||||
{
|
{
|
||||||
wxGtkError error;
|
wxGtkError error;
|
||||||
if ( !secret_password_clearv_sync
|
if ( !secret_service_clear_sync
|
||||||
(
|
(
|
||||||
|
m_service,
|
||||||
GetSchema(),
|
GetSchema(),
|
||||||
BuildAttributes(service),
|
BuildAttributes(service),
|
||||||
NULL, // Can't be cancelled
|
NULL, // Can't be cancelled
|
||||||
@@ -278,6 +344,15 @@ private:
|
|||||||
NULL
|
NULL
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ctor is private, Create() should be used for creating objects of this
|
||||||
|
// class.
|
||||||
|
explicit wxSecretStoreLibSecretImpl(SecretService* service)
|
||||||
|
: m_service(service)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
wxGtkObject<SecretService> m_service;
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* wxSecretStoreLibSecretImpl::FIELD_SERVICE = "service";
|
const char* wxSecretStoreLibSecretImpl::FIELD_SERVICE = "service";
|
||||||
@@ -298,8 +373,17 @@ wxSecretValueImpl* wxSecretValue::NewImpl(size_t size, const void *data)
|
|||||||
/* static */
|
/* static */
|
||||||
wxSecretStore wxSecretStore::GetDefault()
|
wxSecretStore wxSecretStore::GetDefault()
|
||||||
{
|
{
|
||||||
// There is only a single store under Windows anyhow.
|
// Try to create the real implementation.
|
||||||
return wxSecretStore(new wxSecretStoreLibSecretImpl());
|
wxString errmsg;
|
||||||
|
wxSecretStoreImpl* impl = wxSecretStoreLibSecretImpl::Create(errmsg);
|
||||||
|
if ( !impl )
|
||||||
|
{
|
||||||
|
// But if we failed, fall back to a dummy one, so that we could at
|
||||||
|
// least return the error to the code using this class.
|
||||||
|
impl = new wxSecretStoreNotAvailableImpl(errmsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return wxSecretStore(impl);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // wxUSE_SECRETSTORE
|
#endif // wxUSE_SECRETSTORE
|
||||||
|
Reference in New Issue
Block a user