Sun, 23 Jun 2013 13:35:53 +0530
Merged default branch
--- a/.hgignore Sun Jun 23 02:43:06 2013 -0500 +++ b/.hgignore Sun Jun 23 13:35:53 2013 +0530 @@ -59,6 +59,7 @@ libpurple/dbus-signals.c libpurple/dbus-types.c libpurple/dbus-types.h +libpurple/enums.[ch] libpurple/example/nullclient libpurple/gconf/purple.schemas$ libpurple/marshallers.[ch]
--- a/configure.ac Sun Jun 23 02:43:06 2013 -0500 +++ b/configure.ac Sun Jun 23 13:35:53 2013 +0530 @@ -353,6 +353,9 @@ GLIB_GENMARSHAL=`pkg-config --variable=glib_genmarshal glib-2.0` AC_SUBST(GLIB_GENMARSHAL) +GLIB_MKENUMS=`pkg-config --variable=glib_mkenums glib-2.0` +AC_SUBST(GLIB_MKENUMS) + AC_ARG_WITH([extraversion], AS_HELP_STRING([--with-extraversion=STRING], [extra version number to be displayed in Help->About and --help (for packagers)]),
--- a/finch/gntaccount.c Sun Jun 23 02:43:06 2013 -0500 +++ b/finch/gntaccount.c Sun Jun 23 13:35:53 2013 +0530 @@ -188,7 +188,7 @@ /* Alias */ value = gnt_entry_get_text(GNT_ENTRY(dialog->alias)); - purple_account_set_alias(account, value); + purple_account_set_private_alias(account, value); /* Remember password and password */ purple_account_set_remember_password(account, @@ -628,7 +628,7 @@ gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Alias:"))); gnt_box_add_widget(GNT_BOX(hbox), entry); if (account) - gnt_entry_set_text(GNT_ENTRY(entry), purple_account_get_alias(account)); + gnt_entry_set_text(GNT_ENTRY(entry), purple_account_get_private_alias(account)); /* User options */ update_user_options(dialog); @@ -1157,7 +1157,8 @@ NULL, NULL, NULL, - NULL + NULL, + NULL, NULL, NULL, NULL }; PurpleAccountUiOps *finch_accounts_get_ui_ops()
--- a/finch/gntblist.c Sun Jun 23 02:43:06 2013 -0500 +++ b/finch/gntblist.c Sun Jun 23 13:35:53 2013 +0530 @@ -30,7 +30,6 @@ #include <blist.h> #include <log.h> #include <notify.h> -#include <privacy.h> #include <request.h> #include <savedstatuses.h> #include <server.h> @@ -1267,8 +1266,8 @@ PurpleAccount *account = purple_buddy_get_account(buddy); const char *name = purple_buddy_get_name(buddy); - block ? purple_privacy_deny(account, name, FALSE, FALSE) : - purple_privacy_allow(account, name, FALSE, FALSE); + block ? purple_account_privacy_deny(account, name) : + purple_account_privacy_allow(account, name); } static void @@ -1310,7 +1309,7 @@ } account = purple_buddy_get_account(buddy); - permitted = purple_privacy_check(account, purple_buddy_get_name(buddy)); + permitted = purple_account_privacy_check(account, purple_buddy_get_name(buddy)); item = gnt_menuitem_check_new(_("Blocked")); gnt_menuitem_check_set_checked(GNT_MENU_ITEM_CHECK(item), !permitted); @@ -2673,9 +2672,9 @@ const char *name = purple_request_fields_get_string(fields, "screenname"); if (account && name && *name != '\0') { if (purple_request_fields_get_choice(fields, "block") == 1) { - purple_privacy_deny(account, name, FALSE, FALSE); + purple_account_privacy_deny(account, name); } else { - purple_privacy_allow(account, name, FALSE, FALSE); + purple_account_privacy_allow(account, name); } } }
--- a/finch/gntconv.c Sun Jun 23 02:43:06 2013 -0500 +++ b/finch/gntconv.c Sun Jun 23 13:35:53 2013 +0530 @@ -1063,7 +1063,7 @@ { who = purple_connection_get_display_name(purple_account_get_connection(account)); if (!who) - who = purple_account_get_alias(account); + who = purple_account_get_private_alias(account); if (!who) who = purple_account_get_username(account); }
--- a/finch/gntpounce.c Sun Jun 23 02:43:06 2013 -0500 +++ b/finch/gntpounce.c Sun Jun 23 13:35:53 2013 +0530 @@ -849,7 +849,7 @@ * NULL to the account alias if we have it or the account * name if that's all we have */ - if ((name_shown = purple_account_get_alias(account)) == NULL) + if ((name_shown = purple_account_get_private_alias(account)) == NULL) name_shown = purple_account_get_username(account); if (reason == NULL)
--- a/libpurple/Makefile.am Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/Makefile.am Sun Jun 23 13:35:53 2013 +0530 @@ -38,20 +38,24 @@ purple_coresources = \ account.c \ + accounts.c \ accountopt.c \ blist.c \ buddyicon.c \ certificate.c \ cipher.c \ - circbuffer.c \ + circularbuffer.c \ cmds.c \ connection.c \ conversation.c \ + conversationtypes.c \ + conversations.c \ core.c \ debug.c \ desktopitem.c \ eventloop.c \ ft.c \ + hash.c \ http.c \ idle.c \ imgstore.c \ @@ -74,7 +78,6 @@ pluginpref.c \ pounce.c \ prefs.c \ - privacy.c \ proxy.c \ prpl.c \ request.c \ @@ -103,25 +106,30 @@ whiteboard.c purple_builtsources = \ + enums.c \ marshallers.c purple_coreheaders = \ account.h \ + accounts.h \ accountopt.h \ blist.h \ buddyicon.h \ certificate.h \ cipher.h \ - circbuffer.h \ + circularbuffer.h \ cmds.h \ connection.h \ conversation.h \ + conversationtypes.h \ + conversations.h \ core.h \ dbus-maybe.h \ debug.h \ desktopitem.h \ eventloop.h \ ft.h \ + hash.h \ http.h \ idle.h \ imgstore.h \ @@ -139,7 +147,6 @@ pluginpref.h \ pounce.h \ prefs.h \ - privacy.h \ proxy.h \ prpl.h \ request.h \ @@ -172,7 +179,23 @@ codec.h \ enum-types.h -purple_builtheaders = purple.h version.h marshallers.h +purple_builtheaders = purple.h version.h enums.h marshallers.h + +purple_enumheaders = \ + account.h \ + accounts.h \ + cipher.h \ + circularbuffer.h \ + conversation.h \ + conversationtypes.h \ + conversations.h \ + hash.h \ + smiley.h \ + sound-theme.h \ + sound-theme-loader.h \ + theme.h \ + theme-loader.h \ + theme-manager.h marshallers.h: marshallers.list $(AM_V_GEN)$(GLIB_GENMARSHAL) --prefix=purple_smarshal $(srcdir)/marshallers.list --header > marshallers.h @@ -181,6 +204,12 @@ $(AM_V_GEN)echo "#include \"marshallers.h\"" > marshallers.c $(AM_V_at)$(GLIB_GENMARSHAL) --prefix=purple_smarshal $(srcdir)/marshallers.list --body >> marshallers.c +enums.h: enums.h.template $(purple_enumheaders) + $(AM_V_GEN)$(GLIB_MKENUMS) --template enums.h.template $(purple_enumheaders) > $@ + +enums.c: enums.c.template $(purple_enumheaders) + $(AM_V_GEN)$(GLIB_MKENUMS) --template enums.c.template $(purple_enumheaders) > $@ + if ENABLE_DBUS CLEANFILES = \ @@ -190,6 +219,8 @@ dbus-signals.c \ dbus-types.c \ dbus-types.h \ + enums.c \ + enums.h \ marshallers.c \ marshallers.h \ purple-client-bindings.c \ @@ -201,8 +232,8 @@ dbus_sources = dbus-server.c dbus-useful.c dbus_headers = dbus-bindings.h dbus-purple.h dbus-server.h dbus-useful.h dbus-define-api.h dbus-types.h -dbus_exported = dbus-useful.h dbus-define-api.h account.h blist.h buddyicon.h \ - connection.h conversation.h core.h ft.h log.h notify.h prefs.h roomlist.h \ +dbus_exported = dbus-useful.h dbus-define-api.h accounts.h blist.h buddyicon.h \ + connection.h conversations.h core.h ft.h log.h notify.h prefs.h roomlist.h \ savedstatuses.h smiley.h status.h server.h util.h xmlnode.h prpl.h purple_build_coreheaders = $(addprefix $(srcdir)/, $(purple_coreheaders)) \ @@ -304,7 +335,10 @@ mediainclude_HEADERS = \ $(addprefix $(srcdir)/media/, $(purple_mediaheaders)) -libpurple_la_DEPENDENCIES = $(STATIC_LINK_LIBS) +libpurple_la_DEPENDENCIES = \ + $(STATIC_LINK_LIBS) \ + ciphers/libpurple-ciphers.la + libpurple_la_LDFLAGS = -export-dynamic -version-info $(PURPLE_LT_VERSION_INFO) -no-undefined libpurple_la_LIBADD = \ $(STATIC_LINK_LIBS) \
--- a/libpurple/Makefile.mingw Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/Makefile.mingw Sun Jun 23 13:35:53 2013 +0530 @@ -61,22 +61,27 @@ C_SRC = \ account.c \ + accounts.c \ accountopt.c \ blist.c \ buddyicon.c \ certificate.c \ cipher.c \ - ciphers/aes.c \ - ciphers/des.c \ - ciphers/gchecksum.c \ - ciphers/hmac.c \ - ciphers/md4.c \ - ciphers/pbkdf2.c \ - ciphers/rc4.c \ - circbuffer.c \ + ciphers/aescipher.c \ + ciphers/des3cipher.c \ + ciphers/descipher.c \ + ciphers/hmaccipher.c \ + ciphers/md4hash.c \ + ciphers/md5hash.c \ + ciphers/pbkdf2cipher.c \ + ciphers/rc4cipher.c \ + ciphers/sha1hash.c \ + ciphers/sha256hash.c \ + circularbuffer.c \ cmds.c \ connection.c \ conversation.c \ + conversations.c \ core.c \ debug.c \ dnsquery.c \
--- a/libpurple/account.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/account.c Sun Jun 23 13:35:53 2013 +0530 @@ -24,38 +24,77 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ #include "internal.h" -#include "account.h" +#include "accounts.h" #include "core.h" #include "dbus-maybe.h" #include "debug.h" -#include "keyring.h" #include "network.h" #include "notify.h" #include "pounce.h" #include "prefs.h" -#include "privacy.h" -#include "prpl.h" #include "request.h" #include "server.h" #include "signals.h" -#include "status.h" #include "util.h" -#include "xmlnode.h" - -/* TODO: Should use PurpleValue instead of this? What about "ui"? */ + +#define PURPLE_ACCOUNT_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_ACCOUNT, PurpleAccountPrivate)) + typedef struct { - PurplePrefType type; - + char *username; /**< The username. */ + char *alias; /**< How you appear to yourself. */ + char *password; /**< The account password. */ + char *user_info; /**< User information. */ + + char *buddy_icon_path; /**< The buddy icon's non-cached path. */ + + gboolean remember_pass; /**< Remember the password. */ + + /* + * TODO: After a GObject representing a protocol is ready, use it + * here instead of the protocol ID. + */ + char *protocol_id; /**< The ID of the protocol. */ + + PurpleConnection *gc; /**< The connection handle. */ + gboolean disconnecting; /**< The account is currently disconnecting */ + + GHashTable *settings; /**< Protocol-specific settings. */ + GHashTable *ui_settings; /**< UI-specific settings. */ + + PurpleProxyInfo *proxy_info; /**< Proxy information. This will be set */ + /* to NULL when the account inherits */ + /* proxy settings from global prefs. */ + + /* + * TODO: Supplementing the next two linked lists with hash tables + * should help performance a lot when these lists are long. This + * matters quite a bit for protocols like MSN, where all your + * buddies are added to your permit list. Currently we have to + * iterate through the entire list if we want to check if someone + * is permitted or denied. We should do this for 3.0.0. + * Or maybe use a GTree. + */ + GSList *permit; /**< Permit list. */ + GSList *deny; /**< Deny list. */ + PurpleAccountPrivacyType privacy_type; /**< The permit/deny setting. */ + + GList *status_types; /**< Status types. */ + + PurplePresence *presence; /**< Presence. */ + PurpleLog *system_log; /**< The system log */ + + PurpleAccountRegistrationCb registration_cb; + void *registration_cb_user_data; + + PurpleConnectionErrorInfo *current_error; /**< Errors */ +} PurpleAccountPrivate; + +typedef struct +{ char *ui; - - union - { - int integer; - char *string; - gboolean boolean; - - } value; + GValue value; } PurpleAccountSetting; @@ -77,1073 +116,37 @@ gpointer data; } PurpleCallbackBundle; -static PurpleAccountUiOps *account_ui_ops = NULL; - -static GList *accounts = NULL; -static guint save_timer = 0; -static gboolean accounts_loaded = FALSE; - -static GList *handles = NULL; - -static void set_current_error(PurpleAccount *account, - PurpleConnectionErrorInfo *new_err); - -/********************************************************************* - * Writing to disk * - *********************************************************************/ - -static void -setting_to_xmlnode(gpointer key, gpointer value, gpointer user_data) -{ - const char *name; - PurpleAccountSetting *setting; - xmlnode *node, *child; - char buf[21]; - - name = (const char *)key; - setting = (PurpleAccountSetting *)value; - node = (xmlnode *)user_data; - - child = xmlnode_new_child(node, "setting"); - xmlnode_set_attrib(child, "name", name); - - if (setting->type == PURPLE_PREF_INT) { - xmlnode_set_attrib(child, "type", "int"); - g_snprintf(buf, sizeof(buf), "%d", setting->value.integer); - xmlnode_insert_data(child, buf, -1); - } - else if (setting->type == PURPLE_PREF_STRING && setting->value.string != NULL) { - xmlnode_set_attrib(child, "type", "string"); - xmlnode_insert_data(child, setting->value.string, -1); - } - else if (setting->type == PURPLE_PREF_BOOLEAN) { - xmlnode_set_attrib(child, "type", "bool"); - g_snprintf(buf, sizeof(buf), "%d", setting->value.boolean); - xmlnode_insert_data(child, buf, -1); - } -} - -static void -ui_setting_to_xmlnode(gpointer key, gpointer value, gpointer user_data) -{ - const char *ui; - GHashTable *table; - xmlnode *node, *child; - - ui = (const char *)key; - table = (GHashTable *)value; - node = (xmlnode *)user_data; - - if (g_hash_table_size(table) > 0) - { - child = xmlnode_new_child(node, "settings"); - xmlnode_set_attrib(child, "ui", ui); - g_hash_table_foreach(table, setting_to_xmlnode, child); - } -} - -static xmlnode * -status_attr_to_xmlnode(const PurpleStatus *status, const PurpleStatusType *type, const PurpleStatusAttr *attr) -{ - xmlnode *node; - const char *id; - char *value = NULL; - PurpleStatusAttr *default_attr; - PurpleValue *default_value; - PurpleType attr_type; - PurpleValue *attr_value; - - id = purple_status_attr_get_id(attr); - g_return_val_if_fail(id, NULL); - - attr_value = purple_status_get_attr_value(status, id); - g_return_val_if_fail(attr_value, NULL); - attr_type = purple_value_get_type(attr_value); - - /* - * If attr_value is a different type than it should be - * then don't write it to the file. - */ - default_attr = purple_status_type_get_attr(type, id); - default_value = purple_status_attr_get_value(default_attr); - if (attr_type != purple_value_get_type(default_value)) - return NULL; - - /* - * If attr_value is the same as the default for this status - * then there is no need to write it to the file. - */ - if (attr_type == PURPLE_TYPE_STRING) - { - const char *string_value = purple_value_get_string(attr_value); - const char *default_string_value = purple_value_get_string(default_value); - if (purple_strequal(string_value, default_string_value)) - return NULL; - value = g_strdup(purple_value_get_string(attr_value)); - } - else if (attr_type == PURPLE_TYPE_INT) - { - int int_value = purple_value_get_int(attr_value); - if (int_value == purple_value_get_int(default_value)) - return NULL; - value = g_strdup_printf("%d", int_value); - } - else if (attr_type == PURPLE_TYPE_BOOLEAN) - { - gboolean boolean_value = purple_value_get_boolean(attr_value); - if (boolean_value == purple_value_get_boolean(default_value)) - return NULL; - value = g_strdup(boolean_value ? - "true" : "false"); - } - else - { - return NULL; - } - - g_return_val_if_fail(value, NULL); - - node = xmlnode_new("attribute"); - - xmlnode_set_attrib(node, "id", id); - xmlnode_set_attrib(node, "value", value); - - g_free(value); - - return node; -} - -static xmlnode * -status_attrs_to_xmlnode(const PurpleStatus *status) -{ - PurpleStatusType *type = purple_status_get_type(status); - xmlnode *node, *child; - GList *attrs, *attr; - - node = xmlnode_new("attributes"); - - attrs = purple_status_type_get_attrs(type); - for (attr = attrs; attr != NULL; attr = attr->next) - { - child = status_attr_to_xmlnode(status, type, (const PurpleStatusAttr *)attr->data); - if (child) - xmlnode_insert_child(node, child); - } - - return node; -} - -static xmlnode * -status_to_xmlnode(const PurpleStatus *status) -{ - xmlnode *node, *child; - - node = xmlnode_new("status"); - xmlnode_set_attrib(node, "type", purple_status_get_id(status)); - if (purple_status_get_name(status) != NULL) - xmlnode_set_attrib(node, "name", purple_status_get_name(status)); - xmlnode_set_attrib(node, "active", purple_status_is_active(status) ? "true" : "false"); - - child = status_attrs_to_xmlnode(status); - xmlnode_insert_child(node, child); - - return node; -} - -static xmlnode * -statuses_to_xmlnode(const PurplePresence *presence) -{ - xmlnode *node, *child; - GList *statuses; - PurpleStatus *status; - - node = xmlnode_new("statuses"); - - statuses = purple_presence_get_statuses(presence); - for (; statuses != NULL; statuses = statuses->next) - { - status = statuses->data; - if (purple_status_type_is_saveable(purple_status_get_type(status))) - { - child = status_to_xmlnode(status); - xmlnode_insert_child(node, child); - } - } - - return node; -} - -static xmlnode * -proxy_settings_to_xmlnode(PurpleProxyInfo *proxy_info) -{ - xmlnode *node, *child; - PurpleProxyType proxy_type; - const char *value; - int int_value; - char buf[21]; - - proxy_type = purple_proxy_info_get_type(proxy_info); - - node = xmlnode_new("proxy"); - - child = xmlnode_new_child(node, "type"); - xmlnode_insert_data(child, - (proxy_type == PURPLE_PROXY_USE_GLOBAL ? "global" : - proxy_type == PURPLE_PROXY_NONE ? "none" : - proxy_type == PURPLE_PROXY_HTTP ? "http" : - proxy_type == PURPLE_PROXY_SOCKS4 ? "socks4" : - proxy_type == PURPLE_PROXY_SOCKS5 ? "socks5" : - proxy_type == PURPLE_PROXY_TOR ? "tor" : - proxy_type == PURPLE_PROXY_USE_ENVVAR ? "envvar" : "unknown"), -1); - - if ((value = purple_proxy_info_get_host(proxy_info)) != NULL) - { - child = xmlnode_new_child(node, "host"); - xmlnode_insert_data(child, value, -1); - } - - if ((int_value = purple_proxy_info_get_port(proxy_info)) != 0) - { - g_snprintf(buf, sizeof(buf), "%d", int_value); - child = xmlnode_new_child(node, "port"); - xmlnode_insert_data(child, buf, -1); - } - - if ((value = purple_proxy_info_get_username(proxy_info)) != NULL) - { - child = xmlnode_new_child(node, "username"); - xmlnode_insert_data(child, value, -1); - } - - if ((value = purple_proxy_info_get_password(proxy_info)) != NULL) - { - child = xmlnode_new_child(node, "password"); - xmlnode_insert_data(child, value, -1); - } - - return node; -} - -static xmlnode * -current_error_to_xmlnode(PurpleConnectionErrorInfo *err) -{ - xmlnode *node, *child; - char type_str[3]; - - node = xmlnode_new("current_error"); - - if(err == NULL) - return node; - - /* It doesn't make sense to have transient errors persist across a - * restart. - */ - if(!purple_connection_error_is_fatal (err->type)) - return node; - - child = xmlnode_new_child(node, "type"); - g_snprintf(type_str, sizeof(type_str), "%u", err->type); - xmlnode_insert_data(child, type_str, -1); - - child = xmlnode_new_child(node, "description"); - if(err->description) { - char *utf8ized = purple_utf8_try_convert(err->description); - if(utf8ized == NULL) - utf8ized = purple_utf8_salvage(err->description); - xmlnode_insert_data(child, utf8ized, -1); - g_free(utf8ized); - } - - return node; -} - -static xmlnode * -account_to_xmlnode(PurpleAccount *account) -{ - xmlnode *node, *child; - const char *tmp; - PurplePresence *presence; - PurpleProxyInfo *proxy_info; - - node = xmlnode_new("account"); - - child = xmlnode_new_child(node, "protocol"); - xmlnode_insert_data(child, purple_account_get_protocol_id(account), -1); - - child = xmlnode_new_child(node, "name"); - xmlnode_insert_data(child, purple_account_get_username(account), -1); - - if (purple_account_get_remember_password(account)) - { - const char *keyring_id = NULL; - const char *mode = NULL; - char *data = NULL; - GError *error = NULL; - GDestroyNotify destroy = NULL; - gboolean exported = purple_keyring_export_password(account, - &keyring_id, &mode, &data, &error, &destroy); - - if (error != NULL) { - purple_debug_error("account", - "Failed to export password for account %s: %s.\n", - purple_account_get_username(account), - error->message); - } else if (exported) { - child = xmlnode_new_child(node, "password"); - if (keyring_id != NULL) - xmlnode_set_attrib(child, "keyring_id", keyring_id); - if (mode != NULL) - xmlnode_set_attrib(child, "mode", mode); - if (data != NULL) - xmlnode_insert_data(child, data, -1); - - if (destroy != NULL) - destroy(data); - } - } - - if ((tmp = purple_account_get_alias(account)) != NULL) - { - child = xmlnode_new_child(node, "alias"); - xmlnode_insert_data(child, tmp, -1); - } - - if ((presence = purple_account_get_presence(account)) != NULL) - { - child = statuses_to_xmlnode(presence); - xmlnode_insert_child(node, child); - } - - if ((tmp = purple_account_get_user_info(account)) != NULL) - { - /* TODO: Do we need to call purple_str_strip_char(tmp, '\r') here? */ - child = xmlnode_new_child(node, "userinfo"); - xmlnode_insert_data(child, tmp, -1); - } - - if (g_hash_table_size(account->settings) > 0) - { - child = xmlnode_new_child(node, "settings"); - g_hash_table_foreach(account->settings, setting_to_xmlnode, child); - } - - if (g_hash_table_size(account->ui_settings) > 0) - { - g_hash_table_foreach(account->ui_settings, ui_setting_to_xmlnode, node); - } - - if ((proxy_info = purple_account_get_proxy_info(account)) != NULL) - { - child = proxy_settings_to_xmlnode(proxy_info); - xmlnode_insert_child(node, child); - } - - child = current_error_to_xmlnode(account->current_error); - xmlnode_insert_child(node, child); - - return node; -} - -static xmlnode * -accounts_to_xmlnode(void) -{ - xmlnode *node, *child; - GList *cur; - - node = xmlnode_new("account"); - xmlnode_set_attrib(node, "version", "1.0"); - - for (cur = purple_accounts_get_all(); cur != NULL; cur = cur->next) - { - child = account_to_xmlnode(cur->data); - xmlnode_insert_child(node, child); - } - - return node; -} - -static void -sync_accounts(void) -{ - xmlnode *node; - char *data; - - if (!accounts_loaded) - { - purple_debug_error("account", "Attempted to save accounts before " - "they were read!\n"); - return; - } - - node = accounts_to_xmlnode(); - data = xmlnode_to_formatted_str(node, NULL); - purple_util_write_data_to_file("accounts.xml", data, -1); - g_free(data); - xmlnode_free(node); -} - -static gboolean -save_cb(gpointer data) -{ - sync_accounts(); - save_timer = 0; - return FALSE; -} - -static void -schedule_accounts_save(void) -{ - if (save_timer == 0) - save_timer = purple_timeout_add_seconds(5, save_cb, NULL); -} - - -/********************************************************************* - * Reading from disk * - *********************************************************************/ -static void -migrate_yahoo_japan(PurpleAccount *account) -{ - /* detect a Yahoo! JAPAN account that existed prior to 2.6.0 and convert it - * to use the new prpl-yahoojp. Also remove the account-specific settings - * we no longer need */ - - if(purple_strequal(purple_account_get_protocol_id(account), "prpl-yahoo")) { - if(purple_account_get_bool(account, "yahoojp", FALSE)) { - const char *serverjp = purple_account_get_string(account, "serverjp", NULL); - const char *xferjp_host = purple_account_get_string(account, "xferjp_host", NULL); - - g_return_if_fail(serverjp != NULL); - g_return_if_fail(xferjp_host != NULL); - - purple_account_set_string(account, "server", serverjp); - purple_account_set_string(account, "xfer_host", xferjp_host); - - purple_account_set_protocol_id(account, "prpl-yahoojp"); - } - - /* these should always be nuked */ - purple_account_remove_setting(account, "yahoojp"); - purple_account_remove_setting(account, "serverjp"); - purple_account_remove_setting(account, "xferjp_host"); - - } -} - -static void -migrate_icq_server(PurpleAccount *account) -{ - /* Migrate the login server setting for ICQ accounts. See - * 'mtn log --last 1 --no-graph --from b6d7712e90b68610df3bd2d8cbaf46d94c8b3794' - * for details on the change. */ - - if(purple_strequal(purple_account_get_protocol_id(account), "prpl-icq")) { - const char *tmp = purple_account_get_string(account, "server", NULL); - - /* Non-secure server */ - if(purple_strequal(tmp, "login.messaging.aol.com") || - purple_strequal(tmp, "login.oscar.aol.com")) - purple_account_set_string(account, "server", "login.icq.com"); - - /* Secure server */ - if(purple_strequal(tmp, "slogin.oscar.aol.com")) - purple_account_set_string(account, "server", "slogin.icq.com"); - } -} - -static void -migrate_xmpp_encryption(PurpleAccount *account) -{ - /* When this is removed, nuke the "old_ssl" and "require_tls" settings */ - if (g_str_equal(purple_account_get_protocol_id(account), "prpl-jabber")) { - const char *sec = purple_account_get_string(account, "connection_security", ""); - - if (g_str_equal("", sec)) { - const char *val = "require_tls"; - if (purple_account_get_bool(account, "old_ssl", FALSE)) - val = "old_ssl"; - else if (!purple_account_get_bool(account, "require_tls", TRUE)) - val = "opportunistic_tls"; - - purple_account_set_string(account, "connection_security", val); - } - } -} - -static void -parse_settings(xmlnode *node, PurpleAccount *account) +/* GObject Property enums */ +enum { - const char *ui; - xmlnode *child; - - /* Get the UI string, if these are UI settings */ - ui = xmlnode_get_attrib(node, "ui"); - - /* Read settings, one by one */ - for (child = xmlnode_get_child(node, "setting"); child != NULL; - child = xmlnode_get_next_twin(child)) - { - const char *name, *str_type; - PurplePrefType type; - char *data; - - name = xmlnode_get_attrib(child, "name"); - if (name == NULL) - /* Ignore this setting */ - continue; - - str_type = xmlnode_get_attrib(child, "type"); - if (str_type == NULL) - /* Ignore this setting */ - continue; - - if (purple_strequal(str_type, "string")) - type = PURPLE_PREF_STRING; - else if (purple_strequal(str_type, "int")) - type = PURPLE_PREF_INT; - else if (purple_strequal(str_type, "bool")) - type = PURPLE_PREF_BOOLEAN; - else - /* Ignore this setting */ - continue; - - data = xmlnode_get_data(child); - if (data == NULL) - /* Ignore this setting */ - continue; - - if (ui == NULL) - { - if (type == PURPLE_PREF_STRING) - purple_account_set_string(account, name, data); - else if (type == PURPLE_PREF_INT) - purple_account_set_int(account, name, atoi(data)); - else if (type == PURPLE_PREF_BOOLEAN) - purple_account_set_bool(account, name, - (*data == '0' ? FALSE : TRUE)); - } else { - if (type == PURPLE_PREF_STRING) - purple_account_set_ui_string(account, ui, name, data); - else if (type == PURPLE_PREF_INT) - purple_account_set_ui_int(account, ui, name, atoi(data)); - else if (type == PURPLE_PREF_BOOLEAN) - purple_account_set_ui_bool(account, ui, name, - (*data == '0' ? FALSE : TRUE)); - } - - g_free(data); - } - - /* we do this here because we need access to account settings to determine - * if we can/should migrate an old Yahoo! JAPAN account */ - migrate_yahoo_japan(account); - /* we do this here because we need access to account settings to determine - * if we can/should migrate an ICQ account's server setting */ - migrate_icq_server(account); - /* we do this here because we need to do it before the user views the - * Edit Account dialog. */ - migrate_xmpp_encryption(account); -} - -static GList * -parse_status_attrs(xmlnode *node, PurpleStatus *status) -{ - GList *list = NULL; - xmlnode *child; - PurpleValue *attr_value; - - for (child = xmlnode_get_child(node, "attribute"); child != NULL; - child = xmlnode_get_next_twin(child)) - { - const char *id = xmlnode_get_attrib(child, "id"); - const char *value = xmlnode_get_attrib(child, "value"); - - if (!id || !*id || !value || !*value) - continue; - - attr_value = purple_status_get_attr_value(status, id); - if (!attr_value) - continue; - - list = g_list_append(list, (char *)id); - - switch (purple_value_get_type(attr_value)) - { - case PURPLE_TYPE_STRING: - list = g_list_append(list, (char *)value); - break; - case PURPLE_TYPE_INT: - case PURPLE_TYPE_BOOLEAN: - { - int v; - if (sscanf(value, "%d", &v) == 1) - list = g_list_append(list, GINT_TO_POINTER(v)); - else - list = g_list_remove(list, id); - break; - } - default: - break; - } - } - - return list; -} - -static void -parse_status(xmlnode *node, PurpleAccount *account) -{ - gboolean active = FALSE; - const char *data; - const char *type; - xmlnode *child; - GList *attrs = NULL; - - /* Get the active/inactive state */ - data = xmlnode_get_attrib(node, "active"); - if (data == NULL) - return; - if (g_ascii_strcasecmp(data, "true") == 0) - active = TRUE; - else if (g_ascii_strcasecmp(data, "false") == 0) - active = FALSE; - else - return; - - /* Get the type of the status */ - type = xmlnode_get_attrib(node, "type"); - if (type == NULL) - return; - - /* Read attributes into a GList */ - child = xmlnode_get_child(node, "attributes"); - if (child != NULL) - { - attrs = parse_status_attrs(child, - purple_account_get_status(account, type)); - } - - purple_account_set_status_list(account, type, active, attrs); - - g_list_free(attrs); -} - -static void -parse_statuses(xmlnode *node, PurpleAccount *account) -{ - xmlnode *child; - - for (child = xmlnode_get_child(node, "status"); child != NULL; - child = xmlnode_get_next_twin(child)) - { - parse_status(child, account); - } -} - -static void -parse_proxy_info(xmlnode *node, PurpleAccount *account) -{ - PurpleProxyInfo *proxy_info; - xmlnode *child; - char *data; - - proxy_info = purple_proxy_info_new(); - - /* Use the global proxy settings, by default */ - purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_USE_GLOBAL); - - /* Read proxy type */ - child = xmlnode_get_child(node, "type"); - if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) - { - if (purple_strequal(data, "global")) - purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_USE_GLOBAL); - else if (purple_strequal(data, "none")) - purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_NONE); - else if (purple_strequal(data, "http")) - purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_HTTP); - else if (purple_strequal(data, "socks4")) - purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_SOCKS4); - else if (purple_strequal(data, "socks5")) - purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_SOCKS5); - else if (purple_strequal(data, "tor")) - purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_TOR); - else if (purple_strequal(data, "envvar")) - purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_USE_ENVVAR); - else - { - purple_debug_error("account", "Invalid proxy type found when " - "loading account information for %s\n", - purple_account_get_username(account)); - } - g_free(data); - } - - /* Read proxy host */ - child = xmlnode_get_child(node, "host"); - if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) - { - purple_proxy_info_set_host(proxy_info, data); - g_free(data); - } - - /* Read proxy port */ - child = xmlnode_get_child(node, "port"); - if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) - { - purple_proxy_info_set_port(proxy_info, atoi(data)); - g_free(data); - } - - /* Read proxy username */ - child = xmlnode_get_child(node, "username"); - if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) - { - purple_proxy_info_set_username(proxy_info, data); - g_free(data); - } - - /* Read proxy password */ - child = xmlnode_get_child(node, "password"); - if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) - { - purple_proxy_info_set_password(proxy_info, data); - g_free(data); - } - - /* If there are no values set then proxy_info NULL */ - if ((purple_proxy_info_get_type(proxy_info) == PURPLE_PROXY_USE_GLOBAL) && - (purple_proxy_info_get_host(proxy_info) == NULL) && - (purple_proxy_info_get_port(proxy_info) == 0) && - (purple_proxy_info_get_username(proxy_info) == NULL) && - (purple_proxy_info_get_password(proxy_info) == NULL)) - { - purple_proxy_info_destroy(proxy_info); - return; - } - - purple_account_set_proxy_info(account, proxy_info); -} - -static void -parse_current_error(xmlnode *node, PurpleAccount *account) -{ - guint type; - char *type_str = NULL, *description = NULL; - xmlnode *child; - PurpleConnectionErrorInfo *current_error = NULL; - - child = xmlnode_get_child(node, "type"); - if (child == NULL || (type_str = xmlnode_get_data(child)) == NULL) - return; - type = atoi(type_str); - g_free(type_str); - - if (type > PURPLE_CONNECTION_ERROR_OTHER_ERROR) - { - purple_debug_error("account", - "Invalid PurpleConnectionError value %d found when " - "loading account information for %s\n", - type, purple_account_get_username(account)); - type = PURPLE_CONNECTION_ERROR_OTHER_ERROR; - } - - child = xmlnode_get_child(node, "description"); - if (child) - description = xmlnode_get_data(child); - if (description == NULL) - description = g_strdup(""); - - current_error = g_new0(PurpleConnectionErrorInfo, 1); - PURPLE_DBUS_REGISTER_POINTER(current_error, PurpleConnectionErrorInfo); - current_error->type = type; - current_error->description = description; - - set_current_error(account, current_error); -} - -static PurpleAccount * -parse_account(xmlnode *node) -{ - PurpleAccount *ret; - xmlnode *child; - char *protocol_id = NULL; - char *name = NULL; - char *data; - - child = xmlnode_get_child(node, "protocol"); - if (child != NULL) - protocol_id = xmlnode_get_data(child); - - child = xmlnode_get_child(node, "name"); - if (child != NULL) - name = xmlnode_get_data(child); - if (name == NULL) - { - /* Do we really need to do this? */ - child = xmlnode_get_child(node, "username"); - if (child != NULL) - name = xmlnode_get_data(child); - } - - if ((protocol_id == NULL) || (name == NULL)) - { - g_free(protocol_id); - g_free(name); - return NULL; - } - - ret = purple_account_new(name, protocol_id); - g_free(name); - g_free(protocol_id); - - /* Read the alias */ - child = xmlnode_get_child(node, "alias"); - if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) - { - if (*data != '\0') - purple_account_set_alias(ret, data); - g_free(data); - } - - /* Read the statuses */ - child = xmlnode_get_child(node, "statuses"); - if (child != NULL) - { - parse_statuses(child, ret); - } - - /* Read the userinfo */ - child = xmlnode_get_child(node, "userinfo"); - if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) - { - purple_account_set_user_info(ret, data); - g_free(data); - } - - /* Read an old buddyicon */ - child = xmlnode_get_child(node, "buddyicon"); - if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) - { - const char *dirname = purple_buddy_icons_get_cache_dir(); - char *filename = g_build_filename(dirname, data, NULL); - gchar *contents; - gsize len; - - if (g_file_get_contents(filename, &contents, &len, NULL)) - { - purple_buddy_icons_set_account_icon(ret, (guchar *)contents, len); - } - - g_free(filename); - g_free(data); - } - - /* Read settings (both core and UI) */ - for (child = xmlnode_get_child(node, "settings"); child != NULL; - child = xmlnode_get_next_twin(child)) - { - parse_settings(child, ret); - } - - /* Read proxy */ - child = xmlnode_get_child(node, "proxy"); - if (child != NULL) - { - parse_proxy_info(child, ret); - } - - /* Read current error */ - child = xmlnode_get_child(node, "current_error"); - if (child != NULL) - { - parse_current_error(child, ret); - } - - /* Read the password */ - child = xmlnode_get_child(node, "password"); - if (child != NULL) - { - const char *keyring_id = xmlnode_get_attrib(child, "keyring_id"); - const char *mode = xmlnode_get_attrib(child, "mode"); - gboolean result; - - data = xmlnode_get_data(child); - result = purple_keyring_import_password(ret, keyring_id, mode, data, NULL); - - if (result == TRUE || purple_keyring_get_inuse() == NULL) { - purple_account_set_remember_password(ret, TRUE); - } else { - purple_debug_error("account", "Failed to import password.\n"); - } - purple_str_wipe(data); - } - - return ret; -} - -static void -load_accounts(void) -{ - xmlnode *node, *child; - - accounts_loaded = TRUE; - - node = purple_util_read_xml_from_file("accounts.xml", _("accounts")); - - if (node == NULL) - return; - - for (child = xmlnode_get_child(node, "account"); child != NULL; - child = xmlnode_get_next_twin(child)) - { - PurpleAccount *new_acct; - new_acct = parse_account(child); - purple_accounts_add(new_acct); - } - - xmlnode_free(node); - - _purple_buddy_icons_account_loaded_cb(); -} - - -static void -delete_setting(void *data) -{ - PurpleAccountSetting *setting = (PurpleAccountSetting *)data; - - g_free(setting->ui); - - if (setting->type == PURPLE_PREF_STRING) - g_free(setting->value.string); - - g_free(setting); -} - -PurpleAccount * -purple_account_new(const char *username, const char *protocol_id) -{ - PurpleAccount *account = NULL; - PurplePlugin *prpl = NULL; - PurplePluginProtocolInfo *prpl_info = NULL; - PurpleStatusType *status_type; - - g_return_val_if_fail(username != NULL, NULL); - g_return_val_if_fail(protocol_id != NULL, NULL); - - account = purple_accounts_find(username, protocol_id); - - if (account != NULL) - return account; - - account = g_new0(PurpleAccount, 1); - PURPLE_DBUS_REGISTER_POINTER(account, PurpleAccount); - - purple_account_set_username(account, username); - - purple_account_set_protocol_id(account, protocol_id); - - account->settings = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, delete_setting); - account->ui_settings = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, (GDestroyNotify)g_hash_table_destroy); - account->system_log = NULL; - /* 0 is not a valid privacy setting */ - account->perm_deny = PURPLE_PRIVACY_ALLOW_ALL; - - purple_signal_emit(purple_accounts_get_handle(), "account-created", account); - - prpl = purple_find_prpl(protocol_id); - - if (prpl == NULL) - return account; - - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - if (prpl_info != NULL && prpl_info->status_types != NULL) - purple_account_set_status_types(account, prpl_info->status_types(account)); - - account->presence = purple_presence_new_for_account(account); - - status_type = purple_account_get_status_type_with_primitive(account, PURPLE_STATUS_AVAILABLE); - if (status_type != NULL) - purple_presence_set_status_active(account->presence, - purple_status_type_get_id(status_type), - TRUE); - else - purple_presence_set_status_active(account->presence, - "offline", - TRUE); - - return account; -} - -void -purple_account_destroy(PurpleAccount *account) -{ - GList *l; - - g_return_if_fail(account != NULL); - - purple_debug_info("account", "Destroying account %p\n", account); - purple_signal_emit(purple_accounts_get_handle(), "account-destroying", account); - - for (l = purple_get_conversations(); l != NULL; l = l->next) - { - PurpleConversation *conv = (PurpleConversation *)l->data; - - if (purple_conversation_get_account(conv) == account) - purple_conversation_set_account(conv, NULL); - } - - g_free(account->username); - g_free(account->alias); - purple_str_wipe(account->password); - g_free(account->user_info); - g_free(account->buddy_icon_path); - g_free(account->protocol_id); - - g_hash_table_destroy(account->settings); - g_hash_table_destroy(account->ui_settings); - - if (account->proxy_info) - purple_proxy_info_destroy(account->proxy_info); - - purple_account_set_status_types(account, NULL); - - if (account->presence) - purple_presence_destroy(account->presence); - - if(account->system_log) - purple_log_free(account->system_log); - - while (account->deny) { - g_free(account->deny->data); - account->deny = g_slist_delete_link(account->deny, account->deny); - } - - while (account->permit) { - g_free(account->permit->data); - account->permit = g_slist_delete_link(account->permit, account->permit); - } - - PURPLE_DBUS_UNREGISTER_POINTER(account->current_error); - if (account->current_error) { - g_free(account->current_error->description); - g_free(account->current_error); - } - - PURPLE_DBUS_UNREGISTER_POINTER(account); - g_free(account); -} + PROP_0, + PROP_USERNAME, + PROP_PRIVATE_ALIAS, + PROP_ENABLED, + PROP_CONNECTION, + PROP_PROTOCOL_ID, + PROP_USER_INFO, + PROP_BUDDY_ICON_PATH, + PROP_REMEMBER_PASSWORD, + PROP_CHECK_MAIL, + PROP_LAST +}; + +static GObjectClass *parent_class = NULL; +static GList *handles = NULL; + void purple_account_set_register_callback(PurpleAccount *account, PurpleAccountRegistrationCb cb, void *user_data) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); - account->registration_cb = cb; - account->registration_cb_user_data = user_data; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + priv->registration_cb = cb; + priv->registration_cb_user_data = user_data; } static void @@ -1183,10 +186,14 @@ void purple_account_register_completed(PurpleAccount *account, gboolean succeeded) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); - if (account->registration_cb) - (account->registration_cb)(account, succeeded, account->registration_cb_user_data); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + if (priv->registration_cb) + (priv->registration_cb)(account, succeeded, priv->registration_cb_user_data); } void @@ -1299,6 +306,7 @@ PurplePlugin *prpl; const char *username; PurplePluginProtocolInfo *prpl_info; + PurpleAccountPrivate *priv; g_return_if_fail(account != NULL); @@ -1321,12 +329,14 @@ return; } + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + purple_debug_info("account", "Connecting to account %s.\n", username); prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - if (account->password != NULL) { + if (priv->password != NULL) { purple_account_connect_got_password_cb(account, - account->password, NULL, prpl_info); + priv->password, NULL, prpl_info); } else { purple_keyring_get_password(account, purple_account_connect_got_password_cb, prpl_info); @@ -1337,30 +347,36 @@ purple_account_disconnect(PurpleAccount *account) { PurpleConnection *gc; + PurpleAccountPrivate *priv; const char *username; g_return_if_fail(account != NULL); g_return_if_fail(!purple_account_is_disconnected(account)); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + username = purple_account_get_username(account); purple_debug_info("account", "Disconnecting account %s (%p)\n", username ? username : "(null)", account); - account->disconnecting = TRUE; + priv->disconnecting = TRUE; gc = purple_account_get_connection(account); _purple_connection_destroy(gc); purple_account_set_connection(account, NULL); - account->disconnecting = FALSE; + priv->disconnecting = FALSE; } gboolean purple_account_is_disconnecting(const PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, TRUE); - - return account->disconnecting; + + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + return priv->disconnecting; } void @@ -1692,13 +708,16 @@ purple_account_set_username(PurpleAccount *account, const char *username) { PurpleBlistUiOps *blist_ops; + PurpleAccountPrivate *priv; g_return_if_fail(account != NULL); - g_free(account->username); - account->username = g_strdup(username); - - schedule_accounts_save(); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + g_free(priv->username); + priv->username = g_strdup(username); + + purple_accounts_schedule_save(); /* if the name changes, we should re-write the buddy list * to disk with the new name */ @@ -1711,12 +730,16 @@ purple_account_set_password(PurpleAccount *account, const gchar *password, PurpleKeyringSaveCallback cb, gpointer data) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); - purple_str_wipe(account->password); - account->password = g_strdup(password); - - schedule_accounts_save(); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + purple_str_wipe(priv->password); + priv->password = g_strdup(password); + + purple_accounts_schedule_save(); if (!purple_account_get_remember_password(account)) { purple_debug_info("account", @@ -1731,80 +754,102 @@ } void -purple_account_set_alias(PurpleAccount *account, const char *alias) +purple_account_set_private_alias(PurpleAccount *account, const char *alias) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + /* - * Do nothing if alias and account->alias are both NULL. Or if + * Do nothing if alias and priv->alias are both NULL. Or if * they're the exact same string. */ - if (alias == account->alias) + if (alias == priv->alias) return; - if ((!alias && account->alias) || (alias && !account->alias) || - g_utf8_collate(account->alias, alias)) + if ((!alias && priv->alias) || (alias && !priv->alias) || + g_utf8_collate(priv->alias, alias)) { - char *old = account->alias; - - account->alias = g_strdup(alias); + char *old = priv->alias; + + priv->alias = g_strdup(alias); purple_signal_emit(purple_accounts_get_handle(), "account-alias-changed", account, old); g_free(old); - schedule_accounts_save(); + purple_accounts_schedule_save(); } } void purple_account_set_user_info(PurpleAccount *account, const char *user_info) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); - g_free(account->user_info); - account->user_info = g_strdup(user_info); - - schedule_accounts_save(); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + g_free(priv->user_info); + priv->user_info = g_strdup(user_info); + + purple_accounts_schedule_save(); } void purple_account_set_buddy_icon_path(PurpleAccount *account, const char *path) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); - g_free(account->buddy_icon_path); - account->buddy_icon_path = g_strdup(path); - - schedule_accounts_save(); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + g_free(priv->buddy_icon_path); + priv->buddy_icon_path = g_strdup(path); + + purple_accounts_schedule_save(); } void purple_account_set_protocol_id(PurpleAccount *account, const char *protocol_id) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); g_return_if_fail(protocol_id != NULL); - g_free(account->protocol_id); - account->protocol_id = g_strdup(protocol_id); - - schedule_accounts_save(); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + g_free(priv->protocol_id); + priv->protocol_id = g_strdup(protocol_id); + + purple_accounts_schedule_save(); } void purple_account_set_connection(PurpleAccount *account, PurpleConnection *gc) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); - account->gc = gc; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + priv->gc = gc; } void purple_account_set_remember_password(PurpleAccount *account, gboolean value) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); - account->remember_pass = value; - - schedule_accounts_save(); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + priv->remember_pass = value; + + purple_accounts_schedule_save(); } void @@ -1820,6 +865,7 @@ gboolean value) { PurpleConnection *gc; + PurpleAccountPrivate *priv; gboolean was_enabled = FALSE; g_return_if_fail(account != NULL); @@ -1838,7 +884,9 @@ if ((gc != NULL) && (gc->wants_to_die == TRUE)) return; - if (value && purple_presence_is_online(account->presence)) + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + if (value && purple_presence_is_online(priv->presence)) purple_account_connect(account); else if (!value && !purple_account_is_disconnected(account)) purple_account_disconnect(account); @@ -1847,38 +895,49 @@ void purple_account_set_proxy_info(PurpleAccount *account, PurpleProxyInfo *info) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); - if (account->proxy_info != NULL) - purple_proxy_info_destroy(account->proxy_info); - - account->proxy_info = info; - - schedule_accounts_save(); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + if (priv->proxy_info != NULL) + purple_proxy_info_destroy(priv->proxy_info); + + priv->proxy_info = info; + + purple_accounts_schedule_save(); } void -purple_account_set_privacy_type(PurpleAccount *account, PurplePrivacyType privacy_type) +purple_account_set_privacy_type(PurpleAccount *account, PurpleAccountPrivacyType privacy_type) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); - account->perm_deny = privacy_type; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + priv->privacy_type = privacy_type; } void purple_account_set_status_types(PurpleAccount *account, GList *status_types) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + /* Out with the old... */ - if (account->status_types != NULL) + if (priv->status_types != NULL) { - g_list_foreach(account->status_types, (GFunc)purple_status_type_destroy, NULL); - g_list_free(account->status_types); + g_list_foreach(priv->status_types, (GFunc)purple_status_type_destroy, NULL); + g_list_free(priv->status_types); } /* In with the new... */ - account->status_types = status_types; + priv->status_types = status_types; } void @@ -1928,7 +987,7 @@ * Our current statuses are saved to accounts.xml (so that when we * reconnect, we go back to the previous status). */ - schedule_accounts_save(); + purple_accounts_schedule_save(); } struct public_alias_closure @@ -2031,42 +1090,63 @@ purple_account_set_bool(account, "silence-suppression", value); } +static void +delete_setting(void *data) +{ + PurpleAccountSetting *setting = (PurpleAccountSetting *)data; + + g_free(setting->ui); + g_value_unset(&setting->value); + + g_free(setting); +} + void purple_account_clear_settings(PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); - g_hash_table_destroy(account->settings); - - account->settings = g_hash_table_new_full(g_str_hash, g_str_equal, + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + g_hash_table_destroy(priv->settings); + + priv->settings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, delete_setting); } void purple_account_remove_setting(PurpleAccount *account, const char *setting) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); g_return_if_fail(setting != NULL); - g_hash_table_remove(account->settings, setting); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + g_hash_table_remove(priv->settings, setting); } void purple_account_set_int(PurpleAccount *account, const char *name, int value) { PurpleAccountSetting *setting; + PurpleAccountPrivate *priv; g_return_if_fail(account != NULL); g_return_if_fail(name != NULL); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + setting = g_new0(PurpleAccountSetting, 1); - setting->type = PURPLE_PREF_INT; - setting->value.integer = value; - - g_hash_table_insert(account->settings, g_strdup(name), setting); - - schedule_accounts_save(); + g_value_init(&setting->value, G_TYPE_INT); + g_value_set_int(&setting->value, value); + + g_hash_table_insert(priv->settings, g_strdup(name), setting); + + purple_accounts_schedule_save(); } void @@ -2074,49 +1154,56 @@ const char *value) { PurpleAccountSetting *setting; + PurpleAccountPrivate *priv; g_return_if_fail(account != NULL); g_return_if_fail(name != NULL); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + setting = g_new0(PurpleAccountSetting, 1); - setting->type = PURPLE_PREF_STRING; - setting->value.string = g_strdup(value); - - g_hash_table_insert(account->settings, g_strdup(name), setting); - - schedule_accounts_save(); + g_value_init(&setting->value, G_TYPE_STRING); + g_value_set_string(&setting->value, value); + + g_hash_table_insert(priv->settings, g_strdup(name), setting); + + purple_accounts_schedule_save(); } void purple_account_set_bool(PurpleAccount *account, const char *name, gboolean value) { PurpleAccountSetting *setting; + PurpleAccountPrivate *priv; g_return_if_fail(account != NULL); g_return_if_fail(name != NULL); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + setting = g_new0(PurpleAccountSetting, 1); - setting->type = PURPLE_PREF_BOOLEAN; - setting->value.boolean = value; - - g_hash_table_insert(account->settings, g_strdup(name), setting); - - schedule_accounts_save(); + g_value_init(&setting->value, G_TYPE_BOOLEAN); + g_value_set_boolean(&setting->value, value); + + g_hash_table_insert(priv->settings, g_strdup(name), setting); + + purple_accounts_schedule_save(); } static GHashTable * get_ui_settings_table(PurpleAccount *account, const char *ui) { GHashTable *table; - - table = g_hash_table_lookup(account->ui_settings, ui); + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + table = g_hash_table_lookup(priv->ui_settings, ui); if (table == NULL) { table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, delete_setting); - g_hash_table_insert(account->ui_settings, g_strdup(ui), table); + g_hash_table_insert(priv->ui_settings, g_strdup(ui), table); } return table; @@ -2135,15 +1222,15 @@ setting = g_new0(PurpleAccountSetting, 1); - setting->type = PURPLE_PREF_INT; setting->ui = g_strdup(ui); - setting->value.integer = value; + g_value_init(&setting->value, G_TYPE_INT); + g_value_set_int(&setting->value, value); table = get_ui_settings_table(account, ui); g_hash_table_insert(table, g_strdup(name), setting); - schedule_accounts_save(); + purple_accounts_schedule_save(); } void @@ -2159,15 +1246,15 @@ setting = g_new0(PurpleAccountSetting, 1); - setting->type = PURPLE_PREF_STRING; setting->ui = g_strdup(ui); - setting->value.string = g_strdup(value); + g_value_init(&setting->value, G_TYPE_STRING); + g_value_set_string(&setting->value, value); table = get_ui_settings_table(account, ui); g_hash_table_insert(table, g_strdup(name), setting); - schedule_accounts_save(); + purple_accounts_schedule_save(); } void @@ -2183,15 +1270,15 @@ setting = g_new0(PurpleAccountSetting, 1); - setting->type = PURPLE_PREF_BOOLEAN; setting->ui = g_strdup(ui); - setting->value.boolean = value; + g_value_init(&setting->value, G_TYPE_BOOLEAN); + g_value_set_boolean(&setting->value, value); table = get_ui_settings_table(account, ui); g_hash_table_insert(table, g_strdup(name), setting); - schedule_accounts_save(); + purple_accounts_schedule_save(); } static PurpleConnectionState @@ -2229,9 +1316,12 @@ const char * purple_account_get_username(const PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, NULL); - return account->username; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + return priv->username; } static void @@ -2240,13 +1330,14 @@ { PurpleCallbackBundle *cbb = data; PurpleKeyringReadCallback cb; + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); purple_debug_info("account", "Read password for account %s from async keyring.\n", purple_account_get_username(account)); - purple_str_wipe(account->password); - account->password = g_strdup(password); + purple_str_wipe(priv->password); + priv->password = g_strdup(password); cb = (PurpleKeyringReadCallback)cbb->cb; if (cb != NULL) @@ -2259,16 +1350,20 @@ purple_account_get_password(PurpleAccount *account, PurpleKeyringReadCallback cb, gpointer data) { + PurpleAccountPrivate *priv; + if (account == NULL) { cb(NULL, NULL, NULL, data); return; } - if (account->password != NULL) { + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + if (priv->password != NULL) { purple_debug_info("account", "Reading password for account %s from cache.\n", purple_account_get_username(account)); - cb(account, account->password, NULL, data); + cb(account, priv->password, NULL, data); } else { PurpleCallbackBundle *cbb = g_new0(PurpleCallbackBundle, 1); cbb->cb = PURPLE_CALLBACK(cb); @@ -2283,34 +1378,47 @@ } const char * -purple_account_get_alias(const PurpleAccount *account) +purple_account_get_private_alias(const PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, NULL); - return account->alias; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + return priv->alias; } const char * purple_account_get_user_info(const PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, NULL); - return account->user_info; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + return priv->user_info; } const char * purple_account_get_buddy_icon_path(const PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, NULL); - return account->buddy_icon_path; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + return priv->buddy_icon_path; } const char * purple_account_get_protocol_id(const PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, NULL); - return account->protocol_id; + + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + return priv->protocol_id; } const char * @@ -2328,9 +1436,12 @@ PurpleConnection * purple_account_get_connection(const PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, NULL); - return account->gc; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + return priv->gc; } const gchar * @@ -2340,7 +1451,7 @@ PurpleConnection *gc = NULL; const gchar *name = NULL, *username = NULL, *displayname = NULL; - name = purple_account_get_alias(account); + name = purple_account_get_private_alias(account); if (name) { return name; @@ -2372,9 +1483,12 @@ gboolean purple_account_get_remember_password(const PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, FALSE); - return account->remember_pass; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + return priv->remember_pass; } gboolean @@ -2397,34 +1511,436 @@ PurpleProxyInfo * purple_account_get_proxy_info(const PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, NULL); - return account->proxy_info; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + return priv->proxy_info; } -PurplePrivacyType +PurpleAccountPrivacyType purple_account_get_privacy_type(const PurpleAccount *account) { - g_return_val_if_fail(account != NULL, PURPLE_PRIVACY_ALLOW_ALL); - - return account->perm_deny; + PurpleAccountPrivate *priv; + + g_return_val_if_fail(account != NULL, PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL); + + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + return priv->privacy_type; +} + +gboolean +purple_account_privacy_permit_add(PurpleAccount *account, const char *who, + gboolean local_only) +{ + GSList *l; + char *name; + PurpleBuddy *buddy; + PurpleBlistUiOps *blist_ops; + PurpleAccountPrivate *priv; + PurpleAccountUiOps *ui_ops = purple_accounts_get_ui_ops(); + + g_return_val_if_fail(account != NULL, FALSE); + g_return_val_if_fail(who != NULL, FALSE); + + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + name = g_strdup(purple_normalize(account, who)); + + for (l = priv->permit; l != NULL; l = l->next) { + if (g_str_equal(name, l->data)) + /* This buddy already exists */ + break; + } + + if (l != NULL) + { + /* This buddy already exists, so bail out */ + g_free(name); + return FALSE; + } + + priv->permit = g_slist_append(priv->permit, name); + + if (!local_only && purple_account_is_connected(account)) + serv_add_permit(purple_account_get_connection(account), who); + + if (ui_ops != NULL && ui_ops->permit_added != NULL) + ui_ops->permit_added(account, who); + + blist_ops = purple_blist_get_ui_ops(); + if (blist_ops != NULL && blist_ops->save_account != NULL) + blist_ops->save_account(account); + + /* This lets the UI know a buddy has had its privacy setting changed */ + buddy = purple_find_buddy(account, name); + if (buddy != NULL) { + purple_signal_emit(purple_blist_get_handle(), + "buddy-privacy-changed", buddy); + } + return TRUE; +} + +gboolean +purple_account_privacy_permit_remove(PurpleAccount *account, const char *who, + gboolean local_only) +{ + GSList *l; + const char *name; + PurpleBuddy *buddy; + char *del; + PurpleBlistUiOps *blist_ops; + PurpleAccountPrivate *priv; + PurpleAccountUiOps *ui_ops = purple_accounts_get_ui_ops(); + + g_return_val_if_fail(account != NULL, FALSE); + g_return_val_if_fail(who != NULL, FALSE); + + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + name = purple_normalize(account, who); + + for (l = priv->permit; l != NULL; l = l->next) { + if (g_str_equal(name, l->data)) + /* We found the buddy we were looking for */ + break; + } + + if (l == NULL) + /* We didn't find the buddy we were looking for, so bail out */ + return FALSE; + + /* We should not free l->data just yet. There can be occasions where + * l->data == who. In such cases, freeing l->data here can cause crashes + * later when who is used. */ + del = l->data; + priv->permit = g_slist_delete_link(priv->permit, l); + + if (!local_only && purple_account_is_connected(account)) + serv_rem_permit(purple_account_get_connection(account), who); + + if (ui_ops != NULL && ui_ops->permit_removed != NULL) + ui_ops->permit_removed(account, who); + + blist_ops = purple_blist_get_ui_ops(); + if (blist_ops != NULL && blist_ops->save_account != NULL) + blist_ops->save_account(account); + + buddy = purple_find_buddy(account, name); + if (buddy != NULL) { + purple_signal_emit(purple_blist_get_handle(), + "buddy-privacy-changed", buddy); + } + g_free(del); + return TRUE; +} + +gboolean +purple_account_privacy_deny_add(PurpleAccount *account, const char *who, + gboolean local_only) +{ + GSList *l; + char *name; + PurpleBuddy *buddy; + PurpleBlistUiOps *blist_ops; + PurpleAccountPrivate *priv; + PurpleAccountUiOps *ui_ops = purple_accounts_get_ui_ops(); + + g_return_val_if_fail(account != NULL, FALSE); + g_return_val_if_fail(who != NULL, FALSE); + + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + name = g_strdup(purple_normalize(account, who)); + + for (l = priv->deny; l != NULL; l = l->next) { + if (g_str_equal(name, l->data)) + /* This buddy already exists */ + break; + } + + if (l != NULL) + { + /* This buddy already exists, so bail out */ + g_free(name); + return FALSE; + } + + priv->deny = g_slist_append(priv->deny, name); + + if (!local_only && purple_account_is_connected(account)) + serv_add_deny(purple_account_get_connection(account), who); + + if (ui_ops != NULL && ui_ops->deny_added != NULL) + ui_ops->deny_added(account, who); + + blist_ops = purple_blist_get_ui_ops(); + if (blist_ops != NULL && blist_ops->save_account != NULL) + blist_ops->save_account(account); + + buddy = purple_find_buddy(account, name); + if (buddy != NULL) { + purple_signal_emit(purple_blist_get_handle(), + "buddy-privacy-changed", buddy); + } + return TRUE; +} + +gboolean +purple_account_privacy_deny_remove(PurpleAccount *account, const char *who, + gboolean local_only) +{ + GSList *l; + const char *normalized; + char *name; + PurpleBuddy *buddy; + PurpleBlistUiOps *blist_ops; + PurpleAccountPrivate *priv; + PurpleAccountUiOps *ui_ops = purple_accounts_get_ui_ops(); + + g_return_val_if_fail(account != NULL, FALSE); + g_return_val_if_fail(who != NULL, FALSE); + + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + normalized = purple_normalize(account, who); + + for (l = priv->deny; l != NULL; l = l->next) { + if (g_str_equal(normalized, l->data)) + /* We found the buddy we were looking for */ + break; + } + + if (l == NULL) + /* We didn't find the buddy we were looking for, so bail out */ + return FALSE; + + buddy = purple_find_buddy(account, normalized); + + name = l->data; + priv->deny = g_slist_delete_link(priv->deny, l); + + if (!local_only && purple_account_is_connected(account)) + serv_rem_deny(purple_account_get_connection(account), name); + + if (ui_ops != NULL && ui_ops->deny_removed != NULL) + ui_ops->deny_removed(account, who); + + if (buddy != NULL) { + purple_signal_emit(purple_blist_get_handle(), + "buddy-privacy-changed", buddy); + } + + g_free(name); + + blist_ops = purple_blist_get_ui_ops(); + if (blist_ops != NULL && blist_ops->save_account != NULL) + blist_ops->save_account(account); + + return TRUE; +} + +/** + * This makes sure your permit list contains all buddies from your + * buddy list and ONLY buddies from your buddy list. + */ +static void +add_all_buddies_to_permit_list(PurpleAccount *account, gboolean local) +{ + GSList *list; + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + /* Remove anyone in the permit list who is not in the buddylist */ + for (list = priv->permit; list != NULL; ) { + char *person = list->data; + list = list->next; + if (!purple_find_buddy(account, person)) + purple_account_privacy_permit_remove(account, person, local); + } + + /* Now make sure everyone in the buddylist is in the permit list */ + list = purple_find_buddies(account, NULL); + while (list != NULL) + { + PurpleBuddy *buddy = list->data; + const gchar *name = purple_buddy_get_name(buddy); + + if (!g_slist_find_custom(priv->permit, name, (GCompareFunc)g_utf8_collate)) + purple_account_privacy_permit_add(account, name, local); + list = g_slist_delete_link(list, list); + } +} + +void +purple_account_privacy_allow(PurpleAccount *account, const char *who) +{ + GSList *list; + PurpleAccountPrivacyType type = purple_account_get_privacy_type(account); + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + switch (type) { + case PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL: + return; + case PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS: + purple_account_privacy_permit_add(account, who, FALSE); + break; + case PURPLE_ACCOUNT_PRIVACY_DENY_USERS: + purple_account_privacy_deny_remove(account, who, FALSE); + break; + case PURPLE_ACCOUNT_PRIVACY_DENY_ALL: + { + /* Empty the allow-list. */ + const char *norm = purple_normalize(account, who); + for (list = priv->permit; list != NULL;) { + char *person = list->data; + list = list->next; + if (!purple_strequal(norm, person)) + purple_account_privacy_permit_remove(account, person, FALSE); + } + purple_account_privacy_permit_add(account, who, FALSE); + purple_account_set_privacy_type(account, PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS); + } + break; + case PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST: + if (!purple_find_buddy(account, who)) { + add_all_buddies_to_permit_list(account, FALSE); + purple_account_privacy_permit_add(account, who, FALSE); + purple_account_set_privacy_type(account, PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS); + } + break; + default: + g_return_if_reached(); + } + + /* Notify the server if the privacy setting was changed */ + if (type != purple_account_get_privacy_type(account) && purple_account_is_connected(account)) + serv_set_permit_deny(purple_account_get_connection(account)); +} + +void +purple_account_privacy_deny(PurpleAccount *account, const char *who) +{ + GSList *list; + PurpleAccountPrivacyType type = purple_account_get_privacy_type(account); + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + switch (type) { + case PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL: + { + /* Empty the deny-list. */ + const char *norm = purple_normalize(account, who); + for (list = priv->deny; list != NULL; ) { + char *person = list->data; + list = list->next; + if (!purple_strequal(norm, person)) + purple_account_privacy_deny_remove(account, person, FALSE); + } + purple_account_privacy_deny_add(account, who, FALSE); + purple_account_set_privacy_type(account, PURPLE_ACCOUNT_PRIVACY_DENY_USERS); + } + break; + case PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS: + purple_account_privacy_permit_remove(account, who, FALSE); + break; + case PURPLE_ACCOUNT_PRIVACY_DENY_USERS: + purple_account_privacy_deny_add(account, who, FALSE); + break; + case PURPLE_ACCOUNT_PRIVACY_DENY_ALL: + break; + case PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST: + if (purple_find_buddy(account, who)) { + add_all_buddies_to_permit_list(account, FALSE); + purple_account_privacy_permit_remove(account, who, FALSE); + purple_account_set_privacy_type(account, PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS); + } + break; + default: + g_return_if_reached(); + } + + /* Notify the server if the privacy setting was changed */ + if (type != purple_account_get_privacy_type(account) && purple_account_is_connected(account)) + serv_set_permit_deny(purple_account_get_connection(account)); +} + +GSList * +purple_account_privacy_get_permitted(PurpleAccount *account) +{ + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + g_return_val_if_fail(priv != NULL, NULL); + + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + return priv->permit; +} + +GSList * +purple_account_privacy_get_denied(PurpleAccount *account) +{ + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + g_return_val_if_fail(priv != NULL, NULL); + + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + return priv->deny; +} + +gboolean +purple_account_privacy_check(PurpleAccount *account, const char *who) +{ + GSList *list; + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + switch (purple_account_get_privacy_type(account)) { + case PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL: + return TRUE; + + case PURPLE_ACCOUNT_PRIVACY_DENY_ALL: + return FALSE; + + case PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS: + who = purple_normalize(account, who); + for (list=priv->permit; list!=NULL; list=list->next) { + if (g_str_equal(who, list->data)) + return TRUE; + } + return FALSE; + + case PURPLE_ACCOUNT_PRIVACY_DENY_USERS: + who = purple_normalize(account, who); + for (list=priv->deny; list!=NULL; list=list->next) { + if (g_str_equal(who, list->data)) + return FALSE; + } + return TRUE; + + case PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST: + return (purple_find_buddy(account, who) != NULL); + + default: + g_return_val_if_reached(TRUE); + } } PurpleStatus * purple_account_get_active_status(const PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, NULL); - return purple_presence_get_active_status(account->presence); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + return purple_presence_get_active_status(priv->presence); } PurpleStatus * purple_account_get_status(const PurpleAccount *account, const char *status_id) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, NULL); g_return_val_if_fail(status_id != NULL, NULL); - return purple_presence_get_status(account->presence, status_id); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + return purple_presence_get_status(priv->presence, status_id); } PurpleStatusType * @@ -2467,27 +1983,37 @@ PurplePresence * purple_account_get_presence(const PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, NULL); - return account->presence; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + return priv->presence; } gboolean purple_account_is_status_active(const PurpleAccount *account, const char *status_id) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, FALSE); g_return_val_if_fail(status_id != NULL, FALSE); - return purple_presence_is_status_active(account->presence, status_id); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + return purple_presence_is_status_active(priv->presence, status_id); } GList * purple_account_get_status_types(const PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, NULL); - return account->status_types; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + return priv->status_types; } int @@ -2495,18 +2021,21 @@ int default_value) { PurpleAccountSetting *setting; + PurpleAccountPrivate *priv; g_return_val_if_fail(account != NULL, default_value); g_return_val_if_fail(name != NULL, default_value); - setting = g_hash_table_lookup(account->settings, name); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + setting = g_hash_table_lookup(priv->settings, name); if (setting == NULL) return default_value; - g_return_val_if_fail(setting->type == PURPLE_PREF_INT, default_value); - - return setting->value.integer; + g_return_val_if_fail(G_VALUE_HOLDS_INT(&setting->value), default_value); + + return g_value_get_int(&setting->value); } const char * @@ -2514,18 +2043,21 @@ const char *default_value) { PurpleAccountSetting *setting; + PurpleAccountPrivate *priv; g_return_val_if_fail(account != NULL, default_value); g_return_val_if_fail(name != NULL, default_value); - setting = g_hash_table_lookup(account->settings, name); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + setting = g_hash_table_lookup(priv->settings, name); if (setting == NULL) return default_value; - g_return_val_if_fail(setting->type == PURPLE_PREF_STRING, default_value); - - return setting->value.string; + g_return_val_if_fail(G_VALUE_HOLDS_STRING(&setting->value), default_value); + + return g_value_get_string(&setting->value); } gboolean @@ -2533,18 +2065,21 @@ gboolean default_value) { PurpleAccountSetting *setting; + PurpleAccountPrivate *priv; g_return_val_if_fail(account != NULL, default_value); g_return_val_if_fail(name != NULL, default_value); - setting = g_hash_table_lookup(account->settings, name); + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + setting = g_hash_table_lookup(priv->settings, name); if (setting == NULL) return default_value; - g_return_val_if_fail(setting->type == PURPLE_PREF_BOOLEAN, default_value); - - return setting->value.boolean; + g_return_val_if_fail(G_VALUE_HOLDS_BOOLEAN(&setting->value), default_value); + + return g_value_get_boolean(&setting->value); } int @@ -2552,21 +2087,24 @@ const char *name, int default_value) { PurpleAccountSetting *setting; + PurpleAccountPrivate *priv; GHashTable *table; g_return_val_if_fail(account != NULL, default_value); g_return_val_if_fail(ui != NULL, default_value); g_return_val_if_fail(name != NULL, default_value); - if ((table = g_hash_table_lookup(account->ui_settings, ui)) == NULL) + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + if ((table = g_hash_table_lookup(priv->ui_settings, ui)) == NULL) return default_value; if ((setting = g_hash_table_lookup(table, name)) == NULL) return default_value; - g_return_val_if_fail(setting->type == PURPLE_PREF_INT, default_value); - - return setting->value.integer; + g_return_val_if_fail(G_VALUE_HOLDS_INT(&setting->value), default_value); + + return g_value_get_int(&setting->value); } const char * @@ -2574,21 +2112,24 @@ const char *name, const char *default_value) { PurpleAccountSetting *setting; + PurpleAccountPrivate *priv; GHashTable *table; g_return_val_if_fail(account != NULL, default_value); g_return_val_if_fail(ui != NULL, default_value); g_return_val_if_fail(name != NULL, default_value); - if ((table = g_hash_table_lookup(account->ui_settings, ui)) == NULL) + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + if ((table = g_hash_table_lookup(priv->ui_settings, ui)) == NULL) return default_value; if ((setting = g_hash_table_lookup(table, name)) == NULL) return default_value; - g_return_val_if_fail(setting->type == PURPLE_PREF_STRING, default_value); - - return setting->value.string; + g_return_val_if_fail(G_VALUE_HOLDS_STRING(&setting->value), default_value); + + return g_value_get_string(&setting->value); } gboolean @@ -2596,69 +2137,62 @@ const char *name, gboolean default_value) { PurpleAccountSetting *setting; + PurpleAccountPrivate *priv; GHashTable *table; g_return_val_if_fail(account != NULL, default_value); g_return_val_if_fail(ui != NULL, default_value); g_return_val_if_fail(name != NULL, default_value); - if ((table = g_hash_table_lookup(account->ui_settings, ui)) == NULL) + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + if ((table = g_hash_table_lookup(priv->ui_settings, ui)) == NULL) return default_value; if ((setting = g_hash_table_lookup(table, name)) == NULL) return default_value; - g_return_val_if_fail(setting->type == PURPLE_PREF_BOOLEAN, default_value); - - return setting->value.boolean; + g_return_val_if_fail(G_VALUE_HOLDS_BOOLEAN(&setting->value), default_value); + + return g_value_get_boolean(&setting->value); } -gpointer -purple_account_get_ui_data(const PurpleAccount *account) -{ - g_return_val_if_fail(account != NULL, NULL); - - return account->ui_data; -} - -void -purple_account_set_ui_data(PurpleAccount *account, - gpointer ui_data) -{ - g_return_if_fail(account != NULL); - - account->ui_data = ui_data; -} - - PurpleLog * purple_account_get_log(PurpleAccount *account, gboolean create) { + PurpleAccountPrivate *priv; + g_return_val_if_fail(account != NULL, NULL); - if(!account->system_log && create){ + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + if(!priv->system_log && create){ PurplePresence *presence; int login_time; presence = purple_account_get_presence(account); login_time = purple_presence_get_login_time(presence); - account->system_log = purple_log_new(PURPLE_LOG_SYSTEM, + priv->system_log = purple_log_new(PURPLE_LOG_SYSTEM, purple_account_get_username(account), account, NULL, (login_time != 0) ? login_time : time(NULL), NULL); } - return account->system_log; + return priv->system_log; } void purple_account_destroy_log(PurpleAccount *account) { + PurpleAccountPrivate *priv; + g_return_if_fail(account != NULL); - if(account->system_log){ - purple_log_free(account->system_log); - account->system_log = NULL; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + if(priv->system_log){ + purple_log_free(priv->system_log); + priv->system_log = NULL; } } @@ -2829,45 +2363,27 @@ return prpl_info->offline_message(buddy); } -static void -signed_on_cb(PurpleConnection *gc, - gpointer unused) -{ - PurpleAccount *account = purple_connection_get_account(gc); - purple_account_clear_current_error(account); - - purple_signal_emit(purple_accounts_get_handle(), "account-signed-on", - account); -} - -static void -signed_off_cb(PurpleConnection *gc, - gpointer unused) -{ - PurpleAccount *account = purple_connection_get_account(gc); - - purple_signal_emit(purple_accounts_get_handle(), "account-signed-off", - account); -} - -static void -set_current_error(PurpleAccount *account, PurpleConnectionErrorInfo *new_err) +void +purple_account_set_current_error(PurpleAccount *account, + PurpleConnectionErrorInfo *new_err) { PurpleConnectionErrorInfo *old_err; + PurpleAccountPrivate *priv; g_return_if_fail(account != NULL); - - old_err = account->current_error; + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + old_err = priv->current_error; if(new_err == old_err) return; - account->current_error = new_err; + priv->current_error = new_err; purple_signal_emit(purple_accounts_get_handle(), "account-error-changed", account, old_err, new_err); - schedule_accounts_save(); + purple_accounts_schedule_save(); if(old_err) g_free(old_err->description); @@ -2876,435 +2392,714 @@ g_free(old_err); } -static void -connection_error_cb(PurpleConnection *gc, - PurpleConnectionError type, - const gchar *description, - gpointer unused) -{ - PurpleAccount *account; - PurpleConnectionErrorInfo *err; - - account = purple_connection_get_account(gc); - - g_return_if_fail(account != NULL); - - err = g_new0(PurpleConnectionErrorInfo, 1); - PURPLE_DBUS_REGISTER_POINTER(err, PurpleConnectionErrorInfo); - - err->type = type; - err->description = g_strdup(description); - - set_current_error(account, err); - - purple_signal_emit(purple_accounts_get_handle(), "account-connection-error", - account, type, description); -} - -static void -password_migration_cb(PurpleAccount *account) -{ - /* account may be NULL (means: all) */ - - schedule_accounts_save(); -} - const PurpleConnectionErrorInfo * purple_account_get_current_error(PurpleAccount *account) { - return account->current_error; + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + return priv->current_error; } void purple_account_clear_current_error(PurpleAccount *account) { - set_current_error(account, NULL); + purple_account_set_current_error(account, NULL); } -void -purple_accounts_add(PurpleAccount *account) +static xmlnode * +status_attr_to_xmlnode(const PurpleStatus *status, const PurpleStatusType *type, + const PurpleStatusAttr *attr) { - g_return_if_fail(account != NULL); - - if (g_list_find(accounts, account) != NULL) - return; - - accounts = g_list_append(accounts, account); - - schedule_accounts_save(); - - purple_signal_emit(purple_accounts_get_handle(), "account-added", account); + xmlnode *node; + const char *id; + char *value = NULL; + PurpleStatusAttr *default_attr; + PurpleValue *default_value; + PurpleType attr_type; + PurpleValue *attr_value; + + id = purple_status_attr_get_id(attr); + g_return_val_if_fail(id, NULL); + + attr_value = purple_status_get_attr_value(status, id); + g_return_val_if_fail(attr_value, NULL); + attr_type = purple_value_get_type(attr_value); + + /* + * If attr_value is a different type than it should be + * then don't write it to the file. + */ + default_attr = purple_status_type_get_attr(type, id); + default_value = purple_status_attr_get_value(default_attr); + if (attr_type != purple_value_get_type(default_value)) + return NULL; + + /* + * If attr_value is the same as the default for this status + * then there is no need to write it to the file. + */ + if (attr_type == PURPLE_TYPE_STRING) + { + const char *string_value = purple_value_get_string(attr_value); + const char *default_string_value = purple_value_get_string(default_value); + if (purple_strequal(string_value, default_string_value)) + return NULL; + value = g_strdup(purple_value_get_string(attr_value)); + } + else if (attr_type == PURPLE_TYPE_INT) + { + int int_value = purple_value_get_int(attr_value); + if (int_value == purple_value_get_int(default_value)) + return NULL; + value = g_strdup_printf("%d", int_value); + } + else if (attr_type == PURPLE_TYPE_BOOLEAN) + { + gboolean boolean_value = purple_value_get_boolean(attr_value); + if (boolean_value == purple_value_get_boolean(default_value)) + return NULL; + value = g_strdup(boolean_value ? + "true" : "false"); + } + else + { + return NULL; + } + + g_return_val_if_fail(value, NULL); + + node = xmlnode_new("attribute"); + + xmlnode_set_attrib(node, "id", id); + xmlnode_set_attrib(node, "value", value); + + g_free(value); + + return node; +} + +static xmlnode * +status_attrs_to_xmlnode(const PurpleStatus *status) +{ + PurpleStatusType *type = purple_status_get_type(status); + xmlnode *node, *child; + GList *attrs, *attr; + + node = xmlnode_new("attributes"); + + attrs = purple_status_type_get_attrs(type); + for (attr = attrs; attr != NULL; attr = attr->next) + { + child = status_attr_to_xmlnode(status, type, (const PurpleStatusAttr *)attr->data); + if (child) + xmlnode_insert_child(node, child); + } + + return node; +} + +static xmlnode * +status_to_xmlnode(const PurpleStatus *status) +{ + xmlnode *node, *child; + + node = xmlnode_new("status"); + xmlnode_set_attrib(node, "type", purple_status_get_id(status)); + if (purple_status_get_name(status) != NULL) + xmlnode_set_attrib(node, "name", purple_status_get_name(status)); + xmlnode_set_attrib(node, "active", purple_status_is_active(status) ? "true" : "false"); + + child = status_attrs_to_xmlnode(status); + xmlnode_insert_child(node, child); + + return node; } -void -purple_accounts_remove(PurpleAccount *account) +static xmlnode * +statuses_to_xmlnode(const PurplePresence *presence) +{ + xmlnode *node, *child; + GList *statuses; + PurpleStatus *status; + + node = xmlnode_new("statuses"); + + statuses = purple_presence_get_statuses(presence); + for (; statuses != NULL; statuses = statuses->next) + { + status = statuses->data; + if (purple_status_type_is_saveable(purple_status_get_type(status))) + { + child = status_to_xmlnode(status); + xmlnode_insert_child(node, child); + } + } + + return node; +} + +static xmlnode * +proxy_settings_to_xmlnode(PurpleProxyInfo *proxy_info) { - g_return_if_fail(account != NULL); - - accounts = g_list_remove(accounts, account); - - schedule_accounts_save(); - - /* Clearing the error ensures that account-error-changed is emitted, - * which is the end of the guarantee that the the error's pointer is - * valid. + xmlnode *node, *child; + PurpleProxyType proxy_type; + const char *value; + int int_value; + char buf[21]; + + proxy_type = purple_proxy_info_get_type(proxy_info); + + node = xmlnode_new("proxy"); + + child = xmlnode_new_child(node, "type"); + xmlnode_insert_data(child, + (proxy_type == PURPLE_PROXY_USE_GLOBAL ? "global" : + proxy_type == PURPLE_PROXY_NONE ? "none" : + proxy_type == PURPLE_PROXY_HTTP ? "http" : + proxy_type == PURPLE_PROXY_SOCKS4 ? "socks4" : + proxy_type == PURPLE_PROXY_SOCKS5 ? "socks5" : + proxy_type == PURPLE_PROXY_TOR ? "tor" : + proxy_type == PURPLE_PROXY_USE_ENVVAR ? "envvar" : "unknown"), -1); + + if ((value = purple_proxy_info_get_host(proxy_info)) != NULL) + { + child = xmlnode_new_child(node, "host"); + xmlnode_insert_data(child, value, -1); + } + + if ((int_value = purple_proxy_info_get_port(proxy_info)) != 0) + { + g_snprintf(buf, sizeof(buf), "%d", int_value); + child = xmlnode_new_child(node, "port"); + xmlnode_insert_data(child, buf, -1); + } + + if ((value = purple_proxy_info_get_username(proxy_info)) != NULL) + { + child = xmlnode_new_child(node, "username"); + xmlnode_insert_data(child, value, -1); + } + + if ((value = purple_proxy_info_get_password(proxy_info)) != NULL) + { + child = xmlnode_new_child(node, "password"); + xmlnode_insert_data(child, value, -1); + } + + return node; +} + +static xmlnode * +current_error_to_xmlnode(PurpleConnectionErrorInfo *err) +{ + xmlnode *node, *child; + char type_str[3]; + + node = xmlnode_new("current_error"); + + if(err == NULL) + return node; + + /* It doesn't make sense to have transient errors persist across a + * restart. */ - purple_account_clear_current_error(account); - purple_signal_emit(purple_accounts_get_handle(), "account-removed", account); + if(!purple_connection_error_is_fatal (err->type)) + return node; + + child = xmlnode_new_child(node, "type"); + g_snprintf(type_str, sizeof(type_str), "%u", err->type); + xmlnode_insert_data(child, type_str, -1); + + child = xmlnode_new_child(node, "description"); + if(err->description) { + char *utf8ized = purple_utf8_try_convert(err->description); + if(utf8ized == NULL) + utf8ized = purple_utf8_salvage(err->description); + xmlnode_insert_data(child, utf8ized, -1); + g_free(utf8ized); + } + + return node; +} + +static void +setting_to_xmlnode(gpointer key, gpointer value, gpointer user_data) +{ + const char *name; + PurpleAccountSetting *setting; + xmlnode *node, *child; + char buf[21]; + + name = (const char *)key; + setting = (PurpleAccountSetting *)value; + node = (xmlnode *)user_data; + + child = xmlnode_new_child(node, "setting"); + xmlnode_set_attrib(child, "name", name); + + if (G_VALUE_HOLDS_INT(&setting->value)) { + xmlnode_set_attrib(child, "type", "int"); + g_snprintf(buf, sizeof(buf), "%d", g_value_get_int(&setting->value)); + xmlnode_insert_data(child, buf, -1); + } + else if (G_VALUE_HOLDS_STRING(&setting->value) && g_value_get_string(&setting->value) != NULL) { + xmlnode_set_attrib(child, "type", "string"); + xmlnode_insert_data(child, g_value_get_string(&setting->value), -1); + } + else if (G_VALUE_HOLDS_BOOLEAN(&setting->value)) { + xmlnode_set_attrib(child, "type", "bool"); + g_snprintf(buf, sizeof(buf), "%d", g_value_get_boolean(&setting->value)); + xmlnode_insert_data(child, buf, -1); + } } static void -purple_accounts_delete_set(PurpleAccount *account, GError *error, gpointer data) +ui_setting_to_xmlnode(gpointer key, gpointer value, gpointer user_data) { - purple_account_destroy(account); + const char *ui; + GHashTable *table; + xmlnode *node, *child; + + ui = (const char *)key; + table = (GHashTable *)value; + node = (xmlnode *)user_data; + + if (g_hash_table_size(table) > 0) + { + child = xmlnode_new_child(node, "settings"); + xmlnode_set_attrib(child, "ui", ui); + g_hash_table_foreach(table, setting_to_xmlnode, child); + } } -void -purple_accounts_delete(PurpleAccount *account) +xmlnode * +purple_account_to_xmlnode(PurpleAccount *account) { - PurpleBlistNode *gnode, *cnode, *bnode; - GList *iter; - - g_return_if_fail(account != NULL); - - /* - * Disable the account before blowing it out of the water. - * Conceptually it probably makes more sense to disable the - * account for all UIs rather than the just the current UI, - * but it doesn't really matter. - */ - purple_account_set_enabled(account, purple_core_get_ui(), FALSE); - - purple_notify_close_with_handle(account); - purple_request_close_with_handle(account); - - purple_accounts_remove(account); - - /* Remove this account's buddies */ - for (gnode = purple_blist_get_root(); - gnode != NULL; - gnode = purple_blist_node_get_sibling_next(gnode)) + xmlnode *node, *child; + const char *tmp; + PurplePresence *presence; + PurpleProxyInfo *proxy_info; + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + node = xmlnode_new("account"); + + child = xmlnode_new_child(node, "protocol"); + xmlnode_insert_data(child, purple_account_get_protocol_id(account), -1); + + child = xmlnode_new_child(node, "name"); + xmlnode_insert_data(child, purple_account_get_username(account), -1); + + if (purple_account_get_remember_password(account)) { - if (!PURPLE_BLIST_NODE_IS_GROUP(gnode)) - continue; - - cnode = purple_blist_node_get_first_child(gnode); - while (cnode) { - PurpleBlistNode *cnode_next = purple_blist_node_get_sibling_next(cnode); - - if(PURPLE_BLIST_NODE_IS_CONTACT(cnode)) { - bnode = purple_blist_node_get_first_child(cnode); - while (bnode) { - PurpleBlistNode *bnode_next = purple_blist_node_get_sibling_next(bnode); - - if (PURPLE_BLIST_NODE_IS_BUDDY(bnode)) { - PurpleBuddy *b = (PurpleBuddy *)bnode; - - if (purple_buddy_get_account(b) == account) - purple_blist_remove_buddy(b); - } - bnode = bnode_next; - } - } else if (PURPLE_BLIST_NODE_IS_CHAT(cnode)) { - PurpleChat *c = (PurpleChat *)cnode; - - if (purple_chat_get_account(c) == account) - purple_blist_remove_chat(c); - } - cnode = cnode_next; + const char *keyring_id = NULL; + const char *mode = NULL; + char *data = NULL; + GError *error = NULL; + GDestroyNotify destroy = NULL; + gboolean exported = purple_keyring_export_password(account, + &keyring_id, &mode, &data, &error, &destroy); + + if (error != NULL) { + purple_debug_error("account", + "Failed to export password for account %s: %s.\n", + purple_account_get_username(account), + error->message); + } else if (exported) { + child = xmlnode_new_child(node, "password"); + if (keyring_id != NULL) + xmlnode_set_attrib(child, "keyring_id", keyring_id); + if (mode != NULL) + xmlnode_set_attrib(child, "mode", mode); + if (data != NULL) + xmlnode_insert_data(child, data, -1); + + if (destroy != NULL) + destroy(data); } } - /* Remove any open conversation for this account */ - for (iter = purple_get_conversations(); iter; ) { - PurpleConversation *conv = iter->data; - iter = iter->next; - if (purple_conversation_get_account(conv) == account) - purple_conversation_destroy(conv); + if ((tmp = purple_account_get_private_alias(account)) != NULL) + { + child = xmlnode_new_child(node, "alias"); + xmlnode_insert_data(child, tmp, -1); + } + + if ((presence = purple_account_get_presence(account)) != NULL) + { + child = statuses_to_xmlnode(presence); + xmlnode_insert_child(node, child); + } + + if ((tmp = purple_account_get_user_info(account)) != NULL) + { + /* TODO: Do we need to call purple_str_strip_char(tmp, '\r') here? */ + child = xmlnode_new_child(node, "userinfo"); + xmlnode_insert_data(child, tmp, -1); + } + + if (g_hash_table_size(priv->settings) > 0) + { + child = xmlnode_new_child(node, "settings"); + g_hash_table_foreach(priv->settings, setting_to_xmlnode, child); + } + + if (g_hash_table_size(priv->ui_settings) > 0) + { + g_hash_table_foreach(priv->ui_settings, ui_setting_to_xmlnode, node); + } + + if ((proxy_info = purple_account_get_proxy_info(account)) != NULL) + { + child = proxy_settings_to_xmlnode(proxy_info); + xmlnode_insert_child(node, child); } - /* Remove this account's pounces */ - purple_pounce_destroy_all_by_account(account); - - /* This will cause the deletion of an old buddy icon. */ - purple_buddy_icons_set_account_icon(account, NULL, 0); - - /* This is async because we do not want the - * account being overwritten before we are done. - */ - purple_keyring_set_password(account, NULL, - purple_accounts_delete_set, NULL); + child = current_error_to_xmlnode(priv->current_error); + xmlnode_insert_child(node, child); + + return node; } -void -purple_accounts_reorder(PurpleAccount *account, gint new_index) +/**************** + * GObject Code * + ****************/ + +/* GObject Property names */ +#define PROP_USERNAME_S "username" +#define PROP_PRIVATE_ALIAS_S "private-alias" +#define PROP_ENABLED_S "enabled" +#define PROP_CONNECTION_S "connection" +#define PROP_PROTOCOL_ID_S "protocol-id" +#define PROP_USER_INFO_S "userinfo" +#define PROP_BUDDY_ICON_PATH_S "buddy-icon-path" +#define PROP_REMEMBER_PASSWORD_S "remember-password" +#define PROP_CHECK_MAIL_S "check-mail" + +/* Set method for GObject properties */ +static void +purple_account_set_property(GObject *obj, guint param_id, const GValue *value, + GParamSpec *pspec) { - gint index; - GList *l; - - g_return_if_fail(account != NULL); - g_return_if_fail(new_index <= g_list_length(accounts)); - - index = g_list_index(accounts, account); - - if (index == -1) { - purple_debug_error("account", - "Unregistered account (%s) discovered during reorder!\n", - purple_account_get_username(account)); - return; + PurpleAccount *account = PURPLE_ACCOUNT(obj); + + switch (param_id) { + case PROP_USERNAME: + purple_account_set_username(account, g_value_get_string(value)); + break; + case PROP_PRIVATE_ALIAS: + purple_account_set_private_alias(account, g_value_get_string(value)); + break; + case PROP_ENABLED: + purple_account_set_enabled(account, purple_core_get_ui(), + g_value_get_boolean(value)); + break; + case PROP_CONNECTION: +#warning TODO: change get_pointer to get_object when PurpleConnection is a GObject + purple_account_set_connection(account, g_value_get_pointer(value)); + break; + case PROP_PROTOCOL_ID: + purple_account_set_protocol_id(account, g_value_get_string(value)); + break; + case PROP_USER_INFO: + purple_account_set_user_info(account, g_value_get_string(value)); + break; + case PROP_BUDDY_ICON_PATH: + purple_account_set_buddy_icon_path(account, + g_value_get_string(value)); + break; + case PROP_REMEMBER_PASSWORD: + purple_account_set_remember_password(account, + g_value_get_boolean(value)); + break; + case PROP_CHECK_MAIL: + purple_account_set_check_mail(account, g_value_get_boolean(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* Get method for GObject properties */ +static void +purple_account_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleAccount *account = PURPLE_ACCOUNT(obj); + + switch (param_id) { + case PROP_USERNAME: + g_value_set_string(value, purple_account_get_username(account)); + break; + case PROP_PRIVATE_ALIAS: + g_value_set_string(value, purple_account_get_private_alias(account)); + break; + case PROP_ENABLED: + g_value_set_boolean(value, purple_account_get_enabled(account, + purple_core_get_ui())); + break; + case PROP_CONNECTION: +#warning TODO: change set_pointer to set_object when PurpleConnection is a GObject + g_value_set_pointer(value, purple_account_get_connection(account)); + break; + case PROP_PROTOCOL_ID: + g_value_set_string(value, purple_account_get_protocol_id(account)); + break; + case PROP_USER_INFO: + g_value_set_string(value, purple_account_get_user_info(account)); + break; + case PROP_BUDDY_ICON_PATH: + g_value_set_string(value, + purple_account_get_buddy_icon_path(account)); + break; + case PROP_REMEMBER_PASSWORD: + g_value_set_boolean(value, + purple_account_get_remember_password(account)); + break; + case PROP_CHECK_MAIL: + g_value_set_boolean(value, purple_account_get_check_mail(account)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; } - - l = g_list_nth(accounts, index); - - if (new_index > index) - new_index--; - - /* Remove the old one. */ - accounts = g_list_delete_link(accounts, l); - - /* Insert it where it should go. */ - accounts = g_list_insert(accounts, account, new_index); - - schedule_accounts_save(); +} + +/* GObject initialization function */ +static void purple_account_init(GTypeInstance *instance, gpointer klass) +{ + PurpleAccount *account = PURPLE_ACCOUNT(instance); + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + priv->settings = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, delete_setting); + priv->ui_settings = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, (GDestroyNotify)g_hash_table_destroy); + priv->system_log = NULL; + + priv->privacy_type = PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL; } -GList * -purple_accounts_get_all(void) +/* GObject dispose function */ +static void +purple_account_dispose(GObject *object) +{ + GList *l; + PurpleAccount *account = PURPLE_ACCOUNT(object); + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + purple_debug_info("account", "Destroying account %p\n", account); + purple_signal_emit(purple_accounts_get_handle(), "account-destroying", + account); + + for (l = purple_get_conversations(); l != NULL; l = l->next) + { + PurpleConversation *conv = (PurpleConversation *)l->data; + + if (purple_conversation_get_account(conv) == account) + purple_conversation_set_account(conv, NULL); + } + + purple_account_set_status_types(account, NULL); + + if (priv->proxy_info) + purple_proxy_info_destroy(priv->proxy_info); + + if (priv->presence) + purple_presence_destroy(priv->presence); + + if(priv->system_log) + purple_log_free(priv->system_log); + + if (priv->current_error) { + g_free(priv->current_error->description); + g_free(priv->current_error); + } + + PURPLE_DBUS_UNREGISTER_POINTER(priv->current_error); + PURPLE_DBUS_UNREGISTER_POINTER(account); + + parent_class->dispose(object); +} + +/* GObject finalize function */ +static void +purple_account_finalize(GObject *object) +{ + PurpleAccount *account = PURPLE_ACCOUNT(object); + PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + g_free(priv->username); + g_free(priv->alias); + purple_str_wipe(priv->password); + g_free(priv->user_info); + g_free(priv->buddy_icon_path); + g_free(priv->protocol_id); + + g_hash_table_destroy(priv->settings); + g_hash_table_destroy(priv->ui_settings); + + while (priv->deny) { + g_free(priv->deny->data); + priv->deny = g_slist_delete_link(priv->deny, priv->deny); + } + + while (priv->permit) { + g_free(priv->permit->data); + priv->permit = g_slist_delete_link(priv->permit, priv->permit); + } + + parent_class->finalize(object); +} + +/* Class initializer function */ +static void purple_account_class_init(PurpleAccountClass *klass) { - return accounts; + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + obj_class->dispose = purple_account_dispose; + obj_class->finalize = purple_account_finalize; + + /* Setup properties */ + obj_class->get_property = purple_account_get_property; + obj_class->set_property = purple_account_set_property; + + g_object_class_install_property(obj_class, PROP_USERNAME, + g_param_spec_string(PROP_USERNAME_S, _("Username"), + _("The username for the account."), NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT) + ); + + g_object_class_install_property(obj_class, PROP_PRIVATE_ALIAS, + g_param_spec_string(PROP_PRIVATE_ALIAS_S, _("Private Alias"), + _("The private alias for the account."), NULL, + G_PARAM_READWRITE) + ); + + g_object_class_install_property(obj_class, PROP_USER_INFO, + g_param_spec_string(PROP_USER_INFO_S, _("User information"), + _("Detailed user information for the account."), NULL, + G_PARAM_READWRITE) + ); + + g_object_class_install_property(obj_class, PROP_BUDDY_ICON_PATH, + g_param_spec_string(PROP_BUDDY_ICON_PATH_S, _("Buddy icon path"), + _("Path to the buddyicon for the account."), NULL, + G_PARAM_READWRITE) + ); + + g_object_class_install_property(obj_class, PROP_ENABLED, + g_param_spec_boolean(PROP_ENABLED_S, _("Enabled"), + _("Whether the account is enabled or not."), FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT) + ); + + g_object_class_install_property(obj_class, PROP_REMEMBER_PASSWORD, + g_param_spec_boolean(PROP_REMEMBER_PASSWORD_S, _("Remember password"), + _("Whether to remember and store the password for this account."), FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT) + ); + + g_object_class_install_property(obj_class, PROP_CHECK_MAIL, + g_param_spec_boolean(PROP_CHECK_MAIL_S, _("Check mail"), + _("Whether to check mails for this account."), FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT) + ); + +#warning TODO: change spec_pointer to spec_object when PurpleConnection is a GObject + g_object_class_install_property(obj_class, PROP_CONNECTION, + g_param_spec_pointer(PROP_CONNECTION_S, _("Connection"), + _("The PurpleConnection object for the account."), + G_PARAM_READWRITE) + ); + + g_object_class_install_property(obj_class, PROP_PROTOCOL_ID, + g_param_spec_string(PROP_PROTOCOL_ID_S, _("Protocol ID"), + _("ID of the protocol that is responsible for the account."), NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY) + ); + + g_type_class_add_private(klass, sizeof(PurpleAccountPrivate)); } -GList * -purple_accounts_get_all_active(void) +GType +purple_account_get_type(void) { - GList *list = NULL; - GList *all = purple_accounts_get_all(); - - while (all != NULL) { - PurpleAccount *account = all->data; - - if (purple_account_get_enabled(account, purple_core_get_ui())) - list = g_list_append(list, account); - - all = all->next; + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleAccountClass), + NULL, + NULL, + (GClassInitFunc)purple_account_class_init, + NULL, + NULL, + sizeof(PurpleAccount), + 0, + (GInstanceInitFunc)purple_account_init, + NULL, + }; + + type = g_type_register_static(G_TYPE_OBJECT, + "PurpleAccount", + &info, 0); } - return list; + return type; } PurpleAccount * -purple_accounts_find(const char *name, const char *protocol_id) +purple_account_new(const char *username, const char *protocol_id) { PurpleAccount *account = NULL; - GList *l; - char *who; - - g_return_val_if_fail(name != NULL, NULL); + PurplePlugin *prpl = NULL; + PurplePluginProtocolInfo *prpl_info = NULL; + PurpleStatusType *status_type; + PurpleAccountPrivate *priv; + + g_return_val_if_fail(username != NULL, NULL); g_return_val_if_fail(protocol_id != NULL, NULL); - for (l = purple_accounts_get_all(); l != NULL; l = l->next) { - account = (PurpleAccount *)l->data; - if (!purple_strequal(account->protocol_id, protocol_id)) - continue; - - who = g_strdup(purple_normalize(account, name)); - if (purple_strequal(purple_normalize(account, purple_account_get_username(account)), who)) { - g_free(who); - return account; - } - g_free(who); - } - - return NULL; -} - -void -purple_accounts_restore_current_statuses() -{ - GList *l; - PurpleAccount *account; - - /* If we're not connected to the Internet right now, we bail on this */ - if (!purple_network_is_available()) - { - purple_debug_warning("account", "Network not connected; skipping reconnect\n"); - return; - } - - for (l = purple_accounts_get_all(); l != NULL; l = l->next) - { - account = (PurpleAccount *)l->data; - if (purple_account_get_enabled(account, purple_core_get_ui()) && - (purple_presence_is_online(account->presence))) - { - purple_account_connect(account); - } - } -} - -void -purple_accounts_set_ui_ops(PurpleAccountUiOps *ops) -{ - account_ui_ops = ops; -} - -PurpleAccountUiOps * -purple_accounts_get_ui_ops(void) -{ - return account_ui_ops; -} - -void * -purple_accounts_get_handle(void) -{ - static int handle; - - return &handle; + account = purple_accounts_find(username, protocol_id); + + if (account != NULL) + return account; + + account = g_object_new(PURPLE_TYPE_ACCOUNT, + PROP_USERNAME_S, username, + PROP_PROTOCOL_ID_S, protocol_id, + NULL); + PURPLE_DBUS_REGISTER_POINTER(account, PurpleAccount); + + purple_signal_emit(purple_accounts_get_handle(), "account-created", + account); + + prpl = purple_find_prpl(protocol_id); + if (prpl == NULL) + return account; + + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + if (prpl_info != NULL && prpl_info->status_types != NULL) + purple_account_set_status_types(account, + prpl_info->status_types(account)); + + priv = PURPLE_ACCOUNT_GET_PRIVATE(account); + + priv->presence = purple_presence_new_for_account(account); + + status_type = purple_account_get_status_type_with_primitive(account, + PURPLE_STATUS_AVAILABLE); + if (status_type != NULL) + purple_presence_set_status_active(priv->presence, + purple_status_type_get_id(status_type), + TRUE); + else + purple_presence_set_status_active(priv->presence, + "offline", + TRUE); + + return account; } - -void -purple_accounts_init(void) -{ - void *handle = purple_accounts_get_handle(); - void *conn_handle = purple_connections_get_handle(); - - purple_signal_register(handle, "account-connecting", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT)); - - purple_signal_register(handle, "account-disabled", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT)); - - purple_signal_register(handle, "account-enabled", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT)); - - purple_signal_register(handle, "account-setting-info", - purple_marshal_VOID__POINTER_POINTER, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "account-set-info", - purple_marshal_VOID__POINTER_POINTER, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "account-created", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_ACCOUNT)); - - purple_signal_register(handle, "account-destroying", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_ACCOUNT)); - - purple_signal_register(handle, "account-added", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_ACCOUNT)); - - purple_signal_register(handle, "account-removed", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_ACCOUNT)); - - purple_signal_register(handle, "account-status-changed", - purple_marshal_VOID__POINTER_POINTER_POINTER, NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_STATUS), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_STATUS)); - - purple_signal_register(handle, "account-actions-changed", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_ACCOUNT)); - - purple_signal_register(handle, "account-alias-changed", - purple_marshal_VOID__POINTER_POINTER, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "account-authorization-requested", - purple_marshal_INT__POINTER_POINTER_POINTER, - purple_value_new(PURPLE_TYPE_INT), 4, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "account-authorization-denied", - purple_marshal_VOID__POINTER_POINTER, NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "account-authorization-granted", - purple_marshal_VOID__POINTER_POINTER, NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "account-error-changed", - purple_marshal_VOID__POINTER_POINTER_POINTER, - NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_POINTER), - purple_value_new(PURPLE_TYPE_POINTER)); - - purple_signal_register(handle, "account-signed-on", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT)); - - purple_signal_register(handle, "account-signed-off", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT)); - - purple_signal_register(handle, "account-connection-error", - purple_marshal_VOID__POINTER_INT_POINTER, NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_ENUM), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_connect(conn_handle, "signed-on", handle, - PURPLE_CALLBACK(signed_on_cb), NULL); - purple_signal_connect(conn_handle, "signed-off", handle, - PURPLE_CALLBACK(signed_off_cb), NULL); - purple_signal_connect(conn_handle, "connection-error", handle, - PURPLE_CALLBACK(connection_error_cb), NULL); - purple_signal_connect(purple_keyring_get_handle(), "password-migration", handle, - PURPLE_CALLBACK(password_migration_cb), NULL); - - load_accounts(); - -} - -void -purple_accounts_uninit(void) -{ - gpointer handle = purple_accounts_get_handle(); - if (save_timer != 0) - { - purple_timeout_remove(save_timer); - save_timer = 0; - sync_accounts(); - } - - for (; accounts; accounts = g_list_delete_link(accounts, accounts)) - purple_account_destroy(accounts->data); - - purple_signals_disconnect_by_handle(handle); - purple_signals_unregister_by_instance(handle); -}
--- a/libpurple/account.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/account.h Sun Jun 23 13:35:53 2013 +0530 @@ -30,10 +30,17 @@ #include <glib.h> #include <glib-object.h> -/** @copydoc _PurpleAccountUiOps */ -typedef struct _PurpleAccountUiOps PurpleAccountUiOps; +#define PURPLE_TYPE_ACCOUNT (purple_account_get_type()) +#define PURPLE_ACCOUNT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_ACCOUNT, PurpleAccount)) +#define PURPLE_ACCOUNT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_ACCOUNT, PurpleAccountClass)) +#define PURPLE_IS_ACCOUNT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_ACCOUNT)) +#define PURPLE_IS_ACCOUNT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_ACCOUNT)) +#define PURPLE_ACCOUNT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_ACCOUNT, PurpleAccountClass)) + /** @copydoc _PurpleAccount */ -typedef struct _PurpleAccount PurpleAccount; +typedef struct _PurpleAccount PurpleAccount; +/** @copydoc _PurpleAccountClass */ +typedef struct _PurpleAccountClass PurpleAccountClass; typedef gboolean (*PurpleFilterAccountFunc)(PurpleAccount *account); typedef void (*PurpleAccountRequestAuthorizationCb)(const char *, void *); @@ -46,11 +53,11 @@ #include "connection.h" #include "log.h" -#include "privacy.h" #include "proxy.h" #include "prpl.h" #include "status.h" #include "keyring.h" +#include "xmlnode.h" /** * Account request types. @@ -71,51 +78,24 @@ PURPLE_ACCOUNT_RESPONSE_ACCEPT = 1 } PurpleAccountRequestResponse; -/** Account UI operations, used to notify the user of status changes and when - * buddies add this account to their buddy lists. +/** + * Privacy data types. */ -struct _PurpleAccountUiOps +typedef enum { - /** A buddy who is already on this account's buddy list added this account - * to their buddy list. - */ - void (*notify_added)(PurpleAccount *account, - const char *remote_user, - const char *id, - const char *alias, - const char *message); - - /** This account's status changed. */ - void (*status_changed)(PurpleAccount *account, - PurpleStatus *status); + PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL = 1, + PURPLE_ACCOUNT_PRIVACY_DENY_ALL, + PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS, + PURPLE_ACCOUNT_PRIVACY_DENY_USERS, + PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST +} PurpleAccountPrivacyType; - /** Someone we don't have on our list added us; prompt to add them. */ - void (*request_add)(PurpleAccount *account, - const char *remote_user, - const char *id, - const char *alias, - const char *message); - - /** Prompt for authorization when someone adds this account to their buddy - * list. To authorize them to see this account's presence, call \a - * authorize_cb (\a message, \a user_data); otherwise call - * \a deny_cb (\a message, \a user_data); - * @return a UI-specific handle, as passed to #close_account_request. - */ - void *(*request_authorize)(PurpleAccount *account, - const char *remote_user, - const char *id, - const char *alias, - const char *message, - gboolean on_list, - PurpleAccountRequestAuthorizationCb authorize_cb, - PurpleAccountRequestAuthorizationCb deny_cb, - void *user_data); - - /** Close a pending request for authorization. \a ui_handle is a handle - * as returned by #request_authorize. - */ - void (*close_account_request)(void *ui_handle); +/** Structure representing an account. + */ +struct _PurpleAccount +{ + /*< private >*/ + GObject gparent; void (*_purple_reserved1)(void); void (*_purple_reserved2)(void); @@ -123,58 +103,25 @@ void (*_purple_reserved4)(void); }; -/** Structure representing an account. +/** + * PurpleAccountClass: + * + * The base class for all #PurpleAccount's. */ -struct _PurpleAccount -{ - char *username; /**< The username. */ - char *alias; /**< How you appear to yourself. */ - char *password; /**< The account password. */ - char *user_info; /**< User information. */ - - char *buddy_icon_path; /**< The buddy icon's non-cached path. */ - - gboolean remember_pass; /**< Remember the password. */ - - char *protocol_id; /**< The ID of the protocol. */ - - PurpleConnection *gc; /**< The connection handle. */ - gboolean disconnecting; /**< The account is currently disconnecting */ - - GHashTable *settings; /**< Protocol-specific settings. */ - GHashTable *ui_settings; /**< UI-specific settings. */ +struct _PurpleAccountClass { + /*< private >*/ + GObjectClass parent_class; - PurpleProxyInfo *proxy_info; /**< Proxy information. This will be set */ - /* to NULL when the account inherits */ - /* proxy settings from global prefs. */ - - /* - * TODO: Supplementing the next two linked lists with hash tables - * should help performance a lot when these lists are long. This - * matters quite a bit for protocols like MSN, where all your - * buddies are added to your permit list. Currently we have to - * iterate through the entire list if we want to check if someone - * is permitted or denied. We should do this for 3.0.0. - * Or maybe use a GTree. - */ - GSList *permit; /**< Permit list. */ - GSList *deny; /**< Deny list. */ - PurplePrivacyType perm_deny; /**< The permit/deny setting. */ - - GList *status_types; /**< Status types. */ - - PurplePresence *presence; /**< Presence. */ - PurpleLog *system_log; /**< The system log */ - - void *ui_data; /**< The UI can put data here. */ - PurpleAccountRegistrationCb registration_cb; - void *registration_cb_user_data; - - PurpleConnectionErrorInfo *current_error; /**< Errors */ + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); }; G_BEGIN_DECLS +GType purple_account_get_type(void); + /**************************************************************************/ /** @name Account API */ /**************************************************************************/ @@ -191,13 +138,6 @@ PurpleAccount *purple_account_new(const char *username, const char *protocol_id); /** - * Destroys an account. - * - * @param account The account to destroy. - */ -void purple_account_destroy(PurpleAccount *account); - -/** * Connects to an account. * * @param account The account to connect to. @@ -379,12 +319,12 @@ PurpleKeyringSaveCallback cb, gpointer data); /** - * Sets the account's alias. + * Sets the account's private alias. * * @param account The account. * @param alias The alias. */ -void purple_account_set_alias(PurpleAccount *account, const char *alias); +void purple_account_set_private_alias(PurpleAccount *account, const char *alias); /** * Sets the account's user information @@ -460,7 +400,7 @@ * @param account The account. * @param privacy_type The privacy type. */ -void purple_account_set_privacy_type(PurpleAccount *account, PurplePrivacyType privacy_type); +void purple_account_set_privacy_type(PurpleAccount *account, PurpleAccountPrivacyType privacy_type); /** * Sets the account's status types. @@ -629,25 +569,6 @@ const char *name, gboolean value); /** - * Returns the UI data associated with this account. - * - * @param account The account. - * - * @return The UI data associated with this object. This is a - * convenience field provided to the UIs--it is not - * used by the libuprple core. - */ -gpointer purple_account_get_ui_data(const PurpleAccount *account); - -/** - * Set the UI data associated with this account. - * - * @param account The account. - * @param ui_data A pointer to associate with this object. - */ -void purple_account_set_ui_data(PurpleAccount *account, gpointer ui_data); - -/** * Returns whether or not the account is connected. * * @param account The account. @@ -699,13 +620,13 @@ PurpleKeyringReadCallback cb, gpointer data); /** - * Returns the account's alias. + * Returns the account's private alias. * * @param account The account. * * @return The alias. */ -const char *purple_account_get_alias(const PurpleAccount *account); +const char *purple_account_get_private_alias(const PurpleAccount *account); /** * Returns the account's user information. @@ -810,7 +731,135 @@ * * @return The privacy type. */ -PurplePrivacyType purple_account_get_privacy_type(const PurpleAccount *account); +PurpleAccountPrivacyType purple_account_get_privacy_type(const PurpleAccount *account); + +/** + * Adds a user to the account's permit list. + * + * @param account The account. + * @param name The name of the user to add to the list. + * @param local_only If TRUE, only the local list is updated, and not + * the server. + * + * @return TRUE if the user was added successfully, or @c FALSE otherwise. + */ +gboolean purple_account_privacy_permit_add(PurpleAccount *account, + const char *name, gboolean local_only); + +/** + * Removes a user from the account's permit list. + * + * @param account The account. + * @param name The name of the user to add to the list. + * @param local_only If TRUE, only the local list is updated, and not + * the server. + * + * @return TRUE if the user was removed successfully, or @c FALSE otherwise. + */ +gboolean purple_account_privacy_permit_remove(PurpleAccount *account, + const char *name, gboolean local_only); + +/** + * Adds a user to the account's deny list. + * + * @param account The account. + * @param name The name of the user to add to the list. + * @param local_only If TRUE, only the local list is updated, and not + * the server. + * + * @return TRUE if the user was added successfully, or @c FALSE otherwise. + */ +gboolean purple_account_privacy_deny_add(PurpleAccount *account, + const char *name, gboolean local_only); + +/** + * Removes a user from the account's deny list. + * + * @param account The account. + * @param name The name of the user to add to the list. + * @param local_only If TRUE, only the local list is updated, and not + * the server. + * + * @return TRUE if the user was removed successfully, or @c FALSE otherwise. + */ +gboolean purple_account_privacy_deny_remove(PurpleAccount *account, + const char *name, gboolean local_only); + +/** + * Allow a user to send messages. If current privacy setting for the account is: + * PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS: The user is added to the allow-list. + * PURPLE_ACCOUNT_PRIVACY_DENY_USERS : The user is removed from the + * deny-list. + * PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL : No changes made. + * PURPLE_ACCOUNT_PRIVACY_DENY_ALL : The privacy setting is changed to + * PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS and the + * user is added to the allow-list. + * PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST: No changes made if the user is + * already in the buddy-list. Otherwise the + * setting is changed to + * PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS, all the buddies are added to the + * allow-list, and the user is also added to + * the allow-list. + * + * The changes are reflected on the server. The previous allow/deny list is not + * restored if the privacy setting is changed. + * + * @param account The account. + * @param who The name of the user. + */ +void purple_account_privacy_allow(PurpleAccount *account, const char *who); + +/** + * Block messages from a user. If current privacy setting for the account is: + * PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS: The user is removed from the + * allow-list. + * PURPLE_ACCOUNT_PRIVACY_DENY_USERS: The user is added to the deny-list. + * PURPLE_ACCOUNT_PRIVACY_DENY_ALL: No changes made. + * PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL: The privacy setting is changed to + * PURPLE_ACCOUNT_PRIVACY_DENY_USERS and the + * user is added to the deny-list. + * PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST: If the user is not in the + * buddy-list, then no changes made. Otherwise, + * the setting is changed to + * PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS, all + * the buddies are added to the allow-list, and + * this user is removed from the list. + * + * The changes are reflected on the server. The previous allow/deny list is not + * restored if the privacy setting is changed. + * + * @param account The account. + * @param who The name of the user. + */ +void purple_account_privacy_deny(PurpleAccount *account, const char *who); + +/** + * Returns the account's permit list. + * + * @param account The account. + * @constreturn A list of the permitted users + */ +GSList *purple_account_privacy_get_permitted(PurpleAccount *account); + +/** + * Returns the account's deny list. + * + * @param account The account. + * @constreturn A list of the denied users + */ +GSList *purple_account_privacy_get_denied(PurpleAccount *account); + +/** + * Check the privacy-setting for a user. + * + * @param account The account. + * @param who The name of the user. + * + * @return @c FALSE if the specified account's privacy settings block the user + * or @c TRUE otherwise. The meaning of "block" is protocol-dependent and + * generally relates to status and/or sending of messages. + */ +gboolean purple_account_privacy_check(PurpleAccount *account, const char *who); /** * Returns the active status for this account. This looks through @@ -1062,6 +1111,17 @@ gboolean purple_account_supports_offline_message(PurpleAccount *account, PurpleBuddy *buddy); /** + * Sets the error that caused the account to be disconnected. + * You should not ever need to call this function directly, the error is set + * by the accouts subsystem. You should only need to retrieve this error. + * + * @param account The account whose error should be set. + * @param new_err The new error. + */ +void purple_account_set_current_error(PurpleAccount *account, + PurpleConnectionErrorInfo *new_err); + +/** * Get the error that caused the account to be disconnected, or @c NULL if the * account is happily connected or disconnected without an error. * @@ -1080,128 +1140,13 @@ */ void purple_account_clear_current_error(PurpleAccount *account); -/*@}*/ - -/**************************************************************************/ -/** @name Accounts API */ -/**************************************************************************/ -/*@{*/ - /** - * Adds an account to the list of accounts. - * - * @param account The account. - */ -void purple_accounts_add(PurpleAccount *account); - -/** - * Removes an account from the list of accounts. - * - * @param account The account. - */ -void purple_accounts_remove(PurpleAccount *account); - -/** - * Deletes an account. - * - * This will remove any buddies from the buddy list that belong to this - * account, buddy pounces that belong to this account, and will also - * destroy @a account. - * - * @param account The account. - */ -void purple_accounts_delete(PurpleAccount *account); - -/** - * Reorders an account. - * - * @param account The account to reorder. - * @param new_index The new index for the account. - */ -void purple_accounts_reorder(PurpleAccount *account, gint new_index); - -/** - * Returns a list of all accounts. - * - * @constreturn A list of all accounts. - */ -GList *purple_accounts_get_all(void); - -/** - * Returns a list of all enabled accounts - * - * @return A list of all enabled accounts. The list is owned - * by the caller, and must be g_list_free()d to avoid - * leaking the nodes. - */ -GList *purple_accounts_get_all_active(void); - -/** - * Finds an account with the specified name and protocol id. + * Get an XML description of an account. * - * @param name The account username. - * @param protocol The account protocol ID. - * - * @return The account, if found, or @c FALSE otherwise. - */ -PurpleAccount *purple_accounts_find(const char *name, const char *protocol); - -/** - * This is called by the core after all subsystems and what - * not have been initialized. It sets all enabled accounts - * to their startup status by signing them on, setting them - * away, etc. - * - * You probably shouldn't call this unless you really know - * what you're doing. - */ -void purple_accounts_restore_current_statuses(void); - -/*@}*/ - - -/**************************************************************************/ -/** @name UI Registration Functions */ -/**************************************************************************/ -/*@{*/ -/** - * Sets the UI operations structure to be used for accounts. - * - * @param ops The UI operations structure. + * @param account The account + * @return The XML description of the account. */ -void purple_accounts_set_ui_ops(PurpleAccountUiOps *ops); - -/** - * Returns the UI operations structure used for accounts. - * - * @return The UI operations structure in use. - */ -PurpleAccountUiOps *purple_accounts_get_ui_ops(void); - -/*@}*/ - - -/**************************************************************************/ -/** @name Accounts Subsystem */ -/**************************************************************************/ -/*@{*/ - -/** - * Returns the accounts subsystem handle. - * - * @return The accounts subsystem handle. - */ -void *purple_accounts_get_handle(void); - -/** - * Initializes the accounts subsystem. - */ -void purple_accounts_init(void); - -/** - * Uninitializes the accounts subsystem. - */ -void purple_accounts_uninit(void); +xmlnode *purple_account_to_xmlnode(PurpleAccount *account); /*@}*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/accounts.c Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,1047 @@ +/** + * @file accounts.c Accounts API + * @ingroup core + */ + +/* 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 "internal.h" +#include "accounts.h" +#include "core.h" +#include "dbus-maybe.h" +#include "debug.h" +#include "network.h" +#include "pounce.h" + +static PurpleAccountUiOps *account_ui_ops = NULL; + +static GList *accounts = NULL; +static guint save_timer = 0; +static gboolean accounts_loaded = FALSE; + +/********************************************************************* + * Writing to disk * + *********************************************************************/ +static xmlnode * +accounts_to_xmlnode(void) +{ + xmlnode *node, *child; + GList *cur; + + node = xmlnode_new("account"); + xmlnode_set_attrib(node, "version", "1.0"); + + for (cur = purple_accounts_get_all(); cur != NULL; cur = cur->next) + { + child = purple_account_to_xmlnode(cur->data); + xmlnode_insert_child(node, child); + } + + return node; +} + +static void +sync_accounts(void) +{ + xmlnode *node; + char *data; + + if (!accounts_loaded) + { + purple_debug_error("account", "Attempted to save accounts before " + "they were read!\n"); + return; + } + + node = accounts_to_xmlnode(); + data = xmlnode_to_formatted_str(node, NULL); + purple_util_write_data_to_file("accounts.xml", data, -1); + g_free(data); + xmlnode_free(node); +} + +static gboolean +save_cb(gpointer data) +{ + sync_accounts(); + save_timer = 0; + return FALSE; +} + +void +purple_accounts_schedule_save(void) +{ + if (save_timer == 0) + save_timer = purple_timeout_add_seconds(5, save_cb, NULL); +} + +/********************************************************************* + * Reading from disk * + *********************************************************************/ +static void +migrate_yahoo_japan(PurpleAccount *account) +{ + /* detect a Yahoo! JAPAN account that existed prior to 2.6.0 and convert it + * to use the new prpl-yahoojp. Also remove the account-specific settings + * we no longer need */ + + if(purple_strequal(purple_account_get_protocol_id(account), "prpl-yahoo")) { + if(purple_account_get_bool(account, "yahoojp", FALSE)) { + const char *serverjp = purple_account_get_string(account, "serverjp", NULL); + const char *xferjp_host = purple_account_get_string(account, "xferjp_host", NULL); + + g_return_if_fail(serverjp != NULL); + g_return_if_fail(xferjp_host != NULL); + + purple_account_set_string(account, "server", serverjp); + purple_account_set_string(account, "xfer_host", xferjp_host); + + purple_account_set_protocol_id(account, "prpl-yahoojp"); + } + + /* these should always be nuked */ + purple_account_remove_setting(account, "yahoojp"); + purple_account_remove_setting(account, "serverjp"); + purple_account_remove_setting(account, "xferjp_host"); + + } +} + +static void +migrate_icq_server(PurpleAccount *account) +{ + /* Migrate the login server setting for ICQ accounts. See + * 'mtn log --last 1 --no-graph --from b6d7712e90b68610df3bd2d8cbaf46d94c8b3794' + * for details on the change. */ + + if(purple_strequal(purple_account_get_protocol_id(account), "prpl-icq")) { + const char *tmp = purple_account_get_string(account, "server", NULL); + + /* Non-secure server */ + if(purple_strequal(tmp, "login.messaging.aol.com") || + purple_strequal(tmp, "login.oscar.aol.com")) + purple_account_set_string(account, "server", "login.icq.com"); + + /* Secure server */ + if(purple_strequal(tmp, "slogin.oscar.aol.com")) + purple_account_set_string(account, "server", "slogin.icq.com"); + } +} + +static void +migrate_xmpp_encryption(PurpleAccount *account) +{ + /* When this is removed, nuke the "old_ssl" and "require_tls" settings */ + if (g_str_equal(purple_account_get_protocol_id(account), "prpl-jabber")) { + const char *sec = purple_account_get_string(account, "connection_security", ""); + + if (g_str_equal("", sec)) { + const char *val = "require_tls"; + if (purple_account_get_bool(account, "old_ssl", FALSE)) + val = "old_ssl"; + else if (!purple_account_get_bool(account, "require_tls", TRUE)) + val = "opportunistic_tls"; + + purple_account_set_string(account, "connection_security", val); + } + } +} + +static void +parse_settings(xmlnode *node, PurpleAccount *account) +{ + const char *ui; + xmlnode *child; + + /* Get the UI string, if these are UI settings */ + ui = xmlnode_get_attrib(node, "ui"); + + /* Read settings, one by one */ + for (child = xmlnode_get_child(node, "setting"); child != NULL; + child = xmlnode_get_next_twin(child)) + { + const char *name, *str_type; + PurplePrefType type; + char *data; + + name = xmlnode_get_attrib(child, "name"); + if (name == NULL) + /* Ignore this setting */ + continue; + + str_type = xmlnode_get_attrib(child, "type"); + if (str_type == NULL) + /* Ignore this setting */ + continue; + + if (purple_strequal(str_type, "string")) + type = PURPLE_PREF_STRING; + else if (purple_strequal(str_type, "int")) + type = PURPLE_PREF_INT; + else if (purple_strequal(str_type, "bool")) + type = PURPLE_PREF_BOOLEAN; + else + /* Ignore this setting */ + continue; + + data = xmlnode_get_data(child); + if (data == NULL) + /* Ignore this setting */ + continue; + + if (ui == NULL) + { + if (type == PURPLE_PREF_STRING) + purple_account_set_string(account, name, data); + else if (type == PURPLE_PREF_INT) + purple_account_set_int(account, name, atoi(data)); + else if (type == PURPLE_PREF_BOOLEAN) + purple_account_set_bool(account, name, + (*data == '0' ? FALSE : TRUE)); + } else { + if (type == PURPLE_PREF_STRING) + purple_account_set_ui_string(account, ui, name, data); + else if (type == PURPLE_PREF_INT) + purple_account_set_ui_int(account, ui, name, atoi(data)); + else if (type == PURPLE_PREF_BOOLEAN) + purple_account_set_ui_bool(account, ui, name, + (*data == '0' ? FALSE : TRUE)); + } + + g_free(data); + } + + /* we do this here because we need access to account settings to determine + * if we can/should migrate an old Yahoo! JAPAN account */ + migrate_yahoo_japan(account); + /* we do this here because we need access to account settings to determine + * if we can/should migrate an ICQ account's server setting */ + migrate_icq_server(account); + /* we do this here because we need to do it before the user views the + * Edit Account dialog. */ + migrate_xmpp_encryption(account); +} + +static GList * +parse_status_attrs(xmlnode *node, PurpleStatus *status) +{ + GList *list = NULL; + xmlnode *child; + PurpleValue *attr_value; + + for (child = xmlnode_get_child(node, "attribute"); child != NULL; + child = xmlnode_get_next_twin(child)) + { + const char *id = xmlnode_get_attrib(child, "id"); + const char *value = xmlnode_get_attrib(child, "value"); + + if (!id || !*id || !value || !*value) + continue; + + attr_value = purple_status_get_attr_value(status, id); + if (!attr_value) + continue; + + list = g_list_append(list, (char *)id); + + switch (purple_value_get_type(attr_value)) + { + case PURPLE_TYPE_STRING: + list = g_list_append(list, (char *)value); + break; + case PURPLE_TYPE_INT: + case PURPLE_TYPE_BOOLEAN: + { + int v; + if (sscanf(value, "%d", &v) == 1) + list = g_list_append(list, GINT_TO_POINTER(v)); + else + list = g_list_remove(list, id); + break; + } + default: + break; + } + } + + return list; +} + +static void +parse_status(xmlnode *node, PurpleAccount *account) +{ + gboolean active = FALSE; + const char *data; + const char *type; + xmlnode *child; + GList *attrs = NULL; + + /* Get the active/inactive state */ + data = xmlnode_get_attrib(node, "active"); + if (data == NULL) + return; + if (g_ascii_strcasecmp(data, "true") == 0) + active = TRUE; + else if (g_ascii_strcasecmp(data, "false") == 0) + active = FALSE; + else + return; + + /* Get the type of the status */ + type = xmlnode_get_attrib(node, "type"); + if (type == NULL) + return; + + /* Read attributes into a GList */ + child = xmlnode_get_child(node, "attributes"); + if (child != NULL) + { + attrs = parse_status_attrs(child, + purple_account_get_status(account, type)); + } + + purple_account_set_status_list(account, type, active, attrs); + + g_list_free(attrs); +} + +static void +parse_statuses(xmlnode *node, PurpleAccount *account) +{ + xmlnode *child; + + for (child = xmlnode_get_child(node, "status"); child != NULL; + child = xmlnode_get_next_twin(child)) + { + parse_status(child, account); + } +} + +static void +parse_proxy_info(xmlnode *node, PurpleAccount *account) +{ + PurpleProxyInfo *proxy_info; + xmlnode *child; + char *data; + + proxy_info = purple_proxy_info_new(); + + /* Use the global proxy settings, by default */ + purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_USE_GLOBAL); + + /* Read proxy type */ + child = xmlnode_get_child(node, "type"); + if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) + { + if (purple_strequal(data, "global")) + purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_USE_GLOBAL); + else if (purple_strequal(data, "none")) + purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_NONE); + else if (purple_strequal(data, "http")) + purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_HTTP); + else if (purple_strequal(data, "socks4")) + purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_SOCKS4); + else if (purple_strequal(data, "socks5")) + purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_SOCKS5); + else if (purple_strequal(data, "tor")) + purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_TOR); + else if (purple_strequal(data, "envvar")) + purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_USE_ENVVAR); + else + { + purple_debug_error("account", "Invalid proxy type found when " + "loading account information for %s\n", + purple_account_get_username(account)); + } + g_free(data); + } + + /* Read proxy host */ + child = xmlnode_get_child(node, "host"); + if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) + { + purple_proxy_info_set_host(proxy_info, data); + g_free(data); + } + + /* Read proxy port */ + child = xmlnode_get_child(node, "port"); + if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) + { + purple_proxy_info_set_port(proxy_info, atoi(data)); + g_free(data); + } + + /* Read proxy username */ + child = xmlnode_get_child(node, "username"); + if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) + { + purple_proxy_info_set_username(proxy_info, data); + g_free(data); + } + + /* Read proxy password */ + child = xmlnode_get_child(node, "password"); + if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) + { + purple_proxy_info_set_password(proxy_info, data); + g_free(data); + } + + /* If there are no values set then proxy_info NULL */ + if ((purple_proxy_info_get_type(proxy_info) == PURPLE_PROXY_USE_GLOBAL) && + (purple_proxy_info_get_host(proxy_info) == NULL) && + (purple_proxy_info_get_port(proxy_info) == 0) && + (purple_proxy_info_get_username(proxy_info) == NULL) && + (purple_proxy_info_get_password(proxy_info) == NULL)) + { + purple_proxy_info_destroy(proxy_info); + return; + } + + purple_account_set_proxy_info(account, proxy_info); +} + +static void +parse_current_error(xmlnode *node, PurpleAccount *account) +{ + guint type; + char *type_str = NULL, *description = NULL; + xmlnode *child; + PurpleConnectionErrorInfo *current_error = NULL; + + child = xmlnode_get_child(node, "type"); + if (child == NULL || (type_str = xmlnode_get_data(child)) == NULL) + return; + type = atoi(type_str); + g_free(type_str); + + if (type > PURPLE_CONNECTION_ERROR_OTHER_ERROR) + { + purple_debug_error("account", + "Invalid PurpleConnectionError value %d found when " + "loading account information for %s\n", + type, purple_account_get_username(account)); + type = PURPLE_CONNECTION_ERROR_OTHER_ERROR; + } + + child = xmlnode_get_child(node, "description"); + if (child) + description = xmlnode_get_data(child); + if (description == NULL) + description = g_strdup(""); + + current_error = g_new0(PurpleConnectionErrorInfo, 1); + PURPLE_DBUS_REGISTER_POINTER(current_error, PurpleConnectionErrorInfo); + current_error->type = type; + current_error->description = description; + + purple_account_set_current_error(account, current_error); +} + +static PurpleAccount * +parse_account(xmlnode *node) +{ + PurpleAccount *ret; + xmlnode *child; + char *protocol_id = NULL; + char *name = NULL; + char *data; + + child = xmlnode_get_child(node, "protocol"); + if (child != NULL) + protocol_id = xmlnode_get_data(child); + + child = xmlnode_get_child(node, "name"); + if (child != NULL) + name = xmlnode_get_data(child); + if (name == NULL) + { + /* Do we really need to do this? */ + child = xmlnode_get_child(node, "username"); + if (child != NULL) + name = xmlnode_get_data(child); + } + + if ((protocol_id == NULL) || (name == NULL)) + { + g_free(protocol_id); + g_free(name); + return NULL; + } + + ret = purple_account_new(name, protocol_id); + g_free(name); + g_free(protocol_id); + + /* Read the alias */ + child = xmlnode_get_child(node, "alias"); + if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) + { + if (*data != '\0') + purple_account_set_private_alias(ret, data); + g_free(data); + } + + /* Read the statuses */ + child = xmlnode_get_child(node, "statuses"); + if (child != NULL) + { + parse_statuses(child, ret); + } + + /* Read the userinfo */ + child = xmlnode_get_child(node, "userinfo"); + if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) + { + purple_account_set_user_info(ret, data); + g_free(data); + } + + /* Read an old buddyicon */ + child = xmlnode_get_child(node, "buddyicon"); + if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) + { + const char *dirname = purple_buddy_icons_get_cache_dir(); + char *filename = g_build_filename(dirname, data, NULL); + gchar *contents; + gsize len; + + if (g_file_get_contents(filename, &contents, &len, NULL)) + { + purple_buddy_icons_set_account_icon(ret, (guchar *)contents, len); + } + + g_free(filename); + g_free(data); + } + + /* Read settings (both core and UI) */ + for (child = xmlnode_get_child(node, "settings"); child != NULL; + child = xmlnode_get_next_twin(child)) + { + parse_settings(child, ret); + } + + /* Read proxy */ + child = xmlnode_get_child(node, "proxy"); + if (child != NULL) + { + parse_proxy_info(child, ret); + } + + /* Read current error */ + child = xmlnode_get_child(node, "current_error"); + if (child != NULL) + { + parse_current_error(child, ret); + } + + /* Read the password */ + child = xmlnode_get_child(node, "password"); + if (child != NULL) + { + const char *keyring_id = xmlnode_get_attrib(child, "keyring_id"); + const char *mode = xmlnode_get_attrib(child, "mode"); + gboolean result; + + data = xmlnode_get_data(child); + result = purple_keyring_import_password(ret, keyring_id, mode, data, NULL); + + if (result == TRUE || purple_keyring_get_inuse() == NULL) { + purple_account_set_remember_password(ret, TRUE); + } else { + purple_debug_error("account", "Failed to import password.\n"); + } + purple_str_wipe(data); + } + + return ret; +} + +static void +load_accounts(void) +{ + xmlnode *node, *child; + + accounts_loaded = TRUE; + + node = purple_util_read_xml_from_file("accounts.xml", _("accounts")); + + if (node == NULL) + return; + + for (child = xmlnode_get_child(node, "account"); child != NULL; + child = xmlnode_get_next_twin(child)) + { + PurpleAccount *new_acct; + new_acct = parse_account(child); + purple_accounts_add(new_acct); + } + + xmlnode_free(node); + + _purple_buddy_icons_account_loaded_cb(); +} + +void +purple_accounts_add(PurpleAccount *account) +{ + g_return_if_fail(account != NULL); + + if (g_list_find(accounts, account) != NULL) + return; + + accounts = g_list_append(accounts, account); + + purple_accounts_schedule_save(); + + purple_signal_emit(purple_accounts_get_handle(), "account-added", account); +} + +void +purple_accounts_remove(PurpleAccount *account) +{ + g_return_if_fail(account != NULL); + + accounts = g_list_remove(accounts, account); + + purple_accounts_schedule_save(); + + /* Clearing the error ensures that account-error-changed is emitted, + * which is the end of the guarantee that the the error's pointer is + * valid. + */ + purple_account_clear_current_error(account); + purple_signal_emit(purple_accounts_get_handle(), "account-removed", account); +} + +static void +purple_accounts_delete_set(PurpleAccount *account, GError *error, gpointer data) +{ + g_object_unref(G_OBJECT(account)); +} + +void +purple_accounts_delete(PurpleAccount *account) +{ + PurpleBlistNode *gnode, *cnode, *bnode; + GList *iter; + + g_return_if_fail(account != NULL); + + /* + * Disable the account before blowing it out of the water. + * Conceptually it probably makes more sense to disable the + * account for all UIs rather than the just the current UI, + * but it doesn't really matter. + */ + purple_account_set_enabled(account, purple_core_get_ui(), FALSE); + + purple_notify_close_with_handle(account); + purple_request_close_with_handle(account); + + purple_accounts_remove(account); + + /* Remove this account's buddies */ + for (gnode = purple_blist_get_root(); + gnode != NULL; + gnode = purple_blist_node_get_sibling_next(gnode)) + { + if (!PURPLE_BLIST_NODE_IS_GROUP(gnode)) + continue; + + cnode = purple_blist_node_get_first_child(gnode); + while (cnode) { + PurpleBlistNode *cnode_next = purple_blist_node_get_sibling_next(cnode); + + if(PURPLE_BLIST_NODE_IS_CONTACT(cnode)) { + bnode = purple_blist_node_get_first_child(cnode); + while (bnode) { + PurpleBlistNode *bnode_next = purple_blist_node_get_sibling_next(bnode); + + if (PURPLE_BLIST_NODE_IS_BUDDY(bnode)) { + PurpleBuddy *b = (PurpleBuddy *)bnode; + + if (purple_buddy_get_account(b) == account) + purple_blist_remove_buddy(b); + } + bnode = bnode_next; + } + } else if (PURPLE_BLIST_NODE_IS_CHAT(cnode)) { + PurpleChat *c = (PurpleChat *)cnode; + + if (purple_chat_get_account(c) == account) + purple_blist_remove_chat(c); + } + cnode = cnode_next; + } + } + + /* Remove any open conversation for this account */ + for (iter = purple_get_conversations(); iter; ) { + PurpleConversation *conv = iter->data; + iter = iter->next; + if (purple_conversation_get_account(conv) == account) + purple_conversation_destroy(conv); + } + + /* Remove this account's pounces */ + purple_pounce_destroy_all_by_account(account); + + /* This will cause the deletion of an old buddy icon. */ + purple_buddy_icons_set_account_icon(account, NULL, 0); + + /* This is async because we do not want the + * account being overwritten before we are done. + */ + purple_keyring_set_password(account, NULL, + purple_accounts_delete_set, NULL); +} + +void +purple_accounts_reorder(PurpleAccount *account, gint new_index) +{ + gint index; + GList *l; + + g_return_if_fail(account != NULL); + g_return_if_fail(new_index <= g_list_length(accounts)); + + index = g_list_index(accounts, account); + + if (index == -1) { + purple_debug_error("account", + "Unregistered account (%s) discovered during reorder!\n", + purple_account_get_username(account)); + return; + } + + l = g_list_nth(accounts, index); + + if (new_index > index) + new_index--; + + /* Remove the old one. */ + accounts = g_list_delete_link(accounts, l); + + /* Insert it where it should go. */ + accounts = g_list_insert(accounts, account, new_index); + + purple_accounts_schedule_save(); +} + +GList * +purple_accounts_get_all(void) +{ + return accounts; +} + +GList * +purple_accounts_get_all_active(void) +{ + GList *list = NULL; + GList *all = purple_accounts_get_all(); + + while (all != NULL) { + PurpleAccount *account = all->data; + + if (purple_account_get_enabled(account, purple_core_get_ui())) + list = g_list_append(list, account); + + all = all->next; + } + + return list; +} + +PurpleAccount * +purple_accounts_find(const char *name, const char *protocol_id) +{ + PurpleAccount *account = NULL; + GList *l; + char *who; + + g_return_val_if_fail(name != NULL, NULL); + g_return_val_if_fail(protocol_id != NULL, NULL); + + for (l = purple_accounts_get_all(); l != NULL; l = l->next) { + account = (PurpleAccount *)l->data; + + if (!purple_strequal(purple_account_get_protocol_id(account), protocol_id)) + continue; + + who = g_strdup(purple_normalize(account, name)); + if (purple_strequal(purple_normalize(account, purple_account_get_username(account)), who)) { + g_free(who); + return account; + } + g_free(who); + } + + return NULL; +} + +void +purple_accounts_restore_current_statuses() +{ + GList *l; + PurpleAccount *account; + + /* If we're not connected to the Internet right now, we bail on this */ + if (!purple_network_is_available()) + { + purple_debug_warning("account", "Network not connected; skipping reconnect\n"); + return; + } + + for (l = purple_accounts_get_all(); l != NULL; l = l->next) + { + account = (PurpleAccount *)l->data; + + if (purple_account_get_enabled(account, purple_core_get_ui()) && + (purple_presence_is_online(purple_account_get_presence(account)))) + { + purple_account_connect(account); + } + } +} + +void +purple_accounts_set_ui_ops(PurpleAccountUiOps *ops) +{ + account_ui_ops = ops; +} + +PurpleAccountUiOps * +purple_accounts_get_ui_ops(void) +{ + return account_ui_ops; +} + +void * +purple_accounts_get_handle(void) +{ + static int handle; + + return &handle; +} + +static void +signed_on_cb(PurpleConnection *gc, + gpointer unused) +{ + PurpleAccount *account = purple_connection_get_account(gc); + purple_account_clear_current_error(account); + + purple_signal_emit(purple_accounts_get_handle(), "account-signed-on", + account); +} + +static void +signed_off_cb(PurpleConnection *gc, + gpointer unused) +{ + PurpleAccount *account = purple_connection_get_account(gc); + + purple_signal_emit(purple_accounts_get_handle(), "account-signed-off", + account); +} + +static void +connection_error_cb(PurpleConnection *gc, + PurpleConnectionError type, + const gchar *description, + gpointer unused) +{ + PurpleAccount *account; + PurpleConnectionErrorInfo *err; + + account = purple_connection_get_account(gc); + + g_return_if_fail(account != NULL); + + err = g_new0(PurpleConnectionErrorInfo, 1); + PURPLE_DBUS_REGISTER_POINTER(err, PurpleConnectionErrorInfo); + + err->type = type; + err->description = g_strdup(description); + + purple_account_set_current_error(account, err); + + purple_signal_emit(purple_accounts_get_handle(), "account-connection-error", + account, type, description); +} + +static void +password_migration_cb(PurpleAccount *account) +{ + /* account may be NULL (means: all) */ + + purple_accounts_schedule_save(); +} + +void +purple_accounts_init(void) +{ + void *handle = purple_accounts_get_handle(); + void *conn_handle = purple_connections_get_handle(); + + purple_signal_register(handle, "account-connecting", + purple_marshal_VOID__POINTER, NULL, 1, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT)); + + purple_signal_register(handle, "account-disabled", + purple_marshal_VOID__POINTER, NULL, 1, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT)); + + purple_signal_register(handle, "account-enabled", + purple_marshal_VOID__POINTER, NULL, 1, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT)); + + purple_signal_register(handle, "account-setting-info", + purple_marshal_VOID__POINTER_POINTER, NULL, 2, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_STRING)); + + purple_signal_register(handle, "account-set-info", + purple_marshal_VOID__POINTER_POINTER, NULL, 2, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_STRING)); + + purple_signal_register(handle, "account-created", + purple_marshal_VOID__POINTER, NULL, 1, + purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_ACCOUNT)); + + purple_signal_register(handle, "account-destroying", + purple_marshal_VOID__POINTER, NULL, 1, + purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_ACCOUNT)); + + purple_signal_register(handle, "account-added", + purple_marshal_VOID__POINTER, NULL, 1, + purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_ACCOUNT)); + + purple_signal_register(handle, "account-removed", + purple_marshal_VOID__POINTER, NULL, 1, + purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_ACCOUNT)); + + purple_signal_register(handle, "account-status-changed", + purple_marshal_VOID__POINTER_POINTER_POINTER, NULL, 3, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_STATUS), + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_STATUS)); + + purple_signal_register(handle, "account-actions-changed", + purple_marshal_VOID__POINTER, NULL, 1, + purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_ACCOUNT)); + + purple_signal_register(handle, "account-alias-changed", + purple_marshal_VOID__POINTER_POINTER, NULL, 2, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_STRING)); + + purple_signal_register(handle, "account-authorization-requested", + purple_marshal_INT__POINTER_POINTER_POINTER, + purple_value_new(PURPLE_TYPE_INT), 4, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_STRING)); + + purple_signal_register(handle, "account-authorization-denied", + purple_marshal_VOID__POINTER_POINTER, NULL, 3, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_STRING)); + + purple_signal_register(handle, "account-authorization-granted", + purple_marshal_VOID__POINTER_POINTER, NULL, 3, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_STRING)); + + purple_signal_register(handle, "account-error-changed", + purple_marshal_VOID__POINTER_POINTER_POINTER, + NULL, 3, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_POINTER), + purple_value_new(PURPLE_TYPE_POINTER)); + + purple_signal_register(handle, "account-signed-on", + purple_marshal_VOID__POINTER, NULL, 1, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT)); + + purple_signal_register(handle, "account-signed-off", + purple_marshal_VOID__POINTER, NULL, 1, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT)); + + purple_signal_register(handle, "account-connection-error", + purple_marshal_VOID__POINTER_INT_POINTER, NULL, 3, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_ENUM), + purple_value_new(PURPLE_TYPE_STRING)); + + purple_signal_connect(conn_handle, "signed-on", handle, + PURPLE_CALLBACK(signed_on_cb), NULL); + purple_signal_connect(conn_handle, "signed-off", handle, + PURPLE_CALLBACK(signed_off_cb), NULL); + purple_signal_connect(conn_handle, "connection-error", handle, + PURPLE_CALLBACK(connection_error_cb), NULL); + purple_signal_connect(purple_keyring_get_handle(), "password-migration", handle, + PURPLE_CALLBACK(password_migration_cb), NULL); + + load_accounts(); + +} + +void +purple_accounts_uninit(void) +{ + gpointer handle = purple_accounts_get_handle(); + if (save_timer != 0) + { + purple_timeout_remove(save_timer); + save_timer = 0; + sync_accounts(); + } + + for (; accounts; accounts = g_list_delete_link(accounts, accounts)) + g_object_unref(G_OBJECT(accounts->data)); + + purple_signals_disconnect_by_handle(handle); + purple_signals_unregister_by_instance(handle); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/accounts.h Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,224 @@ +/** + * @file accounts.h Accounts API + * @ingroup core + */ + +/* 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 + */ +#ifndef _PURPLE_ACCOUNTS_H_ +#define _PURPLE_ACCOUNTS_H_ + +#include "account.h" +#include "status.h" + +/** @copydoc _PurpleAccountUiOps */ +typedef struct _PurpleAccountUiOps PurpleAccountUiOps; + +/** Account UI operations, used to notify the user of status changes and when + * buddies add this account to their buddy lists. + */ +struct _PurpleAccountUiOps +{ + /** A buddy who is already on this account's buddy list added this account + * to their buddy list. + */ + void (*notify_added)(PurpleAccount *account, + const char *remote_user, + const char *id, + const char *alias, + const char *message); + + /** This account's status changed. */ + void (*status_changed)(PurpleAccount *account, + PurpleStatus *status); + + /** Someone we don't have on our list added us; prompt to add them. */ + void (*request_add)(PurpleAccount *account, + const char *remote_user, + const char *id, + const char *alias, + const char *message); + + /** Prompt for authorization when someone adds this account to their buddy + * list. To authorize them to see this account's presence, call \a + * authorize_cb (\a message, \a user_data); otherwise call + * \a deny_cb (\a message, \a user_data); + * @return a UI-specific handle, as passed to #close_account_request. + */ + void *(*request_authorize)(PurpleAccount *account, + const char *remote_user, + const char *id, + const char *alias, + const char *message, + gboolean on_list, + PurpleAccountRequestAuthorizationCb authorize_cb, + PurpleAccountRequestAuthorizationCb deny_cb, + void *user_data); + + /** Close a pending request for authorization. \a ui_handle is a handle + * as returned by #request_authorize. + */ + void (*close_account_request)(void *ui_handle); + + void (*permit_added)(PurpleAccount *account, const char *name); + void (*permit_removed)(PurpleAccount *account, const char *name); + void (*deny_added)(PurpleAccount *account, const char *name); + void (*deny_removed)(PurpleAccount *account, const char *name); + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +/**************************************************************************/ +/** @name Accounts API */ +/**************************************************************************/ +/*@{*/ + +/** + * Adds an account to the list of accounts. + * + * @param account The account. + */ +void purple_accounts_add(PurpleAccount *account); + +/** + * Removes an account from the list of accounts. + * + * @param account The account. + */ +void purple_accounts_remove(PurpleAccount *account); + +/** + * Deletes an account. + * + * This will remove any buddies from the buddy list that belong to this + * account, buddy pounces that belong to this account, and will also + * destroy @a account. + * + * @param account The account. + */ +void purple_accounts_delete(PurpleAccount *account); + +/** + * Reorders an account. + * + * @param account The account to reorder. + * @param new_index The new index for the account. + */ +void purple_accounts_reorder(PurpleAccount *account, gint new_index); + +/** + * Returns a list of all accounts. + * + * @constreturn A list of all accounts. + */ +GList *purple_accounts_get_all(void); + +/** + * Returns a list of all enabled accounts + * + * @return A list of all enabled accounts. The list is owned + * by the caller, and must be g_list_free()d to avoid + * leaking the nodes. + */ +GList *purple_accounts_get_all_active(void); + +/** + * Finds an account with the specified name and protocol id. + * + * @param name The account username. + * @param protocol The account protocol ID. + * + * @return The account, if found, or @c FALSE otherwise. + */ +PurpleAccount *purple_accounts_find(const char *name, const char *protocol); + +/** + * This is called by the core after all subsystems and what + * not have been initialized. It sets all enabled accounts + * to their startup status by signing them on, setting them + * away, etc. + * + * You probably shouldn't call this unless you really know + * what you're doing. + */ +void purple_accounts_restore_current_statuses(void); + +/*@}*/ + + +/**************************************************************************/ +/** @name UI Registration Functions */ +/**************************************************************************/ +/*@{*/ +/** + * Sets the UI operations structure to be used for accounts. + * + * @param ops The UI operations structure. + */ +void purple_accounts_set_ui_ops(PurpleAccountUiOps *ops); + +/** + * Returns the UI operations structure used for accounts. + * + * @return The UI operations structure in use. + */ +PurpleAccountUiOps *purple_accounts_get_ui_ops(void); + +/*@}*/ + + +/**************************************************************************/ +/** @name Accounts Subsystem */ +/**************************************************************************/ +/*@{*/ + +/** + * Returns the accounts subsystem handle. + * + * @return The accounts subsystem handle. + */ +void *purple_accounts_get_handle(void); + +/** + * Initializes the accounts subsystem. + */ +void purple_accounts_init(void); + +/** + * Uninitializes the accounts subsystem. + */ +void purple_accounts_uninit(void); + +/** + * Schedules saving of accounts + */ +void purple_accounts_schedule_save(void); + +/*@}*/ + +G_END_DECLS + +#endif /* _PURPLE_ACCOUNTS_H_ */
--- a/libpurple/blist.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/blist.c Sun Jun 23 13:35:53 2013 +0530 @@ -30,7 +30,6 @@ #include "notify.h" #include "pounce.h" #include "prefs.h" -#include "privacy.h" #include "prpl.h" #include "server.h" #include "signals.h" @@ -317,13 +316,13 @@ g_snprintf(buf, sizeof(buf), "%d", purple_account_get_privacy_type(account)); xmlnode_set_attrib(node, "mode", buf); - for (cur = account->permit; cur; cur = cur->next) + for (cur = purple_account_privacy_get_permitted(account); cur; cur = cur->next) { child = xmlnode_new_child(node, "permit"); xmlnode_insert_data(child, cur->data, -1); } - for (cur = account->deny; cur; cur = cur->next) + for (cur = purple_account_privacy_get_denied(account); cur; cur = cur->next) { child = xmlnode_new_child(node, "block"); xmlnode_insert_data(child, cur->data, -1); @@ -640,7 +639,7 @@ continue; imode = atoi(mode); - purple_account_set_privacy_type(account, (imode != 0 ? imode : PURPLE_PRIVACY_ALLOW_ALL)); + purple_account_set_privacy_type(account, (imode != 0 ? imode : PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL)); for (x = anode->child; x; x = x->next) { char *name; @@ -649,11 +648,11 @@ if (purple_strequal(x->name, "permit")) { name = xmlnode_get_data(x); - purple_privacy_permit_add(account, name, TRUE); + purple_account_privacy_permit_add(account, name, TRUE); g_free(name); } else if (purple_strequal(x->name, "block")) { name = xmlnode_get_data(x); - purple_privacy_deny_add(account, name, TRUE); + purple_account_privacy_deny_add(account, name, TRUE); g_free(name); } }
--- a/libpurple/cipher.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/cipher.c Sun Jun 23 13:35:53 2013 +0530 @@ -1,24 +1,9 @@ -/* - * purple +/* 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. * - * Original des taken from gpg - * - * des.c - DES and Triple-DES encryption/decryption Algorithm - * Copyright (C) 1998 Free Software Foundation, Inc. - * - * Please see below for more legal information! - * - * According to the definition of DES in FIPS PUB 46-2 from December 1993. - * For a description of triple encryption, see: - * Bruce Schneier: Applied Cryptography. Second Edition. - * John Wiley & Sons, 1996. ISBN 0-471-12845-7. Pages 358 ff. - * - * This file is part of GnuPG. - * * 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 @@ -35,435 +20,230 @@ */ #include "internal.h" #include "cipher.h" -#include "ciphers/ciphers.h" -#include "dbus-maybe.h" #include "debug.h" -#include "signals.h" -#include "value.h" - -/******************************************************************************* - * Structs - ******************************************************************************/ -struct _PurpleCipher { - gchar *name; /**< Internal name - used for searching */ - PurpleCipherOps *ops; /**< Operations supported by this cipher */ - guint ref; /**< Reference count */ -}; - -struct _PurpleCipherContext { - PurpleCipher *cipher; /**< Cipher this context is under */ - gpointer data; /**< Internal cipher state data */ -}; /****************************************************************************** - * Globals + * Object Stuff *****************************************************************************/ -static GList *ciphers = NULL; +static void +purple_cipher_class_init(PurpleCipherClass *klass) { + klass->reset = NULL; + klass->reset_state = NULL; + klass->set_iv = NULL; + klass->append = NULL; + klass->digest = NULL; + klass->get_digest_size = NULL; + klass->encrypt = NULL; + klass->decrypt = NULL; + klass->set_salt = NULL; + klass->set_key = NULL; + klass->get_key_size = NULL; + klass->set_batch_mode = NULL; + klass->get_batch_mode = NULL; + klass->get_block_size = NULL; + klass->get_name = NULL; +} /****************************************************************************** * PurpleCipher API *****************************************************************************/ const gchar * purple_cipher_get_name(PurpleCipher *cipher) { + PurpleCipherClass *klass = NULL; + g_return_val_if_fail(cipher, NULL); + g_return_val_if_fail(PURPLE_IS_CIPHER(cipher), NULL); - return cipher->name; + klass = PURPLE_CIPHER_GET_CLASS(cipher); + g_return_val_if_fail(klass->get_name, NULL); + + return klass->get_name(cipher); } -guint -purple_cipher_get_capabilities(PurpleCipher *cipher) { - PurpleCipherOps *ops = NULL; - guint caps = 0; - - g_return_val_if_fail(cipher, 0); - - ops = cipher->ops; - g_return_val_if_fail(ops, 0); +GType +purple_cipher_get_type(void) { + static GType type = 0; - if(ops->set_option) - caps |= PURPLE_CIPHER_CAPS_SET_OPT; - if(ops->get_option) - caps |= PURPLE_CIPHER_CAPS_GET_OPT; - if(ops->init) - caps |= PURPLE_CIPHER_CAPS_INIT; - if(ops->reset) - caps |= PURPLE_CIPHER_CAPS_RESET; - if(ops->reset_state) - caps |= PURPLE_CIPHER_CAPS_RESET_STATE; - if(ops->uninit) - caps |= PURPLE_CIPHER_CAPS_UNINIT; - if(ops->set_iv) - caps |= PURPLE_CIPHER_CAPS_SET_IV; - if(ops->append) - caps |= PURPLE_CIPHER_CAPS_APPEND; - if(ops->digest) - caps |= PURPLE_CIPHER_CAPS_DIGEST; - if(ops->get_digest_size) - caps |= PURPLE_CIPHER_CAPS_GET_DIGEST_SIZE; - if(ops->encrypt) - caps |= PURPLE_CIPHER_CAPS_ENCRYPT; - if(ops->decrypt) - caps |= PURPLE_CIPHER_CAPS_DECRYPT; - if(ops->set_salt) - caps |= PURPLE_CIPHER_CAPS_SET_SALT; - if(ops->get_salt_size) - caps |= PURPLE_CIPHER_CAPS_GET_SALT_SIZE; - if(ops->set_key) - caps |= PURPLE_CIPHER_CAPS_SET_KEY; - if (ops->get_key_size) - caps |= PURPLE_CIPHER_CAPS_GET_KEY_SIZE; - if(ops->set_batch_mode) - caps |= PURPLE_CIPHER_CAPS_SET_BATCH_MODE; - if(ops->get_batch_mode) - caps |= PURPLE_CIPHER_CAPS_GET_BATCH_MODE; - if(ops->get_block_size) - caps |= PURPLE_CIPHER_CAPS_GET_BLOCK_SIZE; + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleCipherClass), + NULL, + NULL, + (GClassInitFunc)purple_cipher_class_init, + NULL, + NULL, + sizeof(PurpleCipher), + 0, + NULL, + NULL + }; - return caps; -} - -ssize_t -purple_cipher_digest_region(const gchar *name, const guchar *data, - size_t data_len, guchar digest[], size_t out_size) -{ - PurpleCipher *cipher; - PurpleCipherContext *context; - ssize_t digest_size; - gboolean succ; - - g_return_val_if_fail(name, -1); - g_return_val_if_fail(data, -1); - - cipher = purple_ciphers_find_cipher(name); - - g_return_val_if_fail(cipher, -1); - - if(!cipher->ops->append || !cipher->ops->digest || !cipher->ops->get_digest_size) { - purple_debug_warning("cipher", "purple_cipher_region failed: " - "the %s cipher does not support appending and or " - "digesting.", cipher->name); - return -1; + type = g_type_register_static(G_TYPE_OBJECT, + "PurpleCipher", + &info, G_TYPE_FLAG_ABSTRACT); } - context = purple_cipher_context_new(cipher, NULL); - digest_size = purple_cipher_context_get_digest_size(context); - if (out_size < digest_size) { - purple_debug_error("cipher", "purple_cipher_region failed: " - "provided output buffer too small\n"); - purple_cipher_context_destroy(context); - return -1; - } - purple_cipher_context_append(context, data, data_len); - succ = purple_cipher_context_digest(context, digest, out_size); - purple_cipher_context_destroy(context); - - return succ ? digest_size : -1; -} - -/****************************************************************************** - * PurpleCiphers API - *****************************************************************************/ -PurpleCipher * -purple_ciphers_find_cipher(const gchar *name) { - PurpleCipher *cipher; - GList *l; - - g_return_val_if_fail(name, NULL); - - for(l = ciphers; l; l = l->next) { - cipher = PURPLE_CIPHER(l->data); - - if(!g_ascii_strcasecmp(cipher->name, name)) - return cipher; - } - - return NULL; + return type; } -PurpleCipher * -purple_ciphers_register_cipher(const gchar *name, PurpleCipherOps *ops) { - PurpleCipher *cipher = NULL; - - g_return_val_if_fail(name, NULL); - g_return_val_if_fail(ops, NULL); - g_return_val_if_fail(!purple_ciphers_find_cipher(name), NULL); +/** + * purple_cipher_reset: + * @cipher: The cipher to reset + * + * Resets a cipher to it's default value + * + * @note If you have set an IV you will have to set it after resetting + */ +void +purple_cipher_reset(PurpleCipher *cipher) { + PurpleCipherClass *klass = NULL; - cipher = g_new0(PurpleCipher, 1); - PURPLE_DBUS_REGISTER_POINTER(cipher, PurpleCipher); + g_return_if_fail(PURPLE_IS_CIPHER(cipher)); - cipher->name = g_strdup(name); - cipher->ops = ops; + klass = PURPLE_CIPHER_GET_CLASS(cipher); - ciphers = g_list_append(ciphers, cipher); - - purple_signal_emit(purple_ciphers_get_handle(), "cipher-added", cipher); - - return cipher; + if(klass && klass->reset) + klass->reset(cipher); + else + purple_debug_warning("cipher", "the %s cipher does not implement the " + "reset method\n", + klass->get_name ? klass->get_name(cipher) : ""); } -gboolean -purple_ciphers_unregister_cipher(PurpleCipher *cipher) { - g_return_val_if_fail(cipher, FALSE); - g_return_val_if_fail(cipher->ref == 0, FALSE); - - purple_signal_emit(purple_ciphers_get_handle(), "cipher-removed", cipher); - - ciphers = g_list_remove(ciphers, cipher); - - g_free(cipher->name); - - PURPLE_DBUS_UNREGISTER_POINTER(cipher); - g_free(cipher); - - return TRUE; -} - -GList * -purple_ciphers_get_ciphers() { - return ciphers; -} +/** + * Resets a cipher state to it's default value, but doesn't touch stateless + * configuration. + * + * That means, IV and digest context will be wiped out, but keys, ops or salt + * will remain untouched. + */ +void +purple_cipher_reset_state(PurpleCipher *cipher) { + PurpleCipherClass *klass = NULL; -/****************************************************************************** - * PurpleCipher Subsystem API - *****************************************************************************/ -gpointer -purple_ciphers_get_handle() { - static gint handle; + g_return_if_fail(PURPLE_IS_CIPHER(cipher)); - return &handle; -} + klass = PURPLE_CIPHER_GET_CLASS(cipher); -void -purple_ciphers_init() { - gpointer handle; - - handle = purple_ciphers_get_handle(); - - purple_signal_register(handle, "cipher-added", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CIPHER)); - purple_signal_register(handle, "cipher-removed", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CIPHER)); - - purple_ciphers_register_all(); + if(klass && klass->reset_state) + klass->reset_state(cipher); + else + purple_debug_warning("cipher", "the %s cipher does not implement the " + "reset_state method\n", + klass->get_name ? klass->get_name(cipher) : ""); } -void -purple_ciphers_uninit() { - PurpleCipher *cipher; - GList *l, *ll; - - for(l = ciphers; l; l = ll) { - ll = l->next; - - cipher = PURPLE_CIPHER(l->data); - purple_ciphers_unregister_cipher(cipher); - } - - g_list_free(ciphers); - - purple_signals_unregister_by_instance(purple_ciphers_get_handle()); -} - -/****************************************************************************** - * PurpleCipherContext API - *****************************************************************************/ +/** + * purple_cipher_set_iv: + * @cipher: The cipher to set the IV to + * @iv: The initialization vector to set + * @len: The len of the IV + * + * @note This should only be called right after a cipher is created or reset + * + * Sets the initialization vector for a cipher + */ void -purple_cipher_context_set_option(PurpleCipherContext *context, const gchar *name, - gpointer value) +purple_cipher_set_iv(PurpleCipher *cipher, guchar *iv, size_t len) { - PurpleCipher *cipher = NULL; - - g_return_if_fail(context); - g_return_if_fail(name); - - cipher = context->cipher; - g_return_if_fail(cipher); - - if(cipher->ops && cipher->ops->set_option) - cipher->ops->set_option(context, name, value); - else - purple_debug_warning("cipher", "the %s cipher does not support the " - "set_option operation\n", cipher->name); -} - -gpointer -purple_cipher_context_get_option(PurpleCipherContext *context, const gchar *name) { - PurpleCipher *cipher = NULL; + PurpleCipherClass *klass = NULL; - g_return_val_if_fail(context, NULL); - g_return_val_if_fail(name, NULL); - - cipher = context->cipher; - g_return_val_if_fail(cipher, NULL); + g_return_if_fail(PURPLE_IS_CIPHER(cipher)); + g_return_if_fail(iv); - if(cipher->ops && cipher->ops->get_option) - return cipher->ops->get_option(context, name); - else { - purple_debug_warning("cipher", "the %s cipher does not support the " - "get_option operation\n", cipher->name); - - return NULL; - } -} - -PurpleCipherContext * -purple_cipher_context_new(PurpleCipher *cipher, void *extra) { - PurpleCipherContext *context = NULL; - - g_return_val_if_fail(cipher, NULL); + klass = PURPLE_CIPHER_GET_CLASS(cipher); - cipher->ref++; - - context = g_new0(PurpleCipherContext, 1); - context->cipher = cipher; - - if(cipher->ops->init) - cipher->ops->init(context, extra); - - return context; -} - -PurpleCipherContext * -purple_cipher_context_new_by_name(const gchar *name, void *extra) { - PurpleCipher *cipher; - - g_return_val_if_fail(name, NULL); - - cipher = purple_ciphers_find_cipher(name); - - g_return_val_if_fail(cipher, NULL); - - return purple_cipher_context_new(cipher, extra); + if(klass && klass->set_iv) + klass->set_iv(cipher, iv, len); + else + purple_debug_warning("cipher", "the %s cipher does not implement the " + "set_iv method\n", + klass->get_name ? klass->get_name(cipher) : ""); } +/** + * purple_cipher_append: + * @cipher: The cipher to append data to + * @data: The data to append + * @len: The length of the data + * + * Appends data to the cipher + */ void -purple_cipher_context_reset(PurpleCipherContext *context, void *extra) { - PurpleCipher *cipher = NULL; - - g_return_if_fail(context); - - cipher = context->cipher; - g_return_if_fail(cipher); - - if(cipher->ops && cipher->ops->reset) - context->cipher->ops->reset(context, extra); -} - -void -purple_cipher_context_reset_state(PurpleCipherContext *context, void *extra) { - PurpleCipher *cipher = NULL; - - g_return_if_fail(context); - - cipher = context->cipher; - g_return_if_fail(cipher); - g_return_if_fail(cipher->ops); +purple_cipher_append(PurpleCipher *cipher, const guchar *data, + size_t len) +{ + PurpleCipherClass *klass = NULL; - if (cipher->ops->reset_state) { - context->cipher->ops->reset_state(context, extra); - return; - } + g_return_if_fail(PURPLE_IS_CIPHER(cipher)); - purple_debug_warning("cipher", "the %s cipher does not support the " - "reset_state operation\n", cipher->name); - purple_cipher_context_reset(context, extra); -} - -void -purple_cipher_context_destroy(PurpleCipherContext *context) { - PurpleCipher *cipher = NULL; + klass = PURPLE_CIPHER_GET_CLASS(cipher); - g_return_if_fail(context); - - cipher = context->cipher; - g_return_if_fail(cipher); - - cipher->ref--; - - if(cipher->ops && cipher->ops->uninit) - cipher->ops->uninit(context); - - memset(context, 0, sizeof(*context)); - g_free(context); - context = NULL; + if(klass && klass->append) + klass->append(cipher, data, len); + else + purple_debug_warning("cipher", "the %s cipher does not implement the " + "append method\n", + klass->get_name ? klass->get_name(cipher) : ""); } -void -purple_cipher_context_set_iv(PurpleCipherContext *context, guchar *iv, size_t len) +/** + * purple_cipher_digest: + * @cipher: The cipher to digest + * @in_len: The length of the buffer + * @digest: The return buffer for the digest + * @out_len: The length of the returned value + * + * Digests a cipher + * + * Return Value: TRUE if the digest was successful, FALSE otherwise. + */ +gboolean +purple_cipher_digest(PurpleCipher *cipher, guchar digest[], size_t len) { - PurpleCipher *cipher = NULL; - - g_return_if_fail(context); - g_return_if_fail(iv); + PurpleCipherClass *klass = NULL; - cipher = context->cipher; - g_return_if_fail(cipher); + g_return_val_if_fail(PURPLE_IS_CIPHER(cipher), FALSE); + + klass = PURPLE_CIPHER_GET_CLASS(cipher); - if(cipher->ops && cipher->ops->set_iv) - cipher->ops->set_iv(context, iv, len); + if(klass && klass->digest) + return klass->digest(cipher, digest, len); else - purple_debug_warning("cipher", "the %s cipher does not support the set" - "initialization vector operation\n", cipher->name); + purple_debug_warning("cipher", "the %s cipher does not implement the " + "digest method\n", + klass->get_name ? klass->get_name(cipher) : ""); + + return FALSE; } -void -purple_cipher_context_append(PurpleCipherContext *context, const guchar *data, - size_t len) -{ - PurpleCipher *cipher = NULL; - - g_return_if_fail(context); - - cipher = context->cipher; - g_return_if_fail(cipher); - - if(cipher->ops && cipher->ops->append) - cipher->ops->append(context, data, len); - else - purple_debug_warning("cipher", "the %s cipher does not support the append " - "operation\n", cipher->name); -} - +/** + * purple_cipher_digest_to_str: + * @cipher: The cipher to get a digest from + * @in_len: The length of the buffer + * @digest_s: The return buffer for the string digest + * @out_len: The length of the returned value + * + * Converts a guchar digest into a hex string + * + * Return Value: TRUE if the digest was successful, FALSE otherwise. + */ gboolean -purple_cipher_context_digest(PurpleCipherContext *context, guchar digest[], - size_t len) -{ - PurpleCipher *cipher = NULL; - - g_return_val_if_fail(context, FALSE); - - cipher = context->cipher; - - if(cipher->ops && cipher->ops->digest) - return cipher->ops->digest(context, digest, len); - else { - purple_debug_warning("cipher", "the %s cipher does not support the digest " - "operation\n", cipher->name); - return FALSE; - } -} - -gboolean -purple_cipher_context_digest_to_str(PurpleCipherContext *context, - gchar digest_s[], size_t len) +purple_cipher_digest_to_str(PurpleCipher *cipher, gchar digest_s[], size_t len) { /* 8k is a bit excessive, will tweak later. */ guchar digest[BUF_LEN * 4]; gint n = 0; size_t digest_size; - g_return_val_if_fail(context, FALSE); + g_return_val_if_fail(cipher, FALSE); g_return_val_if_fail(digest_s, FALSE); - digest_size = purple_cipher_context_get_digest_size(context); + digest_size = purple_cipher_get_digest_size(cipher); g_return_val_if_fail(digest_size <= BUF_LEN * 4, FALSE); - if(!purple_cipher_context_digest(context, digest, sizeof(digest))) + if(!purple_cipher_digest(cipher, digest, sizeof(digest))) return FALSE; /* Every digest byte occupies 2 chars + the NUL at the end. */ @@ -478,373 +258,240 @@ } size_t -purple_cipher_context_get_digest_size(PurpleCipherContext *context) +purple_cipher_get_digest_size(PurpleCipher *cipher) { - PurpleCipher *cipher = NULL; + PurpleCipherClass *klass = NULL; - g_return_val_if_fail(context, 0); + g_return_val_if_fail(PURPLE_IS_CIPHER(cipher), FALSE); + + klass = PURPLE_CIPHER_GET_CLASS(cipher); - cipher = context->cipher; - g_return_val_if_fail(cipher, 0); + if(klass && klass->get_digest_size) + return klass->get_digest_size(cipher); + else + purple_debug_warning("cipher", "the %s cipher does not implement the " + "get_digest_size method\n", + klass->get_name ? klass->get_name(cipher) : ""); - if(cipher->ops && cipher->ops->get_digest_size) - return cipher->ops->get_digest_size(context); - else { - purple_debug_warning("cipher", "The %s cipher does not support " - "the get_digest_size operation\n", cipher->name); - return 0; - } + return FALSE; } +/** + * purple_cipher_encrypt: + * @cipher: The cipher + * @data: The data to encrypt + * @len: The length of the data + * @output: The output buffer + * @outlen: The len of data that was outputed + * + * Encrypts data using the cipher + * + * Return Value: A cipher specific status code + */ ssize_t -purple_cipher_context_encrypt(PurpleCipherContext *context, - const guchar input[], size_t in_len, guchar output[], size_t out_size) +purple_cipher_encrypt(PurpleCipher *cipher, const guchar input[], + size_t in_len, guchar output[], size_t out_size) { - PurpleCipher *cipher = NULL; + PurpleCipherClass *klass = NULL; - g_return_val_if_fail(context != NULL, -1); + g_return_val_if_fail(PURPLE_IS_CIPHER(cipher), -1); g_return_val_if_fail(input != NULL, -1); g_return_val_if_fail(output != NULL, -1); g_return_val_if_fail(out_size >= in_len, -1); - cipher = context->cipher; - g_return_val_if_fail(cipher, -1); + klass = PURPLE_CIPHER_GET_CLASS(cipher); - if(cipher->ops && cipher->ops->encrypt) - return cipher->ops->encrypt(context, input, in_len, output, out_size); - else { - purple_debug_warning("cipher", "the %s cipher does not support the encrypt" - "operation\n", cipher->name); + if(klass && klass->encrypt) + return klass->encrypt(cipher, input, in_len, output, out_size); + else + purple_debug_warning("cipher", "the %s cipher does not implement the " + "encrypt method\n", + klass->get_name ? klass->get_name(cipher) : ""); - return -1; - } + return -1; } +/** + * purple_cipher_decrypt: + * @cipher: The cipher + * @data: The data to encrypt + * @len: The length of the returned value + * @output: The output buffer + * @outlen: The len of data that was outputed + * + * Decrypts data using the cipher + * + * Return Value: A cipher specific status code + */ ssize_t -purple_cipher_context_decrypt(PurpleCipherContext *context, - const guchar input[], size_t in_len, guchar output[], size_t out_size) +purple_cipher_decrypt(PurpleCipher *cipher, const guchar input[], + size_t in_len, guchar output[], size_t out_size) { - PurpleCipher *cipher = NULL; + PurpleCipherClass *klass = NULL; - g_return_val_if_fail(context != NULL, -1); + g_return_val_if_fail(PURPLE_IS_CIPHER(cipher), -1); g_return_val_if_fail(input != NULL, -1); g_return_val_if_fail(output != NULL, -1); - cipher = context->cipher; - g_return_val_if_fail(cipher, -1); - - if(cipher->ops && cipher->ops->decrypt) - return cipher->ops->decrypt(context, input, in_len, output, out_size); - else { - purple_debug_warning("cipher", "the %s cipher does not support the decrypt" - "operation\n", cipher->name); - - return -1; - } -} - -void -purple_cipher_context_set_salt(PurpleCipherContext *context, const guchar *salt, size_t len) { - PurpleCipher *cipher = NULL; - - g_return_if_fail(context); - - cipher = context->cipher; - g_return_if_fail(cipher); - - if(cipher->ops && cipher->ops->set_salt) - cipher->ops->set_salt(context, salt, len); - else - purple_debug_warning("cipher", "the %s cipher does not support the " - "set_salt operation\n", cipher->name); -} + klass = PURPLE_CIPHER_GET_CLASS(cipher); -size_t -purple_cipher_context_get_salt_size(PurpleCipherContext *context) { - PurpleCipher *cipher = NULL; - - g_return_val_if_fail(context, -1); - - cipher = context->cipher; - g_return_val_if_fail(cipher, -1); - - if(cipher->ops && cipher->ops->get_salt_size) - return cipher->ops->get_salt_size(context); - else { - purple_debug_warning("cipher", "the %s cipher does not support the " - "get_salt_size operation\n", cipher->name); + if(klass && klass->decrypt) + return klass->decrypt(cipher, input, in_len, output, out_size); + else + purple_debug_warning("cipher", "the %s cipher does not implement the " + "decrypt method\n", + klass->get_name ? klass->get_name(cipher) : ""); - return -1; - } -} - -void -purple_cipher_context_set_key(PurpleCipherContext *context, const guchar *key, size_t len) { - PurpleCipher *cipher = NULL; - - g_return_if_fail(context); - - cipher = context->cipher; - g_return_if_fail(cipher); - - if(cipher->ops && cipher->ops->set_key) - cipher->ops->set_key(context, key, len); - else - purple_debug_warning("cipher", "the %s cipher does not support the " - "set_key operation\n", cipher->name); + return -1; } -size_t -purple_cipher_context_get_key_size(PurpleCipherContext *context) { - PurpleCipher *cipher = NULL; - - g_return_val_if_fail(context, 0); - - cipher = context->cipher; - g_return_val_if_fail(cipher, 0); - - if (cipher->ops && cipher->ops->get_key_size) - return cipher->ops->get_key_size(context); - else { - purple_debug_warning("cipher", "the %s cipher does not support " - "the get_key_size operation\n", cipher->name); +/** + * purple_cipher_set_salt: + * @cipher: The cipher whose salt to set + * @salt: The salt + * + * Sets the salt on a cipher + */ +void +purple_cipher_set_salt(PurpleCipher *cipher, const guchar *salt, size_t len) { + PurpleCipherClass *klass = NULL; - return 0; - } -} + g_return_if_fail(PURPLE_IS_CIPHER(cipher)); -void -purple_cipher_context_set_batch_mode(PurpleCipherContext *context, - PurpleCipherBatchMode mode) -{ - PurpleCipher *cipher = NULL; + klass = PURPLE_CIPHER_GET_CLASS(cipher); - g_return_if_fail(context); - - cipher = context->cipher; - g_return_if_fail(cipher); - - if(cipher->ops && cipher->ops->set_batch_mode) - cipher->ops->set_batch_mode(context, mode); + if(klass && klass->set_salt) + klass->set_salt(cipher, salt, len); else - purple_debug_warning("cipher", "The %s cipher does not support the " - "set_batch_mode operation\n", cipher->name); + purple_debug_warning("cipher", "the %s cipher does not implement the " + "set_salt method\n", + klass->get_name ? klass->get_name(cipher) : ""); } -PurpleCipherBatchMode -purple_cipher_context_get_batch_mode(PurpleCipherContext *context) -{ - PurpleCipher *cipher = NULL; - - g_return_val_if_fail(context, -1); - - cipher = context->cipher; - g_return_val_if_fail(cipher, -1); - - if(cipher->ops && cipher->ops->get_batch_mode) - return cipher->ops->get_batch_mode(context); - else { - purple_debug_warning("cipher", "The %s cipher does not support the " - "get_batch_mode operation\n", cipher->name); - return -1; - } -} - -size_t -purple_cipher_context_get_block_size(PurpleCipherContext *context) -{ - PurpleCipher *cipher = NULL; +/** + * purple_cipher_set_key: + * @cipher: The cipher whose key to set + * @key: The key + * + * Sets the key on a cipher + */ +void +purple_cipher_set_key(PurpleCipher *cipher, const guchar *key, size_t len) { + PurpleCipherClass *klass = NULL; - g_return_val_if_fail(context, -1); + g_return_if_fail(PURPLE_IS_CIPHER(cipher)); - cipher = context->cipher; - g_return_val_if_fail(cipher, -1); + klass = PURPLE_CIPHER_GET_CLASS(cipher); - if(cipher->ops && cipher->ops->get_block_size) - return cipher->ops->get_block_size(context); - else { - purple_debug_warning("cipher", "The %s cipher does not support the " - "get_block_size operation\n", cipher->name); - return -1; - } -} - -void -purple_cipher_context_set_data(PurpleCipherContext *context, gpointer data) { - g_return_if_fail(context); - - context->data = data; -} - -gpointer -purple_cipher_context_get_data(PurpleCipherContext *context) { - g_return_val_if_fail(context, NULL); - - return context->data; + if(klass && klass->set_key) + klass->set_key(cipher, key, len); + else + purple_debug_warning("cipher", "the %s cipher does not implement the " + "set_key method\n", + klass->get_name ? klass->get_name(cipher) : ""); } -gchar *purple_cipher_http_digest_calculate_session_key( - const gchar *algorithm, - const gchar *username, - const gchar *realm, - const gchar *password, - const gchar *nonce, - const gchar *client_nonce) -{ - PurpleCipher *cipher; - PurpleCipherContext *context; - gchar hash[33]; /* We only support MD5. */ +/** + * purple_cipher_get_key_size: + * @cipher: The cipher whose key size to get + * + * Gets the key size for a cipher + * + * Return Value: The size of the key + */ +size_t +purple_cipher_get_key_size(PurpleCipher *cipher) { + PurpleCipherClass *klass = NULL; - g_return_val_if_fail(username != NULL, NULL); - g_return_val_if_fail(realm != NULL, NULL); - g_return_val_if_fail(password != NULL, NULL); - g_return_val_if_fail(nonce != NULL, NULL); + g_return_val_if_fail(PURPLE_IS_CIPHER(cipher), -1); + + klass = PURPLE_CIPHER_GET_CLASS(cipher); - /* Check for a supported algorithm. */ - g_return_val_if_fail(algorithm == NULL || - *algorithm == '\0' || - g_ascii_strcasecmp(algorithm, "MD5") || - g_ascii_strcasecmp(algorithm, "MD5-sess"), NULL); - - cipher = purple_ciphers_find_cipher("md5"); - g_return_val_if_fail(cipher != NULL, NULL); - - context = purple_cipher_context_new(cipher, NULL); + if(klass && klass->get_key_size) + return klass->get_key_size(cipher); + else + purple_debug_warning("cipher", "the %s cipher does not implement the " + "get_key_size method\n", + klass->get_name ? klass->get_name(cipher) : ""); - purple_cipher_context_append(context, (guchar *)username, strlen(username)); - purple_cipher_context_append(context, (guchar *)":", 1); - purple_cipher_context_append(context, (guchar *)realm, strlen(realm)); - purple_cipher_context_append(context, (guchar *)":", 1); - purple_cipher_context_append(context, (guchar *)password, strlen(password)); - - if (algorithm != NULL && !g_ascii_strcasecmp(algorithm, "MD5-sess")) - { - guchar digest[16]; + return -1; +} - if (client_nonce == NULL) - { - purple_cipher_context_destroy(context); - purple_debug_error("cipher", "Required client_nonce missing for MD5-sess digest calculation.\n"); - return NULL; - } - - purple_cipher_context_digest(context, digest, sizeof(digest)); - purple_cipher_context_destroy(context); +/** + * purple_cipher_set_batch_mode: + * @cipher: The cipher whose batch mode to set + * @mode: The batch mode under which the cipher should operate + * + * Sets the batch mode of a cipher + */ +void +purple_cipher_set_batch_mode(PurpleCipher *cipher, + PurpleCipherBatchMode mode) +{ + PurpleCipherClass *klass = NULL; - context = purple_cipher_context_new(cipher, NULL); - purple_cipher_context_append(context, digest, sizeof(digest)); - purple_cipher_context_append(context, (guchar *)":", 1); - purple_cipher_context_append(context, (guchar *)nonce, strlen(nonce)); - purple_cipher_context_append(context, (guchar *)":", 1); - purple_cipher_context_append(context, (guchar *)client_nonce, strlen(client_nonce)); - } + g_return_if_fail(PURPLE_IS_CIPHER(cipher)); + + klass = PURPLE_CIPHER_GET_CLASS(cipher); - purple_cipher_context_digest_to_str(context, hash, sizeof(hash)); - purple_cipher_context_destroy(context); - - return g_strdup(hash); + if(klass && klass->set_batch_mode) + klass->set_batch_mode(cipher, mode); + else + purple_debug_warning("cipher", "the %s cipher does not implement the " + "set_batch_mode method\n", + klass->get_name ? klass->get_name(cipher) : ""); } -gchar *purple_cipher_http_digest_calculate_response( - const gchar *algorithm, - const gchar *method, - const gchar *digest_uri, - const gchar *qop, - const gchar *entity, - const gchar *nonce, - const gchar *nonce_count, - const gchar *client_nonce, - const gchar *session_key) +/** + * purple_cipher_get_batch_mode: + * @cipher: The cipher whose batch mode to get + * + * Gets the batch mode of a cipher + * + * Return Value: The batch mode under which the cipher is operating + */ +PurpleCipherBatchMode +purple_cipher_get_batch_mode(PurpleCipher *cipher) { - PurpleCipher *cipher; - PurpleCipherContext *context; - static gchar hash2[33]; /* We only support MD5. */ - - g_return_val_if_fail(method != NULL, NULL); - g_return_val_if_fail(digest_uri != NULL, NULL); - g_return_val_if_fail(nonce != NULL, NULL); - g_return_val_if_fail(session_key != NULL, NULL); + PurpleCipherClass *klass = NULL; - /* Check for a supported algorithm. */ - g_return_val_if_fail(algorithm == NULL || - *algorithm == '\0' || - g_ascii_strcasecmp(algorithm, "MD5") || - g_ascii_strcasecmp(algorithm, "MD5-sess"), NULL); + g_return_val_if_fail(PURPLE_IS_CIPHER(cipher), -1); - /* Check for a supported "quality of protection". */ - g_return_val_if_fail(qop == NULL || - *qop == '\0' || - g_ascii_strcasecmp(qop, "auth") || - g_ascii_strcasecmp(qop, "auth-int"), NULL); + klass = PURPLE_CIPHER_GET_CLASS(cipher); - cipher = purple_ciphers_find_cipher("md5"); - g_return_val_if_fail(cipher != NULL, NULL); - - context = purple_cipher_context_new(cipher, NULL); + if(klass && klass->get_batch_mode) + return klass->get_batch_mode(cipher); + else + purple_debug_warning("cipher", "the %s cipher does not implement the " + "get_batch_mode method\n", + klass->get_name ? klass->get_name(cipher) : ""); - purple_cipher_context_append(context, (guchar *)method, strlen(method)); - purple_cipher_context_append(context, (guchar *)":", 1); - purple_cipher_context_append(context, (guchar *)digest_uri, strlen(digest_uri)); - - if (qop != NULL && !g_ascii_strcasecmp(qop, "auth-int")) - { - PurpleCipherContext *context2; - gchar entity_hash[33]; + return -1; +} - if (entity == NULL) - { - purple_cipher_context_destroy(context); - purple_debug_error("cipher", "Required entity missing for auth-int digest calculation.\n"); - return NULL; - } - - context2 = purple_cipher_context_new(cipher, NULL); - purple_cipher_context_append(context2, (guchar *)entity, strlen(entity)); - purple_cipher_context_digest_to_str(context2, entity_hash, sizeof(entity_hash)); - purple_cipher_context_destroy(context2); - - purple_cipher_context_append(context, (guchar *)":", 1); - purple_cipher_context_append(context, (guchar *)entity_hash, strlen(entity_hash)); - } - - purple_cipher_context_digest_to_str(context, hash2, sizeof(hash2)); - purple_cipher_context_destroy(context); - - context = purple_cipher_context_new(cipher, NULL); - purple_cipher_context_append(context, (guchar *)session_key, strlen(session_key)); - purple_cipher_context_append(context, (guchar *)":", 1); - purple_cipher_context_append(context, (guchar *)nonce, strlen(nonce)); - purple_cipher_context_append(context, (guchar *)":", 1); +/** + * purple_cipher_get_block_size: + * @cipher: The cipher whose block size to get + * + * Gets the block size of a cipher + * + * Return Value: The block size of the cipher + */ +size_t +purple_cipher_get_block_size(PurpleCipher *cipher) +{ + PurpleCipherClass *klass = NULL; - if (qop != NULL && *qop != '\0') - { - if (nonce_count == NULL) - { - purple_cipher_context_destroy(context); - purple_debug_error("cipher", "Required nonce_count missing for digest calculation.\n"); - return NULL; - } + g_return_val_if_fail(PURPLE_IS_CIPHER(cipher), -1); - if (client_nonce == NULL) - { - purple_cipher_context_destroy(context); - purple_debug_error("cipher", "Required client_nonce missing for digest calculation.\n"); - return NULL; - } + klass = PURPLE_CIPHER_GET_CLASS(cipher); - purple_cipher_context_append(context, (guchar *)nonce_count, strlen(nonce_count)); - purple_cipher_context_append(context, (guchar *)":", 1); - purple_cipher_context_append(context, (guchar *)client_nonce, strlen(client_nonce)); - purple_cipher_context_append(context, (guchar *)":", 1); - - purple_cipher_context_append(context, (guchar *)qop, strlen(qop)); + if(klass && klass->get_block_size) + return klass->get_block_size(cipher); + else + purple_debug_warning("cipher", "the %s cipher does not implement the " + "get_block_size method\n", + klass->get_name ? klass->get_name(cipher) : ""); - purple_cipher_context_append(context, (guchar *)":", 1); - } - - purple_cipher_context_append(context, (guchar *)hash2, strlen(hash2)); - purple_cipher_context_digest_to_str(context, hash2, sizeof(hash2)); - purple_cipher_context_destroy(context); - - return g_strdup(hash2); + return -1; }
--- a/libpurple/cipher.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/cipher.h Sun Jun 23 13:35:53 2013 +0530 @@ -28,110 +28,101 @@ #define PURPLE_CIPHER_H #include <glib.h> +#include <glib-object.h> #include <string.h> -#define PURPLE_CIPHER(obj) ((PurpleCipher *)(obj)) /**< PurpleCipher typecast helper */ -#define PURPLE_CIPHER_OPS(obj) ((PurpleCipherOps *)(obj)) /**< PurpleCipherInfo typecase helper */ -#define PURPLE_CIPHER_CONTEXT(obj) ((PurpleCipherContext *)(obj)) /**< PurpleCipherContext typecast helper */ +#include "internal.h" -typedef struct _PurpleCipher PurpleCipher; /**< A handle to a PurpleCipher */ -typedef struct _PurpleCipherOps PurpleCipherOps; /**< Ops for a PurpleCipher */ -typedef struct _PurpleCipherContext PurpleCipherContext; /**< A context for a PurpleCipher */ +#define PURPLE_TYPE_CIPHER (purple_cipher_get_type()) +#define PURPLE_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_CIPHER, PurpleCipher)) +#define PURPLE_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_CIPHER, PurpleCipherClass)) +#define PURPLE_IS_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_CIPHER)) +#define PURPLE_IS_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_CIPHER)) +#define PURPLE_CIPHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_CIPHER, PurpleCipherClass)) + +typedef struct _PurpleCipher PurpleCipher; +typedef struct _PurpleCipherClass PurpleCipherClass; /** + * PurpleCipherBatchMode: + * @PURPLE_CIPHER_BATCH_MODE_ECB: Electronic Codebook Mode + * @PURPLE_CIPHER_BATCH_MODE_CBC: Cipher Block Chaining Mode + * * Modes for batch encrypters */ -typedef enum { - PURPLE_CIPHER_BATCH_MODE_ECB, - PURPLE_CIPHER_BATCH_MODE_CBC +typedef enum { + PURPLE_CIPHER_BATCH_MODE_ECB, /*< nick=ECB Batch Mode >*/ + PURPLE_CIPHER_BATCH_MODE_CBC /*< nick=CBC Batch Mode >*/ } PurpleCipherBatchMode; /** - * The operation flags for a cipher + * PurpleCipher: + * + * Purple Cipher is an opaque data structure and should not be used directly. */ -typedef enum { - PURPLE_CIPHER_CAPS_SET_OPT = 1 << 1, /**< Set option flag */ - PURPLE_CIPHER_CAPS_GET_OPT = 1 << 2, /**< Get option flag */ - PURPLE_CIPHER_CAPS_INIT = 1 << 3, /**< Init flag */ - PURPLE_CIPHER_CAPS_RESET = 1 << 4, /**< Reset flag */ - PURPLE_CIPHER_CAPS_RESET_STATE = 1 << 5, /**< Reset state flag */ - PURPLE_CIPHER_CAPS_UNINIT = 1 << 6, /**< Uninit flag */ - PURPLE_CIPHER_CAPS_SET_IV = 1 << 7, /**< Set IV flag */ - PURPLE_CIPHER_CAPS_APPEND = 1 << 8, /**< Append flag */ - PURPLE_CIPHER_CAPS_DIGEST = 1 << 9, /**< Digest flag */ - PURPLE_CIPHER_CAPS_GET_DIGEST_SIZE = 1 << 10, /**< The get digest size flag */ - PURPLE_CIPHER_CAPS_ENCRYPT = 1 << 11, /**< Encrypt flag */ - PURPLE_CIPHER_CAPS_DECRYPT = 1 << 12, /**< Decrypt flag */ - PURPLE_CIPHER_CAPS_SET_SALT = 1 << 13, /**< Set salt flag */ - PURPLE_CIPHER_CAPS_GET_SALT_SIZE = 1 << 14, /**< Get salt size flag */ - PURPLE_CIPHER_CAPS_SET_KEY = 1 << 15, /**< Set key flag */ - PURPLE_CIPHER_CAPS_GET_KEY_SIZE = 1 << 16, /**< Get key size flag */ - PURPLE_CIPHER_CAPS_SET_BATCH_MODE = 1 << 17, /**< Set batch mode flag */ - PURPLE_CIPHER_CAPS_GET_BATCH_MODE = 1 << 18, /**< Get batch mode flag */ - PURPLE_CIPHER_CAPS_GET_BLOCK_SIZE = 1 << 19, /**< The get block size flag */ - PURPLE_CIPHER_CAPS_UNKNOWN = 1 << 20 /**< Unknown */ -} PurpleCipherCaps; +struct _PurpleCipher { + /*< private >*/ + GObject gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; /** - * The operations of a cipher. Every cipher must implement one of these. + * PurpleCipherClass: + * + * The base class for all #PurpleCipher's. */ -struct _PurpleCipherOps { - /** The set option function */ - void (*set_option)(PurpleCipherContext *context, const gchar *name, void *value); - - /** The get option function */ - void *(*get_option)(PurpleCipherContext *context, const gchar *name); - - /** The init function */ - void (*init)(PurpleCipherContext *context, void *extra); +struct _PurpleCipherClass { + /*< private >*/ + GObjectClass parent_class; /** The reset function */ - void (*reset)(PurpleCipherContext *context, void *extra); + void (*reset)(PurpleCipher *cipher); /** The reset state function */ - void (*reset_state)(PurpleCipherContext *context, void *extra); - - /** The uninit function */ - void (*uninit)(PurpleCipherContext *context); + void (*reset_state)(PurpleCipher *cipher); /** The set initialization vector function */ - void (*set_iv)(PurpleCipherContext *context, guchar *iv, size_t len); + void (*set_iv)(PurpleCipher *cipher, guchar *iv, size_t len); /** The append data function */ - void (*append)(PurpleCipherContext *context, const guchar *data, size_t len); + void (*append)(PurpleCipher *cipher, const guchar *data, size_t len); /** The digest function */ - gboolean (*digest)(PurpleCipherContext *context, guchar digest[], size_t len); + gboolean (*digest)(PurpleCipher *cipher, guchar digest[], size_t len); /** The get digest size function */ - size_t (*get_digest_size)(PurpleCipherContext *context); + size_t (*get_digest_size)(PurpleCipher *cipher); /** The encrypt function */ - ssize_t (*encrypt)(PurpleCipherContext *context, const guchar input[], size_t in_len, guchar output[], size_t out_size); + ssize_t (*encrypt)(PurpleCipher *cipher, const guchar input[], size_t in_len, guchar output[], size_t out_size); /** The decrypt function */ - ssize_t (*decrypt)(PurpleCipherContext *context, const guchar input[], size_t in_len, guchar output[], size_t out_size); + ssize_t (*decrypt)(PurpleCipher *cipher, const guchar input[], size_t in_len, guchar output[], size_t out_size); /** The set salt function */ - void (*set_salt)(PurpleCipherContext *context, const guchar *salt, size_t len); - - /** The get salt size function */ - size_t (*get_salt_size)(PurpleCipherContext *context); + void (*set_salt)(PurpleCipher *cipher, const guchar *salt, size_t len); /** The set key function */ - void (*set_key)(PurpleCipherContext *context, const guchar *key, size_t len); + void (*set_key)(PurpleCipher *cipher, const guchar *key, size_t len); /** The get key size function */ - size_t (*get_key_size)(PurpleCipherContext *context); + size_t (*get_key_size)(PurpleCipher *cipher); /** The set batch mode function */ - void (*set_batch_mode)(PurpleCipherContext *context, PurpleCipherBatchMode mode); + void (*set_batch_mode)(PurpleCipher *cipher, PurpleCipherBatchMode mode); /** The get batch mode function */ - PurpleCipherBatchMode (*get_batch_mode)(PurpleCipherContext *context); + PurpleCipherBatchMode (*get_batch_mode)(PurpleCipher *cipher); /** The get block size function */ - size_t (*get_block_size)(PurpleCipherContext *context); + size_t (*get_block_size)(PurpleCipher *cipher); + + /** The get cipher name function */ + const gchar* (*get_name)(PurpleCipher *cipher); void (*_purple_reserved1)(void); void (*_purple_reserved2)(void); @@ -141,380 +132,31 @@ G_BEGIN_DECLS -/*****************************************************************************/ -/** @name PurpleCipher API */ -/*****************************************************************************/ -/*@{*/ +GType purple_cipher_get_type(void); -/** - * Gets a cipher's name - * - * @param cipher The cipher handle - * - * @return The cipher's name - */ const gchar *purple_cipher_get_name(PurpleCipher *cipher); -/** - * Gets a cipher's capabilities - * - * @param cipher The cipher handle - * - * @return The cipher's info - */ -guint purple_cipher_get_capabilities(PurpleCipher *cipher); - -/** - * Gets a digest from a cipher - * - * @param name The cipher's name - * @param data The data to hash - * @param data_len The length of the data - * @param digest The returned digest - * @param out_size The size of digest buffer - * - * @return The count of bytes written, or -1 if failed - */ -ssize_t purple_cipher_digest_region(const gchar *name, const guchar *data, size_t data_len, guchar digest[], size_t out_size); - -/*@}*/ -/******************************************************************************/ -/** @name PurpleCiphers API */ -/******************************************************************************/ -/*@{*/ - -/** - * Finds a cipher by it's name - * - * @param name The name of the cipher to find - * - * @return The cipher handle or @c NULL - */ -PurpleCipher *purple_ciphers_find_cipher(const gchar *name); - -/** - * Registers a cipher as a usable cipher - * - * @param name The name of the new cipher - * @param ops The cipher ops to register - * - * @return The handle to the new cipher or @c NULL if it failed - */ -PurpleCipher *purple_ciphers_register_cipher(const gchar *name, PurpleCipherOps *ops); - -/** - * Unregisters a cipher - * - * @param cipher The cipher handle to unregister - * - * @return Whether or not the cipher was successfully unloaded - */ -gboolean purple_ciphers_unregister_cipher(PurpleCipher *cipher); - -/** - * Gets the list of ciphers - * - * @return The list of available ciphers - * @note This list should not be modified, it is owned by the cipher core - */ -GList *purple_ciphers_get_ciphers(void); - -/*@}*/ -/******************************************************************************/ -/** @name PurpleCipher Subsystem API */ -/******************************************************************************/ -/*@{*/ - -/** - * Gets the handle to the cipher subsystem - * - * @return The handle to the cipher subsystem - */ -gpointer purple_ciphers_get_handle(void); - -/** - * Initializes the cipher core - */ -void purple_ciphers_init(void); - -/** - * Uninitializes the cipher core - */ -void purple_ciphers_uninit(void); +void purple_cipher_reset(PurpleCipher *cipher); +void purple_cipher_reset_state(PurpleCipher *cipher); +void purple_cipher_set_iv(PurpleCipher *cipher, guchar *iv, size_t len); -/*@}*/ -/******************************************************************************/ -/** @name PurpleCipherContext API */ -/******************************************************************************/ -/*@{*/ - -/** - * Sets the value an option on a cipher context - * - * @param context The cipher context - * @param name The name of the option - * @param value The value to set - */ -void purple_cipher_context_set_option(PurpleCipherContext *context, const gchar *name, gpointer value); - -/** - * Gets the vale of an option on a cipher context - * - * @param context The cipher context - * @param name The name of the option - * @return The value of the option - */ -gpointer purple_cipher_context_get_option(PurpleCipherContext *context, const gchar *name); - -/** - * Creates a new cipher context and initializes it - * - * @param cipher The cipher to use - * @param extra Extra data for the specific cipher - * - * @return The new cipher context - */ -PurpleCipherContext *purple_cipher_context_new(PurpleCipher *cipher, void *extra); - -/** - * Creates a new cipher context by the cipher name and initializes it - * - * @param name The cipher's name - * @param extra Extra data for the specific cipher - * - * @return The new cipher context - */ -PurpleCipherContext *purple_cipher_context_new_by_name(const gchar *name, void *extra); - -/** - * Resets a cipher context to it's default value - * @note If you have set an IV you will have to set it after resetting - * - * @param context The context to reset - * @param extra Extra data for the specific cipher - */ -void purple_cipher_context_reset(PurpleCipherContext *context, gpointer extra); - -/** - * Resets a cipher state to it's default value, but doesn't touch stateless - * configuration. - * - * That means, IV and digest context will be wiped out, but keys, ops or salt - * will remain untouched. - * - * @param context The context to reset - * @param extra Extra data for the specific cipher - */ -void purple_cipher_context_reset_state(PurpleCipherContext *context, gpointer extra); - -/** - * Destorys a cipher context and deinitializes it - * - * @param context The cipher context to destory - */ -void purple_cipher_context_destroy(PurpleCipherContext *context); - -/** - * Sets the initialization vector for a context - * @note This should only be called right after a cipher context is created or reset - * - * @param context The context to set the IV to - * @param iv The initialization vector to set - * @param len The len of the IV - */ -void purple_cipher_context_set_iv(PurpleCipherContext *context, guchar *iv, size_t len); - -/** - * Appends data to the context - * - * @param context The context to append data to - * @param data The data to append - * @param len The length of the data - */ -void purple_cipher_context_append(PurpleCipherContext *context, const guchar *data, size_t len); +void purple_cipher_append(PurpleCipher *cipher, const guchar *data, size_t len); +gboolean purple_cipher_digest(PurpleCipher *cipher, guchar digest[], size_t len); +gboolean purple_cipher_digest_to_str(PurpleCipher *cipher, gchar digest_s[], size_t len); +size_t purple_cipher_get_digest_size(PurpleCipher *cipher); -/** - * Digests a context - * - * @param context The context to digest - * @param digest The return buffer for the digest - * @param len The length of the buffer - */ -gboolean purple_cipher_context_digest(PurpleCipherContext *context, guchar digest[], size_t len); - -/** - * Converts a guchar digest into a hex string - * - * @param context The context to get a digest from - * @param digest_s The return buffer for the string digest - * @param len The length of the buffer - */ -gboolean purple_cipher_context_digest_to_str(PurpleCipherContext *context, gchar digest_s[], size_t len); - -/** - * Gets the digest size of a context - * - * @param context The context whose digest size to get - * - * @return The digest size of the context - */ -size_t purple_cipher_context_get_digest_size(PurpleCipherContext *context); - -/** - * Encrypts data using the context - * - * @param context The context - * @param input The data to encrypt - * @param in_len The length of the data - * @param output The output buffer - * @param out_size The size of the output buffer - * - * @return A length of data that was outputed or -1, if failed - */ -ssize_t purple_cipher_context_encrypt(PurpleCipherContext *context, const guchar input[], size_t in_len, guchar output[], size_t out_size); +ssize_t purple_cipher_encrypt(PurpleCipher *cipher, const guchar input[], size_t in_len, guchar output[], size_t out_size); +ssize_t purple_cipher_decrypt(PurpleCipher *cipher, const guchar input[], size_t in_len, guchar output[], size_t out_size); -/** - * Decrypts data using the context - * - * @param context The context - * @param input The data to encrypt - * @param in_len The length of the returned value - * @param output The output buffer - * @param out_size The size of the output buffer - * - * @return A length of data that was outputed or -1, if failed - */ -ssize_t purple_cipher_context_decrypt(PurpleCipherContext *context, const guchar input[], size_t in_len, guchar output[], size_t out_size); - -/** - * Sets the salt on a context - * - * @param context The context whose salt to set - * @param salt The salt - * @param len The length of the salt - */ -void purple_cipher_context_set_salt(PurpleCipherContext *context, const guchar *salt, size_t len); - -/** - * Gets the size of the salt if the cipher supports it - * - * @param context The context whose salt size to get - * - * @return The size of the salt - */ -size_t purple_cipher_context_get_salt_size(PurpleCipherContext *context); - -/** - * Sets the key on a context - * - * @param context The context whose key to set - * @param key The key - * @param len The size of the key - */ -void purple_cipher_context_set_key(PurpleCipherContext *context, const guchar *key, size_t len); - -/** - * Gets the size of the key if the cipher supports it - * - * @param context The context whose key size to get - * - * @return The size of the key - */ -size_t purple_cipher_context_get_key_size(PurpleCipherContext *context); +void purple_cipher_set_salt(PurpleCipher *cipher, const guchar *salt, size_t len); -/** - * Sets the batch mode of a context - * - * @param context The context whose batch mode to set - * @param mode The batch mode under which the cipher should operate - * - */ -void purple_cipher_context_set_batch_mode(PurpleCipherContext *context, PurpleCipherBatchMode mode); - -/** - * Gets the batch mode of a context - * - * @param context The context whose batch mode to get - * - * @return The batch mode under which the cipher is operating - */ -PurpleCipherBatchMode purple_cipher_context_get_batch_mode(PurpleCipherContext *context); - -/** - * Gets the block size of a context - * - * @param context The context whose block size to get - * - * @return The block size of the context - */ -size_t purple_cipher_context_get_block_size(PurpleCipherContext *context); - -/** - * Sets the cipher data for a context - * - * @param context The context whose cipher data to set - * @param data The cipher data to set - */ -void purple_cipher_context_set_data(PurpleCipherContext *context, gpointer data); - -/** - * Gets the cipher data for a context - * - * @param context The context whose cipher data to get - * - * @return The cipher data - */ -gpointer purple_cipher_context_get_data(PurpleCipherContext *context); +void purple_cipher_set_key(PurpleCipher *cipher, const guchar *key, size_t len); +size_t purple_cipher_get_key_size(PurpleCipher *cipher); -/*@}*/ -/*****************************************************************************/ -/** @name Purple Cipher HTTP Digest Helper Functions */ -/*****************************************************************************/ -/*@{*/ - -/** - * Calculates a session key for HTTP Digest authentation - * - * See RFC 2617 for more information. - * - * @param algorithm The hash algorithm to use - * @param username The username provided by the user - * @param realm The authentication realm provided by the server - * @param password The password provided by the user - * @param nonce The nonce provided by the server - * @param client_nonce The nonce provided by the client - * - * @return The session key, or @c NULL if an error occurred. - */ -gchar *purple_cipher_http_digest_calculate_session_key( - const gchar *algorithm, const gchar *username, - const gchar *realm, const gchar *password, - const gchar *nonce, const gchar *client_nonce); +void purple_cipher_set_batch_mode(PurpleCipher *cipher, PurpleCipherBatchMode mode); +PurpleCipherBatchMode purple_cipher_get_batch_mode(PurpleCipher *cipher); -/** Calculate a response for HTTP Digest authentication - * - * See RFC 2617 for more information. - * - * @param algorithm The hash algorithm to use - * @param method The HTTP method in use - * @param digest_uri The URI from the initial request - * @param qop The "quality of protection" - * @param entity The entity body - * @param nonce The nonce provided by the server - * @param nonce_count The nonce count - * @param client_nonce The nonce provided by the client - * @param session_key The session key from purple_cipher_http_digest_calculate_session_key() - * - * @return The hashed response, or @c NULL if an error occurred. - */ -gchar *purple_cipher_http_digest_calculate_response( - const gchar *algorithm, const gchar *method, - const gchar *digest_uri, const gchar *qop, - const gchar *entity, const gchar *nonce, - const gchar *nonce_count, const gchar *client_nonce, - const gchar *session_key); - -/*@}*/ +size_t purple_cipher_get_block_size(PurpleCipher *cipher); G_END_DECLS
--- a/libpurple/ciphers/Makefile.am Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/ciphers/Makefile.am Sun Jun 23 13:35:53 2013 +0530 @@ -1,24 +1,23 @@ noinst_LTLIBRARIES=libpurple-ciphers.la -# XXX: cipher.lo won't be updated after a change in cipher files if USE_NSS -AES_SOURCE = aes.c +AES_SOURCE = aescipher.c endif if USE_GNUTLS -AES_SOURCE = aes.c +AES_SOURCE = aescipher.c endif libpurple_ciphers_la_SOURCES=\ $(AES_SOURCE) \ - des.c \ - gchecksum.c \ - hmac.c \ - md4.c \ - pbkdf2.c \ - rc4.c - -noinst_HEADERS =\ - ciphers.h + descipher.c \ + des3cipher.c \ + hmaccipher.c \ + md4hash.c \ + md5hash.c \ + pbkdf2cipher.c \ + rc4cipher.c \ + sha1hash.c \ + sha256hash.c INCLUDES = -I$(top_srcdir)/libpurple
--- a/libpurple/ciphers/aes.c Sun Jun 23 02:43:06 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,566 +0,0 @@ -/* - * 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 - * - * Written by Tomek Wasilczyk <tomkiewicz@cpw.pidgin.im> - */ - -#include "internal.h" -#include "cipher.h" -#include "ciphers.h" -#include "debug.h" - -#if defined(HAVE_GNUTLS) -# define PURPLE_AES_USE_GNUTLS 1 -# include <gnutls/gnutls.h> -# include <gnutls/crypto.h> -#elif defined(HAVE_NSS) -# define PURPLE_AES_USE_NSS 1 -# include <nss.h> -# include <pk11pub.h> -# include <prerror.h> -#else -# error "No GnuTLS or NSS support" -#endif - -/* 128bit */ -#define PURPLE_AES_BLOCK_SIZE 16 - -typedef struct -{ - guchar iv[PURPLE_AES_BLOCK_SIZE]; - guchar key[32]; - guint key_size; - gboolean failure; -} AESContext; - -typedef gboolean (*purple_aes_crypt_func)( - const guchar *input, guchar *output, size_t len, - guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size); - -static void -purple_aes_init(PurpleCipherContext *context, void *extra) -{ - AESContext *ctx_data; - - ctx_data = g_new0(AESContext, 1); - purple_cipher_context_set_data(context, ctx_data); - - purple_cipher_context_reset(context, extra); -} - -static void -purple_aes_uninit(PurpleCipherContext *context) -{ - AESContext *ctx_data; - - purple_cipher_context_reset(context, NULL); - - ctx_data = purple_cipher_context_get_data(context); - g_free(ctx_data); - purple_cipher_context_set_data(context, NULL); -} - -static void -purple_aes_reset(PurpleCipherContext *context, void *extra) -{ - AESContext *ctx_data = purple_cipher_context_get_data(context); - - g_return_if_fail(ctx_data != NULL); - - memset(ctx_data->iv, 0, sizeof(ctx_data->iv)); - memset(ctx_data->key, 0, sizeof(ctx_data->key)); - ctx_data->key_size = 32; /* 256bit */ - ctx_data->failure = FALSE; -} - -static void -purple_aes_set_option(PurpleCipherContext *context, const gchar *name, - void *value) -{ - AESContext *ctx_data = purple_cipher_context_get_data(context); - - purple_debug_error("cipher-aes", "set_option not supported\n"); - ctx_data->failure = TRUE; -} - -static void -purple_aes_set_iv(PurpleCipherContext *context, guchar *iv, size_t len) -{ - AESContext *ctx_data = purple_cipher_context_get_data(context); - - if ((len > 0 && iv == NULL) || - (len != 0 && len != sizeof(ctx_data->iv))) { - purple_debug_error("cipher-aes", "invalid IV length\n"); - ctx_data->failure = TRUE; - return; - } - - if (len == 0) - memset(ctx_data->iv, 0, sizeof(ctx_data->iv)); - else - memcpy(ctx_data->iv, iv, len); -} - -static void -purple_aes_set_key(PurpleCipherContext *context, const guchar *key, size_t len) -{ - AESContext *ctx_data = purple_cipher_context_get_data(context); - - if ((len > 0 && key == NULL) || - (len != 0 && len != 16 && len != 24 && len != 32)) { - purple_debug_error("cipher-aes", "invalid key length\n"); - ctx_data->failure = TRUE; - return; - } - - ctx_data->key_size = len; - memset(ctx_data->key, 0, sizeof(ctx_data->key)); - if (len > 0) - memcpy(ctx_data->key, key, len); -} - -static guchar * -purple_aes_pad_pkcs7(const guchar input[], size_t in_len, size_t *out_len) -{ - int padding_len, total_len; - guchar *padded; - - g_return_val_if_fail(input != NULL, NULL); - g_return_val_if_fail(out_len != NULL, NULL); - - padding_len = PURPLE_AES_BLOCK_SIZE - (in_len % PURPLE_AES_BLOCK_SIZE); - total_len = in_len + padding_len; - g_assert((total_len % PURPLE_AES_BLOCK_SIZE) == 0); - - padded = g_new(guchar, total_len); - *out_len = total_len; - - memcpy(padded, input, in_len); - memset(padded + in_len, padding_len, padding_len); - - return padded; -} - -static ssize_t -purple_aes_unpad_pkcs7(guchar input[], size_t in_len) -{ - int padding_len, i; - size_t out_len; - - g_return_val_if_fail(input != NULL, -1); - g_return_val_if_fail(in_len > 0, -1); - - padding_len = input[in_len - 1]; - if (padding_len <= 0 || padding_len > PURPLE_AES_BLOCK_SIZE || - padding_len > in_len) { - purple_debug_warning("cipher-aes", - "Invalid padding length: %d (total %d) - " - "most probably, the key was invalid\n", - padding_len, in_len); - return -1; - } - - out_len = in_len - padding_len; - for (i = 0; i < padding_len; i++) { - if (input[out_len + i] != padding_len) { - purple_debug_warning("cipher-aes", - "Padding doesn't match at pos %d (found %02x, " - "expected %02x) - " - "most probably, the key was invalid\n", - i, input[out_len + i], padding_len); - return -1; - } - } - - memset(input + out_len, 0, padding_len); - return out_len; -} - -#ifdef PURPLE_AES_USE_GNUTLS - -static gnutls_cipher_hd_t -purple_aes_crypt_gnutls_init(guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], - guint key_size) -{ - gnutls_cipher_hd_t handle; - gnutls_cipher_algorithm_t algorithm; - gnutls_datum_t key_info, iv_info; - int ret; - - if (key_size == 16) - algorithm = GNUTLS_CIPHER_AES_128_CBC; - else if (key_size == 24) - algorithm = GNUTLS_CIPHER_AES_192_CBC; - else if (key_size == 32) - algorithm = GNUTLS_CIPHER_AES_256_CBC; - else - g_return_val_if_reached(NULL); - - key_info.data = key; - key_info.size = key_size; - - iv_info.data = iv; - iv_info.size = PURPLE_AES_BLOCK_SIZE; - - ret = gnutls_cipher_init(&handle, algorithm, &key_info, &iv_info); - if (ret != 0) { - purple_debug_error("cipher-aes", - "gnutls_cipher_init failed: %d\n", ret); - return NULL; - } - - return handle; -} - -static gboolean -purple_aes_encrypt_gnutls(const guchar *input, guchar *output, size_t len, - guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size) -{ - gnutls_cipher_hd_t handle; - int ret; - - handle = purple_aes_crypt_gnutls_init(iv, key, key_size); - if (handle == NULL) - return FALSE; - - ret = gnutls_cipher_encrypt2(handle, input, len, output, len); - gnutls_cipher_deinit(handle); - - if (ret != 0) { - purple_debug_error("cipher-aes", - "gnutls_cipher_encrypt2 failed: %d\n", ret); - return FALSE; - } - - return TRUE; -} - -static gboolean -purple_aes_decrypt_gnutls(const guchar *input, guchar *output, size_t len, - guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size) -{ - gnutls_cipher_hd_t handle; - int ret; - - handle = purple_aes_crypt_gnutls_init(iv, key, key_size); - if (handle == NULL) - return FALSE; - - ret = gnutls_cipher_decrypt2(handle, input, len, output, len); - gnutls_cipher_deinit(handle); - - if (ret != 0) { - purple_debug_error("cipher-aes", - "gnutls_cipher_decrypt2 failed: %d\n", ret); - return FALSE; - } - - return TRUE; -} - -#endif /* PURPLE_AES_USE_GNUTLS */ - -#ifdef PURPLE_AES_USE_NSS - -typedef struct -{ - PK11SlotInfo *slot; - PK11SymKey *sym_key; - SECItem *sec_param; - PK11Context *enc_context; -} purple_aes_encrypt_nss_context; - -static void -purple_aes_encrypt_nss_context_cleanup(purple_aes_encrypt_nss_context *ctx) -{ - g_return_if_fail(ctx != NULL); - - if (ctx->enc_context != NULL) - PK11_DestroyContext(ctx->enc_context, TRUE); - if (ctx->sec_param != NULL) - SECITEM_FreeItem(ctx->sec_param, TRUE); - if (ctx->sym_key != NULL) - PK11_FreeSymKey(ctx->sym_key); - if (ctx->slot != NULL) - PK11_FreeSlot(ctx->slot); - - memset(ctx, 0, sizeof(purple_aes_encrypt_nss_context)); -} - -static gboolean -purple_aes_crypt_nss(const guchar *input, guchar *output, size_t len, - guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size, - CK_ATTRIBUTE_TYPE operation) -{ - purple_aes_encrypt_nss_context ctx; - CK_MECHANISM_TYPE cipher_mech = CKM_AES_CBC; - SECItem key_item, iv_item; - SECStatus ret; - int outlen = 0; - unsigned int outlen_tmp = 0; - - memset(&ctx, 0, sizeof(purple_aes_encrypt_nss_context)); - - if (NSS_NoDB_Init(NULL) != SECSuccess) { - purple_debug_error("cipher-aes", - "NSS_NoDB_Init failed: %d\n", PR_GetError()); - return FALSE; - } - - ctx.slot = PK11_GetBestSlot(cipher_mech, NULL); - if (ctx.slot == NULL) { - purple_debug_error("cipher-aes", - "PK11_GetBestSlot failed: %d\n", PR_GetError()); - return FALSE; - } - - key_item.type = siBuffer; - key_item.data = key; - key_item.len = key_size; - ctx.sym_key = PK11_ImportSymKey(ctx.slot, cipher_mech, - PK11_OriginUnwrap, CKA_ENCRYPT, &key_item, NULL); - if (ctx.sym_key == NULL) { - purple_debug_error("cipher-aes", - "PK11_ImportSymKey failed: %d\n", PR_GetError()); - purple_aes_encrypt_nss_context_cleanup(&ctx); - return FALSE; - } - - iv_item.type = siBuffer; - iv_item.data = iv; - iv_item.len = PURPLE_AES_BLOCK_SIZE; - ctx.sec_param = PK11_ParamFromIV(cipher_mech, &iv_item); - if (ctx.sec_param == NULL) { - purple_debug_error("cipher-aes", - "PK11_ParamFromIV failed: %d\n", PR_GetError()); - purple_aes_encrypt_nss_context_cleanup(&ctx); - return FALSE; - } - - ctx.enc_context = PK11_CreateContextBySymKey(cipher_mech, operation, - ctx.sym_key, ctx.sec_param); - if (ctx.enc_context == NULL) { - purple_debug_error("cipher-aes", - "PK11_CreateContextBySymKey failed: %d\n", - PR_GetError()); - purple_aes_encrypt_nss_context_cleanup(&ctx); - return FALSE; - } - - ret = PK11_CipherOp(ctx.enc_context, output, &outlen, len, input, len); - if (ret != SECSuccess) { - purple_debug_error("cipher-aes", - "PK11_CipherOp failed: %d\n", PR_GetError()); - purple_aes_encrypt_nss_context_cleanup(&ctx); - return FALSE; - } - - ret = PK11_DigestFinal(ctx.enc_context, output + outlen, &outlen_tmp, - len - outlen); - if (ret != SECSuccess) { - purple_debug_error("cipher-aes", - "PK11_DigestFinal failed: %d\n", PR_GetError()); - purple_aes_encrypt_nss_context_cleanup(&ctx); - return FALSE; - } - - purple_aes_encrypt_nss_context_cleanup(&ctx); - - outlen += outlen_tmp; - if (outlen != len) { - purple_debug_error("cipher-aes", - "resulting length doesn't match: %d (expected: %d)\n", - outlen, len); - return FALSE; - } - - return TRUE; -} - -static gboolean -purple_aes_encrypt_nss(const guchar *input, guchar *output, size_t len, - guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size) -{ - return purple_aes_crypt_nss(input, output, len, iv, key, key_size, - CKA_ENCRYPT); -} - -static gboolean -purple_aes_decrypt_nss(const guchar *input, guchar *output, size_t len, - guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size) -{ - return purple_aes_crypt_nss(input, output, len, iv, key, key_size, - CKA_DECRYPT); -} - -#endif /* PURPLE_AES_USE_NSS */ - -static ssize_t -purple_aes_encrypt(PurpleCipherContext *context, const guchar input[], - size_t in_len, guchar output[], size_t out_size) -{ - AESContext *ctx_data = purple_cipher_context_get_data(context); - purple_aes_crypt_func encrypt_func; - guchar *input_padded; - size_t out_len = 0; - gboolean succ; - - if (ctx_data->failure) - return -1; - - input_padded = purple_aes_pad_pkcs7(input, in_len, &out_len); - - if (out_len > out_size) { - purple_debug_error("cipher-aes", "Output buffer too small\n"); - memset(input_padded, 0, out_len); - g_free(input_padded); - return -1; - } - -#if defined(PURPLE_AES_USE_GNUTLS) - encrypt_func = purple_aes_encrypt_gnutls; -#elif defined(PURPLE_AES_USE_NSS) - encrypt_func = purple_aes_encrypt_nss; -#else -# error "No matching encrypt_func" -#endif - - succ = encrypt_func(input_padded, output, out_len, ctx_data->iv, - ctx_data->key, ctx_data->key_size); - - memset(input_padded, 0, out_len); - g_free(input_padded); - - if (!succ) { - memset(output, 0, out_len); - return -1; - } - - return out_len; -} - -static ssize_t -purple_aes_decrypt(PurpleCipherContext *context, const guchar input[], - size_t in_len, guchar output[], size_t out_size) -{ - AESContext *ctx_data = purple_cipher_context_get_data(context); - purple_aes_crypt_func decrypt_func; - gboolean succ; - ssize_t out_len; - - if (ctx_data->failure) - return -1; - - if (in_len > out_size) { - purple_debug_error("cipher-aes", "Output buffer too small\n"); - return -1; - } - - if ((in_len % PURPLE_AES_BLOCK_SIZE) != 0 || in_len == 0) { - purple_debug_error("cipher-aes", "Malformed data\n"); - return -1; - } - -#if defined(PURPLE_AES_USE_GNUTLS) - decrypt_func = purple_aes_decrypt_gnutls; -#elif defined(PURPLE_AES_USE_NSS) - decrypt_func = purple_aes_decrypt_nss; -#else -# error "No matching encrypt_func" -#endif - - succ = decrypt_func(input, output, in_len, ctx_data->iv, ctx_data->key, - ctx_data->key_size); - - if (!succ) { - memset(output, 0, in_len); - return -1; - } - - out_len = purple_aes_unpad_pkcs7(output, in_len); - if (out_len < 0) { - memset(output, 0, in_len); - return -1; - } - - return out_len; -} - -static size_t -purple_aes_get_key_size(PurpleCipherContext *context) -{ - AESContext *ctx_data = purple_cipher_context_get_data(context); - - return ctx_data->key_size; -} - -static void -purple_aes_set_batch_mode(PurpleCipherContext *context, - PurpleCipherBatchMode mode) -{ - AESContext *ctx_data = purple_cipher_context_get_data(context); - - if (mode == PURPLE_CIPHER_BATCH_MODE_CBC) - return; - - purple_debug_error("cipher-aes", "unsupported batch mode\n"); - ctx_data->failure = TRUE; -} - -static PurpleCipherBatchMode -purple_aes_get_batch_mode(PurpleCipherContext *context) -{ - return PURPLE_CIPHER_BATCH_MODE_CBC; -} - -static size_t -purple_aes_get_block_size(PurpleCipherContext *context) -{ - return PURPLE_AES_BLOCK_SIZE; -} - -static PurpleCipherOps AESOps = { - purple_aes_set_option, /* set_option */ - NULL, /* get_option */ - purple_aes_init, /* init */ - purple_aes_reset, /* reset */ - NULL, /* reset_state */ - purple_aes_uninit, /* uninit */ - purple_aes_set_iv, /* set_iv */ - NULL, /* append */ - NULL, /* digest */ - NULL, /* get_digest_size */ - purple_aes_encrypt, /* encrypt */ - purple_aes_decrypt, /* decrypt */ - NULL, /* set_salt */ - NULL, /* get_salt_size */ - purple_aes_set_key, /* set_key */ - purple_aes_get_key_size, /* get_key_size */ - purple_aes_set_batch_mode, /* set_batch_mode */ - purple_aes_get_batch_mode, /* get_batch_mode */ - purple_aes_get_block_size, /* get_block_size */ - NULL, NULL, NULL, NULL /* reserved */ -}; - -PurpleCipherOps * -purple_aes_cipher_get_ops(void) { - return &AESOps; -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/ciphers/aescipher.c Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,658 @@ +/* + * 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 + * + * Written by Tomek Wasilczyk <tomkiewicz@cpw.pidgin.im> + */ + +#include "aescipher.h" +#include "debug.h" + +#include <string.h> + +#if defined(HAVE_GNUTLS) +# define PURPLE_AES_USE_GNUTLS 1 +# include <gnutls/gnutls.h> +# include <gnutls/crypto.h> +#elif defined(HAVE_NSS) +# define PURPLE_AES_USE_NSS 1 +# include <nss.h> +# include <pk11pub.h> +# include <prerror.h> +#else +# error "No GnuTLS or NSS support" +#endif + +/* 128bit */ +#define PURPLE_AES_BLOCK_SIZE 16 + +/****************************************************************************** + * Structs + *****************************************************************************/ +#define PURPLE_AES_CIPHER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_AES_CIPHER, PurpleAESCipherPrivate)) + +typedef struct { + guchar iv[PURPLE_AES_BLOCK_SIZE]; + guchar key[32]; + guint key_size; + gboolean failure; +} PurpleAESCipherPrivate; + +/****************************************************************************** + * Enums + *****************************************************************************/ +enum { + PROP_NONE, + PROP_BATCH_MODE, + PROP_IV, + PROP_KEY, + PROP_LAST, +}; + +/****************************************************************************** + * Cipher Stuff + *****************************************************************************/ + +typedef gboolean (*purple_aes_cipher_crypt_func)( + const guchar *input, guchar *output, size_t len, + guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size); + +static void +purple_aes_cipher_reset(PurpleCipher *cipher) +{ + PurpleAESCipherPrivate *priv = PURPLE_AES_CIPHER_GET_PRIVATE(cipher); + + g_return_if_fail(priv != NULL); + + memset(priv->iv, 0, sizeof(priv->iv)); + memset(priv->key, 0, sizeof(priv->key)); + priv->key_size = 32; /* 256bit */ + priv->failure = FALSE; +} + +static void +purple_aes_cipher_set_iv(PurpleCipher *cipher, guchar *iv, size_t len) +{ + PurpleAESCipherPrivate *priv = PURPLE_AES_CIPHER_GET_PRIVATE(cipher); + + if ((len > 0 && iv == NULL) || + (len != 0 && len != sizeof(priv->iv))) { + purple_debug_error("cipher-aes", "invalid IV length\n"); + priv->failure = TRUE; + return; + } + + if (len == 0) + memset(priv->iv, 0, sizeof(priv->iv)); + else + memcpy(priv->iv, iv, len); + + g_object_notify(G_OBJECT(cipher), "iv"); +} + +static void +purple_aes_cipher_set_key(PurpleCipher *cipher, const guchar *key, size_t len) +{ + PurpleAESCipherPrivate *priv = PURPLE_AES_CIPHER_GET_PRIVATE(cipher); + + if ((len > 0 && key == NULL) || + (len != 0 && len != 16 && len != 24 && len != 32)) { + purple_debug_error("cipher-aes", "invalid key length\n"); + priv->failure = TRUE; + return; + } + + priv->key_size = len; + memset(priv->key, 0, sizeof(priv->key)); + if (len > 0) + memcpy(priv->key, key, len); + + g_object_notify(G_OBJECT(cipher), "key"); +} + +static guchar * +purple_aes_cipher_pad_pkcs7(const guchar input[], size_t in_len, size_t *out_len) +{ + int padding_len, total_len; + guchar *padded; + + g_return_val_if_fail(input != NULL, NULL); + g_return_val_if_fail(out_len != NULL, NULL); + + padding_len = PURPLE_AES_BLOCK_SIZE - (in_len % PURPLE_AES_BLOCK_SIZE); + total_len = in_len + padding_len; + g_assert((total_len % PURPLE_AES_BLOCK_SIZE) == 0); + + padded = g_new(guchar, total_len); + *out_len = total_len; + + memcpy(padded, input, in_len); + memset(padded + in_len, padding_len, padding_len); + + return padded; +} + +static ssize_t +purple_aes_cipher_unpad_pkcs7(guchar input[], size_t in_len) +{ + int padding_len, i; + size_t out_len; + + g_return_val_if_fail(input != NULL, -1); + g_return_val_if_fail(in_len > 0, -1); + + padding_len = input[in_len - 1]; + if (padding_len <= 0 || padding_len > PURPLE_AES_BLOCK_SIZE || + padding_len > in_len) { + purple_debug_warning("cipher-aes", + "Invalid padding length: %d (total %lu) - " + "most probably, the key was invalid\n", + padding_len, in_len); + return -1; + } + + out_len = in_len - padding_len; + for (i = 0; i < padding_len; i++) { + if (input[out_len + i] != padding_len) { + purple_debug_warning("cipher-aes", + "Padding doesn't match at pos %d (found %02x, " + "expected %02x) - " + "most probably, the key was invalid\n", + i, input[out_len + i], padding_len); + return -1; + } + } + + memset(input + out_len, 0, padding_len); + return out_len; +} + +#ifdef PURPLE_AES_USE_GNUTLS + +static gnutls_cipher_hd_t +purple_aes_cipher_gnutls_crypt_init(guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], + guint key_size) +{ + gnutls_cipher_hd_t handle; + gnutls_cipher_algorithm_t algorithm; + gnutls_datum_t key_info, iv_info; + int ret; + + if (key_size == 16) + algorithm = GNUTLS_CIPHER_AES_128_CBC; + else if (key_size == 24) + algorithm = GNUTLS_CIPHER_AES_192_CBC; + else if (key_size == 32) + algorithm = GNUTLS_CIPHER_AES_256_CBC; + else + g_return_val_if_reached(NULL); + + key_info.data = key; + key_info.size = key_size; + + iv_info.data = iv; + iv_info.size = PURPLE_AES_BLOCK_SIZE; + + ret = gnutls_cipher_init(&handle, algorithm, &key_info, &iv_info); + if (ret != 0) { + purple_debug_error("cipher-aes", + "gnutls_cipher_init failed: %d\n", ret); + return NULL; + } + + return handle; +} + +static gboolean +purple_aes_cipher_gnutls_encrypt(const guchar *input, guchar *output, size_t len, + guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size) +{ + gnutls_cipher_hd_t handle; + int ret; + + handle = purple_aes_cipher_gnutls_crypt_init(iv, key, key_size); + if (handle == NULL) + return FALSE; + + ret = gnutls_cipher_encrypt2(handle, (guchar *) input, len, output, len); + gnutls_cipher_deinit(handle); + + if (ret != 0) { + purple_debug_error("cipher-aes", + "gnutls_cipher_encrypt2 failed: %d\n", ret); + return FALSE; + } + + return TRUE; +} + +static gboolean +purple_aes_cipher_gnutls_decrypt(const guchar *input, guchar *output, size_t len, + guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size) +{ + gnutls_cipher_hd_t handle; + int ret; + + handle = purple_aes_cipher_gnutls_crypt_init(iv, key, key_size); + if (handle == NULL) + return FALSE; + + ret = gnutls_cipher_decrypt2(handle, input, len, output, len); + gnutls_cipher_deinit(handle); + + if (ret != 0) { + purple_debug_error("cipher-aes", + "gnutls_cipher_decrypt2 failed: %d\n", ret); + return FALSE; + } + + return TRUE; +} + +#endif /* PURPLE_AES_USE_GNUTLS */ + +#ifdef PURPLE_AES_USE_NSS + +typedef struct { + PK11SlotInfo *slot; + PK11SymKey *sym_key; + SECItem *sec_param; + PK11Context *enc_context; +} PurpleAESCipherNSSContext; + +static void +purple_aes_cipher_nss_cleanup(PurpleAESCipherNSSContext *context) +{ + g_return_if_fail(context != NULL); + + if (context->enc_context != NULL) + PK11_DestroyContext(context->enc_context, TRUE); + if (context->sec_param != NULL) + SECITEM_FreeItem(context->sec_param, TRUE); + if (context->sym_key != NULL) + PK11_FreeSymKey(context->sym_key); + if (context->slot != NULL) + PK11_FreeSlot(context->slot); + + memset(context, 0, sizeof(PurpleAESCipherNSSContext)); +} + +static gboolean +purple_aes_cipher_nss_crypt(const guchar *input, guchar *output, size_t len, + guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size, + CK_ATTRIBUTE_TYPE operation) +{ + PurpleAESCipherNSSContext context; + CK_MECHANISM_TYPE cipher_mech = CKM_AES_CBC; + SECItem key_item, iv_item; + SECStatus ret; + int outlen = 0; + unsigned int outlen_tmp = 0; + + memset(&context, 0, sizeof(PurpleAESCipherNSSContext)); + + if (NSS_NoDB_Init(NULL) != SECSuccess) { + purple_debug_error("cipher-aes", + "NSS_NoDB_Init failed: %d\n", PR_GetError()); + return FALSE; + } + + context.slot = PK11_GetBestSlot(cipher_mech, NULL); + if (context.slot == NULL) { + purple_debug_error("cipher-aes", + "PK11_GetBestSlot failed: %d\n", PR_GetError()); + return FALSE; + } + + key_item.type = siBuffer; + key_item.data = key; + key_item.len = key_size; + context.sym_key = PK11_ImportSymKey(context.slot, cipher_mech, + PK11_OriginUnwrap, CKA_ENCRYPT, &key_item, NULL); + if (context.sym_key == NULL) { + purple_debug_error("cipher-aes", + "PK11_ImportSymKey failed: %d\n", PR_GetError()); + purple_aes_cipher_nss_cleanup(&context); + return FALSE; + } + + iv_item.type = siBuffer; + iv_item.data = iv; + iv_item.len = PURPLE_AES_BLOCK_SIZE; + context.sec_param = PK11_ParamFromIV(cipher_mech, &iv_item); + if (context.sec_param == NULL) { + purple_debug_error("cipher-aes", + "PK11_ParamFromIV failed: %d\n", PR_GetError()); + purple_aes_cipher_nss_cleanup(&context); + return FALSE; + } + + context.enc_context = PK11_CreateContextBySymKey(cipher_mech, operation, + context.sym_key, context.sec_param); + if (context.enc_context == NULL) { + purple_debug_error("cipher-aes", + "PK11_CreateContextBySymKey failed: %d\n", + PR_GetError()); + purple_aes_cipher_nss_cleanup(&context); + return FALSE; + } + + ret = PK11_CipherOp(context.enc_context, output, &outlen, len, input, len); + if (ret != SECSuccess) { + purple_debug_error("cipher-aes", + "PK11_CipherOp failed: %d\n", PR_GetError()); + purple_aes_cipher_nss_cleanup(&context); + return FALSE; + } + + ret = PK11_DigestFinal(context.enc_context, output + outlen, &outlen_tmp, + len - outlen); + if (ret != SECSuccess) { + purple_debug_error("cipher-aes", + "PK11_DigestFinal failed: %d\n", PR_GetError()); + purple_aes_cipher_nss_cleanup(&context); + return FALSE; + } + + purple_aes_cipher_nss_cleanup(&context); + + outlen += outlen_tmp; + if (outlen != len) { + purple_debug_error("cipher-aes", + "resulting length doesn't match: %d (expected: %lu)\n", + outlen, len); + return FALSE; + } + + return TRUE; +} + +static gboolean +purple_aes_cipher_nss_encrypt(const guchar *input, guchar *output, size_t len, + guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size) +{ + return purple_aes_cipher_nss_crypt(input, output, len, iv, key, key_size, + CKA_ENCRYPT); +} + +static gboolean +purple_aes_cipher_nss_decrypt(const guchar *input, guchar *output, size_t len, + guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size) +{ + return purple_aes_cipher_nss_crypt(input, output, len, iv, key, key_size, + CKA_DECRYPT); +} + +#endif /* PURPLE_AES_USE_NSS */ + +static ssize_t +purple_aes_cipher_encrypt(PurpleCipher *cipher, const guchar input[], + size_t in_len, guchar output[], size_t out_size) +{ + PurpleAESCipherPrivate *priv = PURPLE_AES_CIPHER_GET_PRIVATE(cipher); + purple_aes_cipher_crypt_func encrypt_func; + guchar *input_padded; + size_t out_len = 0; + gboolean succ; + + if (priv->failure) + return -1; + + input_padded = purple_aes_cipher_pad_pkcs7(input, in_len, &out_len); + + if (out_len > out_size) { + purple_debug_error("cipher-aes", "Output buffer too small\n"); + memset(input_padded, 0, out_len); + g_free(input_padded); + return -1; + } + +#if defined(PURPLE_AES_USE_GNUTLS) + encrypt_func = purple_aes_cipher_gnutls_encrypt; +#elif defined(PURPLE_AES_USE_NSS) + encrypt_func = purple_aes_cipher_nss_encrypt; +#else +# error "No matching encrypt_func" +#endif + + succ = encrypt_func(input_padded, output, out_len, priv->iv, + priv->key, priv->key_size); + + memset(input_padded, 0, out_len); + g_free(input_padded); + + if (!succ) { + memset(output, 0, out_len); + return -1; + } + + return out_len; +} + +static ssize_t +purple_aes_cipher_decrypt(PurpleCipher *cipher, const guchar input[], + size_t in_len, guchar output[], size_t out_size) +{ + PurpleAESCipherPrivate *priv = PURPLE_AES_CIPHER_GET_PRIVATE(cipher); + purple_aes_cipher_crypt_func decrypt_func; + gboolean succ; + ssize_t out_len; + + if (priv->failure) + return -1; + + if (in_len > out_size) { + purple_debug_error("cipher-aes", "Output buffer too small\n"); + return -1; + } + + if ((in_len % PURPLE_AES_BLOCK_SIZE) != 0 || in_len == 0) { + purple_debug_error("cipher-aes", "Malformed data\n"); + return -1; + } + +#if defined(PURPLE_AES_USE_GNUTLS) + decrypt_func = purple_aes_cipher_gnutls_decrypt; +#elif defined(PURPLE_AES_USE_NSS) + decrypt_func = purple_aes_cipher_nss_decrypt; +#else +# error "No matching encrypt_func" +#endif + + succ = decrypt_func(input, output, in_len, priv->iv, priv->key, + priv->key_size); + + if (!succ) { + memset(output, 0, in_len); + return -1; + } + + out_len = purple_aes_cipher_unpad_pkcs7(output, in_len); + if (out_len < 0) { + memset(output, 0, in_len); + return -1; + } + + return out_len; +} + +static size_t +purple_aes_cipher_get_key_size(PurpleCipher *cipher) +{ + PurpleAESCipherPrivate *priv = PURPLE_AES_CIPHER_GET_PRIVATE(cipher); + + return priv->key_size; +} + +static void +purple_aes_cipher_set_batch_mode(PurpleCipher *cipher, + PurpleCipherBatchMode mode) +{ + PurpleAESCipherPrivate *priv = PURPLE_AES_CIPHER_GET_PRIVATE(cipher); + + if (mode == PURPLE_CIPHER_BATCH_MODE_CBC) { + g_object_notify(G_OBJECT(cipher), "batch_mode"); + return; + } + + purple_debug_error("cipher-aes", "unsupported batch mode\n"); + priv->failure = TRUE; +} + +static PurpleCipherBatchMode +purple_aes_cipher_get_batch_mode(PurpleCipher *cipher) +{ + return PURPLE_CIPHER_BATCH_MODE_CBC; +} + +static size_t +purple_aes_cipher_get_block_size(PurpleCipher *cipher) +{ + return PURPLE_AES_BLOCK_SIZE; +} + +static const gchar* +purple_aes_cipher_get_name(PurpleCipher *cipher) +{ + return "aes"; +} + +/****************************************************************************** + * Object Stuff + *****************************************************************************/ +static void +purple_aes_cipher_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleCipher *cipher = PURPLE_CIPHER(obj); + + switch(param_id) { + case PROP_BATCH_MODE: + g_value_set_enum(value, + purple_cipher_get_batch_mode(cipher)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_aes_cipher_set_property(GObject *obj, guint param_id, + const GValue *value, GParamSpec *pspec) +{ + PurpleCipher *cipher = PURPLE_CIPHER(obj); + + switch(param_id) { + case PROP_BATCH_MODE: + purple_cipher_set_batch_mode(cipher, + g_value_get_enum(value)); + break; + case PROP_IV: + { + guchar *iv = (guchar *)g_value_get_string(value); + purple_cipher_set_iv(cipher, iv, strlen((gchar*)iv)); + } + break; + case PROP_KEY: + purple_cipher_set_key(cipher, (guchar *)g_value_get_string(value), + purple_aes_cipher_get_key_size(cipher)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_aes_cipher_class_init(PurpleAESCipherClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + PurpleCipherClass *cipher_class = PURPLE_CIPHER_CLASS(klass); + GParamSpec *pspec; + + obj_class->get_property = purple_aes_cipher_get_property; + obj_class->set_property = purple_aes_cipher_set_property; + + cipher_class->reset = purple_aes_cipher_reset; + cipher_class->set_iv = purple_aes_cipher_set_iv; + cipher_class->encrypt = purple_aes_cipher_encrypt; + cipher_class->decrypt = purple_aes_cipher_decrypt; + cipher_class->set_key = purple_aes_cipher_set_key; + cipher_class->get_key_size = purple_aes_cipher_get_key_size; + cipher_class->set_batch_mode = purple_aes_cipher_set_batch_mode; + cipher_class->get_batch_mode = purple_aes_cipher_get_batch_mode; + cipher_class->get_block_size = purple_aes_cipher_get_block_size; + cipher_class->get_name = purple_aes_cipher_get_name; + + pspec = g_param_spec_enum("batch_mode", "batch_mode", "batch_mode", + PURPLE_TYPE_CIPHER_BATCH_MODE, 0, + G_PARAM_READWRITE); + g_object_class_install_property(obj_class, PROP_BATCH_MODE, pspec); + + pspec = g_param_spec_string("iv", "iv", "iv", NULL, + G_PARAM_WRITABLE); + g_object_class_install_property(obj_class, PROP_IV, pspec); + + pspec = g_param_spec_string("key", "key", "key", NULL, + G_PARAM_WRITABLE); + g_object_class_install_property(obj_class, PROP_KEY, pspec); + + g_type_class_add_private(klass, sizeof(PurpleAESCipherPrivate)); +} + +static void +purple_aes_cipher_init(PurpleCipher *cipher) { + purple_cipher_reset(cipher); +} + +/****************************************************************************** + * API + *****************************************************************************/ +GType +purple_aes_cipher_get_gtype(void) { + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleAESCipherClass), + NULL, + NULL, + (GClassInitFunc)purple_aes_cipher_class_init, + NULL, + NULL, + sizeof(PurpleAESCipher), + 0, + (GInstanceInitFunc)purple_aes_cipher_init, + NULL + }; + + type = g_type_register_static(PURPLE_TYPE_CIPHER, + "PurpleAESCipher", + &info, 0); + } + + return type; +} + +PurpleCipher * +purple_aes_cipher_new(void) { + return g_object_new(PURPLE_TYPE_AES_CIPHER, NULL); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/ciphers/aescipher.h Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,67 @@ +/** + * @file aes.h Purple AES Cipher + * @ingroup core + */ + +/* 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 + */ +#ifndef PURPLE_AES_CIPHER_H +#define PURPLE_AES_CIPHER_H + +#include "cipher.h" + +#define PURPLE_TYPE_AES_CIPHER (purple_aes_cipher_get_gtype()) +#define PURPLE_AES_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_AES_CIPHER, PurpleAESCipher)) +#define PURPLE_AES_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_AES_CIPHER, PurpleAESCipherClass)) +#define PURPLE_IS_AES_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_AES_CIPHER)) +#define PURPLE_IS_AES_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_AES_CIPHER)) +#define PURPLE_AES_CIPHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_AES_CIPHER, PurpleAESCipherClass)) + +typedef struct _PurpleAESCipher PurpleAESCipher; +typedef struct _PurpleAESCipherClass PurpleAESCipherClass; + +struct _PurpleAESCipher { + PurpleCipher gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +struct _PurpleAESCipherClass { + PurpleCipherClass gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType purple_aes_cipher_get_gtype(void); + +PurpleCipher *purple_aes_cipher_new(void); + +G_END_DECLS + +#endif /* PURPLE_AES_CIPHER_H */
--- a/libpurple/ciphers/ciphers.h Sun Jun 23 02:43:06 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* 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 - */ - -/* aes.c */ -PurpleCipherOps * purple_aes_cipher_get_ops(void); - -/* des.c */ -PurpleCipherOps * purple_des_cipher_get_ops(void); -PurpleCipherOps * purple_des3_cipher_get_ops(void); - -/* gchecksum.c */ -PurpleCipherOps * purple_md5_cipher_get_ops(void); -PurpleCipherOps * purple_sha1_cipher_get_ops(void); -PurpleCipherOps * purple_sha256_cipher_get_ops(void); - -/* hmac.c */ -PurpleCipherOps * purple_hmac_cipher_get_ops(void); - -/* md4.c */ -PurpleCipherOps * purple_md4_cipher_get_ops(void); - -/* pbkdf2.c */ -PurpleCipherOps * purple_pbkdf2_cipher_get_ops(void); - -/* rc4.c */ -PurpleCipherOps * purple_rc4_cipher_get_ops(void); - -static inline void purple_ciphers_register_all(void) -{ -#if defined(HAVE_GNUTLS) || defined(HAVE_NSS) - purple_ciphers_register_cipher("aes", purple_aes_cipher_get_ops()); -#endif - - purple_ciphers_register_cipher("des", purple_des_cipher_get_ops()); - purple_ciphers_register_cipher("des3", purple_des3_cipher_get_ops()); - - purple_ciphers_register_cipher("md5", purple_md5_cipher_get_ops()); - purple_ciphers_register_cipher("sha1", purple_sha1_cipher_get_ops()); - purple_ciphers_register_cipher("sha256", purple_sha256_cipher_get_ops()); - - purple_ciphers_register_cipher("hmac", purple_hmac_cipher_get_ops()); - - purple_ciphers_register_cipher("md4", purple_md4_cipher_get_ops()); - - purple_ciphers_register_cipher("pbkdf2", purple_pbkdf2_cipher_get_ops()); - - purple_ciphers_register_cipher("rc4", purple_rc4_cipher_get_ops()); -}
--- a/libpurple/ciphers/des.c Sun Jun 23 02:43:06 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,897 +0,0 @@ -/* - * 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. - * - * Original des taken from gpg - * - * des.c - DES and Triple-DES encryption/decryption Algorithm - * Copyright (C) 1998 Free Software Foundation, Inc. - * - * Please see below for more legal information! - * - * According to the definition of DES in FIPS PUB 46-2 from December 1993. - * For a description of triple encryption, see: - * Bruce Schneier: Applied Cryptography. Second Edition. - * John Wiley & Sons, 1996. ISBN 0-471-12845-7. Pages 358 ff. - * - * This file is part of GnuPG. - * - * 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 "internal.h" -#include <cipher.h> -#include "ciphers.h" - -/****************************************************************************** - * DES - *****************************************************************************/ -typedef struct _des_ctx -{ - guint32 encrypt_subkeys[32]; - guint32 decrypt_subkeys[32]; -} des_ctx[1]; - -/* - * The s-box values are permuted according to the 'primitive function P' - */ -static const guint32 sbox1[64] = -{ - 0x00808200, 0x00000000, 0x00008000, 0x00808202, 0x00808002, 0x00008202, 0x00000002, 0x00008000, - 0x00000200, 0x00808200, 0x00808202, 0x00000200, 0x00800202, 0x00808002, 0x00800000, 0x00000002, - 0x00000202, 0x00800200, 0x00800200, 0x00008200, 0x00008200, 0x00808000, 0x00808000, 0x00800202, - 0x00008002, 0x00800002, 0x00800002, 0x00008002, 0x00000000, 0x00000202, 0x00008202, 0x00800000, - 0x00008000, 0x00808202, 0x00000002, 0x00808000, 0x00808200, 0x00800000, 0x00800000, 0x00000200, - 0x00808002, 0x00008000, 0x00008200, 0x00800002, 0x00000200, 0x00000002, 0x00800202, 0x00008202, - 0x00808202, 0x00008002, 0x00808000, 0x00800202, 0x00800002, 0x00000202, 0x00008202, 0x00808200, - 0x00000202, 0x00800200, 0x00800200, 0x00000000, 0x00008002, 0x00008200, 0x00000000, 0x00808002 -}; - -static const guint32 sbox2[64] = -{ - 0x40084010, 0x40004000, 0x00004000, 0x00084010, 0x00080000, 0x00000010, 0x40080010, 0x40004010, - 0x40000010, 0x40084010, 0x40084000, 0x40000000, 0x40004000, 0x00080000, 0x00000010, 0x40080010, - 0x00084000, 0x00080010, 0x40004010, 0x00000000, 0x40000000, 0x00004000, 0x00084010, 0x40080000, - 0x00080010, 0x40000010, 0x00000000, 0x00084000, 0x00004010, 0x40084000, 0x40080000, 0x00004010, - 0x00000000, 0x00084010, 0x40080010, 0x00080000, 0x40004010, 0x40080000, 0x40084000, 0x00004000, - 0x40080000, 0x40004000, 0x00000010, 0x40084010, 0x00084010, 0x00000010, 0x00004000, 0x40000000, - 0x00004010, 0x40084000, 0x00080000, 0x40000010, 0x00080010, 0x40004010, 0x40000010, 0x00080010, - 0x00084000, 0x00000000, 0x40004000, 0x00004010, 0x40000000, 0x40080010, 0x40084010, 0x00084000 -}; - -static const guint32 sbox3[64] = -{ - 0x00000104, 0x04010100, 0x00000000, 0x04010004, 0x04000100, 0x00000000, 0x00010104, 0x04000100, - 0x00010004, 0x04000004, 0x04000004, 0x00010000, 0x04010104, 0x00010004, 0x04010000, 0x00000104, - 0x04000000, 0x00000004, 0x04010100, 0x00000100, 0x00010100, 0x04010000, 0x04010004, 0x00010104, - 0x04000104, 0x00010100, 0x00010000, 0x04000104, 0x00000004, 0x04010104, 0x00000100, 0x04000000, - 0x04010100, 0x04000000, 0x00010004, 0x00000104, 0x00010000, 0x04010100, 0x04000100, 0x00000000, - 0x00000100, 0x00010004, 0x04010104, 0x04000100, 0x04000004, 0x00000100, 0x00000000, 0x04010004, - 0x04000104, 0x00010000, 0x04000000, 0x04010104, 0x00000004, 0x00010104, 0x00010100, 0x04000004, - 0x04010000, 0x04000104, 0x00000104, 0x04010000, 0x00010104, 0x00000004, 0x04010004, 0x00010100 -}; - -static const guint32 sbox4[64] = -{ - 0x80401000, 0x80001040, 0x80001040, 0x00000040, 0x00401040, 0x80400040, 0x80400000, 0x80001000, - 0x00000000, 0x00401000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00400040, 0x80400000, - 0x80000000, 0x00001000, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x80001000, 0x00001040, - 0x80400040, 0x80000000, 0x00001040, 0x00400040, 0x00001000, 0x00401040, 0x80401040, 0x80000040, - 0x00400040, 0x80400000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00000000, 0x00401000, - 0x00001040, 0x00400040, 0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x00000040, - 0x80401040, 0x80000040, 0x80000000, 0x00001000, 0x80400000, 0x80001000, 0x00401040, 0x80400040, - 0x80001000, 0x00001040, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x00001000, 0x00401040 -}; - -static const guint32 sbox5[64] = -{ - 0x00000080, 0x01040080, 0x01040000, 0x21000080, 0x00040000, 0x00000080, 0x20000000, 0x01040000, - 0x20040080, 0x00040000, 0x01000080, 0x20040080, 0x21000080, 0x21040000, 0x00040080, 0x20000000, - 0x01000000, 0x20040000, 0x20040000, 0x00000000, 0x20000080, 0x21040080, 0x21040080, 0x01000080, - 0x21040000, 0x20000080, 0x00000000, 0x21000000, 0x01040080, 0x01000000, 0x21000000, 0x00040080, - 0x00040000, 0x21000080, 0x00000080, 0x01000000, 0x20000000, 0x01040000, 0x21000080, 0x20040080, - 0x01000080, 0x20000000, 0x21040000, 0x01040080, 0x20040080, 0x00000080, 0x01000000, 0x21040000, - 0x21040080, 0x00040080, 0x21000000, 0x21040080, 0x01040000, 0x00000000, 0x20040000, 0x21000000, - 0x00040080, 0x01000080, 0x20000080, 0x00040000, 0x00000000, 0x20040000, 0x01040080, 0x20000080 -}; - -static const guint32 sbox6[64] = -{ - 0x10000008, 0x10200000, 0x00002000, 0x10202008, 0x10200000, 0x00000008, 0x10202008, 0x00200000, - 0x10002000, 0x00202008, 0x00200000, 0x10000008, 0x00200008, 0x10002000, 0x10000000, 0x00002008, - 0x00000000, 0x00200008, 0x10002008, 0x00002000, 0x00202000, 0x10002008, 0x00000008, 0x10200008, - 0x10200008, 0x00000000, 0x00202008, 0x10202000, 0x00002008, 0x00202000, 0x10202000, 0x10000000, - 0x10002000, 0x00000008, 0x10200008, 0x00202000, 0x10202008, 0x00200000, 0x00002008, 0x10000008, - 0x00200000, 0x10002000, 0x10000000, 0x00002008, 0x10000008, 0x10202008, 0x00202000, 0x10200000, - 0x00202008, 0x10202000, 0x00000000, 0x10200008, 0x00000008, 0x00002000, 0x10200000, 0x00202008, - 0x00002000, 0x00200008, 0x10002008, 0x00000000, 0x10202000, 0x10000000, 0x00200008, 0x10002008 -}; - -static const guint32 sbox7[64] = -{ - 0x00100000, 0x02100001, 0x02000401, 0x00000000, 0x00000400, 0x02000401, 0x00100401, 0x02100400, - 0x02100401, 0x00100000, 0x00000000, 0x02000001, 0x00000001, 0x02000000, 0x02100001, 0x00000401, - 0x02000400, 0x00100401, 0x00100001, 0x02000400, 0x02000001, 0x02100000, 0x02100400, 0x00100001, - 0x02100000, 0x00000400, 0x00000401, 0x02100401, 0x00100400, 0x00000001, 0x02000000, 0x00100400, - 0x02000000, 0x00100400, 0x00100000, 0x02000401, 0x02000401, 0x02100001, 0x02100001, 0x00000001, - 0x00100001, 0x02000000, 0x02000400, 0x00100000, 0x02100400, 0x00000401, 0x00100401, 0x02100400, - 0x00000401, 0x02000001, 0x02100401, 0x02100000, 0x00100400, 0x00000000, 0x00000001, 0x02100401, - 0x00000000, 0x00100401, 0x02100000, 0x00000400, 0x02000001, 0x02000400, 0x00000400, 0x00100001 -}; - -static const guint32 sbox8[64] = -{ - 0x08000820, 0x00000800, 0x00020000, 0x08020820, 0x08000000, 0x08000820, 0x00000020, 0x08000000, - 0x00020020, 0x08020000, 0x08020820, 0x00020800, 0x08020800, 0x00020820, 0x00000800, 0x00000020, - 0x08020000, 0x08000020, 0x08000800, 0x00000820, 0x00020800, 0x00020020, 0x08020020, 0x08020800, - 0x00000820, 0x00000000, 0x00000000, 0x08020020, 0x08000020, 0x08000800, 0x00020820, 0x00020000, - 0x00020820, 0x00020000, 0x08020800, 0x00000800, 0x00000020, 0x08020020, 0x00000800, 0x00020820, - 0x08000800, 0x00000020, 0x08000020, 0x08020000, 0x08020020, 0x08000000, 0x00020000, 0x08000820, - 0x00000000, 0x08020820, 0x00020020, 0x08000020, 0x08020000, 0x08000800, 0x08000820, 0x00000000, - 0x08020820, 0x00020800, 0x00020800, 0x00000820, 0x00000820, 0x00020020, 0x08000000, 0x08020800 -}; - - -/* - * * These two tables are part of the 'permuted choice 1' function. - * * In this implementation several speed improvements are done. - * */ -static const guint32 leftkey_swap[16] = -{ - 0x00000000, 0x00000001, 0x00000100, 0x00000101, - 0x00010000, 0x00010001, 0x00010100, 0x00010101, - 0x01000000, 0x01000001, 0x01000100, 0x01000101, - 0x01010000, 0x01010001, 0x01010100, 0x01010101 -}; - -static const guint32 rightkey_swap[16] = -{ - 0x00000000, 0x01000000, 0x00010000, 0x01010000, - 0x00000100, 0x01000100, 0x00010100, 0x01010100, - 0x00000001, 0x01000001, 0x00010001, 0x01010001, - 0x00000101, 0x01000101, 0x00010101, 0x01010101, -}; - - -/* - * Numbers of left shifts per round for encryption subkey schedule - * To calculate the decryption key scheduling we just reverse the - * ordering of the subkeys so we can omit the table for decryption - * subkey schedule. - */ -static const guint8 encrypt_rotate_tab[16] = -{ - 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 -}; - -/* - * Macro to swap bits across two words - **/ -#define DO_PERMUTATION(a, temp, b, offset, mask) \ - temp = ((a>>offset) ^ b) & mask; \ - b ^= temp; \ - a ^= temp<<offset; - - -/* - * This performs the 'initial permutation' for the data to be encrypted or decrypted - **/ -#define INITIAL_PERMUTATION(left, temp, right) \ - DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) \ - DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ - DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ - DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ - DO_PERMUTATION(left, temp, right, 1, 0x55555555) - - -/* - * The 'inverse initial permutation' - **/ -#define FINAL_PERMUTATION(left, temp, right) \ - DO_PERMUTATION(left, temp, right, 1, 0x55555555) \ - DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ - DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ - DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ - DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) - - -/* - * A full DES round including 'expansion function', 'sbox substitution' - * and 'primitive function P' but without swapping the left and right word. - **/ -#define DES_ROUND(from, to, work, subkey) \ - work = ((from<<1) | (from>>31)) ^ *subkey++; \ - to ^= sbox8[ work & 0x3f ]; \ - to ^= sbox6[ (work>>8) & 0x3f ]; \ - to ^= sbox4[ (work>>16) & 0x3f ]; \ - to ^= sbox2[ (work>>24) & 0x3f ]; \ - work = ((from>>3) | (from<<29)) ^ *subkey++; \ - to ^= sbox7[ work & 0x3f ]; \ - to ^= sbox5[ (work>>8) & 0x3f ]; \ - to ^= sbox3[ (work>>16) & 0x3f ]; \ - to ^= sbox1[ (work>>24) & 0x3f ]; - - -/* - * Macros to convert 8 bytes from/to 32bit words - **/ -#define READ_64BIT_DATA(data, left, right) \ - left = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; \ - right = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7]; - -#define WRITE_64BIT_DATA(data, left, right) \ - data[0] = (left >> 24) &0xff; data[1] = (left >> 16) &0xff; \ - data[2] = (left >> 8) &0xff; data[3] = left &0xff; \ - data[4] = (right >> 24) &0xff; data[5] = (right >> 16) &0xff; \ - data[6] = (right >> 8) &0xff; data[7] = right &0xff; - - -/* - * des_key_schedule(): Calculate 16 subkeys pairs (even/odd) for - * 16 encryption rounds. - * To calculate subkeys for decryption the caller - * have to reorder the generated subkeys. - * - * rawkey: 8 Bytes of key data - * subkey: Array of at least 32 guint32s. Will be filled - * with calculated subkeys. - * - **/ -static void -des_key_schedule (const guint8 * rawkey, guint32 * subkey) -{ - guint32 left, right, work; - int round; - - READ_64BIT_DATA (rawkey, left, right) - - DO_PERMUTATION (right, work, left, 4, 0x0f0f0f0f) - DO_PERMUTATION (right, work, left, 0, 0x10101010) - - left = (leftkey_swap[(left >> 0) & 0xf] << 3) | (leftkey_swap[(left >> 8) & 0xf] << 2) - | (leftkey_swap[(left >> 16) & 0xf] << 1) | (leftkey_swap[(left >> 24) & 0xf]) - | (leftkey_swap[(left >> 5) & 0xf] << 7) | (leftkey_swap[(left >> 13) & 0xf] << 6) - | (leftkey_swap[(left >> 21) & 0xf] << 5) | (leftkey_swap[(left >> 29) & 0xf] << 4); - - left &= 0x0fffffff; - - right = (rightkey_swap[(right >> 1) & 0xf] << 3) | (rightkey_swap[(right >> 9) & 0xf] << 2) - | (rightkey_swap[(right >> 17) & 0xf] << 1) | (rightkey_swap[(right >> 25) & 0xf]) - | (rightkey_swap[(right >> 4) & 0xf] << 7) | (rightkey_swap[(right >> 12) & 0xf] << 6) - | (rightkey_swap[(right >> 20) & 0xf] << 5) | (rightkey_swap[(right >> 28) & 0xf] << 4); - - right &= 0x0fffffff; - - for (round = 0; round < 16; ++round) - { - left = ((left << encrypt_rotate_tab[round]) | (left >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; - right = ((right << encrypt_rotate_tab[round]) | (right >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; - - *subkey++ = ((left << 4) & 0x24000000) - | ((left << 28) & 0x10000000) - | ((left << 14) & 0x08000000) - | ((left << 18) & 0x02080000) - | ((left << 6) & 0x01000000) - | ((left << 9) & 0x00200000) - | ((left >> 1) & 0x00100000) - | ((left << 10) & 0x00040000) - | ((left << 2) & 0x00020000) - | ((left >> 10) & 0x00010000) - | ((right >> 13) & 0x00002000) - | ((right >> 4) & 0x00001000) - | ((right << 6) & 0x00000800) - | ((right >> 1) & 0x00000400) - | ((right >> 14) & 0x00000200) - | (right & 0x00000100) - | ((right >> 5) & 0x00000020) - | ((right >> 10) & 0x00000010) - | ((right >> 3) & 0x00000008) - | ((right >> 18) & 0x00000004) - | ((right >> 26) & 0x00000002) - | ((right >> 24) & 0x00000001); - - *subkey++ = ((left << 15) & 0x20000000) - | ((left << 17) & 0x10000000) - | ((left << 10) & 0x08000000) - | ((left << 22) & 0x04000000) - | ((left >> 2) & 0x02000000) - | ((left << 1) & 0x01000000) - | ((left << 16) & 0x00200000) - | ((left << 11) & 0x00100000) - | ((left << 3) & 0x00080000) - | ((left >> 6) & 0x00040000) - | ((left << 15) & 0x00020000) - | ((left >> 4) & 0x00010000) - | ((right >> 2) & 0x00002000) - | ((right << 8) & 0x00001000) - | ((right >> 14) & 0x00000808) - | ((right >> 9) & 0x00000400) - | ((right) & 0x00000200) - | ((right << 7) & 0x00000100) - | ((right >> 7) & 0x00000020) - | ((right >> 3) & 0x00000011) - | ((right << 2) & 0x00000004) - | ((right >> 21) & 0x00000002); - } -} - - -/* - * Fill a DES context with subkeys calculated from a 64bit key. - * Does not check parity bits, but simply ignore them. - * Does not check for weak keys. - **/ -static void -des_set_key (PurpleCipherContext *context, const guchar * key, size_t len) -{ - struct _des_ctx *ctx = purple_cipher_context_get_data(context); - int i; - - g_return_if_fail(len == 8); - - des_key_schedule (key, ctx->encrypt_subkeys); - - for(i=0; i<32; i+=2) - { - ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[30-i]; - ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[31-i]; - } -} - -static size_t -des_get_key_size(PurpleCipherContext *context) -{ - return 8; -} - -/* - * Electronic Codebook Mode DES encryption/decryption of data according - * to 'mode'. - **/ -static int -des_ecb_crypt (struct _des_ctx *ctx, const guint8 * from, guint8 * to, int mode) -{ - guint32 left, right, work; - guint32 *keys; - - keys = mode ? ctx->decrypt_subkeys : ctx->encrypt_subkeys; - - READ_64BIT_DATA (from, left, right) - INITIAL_PERMUTATION (left, work, right) - - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - - FINAL_PERMUTATION (right, work, left) - WRITE_64BIT_DATA (to, right, left) - - return 0; -} - -static ssize_t -des_encrypt(PurpleCipherContext *context, const guchar input[], size_t in_len, - guchar output[], size_t out_size) -{ - int offset = 0; - int i = 0; - int tmp; - guint8 buf[8] = {0,0,0,0,0,0,0,0}; - ssize_t out_len; - - g_return_val_if_fail(out_size >= in_len, -1); - - while(offset+8<=in_len) { - des_ecb_crypt(purple_cipher_context_get_data(context), - input+offset, - output+offset, - 0); - offset+=8; - } - out_len = in_len; - if(offset<in_len) { - out_len += in_len - offset; - g_return_val_if_fail(out_size >= out_len, -1); - tmp = offset; - while(tmp<in_len) { - buf[i++] = input[tmp]; - tmp++; - } - des_ecb_crypt(purple_cipher_context_get_data(context), - buf, - output+offset, - 0); - } - return out_len; -} - -static ssize_t -des_decrypt(PurpleCipherContext *context, const guchar input[], size_t in_len, - guchar output[], size_t out_size) -{ - int offset = 0; - int i = 0; - int tmp; - guint8 buf[8] = {0,0,0,0,0,0,0,0}; - ssize_t out_len; - - g_return_val_if_fail(out_size >= in_len, -1); - - while(offset+8<=in_len) { - des_ecb_crypt(purple_cipher_context_get_data(context), - input+offset, - output+offset, - 1); - offset+=8; - } - out_len = in_len; - if(offset<in_len) { - out_len += in_len - offset; - g_return_val_if_fail(out_size >= out_len, -1); - tmp = offset; - while(tmp<in_len) { - buf[i++] = input[tmp]; - tmp++; - } - des_ecb_crypt(purple_cipher_context_get_data(context), - buf, - output+offset, - 1); - } - return out_len; -} - -static void -des_init(PurpleCipherContext *context, gpointer extra) { - struct _des_ctx *mctx; - mctx = g_new0(struct _des_ctx, 1); - purple_cipher_context_set_data(context, mctx); -} - -static void -des_uninit(PurpleCipherContext *context) { - struct _des_ctx *des_context; - - des_context = purple_cipher_context_get_data(context); - memset(des_context, 0, sizeof(*des_context)); - - g_free(des_context); - des_context = NULL; -} - -static PurpleCipherOps DESOps = { - NULL, /* Set option */ - NULL, /* Get option */ - des_init, /* init */ - NULL, /* reset */ - NULL, /* reset state */ - des_uninit, /* uninit */ - NULL, /* set iv */ - NULL, /* append */ - NULL, /* digest */ - NULL, /* get_digest_size */ - des_encrypt, /* encrypt */ - des_decrypt, /* decrypt */ - NULL, /* set salt */ - NULL, /* get salt size */ - des_set_key, /* set key */ - des_get_key_size, /* get key size */ - NULL, /* set batch mode */ - NULL, /* get batch mode */ - NULL, /* get block size */ - NULL, NULL, NULL, NULL /* reserved */ -}; - -/****************************************************************************** - * Triple-DES - *****************************************************************************/ - -typedef struct _des3_ctx -{ - PurpleCipherBatchMode mode; - guchar iv[8]; - /* First key for encryption */ - struct _des_ctx key1; - /* Second key for decryption */ - struct _des_ctx key2; - /* Third key for encryption */ - struct _des_ctx key3; -} des3_ctx[1]; - -/* - * Fill a DES3 context with subkeys calculated from 3 64bit key. - * Does not check parity bits, but simply ignore them. - * Does not check for weak keys. - **/ -static void -des3_set_key(PurpleCipherContext *context, const guchar * key, size_t len) -{ - struct _des3_ctx *ctx = purple_cipher_context_get_data(context); - int i; - - g_return_if_fail(len == 24); - - des_key_schedule (key + 0, ctx->key1.encrypt_subkeys); - des_key_schedule (key + 8, ctx->key2.encrypt_subkeys); - des_key_schedule (key + 16, ctx->key3.encrypt_subkeys); - - for (i = 0; i < 32; i += 2) - { - ctx->key1.decrypt_subkeys[i] = ctx->key1.encrypt_subkeys[30-i]; - ctx->key1.decrypt_subkeys[i+1] = ctx->key1.encrypt_subkeys[31-i]; - ctx->key2.decrypt_subkeys[i] = ctx->key2.encrypt_subkeys[30-i]; - ctx->key2.decrypt_subkeys[i+1] = ctx->key2.encrypt_subkeys[31-i]; - ctx->key3.decrypt_subkeys[i] = ctx->key3.encrypt_subkeys[30-i]; - ctx->key3.decrypt_subkeys[i+1] = ctx->key3.encrypt_subkeys[31-i]; - } -} - -static size_t -des3_get_key_size(PurpleCipherContext *context) -{ - return 24; -} - -static ssize_t -des3_ecb_encrypt(struct _des3_ctx *ctx, const guchar input[], size_t in_len, - guchar output[], size_t out_size) -{ - int offset = 0; - int i = 0; - int tmp; - guint8 buf[8] = {0,0,0,0,0,0,0,0}; - ssize_t out_len; - - g_return_val_if_fail(out_size >= in_len, -1); - - while (offset + 8 <= in_len) { - des_ecb_crypt(&ctx->key1, - input+offset, - output+offset, - 0); - des_ecb_crypt(&ctx->key2, - output+offset, - buf, - 1); - des_ecb_crypt(&ctx->key3, - buf, - output+offset, - 0); - offset += 8; - } - out_len = in_len; - if (offset < in_len) { - out_len += in_len - offset; - g_return_val_if_fail(out_size >= out_len, -1); - tmp = offset; - memset(buf, 0, 8); - while (tmp < in_len) { - buf[i++] = input[tmp]; - tmp++; - } - des_ecb_crypt(&ctx->key1, - buf, - output+offset, - 0); - des_ecb_crypt(&ctx->key2, - output+offset, - buf, - 1); - des_ecb_crypt(&ctx->key3, - buf, - output+offset, - 0); - } - return out_len; -} - -static ssize_t -des3_cbc_encrypt(struct _des3_ctx *ctx, const guchar input[], size_t in_len, - guchar output[], size_t out_size) -{ - int offset = 0; - int i = 0; - int tmp; - guint8 buf[8]; - ssize_t out_len; - memcpy(buf, ctx->iv, 8); - - g_return_val_if_fail(out_size >= in_len, -1); - - while (offset + 8 <= in_len) { - for (i = 0; i < 8; i++) - buf[i] ^= input[offset + i]; - - des_ecb_crypt(&ctx->key1, - buf, - output+offset, - 0); - des_ecb_crypt(&ctx->key2, - output+offset, - buf, - 1); - des_ecb_crypt(&ctx->key3, - buf, - output+offset, - 0); - memcpy(buf, output+offset, 8); - offset += 8; - } - out_len = in_len; - if (offset < in_len) { - out_len += in_len - offset; - g_return_val_if_fail(out_size >= out_len, -1); - tmp = offset; - i = 0; - while (tmp < in_len) { - buf[i++] ^= input[tmp]; - tmp++; - } - des_ecb_crypt(&ctx->key1, - buf, - output+offset, - 0); - des_ecb_crypt(&ctx->key2, - output+offset, - buf, - 1); - des_ecb_crypt(&ctx->key3, - buf, - output+offset, - 0); - } - return out_len; -} - -static ssize_t -des3_encrypt(PurpleCipherContext *context, const guchar input[], size_t in_len, - guchar output[], size_t out_size) -{ - struct _des3_ctx *ctx = purple_cipher_context_get_data(context); - - if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_ECB) { - return des3_ecb_encrypt(ctx, input, in_len, output, out_size); - } else if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_CBC) { - return des3_cbc_encrypt(ctx, input, in_len, output, out_size); - } else { - g_return_val_if_reached(0); - } - - return 0; -} - -static ssize_t -des3_ecb_decrypt(struct _des3_ctx *ctx, const guchar input[], size_t in_len, - guchar output[], size_t out_size) -{ - int offset = 0; - int i = 0; - int tmp; - guint8 buf[8] = {0,0,0,0,0,0,0,0}; - ssize_t out_len; - - g_return_val_if_fail(out_size >= in_len, -1); - - while (offset + 8 <= in_len) { - /* NOTE: Apply key in reverse */ - des_ecb_crypt(&ctx->key3, - input+offset, - output+offset, - 1); - des_ecb_crypt(&ctx->key2, - output+offset, - buf, - 0); - des_ecb_crypt(&ctx->key1, - buf, - output+offset, - 1); - offset+=8; - } - out_len = in_len; - if (offset < in_len) { - out_len += in_len - offset; - g_return_val_if_fail(out_size >= out_len, -1); - tmp = offset; - memset(buf, 0, 8); - while (tmp < in_len) { - buf[i++] = input[tmp]; - tmp++; - } - des_ecb_crypt(&ctx->key3, - buf, - output+offset, - 1); - des_ecb_crypt(&ctx->key2, - output+offset, - buf, - 0); - des_ecb_crypt(&ctx->key1, - buf, - output+offset, - 1); - } - return out_len; -} - -static ssize_t -des3_cbc_decrypt(struct _des3_ctx *ctx, const guchar input[], size_t in_len, - guchar output[], size_t out_size) -{ - int offset = 0; - int i = 0; - int tmp; - guint8 buf[8] = {0,0,0,0,0,0,0,0}; - guint8 link[8]; - ssize_t out_len; - - g_return_val_if_fail(out_size >= in_len, -1); - - memcpy(link, ctx->iv, 8); - while (offset + 8 <= in_len) { - des_ecb_crypt(&ctx->key3, - input+offset, - output+offset, - 1); - des_ecb_crypt(&ctx->key2, - output+offset, - buf, - 0); - des_ecb_crypt(&ctx->key1, - buf, - output+offset, - 1); - for (i = 0; i < 8; i++) - output[offset + i] ^= link[i]; - memcpy(link, input + offset, 8); - offset+=8; - } - out_len = in_len; - if(offset<in_len) { - out_len += in_len - offset; - g_return_val_if_fail(out_size >= out_len, -1); - tmp = offset; - memset(buf, 0, 8); - i = 0; - while(tmp<in_len) { - buf[i++] = input[tmp]; - tmp++; - } - des_ecb_crypt(&ctx->key3, - buf, - output+offset, - 1); - des_ecb_crypt(&ctx->key2, - output+offset, - buf, - 0); - des_ecb_crypt(&ctx->key1, - buf, - output+offset, - 1); - for (i = 0; i < 8; i++) - output[offset + i] ^= link[i]; - } - return out_len; -} - -static ssize_t -des3_decrypt(PurpleCipherContext *context, const guchar input[], size_t in_len, - guchar output[], size_t out_size) -{ - struct _des3_ctx *ctx = purple_cipher_context_get_data(context); - - if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_ECB) { - return des3_ecb_decrypt(ctx, input, in_len, output, out_size); - } else if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_CBC) { - return des3_cbc_decrypt(ctx, input, in_len, output, out_size); - } else { - g_return_val_if_reached(0); - } - - return 0; -} - -static void -des3_set_batch(PurpleCipherContext *context, PurpleCipherBatchMode mode) -{ - struct _des3_ctx *ctx = purple_cipher_context_get_data(context); - - ctx->mode = mode; -} - -static PurpleCipherBatchMode -des3_get_batch(PurpleCipherContext *context) -{ - struct _des3_ctx *ctx = purple_cipher_context_get_data(context); - - return ctx->mode; -} - -static void -des3_set_iv(PurpleCipherContext *context, guchar *iv, size_t len) -{ - struct _des3_ctx *ctx; - - g_return_if_fail(len == 8); - - ctx = purple_cipher_context_get_data(context); - - memcpy(ctx->iv, iv, len); -} - -static void -des3_init(PurpleCipherContext *context, gpointer extra) -{ - struct _des3_ctx *mctx; - mctx = g_new0(struct _des3_ctx, 1); - purple_cipher_context_set_data(context, mctx); -} - -static void -des3_uninit(PurpleCipherContext *context) -{ - struct _des3_ctx *des3_context; - - des3_context = purple_cipher_context_get_data(context); - memset(des3_context, 0, sizeof(*des3_context)); - - g_free(des3_context); - des3_context = NULL; -} - -static PurpleCipherOps DES3Ops = { - NULL, /* Set option */ - NULL, /* Get option */ - des3_init, /* init */ - NULL, /* reset */ - NULL, /* reset state */ - des3_uninit, /* uninit */ - des3_set_iv, /* set iv */ - NULL, /* append */ - NULL, /* digest */ - NULL, /* get_digest_size */ - des3_encrypt, /* encrypt */ - des3_decrypt, /* decrypt */ - NULL, /* set salt */ - NULL, /* get salt size */ - des3_set_key, /* set key */ - des3_get_key_size, /* get_key_size */ - des3_set_batch, /* set batch mode */ - des3_get_batch, /* get batch mode */ - NULL, /* get block size */ - NULL, NULL, NULL, NULL /* reserved */ -}; - -/****************************************************************************** - * Registration - *****************************************************************************/ -PurpleCipherOps * -purple_des_cipher_get_ops(void) { - return &DESOps; -} - -PurpleCipherOps * -purple_des3_cipher_get_ops(void) { - return &DES3Ops; -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/ciphers/des3cipher.c Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,523 @@ +/* + * Original des taken from gpg + * + * des.c - Triple-DES encryption/decryption Algorithm + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * Please see below for more legal information! + * + * According to the definition of DES in FIPS PUB 46-2 from December 1993. + * For a description of triple encryption, see: + * Bruce Schneier: Applied Cryptography. Second Edition. + * John Wiley & Sons, 1996. ISBN 0-471-12845-7. Pages 358 ff. + * + * 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 "des3cipher.h" +#include "descipher.h" + +#include <string.h> + +/****************************************************************************** + * Structs + *****************************************************************************/ + +#define PURPLE_DES3_CIPHER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_DES3_CIPHER, PurpleDES3CipherPrivate)) + +typedef struct _PurpleDES3CipherPrivate PurpleDES3CipherPrivate; +struct _PurpleDES3CipherPrivate +{ + PurpleCipherBatchMode mode; + guchar iv[8]; + /* First key for encryption */ + PurpleCipher *key1; + /* Second key for decryption */ + PurpleCipher *key2; + /* Third key for encryption */ + PurpleCipher *key3; +}; + +/****************************************************************************** + * Enums + *****************************************************************************/ +enum { + PROP_NONE, + PROP_BATCH_MODE, + PROP_IV, + PROP_KEY, + PROP_LAST, +}; + +/****************************************************************************** + * Globals + *****************************************************************************/ +static GObjectClass *parent_class = NULL; + +/****************************************************************************** + * Cipher Stuff + *****************************************************************************/ + +static size_t +purple_des3_cipher_get_key_size(PurpleCipher *cipher) +{ + return 24; +} + +/* + * Fill a DES3 context with subkeys calculated from 3 64bit key. + * Does not check parity bits, but simply ignore them. + * Does not check for weak keys. + **/ +static void +purple_des3_cipher_set_key(PurpleCipher *cipher, const guchar *key, size_t len) +{ + PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher); + PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); + + g_return_if_fail(len == 24); + + purple_cipher_set_key(PURPLE_CIPHER(priv->key1), key + 0, + purple_cipher_get_key_size(PURPLE_CIPHER(priv->key1))); + purple_cipher_set_key(PURPLE_CIPHER(priv->key2), key + 8, + purple_cipher_get_key_size(PURPLE_CIPHER(priv->key2))); + purple_cipher_set_key(PURPLE_CIPHER(priv->key3), key + 16, + purple_cipher_get_key_size(PURPLE_CIPHER(priv->key3))); + + g_object_notify(G_OBJECT(des3_cipher), "key"); +} + +static ssize_t +purple_des3_cipher_ecb_encrypt(PurpleDES3Cipher *des3_cipher, const guchar input[], + size_t in_len, guchar output[], size_t out_size) +{ + int offset = 0; + int i = 0; + int tmp; + guint8 buf[8] = {0,0,0,0,0,0,0,0}; + ssize_t out_len; + PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); + + g_return_val_if_fail(out_size >= in_len, -1); + + while (offset + 8 <= in_len) { + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key1), + input + offset, output + offset, 0); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key2), + output + offset, buf, 1); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key3), + buf, output + offset, 0); + + offset += 8; + } + + out_len = in_len; + if (offset < in_len) { + out_len += in_len - offset; + g_return_val_if_fail(out_size >= out_len, -1); + tmp = offset; + memset(buf, 0, 8); + while (tmp < in_len) { + buf[i++] = input[tmp]; + tmp++; + } + + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key1), + buf, output + offset, 0); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key2), + output + offset, buf, 1); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key3), + buf, output + offset, 0); + } + + return out_len; +} + +static ssize_t +purple_des3_cipher_cbc_encrypt(PurpleDES3Cipher *des3_cipher, const guchar input[], + size_t in_len, guchar output[], size_t out_size) +{ + int offset = 0; + int i = 0; + int tmp; + guint8 buf[8]; + ssize_t out_len; + PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); + memcpy(buf, priv->iv, 8); + + g_return_val_if_fail(out_size >= in_len, -1); + + while (offset + 8 <= in_len) { + for (i = 0; i < 8; i++) + buf[i] ^= input[offset + i]; + + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key1), + buf, output + offset, 0); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key2), + output + offset, buf, 1); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key3), + buf, output + offset, 0); + + memcpy(buf, output+offset, 8); + offset += 8; + } + + out_len = in_len; + if (offset < in_len) { + out_len += in_len - offset; + g_return_val_if_fail(out_size >= out_len, -1); + tmp = offset; + i = 0; + while (tmp < in_len) { + buf[i++] ^= input[tmp]; + tmp++; + } + + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key1), + buf, output + offset, 0); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key2), + output + offset, buf, 1); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key3), + buf, output + offset, 0); + } + + return out_len; +} + +static ssize_t +purple_des3_cipher_encrypt(PurpleCipher *cipher, const guchar input[], + size_t in_len, guchar output[], size_t out_size) +{ + PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher); + PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); + + if (priv->mode == PURPLE_CIPHER_BATCH_MODE_ECB) { + return purple_des3_cipher_ecb_encrypt(des3_cipher, input, in_len, output, out_size); + } else if (priv->mode == PURPLE_CIPHER_BATCH_MODE_CBC) { + return purple_des3_cipher_cbc_encrypt(des3_cipher, input, in_len, output, out_size); + } else { + g_return_val_if_reached(0); + } + + return 0; +} + +static ssize_t +purple_des3_cipher_ecb_decrypt(PurpleDES3Cipher *des3_cipher, const guchar input[], + size_t in_len, guchar output[], size_t out_size) +{ + int offset = 0; + int i = 0; + int tmp; + guint8 buf[8] = {0,0,0,0,0,0,0,0}; + ssize_t out_len; + PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); + + g_return_val_if_fail(out_size >= in_len, -1); + + while (offset + 8 <= in_len) { + /* NOTE: Apply key in reverse */ + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key3), + input + offset, output + offset, 1); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key2), + output + offset, buf, 0); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key1), + buf, output + offset, 1); + + offset += 8; + } + + out_len = in_len; + if (offset < in_len) { + out_len += in_len - offset; + g_return_val_if_fail(out_size >= out_len, -1); + tmp = offset; + memset(buf, 0, 8); + while (tmp < in_len) { + buf[i++] = input[tmp]; + tmp++; + } + + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key3), + buf, output + offset, 1); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key2), + output + offset, buf, 0); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key1), + buf, output + offset, 1); + } + + return out_len; +} + +static ssize_t +purple_des3_cipher_cbc_decrypt(PurpleDES3Cipher *des3_cipher, const guchar input[], + size_t in_len, guchar output[], size_t out_size) +{ + int offset = 0; + int i = 0; + int tmp; + guint8 buf[8] = {0,0,0,0,0,0,0,0}; + guint8 link[8]; + ssize_t out_len; + PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); + + g_return_val_if_fail(out_size >= in_len, -1); + + memcpy(link, priv->iv, 8); + while (offset + 8 <= in_len) { + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key3), + input + offset, output + offset, 1); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key2), + output + offset, buf, 0); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key1), + buf, output + offset, 1); + + for (i = 0; i < 8; i++) + output[offset + i] ^= link[i]; + + memcpy(link, input + offset, 8); + + offset+=8; + } + + out_len = in_len; + if(offset<in_len) { + out_len += in_len - offset; + g_return_val_if_fail(out_size >= out_len, -1); + tmp = offset; + memset(buf, 0, 8); + i = 0; + while(tmp<in_len) { + buf[i++] = input[tmp]; + tmp++; + } + + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key3), + buf, output + offset, 1); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key2), + output + offset, buf, 0); + purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(priv->key1), + buf, output + offset, 1); + + for (i = 0; i < 8; i++) + output[offset + i] ^= link[i]; + } + + return out_len; +} + +static ssize_t +purple_des3_cipher_decrypt(PurpleCipher *cipher, const guchar input[], + size_t in_len, guchar output[], size_t out_size) +{ + PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher); + PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(cipher); + + if (priv->mode == PURPLE_CIPHER_BATCH_MODE_ECB) { + return purple_des3_cipher_ecb_decrypt(des3_cipher, input, in_len, output, out_size); + } else if (priv->mode == PURPLE_CIPHER_BATCH_MODE_CBC) { + return purple_des3_cipher_cbc_decrypt(des3_cipher, input, in_len, output, out_size); + } else { + g_return_val_if_reached(0); + } + + return 0; +} + +static void +purple_des3_cipher_set_batch_mode(PurpleCipher *cipher, PurpleCipherBatchMode mode) +{ + PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher); + PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); + + priv->mode = mode; + + g_object_notify(G_OBJECT(des3_cipher), "batch_mode"); +} + +static PurpleCipherBatchMode +purple_des3_cipher_get_batch_mode(PurpleCipher *cipher) +{ + PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher); + PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); + + return priv->mode; +} + +static void +purple_des3_cipher_set_iv(PurpleCipher *cipher, guchar *iv, size_t len) +{ + PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher); + PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); + + g_return_if_fail(len == 8); + + memcpy(priv->iv, iv, len); + + g_object_notify(G_OBJECT(des3_cipher), "iv"); +} + +static const gchar* +purple_des3_cipher_get_name(PurpleCipher *cipher) +{ + return "des3"; +} + +/****************************************************************************** + * Object Stuff + *****************************************************************************/ +static void +purple_des3_cipher_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleCipher *cipher = PURPLE_CIPHER(obj); + + switch(param_id) { + case PROP_BATCH_MODE: + g_value_set_enum(value, + purple_cipher_get_batch_mode(cipher)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_des3_cipher_set_property(GObject *obj, guint param_id, + const GValue *value, GParamSpec *pspec) +{ + PurpleCipher *cipher = PURPLE_CIPHER(obj); + + switch(param_id) { + case PROP_BATCH_MODE: + purple_cipher_set_batch_mode(cipher, + g_value_get_enum(value)); + break; + case PROP_IV: + { + guchar *iv = (guchar *)g_value_get_string(value); + purple_cipher_set_iv(cipher, iv, strlen((gchar*)iv)); + } + break; + case PROP_KEY: + purple_cipher_set_key(cipher, (guchar *)g_value_get_string(value), + purple_des3_cipher_get_key_size(cipher)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_des3_cipher_finalize(GObject *obj) +{ + PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(obj); + PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); + + g_object_unref(G_OBJECT(priv->key1)); + g_object_unref(G_OBJECT(priv->key2)); + g_object_unref(G_OBJECT(priv->key3)); + + memset(priv->iv, 0, sizeof(priv->iv)); + + parent_class->finalize(obj); +} + +static void +purple_des3_cipher_class_init(PurpleDES3CipherClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + PurpleCipherClass *cipher_class = PURPLE_CIPHER_CLASS(klass); + GParamSpec *pspec; + + parent_class = g_type_class_peek_parent(klass); + + obj_class->finalize = purple_des3_cipher_finalize; + obj_class->get_property = purple_des3_cipher_get_property; + obj_class->set_property = purple_des3_cipher_set_property; + + cipher_class->set_iv = purple_des3_cipher_set_iv; + cipher_class->encrypt = purple_des3_cipher_encrypt; + cipher_class->decrypt = purple_des3_cipher_decrypt; + cipher_class->set_key = purple_des3_cipher_set_key; + cipher_class->set_batch_mode = purple_des3_cipher_set_batch_mode; + cipher_class->get_batch_mode = purple_des3_cipher_get_batch_mode; + cipher_class->get_key_size = purple_des3_cipher_get_key_size; + cipher_class->get_name = purple_des3_cipher_get_name; + + pspec = g_param_spec_enum("batch_mode", "batch_mode", "batch_mode", + PURPLE_TYPE_CIPHER_BATCH_MODE, 0, + G_PARAM_READWRITE); + g_object_class_install_property(obj_class, PROP_BATCH_MODE, pspec); + + pspec = g_param_spec_string("iv", "iv", "iv", NULL, + G_PARAM_WRITABLE); + g_object_class_install_property(obj_class, PROP_IV, pspec); + + pspec = g_param_spec_string("key", "key", "key", NULL, + G_PARAM_WRITABLE); + g_object_class_install_property(obj_class, PROP_KEY, pspec); + + g_type_class_add_private(klass, sizeof(PurpleDES3CipherPrivate)); +} + +static void +purple_des3_cipher_init(PurpleCipher *cipher) { + PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher); + PurpleDES3CipherPrivate *priv = PURPLE_DES3_CIPHER_GET_PRIVATE(des3_cipher); + + priv->key1 = purple_des_cipher_new(); + priv->key2 = purple_des_cipher_new(); + priv->key3 = purple_des_cipher_new(); +} + +/****************************************************************************** + * API + *****************************************************************************/ +GType +purple_des3_cipher_get_gtype(void) { + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleDES3CipherClass), + NULL, + NULL, + (GClassInitFunc)purple_des3_cipher_class_init, + NULL, + NULL, + sizeof(PurpleDES3Cipher), + 0, + (GInstanceInitFunc)purple_des3_cipher_init, + NULL + }; + + type = g_type_register_static(PURPLE_TYPE_CIPHER, + "PurpleDES3Cipher", + &info, 0); + } + + return type; +} + +PurpleCipher * +purple_des3_cipher_new(void) { + return g_object_new(PURPLE_TYPE_DES3_CIPHER, NULL); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/ciphers/des3cipher.h Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,68 @@ +/** + * @file des3.h Purple Triple-DES Cipher + * @ingroup core + */ + +/* 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 + */ +#ifndef PURPLE_DES3_CIPHER_H +#define PURPLE_DES3_CIPHER_H + +#include "cipher.h" + +#define PURPLE_TYPE_DES3_CIPHER (purple_des3_cipher_get_gtype()) +#define PURPLE_DES3_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_DES3_CIPHER, PurpleDES3Cipher)) +#define PURPLE_DES3_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_DES3_CIPHER, PurpleDES3CipherClass)) +#define PURPLE_IS_DES3_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_DES3_CIPHER)) +#define PURPLE_IS_DES3_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_DES3_CIPHER)) +#define PURPLE_DES3_CIPHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_DES3_CIPHER, PurpleDES3CipherClass)) + +typedef struct _PurpleDES3Cipher PurpleDES3Cipher; +typedef struct _PurpleDES3CipherClass PurpleDES3CipherClass; + +struct _PurpleDES3Cipher { + PurpleCipher gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +struct _PurpleDES3CipherClass { + PurpleCipherClass gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType purple_des3_cipher_get_gtype(void); + +PurpleCipher *purple_des3_cipher_new(void); + +G_END_DECLS + +#endif /* PURPLE_DES3_CIPHER_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/ciphers/descipher.c Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,576 @@ +/* + * Original des taken from gpg + * + * des.c - DES encryption/decryption Algorithm + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * Please see below for more legal information! + * + * According to the definition of DES in FIPS PUB 46-2 from December 1993. + * For a description of triple encryption, see: + * Bruce Schneier: Applied Cryptography. Second Edition. + * John Wiley & Sons, 1996. ISBN 0-471-12845-7. Pages 358 ff. + * + * 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 "descipher.h" + +#include <string.h> + +/****************************************************************************** + * Structs + *****************************************************************************/ +#define PURPLE_DES_CIPHER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_DES_CIPHER, PurpleDESCipherPrivate)) + +typedef struct { + guint32 encrypt_subkeys[32]; + guint32 decrypt_subkeys[32]; +} PurpleDESCipherPrivate; + +/****************************************************************************** + * Enums + *****************************************************************************/ +enum { + PROP_NONE, + PROP_KEY, + PROP_LAST, +}; + +/****************************************************************************** + * Globals + *****************************************************************************/ +static GObjectClass *parent_class = NULL; + +/* + * The s-box values are permuted according to the 'primitive function P' + */ +static guint32 sbox1[64] = { + 0x00808200, 0x00000000, 0x00008000, 0x00808202, 0x00808002, 0x00008202, + 0x00000002, 0x00008000, 0x00000200, 0x00808200, 0x00808202, 0x00000200, + 0x00800202, 0x00808002, 0x00800000, 0x00000002, 0x00000202, 0x00800200, + 0x00800200, 0x00008200, 0x00008200, 0x00808000, 0x00808000, 0x00800202, + 0x00008002, 0x00800002, 0x00800002, 0x00008002, 0x00000000, 0x00000202, + 0x00008202, 0x00800000, 0x00008000, 0x00808202, 0x00000002, 0x00808000, + 0x00808200, 0x00800000, 0x00800000, 0x00000200, 0x00808002, 0x00008000, + 0x00008200, 0x00800002, 0x00000200, 0x00000002, 0x00800202, 0x00008202, + 0x00808202, 0x00008002, 0x00808000, 0x00800202, 0x00800002, 0x00000202, + 0x00008202, 0x00808200, 0x00000202, 0x00800200, 0x00800200, 0x00000000, + 0x00008002, 0x00008200, 0x00000000, 0x00808002 +}; + +static guint32 sbox2[64] = { + 0x40084010, 0x40004000, 0x00004000, 0x00084010, 0x00080000, 0x00000010, + 0x40080010, 0x40004010, 0x40000010, 0x40084010, 0x40084000, 0x40000000, + 0x40004000, 0x00080000, 0x00000010, 0x40080010, 0x00084000, 0x00080010, + 0x40004010, 0x00000000, 0x40000000, 0x00004000, 0x00084010, 0x40080000, + 0x00080010, 0x40000010, 0x00000000, 0x00084000, 0x00004010, 0x40084000, + 0x40080000, 0x00004010, 0x00000000, 0x00084010, 0x40080010, 0x00080000, + 0x40004010, 0x40080000, 0x40084000, 0x00004000, 0x40080000, 0x40004000, + 0x00000010, 0x40084010, 0x00084010, 0x00000010, 0x00004000, 0x40000000, + 0x00004010, 0x40084000, 0x00080000, 0x40000010, 0x00080010, 0x40004010, + 0x40000010, 0x00080010, 0x00084000, 0x00000000, 0x40004000, 0x00004010, + 0x40000000, 0x40080010, 0x40084010, 0x00084000 +}; + +static guint32 sbox3[64] = { + 0x00000104, 0x04010100, 0x00000000, 0x04010004, 0x04000100, 0x00000000, + 0x00010104, 0x04000100, 0x00010004, 0x04000004, 0x04000004, 0x00010000, + 0x04010104, 0x00010004, 0x04010000, 0x00000104, 0x04000000, 0x00000004, + 0x04010100, 0x00000100, 0x00010100, 0x04010000, 0x04010004, 0x00010104, + 0x04000104, 0x00010100, 0x00010000, 0x04000104, 0x00000004, 0x04010104, + 0x00000100, 0x04000000, 0x04010100, 0x04000000, 0x00010004, 0x00000104, + 0x00010000, 0x04010100, 0x04000100, 0x00000000, 0x00000100, 0x00010004, + 0x04010104, 0x04000100, 0x04000004, 0x00000100, 0x00000000, 0x04010004, + 0x04000104, 0x00010000, 0x04000000, 0x04010104, 0x00000004, 0x00010104, + 0x00010100, 0x04000004, 0x04010000, 0x04000104, 0x00000104, 0x04010000, + 0x00010104, 0x00000004, 0x04010004, 0x00010100 +}; + +static guint32 sbox4[64] = { + 0x80401000, 0x80001040, 0x80001040, 0x00000040, 0x00401040, 0x80400040, + 0x80400000, 0x80001000, 0x00000000, 0x00401000, 0x00401000, 0x80401040, + 0x80000040, 0x00000000, 0x00400040, 0x80400000, 0x80000000, 0x00001000, + 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x80001000, 0x00001040, + 0x80400040, 0x80000000, 0x00001040, 0x00400040, 0x00001000, 0x00401040, + 0x80401040, 0x80000040, 0x00400040, 0x80400000, 0x00401000, 0x80401040, + 0x80000040, 0x00000000, 0x00000000, 0x00401000, 0x00001040, 0x00400040, + 0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x00000040, + 0x80401040, 0x80000040, 0x80000000, 0x00001000, 0x80400000, 0x80001000, + 0x00401040, 0x80400040, 0x80001000, 0x00001040, 0x00400000, 0x80401000, + 0x00000040, 0x00400000, 0x00001000, 0x00401040 +}; + +static guint32 sbox5[64] = { + 0x00000080, 0x01040080, 0x01040000, 0x21000080, 0x00040000, 0x00000080, + 0x20000000, 0x01040000, 0x20040080, 0x00040000, 0x01000080, 0x20040080, + 0x21000080, 0x21040000, 0x00040080, 0x20000000, 0x01000000, 0x20040000, + 0x20040000, 0x00000000, 0x20000080, 0x21040080, 0x21040080, 0x01000080, + 0x21040000, 0x20000080, 0x00000000, 0x21000000, 0x01040080, 0x01000000, + 0x21000000, 0x00040080, 0x00040000, 0x21000080, 0x00000080, 0x01000000, + 0x20000000, 0x01040000, 0x21000080, 0x20040080, 0x01000080, 0x20000000, + 0x21040000, 0x01040080, 0x20040080, 0x00000080, 0x01000000, 0x21040000, + 0x21040080, 0x00040080, 0x21000000, 0x21040080, 0x01040000, 0x00000000, + 0x20040000, 0x21000000, 0x00040080, 0x01000080, 0x20000080, 0x00040000, + 0x00000000, 0x20040000, 0x01040080, 0x20000080 +}; + +static guint32 sbox6[64] = { + 0x10000008, 0x10200000, 0x00002000, 0x10202008, 0x10200000, 0x00000008, + 0x10202008, 0x00200000, 0x10002000, 0x00202008, 0x00200000, 0x10000008, + 0x00200008, 0x10002000, 0x10000000, 0x00002008, 0x00000000, 0x00200008, + 0x10002008, 0x00002000, 0x00202000, 0x10002008, 0x00000008, 0x10200008, + 0x10200008, 0x00000000, 0x00202008, 0x10202000, 0x00002008, 0x00202000, + 0x10202000, 0x10000000, 0x10002000, 0x00000008, 0x10200008, 0x00202000, + 0x10202008, 0x00200000, 0x00002008, 0x10000008, 0x00200000, 0x10002000, + 0x10000000, 0x00002008, 0x10000008, 0x10202008, 0x00202000, 0x10200000, + 0x00202008, 0x10202000, 0x00000000, 0x10200008, 0x00000008, 0x00002000, + 0x10200000, 0x00202008, 0x00002000, 0x00200008, 0x10002008, 0x00000000, + 0x10202000, 0x10000000, 0x00200008, 0x10002008 +}; + +static guint32 sbox7[64] = { + 0x00100000, 0x02100001, 0x02000401, 0x00000000, 0x00000400, 0x02000401, + 0x00100401, 0x02100400, 0x02100401, 0x00100000, 0x00000000, 0x02000001, + 0x00000001, 0x02000000, 0x02100001, 0x00000401, 0x02000400, 0x00100401, + 0x00100001, 0x02000400, 0x02000001, 0x02100000, 0x02100400, 0x00100001, + 0x02100000, 0x00000400, 0x00000401, 0x02100401, 0x00100400, 0x00000001, + 0x02000000, 0x00100400, 0x02000000, 0x00100400, 0x00100000, 0x02000401, + 0x02000401, 0x02100001, 0x02100001, 0x00000001, 0x00100001, 0x02000000, + 0x02000400, 0x00100000, 0x02100400, 0x00000401, 0x00100401, 0x02100400, + 0x00000401, 0x02000001, 0x02100401, 0x02100000, 0x00100400, 0x00000000, + 0x00000001, 0x02100401, 0x00000000, 0x00100401, 0x02100000, 0x00000400, + 0x02000001, 0x02000400, 0x00000400, 0x00100001 +}; + +static guint32 sbox8[64] = { + 0x08000820, 0x00000800, 0x00020000, 0x08020820, 0x08000000, 0x08000820, + 0x00000020, 0x08000000, 0x00020020, 0x08020000, 0x08020820, 0x00020800, + 0x08020800, 0x00020820, 0x00000800, 0x00000020, 0x08020000, 0x08000020, + 0x08000800, 0x00000820, 0x00020800, 0x00020020, 0x08020020, 0x08020800, + 0x00000820, 0x00000000, 0x00000000, 0x08020020, 0x08000020, 0x08000800, + 0x00020820, 0x00020000, 0x00020820, 0x00020000, 0x08020800, 0x00000800, + 0x00000020, 0x08020020, 0x00000800, 0x00020820, 0x08000800, 0x00000020, + 0x08000020, 0x08020000, 0x08020020, 0x08000000, 0x00020000, 0x08000820, + 0x00000000, 0x08020820, 0x00020020, 0x08000020, 0x08020000, 0x08000800, + 0x08000820, 0x00000000, 0x08020820, 0x00020800, 0x00020800, 0x00000820, + 0x00000820, 0x00020020, 0x08000000, 0x08020800 +}; + +/* + * These two tables are part of the 'permuted choice 1' function. + * In this implementation several speed improvements are done. + */ +static guint32 leftkey_swap[16] = { + 0x00000000, 0x00000001, 0x00000100, 0x00000101, 0x00010000, 0x00010001, + 0x00010100, 0x00010101, 0x01000000, 0x01000001, 0x01000100, 0x01000101, + 0x01010000, 0x01010001, 0x01010100, 0x01010101 +}; + +static guint32 rightkey_swap[16] = { + 0x00000000, 0x01000000, 0x00010000, 0x01010000, 0x00000100, 0x01000100, + 0x00010100, 0x01010100, 0x00000001, 0x01000001, 0x00010001, 0x01010001, + 0x00000101, 0x01000101, 0x00010101, 0x01010101, +}; + +/* + * Numbers of left shifts per round for encryption subkey schedule + * To calculate the decryption key scheduling we just reverse the + * ordering of the subkeys so we can omit the table for decryption + * subkey schedule. + */ +static guint8 encrypt_rotate_tab[16] = { + 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 +}; + + +/****************************************************************************** + * Helpers + *****************************************************************************/ +/* + * Macro to swap bits across two words + */ +#define DO_PERMUTATION(a, temp, b, offset, mask) \ + temp = ((a>>offset) ^ b) & mask; \ + b ^= temp; \ + a ^= temp<<offset; + +/* + * This performs the 'initial permutation' for the data to be encrypted or + * decrypted + */ +#define INITIAL_PERMUTATION(left, temp, right) \ + DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) \ + DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ + DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ + DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ + DO_PERMUTATION(left, temp, right, 1, 0x55555555) + +/* + * The 'inverse initial permutation' + */ +#define FINAL_PERMUTATION(left, temp, right) \ + DO_PERMUTATION(left, temp, right, 1, 0x55555555) \ + DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ + DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ + DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ + DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) + +/* + * A full DES round including 'expansion function', 'sbox substitution' + * and 'primitive function P' but without swapping the left and right word. + */ +#define DES_ROUND(from, to, work, subkey) \ + work = ((from<<1) | (from>>31)) ^ *subkey++; \ + to ^= sbox8[ work & 0x3f ]; \ + to ^= sbox6[ (work>>8) & 0x3f ]; \ + to ^= sbox4[ (work>>16) & 0x3f ]; \ + to ^= sbox2[ (work>>24) & 0x3f ]; \ + work = ((from>>3) | (from<<29)) ^ *subkey++; \ + to ^= sbox7[ work & 0x3f ]; \ + to ^= sbox5[ (work>>8) & 0x3f ]; \ + to ^= sbox3[ (work>>16) & 0x3f ]; \ + to ^= sbox1[ (work>>24) & 0x3f ]; + + +/* + * Macros to convert 8 bytes from/to 32bit words + */ +#define READ_64BIT_DATA(data, left, right) \ + left = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; \ + right = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7]; + +#define WRITE_64BIT_DATA(data, left, right) \ + data[0] = (left >> 24) &0xff; data[1] = (left >> 16) &0xff; \ + data[2] = (left >> 8) &0xff; data[3] = left &0xff; \ + data[4] = (right >> 24) &0xff; data[5] = (right >> 16) &0xff; \ + data[6] = (right >> 8) &0xff; data[7] = right &0xff; + +/****************************************************************************** + * Cipher Stuff + *****************************************************************************/ +/* + * des_key_schedule(): Calculate 16 subkeys pairs (even/odd) for + * 16 encryption rounds. + * To calculate subkeys for decryption the caller + * have to reorder the generated subkeys. + * + * rawkey: 8 Bytes of key data + * subkey: Array of at least 32 guint32s. Will be filled + * with calculated subkeys. + * + */ +static void +purple_des_cipher_key_schedule(const guint8 * rawkey, guint32 * subkey) { + guint32 left, right, work; + int round; + + READ_64BIT_DATA (rawkey, left, right) + + DO_PERMUTATION (right, work, left, 4, 0x0f0f0f0f) + DO_PERMUTATION (right, work, left, 0, 0x10101010) + + left = (leftkey_swap[(left >> 0) & 0xf] << 3) + | (leftkey_swap[(left >> 8) & 0xf] << 2) + | (leftkey_swap[(left >> 16) & 0xf] << 1) + | (leftkey_swap[(left >> 24) & 0xf] ) + | (leftkey_swap[(left >> 5) & 0xf] << 7) + | (leftkey_swap[(left >> 13) & 0xf] << 6) + | (leftkey_swap[(left >> 21) & 0xf] << 5) + | (leftkey_swap[(left >> 29) & 0xf] << 4); + + left &= 0x0fffffff; + + right = (rightkey_swap[(right >> 1) & 0xf] << 3) + | (rightkey_swap[(right >> 9) & 0xf] << 2) + | (rightkey_swap[(right >> 17) & 0xf] << 1) + | (rightkey_swap[(right >> 25) & 0xf] ) + | (rightkey_swap[(right >> 4) & 0xf] << 7) + | (rightkey_swap[(right >> 12) & 0xf] << 6) + | (rightkey_swap[(right >> 20) & 0xf] << 5) + | (rightkey_swap[(right >> 28) & 0xf] << 4); + + right &= 0x0fffffff; + + for (round = 0; round < 16; ++round) { + left = ((left << encrypt_rotate_tab[round]) | + (left >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; + right = ((right << encrypt_rotate_tab[round]) | + (right >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; + + *subkey++ = ((left << 4) & 0x24000000) + | ((left << 28) & 0x10000000) + | ((left << 14) & 0x08000000) + | ((left << 18) & 0x02080000) + | ((left << 6) & 0x01000000) + | ((left << 9) & 0x00200000) + | ((left >> 1) & 0x00100000) + | ((left << 10) & 0x00040000) + | ((left << 2) & 0x00020000) + | ((left >> 10) & 0x00010000) + | ((right >> 13) & 0x00002000) + | ((right >> 4) & 0x00001000) + | ((right << 6) & 0x00000800) + | ((right >> 1) & 0x00000400) + | ((right >> 14) & 0x00000200) + | (right & 0x00000100) + | ((right >> 5) & 0x00000020) + | ((right >> 10) & 0x00000010) + | ((right >> 3) & 0x00000008) + | ((right >> 18) & 0x00000004) + | ((right >> 26) & 0x00000002) + | ((right >> 24) & 0x00000001); + + *subkey++ = ((left << 15) & 0x20000000) + | ((left << 17) & 0x10000000) + | ((left << 10) & 0x08000000) + | ((left << 22) & 0x04000000) + | ((left >> 2) & 0x02000000) + | ((left << 1) & 0x01000000) + | ((left << 16) & 0x00200000) + | ((left << 11) & 0x00100000) + | ((left << 3) & 0x00080000) + | ((left >> 6) & 0x00040000) + | ((left << 15) & 0x00020000) + | ((left >> 4) & 0x00010000) + | ((right >> 2) & 0x00002000) + | ((right << 8) & 0x00001000) + | ((right >> 14) & 0x00000808) + | ((right >> 9) & 0x00000400) + | ((right) & 0x00000200) + | ((right << 7) & 0x00000100) + | ((right >> 7) & 0x00000020) + | ((right >> 3) & 0x00000011) + | ((right << 2) & 0x00000004) + | ((right >> 21) & 0x00000002); + } +} + +/* + * Fill a DES context with subkeys calculated from a 64bit key. + * Does not check parity bits, but simply ignore them. + * Does not check for weak keys. + */ +static void +purple_des_cipher_set_key(PurpleCipher *cipher, const guchar *key, size_t len) { + PurpleDESCipher *des_cipher = PURPLE_DES_CIPHER(cipher); + PurpleDESCipherPrivate *priv = PURPLE_DES_CIPHER_GET_PRIVATE(des_cipher); + int i; + + g_return_if_fail(len == 8); + + purple_des_cipher_key_schedule(key, priv->encrypt_subkeys); + + for(i = 0; i < 32; i += 2) { + priv->decrypt_subkeys[i] = priv->encrypt_subkeys[30 - i]; + priv->decrypt_subkeys[i + 1] = priv->encrypt_subkeys[31 - i]; + } + + g_object_notify(G_OBJECT(cipher), "key"); +} + +static size_t +purple_des_cipher_get_key_size(PurpleCipher *cipher) +{ + return 8; +} + +/* + * Electronic Codebook Mode DES encryption/decryption of data according to + * 'mode'. + */ +int +purple_des_cipher_ecb_crypt(PurpleDESCipher *des_cipher, const guint8 * from, guint8 * to, + int mode) +{ + guint32 left, right, work; + guint32 *keys; + PurpleDESCipherPrivate *priv = PURPLE_DES_CIPHER_GET_PRIVATE(des_cipher); + + keys = mode ? priv->decrypt_subkeys : + priv->encrypt_subkeys; + + READ_64BIT_DATA (from, left, right) + INITIAL_PERMUTATION (left, work, right) + + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + + FINAL_PERMUTATION (right, work, left) + WRITE_64BIT_DATA (to, right, left) + + return 0; +} + +static ssize_t +purple_des_cipher_encrypt(PurpleCipher *cipher, const guchar input[], + size_t in_len, guchar output[], size_t out_size) +{ + PurpleDESCipher *des_cipher = PURPLE_DES_CIPHER(cipher); + gint offset = 0, i = 0, tmp; + guint8 buf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + ssize_t out_len; + + g_return_val_if_fail(out_size >= in_len, -1); + + while(offset + 8 <= in_len) { + purple_des_cipher_ecb_crypt(des_cipher, input + offset, output + offset, 0); + offset += 8; + } + + out_len = in_len; + + if(offset<in_len) { + out_len += in_len - offset; + g_return_val_if_fail(out_size >= out_len, -1); + tmp = offset; + while(tmp<in_len) { + buf[i++] = input[tmp]; + tmp++; + } + + purple_des_cipher_ecb_crypt(des_cipher, buf, output + offset, 0); + } + + return out_len; +} + +static ssize_t +purple_des_cipher_decrypt(PurpleCipher *cipher, const guchar input[], + size_t in_len, guchar output[], size_t out_size) +{ + PurpleDESCipher *des_cipher = PURPLE_DES_CIPHER(cipher); + int offset = 0, i = 0, tmp; + guint8 buf[8] = {0,0,0,0,0,0,0,0}; + ssize_t out_len; + + g_return_val_if_fail(out_size >= in_len, -1); + + while(offset + 8 <= in_len) { + purple_des_cipher_ecb_crypt(des_cipher, input + offset, output + offset, 1); + offset += 8; + } + + out_len = in_len; + if(offset<in_len) { + out_len += in_len - offset; + g_return_val_if_fail(out_size >= out_len, -1); + tmp = offset; + while(tmp<in_len) { + buf[i++] = input[tmp]; + tmp++; + } + + purple_des_cipher_ecb_crypt(des_cipher, buf, output + offset, 1); + } + + return out_len; +} + +static const gchar* +purple_des_cipher_get_name(PurpleCipher *cipher) +{ + return "des"; +} + +/****************************************************************************** + * Object Stuff + *****************************************************************************/ +static void +purple_des_cipher_set_property(GObject *obj, guint param_id, + const GValue *value, GParamSpec *pspec) +{ + PurpleCipher *cipher = PURPLE_CIPHER(obj); + + switch(param_id) { + case PROP_KEY: + purple_cipher_set_key(cipher, (guchar *)g_value_get_string(value), + purple_des_cipher_get_key_size(cipher)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_des_cipher_class_init(PurpleDESCipherClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + PurpleCipherClass *cipher_class = PURPLE_CIPHER_CLASS(klass); + GParamSpec *pspec; + + parent_class = g_type_class_peek_parent(klass); + + obj_class->set_property = purple_des_cipher_set_property; + + cipher_class->encrypt = purple_des_cipher_encrypt; + cipher_class->decrypt = purple_des_cipher_decrypt; + cipher_class->set_key = purple_des_cipher_set_key; + cipher_class->get_key_size = purple_des_cipher_get_key_size; + cipher_class->get_name = purple_des_cipher_get_name; + + pspec = g_param_spec_string("key", "key", "key", NULL, + G_PARAM_WRITABLE); + g_object_class_install_property(obj_class, PROP_KEY, pspec); + + g_type_class_add_private(klass, sizeof(PurpleDESCipherPrivate)); +} + +/****************************************************************************** + * API + *****************************************************************************/ +GType +purple_des_cipher_get_type(void) { + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + .class_size = sizeof(PurpleDESCipherClass), + .class_init = (GClassInitFunc)purple_des_cipher_class_init, + .instance_size = sizeof(PurpleDESCipher), + .instance_init = (GInstanceInitFunc)purple_cipher_reset, + }; + + type = g_type_register_static(PURPLE_TYPE_CIPHER, + "PurpleDESCipher", + &info, 0); + } + + return type; +} + +/** + * purple_des_cipher_new: + * + * Creates a new #PurpleCipher instance which implements the DES block cipher. + * + * Return Value: The new DES implementation of #PurpleCipher. + */ +PurpleCipher * +purple_des_cipher_new(void) { + return g_object_new(PURPLE_TYPE_DES_CIPHER, NULL); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/ciphers/descipher.h Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,71 @@ +/** + * @file des.h Purple DES Cipher + * @ingroup core + */ + +/* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef PURPLE_DES_CIPHER_H +#define PURPLE_DES_CIPHER_H + +#include "cipher.h" + +#define PURPLE_TYPE_DES_CIPHER (purple_des_cipher_get_type()) +#define PURPLE_DES_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_DES_CIPHER, PurpleDESCipher)) +#define PURPLE_DES_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_DES_CIPHER, PurpleDESCipherClass)) +#define PURPLE_IS_DES_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_DES_CIPHER)) +#define PURPLE_IS_DES_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_DES_CIPHER)) +#define PURPLE_DES_CIPHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_DES_CIPHER, PurpleDESCipherClass)) + +typedef struct _PurpleDESCipher PurpleDESCipher; +typedef struct _PurpleDESCipherClass PurpleDESCipherClass; + +struct _PurpleDESCipher { + /*< private >*/ + PurpleCipher gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +struct _PurpleDESCipherClass { + /*< private >*/ + PurpleCipherClass gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType purple_des_cipher_get_type(void); + +PurpleCipher *purple_des_cipher_new(void); + +int purple_des_cipher_ecb_crypt(PurpleDESCipher *des_cipher, const guint8 * from, guint8 * to, int mode); + +G_END_DECLS + +#endif /* PURPLE_DES_CIPHER_H */
--- a/libpurple/ciphers/gchecksum.c Sun Jun 23 02:43:06 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ -#include "internal.h" -#include <cipher.h> -#include "ciphers.h" - -static void -purple_g_checksum_init(PurpleCipherContext *context, GChecksumType type) -{ - GChecksum *checksum; - - checksum = g_checksum_new(type); - purple_cipher_context_set_data(context, checksum); -} - -static void -purple_g_checksum_reset(PurpleCipherContext *context, GChecksumType type) -{ - GChecksum *checksum; - - checksum = purple_cipher_context_get_data(context); - g_return_if_fail(checksum != NULL); - - g_checksum_reset(checksum); -} - -static void -purple_g_checksum_uninit(PurpleCipherContext *context) -{ - GChecksum *checksum; - - checksum = purple_cipher_context_get_data(context); - g_return_if_fail(checksum != NULL); - - g_checksum_free(checksum); -} - -static void -purple_g_checksum_append(PurpleCipherContext *context, const guchar *data, - gsize len) -{ - GChecksum *checksum; - - checksum = purple_cipher_context_get_data(context); - g_return_if_fail(checksum != NULL); - - while (len >= G_MAXSSIZE) { - g_checksum_update(checksum, data, G_MAXSSIZE); - len -= G_MAXSSIZE; - data += G_MAXSSIZE; - } - - if (len) - g_checksum_update(checksum, data, len); -} - -static gboolean -purple_g_checksum_digest(PurpleCipherContext *context, GChecksumType type, - guchar *digest, size_t buff_len) -{ - GChecksum *checksum; - const gssize required_len = g_checksum_type_get_length(type); - gsize digest_len = buff_len; - - checksum = purple_cipher_context_get_data(context); - - g_return_val_if_fail(buff_len >= required_len, FALSE); - g_return_val_if_fail(checksum != NULL, FALSE); - - g_checksum_get_digest(checksum, digest, &digest_len); - - if (digest_len != required_len) - return FALSE; - - purple_cipher_context_reset(context, NULL); - - return TRUE; -} - -/****************************************************************************** - * Macros - *****************************************************************************/ -#define PURPLE_G_CHECKSUM_IMPLEMENTATION(lower, camel, type, block_size) \ - static size_t \ - lower##_get_block_size(PurpleCipherContext *context) { \ - return (block_size); \ - } \ - \ - static void \ - lower##_init(PurpleCipherContext *context, gpointer extra) { \ - purple_g_checksum_init(context, (type)); \ - } \ - \ - static void \ - lower##_reset(PurpleCipherContext *context, gpointer extra) { \ - purple_g_checksum_reset(context, (type)); \ - } \ - \ - static gboolean \ - lower##_digest(PurpleCipherContext *context, guchar digest[], \ - size_t len) \ - { \ - return purple_g_checksum_digest(context, (type), digest, len); \ - } \ - \ - static size_t \ - lower##_get_digest_size(PurpleCipherContext *context) \ - { \ - return g_checksum_type_get_length((type)); \ - } \ - \ - static PurpleCipherOps camel##Ops = { \ - NULL, /* Set option */ \ - NULL, /* Get option */ \ - lower##_init, /* init */ \ - lower##_reset, /* reset */ \ - lower##_reset, /* reset state */ \ - purple_g_checksum_uninit, /* uninit */ \ - NULL, /* set iv */ \ - purple_g_checksum_append, /* append */ \ - lower##_digest, /* digest */ \ - lower##_get_digest_size, /* get digest size */ \ - NULL, /* encrypt */ \ - NULL, /* decrypt */ \ - NULL, /* set salt */ \ - NULL, /* get salt size */ \ - NULL, /* set key */ \ - NULL, /* get key size */ \ - NULL, /* set batch mode */ \ - NULL, /* get batch mode */ \ - lower##_get_block_size, /* get block size */ \ - NULL, NULL, NULL, NULL /* reserved */ \ - }; \ - \ - PurpleCipherOps * \ - purple_##lower##_cipher_get_ops(void) { \ - return &camel##Ops; \ - } - -/****************************************************************************** - * Macro Expansion - *****************************************************************************/ -PURPLE_G_CHECKSUM_IMPLEMENTATION(md5, MD5, G_CHECKSUM_MD5, 64); -PURPLE_G_CHECKSUM_IMPLEMENTATION(sha1, SHA1, G_CHECKSUM_SHA1, 64); -PURPLE_G_CHECKSUM_IMPLEMENTATION(sha256, SHA256, G_CHECKSUM_SHA256, 64);
--- a/libpurple/ciphers/hmac.c Sun Jun 23 02:43:06 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,247 +0,0 @@ -/* - * 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 "internal.h" -#include <cipher.h> -#include "ciphers.h" - -#include <util.h> - -struct HMAC_Context { - PurpleCipherContext *hash; - char *name; - int blocksize; - guchar *opad, *ipad; -}; - - static void -hmac_init(PurpleCipherContext *context, gpointer extra) -{ - struct HMAC_Context *hctx; - hctx = g_new0(struct HMAC_Context, 1); - purple_cipher_context_set_data(context, hctx); - purple_cipher_context_reset(context, extra); -} - - static void -hmac_reset(PurpleCipherContext *context, gpointer extra) -{ - struct HMAC_Context *hctx; - - hctx = purple_cipher_context_get_data(context); - - g_free(hctx->name); - hctx->name = NULL; - if (hctx->hash) - purple_cipher_context_destroy(hctx->hash); - hctx->hash = NULL; - hctx->blocksize = 0; - g_free(hctx->opad); - hctx->opad = NULL; - g_free(hctx->ipad); - hctx->ipad = NULL; -} - - static void -hmac_reset_state(PurpleCipherContext *context, gpointer extra) -{ - struct HMAC_Context *hctx; - - hctx = purple_cipher_context_get_data(context); - - if (hctx->hash) { - purple_cipher_context_reset_state(hctx->hash, NULL); - purple_cipher_context_append(hctx->hash, hctx->ipad, hctx->blocksize); - } -} - - static void -hmac_set_opt(PurpleCipherContext *context, const gchar *name, void *value) -{ - struct HMAC_Context *hctx; - - hctx = purple_cipher_context_get_data(context); - - if (purple_strequal(name, "hash")) { - g_free(hctx->name); - if (hctx->hash) - purple_cipher_context_destroy(hctx->hash); - hctx->name = g_strdup((char*)value); - hctx->hash = purple_cipher_context_new_by_name((char *)value, NULL); - hctx->blocksize = purple_cipher_context_get_block_size(hctx->hash); - } -} - - static void * -hmac_get_opt(PurpleCipherContext *context, const gchar *name) -{ - struct HMAC_Context *hctx; - - hctx = purple_cipher_context_get_data(context); - - if (purple_strequal(name, "hash")) { - return hctx->name; - } - - return NULL; -} - - static void -hmac_append(PurpleCipherContext *context, const guchar *data, size_t len) -{ - struct HMAC_Context *hctx = purple_cipher_context_get_data(context); - - g_return_if_fail(hctx->hash != NULL); - - purple_cipher_context_append(hctx->hash, data, len); -} - - static gboolean -hmac_digest(PurpleCipherContext *context, guchar *out, size_t len) -{ - struct HMAC_Context *hctx = purple_cipher_context_get_data(context); - PurpleCipherContext *hash = hctx->hash; - guchar *inner_hash; - size_t hash_len; - gboolean result; - - g_return_val_if_fail(hash != NULL, FALSE); - - hash_len = purple_cipher_context_get_digest_size(hash); - g_return_val_if_fail(hash_len > 0, FALSE); - - inner_hash = g_malloc(hash_len); - result = purple_cipher_context_digest(hash, inner_hash, hash_len); - - purple_cipher_context_reset(hash, NULL); - - purple_cipher_context_append(hash, hctx->opad, hctx->blocksize); - purple_cipher_context_append(hash, inner_hash, hash_len); - - g_free(inner_hash); - - result = result && purple_cipher_context_digest(hash, out, len); - - return result; -} - - static size_t -hmac_get_digest_size(PurpleCipherContext *context) -{ - struct HMAC_Context *hctx = purple_cipher_context_get_data(context); - PurpleCipherContext *hash = hctx->hash; - - g_return_val_if_fail(hash != NULL, 0); - - return purple_cipher_context_get_digest_size(hash); -} - - static void -hmac_uninit(PurpleCipherContext *context) -{ - struct HMAC_Context *hctx; - - purple_cipher_context_reset(context, NULL); - - hctx = purple_cipher_context_get_data(context); - - g_free(hctx); -} - - static void -hmac_set_key(PurpleCipherContext *context, const guchar * key, size_t key_len) -{ - struct HMAC_Context *hctx = purple_cipher_context_get_data(context); - int blocksize, i; - guchar *full_key; - - g_return_if_fail(hctx->hash != NULL); - - g_free(hctx->opad); - g_free(hctx->ipad); - - blocksize = hctx->blocksize; - hctx->ipad = g_malloc(blocksize); - hctx->opad = g_malloc(blocksize); - - if (key_len > blocksize) { - purple_cipher_context_reset(hctx->hash, NULL); - purple_cipher_context_append(hctx->hash, key, key_len); - - key_len = purple_cipher_context_get_digest_size(hctx->hash); - full_key = g_malloc(key_len); - purple_cipher_context_digest(hctx->hash, full_key, key_len); - } else - full_key = g_memdup(key, key_len); - - if (key_len < blocksize) { - full_key = g_realloc(full_key, blocksize); - memset(full_key + key_len, 0, blocksize - key_len); - } - - for(i = 0; i < blocksize; i++) { - hctx->ipad[i] = 0x36 ^ full_key[i]; - hctx->opad[i] = 0x5c ^ full_key[i]; - } - - g_free(full_key); - - purple_cipher_context_reset(hctx->hash, NULL); - purple_cipher_context_append(hctx->hash, hctx->ipad, blocksize); -} - - static size_t -hmac_get_block_size(PurpleCipherContext *context) -{ - struct HMAC_Context *hctx = purple_cipher_context_get_data(context); - - return hctx->blocksize; -} - -static PurpleCipherOps HMACOps = { - hmac_set_opt, /* Set option */ - hmac_get_opt, /* Get option */ - hmac_init, /* init */ - hmac_reset, /* reset */ - hmac_reset_state, /* reset state */ - hmac_uninit, /* uninit */ - NULL, /* set iv */ - hmac_append, /* append */ - hmac_digest, /* digest */ - hmac_get_digest_size, /* get digest size */ - NULL, /* encrypt */ - NULL, /* decrypt */ - NULL, /* set salt */ - NULL, /* get salt size */ - hmac_set_key, /* set key */ - NULL, /* get key size */ - NULL, /* set batch mode */ - NULL, /* get batch mode */ - hmac_get_block_size, /* get block size */ - NULL, NULL, NULL, NULL /* reserved */ -}; - -PurpleCipherOps * -purple_hmac_cipher_get_ops(void) { - return &HMACOps; -} -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/ciphers/hmaccipher.c Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,345 @@ +/* + * 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 "hmaccipher.h" + +#include <string.h> + +/******************************************************************************* + * Structs + ******************************************************************************/ +#define PURPLE_HMAC_CIPHER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_HMAC_CIPHER, PurpleHMACCipherPrivate)) + +typedef struct { + PurpleHash *hash; + guchar *ipad; + guchar *opad; +} PurpleHMACCipherPrivate; + +/****************************************************************************** + * Enums + *****************************************************************************/ +enum { + PROP_NONE, + PROP_HASH, + PROP_LAST, +}; + +/******************************************************************************* + * Globals + ******************************************************************************/ +static GObjectClass *parent_class = NULL; + +/******************************************************************************* + * Helpers + ******************************************************************************/ +static void +purple_hmac_cipher_set_hash(PurpleCipher *cipher, + PurpleHash *hash) +{ + PurpleHMACCipherPrivate *priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); + + priv->hash = g_object_ref(G_OBJECT(hash)); + g_object_notify(G_OBJECT(cipher), "hash"); +} + +/******************************************************************************* + * Cipher Stuff + ******************************************************************************/ +static void +purple_hmac_cipher_reset(PurpleCipher *cipher) { + PurpleHMACCipherPrivate *priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); + + if(PURPLE_IS_HASH(priv->hash)) + purple_hash_reset(priv->hash); + + if(priv->ipad) { + g_free(priv->ipad); + priv->ipad = NULL; + } + if(priv->opad) { + g_free(priv->opad); + priv->opad = NULL; + } +} + +static void +purple_hmac_cipher_reset_state(PurpleCipher *cipher) { + PurpleHMACCipherPrivate *priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); + + if(PURPLE_IS_HASH(priv->hash)) { + purple_hash_reset_state(priv->hash); + purple_hash_append(priv->hash, priv->ipad, + purple_hash_get_block_size(priv->hash)); + } +} + +static void +purple_hmac_cipher_append(PurpleCipher *cipher, const guchar *d, size_t l) { + PurpleHMACCipherPrivate *priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); + + g_return_if_fail(PURPLE_IS_HASH(priv->hash)); + + purple_hash_append(priv->hash, d, l); +} + +static gboolean +purple_hmac_cipher_digest(PurpleCipher *cipher, guchar *out, size_t len) +{ + PurpleHMACCipherPrivate *priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); + guchar *digest = NULL; + size_t hash_len, block_size; + gboolean result = FALSE; + + g_return_val_if_fail(PURPLE_IS_HASH(priv->hash), FALSE); + + hash_len = purple_hash_get_digest_size(priv->hash); + g_return_val_if_fail(hash_len > 0, FALSE); + + block_size = purple_hash_get_block_size(priv->hash); + digest = g_malloc(hash_len); + + /* get the digest of the data */ + result = purple_hash_digest(priv->hash, digest, hash_len); + purple_hash_reset(priv->hash); + + if(!result) { + g_free(digest); + + return FALSE; + } + + /* now append the opad and the digest from above */ + purple_hash_append(priv->hash, priv->opad, block_size); + purple_hash_append(priv->hash, digest, hash_len); + + /* do our last digest */ + result = purple_hash_digest(priv->hash, out, len); + + /* cleanup */ + g_free(digest); + + return result; +} + +static size_t +purple_hmac_cipher_get_digest_size(PurpleCipher *cipher) +{ + PurpleHMACCipherPrivate *priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); + + g_return_val_if_fail(priv->hash != NULL, 0); + + return purple_hash_get_digest_size(priv->hash); +} + +static void +purple_hmac_cipher_set_key(PurpleCipher *cipher, const guchar *key, + size_t key_len) +{ + PurpleHMACCipherPrivate *priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); + gint block_size, i; + guchar *full_key; + + g_return_if_fail(priv->hash); + + g_free(priv->ipad); + g_free(priv->opad); + + block_size = purple_hash_get_block_size(priv->hash); + priv->ipad = g_malloc(block_size); + priv->opad = g_malloc(block_size); + + if (key_len > block_size) { + purple_hash_reset(priv->hash); + purple_hash_append(priv->hash, key, key_len); + + key_len = purple_hash_get_digest_size(priv->hash); + full_key = g_malloc(key_len); + purple_hash_digest(priv->hash, full_key, key_len); + } else { + full_key = g_memdup(key, key_len); + } + + if (key_len < block_size) { + full_key = g_realloc(full_key, block_size); + memset(full_key + key_len, 0, block_size - key_len); + } + + for(i = 0; i < block_size; i++) { + priv->ipad[i] = 0x36 ^ full_key[i]; + priv->opad[i] = 0x5c ^ full_key[i]; + } + + g_free(full_key); + + purple_hash_reset(priv->hash); + purple_hash_append(priv->hash, priv->ipad, block_size); +} + +static size_t +purple_hmac_cipher_get_block_size(PurpleCipher *cipher) +{ + PurpleHMACCipherPrivate *priv = NULL; + + g_return_val_if_fail(PURPLE_IS_HMAC_CIPHER(cipher), 0); + + priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); + + return purple_hash_get_block_size(priv->hash); +} + +static const gchar* +purple_hmac_cipher_get_name(PurpleCipher *cipher) +{ + return "hmac"; +} + +/****************************************************************************** + * Object Stuff + *****************************************************************************/ +static void +purple_hmac_cipher_set_property(GObject *obj, guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + PurpleCipher *cipher = PURPLE_CIPHER(obj); + + switch(param_id) { + case PROP_HASH: + purple_hmac_cipher_set_hash(cipher, g_value_get_object(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_hmac_cipher_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleHMACCipher *cipher = PURPLE_HMAC_CIPHER(obj); + + switch(param_id) { + case PROP_HASH: + g_value_set_object(value, + purple_hmac_cipher_get_hash(cipher)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_hmac_cipher_finalize(GObject *obj) { + PurpleCipher *cipher = PURPLE_CIPHER(obj); + PurpleHMACCipherPrivate *priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); + + purple_hmac_cipher_reset(cipher); + + if (priv->hash != NULL) + g_object_unref(priv->hash); + + parent_class->finalize(obj); +} + +static void +purple_hmac_cipher_class_init(PurpleHMACCipherClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + PurpleCipherClass *cipher_class = PURPLE_CIPHER_CLASS(klass); + GParamSpec *pspec; + + parent_class = g_type_class_peek_parent(klass); + + g_type_class_add_private(klass, sizeof(PurpleHMACCipherPrivate)); + + obj_class->finalize = purple_hmac_cipher_finalize; + obj_class->get_property = purple_hmac_cipher_get_property; + obj_class->set_property = purple_hmac_cipher_set_property; + + cipher_class->reset = purple_hmac_cipher_reset; + cipher_class->reset_state = purple_hmac_cipher_reset_state; + cipher_class->append = purple_hmac_cipher_append; + cipher_class->digest = purple_hmac_cipher_digest; + cipher_class->get_digest_size = purple_hmac_cipher_get_digest_size; + cipher_class->set_key = purple_hmac_cipher_set_key; + cipher_class->get_block_size = purple_hmac_cipher_get_block_size; + cipher_class->get_name = purple_hmac_cipher_get_name; + + pspec = g_param_spec_object("hash", "hash", "hash", PURPLE_TYPE_HASH, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property(obj_class, PROP_HASH, pspec); +} + +/****************************************************************************** + * PurpleHMACCipher API + *****************************************************************************/ +GType +purple_hmac_cipher_get_gtype(void) { + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleHMACCipherClass), + NULL, + NULL, + (GClassInitFunc)purple_hmac_cipher_class_init, + NULL, + NULL, + sizeof(PurpleHMACCipher), + 0, + (GInstanceInitFunc)purple_cipher_reset, + NULL, + }; + + type = g_type_register_static(PURPLE_TYPE_CIPHER, + "PurpleHMACCipher", + &info, 0); + } + + return type; +} + +PurpleCipher * +purple_hmac_cipher_new(PurpleHash *hash) { + g_return_val_if_fail(PURPLE_IS_HASH(hash), NULL); + + return g_object_new(PURPLE_TYPE_HMAC_CIPHER, + "hash", hash, + NULL); +} + +PurpleHash * +purple_hmac_cipher_get_hash(const PurpleHMACCipher *cipher) { + PurpleHMACCipherPrivate *priv = NULL; + + g_return_val_if_fail(PURPLE_IS_HMAC_CIPHER(cipher), NULL); + + priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); + + if(priv && priv->hash) + return priv->hash; + + return NULL; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/ciphers/hmaccipher.h Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,70 @@ +/** + * @file hmac.h Purple HMAC Cipher + * @ingroup core + */ + +/* 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 + */ +#ifndef PURPLE_HMAC_CIPHER_H +#define PURPLE_HMAC_CIPHER_H + +#include "cipher.h" +#include "hash.h" + +#define PURPLE_TYPE_HMAC_CIPHER (purple_hmac_cipher_get_gtype()) +#define PURPLE_HMAC_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_HMAC_CIPHER, PurpleHMACCipher)) +#define PURPLE_HMAC_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_HMAC_CIPHER, PurpleHMACCipherClass)) +#define PURPLE_IS_HMAC_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_HMAC_CIPHER)) +#define PURPLE_IS_HMAC_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_HMAC_CIPHER)) +#define PURPLE_HMAC_CIPHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_HMAC_CIPHER, PurpleHMACCipherClass)) + +typedef struct _PurpleHMACCipher PurpleHMACCipher; +typedef struct _PurpleHMACCipherClass PurpleHMACCipherClass; + +struct _PurpleHMACCipher { + PurpleCipher gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +struct _PurpleHMACCipherClass { + PurpleCipherClass gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType purple_hmac_cipher_get_gtype(void); + +PurpleCipher *purple_hmac_cipher_new(PurpleHash *hash); + +PurpleHash *purple_hmac_cipher_get_hash(const PurpleHMACCipher *cipher); + +G_END_DECLS + +#endif /* PURPLE_HMAC_CIPHER_H */
--- a/libpurple/ciphers/md4.c Sun Jun 23 02:43:06 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,306 +0,0 @@ -/* - * 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. - * - * Original md4 taken from linux kernel - * MD4 Message Digest Algorithm (RFC1320). - * - * Implementation derived from Andrew Tridgell and Steve French's - * CIFS MD4 implementation, and the cryptoapi implementation - * originally based on the public domain implementation written - * by Colin Plumb in 1993. - * - * Copyright (c) Andrew Tridgell 1997-1998. - * Modified by Steve French (sfrench@us.ibm.com) 2002 - * Copyright (c) Cryptoapi developers. - * Copyright (c) 2002 David S. Miller (davem@redhat.com) - * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> - * - * 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 "internal.h" -#include <cipher.h> -#include "ciphers.h" - -#define MD4_DIGEST_SIZE 16 -#define MD4_HMAC_BLOCK_SIZE 64 -#define MD4_BLOCK_WORDS 16 -#define MD4_HASH_WORDS 4 - -struct MD4_Context { - guint32 hash[MD4_HASH_WORDS]; - guint32 block[MD4_BLOCK_WORDS]; - guint64 byte_count; -}; - -static inline guint32 lshift(guint32 x, unsigned int s) -{ - x &= 0xFFFFFFFF; - return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s)); -} - -static inline guint32 F(guint32 x, guint32 y, guint32 z) -{ - return (x & y) | ((~x) & z); -} - -static inline guint32 G(guint32 x, guint32 y, guint32 z) -{ - return (x & y) | (x & z) | (y & z); -} - -static inline guint32 H(guint32 x, guint32 y, guint32 z) -{ - return x ^ y ^ z; -} - -#define ROUND1(a,b,c,d,k,s) (a = lshift(a + F(b,c,d) + k, s)) -#define ROUND2(a,b,c,d,k,s) (a = lshift(a + G(b,c,d) + k + (guint32)0x5A827999,s)) -#define ROUND3(a,b,c,d,k,s) (a = lshift(a + H(b,c,d) + k + (guint32)0x6ED9EBA1,s)) - -static inline void le32_to_cpu_array(guint32 *buf, unsigned int words) -{ - while (words--) { - *buf=GUINT_FROM_LE(*buf); - buf++; - } -} - -static inline void cpu_to_le32_array(guint32 *buf, unsigned int words) -{ - while (words--) { - *buf=GUINT_TO_LE(*buf); - buf++; - } -} - -static void md4_transform(guint32 *hash, guint32 const *in) -{ - guint32 a, b, c, d; - - a = hash[0]; - b = hash[1]; - c = hash[2]; - d = hash[3]; - - ROUND1(a, b, c, d, in[0], 3); - ROUND1(d, a, b, c, in[1], 7); - ROUND1(c, d, a, b, in[2], 11); - ROUND1(b, c, d, a, in[3], 19); - ROUND1(a, b, c, d, in[4], 3); - ROUND1(d, a, b, c, in[5], 7); - ROUND1(c, d, a, b, in[6], 11); - ROUND1(b, c, d, a, in[7], 19); - ROUND1(a, b, c, d, in[8], 3); - ROUND1(d, a, b, c, in[9], 7); - ROUND1(c, d, a, b, in[10], 11); - ROUND1(b, c, d, a, in[11], 19); - ROUND1(a, b, c, d, in[12], 3); - ROUND1(d, a, b, c, in[13], 7); - ROUND1(c, d, a, b, in[14], 11); - ROUND1(b, c, d, a, in[15], 19); - - ROUND2(a, b, c, d,in[ 0], 3); - ROUND2(d, a, b, c, in[4], 5); - ROUND2(c, d, a, b, in[8], 9); - ROUND2(b, c, d, a, in[12], 13); - ROUND2(a, b, c, d, in[1], 3); - ROUND2(d, a, b, c, in[5], 5); - ROUND2(c, d, a, b, in[9], 9); - ROUND2(b, c, d, a, in[13], 13); - ROUND2(a, b, c, d, in[2], 3); - ROUND2(d, a, b, c, in[6], 5); - ROUND2(c, d, a, b, in[10], 9); - ROUND2(b, c, d, a, in[14], 13); - ROUND2(a, b, c, d, in[3], 3); - ROUND2(d, a, b, c, in[7], 5); - ROUND2(c, d, a, b, in[11], 9); - ROUND2(b, c, d, a, in[15], 13); - - ROUND3(a, b, c, d,in[ 0], 3); - ROUND3(d, a, b, c, in[8], 9); - ROUND3(c, d, a, b, in[4], 11); - ROUND3(b, c, d, a, in[12], 15); - ROUND3(a, b, c, d, in[2], 3); - ROUND3(d, a, b, c, in[10], 9); - ROUND3(c, d, a, b, in[6], 11); - ROUND3(b, c, d, a, in[14], 15); - ROUND3(a, b, c, d, in[1], 3); - ROUND3(d, a, b, c, in[9], 9); - ROUND3(c, d, a, b, in[5], 11); - ROUND3(b, c, d, a, in[13], 15); - ROUND3(a, b, c, d, in[3], 3); - ROUND3(d, a, b, c, in[11], 9); - ROUND3(c, d, a, b, in[7], 11); - ROUND3(b, c, d, a, in[15], 15); - - hash[0] += a; - hash[1] += b; - hash[2] += c; - hash[3] += d; -} - -static inline void md4_transform_helper(struct MD4_Context *ctx) -{ - le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(guint32)); - md4_transform(ctx->hash, ctx->block); -} - -static void -md4_init(PurpleCipherContext *context, gpointer extra) { - struct MD4_Context *mctx; - mctx = g_new0(struct MD4_Context, 1); - purple_cipher_context_set_data(context, mctx); - purple_cipher_context_reset(context, extra); - - mctx->hash[0] = 0x67452301; - mctx->hash[1] = 0xefcdab89; - mctx->hash[2] = 0x98badcfe; - mctx->hash[3] = 0x10325476; - mctx->byte_count = 0; -} - -static void -md4_reset(PurpleCipherContext *context, gpointer extra) { - struct MD4_Context *mctx; - - mctx = purple_cipher_context_get_data(context); - - mctx->hash[0] = 0x67452301; - mctx->hash[1] = 0xefcdab89; - mctx->hash[2] = 0x98badcfe; - mctx->hash[3] = 0x10325476; - mctx->byte_count = 0; -} - - static void -md4_append(PurpleCipherContext *context, const guchar *data, size_t len) -{ - struct MD4_Context *mctx = purple_cipher_context_get_data(context); - const guint32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f); - - mctx->byte_count += len; - - if (avail > len) { - memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), - data, len); - return; - } - - memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), - data, avail); - - md4_transform_helper(mctx); - data += avail; - len -= avail; - - while (len >= sizeof(mctx->block)) { - memcpy(mctx->block, data, sizeof(mctx->block)); - md4_transform_helper(mctx); - data += sizeof(mctx->block); - len -= sizeof(mctx->block); - } - - memcpy(mctx->block, data, len); -} - - static gboolean -md4_digest(PurpleCipherContext *context, guchar *out, size_t len) -{ - struct MD4_Context *mctx = purple_cipher_context_get_data(context); - const unsigned int offset = mctx->byte_count & 0x3f; - char *p = (char *)mctx->block + offset; - int padding = 56 - (offset + 1); - - - if(len<16) return FALSE; - *p++ = 0x80; - if (padding < 0) { - memset(p, 0x00, padding + sizeof (guint64)); - md4_transform_helper(mctx); - p = (char *)mctx->block; - padding = 56; - } - - memset(p, 0, padding); - mctx->block[14] = mctx->byte_count << 3; - mctx->block[15] = mctx->byte_count >> 29; - le32_to_cpu_array(mctx->block, (sizeof(mctx->block) - - sizeof(guint64)) / sizeof(guint32)); - md4_transform(mctx->hash, mctx->block); - cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(guint32)); - memcpy(out, mctx->hash, sizeof(mctx->hash)); - memset(mctx, 0, sizeof(*mctx)); - return TRUE; -} - - static size_t -md4_get_digest_size(PurpleCipherContext *context) -{ - return 16; -} - -static void -md4_uninit(PurpleCipherContext *context) { - struct MD4_Context *md4_context; - - purple_cipher_context_reset(context, NULL); - - md4_context = purple_cipher_context_get_data(context); - memset(md4_context, 0, sizeof(*md4_context)); - - g_free(md4_context); - md4_context = NULL; -} - - static size_t -md4_get_block_size(PurpleCipherContext *context) -{ - /* This does not change (in this case) */ - return MD4_HMAC_BLOCK_SIZE; -} - -static PurpleCipherOps MD4Ops = { - NULL, /* Set option */ - NULL, /* Get option */ - md4_init, /* init */ - md4_reset, /* reset */ - md4_reset, /* reset state */ - md4_uninit, /* uninit */ - NULL, /* set iv */ - md4_append, /* append */ - md4_digest, /* digest */ - md4_get_digest_size, /* get digest size */ - NULL, /* encrypt */ - NULL, /* decrypt */ - NULL, /* set salt */ - NULL, /* get salt size */ - NULL, /* set key */ - NULL, /* get key size */ - NULL, /* set batch mode */ - NULL, /* get batch mode */ - md4_get_block_size, /* get block size */ - NULL, NULL, NULL, NULL /* reserved */ -}; - -PurpleCipherOps * -purple_md4_cipher_get_ops(void) { - return &MD4Ops; -} -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/ciphers/md4hash.c Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,317 @@ +/* + * Original md4 taken from linux kernel + * MD4 Message Digest Algorithm (RFC1320). + * + * Implementation derived from Andrew Tridgell and Steve French's + * CIFS MD4 implementation, and the cryptoapi implementation + * originally based on the public domain implementation written + * by Colin Plumb in 1993. + * + * Copyright (c) Andrew Tridgell 1997-1998. + * Modified by Steve French (sfrench@us.ibm.com) 2002 + * Copyright (c) Cryptoapi developers. + * Copyright (c) 2002 David S. Miller (davem@redhat.com) + * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> + */ +#include "md4hash.h" + +#include <string.h> + +#define MD4_DIGEST_SIZE 16 +#define MD4_BLOCK_WORDS 16 +#define MD4_HASH_WORDS 4 + +#define PURPLE_MD4_HASH_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_MD4_HASH, PurpleMD4HashPrivate)) + +/****************************************************************************** + * Structs + *****************************************************************************/ +typedef struct { + guint32 hash[MD4_HASH_WORDS]; + guint32 block[MD4_BLOCK_WORDS]; + guint64 byte_count; +} PurpleMD4HashPrivate; + +/****************************************************************************** + * Globals + *****************************************************************************/ +static GObjectClass *parent_class = NULL; + +/****************************************************************************** + * Helpers + *****************************************************************************/ +#define ROUND1(a,b,c,d,k,s) \ + (a = lshift(a + F(b,c,d) + k, s)) + +#define ROUND2(a,b,c,d,k,s) \ + (a = lshift(a + G(b,c,d) + k + (guint32)0x5a827999,s)) + +#define ROUND3(a,b,c,d,k,s) \ + (a = lshift(a + H(b,c,d) + k + (guint32)0x6ed9eba1,s)) + +static inline guint32 +lshift(guint32 x, unsigned int s) { + x &= 0xffffffff; + return (((x << s) & 0xffffffff) | (x >> (32 - s))); +} + +static inline guint32 +F(guint32 x, guint32 y, guint32 z) { + return ((x & y) | ((~x) & z)); +} + +static inline guint32 +G(guint32 x, guint32 y, guint32 z) { + return ((x & y) | (x & z) | (y & z)); +} + +static inline guint32 +H(guint32 x, guint32 y, guint32 z) { + return (x ^ y ^ z); +} + +static inline void +le32_to_cpu_array(guint32 *buf, unsigned int words) { + while(words--) { + *buf = GUINT_FROM_LE(*buf); + buf++; + } +} + +static inline void +cpu_to_le32_array(guint32 *buf, unsigned int words) { + while(words--) { + *buf = GUINT_TO_LE(*buf); + buf++; + } +} + +static void +md4_transform(guint32 *hash, guint32 const *in) { + guint32 a, b, c, d; + + a = hash[0]; + b = hash[1]; + c = hash[2]; + d = hash[3]; + + ROUND1(a, b, c, d, in[0], 3); + ROUND1(d, a, b, c, in[1], 7); + ROUND1(c, d, a, b, in[2], 11); + ROUND1(b, c, d, a, in[3], 19); + ROUND1(a, b, c, d, in[4], 3); + ROUND1(d, a, b, c, in[5], 7); + ROUND1(c, d, a, b, in[6], 11); + ROUND1(b, c, d, a, in[7], 19); + ROUND1(a, b, c, d, in[8], 3); + ROUND1(d, a, b, c, in[9], 7); + ROUND1(c, d, a, b, in[10], 11); + ROUND1(b, c, d, a, in[11], 19); + ROUND1(a, b, c, d, in[12], 3); + ROUND1(d, a, b, c, in[13], 7); + ROUND1(c, d, a, b, in[14], 11); + ROUND1(b, c, d, a, in[15], 19); + + ROUND2(a, b, c, d,in[ 0], 3); + ROUND2(d, a, b, c, in[4], 5); + ROUND2(c, d, a, b, in[8], 9); + ROUND2(b, c, d, a, in[12], 13); + ROUND2(a, b, c, d, in[1], 3); + ROUND2(d, a, b, c, in[5], 5); + ROUND2(c, d, a, b, in[9], 9); + ROUND2(b, c, d, a, in[13], 13); + ROUND2(a, b, c, d, in[2], 3); + ROUND2(d, a, b, c, in[6], 5); + ROUND2(c, d, a, b, in[10], 9); + ROUND2(b, c, d, a, in[14], 13); + ROUND2(a, b, c, d, in[3], 3); + ROUND2(d, a, b, c, in[7], 5); + ROUND2(c, d, a, b, in[11], 9); + ROUND2(b, c, d, a, in[15], 13); + + ROUND3(a, b, c, d,in[ 0], 3); + ROUND3(d, a, b, c, in[8], 9); + ROUND3(c, d, a, b, in[4], 11); + ROUND3(b, c, d, a, in[12], 15); + ROUND3(a, b, c, d, in[2], 3); + ROUND3(d, a, b, c, in[10], 9); + ROUND3(c, d, a, b, in[6], 11); + ROUND3(b, c, d, a, in[14], 15); + ROUND3(a, b, c, d, in[1], 3); + ROUND3(d, a, b, c, in[9], 9); + ROUND3(c, d, a, b, in[5], 11); + ROUND3(b, c, d, a, in[13], 15); + ROUND3(a, b, c, d, in[3], 3); + ROUND3(d, a, b, c, in[11], 9); + ROUND3(c, d, a, b, in[7], 11); + ROUND3(b, c, d, a, in[15], 15); + + hash[0] += a; + hash[1] += b; + hash[2] += c; + hash[3] += d; +} + +static inline void +md4_transform_helper(PurpleHash *hash) { + PurpleMD4HashPrivate *priv = PURPLE_MD4_HASH_GET_PRIVATE(hash); + + le32_to_cpu_array(priv->block, sizeof(priv->block) / sizeof(guint32)); + md4_transform(priv->hash, priv->block); +} + +/****************************************************************************** + * Hash Stuff + *****************************************************************************/ +static void +purple_md4_hash_reset(PurpleHash *hash) { + PurpleMD4HashPrivate *priv = PURPLE_MD4_HASH_GET_PRIVATE(hash); + + priv->hash[0] = 0x67452301; + priv->hash[1] = 0xefcdab89; + priv->hash[2] = 0x98badcfe; + priv->hash[3] = 0x10325476; + + priv->byte_count = 0; + + memset(priv->block, 0, sizeof(priv->block)); +} + +static void +purple_md4_hash_append(PurpleHash *hash, const guchar *data, size_t len) { + PurpleMD4HashPrivate *priv = PURPLE_MD4_HASH_GET_PRIVATE(hash); + const guint32 avail = sizeof(priv->block) - (priv->byte_count & 0x3f); + + priv->byte_count += len; + + if(avail > len) { + memcpy((char *)priv->block + + (sizeof(priv->block) - avail), + data, len); + return; + } + + memcpy((char *)priv->block + + (sizeof(priv->block) - avail), + data, avail); + + md4_transform_helper(hash); + data += avail; + len -= avail; + + while(len >= sizeof(priv->block)) { + memcpy(priv->block, data, sizeof(priv->block)); + md4_transform_helper(hash); + data += sizeof(priv->block); + len -= sizeof(priv->block); + } + + memcpy(priv->block, data, len); +} + +static gboolean +purple_md4_hash_digest(PurpleHash *hash, guchar *out, size_t len) +{ + PurpleMD4HashPrivate *priv = PURPLE_MD4_HASH_GET_PRIVATE(hash); + const unsigned int offset = priv->byte_count & 0x3f; + gchar *p = (gchar *)priv->block + offset; + gint padding = 56 - (offset + 1); + + if(len < 16) + return FALSE; + + *p++ = 0x80; + + if(padding < 0) { + memset(p, 0x00, padding + sizeof(guint64)); + md4_transform_helper(hash); + p = (gchar *)priv->block; + padding = 56; + } + + memset(p, 0, padding); + priv->block[14] = priv->byte_count << 3; + priv->block[15] = priv->byte_count >> 29; + le32_to_cpu_array(priv->block, + (sizeof(priv->block) - sizeof(guint64)) / + sizeof(guint32)); + md4_transform(priv->hash, priv->block); + cpu_to_le32_array(priv->hash, sizeof(priv->hash) / sizeof(guint32)); + memcpy(out, priv->hash, sizeof(priv->hash)); + + return TRUE; +} + +static size_t +purple_md4_hash_get_digest_size(PurpleHash *hash) +{ + return 16; +} + +static size_t +purple_md4_hash_get_block_size(PurpleHash *hash) +{ + /* This does not change (in this case) */ + return 64; +} + +static const gchar* +purple_md4_hash_get_name(PurpleHash *hash) +{ + return "md4"; +} + +/****************************************************************************** + * Object Stuff + *****************************************************************************/ +static void +purple_md4_hash_class_init(PurpleMD4HashClass *klass) { + PurpleHashClass *hash_class = PURPLE_HASH_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + g_type_class_add_private(klass, sizeof(PurpleMD4HashPrivate)); + + hash_class->reset = purple_md4_hash_reset; + hash_class->reset_state = purple_md4_hash_reset; + hash_class->append = purple_md4_hash_append; + hash_class->digest = purple_md4_hash_digest; + hash_class->get_digest_size = purple_md4_hash_get_digest_size; + hash_class->get_block_size = purple_md4_hash_get_block_size; + hash_class->get_name = purple_md4_hash_get_name; +} + +/****************************************************************************** + * API + *****************************************************************************/ +GType +purple_md4_hash_get_gtype(void) { + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleMD4HashClass), + NULL, + NULL, + (GClassInitFunc)purple_md4_hash_class_init, + NULL, + NULL, + sizeof(PurpleMD4Hash), + 0, + (GInstanceInitFunc)purple_hash_reset, + NULL, + }; + + type = g_type_register_static(PURPLE_TYPE_HASH, + "PurpleMD4Hash", + &info, 0); + } + + return type; +} + +PurpleHash * +purple_md4_hash_new(void) { + return g_object_new(PURPLE_TYPE_MD4_HASH, NULL); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/ciphers/md4hash.h Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,66 @@ +/** + * @file md4.h Purple MD4 hash + * @ingroup core + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef PURPLE_MD4_HASH_H +#define PURPLE_MD4_HASH_H + +#include "hash.h" + +#define PURPLE_TYPE_MD4_HASH (purple_md4_hash_get_gtype()) +#define PURPLE_MD4_HASH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_MD4_HASH, PurpleMD4Hash)) +#define PURPLE_MD4_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_MD4_HASH, PurpleMD4HashClass)) +#define PURPLE_IS_MD4_HASH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_MD4_HASH)) +#define PURPLE_IS_MD4_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_MD4_HASH)) +#define PURPLE_MD4_HASH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_MD4_HASH, PurpleMD4HashClass)) + +typedef struct _PurpleMD4Hash PurpleMD4Hash; +typedef struct _PurpleMD4HashClass PurpleMD4HashClass; + +struct _PurpleMD4Hash { + PurpleHash parent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +struct _PurpleMD4HashClass { + PurpleHashClass parent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType purple_md4_hash_get_gtype(void); + +PurpleHash *purple_md4_hash_new(void); + +G_END_DECLS + +#endif /* PURPLE_MD4_HASH_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/ciphers/md5hash.c Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,195 @@ +/* + * 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 "md5hash.h" + +/******************************************************************************* + * Structs + ******************************************************************************/ +#define PURPLE_MD5_HASH_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_MD5_HASH, PurpleMD5HashPrivate)) + +typedef struct { + GChecksum *checksum; +} PurpleMD5HashPrivate; + +/****************************************************************************** + * Globals + *****************************************************************************/ +static GObjectClass *parent_class = NULL; + +/****************************************************************************** + * Hash Stuff + *****************************************************************************/ + +static void +purple_md5_hash_reset(PurpleHash *hash) +{ + PurpleMD5Hash *md5_hash = PURPLE_MD5_HASH(hash); + PurpleMD5HashPrivate *priv = PURPLE_MD5_HASH_GET_PRIVATE(md5_hash); + + g_return_if_fail(priv != NULL); + g_return_if_fail(priv->checksum != NULL); + + g_checksum_reset(priv->checksum); +} + +static void +purple_md5_hash_append(PurpleHash *hash, const guchar *data, + gsize len) +{ + PurpleMD5Hash *md5_hash = PURPLE_MD5_HASH(hash); + PurpleMD5HashPrivate *priv = PURPLE_MD5_HASH_GET_PRIVATE(md5_hash); + + g_return_if_fail(priv != NULL); + g_return_if_fail(priv->checksum != NULL); + + while (len >= G_MAXSSIZE) { + g_checksum_update(priv->checksum, data, G_MAXSSIZE); + len -= G_MAXSSIZE; + data += G_MAXSSIZE; + } + + if (len) + g_checksum_update(priv->checksum, data, len); +} + +static gboolean +purple_md5_hash_digest(PurpleHash *hash, guchar *digest, size_t buff_len) +{ + PurpleMD5Hash *md5_hash = PURPLE_MD5_HASH(hash); + PurpleMD5HashPrivate *priv = PURPLE_MD5_HASH_GET_PRIVATE(md5_hash); + + const gssize required_len = g_checksum_type_get_length(G_CHECKSUM_MD5); + gsize digest_len = buff_len; + + g_return_val_if_fail(priv != NULL, FALSE); + g_return_val_if_fail(priv->checksum != NULL, FALSE); + g_return_val_if_fail(buff_len >= required_len, FALSE); + + g_checksum_get_digest(priv->checksum, digest, &digest_len); + + if (digest_len != required_len) + return FALSE; + + purple_md5_hash_reset(hash); + + return TRUE; +} + +static size_t +purple_md5_hash_get_block_size(PurpleHash *hash) +{ + return 64; +} + +static size_t +purple_md5_hash_get_digest_size(PurpleHash *hash) +{ + return g_checksum_type_get_length(G_CHECKSUM_MD5); +} + +static const gchar* +purple_md5_hash_get_name(PurpleHash *hash) +{ + return "md5"; +} + +/****************************************************************************** + * Object Stuff + *****************************************************************************/ + +static void +purple_md5_hash_finalize(GObject *obj) +{ + PurpleMD5Hash *md5_hash = PURPLE_MD5_HASH(obj); + PurpleMD5HashPrivate *priv = PURPLE_MD5_HASH_GET_PRIVATE(md5_hash); + + if (priv->checksum) + g_checksum_free(priv->checksum); + + parent_class->finalize(obj); +} + +static void +purple_md5_hash_class_init(PurpleMD5HashClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + PurpleHashClass *hash_class = PURPLE_HASH_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + obj_class->finalize = purple_md5_hash_finalize; + + hash_class->reset = purple_md5_hash_reset; + hash_class->reset_state = purple_md5_hash_reset; + hash_class->append = purple_md5_hash_append; + hash_class->digest = purple_md5_hash_digest; + hash_class->get_digest_size = purple_md5_hash_get_digest_size; + hash_class->get_block_size = purple_md5_hash_get_block_size; + hash_class->get_name = purple_md5_hash_get_name; + + g_type_class_add_private(klass, sizeof(PurpleMD5HashPrivate)); +} + +static void +purple_md5_hash_init(PurpleHash *hash) +{ + PurpleMD5Hash *md5_hash = PURPLE_MD5_HASH(hash); + PurpleMD5HashPrivate *priv = PURPLE_MD5_HASH_GET_PRIVATE(md5_hash); + + priv->checksum = g_checksum_new(G_CHECKSUM_MD5); + + purple_md5_hash_reset(hash); +} + +/****************************************************************************** + * API + *****************************************************************************/ +GType +purple_md5_hash_get_gtype(void) { + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleMD5HashClass), + NULL, + NULL, + (GClassInitFunc)purple_md5_hash_class_init, + NULL, + NULL, + sizeof(PurpleMD5Hash), + 0, + (GInstanceInitFunc)purple_md5_hash_init, + NULL, + }; + + type = g_type_register_static(PURPLE_TYPE_HASH, + "PurpleMD5Hash", + &info, 0); + } + + return type; +} + +PurpleHash * +purple_md5_hash_new(void) { + return g_object_new(PURPLE_TYPE_MD5_HASH, NULL); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/ciphers/md5hash.h Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,67 @@ +/** + * @file md5.h Purple MD5 Hash + * @ingroup core + */ + +/* 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 + */ +#ifndef PURPLE_MD5_HASH_H +#define PURPLE_MD5_HASH_H + +#include "hash.h" + +#define PURPLE_TYPE_MD5_HASH (purple_md5_hash_get_gtype()) +#define PURPLE_MD5_HASH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_MD5_HASH, PurpleMD5Hash)) +#define PURPLE_MD5_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_MD5_HASH, PurpleMD5HashClass)) +#define PURPLE_IS_MD5_HASH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_MD5_HASH)) +#define PURPLE_IS_MD5_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_MD5_HASH)) +#define PURPLE_MD5_HASH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_MD5_HASH, PurpleMD5HashClass)) + +typedef struct _PurpleMD5Hash PurpleMD5Hash; +typedef struct _PurpleMD5HashClass PurpleMD5HashClass; + +struct _PurpleMD5Hash { + PurpleHash gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +struct _PurpleMD5HashClass { + PurpleHashClass gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType purple_md5_hash_get_gtype(void); + +PurpleHash *purple_md5_hash_new(void); + +G_END_DECLS + +#endif /* PURPLE_MD5_HASH_H */
--- a/libpurple/ciphers/pbkdf2.c Sun Jun 23 02:43:06 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,323 +0,0 @@ -/* - * 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 - * - * Written by Tomek Wasilczyk <tomkiewicz@cpw.pidgin.im> - */ - -#include "internal.h" -#include "cipher.h" -#include "ciphers.h" -#include "debug.h" - -/* 1024bit */ -#define PBKDF2_HASH_MAX_LEN 128 - -typedef struct -{ - gchar *hash_func; - guint iter_count; - size_t out_len; - - guchar *salt; - size_t salt_len; - guchar *passphrase; - size_t passphrase_len; -} Pbkdf2Context; - -static void -purple_pbkdf2_init(PurpleCipherContext *context, void *extra) -{ - Pbkdf2Context *ctx_data; - - ctx_data = g_new0(Pbkdf2Context, 1); - purple_cipher_context_set_data(context, ctx_data); - - purple_cipher_context_reset(context, extra); -} - -static void -purple_pbkdf2_uninit(PurpleCipherContext *context) -{ - Pbkdf2Context *ctx_data; - - purple_cipher_context_reset(context, NULL); - - ctx_data = purple_cipher_context_get_data(context); - g_free(ctx_data); - purple_cipher_context_set_data(context, NULL); -} - -static void -purple_pbkdf2_reset(PurpleCipherContext *context, void *extra) -{ - Pbkdf2Context *ctx_data = purple_cipher_context_get_data(context); - - g_return_if_fail(ctx_data != NULL); - - g_free(ctx_data->hash_func); - ctx_data->hash_func = NULL; - ctx_data->iter_count = 1; - ctx_data->out_len = 256; - - purple_cipher_context_reset_state(context, extra); -} - -static void -purple_pbkdf2_reset_state(PurpleCipherContext *context, void *extra) -{ - Pbkdf2Context *ctx_data = purple_cipher_context_get_data(context); - - g_return_if_fail(ctx_data != NULL); - - purple_cipher_context_set_salt(context, NULL, 0); - purple_cipher_context_set_key(context, NULL, 0); -} - -static void -purple_pbkdf2_set_option(PurpleCipherContext *context, const gchar *name, - void *value) -{ - Pbkdf2Context *ctx_data = purple_cipher_context_get_data(context); - - g_return_if_fail(ctx_data != NULL); - - if (g_strcmp0(name, "hash") == 0) { - g_free(ctx_data->hash_func); - ctx_data->hash_func = g_strdup(value); - return; - } - - if (g_strcmp0(name, "iter_count") == 0) { - ctx_data->iter_count = GPOINTER_TO_UINT(value); - return; - } - - if (g_strcmp0(name, "out_len") == 0) { - ctx_data->out_len = GPOINTER_TO_UINT(value); - return; - } - - purple_debug_warning("pbkdf2", "Unknown option: %s\n", - name ? name : "(null)"); -} - -static void * -purple_pbkdf2_get_option(PurpleCipherContext *context, const gchar *name) -{ - Pbkdf2Context *ctx_data = purple_cipher_context_get_data(context); - - g_return_val_if_fail(ctx_data != NULL, NULL); - - if (g_strcmp0(name, "hash") == 0) - return ctx_data->hash_func; - - if (g_strcmp0(name, "iter_count") == 0) - return GUINT_TO_POINTER(ctx_data->iter_count); - - if (g_strcmp0(name, "out_len") == 0) - return GUINT_TO_POINTER(ctx_data->out_len); - - purple_debug_warning("pbkdf2", "Unknown option: %s\n", - name ? name : "(null)"); - return NULL; -} - -static size_t -purple_pbkdf2_get_digest_size(PurpleCipherContext *context) -{ - Pbkdf2Context *ctx_data = purple_cipher_context_get_data(context); - - g_return_val_if_fail(ctx_data != NULL, 0); - - return ctx_data->out_len; -} - -static void -purple_pbkdf2_set_salt(PurpleCipherContext *context, const guchar *salt, size_t len) -{ - Pbkdf2Context *ctx_data = purple_cipher_context_get_data(context); - - g_return_if_fail(ctx_data != NULL); - - g_free(ctx_data->salt); - ctx_data->salt = NULL; - ctx_data->salt_len = 0; - - if (len == 0) - return; - g_return_if_fail(salt != NULL); - - ctx_data->salt = g_memdup(salt, len); - ctx_data->salt_len = len; -} - -static void -purple_pbkdf2_set_key(PurpleCipherContext *context, const guchar *key, - size_t len) -{ - Pbkdf2Context *ctx_data = purple_cipher_context_get_data(context); - - g_return_if_fail(ctx_data != NULL); - - if (ctx_data->passphrase != NULL) { - memset(ctx_data->passphrase, 0, ctx_data->passphrase_len); - g_free(ctx_data->passphrase); - ctx_data->passphrase = NULL; - } - ctx_data->passphrase_len = 0; - - if (len == 0) - return; - g_return_if_fail(key != NULL); - - ctx_data->passphrase = g_memdup(key, len); - ctx_data->passphrase_len = len; -} - -/* inspired by gnutls 3.1.10, pbkdf2-sha1.c */ -static gboolean -purple_pbkdf2_digest(PurpleCipherContext *context, guchar digest[], size_t len) -{ - Pbkdf2Context *ctx_data = purple_cipher_context_get_data(context); - guchar halfkey[PBKDF2_HASH_MAX_LEN], halfkey_hash[PBKDF2_HASH_MAX_LEN]; - guint halfkey_len, halfkey_count, halfkey_pad, halfkey_no; - guchar *salt_ext; - size_t salt_ext_len; - guint iter_no; - PurpleCipherContext *hash; - - g_return_val_if_fail(ctx_data != NULL, FALSE); - g_return_val_if_fail(digest != NULL, FALSE); - g_return_val_if_fail(len >= ctx_data->out_len, FALSE); - - g_return_val_if_fail(ctx_data->hash_func != NULL, FALSE); - g_return_val_if_fail(ctx_data->iter_count > 0, FALSE); - g_return_val_if_fail(ctx_data->passphrase != NULL || - ctx_data->passphrase_len == 0, FALSE); - g_return_val_if_fail(ctx_data->salt != NULL || ctx_data->salt_len == 0, - FALSE); - g_return_val_if_fail(ctx_data->out_len > 0, FALSE); - g_return_val_if_fail(ctx_data->out_len < 0xFFFFFFFFU, FALSE); - - salt_ext_len = ctx_data->salt_len + 4; - - hash = purple_cipher_context_new_by_name("hmac", NULL); - if (hash == NULL) { - purple_debug_error("pbkdf2", "Couldn't create new hmac " - "context\n"); - return FALSE; - } - purple_cipher_context_set_option(hash, "hash", - (void*)ctx_data->hash_func); - purple_cipher_context_set_key(hash, (const guchar*)ctx_data->passphrase, - ctx_data->passphrase_len); - - halfkey_len = purple_cipher_context_get_digest_size(hash); - if (halfkey_len <= 0 || halfkey_len > PBKDF2_HASH_MAX_LEN) { - purple_debug_error("pbkdf2", "Unsupported hash function: %s " - "(digest size: %d)\n", - ctx_data->hash_func ? ctx_data->hash_func : "(null)", - halfkey_len); - return FALSE; - } - - halfkey_count = ((ctx_data->out_len - 1) / halfkey_len) + 1; - halfkey_pad = ctx_data->out_len - (halfkey_count - 1) * halfkey_len; - - salt_ext = g_new(guchar, salt_ext_len); - memcpy(salt_ext, ctx_data->salt, ctx_data->salt_len); - - for (halfkey_no = 1; halfkey_no <= halfkey_count; halfkey_no++) { - memset(halfkey, 0, halfkey_len); - - for (iter_no = 1; iter_no <= ctx_data->iter_count; iter_no++) { - int i; - - purple_cipher_context_reset_state(hash, NULL); - - if (iter_no == 1) { - salt_ext[salt_ext_len - 4] = - (halfkey_no & 0xff000000) >> 24; - salt_ext[salt_ext_len - 3] = - (halfkey_no & 0x00ff0000) >> 16; - salt_ext[salt_ext_len - 2] = - (halfkey_no & 0x0000ff00) >> 8; - salt_ext[salt_ext_len - 1] = - (halfkey_no & 0x000000ff) >> 0; - - purple_cipher_context_append(hash, salt_ext, - salt_ext_len); - } - else - purple_cipher_context_append(hash, halfkey_hash, - halfkey_len); - - if (!purple_cipher_context_digest(hash, halfkey_hash, - halfkey_len)) { - purple_debug_error("pbkdf2", - "Couldn't retrieve a digest\n"); - g_free(salt_ext); - purple_cipher_context_destroy(hash); - return FALSE; - } - - for (i = 0; i < halfkey_len; i++) - halfkey[i] ^= halfkey_hash[i]; - } - - memcpy(digest + (halfkey_no - 1) * halfkey_len, halfkey, - (halfkey_no == halfkey_count) ? halfkey_pad : - halfkey_len); - } - - g_free(salt_ext); - purple_cipher_context_destroy(hash); - - return TRUE; -} - -static PurpleCipherOps PBKDF2Ops = { - purple_pbkdf2_set_option, /* set_option */ - purple_pbkdf2_get_option, /* get_option */ - purple_pbkdf2_init, /* init */ - purple_pbkdf2_reset, /* reset */ - purple_pbkdf2_reset_state, /* reset_state */ - purple_pbkdf2_uninit, /* uninit */ - NULL, /* set_iv */ - NULL, /* append */ - purple_pbkdf2_digest, /* digest */ - purple_pbkdf2_get_digest_size, /* get_digest_size */ - NULL, /* encrypt */ - NULL, /* decrypt */ - purple_pbkdf2_set_salt, /* set_salt */ - NULL, /* get_salt_size */ - purple_pbkdf2_set_key, /* set_key */ - NULL, /* get_key_size */ - NULL, /* set_batch_mode */ - NULL, /* get_batch_mode */ - NULL, /* get_block_size */ - NULL, NULL, NULL, NULL /* reserved */ -}; - -PurpleCipherOps * -purple_pbkdf2_cipher_get_ops(void) { - return &PBKDF2Ops; -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/ciphers/pbkdf2cipher.c Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,418 @@ +/* + * 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 + * + * Written by Tomek Wasilczyk <tomkiewicz@cpw.pidgin.im> + */ + +#include "pbkdf2cipher.h" +#include "hmaccipher.h" +#include "debug.h" + +/* 1024bit */ +#define PBKDF2_HASH_MAX_LEN 128 + +/****************************************************************************** + * Structs + *****************************************************************************/ +#define PURPLE_PBKDF2_CIPHER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_PBKDF2_CIPHER, PurplePBKDF2CipherPrivate)) + +typedef struct { + PurpleHash *hash; + guint iter_count; + size_t out_len; + + guchar *salt; + size_t salt_len; + guchar *passphrase; + size_t passphrase_len; +} PurplePBKDF2CipherPrivate; + +/****************************************************************************** + * Enums + *****************************************************************************/ +enum { + PROP_NONE, + PROP_HASH, + PROP_ITER_COUNT, + PROP_OUT_LEN, + PROP_LAST, +}; + +/******************************************************************************* + * Globals + ******************************************************************************/ +static GObjectClass *parent_class = NULL; + +/******************************************************************************* + * Helpers + ******************************************************************************/ +static void +purple_pbkdf2_cipher_set_hash(PurpleCipher *cipher, + PurpleHash *hash) +{ + PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); + + priv->hash = g_object_ref(G_OBJECT(hash)); + g_object_notify(G_OBJECT(cipher), "hash"); +} + +/****************************************************************************** + * Cipher Stuff + *****************************************************************************/ +static void +purple_pbkdf2_cipher_reset(PurpleCipher *cipher) +{ + PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); + + g_return_if_fail(priv != NULL); + + if(PURPLE_IS_HASH(priv->hash)) + purple_hash_reset(priv->hash); + priv->iter_count = 1; + priv->out_len = 256; + + purple_cipher_reset_state(cipher); +} + +static void +purple_pbkdf2_cipher_reset_state(PurpleCipher *cipher) +{ + PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); + + g_return_if_fail(priv != NULL); + + purple_cipher_set_salt(cipher, NULL, 0); + purple_cipher_set_key(cipher, NULL, 0); +} + +static size_t +purple_pbkdf2_cipher_get_digest_size(PurpleCipher *cipher) +{ + PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); + + g_return_val_if_fail(priv != NULL, 0); + + return priv->out_len; +} + +static void +purple_pbkdf2_cipher_set_salt(PurpleCipher *cipher, const guchar *salt, size_t len) +{ + PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); + + g_return_if_fail(priv != NULL); + + g_free(priv->salt); + priv->salt = NULL; + priv->salt_len = 0; + + if (len == 0) + return; + g_return_if_fail(salt != NULL); + + priv->salt = g_memdup(salt, len); + priv->salt_len = len; +} + +static void +purple_pbkdf2_cipher_set_key(PurpleCipher *cipher, const guchar *key, + size_t len) +{ + PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); + + g_return_if_fail(priv != NULL); + + if (priv->passphrase != NULL) { + memset(priv->passphrase, 0, priv->passphrase_len); + g_free(priv->passphrase); + priv->passphrase = NULL; + } + priv->passphrase_len = 0; + + if (len == 0) + return; + g_return_if_fail(key != NULL); + + priv->passphrase = g_memdup(key, len); + priv->passphrase_len = len; +} + +/* inspired by gnutls 3.1.10, pbkdf2-sha1.c */ +static gboolean +purple_pbkdf2_cipher_digest(PurpleCipher *cipher, guchar digest[], size_t len) +{ + PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); + + guchar halfkey[PBKDF2_HASH_MAX_LEN], halfkey_hash[PBKDF2_HASH_MAX_LEN]; + guint halfkey_len, halfkey_count, halfkey_pad, halfkey_no; + guchar *salt_ext; + size_t salt_ext_len; + guint iter_no; + PurpleCipher *hash; + + g_return_val_if_fail(priv != NULL, FALSE); + g_return_val_if_fail(digest != NULL, FALSE); + g_return_val_if_fail(len >= priv->out_len, FALSE); + + g_return_val_if_fail(priv->hash != NULL, FALSE); + g_return_val_if_fail(priv->iter_count > 0, FALSE); + g_return_val_if_fail(priv->passphrase != NULL || + priv->passphrase_len == 0, FALSE); + g_return_val_if_fail(priv->salt != NULL || priv->salt_len == 0, + FALSE); + g_return_val_if_fail(priv->out_len > 0, FALSE); + g_return_val_if_fail(priv->out_len < 0xFFFFFFFFU, FALSE); + + salt_ext_len = priv->salt_len + 4; + + hash = purple_hmac_cipher_new(priv->hash); + if (hash == NULL) { + purple_debug_error("pbkdf2", "Couldn't create new hmac " + "cipher\n"); + return FALSE; + } + purple_cipher_set_key(hash, (const guchar*)priv->passphrase, + priv->passphrase_len); + + halfkey_len = purple_cipher_get_digest_size(hash); + if (halfkey_len <= 0 || halfkey_len > PBKDF2_HASH_MAX_LEN) { + purple_debug_error("pbkdf2", "Unsupported hash function. " + "(digest size: %d)\n", halfkey_len); + return FALSE; + } + + halfkey_count = ((priv->out_len - 1) / halfkey_len) + 1; + halfkey_pad = priv->out_len - (halfkey_count - 1) * halfkey_len; + + salt_ext = g_new(guchar, salt_ext_len); + memcpy(salt_ext, priv->salt, priv->salt_len); + + for (halfkey_no = 1; halfkey_no <= halfkey_count; halfkey_no++) { + memset(halfkey, 0, halfkey_len); + + for (iter_no = 1; iter_no <= priv->iter_count; iter_no++) { + int i; + + purple_cipher_reset_state(hash); + + if (iter_no == 1) { + salt_ext[salt_ext_len - 4] = + (halfkey_no & 0xff000000) >> 24; + salt_ext[salt_ext_len - 3] = + (halfkey_no & 0x00ff0000) >> 16; + salt_ext[salt_ext_len - 2] = + (halfkey_no & 0x0000ff00) >> 8; + salt_ext[salt_ext_len - 1] = + (halfkey_no & 0x000000ff) >> 0; + + purple_cipher_append(hash, salt_ext, + salt_ext_len); + } + else + purple_cipher_append(hash, halfkey_hash, + halfkey_len); + + if (!purple_cipher_digest(hash, halfkey_hash, + halfkey_len)) { + purple_debug_error("pbkdf2", + "Couldn't retrieve a digest\n"); + g_free(salt_ext); + g_object_unref(hash); + return FALSE; + } + + for (i = 0; i < halfkey_len; i++) + halfkey[i] ^= halfkey_hash[i]; + } + + memcpy(digest + (halfkey_no - 1) * halfkey_len, halfkey, + (halfkey_no == halfkey_count) ? halfkey_pad : + halfkey_len); + } + + g_free(salt_ext); + g_object_unref(hash); + + return TRUE; +} + +static const gchar* +purple_pbkdf2_cipher_get_name(PurpleCipher *cipher) +{ + return "pbkdf2"; +} + +/****************************************************************************** + * Object Stuff + *****************************************************************************/ +static void +purple_pbkdf2_cipher_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurplePBKDF2Cipher *cipher = PURPLE_PBKDF2_CIPHER(obj); + PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); + + switch(param_id) { + case PROP_HASH: + g_value_set_object(value, purple_pbkdf2_cipher_get_hash(cipher)); + break; + case PROP_ITER_COUNT: + g_value_set_uint(value, priv->iter_count); + break; + case PROP_OUT_LEN: + g_value_set_uint(value, priv->out_len); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_pbkdf2_cipher_set_property(GObject *obj, guint param_id, + const GValue *value, GParamSpec *pspec) +{ + PurpleCipher *cipher = PURPLE_CIPHER(obj); + PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); + + switch(param_id) { + case PROP_HASH: + purple_pbkdf2_cipher_set_hash(cipher, g_value_get_object(value)); + break; + case PROP_ITER_COUNT: + priv->iter_count = GPOINTER_TO_UINT(value); + break; + case PROP_OUT_LEN: + priv->out_len = GPOINTER_TO_UINT(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_pbkdf2_cipher_finalize(GObject *obj) +{ + PurpleCipher *cipher = PURPLE_CIPHER(obj); + PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); + + purple_pbkdf2_cipher_reset(cipher); + + if (priv->hash != NULL) + g_object_unref(priv->hash); + + parent_class->finalize(obj); +} + +static void +purple_pbkdf2_cipher_class_init(PurplePBKDF2CipherClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + PurpleCipherClass *cipher_class = PURPLE_CIPHER_CLASS(klass); + GParamSpec *pspec; + + parent_class = g_type_class_peek_parent(klass); + + obj_class->finalize = purple_pbkdf2_cipher_finalize; + obj_class->get_property = purple_pbkdf2_cipher_get_property; + obj_class->set_property = purple_pbkdf2_cipher_set_property; + + cipher_class->reset = purple_pbkdf2_cipher_reset; + cipher_class->reset_state = purple_pbkdf2_cipher_reset_state; + cipher_class->digest = purple_pbkdf2_cipher_digest; + cipher_class->get_digest_size = purple_pbkdf2_cipher_get_digest_size; + cipher_class->set_salt = purple_pbkdf2_cipher_set_salt; + cipher_class->set_key = purple_pbkdf2_cipher_set_key; + cipher_class->get_name = purple_pbkdf2_cipher_get_name; + + pspec = g_param_spec_object("hash", "hash", "hash", PURPLE_TYPE_HASH, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property(obj_class, PROP_HASH, pspec); + + pspec = g_param_spec_uint("iter_count", "iter_count", "iter_count", 0, + G_MAXUINT, 0, G_PARAM_READWRITE); + g_object_class_install_property(obj_class, PROP_ITER_COUNT, pspec); + + pspec = g_param_spec_uint("out_len", "out_len", "out_len", 0, + G_MAXUINT, 0, G_PARAM_READWRITE); + g_object_class_install_property(obj_class, PROP_OUT_LEN, pspec); + + g_type_class_add_private(klass, sizeof(PurplePBKDF2CipherPrivate)); +} + +static void +purple_pbkdf2_cipher_init(PurpleCipher *cipher) +{ + purple_cipher_reset(cipher); +} + +/****************************************************************************** + * API + *****************************************************************************/ +GType +purple_pbkdf2_cipher_get_gtype(void) { + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurplePBKDF2CipherClass), + NULL, + NULL, + (GClassInitFunc)purple_pbkdf2_cipher_class_init, + NULL, + NULL, + sizeof(PurplePBKDF2Cipher), + 0, + (GInstanceInitFunc)purple_pbkdf2_cipher_init, + NULL + }; + + type = g_type_register_static(PURPLE_TYPE_CIPHER, + "PurplePBKDF2Cipher", + &info, 0); + } + + return type; +} + +PurpleCipher * +purple_pbkdf2_cipher_new(PurpleHash *hash) { + g_return_val_if_fail(PURPLE_IS_HASH(hash), NULL); + + return g_object_new(PURPLE_TYPE_PBKDF2_CIPHER, + "hash", hash, + NULL); +} + +PurpleHash * +purple_pbkdf2_cipher_get_hash(const PurplePBKDF2Cipher *cipher) { + PurplePBKDF2CipherPrivate *priv = NULL; + + g_return_val_if_fail(PURPLE_IS_PBKDF2_CIPHER(cipher), NULL); + + priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); + + if(priv && priv->hash) + return priv->hash; + + return NULL; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/ciphers/pbkdf2cipher.h Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,71 @@ +/** + * @file pbkdf2.h Purple PBKDF2 Cipher + * @ingroup core + */ + +/* 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 + */ +#ifndef PURPLE_PBKDF2_CIPHER_H +#define PURPLE_PBKDF2_CIPHER_H + +#include "cipher.h" +#include "hash.h" + +#define PURPLE_TYPE_PBKDF2_CIPHER (purple_pbkdf2_cipher_get_gtype()) +#define PURPLE_PBKDF2_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_PBKDF2_CIPHER, PurplePBKDF2Cipher)) +#define PURPLE_PBKDF2_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_PBKDF2_CIPHER, PurplePBKDF2CipherClass)) +#define PURPLE_IS_PBKDF2_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_PBKDF2_CIPHER)) +#define PURPLE_IS_PBKDF2_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_PBKDF2_CIPHER)) +#define PURPLE_PBKDF2_CIPHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_PBKDF2_CIPHER, PurplePBKDF2CipherClass)) + +typedef struct _PurplePBKDF2Cipher PurplePBKDF2Cipher; +typedef struct _PurplePBKDF2CipherClass PurplePBKDF2CipherClass; + +struct _PurplePBKDF2Cipher { + PurpleCipher gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +struct _PurplePBKDF2CipherClass { + PurpleCipherClass gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType purple_pbkdf2_cipher_get_gtype(void); + +PurpleCipher *purple_pbkdf2_cipher_new(PurpleHash *hash); + +PurpleHash *purple_pbkdf2_cipher_get_hash(const PurplePBKDF2Cipher *cipher); + +G_END_DECLS + +#endif /* PURPLE_PBKDF2_CIPHER_H */ +
--- a/libpurple/ciphers/rc4.c Sun Jun 23 02:43:06 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,159 +0,0 @@ -/* - * 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 "internal.h" -#include <cipher.h> -#include "ciphers.h" -#include <util.h> - -struct RC4Context { - guchar state[256]; - guchar x; - guchar y; - gint key_len; -}; - -static void -rc4_init(PurpleCipherContext *context, void *extra) { - struct RC4Context *rc4_ctx; - rc4_ctx = g_new0(struct RC4Context, 1); - purple_cipher_context_set_data(context, rc4_ctx); - purple_cipher_context_reset(context, extra); -} - - -static void -rc4_reset(PurpleCipherContext *context, void *extra) { - struct RC4Context *rc4_ctx; - guint i; - - rc4_ctx = purple_cipher_context_get_data(context); - - g_return_if_fail(rc4_ctx); - - for(i = 0; i < 256; i++) - rc4_ctx->state[i] = i; - rc4_ctx->x = 0; - rc4_ctx->y = 0; - - /* default is 5 bytes (40bit key) */ - rc4_ctx->key_len = 5; - -} - -static void -rc4_uninit(PurpleCipherContext *context) { - struct RC4Context *rc4_ctx; - - rc4_ctx = purple_cipher_context_get_data(context); - memset(rc4_ctx, 0, sizeof(*rc4_ctx)); - - g_free(rc4_ctx); - rc4_ctx = NULL; -} - - - -static void -rc4_set_key (PurpleCipherContext *context, const guchar * key, size_t len) { - struct RC4Context *ctx; - guchar *state; - guchar temp_swap; - guchar x, y; - guint i; - - ctx = purple_cipher_context_get_data(context); - - x = 0; - y = 0; - state = &ctx->state[0]; - ctx->key_len = len; - for(i = 0; i < 256; i++) - { - y = (key[x] + state[i] + y) % 256; - temp_swap = state[i]; - state[i] = state[y]; - state[y] = temp_swap; - x = (x + 1) % len; - } -} - - -static ssize_t -rc4_encrypt(PurpleCipherContext *context, const guchar input[], size_t in_len, - guchar output[], size_t out_size) { - struct RC4Context *ctx; - guchar temp_swap; - guchar x, y, z; - guchar *state; - guint i; - - ctx = purple_cipher_context_get_data(context); - - x = ctx->x; - y = ctx->y; - state = &ctx->state[0]; - - for(i = 0; i < in_len; i++) - { - x = (x + 1) % 256; - y = (state[x] + y) % 256; - temp_swap = state[x]; - state[x] = state[y]; - state[y] = temp_swap; - z = state[x] + (state[y]) % 256; - output[i] = input[i] ^ state[z]; - } - ctx->x = x; - ctx->y = y; - - return in_len; -} - -static PurpleCipherOps RC4Ops = { - NULL, /* Set Option */ - NULL, /* Get Option */ - rc4_init, /* init */ - rc4_reset, /* reset */ - NULL, /* reset state */ - rc4_uninit, /* uninit */ - NULL, /* set iv */ - NULL, /* append */ - NULL, /* digest */ - NULL, /* get digest size */ - rc4_encrypt, /* encrypt */ - NULL, /* decrypt */ - NULL, /* set salt */ - NULL, /* get salt size */ - rc4_set_key, /* set key */ - NULL, /* get key size */ - NULL, /* set batch mode */ - NULL, /* get batch mode */ - NULL, /* get block size */ - NULL, NULL, NULL, NULL /* reserved */ -}; - -PurpleCipherOps * -purple_rc4_cipher_get_ops(void) { - return &RC4Ops; -} -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/ciphers/rc4cipher.c Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,266 @@ +/* + * 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 "rc4cipher.h" + +/******************************************************************************* + * Structs + ******************************************************************************/ +#define PURPLE_RC4_CIPHER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_RC4_CIPHER, PurpleRC4CipherPrivate)) + +typedef struct { + guchar state[256]; + guchar x; + guchar y; + gint key_len; +} PurpleRC4CipherPrivate; + +/****************************************************************************** + * Enums + *****************************************************************************/ +enum { + PROP_ZERO, + PROP_KEY_LEN, + PROP_KEY, + PROP_LAST, +}; + +/****************************************************************************** + * Globals + *****************************************************************************/ +static GObjectClass *parent_class = NULL; + +/****************************************************************************** + * Cipher Stuff + *****************************************************************************/ +static void +purple_rc4_cipher_reset(PurpleCipher *cipher) { + PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(cipher); + PurpleRC4CipherPrivate *priv = PURPLE_RC4_CIPHER_GET_PRIVATE(rc4_cipher); + guint i; + + for(i = 0; i < 256; i++) + priv->state[i] = i; + priv->x = 0; + priv->y = 0; + + /* default is 5 bytes (40bit key) */ + priv->key_len = 5; +} + +static void +purple_rc4_cipher_set_key(PurpleCipher *cipher, const guchar *key, size_t len) { + PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(cipher); + PurpleRC4CipherPrivate *priv = PURPLE_RC4_CIPHER_GET_PRIVATE(rc4_cipher); + guchar *state; + guchar temp_swap; + guchar x, y; + guint i; + + x = 0; + y = 0; + state = &priv->state[0]; + priv->key_len = len; + for(i = 0; i < 256; i++) + { + y = (key[x] + state[i] + y) % 256; + temp_swap = state[i]; + state[i] = state[y]; + state[y] = temp_swap; + x = (x + 1) % len; + } + + g_object_notify(G_OBJECT(rc4_cipher), "key"); +} + +static ssize_t +purple_rc4_cipher_encrypt(PurpleCipher *cipher, const guchar input[], size_t in_len, + guchar output[], size_t out_size) +{ + PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(cipher); + guchar temp_swap; + guchar x, y, z; + guchar *state; + guint i; + PurpleRC4CipherPrivate *priv = PURPLE_RC4_CIPHER_GET_PRIVATE(rc4_cipher); + + x = priv->x; + y = priv->y; + state = &priv->state[0]; + + for(i = 0; i < in_len; i++) + { + x = (x + 1) % 256; + y = (state[x] + y) % 256; + temp_swap = state[x]; + state[x] = state[y]; + state[y] = temp_swap; + z = state[x] + (state[y]) % 256; + output[i] = input[i] ^ state[z]; + } + priv->x = x; + priv->y = y; + + return in_len; +} + +static const gchar* +purple_rc4_cipher_get_name(PurpleCipher *cipher) +{ + return "rc4"; +} + +/****************************************************************************** + * Object Stuff + *****************************************************************************/ +static void +purple_rc4_cipher_set_property(GObject *obj, guint param_id, + const GValue *value, GParamSpec *pspec) +{ + PurpleCipher *cipher = PURPLE_CIPHER(obj); + PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(obj); + + switch(param_id) { + case PROP_KEY_LEN: + purple_rc4_cipher_set_key_len(rc4_cipher, g_value_get_int(value)); + break; + case PROP_KEY: + { + guchar *key = (guchar *)g_value_get_string(value); + purple_rc4_cipher_set_key(cipher, key, strlen((gchar *) key)); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_rc4_cipher_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(obj); + + switch(param_id) { + case PROP_KEY_LEN: + g_value_set_int(value, + purple_rc4_cipher_get_key_len(rc4_cipher)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_rc4_cipher_class_init(PurpleRC4CipherClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + PurpleCipherClass *cipher_class = PURPLE_CIPHER_CLASS(klass); + GParamSpec *pspec = NULL; + + parent_class = g_type_class_peek_parent(klass); + + obj_class->set_property = purple_rc4_cipher_set_property; + obj_class->get_property = purple_rc4_cipher_get_property; + + cipher_class->reset = purple_rc4_cipher_reset; + cipher_class->encrypt = purple_rc4_cipher_encrypt; + cipher_class->set_key = purple_rc4_cipher_set_key; + cipher_class->get_name = purple_rc4_cipher_get_name; + + pspec = g_param_spec_int("key_len", "key_len", "key_len", + G_MININT, G_MAXINT, 0, + G_PARAM_READWRITE); + g_object_class_install_property(obj_class, PROP_KEY_LEN, pspec); + + pspec = g_param_spec_string("key", "key", "key", NULL, + G_PARAM_WRITABLE); + g_object_class_install_property(obj_class, PROP_KEY, pspec); + + g_type_class_add_private(klass, sizeof(PurpleRC4CipherPrivate)); +} + +static void +purple_rc4_cipher_init(PurpleCipher *cipher) { + purple_rc4_cipher_reset(cipher); +} + +/****************************************************************************** + * API + *****************************************************************************/ +GType +purple_rc4_cipher_get_gtype(void) { + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleRC4CipherClass), + NULL, + NULL, + (GClassInitFunc)purple_rc4_cipher_class_init, + NULL, + NULL, + sizeof(PurpleRC4Cipher), + 0, + (GInstanceInitFunc)purple_rc4_cipher_init, + NULL, + }; + + type = g_type_register_static(PURPLE_TYPE_CIPHER, + "PurpleRC4Cipher", + &info, 0); + } + + return type; +} + +PurpleCipher * +purple_rc4_cipher_new(void) { + return g_object_new(PURPLE_TYPE_RC4_CIPHER, NULL); +} + +void +purple_rc4_cipher_set_key_len(PurpleRC4Cipher *rc4_cipher, + gint key_len) +{ + PurpleRC4CipherPrivate *priv; + + g_return_if_fail(PURPLE_IS_RC4_CIPHER(rc4_cipher)); + + priv = PURPLE_RC4_CIPHER_GET_PRIVATE(rc4_cipher); + priv->key_len = key_len; + + g_object_notify(G_OBJECT(rc4_cipher), "key_len"); +} + +gint +purple_rc4_cipher_get_key_len(PurpleRC4Cipher *rc4_cipher) +{ + PurpleRC4CipherPrivate *priv; + + g_return_val_if_fail(PURPLE_IS_RC4_CIPHER(rc4_cipher), 0); + + priv = PURPLE_RC4_CIPHER_GET_PRIVATE(rc4_cipher); + + return priv->key_len; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/ciphers/rc4cipher.h Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,72 @@ +/** + * @file rc4.h Purple RC4 Cipher + * @ingroup core + */ + +/* 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 + */ +#ifndef PURPLE_RC4_CIPHER_H +#define PURPLE_RC4_CIPHER_H + +#include "cipher.h" + +#define PURPLE_TYPE_RC4_CIPHER (purple_rc4_cipher_get_gtype()) +#define PURPLE_RC4_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_RC4_CIPHER, PurpleRC4Cipher)) +#define PURPLE_RC4_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_RC4_CIPHER, PurpleRC4CipherClass)) +#define PURPLE_IS_RC4_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_RC4_CIPHER)) +#define PURPLE_IS_RC4_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_RC4_CIPHER)) +#define PURPLE_RC4_CIPHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_RC4_CIPHER, PurpleRC4CipherClass)) + +typedef struct _PurpleRC4Cipher PurpleRC4Cipher; +typedef struct _PurpleRC4CipherClass PurpleRC4CipherClass; + +struct _PurpleRC4Cipher { + PurpleCipher gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +struct _PurpleRC4CipherClass { + PurpleCipherClass gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType purple_rc4_cipher_get_gtype(void); + +PurpleCipher *purple_rc4_cipher_new(void); + +gint purple_rc4_cipher_get_key_len(PurpleRC4Cipher *rc4_cipher); +void purple_rc4_cipher_set_key_len(PurpleRC4Cipher *rc4_cipher, gint key_len); + +G_END_DECLS + +#endif /* PURPLE_RC4_CIPHER_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/ciphers/sha1hash.c Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,195 @@ +/* + * 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 "sha1hash.h" + +/******************************************************************************* + * Structs + ******************************************************************************/ +#define PURPLE_SHA1_HASH_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_SHA1_HASH, PurpleSHA1HashPrivate)) + +typedef struct { + GChecksum *checksum; +} PurpleSHA1HashPrivate; + +/****************************************************************************** + * Globals + *****************************************************************************/ +static GObjectClass *parent_class = NULL; + +/****************************************************************************** + * Hash Stuff + *****************************************************************************/ + +static void +purple_sha1_hash_reset(PurpleHash *hash) +{ + PurpleSHA1Hash *sha1_hash = PURPLE_SHA1_HASH(hash); + PurpleSHA1HashPrivate *priv = PURPLE_SHA1_HASH_GET_PRIVATE(sha1_hash); + + g_return_if_fail(priv != NULL); + g_return_if_fail(priv->checksum != NULL); + + g_checksum_reset(priv->checksum); +} + +static void +purple_sha1_hash_append(PurpleHash *hash, const guchar *data, + gsize len) +{ + PurpleSHA1Hash *sha1_hash = PURPLE_SHA1_HASH(hash); + PurpleSHA1HashPrivate *priv = PURPLE_SHA1_HASH_GET_PRIVATE(sha1_hash); + + g_return_if_fail(priv != NULL); + g_return_if_fail(priv->checksum != NULL); + + while (len >= G_MAXSSIZE) { + g_checksum_update(priv->checksum, data, G_MAXSSIZE); + len -= G_MAXSSIZE; + data += G_MAXSSIZE; + } + + if (len) + g_checksum_update(priv->checksum, data, len); +} + +static gboolean +purple_sha1_hash_digest(PurpleHash *hash, guchar *digest, size_t buff_len) +{ + PurpleSHA1Hash *sha1_hash = PURPLE_SHA1_HASH(hash); + PurpleSHA1HashPrivate *priv = PURPLE_SHA1_HASH_GET_PRIVATE(sha1_hash); + + const gssize required_len = g_checksum_type_get_length(G_CHECKSUM_SHA1); + gsize digest_len = buff_len; + + g_return_val_if_fail(priv != NULL, FALSE); + g_return_val_if_fail(priv->checksum != NULL, FALSE); + g_return_val_if_fail(buff_len >= required_len, FALSE); + + g_checksum_get_digest(priv->checksum, digest, &digest_len); + + if (digest_len != required_len) + return FALSE; + + purple_sha1_hash_reset(hash); + + return TRUE; +} + +static size_t +purple_sha1_hash_get_block_size(PurpleHash *hash) +{ + return 64; +} + +static size_t +purple_sha1_hash_get_digest_size(PurpleHash *hash) +{ + return g_checksum_type_get_length(G_CHECKSUM_SHA1); +} + +static const gchar* +purple_sha1_hash_get_name(PurpleHash *hash) +{ + return "sha1"; +} + +/****************************************************************************** + * Object Stuff + *****************************************************************************/ + +static void +purple_sha1_hash_finalize(GObject *obj) +{ + PurpleSHA1Hash *sha1_hash = PURPLE_SHA1_HASH(obj); + PurpleSHA1HashPrivate *priv = PURPLE_SHA1_HASH_GET_PRIVATE(sha1_hash); + + if (priv->checksum) + g_checksum_free(priv->checksum); + + parent_class->finalize(obj); +} + +static void +purple_sha1_hash_class_init(PurpleSHA1HashClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + PurpleHashClass *hash_class = PURPLE_HASH_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + obj_class->finalize = purple_sha1_hash_finalize; + + hash_class->reset = purple_sha1_hash_reset; + hash_class->reset_state = purple_sha1_hash_reset; + hash_class->append = purple_sha1_hash_append; + hash_class->digest = purple_sha1_hash_digest; + hash_class->get_digest_size = purple_sha1_hash_get_digest_size; + hash_class->get_block_size = purple_sha1_hash_get_block_size; + hash_class->get_name = purple_sha1_hash_get_name; + + g_type_class_add_private(klass, sizeof(PurpleSHA1HashPrivate)); +} + +static void +purple_sha1_hash_init(PurpleHash *hash) +{ + PurpleSHA1Hash *sha1_hash = PURPLE_SHA1_HASH(hash); + PurpleSHA1HashPrivate *priv = PURPLE_SHA1_HASH_GET_PRIVATE(sha1_hash); + + priv->checksum = g_checksum_new(G_CHECKSUM_SHA1); + + purple_sha1_hash_reset(hash); +} + +/****************************************************************************** + * API + *****************************************************************************/ +GType +purple_sha1_hash_get_gtype(void) { + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleSHA1HashClass), + NULL, + NULL, + (GClassInitFunc)purple_sha1_hash_class_init, + NULL, + NULL, + sizeof(PurpleSHA1Hash), + 0, + (GInstanceInitFunc)purple_sha1_hash_init, + NULL, + }; + + type = g_type_register_static(PURPLE_TYPE_HASH, + "PurpleSHA1Hash", + &info, 0); + } + + return type; +} + +PurpleHash * +purple_sha1_hash_new(void) { + return g_object_new(PURPLE_TYPE_SHA1_HASH, NULL); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/ciphers/sha1hash.h Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,67 @@ +/** + * @file sha1.h Purple SHA1 Hash + * @ingroup core + */ + +/* 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 + */ +#ifndef PURPLE_SHA1_HASH_H +#define PURPLE_SHA1_HASH_H + +#include "hash.h" + +#define PURPLE_TYPE_SHA1_HASH (purple_sha1_hash_get_gtype()) +#define PURPLE_SHA1_HASH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_SHA1_HASH, PurpleSHA1Hash)) +#define PURPLE_SHA1_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_SHA1_HASH, PurpleSHA1HashClass)) +#define PURPLE_IS_SHA1_HASH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_SHA1_HASH)) +#define PURPLE_IS_SHA1_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_SHA1_HASH)) +#define PURPLE_SHA1_HASH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_SHA1_HASH, PurpleSHA1HashClass)) + +typedef struct _PurpleSHA1Hash PurpleSHA1Hash; +typedef struct _PurpleSHA1HashClass PurpleSHA1HashClass; + +struct _PurpleSHA1Hash { + PurpleHash gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +struct _PurpleSHA1HashClass { + PurpleHashClass gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType purple_sha1_hash_get_gtype(void); + +PurpleHash *purple_sha1_hash_new(void); + +G_END_DECLS + +#endif /* PURPLE_SHA1_HASH_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/ciphers/sha256hash.c Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,195 @@ +/* + * 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 "sha256hash.h" + +/******************************************************************************* + * Structs + ******************************************************************************/ +#define PURPLE_SHA256_HASH_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_SHA256_HASH, PurpleSHA256HashPrivate)) + +typedef struct { + GChecksum *checksum; +} PurpleSHA256HashPrivate; + +/****************************************************************************** + * Globals + *****************************************************************************/ +static GObjectClass *parent_class = NULL; + +/****************************************************************************** + * Hash Stuff + *****************************************************************************/ + +static void +purple_sha256_hash_reset(PurpleHash *hash) +{ + PurpleSHA256Hash *sha256_hash = PURPLE_SHA256_HASH(hash); + PurpleSHA256HashPrivate *priv = PURPLE_SHA256_HASH_GET_PRIVATE(sha256_hash); + + g_return_if_fail(priv != NULL); + g_return_if_fail(priv->checksum != NULL); + + g_checksum_reset(priv->checksum); +} + +static void +purple_sha256_hash_append(PurpleHash *hash, const guchar *data, + gsize len) +{ + PurpleSHA256Hash *sha256_hash = PURPLE_SHA256_HASH(hash); + PurpleSHA256HashPrivate *priv = PURPLE_SHA256_HASH_GET_PRIVATE(sha256_hash); + + g_return_if_fail(priv != NULL); + g_return_if_fail(priv->checksum != NULL); + + while (len >= G_MAXSSIZE) { + g_checksum_update(priv->checksum, data, G_MAXSSIZE); + len -= G_MAXSSIZE; + data += G_MAXSSIZE; + } + + if (len) + g_checksum_update(priv->checksum, data, len); +} + +static gboolean +purple_sha256_hash_digest(PurpleHash *hash, guchar *digest, size_t buff_len) +{ + PurpleSHA256Hash *sha256_hash = PURPLE_SHA256_HASH(hash); + PurpleSHA256HashPrivate *priv = PURPLE_SHA256_HASH_GET_PRIVATE(sha256_hash); + + const gssize required_len = g_checksum_type_get_length(G_CHECKSUM_SHA256); + gsize digest_len = buff_len; + + g_return_val_if_fail(priv != NULL, FALSE); + g_return_val_if_fail(priv->checksum != NULL, FALSE); + g_return_val_if_fail(buff_len >= required_len, FALSE); + + g_checksum_get_digest(priv->checksum, digest, &digest_len); + + if (digest_len != required_len) + return FALSE; + + purple_sha256_hash_reset(hash); + + return TRUE; +} + +static size_t +purple_sha256_hash_get_block_size(PurpleHash *hash) +{ + return 64; +} + +static size_t +purple_sha256_hash_get_digest_size(PurpleHash *hash) +{ + return g_checksum_type_get_length(G_CHECKSUM_SHA256); +} + +static const gchar* +purple_sha256_hash_get_name(PurpleHash *hash) +{ + return "sha256"; +} + +/****************************************************************************** + * Object Stuff + *****************************************************************************/ + +static void +purple_sha256_hash_finalize(GObject *obj) +{ + PurpleSHA256Hash *sha256_hash = PURPLE_SHA256_HASH(obj); + PurpleSHA256HashPrivate *priv = PURPLE_SHA256_HASH_GET_PRIVATE(sha256_hash); + + if (priv->checksum) + g_checksum_free(priv->checksum); + + parent_class->finalize(obj); +} + +static void +purple_sha256_hash_class_init(PurpleSHA256HashClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + PurpleHashClass *hash_class = PURPLE_HASH_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + obj_class->finalize = purple_sha256_hash_finalize; + + hash_class->reset = purple_sha256_hash_reset; + hash_class->reset_state = purple_sha256_hash_reset; + hash_class->append = purple_sha256_hash_append; + hash_class->digest = purple_sha256_hash_digest; + hash_class->get_digest_size = purple_sha256_hash_get_digest_size; + hash_class->get_block_size = purple_sha256_hash_get_block_size; + hash_class->get_name = purple_sha256_hash_get_name; + + g_type_class_add_private(klass, sizeof(PurpleSHA256HashPrivate)); +} + +static void +purple_sha256_hash_init(PurpleHash *hash) +{ + PurpleSHA256Hash *sha256_hash = PURPLE_SHA256_HASH(hash); + PurpleSHA256HashPrivate *priv = PURPLE_SHA256_HASH_GET_PRIVATE(sha256_hash); + + priv->checksum = g_checksum_new(G_CHECKSUM_SHA256); + + purple_sha256_hash_reset(hash); +} + +/****************************************************************************** + * API + *****************************************************************************/ +GType +purple_sha256_hash_get_gtype(void) { + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleSHA256HashClass), + NULL, + NULL, + (GClassInitFunc)purple_sha256_hash_class_init, + NULL, + NULL, + sizeof(PurpleSHA256Hash), + 0, + (GInstanceInitFunc)purple_sha256_hash_init, + NULL, + }; + + type = g_type_register_static(PURPLE_TYPE_HASH, + "PurpleSHA256Hash", + &info, 0); + } + + return type; +} + +PurpleHash * +purple_sha256_hash_new(void) { + return g_object_new(PURPLE_TYPE_SHA256_HASH, NULL); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/ciphers/sha256hash.h Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,67 @@ +/** + * @file sha256.h Purple SHA256 Hash + * @ingroup core + */ + +/* 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 + */ +#ifndef PURPLE_SHA256_HASH_H +#define PURPLE_SHA256_HASH_H + +#include "hash.h" + +#define PURPLE_TYPE_SHA256_HASH (purple_sha256_hash_get_gtype()) +#define PURPLE_SHA256_HASH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_SHA256_HASH, PurpleSHA256Hash)) +#define PURPLE_SHA256_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_SHA256_HASH, PurpleSHA256HashClass)) +#define PURPLE_IS_SHA256_HASH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_SHA256_HASH)) +#define PURPLE_IS_SHA256_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_SHA256_HASH)) +#define PURPLE_SHA256_HASH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_SHA256_HASH, PurpleSHA256HashClass)) + +typedef struct _PurpleSHA256Hash PurpleSHA256Hash; +typedef struct _PurpleSHA256HashClass PurpleSHA256HashClass; + +struct _PurpleSHA256Hash { + PurpleHash gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +struct _PurpleSHA256HashClass { + PurpleHashClass gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType purple_sha256_hash_get_gtype(void); + +PurpleHash *purple_sha256_hash_new(void); + +G_END_DECLS + +#endif /* PURPLE_SHA256_HASH_H */
--- a/libpurple/circbuffer.c Sun Jun 23 02:43:06 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,153 +0,0 @@ -/* - * @file circbuffer.h Buffer Utility Functions - * @ingroup core - */ - -/* 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 "internal.h" - -#include "circbuffer.h" - -#define DEFAULT_BUF_SIZE 256 - -PurpleCircBuffer * -purple_circ_buffer_new(gsize growsize) { - PurpleCircBuffer *buf = g_new0(PurpleCircBuffer, 1); - buf->growsize = growsize ? growsize : DEFAULT_BUF_SIZE; - return buf; -} - -void purple_circ_buffer_destroy(PurpleCircBuffer *buf) { - g_return_if_fail(buf != NULL); - - g_free(buf->buffer); - g_free(buf); -} - -static void grow_circ_buffer(PurpleCircBuffer *buf, gsize len) { - int in_offset = 0, out_offset = 0; - int start_buflen; - - g_return_if_fail(buf != NULL); - - start_buflen = buf->buflen; - - while ((buf->buflen - buf->bufused) < len) - buf->buflen += buf->growsize; - - if (buf->inptr != NULL) { - in_offset = buf->inptr - buf->buffer; - out_offset = buf->outptr - buf->buffer; - } - buf->buffer = g_realloc(buf->buffer, buf->buflen); - - /* adjust the fill and remove pointer locations */ - if (buf->inptr == NULL) { - buf->inptr = buf->outptr = buf->buffer; - } else { - buf->inptr = buf->buffer + in_offset; - buf->outptr = buf->buffer + out_offset; - } - - /* If the fill pointer is wrapped to before the remove - * pointer, we need to shift the data */ - if (in_offset < out_offset - || (in_offset == out_offset && buf->bufused > 0)) { - int shift_n = MIN(buf->buflen - start_buflen, - in_offset); - memcpy(buf->buffer + start_buflen, buf->buffer, - shift_n); - - /* If we couldn't fit the wrapped read buffer - * at the end */ - if (shift_n < in_offset) { - memmove(buf->buffer, - buf->buffer + shift_n, - in_offset - shift_n); - buf->inptr = buf->buffer + - (in_offset - shift_n); - } else { - buf->inptr = buf->buffer + - start_buflen + in_offset; - } - } -} - -void purple_circ_buffer_append(PurpleCircBuffer *buf, gconstpointer src, gsize len) { - - int len_stored; - - g_return_if_fail(buf != NULL); - - /* Grow the buffer, if necessary */ - if ((buf->buflen - buf->bufused) < len) - grow_circ_buffer(buf, len); - - /* If there is not enough room to copy all of src before hitting - * the end of the buffer then we will need to do two copies. - * One copy from inptr to the end of the buffer, and the - * second copy from the start of the buffer to the end of src. */ - if (buf->inptr >= buf->outptr) - len_stored = MIN(len, buf->buflen - - (buf->inptr - buf->buffer)); - else - len_stored = len; - - if (len_stored > 0) - memcpy(buf->inptr, src, len_stored); - - if (len_stored < len) { - memcpy(buf->buffer, (char*)src + len_stored, len - len_stored); - buf->inptr = buf->buffer + (len - len_stored); - } else { - buf->inptr += len_stored; - } - - buf->bufused += len; -} - -gsize purple_circ_buffer_get_max_read(const PurpleCircBuffer *buf) { - gsize max_read; - - g_return_val_if_fail(buf != NULL, 0); - - if (buf->bufused == 0) - max_read = 0; - else if ((buf->outptr - buf->inptr) >= 0) - max_read = buf->buflen - (buf->outptr - buf->buffer); - else - max_read = buf->inptr - buf->outptr; - - return max_read; -} - -gboolean purple_circ_buffer_mark_read(PurpleCircBuffer *buf, gsize len) { - g_return_val_if_fail(buf != NULL, FALSE); - g_return_val_if_fail(purple_circ_buffer_get_max_read(buf) >= len, FALSE); - - buf->outptr += len; - buf->bufused -= len; - /* wrap to the start if we're at the end */ - if ((buf->outptr - buf->buffer) == buf->buflen) - buf->outptr = buf->buffer; - - return TRUE; -} -
--- a/libpurple/circbuffer.h Sun Jun 23 02:43:06 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,114 +0,0 @@ -/** - * @file circbuffer.h Buffer Utility Functions - * @ingroup core - */ - -/* 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 - */ -#ifndef _CIRCBUFFER_H -#define _CIRCBUFFER_H - -#include <glib.h> - -typedef struct _PurpleCircBuffer { - - /** A pointer to the starting address of our chunk of memory. */ - gchar *buffer; - - /** The incremental amount to increase this buffer by when - * the buffer is not big enough to hold incoming data, in bytes. */ - gsize growsize; - - /** The length of this buffer, in bytes. */ - gsize buflen; - - /** The number of bytes of this buffer that contain unread data. */ - gsize bufused; - - /** A pointer to the next byte where new incoming data is - * buffered to. */ - gchar *inptr; - - /** A pointer to the next byte of buffered data that should be - * read by the consumer. */ - gchar *outptr; - -} PurpleCircBuffer; - -G_BEGIN_DECLS - -/** - * Creates a new circular buffer. This will not allocate any memory for the - * actual buffer until data is appended to it. - * - * @param growsize The amount that the buffer should grow the first time data - * is appended and every time more space is needed. Pass in - * "0" to use the default of 256 bytes. - * - * @return The new PurpleCircBuffer. This should be freed with - * purple_circ_buffer_destroy when you are done with it - */ -PurpleCircBuffer *purple_circ_buffer_new(gsize growsize); - -/** - * Dispose of the PurpleCircBuffer and free any memory used by it (including any - * memory used by the internal buffer). - * - * @param buf The PurpleCircBuffer to free - */ -void purple_circ_buffer_destroy(PurpleCircBuffer *buf); - -/** - * Append data to the PurpleCircBuffer. This will grow the internal - * buffer to fit the added data, if needed. - * - * @param buf The PurpleCircBuffer to which to append the data - * @param src pointer to the data to copy into the buffer - * @param len number of bytes to copy into the buffer - */ -void purple_circ_buffer_append(PurpleCircBuffer *buf, gconstpointer src, gsize len); - -/** - * Determine the maximum number of contiguous bytes that can be read from the - * PurpleCircBuffer. - * Note: This may not be the total number of bytes that are buffered - a - * subsequent call after calling purple_circ_buffer_mark_read() may indicate more - * data is available to read. - * - * @param buf the PurpleCircBuffer for which to determine the maximum contiguous - * bytes that can be read. - * - * @return the number of bytes that can be read from the PurpleCircBuffer - */ -gsize purple_circ_buffer_get_max_read(const PurpleCircBuffer *buf); - -/** - * Mark the number of bytes that have been read from the buffer. - * - * @param buf The PurpleCircBuffer to mark bytes read from - * @param len The number of bytes to mark as read - * - * @return TRUE if we successfully marked the bytes as having been read, FALSE - * otherwise. - */ -gboolean purple_circ_buffer_mark_read(PurpleCircBuffer *buf, gsize len); - -G_END_DECLS - -#endif /* _CIRCBUFFER_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/circularbuffer.c Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,444 @@ +/* + * @file circbuffer.h Buffer Utility Functions + * @ingroup core + */ + +/* 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 "internal.h" + +#include "circularbuffer.h" + +#define DEFAULT_BUF_SIZE 256 + +#define PURPLE_CIRCULAR_BUFFER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_CIRCULAR_BUFFER, PurpleCircularBufferPrivate)) + +/****************************************************************************** + * Structs + *****************************************************************************/ +typedef struct { + gchar *buffer; + gsize growsize; + gsize buflen; + gsize bufused; + gchar *input; + gchar *output; +} PurpleCircularBufferPrivate; + +/****************************************************************************** + * Enums + *****************************************************************************/ +enum { + PROP_ZERO, + PROP_GROW_SIZE, + PROP_BUFFER_USED, + PROP_INPUT, + PROP_OUTPUT, + PROP_LAST, +}; + +/****************************************************************************** + * Globals + *****************************************************************************/ +static GObjectClass *parent_class = NULL; + +/****************************************************************************** + * Circular Buffer Implementation + *****************************************************************************/ +static void +purple_circular_buffer_real_grow(PurpleCircularBuffer *buffer, gsize len) { + PurpleCircularBufferPrivate *priv = NULL; + gint in_offset = 0, out_offset = 0; + gint start_buflen; + + priv = PURPLE_CIRCULAR_BUFFER_GET_PRIVATE(buffer); + + start_buflen = priv->buflen; + + while((priv->buflen - priv->bufused) < len) + priv->buflen += priv->growsize; + + if(priv->input != NULL) { + in_offset = priv->input - priv->buffer; + out_offset = priv->output - priv->buffer; + } + + priv->buffer = g_realloc(priv->buffer, priv->buflen); + + /* adjust the fill and remove pointer locations */ + if(priv->input == NULL) { + priv->input = priv->output = priv->buffer; + } else { + priv->input = priv->buffer + in_offset; + priv->output = priv->buffer + out_offset; + } + + /* If the fill pointer is wrapped to before the remove + * pointer, we need to shift the data */ + if(in_offset < out_offset + || (in_offset == out_offset && priv->bufused > 0)) + { + gint shift_n = MIN(priv->buflen - start_buflen, in_offset); + memcpy(priv->buffer + start_buflen, priv->buffer, shift_n); + + /* If we couldn't fit the wrapped read buffer at the end */ + if (shift_n < in_offset) { + memmove(priv->buffer, priv->buffer + shift_n, in_offset - shift_n); + priv->input = priv->buffer + (in_offset - shift_n); + } else { + priv->input = priv->buffer + start_buflen + in_offset; + } + } +} + +static void +purple_circular_buffer_real_append(PurpleCircularBuffer *buffer, + gconstpointer src, gsize len) +{ + PurpleCircularBufferPrivate *priv = NULL; + gint len_stored; + + priv = PURPLE_CIRCULAR_BUFFER_GET_PRIVATE(buffer); + + /* Grow the buffer, if necessary */ + if((priv->buflen - priv->bufused) < len) + purple_circular_buffer_grow(buffer, len); + + /* If there is not enough room to copy all of src before hitting + * the end of the buffer then we will need to do two copies. + * One copy from input to the end of the buffer, and the + * second copy from the start of the buffer to the end of src. */ + if(priv->input >= priv->output) + len_stored = MIN(len, priv->buflen - (priv->input - priv->buffer)); + else + len_stored = len; + + if(len_stored > 0) + memcpy(priv->input, src, len_stored); + + if(len_stored < len) { + memcpy(priv->buffer, (char*)src + len_stored, len - len_stored); + priv->input = priv->buffer + (len - len_stored); + } else { + priv->input += len_stored; + } + + priv->bufused += len; +} + +static gsize +purple_circular_buffer_real_max_read_size(const PurpleCircularBuffer *buffer) { + PurpleCircularBufferPrivate *priv = NULL; + gsize max_read; + + priv = PURPLE_CIRCULAR_BUFFER_GET_PRIVATE(buffer); + + if(priv->bufused == 0) + max_read = 0; + else if((priv->output - priv->input) >= 0) + max_read = priv->buflen - (priv->output - priv->buffer); + else + max_read = priv->input - priv->output; + + return max_read; +} + +static gboolean +purple_circular_buffer_real_mark_read(PurpleCircularBuffer *buffer, + gsize len) +{ + PurpleCircularBufferPrivate *priv = NULL; + + g_return_val_if_fail(purple_circular_buffer_get_max_read(buffer) >= len, FALSE); + + priv = PURPLE_CIRCULAR_BUFFER_GET_PRIVATE(buffer); + + priv->output += len; + priv->bufused -= len; + + /* wrap to the start if we're at the end */ + if((priv->output - priv->buffer) == priv->buflen) + priv->output = priv->buffer; + + return TRUE; +} + +/****************************************************************************** + * Private API + *****************************************************************************/ +static void +purple_circular_buffer_set_grow_size(PurpleCircularBuffer *buffer, + gsize grow_size) +{ + PurpleCircularBufferPrivate *priv = + PURPLE_CIRCULAR_BUFFER_GET_PRIVATE(buffer); + + priv->growsize = (grow_size != 0) ? grow_size : DEFAULT_BUF_SIZE; + + g_object_notify(G_OBJECT(buffer), "grow-size"); +} + +/****************************************************************************** + * Object Stuff + *****************************************************************************/ +static void +purple_circular_buffer_finalize(GObject *obj) { + PurpleCircularBufferPrivate *priv = + PURPLE_CIRCULAR_BUFFER_GET_PRIVATE(obj); + + g_free(priv->buffer); + + G_OBJECT_CLASS(parent_class)->finalize(obj); +} + +static void +purple_circular_buffer_get_property(GObject *obj, guint param_id, + GValue *value, GParamSpec *pspec) +{ + PurpleCircularBuffer *buffer = PURPLE_CIRCULAR_BUFFER(obj); + + switch(param_id) { + case PROP_GROW_SIZE: + g_value_set_ulong(value, + purple_circular_buffer_get_grow_size(buffer)); + break; + case PROP_BUFFER_USED: + g_value_set_ulong(value, + purple_circular_buffer_get_used(buffer)); + break; + case PROP_INPUT: + g_value_set_pointer(value, + (void*) purple_circular_buffer_get_input(buffer)); + break; + case PROP_OUTPUT: + g_value_set_pointer(value, + (void*) purple_circular_buffer_get_output(buffer)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_circular_buffer_set_property(GObject *obj, guint param_id, + const GValue *value, GParamSpec *pspec) +{ + PurpleCircularBuffer *buffer = PURPLE_CIRCULAR_BUFFER(obj); + + switch(param_id) { + case PROP_GROW_SIZE: + purple_circular_buffer_set_grow_size(buffer, + g_value_get_uint(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_circular_buffer_class_init(PurpleCircularBufferClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + PurpleCircularBufferClass *buffer_class = PURPLE_CIRCULAR_BUFFER_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + g_type_class_add_private(klass, sizeof(PurpleCircularBufferPrivate)); + + obj_class->finalize = purple_circular_buffer_finalize; + obj_class->get_property = purple_circular_buffer_get_property; + obj_class->set_property = purple_circular_buffer_set_property; + + buffer_class->grow = purple_circular_buffer_real_grow; + buffer_class->append = purple_circular_buffer_real_append; + buffer_class->max_read_size = purple_circular_buffer_real_max_read_size; + buffer_class->mark_read = purple_circular_buffer_real_mark_read; + + /* using a ulong for the gsize properties since there is no + * g_param_spec_size, and the ulong should always work. --gk 3/21/11 + */ + g_object_class_install_property(obj_class, PROP_GROW_SIZE, + g_param_spec_ulong("grow-size", "grow-size", + "The grow size of the buffer", + 0, G_MAXSIZE, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property(obj_class, PROP_BUFFER_USED, + g_param_spec_ulong("buffer-used", "buffer-used", + "The amount of the buffer used", + 0, G_MAXSIZE, 0, + G_PARAM_READABLE)); + + g_object_class_install_property(obj_class, PROP_INPUT, + g_param_spec_pointer("input", "input", + "The input pointer of the buffer", + G_PARAM_READABLE)); + + g_object_class_install_property(obj_class, PROP_OUTPUT, + g_param_spec_pointer("output", "output", + "The output pointer of the buffer", + G_PARAM_READABLE)); +} + +/****************************************************************************** + * API + *****************************************************************************/ +GType +purple_circular_buffer_get_type(void) { + static GType type = 0; + + if(G_UNLIKELY(type == 0)) { + static const GTypeInfo info = { + .class_size = sizeof(PurpleCircularBufferClass), + .class_init = (GClassInitFunc)purple_circular_buffer_class_init, + .instance_size = sizeof(PurpleCircularBuffer), + }; + + type = g_type_register_static(G_TYPE_OBJECT, + "PurpleCircularBuffer", + &info, 0); + } + + return type; +} + +PurpleCircularBuffer * +purple_circular_buffer_new(gsize growsize) { + return g_object_new(PURPLE_TYPE_CIRCULAR_BUFFER, + "grow-size", growsize ? growsize : DEFAULT_BUF_SIZE, + NULL); +} + +void +purple_circular_buffer_grow(PurpleCircularBuffer *buffer, gsize len) { + PurpleCircularBufferClass *klass = NULL; + + g_return_if_fail(PURPLE_IS_CIRCULAR_BUFFER(buffer)); + + klass = PURPLE_CIRCULAR_BUFFER_GET_CLASS(buffer); + if(klass && klass->grow) + klass->grow(buffer, len); +} + +void +purple_circular_buffer_append(PurpleCircularBuffer *buffer, gconstpointer src, + gsize len) +{ + PurpleCircularBufferClass *klass = NULL; + + g_return_if_fail(PURPLE_IS_CIRCULAR_BUFFER(buffer)); + g_return_if_fail(src != NULL); + + klass = PURPLE_CIRCULAR_BUFFER_GET_CLASS(buffer); + if(klass && klass->append) + klass->append(buffer, src, len); +} + +gsize +purple_circular_buffer_get_max_read(const PurpleCircularBuffer *buffer) { + PurpleCircularBufferClass *klass = NULL; + + g_return_val_if_fail(PURPLE_IS_CIRCULAR_BUFFER(buffer), 0); + + klass = PURPLE_CIRCULAR_BUFFER_GET_CLASS(buffer); + if(klass && klass->max_read_size) + return klass->max_read_size(buffer); + + return 0; +} + +gboolean +purple_circular_buffer_mark_read(PurpleCircularBuffer *buffer, gsize len) { + PurpleCircularBufferClass *klass = NULL; + + g_return_val_if_fail(PURPLE_IS_CIRCULAR_BUFFER(buffer), FALSE); + + klass = PURPLE_CIRCULAR_BUFFER_CLASS(buffer); + if(klass && klass->mark_read) + return klass->mark_read(buffer, len); + + return FALSE; +} + +gsize +purple_circular_buffer_get_grow_size(const PurpleCircularBuffer *buffer) { + + PurpleCircularBufferPrivate *priv = NULL; + + g_return_val_if_fail(PURPLE_IS_CIRCULAR_BUFFER(buffer), 0); + + priv = PURPLE_CIRCULAR_BUFFER_GET_PRIVATE(buffer); + + return priv->growsize; +} + +gsize +purple_circular_buffer_get_used(const PurpleCircularBuffer *buffer) { + PurpleCircularBufferPrivate *priv = NULL; + + g_return_val_if_fail(PURPLE_IS_CIRCULAR_BUFFER(buffer), 0); + + priv = PURPLE_CIRCULAR_BUFFER_GET_PRIVATE(buffer); + + return priv->bufused; +} + +const gchar * +purple_circular_buffer_get_input(const PurpleCircularBuffer *buffer) { + PurpleCircularBufferPrivate *priv = NULL; + + g_return_val_if_fail(PURPLE_IS_CIRCULAR_BUFFER(buffer), NULL); + + priv = PURPLE_CIRCULAR_BUFFER_GET_PRIVATE(buffer); + + return priv->input; +} + +const gchar * +purple_circular_buffer_get_output(const PurpleCircularBuffer *buffer) { + PurpleCircularBufferPrivate *priv = NULL; + + g_return_val_if_fail(PURPLE_IS_CIRCULAR_BUFFER(buffer), NULL); + + priv = PURPLE_CIRCULAR_BUFFER_GET_PRIVATE(buffer); + + return priv->output; +} + +void +purple_circular_buffer_reset(PurpleCircularBuffer *buffer) { + PurpleCircularBufferPrivate *priv = NULL; + GObject *obj = NULL; + + g_return_if_fail(PURPLE_IS_CIRCULAR_BUFFER(buffer)); + + priv = PURPLE_CIRCULAR_BUFFER_GET_PRIVATE(buffer); + + priv->input = priv->buffer; + priv->output = priv->buffer; + + obj = G_OBJECT(buffer); + g_object_freeze_notify(obj); + g_object_notify(obj, "input"); + g_object_notify(obj, "output"); + g_object_thaw_notify(obj); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/circularbuffer.h Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,125 @@ +/** + * @file circbuffer.h Buffer Utility Functions + * @ingroup core + */ + +/* 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 + */ +#ifndef PURPLE_CIRCULAR_BUFFER_H +#define PURPLE_CIRCULAR_BUFFER_H + +#include <glib.h> +#include <glib-object.h> + +#define PURPLE_TYPE_CIRCULAR_BUFFER (purple_circular_buffer_get_type()) +#define PURPLE_CIRCULAR_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_CIRCULAR_BUFFER, PurpleCircularBuffer)) +#define PURPLE_CIRCULAR_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_CIRCULAR_BUFFER, PurpleCircularBufferClass)) +#define PURPLE_IS_CIRCULAR_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_CIRCULAR_BUFFER)) +#define PURPLE_IS_CIRCULAR_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_CIRCULAR_BUFFER)) +#define PURPLE_CIRCULAR_BUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_CIRCULAR_BUFFER, PurpleCircularBufferClass)) + +typedef struct _PurpleCircularBuffer PurpleCircularBuffer; +typedef struct _PurpleCircularBufferClass PurpleCircularBufferClass; + +struct _PurpleCircularBuffer { + GObject parent; + + void (*purple_reserved1)(void); + void (*purple_reserved2)(void); + void (*purple_reserved3)(void); + void (*purple_reserved4)(void); +}; + +struct _PurpleCircularBufferClass { + GObjectClass parent; + + void (*grow)(PurpleCircularBuffer *buffer, gsize len); + void (*append)(PurpleCircularBuffer *buffer, gconstpointer src, gsize len); + gsize (*max_read_size)(const PurpleCircularBuffer *buffer); + gboolean (*mark_read)(PurpleCircularBuffer *buffer, gsize len); + + void (*purple_reserved1)(void); + void (*purple_reserved2)(void); + void (*purple_reserved3)(void); + void (*purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType purple_circular_buffer_get_type(void); + +/** + * Creates a new circular buffer. This will not allocate any memory for the + * actual buffer until data is appended to it. + * + * @param growsize The amount that the buffer should grow the first time data + * is appended and every time more space is needed. Pass in + * "0" to use the default of 256 bytes. + * + * @return The new PurpleCircBuffer. This should be freed with + * purple_circ_buffer_destroy when you are done with it + */ +PurpleCircularBuffer *purple_circular_buffer_new(gsize growsize); + +/** + * Append data to the PurpleCircBuffer. This will grow the internal + * buffer to fit the added data, if needed. + * + * @param buf The PurpleCircBuffer to which to append the data + * @param src pointer to the data to copy into the buffer + * @param len number of bytes to copy into the buffer + */ +void purple_circular_buffer_append(PurpleCircularBuffer *buf, gconstpointer src, gsize len); + +/** + * Determine the maximum number of contiguous bytes that can be read from the + * PurpleCircBuffer. + * Note: This may not be the total number of bytes that are buffered - a + * subsequent call after calling purple_circ_buffer_mark_read() may indicate more + * data is available to read. + * + * @param buf the PurpleCircBuffer for which to determine the maximum contiguous + * bytes that can be read. + * + * @return the number of bytes that can be read from the PurpleCircBuffer + */ +gsize purple_circular_buffer_get_max_read(const PurpleCircularBuffer *buf); + +/** + * Mark the number of bytes that have been read from the buffer. + * + * @param buf The PurpleCircBuffer to mark bytes read from + * @param len The number of bytes to mark as read + * + * @return TRUE if we successfully marked the bytes as having been read, FALSE + * otherwise. + */ +gboolean purple_circular_buffer_mark_read(PurpleCircularBuffer *buf, gsize len); + +void purple_circular_buffer_grow(PurpleCircularBuffer *buffer, gsize len); +gsize purple_circular_buffer_get_grow_size(const PurpleCircularBuffer *buffer); +gsize purple_circular_buffer_get_used(const PurpleCircularBuffer *buffer); +const gchar *purple_circular_buffer_get_input(const PurpleCircularBuffer *buffer); +const gchar *purple_circular_buffer_get_output(const PurpleCircularBuffer *buffer); +void purple_circular_buffer_reset(PurpleCircularBuffer *buffer); + +G_END_DECLS + +#endif /* PURPLE_CIRCULAR_BUFFER_H */ +
--- a/libpurple/conversation.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/conversation.c Sun Jun 23 13:35:53 2013 +0530 @@ -33,89 +33,15 @@ #include "signals.h" #include "util.h" -#define SEND_TYPED_TIMEOUT_SECONDS 5 - -/** - * Data specific to Chats. - */ -struct _PurpleConvChat -{ - PurpleConversation *conv; /**< The parent conversation. */ - - GList *in_room; /**< The users in the room. - * @deprecated Will be removed in 3.0.0 - */ - GList *ignored; /**< Ignored users. */ - char *who; /**< The person who set the topic. */ - char *topic; /**< The topic. */ - int id; /**< The chat ID. */ - char *nick; /**< Your nick in this chat. */ - - gboolean left; /**< We left the chat and kept the window open */ - GHashTable *users; /**< Hash table of the users in the room. */ -}; - -/** - * Data specific to Instant Messages. - */ -struct _PurpleConvIm -{ - PurpleConversation *conv; /**< The parent conversation. */ - - PurpleTypingState typing_state; /**< The current typing state. */ - guint typing_timeout; /**< The typing timer handle. */ - time_t type_again; /**< The type again time. */ - guint send_typed_timeout; /**< The type again timer handle. */ - - PurpleBuddyIcon *icon; /**< The buddy icon. */ -}; - -/** - * Data for "Chat Buddies" - */ -struct _PurpleConvChatBuddy -{ - /** The chat participant's name in the chat. */ - char *name; - - /** The chat participant's alias, if known; @a NULL otherwise. */ - char *alias; - - /** - * A string by which this buddy will be sorted, or @c NULL if the - * buddy should be sorted by its @c name. (This is currently always - * @c NULL. - */ - char *alias_key; - - /** - * @a TRUE if this chat participant is on the buddy list; - * @a FALSE otherwise. - */ - gboolean buddy; - - /** - * A bitwise OR of flags for this participant, such as whether they - * are a channel operator. - */ - PurpleConvChatBuddyFlags flags; - - /** - * A hash table of attributes about the user, such as real name, - * user\@host, etc. - */ - GHashTable *attributes; - - /** The UI can put whatever it wants here. */ - gpointer ui_data; -}; +/** @copydoc _PurpleConversationPrivate */ +typedef struct _PurpleConversationPrivate PurpleConversationPrivate; /** * A core representation of a conversation between two or more people. * * The conversation can be an IM or a chat. */ -struct _PurpleConversation +struct _PurpleConversationPrivate { PurpleConversationType type; /**< The type of conversation. */ @@ -129,42 +55,28 @@ GList *logs; /**< This conversation's logs */ - union - { - PurpleConvIm *im; /**< IM-specific data. */ - PurpleConvChat *chat; /**< Chat-specific data. */ - void *misc; /**< Misc. data. */ - - } u; - PurpleConversationUiOps *ui_ops; /**< UI-specific operations. */ void *ui_data; /**< UI-specific data. */ GHashTable *data; /**< Plugin-specific data. */ PurpleConnectionFlags features; /**< The supported features */ - GList *message_history; /**< Message history, as a GList of PurpleConvMessage's */ + GList *message_history; /**< Message history, as a GList of PurpleConversationMessage's */ }; -/** +/** TODO GBoxed * Description of a conversation message */ -struct _PurpleConvMessage +struct _PurpleConversationMessage { char *who; char *what; - PurpleMessageFlags flags; + PurpleConversationMessageFlags flags; time_t when; PurpleConversation *conv; char *alias; }; - -static GList *conversations = NULL; -static GList *ims = NULL; -static GList *chats = NULL; -static PurpleConversationUiOps *default_ops = NULL; - /** * A hash table used for efficient lookups of conversations by name. * struct _purple_hconv => PurpleConversation* @@ -212,22 +124,16 @@ return !g_utf8_collate(a, b); } -void -purple_conversations_set_ui_ops(PurpleConversationUiOps *ops) -{ - default_ops = ops; -} - static gboolean reset_typing_cb(gpointer data) { PurpleConversation *c = (PurpleConversation *)data; - PurpleConvIm *im; + PurpleIMConversationPrivate *priv; - im = PURPLE_CONV_IM(c); + im = PURPLE_IM_CONVERSATION_GET_PRIVATE(c); - purple_conv_im_set_typing_state(im, PURPLE_NOT_TYPING); - purple_conv_im_stop_typing_timeout(im); + purple_im_conversation_set_typing_state(im, PURPLE_IM_CONVERSATION_NOT_TYPING); + purple_im_conversation_stop_typing_timeout(im); return FALSE; } @@ -245,12 +151,12 @@ name = purple_conversation_get_name(conv); if (gc != NULL && name != NULL) { - /* We set this to 1 so that PURPLE_TYPING will be sent + /* We set this to 1 so that PURPLE_IM_CONVERSATION_TYPING will be sent * if the Purple user types anything else. */ - purple_conv_im_set_type_again(PURPLE_CONV_IM(conv), 1); + purple_im_conversation_set_type_again(PURPLE_IM_CONVERSATION_GET_PRIVATE(conv), 1); - serv_send_typing(gc, name, PURPLE_TYPED); + serv_send_typing(gc, name, PURPLE_IM_CONVERSATION_TYPED); purple_debug(PURPLE_DEBUG_MISC, "conversation", "typed...\n"); } @@ -259,7 +165,7 @@ } static void -common_send(PurpleConversation *conv, const char *message, PurpleMessageFlags msgflags) +common_send(PurpleConversation *conv, const char *message, PurpleConversationMessageFlags msgflags) { PurpleConversationType type; PurpleAccount *account; @@ -280,23 +186,23 @@ /* Always linkfy the text for display, unless we're * explicitly asked to do otheriwse*/ - if (!(msgflags & PURPLE_MESSAGE_INVISIBLE)) { - if(msgflags & PURPLE_MESSAGE_NO_LINKIFY) + if (!(msgflags & PURPLE_CONVERSATION_MESSAGE_INVISIBLE)) { + if(msgflags & PURPLE_CONVERSATION_MESSAGE_NO_LINKIFY) displayed = g_strdup(message); else displayed = purple_markup_linkify(message); } if (displayed && (conv->features & PURPLE_CONNECTION_HTML) && - !(msgflags & PURPLE_MESSAGE_RAW)) { + !(msgflags & PURPLE_CONVERSATION_MESSAGE_RAW)) { sent = g_strdup(displayed); } else sent = g_strdup(message); - msgflags |= PURPLE_MESSAGE_SEND; + msgflags |= PURPLE_CONVERSATION_MESSAGE_SEND; - if (type == PURPLE_CONV_TYPE_IM) { - PurpleConvIm *im = PURPLE_CONV_IM(conv); + if (type == PURPLE_CONVERSATION_TYPE_IM) { + PurpleIMConversationPrivate *priv = PURPLE_IM_CONVERSATION_GET_PRIVATE(conv); purple_signal_emit(purple_conversations_get_handle(), "sending-im-msg", account, @@ -308,7 +214,7 @@ sent, msgflags); if ((err > 0) && (displayed != NULL)) - purple_conv_im_write(im, NULL, displayed, msgflags, time(NULL)); + purple_im_conversation_write(im, NULL, displayed, msgflags, time(NULL)); purple_signal_emit(purple_conversations_get_handle(), "sent-im-msg", account, @@ -318,14 +224,14 @@ else { purple_signal_emit(purple_conversations_get_handle(), "sending-chat-msg", account, &sent, - purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv))); + purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv))); if (sent != NULL && sent[0] != '\0') { - err = serv_chat_send(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), sent, msgflags); + err = serv_chat_send(gc, purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv)), sent, msgflags); purple_signal_emit(purple_conversations_get_handle(), "sent-chat-msg", account, sent, - purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv))); + purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv))); } } @@ -338,7 +244,7 @@ if (err == -E2BIG) { msg = _("Unable to send message: The message is too large."); - if (!purple_conv_present_error(who, account, msg)) { + if (!purple_conversation_helper_present_error(who, account, msg)) { char *msg2 = g_strdup_printf(_("Unable to send message to %s."), who); purple_notify_error(gc, NULL, msg2, _("The message is too large.")); g_free(msg2); @@ -351,7 +257,7 @@ else { msg = _("Unable to send message."); - if (!purple_conv_present_error(who, account, msg)) { + if (!purple_conversation_helper_present_error(who, account, msg)) { char *msg2 = g_strdup_printf(_("Unable to send message to %s."), who); purple_notify_error(gc, NULL, msg2, NULL); g_free(msg2); @@ -366,23 +272,23 @@ static void open_log(PurpleConversation *conv) { - conv->logs = g_list_append(NULL, purple_log_new(conv->type == PURPLE_CONV_TYPE_CHAT ? PURPLE_LOG_CHAT : + conv->logs = g_list_append(NULL, purple_log_new(conv->type == PURPLE_CONVERSATION_TYPE_CHAT ? PURPLE_LOG_CHAT : PURPLE_LOG_IM, conv->name, conv->account, conv, time(NULL), NULL)); } -/* Functions that deal with PurpleConvMessage */ +/* Functions that deal with PurpleConversationMessage */ static void add_message_to_history(PurpleConversation *conv, const char *who, const char *alias, - const char *message, PurpleMessageFlags flags, time_t when) + const char *message, PurpleConversationMessageFlags flags, time_t when) { - PurpleConvMessage *msg; + PurpleConversationMessage *msg; PurpleConnection *gc; gc = purple_account_get_connection(conv->account); - if (flags & PURPLE_MESSAGE_SEND) { + if (flags & PURPLE_CONVERSATION_MESSAGE_SEND) { const char *me = NULL; if (gc) me = purple_connection_get_display_name(gc); @@ -391,8 +297,8 @@ who = me; } - msg = g_new0(PurpleConvMessage, 1); - PURPLE_DBUS_REGISTER_POINTER(msg, PurpleConvMessage); + msg = g_new0(PurpleConversationMessage, 1); + PURPLE_DBUS_REGISTER_POINTER(msg, PurpleConversationMessage); msg->who = g_strdup(who); msg->alias = g_strdup(alias); msg->flags = flags; @@ -404,7 +310,7 @@ } static void -free_conv_message(PurpleConvMessage *msg) +free_conv_message(PurpleConversationMessage *msg) { g_free(msg->who); g_free(msg->alias); @@ -438,18 +344,18 @@ gc = purple_account_get_connection(account); if ((disp = purple_connection_get_display_name(gc)) != NULL) - purple_conv_chat_set_nick(PURPLE_CONV_CHAT(conv), disp); + purple_chat_conversation_set_nick(PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv), disp); else { - purple_conv_chat_set_nick(PURPLE_CONV_CHAT(conv), + purple_chat_conversation_set_nick(PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv), purple_account_get_username(account)); } - purple_conv_chat_clear_users(PURPLE_CONV_CHAT(conv)); - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(conv), NULL, NULL); - PURPLE_CONV_CHAT(conv)->left = FALSE; + purple_chat_conversation_clear_users(PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv)); + purple_chat_conversation_set_topic(PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv), NULL, NULL); + PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv)->left = FALSE; - purple_conversation_update(conv, PURPLE_CONV_UPDATE_CHATLEFT); + purple_conversation_update(conv, PURPLE_CONVERSATION_UPDATE_CHATLEFT); } PurpleConversation * @@ -461,15 +367,15 @@ PurpleConversationUiOps *ops; struct _purple_hconv *hc; - g_return_val_if_fail(type != PURPLE_CONV_TYPE_UNKNOWN, NULL); + g_return_val_if_fail(type != PURPLE_CONVERSATION_TYPE_UNKNOWN, NULL); g_return_val_if_fail(account != NULL, NULL); g_return_val_if_fail(name != NULL, NULL); /* Check if this conversation already exists. */ - if ((conv = purple_find_conversation_with_account(type, name, account)) != NULL) + if ((conv = purple_conversations_find_with_account(type, name, account)) != NULL) { - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT && - !purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv))) { + if (purple_conversation_get_type(conv) == PURPLE_CONVERSATION_TYPE_CHAT && + !purple_chat_conversation_has_left(PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv))) { purple_debug_warning("conversation", "Trying to create multiple " "chats (%s) with the same name is deprecated and will be " "removed in libpurple 3.0.0", name); @@ -483,10 +389,10 @@ * chat. * TODO 3.0.0: Remove this workaround and mandate unique names. */ - if (purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_CHAT || - purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv))) + if (purple_conversation_get_type(conv) != PURPLE_CONVERSATION_TYPE_CHAT || + purple_chat_conversation_has_left(PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv))) { - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) + if (purple_conversation_get_type(conv) == PURPLE_CONVERSATION_TYPE_CHAT) purple_conversation_chat_cleanup_for_rejoin(conv); return conv; @@ -508,18 +414,18 @@ /* copy features from the connection. */ conv->features = purple_connection_get_flags(gc); - if (type == PURPLE_CONV_TYPE_IM) + if (type == PURPLE_CONVERSATION_TYPE_IM) { PurpleBuddyIcon *icon; - conv->u.im = g_new0(PurpleConvIm, 1); + conv->u.im = g_new0(PurpleIMConversationPrivate, 1); conv->u.im->conv = conv; - PURPLE_DBUS_REGISTER_POINTER(conv->u.im, PurpleConvIm); + PURPLE_DBUS_REGISTER_POINTER(conv->u.im, PurpleIMConversationPrivate); ims = g_list_prepend(ims, conv); if ((icon = purple_buddy_icons_find(account, name))) { - purple_conv_im_set_icon(conv->u.im, icon); - /* purple_conv_im_set_icon refs the icon. */ + purple_im_conversation_set_icon(conv->u.im, icon); + /* purple_im_conversation_set_icon refs the icon. */ purple_buddy_icon_unref(icon); } @@ -529,22 +435,22 @@ open_log(conv); } } - else if (type == PURPLE_CONV_TYPE_CHAT) + else if (type == PURPLE_CONVERSATION_TYPE_CHAT) { const char *disp; - conv->u.chat = g_new0(PurpleConvChat, 1); + conv->u.chat = g_new0(PurpleChatConversationPrivate, 1); conv->u.chat->conv = conv; conv->u.chat->users = g_hash_table_new_full(_purple_conversation_user_hash, _purple_conversation_user_equal, g_free, NULL); - PURPLE_DBUS_REGISTER_POINTER(conv->u.chat, PurpleConvChat); + PURPLE_DBUS_REGISTER_POINTER(conv->u.chat, PurpleChatConversationPrivate); chats = g_list_prepend(chats, conv); if ((disp = purple_connection_get_display_name(purple_account_get_connection(account)))) - purple_conv_chat_set_nick(conv->u.chat, disp); + purple_chat_conversation_set_nick(conv->u.chat, disp); else - purple_conv_chat_set_nick(conv->u.chat, + purple_chat_conversation_set_nick(conv->u.chat, purple_account_get_username(account)); if (purple_prefs_get_bool("/purple/logging/log_chats")) @@ -602,17 +508,17 @@ /* Still connected */ prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) + if (purple_conversation_get_type(conv) == PURPLE_CONVERSATION_TYPE_IM) { if (purple_prefs_get_bool("/purple/conversations/im/send_typing")) - serv_send_typing(gc, name, PURPLE_NOT_TYPING); + serv_send_typing(gc, name, PURPLE_IM_CONVERSATION_NOT_TYPING); if (gc && prpl_info->convo_closed != NULL) prpl_info->convo_closed(gc, name); } - else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) + else if (purple_conversation_get_type(conv) == PURPLE_CONVERSATION_TYPE_CHAT) { - int chat_id = purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)); + int chat_id = purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv)); #if 0 /* * This is unfortunately necessary, because calling @@ -644,14 +550,14 @@ * internals on it's own time. Don't do this if the prpl already * knows it left the chat. */ - if (!purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv))) + if (!purple_chat_conversation_has_left(PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv))) serv_chat_leave(gc, chat_id); /* * If they didn't call serv_got_chat_left by now, it's too late. * So we better do it for them before we destroy the thing. */ - if (!purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv))) + if (!purple_chat_conversation_has_left(PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv))) serv_got_chat_left(gc, chat_id); } } @@ -659,9 +565,9 @@ /* remove from conversations and im/chats lists prior to emit */ conversations = g_list_remove(conversations, conv); - if(conv->type==PURPLE_CONV_TYPE_IM) + if(conv->type==PURPLE_CONVERSATION_TYPE_IM) ims = g_list_remove(ims, conv); - else if(conv->type==PURPLE_CONV_TYPE_CHAT) + else if(conv->type==PURPLE_CONVERSATION_TYPE_CHAT) chats = g_list_remove(chats, conv); hc.name = (gchar *)purple_normalize(conv->account, conv->name); @@ -679,9 +585,9 @@ conv->name = NULL; conv->title = NULL; - if (conv->type == PURPLE_CONV_TYPE_IM) { - purple_conv_im_stop_typing_timeout(conv->u.im); - purple_conv_im_stop_send_typed_timeout(conv->u.im); + if (conv->type == PURPLE_CONVERSATION_TYPE_IM) { + purple_im_conversation_stop_typing_timeout(conv->u.im); + purple_im_conversation_stop_send_typed_timeout(conv->u.im); purple_buddy_icon_unref(conv->u.im->icon); conv->u.im->icon = NULL; @@ -690,11 +596,11 @@ g_free(conv->u.im); conv->u.im = NULL; } - else if (conv->type == PURPLE_CONV_TYPE_CHAT) { + else if (conv->type == PURPLE_CONVERSATION_TYPE_CHAT) { g_hash_table_destroy(conv->u.chat->users); conv->u.chat->users = NULL; - g_list_foreach(conv->u.chat->in_room, (GFunc)purple_conv_chat_cb_destroy, NULL); + g_list_foreach(conv->u.chat->in_room, (GFunc)purple_chat_conversation_buddy_destroy, NULL); g_list_free(conv->u.chat->in_room); g_list_foreach(conv->u.chat->ignored, (GFunc)g_free, NULL); @@ -752,7 +658,7 @@ conv->features = features; - purple_conversation_update(conv, PURPLE_CONV_UPDATE_FEATURES); + purple_conversation_update(conv, PURPLE_CONVERSATION_UPDATE_FEATURES); } @@ -767,7 +673,7 @@ PurpleConversationType purple_conversation_get_type(const PurpleConversation *conv) { - g_return_val_if_fail(conv != NULL, PURPLE_CONV_TYPE_UNKNOWN); + g_return_val_if_fail(conv != NULL, PURPLE_CONVERSATION_TYPE_UNKNOWN); return conv->type; } @@ -807,7 +713,7 @@ conv->account = account; - purple_conversation_update(conv, PURPLE_CONV_UPDATE_ACCOUNT); + purple_conversation_update(conv, PURPLE_CONVERSATION_UPDATE_ACCOUNT); } PurpleAccount * @@ -842,7 +748,7 @@ g_free(conv->title); conv->title = g_strdup(title); - purple_conversation_update(conv, PURPLE_CONV_UPDATE_TITLE); + purple_conversation_update(conv, PURPLE_CONVERSATION_UPDATE_TITLE); } const char * @@ -866,10 +772,10 @@ account = purple_conversation_get_account(conv); name = purple_conversation_get_name(conv); - if(purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { + if(purple_conversation_get_type(conv) == PURPLE_CONVERSATION_TYPE_IM) { if(account && ((b = purple_find_buddy(account, name)) != NULL)) text = purple_buddy_get_contact_alias(b); - } else if(purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { + } else if(purple_conversation_get_type(conv) == PURPLE_CONVERSATION_TYPE_CHAT) { if(account && ((chat = purple_blist_find_chat(account, name)) != NULL)) text = purple_chat_get_name(chat); } @@ -882,21 +788,6 @@ } void -purple_conversation_foreach(void (*func)(PurpleConversation *conv)) -{ - PurpleConversation *conv; - GList *l; - - g_return_if_fail(func != NULL); - - for (l = purple_get_conversations(); l != NULL; l = l->next) { - conv = (PurpleConversation *)l->data; - - func(conv); - } -} - -void purple_conversation_set_name(PurpleConversation *conv, const char *name) { struct _purple_hconv *hc; @@ -933,7 +824,7 @@ if (conv->logging != log) { conv->logging = log; - purple_conversation_update(conv, PURPLE_CONV_UPDATE_LOGGING); + purple_conversation_update(conv, PURPLE_CONVERSATION_UPDATE_LOGGING); } } @@ -955,28 +846,6 @@ conv->logs = NULL; } -PurpleConvIm * -purple_conversation_get_im_data(const PurpleConversation *conv) -{ - g_return_val_if_fail(conv != NULL, NULL); - - if (purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_IM) - return NULL; - - return conv->u.im; -} - -PurpleConvChat * -purple_conversation_get_chat_data(const PurpleConversation *conv) -{ - g_return_val_if_fail(conv != NULL, NULL); - - if (purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_CHAT) - return NULL; - - return conv->u.chat; -} - void purple_conversation_set_data(PurpleConversation *conv, const char *key, gpointer data) @@ -996,62 +865,9 @@ return g_hash_table_lookup(conv->data, key); } -GList * -purple_get_conversations(void) -{ - return conversations; -} - -GList * -purple_get_ims(void) -{ - return ims; -} - -GList * -purple_get_chats(void) -{ - return chats; -} - - -PurpleConversation * -purple_find_conversation_with_account(PurpleConversationType type, - const char *name, - const PurpleAccount *account) -{ - PurpleConversation *c = NULL; - struct _purple_hconv hc; - - g_return_val_if_fail(name != NULL, NULL); - - hc.name = (gchar *)purple_normalize(account, name); - hc.account = account; - hc.type = type; - - switch (type) { - case PURPLE_CONV_TYPE_IM: - case PURPLE_CONV_TYPE_CHAT: - c = g_hash_table_lookup(conversation_cache, &hc); - break; - case PURPLE_CONV_TYPE_ANY: - hc.type = PURPLE_CONV_TYPE_IM; - c = g_hash_table_lookup(conversation_cache, &hc); - if (!c) { - hc.type = PURPLE_CONV_TYPE_CHAT; - c = g_hash_table_lookup(conversation_cache, &hc); - } - break; - default: - g_return_val_if_reached(NULL); - } - - return c; -} - void purple_conversation_write(PurpleConversation *conv, const char *who, - const char *message, PurpleMessageFlags flags, + const char *message, PurpleConversationMessageFlags flags, time_t mtime) { PurplePluginProtocolInfo *prpl_info = NULL; @@ -1076,12 +892,12 @@ if (account != NULL) gc = purple_account_get_connection(account); - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT && + if (purple_conversation_get_type(conv) == PURPLE_CONVERSATION_TYPE_CHAT && (gc != NULL && !g_slist_find(gc->buddy_chats, conv))) return; - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM && - !g_list_find(purple_get_conversations(), conv)) + if (purple_conversation_get_type(conv) == PURPLE_CONVERSATION_TYPE_IM && + !g_list_find(purple_conversations_get(), conv)) return; displayed = g_strdup(message); @@ -1093,7 +909,7 @@ plugin_return = GPOINTER_TO_INT(purple_signal_emit_return_1( purple_conversations_get_handle(), - (type == PURPLE_CONV_TYPE_IM ? "writing-im-msg" : "writing-chat-msg"), + (type == PURPLE_CONVERSATION_TYPE_IM ? "writing-im-msg" : "writing-chat-msg"), account, who, &displayed, conv, flags)); if (displayed == NULL) @@ -1107,15 +923,15 @@ if (account != NULL) { prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(account))); - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM || + if (purple_conversation_get_type(conv) == PURPLE_CONVERSATION_TYPE_IM || !(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { - if (flags & PURPLE_MESSAGE_SEND) { + if (flags & PURPLE_CONVERSATION_MESSAGE_SEND) { b = purple_find_buddy(account, purple_account_get_username(account)); - if (purple_account_get_alias(account) != NULL) - alias = purple_account_get_alias(account); + if (purple_account_get_private_alias(account) != NULL) + alias = purple_account_get_private_alias(account); else if (b != NULL && !purple_strequal(purple_buddy_get_name(b), purple_buddy_get_contact_alias(b))) alias = purple_buddy_get_contact_alias(b); else if (purple_connection_get_display_name(gc) != NULL) @@ -1133,7 +949,7 @@ } } - if (!(flags & PURPLE_MESSAGE_NO_LOG) && purple_conversation_is_logging(conv)) { + if (!(flags & PURPLE_CONVERSATION_MESSAGE_NO_LOG) && purple_conversation_is_logging(conv)) { GList *log; if (conv->logs == NULL) @@ -1152,7 +968,7 @@ add_message_to_history(conv, who, alias, message, flags, mtime); purple_signal_emit(purple_conversations_get_handle(), - (type == PURPLE_CONV_TYPE_IM ? "wrote-im-msg" : "wrote-chat-msg"), + (type == PURPLE_CONVERSATION_TYPE_IM ? "wrote-im-msg" : "wrote-chat-msg"), account, who, displayed, conv, flags); g_free(displayed); @@ -1181,7 +997,7 @@ * when chats are added/removed from the blist. */ void -purple_conversation_update(PurpleConversation *conv, PurpleConvUpdateType type) +purple_conversation_update(PurpleConversation *conv, PurpleConversationUpdateType type) { g_return_if_fail(conv != NULL); @@ -1189,194 +1005,7 @@ "conversation-updated", conv, type); } -/************************************************************************** - * IM Conversation API - **************************************************************************/ -PurpleConversation * -purple_conv_im_get_conversation(const PurpleConvIm *im) -{ - g_return_val_if_fail(im != NULL, NULL); - - return im->conv; -} - -void -purple_conv_im_set_icon(PurpleConvIm *im, PurpleBuddyIcon *icon) -{ - g_return_if_fail(im != NULL); - - if (im->icon != icon) - { - purple_buddy_icon_unref(im->icon); - - im->icon = (icon == NULL ? NULL : purple_buddy_icon_ref(icon)); - } - - purple_conversation_update(purple_conv_im_get_conversation(im), - PURPLE_CONV_UPDATE_ICON); -} - -PurpleBuddyIcon * -purple_conv_im_get_icon(const PurpleConvIm *im) -{ - g_return_val_if_fail(im != NULL, NULL); - - return im->icon; -} - -void -purple_conv_im_set_typing_state(PurpleConvIm *im, PurpleTypingState state) -{ - g_return_if_fail(im != NULL); - - if (im->typing_state != state) - { - im->typing_state = state; - - switch (state) - { - case PURPLE_TYPING: - purple_signal_emit(purple_conversations_get_handle(), - "buddy-typing", im->conv->account, im->conv->name); - break; - case PURPLE_TYPED: - purple_signal_emit(purple_conversations_get_handle(), - "buddy-typed", im->conv->account, im->conv->name); - break; - case PURPLE_NOT_TYPING: - purple_signal_emit(purple_conversations_get_handle(), - "buddy-typing-stopped", im->conv->account, im->conv->name); - break; - } - - purple_conv_im_update_typing(im); - } -} - -PurpleTypingState -purple_conv_im_get_typing_state(const PurpleConvIm *im) -{ - g_return_val_if_fail(im != NULL, 0); - - return im->typing_state; -} - -void -purple_conv_im_start_typing_timeout(PurpleConvIm *im, int timeout) -{ - PurpleConversation *conv; - - g_return_if_fail(im != NULL); - - if (im->typing_timeout > 0) - purple_conv_im_stop_typing_timeout(im); - - conv = purple_conv_im_get_conversation(im); - - im->typing_timeout = purple_timeout_add_seconds(timeout, reset_typing_cb, conv); -} - -void -purple_conv_im_stop_typing_timeout(PurpleConvIm *im) -{ - g_return_if_fail(im != NULL); - - if (im->typing_timeout == 0) - return; - - purple_timeout_remove(im->typing_timeout); - im->typing_timeout = 0; -} - -guint -purple_conv_im_get_typing_timeout(const PurpleConvIm *im) -{ - g_return_val_if_fail(im != NULL, 0); - - return im->typing_timeout; -} - -void -purple_conv_im_set_type_again(PurpleConvIm *im, unsigned int val) -{ - g_return_if_fail(im != NULL); - - if (val == 0) - im->type_again = 0; - else - im->type_again = time(NULL) + val; -} - -time_t -purple_conv_im_get_type_again(const PurpleConvIm *im) -{ - g_return_val_if_fail(im != NULL, 0); - - return im->type_again; -} - -void -purple_conv_im_start_send_typed_timeout(PurpleConvIm *im) -{ - g_return_if_fail(im != NULL); - - im->send_typed_timeout = purple_timeout_add_seconds(SEND_TYPED_TIMEOUT_SECONDS, - send_typed_cb, - purple_conv_im_get_conversation(im)); -} - -void -purple_conv_im_stop_send_typed_timeout(PurpleConvIm *im) -{ - g_return_if_fail(im != NULL); - - if (im->send_typed_timeout == 0) - return; - - purple_timeout_remove(im->send_typed_timeout); - im->send_typed_timeout = 0; -} - -guint -purple_conv_im_get_send_typed_timeout(const PurpleConvIm *im) -{ - g_return_val_if_fail(im != NULL, 0); - - return im->send_typed_timeout; -} - -void -purple_conv_im_update_typing(PurpleConvIm *im) -{ - g_return_if_fail(im != NULL); - - purple_conversation_update(purple_conv_im_get_conversation(im), - PURPLE_CONV_UPDATE_TYPING); -} - -void -purple_conv_im_write(PurpleConvIm *im, const char *who, const char *message, - PurpleMessageFlags flags, time_t mtime) -{ - PurpleConversation *c; - - g_return_if_fail(im != NULL); - g_return_if_fail(message != NULL); - - c = purple_conv_im_get_conversation(im); - - if ((flags & PURPLE_MESSAGE_RECV) == PURPLE_MESSAGE_RECV) { - purple_conv_im_set_typing_state(im, PURPLE_NOT_TYPING); - } - - /* Pass this on to either the ops structure or the default write func. */ - if (c->ui_ops != NULL && c->ui_ops->write_im != NULL) - c->ui_ops->write_im(c, who, message, flags, mtime); - else - purple_conversation_write(c, who, message, flags, mtime); -} - -gboolean purple_conv_present_error(const char *who, PurpleAccount *account, const char *what) +gboolean purple_conversation_helper_present_error(const char *who, PurpleAccount *account, const char *what) { PurpleConversation *conv; @@ -1384,23 +1013,17 @@ g_return_val_if_fail(account !=NULL, FALSE); g_return_val_if_fail(what != NULL, FALSE); - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, who, account); + conv = purple_conversations_find_with_account(PURPLE_CONVERSATION_TYPE_ANY, who, account); if (conv != NULL) - purple_conversation_write(conv, NULL, what, PURPLE_MESSAGE_ERROR, time(NULL)); + purple_conversation_write(conv, NULL, what, PURPLE_CONVERSATION_MESSAGE_ERROR, time(NULL)); else return FALSE; return TRUE; } -void -purple_conv_im_send(PurpleConvIm *im, const char *message) -{ - purple_conv_im_send_with_flags(im, message, 0); -} - static void -purple_conv_send_confirm_cb(gpointer *data) +purple_conversation_send_confirm_cb(gpointer *data) { PurpleConversation *conv = data[0]; char *message = data[1]; @@ -1410,7 +1033,7 @@ } void -purple_conv_send_confirm(PurpleConversation *conv, const char *message) +purple_conversation_send_confirm(PurpleConversation *conv, const char *message) { char *text; gpointer *data; @@ -1432,21 +1055,12 @@ purple_request_action(conv, NULL, _("Send Message"), text, 0, purple_conversation_get_account(conv), NULL, conv, data, 2, - _("_Send Message"), G_CALLBACK(purple_conv_send_confirm_cb), + _("_Send Message"), G_CALLBACK(purple_conversation_send_confirm_cb), _("Cancel"), NULL); } -void -purple_conv_im_send_with_flags(PurpleConvIm *im, const char *message, PurpleMessageFlags flags) -{ - g_return_if_fail(im != NULL); - g_return_if_fail(message != NULL); - - common_send(purple_conv_im_get_conversation(im), message, flags); -} - gboolean -purple_conv_custom_smiley_add(PurpleConversation *conv, const char *smile, +purple_conversation_custom_smiley_add(PurpleConversation *conv, const char *smile, const char *cksum_type, const char *chksum, gboolean remote) { @@ -1466,7 +1080,7 @@ } void -purple_conv_custom_smiley_write(PurpleConversation *conv, const char *smile, +purple_conversation_custom_smiley_write(PurpleConversation *conv, const char *smile, const guchar *data, gsize size) { g_return_if_fail(conv != NULL); @@ -1479,7 +1093,7 @@ } void -purple_conv_custom_smiley_close(PurpleConversation *conv, const char *smile) +purple_conversation_custom_smiley_close(PurpleConversation *conv, const char *smile) { g_return_if_fail(conv != NULL); g_return_if_fail(smile != NULL && *smile); @@ -1490,728 +1104,35 @@ purple_debug_info("conversation", "Could not find custom smiley close function"); } - -/************************************************************************** - * Chat Conversation API - **************************************************************************/ - -PurpleConversation * -purple_conv_chat_get_conversation(const PurpleConvChat *chat) -{ - g_return_val_if_fail(chat != NULL, NULL); - - return chat->conv; -} - -GList * -purple_conv_chat_get_users(const PurpleConvChat *chat) -{ - g_return_val_if_fail(chat != NULL, NULL); - - return chat->in_room; -} - -void -purple_conv_chat_ignore(PurpleConvChat *chat, const char *name) -{ - g_return_if_fail(chat != NULL); - g_return_if_fail(name != NULL); - - /* Make sure the user isn't already ignored. */ - if (purple_conv_chat_is_user_ignored(chat, name)) - return; - - purple_conv_chat_set_ignored(chat, - g_list_append(chat->ignored, g_strdup(name))); -} - -void -purple_conv_chat_unignore(PurpleConvChat *chat, const char *name) -{ - GList *item; - - g_return_if_fail(chat != NULL); - g_return_if_fail(name != NULL); - - /* Make sure the user is actually ignored. */ - if (!purple_conv_chat_is_user_ignored(chat, name)) - return; - - item = g_list_find(purple_conv_chat_get_ignored(chat), - purple_conv_chat_get_ignored_user(chat, name)); - - purple_conv_chat_set_ignored(chat, - g_list_remove_link(chat->ignored, item)); - - g_free(item->data); - g_list_free_1(item); -} - -GList * -purple_conv_chat_set_ignored(PurpleConvChat *chat, GList *ignored) -{ - g_return_val_if_fail(chat != NULL, NULL); - - chat->ignored = ignored; - - return ignored; -} - -GList * -purple_conv_chat_get_ignored(const PurpleConvChat *chat) -{ - g_return_val_if_fail(chat != NULL, NULL); - - return chat->ignored; -} - -const char * -purple_conv_chat_get_ignored_user(const PurpleConvChat *chat, const char *user) -{ - GList *ignored; - - g_return_val_if_fail(chat != NULL, NULL); - g_return_val_if_fail(user != NULL, NULL); - - for (ignored = purple_conv_chat_get_ignored(chat); - ignored != NULL; - ignored = ignored->next) { - - const char *ign = (const char *)ignored->data; - - if (!purple_utf8_strcasecmp(user, ign) || - ((*ign == '+' || *ign == '%') && !purple_utf8_strcasecmp(user, ign + 1))) - return ign; - - if (*ign == '@') { - ign++; - - if ((*ign == '+' && !purple_utf8_strcasecmp(user, ign + 1)) || - (*ign != '+' && !purple_utf8_strcasecmp(user, ign))) - return ign; - } - } - - return NULL; -} - -gboolean -purple_conv_chat_is_user_ignored(const PurpleConvChat *chat, const char *user) -{ - g_return_val_if_fail(chat != NULL, FALSE); - g_return_val_if_fail(user != NULL, FALSE); - - return (purple_conv_chat_get_ignored_user(chat, user) != NULL); -} - -void -purple_conv_chat_set_topic(PurpleConvChat *chat, const char *who, const char *topic) -{ - g_return_if_fail(chat != NULL); - - g_free(chat->who); - g_free(chat->topic); - - chat->who = g_strdup(who); - chat->topic = g_strdup(topic); - - purple_conversation_update(purple_conv_chat_get_conversation(chat), - PURPLE_CONV_UPDATE_TOPIC); - - purple_signal_emit(purple_conversations_get_handle(), "chat-topic-changed", - chat->conv, chat->who, chat->topic); -} - -const char * -purple_conv_chat_get_topic(const PurpleConvChat *chat) -{ - g_return_val_if_fail(chat != NULL, NULL); - - return chat->topic; -} - -void -purple_conv_chat_set_id(PurpleConvChat *chat, int id) -{ - g_return_if_fail(chat != NULL); - - chat->id = id; -} - -int -purple_conv_chat_get_id(const PurpleConvChat *chat) -{ - g_return_val_if_fail(chat != NULL, -1); - - return chat->id; -} - -void -purple_conv_chat_write(PurpleConvChat *chat, const char *who, const char *message, - PurpleMessageFlags flags, time_t mtime) -{ - PurpleAccount *account; - PurpleConversation *conv; - PurpleConnection *gc; - - g_return_if_fail(chat != NULL); - g_return_if_fail(who != NULL); - g_return_if_fail(message != NULL); - - conv = purple_conv_chat_get_conversation(chat); - gc = purple_conversation_get_connection(conv); - account = purple_connection_get_account(gc); - - /* Don't display this if the person who wrote it is ignored. */ - if (purple_conv_chat_is_user_ignored(chat, who)) - return; - - if (!(flags & PURPLE_MESSAGE_WHISPER)) { - const char *str; - - str = purple_normalize(account, who); - - if (purple_strequal(str, chat->nick)) { - flags |= PURPLE_MESSAGE_SEND; - } else { - flags |= PURPLE_MESSAGE_RECV; - - if (purple_utf8_has_word(message, chat->nick)) - flags |= PURPLE_MESSAGE_NICK; - } - } - - /* Pass this on to either the ops structure or the default write func. */ - if (conv->ui_ops != NULL && conv->ui_ops->write_chat != NULL) - conv->ui_ops->write_chat(conv, who, message, flags, mtime); - else - purple_conversation_write(conv, who, message, flags, mtime); -} - -void -purple_conv_chat_send(PurpleConvChat *chat, const char *message) -{ - purple_conv_chat_send_with_flags(chat, message, 0); -} - -void -purple_conv_chat_send_with_flags(PurpleConvChat *chat, const char *message, PurpleMessageFlags flags) -{ - g_return_if_fail(chat != NULL); - g_return_if_fail(message != NULL); - - common_send(purple_conv_chat_get_conversation(chat), message, flags); -} - -void -purple_conv_chat_add_user(PurpleConvChat *chat, const char *user, - const char *extra_msg, PurpleConvChatBuddyFlags flags, - gboolean new_arrival) -{ - GList *users = g_list_append(NULL, (char *)user); - GList *extra_msgs = g_list_append(NULL, (char *)extra_msg); - GList *flags2 = g_list_append(NULL, GINT_TO_POINTER(flags)); - - purple_conv_chat_add_users(chat, users, extra_msgs, flags2, new_arrival); - - g_list_free(users); - g_list_free(extra_msgs); - g_list_free(flags2); -} - -static int -purple_conv_chat_cb_compare(PurpleConvChatBuddy *a, PurpleConvChatBuddy *b) -{ - PurpleConvChatBuddyFlags f1 = 0, f2 = 0; - char *user1 = NULL, *user2 = NULL; - gint ret = 0; - - if (a) { - f1 = a->flags; - if (a->alias_key) - user1 = a->alias_key; - else if (a->name) - user1 = a->name; - } - - if (b) { - f2 = b->flags; - if (b->alias_key) - user2 = b->alias_key; - else if (b->name) - user2 = b->name; - } - - if (user1 == NULL || user2 == NULL) { - if (!(user1 == NULL && user2 == NULL)) - ret = (user1 == NULL) ? -1: 1; - } else if (f1 != f2) { - /* sort more important users first */ - ret = (f1 > f2) ? -1 : 1; - } else if (a->buddy != b->buddy) { - ret = a->buddy ? -1 : 1; - } else { - ret = purple_utf8_strcasecmp(user1, user2); - } - - return ret; -} - -void -purple_conv_chat_add_users(PurpleConvChat *chat, GList *users, GList *extra_msgs, - GList *flags, gboolean new_arrivals) -{ - PurpleConversation *conv; - PurpleConversationUiOps *ops; - PurpleConvChatBuddy *cbuddy; - PurpleConnection *gc; - PurplePluginProtocolInfo *prpl_info; - GList *ul, *fl; - GList *cbuddies = NULL; - - g_return_if_fail(chat != NULL); - g_return_if_fail(users != NULL); - - conv = purple_conv_chat_get_conversation(chat); - ops = purple_conversation_get_ui_ops(conv); - - gc = purple_conversation_get_connection(conv); - g_return_if_fail(gc != NULL); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); - g_return_if_fail(prpl_info != NULL); - - ul = users; - fl = flags; - while ((ul != NULL) && (fl != NULL)) { - const char *user = (const char *)ul->data; - const char *alias = user; - gboolean quiet; - PurpleConvChatBuddyFlags flag = GPOINTER_TO_INT(fl->data); - const char *extra_msg = (extra_msgs ? extra_msgs->data : NULL); - - if(!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { - if (purple_strequal(chat->nick, purple_normalize(conv->account, user))) { - const char *alias2 = purple_account_get_alias(conv->account); - if (alias2 != NULL) - alias = alias2; - else - { - const char *display_name = purple_connection_get_display_name(gc); - if (display_name != NULL) - alias = display_name; - } - } else { - PurpleBuddy *buddy; - if ((buddy = purple_find_buddy(purple_connection_get_account(gc), user)) != NULL) - alias = purple_buddy_get_contact_alias(buddy); - } - } - - quiet = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_conversations_get_handle(), - "chat-buddy-joining", conv, user, flag)) || - purple_conv_chat_is_user_ignored(chat, user); - - cbuddy = purple_conv_chat_cb_new(user, alias, flag); - cbuddy->buddy = purple_find_buddy(conv->account, user) != NULL; - - chat->in_room = g_list_prepend(chat->in_room, cbuddy); - g_hash_table_replace(chat->users, g_strdup(cbuddy->name), cbuddy); - - cbuddies = g_list_prepend(cbuddies, cbuddy); - - if (!quiet && new_arrivals) { - char *alias_esc = g_markup_escape_text(alias, -1); - char *tmp; - - if (extra_msg == NULL) - tmp = g_strdup_printf(_("%s entered the room."), alias_esc); - else { - char *extra_msg_esc = g_markup_escape_text(extra_msg, -1); - tmp = g_strdup_printf(_("%s [<I>%s</I>] entered the room."), - alias_esc, extra_msg_esc); - g_free(extra_msg_esc); - } - g_free(alias_esc); - - purple_conversation_write(conv, NULL, tmp, - PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LINKIFY, - time(NULL)); - g_free(tmp); - } - - purple_signal_emit(purple_conversations_get_handle(), - "chat-buddy-joined", conv, user, flag, new_arrivals); - ul = ul->next; - fl = fl->next; - if (extra_msgs != NULL) - extra_msgs = extra_msgs->next; - } - - cbuddies = g_list_sort(cbuddies, (GCompareFunc)purple_conv_chat_cb_compare); - - if (ops != NULL && ops->chat_add_users != NULL) - ops->chat_add_users(conv, cbuddies, new_arrivals); - - g_list_free(cbuddies); -} - -void -purple_conv_chat_rename_user(PurpleConvChat *chat, const char *old_user, - const char *new_user) -{ - PurpleConversation *conv; - PurpleConversationUiOps *ops; - PurpleConnection *gc; - PurplePluginProtocolInfo *prpl_info; - PurpleConvChatBuddy *cb; - PurpleConvChatBuddyFlags flags; - const char *new_alias = new_user; - char tmp[BUF_LONG]; - gboolean is_me = FALSE; - - g_return_if_fail(chat != NULL); - g_return_if_fail(old_user != NULL); - g_return_if_fail(new_user != NULL); - - conv = purple_conv_chat_get_conversation(chat); - ops = purple_conversation_get_ui_ops(conv); - - gc = purple_conversation_get_connection(conv); - g_return_if_fail(gc != NULL); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); - g_return_if_fail(prpl_info != NULL); - - if (purple_strequal(chat->nick, purple_normalize(conv->account, old_user))) { - const char *alias; - - /* Note this for later. */ - is_me = TRUE; - - if(!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { - alias = purple_account_get_alias(conv->account); - if (alias != NULL) - new_alias = alias; - else - { - const char *display_name = purple_connection_get_display_name(gc); - if (display_name != NULL) - new_alias = display_name; - } - } - } else if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { - PurpleBuddy *buddy; - if ((buddy = purple_find_buddy(purple_connection_get_account(gc), new_user)) != NULL) - new_alias = purple_buddy_get_contact_alias(buddy); - } - - flags = purple_conv_chat_user_get_flags(chat, old_user); - cb = purple_conv_chat_cb_new(new_user, new_alias, flags); - cb->buddy = purple_find_buddy(conv->account, new_user) != NULL; - - chat->in_room = g_list_prepend(chat->in_room, cb); - g_hash_table_replace(chat->users, g_strdup(cb->name), cb); - - if (ops != NULL && ops->chat_rename_user != NULL) - ops->chat_rename_user(conv, old_user, new_user, new_alias); - - cb = purple_conv_chat_cb_find(chat, old_user); - - if (cb) { - chat->in_room = g_list_remove(chat->in_room, cb); - g_hash_table_remove(chat->users, cb->name); - purple_conv_chat_cb_destroy(cb); - } - - if (purple_conv_chat_is_user_ignored(chat, old_user)) { - purple_conv_chat_unignore(chat, old_user); - purple_conv_chat_ignore(chat, new_user); - } - else if (purple_conv_chat_is_user_ignored(chat, new_user)) - purple_conv_chat_unignore(chat, new_user); - - if (is_me) - purple_conv_chat_set_nick(chat, new_user); - - if (purple_prefs_get_bool("/purple/conversations/chat/show_nick_change") && - !purple_conv_chat_is_user_ignored(chat, new_user)) { - - if (is_me) { - char *escaped = g_markup_escape_text(new_user, -1); - g_snprintf(tmp, sizeof(tmp), - _("You are now known as %s"), escaped); - g_free(escaped); - } else { - const char *old_alias = old_user; - const char *new_alias = new_user; - char *escaped; - char *escaped2; - - if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { - PurpleBuddy *buddy; - - if ((buddy = purple_find_buddy(purple_connection_get_account(gc), old_user)) != NULL) - old_alias = purple_buddy_get_contact_alias(buddy); - if ((buddy = purple_find_buddy(purple_connection_get_account(gc), new_user)) != NULL) - new_alias = purple_buddy_get_contact_alias(buddy); - } - - escaped = g_markup_escape_text(old_alias, -1); - escaped2 = g_markup_escape_text(new_alias, -1); - g_snprintf(tmp, sizeof(tmp), - _("%s is now known as %s"), escaped, escaped2); - g_free(escaped); - g_free(escaped2); - } - - purple_conversation_write(conv, NULL, tmp, - PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LINKIFY, - time(NULL)); - } -} - -void -purple_conv_chat_remove_user(PurpleConvChat *chat, const char *user, const char *reason) -{ - GList *users = g_list_append(NULL, (char *)user); - - purple_conv_chat_remove_users(chat, users, reason); - - g_list_free(users); -} - -void -purple_conv_chat_remove_users(PurpleConvChat *chat, GList *users, const char *reason) -{ - PurpleConversation *conv; - PurpleConnection *gc; - PurplePluginProtocolInfo *prpl_info; - PurpleConversationUiOps *ops; - PurpleConvChatBuddy *cb; - GList *l; - gboolean quiet; - - g_return_if_fail(chat != NULL); - g_return_if_fail(users != NULL); - - conv = purple_conv_chat_get_conversation(chat); - - gc = purple_conversation_get_connection(conv); - g_return_if_fail(gc != NULL); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); - g_return_if_fail(prpl_info != NULL); - - ops = purple_conversation_get_ui_ops(conv); - - for (l = users; l != NULL; l = l->next) { - const char *user = (const char *)l->data; - quiet = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_conversations_get_handle(), - "chat-buddy-leaving", conv, user, reason)) | - purple_conv_chat_is_user_ignored(chat, user); - - cb = purple_conv_chat_cb_find(chat, user); - - if (cb) { - chat->in_room = g_list_remove(chat->in_room, cb); - g_hash_table_remove(chat->users, cb->name); - purple_conv_chat_cb_destroy(cb); - } - - /* NOTE: Don't remove them from ignored in case they re-enter. */ - - if (!quiet) { - const char *alias = user; - char *alias_esc; - char *tmp; - - if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { - PurpleBuddy *buddy; - - if ((buddy = purple_find_buddy(purple_connection_get_account(gc), user)) != NULL) - alias = purple_buddy_get_contact_alias(buddy); - } - - alias_esc = g_markup_escape_text(alias, -1); - - if (reason == NULL || !*reason) - tmp = g_strdup_printf(_("%s left the room."), alias_esc); - else { - char *reason_esc = g_markup_escape_text(reason, -1); - tmp = g_strdup_printf(_("%s left the room (%s)."), - alias_esc, reason_esc); - g_free(reason_esc); - } - g_free(alias_esc); - - purple_conversation_write(conv, NULL, tmp, - PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LINKIFY, - time(NULL)); - g_free(tmp); - } - - purple_signal_emit(purple_conversations_get_handle(), "chat-buddy-left", - conv, user, reason); - } - - if (ops != NULL && ops->chat_remove_users != NULL) - ops->chat_remove_users(conv, users); -} - -void -purple_conv_chat_clear_users(PurpleConvChat *chat) -{ - PurpleConversation *conv; - PurpleConversationUiOps *ops; - GList *users; - GList *l; - GList *names = NULL; - - g_return_if_fail(chat != NULL); - - conv = purple_conv_chat_get_conversation(chat); - ops = purple_conversation_get_ui_ops(conv); - users = chat->in_room; - - if (ops != NULL && ops->chat_remove_users != NULL) { - for (l = users; l; l = l->next) { - PurpleConvChatBuddy *cb = l->data; - names = g_list_prepend(names, cb->name); - } - ops->chat_remove_users(conv, names); - g_list_free(names); - } - - for (l = users; l; l = l->next) - { - PurpleConvChatBuddy *cb = l->data; - - purple_signal_emit(purple_conversations_get_handle(), - "chat-buddy-leaving", conv, cb->name, NULL); - purple_signal_emit(purple_conversations_get_handle(), - "chat-buddy-left", conv, cb->name, NULL); - - purple_conv_chat_cb_destroy(cb); - } - - g_hash_table_remove_all(chat->users); - - g_list_free(users); - chat->in_room = NULL; -} - - -gboolean -purple_conv_chat_find_user(PurpleConvChat *chat, const char *user) -{ - g_return_val_if_fail(chat != NULL, FALSE); - g_return_val_if_fail(user != NULL, FALSE); - - return (purple_conv_chat_cb_find(chat, user) != NULL); -} - -void -purple_conv_chat_user_set_flags(PurpleConvChat *chat, const char *user, - PurpleConvChatBuddyFlags flags) -{ - PurpleConversation *conv; - PurpleConversationUiOps *ops; - PurpleConvChatBuddy *cb; - PurpleConvChatBuddyFlags oldflags; - - g_return_if_fail(chat != NULL); - g_return_if_fail(user != NULL); - - cb = purple_conv_chat_cb_find(chat, user); - - if (!cb) - return; - - if (flags == cb->flags) - return; - - oldflags = cb->flags; - cb->flags = flags; - - conv = purple_conv_chat_get_conversation(chat); - ops = purple_conversation_get_ui_ops(conv); - - if (ops != NULL && ops->chat_update_user != NULL) - ops->chat_update_user(conv, user); - - purple_signal_emit(purple_conversations_get_handle(), - "chat-buddy-flags", conv, user, oldflags, flags); -} - -PurpleConvChatBuddyFlags -purple_conv_chat_user_get_flags(PurpleConvChat *chat, const char *user) -{ - PurpleConvChatBuddy *cb; - - g_return_val_if_fail(chat != NULL, 0); - g_return_val_if_fail(user != NULL, 0); - - cb = purple_conv_chat_cb_find(chat, user); - - if (!cb) - return PURPLE_CBFLAGS_NONE; - - return cb->flags; -} - -void purple_conv_chat_set_nick(PurpleConvChat *chat, const char *nick) { +void purple_chat_conversation_set_nick(PurpleChatConversation *chat, const char *nick) { g_return_if_fail(chat != NULL); g_free(chat->nick); chat->nick = g_strdup(purple_normalize(chat->conv->account, nick)); } -const char *purple_conv_chat_get_nick(PurpleConvChat *chat) { +const char *purple_chat_conversation_get_nick(PurpleChatConversation *chat) { g_return_val_if_fail(chat != NULL, NULL); return chat->nick; } -PurpleConversation * -purple_find_chat(const PurpleConnection *gc, int id) -{ - GList *l; - PurpleConversation *conv; - - for (l = purple_get_chats(); l != NULL; l = l->next) { - conv = (PurpleConversation *)l->data; - - if (purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)) == id && - purple_conversation_get_connection(conv) == gc) - return conv; - } - - return NULL; -} - -void -purple_conv_chat_left(PurpleConvChat *chat) -{ - g_return_if_fail(chat != NULL); - - chat->left = TRUE; - purple_conversation_update(chat->conv, PURPLE_CONV_UPDATE_CHATLEFT); -} - static void invite_user_to_chat(gpointer data, PurpleRequestFields *fields) { PurpleConversation *conv; - PurpleConvChat *chat; + PurpleChatConversationPrivate *priv; const char *user, *message; conv = data; - chat = PURPLE_CONV_CHAT(conv); + chat = PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv); user = purple_request_fields_get_string(fields, "screenname"); message = purple_request_fields_get_string(fields, "message"); serv_chat_invite(purple_conversation_get_connection(conv), chat->id, message, user); } -void purple_conv_chat_invite_user(PurpleConvChat *chat, const char *user, +void purple_chat_conversation_invite_user(PurpleChatConversation *chat, const char *user, const char *message, gboolean confirm) { PurpleAccount *account; @@ -2230,7 +1151,7 @@ if (!confirm) { serv_chat_invite(purple_account_get_connection(account), - purple_conv_chat_get_id(chat), message, user); + purple_chat_conversation_get_id(chat), message, user); return; } @@ -2256,113 +1177,27 @@ conv); } -gboolean -purple_conv_chat_has_left(PurpleConvChat *chat) -{ - g_return_val_if_fail(chat != NULL, TRUE); - - return chat->left; -} - -PurpleConvChatBuddy * -purple_conv_chat_cb_new(const char *name, const char *alias, PurpleConvChatBuddyFlags flags) -{ - PurpleConvChatBuddy *cb; - - g_return_val_if_fail(name != NULL, NULL); - - cb = g_new0(PurpleConvChatBuddy, 1); - cb->name = g_strdup(name); - cb->flags = flags; - cb->alias = g_strdup(alias); - cb->attributes = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, g_free); - - PURPLE_DBUS_REGISTER_POINTER(cb, PurpleConvChatBuddy); - return cb; -} - -PurpleConvChatBuddy * -purple_conv_chat_cb_find(PurpleConvChat *chat, const char *name) -{ - g_return_val_if_fail(chat != NULL, NULL); - g_return_val_if_fail(name != NULL, NULL); - - return g_hash_table_lookup(chat->users, name); -} - -void -purple_conv_chat_cb_destroy(PurpleConvChatBuddy *cb) -{ - if (cb == NULL) - return; - - purple_signal_emit(purple_conversations_get_handle(), - "deleting-chat-buddy", cb); - - g_free(cb->alias); - g_free(cb->alias_key); - g_free(cb->name); - g_hash_table_destroy(cb->attributes); - - PURPLE_DBUS_UNREGISTER_POINTER(cb); - g_free(cb); -} - -void purple_conv_chat_cb_set_ui_data(PurpleConvChatBuddy *cb, gpointer ui_data) +void purple_chat_conversation_buddy_set_ui_data(PurpleChatConversationBuddy *cb, gpointer ui_data) { g_return_if_fail(cb != NULL); cb->ui_data = ui_data; } -gpointer purple_conv_chat_cb_get_ui_data(const PurpleConvChatBuddy *cb) +gpointer purple_chat_conversation_buddy_get_ui_data(const PurpleChatConversationBuddy *cb) { g_return_val_if_fail(cb != NULL, NULL); return cb->ui_data; } -const char * -purple_conv_chat_cb_get_alias(const PurpleConvChatBuddy *cb) -{ - g_return_val_if_fail(cb != NULL, NULL); - - return cb->alias; -} - -const char * -purple_conv_chat_cb_get_name(const PurpleConvChatBuddy *cb) -{ - g_return_val_if_fail(cb != NULL, NULL); - - return cb->name; -} - -PurpleConvChatBuddyFlags -purple_conv_chat_cb_get_flags(const PurpleConvChatBuddy *cb) -{ - g_return_val_if_fail(cb != NULL, PURPLE_CBFLAGS_NONE); - - return cb->flags; -} - -gboolean purple_conv_chat_cb_is_buddy(const PurpleConvChatBuddy *cb) +gboolean purple_chat_conversation_buddy_is_buddy(const PurpleChatConversationBuddy *cb) { g_return_val_if_fail(cb != NULL, FALSE); return cb->buddy; } -const char * -purple_conv_chat_cb_get_attribute(PurpleConvChatBuddy *cb, const char *key) -{ - g_return_val_if_fail(cb != NULL, NULL); - g_return_val_if_fail(key != NULL, NULL); - - return g_hash_table_lookup(cb->attributes, key); -} - static void append_attribute_key(gpointer key, gpointer value, gpointer user_data) { @@ -2371,60 +1206,6 @@ } GList * -purple_conv_chat_cb_get_attribute_keys(PurpleConvChatBuddy *cb) -{ - GList *keys = NULL; - - g_return_val_if_fail(cb != NULL, NULL); - - g_hash_table_foreach(cb->attributes, (GHFunc)append_attribute_key, &keys); - - return keys; -} - -void -purple_conv_chat_cb_set_attribute(PurpleConvChat *chat, PurpleConvChatBuddy *cb, const char *key, const char *value) -{ - PurpleConversation *conv; - PurpleConversationUiOps *ops; - - g_return_if_fail(cb != NULL); - g_return_if_fail(key != NULL); - g_return_if_fail(value != NULL); - - g_hash_table_replace(cb->attributes, g_strdup(key), g_strdup(value)); - - conv = purple_conv_chat_get_conversation(chat); - ops = purple_conversation_get_ui_ops(conv); - - if (ops != NULL && ops->chat_update_user != NULL) - ops->chat_update_user(conv, cb->name); -} - -void -purple_conv_chat_cb_set_attributes(PurpleConvChat *chat, PurpleConvChatBuddy *cb, GList *keys, GList *values) -{ - PurpleConversation *conv; - PurpleConversationUiOps *ops; - - g_return_if_fail(cb != NULL); - g_return_if_fail(keys != NULL); - g_return_if_fail(values != NULL); - - while (keys != NULL && values != NULL) { - g_hash_table_replace(cb->attributes, g_strdup(keys->data), g_strdup(values->data)); - keys = g_list_next(keys); - values = g_list_next(values); - } - - conv = purple_conv_chat_get_conversation(chat); - ops = purple_conversation_get_ui_ops(conv); - - if (ops != NULL && ops->chat_update_user != NULL) - ops->chat_update_user(conv, cb->name); -} - -GList * purple_conversation_get_extended_menu(PurpleConversation *conv) { GList *menu = NULL; @@ -2451,37 +1232,37 @@ return conv->message_history; } -const char *purple_conversation_message_get_sender(const PurpleConvMessage *msg) +const char *purple_conversation_message_get_sender(const PurpleConversationMessage *msg) { g_return_val_if_fail(msg, NULL); return msg->who; } -const char *purple_conversation_message_get_message(const PurpleConvMessage *msg) +const char *purple_conversation_message_get_message(const PurpleConversationMessage *msg) { g_return_val_if_fail(msg, NULL); return msg->what; } -PurpleMessageFlags purple_conversation_message_get_flags(const PurpleConvMessage *msg) +PurpleConversationMessageFlags purple_conversation_message_get_flags(const PurpleConversationMessage *msg) { g_return_val_if_fail(msg, 0); return msg->flags; } -time_t purple_conversation_message_get_timestamp(const PurpleConvMessage *msg) +time_t purple_conversation_message_get_timestamp(const PurpleConversationMessage *msg) { g_return_val_if_fail(msg, 0); return msg->when; } -const char *purple_conversation_message_get_alias(const PurpleConvMessage *msg) +const char *purple_conversation_message_get_alias(const PurpleConversationMessage *msg) { g_return_val_if_fail(msg, NULL); return msg->alias; } -PurpleConversation *purple_conversation_message_get_conv(const PurpleConvMessage *msg) +PurpleConversation *purple_conversation_message_get_conv(const PurpleConversationMessage *msg) { g_return_val_if_fail(msg, NULL); return msg->conv; @@ -2512,344 +1293,3 @@ g_free(err); return (status == PURPLE_CMD_STATUS_OK); } - -void * -purple_conversations_get_handle(void) -{ - static int handle; - - return &handle; -} - -void -purple_conversations_init(void) -{ - void *handle = purple_conversations_get_handle(); - - conversation_cache = g_hash_table_new_full((GHashFunc)_purple_conversations_hconv_hash, - (GEqualFunc)_purple_conversations_hconv_equal, - (GDestroyNotify)_purple_conversations_hconv_free_key, NULL); - - /********************************************************************** - * Register preferences - **********************************************************************/ - - /* Conversations */ - purple_prefs_add_none("/purple/conversations"); - - /* Conversations -> Chat */ - purple_prefs_add_none("/purple/conversations/chat"); - purple_prefs_add_bool("/purple/conversations/chat/show_nick_change", TRUE); - - /* Conversations -> IM */ - purple_prefs_add_none("/purple/conversations/im"); - purple_prefs_add_bool("/purple/conversations/im/send_typing", TRUE); - - - /********************************************************************** - * Register signals - **********************************************************************/ - purple_signal_register(handle, "writing-im-msg", - purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_UINT, - purple_value_new(PURPLE_TYPE_BOOLEAN), 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new_outgoing(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "wrote-im-msg", - purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT, - NULL, 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "sent-attention", - purple_marshal_VOID__POINTER_POINTER_POINTER_UINT, - NULL, 4, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "got-attention", - purple_marshal_VOID__POINTER_POINTER_POINTER_UINT, - NULL, 4, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "sending-im-msg", - purple_marshal_VOID__POINTER_POINTER_POINTER, - NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new_outgoing(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "sent-im-msg", - purple_marshal_VOID__POINTER_POINTER_POINTER, - NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "receiving-im-msg", - purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER, - purple_value_new(PURPLE_TYPE_BOOLEAN), 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new_outgoing(PURPLE_TYPE_STRING), - purple_value_new_outgoing(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new_outgoing(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "received-im-msg", - purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT, - NULL, 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "blocked-im-msg", - purple_marshal_VOID__POINTER_POINTER_POINTER_UINT_UINT, - NULL, 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_UINT), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "writing-chat-msg", - purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_UINT, - purple_value_new(PURPLE_TYPE_BOOLEAN), 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new_outgoing(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "wrote-chat-msg", - purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT, - NULL, 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "sending-chat-msg", - purple_marshal_VOID__POINTER_POINTER_UINT, NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new_outgoing(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "sent-chat-msg", - purple_marshal_VOID__POINTER_POINTER_UINT, NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "receiving-chat-msg", - purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER, - purple_value_new(PURPLE_TYPE_BOOLEAN), 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new_outgoing(PURPLE_TYPE_STRING), - purple_value_new_outgoing(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new_outgoing(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "received-chat-msg", - purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT, - NULL, 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "conversation-created", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION)); - - purple_signal_register(handle, "conversation-updated", - purple_marshal_VOID__POINTER_UINT, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "deleting-conversation", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION)); - - purple_signal_register(handle, "buddy-typing", - purple_marshal_VOID__POINTER_POINTER, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "buddy-typed", - purple_marshal_VOID__POINTER_POINTER, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "buddy-typing-stopped", - purple_marshal_VOID__POINTER_POINTER, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "chat-buddy-joining", - purple_marshal_BOOLEAN__POINTER_POINTER_UINT, - purple_value_new(PURPLE_TYPE_BOOLEAN), 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "chat-buddy-joined", - purple_marshal_VOID__POINTER_POINTER_UINT_UINT, NULL, 4, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_UINT), - purple_value_new(PURPLE_TYPE_BOOLEAN)); - - purple_signal_register(handle, "chat-buddy-flags", - purple_marshal_VOID__POINTER_POINTER_UINT_UINT, NULL, 4, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_UINT), - purple_value_new(PURPLE_TYPE_UINT)); - - purple_signal_register(handle, "chat-buddy-leaving", - purple_marshal_BOOLEAN__POINTER_POINTER_POINTER, - purple_value_new(PURPLE_TYPE_BOOLEAN), 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "chat-buddy-left", - purple_marshal_VOID__POINTER_POINTER_POINTER, NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "deleting-chat-buddy", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CHATBUDDY)); - - purple_signal_register(handle, "chat-inviting-user", - purple_marshal_VOID__POINTER_POINTER_POINTER, NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new_outgoing(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "chat-invited-user", - purple_marshal_VOID__POINTER_POINTER_POINTER, NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "chat-invited", - purple_marshal_INT__POINTER_POINTER_POINTER_POINTER_POINTER, - purple_value_new(PURPLE_TYPE_INT), 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_POINTER)); - - purple_signal_register(handle, "chat-invite-blocked", - purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_POINTER, - NULL, 5, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_ACCOUNT), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_BOXED, "GHashTable *")); - - purple_signal_register(handle, "chat-joined", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION)); - - purple_signal_register(handle, "chat-join-failed", - purple_marshal_VOID__POINTER_POINTER, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONNECTION), - purple_value_new(PURPLE_TYPE_POINTER)); - - purple_signal_register(handle, "chat-left", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION)); - - purple_signal_register(handle, "chat-topic-changed", - purple_marshal_VOID__POINTER_POINTER_POINTER, NULL, 3, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_STRING), - purple_value_new(PURPLE_TYPE_STRING)); - - purple_signal_register(handle, "cleared-message-history", - purple_marshal_VOID__POINTER, NULL, 1, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION)); - - purple_signal_register(handle, "conversation-extended-menu", - purple_marshal_VOID__POINTER_POINTER, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONVERSATION), - purple_value_new(PURPLE_TYPE_BOXED, "GList **")); -} - -void -purple_conversations_uninit(void) -{ - while (conversations) - purple_conversation_destroy((PurpleConversation*)conversations->data); - g_hash_table_destroy(conversation_cache); - purple_signals_unregister_by_instance(purple_conversations_get_handle()); -} -
--- a/libpurple/conversation.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/conversation.h Sun Jun 23 13:35:53 2013 +0530 @@ -1,7 +1,6 @@ /** * @file conversation.h Conversation API * @ingroup core - * @see @ref conversation-signals */ /* purple @@ -27,128 +26,133 @@ #ifndef _PURPLE_CONVERSATION_H_ #define _PURPLE_CONVERSATION_H_ +#define PURPLE_TYPE_CONVERSATION (purple_conversation_get_type()) +#define PURPLE_CONVERSATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_CONVERSATION, PurpleConversation)) +#define PURPLE_CONVERSATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_CONVERSATION, PurpleConversationClass)) +#define PURPLE_IS_CONVERSATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_CONVERSATION)) +#define PURPLE_IS_CONVERSATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_CONVERSATION)) +#define PURPLE_CONVERSATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_CONVERSATION, PurpleConversationClass)) + /**************************************************************************/ /** Data Structures */ /**************************************************************************/ +/** @copydoc _PurpleConversation */ +typedef struct _PurpleConversation PurpleConversation; +/** @copydoc _PurpleConversation */ +typedef struct _PurpleConversationClass PurpleConversationClass; /** @copydoc _PurpleConversationUiOps */ -typedef struct _PurpleConversationUiOps PurpleConversationUiOps; -/** @copydoc _PurpleConversation */ -typedef struct _PurpleConversation PurpleConversation; -/** @copydoc _PurpleConvIm */ -typedef struct _PurpleConvIm PurpleConvIm; -/** @copydoc _PurpleConvChat */ -typedef struct _PurpleConvChat PurpleConvChat; -/** @copydoc _PurpleConvChatBuddy */ -typedef struct _PurpleConvChatBuddy PurpleConvChatBuddy; -/** @copydoc _PurpleConvMessage */ -typedef struct _PurpleConvMessage PurpleConvMessage; - -/** - * A type of conversation. - */ -typedef enum -{ - PURPLE_CONV_TYPE_UNKNOWN = 0, /**< Unknown conversation type. */ - PURPLE_CONV_TYPE_IM, /**< Instant Message. */ - PURPLE_CONV_TYPE_CHAT, /**< Chat room. */ - PURPLE_CONV_TYPE_MISC, /**< A misc. conversation. */ - PURPLE_CONV_TYPE_ANY /**< Any type of conversation. */ - -} PurpleConversationType; +typedef struct _PurpleConversationUiOps PurpleConversationUiOps; +/** @copydoc _PurpleConversationMessage */ +typedef struct _PurpleConversationMessage PurpleConversationMessage; /** * Conversation update type. */ typedef enum { - PURPLE_CONV_UPDATE_ADD = 0, /**< The buddy associated with the conversation - was added. */ - PURPLE_CONV_UPDATE_REMOVE, /**< The buddy associated with the conversation - was removed. */ - PURPLE_CONV_UPDATE_ACCOUNT, /**< The purple_account was changed. */ - PURPLE_CONV_UPDATE_TYPING, /**< The typing state was updated. */ - PURPLE_CONV_UPDATE_UNSEEN, /**< The unseen state was updated. */ - PURPLE_CONV_UPDATE_LOGGING, /**< Logging for this conversation was - enabled or disabled. */ - PURPLE_CONV_UPDATE_TOPIC, /**< The topic for a chat was updated. */ + PURPLE_CONVERSATION_UPDATE_ADD = 0, /**< The buddy associated with the conversation + was added. */ + PURPLE_CONVERSATION_UPDATE_REMOVE, /**< The buddy associated with the conversation + was removed. */ + PURPLE_CONVERSATION_UPDATE_ACCOUNT, /**< The purple_account was changed. */ + PURPLE_CONVERSATION_UPDATE_TYPING, /**< The typing state was updated. */ + PURPLE_CONVERSATION_UPDATE_UNSEEN, /**< The unseen state was updated. */ + PURPLE_CONVERSATION_UPDATE_LOGGING, /**< Logging for this conversation was + enabled or disabled. */ + PURPLE_CONVERSATION_UPDATE_TOPIC, /**< The topic for a chat was updated. */ /* * XXX These need to go when we implement a more generic core/UI event * system. */ - PURPLE_CONV_ACCOUNT_ONLINE, /**< One of the user's accounts went online. */ - PURPLE_CONV_ACCOUNT_OFFLINE, /**< One of the user's accounts went offline. */ - PURPLE_CONV_UPDATE_AWAY, /**< The other user went away. */ - PURPLE_CONV_UPDATE_ICON, /**< The other user's buddy icon changed. */ - PURPLE_CONV_UPDATE_TITLE, - PURPLE_CONV_UPDATE_CHATLEFT, - - PURPLE_CONV_UPDATE_FEATURES /**< The features for a chat have changed */ - -} PurpleConvUpdateType; + PURPLE_CONVERSATION_ACCOUNT_ONLINE, /**< One of the user's accounts went online. */ + PURPLE_CONVERSATION_ACCOUNT_OFFLINE, /**< One of the user's accounts went offline. */ + PURPLE_CONVERSATION_UPDATE_AWAY, /**< The other user went away. */ + PURPLE_CONVERSATION_UPDATE_ICON, /**< The other user's buddy icon changed. */ + PURPLE_CONVERSATION_UPDATE_TITLE, + PURPLE_CONVERSATION_UPDATE_CHATLEFT, -/** - * The typing state of a user. - */ -typedef enum -{ - PURPLE_NOT_TYPING = 0, /**< Not typing. */ - PURPLE_TYPING, /**< Currently typing. */ - PURPLE_TYPED /**< Stopped typing momentarily. */ + PURPLE_CONVERSATION_UPDATE_FEATURES /**< The features for a chat have changed */ -} PurpleTypingState; +} PurpleConversationUpdateType; /** * Flags applicable to a message. Most will have send, recv or system. */ -typedef enum +typedef enum /*< flags >*/ { - PURPLE_MESSAGE_SEND = 0x0001, /**< Outgoing message. */ - PURPLE_MESSAGE_RECV = 0x0002, /**< Incoming message. */ - PURPLE_MESSAGE_SYSTEM = 0x0004, /**< System message. */ - PURPLE_MESSAGE_AUTO_RESP = 0x0008, /**< Auto response. */ - PURPLE_MESSAGE_ACTIVE_ONLY = 0x0010, /**< Hint to the UI that this - message should not be - shown in conversations - which are only open for - internal UI purposes - (e.g. for contact-aware - conversations). */ - PURPLE_MESSAGE_NICK = 0x0020, /**< Contains your nick. */ - PURPLE_MESSAGE_NO_LOG = 0x0040, /**< Do not log. */ - PURPLE_MESSAGE_WHISPER = 0x0080, /**< Whispered message. */ - PURPLE_MESSAGE_ERROR = 0x0200, /**< Error message. */ - PURPLE_MESSAGE_DELAYED = 0x0400, /**< Delayed message. */ - PURPLE_MESSAGE_RAW = 0x0800, /**< "Raw" message - don't - apply formatting */ - PURPLE_MESSAGE_IMAGES = 0x1000, /**< Message contains images */ - PURPLE_MESSAGE_NOTIFY = 0x2000, /**< Message is a notification */ - PURPLE_MESSAGE_NO_LINKIFY = 0x4000, /**< Message should not be auto- - linkified */ - PURPLE_MESSAGE_INVISIBLE = 0x8000 /**< Message should not be displayed */ -} PurpleMessageFlags; - -/** - * Flags applicable to users in Chats. - */ -typedef enum -{ - PURPLE_CBFLAGS_NONE = 0x0000, /**< No flags */ - PURPLE_CBFLAGS_VOICE = 0x0001, /**< Voiced user or "Participant" */ - PURPLE_CBFLAGS_HALFOP = 0x0002, /**< Half-op */ - PURPLE_CBFLAGS_OP = 0x0004, /**< Channel Op or Moderator */ - PURPLE_CBFLAGS_FOUNDER = 0x0008, /**< Channel Founder */ - PURPLE_CBFLAGS_TYPING = 0x0010, /**< Currently typing */ - PURPLE_CBFLAGS_AWAY = 0x0020 /**< Currently away. */ - -} PurpleConvChatBuddyFlags; + PURPLE_CONVERSATION_MESSAGE_SEND = 0x0001, /**< Outgoing message. */ + PURPLE_CONVERSATION_MESSAGE_RECV = 0x0002, /**< Incoming message. */ + PURPLE_CONVERSATION_MESSAGE_SYSTEM = 0x0004, /**< System message. */ + PURPLE_CONVERSATION_MESSAGE_AUTO_RESP = 0x0008, /**< Auto response. */ + PURPLE_CONVERSATION_MESSAGE_ACTIVE_ONLY = 0x0010, /**< Hint to the UI that this + message should not be + shown in conversations + which are only open for + internal UI purposes + (e.g. for contact-aware + conversations). */ + PURPLE_CONVERSATION_MESSAGE_NICK = 0x0020, /**< Contains your nick. */ + PURPLE_CONVERSATION_MESSAGE_NO_LOG = 0x0040, /**< Do not log. */ + PURPLE_CONVERSATION_MESSAGE_WHISPER = 0x0080, /**< Whispered message. */ + PURPLE_CONVERSATION_MESSAGE_ERROR = 0x0200, /**< Error message. */ + PURPLE_CONVERSATION_MESSAGE_DELAYED = 0x0400, /**< Delayed message. */ + PURPLE_CONVERSATION_MESSAGE_RAW = 0x0800, /**< "Raw" message - don't + apply formatting */ + PURPLE_CONVERSATION_MESSAGE_IMAGES = 0x1000, /**< Message contains images */ + PURPLE_CONVERSATION_MESSAGE_NOTIFY = 0x2000, /**< Message is a notification */ + PURPLE_CONVERSATION_MESSAGE_NO_LINKIFY = 0x4000, /**< Message should not be auto- + linkified */ + PURPLE_CONVERSATION_MESSAGE_INVISIBLE = 0x8000 /**< Message should not be displayed */ +} PurpleConversationMessageFlags; #include "account.h" #include "buddyicon.h" #include "log.h" -#include "server.h" + +/**************************************************************************/ +/** PurpleConversation */ +/**************************************************************************/ +/** Structure representing a conversation instance. */ +struct _PurpleConversation +{ + /*< private >*/ + GObject gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +/** Base class for all #PurpleConversation's */ +struct _PurpleConversationClass { + /*< private >*/ + GObjectClass parent_class; + /** Writes a message to a chat or IM conversation. TODO + * @see purple_conversation_write_message() + */ + void (*write_message)(PurpleConversation *conv, const char *who, + const char *message, PurpleConversationMessageFlags flags, + time_t mtime); + + /** Sends a message to a chat or IM conversation. TODO + * @see purple_conversation_send_message() + */ + void (*send_message)(PurpleConversation *conv, + const char *message, PurpleConversationMessageFlags flags); + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +/**************************************************************************/ +/** PurpleConversationUiOps */ +/**************************************************************************/ /** * Conversation operations and events. * @@ -166,17 +170,17 @@ void (*destroy_conversation)(PurpleConversation *conv); /** Write a message to a chat. If this field is @c NULL, libpurple will * fall back to using #write_conv. - * @see purple_conv_chat_write() + * @see purple_chat_conversation_write() */ void (*write_chat)(PurpleConversation *conv, const char *who, - const char *message, PurpleMessageFlags flags, - time_t mtime); + const char *message, PurpleConversationMessageFlags flags, + time_t mtime); /** Write a message to an IM conversation. If this field is @c NULL, * libpurple will fall back to using #write_conv. - * @see purple_conv_im_write() + * @see purple_im_conversation_write() */ void (*write_im)(PurpleConversation *conv, const char *who, - const char *message, PurpleMessageFlags flags, + const char *message, PurpleConversationMessageFlags flags, time_t mtime); /** Write a message to a conversation. This is used rather than the * chat- or im-specific ops for errors, system messages (such as "x is @@ -190,14 +194,15 @@ const char *name, const char *alias, const char *message, - PurpleMessageFlags flags, + PurpleConversationMessageFlags flags, time_t mtime); /** Add @a cbuddies to a chat. - * @param cbuddies A @c GList of #PurpleConvChatBuddy structs. + * @param cbuddies A @c GList of #PurpleChatConversationBuddy structs. * @param new_arrivals Whether join notices should be shown. * (Join notices are actually written to the - * conversation by #purple_conv_chat_add_users().) + * conversation by + * #purple_chat_conversation_add_users().) */ void (*chat_add_users)(PurpleConversation *conv, GList *cbuddies, @@ -205,17 +210,17 @@ /** Rename the user in this chat named @a old_name to @a new_name. (The * rename message is written to the conversation by libpurple.) * @param new_alias @a new_name's new alias, if they have one. - * @see purple_conv_chat_add_users() + * @see purple_chat_conversation_add_users() */ void (*chat_rename_user)(PurpleConversation *conv, const char *old_name, const char *new_name, const char *new_alias); /** Remove @a users from a chat. * @param users A @c GList of <tt>const char *</tt>s. - * @see purple_conv_chat_rename_user() + * @see purple_chat_conversation_rename_user() */ void (*chat_remove_users)(PurpleConversation *conv, GList *users); /** Called when a user's flags are changed. - * @see purple_conv_chat_user_set_flags() + * @see purple_chat_conversation_user_set_flags() */ void (*chat_update_user)(PurpleConversation *conv, const char *user); @@ -231,7 +236,8 @@ gboolean (*has_focus)(PurpleConversation *conv); /* Custom Smileys */ - gboolean (*custom_smiley_add)(PurpleConversation *conv, const char *smile, gboolean remote); + gboolean (*custom_smiley_add)(PurpleConversation *conv, const char *smile, + gboolean remote); void (*custom_smiley_write)(PurpleConversation *conv, const char *smile, const guchar *data, gsize size); void (*custom_smiley_close)(PurpleConversation *conv, const char *smile); @@ -256,22 +262,12 @@ /**************************************************************************/ /*@{*/ -/** - * Creates a new conversation of the specified type. - * - * @param type The type of conversation. - * @param account The account opening the conversation window on the purple - * user's end. - * @param name The name of the conversation. For PURPLE_CONV_TYPE_IM, - * this is the name of the buddy. - * - * @return The new conversation. +/** TODO + * Returns the GType for the Conversation object. */ -PurpleConversation *purple_conversation_new(PurpleConversationType type, - PurpleAccount *account, - const char *name); +GType purple_conversation_get_type(void); -/** +/** TODO dispose/fnalize * Destroys the specified conversation and removes it from the parent * window. * @@ -282,7 +278,6 @@ */ void purple_conversation_destroy(PurpleConversation *conv); - /** * Present a conversation to the user. This allows core code to initiate a * conversation by displaying the IM dialog. @@ -290,16 +285,6 @@ */ void purple_conversation_present(PurpleConversation *conv); - -/** - * Returns the specified conversation's type. - * - * @param conv The conversation. - * - * @return The conversation's type. - */ -PurpleConversationType purple_conversation_get_type(const PurpleConversation *conv); - /** * Sets the specified conversation's UI operations structure. * @@ -310,21 +295,13 @@ PurpleConversationUiOps *ops); /** - * Sets the default conversation UI operations structure. - * - * @param ops The UI conversation operations structure. - */ -void purple_conversations_set_ui_ops(PurpleConversationUiOps *ops); - -/** * Returns the specified conversation's UI operations structure. * * @param conv The conversation. * * @return The operations structure. */ -PurpleConversationUiOps *purple_conversation_get_ui_ops( - const PurpleConversation *conv); +PurpleConversationUiOps *purple_conversation_get_ui_ops(const PurpleConversation *conv); /** * Sets the specified conversation's purple_account. @@ -405,46 +382,6 @@ const char *purple_conversation_get_name(const PurpleConversation *conv); /** - * Get an attribute of a chat buddy - * - * @param cb The chat buddy. - * @param key The key of the attribute. - * - * @return The value of the attribute key. - */ -const char *purple_conv_chat_cb_get_attribute(PurpleConvChatBuddy *cb, const char *key); - -/** - * Get the keys of all atributes of a chat buddy - * - * @param cb The chat buddy. - * - * @return A list of the attributes of a chat buddy. - */ -GList *purple_conv_chat_cb_get_attribute_keys(PurpleConvChatBuddy *cb); - -/** - * Set an attribute of a chat buddy - * - * @param chat The chat. - * @param cb The chat buddy. - * @param key The key of the attribute. - * @param value The value of the attribute. - */ -void purple_conv_chat_cb_set_attribute(PurpleConvChat *chat, PurpleConvChatBuddy *cb, const char *key, const char *value); - -/** - * Set attributes of a chat buddy - * - * @param chat The chat. - * @param cb The chat buddy. - * @param keys A GList of the keys. - * @param values A GList of the values. - */ -void -purple_conv_chat_cb_set_attributes(PurpleConvChat *chat, PurpleConvChatBuddy *cb, GList *keys, GList *values); - -/** * Enables or disables logging for this conversation. * * @param conv The conversation. @@ -473,32 +410,6 @@ void purple_conversation_close_logs(PurpleConversation *conv); /** - * Returns the specified conversation's IM-specific data. - * - * If the conversation type is not PURPLE_CONV_TYPE_IM, this will return @c NULL. - * - * @param conv The conversation. - * - * @return The IM-specific data. - */ -PurpleConvIm *purple_conversation_get_im_data(const PurpleConversation *conv); - -#define PURPLE_CONV_IM(c) (purple_conversation_get_im_data(c)) - -/** - * Returns the specified conversation's chat-specific data. - * - * If the conversation type is not PURPLE_CONV_TYPE_CHAT, this will return @c NULL. - * - * @param conv The conversation. - * - * @return The chat-specific data. - */ -PurpleConvChat *purple_conversation_get_chat_data(const PurpleConversation *conv); - -#define PURPLE_CONV_CHAT(c) (purple_conversation_get_chat_data(c)) - -/** * Sets extra data for a conversation. * * @param conv The conversation. @@ -519,48 +430,13 @@ gpointer purple_conversation_get_data(PurpleConversation *conv, const char *key); /** - * Returns a list of all conversations. - * - * This list includes both IMs and chats. - * - * @constreturn A GList of all conversations. - */ -GList *purple_get_conversations(void); - -/** - * Returns a list of all IMs. - * - * @constreturn A GList of all IMs. - */ -GList *purple_get_ims(void); - -/** - * Returns a list of all chats. - * - * @constreturn A GList of all chats. - */ -GList *purple_get_chats(void); - -/** - * Finds a conversation with the specified type, name, and Purple account. - * - * @param type The type of the conversation. - * @param name The name of the conversation. - * @param account The purple_account associated with the conversation. - * - * @return The conversation if found, or @c NULL otherwise. - */ -PurpleConversation *purple_find_conversation_with_account( - PurpleConversationType type, const char *name, - const PurpleAccount *account); - -/** * Writes to a conversation window. * * This function should not be used to write IM or chat messages. Use - * purple_conv_im_write() and purple_conv_chat_write() instead. Those functions will - * most likely call this anyway, but they may do their own formatting, - * sound playback, etc. + * purple_conversation_write_message() instead. This function will + * most likely call this anyway, but it may do it's own formatting, + * sound playback, etc. depending on whether the conversation is a chat or an + * IM. * * This can be used to write generic messages, such as "so and so closed * the conversation window." @@ -571,13 +447,45 @@ * @param flags The message flags. * @param mtime The time the message was sent. * - * @see purple_conv_im_write() - * @see purple_conv_chat_write() + * @see purple_conversation_write_message() */ void purple_conversation_write(PurpleConversation *conv, const char *who, - const char *message, PurpleMessageFlags flags, + const char *message, PurpleConversationMessageFlags flags, time_t mtime); +/** TODO pure virtual + * Writes to a chat or an IM. + * + * @param conv The conversation. + * @param who The user who sent the message. + * @param message The message to write. + * @param flags The message flags. + * @param mtime The time the message was sent. + */ +void purple_conversation_write_message(PurpleConversation *conv, + const char *who, const char *message, + PurpleConversationMessageFlags flags, time_t mtime); + +/** TODO forward to send_message + * Sends a message to this conversation. This function calls + * purple_conversation_send_message() with no additional flags. + * + * @param conv The conversation. + * @param message The message to send. + */ +void purple_conversation_send(PurpleConversation *conv, const char *message); + +/** TODO pure virtual + * Sends a message to this conversation with specified flags. + * + * @param conv The conversation. + * @param message The message to send. + * @param flags The PurpleConversationMessageFlags flags to use in addition to + * PURPLE_CONVERSATION_MESSAGE_SEND. + */ +void purple_conversation_send_message(PurpleConversation *conv, const char *message, + PurpleConversationMessageFlags flags); + /** Set the features as supported for the given conversation. @param conv The conversation @@ -609,21 +517,14 @@ * @param conv The conversation. * @param type The update type. */ -void purple_conversation_update(PurpleConversation *conv, PurpleConvUpdateType type); - -/** - * Calls a function on each conversation. - * - * @param func The function. - */ -void purple_conversation_foreach(void (*func)(PurpleConversation *conv)); +void purple_conversation_update(PurpleConversation *conv, PurpleConversationUpdateType type); /** * Retrieve the message history of a conversation. * * @param conv The conversation * - * @return A GList of PurpleConvMessage's. The must not modify the list or the data within. + * @return A GList of PurpleConversationMessage's. The must not modify the list or the data within. * The list contains the newest message at the beginning, and the oldest message at * the end. */ @@ -637,60 +538,6 @@ void purple_conversation_clear_message_history(PurpleConversation *conv); /** - * Get the sender from a PurpleConvMessage - * - * @param msg A PurpleConvMessage - * - * @return The name of the sender of the message - */ -const char *purple_conversation_message_get_sender(const PurpleConvMessage *msg); - -/** - * Get the message from a PurpleConvMessage - * - * @param msg A PurpleConvMessage - * - * @return The name of the sender of the message - */ -const char *purple_conversation_message_get_message(const PurpleConvMessage *msg); - -/** - * Get the message-flags of a PurpleConvMessage - * - * @param msg A PurpleConvMessage - * - * @return The message flags - */ -PurpleMessageFlags purple_conversation_message_get_flags(const PurpleConvMessage *msg); - -/** - * Get the timestamp of a PurpleConvMessage - * - * @param msg A PurpleConvMessage - * - * @return The timestamp of the message - */ -time_t purple_conversation_message_get_timestamp(const PurpleConvMessage *msg); - -/** - * Get the alias from a PurpleConvMessage - * - * @param msg A PurpleConvMessage - * - * @return The alias of the sender of the message - */ -const char *purple_conversation_message_get_alias(const PurpleConvMessage *msg); - -/** - * Get the conversation associated with the PurpleConvMessage - * - * @param msg A PurpleConvMessage - * - * @return The conversation - */ -PurpleConversation *purple_conversation_message_get_conv(const PurpleConvMessage *msg); - -/** * Set the UI data associated with this conversation. * * @param conv The conversation. @@ -709,175 +556,6 @@ */ gpointer purple_conversation_get_ui_data(const PurpleConversation *conv); -/*@}*/ - - -/**************************************************************************/ -/** @name IM Conversation API */ -/**************************************************************************/ -/*@{*/ - -/** - * Gets an IM's parent conversation. - * - * @param im The IM. - * - * @return The parent conversation. - */ -PurpleConversation *purple_conv_im_get_conversation(const PurpleConvIm *im); - -/** - * Sets the IM's buddy icon. - * - * This should only be called from within Purple. You probably want to - * call purple_buddy_icon_set_data(). - * - * @param im The IM. - * @param icon The buddy icon. - * - * @see purple_buddy_icon_set_data() - */ -void purple_conv_im_set_icon(PurpleConvIm *im, PurpleBuddyIcon *icon); - -/** - * Returns the IM's buddy icon. - * - * @param im The IM. - * - * @return The buddy icon. - */ -PurpleBuddyIcon *purple_conv_im_get_icon(const PurpleConvIm *im); - -/** - * Sets the IM's typing state. - * - * @param im The IM. - * @param state The typing state. - */ -void purple_conv_im_set_typing_state(PurpleConvIm *im, PurpleTypingState state); - -/** - * Returns the IM's typing state. - * - * @param im The IM. - * - * @return The IM's typing state. - */ -PurpleTypingState purple_conv_im_get_typing_state(const PurpleConvIm *im); - -/** - * Starts the IM's typing timeout. - * - * @param im The IM. - * @param timeout The timeout. - */ -void purple_conv_im_start_typing_timeout(PurpleConvIm *im, int timeout); - -/** - * Stops the IM's typing timeout. - * - * @param im The IM. - */ -void purple_conv_im_stop_typing_timeout(PurpleConvIm *im); - -/** - * Returns the IM's typing timeout. - * - * @param im The IM. - * - * @return The timeout. - */ -guint purple_conv_im_get_typing_timeout(const PurpleConvIm *im); - -/** - * Sets the quiet-time when no PURPLE_TYPING messages will be sent. - * Few protocols need this (maybe only MSN). If the user is still - * typing after this quiet-period, then another PURPLE_TYPING message - * will be sent. - * - * @param im The IM. - * @param val The number of seconds to wait before allowing another - * PURPLE_TYPING message to be sent to the user. Or 0 to - * not send another PURPLE_TYPING message. - */ -void purple_conv_im_set_type_again(PurpleConvIm *im, unsigned int val); - -/** - * Returns the time after which another PURPLE_TYPING message should be sent. - * - * @param im The IM. - * - * @return The time in seconds since the epoch. Or 0 if no additional - * PURPLE_TYPING message should be sent. - */ -time_t purple_conv_im_get_type_again(const PurpleConvIm *im); - -/** - * Starts the IM's type again timeout. - * - * @param im The IM. - */ -void purple_conv_im_start_send_typed_timeout(PurpleConvIm *im); - -/** - * Stops the IM's type again timeout. - * - * @param im The IM. - */ -void purple_conv_im_stop_send_typed_timeout(PurpleConvIm *im); - -/** - * Returns the IM's type again timeout interval. - * - * @param im The IM. - * - * @return The type again timeout interval. - */ -guint purple_conv_im_get_send_typed_timeout(const PurpleConvIm *im); - -/** - * Updates the visual typing notification for an IM conversation. - * - * @param im The IM. - */ -void purple_conv_im_update_typing(PurpleConvIm *im); - -/** - * Writes to an IM. - * - * @param im The IM. - * @param who The user who sent the message. - * @param message The message to write. - * @param flags The message flags. - * @param mtime The time the message was sent. - */ -void purple_conv_im_write(PurpleConvIm *im, const char *who, - const char *message, PurpleMessageFlags flags, - time_t mtime); - -/** - * Presents an IM-error to the user - * - * This is a helper function to find a conversation, write an error to it, and - * raise the window. If a conversation with this user doesn't already exist, - * the function will return FALSE and the calling function can attempt to present - * the error another way (purple_notify_error, most likely) - * - * @param who The user this error is about - * @param account The account this error is on - * @param what The error - * @return TRUE if the error was presented, else FALSE - */ -gboolean purple_conv_present_error(const char *who, PurpleAccount *account, const char *what); - -/** - * Sends a message to this IM conversation. - * - * @param im The IM. - * @param message The message to send. - */ -void purple_conv_im_send(PurpleConvIm *im, const char *message); - /** * Sends a message to a conversation after confirming with * the user. @@ -890,21 +568,12 @@ * @param conv The conversation. * @param message The message to send. */ -void purple_conv_send_confirm(PurpleConversation *conv, const char *message); - -/** - * Sends a message to this IM conversation with specified flags. - * - * @param im The IM. - * @param message The message to send. - * @param flags The PurpleMessageFlags flags to use in addition to PURPLE_MESSAGE_SEND. - */ -void purple_conv_im_send_with_flags(PurpleConvIm *im, const char *message, PurpleMessageFlags flags); +void purple_conversation_send_confirm(PurpleConversation *conv, const char *message); /** * Adds a smiley to the conversation's smiley tree. If this returns - * @c TRUE you should call purple_conv_custom_smiley_write() one or more - * times, and then purple_conv_custom_smiley_close(). If this returns + * @c TRUE you should call purple_conversation_custom_smiley_write() one or more + * times, and then purple_conversation_custom_smiley_close(). If this returns * @c FALSE, either the conv or smile were invalid, or the icon was * found in the cache. In either case, calling write or close would * be an error. @@ -915,16 +584,15 @@ * @param chksum The checksum, as a NUL terminated base64 string. * @param remote @c TRUE if the custom smiley is set by the remote user (buddy). * @return @c TRUE if an icon is expected, else FALSE. Note that - * it is an error to never call purple_conv_custom_smiley_close if + * it is an error to never call purple_conversation_custom_smiley_close if * this function returns @c TRUE, but an error to call it if * @c FALSE is returned. */ -gboolean purple_conv_custom_smiley_add(PurpleConversation *conv, const char *smile, +gboolean purple_conversation_custom_smiley_add(PurpleConversation *conv, const char *smile, const char *cksum_type, const char *chksum, gboolean remote); - /** * Updates the image associated with the current smiley. * @@ -934,421 +602,21 @@ * @param size The length of the data. */ -void purple_conv_custom_smiley_write(PurpleConversation *conv, +void purple_conversation_custom_smiley_write(PurpleConversation *conv, const char *smile, const guchar *data, gsize size); /** * Close the custom smiley, all data has been written with - * purple_conv_custom_smiley_write, and it is no longer valid + * purple_conversation_custom_smiley_write, and it is no longer valid * to call that function on that smiley. * * @param conv The purple conversation associated with the smiley. * @param smile The text associated with the smiley */ -void purple_conv_custom_smiley_close(PurpleConversation *conv, const char *smile); - -/*@}*/ - - -/**************************************************************************/ -/** @name Chat Conversation API */ -/**************************************************************************/ -/*@{*/ - -/** - * Gets a chat's parent conversation. - * - * @param chat The chat. - * - * @return The parent conversation. - */ -PurpleConversation *purple_conv_chat_get_conversation(const PurpleConvChat *chat); - -/** - * Returns a list of users in the chat room. The members of the list - * are PurpleConvChatBuddy objects. - * - * @param chat The chat. - * - * @constreturn The list of users. - */ -GList *purple_conv_chat_get_users(const PurpleConvChat *chat); - -/** - * Ignores a user in a chat room. - * - * @param chat The chat. - * @param name The name of the user. - */ -void purple_conv_chat_ignore(PurpleConvChat *chat, const char *name); - -/** - * Unignores a user in a chat room. - * - * @param chat The chat. - * @param name The name of the user. - */ -void purple_conv_chat_unignore(PurpleConvChat *chat, const char *name); - -/** - * Sets the list of ignored users in the chat room. - * - * @param chat The chat. - * @param ignored The list of ignored users. - * - * @return The list passed. - */ -GList *purple_conv_chat_set_ignored(PurpleConvChat *chat, GList *ignored); - -/** - * Returns the list of ignored users in the chat room. - * - * @param chat The chat. - * - * @constreturn The list of ignored users. - */ -GList *purple_conv_chat_get_ignored(const PurpleConvChat *chat); - -/** - * Returns the actual name of the specified ignored user, if it exists in - * the ignore list. - * - * If the user found contains a prefix, such as '+' or '\@', this is also - * returned. The username passed to the function does not have to have this - * formatting. - * - * @param chat The chat. - * @param user The user to check in the ignore list. - * - * @return The ignored user if found, complete with prefixes, or @c NULL - * if not found. - */ -const char *purple_conv_chat_get_ignored_user(const PurpleConvChat *chat, - const char *user); - -/** - * Returns @c TRUE if the specified user is ignored. - * - * @param chat The chat. - * @param user The user. - * - * @return @c TRUE if the user is in the ignore list; @c FALSE otherwise. - */ -gboolean purple_conv_chat_is_user_ignored(const PurpleConvChat *chat, - const char *user); - -/** - * Sets the chat room's topic. - * - * @param chat The chat. - * @param who The user that set the topic. - * @param topic The topic. - */ -void purple_conv_chat_set_topic(PurpleConvChat *chat, const char *who, - const char *topic); - -/** - * Returns the chat room's topic. - * - * @param chat The chat. - * - * @return The chat's topic. - */ -const char *purple_conv_chat_get_topic(const PurpleConvChat *chat); - -/** - * Sets the chat room's ID. - * - * @param chat The chat. - * @param id The ID. - */ -void purple_conv_chat_set_id(PurpleConvChat *chat, int id); - -/** - * Returns the chat room's ID. - * - * @param chat The chat. - * - * @return The ID. - */ -int purple_conv_chat_get_id(const PurpleConvChat *chat); - -/** - * Writes to a chat. - * - * @param chat The chat. - * @param who The user who sent the message. - * @param message The message to write. - * @param flags The flags. - * @param mtime The time the message was sent. - */ -void purple_conv_chat_write(PurpleConvChat *chat, const char *who, - const char *message, PurpleMessageFlags flags, - time_t mtime); - -/** - * Sends a message to this chat conversation. - * - * @param chat The chat. - * @param message The message to send. - */ -void purple_conv_chat_send(PurpleConvChat *chat, const char *message); - -/** - * Sends a message to this chat conversation with specified flags. - * - * @param chat The chat. - * @param message The message to send. - * @param flags The PurpleMessageFlags flags to use. - */ -void purple_conv_chat_send_with_flags(PurpleConvChat *chat, const char *message, PurpleMessageFlags flags); - -/** - * Adds a user to a chat. - * - * @param chat The chat. - * @param user The user to add. - * @param extra_msg An extra message to display with the join message. - * @param flags The users flags - * @param new_arrival Decides whether or not to show a join notice. - */ -void purple_conv_chat_add_user(PurpleConvChat *chat, const char *user, - const char *extra_msg, PurpleConvChatBuddyFlags flags, - gboolean new_arrival); - -/** - * Adds a list of users to a chat. - * - * The data is copied from @a users, @a extra_msgs, and @a flags, so it is up to - * the caller to free this list after calling this function. - * - * @param chat The chat. - * @param users The list of users to add. - * @param extra_msgs An extra message to display with the join message for each - * user. This list may be shorter than @a users, in which - * case, the users after the end of extra_msgs will not have - * an extra message. By extension, this means that extra_msgs - * can simply be @c NULL and none of the users will have an - * extra message. - * @param flags The list of flags for each user. - * @param new_arrivals Decides whether or not to show join notices. - */ -void purple_conv_chat_add_users(PurpleConvChat *chat, GList *users, GList *extra_msgs, - GList *flags, gboolean new_arrivals); - -/** - * Renames a user in a chat. - * - * @param chat The chat. - * @param old_user The old username. - * @param new_user The new username. - */ -void purple_conv_chat_rename_user(PurpleConvChat *chat, const char *old_user, - const char *new_user); - -/** - * Removes a user from a chat, optionally with a reason. - * - * It is up to the developer to free this list after calling this function. - * - * @param chat The chat. - * @param user The user that is being removed. - * @param reason The optional reason given for the removal. Can be @c NULL. - */ -void purple_conv_chat_remove_user(PurpleConvChat *chat, const char *user, - const char *reason); - -/** - * Removes a list of users from a chat, optionally with a single reason. - * - * @param chat The chat. - * @param users The users that are being removed. - * @param reason The optional reason given for the removal. Can be @c NULL. - */ -void purple_conv_chat_remove_users(PurpleConvChat *chat, GList *users, - const char *reason); - -/** - * Finds a user in a chat - * - * @param chat The chat. - * @param user The user to look for. - * - * @return TRUE if the user is in the chat, FALSE if not - */ -gboolean purple_conv_chat_find_user(PurpleConvChat *chat, const char *user); - -/** - * Set a users flags in a chat - * - * @param chat The chat. - * @param user The user to update. - * @param flags The new flags. - */ -void purple_conv_chat_user_set_flags(PurpleConvChat *chat, const char *user, - PurpleConvChatBuddyFlags flags); - -/** - * Get the flags for a user in a chat - * - * @param chat The chat. - * @param user The user to find the flags for - * - * @return The flags for the user - */ -PurpleConvChatBuddyFlags purple_conv_chat_user_get_flags(PurpleConvChat *chat, - const char *user); - -/** - * Clears all users from a chat. - * - * @param chat The chat. - */ -void purple_conv_chat_clear_users(PurpleConvChat *chat); - -/** - * Sets your nickname (used for hilighting) for a chat. - * - * @param chat The chat. - * @param nick The nick. - */ -void purple_conv_chat_set_nick(PurpleConvChat *chat, const char *nick); - -/** - * Gets your nickname (used for hilighting) for a chat. - * - * @param chat The chat. - * @return The nick. - */ -const char *purple_conv_chat_get_nick(PurpleConvChat *chat); - -/** - * Finds a chat with the specified chat ID. - * - * @param gc The purple_connection. - * @param id The chat ID. - * - * @return The chat conversation. - */ -PurpleConversation *purple_find_chat(const PurpleConnection *gc, int id); - -/** - * Lets the core know we left a chat, without destroying it. - * Called from serv_got_chat_left(). - * - * @param chat The chat. - */ -void purple_conv_chat_left(PurpleConvChat *chat); - -/** - * Invite a user to a chat. - * The user will be prompted to enter the user's name or a message if one is - * not given. - * - * @param chat The chat. - * @param user The user to invite to the chat. - * @param message The message to send with the invitation. - * @param confirm Prompt before sending the invitation. The user is always - * prompted if either \a user or \a message is @c NULL. - */ -void purple_conv_chat_invite_user(PurpleConvChat *chat, const char *user, - const char *message, gboolean confirm); - -/** - * Returns true if we're no longer in this chat, - * and just left the window open. - * - * @param chat The chat. - * - * @return @c TRUE if we left the chat already, @c FALSE if - * we're still there. - */ -gboolean purple_conv_chat_has_left(PurpleConvChat *chat); - -/** - * Creates a new chat buddy - * - * @param name The name. - * @param alias The alias. - * @param flags The flags. - * - * @return The new chat buddy - */ -PurpleConvChatBuddy *purple_conv_chat_cb_new(const char *name, const char *alias, - PurpleConvChatBuddyFlags flags); - -/** - * Find a chat buddy in a chat - * - * @param chat The chat. - * @param name The name of the chat buddy to find. - */ -PurpleConvChatBuddy *purple_conv_chat_cb_find(PurpleConvChat *chat, const char *name); - -/** - * Set the UI data associated with this chat buddy. - * - * @param cb The chat buddy - * @param ui_data A pointer to associate with this chat buddy. - */ -void purple_conv_chat_cb_set_ui_data(PurpleConvChatBuddy *cb, gpointer ui_data); - -/** - * Get the UI data associated with this chat buddy. - * - * @param cb The chat buddy. - * - * @return The UI data associated with this chat buddy. This is a - * convenience field provided to the UIs--it is not - * used by the libpurple core. - */ -gpointer purple_conv_chat_cb_get_ui_data(const PurpleConvChatBuddy *conv); - -/** - * Get the alias of a chat buddy - * - * @param cb The chat buddy. - * - * @return The alias of the chat buddy. - */ -const char *purple_conv_chat_cb_get_alias(const PurpleConvChatBuddy *cb); - -/** - * Get the name of a chat buddy - * - * @param cb The chat buddy. - * - * @return The name of the chat buddy. - */ -const char *purple_conv_chat_cb_get_name(const PurpleConvChatBuddy *cb); - -/** - * Get the flags of a chat buddy. - * - * @param cb The chat buddy. - * - * @return The flags of the chat buddy. - */ -PurpleConvChatBuddyFlags purple_conv_chat_cb_get_flags(const PurpleConvChatBuddy *cb); - -/** - * Indicates if this chat buddy is on the buddy list. - * - * @param cb The chat buddy. - * - * @return TRUE if the chat buddy is on the buddy list. - */ -gboolean purple_conv_chat_cb_is_buddy(const PurpleConvChatBuddy *cb); - -/** - * Destroys a chat buddy - * - * @param cb The chat buddy to destroy - */ -void purple_conv_chat_cb_destroy(PurpleConvChatBuddy *cb); +void purple_conversation_custom_smiley_close(PurpleConversation *conv, const char *smile); /** * Retrieves the extended menu items for the conversation. @@ -1372,31 +640,91 @@ * * @return @c TRUE if the command was executed successfully, @c FALSE otherwise. */ -gboolean purple_conversation_do_command(PurpleConversation *conv, const gchar *cmdline, const gchar *markup, gchar **error); +gboolean purple_conversation_do_command(PurpleConversation *conv, + const gchar *cmdline, const gchar *markup, gchar **error); /*@}*/ /**************************************************************************/ -/** @name Conversations Subsystem */ +/** @name Conversation Helper API */ +/**************************************************************************/ +/*@{*/ + +/** + * Presents an IM-error to the user + * + * This is a helper function to find a conversation, write an error to it, and + * raise the window. If a conversation with this user doesn't already exist, + * the function will return FALSE and the calling function can attempt to present + * the error another way (purple_notify_error, most likely) + * + * @param who The user this error is about + * @param account The account this error is on + * @param what The error + * @return TRUE if the error was presented, else FALSE + */ +gboolean purple_conversation_helper_present_error(const char *who, PurpleAccount *account, const char *what); + +/*@}*/ + +/**************************************************************************/ +/** @name Conversation Message API */ /**************************************************************************/ /*@{*/ /** - * Returns the conversation subsystem handle. + * Get the sender from a PurpleConversationMessage + * + * @param msg A PurpleConversationMessage * - * @return The conversation subsystem handle. + * @return The name of the sender of the message */ -void *purple_conversations_get_handle(void); +const char *purple_conversation_message_get_sender(const PurpleConversationMessage *msg); + +/** + * Get the message from a PurpleConversationMessage + * + * @param msg A PurpleConversationMessage + * + * @return The name of the sender of the message + */ +const char *purple_conversation_message_get_message(const PurpleConversationMessage *msg); /** - * Initializes the conversation subsystem. + * Get the message-flags of a PurpleConversationMessage + * + * @param msg A PurpleConversationMessage + * + * @return The message flags */ -void purple_conversations_init(void); +PurpleConversationMessageFlags purple_conversation_message_get_flags(const PurpleConversationMessage *msg); /** - * Uninitializes the conversation subsystem. + * Get the timestamp of a PurpleConversationMessage + * + * @param msg A PurpleConversationMessage + * + * @return The timestamp of the message */ -void purple_conversations_uninit(void); +time_t purple_conversation_message_get_timestamp(const PurpleConversationMessage *msg); + +/** + * Get the alias from a PurpleConversationMessage + * + * @param msg A PurpleConversationMessage + * + * @return The alias of the sender of the message + */ +const char *purple_conversation_message_get_alias(const PurpleConversationMessage *msg); + +/** + * Get the conversation associated with the PurpleConversationMessage + * + * @param msg A PurpleConversationMessage + * + * @return The conversation + */ +PurpleConversation *purple_conversation_message_get_conv(const PurpleConversationMessage *msg); /*@}*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/conversations.c Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,442 @@ +/* + * 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 "conversations.h" + +static GList *conversations = NULL; +static GList *ims = NULL; +static GList *chats = NULL; +static PurpleConversationUiOps *default_ops = NULL; + +GList * +purple_conversations_get(void) +{ + return conversations; +} + +GList * +purple_conversations_get_ims(void) +{ + return ims; +} + +GList * +purple_conversations_get_chats(void) +{ + return chats; +} + +PurpleConversation * +purple_conversations_find_with_account(PurpleConversationType type, + const char *name, + const PurpleAccount *account) +{ + PurpleConversation *c = NULL; + struct _purple_hconv hc; + + g_return_val_if_fail(name != NULL, NULL); + + hc.name = (gchar *)purple_normalize(account, name); + hc.account = account; + hc.type = type; + + switch (type) { + case PURPLE_CONVERSATION_TYPE_IM: + case PURPLE_CONVERSATION_TYPE_CHAT: + c = g_hash_table_lookup(conversation_cache, &hc); + break; + case PURPLE_CONVERSATION_TYPE_ANY: + hc.type = PURPLE_CONVERSATION_TYPE_IM; + c = g_hash_table_lookup(conversation_cache, &hc); + if (!c) { + hc.type = PURPLE_CONVERSATION_TYPE_CHAT; + c = g_hash_table_lookup(conversation_cache, &hc); + } + break; + default: + g_return_val_if_reached(NULL); + } + + return c; +} + +PurpleChatConversation * +purple_conversations_find_chat(const PurpleConnection *gc, int id) +{ + GList *l; + PurpleConversation *conv; + + for (l = purple_conversations_get_chats(); l != NULL; l = l->next) { + conv = (PurpleConversation *)l->data; + + if (purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION_GET_PRIVATE(conv)) == id && + purple_conversation_get_connection(conv) == gc) + return conv; + } + + return NULL; +} + +void +purple_conversations_set_ui_ops(PurpleConversationUiOps *ops) +{ + default_ops = ops; +} + +void * +purple_conversations_get_handle(void) +{ + static int handle; + + return &handle; +} + +void +purple_conversations_init(void) +{ + void *handle = purple_conversations_get_handle(); + + conversation_cache = g_hash_table_new_full((GHashFunc)_purple_conversations_hconv_hash, + (GEqualFunc)_purple_conversations_hconv_equal, + (GDestroyNotify)_purple_conversations_hconv_free_key, NULL); + + /********************************************************************** + * Register preferences + **********************************************************************/ + + /* Conversations */ + purple_prefs_add_none("/purple/conversations"); + + /* Conversations -> Chat */ + purple_prefs_add_none("/purple/conversations/chat"); + purple_prefs_add_bool("/purple/conversations/chat/show_nick_change", TRUE); + + /* Conversations -> IM */ + purple_prefs_add_none("/purple/conversations/im"); + purple_prefs_add_bool("/purple/conversations/im/send_typing", TRUE); + + + /********************************************************************** + * Register signals + **********************************************************************/ + purple_signal_register(handle, "writing-im-msg", + purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_UINT, + purple_value_new(PURPLE_TYPE_BOOLEAN), 5, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new_outgoing(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONVERSATION), + purple_value_new(PURPLE_TYPE_UINT)); + + purple_signal_register(handle, "wrote-im-msg", + purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT, + NULL, 5, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONVERSATION), + purple_value_new(PURPLE_TYPE_UINT)); + + purple_signal_register(handle, "sent-attention", + purple_marshal_VOID__POINTER_POINTER_POINTER_UINT, + NULL, 4, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONVERSATION), + purple_value_new(PURPLE_TYPE_UINT)); + + purple_signal_register(handle, "got-attention", + purple_marshal_VOID__POINTER_POINTER_POINTER_UINT, + NULL, 4, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONVERSATION), + purple_value_new(PURPLE_TYPE_UINT)); + + purple_signal_register(handle, "sending-im-msg", + purple_marshal_VOID__POINTER_POINTER_POINTER, + NULL, 3, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new_outgoing(PURPLE_TYPE_STRING)); + + purple_signal_register(handle, "sent-im-msg", + purple_marshal_VOID__POINTER_POINTER_POINTER, + NULL, 3, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_STRING)); + + purple_signal_register(handle, "receiving-im-msg", + purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER, + purple_value_new(PURPLE_TYPE_BOOLEAN), 5, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new_outgoing(PURPLE_TYPE_STRING), + purple_value_new_outgoing(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONVERSATION), + purple_value_new_outgoing(PURPLE_TYPE_UINT)); + + purple_signal_register(handle, "received-im-msg", + purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT, + NULL, 5, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONVERSATION), + purple_value_new(PURPLE_TYPE_UINT)); + + purple_signal_register(handle, "blocked-im-msg", + purple_marshal_VOID__POINTER_POINTER_POINTER_UINT_UINT, + NULL, 5, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_UINT), + purple_value_new(PURPLE_TYPE_UINT)); + + purple_signal_register(handle, "writing-chat-msg", + purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_UINT, + purple_value_new(PURPLE_TYPE_BOOLEAN), 5, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new_outgoing(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONVERSATION), + purple_value_new(PURPLE_TYPE_UINT)); + + purple_signal_register(handle, "wrote-chat-msg", + purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT, + NULL, 5, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONVERSATION), + purple_value_new(PURPLE_TYPE_UINT)); + + purple_signal_register(handle, "sending-chat-msg", + purple_marshal_VOID__POINTER_POINTER_UINT, NULL, 3, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new_outgoing(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_UINT)); + + purple_signal_register(handle, "sent-chat-msg", + purple_marshal_VOID__POINTER_POINTER_UINT, NULL, 3, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_UINT)); + + purple_signal_register(handle, "receiving-chat-msg", + purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER, + purple_value_new(PURPLE_TYPE_BOOLEAN), 5, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new_outgoing(PURPLE_TYPE_STRING), + purple_value_new_outgoing(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONVERSATION), + purple_value_new_outgoing(PURPLE_TYPE_UINT)); + + purple_signal_register(handle, "received-chat-msg", + purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT, + NULL, 5, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONVERSATION), + purple_value_new(PURPLE_TYPE_UINT)); + + purple_signal_register(handle, "conversation-created", + purple_marshal_VOID__POINTER, NULL, 1, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONVERSATION)); + + purple_signal_register(handle, "conversation-updated", + purple_marshal_VOID__POINTER_UINT, NULL, 2, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONVERSATION), + purple_value_new(PURPLE_TYPE_UINT)); + + purple_signal_register(handle, "deleting-conversation", + purple_marshal_VOID__POINTER, NULL, 1, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONVERSATION)); + + purple_signal_register(handle, "buddy-typing", + purple_marshal_VOID__POINTER_POINTER, NULL, 2, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_STRING)); + + purple_signal_register(handle, "buddy-typed", + purple_marshal_VOID__POINTER_POINTER, NULL, 2, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_STRING)); + + purple_signal_register(handle, "buddy-typing-stopped", + purple_marshal_VOID__POINTER_POINTER, NULL, 2, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_STRING)); + + purple_signal_register(handle, "chat-buddy-joining", + purple_marshal_BOOLEAN__POINTER_POINTER_UINT, + purple_value_new(PURPLE_TYPE_BOOLEAN), 3, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONVERSATION), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_UINT)); + + purple_signal_register(handle, "chat-buddy-joined", + purple_marshal_VOID__POINTER_POINTER_UINT_UINT, NULL, 4, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONVERSATION), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_UINT), + purple_value_new(PURPLE_TYPE_BOOLEAN)); + + purple_signal_register(handle, "chat-buddy-flags", + purple_marshal_VOID__POINTER_POINTER_UINT_UINT, NULL, 4, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONVERSATION), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_UINT), + purple_value_new(PURPLE_TYPE_UINT)); + + purple_signal_register(handle, "chat-buddy-leaving", + purple_marshal_BOOLEAN__POINTER_POINTER_POINTER, + purple_value_new(PURPLE_TYPE_BOOLEAN), 3, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONVERSATION), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_STRING)); + + purple_signal_register(handle, "chat-buddy-left", + purple_marshal_VOID__POINTER_POINTER_POINTER, NULL, 3, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONVERSATION), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_STRING)); + + purple_signal_register(handle, "deleting-chat-buddy", + purple_marshal_VOID__POINTER, NULL, 1, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CHATBUDDY)); + + purple_signal_register(handle, "chat-inviting-user", + purple_marshal_VOID__POINTER_POINTER_POINTER, NULL, 3, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONVERSATION), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new_outgoing(PURPLE_TYPE_STRING)); + + purple_signal_register(handle, "chat-invited-user", + purple_marshal_VOID__POINTER_POINTER_POINTER, NULL, 3, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONVERSATION), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_STRING)); + + purple_signal_register(handle, "chat-invited", + purple_marshal_INT__POINTER_POINTER_POINTER_POINTER_POINTER, + purple_value_new(PURPLE_TYPE_INT), 5, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_POINTER)); + + purple_signal_register(handle, "chat-invite-blocked", + purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_POINTER, + NULL, 5, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_ACCOUNT), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_BOXED, "GHashTable *")); + + purple_signal_register(handle, "chat-joined", + purple_marshal_VOID__POINTER, NULL, 1, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONVERSATION)); + + purple_signal_register(handle, "chat-join-failed", + purple_marshal_VOID__POINTER_POINTER, NULL, 2, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONNECTION), + purple_value_new(PURPLE_TYPE_POINTER)); + + purple_signal_register(handle, "chat-left", + purple_marshal_VOID__POINTER, NULL, 1, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONVERSATION)); + + purple_signal_register(handle, "chat-topic-changed", + purple_marshal_VOID__POINTER_POINTER_POINTER, NULL, 3, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONVERSATION), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_STRING)); + + purple_signal_register(handle, "cleared-message-history", + purple_marshal_VOID__POINTER, NULL, 1, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONVERSATION)); + + purple_signal_register(handle, "conversation-extended-menu", + purple_marshal_VOID__POINTER_POINTER, NULL, 2, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_CONVERSATION), + purple_value_new(PURPLE_TYPE_BOXED, "GList **")); +} + +void +purple_conversations_uninit(void) +{ + while (conversations) + purple_conversation_destroy((PurpleConversation*)conversations->data); + g_hash_table_destroy(conversation_cache); + purple_signals_unregister_by_instance(purple_conversations_get_handle()); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/conversations.h Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,135 @@ +/** + * @file conversations.h Conversations API + * @ingroup core + * @see @ref conversation-signals + */ + +/* 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 + */ +#ifndef _PURPLE_CONVERSATIONS_H_ +#define _PURPLE_CONVERSATIONS_H_ + +#include "conversation.h" +#include "conversationtypes.h" +#include "server.h" + +G_BEGIN_DECLS + +/**************************************************************************/ +/** @name Conversations Subsystem */ +/**************************************************************************/ +/*@{*/ + +/** + * Returns a list of all conversations. + * + * This list includes both IMs and chats. + * + * @constreturn A GList of all conversations. + */ +GList *purple_conversations_get(void); + +/** + * Returns a list of all IMs. + * + * @constreturn A GList of all IMs. + */ +GList *purple_conversations_get_ims(void); + +/** + * Returns a list of all chats. + * + * @constreturn A GList of all chats. + */ +GList *purple_conversations_get_chats(void); + +/** TODO all + * Finds a conversation of any type with the specified name and Purple account. + * + * @param name The name of the conversation. + * @param account The purple_account associated with the conversation. + * + * @return The conversation if found, or @c NULL otherwise. + */ +PurpleConversation *purple_conversations_find_with_account(const char *name, + const PurpleAccount *account); + +/** TODO IMs + * Finds an IM with the specified name and Purple account. + * + * @param name The name of the conversation. + * @param account The purple_account associated with the conversation. + * + * @return The conversation if found, or @c NULL otherwise. + */ +PurpleConversation *purple_conversations_find_im_with_account(const char *name, + const PurpleAccount *account); + +/** TODO chats + * Finds a chat with the specified name and Purple account. + * + * @param name The name of the conversation. + * @param account The purple_account associated with the conversation. + * + * @return The conversation if found, or @c NULL otherwise. + */ +PurpleConversation *purple_conversations_find_chat_with_account(const char *name, + const PurpleAccount *account); + +/** + * Finds a chat with the specified chat ID. + * + * @param gc The purple_connection. + * @param id The chat ID. + * + * @return The chat conversation. + */ +PurpleConversation *purple_conversations_find_chat(const PurpleConnection *gc, int id); + +/** + * Sets the default conversation UI operations structure. + * + * @param ops The UI conversation operations structure. + */ +void purple_conversations_set_ui_ops(PurpleConversationUiOps *ops); + +/** + * Returns the conversation subsystem handle. + * + * @return The conversation subsystem handle. + */ +void *purple_conversations_get_handle(void); + +/** + * Initializes the conversation subsystem. + */ +void purple_conversations_init(void); + +/** + * Uninitializes the conversation subsystem. + */ +void purple_conversations_uninit(void); + +/*@}*/ + +G_END_DECLS + +#endif /* _PURPLE_CONVERSATIONS_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/conversationtypes.c Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,1113 @@ +/* + * 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 "conversationtypes.h" + +#define SEND_TYPED_TIMEOUT_SECONDS 5 + +/** @copydoc _PurpleChatConversationPrivate */ +typedef struct _PurpleChatConversationPrivate PurpleChatConversationPrivate; +/** @copydoc _PurpleIMConversationPrivate */ +typedef struct _PurpleIMConversationPrivate PurpleIMConversationPrivate; +/** @copydoc _PurpleChatConversationBuddyPrivate */ +typedef struct _PurpleChatConversationBuddyPrivate PurpleChatConversationBuddyPrivate; + +/** + * Data specific to Chats. + */ +struct _PurpleChatConversationPrivate +{ + GList *in_room; /**< The users in the room. + * @deprecated Will be removed in 3.0.0 TODO + */ + GList *ignored; /**< Ignored users. */ + char *who; /**< The person who set the topic. */ + char *topic; /**< The topic. */ + int id; /**< The chat ID. */ + char *nick; /**< Your nick in this chat. */ + + gboolean left; /**< We left the chat and kept the window open */ + GHashTable *users; /**< Hash table of the users in the room. */ +}; + +/** + * Data specific to Instant Messages. + */ +struct _PurpleIMConversationPrivate +{ + PurpleIMConversationTypingState typing_state; /**< The current typing state. */ + guint typing_timeout; /**< The typing timer handle. */ + time_t type_again; /**< The type again time. */ + guint send_typed_timeout; /**< The type again timer handle. */ + + PurpleBuddyIcon *icon; /**< The buddy icon. */ +}; + +/** + * Data for "Chat Buddies" + */ +struct _PurpleChatConversationBuddyPrivate +{ + /** The chat participant's name in the chat. */ + char *name; + + /** The chat participant's alias, if known; @a NULL otherwise. */ + char *alias; + + /** + * A string by which this buddy will be sorted, or @c NULL if the + * buddy should be sorted by its @c name. (This is currently always + * @c NULL. + */ + char *alias_key; + + /** + * @a TRUE if this chat participant is on the buddy list; + * @a FALSE otherwise. + */ + gboolean buddy; + + /** + * A bitwise OR of flags for this participant, such as whether they + * are a channel operator. + */ + PurpleChatConversationBuddyFlags flags; + + /** + * A hash table of attributes about the user, such as real name, + * user\@host, etc. + */ + GHashTable *attributes; + + /** The UI can put whatever it wants here. */ + gpointer ui_data; +}; + +/************************************************************************** + * IM Conversation API + **************************************************************************/ +void +purple_im_conversation_set_icon(PurpleIMConversation *im, PurpleBuddyIcon *icon) +{ + g_return_if_fail(im != NULL); + + if (im->icon != icon) + { + purple_buddy_icon_unref(im->icon); + + im->icon = (icon == NULL ? NULL : purple_buddy_icon_ref(icon)); + } + + purple_conversation_update(purple_im_conversation_get_conversation(im), + PURPLE_CONVERSATION_UPDATE_ICON); +} + +PurpleBuddyIcon * +purple_im_conversation_get_icon(const PurpleIMConversation *im) +{ + g_return_val_if_fail(im != NULL, NULL); + + return im->icon; +} + +void +purple_im_conversation_set_typing_state(PurpleIMConversation *im, PurpleIMConversationTypingState state) +{ + g_return_if_fail(im != NULL); + + if (im->typing_state != state) + { + im->typing_state = state; + + switch (state) + { + case PURPLE_IM_CONVERSATION_TYPING: + purple_signal_emit(purple_conversations_get_handle(), + "buddy-typing", im->conv->account, im->conv->name); + break; + case PURPLE_IM_CONVERSATION_TYPED: + purple_signal_emit(purple_conversations_get_handle(), + "buddy-typed", im->conv->account, im->conv->name); + break; + case PURPLE_IM_CONVERSATION_NOT_TYPING: + purple_signal_emit(purple_conversations_get_handle(), + "buddy-typing-stopped", im->conv->account, im->conv->name); + break; + } + + purple_im_conversation_update_typing(im); + } +} + +PurpleIMConversationTypingState +purple_im_conversation_get_typing_state(const PurpleIMConversation *im) +{ + g_return_val_if_fail(im != NULL, 0); + + return im->typing_state; +} + +void +purple_im_conversation_start_typing_timeout(PurpleIMConversation *im, int timeout) +{ + PurpleConversation *conv; + + g_return_if_fail(im != NULL); + + if (im->typing_timeout > 0) + purple_im_conversation_stop_typing_timeout(im); + + conv = purple_im_conversation_get_conversation(im); + + im->typing_timeout = purple_timeout_add_seconds(timeout, reset_typing_cb, conv); +} + +void +purple_im_conversation_stop_typing_timeout(PurpleIMConversation *im) +{ + g_return_if_fail(im != NULL); + + if (im->typing_timeout == 0) + return; + + purple_timeout_remove(im->typing_timeout); + im->typing_timeout = 0; +} + +guint +purple_im_conversation_get_typing_timeout(const PurpleIMConversation *im) +{ + g_return_val_if_fail(im != NULL, 0); + + return im->typing_timeout; +} + +void +purple_im_conversation_set_type_again(PurpleIMConversation *im, unsigned int val) +{ + g_return_if_fail(im != NULL); + + if (val == 0) + im->type_again = 0; + else + im->type_again = time(NULL) + val; +} + +time_t +purple_im_conversation_get_type_again(const PurpleIMConversation *im) +{ + g_return_val_if_fail(im != NULL, 0); + + return im->type_again; +} + +void +purple_im_conversation_start_send_typed_timeout(PurpleIMConversation *im) +{ + g_return_if_fail(im != NULL); + + im->send_typed_timeout = purple_timeout_add_seconds(SEND_TYPED_TIMEOUT_SECONDS, + send_typed_cb, + purple_im_conversation_get_conversation(im)); +} + +void +purple_im_conversation_stop_send_typed_timeout(PurpleIMConversation *im) +{ + g_return_if_fail(im != NULL); + + if (im->send_typed_timeout == 0) + return; + + purple_timeout_remove(im->send_typed_timeout); + im->send_typed_timeout = 0; +} + +guint +purple_im_conversation_get_send_typed_timeout(const PurpleIMConversation *im) +{ + g_return_val_if_fail(im != NULL, 0); + + return im->send_typed_timeout; +} + +void +purple_im_conversation_update_typing(PurpleIMConversation *im) +{ + g_return_if_fail(im != NULL); + + purple_conversation_update(purple_im_conversation_get_conversation(im), + PURPLE_CONVERSATION_UPDATE_TYPING); +} + +void +purple_im_conversation_write(PurpleIMConversation *im, const char *who, const char *message, + PurpleConversationMessageFlags flags, time_t mtime) +{ + PurpleConversation *c; + + g_return_if_fail(im != NULL); + g_return_if_fail(message != NULL); + + c = purple_im_conversation_get_conversation(im); + + if ((flags & PURPLE_CONVERSATION_MESSAGE_RECV) == PURPLE_CONVERSATION_MESSAGE_RECV) { + purple_im_conversation_set_typing_state(im, PURPLE_IM_CONVERSATION_NOT_TYPING); + } + + /* Pass this on to either the ops structure or the default write func. */ + if (c->ui_ops != NULL && c->ui_ops->write_im != NULL) + c->ui_ops->write_im(c, who, message, flags, mtime); + else + purple_conversation_write(c, who, message, flags, mtime); +} + +void +purple_im_conversation_send(PurpleIMConversation *im, const char *message) +{ + purple_im_conversation_send_with_flags(im, message, 0); +} + +void +purple_im_conversation_send_with_flags(PurpleIMConversation *im, const char *message, PurpleConversationMessageFlags flags) +{ + g_return_if_fail(im != NULL); + g_return_if_fail(message != NULL); + + common_send(purple_im_conversation_get_conversation(im), message, flags); +} + +/************************************************************************** + * Chat Conversation API + **************************************************************************/ +PurpleConversation * +purple_chat_conversation_get_conversation(const PurpleChatConversation *chat) +{ + g_return_val_if_fail(chat != NULL, NULL); + + return chat->conv; +} + +GList * +purple_chat_conversation_get_users(const PurpleChatConversation *chat) +{ + g_return_val_if_fail(chat != NULL, NULL); + + return chat->in_room; +} + +void +purple_chat_conversation_ignore(PurpleChatConversation *chat, const char *name) +{ + g_return_if_fail(chat != NULL); + g_return_if_fail(name != NULL); + + /* Make sure the user isn't already ignored. */ + if (purple_chat_conversation_is_ignored_user(chat, name)) + return; + + purple_chat_conversation_set_ignored(chat, + g_list_append(chat->ignored, g_strdup(name))); +} + +void +purple_chat_conversation_unignore(PurpleChatConversation *chat, const char *name) +{ + GList *item; + + g_return_if_fail(chat != NULL); + g_return_if_fail(name != NULL); + + /* Make sure the user is actually ignored. */ + if (!purple_chat_conversation_is_ignored_user(chat, name)) + return; + + item = g_list_find(purple_chat_conversation_get_ignored(chat), + purple_chat_conversation_get_ignored_user(chat, name)); + + purple_chat_conversation_set_ignored(chat, + g_list_remove_link(chat->ignored, item)); + + g_free(item->data); + g_list_free_1(item); +} + +GList * +purple_chat_conversation_set_ignored(PurpleChatConversation *chat, GList *ignored) +{ + g_return_val_if_fail(chat != NULL, NULL); + + chat->ignored = ignored; + + return ignored; +} + +GList * +purple_chat_conversation_get_ignored(const PurpleChatConversation *chat) +{ + g_return_val_if_fail(chat != NULL, NULL); + + return chat->ignored; +} + +const char * +purple_chat_conversation_get_ignored_user(const PurpleChatConversation *chat, const char *user) +{ + GList *ignored; + + g_return_val_if_fail(chat != NULL, NULL); + g_return_val_if_fail(user != NULL, NULL); + + for (ignored = purple_chat_conversation_get_ignored(chat); + ignored != NULL; + ignored = ignored->next) { + + const char *ign = (const char *)ignored->data; + + if (!purple_utf8_strcasecmp(user, ign) || + ((*ign == '+' || *ign == '%') && !purple_utf8_strcasecmp(user, ign + 1))) + return ign; + + if (*ign == '@') { + ign++; + + if ((*ign == '+' && !purple_utf8_strcasecmp(user, ign + 1)) || + (*ign != '+' && !purple_utf8_strcasecmp(user, ign))) + return ign; + } + } + + return NULL; +} + +gboolean +purple_chat_conversation_is_ignored_user(const PurpleChatConversation *chat, const char *user) +{ + g_return_val_if_fail(chat != NULL, FALSE); + g_return_val_if_fail(user != NULL, FALSE); + + return (purple_chat_conversation_get_ignored_user(chat, user) != NULL); +} + +void +purple_chat_conversation_set_topic(PurpleChatConversation *chat, const char *who, const char *topic) +{ + g_return_if_fail(chat != NULL); + + g_free(chat->who); + g_free(chat->topic); + + chat->who = g_strdup(who); + chat->topic = g_strdup(topic); + + purple_conversation_update(purple_chat_conversation_get_conversation(chat), + PURPLE_CONVERSATION_UPDATE_TOPIC); + + purple_signal_emit(purple_conversations_get_handle(), "chat-topic-changed", + chat->conv, chat->who, chat->topic); +} + +const char * +purple_chat_conversation_get_topic(const PurpleChatConversation *chat) +{ + g_return_val_if_fail(chat != NULL, NULL); + + return chat->topic; +} + +void +purple_chat_conversation_set_id(PurpleChatConversation *chat, int id) +{ + g_return_if_fail(chat != NULL); + + chat->id = id; +} + +int +purple_chat_conversation_get_id(const PurpleChatConversation *chat) +{ + g_return_val_if_fail(chat != NULL, -1); + + return chat->id; +} + +void +purple_chat_conversation_write(PurpleChatConversation *chat, const char *who, const char *message, + PurpleConversationMessageFlags flags, time_t mtime) +{ + PurpleAccount *account; + PurpleConversation *conv; + PurpleConnection *gc; + + g_return_if_fail(chat != NULL); + g_return_if_fail(who != NULL); + g_return_if_fail(message != NULL); + + conv = purple_chat_conversation_get_conversation(chat); + gc = purple_conversation_get_connection(conv); + account = purple_connection_get_account(gc); + + /* Don't display this if the person who wrote it is ignored. */ + if (purple_chat_conversation_is_ignored_user(chat, who)) + return; + + if (!(flags & PURPLE_CONVERSATION_MESSAGE_WHISPER)) { + const char *str; + + str = purple_normalize(account, who); + + if (purple_strequal(str, chat->nick)) { + flags |= PURPLE_CONVERSATION_MESSAGE_SEND; + } else { + flags |= PURPLE_CONVERSATION_MESSAGE_RECV; + + if (purple_utf8_has_word(message, chat->nick)) + flags |= PURPLE_CONVERSATION_MESSAGE_NICK; + } + } + + /* Pass this on to either the ops structure or the default write func. */ + if (conv->ui_ops != NULL && conv->ui_ops->write_chat != NULL) + conv->ui_ops->write_chat(conv, who, message, flags, mtime); + else + purple_conversation_write(conv, who, message, flags, mtime); +} + +void +purple_chat_conversation_send(PurpleChatConversation *chat, const char *message) +{ + purple_chat_conversation_send_with_flags(chat, message, 0); +} + +void +purple_chat_conversation_send_with_flags(PurpleChatConversation *chat, const char *message, PurpleConversationMessageFlags flags) +{ + g_return_if_fail(chat != NULL); + g_return_if_fail(message != NULL); + + common_send(purple_chat_conversation_get_conversation(chat), message, flags); +} + +void +purple_chat_conversation_add_user(PurpleChatConversation *chat, const char *user, + const char *extra_msg, PurpleChatConversationBuddyFlags flags, + gboolean new_arrival) +{ + GList *users = g_list_append(NULL, (char *)user); + GList *extra_msgs = g_list_append(NULL, (char *)extra_msg); + GList *flags2 = g_list_append(NULL, GINT_TO_POINTER(flags)); + + purple_chat_conversation_add_users(chat, users, extra_msgs, flags2, new_arrival); + + g_list_free(users); + g_list_free(extra_msgs); + g_list_free(flags2); +} + +void +purple_chat_conversation_add_users(PurpleChatConversation *chat, GList *users, GList *extra_msgs, + GList *flags, gboolean new_arrivals) +{ + PurpleConversation *conv; + PurpleConversationUiOps *ops; + PurpleChatConversationBuddy *cbuddy; + PurpleConnection *gc; + PurplePluginProtocolInfo *prpl_info; + GList *ul, *fl; + GList *cbuddies = NULL; + + g_return_if_fail(chat != NULL); + g_return_if_fail(users != NULL); + + conv = purple_chat_conversation_get_conversation(chat); + ops = purple_conversation_get_ui_ops(conv); + + gc = purple_conversation_get_connection(conv); + g_return_if_fail(gc != NULL); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + g_return_if_fail(prpl_info != NULL); + + ul = users; + fl = flags; + while ((ul != NULL) && (fl != NULL)) { + const char *user = (const char *)ul->data; + const char *alias = user; + gboolean quiet; + PurpleChatConversationBuddyFlags flag = GPOINTER_TO_INT(fl->data); + const char *extra_msg = (extra_msgs ? extra_msgs->data : NULL); + + if(!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { + if (purple_strequal(chat->nick, purple_normalize(conv->account, user))) { + const char *alias2 = purple_account_get_private_alias(conv->account); + if (alias2 != NULL) + alias = alias2; + else + { + const char *display_name = purple_connection_get_display_name(gc); + if (display_name != NULL) + alias = display_name; + } + } else { + PurpleBuddy *buddy; + if ((buddy = purple_find_buddy(purple_connection_get_account(gc), user)) != NULL) + alias = purple_buddy_get_contact_alias(buddy); + } + } + + quiet = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_conversations_get_handle(), + "chat-buddy-joining", conv, user, flag)) || + purple_chat_conversation_is_ignored_user(chat, user); + + cbuddy = purple_chat_conversation_buddy_new(user, alias, flag); + cbuddy->buddy = purple_find_buddy(conv->account, user) != NULL; + + chat->in_room = g_list_prepend(chat->in_room, cbuddy); + g_hash_table_replace(chat->users, g_strdup(cbuddy->name), cbuddy); + + cbuddies = g_list_prepend(cbuddies, cbuddy); + + if (!quiet && new_arrivals) { + char *alias_esc = g_markup_escape_text(alias, -1); + char *tmp; + + if (extra_msg == NULL) + tmp = g_strdup_printf(_("%s entered the room."), alias_esc); + else { + char *extra_msg_esc = g_markup_escape_text(extra_msg, -1); + tmp = g_strdup_printf(_("%s [<I>%s</I>] entered the room."), + alias_esc, extra_msg_esc); + g_free(extra_msg_esc); + } + g_free(alias_esc); + + purple_conversation_write(conv, NULL, tmp, + PURPLE_CONVERSATION_MESSAGE_SYSTEM | PURPLE_CONVERSATION_MESSAGE_NO_LINKIFY, + time(NULL)); + g_free(tmp); + } + + purple_signal_emit(purple_conversations_get_handle(), + "chat-buddy-joined", conv, user, flag, new_arrivals); + ul = ul->next; + fl = fl->next; + if (extra_msgs != NULL) + extra_msgs = extra_msgs->next; + } + + cbuddies = g_list_sort(cbuddies, (GCompareFunc)purple_chat_conversation_buddy_compare); + + if (ops != NULL && ops->chat_add_users != NULL) + ops->chat_add_users(conv, cbuddies, new_arrivals); + + g_list_free(cbuddies); +} + +void +purple_chat_conversation_rename_user(PurpleChatConversation *chat, const char *old_user, + const char *new_user) +{ + PurpleConversation *conv; + PurpleConversationUiOps *ops; + PurpleConnection *gc; + PurplePluginProtocolInfo *prpl_info; + PurpleChatConversationBuddy *cb; + PurpleChatConversationBuddyFlags flags; + const char *new_alias = new_user; + char tmp[BUF_LONG]; + gboolean is_me = FALSE; + + g_return_if_fail(chat != NULL); + g_return_if_fail(old_user != NULL); + g_return_if_fail(new_user != NULL); + + conv = purple_chat_conversation_get_conversation(chat); + ops = purple_conversation_get_ui_ops(conv); + + gc = purple_conversation_get_connection(conv); + g_return_if_fail(gc != NULL); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + g_return_if_fail(prpl_info != NULL); + + if (purple_strequal(chat->nick, purple_normalize(conv->account, old_user))) { + const char *alias; + + /* Note this for later. */ + is_me = TRUE; + + if(!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { + alias = purple_account_get_private_alias(conv->account); + if (alias != NULL) + new_alias = alias; + else + { + const char *display_name = purple_connection_get_display_name(gc); + if (display_name != NULL) + new_alias = display_name; + } + } + } else if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { + PurpleBuddy *buddy; + if ((buddy = purple_find_buddy(purple_connection_get_account(gc), new_user)) != NULL) + new_alias = purple_buddy_get_contact_alias(buddy); + } + + flags = purple_chat_conversation_user_get_flags(chat, old_user); + cb = purple_chat_conversation_buddy_new(new_user, new_alias, flags); + cb->buddy = purple_find_buddy(conv->account, new_user) != NULL; + + chat->in_room = g_list_prepend(chat->in_room, cb); + g_hash_table_replace(chat->users, g_strdup(cb->name), cb); + + if (ops != NULL && ops->chat_rename_user != NULL) + ops->chat_rename_user(conv, old_user, new_user, new_alias); + + cb = purple_chat_conversation_find_buddy(chat, old_user); + + if (cb) { + chat->in_room = g_list_remove(chat->in_room, cb); + g_hash_table_remove(chat->users, cb->name); + purple_chat_conversation_buddy_destroy(cb); + } + + if (purple_chat_conversation_is_ignored_user(chat, old_user)) { + purple_chat_conversation_unignore(chat, old_user); + purple_chat_conversation_ignore(chat, new_user); + } + else if (purple_chat_conversation_is_ignored_user(chat, new_user)) + purple_chat_conversation_unignore(chat, new_user); + + if (is_me) + purple_chat_conversation_set_nick(chat, new_user); + + if (purple_prefs_get_bool("/purple/conversations/chat/show_nick_change") && + !purple_chat_conversation_is_ignored_user(chat, new_user)) { + + if (is_me) { + char *escaped = g_markup_escape_text(new_user, -1); + g_snprintf(tmp, sizeof(tmp), + _("You are now known as %s"), escaped); + g_free(escaped); + } else { + const char *old_alias = old_user; + const char *new_alias = new_user; + char *escaped; + char *escaped2; + + if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { + PurpleBuddy *buddy; + + if ((buddy = purple_find_buddy(purple_connection_get_account(gc), old_user)) != NULL) + old_alias = purple_buddy_get_contact_alias(buddy); + if ((buddy = purple_find_buddy(purple_connection_get_account(gc), new_user)) != NULL) + new_alias = purple_buddy_get_contact_alias(buddy); + } + + escaped = g_markup_escape_text(old_alias, -1); + escaped2 = g_markup_escape_text(new_alias, -1); + g_snprintf(tmp, sizeof(tmp), + _("%s is now known as %s"), escaped, escaped2); + g_free(escaped); + g_free(escaped2); + } + + purple_conversation_write(conv, NULL, tmp, + PURPLE_CONVERSATION_MESSAGE_SYSTEM | PURPLE_CONVERSATION_MESSAGE_NO_LINKIFY, + time(NULL)); + } +} + +void +purple_chat_conversation_remove_user(PurpleChatConversation *chat, const char *user, const char *reason) +{ + GList *users = g_list_append(NULL, (char *)user); + + purple_chat_conversation_remove_users(chat, users, reason); + + g_list_free(users); +} + +void +purple_chat_conversation_remove_users(PurpleChatConversation *chat, GList *users, const char *reason) +{ + PurpleConversation *conv; + PurpleConnection *gc; + PurplePluginProtocolInfo *prpl_info; + PurpleConversationUiOps *ops; + PurpleChatConversationBuddy *cb; + GList *l; + gboolean quiet; + + g_return_if_fail(chat != NULL); + g_return_if_fail(users != NULL); + + conv = purple_chat_conversation_get_conversation(chat); + + gc = purple_conversation_get_connection(conv); + g_return_if_fail(gc != NULL); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + g_return_if_fail(prpl_info != NULL); + + ops = purple_conversation_get_ui_ops(conv); + + for (l = users; l != NULL; l = l->next) { + const char *user = (const char *)l->data; + quiet = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_conversations_get_handle(), + "chat-buddy-leaving", conv, user, reason)) | + purple_chat_conversation_is_ignored_user(chat, user); + + cb = purple_chat_conversation_find_buddy(chat, user); + + if (cb) { + chat->in_room = g_list_remove(chat->in_room, cb); + g_hash_table_remove(chat->users, cb->name); + purple_chat_conversation_buddy_destroy(cb); + } + + /* NOTE: Don't remove them from ignored in case they re-enter. */ + + if (!quiet) { + const char *alias = user; + char *alias_esc; + char *tmp; + + if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { + PurpleBuddy *buddy; + + if ((buddy = purple_find_buddy(purple_connection_get_account(gc), user)) != NULL) + alias = purple_buddy_get_contact_alias(buddy); + } + + alias_esc = g_markup_escape_text(alias, -1); + + if (reason == NULL || !*reason) + tmp = g_strdup_printf(_("%s left the room."), alias_esc); + else { + char *reason_esc = g_markup_escape_text(reason, -1); + tmp = g_strdup_printf(_("%s left the room (%s)."), + alias_esc, reason_esc); + g_free(reason_esc); + } + g_free(alias_esc); + + purple_conversation_write(conv, NULL, tmp, + PURPLE_CONVERSATION_MESSAGE_SYSTEM | PURPLE_CONVERSATION_MESSAGE_NO_LINKIFY, + time(NULL)); + g_free(tmp); + } + + purple_signal_emit(purple_conversations_get_handle(), "chat-buddy-left", + conv, user, reason); + } + + if (ops != NULL && ops->chat_remove_users != NULL) + ops->chat_remove_users(conv, users); +} + +void +purple_chat_conversation_clear_users(PurpleChatConversation *chat) +{ + PurpleConversation *conv; + PurpleConversationUiOps *ops; + GList *users; + GList *l; + GList *names = NULL; + + g_return_if_fail(chat != NULL); + + conv = purple_chat_conversation_get_conversation(chat); + ops = purple_conversation_get_ui_ops(conv); + users = chat->in_room; + + if (ops != NULL && ops->chat_remove_users != NULL) { + for (l = users; l; l = l->next) { + PurpleChatConversationBuddy *cb = l->data; + names = g_list_prepend(names, cb->name); + } + ops->chat_remove_users(conv, names); + g_list_free(names); + } + + for (l = users; l; l = l->next) + { + PurpleChatConversationBuddy *cb = l->data; + + purple_signal_emit(purple_conversations_get_handle(), + "chat-buddy-leaving", conv, cb->name, NULL); + purple_signal_emit(purple_conversations_get_handle(), + "chat-buddy-left", conv, cb->name, NULL); + + purple_chat_conversation_buddy_destroy(cb); + } + + g_hash_table_remove_all(chat->users); + + g_list_free(users); + chat->in_room = NULL; +} + + +gboolean +purple_chat_conversation_find_user(PurpleChatConversation *chat, const char *user) +{ + g_return_val_if_fail(chat != NULL, FALSE); + g_return_val_if_fail(user != NULL, FALSE); + + return (purple_chat_conversation_find_buddy(chat, user) != NULL); +} + +void +purple_chat_conversation_user_set_flags(PurpleChatConversation *chat, const char *user, + PurpleChatConversationBuddyFlags flags) +{ + PurpleConversation *conv; + PurpleConversationUiOps *ops; + PurpleChatConversationBuddy *cb; + PurpleChatConversationBuddyFlags oldflags; + + g_return_if_fail(chat != NULL); + g_return_if_fail(user != NULL); + + cb = purple_chat_conversation_find_buddy(chat, user); + + if (!cb) + return; + + if (flags == cb->flags) + return; + + oldflags = cb->flags; + cb->flags = flags; + + conv = purple_chat_conversation_get_conversation(chat); + ops = purple_conversation_get_ui_ops(conv); + + if (ops != NULL && ops->chat_update_user != NULL) + ops->chat_update_user(conv, user); + + purple_signal_emit(purple_conversations_get_handle(), + "chat-buddy-flags", conv, user, oldflags, flags); +} + +PurpleChatConversationBuddyFlags +purple_chat_conversation_user_get_flags(PurpleChatConversation *chat, const char *user) +{ + PurpleChatConversationBuddy *cb; + + g_return_val_if_fail(chat != NULL, 0); + g_return_val_if_fail(user != NULL, 0); + + cb = purple_chat_conversation_find_buddy(chat, user); + + if (!cb) + return PURPLE_CHAT_CONVERSATION_BUDDY_NONE; + + return cb->flags; +} + +void +purple_chat_conversation_leave(PurpleChatConversation *chat) +{ + g_return_if_fail(chat != NULL); + + chat->left = TRUE; + purple_conversation_update(chat->conv, PURPLE_CONVERSATION_UPDATE_CHATLEFT); +} + +gboolean +purple_chat_conversation_has_left(PurpleChatConversation *chat) +{ + g_return_val_if_fail(chat != NULL, TRUE); + + return chat->left; +} + +PurpleChatConversationBuddy * +purple_chat_conversation_find_buddy(PurpleChatConversation *chat, const char *name) +{ + g_return_val_if_fail(chat != NULL, NULL); + g_return_val_if_fail(name != NULL, NULL); + + return g_hash_table_lookup(chat->users, name); +} + +/************************************************************************** + * Chat Conversation Buddy API + **************************************************************************/ +static int +purple_chat_conversation_buddy_compare(PurpleChatConversationBuddy *a, PurpleChatConversationBuddy *b) +{ + PurpleChatConversationBuddyFlags f1 = 0, f2 = 0; + char *user1 = NULL, *user2 = NULL; + gint ret = 0; + + if (a) { + f1 = a->flags; + if (a->alias_key) + user1 = a->alias_key; + else if (a->name) + user1 = a->name; + } + + if (b) { + f2 = b->flags; + if (b->alias_key) + user2 = b->alias_key; + else if (b->name) + user2 = b->name; + } + + if (user1 == NULL || user2 == NULL) { + if (!(user1 == NULL && user2 == NULL)) + ret = (user1 == NULL) ? -1: 1; + } else if (f1 != f2) { + /* sort more important users first */ + ret = (f1 > f2) ? -1 : 1; + } else if (a->buddy != b->buddy) { + ret = a->buddy ? -1 : 1; + } else { + ret = purple_utf8_strcasecmp(user1, user2); + } + + return ret; +} + +PurpleChatConversationBuddy * +purple_chat_conversation_buddy_new(const char *name, const char *alias, PurpleChatConversationBuddyFlags flags) +{ + PurpleChatConversationBuddy *cb; + + g_return_val_if_fail(name != NULL, NULL); + + cb = g_new0(PurpleChatConversationBuddy, 1); + cb->name = g_strdup(name); + cb->flags = flags; + cb->alias = g_strdup(alias); + cb->attributes = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, g_free); + + PURPLE_DBUS_REGISTER_POINTER(cb, PurpleChatConversationBuddy); + return cb; +} + +void +purple_chat_conversation_buddy_destroy(PurpleChatConversationBuddy *cb) +{ + if (cb == NULL) + return; + + purple_signal_emit(purple_conversations_get_handle(), + "deleting-chat-buddy", cb); + + g_free(cb->alias); + g_free(cb->alias_key); + g_free(cb->name); + g_hash_table_destroy(cb->attributes); + + PURPLE_DBUS_UNREGISTER_POINTER(cb); + g_free(cb); +} + +const char * +purple_chat_conversation_buddy_get_alias(const PurpleChatConversationBuddy *cb) +{ + g_return_val_if_fail(cb != NULL, NULL); + + return cb->alias; +} + +const char * +purple_chat_conversation_buddy_get_name(const PurpleChatConversationBuddy *cb) +{ + g_return_val_if_fail(cb != NULL, NULL); + + return cb->name; +} + +PurpleChatConversationBuddyFlags +purple_chat_conversation_buddy_get_flags(const PurpleChatConversationBuddy *cb) +{ + g_return_val_if_fail(cb != NULL, PURPLE_CHAT_CONVERSATION_BUDDY_NONE); + + return cb->flags; +} + +const char * +purple_chat_conversation_buddy_get_attribute(PurpleChatConversationBuddy *cb, const char *key) +{ + g_return_val_if_fail(cb != NULL, NULL); + g_return_val_if_fail(key != NULL, NULL); + + return g_hash_table_lookup(cb->attributes, key); +} + +GList * +purple_chat_conversation_buddy_get_attribute_keys(PurpleChatConversationBuddy *cb) +{ + GList *keys = NULL; + + g_return_val_if_fail(cb != NULL, NULL); + + g_hash_table_foreach(cb->attributes, (GHFunc)append_attribute_key, &keys); + + return keys; +} + +void +purple_chat_conversation_buddy_set_attribute(PurpleChatConversation *chat, PurpleChatConversationBuddy *cb, const char *key, const char *value) +{ + PurpleConversation *conv; + PurpleConversationUiOps *ops; + + g_return_if_fail(cb != NULL); + g_return_if_fail(key != NULL); + g_return_if_fail(value != NULL); + + g_hash_table_replace(cb->attributes, g_strdup(key), g_strdup(value)); + + conv = purple_chat_conversation_get_conversation(chat); + ops = purple_conversation_get_ui_ops(conv); + + if (ops != NULL && ops->chat_update_user != NULL) + ops->chat_update_user(conv, cb->name); +} + +void +purple_chat_conversation_buddy_set_attributes(PurpleChatConversation *chat, PurpleChatConversationBuddy *cb, GList *keys, GList *values) +{ + PurpleConversation *conv; + PurpleConversationUiOps *ops; + + g_return_if_fail(cb != NULL); + g_return_if_fail(keys != NULL); + g_return_if_fail(values != NULL); + + while (keys != NULL && values != NULL) { + g_hash_table_replace(cb->attributes, g_strdup(keys->data), g_strdup(values->data)); + keys = g_list_next(keys); + values = g_list_next(values); + } + + conv = purple_chat_conversation_get_conversation(chat); + ops = purple_conversation_get_ui_ops(conv); + + if (ops != NULL && ops->chat_update_user != NULL) + ops->chat_update_user(conv, cb->name); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/conversationtypes.h Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,829 @@ +/** + * @file conversationtypes.h Chat and IM Conversation API + * @ingroup core + */ + +/* 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 + */ +#ifndef _PURPLE_CONVERSATION_TYPES_H_ +#define _PURPLE_CONVERSATION_TYPES_H_ + +/**************************************************************************/ +/** Data Structures */ +/**************************************************************************/ + +#define PURPLE_TYPE_IM_CONVERSATION (purple_im_conversation_get_type()) +#define PURPLE_IM_CONVERSATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + PURPLE_TYPE_IM_CONVERSATION, \ + PurpleIMConversation)) +#define PURPLE_IM_CONVERSATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \ + PURPLE_TYPE_IM_CONVERSATION, \ + PurpleIMConversationClass)) +#define PURPLE_IS_IM_CONVERSATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \ + PURPLE_TYPE_IM_CONVERSATION)) +#define PURPLE_IS_IM_CONVERSATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),\ + PURPLE_TYPE_IM_CONVERSATION)) +#define PURPLE_IM_CONVERSATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),\ + PURPLE_TYPE_IM_CONVERSATION, \ + PurpleIMConversationClass)) + +/** @copydoc _PurpleIMConversation */ +typedef struct _PurpleIMConversation PurpleIMConversation; +/** @copydoc _PurpleIMConversationClass */ +typedef struct _PurpleIMConversationClass PurpleIMConversationClass; + +#define PURPLE_TYPE_CHAT_CONVERSATION (purple_chat_conversation_get_type()) +#define PURPLE_CHAT_CONVERSATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + PURPLE_TYPE_CHAT_CONVERSATION, \ + PurpleChatConversation)) +#define PURPLE_CHAT_CONVERSATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),\ + PURPLE_TYPE_CHAT_CONVERSATION, \ + PurpleChatConversationClass)) +#define PURPLE_IS_CHAT_CONVERSATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \ + PURPLE_TYPE_CHAT_CONVERSATION)) +#define PURPLE_IS_CHAT_CONVERSATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),\ + PURPLE_TYPE_CHAT_CONVERSATION)) +#define PURPLE_CHAT_CONVERSATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),\ + PURPLE_TYPE_CHAT_CONVERSATION, \ + PurpleChatConversationClass)) + +/** @copydoc _PurpleChatConversation */ +typedef struct _PurpleChatConversation PurpleChatConversation; +/** @copydoc _PurpleChatConversationClass */ +typedef struct _PurpleChatConversationClass PurpleChatConversationClass; + +#define PURPLE_TYPE_CHAT_CONVERSATION_BUDDY (purple_chat_conversation_buddy_get_type()) +#define PURPLE_CHAT_CONVERSATION_BUDDY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + PURPLE_TYPE_CHAT_CONVERSATION_BUDDY,\ + PurpleChatConversationBuddy)) +#define PURPLE_CHAT_CONVERSATION_BUDDY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),\ + PURPLE_TYPE_CHAT_CONVERSATION_BUDDY,\ + PurpleChatConversationBuddyClass)) +#define PURPLE_IS_CHAT_CONVERSATION_BUDDY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),\ + PURPLE_TYPE_CHAT_CONVERSATION_BUDDY)) +#define PURPLE_IS_CHAT_CONVERSATION_BUDDY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),\ + PURPLE_TYPE_CHAT_CONVERSATION_BUDDY)) +#define PURPLE_CHAT_CONVERSATION_BUDDY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),\ + PURPLE_TYPE_CHAT_CONVERSATION_BUDDY,\ + PurpleChatConversationBuddyClass)) + +/** @copydoc _PurpleChatConversationBuddy */ +typedef struct _PurpleChatConversationBuddy PurpleChatConversationBuddy; +/** @copydoc _PurpleChatConversationBuddyClass */ +typedef struct _PurpleChatConversationBuddyClass PurpleChatConversationBuddyClass; + +/** + * The typing state of a user. + */ +typedef enum +{ + PURPLE_IM_CONVERSATION_NOT_TYPING = 0, /**< Not typing. */ + PURPLE_IM_CONVERSATION_TYPING, /**< Currently typing. */ + PURPLE_IM_CONVERSATION_TYPED /**< Stopped typing momentarily. */ + +} PurpleIMConversationTypingState; + +/** + * Flags applicable to users in Chats. + */ +typedef enum /*< flags >*/ +{ + PURPLE_CHAT_CONVERSATION_BUDDY_NONE = 0x0000, /**< No flags */ + PURPLE_CHAT_CONVERSATION_BUDDY_VOICE = 0x0001, /**< Voiced user or "Participant" */ + PURPLE_CHAT_CONVERSATION_BUDDY_HALFOP = 0x0002, /**< Half-op */ + PURPLE_CHAT_CONVERSATION_BUDDY_OP = 0x0004, /**< Channel Op or Moderator */ + PURPLE_CHAT_CONVERSATION_BUDDY_FOUNDER = 0x0008, /**< Channel Founder */ + PURPLE_CHAT_CONVERSATION_BUDDY_TYPING = 0x0010, /**< Currently typing */ + PURPLE_CHAT_CONVERSATION_BUDDY_AWAY = 0x0020 /**< Currently away. */ + +} PurpleChatConversationBuddyFlags; + +#include "conversation.h" + +/**************************************************************************/ +/** PurpleIMConversation */ +/**************************************************************************/ +/** Structure representing an IM conversation instance. */ +struct _PurpleIMConversation +{ + /*< private >*/ + PurpleConversation parent_object; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +/** Base class for all #PurpleIMConversation's */ +struct _PurpleIMConversationClass { + /*< private >*/ + PurpleConversationClass parent_class; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +/**************************************************************************/ +/** PurpleChatConversation */ +/**************************************************************************/ +/** Structure representing a chat conversation instance. */ +struct _PurpleChatConversation +{ + /*< private >*/ + PurpleConversation parent_object; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +/** Base class for all #PurpleChatConversation's */ +struct _PurpleChatConversationClass { + /*< private >*/ + PurpleConversationClass parent_class; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +/**************************************************************************/ +/** PurpleChatConversationBuddy */ +/**************************************************************************/ +/** Structure representing a chat buddy instance. */ +struct _PurpleChatConversationBuddy +{ + /*< private >*/ + GObject gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +/** Base class for all #PurpleChatConversationBuddy's */ +struct _PurpleChatConversationBuddyClass { + /*< private >*/ + GObjectClass parent_class; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +/**************************************************************************/ +/** @name IM Conversation API */ +/**************************************************************************/ +/*@{*/ + +/** TODO + * Returns the GType for the IMConversation object. + */ +GType purple_im_conversation_get_type(void); + +/** TODO take from conversation.c purple_conversation_new() + * Creates a new IM conversation. + * + * @param account The account opening the conversation window on the purple + * user's end. + * @param name Name of the buddy. + * + * @return The new conversation. + */ +PurpleConversation *purple_im_conversation_new(PurpleAccount *account, + const char *name); + +/** + * Sets the IM's buddy icon. + * + * This should only be called from within Purple. You probably want to + * call purple_buddy_icon_set_data(). + * + * @param im The IM. + * @param icon The buddy icon. + * + * @see purple_buddy_icon_set_data() + */ +void purple_im_conversation_set_icon(PurpleIMConversation *im, PurpleBuddyIcon *icon); + +/** + * Returns the IM's buddy icon. + * + * @param im The IM. + * + * @return The buddy icon. + */ +PurpleBuddyIcon *purple_im_conversation_get_icon(const PurpleIMConversation *im); + +/** + * Sets the IM's typing state. + * + * @param im The IM. + * @param state The typing state. + */ +void purple_im_conversation_set_typing_state(PurpleIMConversation *im, PurpleIMConversationTypingState state); + +/** + * Returns the IM's typing state. + * + * @param im The IM. + * + * @return The IM's typing state. + */ +PurpleIMConversationTypingState purple_im_conversation_get_typing_state(const PurpleIMConversation *im); + +/** + * Starts the IM's typing timeout. + * + * @param im The IM. + * @param timeout The timeout. + */ +void purple_im_conversation_start_typing_timeout(PurpleIMConversation *im, int timeout); + +/** + * Stops the IM's typing timeout. + * + * @param im The IM. + */ +void purple_im_conversation_stop_typing_timeout(PurpleIMConversation *im); + +/** + * Returns the IM's typing timeout. + * + * @param im The IM. + * + * @return The timeout. + */ +guint purple_im_conversation_get_typing_timeout(const PurpleIMConversation *im); + +/** + * Sets the quiet-time when no PURPLE_IM_CONVERSATION_TYPING messages will be sent. + * Few protocols need this (maybe only MSN). If the user is still + * typing after this quiet-period, then another PURPLE_IM_CONVERSATION_TYPING message + * will be sent. + * + * @param im The IM. + * @param val The number of seconds to wait before allowing another + * PURPLE_IM_CONVERSATION_TYPING message to be sent to the user. Or 0 to + * not send another PURPLE_IM_CONVERSATION_TYPING message. + */ +void purple_im_conversation_set_type_again(PurpleIMConversation *im, unsigned int val); + +/** + * Returns the time after which another PURPLE_IM_CONVERSATION_TYPING message should be sent. + * + * @param im The IM. + * + * @return The time in seconds since the epoch. Or 0 if no additional + * PURPLE_IM_CONVERSATION_TYPING message should be sent. + */ +time_t purple_im_conversation_get_type_again(const PurpleIMConversation *im); + +/** + * Starts the IM's type again timeout. + * + * @param im The IM. + */ +void purple_im_conversation_start_send_typed_timeout(PurpleIMConversation *im); + +/** + * Stops the IM's type again timeout. + * + * @param im The IM. + */ +void purple_im_conversation_stop_send_typed_timeout(PurpleIMConversation *im); + +/** + * Returns the IM's type again timeout interval. + * + * @param im The IM. + * + * @return The type again timeout interval. + */ +guint purple_im_conversation_get_send_typed_timeout(const PurpleIMConversation *im); + +/** + * Updates the visual typing notification for an IM conversation. + * + * @param im The IM. + */ +void purple_im_conversation_update_typing(PurpleIMConversation *im); + +/** TODO override + * Writes to an IM. + * + * @param im The IM. + * @param who The user who sent the message. + * @param message The message to write. + * @param flags The message flags. + * @param mtime The time the message was sent. + */ +/*void purple_im_conversation_write(PurpleIMConversation *im, const char *who, + const char *message, PurpleConversationMessageFlags flags, + time_t mtime);*/ + +/** TODO write forward + * Sends a message to this IM conversation. + * + * @param im The IM. + * @param message The message to send. + */ +/*void purple_im_conversation_send(PurpleIMConversation *im, const char *message);*/ + +/** TODO override + * Sends a message to this IM conversation with specified flags. + * + * @param im The IM. + * @param message The message to send. + * @param flags The PurpleConversationMessageFlags flags to use in addition to + * PURPLE_CONVERSATION_MESSAGE_SEND. + */ +/*void purple_im_conversation_send_with_flags(PurpleIMConversation *im, + const char *message, PurpleConversationMessageFlags flags);*/ + +/*@}*/ + +/**************************************************************************/ +/** @name Chat Conversation API */ +/**************************************************************************/ +/*@{*/ + +/** TODO + * Returns the GType for the ChatConversation object. + */ +GType purple_chat_conversation_get_type(void); + +/** TODO take from conversation.c purple_conversation_new() + * Creates a new chat conversation. + * + * @param account The account opening the conversation window on the purple + * user's end. + * @param name The name of the conversation. + * + * @return The new conversation. + */ +PurpleConversation *purple_chat_conversation_new(PurpleAccount *account, + const char *name); + +/** + * Returns a list of users in the chat room. The members of the list + * are PurpleChatConversationBuddy objects. + * + * @param chat The chat. + * + * @constreturn The list of users. + */ +GList *purple_chat_conversation_get_users(const PurpleChatConversation *chat); + +/** + * Ignores a user in a chat room. + * + * @param chat The chat. + * @param name The name of the user. + */ +void purple_chat_conversation_ignore(PurpleChatConversation *chat, const char *name); + +/** + * Unignores a user in a chat room. + * + * @param chat The chat. + * @param name The name of the user. + */ +void purple_chat_conversation_unignore(PurpleChatConversation *chat, const char *name); + +/** + * Sets the list of ignored users in the chat room. + * + * @param chat The chat. + * @param ignored The list of ignored users. + * + * @return The list passed. + */ +GList *purple_chat_conversation_set_ignored(PurpleChatConversation *chat, GList *ignored); + +/** + * Returns the list of ignored users in the chat room. + * + * @param chat The chat. + * + * @constreturn The list of ignored users. + */ +GList *purple_chat_conversation_get_ignored(const PurpleChatConversation *chat); + +/** + * Returns the actual name of the specified ignored user, if it exists in + * the ignore list. + * + * If the user found contains a prefix, such as '+' or '\@', this is also + * returned. The username passed to the function does not have to have this + * formatting. + * + * @param chat The chat. + * @param user The user to check in the ignore list. + * + * @return The ignored user if found, complete with prefixes, or @c NULL + * if not found. + */ +const char *purple_chat_conversation_get_ignored_user(const PurpleChatConversation *chat, + const char *user); + +/** + * Returns @c TRUE if the specified user is ignored. + * + * @param chat The chat. + * @param user The user. + * + * @return @c TRUE if the user is in the ignore list; @c FALSE otherwise. + */ +gboolean purple_chat_conversation_is_ignored_user(const PurpleChatConversation *chat, + const char *user); + +/** + * Sets the chat room's topic. + * + * @param chat The chat. + * @param who The user that set the topic. + * @param topic The topic. + */ +void purple_chat_conversation_set_topic(PurpleChatConversation *chat, const char *who, + const char *topic); + +/** + * Returns the chat room's topic. + * + * @param chat The chat. + * + * @return The chat's topic. + */ +const char *purple_chat_conversation_get_topic(const PurpleChatConversation *chat); + +/** + * Sets the chat room's ID. + * + * @param chat The chat. + * @param id The ID. + */ +void purple_chat_conversation_set_id(PurpleChatConversation *chat, int id); + +/** + * Returns the chat room's ID. + * + * @param chat The chat. + * + * @return The ID. + */ +int purple_chat_conversation_get_id(const PurpleChatConversation *chat); + +/** TODO override + * Writes to a chat. + * + * @param chat The chat. + * @param who The user who sent the message. + * @param message The message to write. + * @param flags The flags. + * @param mtime The time the message was sent. + */ +/*void purple_chat_conversation_write(PurpleChatConversation *chat, const char *who, + const char *message, PurpleConversationMessageFlags flags, + time_t mtime);*/ + +/** TODO write forward + * Sends a message to this chat conversation. + * + * @param chat The chat. + * @param message The message to send. + */ +/*void purple_chat_conversation_send(PurpleChatConversation *chat, const char *message);*/ + +/** TODO override + * Sends a message to this chat conversation with specified flags. + * + * @param chat The chat. + * @param message The message to send. + * @param flags The PurpleConversationMessageFlags flags to use. + */ +/*void purple_chat_conversation_send_with_flags(PurpleChatConversation *chat, + const char *message, PurpleConversationMessageFlags flags);*/ + +/** + * Adds a user to a chat. + * + * @param chat The chat. + * @param user The user to add. + * @param extra_msg An extra message to display with the join message. + * @param flags The users flags + * @param new_arrival Decides whether or not to show a join notice. + */ +void purple_chat_conversation_add_user(PurpleChatConversation *chat, const char *user, + const char *extra_msg, PurpleChatConversationBuddyFlags flags, + gboolean new_arrival); + +/** + * Adds a list of users to a chat. + * + * The data is copied from @a users, @a extra_msgs, and @a flags, so it is up to + * the caller to free this list after calling this function. + * + * @param chat The chat. + * @param users The list of users to add. + * @param extra_msgs An extra message to display with the join message for each + * user. This list may be shorter than @a users, in which + * case, the users after the end of extra_msgs will not have + * an extra message. By extension, this means that extra_msgs + * can simply be @c NULL and none of the users will have an + * extra message. + * @param flags The list of flags for each user. + * @param new_arrivals Decides whether or not to show join notices. + */ +void purple_chat_conversation_add_users(PurpleChatConversation *chat, + GList *users, GList *extra_msgs, GList *flags, gboolean new_arrivals); + +/** + * Renames a user in a chat. + * + * @param chat The chat. + * @param old_user The old username. + * @param new_user The new username. + */ +void purple_chat_conversation_rename_user(PurpleChatConversation *chat, + const char *old_user, const char *new_user); + +/** + * Removes a user from a chat, optionally with a reason. + * + * It is up to the developer to free this list after calling this function. + * + * @param chat The chat. + * @param user The user that is being removed. + * @param reason The optional reason given for the removal. Can be @c NULL. + */ +void purple_chat_conversation_remove_user(PurpleChatConversation *chat, + const char *user, const char *reason); + +/** + * Removes a list of users from a chat, optionally with a single reason. + * + * @param chat The chat. + * @param users The users that are being removed. + * @param reason The optional reason given for the removal. Can be @c NULL. + */ +void purple_chat_conversation_remove_users(PurpleChatConversation *chat, + GList *users, const char *reason); + +/** + * Finds a user in a chat + * + * @param chat The chat. + * @param user The user to look for. + * + * @return TRUE if the user is in the chat, FALSE if not + */ +gboolean purple_chat_conversation_find_user(PurpleChatConversation *chat, + const char *user); + +/** + * Set a users flags in a chat + * + * @param chat The chat. + * @param user The user to update. + * @param flags The new flags. + */ +void purple_chat_conversation_user_set_flags(PurpleChatConversation *chat, + const char *user, PurpleChatConversationBuddyFlags flags); + +/** + * Get the flags for a user in a chat + * + * @param chat The chat. + * @param user The user to find the flags for + * + * @return The flags for the user + */ +PurpleChatConversationBuddyFlags purple_chat_conversation_user_get_flags(PurpleChatConversation *chat, + const char *user); + +/** + * Clears all users from a chat. + * + * @param chat The chat. + */ +void purple_chat_conversation_clear_users(PurpleChatConversation *chat); + +/** + * Sets your nickname (used for hilighting) for a chat. + * + * @param chat The chat. + * @param nick The nick. + */ +void purple_chat_conversation_set_nick(PurpleChatConversation *chat, + const char *nick); + +/** + * Gets your nickname (used for hilighting) for a chat. + * + * @param chat The chat. + * @return The nick. + */ +const char *purple_chat_conversation_get_nick(PurpleChatConversation *chat); + +/** + * Lets the core know we left a chat, without destroying it. + * Called from serv_got_chat_left(). + * + * @param chat The chat. + */ +void purple_chat_conversation_leave(PurpleChatConversation *chat); + +/** + * Find a chat buddy in a chat + * + * @param chat The chat. + * @param name The name of the chat buddy to find. + */ +PurpleChatConversationBuddy *purple_chat_conversation_find_buddy(PurpleChatConversation *chat, const char *name); + +/** + * Invite a user to a chat. + * The user will be prompted to enter the user's name or a message if one is + * not given. + * + * @param chat The chat. + * @param user The user to invite to the chat. + * @param message The message to send with the invitation. + * @param confirm Prompt before sending the invitation. The user is always + * prompted if either \a user or \a message is @c NULL. + */ +void purple_chat_conversation_invite_user(PurpleChatConversation *chat, + const char *user, const char *message, gboolean confirm); + +/** + * Returns true if we're no longer in this chat, + * and just left the window open. + * + * @param chat The chat. + * + * @return @c TRUE if we left the chat already, @c FALSE if + * we're still there. + */ +gboolean purple_chat_conversation_has_left(PurpleChatConversation *chat); + +/*@}*/ + +/**************************************************************************/ +/** @name Chat Conversation Buddy API */ +/**************************************************************************/ +/*@{*/ + +/** TODO + * Returns the GType for the ChatConversationBuddy object. + */ +GType purple_chat_conversation_buddy_get_type(void); + +/** + * Get an attribute of a chat buddy + * + * @param cb The chat buddy. + * @param key The key of the attribute. + * + * @return The value of the attribute key. + */ +const char *purple_chat_conversation_buddy_get_attribute(PurpleChatConversationBuddy *cb, const char *key); + +/** + * Get the keys of all atributes of a chat buddy + * + * @param cb The chat buddy. + * + * @return A list of the attributes of a chat buddy. + */ +GList *purple_chat_conversation_buddy_get_attribute_keys(PurpleChatConversationBuddy *cb); + +/** + * Set an attribute of a chat buddy + * + * @param chat The chat. + * @param cb The chat buddy. + * @param key The key of the attribute. + * @param value The value of the attribute. + */ +void purple_chat_conversation_buddy_set_attribute(PurpleChatConversation *chat, + PurpleChatConversationBuddy *cb, const char *key, const char *value); + +/** + * Set attributes of a chat buddy + * + * @param chat The chat. + * @param cb The chat buddy. + * @param keys A GList of the keys. + * @param values A GList of the values. + */ +void +purple_chat_conversation_buddy_set_attributes(PurpleChatConversation *chat, + PurpleChatConversationBuddy *cb, GList *keys, GList *values); + +/** TODO GObjectify + * Creates a new chat buddy + * + * @param name The name. + * @param alias The alias. + * @param flags The flags. + * + * @return The new chat buddy + */ +PurpleChatConversationBuddy *purple_chat_conversation_buddy_new(const char *name, + const char *alias, PurpleChatConversationBuddyFlags flags); + +/** + * Set the UI data associated with this chat buddy. + * + * @param cb The chat buddy + * @param ui_data A pointer to associate with this chat buddy. + */ +void purple_chat_conversation_buddy_set_ui_data(PurpleChatConversationBuddy *cb, gpointer ui_data); + +/** + * Get the UI data associated with this chat buddy. + * + * @param cb The chat buddy. + * + * @return The UI data associated with this chat buddy. This is a + * convenience field provided to the UIs--it is not + * used by the libpurple core. + */ +gpointer purple_chat_conversation_buddy_get_ui_data(const PurpleChatConversationBuddy *cb); + +/** + * Get the alias of a chat buddy + * + * @param cb The chat buddy. + * + * @return The alias of the chat buddy. + */ +const char *purple_chat_conversation_buddy_get_alias(const PurpleChatConversationBuddy *cb); + +/** + * Get the name of a chat buddy + * + * @param cb The chat buddy. + * + * @return The name of the chat buddy. + */ +const char *purple_chat_conversation_buddy_get_name(const PurpleChatConversationBuddy *cb); + +/** + * Get the flags of a chat buddy. + * + * @param cb The chat buddy. + * + * @return The flags of the chat buddy. + */ +PurpleChatConversationBuddyFlags purple_chat_conversation_buddy_get_flags(const PurpleChatConversationBuddy *cb); + +/** + * Indicates if this chat buddy is on the buddy list. + * + * @param cb The chat buddy. + * + * @return TRUE if the chat buddy is on the buddy list. + */ +gboolean purple_chat_conversation_buddy_is_buddy(const PurpleChatConversationBuddy *cb); + +/** TODO finalize/dispose + * Destroys a chat buddy + * + * @param cb The chat buddy to destroy + */ +void purple_chat_conversation_buddy_destroy(PurpleChatConversationBuddy *cb); + +/*@}*/ + +G_END_DECLS + +#endif /* _PURPLE_CONVERSATION_TYPES_H_ */
--- a/libpurple/core.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/core.c Sun Jun 23 13:35:53 2013 +0530 @@ -43,7 +43,6 @@ #include "plugin.h" #include "pounce.h" #include "prefs.h" -#include "privacy.h" #include "proxy.h" #include "savedstatuses.h" #include "signals.h" @@ -139,7 +138,6 @@ purple_dbus_init(); #endif - purple_ciphers_init(); purple_cmds_init(); /* Since plugins get probed so early we should probably initialize their @@ -173,7 +171,6 @@ purple_blist_init(); purple_log_init(); purple_network_init(); - purple_privacy_init(); purple_pounces_init(); purple_proxy_init(); purple_dnsquery_init(); @@ -240,7 +237,6 @@ purple_idle_uninit(); purple_pounces_uninit(); purple_blist_uninit(); - purple_ciphers_uninit(); purple_notify_uninit(); purple_conversations_uninit(); purple_connections_uninit();
--- a/libpurple/dbus-useful.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/dbus-useful.c Sun Jun 23 13:35:53 2013 +0530 @@ -2,6 +2,7 @@ #include <glib.h> #include "dbus-useful.h" +#include "accounts.h" #include "conversation.h" #include "util.h"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/enums.c.template Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,64 @@ +/*** BEGIN file-header ***/ +/* 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 + */ +#if HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include "enums.h" + +/*** END file-header ***/ +/*** BEGIN file-production ***/ + +/* enumerations from "@filename@" */ +#include "@filename@" + +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +GType +@enum_name@_get_type(void) { + static volatile gsize g_define_type_id__volatile = 0; + + if(g_once_init_enter(&g_define_type_id__volatile)) { + static const G@Type@Value values [] = { +/*** END value-header ***/ + +/*** BEGIN value-production ***/ + { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, +/*** END value-production ***/ + +/*** BEGIN value-tail ***/ + { 0, NULL, NULL } + }; + + GType g_define_type_id = + g_@type@_register_static(g_intern_static_string("@EnumName@"), values); + g_once_init_leave(&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} + +/*** END value-tail ***/ + +/*** BEGIN file-tail ***/ +/*** END file-tail ***/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/enums.h.template Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,45 @@ +/*** BEGIN file-header ***/ +/* 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 + */ +#ifndef PURPLE_ENUM_H +#define PURPLE_ENUM_H + +#include <glib-object.h> + +G_BEGIN_DECLS +/*** END file-header ***/ + +/*** BEGIN file-production ***/ + +/* enumerations from "@filename@" */ +/*** END file-production ***/ +/*** BEGIN value-header ***/ +GType @enum_name@_get_type(void) G_GNUC_CONST; +#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type()) +/*** END value-header ***/ + +/*** BEGIN file-tail ***/ +G_END_DECLS + +#endif /* PURPLE_ENUM_H */ + +/*** END file-tail ***/ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/hash.c Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,268 @@ +/* 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 "internal.h" +#include "hash.h" +#include "debug.h" + +/****************************************************************************** + * Object Stuff + *****************************************************************************/ +static void +purple_hash_class_init(PurpleHashClass *klass) { + klass->reset = NULL; + klass->reset_state = NULL; + klass->append = NULL; + klass->digest = NULL; + klass->get_digest_size = NULL; + klass->get_block_size = NULL; + klass->get_name = NULL; +} + +/****************************************************************************** + * PurpleHash API + *****************************************************************************/ +const gchar * +purple_hash_get_name(PurpleHash *hash) { + PurpleHashClass *klass = NULL; + + g_return_val_if_fail(hash, NULL); + g_return_val_if_fail(PURPLE_IS_HASH(hash), NULL); + + klass = PURPLE_HASH_GET_CLASS(hash); + g_return_val_if_fail(klass->get_name, NULL); + + return klass->get_name(hash); +} + +GType +purple_hash_get_type(void) { + static GType type = 0; + + if(type == 0) { + static const GTypeInfo info = { + sizeof(PurpleHashClass), + NULL, + NULL, + (GClassInitFunc)purple_hash_class_init, + NULL, + NULL, + sizeof(PurpleHash), + 0, + NULL, + NULL + }; + + type = g_type_register_static(G_TYPE_OBJECT, + "PurpleHash", + &info, G_TYPE_FLAG_ABSTRACT); + } + + return type; +} + +/** + * purple_hash_reset: + * @hash: The hash to reset + * + * Resets a hash to it's default value + * + * @note If you have set an IV you will have to set it after resetting + */ +void +purple_hash_reset(PurpleHash *hash) { + PurpleHashClass *klass = NULL; + + g_return_if_fail(PURPLE_IS_HASH(hash)); + + klass = PURPLE_HASH_GET_CLASS(hash); + + if(klass && klass->reset) + klass->reset(hash); + else + purple_debug_warning("hash", "the %s hash does not implement the " + "reset method\n", + klass->get_name ? klass->get_name(hash) : ""); +} + +/** + * Resets a hash state to it's default value, but doesn't touch stateless + * configuration. + * + * That means, IV and digest context will be wiped out, but keys, ops or salt + * will remain untouched. + */ +void +purple_hash_reset_state(PurpleHash *hash) { + PurpleHashClass *klass = NULL; + + g_return_if_fail(PURPLE_IS_HASH(hash)); + + klass = PURPLE_HASH_GET_CLASS(hash); + + if(klass && klass->reset_state) + klass->reset_state(hash); + else + purple_debug_warning("hash", "the %s hash does not implement the " + "reset_state method\n", + klass->get_name ? klass->get_name(hash) : ""); +} + +/** + * purple_hash_append: + * @hash: The hash to append data to + * @data: The data to append + * @len: The length of the data + * + * Appends data to the hash + */ +void +purple_hash_append(PurpleHash *hash, const guchar *data, + size_t len) +{ + PurpleHashClass *klass = NULL; + + g_return_if_fail(PURPLE_IS_HASH(hash)); + + klass = PURPLE_HASH_GET_CLASS(hash); + + if(klass && klass->append) + klass->append(hash, data, len); + else + purple_debug_warning("hash", "the %s hash does not implement the " + "append method\n", + klass->get_name ? klass->get_name(hash) : ""); +} + +/** + * purple_hash_digest: + * @hash: The hash to digest + * @in_len: The length of the buffer + * @digest: The return buffer for the digest + * @out_len: The length of the returned value + * + * Digests a hash + * + * Return Value: TRUE if the digest was successful, FALSE otherwise. + */ +gboolean +purple_hash_digest(PurpleHash *hash, guchar digest[], size_t len) +{ + PurpleHashClass *klass = NULL; + + g_return_val_if_fail(PURPLE_IS_HASH(hash), FALSE); + + klass = PURPLE_HASH_GET_CLASS(hash); + + if(klass && klass->digest) + return klass->digest(hash, digest, len); + else + purple_debug_warning("hash", "the %s hash does not implement the " + "digest method\n", + klass->get_name ? klass->get_name(hash) : ""); + + return FALSE; +} + +/** + * purple_hash_digest_to_str: + * @hash: The hash to get a digest from + * @in_len: The length of the buffer + * @digest_s: The return buffer for the string digest + * @out_len: The length of the returned value + * + * Converts a guchar digest into a hex string + * + * Return Value: TRUE if the digest was successful, FALSE otherwise. + */ +gboolean +purple_hash_digest_to_str(PurpleHash *hash, gchar digest_s[], size_t len) +{ + /* 8k is a bit excessive, will tweak later. */ + guchar digest[BUF_LEN * 4]; + gint n = 0; + size_t digest_size; + + g_return_val_if_fail(hash, FALSE); + g_return_val_if_fail(digest_s, FALSE); + + digest_size = purple_hash_get_digest_size(hash); + + g_return_val_if_fail(digest_size <= BUF_LEN * 4, FALSE); + + if(!purple_hash_digest(hash, digest, sizeof(digest))) + return FALSE; + + /* Every digest byte occupies 2 chars + the NUL at the end. */ + g_return_val_if_fail(digest_size * 2 + 1 <= len, FALSE); + + for(n = 0; n < digest_size; n++) + sprintf(digest_s + (n * 2), "%02x", digest[n]); + + digest_s[n * 2] = '\0'; + + return TRUE; +} + +size_t +purple_hash_get_digest_size(PurpleHash *hash) +{ + PurpleHashClass *klass = NULL; + + g_return_val_if_fail(PURPLE_IS_HASH(hash), FALSE); + + klass = PURPLE_HASH_GET_CLASS(hash); + + if(klass && klass->get_digest_size) + return klass->get_digest_size(hash); + else + purple_debug_warning("hash", "the %s hash does not implement the " + "get_digest_size method\n", + klass->get_name ? klass->get_name(hash) : ""); + + return FALSE; +} + +/** + * purple_hash_get_block_size: + * @hash: The hash whose block size to get + * + * Gets the block size of a hash + * + * Return Value: The block size of the hash + */ +size_t +purple_hash_get_block_size(PurpleHash *hash) +{ + PurpleHashClass *klass = NULL; + + g_return_val_if_fail(PURPLE_IS_HASH(hash), -1); + + klass = PURPLE_HASH_GET_CLASS(hash); + + if(klass && klass->get_block_size) + return klass->get_block_size(hash); + else + purple_debug_warning("hash", "the %s hash does not implement the " + "get_block_size method\n", + klass->get_name ? klass->get_name(hash) : ""); + + return -1; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/hash.h Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,115 @@ +/** + * @file hash.h Purple Hash API + * @ingroup core + * @see @ref hash-signals + */ + +/* 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 + */ +#ifndef PURPLE_HASH_H +#define PURPLE_HASH_H + +#include <glib.h> +#include <glib-object.h> +#include <string.h> + +#include "internal.h" + +#define PURPLE_TYPE_HASH (purple_hash_get_type()) +#define PURPLE_HASH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_HASH, PurpleHash)) +#define PURPLE_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_HASH, PurpleHashClass)) +#define PURPLE_IS_HASH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_HASH)) +#define PURPLE_IS_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_HASH)) +#define PURPLE_HASH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_HASH, PurpleHashClass)) + +typedef struct _PurpleHash PurpleHash; +typedef struct _PurpleHashClass PurpleHashClass; + +/** + * PurpleHash: + * + * Purple Hash is an opaque data structure and should not be used directly. + */ +struct _PurpleHash { + /*< private >*/ + GObject gparent; + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +/** + * PurpleHashClass: + * + * The base class for all #PurpleHash's. + */ +struct _PurpleHashClass { + /*< private >*/ + GObjectClass parent_class; + + /** The reset function */ + void (*reset)(PurpleHash *hash); + + /** The reset state function */ + void (*reset_state)(PurpleHash *hash); + + /** The append data function */ + void (*append)(PurpleHash *hash, const guchar *data, size_t len); + + /** The digest function */ + gboolean (*digest)(PurpleHash *hash, guchar digest[], size_t len); + + /** The get digest size function */ + size_t (*get_digest_size)(PurpleHash *hash); + + /** The get block size function */ + size_t (*get_block_size)(PurpleHash *hash); + + /** The get hash name function */ + const gchar* (*get_name)(PurpleHash *hash); + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType purple_hash_get_type(void); + +const gchar *purple_hash_get_name(PurpleHash *hash); + +void purple_hash_reset(PurpleHash *hash); +void purple_hash_reset_state(PurpleHash *hash); + +void purple_hash_append(PurpleHash *hash, const guchar *data, size_t len); +gboolean purple_hash_digest(PurpleHash *hash, guchar digest[], size_t len); +gboolean purple_hash_digest_to_str(PurpleHash *hash, gchar digest_s[], size_t len); +size_t purple_hash_get_digest_size(PurpleHash *hash); + +size_t purple_hash_get_block_size(PurpleHash *hash); + +G_END_DECLS + +#endif /* PURPLE_HASH_H */
--- a/libpurple/internal.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/internal.h Sun Jun 23 13:35:53 2013 +0530 @@ -156,7 +156,7 @@ /* INTERNAL FUNCTIONS */ -#include "account.h" +#include "accounts.h" #include "connection.h" /* This is for the accounts code to notify the buddy icon code that
--- a/libpurple/log.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/log.h Sun Jun 23 13:35:53 2013 +0530 @@ -70,7 +70,7 @@ /** This is used to write to the log file */ gsize (*write)(PurpleLog *log, - PurpleMessageFlags type, + PurpleConversationMessageFlags type, const char *from, time_t time, const char *message); @@ -222,7 +222,7 @@ * @param message The message to log */ void purple_log_write(PurpleLog *log, - PurpleMessageFlags type, + PurpleConversationMessageFlags type, const char *from, time_t time, const char *message);
--- a/libpurple/media.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/media.c Sun Jun 23 13:35:53 2013 +0530 @@ -44,23 +44,6 @@ typedef struct _PurpleMediaSession PurpleMediaSession; /** @copydoc _PurpleMediaStream */ typedef struct _PurpleMediaStream PurpleMediaStream; -/** @copydoc _PurpleMediaClass */ -typedef struct _PurpleMediaClass PurpleMediaClass; -/** @copydoc _PurpleMediaPrivate */ -typedef struct _PurpleMediaPrivate PurpleMediaPrivate; - -/** The media class */ -struct _PurpleMediaClass -{ - GObjectClass parent_class; /**< The parent class. */ -}; - -/** The media class's private data */ -struct _PurpleMedia -{ - GObject parent; /**< The parent of this object. */ - PurpleMediaPrivate *priv; /**< The private data of this object. */ -}; struct _PurpleMediaSession {
--- a/libpurple/media.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/media.h Sun Jun 23 13:35:53 2013 +0530 @@ -41,12 +41,44 @@ #define PURPLE_IS_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_MEDIA)) #define PURPLE_MEDIA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_MEDIA, PurpleMediaClass)) -/** An opaque structure representing a media call. */ +/** A structure representing a media call. */ typedef struct _PurpleMedia PurpleMedia; #include "signals.h" #include "util.h" +#ifdef USE_VV + +/** @copydoc _PurpleMediaClass */ +typedef struct _PurpleMediaClass PurpleMediaClass; +/** @copydoc _PurpleMediaPrivate */ +typedef struct _PurpleMediaPrivate PurpleMediaPrivate; + +/** The media instance */ +struct _PurpleMedia +{ + GObject parent; /**< The parent of this object. */ + PurpleMediaPrivate *priv; /**< The private data of this object. */ + + void (*purple_reserved1)(void); + void (*purple_reserved2)(void); + void (*purple_reserved3)(void); + void (*purple_reserved4)(void); +}; + +/** The media class */ +struct _PurpleMediaClass +{ + GObjectClass parent_class; /**< The parent class. */ + + void (*purple_reserved1)(void); + void (*purple_reserved2)(void); + void (*purple_reserved3)(void); + void (*purple_reserved4)(void); +}; + +#endif + G_BEGIN_DECLS /**
--- a/libpurple/ntlm.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/ntlm.c Sun Jun 23 13:35:53 2013 +0530 @@ -28,8 +28,11 @@ #include "util.h" #include "ntlm.h" -#include "cipher.h" #include "debug.h" + +#include "ciphers/descipher.h" +#include "ciphers/md4hash.h" + #include <string.h> #define NTLM_NEGOTIATE_NTLM2_KEY 0x00080000 @@ -191,13 +194,11 @@ des_ecb_encrypt(const guint8 *plaintext, guint8 *result, const guint8 *key) { PurpleCipher *cipher; - PurpleCipherContext *context; - cipher = purple_ciphers_find_cipher("des"); - context = purple_cipher_context_new(cipher, NULL); - purple_cipher_context_set_key(context, key, 8); - purple_cipher_context_encrypt(context, plaintext, 8, result, 8); - purple_cipher_context_destroy(context); + cipher = purple_des_cipher_new(); + purple_cipher_set_key(cipher, key, 8); + purple_cipher_encrypt(cipher, plaintext, 8, result, 8); + g_object_unref(cipher); } /* @@ -273,8 +274,7 @@ unsigned char magic[] = { 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 }; unsigned char nt_hpw[21]; char nt_pw[128]; - PurpleCipher *cipher; - PurpleCipherContext *context; + PurpleHash *hash; char *tmp; int idx; gchar *ucs2le; @@ -375,11 +375,10 @@ nt_pw[2 * idx + 1] = 0; } - cipher = purple_ciphers_find_cipher("md4"); - context = purple_cipher_context_new(cipher, NULL); - purple_cipher_context_append(context, (guint8 *)nt_pw, 2 * lennt); - purple_cipher_context_digest(context, nt_hpw, sizeof(nt_hpw)); - purple_cipher_context_destroy(context); + hash = purple_md4_hash_new(); + purple_hash_append(hash, (guint8 *)nt_pw, 2 * lennt); + purple_hash_digest(hash, nt_hpw, sizeof(nt_hpw)); + g_object_unref(hash); memset(nt_hpw + 16, 0, 5); calc_resp(nt_hpw, nonce, nt_resp);
--- a/libpurple/plugins/ciphertest.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/plugins/ciphertest.c Sun Jun 23 13:35:53 2013 +0530 @@ -32,10 +32,16 @@ #include <glib.h> #include <string.h> -#include "cipher.h" #include "debug.h" #include "plugin.h" #include "version.h" +#include "util.h" + +#include "ciphers/aescipher.h" +#include "ciphers/md5hash.h" +#include "ciphers/pbkdf2cipher.h" +#include "ciphers/sha1hash.h" +#include "ciphers/sha256hash.h" struct test { const gchar *question; @@ -62,14 +68,13 @@ static void cipher_test_md5(void) { - PurpleCipher *cipher; - PurpleCipherContext *context; + PurpleHash *hash; gchar digest[33]; gboolean ret; gint i = 0; - cipher = purple_ciphers_find_cipher("md5"); - if(!cipher) { + hash = purple_md5_hash_new(); + if(!hash) { purple_debug_info("cipher-test", "could not find md5 cipher, not testing\n"); return; @@ -77,16 +82,14 @@ purple_debug_info("cipher-test", "Running md5 tests\n"); - context = purple_cipher_context_new(cipher, NULL); - while(md5_tests[i].answer) { purple_debug_info("cipher-test", "Test %02d:\n", i); purple_debug_info("cipher-test", "Testing '%s'\n", md5_tests[i].question); - purple_cipher_context_append(context, (guchar *)md5_tests[i].question, + purple_hash_append(hash, (guchar *)md5_tests[i].question, strlen(md5_tests[i].question)); - ret = purple_cipher_context_digest_to_str(context, digest, sizeof(digest)); + ret = purple_hash_digest_to_str(hash, digest, sizeof(digest)); if(!ret) { purple_debug_info("cipher-test", "failed\n"); @@ -96,11 +99,11 @@ md5_tests[i].answer); } - purple_cipher_context_reset(context, NULL); + purple_hash_reset(hash); i++; } - purple_cipher_context_destroy(context); + g_object_unref(hash); purple_debug_info("cipher-test", "md5 tests completed\n\n"); } @@ -118,14 +121,13 @@ static void cipher_test_sha1(void) { - PurpleCipher *cipher; - PurpleCipherContext *context; + PurpleHash *hash; gchar digest[41]; gint i = 0; gboolean ret; - cipher = purple_ciphers_find_cipher("sha1"); - if(!cipher) { + hash = purple_sha1_hash_new(); + if(!hash) { purple_debug_info("cipher-test", "could not find sha1 cipher, not testing\n"); return; @@ -133,8 +135,6 @@ purple_debug_info("cipher-test", "Running sha1 tests\n"); - context = purple_cipher_context_new(cipher, NULL); - while(sha1_tests[i].answer) { purple_debug_info("cipher-test", "Test %02d:\n", i); purple_debug_info("cipher-test", "Testing '%s'\n", @@ -142,7 +142,7 @@ sha1_tests[i].question : "'a'x1000, 1000 times"); if(sha1_tests[i].question) { - purple_cipher_context_append(context, (guchar *)sha1_tests[i].question, + purple_hash_append(hash, (guchar *)sha1_tests[i].question, strlen(sha1_tests[i].question)); } else { gint j; @@ -151,10 +151,10 @@ memset(buff, 'a', 1000); for(j = 0; j < 1000; j++) - purple_cipher_context_append(context, buff, 1000); + purple_hash_append(hash, buff, 1000); } - ret = purple_cipher_context_digest_to_str(context, digest, sizeof(digest)); + ret = purple_hash_digest_to_str(hash, digest, sizeof(digest)); if(!ret) { purple_debug_info("cipher-test", "failed\n"); @@ -164,11 +164,11 @@ sha1_tests[i].answer); } - purple_cipher_context_reset(context, NULL); + purple_hash_reset(hash); i++; } - purple_cipher_context_destroy(context); + g_object_unref(hash); purple_debug_info("cipher-test", "sha1 tests completed\n\n"); } @@ -192,7 +192,7 @@ purple_debug_info("cipher-test", "Running HTTP Digest tests\n"); - session_key = purple_cipher_http_digest_calculate_session_key( + session_key = purple_http_digest_calculate_session_key( algorithm, username, realm, password, nonce, client_nonce); @@ -208,7 +208,7 @@ purple_debug_info("cipher-test", "\tsession_key: Got: %s\n", session_key); purple_debug_info("cipher-test", "\tsession_key: Wanted: %s\n", "939e7578ed9e3c518a452acee763bce9"); - response = purple_cipher_http_digest_calculate_response( + response = purple_http_digest_calculate_response( algorithm, method, digest_uri, qop, entity, nonce, nonce_count, client_nonce, session_key); @@ -362,14 +362,13 @@ static void cipher_test_pbkdf2(void) { - PurpleCipherContext *context; + PurpleCipher *cipher; + PurpleHash *hash; int i = 0; gboolean fail = FALSE; purple_debug_info("cipher-test", "Running PBKDF2 tests\n"); - context = purple_cipher_context_new_by_name("pbkdf2", NULL); - while (!fail && pbkdf2_tests[i].answer) { pbkdf2_test *test = &pbkdf2_tests[i]; gchar digest[2 * 32 + 1 + 10]; @@ -384,18 +383,28 @@ test->passphrase, test->salt, test->hash, test->iter_count); - purple_cipher_context_set_option(context, "hash", (gpointer)test->hash); - purple_cipher_context_set_option(context, "iter_count", GUINT_TO_POINTER(test->iter_count)); - purple_cipher_context_set_option(context, "out_len", GUINT_TO_POINTER(test->out_len)); - purple_cipher_context_set_salt(context, (const guchar*)test->salt, test->salt ? strlen(test->salt): 0); - purple_cipher_context_set_key(context, (const guchar*)test->passphrase, strlen(test->passphrase)); + if (!strcmp(test->hash, "sha1")) + hash = purple_sha1_hash_new(); + else if (!strcmp(test->hash, "sha256")) + hash = purple_sha256_hash_new(); + else + hash = NULL; - ret = purple_cipher_context_digest_to_str(context, digest, sizeof(digest)); - purple_cipher_context_reset(context, NULL); + cipher = purple_pbkdf2_cipher_new(hash); + + g_object_set(G_OBJECT(cipher), "iter_count", GUINT_TO_POINTER(test->iter_count), NULL); + g_object_set(G_OBJECT(cipher), "out_len", GUINT_TO_POINTER(test->out_len), NULL); + purple_cipher_set_salt(cipher, (const guchar*)test->salt, test->salt ? strlen(test->salt): 0); + purple_cipher_set_key(cipher, (const guchar*)test->passphrase, strlen(test->passphrase)); + + ret = purple_cipher_digest_to_str(cipher, digest, sizeof(digest)); + purple_cipher_reset(cipher); if (!ret) { purple_debug_info("cipher-test", "\tfailed\n"); fail = TRUE; + g_object_unref(cipher); + g_object_unref(hash); continue; } @@ -431,10 +440,11 @@ purple_debug_info("cipher-test", "\twrong answer\n"); fail = TRUE; } + + g_object_unref(cipher); + g_object_unref(hash); } - purple_cipher_context_destroy(context); - if (fail) purple_debug_info("cipher-test", "PBKDF2 tests FAILED\n\n"); else @@ -466,14 +476,14 @@ static void cipher_test_aes(void) { - PurpleCipherContext *context; + PurpleCipher *cipher; int i = 0; gboolean fail = FALSE; purple_debug_info("cipher-test", "Running AES tests\n"); - context = purple_cipher_context_new_by_name("aes", NULL); - if (context == NULL) { + cipher = purple_aes_cipher_new(); + if (cipher == NULL) { purple_debug_error("cipher-test", "AES cipher not found\n"); fail = TRUE; } @@ -482,49 +492,49 @@ aes_test *test = &aes_tests[i]; gsize key_size; guchar *key; - guchar cipher[1024], decipher[1024]; + guchar cipher_s[1024], decipher_s[1024]; ssize_t cipher_len, decipher_len; gchar *cipher_b16, *deciphered; purple_debug_info("cipher-test", "Test %02d:\n", i); - purple_debug_info("cipher-test", "\tTesting '%s' (%dbit) \n", + purple_debug_info("cipher-test", "\tTesting '%s' (%lubit) \n", test->plaintext ? test->plaintext : "(null)", strlen(test->key) * 8 / 2); i++; - purple_cipher_context_reset(context, NULL); + purple_cipher_reset(cipher); if (test->iv) { gsize iv_size; guchar *iv = purple_base16_decode(test->iv, &iv_size); g_assert(iv != NULL); - purple_cipher_context_set_iv(context, iv, iv_size); + purple_cipher_set_iv(cipher, iv, iv_size); g_free(iv); } key = purple_base16_decode(test->key, &key_size); g_assert(key != NULL); - purple_cipher_context_set_key(context, key, key_size); + purple_cipher_set_key(cipher, key, key_size); g_free(key); - if (purple_cipher_context_get_key_size(context) != key_size) { + if (purple_cipher_get_key_size(cipher) != key_size) { purple_debug_info("cipher-test", "\tinvalid key size\n"); fail = TRUE; continue; } - cipher_len = purple_cipher_context_encrypt(context, + cipher_len = purple_cipher_encrypt(cipher, (const guchar*)(test->plaintext ? test->plaintext : ""), test->plaintext ? (strlen(test->plaintext) + 1) : 0, - cipher, sizeof(cipher)); + cipher_s, sizeof(cipher_s)); if (cipher_len < 0) { purple_debug_info("cipher-test", "\tencryption failed\n"); fail = TRUE; continue; } - cipher_b16 = purple_base16_encode(cipher, cipher_len); + cipher_b16 = purple_base16_encode(cipher_s, cipher_len); purple_debug_info("cipher-test", "\tGot: %s\n", cipher_b16); purple_debug_info("cipher-test", "\tWanted: %s\n", test->cipher); @@ -538,15 +548,15 @@ } g_free(cipher_b16); - decipher_len = purple_cipher_context_decrypt(context, - cipher, cipher_len, decipher, sizeof(decipher)); + decipher_len = purple_cipher_decrypt(cipher, + cipher_s, cipher_len, decipher_s, sizeof(decipher_s)); if (decipher_len < 0) { purple_debug_info("cipher-test", "\tdecryption failed\n"); fail = TRUE; continue; } - deciphered = (decipher_len > 0) ? (gchar*)decipher : NULL; + deciphered = (decipher_len > 0) ? (gchar*)decipher_s : NULL; if (g_strcmp0(deciphered, test->plaintext) != 0) { purple_debug_info("cipher-test", @@ -558,8 +568,8 @@ purple_debug_info("cipher-test", "\tTest OK\n"); } - if (context != NULL) - purple_cipher_context_destroy(context); + if (cipher != NULL) + g_object_unref(cipher); if (fail) purple_debug_info("cipher-test", "AES tests FAILED\n\n");
--- a/libpurple/plugins/keyrings/internalkeyring.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/plugins/keyrings/internalkeyring.c Sun Jun 23 13:35:53 2013 +0530 @@ -26,12 +26,15 @@ #include "internal.h" #include "account.h" -#include "cipher.h" #include "debug.h" #include "keyring.h" #include "plugin.h" #include "version.h" +#include "ciphers/aescipher.h" +#include "ciphers/pbkdf2cipher.h" +#include "ciphers/sha256hash.h" + #define INTKEYRING_NAME N_("Internal keyring") #define INTKEYRING_DESCRIPTION N_("This plugin provides the default password " \ "storage behaviour for libpurple.") @@ -147,30 +150,31 @@ static intkeyring_buff_t * intkeyring_derive_key(const gchar *passphrase, intkeyring_buff_t *salt) { - PurpleCipherContext *context; + PurpleCipher *cipher; + PurpleHash *hash; gboolean succ; intkeyring_buff_t *ret; g_return_val_if_fail(passphrase != NULL, NULL); - context = purple_cipher_context_new_by_name("pbkdf2", NULL); - g_return_val_if_fail(context != NULL, NULL); + hash = purple_sha256_hash_new(); + cipher = purple_pbkdf2_cipher_new(hash); - purple_cipher_context_set_option(context, "hash", "sha256"); - purple_cipher_context_set_option(context, "iter_count", + g_object_set(G_OBJECT(cipher), "iter_count", GUINT_TO_POINTER(purple_prefs_get_int(INTKEYRING_PREFS - "pbkdf2_iterations"))); - purple_cipher_context_set_option(context, "out_len", GUINT_TO_POINTER( - INTKEYRING_KEY_LEN)); - purple_cipher_context_set_salt(context, salt->data, salt->len); - purple_cipher_context_set_key(context, (const guchar*)passphrase, + "pbkdf2_iterations")), NULL); + g_object_set(G_OBJECT(cipher), "out_len", GUINT_TO_POINTER( + INTKEYRING_KEY_LEN), NULL); + purple_cipher_set_salt(cipher, salt->data, salt->len); + purple_cipher_set_key(cipher, (const guchar*)passphrase, strlen(passphrase)); ret = intkeyring_buff_new(g_new(guchar, INTKEYRING_KEY_LEN), INTKEYRING_KEY_LEN); - succ = purple_cipher_context_digest(context, ret->data, ret->len); + succ = purple_cipher_digest(cipher, ret->data, ret->len); - purple_cipher_context_destroy(context); + g_object_unref(cipher); + g_object_unref(hash); if (!succ) { intkeyring_buff_free(ret); @@ -229,7 +233,7 @@ static gchar * intkeyring_encrypt(intkeyring_buff_t *key, const gchar *str) { - PurpleCipherContext *context; + PurpleCipher *cipher; intkeyring_buff_t *iv; guchar plaintext[INTKEYRING_ENCRYPT_BUFF_LEN]; size_t plaintext_len, text_len, verify_len; @@ -248,30 +252,30 @@ g_return_val_if_fail(plaintext_len + verify_len <= sizeof(plaintext), NULL); - context = purple_cipher_context_new_by_name("aes", NULL); - g_return_val_if_fail(context != NULL, NULL); + cipher = purple_aes_cipher_new(); + g_return_val_if_fail(cipher != NULL, NULL); memset(plaintext, 0, plaintext_len); memcpy(plaintext, str, text_len); memcpy(plaintext + plaintext_len, INTKEYRING_VERIFY_STR, verify_len); plaintext_len += verify_len; - iv = intkeyring_gen_salt(purple_cipher_context_get_block_size(context)); - purple_cipher_context_set_iv(context, iv->data, iv->len); - purple_cipher_context_set_key(context, key->data, key->len); - purple_cipher_context_set_batch_mode(context, + iv = intkeyring_gen_salt(purple_cipher_get_block_size(cipher)); + purple_cipher_set_iv(cipher, iv->data, iv->len); + purple_cipher_set_key(cipher, key->data, key->len); + purple_cipher_set_batch_mode(cipher, PURPLE_CIPHER_BATCH_MODE_CBC); memcpy(encrypted_raw, iv->data, iv->len); - encrypted_size = purple_cipher_context_encrypt(context, + encrypted_size = purple_cipher_encrypt(cipher, plaintext, plaintext_len, encrypted_raw + iv->len, sizeof(encrypted_raw) - iv->len); encrypted_size += iv->len; memset(plaintext, 0, plaintext_len); intkeyring_buff_free(iv); - purple_cipher_context_destroy(context); + g_object_unref(cipher); if (encrypted_size < 0) return NULL; @@ -283,7 +287,7 @@ static gchar * intkeyring_decrypt(intkeyring_buff_t *key, const gchar *str) { - PurpleCipherContext *context; + PurpleCipher *cipher; guchar *encrypted_raw; gsize encrypted_size; size_t iv_len, verify_len, text_len; @@ -295,29 +299,29 @@ g_return_val_if_fail(key != NULL, NULL); g_return_val_if_fail(str != NULL, NULL); - context = purple_cipher_context_new_by_name("aes", NULL); - g_return_val_if_fail(context != NULL, NULL); + cipher = purple_aes_cipher_new(); + g_return_val_if_fail(cipher != NULL, NULL); encrypted_raw = purple_base64_decode(str, &encrypted_size); g_return_val_if_fail(encrypted_raw != NULL, NULL); - iv_len = purple_cipher_context_get_block_size(context); + iv_len = purple_cipher_get_block_size(cipher); if (encrypted_size < iv_len) { g_free(encrypted_raw); return NULL; } - purple_cipher_context_set_iv(context, encrypted_raw, iv_len); - purple_cipher_context_set_key(context, key->data, key->len); - purple_cipher_context_set_batch_mode(context, + purple_cipher_set_iv(cipher, encrypted_raw, iv_len); + purple_cipher_set_key(cipher, key->data, key->len); + purple_cipher_set_batch_mode(cipher, PURPLE_CIPHER_BATCH_MODE_CBC); - plaintext_len = purple_cipher_context_decrypt(context, + plaintext_len = purple_cipher_decrypt(cipher, encrypted_raw + iv_len, encrypted_size - iv_len, plaintext, sizeof(plaintext)); g_free(encrypted_raw); - purple_cipher_context_destroy(context); + g_object_unref(cipher); verify_len = strlen(INTKEYRING_VERIFY_STR); /* Don't remove the len > 0 check! */
--- a/libpurple/plugins/log_reader.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/plugins/log_reader.c Sun Jun 23 13:35:53 2013 +0530 @@ -986,7 +986,7 @@ if (buddy) their_name = purple_buddy_get_alias(buddy); - alias = purple_account_get_alias(log->account); + alias = purple_account_get_private_alias(log->account); if (alias) { alias_length = strlen(alias); } else { @@ -1111,8 +1111,8 @@ text = g_string_append(text, "<b>"); if (name_guessed == NAME_GUESS_ME) { - if (purple_account_get_alias(log->account)) - text = g_string_append(text, purple_account_get_alias(log->account)); + if (purple_account_get_private_alias(log->account)) + text = g_string_append(text, purple_account_get_private_alias(log->account)); else text = g_string_append(text, purple_account_get_username(log->account)); } @@ -1663,7 +1663,7 @@ const char *acct_name; line2++; line = line2; - acct_name = purple_account_get_alias(log->account); + acct_name = purple_account_get_private_alias(log->account); if (!acct_name) acct_name = purple_account_get_username(log->account); @@ -2032,7 +2032,7 @@ } } else { const char *acct_name; - acct_name = purple_account_get_alias(log->account); + acct_name = purple_account_get_private_alias(log->account); if (!acct_name) acct_name = purple_account_get_username(log->account);
--- a/libpurple/plugins/perl/common/Account.xs Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/plugins/perl/common/Account.xs Sun Jun 23 13:35:53 2013 +0530 @@ -1,6 +1,57 @@ #include "module.h" #include "../perl-handlers.h" +MODULE = Purple::Account PACKAGE = Purple::Accounts PREFIX = purple_accounts_ +PROTOTYPES: ENABLE + +void +purple_accounts_add(account) + Purple::Account account + +void +purple_accounts_remove(account) + Purple::Account account + +void +purple_accounts_delete(account) + Purple::Account account + +void +purple_accounts_reorder(account, new_index) + Purple::Account account + size_t new_index + +void +purple_accounts_get_all() +PREINIT: + GList *l; +PPCODE: + for (l = purple_accounts_get_all(); l != NULL; l = l->next) { + XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Account"))); + } + +void +purple_accounts_get_all_active() +PREINIT: + GList *list, *iter; +PPCODE: + list = purple_accounts_get_all_active(); + for (iter = list; iter != NULL; iter = iter->next) { + XPUSHs(sv_2mortal(purple_perl_bless_object(iter->data, "Purple::Account"))); + } + g_list_free(list); + +void +purple_accounts_restore_current_statuses() + +Purple::Account +purple_accounts_find(name, protocol) + const char * name + const char * protocol + +Purple::Handle +purple_accounts_get_handle() + MODULE = Purple::Account PACKAGE = Purple::Account PREFIX = purple_account_ PROTOTYPES: ENABLE @@ -16,10 +67,6 @@ username, protocol_id void -purple_account_destroy(account) - Purple::Account account - -void purple_account_connect(account) Purple::Account account @@ -54,7 +101,7 @@ purple_perl_account_set_password(account, password, func, data); void -purple_account_set_alias(account, alias) +purple_account_set_private_alias(account, alias) Purple::Account account const char * alias @@ -144,7 +191,7 @@ purple_perl_account_get_password(account, func, data); const char * -purple_account_get_alias(account) +purple_account_get_private_alias(account) Purple::Account account const char * @@ -273,53 +320,34 @@ Purple::Account account Purple::BuddyList::Group group -MODULE = Purple::Account PACKAGE = Purple::Accounts PREFIX = purple_accounts_ +MODULE = Purple::Account PACKAGE = Purple::Account::Privacy PREFIX = purple_account_privacy_ PROTOTYPES: ENABLE -void -purple_accounts_add(account) - Purple::Account account - -void -purple_accounts_remove(account) - Purple::Account account +gboolean +purple_account_privacy_permit_add(account, name, local_only) + Purple::Account account + const char * name + gboolean local_only -void -purple_accounts_delete(account) - Purple::Account account - -void -purple_accounts_reorder(account, new_index) - Purple::Account account - size_t new_index +gboolean +purple_account_privacy_permit_remove(account, name, local_only) + Purple::Account account + const char * name + gboolean local_only -void -purple_accounts_get_all() -PREINIT: - GList *l; -PPCODE: - for (l = purple_accounts_get_all(); l != NULL; l = l->next) { - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Account"))); - } +gboolean +purple_account_privacy_deny_add(account, name, local_only) + Purple::Account account + const char * name + gboolean local_only -void -purple_accounts_get_all_active() -PREINIT: - GList *list, *iter; -PPCODE: - list = purple_accounts_get_all_active(); - for (iter = list; iter != NULL; iter = iter->next) { - XPUSHs(sv_2mortal(purple_perl_bless_object(iter->data, "Purple::Account"))); - } - g_list_free(list); +gboolean +purple_account_privacy_deny_remove(account, name, local_only) + Purple::Account account + const char * name + gboolean local_only -void -purple_accounts_restore_current_statuses() - -Purple::Account -purple_accounts_find(name, protocol) - const char * name - const char * protocol - -Purple::Handle -purple_accounts_get_handle() +gboolean +purple_account_privacy_check(account, who) + Purple::Account account + const char * who
--- a/libpurple/plugins/perl/common/Cipher.xs Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/plugins/perl/common/Cipher.xs Sun Jun 23 13:35:53 2013 +0530 @@ -6,7 +6,6 @@ BOOT: { HV *stash = gv_stashpv("Purple::Cipher::BatchMode", 1); - HV *cipher_caps = gv_stashpv("Purple::Cipher::Caps", 1); static const constiv *civ, const_iv[] = { #define const_iv(name) {#name, (IV)PURPLE_CIPHER_BATCH_MODE_##name} @@ -15,74 +14,16 @@ #undef const_iv }; - static const constiv bm_const_iv[] = { -#define const_iv(name) {#name, (IV)PURPLE_CIPHER_CAPS_##name} - const_iv(SET_OPT), - const_iv(GET_OPT), - const_iv(INIT), - const_iv(RESET), - const_iv(UNINIT), - const_iv(SET_IV), - const_iv(APPEND), - const_iv(DIGEST), - const_iv(GET_DIGEST_SIZE), - const_iv(ENCRYPT), - const_iv(DECRYPT), - const_iv(SET_SALT), - const_iv(GET_SALT_SIZE), - const_iv(SET_KEY), - const_iv(GET_KEY_SIZE), - const_iv(SET_BATCH_MODE), - const_iv(GET_BATCH_MODE), - const_iv(GET_BLOCK_SIZE), - const_iv(UNKNOWN), -#undef const_iv - }; - for (civ = const_iv + sizeof(const_iv) / sizeof(const_iv[0]); civ-- > const_iv; ) newCONSTSUB(stash, (char *)civ->name, newSViv(civ->iv)); - - for (civ = bm_const_iv + sizeof(bm_const_iv) / sizeof(bm_const_iv[0]); civ-- > bm_const_iv; ) - newCONSTSUB(cipher_caps, (char *)civ->name, newSViv(civ->iv)); } const gchar * purple_cipher_get_name(cipher) Purple::Cipher cipher -guint -purple_cipher_get_capabilities(cipher) - Purple::Cipher cipher - -gboolean -purple_cipher_digest_region(name, data_sv, data_len, digest) - const gchar *name - SV *data_sv - size_t data_len - SV *digest - PREINIT: - guchar *buff = NULL; - guchar *data = NULL; - ssize_t digest_len; - size_t max_digest_len = 100; - CODE: - data = (guchar *)SvPV(data_sv, data_len); - SvUPGRADE(digest, SVt_PV); - buff = (guchar *)SvGROW(digest, max_digest_len); - digest_len = purple_cipher_digest_region(name, data, data_len, buff, max_digest_len); - if(digest_len == -1) { - SvSetSV_nosteal(digest, &PL_sv_undef); - RETVAL = 0; - } else { - SvCUR_set(digest, digest_len); - SvPOK_only(digest); - RETVAL = 1; - } - OUTPUT: - RETVAL - gchar_own* -purple_cipher_http_digest_calculate_response(algorithm, method, digest_uri, qop, entity, nonce, nonce_count, client_nonce, session_key) +purple_http_digest_calculate_response(algorithm, method, digest_uri, qop, entity, nonce, nonce_count, client_nonce, session_key) const gchar* algorithm const gchar* method const gchar* digest_uri @@ -94,7 +35,7 @@ const gchar* session_key gchar_own* -purple_cipher_http_digest_calculate_session_key(algorithm, username, realm, password, nonce, client_nonce) +purple_http_digest_calculate_session_key(algorithm, username, realm, password, nonce, client_nonce) const gchar* algorithm const gchar* username const gchar* realm @@ -102,89 +43,30 @@ const gchar* nonce const gchar* client_nonce -MODULE = Purple::Cipher PACKAGE = Purple::Ciphers PREFIX = purple_ciphers_ -PROTOTYPES: ENABLE - -Purple::Cipher -purple_ciphers_find_cipher(name) - gchar * name - -Purple::Cipher -purple_ciphers_register_cipher(name, ops) - gchar * name - Purple::Cipher::Ops ops - -gboolean -purple_ciphers_unregister_cipher(cipher) +void +purple_cipher_reset(cipher) Purple::Cipher cipher void -purple_ciphers_get_ciphers() -PREINIT: - GList *l; -PPCODE: - for (l = purple_ciphers_get_ciphers(); l != NULL; l = l->next) { - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Cipher"))); - } - -Purple::Handle -purple_ciphers_get_handle() - -MODULE = Purple::Cipher PACKAGE = Purple::Cipher::Context PREFIX = purple_cipher_context_ -PROTOTYPES: ENABLE - -void -purple_cipher_context_set_option(context, name, value) - Purple::Cipher::Context context - gchar *name - gpointer value - -gpointer -purple_cipher_context_get_option(context, name) - Purple::Cipher::Context context - gchar *name - -Purple::Cipher::Context -purple_cipher_context_new(klass, cipher, extra = NULL) - Purple::Cipher cipher - void *extra - C_ARGS: cipher, extra - -Purple::Cipher::Context -purple_cipher_context_new_by_name(klass, name, extra = NULL) - gchar *name - void *extra - C_ARGS: name, extra - -void -purple_cipher_context_reset(context, extra = NULL) - Purple::Cipher::Context context - gpointer extra - -void -purple_cipher_context_destroy(context) - Purple::Cipher::Context context - -void -purple_cipher_context_set_iv(Purple::Cipher::Context context, guchar *iv, size_t length(iv)) +purple_cipher_set_iv(Purple::Cipher cipher, guchar *iv, size_t length(iv)) PROTOTYPE: $$ void -purple_cipher_context_append(Purple::Cipher::Context context, guchar *data, size_t length(data)) +purple_cipher_append(Purple::Cipher cipher, guchar *data, size_t length(data)) PROTOTYPE: $$ gboolean -purple_cipher_context_digest(context, digest) - Purple::Cipher::Context context +purple_cipher_digest(cipher, digest) + Purple::Cipher cipher SV *digest PREINIT: guchar *buff = NULL; size_t digest_size; CODE: - digest_size = purple_cipher_context_get_digest_size(context); + digest_size = purple_cipher_get_digest_size(cipher); SvUPGRADE(digest, SVt_PV); buff = (guchar *)SvGROW(digest, digest_size); - if (purple_cipher_context_digest(context, buff, digest_size)) { + if (purple_cipher_digest(cipher, buff, digest_size)) { SvCUR_set(digest, digest_size); SvPOK_only(digest); RETVAL = 1; @@ -196,18 +78,18 @@ RETVAL gboolean -purple_cipher_context_digest_to_str(context, digest_s) - Purple::Cipher::Context context +purple_cipher_digest_to_str(cipher, digest_s) + Purple::Cipher cipher SV *digest_s PREINIT: gchar *buff = NULL; size_t digest_size, str_len; CODE: - digest_size = purple_cipher_context_get_digest_size(context); + digest_size = purple_cipher_get_digest_size(cipher); str_len = 2 * digest_size; SvUPGRADE(digest_s, SVt_PV); buff = SvGROW(digest_s, str_len + 1); - if (purple_cipher_context_digest_to_str(context, buff, str_len + 1)) { + if (purple_cipher_digest_to_str(cipher, buff, str_len + 1)) { SvCUR_set(digest_s, str_len); SvPOK_only(digest_s); RETVAL = 1; @@ -219,8 +101,8 @@ RETVAL gboolean -purple_cipher_context_encrypt(context, input, output) - Purple::Cipher::Context context +purple_cipher_encrypt(cipher, input, output) + Purple::Cipher cipher SV *input SV *output PREINIT: @@ -230,10 +112,10 @@ guchar *data = NULL; CODE: data = (guchar *)SvPV(input, input_len); - output_len = input_len + purple_cipher_context_get_block_size(context); + output_len = input_len + purple_cipher_get_block_size(cipher); SvUPGRADE(output, SVt_PV); buff = (guchar *)SvGROW(output, output_len); - ret = purple_cipher_context_encrypt(context, data, input_len, buff, output_len); + ret = purple_cipher_encrypt(cipher, data, input_len, buff, output_len); if (ret >= 0) { RETVAL = 1; SvPOK_only(output); @@ -246,8 +128,8 @@ RETVAL gboolean -purple_cipher_context_decrypt(context, input, output) - Purple::Cipher::Context context +purple_cipher_decrypt(cipher, input, output) + Purple::Cipher cipher SV *input SV *output PREINIT: @@ -257,10 +139,10 @@ guchar *data = NULL; CODE: data = (guchar *)SvPV(input, input_len); - output_len = input_len + purple_cipher_context_get_block_size(context); + output_len = input_len + purple_cipher_get_block_size(cipher); SvUPGRADE(output, SVt_PV); buff = (guchar *)SvGROW(output, output_len); - ret = purple_cipher_context_decrypt(context, data, input_len, buff, output_len); + ret = purple_cipher_decrypt(cipher, data, input_len, buff, output_len); if (ret >= 0) { RETVAL = 1; SvPOK_only(output); @@ -273,44 +155,68 @@ RETVAL void -purple_cipher_context_set_salt(context, salt, len) - Purple::Cipher::Context context +purple_cipher_set_salt(cipher, salt, len) + Purple::Cipher cipher guchar *salt size_t len -size_t -purple_cipher_context_get_salt_size(context) - Purple::Cipher::Context context - void -purple_cipher_context_set_key(context, key, len) - Purple::Cipher::Context context +purple_cipher_set_key(cipher, key, len) + Purple::Cipher cipher guchar *key size_t len size_t -purple_cipher_context_get_key_size(context) - Purple::Cipher::Context context - -void -purple_cipher_context_set_data(context, data) - Purple::Cipher::Context context - gpointer data - -gpointer -purple_cipher_context_get_data(context) - Purple::Cipher::Context context +purple_cipher_get_key_size(cipher) + Purple::Cipher cipher Purple::Cipher::BatchMode -purple_cipher_context_get_batch_mode(context) - Purple::Cipher::Context context +purple_cipher_get_batch_mode(cipher) + Purple::Cipher cipher size_t -purple_cipher_context_get_block_size(context) - Purple::Cipher::Context context +purple_cipher_get_block_size(cipher) + Purple::Cipher cipher void -purple_cipher_context_set_batch_mode(context, mode) - Purple::Cipher::Context context +purple_cipher_set_batch_mode(cipher, mode) + Purple::Cipher cipher Purple::Cipher::BatchMode mode +MODULE = Purple::Cipher PACKAGE = Purple::AESCipher PREFIX = purple_aes_cipher_ +PROTOTYPES: ENABLE + +Purple::Cipher +purple_aes_cipher_new() + +MODULE = Purple::Cipher PACKAGE = Purple::DES3Cipher PREFIX = purple_des3_cipher_ +PROTOTYPES: ENABLE + +Purple::Cipher +purple_des3_cipher_new() + +MODULE = Purple::Cipher PACKAGE = Purple::DESCipher PREFIX = purple_des_cipher_ +PROTOTYPES: ENABLE + +Purple::Cipher +purple_des_cipher_new() + +MODULE = Purple::Cipher PACKAGE = Purple::HMACCipher PREFIX = purple_hmac_cipher_ +PROTOTYPES: ENABLE + +Purple::Cipher +purple_hmac_cipher_new(hash) + Purple::Hash hash + +MODULE = Purple::Cipher PACKAGE = Purple::PBKDF2Cipher PREFIX = purple_pbkdf2_cipher_ +PROTOTYPES: ENABLE + +Purple::Cipher +purple_pbkdf2_cipher_new(hash) + Purple::Hash hash + +MODULE = Purple::Cipher PACKAGE = Purple::RC4Cipher PREFIX = purple_rc4_cipher_ +PROTOTYPES: ENABLE + +Purple::Cipher +purple_rc4_cipher_new()
--- a/libpurple/plugins/perl/common/Conversation.xs Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/plugins/perl/common/Conversation.xs Sun Jun 23 13:35:53 2013 +0530 @@ -5,23 +5,14 @@ BOOT: { - HV *type_stash = gv_stashpv("Purple::Conversation::Type", 1); - HV *update_stash = gv_stashpv("Purple::Conversation::Update::Type", 1); - HV *typing_stash = gv_stashpv("Purple::Conversation::TypingState", 1); - HV *flags_stash = gv_stashpv("Purple::Conversation::Flags", 1); - HV *cbflags_stash = gv_stashpv("Purple::Conversation::ChatBuddy::Flags", 1); + HV *update_stash = gv_stashpv("Purple::Conversation::UpdateType", 1); + HV *typing_stash = gv_stashpv("Purple::IMConversation::TypingState", 1); + HV *flags_stash = gv_stashpv("Purple::Conversation::MessageFlags", 1); + HV *cbflags_stash = gv_stashpv("Purple::ChatConversation::Buddy::Flags", 1); - static const constiv *civ, type_const_iv[] = { -#define const_iv(name) {#name, (IV)PURPLE_CONV_TYPE_##name} - const_iv(UNKNOWN), - const_iv(IM), - const_iv(CHAT), - const_iv(MISC), - const_iv(ANY), - }; - static const constiv update_const_iv[] = { + static const constiv *civ, update_const_iv[] = { #undef const_iv -#define const_iv(name) {#name, (IV)PURPLE_CONV_UPDATE_##name} +#define const_iv(name) {#name, (IV)PURPLE_CONVERSATION_UPDATE_##name} const_iv(ADD), const_iv(REMOVE), const_iv(ACCOUNT), @@ -41,14 +32,14 @@ }; static const constiv typing_const_iv[] = { #undef const_iv -#define const_iv(name) {#name, (IV)PURPLE_##name} +#define const_iv(name) {#name, (IV)PURPLE_IM_CONVERSATION_##name} const_iv(NOT_TYPING), const_iv(TYPING), const_iv(TYPED), }; static const constiv flags_const_iv[] = { #undef const_iv -#define const_iv(name) {#name, (IV)PURPLE_MESSAGE_##name} +#define const_iv(name) {#name, (IV)PURPLE_CONVERSATION_MESSAGE_##name} const_iv(SEND), const_iv(RECV), const_iv(SYSTEM), @@ -66,7 +57,7 @@ }; static const constiv cbflags_const_iv[] = { #undef const_iv -#define const_iv(name) {#name, (IV)PURPLE_CBFLAGS_##name} +#define const_iv(name) {#name, (IV)PURPLE_CHAT_CONVERSATION_BUDDY_##name} const_iv(NONE), const_iv(VOICE), const_iv(HALFOP), @@ -75,9 +66,6 @@ const_iv(TYPING), }; - for (civ = type_const_iv + sizeof(type_const_iv) / sizeof(type_const_iv[0]); civ-- > type_const_iv; ) - newCONSTSUB(type_stash, (char *)civ->name, newSViv(civ->iv)); - for (civ = update_const_iv + sizeof(update_const_iv) / sizeof(update_const_iv[0]); civ-- > update_const_iv; ) newCONSTSUB(update_stash, (char *)civ->name, newSViv(civ->iv)); @@ -91,55 +79,61 @@ newCONSTSUB(cbflags_stash, (char *)civ->name, newSViv(civ->iv)); } -void -purple_get_ims() -PREINIT: - GList *l; -PPCODE: - for (l = purple_get_ims(); l != NULL; l = l->next) { - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Conversation"))); - } - -void -purple_get_conversations() -PREINIT: - GList *l; -PPCODE: - for (l = purple_get_conversations(); l != NULL; l = l->next) { - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Conversation"))); - } - -void -purple_get_chats() -PREINIT: - GList *l; -PPCODE: - for (l = purple_get_chats(); l != NULL; l = l->next) { - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Conversation"))); - } - -Purple::Conversation -purple_find_conversation_with_account(type, name, account) - Purple::ConversationType type - const char *name - Purple::Account account - MODULE = Purple::Conversation PACKAGE = Purple::Conversations PREFIX = purple_conversations_ PROTOTYPES: ENABLE Purple::Handle purple_conversations_get_handle() -MODULE = Purple::Conversation PACKAGE = Purple::Conversation PREFIX = purple_conversation_ -PROTOTYPES: ENABLE +Purple::ChatConversation +purple_conversations_find_chat(gc, id) + Purple::Connection gc + int id + +void +purple_conversations_get_ims() +PREINIT: + GList *l; +PPCODE: + for (l = purple_conversations_get_ims(); l != NULL; l = l->next) { + XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Conversation"))); + } + +void +purple_conversations_get() +PREINIT: + GList *l; +PPCODE: + for (l = purple_conversations_get(); l != NULL; l = l->next) { + XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Conversation"))); + } void -purple_conversation_destroy(conv) - Purple::Conversation conv +purple_conversations_get_chats() +PREINIT: + GList *l; +PPCODE: + for (l = purple_conversations_get_chats(); l != NULL; l = l->next) { + XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Conversation"))); + } + +Purple::Conversation +purple_conversations_find_with_account(name, account) + const char *name + Purple::Account account -Purple::ConversationType -purple_conversation_get_type(conv) - Purple::Conversation conv +Purple::ChatConversation +purple_conversations_find_chat_with_account(name, account) + const char *name + Purple::Account account + +Purple::IMConversation +purple_conversations_find_im_with_account(name, account) + const char *name + Purple::Account account + +MODULE = Purple::Conversation PACKAGE = Purple::Conversation PREFIX = purple_conversation_ +PROTOTYPES: ENABLE Purple::Account purple_conversation_get_account(conv) @@ -180,14 +174,6 @@ purple_conversation_is_logging(conv) Purple::Conversation conv -Purple::Conversation::IM -purple_conversation_get_im_data(conv) - Purple::Conversation conv - -Purple::Conversation::Chat -purple_conversation_get_chat_data(conv) - Purple::Conversation conv - gpointer purple_conversation_get_data(conv, key) Purple::Conversation conv @@ -204,15 +190,7 @@ void purple_conversation_update(conv, type) Purple::Conversation conv - Purple::ConvUpdateType type - -Purple::Conversation -purple_conversation_new(class, type, account, name) - Purple::ConversationType type - Purple::Account account - const char *name - C_ARGS: - type, account, name + Purple::Conversation::UpdateType type void purple_conversation_set_account(conv, account); @@ -224,9 +202,28 @@ Purple::Conversation conv const char *who const char *message - Purple::MessageFlags flags + Purple::Conversation::MessageFlags flags + time_t mtime + +void +purple_conversation_write_message(conv, who, message, flags, mtime) + Purple::Conversation conv + const char *who + const char *message + Purple::Conversation::MessageFlags flags time_t mtime +void +purple_conversation_send(conv, message) + Purple::Conversation conv + const char *message + +void +purple_conversation_send_message(conv, message, flags) + Purple::Conversation conv + const char *message + Purple::Conversation::MessageFlags flags + gboolean purple_conversation_do_command(conv, cmdline, markup, error) Purple::Conversation conv @@ -234,132 +231,122 @@ const char *markup char **error -MODULE = Purple::Conversation PACKAGE = Purple::Conversation::IM PREFIX = purple_conv_im_ +MODULE = Purple::Conversation PACKAGE = Purple::IMConversation PREFIX = purple_im_conversation_ PROTOTYPES: ENABLE Purple::Conversation -purple_conv_im_get_conversation(im) - Purple::Conversation::IM im +purple_im_conversation_new(class, account, name) + Purple::Account account + const char *name + C_ARGS: + account, name void -purple_conv_im_set_icon(im, icon) - Purple::Conversation::IM im +purple_im_conversation_set_icon(im, icon) + Purple::IMConversation im Purple::Buddy::Icon icon Purple::Buddy::Icon -purple_conv_im_get_icon(im) - Purple::Conversation::IM im +purple_im_conversation_get_icon(im) + Purple::IMConversation im void -purple_conv_im_set_typing_state(im, state) - Purple::Conversation::IM im - Purple::TypingState state +purple_im_conversation_set_typing_state(im, state) + Purple::IMConversation im + Purple::IMConversation::TypingState state -Purple::TypingState -purple_conv_im_get_typing_state(im) - Purple::Conversation::IM im +Purple::IMConversation::TypingState +purple_im_conversation_get_typing_state(im) + Purple::IMConversation im void -purple_conv_im_start_typing_timeout(im, timeout) - Purple::Conversation::IM im +purple_im_conversation_start_typing_timeout(im, timeout) + Purple::IMConversation im int timeout void -purple_conv_im_stop_typing_timeout(im) - Purple::Conversation::IM im +purple_im_conversation_stop_typing_timeout(im) + Purple::IMConversation im guint -purple_conv_im_get_typing_timeout(im) - Purple::Conversation::IM im +purple_im_conversation_get_typing_timeout(im) + Purple::IMConversation im void -purple_conv_im_set_type_again(im, val) - Purple::Conversation::IM im +purple_im_conversation_set_type_again(im, val) + Purple::IMConversation im time_t val time_t -purple_conv_im_get_type_again(im) - Purple::Conversation::IM im - -void -purple_conv_im_start_send_typed_timeout(im) - Purple::Conversation::IM im +purple_im_conversation_get_type_again(im) + Purple::IMConversation im void -purple_conv_im_stop_send_typed_timeout(im) - Purple::Conversation::IM im - -guint -purple_conv_im_get_send_typed_timeout(im) - Purple::Conversation::IM im - -void -purple_conv_im_update_typing(im) - Purple::Conversation::IM im +purple_im_conversation_start_send_typed_timeout(im) + Purple::IMConversation im void -purple_conv_im_send(im, message) - Purple::Conversation::IM im - const char *message +purple_im_conversation_stop_send_typed_timeout(im) + Purple::IMConversation im + +guint +purple_im_conversation_get_send_typed_timeout(im) + Purple::IMConversation im void -purple_conv_im_send_with_flags(im, message, flags) - Purple::Conversation::IM im - const char *message - Purple::MessageFlags flags +purple_im_conversation_update_typing(im) + Purple::IMConversation im -void -purple_conv_im_write(im, who, message, flags, mtime) - Purple::Conversation::IM im - const char *who - const char *message - Purple::MessageFlags flags - time_t mtime - -MODULE = Purple::Conversation PACKAGE = Purple::Conversation PREFIX = purple_conv_ +MODULE = Purple::Conversation PACKAGE = Purple::Conversation::Helper PREFIX = purple_conversation_helper_ PROTOTYPES: ENABLE gboolean -purple_conv_present_error(who, account, what) +purple_conversation_helper_present_error(who, account, what) const char *who Purple::Account account const char *what +MODULE = Purple::Conversation PACKAGE = Purple::Conversation PREFIX = purple_conversation_ +PROTOTYPES: ENABLE + void -purple_conv_custom_smiley_close(conv, smile) +purple_conversation_custom_smiley_close(conv, smile) Purple::Conversation conv const char *smile -MODULE = Purple::Conversation PACKAGE = Purple::Conversation::Chat PREFIX = purple_conv_chat_ +MODULE = Purple::Conversation PACKAGE = Purple::ChatConversation PREFIX = purple_chat_conversation_ PROTOTYPES: ENABLE Purple::Conversation -purple_conv_chat_get_conversation(chat) - Purple::Conversation::Chat chat +purple_chat_conversation_new(class, account, name) + Purple::Account account + const char *name + C_ARGS: + account, name void -purple_conv_chat_get_users(chat) - Purple::Conversation::Chat chat +purple_chat_conversation_get_users(chat) + Purple::ChatConversation chat PREINIT: GList *l; PPCODE: - for (l = purple_conv_chat_get_users(chat); l != NULL; l = l->next) { + for (l = purple_chat_conversation_get_users(chat); l != NULL; l = l->next) { XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::ListEntry"))); } void -purple_conv_chat_ignore(chat, name) - Purple::Conversation::Chat chat +purple_chat_conversation_ignore(chat, name) + Purple::ChatConversation chat const char *name void -purple_conv_chat_unignore(chat, name) - Purple::Conversation::Chat chat +purple_chat_conversation_unignore(chat, name) + Purple::ChatConversation chat const char *name void -purple_conv_chat_set_ignored(chat, ignored) - Purple::Conversation::Chat chat +purple_chat_conversation_set_ignored(chat, ignored) + Purple::ChatConversation chat SV * ignored PREINIT: GList *l, *t_GL; @@ -371,55 +358,36 @@ for (i = 0; i <= t_len; i++) t_GL = g_list_append(t_GL, SvPVutf8_nolen(*av_fetch((AV *)SvRV(ignored), i, 0))); - for (l = purple_conv_chat_set_ignored(chat, t_GL); l != NULL; l = l->next) { + for (l = purple_chat_conversation_set_ignored(chat, t_GL); l != NULL; l = l->next) { XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::ListEntry"))); } void -purple_conv_chat_get_ignored(chat) - Purple::Conversation::Chat chat +purple_chat_conversation_get_ignored(chat) + Purple::ChatConversation chat PREINIT: GList *l; PPCODE: - for (l = purple_conv_chat_get_ignored(chat); l != NULL; l = l->next) { + for (l = purple_chat_conversation_get_ignored(chat); l != NULL; l = l->next) { XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::ListEntry"))); } const char * -purple_conv_chat_get_topic(chat) - Purple::Conversation::Chat chat +purple_chat_conversation_get_topic(chat) + Purple::ChatConversation chat void -purple_conv_chat_set_id(chat, id) - Purple::Conversation::Chat chat +purple_chat_conversation_set_id(chat, id) + Purple::ChatConversation chat int id int -purple_conv_chat_get_id(chat) - Purple::Conversation::Chat chat - -void -purple_conv_chat_send(chat, message) - Purple::Conversation::Chat chat - const char * message +purple_chat_conversation_get_id(chat) + Purple::ChatConversation chat void -purple_conv_chat_send_with_flags(chat, message, flags) - Purple::Conversation::Chat chat - const char * message - Purple::MessageFlags flags - -void -purple_conv_chat_write(chat, who, message, flags, mtime) - Purple::Conversation::Chat chat - const char *who - const char *message - Purple::MessageFlags flags - time_t mtime - -void -purple_conv_chat_add_users(chat, users, extra_msgs, flags, new_arrivals) - Purple::Conversation::Chat chat +purple_chat_conversation_add_users(chat, users, extra_msgs, flags, new_arrivals) + Purple::ChatConversation chat SV * users SV * extra_msgs SV * flags @@ -446,48 +414,43 @@ for (i = 0; i <= t_len; i++) t_GL_extra_msgs = g_list_append(t_GL_extra_msgs, SvPVutf8_nolen(*av_fetch((AV *)SvRV(extra_msgs), i, 0))); - purple_conv_chat_add_users(chat, t_GL_users, t_GL_extra_msgs, t_GL_flags, new_arrivals); + purple_chat_conversation_add_users(chat, t_GL_users, t_GL_extra_msgs, t_GL_flags, new_arrivals); g_list_free(t_GL_users); g_list_free(t_GL_extra_msgs); g_list_free(t_GL_flags); gboolean -purple_conv_chat_find_user(chat, user) - Purple::Conversation::Chat chat +purple_chat_conversation_find_user(chat, user) + Purple::ChatConversation chat const char * user -void purple_conv_chat_clear_users(chat) - Purple::Conversation::Chat chat +void purple_chat_conversation_clear_users(chat) + Purple::ChatConversation chat -void purple_conv_chat_set_nick(chat, nick) - Purple::Conversation::Chat chat +void purple_chat_conversation_set_nick(chat, nick) + Purple::ChatConversation chat const char * nick const char * -purple_conv_chat_get_nick(chat) - Purple::Conversation::Chat chat +purple_chat_conversation_get_nick(chat) + Purple::ChatConversation chat -Purple::Conversation -purple_find_chat(gc, id) - Purple::Connection gc - int id +void purple_chat_conversation_leave(chat) + Purple::ChatConversation chat -void purple_conv_chat_left(chat) - Purple::Conversation::Chat chat +gboolean purple_chat_conversation_has_left(chat) + Purple::ChatConversation chat -gboolean purple_conv_chat_has_left(chat) - Purple::Conversation::Chat chat - -Purple::Conversation::ChatBuddy -purple_conv_chat_cb_find(chat, name) - Purple::Conversation::Chat chat +Purple::ChatConversation::Buddy +purple_chat_conversation_find_buddy(chat, name) + Purple::ChatConversation chat const char *name const char * -purple_conv_chat_cb_get_name(cb) - Purple::Conversation::ChatBuddy cb +purple_chat_conversation_buddy_get_name(cb) + Purple::ChatConversation::Buddy cb void -purple_conv_chat_cb_destroy(cb); - Purple::Conversation::ChatBuddy cb +purple_chat_conversation_buddy_destroy(cb); + Purple::ChatConversation::Buddy cb
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/plugins/perl/common/Hash.xs Sun Jun 23 13:35:53 2013 +0530 @@ -0,0 +1,110 @@ +#include "module.h" + +MODULE = Purple::Hash PACKAGE = Purple::Hash PREFIX = purple_hash_ +PROTOTYPES: ENABLE + +const gchar * +purple_hash_get_name(hash) + Purple::Hash hash + +gchar_own* +purple_http_digest_calculate_response(algorithm, method, digest_uri, qop, entity, nonce, nonce_count, client_nonce, session_key) + const gchar* algorithm + const gchar* method + const gchar* digest_uri + const gchar* qop + const gchar* entity + const gchar* nonce + const gchar* nonce_count + const gchar* client_nonce + const gchar* session_key + +gchar_own* +purple_http_digest_calculate_session_key(algorithm, username, realm, password, nonce, client_nonce) + const gchar* algorithm + const gchar* username + const gchar* realm + const gchar* password + const gchar* nonce + const gchar* client_nonce + +void +purple_hash_reset(hash) + Purple::Hash hash + +void +purple_hash_append(Purple::Hash hash, guchar *data, size_t length(data)) + PROTOTYPE: $$ + +gboolean +purple_hash_digest(hash, digest) + Purple::Hash hash + SV *digest + PREINIT: + guchar *buff = NULL; + size_t digest_size; + CODE: + digest_size = purple_hash_get_digest_size(hash); + SvUPGRADE(digest, SVt_PV); + buff = (guchar *)SvGROW(digest, digest_size); + if (purple_hash_digest(hash, buff, digest_size)) { + SvCUR_set(digest, digest_size); + SvPOK_only(digest); + RETVAL = 1; + } else { + SvSetSV_nosteal(digest, &PL_sv_undef); + RETVAL = 0; + } + OUTPUT: + RETVAL + +gboolean +purple_hash_digest_to_str(hash, digest_s) + Purple::Hash hash + SV *digest_s + PREINIT: + gchar *buff = NULL; + size_t digest_size, str_len; + CODE: + digest_size = purple_hash_get_digest_size(hash); + str_len = 2 * digest_size; + SvUPGRADE(digest_s, SVt_PV); + buff = SvGROW(digest_s, str_len + 1); + if (purple_hash_digest_to_str(hash, buff, str_len + 1)) { + SvCUR_set(digest_s, str_len); + SvPOK_only(digest_s); + RETVAL = 1; + } else { + SvSetSV_nosteal(digest_s, &PL_sv_undef); + RETVAL = 0; + } + OUTPUT: + RETVAL + +size_t +purple_hash_get_block_size(hash) + Purple::Hash hash + +MODULE = Purple::Hash PACKAGE = Purple::MD4Hash PREFIX = purple_md4_hash_ +PROTOTYPES: ENABLE + +Purple::Hash +purple_md4_hash_new() + +MODULE = Purple::Hash PACKAGE = Purple::MD5Hash PREFIX = purple_md5_hash_ +PROTOTYPES: ENABLE + +Purple::Hash +purple_md5_hash_new() + +MODULE = Purple::Hash PACKAGE = Purple::SHA1Hash PREFIX = purple_sha1_hash_ +PROTOTYPES: ENABLE + +Purple::Hash +purple_sha1_hash_new() + +MODULE = Purple::Hash PACKAGE = Purple::SHA256Hash PREFIX = purple_sha256_hash_ +PROTOTYPES: ENABLE + +Purple::Hash +purple_sha256_hash_new()
--- a/libpurple/plugins/perl/common/MANIFEST Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/plugins/perl/common/MANIFEST Sun Jun 23 13:35:53 2013 +0530 @@ -8,6 +8,7 @@ Conversation.xs Debug.xs FT.xs +Hash.xs ImgStore.xs Log.xs Makefile.PL @@ -17,7 +18,6 @@ PluginPref.xs Pounce.xs Prefs.xs -Privacy.xs Proxy.xs Prpl.xs Purple.pm
--- a/libpurple/plugins/perl/common/Makefile.mingw Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/plugins/perl/common/Makefile.mingw Sun Jun 23 13:35:53 2013 +0530 @@ -48,6 +48,7 @@ Core.xs \ Debug.xs \ FT.xs \ + Hash.xs \ Idle.xs \ Purple.xs \ ImgStore.xs \ @@ -58,7 +59,6 @@ PluginPref.xs \ Pounce.xs \ Prefs.xs \ - Privacy.xs \ Proxy.xs \ Prpl.xs \ Request.xs \
--- a/libpurple/plugins/perl/common/Privacy.xs Sun Jun 23 02:43:06 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -#include "module.h" - -MODULE = Purple::Privacy PACKAGE = Purple::Privacy PREFIX = purple_privacy_ -PROTOTYPES: ENABLE - -gboolean -purple_privacy_permit_add(account, name, local_only) - Purple::Account account - const char * name - gboolean local_only - -gboolean -purple_privacy_permit_remove(account, name, local_only) - Purple::Account account - const char * name - gboolean local_only - -gboolean -purple_privacy_deny_add(account, name, local_only) - Purple::Account account - const char * name - gboolean local_only - -gboolean -purple_privacy_deny_remove(account, name, local_only) - Purple::Account account - const char * name - gboolean local_only - -gboolean -purple_privacy_check(account, who) - Purple::Account account - const char * who
--- a/libpurple/plugins/perl/common/Server.xs Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/plugins/perl/common/Server.xs Sun Jun 23 13:35:53 2013 +0530 @@ -35,7 +35,7 @@ Purple::Connection con int a const char * b - Purple::MessageFlags flags + Purple::Conversation::MessageFlags flags void serv_chat_whisper(con, a, b, c) @@ -60,7 +60,7 @@ Purple::Connection g int id const char *who - Purple::MessageFlags chatflags + Purple::Conversation::MessageFlags chatflags const char *message time_t mtime @@ -101,7 +101,7 @@ Purple::Connection gc const char *who const char *msg - Purple::MessageFlags imflags + Purple::Conversation::MessageFlags imflags time_t mtime Purple::Conversation @@ -115,7 +115,7 @@ Purple::Connection gc const char *name int timeout - Purple::TypingState state + Purple::IMConversation::TypingState state void serv_got_typing_stopped(gc, name) @@ -197,13 +197,13 @@ Purple::Connection con const char * a const char * b - Purple::MessageFlags flags + Purple::Conversation::MessageFlags flags int serv_send_typing(con, a, state) Purple::Connection con const char * a - Purple::TypingState state + Purple::IMConversation::TypingState state void serv_set_info(con, a)
--- a/libpurple/plugins/perl/common/module.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/plugins/perl/common/module.h Sun Jun 23 13:35:53 2013 +0530 @@ -19,15 +19,26 @@ #include "../perl-common.h" -#include "account.h" +#include "accounts.h" #include "accountopt.h" #include "blist.h" #include "buddyicon.h" #include "certificate.h" #include "cipher.h" +#include "ciphers/aescipher.h" +#include "ciphers/des3cipher.h" +#include "ciphers/descipher.h" +#include "ciphers/hmaccipher.h" +#include "ciphers/pbkdf2cipher.h" +#include "ciphers/rc4cipher.h" +#include "hash.h" +#include "ciphers/md4hash.h" +#include "ciphers/md5hash.h" +#include "ciphers/sha1hash.h" +#include "ciphers/sha256hash.h" #include "cmds.h" #include "connection.h" -#include "conversation.h" +#include "conversations.h" #include "core.h" #include "debug.h" #include "desktopitem.h" @@ -48,7 +59,6 @@ #include "pluginpref.h" #include "pounce.h" #include "prefs.h" -#include "privacy.h" #include "prpl.h" #include "proxy.h" #include "request.h" @@ -71,6 +81,7 @@ typedef PurpleAccount * Purple__Account; typedef PurpleAccountOption * Purple__Account__Option; typedef PurpleAccountUserSplit * Purple__Account__UserSplit; +typedef PurpleAccountPrivacyType Purple__Account__PrivacyType; /* blist.h */ typedef PurpleBlistNode * Purple__BuddyList__Node; @@ -95,9 +106,6 @@ /* cipher.h */ typedef PurpleCipher * Purple__Cipher; -typedef PurpleCipherCaps Purple__CipherCaps; -typedef PurpleCipherContext * Purple__Cipher__Context; -typedef PurpleCipherOps * Purple__Cipher__Ops; typedef PurpleCipherBatchMode Purple__Cipher__BatchMode; /* cmds.h */ @@ -111,16 +119,15 @@ typedef PurpleConnectionFlags Purple__ConnectionFlags; typedef PurpleConnectionState Purple__ConnectionState; -/* conversation.h */ -typedef PurpleConversationType Purple__ConversationType; -typedef PurpleConvUpdateType Purple__ConvUpdateType; -typedef PurpleTypingState Purple__TypingState; -typedef PurpleMessageFlags Purple__MessageFlags; -typedef PurpleConvChatBuddyFlags Purple__ConvChatBuddyFlags; +/* conversations.h */ +typedef PurpleConversationUpdateType Purple__Conversation__UpdateType; +typedef PurpleIMConversationTypingState Purple__IMConversation__TypingState; +typedef PurpleConversationMessageFlags Purple__Conversation__MessageFlags; +typedef PurpleChatConversationBuddyFlags Purple__ChatConversation__Buddy__Flags; typedef PurpleConversation * Purple__Conversation; -typedef PurpleConvIm * Purple__Conversation__IM; -typedef PurpleConvChat * Purple__Conversation__Chat; -typedef PurpleConvChatBuddy * Purple__Conversation__ChatBuddy; +typedef PurpleIMConversation * Purple__IMConversation; +typedef PurpleChatConversation * Purple__ChatConversation; +typedef PurpleChatConversationBuddy * Purple__ChatConversation__Buddy; /* core.h */ @@ -168,6 +175,9 @@ /* gtkconn.h */ #endif +/* hash.h */ +typedef PurpleHash * Purple__Hash; + /* imgstore.h */ typedef PurpleStoredImage * Purple__StoredImage; @@ -215,9 +225,6 @@ /* prefs.h */ typedef PurplePrefType Purple__PrefType; -/* privacy.h */ -typedef PurplePrivacyType Purple__PrivacyType; - /* proxy.h */ typedef PurpleProxyInfo * Purple__ProxyInfo; typedef PurpleProxyType Purple__ProxyType;
--- a/libpurple/plugins/perl/common/typemap Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/plugins/perl/common/typemap Sun Jun 23 13:35:53 2013 +0530 @@ -37,10 +37,12 @@ const xmlnode * T_PTR gssize T_IV const void * T_PTR +GType T_IV Purple::Account T_PurpleObj Purple::Account::Option T_PurpleObj Purple::Account::UserSplit T_PurpleObj +Purple::Account::PrivacyType T_IV Purple::Buddy::Icon T_PurpleObj Purple::Buddy::Icon::Spec T_PurpleObj @@ -54,18 +56,12 @@ Purple::BuddyList::NodeType T_IV Purple::Cipher T_PurpleObj -Purple::CipherCaps T_IV -Purple::Cipher::Ops T_PurpleObj -Purple::Cipher::Context T_PurpleObj +Purple::Hash T_PurpleObj Purple::Cmd::Flag T_IV Purple::Cmd::Id T_IV Purple::Cmd::Priority T_IV Purple::Cmd::Ret T_IV Purple::Connection T_PurpleObj -Purple::Conversation T_PurpleObj -Purple::Conversation::Chat T_PurpleObj -Purple::Conversation::ChatBuddy T_PurpleObj -Purple::Conversation::IM T_PurpleObj Purple::Core T_PurpleObj Purple::Desktop::Item T_PurpleObj @@ -111,7 +107,6 @@ Purple::Pounce T_PurpleObj Purple::PounceEvent T_IV Purple::Presence T_PurpleObj -Purple::PrivacyType T_IV Purple::ProtocolOptions T_IV Purple::ProxyInfo T_PurpleObj Purple::ProxyType T_IV @@ -180,12 +175,15 @@ /* debug.h */ Purple::DebugLevel T_IV -/* conversation.h */ -Purple::ConvChatBuddyFlags T_IV -Purple::ConvUpdateType T_IV -Purple::ConversationType T_IV -Purple::MessageFlags T_IV -Purple::TypingState T_IV +/* conversations.h */ +Purple::Conversation T_PurpleObj +Purple::ChatConversation T_PurpleObj +Purple::ChatConversation::Buddy T_PurpleObj +Purple::IMConversation T_PurpleObj +Purple::ChatConversation::Buddy::Flags T_IV +Purple::Conversation::UpdateType T_IV +Purple::Conversation::MessageFlags T_IV +Purple::IMConversation::TypingState T_IV Purple::UnseenState T_IV /* connection.h */
--- a/libpurple/plugins/psychic.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/plugins/psychic.c Sun Jun 23 13:35:53 2013 +0530 @@ -9,7 +9,6 @@ #include "signals.h" #include "status.h" #include "version.h" -#include "privacy.h" #include "plugin.h" #include "pluginpref.h" @@ -48,7 +47,7 @@ return; } - if(FALSE == purple_privacy_check(acct, name)) { + if(FALSE == purple_account_privacy_check(acct, name)) { purple_debug_info("psychic", "user %s is blocked\n", name); return; }
--- a/libpurple/plugins/signals-test.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/plugins/signals-test.c Sun Jun 23 13:35:53 2013 +0530 @@ -24,7 +24,6 @@ #include <stdio.h> -#include "cipher.h" #include "connection.h" #include "conversation.h" #include "core.h" @@ -74,7 +73,7 @@ { purple_debug_misc("signals test", "account-alias-changed (%s, %s, %s)\n", purple_account_get_username(account), - old, purple_account_get_alias(account)); + old, purple_account_get_private_alias(account)); } static int @@ -524,21 +523,6 @@ (who) ? who : "unknown"); } /************************************************************************** - * Ciphers signal callbacks - **************************************************************************/ -static void -cipher_added_cb(PurpleCipher *cipher, void *data) { - purple_debug_misc("signals test", "cipher %s added\n", - purple_cipher_get_name(cipher)); -} - -static void -cipher_removed_cb(PurpleCipher *cipher, void *data) { - purple_debug_misc("signals test", "cipher %s removed\n", - purple_cipher_get_name(cipher)); -} - -/************************************************************************** * Core signal callbacks **************************************************************************/ static void @@ -719,7 +703,6 @@ void *conn_handle = purple_connections_get_handle(); void *conv_handle = purple_conversations_get_handle(); void *accounts_handle = purple_accounts_get_handle(); - void *ciphers_handle = purple_ciphers_get_handle(); void *ft_handle = purple_xfers_get_handle(); void *sound_handle = purple_sounds_get_handle(); void *notify_handle = purple_notify_get_handle(); @@ -831,12 +814,6 @@ purple_signal_connect(conv_handle, "chat-topic-changed", plugin, PURPLE_CALLBACK(chat_topic_changed_cb), NULL); - /* Ciphers signals */ - purple_signal_connect(ciphers_handle, "cipher-added", - plugin, PURPLE_CALLBACK(cipher_added_cb), NULL); - purple_signal_connect(ciphers_handle, "cipher-removed", - plugin, PURPLE_CALLBACK(cipher_removed_cb), NULL); - /* Core signals */ purple_signal_connect(core_handle, "quitting", plugin, PURPLE_CALLBACK(quitting_cb), NULL);
--- a/libpurple/plugins/tcl/tcl_cmds.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/plugins/tcl/tcl_cmds.c Sun Jun 23 13:35:53 2013 +0530 @@ -70,7 +70,7 @@ if (convo == NULL) return NULL; - for (cur = purple_get_conversations(); cur != NULL; cur = g_list_next(cur)) { + for (cur = purple_conversations_get(); cur != NULL; cur = g_list_next(cur)) { if (convo == cur->data) return convo; } @@ -139,7 +139,7 @@ } if ((account = tcl_validate_account(objv[2], interp)) == NULL) return TCL_ERROR; - alias = purple_account_get_alias(account); + alias = purple_account_get_private_alias(account); Tcl_SetObjResult(interp, Tcl_NewStringObj(alias ? (char *)alias : "", -1)); break; case CMD_ACCOUNT_CONNECT: @@ -775,7 +775,7 @@ enum { CMD_CONV_NEW_CHAT, CMD_CONV_NEW_IM } newopt; PurpleConversation *convo; PurpleAccount *account; - PurpleConversationType type; + gboolean is_chat = FALSE; GList *cur; char *opt, *from, *what; int error, argsused, flags = 0; @@ -797,8 +797,7 @@ account = NULL; if ((account = tcl_validate_account(objv[2], interp)) == NULL) return TCL_ERROR; - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, - Tcl_GetString(objv[3]), + convo = purple_conversations_find_with_account(Tcl_GetString(objv[3]), account); Tcl_SetObjResult(interp, purple_tcl_ref_new(PurpleTclRefConversation, convo)); break; @@ -813,7 +812,7 @@ break; case CMD_CONV_LIST: list = Tcl_NewListObj(0, NULL); - for (cur = purple_get_conversations(); cur != NULL; cur = g_list_next(cur)) { + for (cur = purple_conversations_get(); cur != NULL; cur = g_list_next(cur)) { elem = purple_tcl_ref_new(PurpleTclRefConversation, cur->data); Tcl_ListObjAppendElement(interp, list, elem); } @@ -825,7 +824,7 @@ return TCL_ERROR; } argsused = 2; - type = PURPLE_CONV_TYPE_IM; + is_chat = FALSE; while (argsused < objc) { opt = Tcl_GetString(objv[argsused]); if (*opt == '-') { @@ -835,10 +834,10 @@ argsused++; switch (newopt) { case CMD_CONV_NEW_CHAT: - type = PURPLE_CONV_TYPE_CHAT; + is_chat = TRUE; break; case CMD_CONV_NEW_IM: - type = PURPLE_CONV_TYPE_IM; + is_chat = FALSE; break; } } else { @@ -851,7 +850,10 @@ } if ((account = tcl_validate_account(objv[argsused++], interp)) == NULL) return TCL_ERROR; - convo = purple_conversation_new(type, account, Tcl_GetString(objv[argsused])); + if (is_chat) + convo = purple_chat_conversation_new(account, Tcl_GetString(objv[argsused])); + else + convo = purple_im_conversation_new(account, Tcl_GetString(objv[argsused])); Tcl_SetObjResult(interp, purple_tcl_ref_new(PurpleTclRefConversation, convo)); break; case CMD_CONV_WRITE: @@ -868,20 +870,16 @@ switch (style) { case CMD_CONV_WRITE_SEND: - flags = PURPLE_MESSAGE_SEND; + flags = PURPLE_CONVERSATION_MESSAGE_SEND; break; case CMD_CONV_WRITE_RECV: - flags = PURPLE_MESSAGE_RECV; + flags = PURPLE_CONVERSATION_MESSAGE_RECV; break; case CMD_CONV_WRITE_SYSTEM: - flags = PURPLE_MESSAGE_SYSTEM; + flags = PURPLE_CONVERSATION_MESSAGE_SYSTEM; break; } - if (purple_conversation_get_type(convo) == PURPLE_CONV_TYPE_CHAT) - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), from, what, flags, time(NULL)); - else - purple_conv_im_write(PURPLE_CONV_IM(convo), from, what, flags, time(NULL)); - break; + purple_conversation_write_message(convo, from, what, flags, time(NULL)); case CMD_CONV_NAME: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "conversation"); @@ -912,10 +910,7 @@ if ((convo = tcl_validate_conversation(objv[2], interp)) == NULL) return TCL_ERROR; what = Tcl_GetString(objv[3]); - if (purple_conversation_get_type(convo) == PURPLE_CONV_TYPE_CHAT) - purple_conv_chat_send(PURPLE_CONV_CHAT(convo), what); - else - purple_conv_im_send(PURPLE_CONV_IM(convo), what); + purple_conversation_send(convo, what); break; }
--- a/libpurple/privacy.c Sun Jun 23 02:43:06 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,411 +0,0 @@ -/** - * 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 "internal.h" - -#include "account.h" -#include "privacy.h" -#include "server.h" -#include "util.h" - -static PurplePrivacyUiOps *privacy_ops = NULL; - -gboolean -purple_privacy_permit_add(PurpleAccount *account, const char *who, - gboolean local_only) -{ - GSList *l; - char *name; - PurpleBuddy *buddy; - PurpleBlistUiOps *blist_ops; - - g_return_val_if_fail(account != NULL, FALSE); - g_return_val_if_fail(who != NULL, FALSE); - - name = g_strdup(purple_normalize(account, who)); - - for (l = account->permit; l != NULL; l = l->next) { - if (g_str_equal(name, l->data)) - /* This buddy already exists */ - break; - } - - if (l != NULL) - { - /* This buddy already exists, so bail out */ - g_free(name); - return FALSE; - } - - account->permit = g_slist_append(account->permit, name); - - if (!local_only && purple_account_is_connected(account)) - serv_add_permit(purple_account_get_connection(account), who); - - if (privacy_ops != NULL && privacy_ops->permit_added != NULL) - privacy_ops->permit_added(account, who); - - blist_ops = purple_blist_get_ui_ops(); - if (blist_ops != NULL && blist_ops->save_account != NULL) - blist_ops->save_account(account); - - /* This lets the UI know a buddy has had its privacy setting changed */ - buddy = purple_find_buddy(account, name); - if (buddy != NULL) { - purple_signal_emit(purple_blist_get_handle(), - "buddy-privacy-changed", buddy); - } - return TRUE; -} - -gboolean -purple_privacy_permit_remove(PurpleAccount *account, const char *who, - gboolean local_only) -{ - GSList *l; - const char *name; - PurpleBuddy *buddy; - char *del; - PurpleBlistUiOps *blist_ops; - - g_return_val_if_fail(account != NULL, FALSE); - g_return_val_if_fail(who != NULL, FALSE); - - name = purple_normalize(account, who); - - for (l = account->permit; l != NULL; l = l->next) { - if (g_str_equal(name, l->data)) - /* We found the buddy we were looking for */ - break; - } - - if (l == NULL) - /* We didn't find the buddy we were looking for, so bail out */ - return FALSE; - - /* We should not free l->data just yet. There can be occasions where - * l->data == who. In such cases, freeing l->data here can cause crashes - * later when who is used. */ - del = l->data; - account->permit = g_slist_delete_link(account->permit, l); - - if (!local_only && purple_account_is_connected(account)) - serv_rem_permit(purple_account_get_connection(account), who); - - if (privacy_ops != NULL && privacy_ops->permit_removed != NULL) - privacy_ops->permit_removed(account, who); - - blist_ops = purple_blist_get_ui_ops(); - if (blist_ops != NULL && blist_ops->save_account != NULL) - blist_ops->save_account(account); - - buddy = purple_find_buddy(account, name); - if (buddy != NULL) { - purple_signal_emit(purple_blist_get_handle(), - "buddy-privacy-changed", buddy); - } - g_free(del); - return TRUE; -} - -gboolean -purple_privacy_deny_add(PurpleAccount *account, const char *who, - gboolean local_only) -{ - GSList *l; - char *name; - PurpleBuddy *buddy; - PurpleBlistUiOps *blist_ops; - - g_return_val_if_fail(account != NULL, FALSE); - g_return_val_if_fail(who != NULL, FALSE); - - name = g_strdup(purple_normalize(account, who)); - - for (l = account->deny; l != NULL; l = l->next) { - if (g_str_equal(name, l->data)) - /* This buddy already exists */ - break; - } - - if (l != NULL) - { - /* This buddy already exists, so bail out */ - g_free(name); - return FALSE; - } - - account->deny = g_slist_append(account->deny, name); - - if (!local_only && purple_account_is_connected(account)) - serv_add_deny(purple_account_get_connection(account), who); - - if (privacy_ops != NULL && privacy_ops->deny_added != NULL) - privacy_ops->deny_added(account, who); - - blist_ops = purple_blist_get_ui_ops(); - if (blist_ops != NULL && blist_ops->save_account != NULL) - blist_ops->save_account(account); - - buddy = purple_find_buddy(account, name); - if (buddy != NULL) { - purple_signal_emit(purple_blist_get_handle(), - "buddy-privacy-changed", buddy); - } - return TRUE; -} - -gboolean -purple_privacy_deny_remove(PurpleAccount *account, const char *who, - gboolean local_only) -{ - GSList *l; - const char *normalized; - char *name; - PurpleBuddy *buddy; - PurpleBlistUiOps *blist_ops; - - g_return_val_if_fail(account != NULL, FALSE); - g_return_val_if_fail(who != NULL, FALSE); - - normalized = purple_normalize(account, who); - - for (l = account->deny; l != NULL; l = l->next) { - if (g_str_equal(normalized, l->data)) - /* We found the buddy we were looking for */ - break; - } - - if (l == NULL) - /* We didn't find the buddy we were looking for, so bail out */ - return FALSE; - - buddy = purple_find_buddy(account, normalized); - - name = l->data; - account->deny = g_slist_delete_link(account->deny, l); - - if (!local_only && purple_account_is_connected(account)) - serv_rem_deny(purple_account_get_connection(account), name); - - if (privacy_ops != NULL && privacy_ops->deny_removed != NULL) - privacy_ops->deny_removed(account, who); - - if (buddy != NULL) { - purple_signal_emit(purple_blist_get_handle(), - "buddy-privacy-changed", buddy); - } - - g_free(name); - - blist_ops = purple_blist_get_ui_ops(); - if (blist_ops != NULL && blist_ops->save_account != NULL) - blist_ops->save_account(account); - - return TRUE; -} - -/** - * This makes sure your permit list contains all buddies from your - * buddy list and ONLY buddies from your buddy list. - */ -static void -add_all_buddies_to_permit_list(PurpleAccount *account, gboolean local) -{ - GSList *list; - - /* Remove anyone in the permit list who is not in the buddylist */ - for (list = account->permit; list != NULL; ) { - char *person = list->data; - list = list->next; - if (!purple_find_buddy(account, person)) - purple_privacy_permit_remove(account, person, local); - } - - /* Now make sure everyone in the buddylist is in the permit list */ - list = purple_find_buddies(account, NULL); - while (list != NULL) - { - PurpleBuddy *buddy = list->data; - const gchar *name = purple_buddy_get_name(buddy); - - if (!g_slist_find_custom(account->permit, name, (GCompareFunc)g_utf8_collate)) - purple_privacy_permit_add(account, name, local); - list = g_slist_delete_link(list, list); - } -} - -/* - * TODO: All callers of this function pass in FALSE for local and - * restore and I don't understand when you would ever want to - * use TRUE for either of them. I think both parameters could - * safely be removed in the next major version bump. - */ -void -purple_privacy_allow(PurpleAccount *account, const char *who, gboolean local, - gboolean restore) -{ - GSList *list; - PurplePrivacyType type = purple_account_get_privacy_type(account); - - switch (type) { - case PURPLE_PRIVACY_ALLOW_ALL: - return; - case PURPLE_PRIVACY_ALLOW_USERS: - purple_privacy_permit_add(account, who, local); - break; - case PURPLE_PRIVACY_DENY_USERS: - purple_privacy_deny_remove(account, who, local); - break; - case PURPLE_PRIVACY_DENY_ALL: - if (!restore) { - /* Empty the allow-list. */ - const char *norm = purple_normalize(account, who); - for (list = account->permit; list != NULL;) { - char *person = list->data; - list = list->next; - if (!purple_strequal(norm, person)) - purple_privacy_permit_remove(account, person, local); - } - } - purple_privacy_permit_add(account, who, local); - purple_account_set_privacy_type(account, PURPLE_PRIVACY_ALLOW_USERS); - break; - case PURPLE_PRIVACY_ALLOW_BUDDYLIST: - if (!purple_find_buddy(account, who)) { - add_all_buddies_to_permit_list(account, local); - purple_privacy_permit_add(account, who, local); - purple_account_set_privacy_type(account, PURPLE_PRIVACY_ALLOW_USERS); - } - break; - default: - g_return_if_reached(); - } - - /* Notify the server if the privacy setting was changed */ - if (type != purple_account_get_privacy_type(account) && purple_account_is_connected(account)) - serv_set_permit_deny(purple_account_get_connection(account)); -} - -/* - * TODO: All callers of this function pass in FALSE for local and - * restore and I don't understand when you would ever want to - * use TRUE for either of them. I think both parameters could - * safely be removed in the next major version bump. - */ -void -purple_privacy_deny(PurpleAccount *account, const char *who, gboolean local, - gboolean restore) -{ - GSList *list; - PurplePrivacyType type = purple_account_get_privacy_type(account); - - switch (type) { - case PURPLE_PRIVACY_ALLOW_ALL: - if (!restore) { - /* Empty the deny-list. */ - const char *norm = purple_normalize(account, who); - for (list = account->deny; list != NULL; ) { - char *person = list->data; - list = list->next; - if (!purple_strequal(norm, person)) - purple_privacy_deny_remove(account, person, local); - } - } - purple_privacy_deny_add(account, who, local); - purple_account_set_privacy_type(account, PURPLE_PRIVACY_DENY_USERS); - break; - case PURPLE_PRIVACY_ALLOW_USERS: - purple_privacy_permit_remove(account, who, local); - break; - case PURPLE_PRIVACY_DENY_USERS: - purple_privacy_deny_add(account, who, local); - break; - case PURPLE_PRIVACY_DENY_ALL: - break; - case PURPLE_PRIVACY_ALLOW_BUDDYLIST: - if (purple_find_buddy(account, who)) { - add_all_buddies_to_permit_list(account, local); - purple_privacy_permit_remove(account, who, local); - purple_account_set_privacy_type(account, PURPLE_PRIVACY_ALLOW_USERS); - } - break; - default: - g_return_if_reached(); - } - - /* Notify the server if the privacy setting was changed */ - if (type != purple_account_get_privacy_type(account) && purple_account_is_connected(account)) - serv_set_permit_deny(purple_account_get_connection(account)); -} - -gboolean -purple_privacy_check(PurpleAccount *account, const char *who) -{ - GSList *list; - - switch (purple_account_get_privacy_type(account)) { - case PURPLE_PRIVACY_ALLOW_ALL: - return TRUE; - - case PURPLE_PRIVACY_DENY_ALL: - return FALSE; - - case PURPLE_PRIVACY_ALLOW_USERS: - who = purple_normalize(account, who); - for (list=account->permit; list!=NULL; list=list->next) { - if (g_str_equal(who, list->data)) - return TRUE; - } - return FALSE; - - case PURPLE_PRIVACY_DENY_USERS: - who = purple_normalize(account, who); - for (list=account->deny; list!=NULL; list=list->next) { - if (g_str_equal(who, list->data)) - return FALSE; - } - return TRUE; - - case PURPLE_PRIVACY_ALLOW_BUDDYLIST: - return (purple_find_buddy(account, who) != NULL); - - default: - g_return_val_if_reached(TRUE); - } -} - -void -purple_privacy_set_ui_ops(PurplePrivacyUiOps *ops) -{ - privacy_ops = ops; -} - -PurplePrivacyUiOps * -purple_privacy_get_ui_ops(void) -{ - return privacy_ops; -} - -void -purple_privacy_init(void) -{ -}
--- a/libpurple/privacy.h Sun Jun 23 02:43:06 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,190 +0,0 @@ -/** - * @file privacy.h Privacy API - * @ingroup core - */ - -/* 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 - */ -#ifndef _PURPLE_PRIVACY_H_ -#define _PURPLE_PRIVACY_H_ - -/** - * Privacy data types. - */ -typedef enum -{ - PURPLE_PRIVACY_ALLOW_ALL = 1, - PURPLE_PRIVACY_DENY_ALL, - PURPLE_PRIVACY_ALLOW_USERS, - PURPLE_PRIVACY_DENY_USERS, - PURPLE_PRIVACY_ALLOW_BUDDYLIST -} PurplePrivacyType; - -#include "account.h" - -/** - * Privacy core/UI operations. - */ -typedef struct -{ - void (*permit_added)(PurpleAccount *account, const char *name); - void (*permit_removed)(PurpleAccount *account, const char *name); - void (*deny_added)(PurpleAccount *account, const char *name); - void (*deny_removed)(PurpleAccount *account, const char *name); - - void (*_purple_reserved1)(void); - void (*_purple_reserved2)(void); - void (*_purple_reserved3)(void); - void (*_purple_reserved4)(void); -} PurplePrivacyUiOps; - -G_BEGIN_DECLS - -/** - * Adds a user to the account's permit list. - * - * @param account The account. - * @param name The name of the user to add to the list. - * @param local_only If TRUE, only the local list is updated, and not - * the server. - * - * @return TRUE if the user was added successfully, or @c FALSE otherwise. - */ -gboolean purple_privacy_permit_add(PurpleAccount *account, const char *name, - gboolean local_only); - -/** - * Removes a user from the account's permit list. - * - * @param account The account. - * @param name The name of the user to add to the list. - * @param local_only If TRUE, only the local list is updated, and not - * the server. - * - * @return TRUE if the user was removed successfully, or @c FALSE otherwise. - */ -gboolean purple_privacy_permit_remove(PurpleAccount *account, const char *name, - gboolean local_only); - -/** - * Adds a user to the account's deny list. - * - * @param account The account. - * @param name The name of the user to add to the list. - * @param local_only If TRUE, only the local list is updated, and not - * the server. - * - * @return TRUE if the user was added successfully, or @c FALSE otherwise. - */ -gboolean purple_privacy_deny_add(PurpleAccount *account, const char *name, - gboolean local_only); - -/** - * Removes a user from the account's deny list. - * - * @param account The account. - * @param name The name of the user to add to the list. - * @param local_only If TRUE, only the local list is updated, and not - * the server. - * - * @return TRUE if the user was removed successfully, or @c FALSE otherwise. - */ -gboolean purple_privacy_deny_remove(PurpleAccount *account, const char *name, - gboolean local_only); - -/** - * Allow a user to send messages. If current privacy setting for the account is: - * PURPLE_PRIVACY_ALLOW_USERS: The user is added to the allow-list. - * PURPLE_PRIVACY_DENY_USERS : The user is removed from the deny-list. - * PURPLE_PRIVACY_ALLOW_ALL : No changes made. - * PURPLE_PRIVACY_DENY_ALL : The privacy setting is changed to - * PURPLE_PRIVACY_ALLOW_USERS and the user - * is added to the allow-list. - * PURPLE_PRIVACY_ALLOW_BUDDYLIST: No changes made if the user is already in - * the buddy-list. Otherwise the setting is - * changed to PURPLE_PRIVACY_ALLOW_USERS, all the - * buddies are added to the allow-list, and the - * user is also added to the allow-list. - * - * @param account The account. - * @param who The name of the user. - * @param local Whether the change is local-only. - * @param restore Should the previous allow/deny list be restored if the - * privacy setting is changed. - */ -void purple_privacy_allow(PurpleAccount *account, const char *who, gboolean local, - gboolean restore); - -/** - * Block messages from a user. If current privacy setting for the account is: - * PURPLE_PRIVACY_ALLOW_USERS: The user is removed from the allow-list. - * PURPLE_PRIVACY_DENY_USERS : The user is added to the deny-list. - * PURPLE_PRIVACY_DENY_ALL : No changes made. - * PURPLE_PRIVACY_ALLOW_ALL : The privacy setting is changed to - * PURPLE_PRIVACY_DENY_USERS and the user is - * added to the deny-list. - * PURPLE_PRIVACY_ALLOW_BUDDYLIST: If the user is not in the buddy-list, - * then no changes made. Otherwise, the setting - * is changed to PURPLE_PRIVACY_ALLOW_USERS, all - * the buddies are added to the allow-list, and - * this user is removed from the list. - * - * @param account The account. - * @param who The name of the user. - * @param local Whether the change is local-only. - * @param restore Should the previous allow/deny list be restored if the - * privacy setting is changed. - */ -void purple_privacy_deny(PurpleAccount *account, const char *who, gboolean local, - gboolean restore); - -/** - * Check the privacy-setting for a user. - * - * @param account The account. - * @param who The name of the user. - * - * @return @c FALSE if the specified account's privacy settings block the user or @c TRUE otherwise. The meaning of "block" is protocol-dependent and generally relates to status and/or sending of messages. - */ -gboolean purple_privacy_check(PurpleAccount *account, const char *who); - -/** - * Sets the UI operations structure for the privacy subsystem. - * - * @param ops The UI operations structure. - */ -void purple_privacy_set_ui_ops(PurplePrivacyUiOps *ops); - -/** - * Returns the UI operations structure for the privacy subsystem. - * - * @return The UI operations structure. - */ -PurplePrivacyUiOps *purple_privacy_get_ui_ops(void); - -/** - * Initializes the privacy subsystem. - */ -void purple_privacy_init(void); - -G_END_DECLS - -#endif /* _PURPLE_PRIVACY_H_ */
--- a/libpurple/protocols/bonjour/bonjour_ft.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/bonjour/bonjour_ft.c Sun Jun 23 13:35:53 2013 +0530 @@ -28,7 +28,7 @@ #include "buddy.h" #include "bonjour.h" #include "bonjour_ft.h" -#include "cipher.h" +#include "ciphers/sha1hash.h" static void bonjour_bytestreams_init(PurpleXfer *xfer); @@ -1018,6 +1018,7 @@ { PurpleBuddy *pb; PurpleAccount *account = NULL; + PurpleHash *hash; XepXfer *xf; char dstaddr[41]; const gchar *name = NULL; @@ -1039,8 +1040,12 @@ account = purple_buddy_get_account(pb); p = g_strdup_printf("%s%s%s", xf->sid, name, bonjour_get_jid(account)); - purple_cipher_digest_region("sha1", (guchar *)p, strlen(p), hashval, - sizeof(hashval)); + + hash = purple_sha1_hash_new(); + purple_hash_append(hash, (guchar *)p, strlen(p)); + purple_hash_digest(hash, hashval, sizeof(hashval)); + g_object_unref(G_OBJECT(hash)); + g_free(p); memset(dstaddr, 0, 41);
--- a/libpurple/protocols/bonjour/jabber.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/bonjour/jabber.c Sun Jun 23 13:35:53 2013 +0530 @@ -89,7 +89,7 @@ BonjourJabberConversation *bconv = g_new0(BonjourJabberConversation, 1); bconv->socket = -1; - bconv->tx_buf = purple_circ_buffer_new(512); + bconv->tx_buf = purple_circular_buffer_new(512); bconv->tx_handler = 0; bconv->rx_handler = 0; bconv->pb = pb; @@ -280,7 +280,7 @@ BonjourJabberConversation *bconv = bb->conversation; int ret, writelen; - writelen = purple_circ_buffer_get_max_read(bconv->tx_buf); + writelen = purple_circular_buffer_get_max_read(bconv->tx_buf); if (writelen == 0) { purple_input_remove(bconv->tx_handler); @@ -288,7 +288,7 @@ return; } - ret = send(bconv->socket, bconv->tx_buf->outptr, writelen, 0); + ret = send(bconv->socket, purple_circular_buffer_get_output(bconv->tx_buf), writelen, 0); if (ret < 0 && errno == EAGAIN) return; @@ -313,7 +313,7 @@ return; } - purple_circ_buffer_mark_read(bconv->tx_buf, ret); + purple_circular_buffer_mark_read(bconv->tx_buf, ret); } static gint @@ -329,7 +329,7 @@ || bconv->connect_data != NULL || bconv->sent_stream_start != FULLY_SENT || !bconv->recv_stream_start - || purple_circ_buffer_get_max_read(bconv->tx_buf) > 0) { + || purple_circular_buffer_get_max_read(bconv->tx_buf) > 0) { ret = -1; errno = EAGAIN; } else { @@ -364,7 +364,7 @@ if (bconv->sent_stream_start == FULLY_SENT && bconv->recv_stream_start && bconv->tx_handler == 0) bconv->tx_handler = purple_input_add(bconv->socket, PURPLE_INPUT_WRITE, _send_data_write_cb, pb); - purple_circ_buffer_append(bconv->tx_buf, message + ret, len - ret); + purple_circular_buffer_append(bconv->tx_buf, message + ret, len - ret); } return ret; @@ -616,7 +616,7 @@ /* If the stream has been completely started and we know who we're talking to, we can start doing stuff. */ /* I don't think the circ_buffer can actually contain anything without a buddy being associated, but lets be explicit. */ if (bconv->sent_stream_start == FULLY_SENT && bconv->recv_stream_start - && bconv->pb && purple_circ_buffer_get_max_read(bconv->tx_buf) > 0) { + && bconv->pb && purple_circular_buffer_get_max_read(bconv->tx_buf) > 0) { /* Watch for when we can write the buffered messages */ bconv->tx_handler = purple_input_add(bconv->socket, PURPLE_INPUT_WRITE, _send_data_write_cb, bconv->pb); @@ -1189,7 +1189,7 @@ purple_input_remove(bconv->tx_handler); /* Free all the data related to the conversation */ - purple_circ_buffer_destroy(bconv->tx_buf); + g_object_unref(G_OBJECT(bconv->tx_buf)); if (bconv->connect_data != NULL) purple_proxy_connect_cancel(bconv->connect_data); if (bconv->stream_data != NULL) { @@ -1303,7 +1303,7 @@ acc = purple_buddy_get_account(pb); - for(l = acc->deny; l != NULL; l = l->next) { + for(l = purple_account_privacy_get_denied(acc); l != NULL; l = l->next) { const gchar *name = purple_buddy_get_name(pb); const gchar *username = bonjour_get_jid(acc);
--- a/libpurple/protocols/bonjour/jabber.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/bonjour/jabber.h Sun Jun 23 13:35:53 2013 +0530 @@ -31,7 +31,7 @@ #include "xmlnode.h" #include "account.h" -#include "circbuffer.h" +#include "circularbuffer.h" typedef struct _BonjourJabber { @@ -50,7 +50,7 @@ guint rx_handler; guint tx_handler; guint close_timeout; - PurpleCircBuffer *tx_buf; + PurpleCircularBuffer *tx_buf; int sent_stream_start; /* 0 = Unsent, 1 = Partial, 2 = Complete */ gboolean recv_stream_start; PurpleProxyConnectData *connect_data;
--- a/libpurple/protocols/gg/oauth/oauth.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/gg/oauth/oauth.c Sun Jun 23 13:35:53 2013 +0530 @@ -26,7 +26,8 @@ #include "oauth.h" #include "oauth-parameter.h" -#include <cipher.h> +#include "ciphers/hmaccipher.h" +#include "ciphers/sha1hash.h" char *gg_oauth_static_nonce; /* dla unit testów */ char *gg_oauth_static_timestamp; /* dla unit testów */ @@ -48,15 +49,19 @@ static gchar *gg_hmac_sha1(const char *key, const char *message) { - PurpleCipherContext *context; + PurpleCipher *cipher; + PurpleHash *hash; guchar digest[20]; - - context = purple_cipher_context_new_by_name("hmac", NULL); - purple_cipher_context_set_option(context, "hash", "sha1"); - purple_cipher_context_set_key(context, (guchar *)key, strlen(key)); - purple_cipher_context_append(context, (guchar *)message, strlen(message)); - purple_cipher_context_digest(context, digest, sizeof(digest)); - purple_cipher_context_destroy(context); + + hash = purple_sha1_hash_new(); + cipher = purple_hmac_cipher_new(hash); + + purple_cipher_set_key(cipher, (guchar *)key, strlen(key)); + purple_cipher_append(cipher, (guchar *)message, strlen(message)); + purple_cipher_digest(cipher, digest, sizeof(digest)); + + g_object_unref(cipher); + g_object_unref(hash); return purple_base64_encode(digest, sizeof(digest)); }
--- a/libpurple/protocols/irc/irc.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/irc/irc.c Sun Jun 23 13:35:53 2013 +0530 @@ -111,8 +111,9 @@ { struct irc_conn *irc = data; int ret, writelen; + const gchar *buffer = NULL; - writelen = purple_circ_buffer_get_max_read(irc->outbuf); + writelen = purple_circular_buffer_get_max_read(irc->outbuf); if (writelen == 0) { purple_input_remove(irc->writeh); @@ -120,7 +121,9 @@ return; } - ret = do_send(irc, irc->outbuf->outptr, writelen); + buffer = purple_circular_buffer_get_output(irc->outbuf); + + ret = do_send(irc, buffer, writelen); if (ret < 0 && errno == EAGAIN) return; @@ -134,7 +137,7 @@ return; } - purple_circ_buffer_mark_read(irc->outbuf, ret); + purple_circular_buffer_mark_read(irc->outbuf, ret); #if 0 /* We *could* try to write more if we wrote it all */ @@ -183,7 +186,7 @@ irc->writeh = purple_input_add( irc->gsc ? irc->gsc->fd : irc->fd, PURPLE_INPUT_WRITE, irc_send_cb, irc); - purple_circ_buffer_append(irc->outbuf, tosend + ret, + purple_circular_buffer_append(irc->outbuf, tosend + ret, buflen - ret); } g_free(tosend); @@ -345,7 +348,7 @@ purple_connection_set_protocol_data(gc, irc); irc->fd = -1; irc->account = account; - irc->outbuf = purple_circ_buffer_new(512); + irc->outbuf = purple_circular_buffer_new(512); userparts = g_strsplit(username, "@", 2); purple_connection_set_display_name(gc, userparts[0]); @@ -533,7 +536,7 @@ if (irc->writeh) purple_input_remove(irc->writeh); - purple_circ_buffer_destroy(irc->outbuf); + g_object_unref(G_OBJECT(irc->outbuf)); g_free(irc->mode_chars); g_free(irc->reqnick);
--- a/libpurple/protocols/irc/irc.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/irc/irc.h Sun Jun 23 13:35:53 2013 +0530 @@ -29,7 +29,7 @@ #include <sasl/sasl.h> #endif -#include "circbuffer.h" +#include "circularbuffer.h" #include "ft.h" #include "roomlist.h" #include "sslconn.h" @@ -89,7 +89,7 @@ gboolean quitting; - PurpleCircBuffer *outbuf; + PurpleCircularBuffer *outbuf; guint writeh; time_t recv_time;
--- a/libpurple/protocols/jabber/auth.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/jabber/auth.c Sun Jun 23 13:35:53 2013 +0530 @@ -24,7 +24,6 @@ #include "account.h" #include "debug.h" -#include "cipher.h" #include "core.h" #include "conversation.h" #include "request.h" @@ -39,6 +38,9 @@ #include "iq.h" #include "notify.h" +#include "ciphers/hmaccipher.h" +#include "ciphers/md5hash.h" + static GSList *auth_mechs = NULL; static void auth_old_result_cb(JabberStream *js, const char *from, @@ -276,16 +278,18 @@ */ const char *challenge; gchar digest[33]; - PurpleCipherContext *hmac; + PurpleCipher *hmac; + PurpleHash *md5; /* Calculate the MHAC-MD5 digest */ + md5 = purple_md5_hash_new(); + hmac = purple_hmac_cipher_new(md5); challenge = xmlnode_get_attrib(x, "challenge"); - hmac = purple_cipher_context_new_by_name("hmac", NULL); - purple_cipher_context_set_option(hmac, "hash", "md5"); - purple_cipher_context_set_key(hmac, (guchar *)pw, strlen(pw)); - purple_cipher_context_append(hmac, (guchar *)challenge, strlen(challenge)); - purple_cipher_context_digest_to_str(hmac, digest, 33); - purple_cipher_context_destroy(hmac); + purple_cipher_set_key(hmac, (guchar *)pw, strlen(pw)); + purple_cipher_append(hmac, (guchar *)challenge, strlen(challenge)); + purple_cipher_digest_to_str(hmac, digest, 33); + g_object_unref(hmac); + g_object_unref(md5); /* Create the response query */ iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:auth");
--- a/libpurple/protocols/jabber/auth_digest_md5.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/jabber/auth_digest_md5.c Sun Jun 23 13:35:53 2013 +0530 @@ -23,7 +23,7 @@ #include "internal.h" #include "debug.h" -#include "cipher.h" +#include "ciphers/md5hash.h" #include "util.h" #include "xmlnode.h" @@ -106,8 +106,7 @@ generate_response_value(JabberID *jid, const char *passwd, const char *nonce, const char *cnonce, const char *a2, const char *realm) { - PurpleCipher *cipher; - PurpleCipherContext *context; + PurpleHash *hash; guchar result[16]; size_t a1len; @@ -122,35 +121,34 @@ convpasswd = g_strdup(passwd); } - cipher = purple_ciphers_find_cipher("md5"); - context = purple_cipher_context_new(cipher, NULL); + hash = purple_md5_hash_new(); x = g_strdup_printf("%s:%s:%s", convnode, realm, convpasswd ? convpasswd : ""); - purple_cipher_context_append(context, (const guchar *)x, strlen(x)); - purple_cipher_context_digest(context, result, sizeof(result)); + purple_hash_append(hash, (const guchar *)x, strlen(x)); + purple_hash_digest(hash, result, sizeof(result)); a1 = g_strdup_printf("xxxxxxxxxxxxxxxx:%s:%s", nonce, cnonce); a1len = strlen(a1); g_memmove(a1, result, 16); - purple_cipher_context_reset(context, NULL); - purple_cipher_context_append(context, (const guchar *)a1, a1len); - purple_cipher_context_digest(context, result, sizeof(result)); + purple_hash_reset(hash); + purple_hash_append(hash, (const guchar *)a1, a1len); + purple_hash_digest(hash, result, sizeof(result)); ha1 = purple_base16_encode(result, 16); - purple_cipher_context_reset(context, NULL); - purple_cipher_context_append(context, (const guchar *)a2, strlen(a2)); - purple_cipher_context_digest(context, result, sizeof(result)); + purple_hash_reset(hash); + purple_hash_append(hash, (const guchar *)a2, strlen(a2)); + purple_hash_digest(hash, result, sizeof(result)); ha2 = purple_base16_encode(result, 16); kd = g_strdup_printf("%s:%s:00000001:%s:auth:%s", ha1, nonce, cnonce, ha2); - purple_cipher_context_reset(context, NULL); - purple_cipher_context_append(context, (const guchar *)kd, strlen(kd)); - purple_cipher_context_digest(context, result, sizeof(result)); - purple_cipher_context_destroy(context); + purple_hash_reset(hash); + purple_hash_append(hash, (const guchar *)kd, strlen(kd)); + purple_hash_digest(hash, result, sizeof(result)); + g_object_unref(hash); z = purple_base16_encode(result, 16);
--- a/libpurple/protocols/jabber/auth_scram.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/jabber/auth_scram.c Sun Jun 23 13:35:53 2013 +0530 @@ -25,11 +25,12 @@ #include "auth.h" #include "auth_scram.h" -#include "cipher.h" +#include "ciphers/hmaccipher.h" +#include "ciphers/sha1hash.h" #include "debug.h" static const JabberScramHash hashes[] = { - { "-SHA-1", "sha1", 20 }, + { "-SHA-1", purple_sha1_hash_new, 20 }, }; static const JabberScramHash *mech_to_hash(const char *mech) @@ -76,7 +77,8 @@ guchar *jabber_scram_hi(const JabberScramHash *hash, const GString *str, GString *salt, guint iterations) { - PurpleCipherContext *context; + PurpleHash *hasher; + PurpleCipher *cipher; guchar *result; guint i; guchar *prev, *tmp; @@ -90,27 +92,28 @@ tmp = g_new0(guint8, hash->size); result = g_new0(guint8, hash->size); - context = purple_cipher_context_new_by_name("hmac", NULL); + hasher = hash->new_cipher(); + cipher = purple_hmac_cipher_new(hasher); + g_object_unref(G_OBJECT(hasher)); /* Append INT(1), a four-octet encoding of the integer 1, most significant * octet first. */ g_string_append_len(salt, "\0\0\0\1", 4); /* Compute U0 */ - purple_cipher_context_set_option(context, "hash", (gpointer)hash->name); - purple_cipher_context_set_key(context, (guchar *)str->str, str->len); - purple_cipher_context_append(context, (guchar *)salt->str, salt->len); - purple_cipher_context_digest(context, result, hash->size); + purple_cipher_set_key(cipher, (guchar *)str->str, str->len); + purple_cipher_append(cipher, (guchar *)salt->str, salt->len); + purple_cipher_digest(cipher, result, hash->size); memcpy(prev, result, hash->size); /* Compute U1...Ui */ for (i = 1; i < iterations; ++i) { guint j; - purple_cipher_context_set_option(context, "hash", (gpointer)hash->name); - purple_cipher_context_set_key(context, (guchar *)str->str, str->len); - purple_cipher_context_append(context, prev, hash->size); - purple_cipher_context_digest(context, tmp, hash->size); + purple_cipher_reset(cipher); + purple_cipher_set_key(cipher, (guchar *)str->str, str->len); + purple_cipher_append(cipher, prev, hash->size); + purple_cipher_digest(cipher, tmp, hash->size); for (j = 0; j < hash->size; ++j) result[j] ^= tmp[j]; @@ -118,7 +121,7 @@ memcpy(prev, tmp, hash->size); } - purple_cipher_context_destroy(context); + g_object_unref(G_OBJECT(cipher)); g_free(tmp); g_free(prev); return result; @@ -136,25 +139,27 @@ static void hmac(const JabberScramHash *hash, guchar *out, const guchar *key, const gchar *str) { - PurpleCipherContext *context; + PurpleHash *hasher; + PurpleCipher *cipher; - context = purple_cipher_context_new_by_name("hmac", NULL); - purple_cipher_context_set_option(context, "hash", (gpointer)hash->name); - purple_cipher_context_set_key(context, key, hash->size); - purple_cipher_context_append(context, (guchar *)str, strlen(str)); - purple_cipher_context_digest(context, out, hash->size); - purple_cipher_context_destroy(context); + hasher = hash->new_cipher(); + cipher = purple_hmac_cipher_new(hasher); + g_object_unref(G_OBJECT(hasher)); + purple_cipher_set_key(cipher, key, hash->size); + purple_cipher_append(cipher, (guchar *)str, strlen(str)); + purple_cipher_digest(cipher, out, hash->size); + g_object_unref(G_OBJECT(cipher)); } static void hash(const JabberScramHash *hash, guchar *out, const guchar *data) { - PurpleCipherContext *context; + PurpleHash *hasher; - context = purple_cipher_context_new_by_name(hash->name, NULL); - purple_cipher_context_append(context, data, hash->size); - purple_cipher_context_digest(context, out, hash->size); - purple_cipher_context_destroy(context); + hasher = hash->new_cipher(); + purple_hash_append(hasher, data, hash->size); + purple_hash_digest(hasher, out, hash->size); + g_object_unref(G_OBJECT(hasher)); } gboolean
--- a/libpurple/protocols/jabber/auth_scram.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/jabber/auth_scram.h Sun Jun 23 13:35:53 2013 +0530 @@ -29,12 +29,14 @@ * DO NOT USE ANYTHING HERE OR YOU WILL BE SENT TO THE PIT OF DESPAIR. */ +#include "hash.h" + /* Per-connection state stored between messages. * This is stored in js->auth_data_mech. */ typedef struct { const char *mech_substr; - const char *name; + PurpleHash *(*new_cipher)(void); guint size; } JabberScramHash;
--- a/libpurple/protocols/jabber/bosh.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/jabber/bosh.c Sun Jun 23 13:35:53 2013 +0530 @@ -21,7 +21,7 @@ * */ #include "internal.h" -#include "circbuffer.h" +#include "circularbuffer.h" #include "core.h" #include "cipher.h" #include "debug.h" @@ -56,7 +56,7 @@ JabberStream *js; PurpleHTTPConnection *connections[NUM_HTTP_CONNECTIONS]; - PurpleCircBuffer *pending; + PurpleCircularBuffer *pending; PurpleBOSHConnectionConnectFunction connect_cb; PurpleBOSHConnectionReceiveFunction receive_cb; @@ -91,7 +91,7 @@ PurpleBOSHConnection *bosh; PurpleSslConnection *psc; - PurpleCircBuffer *write_buf; + PurpleCircularBuffer *write_buf; GString *read_buf; gsize handled_len; @@ -169,7 +169,7 @@ conn->fd = -1; conn->state = HTTP_CONN_OFFLINE; - conn->write_buf = purple_circ_buffer_new(0 /* default grow size */); + conn->write_buf = purple_circular_buffer_new(0 /* default grow size */); return conn; } @@ -181,7 +181,7 @@ g_string_free(conn->read_buf, TRUE); if (conn->write_buf) - purple_circ_buffer_destroy(conn->write_buf); + g_object_unref(G_OBJECT(conn->write_buf)); if (conn->readh) purple_input_remove(conn->readh); if (conn->writeh) @@ -239,7 +239,7 @@ conn->rid = ((guint64)g_random_int() << 32) | g_random_int(); conn->rid &= 0xFFFFFFFFFFFFFLL; - conn->pending = purple_circ_buffer_new(0 /* default grow size */); + conn->pending = purple_circular_buffer_new(0 /* default grow size */); conn->state = BOSH_CONN_OFFLINE; if (purple_strcasestr(url, "https://") != NULL) @@ -263,7 +263,7 @@ if (conn->send_timer) purple_timeout_remove(conn->send_timer); - purple_circ_buffer_destroy(conn->pending); + g_object_unref(G_OBJECT(conn->pending)); for (i = 0; i < NUM_HTTP_CONNECTIONS; ++i) { if (conn->connections[i]) @@ -350,11 +350,14 @@ * the buffer. */ if (data) - purple_circ_buffer_append(conn->pending, data, strlen(data)); + purple_circular_buffer_append(conn->pending, data, strlen(data)); - if (purple_debug_is_verbose()) + if (purple_debug_is_verbose()) { + gsize bufused = purple_circular_buffer_get_used(conn->pending); purple_debug_misc("jabber", "bosh: %p has %" G_GSIZE_FORMAT " bytes in " - "the buffer.\n", conn, conn->pending->bufused); + "the buffer.\n", conn, bufused); + } + if (conn->send_timer == 0) conn->send_timer = purple_timeout_add_seconds(BUFFER_SEND_IN_SECS, send_timer_cb, conn); @@ -409,9 +412,10 @@ packet = g_string_append_c(packet, '>'); - while ((read_amt = purple_circ_buffer_get_max_read(conn->pending)) > 0) { - packet = g_string_append_len(packet, conn->pending->outptr, read_amt); - purple_circ_buffer_mark_read(conn->pending, read_amt); + while ((read_amt = purple_circular_buffer_get_max_read(conn->pending)) > 0) { + const gchar *output = purple_circular_buffer_get_output(conn->pending); + packet = g_string_append_len(packet, output, read_amt); + purple_circular_buffer_mark_read(conn->pending, read_amt); } if (data) @@ -678,7 +682,7 @@ jabber_bosh_connection_send(conn->bosh, PACKET_NORMAL, NULL); else if (conn->bosh->state == BOSH_CONN_ONLINE) { purple_debug_info("jabber", "BOSH session already exists. Trying to reuse it.\n"); - if (conn->bosh->requests == 0 || conn->bosh->pending->bufused > 0) { + if (conn->bosh->requests == 0 || purple_circular_buffer_get_used(conn->bosh->pending) > 0) { /* Send the pending data */ jabber_bosh_connection_send(conn->bosh, PACKET_FLUSH, NULL); } @@ -832,7 +836,9 @@ } if (conn->bosh->state == BOSH_CONN_ONLINE && - (conn->bosh->requests == 0 || conn->bosh->pending->bufused > 0)) { + (conn->bosh->requests == 0 || + purple_circular_buffer_get_used(conn->bosh->pending) > 0)) + { purple_debug_misc("jabber", "BOSH: Sending an empty request\n"); jabber_bosh_connection_send(conn->bosh, PACKET_NORMAL, NULL); } @@ -1001,8 +1007,9 @@ http_connection_send_cb(gpointer data, gint source, PurpleInputCondition cond) { PurpleHTTPConnection *conn = data; + const gchar *output = NULL; int ret; - int writelen = purple_circ_buffer_get_max_read(conn->write_buf); + int writelen = purple_circular_buffer_get_max_read(conn->write_buf); if (writelen == 0) { purple_input_remove(conn->writeh); @@ -1010,7 +1017,8 @@ return; } - ret = http_connection_do_send(conn, conn->write_buf->outptr, writelen); + output = purple_circular_buffer_get_output(conn->write_buf); + ret = http_connection_do_send(conn, output, writelen); if (ret < 0 && errno == EAGAIN) return; @@ -1029,7 +1037,7 @@ return; } - purple_circ_buffer_mark_read(conn->write_buf, ret); + purple_circular_buffer_mark_read(conn->write_buf, ret); } static void @@ -1089,7 +1097,7 @@ if (conn->writeh == 0) conn->writeh = purple_input_add(conn->psc ? conn->psc->fd : conn->fd, PURPLE_INPUT_WRITE, http_connection_send_cb, conn); - purple_circ_buffer_append(conn->write_buf, data + ret, len - ret); + purple_circular_buffer_append(conn->write_buf, data + ret, len - ret); } }
--- a/libpurple/protocols/jabber/caps.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/jabber/caps.c Sun Jun 23 13:35:53 2013 +0530 @@ -25,12 +25,14 @@ #include "debug.h" #include "caps.h" -#include "cipher.h" #include "iq.h" #include "presence.h" #include "util.h" #include "xdata.h" +#include "ciphers/md5hash.h" +#include "ciphers/sha1hash.h" + #define JABBER_CAPS_FILENAME "xmpp-caps.xml" typedef struct _JabberDataFormField { @@ -455,16 +457,18 @@ /* Only validate if these are v1.5 capabilities */ if (userdata->hash) { gchar *hash = NULL; + PurpleHash *hasher = NULL; /* * TODO: If you add *any* hash here, make sure the checksum buffer * size in jabber_caps_calculate_hash is large enough. The cipher API * doesn't seem to offer a "Get the hash size" function(?). */ if (g_str_equal(userdata->hash, "sha-1")) { - hash = jabber_caps_calculate_hash(info, "sha1"); + hasher = purple_sha1_hash_new(); } else if (g_str_equal(userdata->hash, "md5")) { - hash = jabber_caps_calculate_hash(info, "md5"); + hasher = purple_md5_hash_new(); } + hash = jabber_caps_calculate_hash(info, hasher); if (!hash || !g_str_equal(hash, userdata->ver)) { purple_debug_warning("jabber", "Could not validate caps info from " @@ -480,6 +484,7 @@ } g_free(hash); + g_object_unref(hasher); } if (!userdata->hash && userdata->node_exts) { @@ -806,28 +811,33 @@ } static void -append_escaped_string(PurpleCipherContext *context, const gchar *str) +append_escaped_string(PurpleHash *hash, const gchar *str) { + g_return_if_fail(hash != NULL); + g_object_ref(hash); + if (str && *str) { char *tmp = g_markup_escape_text(str, -1); - purple_cipher_context_append(context, (const guchar *)tmp, strlen(tmp)); + purple_hash_append(hash, (const guchar *)tmp, strlen(tmp)); g_free(tmp); } - purple_cipher_context_append(context, (const guchar *)"<", 1); + purple_hash_append(hash, (const guchar *)"<", 1); + g_object_unref(hash); } -gchar *jabber_caps_calculate_hash(JabberCapsClientInfo *info, const char *hash) +gchar *jabber_caps_calculate_hash(JabberCapsClientInfo *info, PurpleHash *hash) { GList *node; - PurpleCipherContext *context; guint8 checksum[20]; gsize checksum_size = 20; gboolean success; - if (!info || !(context = purple_cipher_context_new_by_name(hash, NULL))) + if (!info || !hash) return NULL; + g_object_ref(hash); + /* sort identities, features and x-data forms */ info->identities = g_list_sort(info->identities, jabber_identity_compare); info->features = g_list_sort(info->features, (GCompareFunc)strcmp); @@ -850,7 +860,7 @@ tmp = g_strconcat(category, "/", type, "/", lang ? lang : "", "/", name ? name : "", "<", NULL); - purple_cipher_context_append(context, (const guchar *)tmp, strlen(tmp)); + purple_hash_append(hash, (const guchar *)tmp, strlen(tmp)); g_free(tmp); g_free(category); @@ -861,7 +871,7 @@ /* concat features to the verification string */ for (node = info->features; node; node = node->next) { - append_escaped_string(context, node->data); + append_escaped_string(hash, node->data); } /* concat x-data forms to the verification string */ @@ -871,7 +881,7 @@ GList *fields = jabber_caps_xdata_get_fields(data); /* append FORM_TYPE's field value to the verification string */ - append_escaped_string(context, formtype); + append_escaped_string(hash, formtype); g_free(formtype); while (fields) { @@ -879,10 +889,10 @@ if (!g_str_equal(field->var, "FORM_TYPE")) { /* Append the "var" attribute */ - append_escaped_string(context, field->var); + append_escaped_string(hash, field->var); /* Append <value/> elements' cdata */ while (field->values) { - append_escaped_string(context, field->values->data); + append_escaped_string(hash, field->values->data); g_free(field->values->data); field->values = g_list_delete_link(field->values, field->values); @@ -900,16 +910,17 @@ } /* generate hash */ - success = purple_cipher_context_digest(context, checksum, checksum_size); - checksum_size = purple_cipher_context_get_digest_size(context); + success = purple_hash_digest(hash, checksum, checksum_size); + checksum_size = purple_hash_get_digest_size(hash); - purple_cipher_context_destroy(context); + g_object_unref(hash); return (success ? purple_base64_encode(checksum, checksum_size) : NULL); } void jabber_caps_calculate_own_hash(JabberStream *js) { JabberCapsClientInfo info; + PurpleHash *hasher; GList *iter = 0; GList *features = 0; @@ -940,7 +951,9 @@ info.forms = NULL; g_free(js->caps_hash); - js->caps_hash = jabber_caps_calculate_hash(&info, "sha1"); + hasher = purple_sha1_hash_new(); + js->caps_hash = jabber_caps_calculate_hash(&info, hasher); + g_object_unref(hasher); g_list_free(info.identities); g_list_free(info.features); }
--- a/libpurple/protocols/jabber/caps.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/jabber/caps.h Sun Jun 23 13:35:53 2013 +0530 @@ -27,6 +27,7 @@ typedef struct _JabberCapsClientInfo JabberCapsClientInfo; #include "jabber.h" +#include "hash.h" /* Implementation of XEP-0115 - Entity Capabilities */ @@ -98,7 +99,7 @@ * @param hash Hash cipher to be used. Either sha-1 or md5. * @return The base64 encoded SHA-1 hash; must be freed by caller */ -gchar *jabber_caps_calculate_hash(JabberCapsClientInfo *info, const char *hash); +gchar *jabber_caps_calculate_hash(JabberCapsClientInfo *info, PurpleHash *hash); /** * Calculate SHA1 hash for own featureset.
--- a/libpurple/protocols/jabber/google/google_roster.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/jabber/google/google_roster.c Sun Jun 23 13:35:53 2013 +0530 @@ -28,7 +28,7 @@ void jabber_google_roster_outgoing(JabberStream *js, xmlnode *query, xmlnode *item) { PurpleAccount *account = purple_connection_get_account(js->gc); - GSList *list = account->deny; + GSList *list = purple_account_privacy_get_denied(account); const char *jid = xmlnode_get_attrib(item, "jid"); char *jid_norm = (char *)jabber_normalize(account, jid); @@ -64,8 +64,8 @@ jid_norm = g_strdup(jabber_normalize(account, jid)); - on_block_list = NULL != g_slist_find_custom(account->deny, jid_norm, - (GCompareFunc)strcmp); + on_block_list = NULL != g_slist_find_custom(purple_account_privacy_get_denied(account), + jid_norm, (GCompareFunc)strcmp); if (grt && (*grt == 'H' || *grt == 'h')) { /* Hidden; don't show this buddy. */ @@ -86,10 +86,10 @@ if (!on_block_list && (grt && (*grt == 'B' || *grt == 'b'))) { purple_debug_info("jabber", "Blocking %s\n", jid_norm); - purple_privacy_deny_add(account, jid_norm, TRUE); + purple_account_privacy_deny_add(account, jid_norm, TRUE); } else if (on_block_list && (!grt || (*grt != 'B' && *grt != 'b' ))){ purple_debug_info("jabber", "Unblocking %s\n", jid_norm); - purple_privacy_deny_remove(account, jid_norm, TRUE); + purple_account_privacy_deny_remove(account, jid_norm, TRUE); } g_free(jid_norm);
--- a/libpurple/protocols/jabber/jabber.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/jabber/jabber.c Sun Jun 23 13:35:53 2013 +0530 @@ -35,7 +35,6 @@ #include "message.h" #include "notify.h" #include "pluginpref.h" -#include "privacy.h" #include "proxy.h" #include "prpl.h" #include "request.h" @@ -392,8 +391,11 @@ static void jabber_send_cb(gpointer data, gint source, PurpleInputCondition cond) { JabberStream *js = data; + const gchar *output = NULL; int ret, writelen; - writelen = purple_circ_buffer_get_max_read(js->write_buffer); + + writelen = purple_circular_buffer_get_max_read(js->write_buffer); + output = purple_circular_buffer_get_output(js->write_buffer); if (writelen == 0) { purple_input_remove(js->writeh); @@ -401,7 +403,7 @@ return; } - ret = jabber_do_send(js, js->write_buffer->outptr, writelen); + ret = jabber_do_send(js, output, writelen); if (ret < 0 && errno == EAGAIN) return; @@ -414,7 +416,7 @@ return; } - purple_circ_buffer_mark_read(js->write_buffer, ret); + purple_circular_buffer_mark_read(js->write_buffer, ret); } static gboolean do_jabber_send_raw(JabberStream *js, const char *data, int len) @@ -457,7 +459,7 @@ js->writeh = purple_input_add( js->gsc ? js->gsc->fd : js->fd, PURPLE_INPUT_WRITE, jabber_send_cb, js); - purple_circ_buffer_append(js->write_buffer, + purple_circular_buffer_append(js->write_buffer, data + ret, len - ret); } @@ -994,7 +996,7 @@ js->chats = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)jabber_chat_free); js->next_id = g_random_int(); - js->write_buffer = purple_circ_buffer_new(512); + js->write_buffer = purple_circular_buffer_new(512); js->old_length = 0; js->keepalive_timeout = 0; js->max_inactivity = DEFAULT_INACTIVITY_TIME; @@ -1419,7 +1421,7 @@ if((node = xmlnode_get_child(query, "name"))) { if(js->registration) field = purple_request_field_string_new("name", _("Name"), - purple_account_get_alias(purple_connection_get_account(js->gc)), FALSE); + purple_account_get_private_alias(purple_connection_get_account(js->gc)), FALSE); else { char *data = xmlnode_get_data(node); field = purple_request_field_string_new("name", _("Name"), data, FALSE); @@ -1653,7 +1655,7 @@ g_free(js->caps_hash); if (js->write_buffer) - purple_circ_buffer_destroy(js->write_buffer); + g_object_unref(G_OBJECT(js->write_buffer)); if(js->writeh) purple_input_remove(js->writeh); if (js->auth_mech && js->auth_mech->dispose) @@ -1796,6 +1798,7 @@ xmlnode *item; PurpleAccount *account; gboolean is_block; + GSList *deny; if (!jabber_is_own_account(js, from)) { xmlnode *error, *x; @@ -1821,8 +1824,8 @@ /* Unblock everyone */ purple_debug_info("jabber", "Received unblock push. Unblocking everyone.\n"); - while (account->deny != NULL) { - purple_privacy_deny_remove(account, account->deny->data, TRUE); + while ((deny = purple_account_privacy_get_denied(account)) != NULL) { + purple_account_privacy_deny_remove(account, deny->data, TRUE); } } else if (item == NULL) { /* An empty <block/> is bogus */ @@ -1844,9 +1847,9 @@ continue; if (is_block) - purple_privacy_deny_add(account, jid, TRUE); + purple_account_privacy_deny_add(account, jid, TRUE); else - purple_privacy_deny_remove(account, jid, TRUE); + purple_account_privacy_deny_remove(account, jid, TRUE); } } @@ -1861,6 +1864,7 @@ { xmlnode *blocklist, *item; PurpleAccount *account; + GSList *deny; blocklist = xmlnode_get_child_with_namespace(packet, "blocklist", NS_SIMPLE_BLOCKING); @@ -1870,19 +1874,19 @@ return; /* This is the only privacy method supported by XEP-0191 */ - purple_account_set_privacy_type(account, PURPLE_PRIVACY_DENY_USERS); + purple_account_set_privacy_type(account, PURPLE_ACCOUNT_PRIVACY_DENY_USERS); /* * TODO: When account->deny is something more than a hash table, this can * be re-written to find the set intersection and difference. */ - while (account->deny) - purple_privacy_deny_remove(account, account->deny->data, TRUE); + while ((deny = purple_account_privacy_get_denied(account))) + purple_account_privacy_deny_remove(account, deny->data, TRUE); item = xmlnode_get_child(blocklist, "item"); while (item != NULL) { const char *jid = xmlnode_get_attrib(item, "jid"); - purple_privacy_deny_add(account, jid, TRUE); + purple_account_privacy_deny_add(account, jid, TRUE); item = xmlnode_get_next_twin(item); } }
--- a/libpurple/protocols/jabber/jabber.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/jabber/jabber.h Sun Jun 23 13:35:53 2013 +0530 @@ -56,7 +56,7 @@ #include <libxml/parser.h> #include <glib.h> -#include "circbuffer.h" +#include "circularbuffer.h" #include "connection.h" #include "dnsquery.h" #include "dnssrv.h" @@ -190,7 +190,7 @@ GSList *pending_buddy_info_requests; - PurpleCircBuffer *write_buffer; + PurpleCircularBuffer *write_buffer; guint writeh; gboolean reinit;
--- a/libpurple/protocols/jabber/jutil.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/jabber/jutil.c Sun Jun 23 13:35:53 2013 +0530 @@ -22,7 +22,6 @@ */ #include "internal.h" #include "account.h" -#include "cipher.h" #include "conversation.h" #include "debug.h" #include "server.h" @@ -33,6 +32,10 @@ #include "presence.h" #include "jutil.h" +#include "ciphers/md4hash.h" +#include "ciphers/md5hash.h" +#include "ciphers/sha1hash.h" + #ifdef USE_IDN #include <idna.h> #include <stringprep.h> @@ -736,25 +739,31 @@ jabber_calculate_data_hash(gconstpointer data, size_t len, const gchar *hash_algo) { - PurpleCipherContext *context; + PurpleHash *hash = NULL; static gchar digest[129]; /* 512 bits hex + \0 */ - context = purple_cipher_context_new_by_name(hash_algo, NULL); - if (context == NULL) + /* FIXME: Check the source of this change and what we need here... */ + if (g_str_equal(hash_algo, "sha1")) + hash = purple_sha1_hash_new(); + else if (g_str_equal(hash_algo, "md4")) + hash = purple_md4_hash_new(); + else if (g_str_equal(hash_algo, "md5")) + hash = purple_md5_hash_new(); + if (hash == NULL) { purple_debug_error("jabber", "Could not find %s cipher\n", hash_algo); g_return_val_if_reached(NULL); } /* Hash the data */ - purple_cipher_context_append(context, data, len); - if (!purple_cipher_context_digest_to_str(context, digest, sizeof(digest))) + purple_hash_append(hash, data, len); + if (!purple_hash_digest_to_str(hash, digest, sizeof(digest))) { purple_debug_error("jabber", "Failed to get digest for %s cipher.\n", hash_algo); g_return_val_if_reached(NULL); } - purple_cipher_context_destroy(context); + g_object_unref(G_OBJECT(hash)); return g_strdup(digest); }
--- a/libpurple/protocols/jabber/si.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/jabber/si.c Sun Jun 23 13:35:53 2013 +0530 @@ -71,7 +71,7 @@ JabberIBBSession *ibb_session; guint ibb_timeout_handle; - PurpleCircBuffer *ibb_buffer; + PurpleCircularBuffer *ibb_buffer; } JabberSIXfer; /* some forward declarations */ @@ -1011,7 +1011,7 @@ if (size <= purple_xfer_get_bytes_remaining(xfer)) { purple_debug_info("jabber", "about to write %" G_GSIZE_FORMAT " bytes from IBB stream\n", size); - purple_circ_buffer_append(jsx->ibb_buffer, data, size); + purple_circular_buffer_append(jsx->ibb_buffer, data, size); purple_xfer_prpl_ready(xfer); } else { /* trying to write past size of file transfers negotiated size, @@ -1028,15 +1028,15 @@ { JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); guchar *buffer; - gsize size; + gsize size = purple_circular_buffer_get_used(jsx->ibb_buffer); gsize tmp; - size = jsx->ibb_buffer->bufused; *out_buffer = buffer = g_malloc(size); - while ((tmp = purple_circ_buffer_get_max_read(jsx->ibb_buffer))) { - memcpy(buffer, jsx->ibb_buffer->outptr, tmp); + while ((tmp = purple_circular_buffer_get_max_read(jsx->ibb_buffer))) { + const gchar *output = purple_circular_buffer_get_output(jsx->ibb_buffer); + memcpy(buffer, output, tmp); buffer += tmp; - purple_circ_buffer_mark_read(jsx->ibb_buffer, tmp); + purple_circular_buffer_mark_read(jsx->ibb_buffer, tmp); } return size; @@ -1069,7 +1069,7 @@ clients interpreting the block-size attribute as that (see also remark in ibb.c) */ jsx->ibb_buffer = - purple_circ_buffer_new(jabber_ibb_session_get_block_size(sess)); + purple_circular_buffer_new(jabber_ibb_session_get_block_size(sess)); /* set up read function */ purple_xfer_set_read_fnc(xfer, jabber_si_xfer_ibb_read); @@ -1157,7 +1157,7 @@ purple_xfer_set_write_fnc(xfer, jabber_si_xfer_ibb_write); jsx->ibb_buffer = - purple_circ_buffer_new(jabber_ibb_session_get_max_data_size(jsx->ibb_session)); + purple_circular_buffer_new(jabber_ibb_session_get_max_data_size(jsx->ibb_session)); /* open the IBB session */ jabber_ibb_session_open(jsx->ibb_session); @@ -1334,7 +1334,7 @@ } if (jsx->ibb_buffer) { - purple_circ_buffer_destroy(jsx->ibb_buffer); + g_object_unref(G_OBJECT(jsx->ibb_buffer)); } purple_debug_info("jabber", "jabber_si_xfer_free(): freeing jsx %p\n", jsx);
--- a/libpurple/protocols/msn/contact.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/msn/contact.c Sun Jun 23 13:35:53 2013 +0530 @@ -1664,10 +1664,10 @@ msn_add_contact_to_list(session, new_state, state->who, MSN_LIST_RL); return; } else if (state->list_id == MSN_LIST_AL) { - purple_privacy_permit_remove(session->account, state->who, TRUE); + purple_account_privacy_permit_remove(session->account, state->who, TRUE); msn_add_contact_to_list(session, NULL, state->who, MSN_LIST_BL); } else if (state->list_id == MSN_LIST_BL) { - purple_privacy_deny_remove(session->account, state->who, TRUE); + purple_account_privacy_deny_remove(session->account, state->who, TRUE); msn_add_contact_to_list(session, NULL, state->who, MSN_LIST_AL); } @@ -1764,9 +1764,9 @@ if (state->action & MSN_DENIED_BUDDY) { msn_add_contact_to_list(state->session, NULL, state->who, MSN_LIST_BL); } else if (state->list_id == MSN_LIST_AL) { - purple_privacy_permit_add(state->session->account, state->who, TRUE); + purple_account_privacy_permit_add(state->session->account, state->who, TRUE); } else if (state->list_id == MSN_LIST_BL) { - purple_privacy_deny_add(state->session->account, state->who, TRUE); + purple_account_privacy_deny_add(state->session->account, state->who, TRUE); } } }
--- a/libpurple/protocols/msn/directconn.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/msn/directconn.c Sun Jun 23 13:35:53 2013 +0530 @@ -23,7 +23,7 @@ */ #include "internal.h" -#include "cipher.h" +#include "ciphers/sha1hash.h" #include "debug.h" #include "msn.h" @@ -44,11 +44,10 @@ guchar digest[20]; if (type == DC_NONCE_SHA1) { - PurpleCipher *cipher = purple_ciphers_find_cipher("sha1"); - PurpleCipherContext *context = purple_cipher_context_new(cipher, NULL); - purple_cipher_context_append(context, nonce, nonce_len); - purple_cipher_context_digest(context, digest, sizeof(digest)); - purple_cipher_context_destroy(context); + PurpleHash *hash = purple_sha1_hash_new(); + purple_hash_append(hash, nonce, nonce_len); + purple_hash_digest(hash, digest, sizeof(digest)); + g_object_unref(hash); } else if (type == DC_NONCE_PLAIN) { memcpy(digest, nonce, nonce_len); } else {
--- a/libpurple/protocols/msn/directconn.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/msn/directconn.h Sun Jun 23 13:35:53 2013 +0530 @@ -28,7 +28,7 @@ #include "network.h" #include "proxy.h" -#include "circbuffer.h" +#include "circularbuffer.h" #include "slp.h" #include "slplink.h"
--- a/libpurple/protocols/msn/httpconn.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/msn/httpconn.c Sun Jun 23 13:35:53 2013 +0530 @@ -353,9 +353,11 @@ MsnHttpConn *httpconn; gssize ret; int writelen; + const gchar *output = NULL; httpconn = data; - writelen = purple_circ_buffer_get_max_read(httpconn->tx_buf); + writelen = purple_circular_buffer_get_max_read(httpconn->tx_buf); + output = purple_circular_buffer_get_output(httpconn->tx_buf); if (writelen == 0) { @@ -364,7 +366,7 @@ return; } - ret = write(httpconn->fd, httpconn->tx_buf->outptr, writelen); + ret = write(httpconn->fd, output, writelen); if (ret <= 0) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) @@ -376,7 +378,7 @@ return; } - purple_circ_buffer_mark_read(httpconn->tx_buf, ret); + purple_circular_buffer_mark_read(httpconn->tx_buf, ret); /* TODO: I don't think these 2 lines are needed. Remove them? */ if (ret == writelen) @@ -409,7 +411,7 @@ if (httpconn->tx_handler == 0 && httpconn->fd) httpconn->tx_handler = purple_input_add(httpconn->fd, PURPLE_INPUT_WRITE, httpconn_write_cb, httpconn); - purple_circ_buffer_append(httpconn->tx_buf, data + res, + purple_circular_buffer_append(httpconn->tx_buf, data + res, data_len - res); } @@ -612,7 +614,7 @@ httpconn->servconn = servconn; - httpconn->tx_buf = purple_circ_buffer_new(MSN_BUF_LEN); + httpconn->tx_buf = purple_circular_buffer_new(MSN_BUF_LEN); httpconn->tx_handler = 0; httpconn->fd = -1; @@ -647,7 +649,7 @@ g_free(queue_data); } - purple_circ_buffer_destroy(httpconn->tx_buf); + g_object_unref(G_OBJECT(httpconn->tx_buf)); if (httpconn->tx_handler > 0) purple_input_remove(httpconn->tx_handler);
--- a/libpurple/protocols/msn/httpconn.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/msn/httpconn.h Sun Jun 23 13:35:53 2013 +0530 @@ -26,7 +26,7 @@ typedef struct _MsnHttpConn MsnHttpConn; -#include "circbuffer.h" +#include "circularbuffer.h" #include "servconn.h" #include "session.h" @@ -61,7 +61,7 @@ char *rx_buf; /**< The receive buffer. */ int rx_len; /**< The receive buffer length. */ - PurpleCircBuffer *tx_buf; + PurpleCircularBuffer *tx_buf; guint tx_handler; };
--- a/libpurple/protocols/msn/msn.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/msn/msn.c Sun Jun 23 13:35:53 2013 +0530 @@ -814,8 +814,8 @@ session = purple_connection_get_protocol_data(gc); cmdproc = session->notification->cmdproc; - if (purple_account_get_privacy_type(account) == PURPLE_PRIVACY_ALLOW_ALL || - purple_account_get_privacy_type(account) == PURPLE_PRIVACY_DENY_USERS) + if (purple_account_get_privacy_type(account) == PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL || + purple_account_get_privacy_type(account) == PURPLE_ACCOUNT_PRIVACY_DENY_USERS) trans = msn_transaction_new(cmdproc, "BLP", "%s", "AL"); else trans = msn_transaction_new(cmdproc, "BLP", "%s", "BL"); @@ -853,7 +853,7 @@ swboard->flag = MSN_SB_FLAG_IM; /* Local alias > Display name > Username */ - if ((alias = purple_account_get_alias(account)) == NULL) + if ((alias = purple_account_get_private_alias(account)) == NULL) if ((alias = purple_connection_get_display_name(gc)) == NULL) alias = purple_account_get_username(account);
--- a/libpurple/protocols/msn/msnutils.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/msn/msnutils.c Sun Jun 23 13:35:53 2013 +0530 @@ -27,7 +27,7 @@ #include "msn.h" #include "msnutils.h" -#include "cipher.h" +#include "ciphers/md5hash.h" /************************************************************************** * Util @@ -542,8 +542,7 @@ void msn_handle_chl(char *input, char *output) { - PurpleCipher *cipher; - PurpleCipherContext *context; + PurpleHash *hash; const guchar productKey[] = MSNP15_WLM_PRODUCT_KEY; const guchar productID[] = MSNP15_WLM_PRODUCT_ID; const char hexChars[] = "0123456789abcdef"; @@ -560,13 +559,12 @@ int i; /* Create the MD5 hash by using Purple MD5 algorithm */ - cipher = purple_ciphers_find_cipher("md5"); - context = purple_cipher_context_new(cipher, NULL); + hash = purple_md5_hash_new(); - purple_cipher_context_append(context, (guchar *)input, strlen(input)); - purple_cipher_context_append(context, productKey, sizeof(productKey) - 1); - purple_cipher_context_digest(context, md5Hash, sizeof(md5Hash)); - purple_cipher_context_destroy(context); + purple_hash_append(hash, (guchar *)input, strlen(input)); + purple_hash_append(hash, productKey, sizeof(productKey) - 1); + purple_hash_digest(hash, md5Hash, sizeof(md5Hash)); + g_object_unref(hash); /* Split it into four integers */ md5Parts = (unsigned int *)md5Hash;
--- a/libpurple/protocols/msn/nexus.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/msn/nexus.c Sun Jun 23 13:35:53 2013 +0530 @@ -23,7 +23,6 @@ */ #include "internal.h" -#include "cipher.h" #include "debug.h" #include "msnutils.h" @@ -31,6 +30,10 @@ #include "nexus.h" #include "notification.h" +#include "ciphers/des3cipher.h" +#include "ciphers/hmaccipher.h" +#include "ciphers/sha1hash.h" + /************************************************************************** * Valid Ticket Tokens **************************************************************************/ @@ -99,35 +102,37 @@ const guchar magic[] = "WS-SecureConversation"; const int magic_len = sizeof(magic) - 1; - PurpleCipherContext *hmac; + PurpleCipher *hmac; + PurpleHash *hash; guchar hash1[20], hash2[20], hash3[20], hash4[20]; char *result; - hmac = purple_cipher_context_new_by_name("hmac", NULL); - purple_cipher_context_set_option(hmac, "hash", "sha1"); - purple_cipher_context_set_key(hmac, (guchar *)key, key_len); + hash = purple_sha1_hash_new(); + hmac = purple_hmac_cipher_new(hash); + purple_cipher_set_key(hmac, (guchar *)key, key_len); - purple_cipher_context_append(hmac, magic, magic_len); - purple_cipher_context_append(hmac, (guchar *)data, data_len); - purple_cipher_context_digest(hmac, hash1, sizeof(hash1)); + purple_cipher_append(hmac, magic, magic_len); + purple_cipher_append(hmac, (guchar *)data, data_len); + purple_cipher_digest(hmac, hash1, sizeof(hash1)); - purple_cipher_context_reset_state(hmac, NULL); - purple_cipher_context_append(hmac, hash1, 20); - purple_cipher_context_append(hmac, magic, magic_len); - purple_cipher_context_append(hmac, (guchar *)data, data_len); - purple_cipher_context_digest(hmac, hash2, sizeof(hash2)); + purple_cipher_reset_state(hmac); + purple_cipher_append(hmac, hash1, 20); + purple_cipher_append(hmac, magic, magic_len); + purple_cipher_append(hmac, (guchar *)data, data_len); + purple_cipher_digest(hmac, hash2, sizeof(hash2)); - purple_cipher_context_reset_state(hmac, NULL); - purple_cipher_context_append(hmac, hash1, 20); - purple_cipher_context_digest(hmac, hash3, sizeof(hash3)); + purple_cipher_reset_state(hmac); + purple_cipher_append(hmac, hash1, 20); + purple_cipher_digest(hmac, hash3, sizeof(hash3)); - purple_cipher_context_reset_state(hmac, NULL); - purple_cipher_context_append(hmac, hash3, sizeof(hash3)); - purple_cipher_context_append(hmac, magic, magic_len); - purple_cipher_context_append(hmac, (guchar *)data, data_len); - purple_cipher_context_digest(hmac, hash4, sizeof(hash4)); + purple_cipher_reset_state(hmac); + purple_cipher_append(hmac, hash3, sizeof(hash3)); + purple_cipher_append(hmac, magic, magic_len); + purple_cipher_append(hmac, (guchar *)data, data_len); + purple_cipher_digest(hmac, hash4, sizeof(hash4)); - purple_cipher_context_destroy(hmac); + g_object_unref(hmac); + g_object_unref(hash); result = g_malloc(24); memcpy(result, hash2, sizeof(hash2)); @@ -139,21 +144,21 @@ static char * des3_cbc(const char *key, const char *iv, const char *data, int len, gboolean decrypt) { - PurpleCipherContext *des3; + PurpleCipher *des3; char *out; - des3 = purple_cipher_context_new_by_name("des3", NULL); - purple_cipher_context_set_key(des3, (guchar *)key, 24); - purple_cipher_context_set_batch_mode(des3, PURPLE_CIPHER_BATCH_MODE_CBC); - purple_cipher_context_set_iv(des3, (guchar *)iv, 8); + des3 = purple_des3_cipher_new(); + purple_cipher_set_key(des3, (guchar *)key, 24); + purple_cipher_set_batch_mode(des3, PURPLE_CIPHER_BATCH_MODE_CBC); + purple_cipher_set_iv(des3, (guchar *)iv, 8); out = g_malloc(len); if (decrypt) - purple_cipher_context_decrypt(des3, (guchar *)data, len, (guchar *)out, len); + purple_cipher_decrypt(des3, (guchar *)data, len, (guchar *)out, len); else - purple_cipher_context_encrypt(des3, (guchar *)data, len, (guchar *)out, len); + purple_cipher_encrypt(des3, (guchar *)data, len, (guchar *)out, len); - purple_cipher_context_destroy(des3); + g_object_unref(des3); return out; } @@ -168,7 +173,8 @@ char usr_key_base[MSN_USER_KEY_SIZE], *usr_key; const char magic1[] = "SESSION KEY HASH"; const char magic2[] = "SESSION KEY ENCRYPTION"; - PurpleCipherContext *hmac; + PurpleCipher *hmac; + PurpleHash *hasher; size_t len; guchar *hash; char *key1, *key2, *key3; @@ -199,12 +205,13 @@ key3 = rps_create_key(key1, key1_len, magic2, sizeof(magic2) - 1); len = strlen(nexus->nonce); - hmac = purple_cipher_context_new_by_name("hmac", NULL); - purple_cipher_context_set_option(hmac, "hash", "sha1"); - purple_cipher_context_set_key(hmac, (guchar *)key2, 24); - purple_cipher_context_append(hmac, (guchar *)nexus->nonce, len); - purple_cipher_context_digest(hmac, hash, 20); - purple_cipher_context_destroy(hmac); + hasher = purple_sha1_hash_new(); + hmac = purple_hmac_cipher_new(hasher); + purple_cipher_set_key(hmac, (guchar *)key2, 24); + purple_cipher_append(hmac, (guchar *)nexus->nonce, len); + purple_cipher_digest(hmac, hash, 20); + g_object_unref(hmac); + g_object_unref(hasher); /* We need to pad this to 72 bytes, apparently */ nonce_fixed = g_malloc(len + 8); @@ -508,8 +515,8 @@ MsnSession *session = nexus->session; MsnNexusUpdateData *ud; MsnNexusUpdateCallback *update; - PurpleCipherContext *sha1; - PurpleCipherContext *hmac; + PurpleHash *sha1; + PurpleCipher *hmac; char *key; @@ -560,7 +567,7 @@ ud->nexus = nexus; ud->id = id; - sha1 = purple_cipher_context_new_by_name("sha1", NULL); + sha1 = purple_sha1_hash_new(); domain = g_strdup_printf(MSN_SSO_RST_TEMPLATE, id, @@ -568,8 +575,8 @@ ticket_domains[id][SSO_VALID_TICKET_POLICY] != NULL ? ticket_domains[id][SSO_VALID_TICKET_POLICY] : nexus->policy); - purple_cipher_context_append(sha1, (guchar *)domain, strlen(domain)); - purple_cipher_context_digest(sha1, digest, 20); + purple_hash_append(sha1, (guchar *)domain, strlen(domain)); + purple_hash_digest(sha1, digest, 20); domain_b64 = purple_base64_encode(digest, 20); now = time(NULL); @@ -580,13 +587,13 @@ timestamp = g_strdup_printf(MSN_SSO_TIMESTAMP_TEMPLATE, now_str, purple_utf8_strftime("%Y-%m-%dT%H:%M:%SZ", tm)); - purple_cipher_context_reset(sha1, NULL); - purple_cipher_context_append(sha1, (guchar *)timestamp, strlen(timestamp)); - purple_cipher_context_digest(sha1, digest, 20); + purple_hash_reset(sha1); + purple_hash_append(sha1, (guchar *)timestamp, strlen(timestamp)); + purple_hash_digest(sha1, digest, 20); timestamp_b64 = purple_base64_encode(digest, 20); g_free(now_str); - purple_cipher_context_destroy(sha1); + purple_hash_reset(sha1); signedinfo = g_strdup_printf(MSN_SSO_SIGNEDINFO_TEMPLATE, id, @@ -598,12 +605,14 @@ nonce_b64 = purple_base64_encode((guchar *)&nonce, sizeof(nonce)); key = rps_create_key(nexus->secret, 24, (char *)nonce, sizeof(nonce)); - hmac = purple_cipher_context_new_by_name("hmac", NULL); - purple_cipher_context_set_option(hmac, "hash", "sha1"); - purple_cipher_context_set_key(hmac, (guchar *)key, 24); - purple_cipher_context_append(hmac, (guchar *)signedinfo, strlen(signedinfo)); - purple_cipher_context_digest(hmac, signature, 20); - purple_cipher_context_destroy(hmac); + hmac = purple_hmac_cipher_new(sha1); + purple_cipher_set_key(hmac, (guchar *)key, 24); + purple_cipher_append(hmac, (guchar *)signedinfo, strlen(signedinfo)); + purple_cipher_digest(hmac, signature, 20); + + g_object_unref(hmac); + g_object_unref(sha1); + signature_b64 = purple_base64_encode(signature, 20); request = g_strdup_printf(MSN_SSO_TOKEN_UPDATE_TEMPLATE,
--- a/libpurple/protocols/msn/notification.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/msn/notification.c Sun Jun 23 13:35:53 2013 +0530 @@ -23,7 +23,7 @@ */ #include "internal.h" -#include "cipher.h" +#include "ciphers/md5hash.h" #include "core.h" #include "debug.h" @@ -1394,7 +1394,7 @@ PurpleAccount *account; const char *rru; const char *url; - PurpleCipherContext *cipher; + PurpleHash *hash; gchar creds[33]; char *buf; @@ -1415,10 +1415,10 @@ tmp_timestamp, purple_connection_get_password(gc)); - cipher = purple_cipher_context_new_by_name("md5", NULL); - purple_cipher_context_append(cipher, (const guchar *)buf, strlen(buf)); - purple_cipher_context_digest_to_str(cipher, creds, sizeof(creds)); - purple_cipher_context_destroy(cipher); + hash = purple_md5_hash_new(); + purple_hash_append(hash, (const guchar *)buf, strlen(buf)); + purple_hash_digest_to_str(hash, creds, sizeof(creds)); + g_object_unref(hash); g_free(buf); g_free(session->passport_info.mail_url);
--- a/libpurple/protocols/msn/object.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/msn/object.c Sun Jun 23 13:35:53 2013 +0530 @@ -26,7 +26,7 @@ #include "object.h" #include "debug.h" /* Sha1 stuff */ -#include "cipher.h" +#include "ciphers/sha1hash.h" /* Base64 stuff */ #include "util.h" @@ -130,7 +130,7 @@ { MsnObject *msnobj; - PurpleCipherContext *ctx; + PurpleHash *hash; char *buf; gconstpointer data; size_t size; @@ -157,9 +157,9 @@ /* Compute the SHA1D field. */ memset(digest, 0, sizeof(digest)); - ctx = purple_cipher_context_new_by_name("sha1", NULL); - purple_cipher_context_append(ctx, data, size); - purple_cipher_context_digest(ctx, digest, sizeof(digest)); + hash = purple_sha1_hash_new(); + purple_hash_append(hash, data, size); + purple_hash_digest(hash, digest, sizeof(digest)); base64 = purple_base64_encode(digest, sizeof(digest)); msn_object_set_sha1d(msnobj, base64); @@ -179,10 +179,10 @@ memset(digest, 0, sizeof(digest)); - purple_cipher_context_reset(ctx, NULL); - purple_cipher_context_append(ctx, (const guchar *)buf, strlen(buf)); - purple_cipher_context_digest(ctx, digest, sizeof(digest)); - purple_cipher_context_destroy(ctx); + purple_hash_reset(hash); + purple_hash_append(hash, (const guchar *)buf, strlen(buf)); + purple_hash_digest(hash, digest, sizeof(digest)); + g_object_unref(hash); g_free(buf); base64 = purple_base64_encode(digest, sizeof(digest));
--- a/libpurple/protocols/msn/servconn.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/msn/servconn.c Sun Jun 23 13:35:53 2013 +0530 @@ -53,7 +53,7 @@ servconn->num = session->servconns_count++; - servconn->tx_buf = purple_circ_buffer_new(MSN_BUF_LEN); + servconn->tx_buf = purple_circular_buffer_new(MSN_BUF_LEN); servconn->tx_handler = 0; servconn->timeout_sec = 0; servconn->timeout_handle = 0; @@ -84,7 +84,7 @@ g_free(servconn->host); - purple_circ_buffer_destroy(servconn->tx_buf); + g_object_unref(G_OBJECT(servconn->tx_buf)); if (servconn->tx_handler > 0) purple_input_remove(servconn->tx_handler); if (servconn->timeout_handle > 0) @@ -334,8 +334,10 @@ MsnServConn *servconn = data; gssize ret; int writelen; + const gchar *output = NULL; - writelen = purple_circ_buffer_get_max_read(servconn->tx_buf); + writelen = purple_circular_buffer_get_max_read(servconn->tx_buf); + output = purple_circular_buffer_get_output(servconn->tx_buf); if (writelen == 0) { purple_input_remove(servconn->tx_handler); @@ -343,7 +345,7 @@ return; } - ret = write(servconn->fd, servconn->tx_buf->outptr, writelen); + ret = write(servconn->fd, output, writelen); if (ret < 0 && errno == EAGAIN) return; @@ -352,7 +354,7 @@ return; } - purple_circ_buffer_mark_read(servconn->tx_buf, ret); + purple_circular_buffer_mark_read(servconn->tx_buf, ret); servconn_timeout_renew(servconn); } @@ -394,7 +396,7 @@ servconn->tx_handler = purple_input_add( servconn->fd, PURPLE_INPUT_WRITE, servconn_write_cb, servconn); - purple_circ_buffer_append(servconn->tx_buf, buf + ret, + purple_circular_buffer_append(servconn->tx_buf, buf + ret, len - ret); } }
--- a/libpurple/protocols/msn/servconn.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/msn/servconn.h Sun Jun 23 13:35:53 2013 +0530 @@ -85,7 +85,7 @@ It's only set when we've received a command that has a payload. */ - PurpleCircBuffer *tx_buf; + PurpleCircularBuffer *tx_buf; guint tx_handler; guint timeout_sec; guint timeout_handle;
--- a/libpurple/protocols/msn/userlist.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/msn/userlist.c Sun Jun 23 13:35:53 2013 +0530 @@ -59,8 +59,8 @@ PurpleAccount *account = purple_connection_get_account(pa->gc); msn_userlist_add_buddy_to_list(userlist, pa->who, MSN_LIST_AL); - purple_privacy_deny_remove(account, pa->who, TRUE); - purple_privacy_permit_add(account, pa->who, TRUE); + purple_account_privacy_deny_remove(account, pa->who, TRUE); + purple_account_privacy_permit_add(account, pa->who, TRUE); msn_del_contact_from_list(session, NULL, pa->who, MSN_LIST_PL); } @@ -152,15 +152,15 @@ if (list_op & MSN_LIST_AL_OP) { /* These are users who are allowed to see our status. */ - purple_privacy_deny_remove(account, passport, TRUE); - purple_privacy_permit_add(account, passport, TRUE); + purple_account_privacy_deny_remove(account, passport, TRUE); + purple_account_privacy_permit_add(account, passport, TRUE); } if (list_op & MSN_LIST_BL_OP) { /* These are users who are not allowed to see our status. */ - purple_privacy_permit_remove(account, passport, TRUE); - purple_privacy_deny_add(account, passport, TRUE); + purple_account_privacy_permit_remove(account, passport, TRUE); + purple_account_privacy_deny_add(account, passport, TRUE); } if (list_op & MSN_LIST_RL_OP) @@ -742,13 +742,13 @@ purple_buddy_set_protocol_data(buddy, user); msn_user_set_op(user, MSN_LIST_FL_OP); } - for (l = session->account->permit; l != NULL; l = l->next) + for (l = purple_account_privacy_get_permitted(session->account); l != NULL; l = l->next) { user = msn_userlist_find_add_user(session->userlist, (char *)l->data,NULL); msn_user_set_op(user, MSN_LIST_AL_OP); } - for (l = session->account->deny; l != NULL; l = l->next) + for (l = purple_account_privacy_get_denied(session->account); l != NULL; l = l->next) { user = msn_userlist_find_add_user(session->userlist, (char *)l->data,NULL);
--- a/libpurple/protocols/mxit/multimx.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/mxit/multimx.c Sun Jun 23 13:35:53 2013 +0530 @@ -638,7 +638,7 @@ if (multimx->nickname) nickname = multimx->nickname; else - nickname = purple_account_get_alias(purple_connection_get_account(gc)); /* local alias */ + nickname = purple_account_get_private_alias(purple_connection_get_account(gc)); /* local alias */ /* Display message in chat window */ serv_got_chat_in(gc, id, nickname, flags, message, time(NULL));
--- a/libpurple/protocols/myspace/myspace.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/myspace/myspace.c Sun Jun 23 13:35:53 2013 +0530 @@ -36,8 +36,6 @@ #include "myspace.h" -#include "privacy.h" - static void msim_set_status(PurpleAccount *account, PurpleStatus *status); static void msim_set_idle(PurpleConnection *gc, int time); @@ -532,9 +530,8 @@ msim_compute_login_response(const gchar nonce[2 * NONCE_SIZE], const gchar *email, const gchar *password, guint *response_len) { - PurpleCipherContext *key_context; - PurpleCipher *sha1; - PurpleCipherContext *rc4; + PurpleHash *sha1; + PurpleCipher *rc4; guchar hash_pw[HASH_SIZE]; guchar key[HASH_SIZE]; @@ -583,8 +580,11 @@ } /* Compute password hash */ - purple_cipher_digest_region("sha1", (guchar *)password_utf16le, - conv_bytes_written, hash_pw, sizeof(hash_pw)); + sha1 = purple_sha1_hash_new(); + purple_hash_append(sha1, (guchar *)password_utf16le, + conv_bytes_written); + purple_hash_digest(sha1, hash_pw, sizeof(hash_pw)); + purple_hash_reset(sha1); g_free(password_utf16le); #ifdef MSIM_DEBUG_LOGIN_CHALLENGE @@ -595,12 +595,10 @@ #endif /* key = sha1(sha1(pw) + nonce2) */ - sha1 = purple_ciphers_find_cipher("sha1"); - key_context = purple_cipher_context_new(sha1, NULL); - purple_cipher_context_append(key_context, hash_pw, HASH_SIZE); - purple_cipher_context_append(key_context, (guchar *)(nonce + NONCE_SIZE), NONCE_SIZE); - purple_cipher_context_digest(key_context, key, sizeof(key)); - purple_cipher_context_destroy(key_context); + purple_hash_append(sha1, hash_pw, HASH_SIZE); + purple_hash_append(sha1, (guchar *)(nonce + NONCE_SIZE), NONCE_SIZE); + purple_hash_digest(sha1, key, sizeof(key)); + g_object_unref(sha1); #ifdef MSIM_DEBUG_LOGIN_CHALLENGE purple_debug_info("msim", "key = "); @@ -610,11 +608,11 @@ purple_debug_info("msim", "\n"); #endif - rc4 = purple_cipher_context_new_by_name("rc4", NULL); + rc4 = purple_rc4_cipher_new(); /* Note: 'key' variable is 0x14 bytes (from SHA-1 hash), * but only first 0x10 used for the RC4 key. */ - purple_cipher_context_set_key(rc4, key, 0x10); + purple_cipher_set_key(rc4, key, 0x10); /* rc4 encrypt: * nonce1+email+IP list */ @@ -640,9 +638,9 @@ data_out = g_new0(guchar, data->len); - data_out_len = purple_cipher_context_encrypt(rc4, + data_out_len = purple_cipher_encrypt(rc4, (const guchar *)data->str, data->len, data_out, data->len); - purple_cipher_context_destroy(rc4); + g_object_unref(rc4); if (data_out_len != data->len) { purple_debug_info("msim", "msim_compute_login_response: " @@ -1019,7 +1017,7 @@ visibility = msim_msg_get_integer(contact_info, "Visibility"); if (visibility == 2) { /* This buddy is blocked (and therefore not on our buddy list */ - purple_privacy_deny_add(session->account, username, TRUE); + purple_account_privacy_deny_add(session->account, username, TRUE); msim_msg_free(contact_info); g_free(username); g_free(display_name); @@ -2179,6 +2177,7 @@ { PurpleConnection *gc; const gchar *host; + GSList *deny; int port; g_return_if_fail(acct != NULL); @@ -2195,8 +2194,8 @@ * list of all blocked buddies from the server, and we shouldn't * have stuff in the local list that isn't on the server list. */ - while (acct->deny != NULL) - purple_privacy_deny_remove(acct, acct->deny->data, TRUE); + while ((deny = purple_account_privacy_get_denied(acct)) != NULL) + purple_account_privacy_deny_remove(acct, deny->data, TRUE); /* 1. connect to server */ purple_connection_update_progress(gc, _("Connecting"), @@ -3089,16 +3088,6 @@ static gboolean msim_load(PurplePlugin *plugin) { - /* If compiled to use RC4 from libpurple, check if it is really there. */ - if (!purple_ciphers_find_cipher("rc4")) { - purple_debug_error("msim", "rc4 not in libpurple, but it is required - not loading MySpaceIM plugin!\n"); - purple_notify_error(plugin, _("Missing Cipher"), - _("The RC4 cipher could not be found"), - _("Upgrade " - "to a libpurple with RC4 support (>= 2.0.1). MySpaceIM " - "plugin will not be loaded.")); - return FALSE; - } return TRUE; }
--- a/libpurple/protocols/myspace/myspace.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/myspace/myspace.h Sun Jun 23 13:35:53 2013 +0530 @@ -42,7 +42,6 @@ #include "plugin.h" #include "accountopt.h" #include "version.h" -#include "cipher.h" /* for SHA-1 */ #include "util.h" /* for base64 */ #include "debug.h" /* for purple_debug_info */ #include "request.h" /* For dialogs used in setting the username */ @@ -50,6 +49,10 @@ #include "core.h" #include "conversation.h" /* For late normalization */ +/* Ciphers */ +#include "ciphers/rc4cipher.h" +#include "ciphers/sha1hash.h" + /* MySpaceIM includes */ #include "persist.h" #include "message.h"
--- a/libpurple/protocols/novell/novell.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/novell/novell.c Sun Jun 23 13:35:53 2013 +0530 @@ -29,7 +29,6 @@ #include "sslconn.h" #include "request.h" #include "network.h" -#include "privacy.h" #include "status.h" #include "version.h" @@ -102,12 +101,12 @@ if (ret_code == NM_OK) { /* Set alias for user if not set (use Full Name) */ - alias = purple_account_get_alias(user->client_data); + alias = purple_account_get_private_alias(user->client_data); if (alias == NULL || *alias == '\0') { alias = nm_user_record_get_full_name(user->user_record); if (alias) - purple_account_set_alias(user->client_data, alias); + purple_account_set_private_alias(user->client_data, alias); } /* Tell Purple that we are connected */ @@ -726,6 +725,7 @@ gpointer resp_data, gpointer user_data) { PurpleConnection *gc; + PurpleAccount *account; NMUserRecord *user_record = resp_data; char *err; gboolean allowed = GPOINTER_TO_INT(user_data); @@ -736,21 +736,22 @@ gc = purple_account_get_connection(user->client_data); display_id = nm_user_record_get_display_id(user_record); + account = purple_connection_get_account(gc); if (ret_code == NM_OK) { if (allowed) { - if (!g_slist_find_custom(purple_connection_get_account(gc)->permit, + if (!g_slist_find_custom(purple_account_privacy_get_denied(account), display_id, (GCompareFunc)purple_utf8_strcasecmp)) { - purple_privacy_permit_add(purple_connection_get_account(gc), display_id, TRUE); + purple_account_privacy_permit_add(account, display_id, TRUE); } } else { - if (!g_slist_find_custom(purple_connection_get_account(gc)->permit, + if (!g_slist_find_custom(purple_account_privacy_get_denied(account), display_id, (GCompareFunc)purple_utf8_strcasecmp)) { - purple_privacy_deny_add(purple_connection_get_account(gc), display_id, TRUE); + purple_account_privacy_deny_add(account, display_id, TRUE); } } @@ -770,6 +771,7 @@ gpointer resp_data, gpointer user_data) { PurpleConnection *gc; + PurpleAccount *account; NMUserRecord *user_record; char *who = user_data; char *err; @@ -780,6 +782,7 @@ return; gc = purple_account_get_connection(user->client_data); + account = purple_connection_get_account(gc); if (ret_code == NM_OK) { @@ -789,10 +792,10 @@ if (display_id) { - if (!g_slist_find_custom(purple_connection_get_account(gc)->deny, + if (!g_slist_find_custom(purple_account_privacy_get_denied(account), display_id, (GCompareFunc)purple_utf8_strcasecmp)) { - purple_privacy_deny_add(purple_connection_get_account(gc), display_id, TRUE); + purple_account_privacy_deny_add(account, display_id, TRUE); } } else { @@ -821,6 +824,7 @@ gpointer resp_data, gpointer user_data) { PurpleConnection *gc; + PurpleAccount *account; NMUserRecord *user_record; char *who = user_data; char *err; @@ -831,6 +835,7 @@ return; gc = purple_account_get_connection(user->client_data); + account = purple_connection_get_account(gc); if (ret_code == NM_OK) { @@ -840,11 +845,11 @@ if (display_id) { - if (!g_slist_find_custom(purple_connection_get_account(gc)->permit, + if (!g_slist_find_custom(purple_account_privacy_get_permitted(account), display_id, (GCompareFunc)purple_utf8_strcasecmp)) { - purple_privacy_permit_add(purple_connection_get_account(gc), display_id, TRUE); + purple_account_privacy_permit_add(account, display_id, TRUE); } } else { @@ -1386,6 +1391,7 @@ { GSList *node = NULL, *rem_list = NULL; PurpleConnection *gc; + PurpleAccount *account; const char *name, *dn; NMUserRecord *user_record; @@ -1396,18 +1402,20 @@ if (gc == NULL) return; + account = purple_connection_get_account(gc); + /* Set the Purple privacy setting */ if (user->default_deny) { if (user->allow_list == NULL) { - purple_account_set_privacy_type(purple_connection_get_account(gc), PURPLE_PRIVACY_DENY_ALL); + purple_account_set_privacy_type(account, PURPLE_ACCOUNT_PRIVACY_DENY_ALL); } else { - purple_account_set_privacy_type(purple_connection_get_account(gc), PURPLE_PRIVACY_ALLOW_USERS); + purple_account_set_privacy_type(account, PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS); } } else { if (user->deny_list == NULL) { - purple_account_set_privacy_type(purple_connection_get_account(gc), PURPLE_PRIVACY_ALLOW_ALL); + purple_account_set_privacy_type(account, PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL); } else { - purple_account_set_privacy_type(purple_connection_get_account(gc), PURPLE_PRIVACY_DENY_USERS); + purple_account_set_privacy_type(account, PURPLE_ACCOUNT_PRIVACY_DENY_USERS); } } @@ -1419,9 +1427,9 @@ else name =(char *)node->data; - if (!g_slist_find_custom(purple_connection_get_account(gc)->permit, + if (!g_slist_find_custom(purple_account_privacy_get_permitted(account), name, (GCompareFunc)purple_utf8_strcasecmp)) { - purple_privacy_permit_add(purple_connection_get_account(gc), name , TRUE); + purple_account_privacy_permit_add(account, name , TRUE); } } @@ -1432,15 +1440,15 @@ else name =(char *)node->data; - if (!g_slist_find_custom(purple_connection_get_account(gc)->deny, + if (!g_slist_find_custom(purple_account_privacy_get_denied(account), name, (GCompareFunc)purple_utf8_strcasecmp)) { - purple_privacy_deny_add(purple_connection_get_account(gc), name, TRUE); + purple_account_privacy_deny_add(account, name, TRUE); } } /* Remove stuff */ - for (node = purple_connection_get_account(gc)->permit; node; node = node->next) { + for (node = purple_account_privacy_get_permitted(account); node; node = node->next) { dn = nm_lookup_dn(user, (char *)node->data); if (dn != NULL && !g_slist_find_custom(user->allow_list, @@ -1451,13 +1459,13 @@ if (rem_list) { for (node = rem_list; node; node = node->next) { - purple_privacy_permit_remove(purple_connection_get_account(gc), (char *)node->data, TRUE); + purple_account_privacy_permit_remove(account, (char *)node->data, TRUE); } g_slist_free(rem_list); rem_list = NULL; } - for (node = purple_connection_get_account(gc)->deny; node; node = node->next) { + for (node = purple_account_privacy_get_denied(account); node; node = node->next) { dn = nm_lookup_dn(user, (char *)node->data); if (dn != NULL && !g_slist_find_custom(user->deny_list, @@ -1468,7 +1476,7 @@ if (rem_list) { for (node = rem_list; node; node = node->next) { - purple_privacy_deny_remove(purple_connection_get_account(gc), (char *)node->data, TRUE); + purple_account_privacy_deny_remove(account, (char *)node->data, TRUE); } g_slist_free(rem_list); } @@ -2502,7 +2510,7 @@ if (!_check_for_disconnect(user, rc)) { /* Use the account alias if it is set */ - name = purple_account_get_alias(user->client_data); + name = purple_account_get_private_alias(user->client_data); if (name == NULL || *name == '\0') { /* If there is no account alias, try full name */ @@ -3086,7 +3094,7 @@ /* Remove first -- we will add it back in when we get * the okay from the server */ - purple_privacy_permit_remove(purple_connection_get_account(gc), who, TRUE); + purple_account_privacy_permit_remove(purple_connection_get_account(gc), who, TRUE); if (nm_user_is_privacy_locked(user)) { _show_privacy_locked_error(gc, user); @@ -3130,7 +3138,7 @@ /* Remove first -- we will add it back in when we get * the okay from the server */ - purple_privacy_deny_remove(purple_connection_get_account(gc), who, TRUE); + purple_account_privacy_deny_remove(purple_connection_get_account(gc), who, TRUE); if (nm_user_is_privacy_locked(user)) { _show_privacy_locked_error(gc, user); @@ -3228,10 +3236,13 @@ int i, j, num_contacts, num_folders; NMContact *contact; NMFolder *folder = NULL; + PurpleAccount *account; if (gc == NULL) return; + account = purple_connection_get_account(gc); + user = purple_connection_get_protocol_data(gc); if (user == NULL) return; @@ -3248,9 +3259,9 @@ return; } - switch (purple_account_get_privacy_type(purple_connection_get_account(gc))) { - - case PURPLE_PRIVACY_ALLOW_ALL: + switch (purple_account_get_privacy_type(account)) { + + case PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL: rc = nm_send_set_privacy_default(user, FALSE, _set_privacy_default_resp_cb, NULL); _check_for_disconnect(user, rc); @@ -3270,7 +3281,7 @@ } break; - case PURPLE_PRIVACY_DENY_ALL: + case PURPLE_ACCOUNT_PRIVACY_DENY_ALL: rc = nm_send_set_privacy_default(user, TRUE, _set_privacy_default_resp_cb, NULL); _check_for_disconnect(user, rc); @@ -3290,7 +3301,7 @@ } break; - case PURPLE_PRIVACY_ALLOW_USERS: + case PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS: rc = nm_send_set_privacy_default(user, TRUE, _set_privacy_default_resp_cb, NULL); @@ -3304,14 +3315,14 @@ if (user_record) { name = nm_user_record_get_display_id(user_record); - if (!g_slist_find_custom(purple_connection_get_account(gc)->permit, + if (!g_slist_find_custom(purple_account_privacy_get_permitted(account), name, (GCompareFunc)purple_utf8_strcasecmp)) { - purple_privacy_permit_add(purple_connection_get_account(gc), name , TRUE); + purple_account_privacy_permit_add(account, name , TRUE); } } } - for (node = purple_connection_get_account(gc)->permit; node; node = node->next) { + for (node = purple_account_privacy_get_permitted(account); node; node = node->next) { dn = nm_lookup_dn(user, (char *)node->data); if (dn) { @@ -3322,13 +3333,13 @@ g_strdup(dn)); } } else { - purple_privacy_permit_remove(purple_connection_get_account(gc), (char *)node->data, TRUE); + purple_account_privacy_permit_remove(account, (char *)node->data, TRUE); } } } break; - case PURPLE_PRIVACY_DENY_USERS: + case PURPLE_ACCOUNT_PRIVACY_DENY_USERS: /* set to default allow */ rc = nm_send_set_privacy_default(user, FALSE, @@ -3343,14 +3354,14 @@ if (user_record) { name = nm_user_record_get_display_id(user_record); - if (!g_slist_find_custom(purple_connection_get_account(gc)->deny, + if (!g_slist_find_custom(purple_account_privacy_get_denied(account), name, (GCompareFunc)purple_utf8_strcasecmp)) { - purple_privacy_deny_add(purple_connection_get_account(gc), name , TRUE); + purple_account_privacy_deny_add(account, name , TRUE); } } } - for (node = purple_connection_get_account(gc)->deny; node; node = node->next) { + for (node = purple_account_privacy_get_denied(account); node; node = node->next) { name = NULL; dn = nm_lookup_dn(user, (char *)node->data); @@ -3365,14 +3376,14 @@ g_strdup(name)); } } else { - purple_privacy_deny_remove(purple_connection_get_account(gc), (char *)node->data, TRUE); + purple_account_privacy_deny_remove(account, (char *)node->data, TRUE); } } } break; - case PURPLE_PRIVACY_ALLOW_BUDDYLIST: + case PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST: /* remove users from allow list that are not in buddy list */ copy = g_slist_copy(user->allow_list);
--- a/libpurple/protocols/oscar/clientlogin.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/oscar/clientlogin.c Sun Jun 23 13:35:53 2013 +0530 @@ -38,9 +38,10 @@ #include "oscar.h" #include "oscarcommon.h" +#include "core.h" -#include "cipher.h" -#include "core.h" +#include "ciphers/hmaccipher.h" +#include "ciphers/sha256hash.h" #define AIM_LOGIN_HOST "api.screenname.aol.com" #define ICQ_LOGIN_HOST "api.login.icq.net" @@ -128,15 +129,17 @@ */ static gchar *hmac_sha256(const char *key, const char *message) { - PurpleCipherContext *context; + PurpleCipher *cipher; + PurpleHash *hash; guchar digest[32]; - context = purple_cipher_context_new_by_name("hmac", NULL); - purple_cipher_context_set_option(context, "hash", "sha256"); - purple_cipher_context_set_key(context, (guchar *)key, strlen(key)); - purple_cipher_context_append(context, (guchar *)message, strlen(message)); - purple_cipher_context_digest(context, digest, sizeof(digest)); - purple_cipher_context_destroy(context); + hash = purple_sha256_hash_new(); + cipher = purple_hmac_cipher_new(hash); + purple_cipher_set_key(cipher, (guchar *)key, strlen(key)); + purple_cipher_append(cipher, (guchar *)message, strlen(message)); + purple_cipher_digest(cipher, digest, sizeof(digest)); + g_object_unref(cipher); + g_object_unref(hash); return purple_base64_encode(digest, sizeof(digest)); }
--- a/libpurple/protocols/oscar/family_auth.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/oscar/family_auth.c Sun Jun 23 13:35:53 2013 +0530 @@ -31,7 +31,7 @@ #include <ctype.h> -#include "cipher.h" +#include "ciphers/md5hash.h" /* #define USE_XOR_FOR_ICQ */ @@ -75,14 +75,14 @@ static int aim_encode_password_md5(const char *password, size_t password_len, const char *key, guint8 *digest) { - PurpleCipherContext *context; + PurpleHash *hash; - context = purple_cipher_context_new_by_name("md5", NULL); - purple_cipher_context_append(context, (const guchar *)key, strlen(key)); - purple_cipher_context_append(context, (const guchar *)password, password_len); - purple_cipher_context_append(context, (const guchar *)AIM_MD5_STRING, strlen(AIM_MD5_STRING)); - purple_cipher_context_digest(context, 16, digest, NULL); - purple_cipher_context_destroy(context); + hash = purple_md5_hash_new(); + purple_hash_append(hash, (const guchar *)key, strlen(key)); + purple_hash_append(hash, (const guchar *)password, password_len); + purple_hash_append(hash, (const guchar *)AIM_MD5_STRING, strlen(AIM_MD5_STRING)); + purple_hash_digest(hash, 16, digest, NULL); + g_object_unref(hash); return 0; } @@ -90,23 +90,19 @@ static int aim_encode_password_md5(const char *password, size_t password_len, const char *key, guint8 *digest) { - PurpleCipher *cipher; - PurpleCipherContext *context; + PurpleHash *hash; guchar passdigest[16]; - cipher = purple_ciphers_find_cipher("md5"); - - context = purple_cipher_context_new(cipher, NULL); - purple_cipher_context_append(context, (const guchar *)password, password_len); - purple_cipher_context_digest(context, passdigest, sizeof(passdigest)); - purple_cipher_context_destroy(context); + hash = purple_md5_hash_new(); + purple_hash_append(hash, (const guchar *)password, password_len); + purple_hash_digest(hash, passdigest, sizeof(passdigest)); + purple_hash_reset(hash); - context = purple_cipher_context_new(cipher, NULL); - purple_cipher_context_append(context, (const guchar *)key, strlen(key)); - purple_cipher_context_append(context, passdigest, 16); - purple_cipher_context_append(context, (const guchar *)AIM_MD5_STRING, strlen(AIM_MD5_STRING)); - purple_cipher_context_digest(context, digest, 16); - purple_cipher_context_destroy(context); + purple_hash_append(hash, (const guchar *)key, strlen(key)); + purple_hash_append(hash, passdigest, 16); + purple_hash_append(hash, (const guchar *)AIM_MD5_STRING, strlen(AIM_MD5_STRING)); + purple_hash_digest(hash, digest, 16); + g_object_unref(hash); return 0; }
--- a/libpurple/protocols/oscar/family_oservice.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/oscar/family_oservice.c Sun Jun 23 13:35:53 2013 +0530 @@ -25,7 +25,7 @@ #include "oscar.h" -#include "cipher.h" +#include "ciphers/md5hash.h" /* * Each time we make a FLAP connection to an oscar server the server gives @@ -972,18 +972,18 @@ byte_stream_putraw(&bs, buf, 0x10); } else if (buf && (len > 0)) { /* use input buffer */ - PurpleCipherContext *context; + PurpleHash *hash; guchar digest[16]; - context = purple_cipher_context_new_by_name("md5", NULL); - purple_cipher_context_append(context, buf, len); - purple_cipher_context_digest(context, digest, sizeof(digest)); - purple_cipher_context_destroy(context); + hash = purple_md5_hash_new(); + purple_hash_append(hash, buf, len); + purple_hash_digest(hash, digest, sizeof(digest)); + g_object_unref(hash); byte_stream_putraw(&bs, digest, 0x10); } else if (len == 0) { /* no length, just hash NULL (buf is optional) */ - PurpleCipherContext *context; + PurpleHash *hash; guchar digest[16]; guint8 nil = '\0'; @@ -991,10 +991,10 @@ * I'm not sure if we really need the empty append with the * new MD5 functions, so I'll leave it in, just in case. */ - context = purple_cipher_context_new_by_name("md5", NULL); - purple_cipher_context_append(context, &nil, 0); - purple_cipher_context_digest(context, digest, sizeof(digest)); - purple_cipher_context_destroy(context); + hash = purple_md5_hash_new(); + purple_hash_append(hash, &nil, 0); + purple_hash_digest(hash, digest, sizeof(digest)); + g_object_unref(hash); byte_stream_putraw(&bs, digest, 0x10);
--- a/libpurple/protocols/oscar/flap_connection.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/oscar/flap_connection.c Sun Jun 23 13:35:53 2013 +0530 @@ -336,7 +336,7 @@ conn = g_new0(FlapConnection, 1); conn->od = od; - conn->buffer_outgoing = purple_circ_buffer_new(0); + conn->buffer_outgoing = purple_circular_buffer_new(0); conn->fd = -1; conn->subtype = -1; conn->type = type; @@ -410,7 +410,7 @@ g_free(conn->buffer_incoming.data.data); conn->buffer_incoming.data.data = NULL; - purple_circ_buffer_destroy(conn->buffer_outgoing); + g_object_unref(G_OBJECT(conn->buffer_outgoing)); conn->buffer_outgoing = NULL; } @@ -1020,9 +1020,11 @@ { FlapConnection *conn; int writelen, ret; + const gchar *output = NULL; conn = data; - writelen = purple_circ_buffer_get_max_read(conn->buffer_outgoing); + writelen = purple_circular_buffer_get_max_read(conn->buffer_outgoing); + output = purple_circular_buffer_get_output(conn->buffer_outgoing); if (writelen == 0) { @@ -1032,10 +1034,9 @@ } if (conn->gsc) - ret = purple_ssl_write(conn->gsc, conn->buffer_outgoing->outptr, - writelen); + ret = purple_ssl_write(conn->gsc, output, writelen); else - ret = send(conn->fd, conn->buffer_outgoing->outptr, writelen, 0); + ret = send(conn->fd, output, writelen, 0); if (ret <= 0) { if (ret < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) @@ -1057,7 +1058,7 @@ return; } - purple_circ_buffer_mark_read(conn->buffer_outgoing, ret); + purple_circular_buffer_mark_read(conn->buffer_outgoing, ret); } static void @@ -1074,7 +1075,7 @@ return; /* Add everything to our outgoing buffer */ - purple_circ_buffer_append(conn->buffer_outgoing, bs->data, count); + purple_circular_buffer_append(conn->buffer_outgoing, bs->data, count); /* If we haven't already started writing stuff, then start the cycle */ if (conn->watcher_outgoing == 0)
--- a/libpurple/protocols/oscar/oft.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/oscar/oft.c Sun Jun 23 13:35:53 2013 +0530 @@ -360,7 +360,7 @@ conn = data; - if (purple_circ_buffer_get_max_read(conn->buffer_outgoing) == 0) + if (purple_circular_buffer_get_max_read(conn->buffer_outgoing) == 0) { int fd = conn->fd; conn->sending_data_timer = 0; @@ -385,7 +385,7 @@ conn = data; - if (purple_circ_buffer_get_max_read(conn->buffer_outgoing) == 0) + if (purple_circular_buffer_get_max_read(conn->buffer_outgoing) == 0) { conn->sending_data_timer = 0; peer_connection_destroy(conn, conn->disconnect_reason, NULL);
--- a/libpurple/protocols/oscar/oscar.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/oscar/oscar.c Sun Jun 23 13:35:53 2013 +0530 @@ -33,7 +33,7 @@ #include "account.h" #include "accountopt.h" #include "buddyicon.h" -#include "cipher.h" +#include "ciphers/md5hash.h" #include "conversation.h" #include "core.h" #include "debug.h" @@ -41,7 +41,6 @@ #include "imgstore.h" #include "network.h" #include "notify.h" -#include "privacy.h" #include "prpl.h" #include "proxy.h" #include "request.h" @@ -3118,10 +3117,12 @@ } else { /* Don't send if this turkey is in our deny list */ + PurpleAccount *account = purple_connection_get_account(gc); GSList *list; - for (list=purple_connection_get_account(gc)->deny; (list && oscar_util_name_compare(name, list->data)); list=list->next); + + for (list=purple_account_privacy_get_denied(account); (list && oscar_util_name_compare(name, list->data)); list=list->next); if (!list) { - struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(purple_connection_get_account(gc), name)); + struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(account, name)); if (bi && bi->typingnot) { if (state == PURPLE_TYPING) aim_im_sendmtn(od, 0x0001, name, 0x0002); @@ -3599,12 +3600,12 @@ /* * For ICQ the permit/deny setting controls who can see you - * online. Mimicking the official client's behavior, we use PURPLE_PRIVACY_ALLOW_USERS - * when our status is "invisible" and PURPLE_PRIVACY_DENY_USERS otherwise. + * online. Mimicking the official client's behavior, we use PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS + * when our status is "invisible" and PURPLE_ACCOUNT_PRIVACY_DENY_USERS otherwise. * In the former case, we are visible only to buddies on our "permanently visible" list. * In the latter, we are invisible only to buddies on our "permanently invisible" list. */ - aim_ssi_setpermdeny(od, invisible ? PURPLE_PRIVACY_ALLOW_USERS : PURPLE_PRIVACY_DENY_USERS); + aim_ssi_setpermdeny(od, invisible ? PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS : PURPLE_ACCOUNT_PRIVACY_DENY_USERS); } void @@ -3909,27 +3910,27 @@ /* Permit list (ICQ doesn't have one) */ if (!od->icq) { - next = account->permit; + next = purple_account_privacy_get_permitted(account); while (next != NULL) { cur = next; next = next->next; if (!aim_ssi_itemlist_finditem(&od->ssi.local, NULL, cur->data, AIM_SSI_TYPE_PERMIT)) { purple_debug_info("oscar", "ssi: removing permit %s from local list\n", (const char *)cur->data); - purple_privacy_permit_remove(account, cur->data, TRUE); + purple_account_privacy_permit_remove(account, cur->data, TRUE); } } } /* Deny list */ - next = account->deny; + next = purple_account_privacy_get_denied(account); while (next != NULL) { cur = next; next = next->next; if (!aim_ssi_itemlist_finditem(&od->ssi.local, NULL, cur->data, deny_entry_type)) { purple_debug_info("oscar", "ssi: removing deny %s from local list\n", (const char *)cur->data); - purple_privacy_deny_remove(account, cur->data, TRUE); + purple_account_privacy_deny_remove(account, cur->data, TRUE); } } @@ -4016,11 +4017,11 @@ case AIM_SSI_TYPE_PERMIT: { /* Permit buddy (unless we're on ICQ) */ if (!od->icq && curitem->name) { - for (cur = account->permit; (cur && oscar_util_name_compare(curitem->name, cur->data)); cur = cur->next); + for (cur = purple_account_privacy_get_permitted(account); (cur && oscar_util_name_compare(curitem->name, cur->data)); cur = cur->next); if (!cur) { purple_debug_info("oscar", "ssi: adding permit buddy %s to local list\n", curitem->name); - purple_privacy_permit_add(account, curitem->name, TRUE); + purple_account_privacy_permit_add(account, curitem->name, TRUE); } } } break; @@ -4028,11 +4029,11 @@ case AIM_SSI_TYPE_ICQDENY: case AIM_SSI_TYPE_DENY: { /* Deny buddy */ if (curitem->type == deny_entry_type && curitem->name) { - for (cur = account->deny; (cur && oscar_util_name_compare(curitem->name, cur->data)); cur = cur->next); + for (cur = purple_account_privacy_get_denied(account); (cur && oscar_util_name_compare(curitem->name, cur->data)); cur = cur->next); if (!cur) { purple_debug_info("oscar", "ssi: adding deny buddy %s to local list\n", curitem->name); - purple_privacy_deny_add(account, curitem->name, TRUE); + purple_account_privacy_deny_add(account, curitem->name, TRUE); } } } break; @@ -5336,15 +5337,15 @@ if (img == NULL) { aim_ssi_delicon(od); } else { - PurpleCipherContext *context; + PurpleHash *hash; guchar md5[16]; gconstpointer data = purple_imgstore_get_data(img); size_t len = purple_imgstore_get_size(img); - context = purple_cipher_context_new_by_name("md5", NULL); - purple_cipher_context_append(context, data, len); - purple_cipher_context_digest(context, md5, sizeof(md5)); - purple_cipher_context_destroy(context); + hash = purple_md5_hash_new(); + purple_hash_append(hash, data, len); + purple_hash_digest(hash, md5, sizeof(md5)); + g_object_unref(hash); aim_ssi_seticon(od, md5, 16); }
--- a/libpurple/protocols/oscar/oscar.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/oscar/oscar.h Sun Jun 23 13:35:53 2013 +0530 @@ -30,7 +30,7 @@ #define _OSCAR_H_ #include "internal.h" -#include "circbuffer.h" +#include "circularbuffer.h" #include "debug.h" #include "eventloop.h" #include "proxy.h" @@ -280,7 +280,7 @@ guint8 header[6]; gssize header_received; FlapFrame buffer_incoming; - PurpleCircBuffer *buffer_outgoing; + PurpleCircularBuffer *buffer_outgoing; guint watcher_incoming; guint watcher_outgoing;
--- a/libpurple/protocols/oscar/peer.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/oscar/peer.c Sun Jun 23 13:35:53 2013 +0530 @@ -115,7 +115,7 @@ conn->od = od; conn->type = type; conn->bn = g_strdup(bn); - conn->buffer_outgoing = purple_circ_buffer_new(0); + conn->buffer_outgoing = purple_circular_buffer_new(0); conn->listenerfd = -1; conn->fd = -1; conn->lastactivity = time(NULL); @@ -189,8 +189,8 @@ conn->buffer_incoming.len = 0; conn->buffer_incoming.offset = 0; - purple_circ_buffer_destroy(conn->buffer_outgoing); - conn->buffer_outgoing = purple_circ_buffer_new(0); + g_object_unref(G_OBJECT(conn->buffer_outgoing)); + conn->buffer_outgoing = purple_circular_buffer_new(0); conn->flags &= ~PEER_CONNECTION_FLAG_IS_INCOMING; } @@ -234,7 +234,7 @@ g_free(conn->clientip); g_free(conn->verifiedip); g_free(conn->xferdata.name); - purple_circ_buffer_destroy(conn->buffer_outgoing); + g_object_unref(G_OBJECT(conn->buffer_outgoing)); conn->od->peer_connections = g_slist_remove(conn->od->peer_connections, conn); @@ -408,9 +408,10 @@ PeerConnection *conn; gsize writelen; gssize wrotelen; + const gchar *output = NULL; conn = data; - writelen = purple_circ_buffer_get_max_read(conn->buffer_outgoing); + writelen = purple_circular_buffer_get_max_read(conn->buffer_outgoing); if (writelen == 0) { @@ -433,12 +434,13 @@ * file transfer. Somebody should teach those guys how to * write good TCP code. */ - conn->buffer_outgoing->inptr = conn->buffer_outgoing->buffer; - conn->buffer_outgoing->outptr = conn->buffer_outgoing->buffer; + purple_circular_buffer_reset(conn->buffer_outgoing); return; } - wrotelen = send(conn->fd, conn->buffer_outgoing->outptr, writelen, 0); + output = purple_circular_buffer_get_output(conn->buffer_outgoing); + + wrotelen = send(conn->fd, output, writelen, 0); if (wrotelen <= 0) { if (wrotelen < 0 && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) @@ -465,7 +467,7 @@ return; } - purple_circ_buffer_mark_read(conn->buffer_outgoing, wrotelen); + purple_circular_buffer_mark_read(conn->buffer_outgoing, wrotelen); conn->lastactivity = time(NULL); } @@ -478,7 +480,7 @@ peer_connection_send(PeerConnection *conn, ByteStream *bs) { /* Add everything to our outgoing buffer */ - purple_circ_buffer_append(conn->buffer_outgoing, bs->data, bs->len); + purple_circular_buffer_append(conn->buffer_outgoing, bs->data, bs->len); /* If we haven't already started writing stuff, then start the cycle */ if ((conn->watcher_outgoing == 0) && (conn->fd >= 0))
--- a/libpurple/protocols/oscar/peer.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/oscar/peer.h Sun Jun 23 13:35:53 2013 +0530 @@ -184,7 +184,7 @@ guint8 proxy_header[12]; gssize proxy_header_received; ByteStream buffer_incoming; - PurpleCircBuffer *buffer_outgoing; + PurpleCircularBuffer *buffer_outgoing; guint watcher_incoming; guint watcher_outgoing;
--- a/libpurple/protocols/sametime/sametime.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/sametime/sametime.c Sun Jun 23 13:35:53 2013 +0530 @@ -33,7 +33,7 @@ /* purple includes */ #include "account.h" #include "accountopt.h" -#include "circbuffer.h" +#include "circularbuffer.h" #include "conversation.h" #include "debug.h" #include "ft.h" @@ -41,7 +41,6 @@ #include "mime.h" #include "notify.h" #include "plugin.h" -#include "privacy.h" #include "prpl.h" #include "request.h" #include "util.h" @@ -221,7 +220,7 @@ gint outpa; /* like inpa, but the other way */ /** circular buffer for outgoing data */ - PurpleCircBuffer *sock_buf; + PurpleCircularBuffer *sock_buf; PurpleConnection *gc; }; @@ -343,7 +342,7 @@ static void write_cb(gpointer data, gint source, PurpleInputCondition cond) { struct mwPurplePluginData *pd = data; - PurpleCircBuffer *circ = pd->sock_buf; + PurpleCircularBuffer *circ = pd->sock_buf; gsize avail; int ret; @@ -351,17 +350,17 @@ g_return_if_fail(circ != NULL); - avail = purple_circ_buffer_get_max_read(circ); + avail = purple_circular_buffer_get_max_read(circ); if(BUF_LONG < avail) avail = BUF_LONG; while(avail) { - ret = write(pd->socket, circ->outptr, avail); + ret = write(pd->socket, purple_circular_buffer_get_output(circ), avail); if(ret <= 0) break; - purple_circ_buffer_mark_read(circ, ret); - avail = purple_circ_buffer_get_max_read(circ); + purple_circular_buffer_mark_read(circ, ret); + avail = purple_circular_buffer_get_max_read(circ); if(BUF_LONG < avail) avail = BUF_LONG; } @@ -386,7 +385,7 @@ if(pd->outpa) { DEBUG_INFO("already pending INPUT_WRITE, buffering\n"); - purple_circ_buffer_append(pd->sock_buf, buf, len); + purple_circular_buffer_append(pd->sock_buf, buf, len); return 0; } @@ -406,7 +405,7 @@ if(err == EAGAIN) { /* append remainder to circular buffer */ DEBUG_INFO("EAGAIN\n"); - purple_circ_buffer_append(pd->sock_buf, buf, len); + purple_circular_buffer_append(pd->sock_buf, buf, len); pd->outpa = purple_input_add(pd->socket, PURPLE_INPUT_WRITE, write_cb, pd); } else if(len > 0) { @@ -1634,7 +1633,7 @@ PurpleConnection *gc; PurpleAccount *acct; struct mwPrivacyInfo *privacy; - GSList *l, **ll; + GSList *list; guint count; DEBUG_INFO("privacy information set from server\n"); @@ -1653,16 +1652,25 @@ privacy = mwSession_getPrivacyInfo(session); count = privacy->count; - ll = (privacy->deny)? &acct->deny: &acct->permit; - for(l = *ll; l; l = l->next) g_free(l->data); - g_slist_free(*ll); - l = *ll = NULL; - - while(count--) { - struct mwUserItem *u = privacy->users + count; - l = g_slist_prepend(l, g_strdup(u->id)); + if (privacy->deny) { + while ((list = purple_account_privacy_get_denied(acct))) { + g_free(list->data); + purple_account_privacy_deny_remove(acct, list->data, TRUE); + } + while (count--) { + struct mwUserItem *u = privacy->users + count; + purple_account_privacy_deny_add(acct, u->id, TRUE); + } + } else { + while ((list = purple_account_privacy_get_permitted(acct))) { + g_free(list->data); + purple_account_privacy_permit_remove(acct, list->data, TRUE); + } + while (count--) { + struct mwUserItem *u = privacy->users + count; + purple_account_privacy_permit_add(acct, u->id, TRUE); + } } - *ll = l; } @@ -3150,7 +3158,7 @@ pd->srvc_resolve = mw_srvc_resolve_new(pd->session); pd->srvc_store = mw_srvc_store_new(pd->session); pd->group_list_map = g_hash_table_new(g_direct_hash, g_direct_equal); - pd->sock_buf = purple_circ_buffer_new(0); + pd->sock_buf = purple_circular_buffer_new(0); mwSession_addService(pd->session, MW_SERVICE(pd->srvc_aware)); mwSession_addService(pd->session, MW_SERVICE(pd->srvc_conf)); @@ -3197,7 +3205,7 @@ mwSession_free(pd->session); g_hash_table_destroy(pd->group_list_map); - purple_circ_buffer_destroy(pd->sock_buf); + g_object_unref(G_OBJECT(pd->sock_buf)); g_free(pd); } @@ -4604,25 +4612,25 @@ g_return_if_fail(session != NULL); switch(purple_account_get_privacy_type(acct)) { - case PURPLE_PRIVACY_DENY_USERS: - DEBUG_INFO("PURPLE_PRIVACY_DENY_USERS\n"); - privacy_fill(&privacy, acct->deny); + case PURPLE_ACCOUNT_PRIVACY_DENY_USERS: + DEBUG_INFO("PURPLE_ACCOUNT_PRIVACY_DENY_USERS\n"); + privacy_fill(&privacy, purple_account_privacy_get_denied(acct)); privacy.deny = TRUE; break; - case PURPLE_PRIVACY_ALLOW_ALL: - DEBUG_INFO("PURPLE_PRIVACY_ALLOW_ALL\n"); + case PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL: + DEBUG_INFO("PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL\n"); privacy.deny = TRUE; break; - case PURPLE_PRIVACY_ALLOW_USERS: - DEBUG_INFO("PURPLE_PRIVACY_ALLOW_USERS\n"); - privacy_fill(&privacy, acct->permit); + case PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS: + DEBUG_INFO("PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS\n"); + privacy_fill(&privacy, purple_account_privacy_get_permitted(acct)); privacy.deny = FALSE; break; - case PURPLE_PRIVACY_DENY_ALL: - DEBUG_INFO("PURPLE_PRIVACY_DENY_ALL\n"); + case PURPLE_ACCOUNT_PRIVACY_DENY_ALL: + DEBUG_INFO("PURPLE_ACCOUNT_PRIVACY_DENY_ALL\n"); privacy.deny = FALSE; break;
--- a/libpurple/protocols/simple/simple.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/simple/simple.c Sun Jun 23 13:35:53 2013 +0530 @@ -32,7 +32,6 @@ #include "dnsquery.h" #include "debug.h" #include "notify.h" -#include "privacy.h" #include "prpl.h" #include "plugin.h" #include "util.h" @@ -274,7 +273,7 @@ if(auth->type == 1) { /* Digest */ sprintf(noncecount, "%08d", auth->nc++); - response = purple_cipher_http_digest_calculate_response( + response = purple_http_digest_calculate_response( "md5", method, target, NULL, NULL, auth->nonce, noncecount, NULL, auth->digest_session_key); purple_debug(PURPLE_DEBUG_MISC, "simple", "response %s\n", response); @@ -295,7 +294,7 @@ } sprintf(noncecount, "%08d", auth->nc++); - response = purple_cipher_http_digest_calculate_response( + response = purple_http_digest_calculate_response( "md5", method, target, NULL, NULL, auth->nonce, noncecount, NULL, auth->digest_session_key); purple_debug(PURPLE_DEBUG_MISC, "simple", "response %s\n", response); @@ -399,7 +398,7 @@ auth->realm ? auth->realm : "(null)"); if(auth->realm) { - auth->digest_session_key = purple_cipher_http_digest_calculate_session_key( + auth->digest_session_key = purple_http_digest_calculate_session_key( "md5", authuser, auth->realm, sip->password, auth->nonce, NULL); auth->nc = 1; @@ -416,8 +415,9 @@ struct simple_account_data *sip = purple_connection_get_protocol_data(gc); gsize max_write; gssize written; + const gchar *output = NULL; - max_write = purple_circ_buffer_get_max_read(sip->txbuf); + max_write = purple_circular_buffer_get_max_read(sip->txbuf); if(max_write == 0) { purple_input_remove(sip->tx_handler); @@ -425,7 +425,9 @@ return; } - written = write(sip->fd, sip->txbuf->outptr, max_write); + output = purple_circular_buffer_get_output(sip->txbuf); + + written = write(sip->fd, output, max_write); if(written < 0 && errno == EAGAIN) written = 0; @@ -439,7 +441,7 @@ return; } - purple_circ_buffer_mark_read(sip->txbuf, written); + purple_circular_buffer_mark_read(sip->txbuf, written); } static void simple_input_cb(gpointer data, gint source, PurpleInputCondition cond); @@ -465,7 +467,7 @@ simple_canwrite_cb(gc, sip->fd, PURPLE_INPUT_WRITE); /* If there is more to write now, we need to register a handler */ - if(sip->txbuf->bufused > 0) + if(purple_circular_buffer_get_used(sip->txbuf) > 0) sip->tx_handler = purple_input_add(sip->fd, PURPLE_INPUT_WRITE, simple_canwrite_cb, gc); @@ -485,10 +487,10 @@ sip->connecting = TRUE; } - if(purple_circ_buffer_get_max_read(sip->txbuf) > 0) - purple_circ_buffer_append(sip->txbuf, "\r\n", 2); + if(purple_circular_buffer_get_max_read(sip->txbuf) > 0) + purple_circular_buffer_append(sip->txbuf, "\r\n", 2); - purple_circ_buffer_append(sip->txbuf, buf, strlen(buf)); + purple_circular_buffer_append(sip->txbuf, buf, strlen(buf)); } static void sendout_pkt(PurpleConnection *gc, const char *buf) { @@ -529,10 +531,10 @@ /* XXX: is it OK to do this? You might get part of a request sent with part of another. */ - if(sip->txbuf->bufused > 0) - purple_circ_buffer_append(sip->txbuf, "\r\n", 2); + if(purple_circular_buffer_get_used(sip->txbuf) > 0) + purple_circular_buffer_append(sip->txbuf, "\r\n", 2); - purple_circ_buffer_append(sip->txbuf, buf + ret, + purple_circular_buffer_append(sip->txbuf, buf + ret, writelen - ret); } } @@ -1452,7 +1454,7 @@ if(!watcher) { /* new subscription */ const gchar *acceptheader = sipmsg_find_header(msg, "Accept"); gboolean needsxpidf = FALSE; - if(!purple_privacy_check(sip->account, from)) { + if(!purple_account_privacy_check(sip->account, from)) { send_sip_response(sip->gc, msg, 202, "Ok", NULL); goto privend; } @@ -1941,7 +1943,7 @@ sip->udp = purple_account_get_bool(account, "udp", FALSE); /* TODO: is there a good default grow size? */ if(!sip->udp) - sip->txbuf = purple_circ_buffer_new(0); + sip->txbuf = purple_circular_buffer_new(0); userserver = g_strsplit(username, "@", 2); if (userserver[1] == NULL || userserver[1][0] == '\0') { @@ -2037,7 +2039,7 @@ transactions_remove(sip, sip->transactions->data); g_free(sip->publish_etag); if (sip->txbuf) - purple_circ_buffer_destroy(sip->txbuf); + g_object_unref(G_OBJECT(sip->txbuf)); g_free(sip->realhostname); g_free(sip);
--- a/libpurple/protocols/simple/simple.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/simple/simple.h Sun Jun 23 13:35:53 2013 +0530 @@ -27,7 +27,7 @@ #include <time.h> #include "cipher.h" -#include "circbuffer.h" +#include "circularbuffer.h" #include "dnsquery.h" #include "dnssrv.h" #include "network.h" @@ -101,7 +101,7 @@ guint resendtimeout; gboolean connecting; PurpleAccount *account; - PurpleCircBuffer *txbuf; + PurpleCircularBuffer *txbuf; guint tx_handler; gchar *regcallid; GSList *transactions;
--- a/libpurple/protocols/yahoo/libymsg.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/yahoo/libymsg.c Sun Jun 23 13:35:53 2013 +0530 @@ -27,13 +27,12 @@ #include "account.h" #include "accountopt.h" #include "blist.h" -#include "cipher.h" +#include "ciphers/md5hash.h" #include "cmds.h" #include "core.h" #include "debug.h" #include "network.h" #include "notify.h" -#include "privacy.h" #include "prpl.h" #include "proxy.h" #include "request.h" @@ -575,7 +574,7 @@ } else { /* This buddy is on the ignore list (and therefore in no group) */ purple_debug_info("yahoo", "%s adding %s to the deny list because of the ignore list / no group was found\n", purple_account_get_username(account), norm_bud); - purple_privacy_deny_add(account, norm_bud, 1); + purple_account_privacy_deny_add(account, norm_bud, 1); } g_free(norm_bud); @@ -738,7 +737,7 @@ for (bud = buddies; bud && *bud; bud++) { /* The server is already ignoring the user */ got_serv_list = TRUE; - purple_privacy_deny_add(account, *bud, 1); + purple_account_privacy_deny_add(account, *bud, 1); } g_strfreev(buddies); @@ -747,12 +746,12 @@ } if (got_serv_list && - ((purple_account_get_privacy_type(account) != PURPLE_PRIVACY_ALLOW_BUDDYLIST) && - (purple_account_get_privacy_type(account) != PURPLE_PRIVACY_DENY_ALL) && - (purple_account_get_privacy_type(account) != PURPLE_PRIVACY_ALLOW_USERS))) + ((purple_account_get_privacy_type(account) != PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST) && + (purple_account_get_privacy_type(account) != PURPLE_ACCOUNT_PRIVACY_DENY_ALL) && + (purple_account_get_privacy_type(account) != PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS))) { - purple_account_set_privacy_type(account, PURPLE_PRIVACY_DENY_USERS); - purple_debug_info("yahoo", "%s privacy defaulting to PURPLE_PRIVACY_DENY_USERS.\n", + purple_account_set_privacy_type(account, PURPLE_ACCOUNT_PRIVACY_DENY_USERS); + purple_debug_info("yahoo", "%s privacy defaulting to PURPLE_ACCOUNT_PRIVACY_DENY_USERS.\n", purple_account_get_username(account)); } @@ -820,7 +819,7 @@ } if (!g_ascii_strncasecmp(msg, "TYPING", strlen("TYPING")) - && (purple_privacy_check(account, from))) + && (purple_account_privacy_check(account, from))) { char *fed_from = from; switch (fed) { @@ -1044,7 +1043,7 @@ { PurpleWhiteboard *wb; - if (!purple_privacy_check(account, im->from)) { + if (!purple_account_privacy_check(account, im->from)) { purple_debug_info("yahoo", "Doodle request from %s dropped.\n", im->from); g_free(im->fed_from); @@ -1090,7 +1089,7 @@ continue; } - if (!purple_privacy_check(account, im->fed_from)) { + if (!purple_account_privacy_check(account, im->fed_from)) { purple_debug_info("yahoo", "Message from %s dropped.\n", im->fed_from); return; } @@ -1409,7 +1408,7 @@ if (add_req->id && add_req->who) { char *alias = NULL, *dec_msg = NULL; - if (!purple_privacy_check(account, add_req->who)) + if (!purple_account_privacy_check(account, add_req->who)) { purple_debug_misc("yahoo", "Auth. request from %s dropped and automatically denied due to privacy settings!\n", add_req->who); @@ -1482,7 +1481,7 @@ if (add_req->id && add_req->who) { char *dec_msg = NULL; - if (!purple_privacy_check(account, add_req->who)) { + if (!purple_account_privacy_check(account, add_req->who)) { purple_debug_misc("yahoo", "Auth. request from %s dropped and automatically denied due to privacy settings!\n", add_req->who); yahoo_buddy_add_deny_cb(NULL, add_req); @@ -1692,18 +1691,16 @@ YahooData *yd = purple_connection_get_protocol_data(gc); PurpleAccount *account = purple_connection_get_account(gc); const char *name = purple_normalize(account, purple_account_get_username(account)); - PurpleCipher *md5_cipher; - PurpleCipherContext *md5_ctx; + PurpleHash *md5_hash; guchar md5_digest[16]; gchar base64_string[25]; struct yahoo_packet *pkt; purple_debug_info("yahoo","Authentication: In yahoo_auth16_stage3\n"); - md5_cipher = purple_ciphers_find_cipher("md5"); - md5_ctx = purple_cipher_context_new(md5_cipher, NULL); - purple_cipher_context_append(md5_ctx, (guchar *)crypt, strlen(crypt)); - purple_cipher_context_digest(md5_ctx, md5_digest, sizeof(md5_digest)); + md5_hash = purple_md5_hash_new(); + purple_hash_append(md5_hash, (guchar *)crypt, strlen(crypt)); + purple_hash_digest(md5_hash, md5_digest, sizeof(md5_digest)); to_y64(base64_string, md5_digest, 16); @@ -1741,7 +1738,7 @@ yahoo_packet_hash_int(pkt, 192, yd->picture_checksum); yahoo_packet_send_and_free(pkt, yd); - purple_cipher_context_destroy(md5_ctx); + g_object_unref(md5_hash); } static gchar *yahoo_auth16_get_cookie_b(gchar *headers) @@ -2112,7 +2109,7 @@ static void keep_buddy(PurpleBuddy *b) { - purple_privacy_deny_remove(purple_buddy_get_account(b), + purple_account_privacy_deny_remove(purple_buddy_get_account(b), purple_buddy_get_name(b), 1); } @@ -2946,7 +2943,7 @@ purple_debug_misc("yahoo", "Warning, nonutf8 audible, ignoring!\n"); return; } - if (!purple_privacy_check(account, who)) { + if (!purple_account_privacy_check(account, who)) { purple_debug_misc("yahoo", "Audible message from %s for %s dropped!\n", purple_account_get_username(account), who); return; @@ -3668,7 +3665,7 @@ yd->fd = -1; yd->txhandler = 0; /* TODO: Is there a good grow size for the buffer? */ - yd->txbuf = purple_circ_buffer_new(0); + yd->txbuf = purple_circular_buffer_new(0); yd->friends = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, yahoo_friend_free); yd->imvironments = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); yd->xfer_peer_idstring_map = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); @@ -3762,7 +3759,7 @@ if (yd->txhandler) purple_input_remove(yd->txhandler); - purple_circ_buffer_destroy(yd->txbuf); + g_object_unref(G_OBJECT(yd->txbuf)); if (yd->fd >= 0) close(yd->fd); @@ -4543,7 +4540,7 @@ return -1; } - alias = purple_account_get_alias(account); + alias = purple_account_get_private_alias(account); pkt = yahoo_packet_new(YAHOO_SERVICE_SMS_MSG, YAHOO_STATUS_AVAILABLE, yd->session_id); yahoo_packet_hash(pkt, "sssss", 1, purple_connection_get_display_name(gc), @@ -4939,7 +4936,7 @@ return; fed_bname = bname = purple_buddy_get_name(buddy); - if (!purple_privacy_check(purple_connection_get_account(gc), bname)) + if (!purple_account_privacy_check(purple_connection_get_account(gc), bname)) return; fed = yahoo_get_federation_from_name(bname); @@ -5099,16 +5096,16 @@ switch (purple_account_get_privacy_type(account)) { - case PURPLE_PRIVACY_ALLOW_ALL: - for (deny = account->deny; deny; deny = deny->next) + case PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL: + for (deny = purple_account_privacy_get_denied(account); deny; deny = deny->next) yahoo_rem_deny(gc, deny->data); break; - case PURPLE_PRIVACY_ALLOW_BUDDYLIST: - case PURPLE_PRIVACY_ALLOW_USERS: - case PURPLE_PRIVACY_DENY_USERS: - case PURPLE_PRIVACY_DENY_ALL: - for (deny = account->deny; deny; deny = deny->next) + case PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST: + case PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS: + case PURPLE_ACCOUNT_PRIVACY_DENY_USERS: + case PURPLE_ACCOUNT_PRIVACY_DENY_ALL: + for (deny = purple_account_privacy_get_denied(account); deny; deny = deny->next) yahoo_add_deny(gc, deny->data); break; }
--- a/libpurple/protocols/yahoo/libymsg.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/yahoo/libymsg.h Sun Jun 23 13:35:53 2013 +0530 @@ -25,7 +25,7 @@ #ifndef _LIBYMSG_H_ #define _LIBYMSG_H_ -#include "circbuffer.h" +#include "circularbuffer.h" #include "cmds.h" #include "prpl.h" #include "network.h" @@ -192,7 +192,7 @@ guint inpa; guchar *rxqueue; int rxlen; - PurpleCircBuffer *txbuf; + PurpleCircularBuffer *txbuf; guint txhandler; GHashTable *friends;
--- a/libpurple/protocols/yahoo/yahoo_doodle.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/yahoo/yahoo_doodle.c Sun Jun 23 13:35:53 2013 +0530 @@ -33,7 +33,6 @@ #include "cmds.h" #include "debug.h" #include "notify.h" -#include "privacy.h" #include "prpl.h" #include "proxy.h" #include "request.h"
--- a/libpurple/protocols/yahoo/yahoo_packet.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/yahoo/yahoo_packet.c Sun Jun 23 13:35:53 2013 +0530 @@ -287,8 +287,9 @@ { YahooData *yd = data; int ret, writelen; + const gchar *output = NULL; - writelen = purple_circ_buffer_get_max_read(yd->txbuf); + writelen = purple_circular_buffer_get_max_read(yd->txbuf); if (writelen == 0) { purple_input_remove(yd->txhandler); @@ -296,7 +297,9 @@ return; } - ret = write(yd->fd, yd->txbuf->outptr, writelen); + output = purple_circular_buffer_get_output(yd->txbuf); + + ret = write(yd->fd, output, writelen); if (ret < 0 && errno == EAGAIN) return; @@ -307,7 +310,7 @@ return; } - purple_circ_buffer_mark_read(yd->txbuf, ret); + purple_circular_buffer_mark_read(yd->txbuf, ret); } @@ -374,7 +377,7 @@ if (yd->txhandler == 0) yd->txhandler = purple_input_add(yd->fd, PURPLE_INPUT_WRITE, yahoo_packet_send_can_write, yd); - purple_circ_buffer_append(yd->txbuf, data + ret, len - ret); + purple_circular_buffer_append(yd->txbuf, data + ret, len - ret); } g_free(data);
--- a/libpurple/protocols/yahoo/yahoo_picture.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/yahoo/yahoo_picture.c Sun Jun 23 13:35:53 2013 +0530 @@ -28,7 +28,6 @@ #include "accountopt.h" #include "blist.h" #include "debug.h" -#include "privacy.h" #include "prpl.h" #include "proxy.h" #include "util.h" @@ -113,7 +112,7 @@ if (!who) return; - if (!purple_privacy_check(purple_connection_get_account(gc), who)) { + if (!purple_account_privacy_check(purple_connection_get_account(gc), who)) { purple_debug_info("yahoo", "Picture packet from %s dropped.\n", who); return; }
--- a/libpurple/protocols/yahoo/yahoochat.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/yahoo/yahoochat.c Sun Jun 23 13:35:53 2013 +0530 @@ -34,7 +34,6 @@ #include "debug.h" #include "http.h" -#include "privacy.h" #include "prpl.h" #include "conversation.h" @@ -182,7 +181,7 @@ return; } - if (!purple_privacy_check(account, who) || + if (!purple_account_privacy_check(account, who) || (purple_account_get_bool(account, "ignore_invites", FALSE))) { purple_debug_info("yahoo", @@ -232,7 +231,7 @@ break; } } - if (!purple_privacy_check(purple_connection_get_account(gc), who)) + if (!purple_account_privacy_check(purple_connection_get_account(gc), who)) { g_free(room); g_free(msg); @@ -590,9 +589,9 @@ yahoo_chat_add_users(PURPLE_CONV_CHAT(c), members); } - if (account->deny && c) { + if (purple_account_privacy_get_denied(account) && c) { PurpleConversationUiOps *ops = purple_conversation_get_ui_ops(c); - for (l = account->deny; l != NULL; l = l->next) { + for (l = purple_account_privacy_get_denied(account); l != NULL; l = l->next) { for (roomies = members; roomies; roomies = roomies->next) { if (!purple_utf8_strcasecmp((char *)l->data, roomies->data)) { purple_debug_info("yahoo", "Ignoring room member %s in room %s\n" , (char *)roomies->data, room ? room : ""); @@ -730,7 +729,7 @@ if (room && who) { GHashTable *components; - if (!purple_privacy_check(account, who) || + if (!purple_account_privacy_check(account, who) || (purple_account_get_bool(account, "ignore_invites", FALSE))) { purple_debug_info("yahoo", "Invite to room %s from %s has been dropped.\n", room, who);
--- a/libpurple/protocols/yahoo/ycht.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/yahoo/ycht.c Sun Jun 23 13:35:53 2013 +0530 @@ -267,8 +267,9 @@ { YchtConn *ycht = data; int ret, writelen; + const gchar *output = NULL; - writelen = purple_circ_buffer_get_max_read(ycht->txbuf); + writelen = purple_circular_buffer_get_max_read(ycht->txbuf); if (writelen == 0) { purple_input_remove(ycht->tx_handler); @@ -276,7 +277,9 @@ return; } - ret = write(ycht->fd, ycht->txbuf->outptr, writelen); + output = purple_circular_buffer_get_output(ycht->txbuf); + + ret = write(ycht->fd, output, writelen); if (ret < 0 && errno == EAGAIN) return; @@ -292,7 +295,7 @@ return; } - purple_circ_buffer_mark_read(ycht->txbuf, ret); + purple_circular_buffer_mark_read(ycht->txbuf, ret); } @@ -345,7 +348,7 @@ ycht->tx_handler = purple_input_add(ycht->fd, PURPLE_INPUT_WRITE, ycht_packet_send_write_cb, ycht); - purple_circ_buffer_append(ycht->txbuf, buf + written, + purple_circular_buffer_append(ycht->txbuf, buf + written, len - written); } @@ -444,7 +447,7 @@ if (ycht->tx_handler) purple_input_remove(ycht->tx_handler); - purple_circ_buffer_destroy(ycht->txbuf); + g_object_unref(G_OBJECT(ycht->txbuf)); g_free(ycht->rxqueue);
--- a/libpurple/protocols/yahoo/ycht.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/yahoo/ycht.h Sun Jun 23 13:35:53 2013 +0530 @@ -73,7 +73,7 @@ gboolean changing_rooms; guchar *rxqueue; guint rxlen; - PurpleCircBuffer *txbuf; + PurpleCircularBuffer *txbuf; guint tx_handler; } YchtConn;
--- a/libpurple/protocols/zephyr/zephyr.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/protocols/zephyr/zephyr.c Sun Jun 23 13:35:53 2013 +0530 @@ -35,7 +35,6 @@ #include "server.h" #include "util.h" #include "cmds.h" -#include "privacy.h" #include "version.h" #include "internal.h"
--- a/libpurple/proxy.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/proxy.c Sun Jun 23 13:35:53 2013 +0530 @@ -32,7 +32,7 @@ #define _PURPLE_PROXY_C_ #include "internal.h" -#include "cipher.h" +#include "ciphers/md5hash.h" #include "debug.h" #include "dnsquery.h" #include "http.h" @@ -1682,23 +1682,21 @@ static void hmacmd5_chap(const unsigned char * challenge, int challen, const char * passwd, unsigned char * response) { - PurpleCipher *cipher; - PurpleCipherContext *ctx; + PurpleHash *hash; int i; unsigned char Kxoripad[65]; unsigned char Kxoropad[65]; size_t pwlen; - cipher = purple_ciphers_find_cipher("md5"); - ctx = purple_cipher_context_new(cipher, NULL); + hash = purple_md5_hash_new(); memset(Kxoripad,0,sizeof(Kxoripad)); memset(Kxoropad,0,sizeof(Kxoropad)); pwlen=strlen(passwd); if (pwlen>64) { - purple_cipher_context_append(ctx, (const guchar *)passwd, strlen(passwd)); - purple_cipher_context_digest(ctx, Kxoripad, sizeof(Kxoripad)); + purple_hash_append(hash, (const guchar *)passwd, strlen(passwd)); + purple_hash_digest(hash, Kxoripad, sizeof(Kxoripad)); pwlen=16; } else { memcpy(Kxoripad, passwd, pwlen); @@ -1710,17 +1708,17 @@ Kxoropad[i]^=0x5c; } - purple_cipher_context_reset(ctx, NULL); - purple_cipher_context_append(ctx, Kxoripad, 64); - purple_cipher_context_append(ctx, challenge, challen); - purple_cipher_context_digest(ctx, Kxoripad, sizeof(Kxoripad)); - - purple_cipher_context_reset(ctx, NULL); - purple_cipher_context_append(ctx, Kxoropad, 64); - purple_cipher_context_append(ctx, Kxoripad, 16); - purple_cipher_context_digest(ctx, response, 16); - - purple_cipher_context_destroy(ctx); + purple_hash_reset(hash); + purple_hash_append(hash, Kxoripad, 64); + purple_hash_append(hash, challenge, challen); + purple_hash_digest(hash, Kxoripad, sizeof(Kxoripad)); + + purple_hash_reset(hash); + purple_hash_append(hash, Kxoropad, 64); + purple_hash_append(hash, Kxoripad, 16); + purple_hash_digest(hash, response, 16); + + g_object_unref(hash); } static void
--- a/libpurple/prpl.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/prpl.h Sun Jun 23 13:35:53 2013 +0530 @@ -72,7 +72,7 @@ #endif #include "blist.h" -#include "conversation.h" +#include "conversations.h" #include "ft.h" #include "imgstore.h" #include "media.h" @@ -327,7 +327,7 @@ */ int (*send_im)(PurpleConnection *, const char *who, const char *message, - PurpleMessageFlags flags); + PurpleConversationMessageFlags flags); void (*set_info)(PurpleConnection *, const char *info); @@ -338,7 +338,7 @@ * seconds to wait before sending a subsequent notification. * Otherwise the PRPL should return 0. */ - unsigned int (*send_typing)(PurpleConnection *, const char *name, PurpleTypingState state); + unsigned int (*send_typing)(PurpleConnection *, const char *name, PurpleIMConversationTypingState state); /** * Should arrange for purple_notify_userinfo() to be called with @@ -438,12 +438,12 @@ * * @param id The id of the chat to send the message to. * @param message The message to send to the chat. - * @param flags A bitwise OR of #PurpleMessageFlags representing + * @param flags A bitwise OR of #PurpleConversationMessageFlags representing * message flags. * @return A positive number or 0 in case of success, * a negative error number in case of failure. */ - int (*chat_send)(PurpleConnection *, int id, const char *message, PurpleMessageFlags flags); + int (*chat_send)(PurpleConnection *, int id, const char *message, PurpleConversationMessageFlags flags); /** If implemented, this will be called regularly for this prpl's * active connections. You'd want to do this if you need to repeatedly
--- a/libpurple/purple.h.in Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/purple.h.in Sun Jun 23 13:35:53 2013 +0530 @@ -44,16 +44,16 @@ @PLUGINS_DEFINE@ -#include <account.h> +#include <accounts.h> #include <accountopt.h> #include <blist.h> #include <buddyicon.h> #include <certificate.h> #include <cipher.h> -#include <circbuffer.h> +#include <circularbuffer.h> #include <cmds.h> #include <connection.h> -#include <conversation.h> +#include <conversations.h> #include <core.h> #include <debug.h> #include <desktopitem.h> @@ -75,7 +75,6 @@ #include <pluginpref.h> #include <pounce.h> #include <prefs.h> -#include <privacy.h> #include <proxy.h> #include <prpl.h> #include <request.h>
--- a/libpurple/server.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/server.c Sun Jun 23 13:35:53 2013 +0530 @@ -30,7 +30,6 @@ #include "log.h" #include "notify.h" #include "prefs.h" -#include "privacy.h" #include "prpl.h" #include "request.h" #include "signals.h" @@ -560,7 +559,7 @@ */ flags |= PURPLE_MESSAGE_RECV; - if (!purple_privacy_check(account, who)) { + if (!purple_account_privacy_check(account, who)) { purple_signal_emit(purple_conversations_get_handle(), "blocked-im-msg", account, who, msg, flags, (unsigned int)mtime); return; @@ -778,7 +777,7 @@ g_return_if_fail(who != NULL); account = purple_connection_get_account(gc); - if (!purple_privacy_check(account, who)) { + if (!purple_account_privacy_check(account, who)) { purple_signal_emit(purple_conversations_get_handle(), "chat-invite-blocked", account, who, name, message, data); return;
--- a/libpurple/server.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/server.h Sun Jun 23 13:35:53 2013 +0530 @@ -26,8 +26,8 @@ #ifndef _PURPLE_SERVER_H_ #define _PURPLE_SERVER_H_ -#include "account.h" -#include "conversation.h" +#include "accounts.h" +#include "conversations.h" #include "prpl.h" G_BEGIN_DECLS @@ -48,10 +48,10 @@ * user is still typing then Purple will send another PURPLE_TYPING * message. */ -unsigned int serv_send_typing(PurpleConnection *gc, const char *name, PurpleTypingState state); +unsigned int serv_send_typing(PurpleConnection *gc, const char *name, PurpleIMConversationTypingState state); void serv_move_buddy(PurpleBuddy *, PurpleGroup *, PurpleGroup *); -int serv_send_im(PurpleConnection *, const char *, const char *, PurpleMessageFlags flags); +int serv_send_im(PurpleConnection *, const char *, const char *, PurpleConversationMessageFlags flags); /** Get information about an account's attention commands, from the prpl. * @@ -70,7 +70,7 @@ void serv_chat_invite(PurpleConnection *, int, const char *, const char *); void serv_chat_leave(PurpleConnection *, int); void serv_chat_whisper(PurpleConnection *, int, const char *, const char *); -int serv_chat_send(PurpleConnection *, int, const char *, PurpleMessageFlags flags); +int serv_chat_send(PurpleConnection *, int, const char *, PurpleConversationMessageFlags flags); void serv_alias_buddy(PurpleBuddy *); void serv_got_alias(PurpleConnection *gc, const char *who, const char *alias); @@ -103,7 +103,7 @@ * @param state The typing state received */ void serv_got_typing(PurpleConnection *gc, const char *name, int timeout, - PurpleTypingState state); + PurpleIMConversationTypingState state); /** * TODO: Could probably move this into the conversation API. @@ -111,7 +111,7 @@ void serv_got_typing_stopped(PurpleConnection *gc, const char *name); void serv_got_im(PurpleConnection *gc, const char *who, const char *msg, - PurpleMessageFlags flags, time_t mtime); + PurpleConversationMessageFlags flags, time_t mtime); /** * @param data The hash function should be g_str_hash() and the equal @@ -180,7 +180,7 @@ * @param mtime The time when the message was received. */ void serv_got_chat_in(PurpleConnection *g, int id, const char *who, - PurpleMessageFlags flags, const char *message, time_t mtime); + PurpleConversationMessageFlags flags, const char *message, time_t mtime); void serv_send_file(PurpleConnection *gc, const char *who, const char *file); G_END_DECLS
--- a/libpurple/smiley.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/smiley.c Sun Jun 23 13:35:53 2013 +0530 @@ -32,25 +32,21 @@ #include "util.h" #include "xmlnode.h" +#define PURPLE_SMILEY_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_SMILEY, PurpleSmileyPrivate)) + /**************************************************************************/ -/* Main structures, members and constants */ +/* Structs */ /**************************************************************************/ -struct _PurpleSmiley -{ - GObject parent; +typedef struct { PurpleStoredImage *img; /**< The id of the stored image with the the smiley data. */ char *shortcut; /**< Shortcut associated with the custom smiley. This field will work as a unique key by this API. */ char *checksum; /**< The smiley checksum. */ -}; - -struct _PurpleSmileyClass -{ - GObjectClass parent_class; -}; +} PurpleSmileyPrivate; static GHashTable *smiley_shortcut_index = NULL; /* shortcut (char *) => smiley (PurpleSmiley*) */ static GHashTable *smiley_checksum_index = NULL; /* checksum (char *) => smiley (PurpleSmiley*) */ @@ -134,6 +130,7 @@ static xmlnode * smiley_to_xmlnode(PurpleSmiley *smiley) { + PurpleSmileyPrivate *priv = NULL; xmlnode *smiley_node = NULL; smiley_node = xmlnode_new(XML_SMILEY_TAG); @@ -141,14 +138,16 @@ if (!smiley_node) return NULL; + priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + xmlnode_set_attrib(smiley_node, XML_SHORTCUT_ATTRIB_TAG, - smiley->shortcut); + priv->shortcut); xmlnode_set_attrib(smiley_node, XML_CHECKSUM_ATRIB_TAG, - smiley->checksum); + priv->checksum); xmlnode_set_attrib(smiley_node, XML_FILENAME_ATRIB_TAG, - purple_imgstore_get_filename(smiley->img)); + purple_imgstore_get_filename(priv->img)); return smiley_node; } @@ -310,12 +309,14 @@ GParamSpec *spec) { PurpleSmiley *smiley = PURPLE_SMILEY(object); + PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + switch (param_id) { case PROP_SHORTCUT: - g_value_set_string(value, smiley->shortcut); + g_value_set_string(value, priv->shortcut); break; case PROP_IMGSTORE: - g_value_set_pointer(value, smiley->img); + g_value_set_pointer(value, priv->img); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, spec); @@ -328,6 +329,8 @@ GParamSpec *spec) { PurpleSmiley *smiley = PURPLE_SMILEY(object); + PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + switch (param_id) { case PROP_SHORTCUT: { @@ -339,18 +342,18 @@ { PurpleStoredImage *img = g_value_get_pointer(value); - purple_imgstore_unref(smiley->img); - g_free(smiley->checksum); + purple_imgstore_unref(priv->img); + g_free(priv->checksum); - smiley->img = img; + priv->img = img; if (img) { - smiley->checksum = g_compute_checksum_for_data( + priv->checksum = g_compute_checksum_for_data( G_CHECKSUM_SHA1, purple_imgstore_get_data(img), purple_imgstore_get_size(img)); purple_smiley_data_store(img); } else { - smiley->checksum = NULL; + priv->checksum = NULL; } g_object_notify(object, PROP_IMGSTORE_S); @@ -366,17 +369,18 @@ purple_smiley_finalize(GObject *obj) { PurpleSmiley *smiley = PURPLE_SMILEY(obj); + PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley); - if (g_hash_table_lookup(smiley_shortcut_index, smiley->shortcut)) { - g_hash_table_remove(smiley_shortcut_index, smiley->shortcut); - g_hash_table_remove(smiley_checksum_index, smiley->checksum); + if (g_hash_table_lookup(smiley_shortcut_index, priv->shortcut)) { + g_hash_table_remove(smiley_shortcut_index, priv->shortcut); + g_hash_table_remove(smiley_checksum_index, priv->checksum); } - g_free(smiley->shortcut); - g_free(smiley->checksum); - if (smiley->img) - purple_smiley_data_unstore(purple_imgstore_get_filename(smiley->img)); - purple_imgstore_unref(smiley->img); + g_free(priv->shortcut); + g_free(priv->checksum); + if (priv->img) + purple_smiley_data_unstore(purple_imgstore_get_filename(priv->img)); + purple_imgstore_unref(priv->img); PURPLE_DBUS_UNREGISTER_POINTER(smiley); @@ -398,6 +402,8 @@ parent_class = g_type_class_peek_parent(klass); + g_type_class_add_private(klass, sizeof(PurpleSmileyPrivate)); + gobj_class->get_property = purple_smiley_get_property; gobj_class->set_property = purple_smiley_set_property; gobj_class->finalize = purple_smiley_finalize; @@ -473,6 +479,7 @@ purple_smiley_load_file(const char *shortcut, const char *checksum, const char *filename) { PurpleSmiley *smiley = NULL; + PurpleSmileyPrivate *priv = NULL; guchar *smiley_data; size_t smiley_data_len; char *fullpath = NULL; @@ -493,7 +500,9 @@ return; } - smiley->checksum = g_strdup(checksum); + priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + + priv->checksum = g_strdup(checksum); if (read_smiley_file(fullpath, &smiley_data, &smiley_data_len)) purple_smiley_set_data_impl(smiley, smiley_data, @@ -616,6 +625,7 @@ purple_smiley_set_data_impl(PurpleSmiley *smiley, guchar *smiley_data, size_t smiley_data_len) { + PurpleSmileyPrivate *priv = NULL; PurpleStoredImage *old_img, *new_img; const char *old_filename = NULL; const char *new_filename = NULL; @@ -624,7 +634,9 @@ g_return_if_fail(smiley_data != NULL); g_return_if_fail(smiley_data_len > 0); - old_img = smiley->img; + priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + + old_img = priv->img; new_img = purple_smiley_data_new(smiley_data, smiley_data_len); @@ -636,7 +648,7 @@ return; old_filename = purple_imgstore_get_filename(old_img); - new_filename = purple_imgstore_get_filename(smiley->img); + new_filename = purple_imgstore_get_filename(priv->img); if (g_ascii_strcasecmp(old_filename, new_filename)) purple_smiley_data_unstore(old_filename); @@ -683,7 +695,8 @@ purple_smiley_new_from_stream(const char *shortcut, guchar *smiley_data, size_t smiley_data_len) { - PurpleSmiley *smiley; + PurpleSmiley *smiley = NULL; + PurpleSmileyPrivate *priv = NULL; g_return_val_if_fail(shortcut != NULL, NULL); g_return_val_if_fail(smiley_data != NULL, NULL); @@ -698,9 +711,10 @@ if (!smiley) return NULL; - purple_smiley_set_data_impl(smiley, smiley_data, smiley_data_len); + priv = PURPLE_SMILEY_GET_PRIVATE(smiley); - purple_smiley_data_store(smiley->img); + purple_smiley_set_data_impl(smiley, smiley_data, smiley_data_len); + purple_smiley_data_store(priv->img); return smiley; } @@ -734,6 +748,8 @@ gboolean purple_smiley_set_shortcut(PurpleSmiley *smiley, const char *shortcut) { + PurpleSmileyPrivate *priv = NULL; + g_return_val_if_fail(smiley != NULL, FALSE); g_return_val_if_fail(shortcut != NULL, FALSE); @@ -741,15 +757,17 @@ if (g_hash_table_lookup(smiley_shortcut_index, shortcut)) return FALSE; + priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + /* Remove the old shortcut. */ - if (smiley->shortcut) - g_hash_table_remove(smiley_shortcut_index, smiley->shortcut); + if (priv->shortcut) + g_hash_table_remove(smiley_shortcut_index, priv->shortcut); /* Insert the new shortcut. */ g_hash_table_insert(smiley_shortcut_index, g_strdup(shortcut), smiley); - g_free(smiley->shortcut); - smiley->shortcut = g_strdup(shortcut); + g_free(priv->shortcut); + priv->shortcut = g_strdup(shortcut); g_object_notify(G_OBJECT(smiley), PROP_SHORTCUT_S); @@ -762,18 +780,22 @@ purple_smiley_set_data(PurpleSmiley *smiley, guchar *smiley_data, size_t smiley_data_len) { + PurpleSmileyPrivate *priv = NULL; + g_return_if_fail(smiley != NULL); g_return_if_fail(smiley_data != NULL); g_return_if_fail(smiley_data_len > 0); + priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + /* Remove the previous entry */ - g_hash_table_remove(smiley_checksum_index, smiley->checksum); + g_hash_table_remove(smiley_checksum_index, priv->checksum); /* Update the file data. This also updates the checksum. */ purple_smiley_set_data_impl(smiley, smiley_data, smiley_data_len); /* Reinsert the index item. */ - g_hash_table_insert(smiley_checksum_index, g_strdup(smiley->checksum), smiley); + g_hash_table_insert(smiley_checksum_index, g_strdup(priv->checksum), smiley); purple_smileys_save(); } @@ -781,34 +803,45 @@ PurpleStoredImage * purple_smiley_get_stored_image(const PurpleSmiley *smiley) { - return purple_imgstore_ref(smiley->img); + PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + return purple_imgstore_ref(priv->img); } const char *purple_smiley_get_shortcut(const PurpleSmiley *smiley) { + PurpleSmileyPrivate *priv = NULL; + g_return_val_if_fail(smiley != NULL, NULL); - return smiley->shortcut; + priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + return priv->shortcut; } const char * purple_smiley_get_checksum(const PurpleSmiley *smiley) { + PurpleSmileyPrivate *priv = NULL; + g_return_val_if_fail(smiley != NULL, NULL); - return smiley->checksum; + priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + return priv->checksum; } gconstpointer purple_smiley_get_data(const PurpleSmiley *smiley, size_t *len) { + PurpleSmileyPrivate *priv = NULL; + g_return_val_if_fail(smiley != NULL, NULL); - if (smiley->img) { + priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + + if (priv->img) { if (len != NULL) - *len = purple_imgstore_get_size(smiley->img); + *len = purple_imgstore_get_size(priv->img); - return purple_imgstore_get_data(smiley->img); + return purple_imgstore_get_data(priv->img); } return NULL; @@ -817,20 +850,26 @@ const char * purple_smiley_get_extension(const PurpleSmiley *smiley) { - if (smiley->img != NULL) - return purple_imgstore_get_extension(smiley->img); + PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + + if (priv->img != NULL) + return purple_imgstore_get_extension(priv->img); return NULL; } char *purple_smiley_get_full_path(PurpleSmiley *smiley) { + PurpleSmileyPrivate *priv = NULL; + g_return_val_if_fail(smiley != NULL, NULL); - if (smiley->img == NULL) + priv = PURPLE_SMILEY_GET_PRIVATE(smiley); + + if (priv->img == NULL) return NULL; - return get_file_full_path(purple_imgstore_get_filename(smiley->img)); + return get_file_full_path(purple_imgstore_get_filename(priv->img)); } static void add_smiley_to_list(gpointer key, gpointer value, gpointer user_data)
--- a/libpurple/smiley.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/smiley.h Sun Jun 23 13:35:53 2013 +0530 @@ -50,6 +50,26 @@ #define PURPLE_IS_SMILEY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PURPLE_TYPE_SMILEY)) #define PURPLE_SMILEY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PURPLE_TYPE_SMILEY, PurpleSmileyClass)) +struct _PurpleSmiley +{ + GObject parent; + + void (*purple_reserved1)(void); + void (*purple_reserved2)(void); + void (*purple_reserved3)(void); + void (*purple_reserved4)(void); +}; + +struct _PurpleSmileyClass +{ + GObjectClass parent_class; + + void (*purple_reserved1)(void); + void (*purple_reserved2)(void); + void (*purple_reserved3)(void); + void (*purple_reserved4)(void); +}; + G_BEGIN_DECLS /**************************************************************************/
--- a/libpurple/sound-theme-loader.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/sound-theme-loader.h Sun Jun 23 13:35:53 2013 +0530 @@ -49,11 +49,21 @@ struct _PurpleSoundThemeLoader { PurpleThemeLoader parent; + + void (*purple_reserved1)(void); + void (*purple_reserved2)(void); + void (*purple_reserved3)(void); + void (*purple_reserved4)(void); }; struct _PurpleSoundThemeLoaderClass { PurpleThemeLoaderClass parent_class; + + void (*purple_reserved1)(void); + void (*purple_reserved2)(void); + void (*purple_reserved3)(void); + void (*purple_reserved4)(void); }; /**************************************************************************/
--- a/libpurple/sound-theme.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/sound-theme.h Sun Jun 23 13:35:53 2013 +0530 @@ -51,11 +51,21 @@ struct _PurpleSoundTheme { PurpleTheme parent; + + void (*purple_reserved1)(void); + void (*purple_reserved2)(void); + void (*purple_reserved3)(void); + void (*purple_reserved4)(void); }; struct _PurpleSoundThemeClass { PurpleThemeClass parent_class; + + void (*purple_reserved1)(void); + void (*purple_reserved2)(void); + void (*purple_reserved3)(void); + void (*purple_reserved4)(void); }; /**************************************************************************/
--- a/libpurple/tests/test_cipher.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/tests/test_cipher.c Sun Jun 23 13:35:53 2013 +0530 @@ -7,28 +7,32 @@ #include "tests.h" -#include "../cipher.h" +#include "../ciphers/des3cipher.h" +#include "../ciphers/descipher.h" +#include "../ciphers/hmaccipher.h" +#include "../ciphers/md4hash.h" +#include "../ciphers/md5hash.h" +#include "../ciphers/sha1hash.h" +#include "../ciphers/sha256hash.h" /****************************************************************************** * MD4 Tests *****************************************************************************/ #define MD4_TEST(data, digest) { \ - PurpleCipher *cipher = NULL; \ - PurpleCipherContext *context = NULL; \ + PurpleHash *hash = NULL; \ gchar cdigest[33]; \ gboolean ret = FALSE; \ \ - cipher = purple_ciphers_find_cipher("md4"); \ - context = purple_cipher_context_new(cipher, NULL); \ - purple_cipher_context_append(context, (guchar *)(data), strlen((data))); \ + hash = purple_md4_hash_new(); \ + purple_hash_append(hash, (guchar *)(data), strlen((data))); \ \ - ret = purple_cipher_context_digest_to_str(context, cdigest, sizeof(cdigest)); \ + ret = purple_hash_digest_to_str(hash, cdigest, sizeof(cdigest)); \ \ fail_unless(ret == TRUE, NULL); \ \ fail_unless(strcmp((digest), cdigest) == 0, NULL); \ \ - purple_cipher_context_destroy(context); \ + g_object_unref(hash); \ } START_TEST(test_md4_empty_string) { @@ -75,22 +79,20 @@ * MD5 Tests *****************************************************************************/ #define MD5_TEST(data, digest) { \ - PurpleCipher *cipher = NULL; \ - PurpleCipherContext *context = NULL; \ + PurpleHash *hash = NULL; \ gchar cdigest[33]; \ gboolean ret = FALSE; \ \ - cipher = purple_ciphers_find_cipher("md5"); \ - context = purple_cipher_context_new(cipher, NULL); \ - purple_cipher_context_append(context, (guchar *)(data), strlen((data))); \ + hash = purple_md5_hash_new(); \ + purple_hash_append(hash, (guchar *)(data), strlen((data))); \ \ - ret = purple_cipher_context_digest_to_str(context, cdigest, sizeof(cdigest)); \ + ret = purple_hash_digest_to_str(hash, cdigest, sizeof(cdigest)); \ \ fail_unless(ret == TRUE, NULL); \ \ fail_unless(strcmp((digest), cdigest) == 0, NULL); \ \ - purple_cipher_context_destroy(context); \ + g_object_unref(hash); \ } START_TEST(test_md5_empty_string) { @@ -136,17 +138,15 @@ * SHA-1 Tests *****************************************************************************/ #define SHA1_TEST(data, digest) { \ - PurpleCipher *cipher = NULL; \ - PurpleCipherContext *context = NULL; \ + PurpleHash *hash = NULL; \ gchar cdigest[41]; \ gboolean ret = FALSE; \ gchar *input = data; \ \ - cipher = purple_ciphers_find_cipher("sha1"); \ - context = purple_cipher_context_new(cipher, NULL); \ + hash = purple_sha1_hash_new(); \ \ if (input) { \ - purple_cipher_context_append(context, (guchar *)input, strlen(input)); \ + purple_hash_append(hash, (guchar *)input, strlen(input)); \ } else { \ gint j; \ guchar buff[1000]; \ @@ -154,16 +154,16 @@ memset(buff, 'a', 1000); \ \ for(j = 0; j < 1000; j++) \ - purple_cipher_context_append(context, buff, 1000); \ + purple_hash_append(hash, buff, 1000); \ } \ \ - ret = purple_cipher_context_digest_to_str(context, cdigest, sizeof(cdigest)); \ + ret = purple_hash_digest_to_str(hash, cdigest, sizeof(cdigest)); \ \ fail_unless(ret == TRUE, NULL); \ \ fail_unless(strcmp((digest), cdigest) == 0, NULL); \ \ - purple_cipher_context_destroy(context); \ + g_object_unref(hash); \ } START_TEST(test_sha1_empty_string) { @@ -196,17 +196,15 @@ * SHA-256 Tests *****************************************************************************/ #define SHA256_TEST(data, digest) { \ - PurpleCipher *cipher = NULL; \ - PurpleCipherContext *context = NULL; \ + PurpleHash *hash = NULL; \ gchar cdigest[65]; \ gboolean ret = FALSE; \ gchar *input = data; \ \ - cipher = purple_ciphers_find_cipher("sha256"); \ - context = purple_cipher_context_new(cipher, NULL); \ + hash = purple_sha256_hash_new(); \ \ if (input) { \ - purple_cipher_context_append(context, (guchar *)input, strlen(input)); \ + purple_hash_append(hash, (guchar *)input, strlen(input)); \ } else { \ gint j; \ guchar buff[1000]; \ @@ -214,16 +212,16 @@ memset(buff, 'a', 1000); \ \ for(j = 0; j < 1000; j++) \ - purple_cipher_context_append(context, buff, 1000); \ + purple_hash_append(hash, buff, 1000); \ } \ \ - ret = purple_cipher_context_digest_to_str(context, cdigest, sizeof(cdigest)); \ + ret = purple_hash_digest_to_str(hash, cdigest, sizeof(cdigest)); \ \ fail_unless(ret == TRUE, NULL); \ \ fail_unless(strcmp((digest), cdigest) == 0, NULL); \ \ - purple_cipher_context_destroy(context); \ + g_object_unref(hash); \ } START_TEST(test_sha256_empty_string) { @@ -257,26 +255,24 @@ *****************************************************************************/ #define DES_TEST(in, keyz, out, len) { \ PurpleCipher *cipher = NULL; \ - PurpleCipherContext *context = NULL; \ guchar answer[len+1]; \ gint ret = 0; \ guchar decrypt[len+1] = in; \ guchar key[8+1] = keyz;\ guchar encrypt[len+1] = out;\ \ - cipher = purple_ciphers_find_cipher("des"); \ - context = purple_cipher_context_new(cipher, NULL); \ - purple_cipher_context_set_key(context, key, 8); \ + cipher = purple_des_cipher_new(); \ + purple_cipher_set_key(cipher, key, 8); \ \ - ret = purple_cipher_context_encrypt(context, decrypt, len, answer, len); \ + ret = purple_cipher_encrypt(cipher, decrypt, len, answer, len); \ fail_unless(ret == len, NULL); \ fail_unless(memcmp(encrypt, answer, len) == 0, NULL); \ \ - ret = purple_cipher_context_decrypt(context, encrypt, len, answer, len); \ + ret = purple_cipher_decrypt(cipher, encrypt, len, answer, len); \ fail_unless(ret == len, NULL); \ fail_unless(memcmp(decrypt, answer, len) == 0, NULL); \ \ - purple_cipher_context_destroy(context); \ + g_object_unref(cipher); \ } START_TEST(test_des_12345678) { @@ -303,28 +299,25 @@ #define DES3_TEST(in, key, iv, out, len, mode) { \ PurpleCipher *cipher = NULL; \ - PurpleCipherContext *context = NULL; \ guchar answer[len+1]; \ guchar decrypt[len+1] = in; \ guchar encrypt[len+1] = out; \ gint ret = 0; \ \ - cipher = purple_ciphers_find_cipher("des3"); \ - context = purple_cipher_context_new(cipher, NULL); \ - purple_cipher_context_set_key(context, (guchar *)key, 24); \ - purple_cipher_context_set_batch_mode(context, (mode)); \ - purple_cipher_context_set_iv(context, (guchar *)iv, 8); \ + cipher = purple_des3_cipher_new(); \ + purple_cipher_set_key(cipher, (guchar *)key, 24); \ + purple_cipher_set_batch_mode(cipher, (mode)); \ + purple_cipher_set_iv(cipher, (guchar *)iv, 8); \ \ - fprintf(stderr, "len: %lu\n", len); \ - ret = purple_cipher_context_encrypt(context, decrypt, len, answer, len); \ + ret = purple_cipher_encrypt(cipher, decrypt, len, answer, len); \ fail_unless(ret == len, NULL); \ fail_unless(memcmp(encrypt, answer, len) == 0, NULL); \ \ - ret = purple_cipher_context_decrypt(context, encrypt, len, answer, len); \ + ret = purple_cipher_decrypt(cipher, encrypt, len, answer, len); \ fail_unless(ret == len, NULL); \ fail_unless(memcmp(decrypt, answer, len) == 0, NULL); \ \ - purple_cipher_context_destroy(context); \ + g_object_unref(cipher); \ } START_TEST(test_des3_ecb_nist1) { @@ -472,22 +465,22 @@ #define HMAC_TEST(data, data_len, key, key_len, type, digest) { \ PurpleCipher *cipher = NULL; \ - PurpleCipherContext *context = NULL; \ + PurpleHash *hash = NULL; \ gchar cdigest[41]; \ gboolean ret = FALSE; \ \ - cipher = purple_ciphers_find_cipher("hmac"); \ - context = purple_cipher_context_new(cipher, NULL); \ - purple_cipher_context_set_option(context, "hash", type); \ - purple_cipher_context_set_key(context, (guchar *)key, (key_len)); \ + hash = purple_##type##_hash_new(); \ + cipher = purple_hmac_cipher_new(hash); \ + purple_cipher_set_key(cipher, (guchar *)key, (key_len)); \ \ - purple_cipher_context_append(context, (guchar *)(data), (data_len)); \ - ret = purple_cipher_context_digest_to_str(context, cdigest, sizeof(cdigest)); \ + purple_cipher_append(cipher, (guchar *)(data), (data_len)); \ + ret = purple_cipher_digest_to_str(cipher, cdigest, sizeof(cdigest)); \ \ fail_unless(ret == TRUE, NULL); \ fail_unless(strcmp((digest), cdigest) == 0, NULL); \ \ - purple_cipher_context_destroy(context); \ + g_object_unref(cipher); \ + g_object_unref(hash); \ } /* HMAC MD5 */ @@ -497,7 +490,7 @@ 8, "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 16, - "md5", + md5, "9294727a3638bb1c13f48ef8158bfc9d"); } END_TEST @@ -507,7 +500,7 @@ 28, "Jefe", 4, - "md5", + md5, "750c783e6ab0b503eaa86e310a5db738"); } END_TEST @@ -521,7 +514,7 @@ 50, "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 16, - "md5", + md5, "56be34521d144c88dbb8c733f0e8b3f6"); } END_TEST @@ -537,7 +530,7 @@ "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" "\x15\x16\x17\x18\x19", 25, - "md5", + md5, "697eaf0aca3a3aea3a75164746ffaa79"); } END_TEST @@ -547,7 +540,7 @@ 20, "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", 16, - "md5", + md5, "56461ef2342edc00f9bab995690efd4c"); } END_TEST @@ -564,7 +557,7 @@ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 80, - "md5", + md5, "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd"); } END_TEST @@ -581,7 +574,7 @@ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 80, - "md5", + md5, "6f630fad67cda0ee1fb1f562db3aa53e"); } END_TEST @@ -592,7 +585,7 @@ "\x0a\x0b\x00\x0d\x0e\x0f\x1a\x2f\x0b\x0b" "\x0b\x00\x00\x0b\x0b\x49\x5f\x6e\x0b\x0b", 20, - "md5", + md5, "597bfd644b797a985561eeb03a169e59"); } END_TEST @@ -603,7 +596,7 @@ "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 20, - "md5", + md5, "70be8e1b7b50dfcc335d6cd7992c564f"); } END_TEST @@ -614,7 +607,7 @@ "\x0c\x0d\x00\x0f\x10\x1a\x3a\x3a\xe6\x34" "\x0b\x00\x00\x0b\x0b\x49\x5f\x6e\x0b\x0b", 20, - "md5", + md5, "b31bcbba35a33a067cbba9131cba4889"); } END_TEST @@ -627,7 +620,7 @@ "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 20, - "sha1", + sha1, "b617318655057264e28bc0b6fb378c8ef146be00"); } END_TEST @@ -637,7 +630,7 @@ 28, "Jefe", 4, - "sha1", + sha1, "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79"); } END_TEST @@ -652,7 +645,7 @@ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 20, - "sha1", + sha1, "125d7342b9ac11cd91a39af48aa17b4f63f175d3"); } END_TEST @@ -668,7 +661,7 @@ "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" "\x15\x16\x17\x18\x19", 25, - "sha1", + sha1, "4c9007f4026250c6bc8414f9bf50c86c2d7235da"); } END_TEST @@ -679,7 +672,7 @@ "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", 20, - "sha1", + sha1, "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04"); } END_TEST @@ -696,7 +689,7 @@ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 80, - "sha1", + sha1, "aa4ae5e15272d00e95705637ce8a3b55ed402112"); } END_TEST @@ -713,7 +706,7 @@ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 80, - "sha1", + sha1, "e8e99d0f45237d786d6bbaa7965c7808bbff1a91"); } END_TEST @@ -724,7 +717,7 @@ "\x0a\x0b\x00\x0d\x0e\x0f\x1a\x2f\x0b\x0b" "\x0b\x00\x00\x0b\x0b\x49\x5f\x6e\x0b\x0b", 20, - "sha1", + sha1, "eb62a2e0e33d300be669c52aab3f591bc960aac5"); } END_TEST @@ -735,7 +728,7 @@ "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 20, - "sha1", + sha1, "31ca58d849e971e418e3439de2c6f83144b6abb7"); } END_TEST @@ -746,7 +739,7 @@ "\x0c\x0d\x00\x0f\x10\x1a\x3a\x3a\xe6\x34" "\x0b\x00\x00\x0b\x0b\x49\x5f\x6e\x0b\x0b", 20, - "sha1", + sha1, "e6b8e2fede87aa09dcb13e554df1435e056eae36"); } END_TEST
--- a/libpurple/tests/test_jabber_caps.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/tests/test_jabber_caps.c Sun Jun 23 13:35:53 2013 +0530 @@ -3,6 +3,8 @@ #include "tests.h" #include "../xmlnode.h" #include "../protocols/jabber/caps.h" +#include "../ciphers/md5hash.h" +#include "../ciphers/sha1hash.h" START_TEST(test_parse_invalid) { @@ -25,14 +27,22 @@ #define assert_caps_calculate_match(hash_func, hash, str) { \ xmlnode *query = xmlnode_from_str((str), -1); \ + PurpleHash *hasher = NULL; \ JabberCapsClientInfo *info = jabber_caps_parse_client_info(query); \ - gchar *got_hash = jabber_caps_calculate_hash(info, (hash_func)); \ + gchar *got_hash; \ + if (g_str_equal(hash_func, "sha-1")) { \ + hasher = purple_sha1_hash_new(); \ + } else if (g_str_equal(hash_func, "md5")) { \ + hasher = purple_md5_hash_new(); \ + } \ + got_hash = jabber_caps_calculate_hash(info, hasher); \ + g_object_unref(hasher); \ assert_string_equal_free((hash), got_hash); \ } START_TEST(test_calculate_caps) { - assert_caps_calculate_match("sha1", "GNjxthSckUNvAIoCCJFttjl6VL8=", + assert_caps_calculate_match("sha-1", "GNjxthSckUNvAIoCCJFttjl6VL8=", "<query xmlns='http://jabber.org/protocol/disco#info' node='http://tkabber.jabber.ru/#GNjxthSckUNvAIoCCJFttjl6VL8='><identity category='client' type='pc' name='Tkabber'/><x xmlns='jabber:x:data' type='result'><field var='FORM_TYPE' type='hidden'><value>urn:xmpp:dataforms:softwareinfo</value></field><field var='software'><value>Tkabber</value></field><field var='software_version'><value> ( 8.5.5 )</value></field><field var='os'><value>ATmega640-16AU</value></field><field var='os_version'><value/></field></x><feature var='games:board'/><feature var='google:mail:notify'/><feature var='http://jabber.org/protocol/activity'/><feature var='http://jabber.org/protocol/bytestreams'/><feature var='http://jabber.org/protocol/chatstates'/><feature var='http://jabber.org/protocol/commands'/><feature var='http://jabber.org/protocol/commands'/><feature var='http://jabber.org/protocol/disco#info'/><feature var='http://jabber.org/protocol/disco#items'/><feature var='http://jabber.org/protocol/feature-neg'/><feature var='http://jabber.org/protocol/geoloc'/><feature var='http://jabber.org/protocol/ibb'/><feature var='http://jabber.org/protocol/iqibb'/><feature var='http://jabber.org/protocol/mood'/><feature var='http://jabber.org/protocol/muc'/><feature var='http://jabber.org/protocol/mute#ancestor'/><feature var='http://jabber.org/protocol/mute#editor'/><feature var='http://jabber.org/protocol/rosterx'/><feature var='http://jabber.org/protocol/si'/><feature var='http://jabber.org/protocol/si/profile/file-transfer'/><feature var='http://jabber.org/protocol/tune'/><feature var='jabber:iq:avatar'/><feature var='jabber:iq:browse'/><feature var='jabber:iq:dtcp'/><feature var='jabber:iq:filexfer'/><feature var='jabber:iq:ibb'/><feature var='jabber:iq:inband'/><feature var='jabber:iq:jidlink'/><feature var='jabber:iq:last'/><feature var='jabber:iq:oob'/><feature var='jabber:iq:privacy'/><feature var='jabber:iq:time'/><feature var='jabber:iq:version'/><feature var='jabber:x:data'/><feature var='jabber:x:event'/><feature var='jabber:x:oob'/><feature var='urn:xmpp:ping'/><feature var='urn:xmpp:receipts'/><feature var='urn:xmpp:time'/></query>"); } END_TEST
--- a/libpurple/tests/test_jabber_scram.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/tests/test_jabber_scram.c Sun Jun 23 13:35:53 2013 +0530 @@ -4,8 +4,9 @@ #include "../util.h" #include "../protocols/jabber/auth_scram.h" #include "../protocols/jabber/jutil.h" +#include "../ciphers/sha1hash.h" -static JabberScramHash sha1_mech = { "-SHA-1", "sha1", 20 }; +static JabberScramHash sha1_mech = { "-SHA-1", purple_sha1_hash_new, 20 }; #define assert_pbkdf2_equal(password, salt, count, expected) { \ GString *p = g_string_new(password); \
--- a/libpurple/theme-loader.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/theme-loader.h Sun Jun 23 13:35:53 2013 +0530 @@ -50,6 +50,11 @@ struct _PurpleThemeLoader { GObject parent; + + void (*purple_reserved1)(void); + void (*purple_reserved2)(void); + void (*purple_reserved3)(void); + void (*purple_reserved4)(void); }; struct _PurpleThemeLoaderClass @@ -57,6 +62,11 @@ GObjectClass parent_class; PurpleTheme *((*purple_theme_loader_build)(const gchar*)); gboolean (*probe_directory)(const gchar *); + + void (*purple_reserved1)(void); + void (*purple_reserved2)(void); + void (*purple_reserved3)(void); + void (*purple_reserved4)(void); }; /**************************************************************************/
--- a/libpurple/theme-manager.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/theme-manager.h Sun Jun 23 13:35:53 2013 +0530 @@ -46,10 +46,20 @@ struct _PurpleThemeManager { GObject parent; + + void (*purple_reserved1)(void); + void (*purple_reserved2)(void); + void (*purple_reserved3)(void); + void (*purple_reserved4)(void); }; struct _PurpleThemeManagerClass { GObjectClass parent_class; + + void (*purple_reserved1)(void); + void (*purple_reserved2)(void); + void (*purple_reserved3)(void); + void (*purple_reserved4)(void); }; /**************************************************************************/
--- a/libpurple/theme.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/theme.h Sun Jun 23 13:35:53 2013 +0530 @@ -49,11 +49,21 @@ struct _PurpleTheme { GObject parent; + + void (*purple_reserved1)(void); + void (*purple_reserved2)(void); + void (*purple_reserved3)(void); + void (*purple_reserved4)(void); }; struct _PurpleThemeClass { GObjectClass parent_class; + + void (*purple_reserved1)(void); + void (*purple_reserved2)(void); + void (*purple_reserved3)(void); + void (*purple_reserved4)(void); }; /**************************************************************************/
--- a/libpurple/util.c Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/util.c Sun Jun 23 13:35:53 2013 +0530 @@ -23,7 +23,7 @@ */ #include "internal.h" -#include "cipher.h" +#include "ciphers/md5hash.h" #include "conversation.h" #include "core.h" #include "debug.h" @@ -4743,3 +4743,161 @@ b, (tmp >> 16) & 0xFFFF, g_random_int()); } + +gchar *purple_http_digest_calculate_session_key( + const gchar *algorithm, + const gchar *username, + const gchar *realm, + const gchar *password, + const gchar *nonce, + const gchar *client_nonce) +{ + PurpleHash *hasher; + gchar hash[33]; /* We only support MD5. */ + + g_return_val_if_fail(username != NULL, NULL); + g_return_val_if_fail(realm != NULL, NULL); + g_return_val_if_fail(password != NULL, NULL); + g_return_val_if_fail(nonce != NULL, NULL); + + /* Check for a supported algorithm. */ + g_return_val_if_fail(algorithm == NULL || + *algorithm == '\0' || + g_ascii_strcasecmp(algorithm, "MD5") || + g_ascii_strcasecmp(algorithm, "MD5-sess"), NULL); + + hasher = purple_md5_hash_new(); + g_return_val_if_fail(hash != NULL, NULL); + + purple_hash_append(hasher, (guchar *)username, strlen(username)); + purple_hash_append(hasher, (guchar *)":", 1); + purple_hash_append(hasher, (guchar *)realm, strlen(realm)); + purple_hash_append(hasher, (guchar *)":", 1); + purple_hash_append(hasher, (guchar *)password, strlen(password)); + + if (algorithm != NULL && !g_ascii_strcasecmp(algorithm, "MD5-sess")) + { + guchar digest[16]; + + if (client_nonce == NULL) + { + g_object_unref(hasher); + purple_debug_error("hash", "Required client_nonce missing for MD5-sess digest calculation.\n"); + return NULL; + } + + purple_hash_digest(hasher, digest, sizeof(digest)); + + purple_hash_reset(hasher); + purple_hash_append(hasher, digest, sizeof(digest)); + purple_hash_append(hasher, (guchar *)":", 1); + purple_hash_append(hasher, (guchar *)nonce, strlen(nonce)); + purple_hash_append(hasher, (guchar *)":", 1); + purple_hash_append(hasher, (guchar *)client_nonce, strlen(client_nonce)); + } + + purple_hash_digest_to_str(hasher, hash, sizeof(hash)); + g_object_unref(hasher); + + return g_strdup(hash); +} + +gchar *purple_http_digest_calculate_response( + const gchar *algorithm, + const gchar *method, + const gchar *digest_uri, + const gchar *qop, + const gchar *entity, + const gchar *nonce, + const gchar *nonce_count, + const gchar *client_nonce, + const gchar *session_key) +{ + PurpleHash *hash; + static gchar hash2[33]; /* We only support MD5. */ + + g_return_val_if_fail(method != NULL, NULL); + g_return_val_if_fail(digest_uri != NULL, NULL); + g_return_val_if_fail(nonce != NULL, NULL); + g_return_val_if_fail(session_key != NULL, NULL); + + /* Check for a supported algorithm. */ + g_return_val_if_fail(algorithm == NULL || + *algorithm == '\0' || + g_ascii_strcasecmp(algorithm, "MD5") || + g_ascii_strcasecmp(algorithm, "MD5-sess"), NULL); + + /* Check for a supported "quality of protection". */ + g_return_val_if_fail(qop == NULL || + *qop == '\0' || + g_ascii_strcasecmp(qop, "auth") || + g_ascii_strcasecmp(qop, "auth-int"), NULL); + + hash = purple_md5_hash_new(); + g_return_val_if_fail(hash != NULL, NULL); + + purple_hash_append(hash, (guchar *)method, strlen(method)); + purple_hash_append(hash, (guchar *)":", 1); + purple_hash_append(hash, (guchar *)digest_uri, strlen(digest_uri)); + + if (qop != NULL && !g_ascii_strcasecmp(qop, "auth-int")) + { + PurpleHash *hash2; + gchar entity_hash[33]; + + if (entity == NULL) + { + g_object_unref(hash); + purple_debug_error("hash", "Required entity missing for auth-int digest calculation.\n"); + return NULL; + } + + hash2 = purple_md5_hash_new(); + purple_hash_append(hash2, (guchar *)entity, strlen(entity)); + purple_hash_digest_to_str(hash2, entity_hash, sizeof(entity_hash)); + g_object_unref(hash2); + + purple_hash_append(hash, (guchar *)":", 1); + purple_hash_append(hash, (guchar *)entity_hash, strlen(entity_hash)); + } + + purple_hash_digest_to_str(hash, hash2, sizeof(hash2)); + purple_hash_reset(hash); + + purple_hash_append(hash, (guchar *)session_key, strlen(session_key)); + purple_hash_append(hash, (guchar *)":", 1); + purple_hash_append(hash, (guchar *)nonce, strlen(nonce)); + purple_hash_append(hash, (guchar *)":", 1); + + if (qop != NULL && *qop != '\0') + { + if (nonce_count == NULL) + { + g_object_unref(hash); + purple_debug_error("hash", "Required nonce_count missing for digest calculation.\n"); + return NULL; + } + + if (client_nonce == NULL) + { + g_object_unref(hash); + purple_debug_error("hash", "Required client_nonce missing for digest calculation.\n"); + return NULL; + } + + purple_hash_append(hash, (guchar *)nonce_count, strlen(nonce_count)); + purple_hash_append(hash, (guchar *)":", 1); + purple_hash_append(hash, (guchar *)client_nonce, strlen(client_nonce)); + purple_hash_append(hash, (guchar *)":", 1); + + purple_hash_append(hash, (guchar *)qop, strlen(qop)); + + purple_hash_append(hash, (guchar *)":", 1); + } + + purple_hash_append(hash, (guchar *)hash2, strlen(hash2)); + purple_hash_digest_to_str(hash, hash2, sizeof(hash2)); + g_object_unref(hash); + + return g_strdup(hash2); +}
--- a/libpurple/util.h Sun Jun 23 02:43:06 2013 -0500 +++ b/libpurple/util.h Sun Jun 23 13:35:53 2013 +0530 @@ -1431,6 +1431,48 @@ */ gchar *purple_uuid_random(void); +/** + * Calculates a session key for HTTP Digest authentation + * + * See RFC 2617 for more information. + * + * @param algorithm The hash algorithm to use + * @param username The username provided by the user + * @param realm The authentication realm provided by the server + * @param password The password provided by the user + * @param nonce The nonce provided by the server + * @param client_nonce The nonce provided by the client + * + * @return The session key, or @c NULL if an error occurred. + */ +gchar *purple_http_digest_calculate_session_key( + const gchar *algorithm, const gchar *username, + const gchar *realm, const gchar *password, + const gchar *nonce, const gchar *client_nonce); + +/** Calculate a response for HTTP Digest authentication + * + * See RFC 2617 for more information. + * + * @param algorithm The hash algorithm to use + * @param method The HTTP method in use + * @param digest_uri The URI from the initial request + * @param qop The "quality of protection" + * @param entity The entity body + * @param nonce The nonce provided by the server + * @param nonce_count The nonce count + * @param client_nonce The nonce provided by the client + * @param session_key The session key from purple_cipher_http_digest_calculate_session_key() + * + * @return The hashed response, or @c NULL if an error occurred. + */ +gchar *purple_http_digest_calculate_response( + const gchar *algorithm, const gchar *method, + const gchar *digest_uri, const gchar *qop, + const gchar *entity, const gchar *nonce, + const gchar *nonce_count, const gchar *client_nonce, + const gchar *session_key); + G_END_DECLS #endif /* _PURPLE_UTIL_H_ */
--- a/pidgin/gtkaccount.c Sun Jun 23 02:43:06 2013 -0500 +++ b/pidgin/gtkaccount.c Sun Jun 23 13:35:53 2013 +0530 @@ -165,6 +165,10 @@ static void set_account(GtkListStore *store, GtkTreeIter *iter, PurpleAccount *account, GdkPixbuf *global_buddyicon); +/* privacy UI ops */ +void pidgin_permit_added_removed(PurpleAccount *account, const char *name); +void pidgin_deny_added_removed(PurpleAccount *account, const char *name); + /************************************************************************** * Add/Modify Account dialog **************************************************************************/ @@ -859,9 +863,9 @@ gpointer data = NULL; size_t len = 0; - if (purple_account_get_alias(dialog->account)) + if (purple_account_get_private_alias(dialog->account)) gtk_entry_set_text(GTK_ENTRY(dialog->alias_entry), - purple_account_get_alias(dialog->account)); + purple_account_get_private_alias(dialog->account)); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->new_mail_check), purple_account_get_check_mail(dialog->account)); @@ -1401,7 +1405,7 @@ if (succeeded) { const PurpleSavedStatus *saved_status = purple_savedstatus_get_current(); - purple_signal_emit(pidgin_account_get_handle(), "account-modified", account); + purple_signal_emit(pidgin_accounts_get_handle(), "account-modified", account); if (saved_status != NULL && purple_account_get_remember_password(account)) { purple_savedstatus_activate_for_account(saved_status, account); @@ -1485,9 +1489,9 @@ value = gtk_entry_get_text(GTK_ENTRY(dialog->alias_entry)); if (*value != '\0') - purple_account_set_alias(account, value); + purple_account_set_private_alias(account, value); else - purple_account_set_alias(account, NULL); + purple_account_set_private_alias(account, NULL); /* Buddy Icon */ if (dialog->prpl_info != NULL && dialog->prpl_info->icon_spec.format != NULL) @@ -1668,7 +1672,7 @@ if (new_acct) purple_accounts_add(account); else - purple_signal_emit(pidgin_account_get_handle(), "account-modified", account); + purple_signal_emit(pidgin_accounts_get_handle(), "account-modified", account); /* If this is a new account, then sign on! */ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->register_button))) { @@ -2555,7 +2559,7 @@ /* Close button */ pidgin_dialog_add_button(GTK_DIALOG(win), GTK_STOCK_CLOSE, G_CALLBACK(close_accounts_cb), dialog); - purple_signal_connect(pidgin_account_get_handle(), "account-modified", + purple_signal_connect(pidgin_accounts_get_handle(), "account-modified", accounts_window, PURPLE_CALLBACK(account_modified_cb), accounts_window); purple_prefs_connect_callback(accounts_window, @@ -2901,10 +2905,11 @@ pidgin_accounts_request_add, pidgin_accounts_request_authorization, pidgin_accounts_request_close, - NULL, - NULL, - NULL, - NULL + pidgin_permit_added_removed, + pidgin_permit_added_removed, + pidgin_deny_added_removed, + pidgin_deny_added_removed, + NULL, NULL, NULL, NULL }; PurpleAccountUiOps * @@ -2914,14 +2919,14 @@ } void * -pidgin_account_get_handle(void) { +pidgin_accounts_get_handle(void) { static int handle; return &handle; } void -pidgin_account_init(void) +pidgin_accounts_init(void) { char *default_avatar = NULL; purple_prefs_add_none(PIDGIN_PREFS_ROOT "/accounts"); @@ -2941,29 +2946,29 @@ purple_prefs_add_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon", default_avatar); g_free(default_avatar); - purple_signal_register(pidgin_account_get_handle(), "account-modified", + purple_signal_register(pidgin_accounts_get_handle(), "account-modified", purple_marshal_VOID__POINTER, NULL, 1, purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_ACCOUNT)); /* Setup some purple signal handlers. */ purple_signal_connect(purple_connections_get_handle(), "signed-on", - pidgin_account_get_handle(), + pidgin_accounts_get_handle(), PURPLE_CALLBACK(signed_on_off_cb), NULL); purple_signal_connect(purple_connections_get_handle(), "signed-off", - pidgin_account_get_handle(), + pidgin_accounts_get_handle(), PURPLE_CALLBACK(signed_on_off_cb), NULL); purple_signal_connect(purple_accounts_get_handle(), "account-added", - pidgin_account_get_handle(), + pidgin_accounts_get_handle(), PURPLE_CALLBACK(add_account_to_liststore), NULL); purple_signal_connect(purple_accounts_get_handle(), "account-removed", - pidgin_account_get_handle(), + pidgin_accounts_get_handle(), PURPLE_CALLBACK(account_removed_cb), NULL); purple_signal_connect(purple_accounts_get_handle(), "account-disabled", - pidgin_account_get_handle(), + pidgin_accounts_get_handle(), PURPLE_CALLBACK(account_abled_cb), GINT_TO_POINTER(FALSE)); purple_signal_connect(purple_accounts_get_handle(), "account-enabled", - pidgin_account_get_handle(), + pidgin_accounts_get_handle(), PURPLE_CALLBACK(account_abled_cb), GINT_TO_POINTER(TRUE)); account_pref_wins = @@ -2971,7 +2976,7 @@ } void -pidgin_account_uninit(void) +pidgin_accounts_uninit(void) { /* * TODO: Need to free all the dialogs in here. Could probably create @@ -2980,7 +2985,7 @@ */ g_hash_table_destroy(account_pref_wins); - purple_signals_disconnect_by_handle(pidgin_account_get_handle()); - purple_signals_unregister_by_instance(pidgin_account_get_handle()); + purple_signals_disconnect_by_handle(pidgin_accounts_get_handle()); + purple_signals_unregister_by_instance(pidgin_accounts_get_handle()); }
--- a/pidgin/gtkaccount.h Sun Jun 23 02:43:06 2013 -0500 +++ b/pidgin/gtkaccount.h Sun Jun 23 13:35:53 2013 +0530 @@ -27,7 +27,7 @@ #ifndef _PIDGINACCOUNT_H_ #define _PIDGINACCOUNT_H_ -#include "account.h" +#include "accounts.h" typedef enum { @@ -70,17 +70,17 @@ * * @return The handle to the GTK+ account system */ -void *pidgin_account_get_handle(void); +void *pidgin_accounts_get_handle(void); /** * Initializes the GTK+ account system */ -void pidgin_account_init(void); +void pidgin_accounts_init(void); /** * Uninitializes the GTK+ account system */ -void pidgin_account_uninit(void); +void pidgin_accounts_uninit(void); G_END_DECLS
--- a/pidgin/gtkblist.c Sun Jun 23 02:43:06 2013 -0500 +++ b/pidgin/gtkblist.c Sun Jun 23 13:35:53 2013 +0530 @@ -1416,14 +1416,14 @@ account = purple_buddy_get_account(buddy); name = purple_buddy_get_name(buddy); - permitted = purple_privacy_check(account, name); + permitted = purple_account_privacy_check(account, name); /* XXX: Perhaps ask whether to restore the previous lists where appropirate? */ if (permitted) - purple_privacy_deny(account, name, FALSE, FALSE); + purple_account_privacy_deny(account, name); else - purple_privacy_allow(account, name, FALSE, FALSE); + purple_account_privacy_allow(account, name); pidgin_blist_update(purple_get_blist(), node); } @@ -1435,7 +1435,7 @@ gboolean permitted; account = purple_buddy_get_account(buddy); - permitted = purple_privacy_check(account, purple_buddy_get_name(buddy)); + permitted = purple_account_privacy_check(account, purple_buddy_get_name(buddy)); pidgin_new_item_from_stock(menu, permitted ? _("_Block") : _("Un_block"), permitted ? PIDGIN_STOCK_TOOLBAR_BLOCK : PIDGIN_STOCK_TOOLBAR_UNBLOCK, G_CALLBACK(toggle_privacy), @@ -4159,7 +4159,7 @@ g_return_val_if_fail(buddy != NULL, NULL); - if (!purple_privacy_check(purple_buddy_get_account(buddy), purple_buddy_get_name(buddy))) { + if (!purple_account_privacy_check(purple_buddy_get_account(buddy), purple_buddy_get_name(buddy))) { path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", "16", "blocked.png", NULL); return _pidgin_blist_get_cached_emblem(path); } @@ -6309,7 +6309,7 @@ purple_signal_connect(handle, "account-actions-changed", gtkblist, PURPLE_CALLBACK(account_actions_changed), NULL); - handle = pidgin_account_get_handle(); + handle = pidgin_accounts_get_handle(); purple_signal_connect(handle, "account-modified", gtkblist, PURPLE_CALLBACK(account_modified), gtkblist);
--- a/pidgin/gtkconv.c Sun Jun 23 02:43:06 2013 -0500 +++ b/pidgin/gtkconv.c Sun Jun 23 13:35:53 2013 +0530 @@ -5140,7 +5140,7 @@ replace = purple_conversation_get_name(conv); } else if (g_str_has_prefix(cur, "%sourceName%")) { - replace = purple_account_get_alias(account); + replace = purple_account_get_private_alias(account); if (replace == NULL) replace = purple_account_get_username(account); @@ -7205,7 +7205,7 @@ gtk_action_set_visible(win->menu.get_info, TRUE); gtk_action_set_visible(win->menu.invite, FALSE); gtk_action_set_visible(win->menu.alias, TRUE); - if (purple_privacy_check(account, purple_conversation_get_name(conv))) { + if (purple_account_privacy_check(account, purple_conversation_get_name(conv))) { gtk_action_set_visible(win->menu.unblock, FALSE); gtk_action_set_visible(win->menu.block, TRUE); } else {
--- a/pidgin/gtkmain.c Sun Jun 23 02:43:06 2013 -0500 +++ b/pidgin/gtkmain.c Sun Jun 23 13:35:53 2013 +0530 @@ -257,7 +257,6 @@ purple_xfers_set_ui_ops(pidgin_xfers_get_ui_ops()); purple_blist_set_ui_ops(pidgin_blist_get_ui_ops()); purple_notify_set_ui_ops(pidgin_notify_get_ui_ops()); - purple_privacy_set_ui_ops(pidgin_privacy_get_ui_ops()); purple_request_set_ui_ops(pidgin_request_get_ui_ops()); purple_sound_set_ui_ops(pidgin_sound_get_ui_ops()); purple_connections_set_ui_ops(pidgin_connections_get_ui_ops()); @@ -266,7 +265,7 @@ purple_idle_set_ui_ops(pidgin_idle_get_ui_ops()); #endif - pidgin_account_init(); + pidgin_accounts_init(); pidgin_connection_init(); pidgin_blist_init(); pidgin_status_init(); @@ -302,7 +301,7 @@ pidgin_docklet_uninit(); pidgin_blist_uninit(); pidgin_connection_uninit(); - pidgin_account_uninit(); + pidgin_accounts_uninit(); pidgin_xfers_uninit(); pidgin_debug_uninit();
--- a/pidgin/gtkprivacy.c Sun Jun 23 02:43:06 2013 -0500 +++ b/pidgin/gtkprivacy.c Sun Jun 23 13:35:53 2013 +0530 @@ -28,7 +28,6 @@ #include "connection.h" #include "debug.h" -#include "privacy.h" #include "request.h" #include "util.h" @@ -80,17 +79,20 @@ } const menu_entries[] = { - { N_("Allow all users to contact me"), PURPLE_PRIVACY_ALLOW_ALL }, - { N_("Allow only the users on my buddy list"), PURPLE_PRIVACY_ALLOW_BUDDYLIST }, - { N_("Allow only the users below"), PURPLE_PRIVACY_ALLOW_USERS }, - { N_("Block all users"), PURPLE_PRIVACY_DENY_ALL }, - { N_("Block only the users below"), PURPLE_PRIVACY_DENY_USERS } + { N_("Allow all users to contact me"), PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL }, + { N_("Allow only the users on my buddy list"), PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST }, + { N_("Allow only the users below"), PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS }, + { N_("Block all users"), PURPLE_ACCOUNT_PRIVACY_DENY_ALL }, + { N_("Block only the users below"), PURPLE_ACCOUNT_PRIVACY_DENY_USERS } }; static const size_t menu_entry_count = sizeof(menu_entries) / sizeof(*menu_entries); static PidginPrivacyDialog *privacy_dialog = NULL; +void pidgin_permit_added_removed(PurpleAccount *account, const char *name); +void pidgin_deny_added_removed(PurpleAccount *account, const char *name); + static void rebuild_allow_list(PidginPrivacyDialog *dialog) { @@ -99,7 +101,7 @@ gtk_list_store_clear(dialog->allow_store); - for (l = dialog->account->permit; l != NULL; l = l->next) { + for (l = purple_account_privacy_get_permitted(dialog->account); l != NULL; l = l->next) { gtk_list_store_append(dialog->allow_store, &iter); gtk_list_store_set(dialog->allow_store, &iter, 0, l->data, -1); } @@ -113,7 +115,7 @@ gtk_list_store_clear(dialog->block_store); - for (l = dialog->account->deny; l != NULL; l = l->next) { + for (l = purple_account_privacy_get_denied(dialog->account); l != NULL; l = l->next) { gtk_list_store_append(dialog->block_store, &iter); gtk_list_store_set(dialog->block_store, &iter, 0, l->data, -1); } @@ -239,12 +241,12 @@ gtk_widget_hide(dialog->block_widget); gtk_widget_hide(dialog->button_box); - if (new_type == PURPLE_PRIVACY_ALLOW_USERS) { + if (new_type == PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS) { gtk_widget_show(dialog->allow_widget); gtk_widget_show_all(dialog->button_box); dialog->in_allow_list = TRUE; } - else if (new_type == PURPLE_PRIVACY_DENY_USERS) { + else if (new_type == PURPLE_ACCOUNT_PRIVACY_DENY_USERS) { gtk_widget_show(dialog->block_widget); gtk_widget_show_all(dialog->button_box); dialog->in_allow_list = FALSE; @@ -295,9 +297,9 @@ return; if (dialog->in_allow_list) - purple_privacy_permit_remove(dialog->account, name, FALSE); + purple_account_privacy_permit_remove(dialog->account, name, FALSE); else - purple_privacy_deny_remove(dialog->account, name, FALSE); + purple_account_privacy_deny_remove(dialog->account, name, FALSE); g_free(name); } @@ -307,17 +309,17 @@ { GSList *l; if (dialog->in_allow_list) - l = dialog->account->permit; + l = purple_account_privacy_get_permitted(dialog->account); else - l = dialog->account->deny; + l = purple_account_privacy_get_denied(dialog->account); while (l) { char *user; user = l->data; l = l->next; if (dialog->in_allow_list) - purple_privacy_permit_remove(dialog->account, user, FALSE); + purple_account_privacy_permit_remove(dialog->account, user, FALSE); else - purple_privacy_deny_remove(dialog->account, user, FALSE); + purple_account_privacy_deny_remove(dialog->account, user, FALSE); } } @@ -413,12 +415,12 @@ type_changed_cb(GTK_COMBO_BOX(dialog->type_menu), dialog); #if 0 - if (purple_account_get_privacy_type(dialog->account) == PURPLE_PRIVACY_ALLOW_USERS) { + if (purple_account_get_privacy_type(dialog->account) == PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS) { gtk_widget_show(dialog->allow_widget); gtk_widget_show(dialog->button_box); dialog->in_allow_list = TRUE; } - else if (purple_account_get_privacy_type(dialog->account) == PURPLE_PRIVACY_DENY_USERS) { + else if (purple_account_get_privacy_type(dialog->account) == PURPLE_ACCOUNT_PRIVACY_DENY_USERS) { gtk_widget_show(dialog->block_widget); gtk_widget_show(dialog->button_box); dialog->in_allow_list = FALSE; @@ -462,9 +464,9 @@ confirm_permit_block_cb(PidginPrivacyRequestData *data, int option) { if (data->block) - purple_privacy_deny(data->account, data->name, FALSE, FALSE); + purple_account_privacy_deny(data->account, data->name); else - purple_privacy_allow(data->account, data->name, FALSE, FALSE); + purple_account_privacy_allow(data->account, data->name); destroy_request_data(data); } @@ -558,38 +560,20 @@ } } -static void +void pidgin_permit_added_removed(PurpleAccount *account, const char *name) { if (privacy_dialog != NULL) rebuild_allow_list(privacy_dialog); } -static void +void pidgin_deny_added_removed(PurpleAccount *account, const char *name) { if (privacy_dialog != NULL) rebuild_block_list(privacy_dialog); } -static PurplePrivacyUiOps privacy_ops = -{ - pidgin_permit_added_removed, - pidgin_permit_added_removed, - pidgin_deny_added_removed, - pidgin_deny_added_removed, - NULL, - NULL, - NULL, - NULL -}; - -PurplePrivacyUiOps * -pidgin_privacy_get_ui_ops(void) -{ - return &privacy_ops; -} - void pidgin_privacy_init(void) {
--- a/pidgin/gtkprivacy.h Sun Jun 23 02:43:06 2013 -0500 +++ b/pidgin/gtkprivacy.h Sun Jun 23 13:35:53 2013 +0530 @@ -26,7 +26,7 @@ #ifndef _PIDGINPRIVACY_H_ #define _PIDGINPRIVACY_H_ -#include "privacy.h" +#include "account.h" G_BEGIN_DECLS @@ -67,13 +67,6 @@ */ void pidgin_request_add_block(PurpleAccount *account, const char *name); -/** - * Returns the UI operations structure for the GTK+ privacy subsystem. - * - * @return The GTK+ UI privacy operations structure. - */ -PurplePrivacyUiOps *pidgin_privacy_get_ui_ops(void); - G_END_DECLS #endif /* _PIDGINPRIVACY_H_ */
--- a/pidgin/gtksession.c Sun Jun 23 02:43:06 2013 -0500 +++ b/pidgin/gtksession.c Sun Jun 23 13:35:53 2013 +0530 @@ -366,7 +366,7 @@ g_free(tmp); session_set_gchar(session, SmRestartStyleHint, (gchar) SmRestartIfRunning); - session_set_string(session, SmProgram, g_get_prgname()); + session_set_string(session, SmProgram, (gchar *) g_get_prgname()); myself = g_strdup(argv0); purple_debug(PURPLE_DEBUG_MISC, "Session Management",
--- a/pidgin/gtkutils.c Sun Jun 23 02:43:06 2013 -0500 +++ b/pidgin/gtkutils.c Sun Jun 23 13:35:53 2013 +0530 @@ -733,10 +733,10 @@ gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE); } - if (purple_account_get_alias(account)) { + if (purple_account_get_private_alias(account)) { g_snprintf(buf, sizeof(buf), "%s (%s) (%s)", purple_account_get_username(account), - purple_account_get_alias(account), + purple_account_get_private_alias(account), purple_account_get_protocol_name(account)); } else { g_snprintf(buf, sizeof(buf), "%s (%s)",
--- a/pidgin/plugins/gtk-signals-test.c Sun Jun 23 02:43:06 2013 -0500 +++ b/pidgin/plugins/gtk-signals-test.c Sun Jun 23 13:35:53 2013 +0530 @@ -110,7 +110,7 @@ static gboolean plugin_load(PurplePlugin *plugin) { - void *accounts_handle = pidgin_account_get_handle(); + void *accounts_handle = pidgin_accounts_get_handle(); void *blist_handle = pidgin_blist_get_handle(); void *conv_handle = pidgin_conversations_get_handle();
--- a/pidgin/plugins/perl/common/GtkAccount.xs Sun Jun 23 02:43:06 2013 -0500 +++ b/pidgin/plugins/perl/common/GtkAccount.xs Sun Jun 23 13:35:53 2013 +0530 @@ -4,7 +4,7 @@ PROTOTYPES: ENABLE Purple::Handle -pidgin_account_get_handle() +pidgin_accounts_get_handle() MODULE = Pidgin::Account PACKAGE = Pidgin::Account::Dialog PREFIX = pidgin_account_dialog_ PROTOTYPES: ENABLE
--- a/po/POTFILES.in Sun Jun 23 02:43:06 2013 -0500 +++ b/po/POTFILES.in Sun Jun 23 13:35:53 2013 +0530 @@ -18,20 +18,6 @@ finch/gntsound.c finch/gntstatus.c finch/gntui.c -finch/libgnt/gntbox.c -finch/libgnt/gntbutton.c -finch/libgnt/gntcheckbox.c -finch/libgnt/gntcolors.c -finch/libgnt/gntcombobox.c -finch/libgnt/gntentry.c -finch/libgnt/gntkeys.c -finch/libgnt/gntlabel.c -finch/libgnt/gntline.c -finch/libgnt/gntstyle.c -finch/libgnt/gnttextview.c -finch/libgnt/gnttree.c -finch/libgnt/gntutils.c -finch/libgnt/gntwidget.c finch/plugins/gntclipboard.c finch/plugins/gntgf.c finch/plugins/gnthistory.c @@ -44,14 +30,15 @@ libpurple/connection.c libpurple/conversation.c libpurple/dbus-server.c -libpurple/dbus-server.h libpurple/desktopitem.c libpurple/dnsquery.c libpurple/ft.c libpurple/gconf/purple.schemas.in +libpurple/http.c libpurple/keyring.c libpurple/log.c libpurple/media/backend-fs2.c +libpurple/obsolete.c libpurple/plugin.c libpurple/plugins/autoaccept.c libpurple/plugins/buddynote.c @@ -82,10 +69,16 @@ libpurple/plugins/statenotify.c libpurple/plugins/tcl/tcl.c libpurple/protocols/bonjour/bonjour.c -libpurple/protocols/bonjour/bonjour.h libpurple/protocols/bonjour/jabber.c libpurple/protocols/bonjour/mdns_win32.c +libpurple/protocols/gg/account.c +libpurple/protocols/gg/deprecated.c libpurple/protocols/gg/gg.c +libpurple/protocols/gg/image.c +libpurple/protocols/gg/pubdir-prpl.c +libpurple/protocols/gg/purplew.c +libpurple/protocols/gg/status.c +libpurple/protocols/gg/validator.c libpurple/protocols/irc/cmds.c libpurple/protocols/irc/dcc_send.c libpurple/protocols/irc/irc.c @@ -102,6 +95,8 @@ libpurple/protocols/jabber/chat.c libpurple/protocols/jabber/jabber.c libpurple/protocols/jabber/jutil.c +libpurple/protocols/jabber/libfacebook.c +libpurple/protocols/jabber/libgtalk.c libpurple/protocols/jabber/libxmpp.c libpurple/protocols/jabber/message.c libpurple/protocols/jabber/parser.c @@ -113,7 +108,6 @@ libpurple/protocols/jabber/xdata.c libpurple/protocols/msn/contact.c libpurple/protocols/msn/error.c -libpurple/protocols/msn/group.h libpurple/protocols/msn/msg.c libpurple/protocols/msn/msn.c libpurple/protocols/msn/nexus.c @@ -121,20 +115,11 @@ libpurple/protocols/msn/oim.c libpurple/protocols/msn/servconn.c libpurple/protocols/msn/session.c -libpurple/protocols/msn/slp.c libpurple/protocols/msn/slpcall.c libpurple/protocols/msn/state.c libpurple/protocols/msn/switchboard.c libpurple/protocols/msn/userlist.c -libpurple/protocols/mxit/actions.c -libpurple/protocols/mxit/filexfer.c -libpurple/protocols/mxit/http.c -libpurple/protocols/mxit/login.c libpurple/protocols/mxit/multimx.c -libpurple/protocols/mxit/mxit.c -libpurple/protocols/mxit/profile.c -libpurple/protocols/mxit/protocol.c -libpurple/protocols/mxit/roster.c libpurple/protocols/mxit/splashscreen.c libpurple/protocols/myspace/myspace.c libpurple/protocols/myspace/user.c @@ -144,7 +129,9 @@ libpurple/protocols/oscar/authorization.c libpurple/protocols/oscar/clientlogin.c libpurple/protocols/oscar/encoding.c +libpurple/protocols/oscar/family_auth.c libpurple/protocols/oscar/family_chatnav.c +libpurple/protocols/oscar/family_feedbag.c libpurple/protocols/oscar/family_icbm.c libpurple/protocols/oscar/family_locate.c libpurple/protocols/oscar/flap_connection.c @@ -180,7 +167,7 @@ libpurple/protocols/zephyr/zephyr.c libpurple/proxy.c libpurple/prpl.c -libpurple/request.h +libpurple/request.c libpurple/savedstatuses.c libpurple/server.c libpurple/smiley.c @@ -194,7 +181,6 @@ pidgin/gtkblist-theme.c pidgin/gtkblist.c pidgin/gtkcertmgr.c -pidgin/gtkconn.c pidgin/gtkconv.c pidgin/gtkdebug.c pidgin/gtkdialogs.c @@ -217,8 +203,9 @@ pidgin/gtksound.c pidgin/gtkstatusbox.c pidgin/gtkutils.c +pidgin/gtkwebview.c +pidgin/gtkwebviewtoolbar.c pidgin/gtkwhiteboard.c -pidgin/pidgin.h pidgin/pidginstock.c pidgin/pidgintooltip.c pidgin/pixmaps/emotes/default/24/default.theme.in @@ -254,9 +241,7 @@ pidgin/plugins/themeedit-icon.c pidgin/plugins/themeedit.c pidgin/plugins/ticker/ticker.c -pidgin/plugins/timestamp.c -pidgin/plugins/timestamp_format.c -pidgin/plugins/vvconfig.c +pidgin/plugins/webkit.c pidgin/plugins/win32/transparency/win2ktrans.c pidgin/plugins/win32/winprefs/winprefs.c pidgin/plugins/xmppconsole.c