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
*
* Purple is the legal property of its developers, whose names are too numerous
* to list here. Please refer to the COPYRIGHT file distributed with this
* source distribution.
*
* 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 of the License, 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 this program ; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#include <glib/gi18n-lib.h>
#include <purple.h>
#include <wincred.h>
#define WINCRED_ID "keyring-wincred"
#define WINCRED_NAME N_("Windows credentials")
#define WINCRED_DESCRIPTION N_("The built-in credential manager for Windows.")
#define WINCRED_MAX_TARGET_NAME 256
/******************************************************************************
* Globals
*****************************************************************************/
static PurpleCredentialProvider *instance = NULL;
#define PURPLE_TYPE_WINCRED (purple_wincred_get_type())
G_DECLARE_FINAL_TYPE(PurpleWinCred, purple_wincred, PURPLE, SECRET_SERVICE,
PurpleCredentialProvider)
struct _PurpleWinCred {
PurpleCredentialProvider parent;
};
#define PURPLE_WINCRED_ERROR (g_quark_from_static_string("wincred"))
G_DEFINE_DYNAMIC_TYPE(PurpleWinCred, purple_wincred,
PURPLE_TYPE_CREDENTIAL_PROVIDER)
/******************************************************************************
* PurpleCredentialProvider Implementation
*****************************************************************************/
static gunichar2 *
wincred_get_target_name(PurpleAccount *account, GError **error)
{
gchar target_name_utf8[WINCRED_MAX_TARGET_NAME];
gunichar2 *target_name_utf16;
g_return_val_if_fail(account != NULL, NULL);
g_snprintf(target_name_utf8, WINCRED_MAX_TARGET_NAME, "libpurple_%s_%s",
purple_account_get_protocol_id(account),
purple_account_get_username(account));
target_name_utf16 =
g_utf8_to_utf16(target_name_utf8, -1, NULL, NULL, error);
if (target_name_utf16 == NULL) {
purple_debug_fatal("keyring-wincred", "Couldn't convert target name");
return NULL;
}
return target_name_utf16;
}
static void
purple_wincred_read_password_async(PurpleCredentialProvider *provider,
PurpleAccount *account,
GCancellable *cancellable,
GAsyncReadyCallback callback, gpointer data)
{
GTask *task = NULL;
GError *error = NULL;
gunichar2 *target_name = NULL;
gchar *password = NULL;
PCREDENTIALW credential = NULL;
task = g_task_new(G_OBJECT(provider), cancellable, callback, data);
target_name = wincred_get_target_name(account, &error);
if (target_name == NULL) {
g_task_return_error(task, error);
g_object_unref(G_OBJECT(task));
return;
}
if (!CredReadW(target_name, CRED_TYPE_GENERIC, 0, &credential)) {
DWORD error_code = GetLastError();
if (error_code == ERROR_NOT_FOUND) {
if (purple_debug_is_verbose()) {
purple_debug_misc("keyring-wincred",
"No password found for account %s\n",
purple_account_get_username(account));
}
error = g_error_new(PURPLE_WINCRED_ERROR,
error_code,
_("Password not found."));
} else if (error_code == ERROR_NO_SUCH_LOGON_SESSION) {
purple_debug_error("keyring-wincred",
"Cannot read password, no valid logon "
"session\n");
error = g_error_new(PURPLE_WINCRED_ERROR,
error_code,
_("Cannot read password, no valid logon "
"session."));
} else {
purple_debug_error("keyring-wincred",
"Cannot read password, error %lx\n",
error_code);
error = g_error_new(PURPLE_WINCRED_ERROR,
error_code,
_("Cannot read password (error %lx)."), error_code);
}
g_task_return_error(task, error);
g_object_unref(G_OBJECT(task));
return;
}
password = g_utf16_to_utf8((gunichar2*)credential->CredentialBlob,
credential->CredentialBlobSize / sizeof(gunichar2),
NULL, NULL, NULL);
memset(credential->CredentialBlob, 0, credential->CredentialBlobSize);
CredFree(credential);
if (password == NULL) {
purple_debug_error("keyring-wincred",
"Cannot convert password\n");
error = g_error_new(PURPLE_WINCRED_ERROR,
0,
_("Cannot read password (unicode error)."));
g_task_return_error(task, error);
g_object_unref(G_OBJECT(task));
return;
} else {
purple_debug_misc("keyring-wincred",
_("Got password for account %s.\n"),
purple_account_get_username(account));
}
g_task_return_pointer(task, password, g_free);
g_object_unref(G_OBJECT(task));
}
static gchar *
purple_wincred_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_wincred_write_password_async(PurpleCredentialProvider *provider,
PurpleAccount *account,
const gchar *password,
GCancellable *cancellable,
GAsyncReadyCallback callback, gpointer data)
{
GTask *task = NULL;
GError *error = NULL;
gunichar2 *target_name = NULL;
gunichar2 *username_utf16 = NULL;
gunichar2 *password_utf16 = NULL;
glong password_len = 0;
CREDENTIALW credential;
task = g_task_new(G_OBJECT(provider), cancellable, callback, data);
target_name = wincred_get_target_name(account, &error);
if (target_name == NULL) {
g_task_return_error(task, error);
g_object_unref(G_OBJECT(task));
return;
}
username_utf16 = g_utf8_to_utf16(purple_account_get_username(account), -1,
NULL, NULL, &error);
if (username_utf16 == NULL) {
g_free(target_name);
purple_debug_fatal("keyring-wincred", "Couldn't convert username");
g_task_return_error(task, error);
g_object_unref(G_OBJECT(task));
return;
}
password_utf16 = g_utf8_to_utf16(password, -1, NULL, &password_len, &error);
if (password_utf16 == NULL) {
g_free(username_utf16);
g_free(target_name);
purple_debug_fatal("keyring-wincred", "Couldn't convert password");
g_task_return_error(task, error);
g_object_unref(G_OBJECT(task));
return;
}
memset(&credential, 0, sizeof(CREDENTIALW));
credential.Type = CRED_TYPE_GENERIC;
credential.TargetName = target_name;
credential.CredentialBlobSize = password_len * sizeof(gunichar2);
credential.CredentialBlob = (LPBYTE)password_utf16;
credential.Persist = CRED_PERSIST_LOCAL_MACHINE;
credential.UserName = username_utf16;
if (!CredWriteW(&credential, 0)) {
DWORD error_code = GetLastError();
if (error_code == ERROR_NO_SUCH_LOGON_SESSION) {
purple_debug_error("keyring-wincred",
"Cannot store password, no valid logon session");
error = g_error_new(
PURPLE_WINCRED_ERROR, error_code,
_("Cannot remove password, no valid logon session."));
} else {
purple_debug_error("keyring-wincred",
"Cannot store password, error %lx\n",
error_code);
error = g_error_new(PURPLE_WINCRED_ERROR, error_code,
_("Cannot store password (error %lx)."), error_code);
}
} else {
purple_debug_misc("keyring-wincred", "Password updated for account %s.",
purple_account_get_username(account));
}
g_free(target_name);
g_free(username_utf16);
g_free(password_utf16);
if (error != NULL) {
g_task_return_error(task, error);
} else {
g_task_return_boolean(task, TRUE);
}
g_object_unref(G_OBJECT(task));
}
static gboolean
purple_wincred_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_wincred_clear_password_async(PurpleCredentialProvider *provider,
PurpleAccount *account,
GCancellable *cancellable,
GAsyncReadyCallback callback, gpointer data)
{
GTask *task = NULL;
GError *error = NULL;
gunichar2 *target_name = NULL;
task = g_task_new(G_OBJECT(provider), cancellable, callback, data);
target_name = wincred_get_target_name(account, &error);
if (target_name == NULL) {
g_task_return_error(task, error);
g_object_unref(G_OBJECT(task));
return;
}
if (CredDeleteW(target_name, CRED_TYPE_GENERIC, 0)) {
purple_debug_misc("keyring-wincred", "Password for account %s removed",
purple_account_get_username(account));
g_task_return_boolean(task, TRUE);
} else {
DWORD error_code = GetLastError();
if (error_code == ERROR_NOT_FOUND) {
if (purple_debug_is_verbose()) {
purple_debug_misc(
"keyring-wincred",
"Password for account %s was already removed.",
purple_account_get_username(account));
}
} else if (error_code == ERROR_NO_SUCH_LOGON_SESSION) {
purple_debug_error(
"keyring-wincred",
"Cannot remove password, no valid logon session");
error = g_error_new(
PURPLE_WINCRED_ERROR, error_code,
_("Cannot remove password, no valid logon session."));
} else {
purple_debug_error("keyring-wincred",
"Cannot remove password, error %lx", error_code);
error = g_error_new(
PURPLE_WINCRED_ERROR, error_code,
_("Cannot remove password (error %lx)."), error_code);
}
g_task_return_error(task, error);
}
g_object_unref(G_OBJECT(task));
}
static gboolean
purple_wincred_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_wincred_init(PurpleWinCred *wincred)
{
}
static void
purple_wincred_class_init(PurpleWinCredClass *klass)
{
PurpleCredentialProviderClass *provider_class = NULL;
provider_class = PURPLE_CREDENTIAL_PROVIDER_CLASS(klass);
provider_class->read_password_async = purple_wincred_read_password_async;
provider_class->read_password_finish = purple_wincred_read_password_finish;
provider_class->write_password_async = purple_wincred_write_password_async;
provider_class->write_password_finish =
purple_wincred_write_password_finish;
provider_class->clear_password_async = purple_wincred_clear_password_async;
provider_class->clear_password_finish =
purple_wincred_clear_password_finish;
}
static void
purple_wincred_class_finalize(PurpleWinCredClass *klass)
{
}
/******************************************************************************
* API
*****************************************************************************/
static PurpleCredentialProvider *
purple_wincred_new(void)
{
return PURPLE_CREDENTIAL_PROVIDER(g_object_new(
PURPLE_TYPE_WINCRED,
"id", WINCRED_ID,
"name", _(WINCRED_NAME),
"description", _(WINCRED_DESCRIPTION),
NULL
));
}
/******************************************************************************
* Plugin Exports
*****************************************************************************/
G_MODULE_EXPORT GPluginPluginInfo *gplugin_query(GError **error);
G_MODULE_EXPORT gboolean gplugin_load(GPluginNativePlugin *plugin,
GError **error);
G_MODULE_EXPORT gboolean gplugin_unload(GPluginNativePlugin *plugin,
GError **error);
G_MODULE_EXPORT GPluginPluginInfo *
gplugin_query(GError **error)
{
const gchar * const authors[] = {
"Tomek Wasilczyk <twasilczyk@pidgin.im>",
NULL
};
return GPLUGIN_PLUGIN_INFO(purple_plugin_info_new(
"id", WINCRED_ID,
"name", WINCRED_NAME,
"version", DISPLAY_VERSION,
"category", _("Keyring"),
"summary", _("Store passwords using Windows credentials"),
"description", _("This plugin stores passwords using Windows credentials."),
"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(GPluginNativePlugin *plugin, GError **error)
{
PurpleCredentialManager *manager = NULL;
purple_wincred_register_type(G_TYPE_MODULE(plugin));
manager = purple_credential_manager_get_default();
instance = purple_wincred_new();
return purple_credential_manager_register_provider(manager, instance,
error);
}
G_MODULE_EXPORT gboolean
gplugin_unload(GPluginNativePlugin *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;
}