changeset 22308:3867cef6a0d5

merge of '679333d47d0d179f9027ef1c5f82a2eef5811b95' and '782f53e182e5aae0645ddca95945dd0c104330ff'
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Sun, 17 Feb 2008 17:15:40 +0000
parents d270b6aebabc (current diff) bf4902fce6e4 (diff)
children 07073da46dd5
files
diffstat 6 files changed, 349 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/myspace/myspace.c	Sun Feb 17 17:14:29 2008 +0000
+++ b/libpurple/protocols/myspace/myspace.c	Sun Feb 17 17:15:40 2008 +0000
@@ -73,7 +73,7 @@
 static gboolean msim_check_alive(gpointer data);
 #endif
 
-static gboolean msim_we_are_logged_on(MsimSession *session, MsimMessage *msg);
+static gboolean msim_is_username_set(MsimSession *session, MsimMessage *msg);
 
 static gboolean msim_process(MsimSession *session, MsimMessage *msg);
 
@@ -1546,14 +1546,14 @@
 }
 #endif
 
-/** Called when the session key arrives. */
+/** Called when the session key arrives to check whether the user
+ * has a username, and set one if desired. */
 static gboolean
-msim_we_are_logged_on(MsimSession *session, MsimMessage *msg)
+msim_is_username_set(MsimSession *session, MsimMessage *msg) 
 {
-	MsimMessage *body;
-
 	g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE);
 	g_return_val_if_fail(msg != NULL, FALSE);
+	g_return_val_if_fail(session->gc != NULL, FALSE);
 
 	session->sesskey = msim_msg_get_integer(msg, "sesskey");
 	purple_debug_info("msim", "SESSKEY=<%d>\n", session->sesskey);
@@ -1581,27 +1581,39 @@
 	/* Set display name to username (otherwise will show email address) */
 	purple_connection_set_display_name(session->gc, session->username);
 
+	/* If user lacks a username, help them get one. */
+	if (msim_msg_get_integer(msg, "uniquenick") == session->userid) {
+		purple_debug_info("msim_is_username_set", "no username is set\n");
+		purple_request_yes_no(session->gc,
+			_("MySpaceIM - No Username Set"),
+			_("You appear to have no MySpace username."),
+			_("Would you like to set one now? (Note: THIS CANNOT BE CHANGED!)"),
+			0,
+			session->account,
+			NULL,
+			NULL,
+			session->gc, 
+			G_CALLBACK(msim_set_username_cb), 
+			G_CALLBACK(msim_do_not_set_username_cb));
+		purple_debug_info("msim_is_username_set","'username not set' alert prompted\n");
+		return FALSE;
+	}
+	return TRUE;
+}
+
+/** Called after username is set, if necessary and we're open for business. */
+gboolean msim_we_are_logged_on(MsimSession *session) 
+{
+	MsimMessage *body;
+
+	g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE);
+
 	/* The session is now set up, ready to be connected. This emits the
 	 * signedOn signal, so clients can now do anything with msimprpl, and
 	 * we're ready for it (session key, userid, username all setup). */
 	purple_connection_update_progress(session->gc, _("Connected"), 3, 4);
 	purple_connection_set_state(session->gc, PURPLE_CONNECTED);
 
-
-	/* Additional post-connect operations */
-
-
-	if (msim_msg_get_integer(msg, "uniquenick") == session->userid) {
-		purple_debug_info("msim_we_are_logged_on", "TODO: pick username\n");
-		/* No username is set. */
-		purple_notify_error(session->account, 
-				_("No username set"),
-				_("Please go to http://editprofile.myspace.com/index.cfm?fuseaction=profile.username and choose a username and try to login again."), NULL);
-		purple_connection_error_reason (session->gc,
-			PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("No username set"));
-		return FALSE;
-	}
-
 	body = msim_msg_new(
 			"UserID", MSIM_TYPE_INTEGER, session->userid,
 			NULL);
@@ -1687,7 +1699,14 @@
 	if (msim_msg_get_integer(msg, "lc") == 1) {
 		return msim_login_challenge(session, msg);
 	} else if (msim_msg_get_integer(msg, "lc") == 2) {
-		return msim_we_are_logged_on(session, msg);
+		/* return msim_we_are_logged_on(session, msg); */
+		if (msim_is_username_set(session, msg)) {
+			return msim_we_are_logged_on(session);
+		} else {
+			/* No username is set... We'll wait for the callbacks to do their work */
+			/* When they're all done, the last one will call msim_we_are_logged_on() and pick up where we left off */
+			return FALSE;
+		}
 	} else if (msim_msg_get(msg, "bm"))  {
 		return msim_incoming_bm(session, msg);
 	} else if (msim_msg_get(msg, "rid")) {
--- a/libpurple/protocols/myspace/myspace.h	Sun Feb 17 17:14:29 2008 +0000
+++ b/libpurple/protocols/myspace/myspace.h	Sun Feb 17 17:15:40 2008 +0000
@@ -45,6 +45,7 @@
 #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 */
 #include "xmlnode.h"
 #include "core.h"
 
@@ -88,6 +89,9 @@
  * warn user that it may be too long. */
 #define MSIM_MAX_PASSWORD_LENGTH    10
 
+/* Maximum length of usernames, when setting. */
+#define MSIM_MAX_USERNAME_LENGTH    25
+
 /* Build version of MySpaceIM to report to servers (1.0.xxx.0) */
 #define MSIM_CLIENT_VERSION         697
 
@@ -108,6 +112,7 @@
 
 /* Time between keepalives (seconds) - if no data within this time, is dead. */
 #define MSIM_KEEPALIVE_INTERVAL     (3 * 60)
+/*#define MSIM_USE_KEEPALIVE*/
 
 /* Time to check if alive (milliseconds) */
 #define MSIM_KEEPALIVE_INTERVAL_CHECK   (30 * 1000)
@@ -221,6 +226,8 @@
 
 gboolean msim_send_bm(MsimSession *session, const gchar *who, const gchar *text, int type);
 
+gboolean msim_we_are_logged_on(MsimSession *session);
+
 
 void msim_unrecognized(MsimSession *session, MsimMessage *msg, gchar *note);
 guint msim_new_reply_callback(MsimSession *session, MSIM_USER_LOOKUP_CB cb, gpointer data);
--- a/libpurple/protocols/myspace/persist.h	Sun Feb 17 17:14:29 2008 +0000
+++ b/libpurple/protocols/myspace/persist.h	Sun Feb 17 17:15:40 2008 +0000
@@ -73,7 +73,8 @@
 /** Messages to Change/send information */
 MSIM_PERSIST_DSN_LID(MC_USER_PREFERENCES,          1, 10)
 MSIM_PERSIST_DSN_LID(MC_CONTACT_INFO,              0, 9)
-MSIM_PERSIST_DSN_LID(MC_IMPORT_ALL_FRIENDS,        14, 21)
+MSIM_PERSIST_DSN_LID(MC_SET_USERNAME,              9, 14)
+MSIM_PERSIST_DSN_LID(MC_IMPORT_ALL_FRIENDS,       14, 21)
 MSIM_PERSIST_DSN_LID(MC_INVITE,                   16, 25)
 
 /** Messages to Delete information */
--- a/libpurple/protocols/myspace/user.c	Sun Feb 17 17:14:29 2008 +0000
+++ b/libpurple/protocols/myspace/user.c	Sun Feb 17 17:15:40 2008 +0000
@@ -24,6 +24,15 @@
 static void msim_downloaded_buddy_icon(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text,
 		gsize len, const gchar *error_message);
 
+/* Callbacks for setting the username bit */
+static void msim_check_username_availability_cb(PurpleConnection *gc, const char *value);
+static void msim_username_is_available_cb(MsimSession *session, MsimMessage *userinfo, gpointer data);
+static void msim_set_username_confirmed_cb(PurpleConnection *gc);
+static void msim_username_is_set_cb(MsimSession *session, MsimMessage *userinfo, gpointer data);
+static void msim_set_username(MsimSession *session, const gchar *username,
+		MSIM_USER_LOOKUP_CB cb, gpointer data);
+static char *msim_username_to_set;
+
 /** Format the "now playing" indicator, showing the artist and song.
  * @return Return a new string (must be g_free()'d), or NULL.
  */
@@ -487,6 +496,19 @@
 	return strspn(user, "0123456789") == strlen(user);
 }
 
+/** Return whether a given username is syntactically valid. 
+ * Note: does not actually check that the user exists. */
+gboolean
+msim_is_valid_username(const gchar *user)
+{
+	return !msim_is_userid(user) &&  /* Not all numeric */
+		strlen(user) <= MSIM_MAX_USERNAME_LENGTH
+		&& strspn(user, "0123456789"
+			"abcdefghijklmnopqrstuvwxyz"
+			"_"
+			"ABCDEFGHIJKLMNOPQRSTUVWXYZ") == strlen(user);
+}
+
 /**
  * Check if a string is an email address (contains an @).
  *
@@ -537,4 +559,279 @@
 			user->image_url);		/* checksum */
 }
 
+/*** 
+ * If they hit cancel or no at any point in the Setting Username process, we come here.              *
+ * Currently.. We're safe letting them get by without setting it.. Unless we hear otherwise..        *
+ * So for now, give them a menu.. If this becomes an issue with the Official client.. boot them here */
+void msim_do_not_set_username_cb(PurpleConnection *gc) {
+	purple_debug_info("msim", "Dont set username");
 
+	/* Protocol won't log in now without a username set.. Disconnect */
+	purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("No username set"));
+}
+ 
+/** They've decided to set a username! Yay! */
+void msim_set_username_cb(PurpleConnection *gc) {
+	g_return_if_fail(gc != NULL);
+	purple_debug_info("msim","Set username\n");
+	purple_request_input(gc, _("MySpaceIM - Please Set a Username"),
+			_("Please enter a username to check its availability:"),
+			NULL,
+			"", FALSE, FALSE, NULL,
+			_("OK"), G_CALLBACK(msim_check_username_availability_cb),
+			_("Cancel"), G_CALLBACK(msim_do_not_set_username_cb),
+			purple_connection_get_account(gc),
+			NULL,
+			NULL,
+			gc);
+}
+
+/** Once they've submitted their desired new username, 
+ * check if it is available here. */
+static void msim_check_username_availability_cb(PurpleConnection *gc, const char *username_to_check) 
+{
+	MsimMessage *user_msg;
+	MsimSession *session;
+
+	g_return_if_fail(gc != NULL);
+
+	session = (MsimSession *)gc->proto_data;
+
+	g_return_if_fail(MSIM_SESSION_VALID(session));
+
+	purple_debug_info("msim_check_username_availability_cb", "Checking username: %s\n", username_to_check);
+	
+	user_msg = msim_msg_new(
+			"user", MSIM_TYPE_STRING, g_strdup(username_to_check),
+			NULL);
+
+	/* 25 characters: letters, numbers, underscores */
+	/* TODO: VERIFY ABOVE */
+
+	/* \persist\1\sesskey\288500516\cmd\1\dsn\5\uid\204084363\lid\7\rid\367\body\UserName=Jaywalker\final\ */
+	/* Official client uses a standard lookup... So do we! */
+	msim_lookup_user(session, username_to_check, msim_username_is_available_cb, user_msg);
+}
+
+/** This is where we do a bit more than merely prompt the user. 
+ * Now we have some real data to tell us the state of their requested username 
+ * \persistr\\cmd\257\dsn\5\uid\204084363\lid\7\rid\367\body\UserName=TheAlbinoRhino1\final\ */
+static void msim_username_is_available_cb(MsimSession *session, MsimMessage *userinfo, gpointer data) 
+{
+	MsimMessage *msg;
+	gchar *username;
+	MsimMessage *body;
+	gint userid;
+
+	purple_debug_info("msim_username_is_available_cb", "Look up username callback made\n");
+	
+	msg = (MsimMessage *)data;
+	g_return_if_fail(MSIM_SESSION_VALID(session));
+	g_return_if_fail(msg != NULL);
+	
+	username = msim_msg_get_string(msg, "user");
+	body = msim_msg_get_dictionary(userinfo, "body");
+
+	if (!body) {
+		purple_debug_info("msim_username_is_available_cb", "No body for %s?!\n", username);
+		purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, 
+				"An error occured while trying to set the username.\n"
+				"Please try again, or visit http://editprofile.myspace.com/index.cfm?"
+				"fuseaction=profile.username to set your username.");
+		return;
+	}
+
+	userid = msim_msg_get_integer(body, "UserID");
+
+	purple_debug_info("msim_username_is_available_cb", "Returned username is %s and userid is %d\n", username, userid);
+	msim_msg_free(body);
+	msim_msg_free(msg);
+
+	/* The response for a free username will ONLY have the UserName in it.. 
+	 * thus making UserID return 0 when we msg_get_integer it */
+	if (userid == 0) {
+		/* This username is currently unused */
+		purple_debug_info("msim_username_is_available_cb", "Username available. Prompting to Confirm.\n");
+		msim_username_to_set = g_strdup(username);
+		g_free(username);
+		purple_request_yes_no(session->gc,
+			_("MySpaceIM - Username Available"),
+			_("This username is available. Would you like to set it?"),
+			_("ONCE SET, THIS CANNOT BE CHANGED!"),
+			0,
+			session->account,
+			NULL,
+			NULL,
+			session->gc, 
+			G_CALLBACK(msim_set_username_confirmed_cb), 
+			G_CALLBACK(msim_do_not_set_username_cb));
+	} else {
+		/* Looks like its in use or we have an invalid response */
+		purple_debug_info("msim_username_is_available_cb", "Username unavaiable. Prompting for new entry.\n");
+		purple_request_input(session->gc, _("MySpaceIM - Please Set a Username"),
+			_("This username is unavailable."),
+				_("Please try another username:"),
+				"", FALSE, FALSE, NULL,
+				_("OK"), G_CALLBACK(msim_check_username_availability_cb),
+				_("Cancel"), G_CALLBACK(msim_do_not_set_username_cb),
+				session->account,
+				NULL,
+				NULL,
+				session->gc);
+	}
+}
+
+/* They've confirmed that username that was available, Lets make the call to set it */
+static void msim_set_username_confirmed_cb(PurpleConnection *gc) 
+{
+	MsimMessage *user_msg;
+	MsimSession *session;
+
+	g_return_if_fail(gc != NULL);
+
+	session = (MsimSession *)gc->proto_data;
+
+	g_return_if_fail(MSIM_SESSION_VALID(session));
+
+
+	user_msg = msim_msg_new(
+			"user", MSIM_TYPE_STRING, g_strdup(msim_username_to_set),
+			NULL);
+
+	purple_debug_info("msim_set_username_confirmed_cb", "Setting username to %s\n", msim_username_to_set);
+	
+	/* Sets our username... keep your fingers crossed :) */
+	msim_set_username(session, msim_username_to_set, msim_username_is_set_cb, user_msg);
+	g_free(msim_username_to_set);
+}
+
+/**
+ * Asynchronously set new username, calling callback when receive result.
+ *
+ * @param session
+ * @param username The username we're setting for ourselves. Not freed.
+ * @param cb Callback, called with user information when available.
+ * @param data An arbitray data pointer passed to the callback.
+ */
+static void 
+msim_set_username(MsimSession *session, const gchar *username,
+		MSIM_USER_LOOKUP_CB cb, gpointer data)
+{
+	MsimMessage *body;
+	guint rid;
+
+	g_return_if_fail(MSIM_SESSION_VALID(session));
+	g_return_if_fail(username != NULL);
+	g_return_if_fail(cb != NULL);
+
+	purple_debug_info("msim", "msim_set_username: "
+			"Setting username %s\n", username);
+
+	msim_msg_dump("msim_set_username: data=%s\n", (MsimMessage *)data);
+
+	/* Setup callback. Response will be associated with request using 'rid'. */
+	rid = msim_new_reply_callback(session, cb, data);
+
+	/* TODO: I dont know if the ContactType is -/ALWAYS/- 1 */
+
+	body = msim_msg_new("UserName", MSIM_TYPE_STRING, g_strdup(username),NULL);
+/* \setinfo\\sesskey\469958979\info\Age=21.AvatarUrl=.BandName=.ContactType=1.DisplayName=Msim.Gender=M.ImageURL=http:/1/1x.myspace.com/1images/1no_pic.gif.LastLogin=128335268400000000.Location=US.ShowAvatar=False.SongName=.TotalFriends=1.UserName=msimprpl2\final\
+*/
+
+	/* Send request */
+	g_return_if_fail(msim_send(session,
+			 "setinfo", MSIM_TYPE_BOOLEAN, TRUE,
+			 "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
+			 "info", MSIM_TYPE_DICTIONARY, body,
+			 NULL));
+	body = msim_msg_new("UserName", MSIM_TYPE_STRING, g_strdup(username),NULL);
+	g_return_if_fail(msim_send(session,
+			 "persist", MSIM_TYPE_INTEGER, 1,
+			 "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
+			 "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_GET,
+			 "dsn", MSIM_TYPE_INTEGER, MG_MYSPACE_INFO_BY_STRING_DSN,
+			 "uid", MSIM_TYPE_INTEGER, session->userid,
+			 "lid", MSIM_TYPE_INTEGER, MG_MYSPACE_INFO_BY_STRING_LID,
+			 "rid", MSIM_TYPE_INTEGER, rid,
+			 "body", MSIM_TYPE_DICTIONARY, body,
+			 NULL));
+}
+
+/** Called after username is set. */
+static void msim_username_is_set_cb(MsimSession *session, MsimMessage *userinfo, gpointer data) 
+{
+	gchar *username, *errmsg;
+	MsimMessage *body;
+
+	guint rid;
+	gint cmd,dsn,uid,lid,code;
+	/* \persistr\\cmd\258\dsn\9\uid\204084363\lid\14\rid\369\body\UserName=TheAlbinoRhino1.Code=0\final\ */
+
+	purple_debug_info("msim","username_is_set made\n");
+	
+	g_return_if_fail(MSIM_SESSION_VALID(session));
+
+
+	msim_msg_dump("username_is_set message is: %s\n", userinfo);
+	cmd = msim_msg_get_integer(userinfo, "cmd");
+	dsn = msim_msg_get_integer(userinfo, "dsn");
+	uid = msim_msg_get_integer(userinfo, "uid");
+	lid = msim_msg_get_integer(userinfo, "lid");
+	body = msim_msg_get_dictionary(userinfo, "body");
+	errmsg = g_strdup("An error occured while trying to set the username.\n"
+			"Please try again, or visit http://editprofile.myspace.com/index.cfm?"
+			"fuseaction=profile.username to set your username.");
+	
+	if (!body) {
+		purple_debug_info("msim_username_is_set_cb", "No body");
+		/* Error: No body! */
+		purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg);
+	}
+	username = msim_msg_get_string(body, "UserName");
+	code = msim_msg_get_integer(body,"Code");
+
+	msim_msg_free(body);
+
+	purple_debug_info("msim_username_is_set_cb", 
+			"cmd = %d, dsn = %d, lid = %d, code = %d, username = %s\n", 
+			cmd, dsn, lid, code, username);
+
+	if (cmd == (MSIM_CMD_BIT_REPLY | MSIM_CMD_PUT) 
+			&& dsn == MC_SET_USERNAME_DSN 
+			&& lid == MC_SET_USERNAME_LID) {
+		purple_debug_info("msim_username_is_set_cb", "Proper cmd,dsn,lid for username_is_set!\n");
+		purple_debug_info("msim_username_is_set_cb", "Username Set with return code %d\n",code);
+		if (code == 0) {
+			/* Good! */
+			msim_we_are_logged_on(session);
+		} else {
+			purple_debug_info("msim_username_is_set", "code is %d",code);
+			/* TODO: what to do here? */
+		}
+	} else if (cmd == (MSIM_CMD_BIT_REPLY | MSIM_CMD_GET) 
+			&& dsn == MG_MYSPACE_INFO_BY_STRING_DSN 
+			&& lid == MG_MYSPACE_INFO_BY_STRING_LID) {
+		/* Not quite done... ONE MORE STEP :) */
+		rid = msim_new_reply_callback(session, msim_username_is_set_cb, data);
+		body = msim_msg_new("UserName", MSIM_TYPE_STRING, g_strdup(username),NULL);
+		if (!msim_send(session, "persist", MSIM_TYPE_INTEGER, 1, 
+					"sesskey", MSIM_TYPE_INTEGER, session->sesskey,
+					"cmd", MSIM_TYPE_INTEGER, MSIM_CMD_PUT, 
+					"dsn", MSIM_TYPE_INTEGER, MC_SET_USERNAME_DSN, 
+					"uid", MSIM_TYPE_INTEGER, session->userid,
+					"lid", MSIM_TYPE_INTEGER, MC_SET_USERNAME_LID, 
+					"rid", MSIM_TYPE_INTEGER, rid, 
+					"body", MSIM_TYPE_DICTIONARY, body, 
+					NULL)) {
+			/* Error! */
+			/* Can't set... Disconnect */
+			purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg);
+		}
+			
+	} else {
+		/* Error! */
+		purple_debug_info("msim","username_is_set Error: Invalid cmd/dsn/lid combination");
+		purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg);
+	}
+	g_free(errmsg);
+}
--- a/libpurple/protocols/myspace/user.h	Sun Feb 17 17:14:29 2008 +0000
+++ b/libpurple/protocols/myspace/user.h	Sun Feb 17 17:15:40 2008 +0000
@@ -51,6 +51,9 @@
 gboolean msim_store_user_info(MsimSession *session, MsimMessage *msg, MsimUser *user);
 gboolean msim_is_userid(const gchar *user);
 gboolean msim_is_email(const gchar *user);
+gboolean msim_is_valid_username(const gchar *user);
 void msim_lookup_user(MsimSession *session, const gchar *user, MSIM_USER_LOOKUP_CB cb, gpointer data);
+void msim_set_username_cb(PurpleConnection *gc);
+void msim_do_not_set_username_cb(PurpleConnection *gc);
 
 #endif /* !_MYSPACE_USER_H */
Binary file pidgin/pixmaps/toolbar/16/get-attention.png has changed