pidgin/pidgin

IRC: fill required command parameter counts (part 3)
release-2.x.y
2014-01-16, Tomasz Wasilczyk
6b0e0566af20
IRC: fill required command parameter counts (part 3)
/* MySpaceIM Protocol Plugin, header file
*
* Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
*
* 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 "myspace.h"
static void msim_check_username_availability_cb(PurpleConnection *gc, const char *username_to_check);
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.
*/
static gchar *
msim_format_now_playing(const gchar *band, const gchar *song)
{
if ((band && *band) || (song && *song)) {
return g_strdup_printf("%s - %s",
(band && *band) ? band : "Unknown Artist",
(song && *song) ? song : "Unknown Song");
} else {
return NULL;
}
}
/**
* Get the MsimUser from a PurpleBuddy, optionally creating it if needed.
*/
MsimUser *
msim_get_user_from_buddy(PurpleBuddy *buddy, gboolean create)
{
MsimUser *user;
if (!buddy) {
return NULL;
}
user = purple_buddy_get_protocol_data(buddy);
if (create && !user) {
PurpleBlistNode *node = PURPLE_BLIST_NODE(buddy);
/* No MsimUser for this buddy; make one. */
user = g_new0(MsimUser, 1);
user->buddy = buddy;
user->id = purple_blist_node_get_int(node, "UserID");
purple_buddy_set_protocol_data(buddy, user);
}
return user;
}
void msim_user_free(MsimUser *user)
{
if (!user)
return;
if (user->url_data != NULL)
purple_util_fetch_url_cancel(user->url_data);
g_free(user->client_info);
g_free(user->gender);
g_free(user->location);
g_free(user->headline);
g_free(user->display_name);
g_free(user->username);
g_free(user->band_name);
g_free(user->song_name);
g_free(user->image_url);
g_free(user);
}
/**
* Find and return an MsimUser * representing a user on the buddy list, or NULL.
*/
MsimUser *
msim_find_user(MsimSession *session, const gchar *username)
{
PurpleBuddy *buddy;
buddy = purple_find_buddy(session->account, username);
if (!buddy) {
return NULL;
}
return msim_get_user_from_buddy(buddy, TRUE);
}
/**
* Append user information to a PurpleNotifyUserInfo, given an MsimUser.
* Used by msim_tooltip_text() and msim_get_info_cb() to show a user's profile.
*/
void
msim_append_user_info(MsimSession *session, PurpleNotifyUserInfo *user_info, MsimUser *user, gboolean full)
{
PurplePresence *presence;
gchar *str;
guint cv;
/* Useful to identify the account the tooltip refers to.
* Other prpls show this. */
if (user->username) {
purple_notify_user_info_add_pair(user_info, _("User"), user->username);
}
/* a/s/l...the vitals */
if (user->age) {
char age[16];
g_snprintf(age, sizeof(age), "%d", user->age);
purple_notify_user_info_add_pair(user_info, _("Age"), age);
}
if (user->gender && *user->gender) {
purple_notify_user_info_add_pair(user_info, _("Gender"), user->gender);
}
if (user->location && *user->location) {
purple_notify_user_info_add_pair(user_info, _("Location"), user->location);
}
/* Other information */
if (user->headline && *user->headline) {
purple_notify_user_info_add_pair(user_info, _("Headline"), user->headline);
}
if (user->buddy != NULL) {
presence = purple_buddy_get_presence(user->buddy);
if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
PurpleStatus *status;
const char *artist, *title;
status = purple_presence_get_status(presence, "tune");
title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE);
artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST);
str = msim_format_now_playing(artist, title);
if (str && *str) {
purple_notify_user_info_add_pair(user_info, _("Song"), str);
}
g_free(str);
}
}
/* Note: total friends only available if looked up by uid, not username. */
if (user->total_friends) {
char friends[16];
g_snprintf(friends, sizeof(friends), "%d", user->total_friends);
purple_notify_user_info_add_pair(user_info, _("Total Friends"), friends);
}
if (full) {
/* Client information */
char *client = NULL;
str = user->client_info;
cv = user->client_cv;
if (str && cv != 0) {
client = g_strdup_printf("%s (build %d)", str, cv);
} else if (str) {
client = g_strdup(str);
} else if (cv) {
client = g_strdup_printf("Build %d", cv);
}
if (client && *client)
purple_notify_user_info_add_pair(user_info, _("Client Version"), client);
g_free(client);
}
if (full && user->id) {
/* TODO: link to username, if available */
char *profile;
purple_notify_user_info_add_section_break(user_info);
if (user->buddy != NULL)
profile = g_strdup_printf("<a href=\"http://myspace.com/%s\">%s</a>",
purple_buddy_get_name(user->buddy), _("View web profile"));
else
profile = g_strdup_printf("<a href=\"http://myspace.com/%d\">%s</a>",
user->id, _("View web profile"));
purple_notify_user_info_add_pair(user_info, NULL, profile);
g_free(profile);
}
}
/**
* Callback for when a buddy icon finished being downloaded.
*/
static void
msim_downloaded_buddy_icon(PurpleUtilFetchUrlData *url_data,
gpointer user_data,
const gchar *url_text,
gsize len,
const gchar *error_message)
{
MsimUser *user = (MsimUser *)user_data;
const char *name = purple_buddy_get_name(user->buddy);
PurpleAccount *account;
user->url_data = NULL;
purple_debug_info("msim_downloaded_buddy_icon",
"Downloaded %" G_GSIZE_FORMAT " bytes\n", len);
if (!url_text) {
purple_debug_info("msim_downloaded_buddy_icon",
"failed to download icon for %s",
name);
return;
}
account = purple_buddy_get_account(user->buddy);
purple_buddy_icons_set_for_user(account, name,
g_memdup((gchar *)url_text, len), len,
/* Use URL itself as buddy icon "checksum" (TODO: ETag) */
user->image_url); /* checksum */
}
/**
* Set the currently playing song artist and or title.
*
* @param user User associated with the now playing information.
*
* @param new_artist New artist to set, or NULL/empty to not change artist.
*
* @param new_title New title to set, or NULL/empty to not change title.
*
* If new_artist and new_title are NULL/empty, deactivate PURPLE_STATUS_TUNE.
*
* This function is useful because it lets you set the artist or title
* individually, which purple_prpl_got_user_status() doesn't do.
*/
static void msim_set_artist_or_title(MsimUser *user, const char *new_artist, const char *new_title)
{
PurplePresence *presence;
PurpleAccount *account;
const char *prev_artist, *prev_title;
const char *name;
if (user->buddy == NULL)
/* User not on buddy list so nothing to do */
return;
prev_artist = NULL;
prev_title = NULL;
if (new_artist && !*new_artist)
new_artist = NULL;
if (new_title && !*new_title)
new_title = NULL;
account = purple_buddy_get_account(user->buddy);
name = purple_buddy_get_name(user->buddy);
if (!new_artist && !new_title) {
purple_prpl_got_user_status_deactive(account, name, "tune");
return;
}
presence = purple_buddy_get_presence(user->buddy);
if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
PurpleStatus *status;
status = purple_presence_get_status(presence, "tune");
prev_title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE);
prev_artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST);
}
if (!new_artist)
new_artist = prev_artist;
if (!new_title)
new_title = prev_title;
purple_prpl_got_user_status(account, name, "tune",
PURPLE_TUNE_TITLE, new_title,
PURPLE_TUNE_ARTIST, new_artist,
NULL);
}
/**
* Store a field of information about a buddy.
*
* @param key_str Key to store.
* @param value_str Value string, either user takes ownership of this string
* or it is freed if MsimUser doesn't store the string.
* @param user User to store data in. Existing data will be replaced.
*/
static void
msim_store_user_info_each(const gchar *key_str, gchar *value_str, MsimUser *user)
{
const char *name = user->buddy ? purple_buddy_get_name(user->buddy) : NULL;
if (g_str_equal(key_str, "UserID") || g_str_equal(key_str, "ContactID")) {
/* Save to buddy list, if it exists, for quick cached uid lookup with msim_uid2username_from_blist(). */
user->id = atol(value_str);
g_free(value_str);
if (user->buddy)
{
purple_debug_info("msim", "associating uid %s with username %s\n", key_str, name);
purple_blist_node_set_int(PURPLE_BLIST_NODE(user->buddy), "UserID", user->id);
}
/* Need to store in MsimUser, too? What if not on blist? */
} else if (g_str_equal(key_str, "Age")) {
user->age = atol(value_str);
g_free(value_str);
} else if (g_str_equal(key_str, "Gender")) {
g_free(user->gender);
user->gender = value_str;
} else if (g_str_equal(key_str, "Location")) {
g_free(user->location);
user->location = value_str;
} else if (g_str_equal(key_str, "TotalFriends")) {
user->total_friends = atol(value_str);
g_free(value_str);
} else if (g_str_equal(key_str, "DisplayName")) {
g_free(user->display_name);
user->display_name = value_str;
} else if (g_str_equal(key_str, "BandName")) {
msim_set_artist_or_title(user, value_str, NULL);
g_free(value_str);
} else if (g_str_equal(key_str, "SongName")) {
msim_set_artist_or_title(user, NULL, value_str);
g_free(value_str);
} else if (g_str_equal(key_str, "UserName") || g_str_equal(key_str, "IMName") || g_str_equal(key_str, "NickName")) {
/* Ignore because PurpleBuddy knows this already */
g_free(value_str);
} else if (g_str_equal(key_str, "ImageURL") || g_str_equal(key_str, "AvatarURL")) {
const gchar *previous_url;
if (user->temporary_user) {
/* This user will be destroyed soon; don't try to look up its image or avatar,
* since that won't return immediately and we will end up accessing freed data.
*/
g_free(value_str);
return;
}
g_free(user->image_url);
user->image_url = value_str;
/* Instead of showing 'no photo' picture, show nothing. */
if (g_str_equal(user->image_url, "http://x.myspace.com/images/no_pic.gif"))
{
purple_buddy_icons_set_for_user(purple_buddy_get_account(user->buddy),
name, NULL, 0, NULL);
return;
}
/* TODO: use ETag for checksum */
previous_url = purple_buddy_icons_get_checksum_for_user(user->buddy);
/* Only download if URL changed */
if (!previous_url || !g_str_equal(previous_url, user->image_url)) {
if (user->url_data != NULL)
purple_util_fetch_url_cancel(user->url_data);
user->url_data = purple_util_fetch_url(user->image_url, TRUE, NULL, TRUE, msim_downloaded_buddy_icon, (gpointer)user);
}
} else if (g_str_equal(key_str, "LastImageUpdated")) {
/* TODO: use somewhere */
user->last_image_updated = atol(value_str);
g_free(value_str);
} else if (g_str_equal(key_str, "Headline")) {
g_free(user->headline);
user->headline = value_str;
} else {
/* TODO: other fields in MsimUser */
gchar *msg;
msg = g_strdup_printf("msim_store_user_info_each: unknown field %s=%s",
key_str, value_str);
g_free(value_str);
msim_unrecognized(NULL, NULL, msg);
g_free(msg);
}
}
/**
* Save buddy information to the buddy list from a user info reply message.
*
* @param session
* @param msg The user information reply, with any amount of information.
* @param user The structure to save to, or NULL to save in PurpleBuddy->proto_data.
*
* Variable information is saved to the passed MsimUser structure. Permanent
* information (UserID) is stored in the blist node of the buddy list (and
* ends up in blist.xml, persisted to disk) if it exists.
*
* If the function has no buddy information, this function
* is a no-op (and returns FALSE).
*/
gboolean
msim_store_user_info(MsimSession *session, const MsimMessage *msg, MsimUser *user)
{
gchar *username;
MsimMessage *body, *body_node;
g_return_val_if_fail(msg != NULL, FALSE);
body = msim_msg_get_dictionary(msg, "body");
if (!body) {
return FALSE;
}
if (msim_msg_get_integer(msg, "dsn") == MG_OWN_IM_INFO_DSN &&
msim_msg_get_integer(msg, "lid") == MG_OWN_IM_INFO_LID)
{
/*
* Some of this info will be available on the buddy list if the
* user has themselves as their own buddy.
*
* Much of the info is already available in MsimSession,
* stored in msim_we_are_logged_on().
*/
gchar *tmpstr;
tmpstr = msim_msg_get_string(body, "ShowOnlyToList");
if (tmpstr != NULL) {
session->show_only_to_list = g_str_equal(tmpstr, "True");
g_free(tmpstr);
}
session->privacy_mode = msim_msg_get_integer(body, "PrivacyMode");
session->offline_message_mode = msim_msg_get_integer(body, "OfflineMessageMode");
msim_send(session,
"blocklist", MSIM_TYPE_BOOLEAN, TRUE,
"sesskey", MSIM_TYPE_INTEGER, session->sesskey,
"idlist", MSIM_TYPE_STRING,
g_strdup_printf("w%d|c%d",
session->show_only_to_list ? 1 : 0,
session->privacy_mode & 1),
NULL);
} else if (msim_msg_get_integer(msg, "dsn") == MG_OWN_MYSPACE_INFO_DSN &&
msim_msg_get_integer(msg, "lid") == MG_OWN_MYSPACE_INFO_LID) {
/* TODO: same as above, but for MySpace info. */
}
username = msim_msg_get_string(body, "UserName");
if (!username) {
purple_debug_info("msim",
"msim_process_reply: not caching body, no UserName\n");
msim_msg_free(body);
g_free(username);
return FALSE;
}
/* Null user = find and store in PurpleBuddy's proto_data */
if (!user) {
user = msim_find_user(session, username);
if (!user) {
msim_msg_free(body);
g_free(username);
return FALSE;
}
}
/* TODO: make looping over MsimMessage's easier. */
for (body_node = body;
body_node != NULL;
body_node = msim_msg_get_next_element_node(body_node))
{
const gchar *key_str;
gchar *value_str;
MsimMessageElement *elem;
elem = (MsimMessageElement *)body_node->data;
key_str = elem->name;
value_str = msim_msg_get_string_from_element(elem);
msim_store_user_info_each(key_str, value_str, user);
}
msim_msg_free(body);
g_free(username);
return TRUE;
}
#if 0
/**
* Return whether a given username is syntactically valid.
* Note: does not actually check that the user exists.
*/
static 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);
}
#endif
/**
* Check if a string is a userid (all numeric).
*
* @param user The user id, email, or name.
*
* @return TRUE if is userid, FALSE if not.
*/
gboolean
msim_is_userid(const gchar *user)
{
g_return_val_if_fail(user != NULL, FALSE);
return strspn(user, "0123456789") == strlen(user);
}
/**
* Check if a string is an email address (contains an @).
*
* @param user The user id, email, or name.
*
* @return TRUE if is an email, FALSE if not.
*
* This function is not intended to be used as a generic
* means of validating email addresses, but to distinguish
* between a user represented by an email address from
* other forms of identification.
*/
static gboolean
msim_is_email(const gchar *user)
{
g_return_val_if_fail(user != NULL, FALSE);
return strchr(user, '@') != NULL;
}
/**
* Asynchronously lookup user information, calling callback when receive result.
*
* @param session
* @param user The user id, email address, or username. Not freed.
* @param cb Callback, called with user information when available.
* @param data An arbitray data pointer passed to the callback.
*/
/* TODO: change to not use callbacks */
void
msim_lookup_user(MsimSession *session, const gchar *user, MSIM_USER_LOOKUP_CB cb, gpointer data)
{
MsimMessage *body;
gchar *field_name;
guint rid, dsn, lid;
g_return_if_fail(user != NULL);
/* Callback can be null to not call anything, just lookup & store information. */
/*g_return_if_fail(cb != NULL);*/
purple_debug_info("msim", "msim_lookup_userid: "
"asynchronously looking up <%s>\n", user);
/* Setup callback. Response will be associated with request using 'rid'. */
rid = msim_new_reply_callback(session, cb, data);
/* Send request */
if (msim_is_userid(user)) {
field_name = "UserID";
dsn = MG_MYSPACE_INFO_BY_ID_DSN;
lid = MG_MYSPACE_INFO_BY_ID_LID;
} else if (msim_is_email(user)) {
field_name = "Email";
dsn = MG_MYSPACE_INFO_BY_STRING_DSN;
lid = MG_MYSPACE_INFO_BY_STRING_LID;
} else {
field_name = "UserName";
dsn = MG_MYSPACE_INFO_BY_STRING_DSN;
lid = MG_MYSPACE_INFO_BY_STRING_LID;
}
body = msim_msg_new(
field_name, MSIM_TYPE_STRING, g_strdup(user),
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, dsn,
"uid", MSIM_TYPE_INTEGER, session->userid,
"lid", MSIM_TYPE_INTEGER, 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, const MsimMessage *userinfo, gpointer data)
{
gchar *username;
const gchar *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");
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 = _("An error occurred while trying to set the username. "
"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! */
session->username = username;
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);
}
}
/**
* 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(username != NULL);
g_return_if_fail(cb != NULL);
purple_debug_info("msim", "msim_set_username: "
"Setting username %s\n", username);
/* 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));
}
/**
* 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;
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);
}
/**
* 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, const 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(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 occurred while trying to set the username. "
"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);
}
}
/**
* 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;
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);
}
/***
* 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 then boot them here.
*/
void msim_do_not_set_username_cb(PurpleConnection *gc)
{
purple_debug_info("msim", "Don't 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);
}