pidgin/pidgin

Ignore pidginprivate.h from the docs

2021-05-13, Gary Kramlich
1b5b70f24f62
Ignore pidginprivate.h from the docs

Testing Done:
Ran docs locally, had to remove the html and xml directories to have a clean build.

Reviewed at https://reviews.imfreedom.org/r/653/
/*
* Purple - Internet Messaging Library
* Copyright (C) Pidgin Developers <devel@pidgin.im>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <https://www.gnu.org/licenses/>.
*/
/* TODO
*
* This keyring now works (at the time of this writing), but there are
* some inconvenient edge cases. When looking up passwords, libsecret
* doesn't error if the keyring is locked. Therefore, it appears to
* this plugin that there's no stored password. libpurple seems to
* handle this as gracefully as possible, but it's still inconvenient.
* This plugin could possibly be ported to use libsecret's "Complete API"
* to resolve this if desired.
*/
#include <glib/gi18n-lib.h>
#include <purple.h>
#include <libsecret/secret.h>
/* Translators: Secret Service is a service that runs on the user's computer.
It is one option for where the user's passwords can be stored. It is a
project name. It may not be appropriate to translate this string, but
transliterating to your alphabet is reasonable. More info about the
project can be found at https://wiki.gnome.org/Projects/Libsecret */
#define SECRETSERVICE_ID "secret-service"
#define SECRETSERVICE_NAME N_("Secret Service")
#define SECRETSERVICE_DESCRIPTION N_("D-Bus Secret Service. Common in GNOME " \
"and other desktop environments.")
/******************************************************************************
* Globals
*****************************************************************************/
static PurpleCredentialProvider *instance = NULL;
static const SecretSchema purple_secret_service_schema = {
"im.pidgin.Purple3", SECRET_SCHEMA_NONE,
{
{"user", SECRET_SCHEMA_ATTRIBUTE_STRING},
{"protocol", SECRET_SCHEMA_ATTRIBUTE_STRING},
{"NULL", 0}
},
/* Reserved fields */
0, 0, 0, 0, 0, 0, 0, 0
};
#define PURPLE_TYPE_SECRET_SERVICE (purple_secret_service_get_type())
G_DECLARE_FINAL_TYPE(PurpleSecretService, purple_secret_service,
PURPLE, SECRET_SERVICE, PurpleCredentialProvider)
struct _PurpleSecretService {
PurpleCredentialProvider parent;
};
G_DEFINE_DYNAMIC_TYPE(PurpleSecretService, purple_secret_service,
PURPLE_TYPE_CREDENTIAL_PROVIDER)
/******************************************************************************
* Callbacks
*****************************************************************************/
static void
purple_secret_service_read_password_callback(GObject *obj,
GAsyncResult *result,
gpointer data)
{
GTask *task = G_TASK(data);
GError *error = NULL;
gchar *password = NULL;
password = secret_password_lookup_finish(result, &error);
if(error != NULL) {
g_task_return_error(task, error);
} else {
g_task_return_pointer(task, password, g_free);
}
g_object_unref(G_OBJECT(task));
}
static void
purple_secret_service_write_password_callback(GObject *obj,
GAsyncResult *result,
gpointer data)
{
GTask *task = G_TASK(data);
GError *error = NULL;
gboolean ret = FALSE;
ret = secret_password_store_finish(result, &error);
if(error != NULL) {
g_task_return_error(task, error);
} else {
g_task_return_boolean(task, ret);
}
g_object_unref(G_OBJECT(task));
}
static void
purple_secret_service_clear_password_callback(GObject *obj,
GAsyncResult *result,
gpointer data)
{
GTask *task = G_TASK(data);
GError *error = NULL;
gboolean ret = FALSE;
ret = secret_password_clear_finish(result, &error);
if(error != NULL) {
g_task_return_error(task, error);
} else {
g_task_return_boolean(task, ret);
}
g_object_unref(G_OBJECT(task));
}
/******************************************************************************
* PurpleCredentialProvider Implementation
*****************************************************************************/
static void
purple_secret_service_read_password_async(PurpleCredentialProvider *provider,
PurpleAccount *account,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer data)
{
GTask *task = g_task_new(G_OBJECT(provider), cancellable, callback, data);
secret_password_lookup(&purple_secret_service_schema, cancellable,
purple_secret_service_read_password_callback, task,
"user", purple_account_get_username(account),
"protocol", purple_account_get_protocol_id(account),
NULL);
}
static gchar *
purple_secret_service_read_password_finish(PurpleCredentialProvider *provider,
GAsyncResult *result,
GError **error)
{
g_return_val_if_fail(PURPLE_IS_CREDENTIAL_PROVIDER(provider), FALSE);
g_return_val_if_fail(G_IS_ASYNC_RESULT(result), FALSE);
return g_task_propagate_pointer(G_TASK(result), error);
}
static void
purple_secret_service_write_password_async(PurpleCredentialProvider *provider,
PurpleAccount *account,
const gchar *password,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer data)
{
GTask *task = NULL;
gchar *label = NULL;
const gchar *username = NULL;
task = g_task_new(G_OBJECT(provider), cancellable, callback, data);
username = purple_account_get_username(account);
label = g_strdup_printf(_("libpurple password for account %s"), username);
secret_password_store(&purple_secret_service_schema,
SECRET_COLLECTION_DEFAULT, label, password,
cancellable,
purple_secret_service_write_password_callback, task,
"user", username,
"protocol", purple_account_get_protocol_id(account),
NULL);
g_free(label);
}
static gboolean
purple_secret_service_write_password_finish(PurpleCredentialProvider *provider,
GAsyncResult *result,
GError **error)
{
g_return_val_if_fail(PURPLE_IS_CREDENTIAL_PROVIDER(provider), FALSE);
g_return_val_if_fail(G_IS_ASYNC_RESULT(result), FALSE);
return g_task_propagate_boolean(G_TASK(result), error);
}
static void
purple_secret_service_clear_password_async(PurpleCredentialProvider *provider,
PurpleAccount *account,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer data)
{
GTask *task = g_task_new(G_OBJECT(provider), cancellable, callback, data);
secret_password_clear(&purple_secret_service_schema, cancellable,
purple_secret_service_clear_password_callback, task,
"user", purple_account_get_username(account),
"protocol", purple_account_get_protocol_id(account),
NULL);
}
static gboolean
purple_secret_service_clear_password_finish(PurpleCredentialProvider *provider,
GAsyncResult *result,
GError **error)
{
g_return_val_if_fail(PURPLE_IS_CREDENTIAL_PROVIDER(provider), FALSE);
g_return_val_if_fail(G_IS_ASYNC_RESULT(result), FALSE);
return g_task_propagate_boolean(G_TASK(result), error);
}
/******************************************************************************
* GObject Implementation
*****************************************************************************/
static void
purple_secret_service_init(PurpleSecretService *ss) {
}
static void
purple_secret_service_class_init(PurpleSecretServiceClass *klass) {
PurpleCredentialProviderClass *provider_class = NULL;
provider_class = PURPLE_CREDENTIAL_PROVIDER_CLASS(klass);
provider_class->read_password_async =
purple_secret_service_read_password_async;
provider_class->read_password_finish =
purple_secret_service_read_password_finish;
provider_class->write_password_async =
purple_secret_service_write_password_async;
provider_class->write_password_finish =
purple_secret_service_write_password_finish;
provider_class->clear_password_async =
purple_secret_service_clear_password_async;
provider_class->clear_password_finish =
purple_secret_service_clear_password_finish;
}
static void
purple_secret_service_class_finalize(PurpleSecretServiceClass *klass) {
}
/******************************************************************************
* API
*****************************************************************************/
static PurpleCredentialProvider *
purple_secret_service_new(void) {
return PURPLE_CREDENTIAL_PROVIDER(g_object_new(
PURPLE_TYPE_SECRET_SERVICE,
"id", SECRETSERVICE_ID,
"name", _(SECRETSERVICE_NAME),
"description", _(SECRETSERVICE_DESCRIPTION),
NULL
));
}
/******************************************************************************
* Plugin Exports
*****************************************************************************/
G_MODULE_EXPORT GPluginPluginInfo *gplugin_query(GPluginPlugin *plugin, GError **error);
G_MODULE_EXPORT gboolean gplugin_load(GPluginPlugin *plugin, GError **error);
G_MODULE_EXPORT gboolean gplugin_unload(GPluginPlugin *plugin, GError **error);
G_MODULE_EXPORT GPluginPluginInfo *
gplugin_query(GPluginPlugin *plugin, GError **error) {
const gchar * const authors[] = {
"Elliott Sales de Andrade (qulogic[at]pidgin.im)",
NULL
};
return GPLUGIN_PLUGIN_INFO(purple_plugin_info_new(
"id", SECRETSERVICE_ID,
"name", SECRETSERVICE_NAME,
"version", DISPLAY_VERSION,
"category", N_("Keyring"),
"summary", "Secret Service Plugin",
"description", N_("This plugin will store passwords in Secret Service."),
"authors", authors,
"website", PURPLE_WEBSITE,
"abi-version", PURPLE_ABI_VERSION,
"flags", PURPLE_PLUGIN_INFO_FLAGS_INTERNAL |
PURPLE_PLUGIN_INFO_FLAGS_AUTO_LOAD,
NULL
));
}
G_MODULE_EXPORT gboolean
gplugin_load(GPluginPlugin *plugin, GError **error) {
PurpleCredentialManager *manager = NULL;
purple_secret_service_register_type(G_TYPE_MODULE(plugin));
manager = purple_credential_manager_get_default();
instance = purple_secret_service_new();
return purple_credential_manager_register_provider(manager, instance,
error);
}
G_MODULE_EXPORT gboolean
gplugin_unload(GPluginPlugin *plugin, GError **error) {
PurpleCredentialManager *manager = NULL;
gboolean ret = FALSE;
manager = purple_credential_manager_get_default();
ret = purple_credential_manager_unregister_provider(manager, instance,
error);
if(!ret) {
return ret;
}
g_clear_object(&instance);
return TRUE;
}