/soc/2012/tomkiewicz/gg: 57013b9e1a8e: Gadu-Gadu: roster - downl...

Tomasz Wasilczyk tomkiewicz at cpw.pidgin.im
Mon Jul 9 15:21:39 EDT 2012


Changeset: 57013b9e1a8e44cda2d00de413bdb160858d070c
Author:	 Tomasz Wasilczyk <tomkiewicz at cpw.pidgin.im>
Date:	 2012-07-09 21:21 +0200
Branch:	 soc.2012.gg
URL: http://hg.pidgin.im/soc/2012/tomkiewicz/gg/rev/57013b9e1a8e

Description:

Gadu-Gadu: roster - downloading

diffstat:

 configure.ac                        |   13 +
 libpurple/protocols/gg/Makefile.am  |   10 +-
 libpurple/protocols/gg/gg.c         |   17 +-
 libpurple/protocols/gg/gg.h         |    2 +
 libpurple/protocols/gg/lib/config.h |    2 +-
 libpurple/protocols/gg/roster.c     |  325 ++++++++++++++++++++++++++++++++++++
 libpurple/protocols/gg/roster.h     |   19 ++
 libpurple/protocols/gg/xml.c        |   58 ++++++
 libpurple/protocols/gg/xml.h        |   11 +
 9 files changed, 450 insertions(+), 7 deletions(-)

diffs (truncated from 568 to 300 lines):

diff --git a/configure.ac b/configure.ac
--- a/configure.ac
+++ b/configure.ac
@@ -765,6 +765,19 @@
 AC_SUBST(LIBXML_LIBS)
 
 dnl #######################################################################
+dnl # Check for zlib (required)
+dnl #######################################################################
+
+PKG_CHECK_MODULES(ZLIB, [zlib >= 1.2.0], , [
+	AC_MSG_RESULT(no)
+	AC_MSG_ERROR([
+You must have zlib >= 1.2.0 development headers installed to build.
+])])
+
+AC_SUBST(ZLIB_CFLAGS)
+AC_SUBST(ZLIB_LIBS)
+
+dnl #######################################################################
 dnl # GConf schemas
 dnl #######################################################################
 AC_PATH_PROG(GCONFTOOL, gconftool-2, no)
diff --git a/libpurple/protocols/gg/Makefile.am b/libpurple/protocols/gg/Makefile.am
--- a/libpurple/protocols/gg/Makefile.am
+++ b/libpurple/protocols/gg/Makefile.am
@@ -1,3 +1,5 @@
+V=0
+
 pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
 
 EXTRA_DIST = \
@@ -35,8 +37,10 @@
 	lib/sha1.c
 
 INTGG_CFLAGS = -I$(top_srcdir)/libpurple/protocols/gg/lib \
+	$(ZLIB_CFLAGS) \
 	-DGG_IGNORE_DEPRECATED \
 	-DGG_INTERNAL_LIBGADU_VERSION=$(GADU_LIBGADU_VERSION)
+GADU_LIBS += $(ZLIB_LIBS)
 endif
 
 if USE_GNUTLS
@@ -71,7 +75,11 @@
 	avatar.h \
 	avatar.c \
 	libgadu-events.h \
-	libgadu-events.c
+	libgadu-events.c \
+	roster.c \
+	roster.h \
+	xml.c \
+	xml.h
 
 AM_CFLAGS = $(st)
 
diff --git a/libpurple/protocols/gg/gg.c b/libpurple/protocols/gg/gg.c
--- a/libpurple/protocols/gg/gg.c
+++ b/libpurple/protocols/gg/gg.c
@@ -65,11 +65,9 @@
 static void ggp_action_buddylist_get(PurplePluginAction *action)
 {
 	PurpleConnection *gc = (PurpleConnection *)action->context;
-	GGPInfo *info = purple_connection_get_protocol_data(gc);
-
-	purple_debug_info("gg", "Downloading...\n");
-
-	gg_userlist_request(info->session, GG_USERLIST_GET, NULL);
+	// TODO: just for debugging
+	// we will drop this action when roster will be ready
+	ggp_roster_update(gc);
 }
 
 /**
@@ -1197,6 +1195,13 @@
 		case GG_EVENT_USER_DATA:
 			ggp_events_user_data(gc, &ev->event.user_data);
 			break;
+		case GG_EVENT_USERLIST100_VERSION:
+			purple_debug_info("gg", "GG_EVENT_USERLIST100_VERSION: %u\n",
+				ev->event.userlist100_version.version);
+			break;
+		case GG_EVENT_USERLIST100_REPLY:
+			ggp_roster_reply(gc, &ev->event.userlist100_reply);
+			break;
 		default:
 			purple_debug_error("gg",
 				"unsupported event type=%d\n", ev->type);
@@ -1568,6 +1573,7 @@
 
 	ggp_image_setup(gc);
 	ggp_avatar_setup(gc);
+	ggp_roster_setup(gc);
 	
 	glp->uin = ggp_str_to_uin(purple_account_get_username(account));
 	glp->password = ggp_convert_to_cp1250(purple_account_get_password(account));
@@ -1683,6 +1689,7 @@
 		ggp_search_destroy(info->searches);
 		ggp_image_cleanup(gc);
 		ggp_avatar_cleanup(gc);
+		ggp_roster_cleanup(gc);
 
 		if (info->inpa > 0)
 			purple_input_remove(info->inpa);
diff --git a/libpurple/protocols/gg/gg.h b/libpurple/protocols/gg/gg.h
--- a/libpurple/protocols/gg/gg.h
+++ b/libpurple/protocols/gg/gg.h
@@ -32,6 +32,7 @@
 #include "image.h"
 #include "avatar.h"
 #include "account.h"
+#include "roster.h"
 
 
 #define PUBDIR_RESULTS_MAX 20
@@ -57,6 +58,7 @@
 
 	ggp_image_connection_data image_data;
 	ggp_avatar_session_data avatar_data;
+	ggp_roster_session_data roster_data;
 } GGPInfo;
 
 #endif /* _PURPLE_GG_H */
diff --git a/libpurple/protocols/gg/lib/config.h b/libpurple/protocols/gg/lib/config.h
--- a/libpurple/protocols/gg/lib/config.h
+++ b/libpurple/protocols/gg/lib/config.h
@@ -58,7 +58,7 @@
 #undef GG_CONFIG_HAVE_OPENSSL
 
 /* Defined if libgadu was compiled and linked with zlib support. */
-#undef GG_CONFIG_HAVE_ZLIB
+#define GG_CONFIG_HAVE_ZLIB
 
 /* Defined if uintX_t types are defined in <stdint.h>. */
 #undef GG_CONFIG_HAVE_STDINT_H
diff --git a/libpurple/protocols/gg/roster.c b/libpurple/protocols/gg/roster.c
new file mode 100644
--- /dev/null
+++ b/libpurple/protocols/gg/roster.c
@@ -0,0 +1,325 @@
+#include "roster.h"
+
+#include "gg.h"
+#include "xml.h"
+#include "utils.h"
+
+#include <debug.h>
+
+#define GGP_ROSTER_SYNC_SETT "gg-synchronized"
+#define GGP_ROSTER_DEBUG 1
+
+static void ggp_roster_set_synchronized(PurpleBuddy *buddy, gboolean synchronized);
+static gboolean ggp_roster_is_synchronized(PurpleBuddy *buddy);
+
+static void ggp_roster_reply_list(PurpleConnection *gc, uint32_t version, const char *reply);
+
+#if GGP_ROSTER_DEBUG
+static void ggp_roster_dump(PurpleConnection *gc);
+#endif
+
+/********/
+
+static inline ggp_roster_session_data *
+ggp_roster_get_rdata(PurpleConnection *gc)
+{
+	GGPInfo *accdata = purple_connection_get_protocol_data(gc);
+	return &accdata->roster_data;
+} 
+
+void ggp_roster_setup(PurpleConnection *gc)
+{
+	ggp_roster_session_data *rdata = ggp_roster_get_rdata(gc);
+
+	rdata->xml = NULL;
+	rdata->version = 0;
+}
+
+void ggp_roster_cleanup(PurpleConnection *gc)
+{
+	ggp_roster_session_data *rdata = ggp_roster_get_rdata(gc);
+
+	if (rdata->xml)
+		xmlnode_free(rdata->xml);
+}
+
+static void ggp_roster_set_synchronized(PurpleBuddy *buddy, gboolean synchronized)
+{
+	purple_blist_node_set_bool((PurpleBlistNode*)buddy, GGP_ROSTER_SYNC_SETT, synchronized);
+}
+
+static gboolean ggp_roster_is_synchronized(PurpleBuddy *buddy)
+{
+	return purple_blist_node_get_bool((PurpleBlistNode*)buddy, GGP_ROSTER_SYNC_SETT);
+}
+
+void ggp_roster_update(PurpleConnection *gc)
+{
+	GGPInfo *accdata = purple_connection_get_protocol_data(gc);
+	
+	purple_debug_info("gg", "ggp_roster_update\n");
+	
+	if (!gg_libgadu_check_feature(GG_LIBGADU_FEATURE_USERLIST100))
+	{
+		purple_debug_error("gg", "ggp_roster_update - feature disabled\n");
+		return;
+	}
+	
+	gg_userlist100_request(accdata->session, GG_USERLIST100_GET, 0, GG_USERLIST100_FORMAT_TYPE_GG100, NULL);
+}
+
+void ggp_roster_reply(PurpleConnection *gc, struct gg_event_userlist100_reply *reply)
+{
+	purple_debug_info("gg", "ggp_roster_reply [type=%d, version=%u, format_type=%d]\n",
+		reply->type, reply->version, reply->format_type);
+	
+	if (reply->type != GG_USERLIST100_REPLY_LIST)
+		return;
+	
+	if (GG_USERLIST100_FORMAT_TYPE_GG100 != reply->format_type)
+	{
+		purple_debug_warning("gg", "ggp_buddylist_load100_reply: unsupported format type (%u)\n", reply->format_type);
+		return;
+	}
+	
+	ggp_roster_reply_list(gc, reply->version, reply->reply);
+}
+
+static void ggp_roster_reply_list(PurpleConnection *gc, uint32_t version, const char *data)
+{
+	ggp_roster_session_data *rdata = ggp_roster_get_rdata(gc);
+	xmlnode *xml, *curr_list, *curr_elem;
+	GHashTable *groups;
+	PurpleAccount *account;
+	GSList *buddies;
+	GHashTable *remove_buddies;
+	GList *remove_buddies_list, *remove_buddies_it;
+
+	g_return_if_fail(gc != NULL);
+	g_return_if_fail(data != NULL);
+
+	account = purple_connection_get_account(gc);
+
+	xml = xmlnode_from_str(data, -1);
+	if (xml == NULL)
+	{
+		purple_debug_warning("gg", "ggp_roster_reply_list: invalid xml\n");
+		return;
+	}
+
+	if (rdata->xml)
+		xmlnode_free(rdata->xml);
+	rdata->xml = xml;
+
+#if GGP_ROSTER_DEBUG
+	ggp_roster_dump(gc);
+#endif
+
+	// reading groups
+
+	curr_list = xmlnode_get_child(xml, "Groups");
+	g_return_if_fail(curr_list != NULL);
+
+	groups = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+	curr_elem = xmlnode_get_child(curr_list, "Group");
+	while (curr_elem != NULL)
+	{
+		char *name, *id;
+		gboolean removable;
+		gboolean succ = TRUE;
+		
+		succ &= ggp_xml_get_string(curr_elem, "Id", &id);
+		succ &= ggp_xml_get_string(curr_elem, "Name", &name);
+		succ &= ggp_xml_get_bool(curr_elem, "IsRemovable", &removable);
+		
+		if (!succ)
+		{
+			g_free(id);
+			g_free(name);
+			g_hash_table_destroy(groups);
+			g_return_if_reached();
+		}
+		
+		if (removable)
+		{
+			g_hash_table_insert(groups, id, name);
+			purple_debug_misc("gg", "ggp_roster_reply_list: group %s [id=%s]\n", name, id);
+		}
+		else
+		{
+			g_free(id);
+			g_free(name);
+		}
+		
+		curr_elem = xmlnode_get_next_twin(curr_elem);
+	}
+	
+	// dumping current buddy list
+	// we will remove them, if not found in list at server
+	
+	buddies = purple_find_buddies(account, NULL);



More information about the Commits mailing list