Wed, 09 Jul 2008 00:08:41 +0000
added files that were'nt in workspace
| libpurple/keyring.c | file | annotate | diff | comparison | revisions | |
| libpurple/plugins/keyrings/internalkeyring.c | file | annotate | diff | comparison | revisions |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/keyring.c Wed Jul 09 00:08:41 2008 +0000 @@ -0,0 +1,488 @@ +/** + * @file keyring.c Keyring plugin API + */ + +/* 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 + */ + + +/** + * Most functions in this files are : + * - wrappers that will call the plugin + * - keyring managment stuff + * - accessors + * + * TODO : + * - use accessors + * - compare header with this file + * - purple_keyring_init() + * - purple_keyring_set_inuse() + * + * Questions : + * - use accessors internally + * - cleanup + * - public/opaque struct + * - wrapper for g_list_foreach ? + */ + +#include <glib.h> +#include "keyring.h" +#include "account.h" + +/*******************************/ +/* opaque structures */ +/*******************************/ + +/* information about a keyring */ +// FIXME : This should actually probably a public structure +struct _PurpleKeyring +{ + char * name; + PurpleKeyringRead read_password; + PurpleKeyringSave save_password; + PurpleKeyringClose close_keyring; + PurpleKeyringFree free_password; + PurpleKeyringChangeMaster change_master; + PurpleKeyringImportPassword import_password; + PurpleKeyringExportPassword export_password; + gpointer r1; /* RESERVED */ + gpointer r2; /* RESERVED */ + gpointer r3; /* RESERVED */ +}; + + +/* used to import and export password info */ +struct _PurpleKeyringPasswordNode +{ + PurpleAccount * account; + char * encryption; + char * mode; + char * data; +}; + + +/*******************************/ +/* globals */ +/*******************************/ + +GList * purple_keyring_keyringlist = NULL; /* list of available keyrings */ +PurpleKeyring * purple_keyring_inuse = NULL; /* keyring being used */ + + +/*******************************/ +/* functions */ +/*******************************/ + +/* manipulate keyring list, used by config interface */ + +const GList * +purple_keyring_get_keyringlist(void) +/* XXX add some more abstraction so we can change from GList to anything ? */ +{ + return purple_keyring_keyringlist; +} + +const PurpleKeyring * +purple_keyring_get_inuse(void) +{ + return purple_keyring_inuse; +} + + +/* change keyring to use */ +struct keyringchangeloop +{ + /*FIXME : type*/ cb; + gpointer data; + PurpleKeyring * new; + PurpleKeyring * old; + GList * cur; // the account we're playing with + char * pass; + GError * error; +}; + +void +purple_keyring_set_inuse_loop_read(struct keyringchangeloop * info) +{ + GList * cur; + PurpleAccount * account; + + cur = info->cur; + + if (cur == NULL) { + + /* we are done, trigger callback */ + cur->cb(cur->error,cur->data); + + } else { + + account = cur->data; + + info->pass + /* FIXME : + -read with callback purple_keyring_set_inuse_loop_save() + */ + } +} + + + +/* FIXME : needs to be async !!! */ +void +purple_keyring_set_inuse(PurpleKeyring * new, + GError ** error, + /*FIXME : type*/ cb, + gpointer data); +{ + + GList * cur; + PurpleKeyring * old; + char * password; + + + if (purple_keyring_inuse != NULL) { + + /* XXX use a wrapper for g_list_foreach ? */ + /* PSEUDOCODE (FIXME): + for all accounts + read password from old safe + store it in new safe + close old safe + */ + old = purple_keyring_get_inuse(); + + for (cur = purple_accounts_get_all(); cur != NULL; cur = cur->next) + { +// FIXME MOAR HERE password = old->read(cur) + } + + old->close(); + } + + purple_keyring_inuse = keyring; + return; + +} + +/* register a keyring plugin */ +/** + * TODO : function to unregister a keyring ? + * validate input ? add magix field ? + */ +void +purple_plugin_keyring_register(PurpleKeyring * info) +{ + purple_keyring_keyringlist = g_list_prepend(purple_keyring_keyringlist, + info); +} + + +/** + * wrappers to import and export passwords + */ + + +/** + * used by account.c while reading a password from xml + * might not really need to be async. + * TODO : use PurpleKeyringPasswordNode instead of xmlnode ? + */ +gboolean +purple_keyring_import_password(const PurpleKeyringPasswordNode * passwordnode, + GError ** error, // FIXME : re-order arguments in header + PurpleKeyringImportCallback cb, + gpointer data) +{ + if (purple_keyring_inuse == NULL) { + + g_set_error(error, ERR_PIDGINKEYRING, ERR_NOKEYRING, + "No Keyring configured."); + cb(error, data); + + } else { + purple_keyring_inuse->import_password(passwordnode, error, cb, data); + } + return; +} + +/* + * used by account.c while syncing accounts + * returned data must be g_free()'d + */ +void +purple_keyring_export_password(PurpleAccount * account, + GError ** error, // FIXME : re-order arguments in header + PurpleKeyringImportCallback cb, + gpointer data) +{ + if (purple_keyring_inuse == NULL) { + + g_set_error(error, ERR_PIDGINKEYRING, ERR_NOKEYRING, + "No Keyring configured."); + cb(NULL, error, data); + + } else { + // FIXME : use accessor + purple_keyring_inuse->export_password(passwordnode, error, cb, data); + } + return; +} + + +/** + * functions called from the code to access passwords (account.h): + * purple_account_get_password() <- TODO : rewrite these functions :) + * purple_account_set_password() + * so these functions will call : + */ +void +purple_keyring_get_password(const PurpleAccount *account, + GError ** error, + PurpleKeyringReadCallback cb, + gpointer data) +{ + if (purple_keyring_inuse == NULL) { + + g_set_error(error, ERR_PIDGINKEYRING, ERR_NOKEYRING, + "No Keyring configured."); + cb(account, NULL, error, data); + + } else { + purple_keyring_inuse->read(account, error, cb, data); + } + return; +} + +void +purple_keyring_set_password(const PurpleAccount * account, + gchar * password, + GError ** error, + PurpleKeyringSaveCallback cb, + gpointer data) +{ + if (purple_keyring_inuse == NULL) { + + g_set_error(error, ERR_PIDGINKEYRING, ERR_NOKEYRING, + "No Keyring configured."); + cb(account, error, data); + + } else { + purple_keyring_inuse->save(account, password, error, cb, data); + } + return; +} + +/* accessors for data structure fields */ + /* PurpleKeyring */ +const char * +purple_keyring_get_name(PurpleKeyring * info) +{ + return info->name; +} + +PurpleKeyringRead +purple_keyring_get_read_password(const PurpleKeyring * info) +{ + return info->read_password; +} + +PurpleKeyringSave +purple_keyring_get_save_password(const PurpleKeyring * info) +{ + return info->save_password; +} + +PurpleKeyringClose +purple_keyring_get_close_keyring(const PurpleKeyring * info) +{ + return info->close_keyring; +} + +PurpleKeyringFree +purple_keyring_get_free_password(const PurpleKeyring * info) +{ + return info->free_password; +} + +PurpleKeyringChangeMaster +purple_keyring_get_change_master(const PurpleKeyring * info) +{ + return info->change_master; +} + +PurpleKeyringImportPassword +purple_keyring_get_import_password(const PurpleKeyring * info) +{ + return info->import_password; +} + +PurpleKeyringExportPassword +purple_keyring_get_export_password(constPurpleKeyring * info) +{ + return info->export_password; +} + + +void +purple_keyring_set_name(PurpleKeyring * info, + char * name) +{ + info->name = name; +} + +void +purple_keyring_set_read_password(PurpleKeyring * info, + PurpleKeyringRead read) +{ + info->read_password = read; /* returned data must be g_free()'d */ +} + +void +purple_keyring_set_save_password(PurpleKeyring * info, + PurpleKeyringSave save) +{ + info->save_password = save; +} + +void +purple_keyring_set_close_keyring(PurpleKeyring * info, + PurpleKeyringClose close) +{ + info->close_keyring = close; +} + +void +purple_keyring_set_free_password(PurpleKeyring * info, + PurpleKeyringFree free) +{ + info->free_password = free; +} + +void +purple_keyring_set_change_master(PurpleKeyring * info, + PurpleKeyringChangeMaster change_master) +{ + info->change_master = change_master; +} + +void +purple_keyring_set_import_password(PurpleKeyring * info, + PurpleKeyringImportPassword import_password) +{ + info->import_password = import_password; +} +void +purple_keyring_set_export_password(PurpleKeyring * info, + PurpleKeyringExportPassword export_password) +{ + info->export_password = export_password; +} + + + /* PurpleKeyringPasswordNode */ + +PurpleKeyringPasswordNode * +purple_keyring_password_node_new(void) +{ + PurpleKeyringPasswordNode * ret; + + ret = g_malloc(sizeof(PurpleKeyringPasswordNode)); + return ret; +} + +void +purple_keyring_password_node_free(PurpleKeyringPasswordNode * node) +{ + g_free(PurpleKeyringPasswordNode * node); + return; +} + +PurpleAccount * +purple_keyring_password_node_get_account(PurpleKeyringPasswordNode * info) +{ + return info->account; +} + +const char * +purple_keyring_password_node_get_encryption(PurpleKeyringPasswordNode * info) +{ + return info->encryption; +} + +const char * +purple_keyring_password_node_get_mode(PurpleKeyringPasswordNode * info) +{ + return info->mode; +} + +const char * +purple_keyring_password_node_get_data(PurpleKeyringPasswordNode * info); +{ + return info->data; +} + + +void +purple_keyring_password_node_set_account(PurpleKeyringPasswordNode * info, + PurpleAccount * account) +{ + info->account = account; + return; +} + +void +purple_keyring_password_node_set_encryption(PurpleKeyringPasswordNode * info, + const char * encryption) +{ + info->encryption = encryption; + return; +} + +void +purple_keyring_password_node_set_mode(PurpleKeyringPasswordNode * info, + const char * mode) +{ + info->mode = mode; + return; +} + +void +purple_keyring_password_node_set_data(PurpleKeyringPasswordNode * info, + const char * data) +{ + info->data = data; + return; +} + + +/** + * prepare stuff (called at startup) + * TODO : see if we need to cleanup + */ +void purple_keyring_init() +{//FIXME + /** + * init error GQuark (FIXME change it in headers as well) + * read safe to use in confing + * make sure said safe is loaded + * else fallback + */ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/plugins/keyrings/internalkeyring.c Wed Jul 09 00:08:41 2008 +0000 @@ -0,0 +1,323 @@ +/* TODO + - fix error reporting + - uses accessors for PurpleKeyringPasswordNode + - use hashtable instead of Glib + - plugin interface + - keyring info struct +*/ + +#include <glib.h> +#include <string.h> +#include "keyring.h" +#include "account.h" + +/******************************/ +/** Macros and constants */ +/******************************/ + +#define INTERNALKEYRING_VERSION "0.2a" +#define INTERNALKEYRING_ID "???" +#define INTERNALKEYRING_AUTHOR "Vivien Bernet-Rollande <vbernetr@etu.utc.fr>" +#define INTERNALKEYRING_DESCRIPTION \ + "This keyring plugin offers a password storage backend compatible with the former storage system." + +#define IS_VALID_CLEARTEXT_INFO(nodeinfo) \ + (((nodeinfo->encryption == NULL) || (strcpy(nodeinfo->encryption, KEYRINGNAME) == 0)) \ + && ((nodeinfo->mode == NULL) || (strcpy(nodeinfo->mode, "cleartext") == 0)) \ + && (nodeinfo->data != NULL) && (nodeinfo->account != NULL)) + + +/******************************/ +/** Data Structures */ +/******************************/ + +typedef stuct _InternalKeyring_PasswordInfo InternalKeyring_PasswordInfo; + +struct _InternalKeyring_PasswordInfo { + PurpleAccount * account; + gchar * password; +}; + +/******************************/ +/** Globals */ +/******************************/ + +GList * InternalKeyring_passwordlist = NULL; /* use hashtable ? */ + + +/******************************/ +/** Internal functions */ +/******************************/ + +/** + * retrieve the InternalKeyring_PasswordInfo structure for an account + * TODO : rewrite this to use hashtables rather than GList + */ +PasswordInfo * InternalKeyring_get_account_info(PurpleAccount * account) +{ + GList * p; + InternalKeyring_PasswordInfo i; + + for (p = InternalKeyring_passworlist; p != NULL; p = p->next) { + i = (PasswordInfo)(p->data) + if (i->account == account) + return i; + } + return NULL; +} + +/** + * Free or create an InternalKeyring_PasswordInfo structure and all pointed data. + * /!\ Update this when adding fields to InternalKeyring_PasswordInfo + * TODO : rewrite this to use hashtables rather than GList + * (fix InternalKeyring_Close() as well) + */ +void +InternalKeyring_add_passwordinfo(InternalKeyring_PasswordInfo * info) +{ + InternalKeyring_passwordlist = g_list_prepend(InternalKeyring_passwordlist, info); + return; +} + +void +InternalKeyring_free_passwordinfo(InternalKeyring_PasswordInfo * info) +{ + g_free(info->password); + g_list_remove(InternalKeyring_passwordlist, info); + g_free(info); + return; +} + + +/******************************/ +/** Keyring interface */ +/******************************/ + +/** + * returns the password if the password is known. + */ +void +InternalKeyring_read(const PurpleAccount * account, + GError ** error, + PurpleKeyringReadCallback cb, + gpointer data) +{ + InternalKeyring_PasswordInfo * info; + char * ret; + + info = InternalKeyring_get_account_info(account); + + if ( info == NULL ) { /* no info on account */ + + g_set_error(error, ERR_PIDGINKEYRING, ERR_NOACCOUNT, + "No info for account."); + cb(account, NULL, error, data); + return; + + } else if (info->password == NULL) { /* unknown password */ + + g_set_error(error, ERR_PIDGINKEYRING, ERR_NOPASSWD, + "No Password for this account."); + cb(account, NULL, error, data); + return; + + } else { + + ret = info->password; + cb(account, ret, error, data); + } +} + +/* + * save a new password + */ +void +InternalKeyring_save(const PurpleAccount * account, + gchar * password, + GError ** error, import + PurpleKeyringSaveCallback cb, + gpointer data) +{ + InternalKeyring_PasswordInfo info; + + info = InternalKeyring_get_account_info(account); + + if (password == NULL) { + /* forget password */ + if (info == NULL) { + g_set_error(error, ERR_PIDGINKEYRING, ERR_NOPASSWD, + "No Password for this account."); + cb(account, error, data); + return; + } + + InternalKeyring_free_passwordinfo(info); + + if (cb != NULL) + cb(account, error, data); + return; + + } else { /* password != NULL */ + + if ( info == null ) { + info = g_malloc0(sizeof (InternalKeyring_PasswordInfo)); + InternalKeyring_add_passwordinfo(info); + } + + /* if we already had a password, forget about it */ + if ( info->password != NULL ) + g_free(info->password); + + info->password = g_malloc(strlen( password + 1 )); + strcpy(info->password, password); + + if (cb != NULL) + cb(account, error, data); + return; + } +} + +/* + * clears and frees all PasswordInfo structures. + * TODO : rewrite using Hashtable + */ +void +InternalKeyring_Close(GError ** error) +{ + g_list_foreach(InternalKeyring_passwordlist, InternalKeyring_free_passwordinfo, + NULL); + return; +} + +/* + * does nothing since we don't want to free the stored info + */ +void +InternalKeyring_free(gchar * password, + GError ** error) +{ + return; /* nothing to free or cleanup until we forget the password */ +} + +/** + * Imports password info from a PurpleKeyringPasswordNode structure + * (called for each account when accounts.xml is parsed) + * returns TRUE if sucessful, FALSE otherwise. + * TODO : add error reporting + * use accessors for PurpleKeyringPasswordNode (FIXME) + * FIXME : REWRITE AS ASYNC + */ +gboolean +InternalKeyring_import_password(PurpleKeyringPasswordNode * nodeinfo) +{ + InternalKeyring_PasswordInfo * pwinfo; + + if (IS_VALID_CLEARTEXT_INFO(nodeinfo) { + + pwinfo = g_malloc0(sizeof(InternalKeyring_PasswordInfo)); + InternalKeyring_add_passwordinfo(pwinfo); + + pwinfo->password = g_malloc(strlen(nodeinfo->data) + 1); + strcpy(pwinfo->password, nodeinfo->data); + + pwinfo->account = nodeinfo->account; + + return TRUE; + + } else { + /* invalid input */ + return FALSE; + } +} + + +/** + * Exports password info to a PurpleKeyringPasswordNode structure + * (called for each account when accounts are synced) + * TODO : add error reporting + * use accessors for PurpleKeyringPasswordNode (FIXME) + * FIXME : REWRITE AS ASYNC + */ +PurpleKeyringPasswordNode * +InternalKeyring_export_password(PurpleAccount * account) +{ + PurpleKeyringPasswordNode * nodeinfo + InternalKeyring_PasswordInfo pwinfo; + + nodeinfo = purple_keyring_password_node_new(); + pwinfo = InternalKeyring_get_account_info(account); + + if (pwinfo->password == NULL) + return NULL; + else { + purple_keyring_password_node_set_encryption(nodeinfo, KEYRINGNAME); + purple_keyring_password_node_set_mode(nodeinfo, "cleartext"); + purple_keyring_password_node_set_data(nodeinfo, password); + + return nodeinfo; + } +} + + +/******************************/ +/** Plugin interface */ +/******************************/ + +gboolean +InternalKeyring_load(PurplePlugin *plugin) +{ + purple_plugin_keyring_register(InternalKeyring_KeyringInfo); + return TRUE; +} + +/** + * TODO : handle error, maybe return FALSE on problem + * (no reason for it to fail unless data is corrupted though) + */ +gboolean +InternalKeyring_unload(PurplePlugin *plugin) +{ + InternalKeyring_Close(NULL); + return TRUE; +} + +void +InternalKeyring_destroy(PurplePlugin *plugin) +{ + InternalKeyring_Close(NULL); + return; +} + +/******************************/ +/** Generic plugin stuff */ +/******************************/ + +PurplePluginInfo plugininfo = +{ + PURPLE_PLUGIN_MAGIC, /* magic */ + PURPLE_MAJOR_VERSION, /* major_version */ + PURPLE_MINOR_VERSION, /* minor_version */ + PURPLE_PLUGIN_STANDARD, /* type */ + NULL, /* ui_requirement */ + PURPLE_PLUGIN_FLAG_INVISIBLE|PURPLE_PLUGIN_FLAG_AUTOLOAD, /* flags */ + NULL, /* dependencies */ + PURPLE_PRIORITY_DEFAULT, /* priority */ + INTERNALKEYRING_ID, /* id */ + "internal-keyring-plugin", /* name */ + INTERNALKEYRING_VERSION, /* version */ + "Internal Keyring Plugin", /* summary */ + INTERNALKEYRING_DESCRIPTION, /* description */ + INTERNALKEYRING_AUTHOR, /* author */ + "N/A", /* homepage */ + InternalKeyring_load, /* load */ + InternalKeyring_unload, /* unload */ + InternalKeyring_destroy, /* destroy */ + NULL, /* ui_info */ + NULL, /* extra_info */ + NULL, /* prefs_info */ + NULL, /* actions */ + NULL, /* padding... */ + NULL, + NULL, + NULL, +};