libpurple/protocols/myspace/myspace.c

branch
soc.2007.msimprpl
changeset 19166
d625520b98ac
parent 19164
1fd7022f57eb
child 19167
4ec67fc6d814
--- a/libpurple/protocols/myspace/myspace.c	Sun Aug 12 23:16:53 2007 +0000
+++ b/libpurple/protocols/myspace/myspace.c	Sun Aug 12 23:20:07 2007 +0000
@@ -129,6 +129,9 @@
 static gchar *msim_markup_to_html(MsimSession *, const gchar *raw);
 static gchar *html_to_msim_markup(MsimSession *, const gchar *raw);
 
+static MsimUser *msim_get_user_from_buddy(PurpleBuddy *buddy);
+static MsimUser *msim_find_user(MsimSession *session, const gchar *username);
+
 static gboolean msim_incoming_bm_record_cv(MsimSession *session, 
 		MsimMessage *msg);
 static gboolean msim_incoming_bm(MsimSession *session, MsimMessage *msg);
@@ -146,13 +149,14 @@
 #endif
 
 static void msim_get_info_cb(MsimSession *session, MsimMessage *userinfo, gpointer data);
+static gchar *msim_format_now_playing(gchar *band, gchar *song);
 
 static void msim_set_status_code(MsimSession *session, guint code, 
 		gchar *statstring);
 
-static void msim_store_buddy_info_each(gpointer key, gpointer value, 
+static void msim_store_user_info_each(gpointer key, gpointer value, 
 		gpointer user_data);
-static gboolean msim_store_buddy_info(MsimSession *session, MsimMessage *msg);
+static gboolean msim_store_user_info(MsimSession *session, MsimMessage *msg);
 static gboolean msim_process_server_info(MsimSession *session, 
 		MsimMessage *msg);
 static gboolean msim_web_challenge(MsimSession *session, MsimMessage *msg); 
@@ -307,7 +311,7 @@
 	gc = purple_account_get_connection(buddy->account);
 	g_return_if_fail(gc != NULL);
 
-	session = (MsimSession *)(gc->proto_data);
+	session = (MsimSession *)gc->proto_data;
 	g_return_if_fail(session != NULL);
 
 	username = buddy->name;
@@ -467,7 +471,7 @@
 	g_return_val_if_fail(buf != NULL, -1);
 	g_return_val_if_fail(total_bytes >= 0, -1);
 
-	session = (MsimSession *)(gc->proto_data);
+	session = (MsimSession *)gc->proto_data;
 
 	g_return_val_if_fail(MSIM_SESSION_VALID(session), -1);
 	
@@ -1409,13 +1413,56 @@
 	return markup;
 }
 
+/** Get the MsimUser from a PurpleBuddy, creating it if needed. */
+static MsimUser *
+msim_get_user_from_buddy(PurpleBuddy *buddy)
+{
+	MsimUser *user;
+
+	if (!buddy) {
+		return NULL;
+	}
+
+	if (!buddy->proto_data) {
+		/* TODO: where is this freed? */
+		user = g_new0(MsimUser, 1);
+		user->buddy = buddy;
+		buddy->proto_data = (gpointer)user;
+		purple_debug_info("msim_get_user_from_buddy",
+				"creating new user for %s to %X\n",
+				buddy->name, buddy->proto_data);
+	} 
+
+	user = (MsimUser *)(buddy->proto_data);
+
+	return user;
+}
+
+/** Find and return an MsimUser * representing a user on the buddy list, or NULL. */
+static MsimUser *
+msim_find_user(MsimSession *session, const gchar *username)
+{
+	PurpleBuddy *buddy;
+	MsimUser *user;
+
+	buddy = purple_find_buddy(session->account, username);
+	if (!buddy) {
+		return NULL;
+	}
+
+	user = msim_get_user_from_buddy(buddy);
+
+	return user;
+}
+
+
 /** Record the client version in the buddy list, from an incoming message. */
 static gboolean
 msim_incoming_bm_record_cv(MsimSession *session, MsimMessage *msg)
 {
 	gchar *username, *cv;
 	gboolean ret;
-	PurpleBuddy *buddy;
+	MsimUser *user;
 
 	username = msim_msg_get_string(msg, "_username");
 	cv = msim_msg_get_string(msg, "cv");
@@ -1426,10 +1473,10 @@
 		return FALSE;
 	}
 
-	buddy = purple_find_buddy(session->account, username);
-
-	if (buddy) {
-		purple_blist_node_set_int(&buddy->node, "client_cv", atol(cv));
+	user = msim_find_user(session, username);
+
+	if (user) {
+		user->client_cv = atol(cv);
 		ret = TRUE;
 	} else {
 		ret = FALSE;
@@ -1657,7 +1704,7 @@
 static gboolean
 msim_incoming_unofficial_client(MsimSession *session, MsimMessage *msg)
 {
-	PurpleBuddy *buddy;
+	MsimUser *user;
 	gchar *username, *client_info;
 
 	username = msim_msg_get_string(msg, "_username");
@@ -1669,15 +1716,17 @@
 	purple_debug_info("msim", "msim_incoming_unofficial_client: %s is using client %s\n",
 		username, client_info);
 
-	buddy = purple_find_buddy(session->account, username);
+	user = msim_find_user(session, username);
 	
-	g_return_val_if_fail(buddy != NULL, FALSE);
-
-	purple_blist_node_remove_setting(&buddy->node, "client");
-	purple_blist_node_set_string(&buddy->node, "client", client_info);
+	g_return_val_if_fail(user != NULL, FALSE);
+
+	if (user->client_info) {
+		g_free(user->client_info);
+	}
+	user->client_info = client_info;
 
 	g_free(username);
-	/* Do not free client_info - the blist now owns it. */
+	/* Do not free client_info - the MsimUser now owns it. */
 
 	return TRUE;
 }
@@ -1743,6 +1792,21 @@
 	return 0;
 }
 
+/** Format the "now playing" indicator, showing the artist and song.
+ * @return Return a new string (must be g_free()'d), or NULL.
+ */
+static gchar *
+msim_format_now_playing(gchar *band, gchar *song)
+{
+	if ((band && strlen(band)) || (song && strlen(song))) {
+		return g_strdup_printf("%s - %s",
+			(band && strlen(band)) ? band : "Unknown Artist",
+			(song && strlen(song)) ? song : "Unknown Song");
+	} else {
+		return NULL;
+	}
+}
+
 /** Callback for msim_get_info(), for when user info is received. */
 static void 
 msim_get_info_cb(MsimSession *session, MsimMessage *user_info_msg, 
@@ -1751,10 +1815,10 @@
 	GHashTable *body;
 	gchar *body_str;
 	MsimMessage *msg;
-	gchar *user;
+	gchar *username;
 	PurpleNotifyUserInfo *user_info;
-	PurpleBuddy *buddy;
-	const gchar *str, *str2;
+	MsimUser *user;
+	const gchar *str;
 
 	g_return_if_fail(MSIM_SESSION_VALID(session));
 
@@ -1763,30 +1827,30 @@
 	msg = (MsimMessage *)data;
 	g_return_if_fail(msg != NULL);
 
-	user = msim_msg_get_string(msg, "user");
-	if (!user) {
+	username = msim_msg_get_string(msg, "user");
+	if (!username) {
 		purple_debug_info("msim", "msim_get_info_cb: no 'user' in msg");
 		return;
 	}
 
 	msim_msg_free(msg);
-	purple_debug_info("msim", "msim_get_info_cb: got for user: %s\n", user);
+	purple_debug_info("msim", "msim_get_info_cb: got for user: %s\n", username);
 
 	body_str = msim_msg_get_string(user_info_msg, "body");
 	g_return_if_fail(body_str != NULL);
 	body = msim_parse_body(body_str);
 	g_free(body_str);
 
-	buddy = purple_find_buddy(session->account, user);
-	/* Note: don't assume buddy is non-NULL; will be if lookup random user 
-	 * not on blist. */
+	user = msim_find_user(session, username);
+	/* Note: user will be NULL if not on buddy list. */
 
 	user_info = purple_notify_user_info_new();
 
 	/* Identification */
-	purple_notify_user_info_add_pair(user_info, _("User"), user);
-
-	/* note: g_hash_table_lookup does not create a new string! */
+	purple_notify_user_info_add_pair(user_info, _("User"), username);
+
+	/* XXX TODO XXX TODO Avoid duplicating this and tooltip text, and
+	 * maybe integrate msim_store_buddy_info() here? */
 	str = g_hash_table_lookup(body, "UserID");
 	if (str)
 		purple_notify_user_info_add_pair(user_info, _("User ID"), 
@@ -1794,35 +1858,31 @@
 
 	/* a/s/l...the vitals */
 	str = g_hash_table_lookup(body, "Age");
-	if (str)
+	if (str && strcmp(str, "0"))
 		purple_notify_user_info_add_pair(user_info, _("Age"), g_strdup(str));
 
 	str = g_hash_table_lookup(body, "Gender");
-	if (str)
+	if (str && strlen(str) != 0)
 		purple_notify_user_info_add_pair(user_info, _("Gender"), g_strdup(str));
 
 	str = g_hash_table_lookup(body, "Location");
-	if (str)
+	if (str && strlen(str) != 0)
 		purple_notify_user_info_add_pair(user_info, _("Location"), 
 				g_strdup(str));
 
 	/* Other information */
 
-	if (buddy) {
+	if (user) {
 		/* Headline comes from buddy status messages */
-		str = purple_blist_node_get_string(&buddy->node, "Headline");
-		if (str)
-			purple_notify_user_info_add_pair(user_info, "Headline", str);
+		if (user->headline)
+			purple_notify_user_info_add_pair(user_info, "Headline", user->headline);
 	}
 
 
-	str = g_hash_table_lookup(body, "BandName");
-	str2 = g_hash_table_lookup(body, "SongName");
-	if (str || str2) {
-		purple_notify_user_info_add_pair(user_info, _("Song"), 
-			g_strdup_printf("%s - %s",
-				str ? str : "Unknown Artist",
-				str2 ? str2 : "Unknown Song"));
+	str = msim_format_now_playing(g_hash_table_lookup(body, "BandName"), g_hash_table_lookup(body, "SongName"));
+
+	if (str) {
+		purple_notify_user_info_add_pair(user_info, _("Song"), str);
 	}
 
 
@@ -1832,74 +1892,72 @@
 		purple_notify_user_info_add_pair(user_info, _("Total Friends"), 
 			g_strdup(str));
 	}
-
-	if (buddy) {
+	g_hash_table_destroy(body);
+
+	if (user) {
 		gint cv;
 
-		str = purple_blist_node_get_string(&buddy->node, "client");
-		cv = purple_blist_node_get_int(&buddy->node, "client_cv");
-
-		if (str) {
+		str = user->client_info;
+		cv = user->client_cv;
+
+		if (str && cv != 0) {
 			purple_notify_user_info_add_pair(user_info, _("Client Version"),
 					g_strdup_printf("%s (build %d)", str, cv));
+		} else if (str) {
+			purple_notify_user_info_add_pair(user_info, _("Client Version"),
+					g_strdup(str));
+		} else if (cv) {
+			purple_notify_user_info_add_pair(user_info, _("Client Version"),
+					g_strdup_printf("Build %d", cv));
 		}
 	}
 
-	purple_notify_userinfo(session->gc, user, user_info, NULL, NULL);
-	purple_debug_info("msim", "msim_get_info_cb: username=%s\n", user);
-	//purple_notify_user_info_destroy(user_info);
+	purple_notify_userinfo(session->gc, username, user_info, NULL, NULL);
+	purple_debug_info("msim", "msim_get_info_cb: username=%s\n", username);
+
+	/* purple_notify_user_info_destroy(user_info); */
 	/* Do not free username, since it will be used by user_info. */
 
-	g_hash_table_destroy(body);
 }
 
-/** Retrieve a user's profile. */
+/** Retrieve a user's profile. 
+ * @param username Username, user ID, or email address to lookup.
+ */
 void 
-msim_get_info(PurpleConnection *gc, const gchar *user)
+msim_get_info(PurpleConnection *gc, const gchar *username)
 {
-	PurpleBuddy *buddy;
 	MsimSession *session;
+	MsimUser *user;
 	guint uid;
 	gchar *user_to_lookup;
 	MsimMessage *user_msg;
 
 	g_return_if_fail(gc != NULL);
-	g_return_if_fail(user != NULL);
+	g_return_if_fail(username != NULL);
 
 	session = (MsimSession *)gc->proto_data;
 
 	g_return_if_fail(MSIM_SESSION_VALID(session));
 
 	/* Obtain uid of buddy. */
-	buddy = purple_find_buddy(session->account, user);
-	if (buddy) {
-		uid = purple_blist_node_get_int(&buddy->node, "UserID");
-		if (!uid) {
-			PurpleNotifyUserInfo *user_info;
-
-			user_info = purple_notify_user_info_new();
-			purple_notify_user_info_add_pair(user_info, NULL,
-					_("This buddy appears to not have a userid stored in the buddy list, can't look up. Is the user really on the buddy list?"));
-
-			purple_notify_userinfo(session->gc, user, user_info, NULL, NULL);
-			purple_notify_user_info_destroy(user_info);
-			return;
-		}
-
+	user = msim_find_user(session, username);
+
+	/* If is on buddy list, lookup by uid since it is faster. */
+	if (user && (uid = purple_blist_node_get_int(&user->buddy->node, "UserID"))) {
 		user_to_lookup = g_strdup_printf("%d", uid);
 	} else {
 		/* Looking up buddy not on blist. Lookup by whatever user entered. */
-		user_to_lookup = g_strdup(user);
+		user_to_lookup = g_strdup(username);
 	}
 
 	/* Pass the username to msim_get_info_cb(), because since we lookup
 	 * by userid, the userinfo message will only contain the uid (not 
-	 * the username).
+	 * the username) but it would be useful to display the username too.
 	 */
 	user_msg = msim_msg_new(
-			"user", MSIM_TYPE_STRING, g_strdup(user),
+			"user", MSIM_TYPE_STRING, g_strdup(username),
 			NULL);
-	purple_debug_info("msim", "msim_get_info, setting up lookup, user=%s\n", user);
+	purple_debug_info("msim", "msim_get_info, setting up lookup, user=%s\n", username);
 
 	msim_lookup_user(session, user_to_lookup, msim_get_info_cb, user_msg);
 
@@ -2456,24 +2514,46 @@
 
 /** Store an field of information about a buddy. */
 static void 
-msim_store_buddy_info_each(gpointer key, gpointer value, gpointer user_data)
+msim_store_user_info_each(gpointer key, gpointer value, gpointer user_data)
 {
-	PurpleBuddy *buddy;
+	MsimUser *user;
 	gchar *key_str, *value_str;
 
-	buddy = (PurpleBuddy *)user_data;
+	user = (MsimUser *)user_data;
 	key_str = (gchar *)key;
 	value_str = (gchar *)value;
 
-	if (strcmp(key_str, "UserID") == 0 ||
-			strcmp(key_str, "Age") == 0 ||
-			strcmp(key_str, "TotalFriends") == 0) {
-		/* Certain fields get set as integers, instead of strings, for
-		 * convenience. May not be the best way to do it, but having at least
-		 * UserID as an integer is convenient...until it overflows! */
-		purple_blist_node_set_int(&buddy->node, key_str, atol(value_str));
+	if (!strcmp(key_str, "UserID")) {
+		purple_blist_node_set_int(&user->buddy->node, "UserID", atol(value_str));
+	} else if (!strcmp(key_str, "Age")) {
+		user->age = atol(value_str);
+	} else if (!strcmp(key_str, "Gender")) {
+		user->gender = g_strdup(value_str);
+	} else if (!strcmp(key_str, "Location")) {
+		user->location = g_strdup(value_str);
+	} else if (!strcmp(key_str, "TotalFriends")) {
+		user->total_friends = atol(value_str);
+	} else if (!strcmp(key_str, "DisplayName")) {
+		user->display_name = g_strdup(value_str);
+	} else if (!strcmp(key_str, "BandName")) {
+		user->band_name = g_strdup(value_str);
+	} else if (!strcmp(key_str, "SongName")) {
+		user->song_name = g_strdup(value_str);
+	} else if (!strcmp(key_str, "UserName")) {
+		/* Ignore because PurpleBuddy knows this already */
+		;
+	} else if (!strcmp(key_str, "ImageURL")) {
+		user->image_url = g_strdup(value_str);
 	} else {
-		purple_blist_node_set_string(&buddy->node, key_str, value_str);
+		/* TODO: other fields in MsimUser */
+		gchar *msg;
+
+		msg = g_strdup_printf("msim_store_user_info_each: unknown field %s=%s",
+				key_str, value_str);
+
+		msim_unrecognized(NULL, NULL, msg);
+
+		g_free(msg);
 	}
 }
 
@@ -2486,14 +2566,14 @@
  * blist.xml. If the function has no buddy information, this function
  * is a no-op (and returns FALSE).
  *
- * TODO: Store ephemeral information in MsimBuddy instead.
+ * TODO: Store ephemeral information in MsimUser instead.
  */
 static gboolean 
-msim_store_buddy_info(MsimSession *session, MsimMessage *msg)
+msim_store_user_info(MsimSession *session, MsimMessage *msg)
 {
 	GHashTable *body;
 	gchar *username, *body_str, *uid;
-	PurpleBuddy *buddy;
+	MsimUser *user;
 
 	g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE);
 	g_return_val_if_fail(msg != NULL, FALSE);
@@ -2525,9 +2605,9 @@
 
 	purple_debug_info("msim", "associating uid %s with username %s\n", uid, username);
 
-	buddy = purple_find_buddy(session->account, username);
-	if (buddy) {
-		g_hash_table_foreach(body, msim_store_buddy_info_each, buddy);
+	user = msim_find_user(session, username);
+	if (user) {
+		g_hash_table_foreach(body, msim_store_user_info_each, user);
 	}
 
 	if (msim_msg_get_integer(msg, "dsn") == MG_OWN_IM_INFO_DSN &&
@@ -2617,7 +2697,7 @@
 	g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE);
 	g_return_val_if_fail(msg != NULL, FALSE);
 
-	msim_store_buddy_info(session, msg);
+	msim_store_user_info(session, msg);
 
 	rid = msim_msg_get_integer(msg, "rid");
 	cmd = msim_msg_get_integer(msg, "cmd");
@@ -2704,7 +2784,7 @@
 msim_incoming_status(MsimSession *session, MsimMessage *msg)
 {
 	PurpleBuddyList *blist;
-	PurpleBuddy *buddy;
+	MsimUser *user;
 	GList *list;
 	gchar *status_headline;
 	gint status_code, purple_status_code;
@@ -2742,23 +2822,26 @@
 	blist = purple_get_blist();
 
 	/* Add buddy if not found */
-	buddy = purple_find_buddy(session->account, username);
-	if (!buddy) {
+	user = msim_find_user(session, username);
+	if (!user) {
+		PurpleBuddy *buddy;
+
 		purple_debug_info("msim", 
 				"msim_status: making new buddy for %s\n", username);
 		buddy = purple_buddy_new(session->account, username, NULL);
-
 		purple_blist_add_buddy(buddy, NULL, NULL, NULL);
 
+		user = msim_get_user_from_buddy(buddy);
+
 		/* All buddies on list should have 'uid' integer associated with them. */
 		purple_blist_node_set_int(&buddy->node, "UserID", msim_msg_get_integer(msg, "f"));
 		
-		msim_store_buddy_info(session, msg);
+		msim_store_user_info(session, msg);
 	} else {
 		purple_debug_info("msim", "msim_status: found buddy %s\n", username);
 	}
 
-	purple_blist_node_set_string(&buddy->node, "Headline", status_headline);
+	user->headline = g_strdup(status_headline);
   
 	/* Set user status */
 	switch (status_code) {
@@ -3549,10 +3632,13 @@
 msim_status_text(PurpleBuddy *buddy)
 {
 	MsimSession *session;
+	MsimUser *user;
 	const gchar *display_name, *headline;
 
 	g_return_val_if_fail(buddy != NULL, NULL);
 
+	user = msim_get_user_from_buddy(buddy);
+
 	session = (MsimSession *)buddy->account->gc->proto_data;
 	g_return_val_if_fail(MSIM_SESSION_VALID(session), NULL);
 
@@ -3560,24 +3646,20 @@
 
 	/* Retrieve display name and/or headline, depending on user preference. */
 	if (purple_account_get_bool(session->account, "show_display_name", TRUE)) {
-		display_name = purple_blist_node_get_string(&buddy->node, "DisplayName");
+		display_name = user->display_name;
 	} 
 
 	if (purple_account_get_bool(session->account, "show_headline", FALSE)) {
-		headline = purple_blist_node_get_string(&buddy->node, "Headline");
+		headline = user->headline;
 	}
 
 	/* Return appropriate combination of display name and/or headline, or neither. */
 
 	if (display_name && headline) {
 		return g_strconcat(display_name, " ", headline, NULL);
-	}
-
-	if (display_name) {
+	} else if (display_name) {
 		return g_strdup(display_name);
-	}
-
-	if (headline) {
+	} else if (headline) {
 		return g_strdup(headline);
 	}
 
@@ -3596,12 +3678,14 @@
 msim_tooltip_text(PurpleBuddy *buddy, PurpleNotifyUserInfo *user_info, 
 		gboolean full)
 {
-	const gchar *str, *str2;
-	gint n;
+	const gchar *str;
+	MsimUser *user;
 
 	g_return_if_fail(buddy != NULL);
 	g_return_if_fail(user_info != NULL);
 
+	user = msim_get_user_from_buddy(buddy);
+
 	if (PURPLE_BUDDY_IS_ONLINE(buddy)) {
 		MsimSession *session;
 
@@ -3609,51 +3693,41 @@
 
 		g_return_if_fail(MSIM_SESSION_VALID(session));
 
-		/* TODO: if (full), do something different */
+		/* TODO: if (full), do something different? */
 		
 		/* Useful to identify the account the tooltip refers to. 
 		 *  Other prpls show this. */
-		str = purple_blist_node_get_string(&buddy->node, "UserName"); 
-		if (str) {
-			purple_notify_user_info_add_pair(user_info, _("User Name"), str);
+		if (user->username) {
+			purple_notify_user_info_add_pair(user_info, _("User Name"), user->username);
 		}
 
 		/* a/s/l...the vitals */
-		n = purple_blist_node_get_int(&buddy->node, "Age");
-		if (n) {
+		if (user->age) {
 			purple_notify_user_info_add_pair(user_info, _("Age"),
-					g_strdup_printf("%d", n));
+					g_strdup_printf("%d", user->age));
 		}
 
-		str = purple_blist_node_get_string(&buddy->node, "Gender");
-		if (str) {
-			purple_notify_user_info_add_pair(user_info, _("Gender"), str);
+		if (user->gender) {
+			purple_notify_user_info_add_pair(user_info, _("Gender"), user->gender);
 		}
 
-		str = purple_blist_node_get_string(&buddy->node, "Location");
-		if (str) {
-			purple_notify_user_info_add_pair(user_info, _("Location"), str);
+		if (user->location) {
+			purple_notify_user_info_add_pair(user_info, _("Location"), user->location);
 		}
 
 		/* Other information */
-		str = purple_blist_node_get_string(&buddy->node, "Headline");
-		if (str) {
-			purple_notify_user_info_add_pair(user_info, _("Headline"), str);
+		if (user->headline) {
+			purple_notify_user_info_add_pair(user_info, _("Headline"), user->headline);
 		}
 
-		str = purple_blist_node_get_string(&buddy->node, "BandName");
-		str2 = purple_blist_node_get_string(&buddy->node, "SongName");
-		if (str || str2) {
-			purple_notify_user_info_add_pair(user_info, _("Song"), 
-				g_strdup_printf("%s - %s",
-					str ? str : _("Unknown Artist"),
-					str2 ? str2 : _("Unknown Song")));
+		str = msim_format_now_playing(user->band_name, user->song_name);
+		if (str) {
+			purple_notify_user_info_add_pair(user_info, _("Song"), str);
 		}
 
-		n = purple_blist_node_get_int(&buddy->node, "TotalFriends");
-		if (n) {
+		if (user->total_friends) {
 			purple_notify_user_info_add_pair(user_info, _("Total Friends"),
-				g_strdup_printf("%d", n));
+				g_strdup_printf("%d", user->total_friends));
 		}
 
 	}

mercurial