Open an explorer.exe window at the location of the file when clicking
[pidgin-git.git] / libpurple / protocols / myspace / user.c
blob738045043a1dd951a26d3882844bfeeb8f37ec1f
1 /* MySpaceIM Protocol Plugin, header file
3 * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
20 #include "myspace.h"
22 static void msim_check_username_availability_cb(PurpleConnection *gc, const char *username_to_check);
24 static char *msim_username_to_set;
26 /**
27 * Format the "now playing" indicator, showing the artist and song.
29 * @return Return a new string (must be g_free()'d), or NULL.
31 static gchar *
32 msim_format_now_playing(const gchar *band, const gchar *song)
34 if ((band && *band) || (song && *song)) {
35 return g_strdup_printf("%s - %s",
36 (band && *band) ? band : "Unknown Artist",
37 (song && *song) ? song : "Unknown Song");
38 } else {
39 return NULL;
43 /**
44 * Get the MsimUser from a PurpleBuddy, optionally creating it if needed.
46 MsimUser *
47 msim_get_user_from_buddy(PurpleBuddy *buddy, gboolean create)
49 MsimUser *user;
51 if (!buddy) {
52 return NULL;
55 user = purple_buddy_get_protocol_data(buddy);
56 if (create && !user) {
57 PurpleBlistNode *node = PURPLE_BLIST_NODE(buddy);
59 /* No MsimUser for this buddy; make one. */
61 user = g_new0(MsimUser, 1);
62 user->buddy = buddy;
63 user->id = purple_blist_node_get_int(node, "UserID");
64 purple_buddy_set_protocol_data(buddy, user);
67 return user;
70 void msim_user_free(MsimUser *user)
72 if (!user)
73 return;
75 if (user->url_data != NULL)
76 purple_util_fetch_url_cancel(user->url_data);
78 g_free(user->client_info);
79 g_free(user->gender);
80 g_free(user->location);
81 g_free(user->headline);
82 g_free(user->display_name);
83 g_free(user->username);
84 g_free(user->band_name);
85 g_free(user->song_name);
86 g_free(user->image_url);
87 g_free(user);
90 /**
91 * Find and return an MsimUser * representing a user on the buddy list, or NULL.
93 MsimUser *
94 msim_find_user(MsimSession *session, const gchar *username)
96 PurpleBuddy *buddy;
98 buddy = purple_find_buddy(session->account, username);
99 if (!buddy) {
100 return NULL;
103 return msim_get_user_from_buddy(buddy, TRUE);
107 * Append user information to a PurpleNotifyUserInfo, given an MsimUser.
108 * Used by msim_tooltip_text() and msim_get_info_cb() to show a user's profile.
110 void
111 msim_append_user_info(MsimSession *session, PurpleNotifyUserInfo *user_info, MsimUser *user, gboolean full)
113 PurplePresence *presence;
114 gchar *str;
115 guint cv;
117 /* Useful to identify the account the tooltip refers to.
118 * Other prpls show this. */
119 if (user->username) {
120 purple_notify_user_info_add_pair(user_info, _("User"), user->username);
123 /* a/s/l...the vitals */
124 if (user->age) {
125 char age[16];
126 g_snprintf(age, sizeof(age), "%d", user->age);
127 purple_notify_user_info_add_pair(user_info, _("Age"), age);
130 if (user->gender && *user->gender) {
131 purple_notify_user_info_add_pair(user_info, _("Gender"), user->gender);
134 if (user->location && *user->location) {
135 purple_notify_user_info_add_pair(user_info, _("Location"), user->location);
138 /* Other information */
139 if (user->headline && *user->headline) {
140 purple_notify_user_info_add_pair(user_info, _("Headline"), user->headline);
143 if (user->buddy != NULL) {
144 presence = purple_buddy_get_presence(user->buddy);
146 if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
147 PurpleStatus *status;
148 const char *artist, *title;
150 status = purple_presence_get_status(presence, "tune");
151 title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE);
152 artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST);
154 str = msim_format_now_playing(artist, title);
155 if (str && *str) {
156 purple_notify_user_info_add_pair(user_info, _("Song"), str);
158 g_free(str);
162 /* Note: total friends only available if looked up by uid, not username. */
163 if (user->total_friends) {
164 char friends[16];
165 g_snprintf(friends, sizeof(friends), "%d", user->total_friends);
166 purple_notify_user_info_add_pair(user_info, _("Total Friends"), friends);
169 if (full) {
170 /* Client information */
171 char *client = NULL;
173 str = user->client_info;
174 cv = user->client_cv;
176 if (str && cv != 0) {
177 client = g_strdup_printf("%s (build %d)", str, cv);
178 } else if (str) {
179 client = g_strdup(str);
180 } else if (cv) {
181 client = g_strdup_printf("Build %d", cv);
183 if (client && *client)
184 purple_notify_user_info_add_pair(user_info, _("Client Version"), client);
185 g_free(client);
188 if (full && user->id) {
189 /* TODO: link to username, if available */
190 char *profile;
191 purple_notify_user_info_add_section_break(user_info);
192 if (user->buddy != NULL)
193 profile = g_strdup_printf("<a href=\"http://myspace.com/%s\">%s</a>",
194 purple_buddy_get_name(user->buddy), _("View web profile"));
195 else
196 profile = g_strdup_printf("<a href=\"http://myspace.com/%d\">%s</a>",
197 user->id, _("View web profile"));
198 purple_notify_user_info_add_pair(user_info, NULL, profile);
199 g_free(profile);
204 * Callback for when a buddy icon finished being downloaded.
206 static void
207 msim_downloaded_buddy_icon(PurpleUtilFetchUrlData *url_data,
208 gpointer user_data,
209 const gchar *url_text,
210 gsize len,
211 const gchar *error_message)
213 MsimUser *user = (MsimUser *)user_data;
214 const char *name = purple_buddy_get_name(user->buddy);
215 PurpleAccount *account;
217 user->url_data = NULL;
219 purple_debug_info("msim_downloaded_buddy_icon",
220 "Downloaded %" G_GSIZE_FORMAT " bytes\n", len);
222 if (!url_text) {
223 purple_debug_info("msim_downloaded_buddy_icon",
224 "failed to download icon for %s",
225 name);
226 return;
229 account = purple_buddy_get_account(user->buddy);
230 purple_buddy_icons_set_for_user(account, name,
231 g_memdup((gchar *)url_text, len), len,
232 /* Use URL itself as buddy icon "checksum" (TODO: ETag) */
233 user->image_url); /* checksum */
237 * Set the currently playing song artist and or title.
239 * @param user User associated with the now playing information.
241 * @param new_artist New artist to set, or NULL/empty to not change artist.
243 * @param new_title New title to set, or NULL/empty to not change title.
245 * If new_artist and new_title are NULL/empty, deactivate PURPLE_STATUS_TUNE.
247 * This function is useful because it lets you set the artist or title
248 * individually, which purple_prpl_got_user_status() doesn't do.
250 static void msim_set_artist_or_title(MsimUser *user, const char *new_artist, const char *new_title)
252 PurplePresence *presence;
253 PurpleAccount *account;
254 const char *prev_artist, *prev_title;
255 const char *name;
257 if (user->buddy == NULL)
258 /* User not on buddy list so nothing to do */
259 return;
261 prev_artist = NULL;
262 prev_title = NULL;
264 if (new_artist && !*new_artist)
265 new_artist = NULL;
266 if (new_title && !*new_title)
267 new_title = NULL;
269 account = purple_buddy_get_account(user->buddy);
270 name = purple_buddy_get_name(user->buddy);
272 if (!new_artist && !new_title) {
273 purple_prpl_got_user_status_deactive(account, name, "tune");
274 return;
277 presence = purple_buddy_get_presence(user->buddy);
279 if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
280 PurpleStatus *status;
282 status = purple_presence_get_status(presence, "tune");
283 prev_title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE);
284 prev_artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST);
287 if (!new_artist)
288 new_artist = prev_artist;
290 if (!new_title)
291 new_title = prev_title;
293 purple_prpl_got_user_status(account, name, "tune",
294 PURPLE_TUNE_TITLE, new_title,
295 PURPLE_TUNE_ARTIST, new_artist,
296 NULL);
300 * Store a field of information about a buddy.
302 * @param key_str Key to store.
303 * @param value_str Value string, either user takes ownership of this string
304 * or it is freed if MsimUser doesn't store the string.
305 * @param user User to store data in. Existing data will be replaced.
307 static void
308 msim_store_user_info_each(const gchar *key_str, gchar *value_str, MsimUser *user)
310 const char *name = user->buddy ? purple_buddy_get_name(user->buddy) : NULL;
312 if (g_str_equal(key_str, "UserID") || g_str_equal(key_str, "ContactID")) {
313 /* Save to buddy list, if it exists, for quick cached uid lookup with msim_uid2username_from_blist(). */
314 user->id = atol(value_str);
315 g_free(value_str);
316 if (user->buddy)
318 purple_debug_info("msim", "associating uid %s with username %s\n", key_str, name);
319 purple_blist_node_set_int(PURPLE_BLIST_NODE(user->buddy), "UserID", user->id);
321 /* Need to store in MsimUser, too? What if not on blist? */
322 } else if (g_str_equal(key_str, "Age")) {
323 user->age = atol(value_str);
324 g_free(value_str);
325 } else if (g_str_equal(key_str, "Gender")) {
326 g_free(user->gender);
327 user->gender = value_str;
328 } else if (g_str_equal(key_str, "Location")) {
329 g_free(user->location);
330 user->location = value_str;
331 } else if (g_str_equal(key_str, "TotalFriends")) {
332 user->total_friends = atol(value_str);
333 g_free(value_str);
334 } else if (g_str_equal(key_str, "DisplayName")) {
335 g_free(user->display_name);
336 user->display_name = value_str;
337 } else if (g_str_equal(key_str, "BandName")) {
338 msim_set_artist_or_title(user, value_str, NULL);
339 g_free(value_str);
340 } else if (g_str_equal(key_str, "SongName")) {
341 msim_set_artist_or_title(user, NULL, value_str);
342 g_free(value_str);
343 } else if (g_str_equal(key_str, "UserName") || g_str_equal(key_str, "IMName") || g_str_equal(key_str, "NickName")) {
344 /* Ignore because PurpleBuddy knows this already */
345 g_free(value_str);
346 } else if (g_str_equal(key_str, "ImageURL") || g_str_equal(key_str, "AvatarURL")) {
347 const gchar *previous_url;
349 if (user->temporary_user) {
350 /* This user will be destroyed soon; don't try to look up its image or avatar,
351 * since that won't return immediately and we will end up accessing freed data.
353 g_free(value_str);
354 return;
357 g_free(user->image_url);
359 user->image_url = value_str;
361 /* Instead of showing 'no photo' picture, show nothing. */
362 if (g_str_equal(user->image_url, "http://x.myspace.com/images/no_pic.gif"))
364 purple_buddy_icons_set_for_user(purple_buddy_get_account(user->buddy),
365 name, NULL, 0, NULL);
366 return;
369 /* TODO: use ETag for checksum */
370 previous_url = purple_buddy_icons_get_checksum_for_user(user->buddy);
372 /* Only download if URL changed */
373 if (!previous_url || !g_str_equal(previous_url, user->image_url)) {
374 if (user->url_data != NULL)
375 purple_util_fetch_url_cancel(user->url_data);
376 user->url_data = purple_util_fetch_url(user->image_url, TRUE, NULL, TRUE, msim_downloaded_buddy_icon, (gpointer)user);
378 } else if (g_str_equal(key_str, "LastImageUpdated")) {
379 /* TODO: use somewhere */
380 user->last_image_updated = atol(value_str);
381 g_free(value_str);
382 } else if (g_str_equal(key_str, "Headline")) {
383 g_free(user->headline);
384 user->headline = value_str;
385 } else {
386 /* TODO: other fields in MsimUser */
387 gchar *msg;
389 msg = g_strdup_printf("msim_store_user_info_each: unknown field %s=%s",
390 key_str, value_str);
391 g_free(value_str);
393 msim_unrecognized(NULL, NULL, msg);
395 g_free(msg);
400 * Save buddy information to the buddy list from a user info reply message.
402 * @param session
403 * @param msg The user information reply, with any amount of information.
404 * @param user The structure to save to, or NULL to save in PurpleBuddy->proto_data.
406 * Variable information is saved to the passed MsimUser structure. Permanent
407 * information (UserID) is stored in the blist node of the buddy list (and
408 * ends up in blist.xml, persisted to disk) if it exists.
410 * If the function has no buddy information, this function
411 * is a no-op (and returns FALSE).
413 gboolean
414 msim_store_user_info(MsimSession *session, const MsimMessage *msg, MsimUser *user)
416 gchar *username;
417 MsimMessage *body, *body_node;
419 g_return_val_if_fail(msg != NULL, FALSE);
421 body = msim_msg_get_dictionary(msg, "body");
422 if (!body) {
423 return FALSE;
426 if (msim_msg_get_integer(msg, "dsn") == MG_OWN_IM_INFO_DSN &&
427 msim_msg_get_integer(msg, "lid") == MG_OWN_IM_INFO_LID)
430 * Some of this info will be available on the buddy list if the
431 * user has themselves as their own buddy.
433 * Much of the info is already available in MsimSession,
434 * stored in msim_we_are_logged_on().
436 gchar *tmpstr;
438 tmpstr = msim_msg_get_string(body, "ShowOnlyToList");
439 if (tmpstr != NULL) {
440 session->show_only_to_list = g_str_equal(tmpstr, "True");
441 g_free(tmpstr);
444 session->privacy_mode = msim_msg_get_integer(body, "PrivacyMode");
445 session->offline_message_mode = msim_msg_get_integer(body, "OfflineMessageMode");
447 msim_send(session,
448 "blocklist", MSIM_TYPE_BOOLEAN, TRUE,
449 "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
450 "idlist", MSIM_TYPE_STRING,
451 g_strdup_printf("w%d|c%d",
452 session->show_only_to_list ? 1 : 0,
453 session->privacy_mode & 1),
454 NULL);
455 } else if (msim_msg_get_integer(msg, "dsn") == MG_OWN_MYSPACE_INFO_DSN &&
456 msim_msg_get_integer(msg, "lid") == MG_OWN_MYSPACE_INFO_LID) {
457 /* TODO: same as above, but for MySpace info. */
460 username = msim_msg_get_string(body, "UserName");
462 if (!username) {
463 purple_debug_info("msim",
464 "msim_process_reply: not caching body, no UserName\n");
465 msim_msg_free(body);
466 g_free(username);
467 return FALSE;
470 /* Null user = find and store in PurpleBuddy's proto_data */
471 if (!user) {
472 user = msim_find_user(session, username);
473 if (!user) {
474 msim_msg_free(body);
475 g_free(username);
476 return FALSE;
480 /* TODO: make looping over MsimMessage's easier. */
481 for (body_node = body;
482 body_node != NULL;
483 body_node = msim_msg_get_next_element_node(body_node))
485 const gchar *key_str;
486 gchar *value_str;
487 MsimMessageElement *elem;
489 elem = (MsimMessageElement *)body_node->data;
490 key_str = elem->name;
492 value_str = msim_msg_get_string_from_element(elem);
493 msim_store_user_info_each(key_str, value_str, user);
496 msim_msg_free(body);
497 g_free(username);
499 return TRUE;
502 #if 0
504 * Return whether a given username is syntactically valid.
505 * Note: does not actually check that the user exists.
507 static gboolean
508 msim_is_valid_username(const gchar *user)
510 return !msim_is_userid(user) && /* Not all numeric */
511 strlen(user) <= MSIM_MAX_USERNAME_LENGTH
512 && strspn(user, "0123456789"
513 "abcdefghijklmnopqrstuvwxyz"
515 "ABCDEFGHIJKLMNOPQRSTUVWXYZ") == strlen(user);
517 #endif
520 * Check if a string is a userid (all numeric).
522 * @param user The user id, email, or name.
524 * @return TRUE if is userid, FALSE if not.
526 gboolean
527 msim_is_userid(const gchar *user)
529 g_return_val_if_fail(user != NULL, FALSE);
531 return strspn(user, "0123456789") == strlen(user);
535 * Check if a string is an email address (contains an @).
537 * @param user The user id, email, or name.
539 * @return TRUE if is an email, FALSE if not.
541 * This function is not intended to be used as a generic
542 * means of validating email addresses, but to distinguish
543 * between a user represented by an email address from
544 * other forms of identification.
546 static gboolean
547 msim_is_email(const gchar *user)
549 g_return_val_if_fail(user != NULL, FALSE);
551 return strchr(user, '@') != NULL;
555 * Asynchronously lookup user information, calling callback when receive result.
557 * @param session
558 * @param user The user id, email address, or username. Not freed.
559 * @param cb Callback, called with user information when available.
560 * @param data An arbitray data pointer passed to the callback.
562 /* TODO: change to not use callbacks */
563 void
564 msim_lookup_user(MsimSession *session, const gchar *user, MSIM_USER_LOOKUP_CB cb, gpointer data)
566 MsimMessage *body;
567 gchar *field_name;
568 guint rid, dsn, lid;
570 g_return_if_fail(user != NULL);
571 /* Callback can be null to not call anything, just lookup & store information. */
572 /*g_return_if_fail(cb != NULL);*/
574 purple_debug_info("msim", "msim_lookup_userid: "
575 "asynchronously looking up <%s>\n", user);
577 /* Setup callback. Response will be associated with request using 'rid'. */
578 rid = msim_new_reply_callback(session, cb, data);
580 /* Send request */
582 if (msim_is_userid(user)) {
583 field_name = "UserID";
584 dsn = MG_MYSPACE_INFO_BY_ID_DSN;
585 lid = MG_MYSPACE_INFO_BY_ID_LID;
586 } else if (msim_is_email(user)) {
587 field_name = "Email";
588 dsn = MG_MYSPACE_INFO_BY_STRING_DSN;
589 lid = MG_MYSPACE_INFO_BY_STRING_LID;
590 } else {
591 field_name = "UserName";
592 dsn = MG_MYSPACE_INFO_BY_STRING_DSN;
593 lid = MG_MYSPACE_INFO_BY_STRING_LID;
596 body = msim_msg_new(
597 field_name, MSIM_TYPE_STRING, g_strdup(user),
598 NULL);
600 g_return_if_fail(msim_send(session,
601 "persist", MSIM_TYPE_INTEGER, 1,
602 "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
603 "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_GET,
604 "dsn", MSIM_TYPE_INTEGER, dsn,
605 "uid", MSIM_TYPE_INTEGER, session->userid,
606 "lid", MSIM_TYPE_INTEGER, lid,
607 "rid", MSIM_TYPE_INTEGER, rid,
608 "body", MSIM_TYPE_DICTIONARY, body,
609 NULL));
613 * Called after username is set.
615 static void msim_username_is_set_cb(MsimSession *session, const MsimMessage *userinfo, gpointer data)
617 gchar *username;
618 const gchar *errmsg;
619 MsimMessage *body;
621 guint rid;
622 gint cmd,dsn,uid,lid,code;
623 /* \persistr\\cmd\258\dsn\9\uid\204084363\lid\14\rid\369\body\UserName=TheAlbinoRhino1.Code=0\final\ */
625 purple_debug_info("msim","username_is_set made\n");
627 cmd = msim_msg_get_integer(userinfo, "cmd");
628 dsn = msim_msg_get_integer(userinfo, "dsn");
629 uid = msim_msg_get_integer(userinfo, "uid");
630 lid = msim_msg_get_integer(userinfo, "lid");
631 body = msim_msg_get_dictionary(userinfo, "body");
632 errmsg = _("An error occurred while trying to set the username. "
633 "Please try again, or visit http://editprofile.myspace.com/index.cfm?"
634 "fuseaction=profile.username to set your username.");
636 if (!body) {
637 purple_debug_info("msim_username_is_set_cb", "No body");
638 /* Error: No body! */
639 purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg);
641 username = msim_msg_get_string(body, "UserName");
642 code = msim_msg_get_integer(body,"Code");
644 msim_msg_free(body);
646 purple_debug_info("msim_username_is_set_cb",
647 "cmd = %d, dsn = %d, lid = %d, code = %d, username = %s\n",
648 cmd, dsn, lid, code, username);
650 if (cmd == (MSIM_CMD_BIT_REPLY | MSIM_CMD_PUT)
651 && dsn == MC_SET_USERNAME_DSN
652 && lid == MC_SET_USERNAME_LID)
654 purple_debug_info("msim_username_is_set_cb", "Proper cmd,dsn,lid for username_is_set!\n");
655 purple_debug_info("msim_username_is_set_cb", "Username Set with return code %d\n",code);
656 if (code == 0) {
657 /* Good! */
658 session->username = username;
659 msim_we_are_logged_on(session);
660 } else {
661 purple_debug_info("msim_username_is_set", "code is %d",code);
662 /* TODO: what to do here? */
664 } else if (cmd == (MSIM_CMD_BIT_REPLY | MSIM_CMD_GET)
665 && dsn == MG_MYSPACE_INFO_BY_STRING_DSN
666 && lid == MG_MYSPACE_INFO_BY_STRING_LID) {
667 /* Not quite done... ONE MORE STEP :) */
668 rid = msim_new_reply_callback(session, msim_username_is_set_cb, data);
669 body = msim_msg_new("UserName", MSIM_TYPE_STRING, g_strdup(username), NULL);
670 if (!msim_send(session, "persist", MSIM_TYPE_INTEGER, 1,
671 "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
672 "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_PUT,
673 "dsn", MSIM_TYPE_INTEGER, MC_SET_USERNAME_DSN,
674 "uid", MSIM_TYPE_INTEGER, session->userid,
675 "lid", MSIM_TYPE_INTEGER, MC_SET_USERNAME_LID,
676 "rid", MSIM_TYPE_INTEGER, rid,
677 "body", MSIM_TYPE_DICTIONARY, body,
678 NULL)) {
679 /* Error! */
680 /* Can't set... Disconnect */
681 purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg);
684 } else {
685 /* Error! */
686 purple_debug_info("msim","username_is_set Error: Invalid cmd/dsn/lid combination");
687 purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg);
692 * Asynchronously set new username, calling callback when receive result.
694 * @param session
695 * @param username The username we're setting for ourselves. Not freed.
696 * @param cb Callback, called with user information when available.
697 * @param data An arbitray data pointer passed to the callback.
699 static void
700 msim_set_username(MsimSession *session, const gchar *username,
701 MSIM_USER_LOOKUP_CB cb, gpointer data)
703 MsimMessage *body;
704 guint rid;
706 g_return_if_fail(username != NULL);
707 g_return_if_fail(cb != NULL);
709 purple_debug_info("msim", "msim_set_username: "
710 "Setting username %s\n", username);
712 /* Setup callback. Response will be associated with request using 'rid'. */
713 rid = msim_new_reply_callback(session, cb, data);
715 /* TODO: I dont know if the ContactType is -/ALWAYS/- 1 */
717 body = msim_msg_new("UserName", MSIM_TYPE_STRING, g_strdup(username),NULL);
718 /* \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\
721 /* Send request */
722 g_return_if_fail(msim_send(session,
723 "setinfo", MSIM_TYPE_BOOLEAN, TRUE,
724 "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
725 "info", MSIM_TYPE_DICTIONARY, body,
726 NULL));
727 body = msim_msg_new("UserName", MSIM_TYPE_STRING, g_strdup(username),NULL);
728 g_return_if_fail(msim_send(session,
729 "persist", MSIM_TYPE_INTEGER, 1,
730 "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
731 "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_GET,
732 "dsn", MSIM_TYPE_INTEGER, MG_MYSPACE_INFO_BY_STRING_DSN,
733 "uid", MSIM_TYPE_INTEGER, session->userid,
734 "lid", MSIM_TYPE_INTEGER, MG_MYSPACE_INFO_BY_STRING_LID,
735 "rid", MSIM_TYPE_INTEGER, rid,
736 "body", MSIM_TYPE_DICTIONARY, body,
737 NULL));
741 * They've confirmed that username that was available, Lets make the call to set it
743 static void msim_set_username_confirmed_cb(PurpleConnection *gc)
745 MsimMessage *user_msg;
746 MsimSession *session;
748 g_return_if_fail(gc != NULL);
750 session = (MsimSession *)gc->proto_data;
752 user_msg = msim_msg_new(
753 "user", MSIM_TYPE_STRING, g_strdup(msim_username_to_set),
754 NULL);
756 purple_debug_info("msim_set_username_confirmed_cb", "Setting username to %s\n", msim_username_to_set);
758 /* Sets our username... keep your fingers crossed :) */
759 msim_set_username(session, msim_username_to_set, msim_username_is_set_cb, user_msg);
760 g_free(msim_username_to_set);
764 * This is where we do a bit more than merely prompt the user.
765 * Now we have some real data to tell us the state of their requested username
766 * \persistr\\cmd\257\dsn\5\uid\204084363\lid\7\rid\367\body\UserName=TheAlbinoRhino1\final\
768 static void msim_username_is_available_cb(MsimSession *session, const MsimMessage *userinfo, gpointer data)
770 MsimMessage *msg;
771 gchar *username;
772 MsimMessage *body;
773 gint userid;
775 purple_debug_info("msim_username_is_available_cb", "Look up username callback made\n");
777 msg = (MsimMessage *)data;
778 g_return_if_fail(msg != NULL);
780 username = msim_msg_get_string(msg, "user");
781 body = msim_msg_get_dictionary(userinfo, "body");
783 if (!body) {
784 purple_debug_info("msim_username_is_available_cb", "No body for %s?!\n", username);
785 purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
786 _("An error occurred while trying to set the username. "
787 "Please try again, or visit http://editprofile.myspace.com/index.cfm?"
788 "fuseaction=profile.username to set your username."));
789 return;
792 userid = msim_msg_get_integer(body, "UserID");
794 purple_debug_info("msim_username_is_available_cb", "Returned username is %s and userid is %d\n", username, userid);
795 msim_msg_free(body);
796 msim_msg_free(msg);
798 /* The response for a free username will ONLY have the UserName in it..
799 * thus making UserID return 0 when we msg_get_integer it */
800 if (userid == 0) {
801 /* This username is currently unused */
802 purple_debug_info("msim_username_is_available_cb", "Username available. Prompting to Confirm.\n");
803 msim_username_to_set = g_strdup(username);
804 g_free(username);
805 purple_request_yes_no(session->gc,
806 _("MySpaceIM - Username Available"),
807 _("This username is available. Would you like to set it?"),
808 _("ONCE SET, THIS CANNOT BE CHANGED!"),
810 session->account,
811 NULL,
812 NULL,
813 session->gc,
814 G_CALLBACK(msim_set_username_confirmed_cb),
815 G_CALLBACK(msim_do_not_set_username_cb));
816 } else {
817 /* Looks like its in use or we have an invalid response */
818 purple_debug_info("msim_username_is_available_cb", "Username unavaiable. Prompting for new entry.\n");
819 purple_request_input(session->gc, _("MySpaceIM - Please Set a Username"),
820 _("This username is unavailable."),
821 _("Please try another username:"),
822 "", FALSE, FALSE, NULL,
823 _("OK"), G_CALLBACK(msim_check_username_availability_cb),
824 _("Cancel"), G_CALLBACK(msim_do_not_set_username_cb),
825 session->account,
826 NULL,
827 NULL,
828 session->gc);
833 * Once they've submitted their desired new username,
834 * check if it is available here.
836 static void msim_check_username_availability_cb(PurpleConnection *gc, const char *username_to_check)
838 MsimMessage *user_msg;
839 MsimSession *session;
841 g_return_if_fail(gc != NULL);
843 session = (MsimSession *)gc->proto_data;
845 purple_debug_info("msim_check_username_availability_cb", "Checking username: %s\n", username_to_check);
847 user_msg = msim_msg_new(
848 "user", MSIM_TYPE_STRING, g_strdup(username_to_check),
849 NULL);
851 /* 25 characters: letters, numbers, underscores */
852 /* TODO: VERIFY ABOVE */
854 /* \persist\1\sesskey\288500516\cmd\1\dsn\5\uid\204084363\lid\7\rid\367\body\UserName=Jaywalker\final\ */
855 /* Official client uses a standard lookup... So do we! */
856 msim_lookup_user(session, username_to_check, msim_username_is_available_cb, user_msg);
859 /***
860 * If they hit cancel or no at any point in the Setting Username process,
861 * we come here. Currently we're safe letting them get by without
862 * setting it, unless we hear otherwise. So for now give them a menu.
863 * If this becomes an issue with the official client then boot them here.
865 void msim_do_not_set_username_cb(PurpleConnection *gc)
867 purple_debug_info("msim", "Don't set username");
869 /* Protocol won't log in now without a username set.. Disconnect */
870 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("No username set"));
874 * They've decided to set a username! Yay!
876 void msim_set_username_cb(PurpleConnection *gc)
878 g_return_if_fail(gc != NULL);
879 purple_debug_info("msim","Set username\n");
880 purple_request_input(gc, _("MySpaceIM - Please Set a Username"),
881 _("Please enter a username to check its availability:"),
882 NULL,
883 "", FALSE, FALSE, NULL,
884 _("OK"), G_CALLBACK(msim_check_username_availability_cb),
885 _("Cancel"), G_CALLBACK(msim_do_not_set_username_cb),
886 purple_connection_get_account(gc),
887 NULL,
888 NULL,
889 gc);