comparison libpurple/protocols/myspace/user.c @ 25005:401f548e3544

propagate from branch 'im.pidgin.pidgin' (head df6eba32e5b6b34d7483cbfb7e9f2e4c836ac35f) to branch 'org.darkrain42.pidgin.buddy-add' (head 6831808999a270f8c1a128c7430a73d3dc0bfae2)
author Paul Aurich <paul@darkrain42.org>
date Sun, 21 Dec 2008 18:32:37 +0000
parents 125cac3e24ee 22fd7467f0cc
children ae544623840b
comparison
equal deleted inserted replaced
24509:125cac3e24ee 25005:401f548e3544
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
18 */ 18 */
19 19
20 #include "myspace.h" 20 #include "myspace.h"
21 21
22 static void msim_store_user_info_each(const gchar *key_str, gchar *value_str, MsimUser *user); 22 static void msim_check_username_availability_cb(PurpleConnection *gc, const char *username_to_check);
23 static gchar *msim_format_now_playing(const gchar *band, const gchar *song); 23
24 static void msim_downloaded_buddy_icon(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text,
25 gsize len, const gchar *error_message);
26
27 /* Callbacks for setting the username bit */
28 static void msim_check_username_availability_cb(PurpleConnection *gc, const char *value);
29 static void msim_username_is_available_cb(MsimSession *session, MsimMessage *userinfo, gpointer data);
30 static void msim_set_username_confirmed_cb(PurpleConnection *gc);
31 static void msim_username_is_set_cb(MsimSession *session, MsimMessage *userinfo, gpointer data);
32 static void msim_set_username(MsimSession *session, const gchar *username,
33 MSIM_USER_LOOKUP_CB cb, gpointer data);
34 static char *msim_username_to_set; 24 static char *msim_username_to_set;
35 25
36 /** Format the "now playing" indicator, showing the artist and song. 26 /**
27 * Format the "now playing" indicator, showing the artist and song.
28 *
37 * @return Return a new string (must be g_free()'d), or NULL. 29 * @return Return a new string (must be g_free()'d), or NULL.
38 */ 30 */
39 static gchar * 31 static gchar *
40 msim_format_now_playing(const gchar *band, const gchar *song) 32 msim_format_now_playing(const gchar *band, const gchar *song)
41 { 33 {
46 } else { 38 } else {
47 return NULL; 39 return NULL;
48 } 40 }
49 } 41 }
50 42
51 /** Get the MsimUser from a PurpleBuddy, optionally creating it if needed. */ 43 /**
44 * Get the MsimUser from a PurpleBuddy, optionally creating it if needed.
45 */
52 MsimUser * 46 MsimUser *
53 msim_get_user_from_buddy(PurpleBuddy *buddy, gboolean create) 47 msim_get_user_from_buddy(PurpleBuddy *buddy, gboolean create)
54 { 48 {
55 MsimUser *user; 49 MsimUser *user;
56 50
57 g_return_val_if_fail(buddy != NULL, NULL); 51 if (!buddy) {
52 return NULL;
53 }
58 54
59 if (create && !buddy->proto_data) { 55 if (create && !buddy->proto_data) {
60 /* No MsimUser for this buddy; make one. */ 56 /* No MsimUser for this buddy; make one. */
61 57
62 /* TODO: where is this freed? */ 58 /* TODO: where is this freed? */
63 user = g_new0(MsimUser, 1); 59 user = g_new0(MsimUser, 1);
64 user->buddy = buddy; 60 user->buddy = buddy;
61 user->id = purple_blist_node_get_int(&buddy->node, "UserID");
65 buddy->proto_data = (gpointer)user; 62 buddy->proto_data = (gpointer)user;
66 } else { 63 } else {
67 user = (MsimUser *)(buddy->proto_data); 64 user = (MsimUser *)(buddy->proto_data);
68 } 65 }
69 66
70 return user; 67 return user;
71 } 68 }
72 69
73 /** Find and return an MsimUser * representing a user on the buddy list, or NULL. */ 70 /**
71 * Find and return an MsimUser * representing a user on the buddy list, or NULL.
72 */
74 MsimUser * 73 MsimUser *
75 msim_find_user(MsimSession *session, const gchar *username) 74 msim_find_user(MsimSession *session, const gchar *username)
76 { 75 {
77 PurpleBuddy *buddy; 76 PurpleBuddy *buddy;
78 MsimUser *user; 77 MsimUser *user;
85 user = msim_get_user_from_buddy(buddy, TRUE); 84 user = msim_get_user_from_buddy(buddy, TRUE);
86 85
87 return user; 86 return user;
88 } 87 }
89 88
90 /** Append user information to a PurpleNotifyUserInfo, given an MsimUser. 89 /**
90 * Append user information to a PurpleNotifyUserInfo, given an MsimUser.
91 * Used by msim_tooltip_text() and msim_get_info_cb() to show a user's profile. 91 * Used by msim_tooltip_text() and msim_get_info_cb() to show a user's profile.
92 */ 92 */
93 void 93 void
94 msim_append_user_info(MsimSession *session, PurpleNotifyUserInfo *user_info, MsimUser *user, gboolean full) 94 msim_append_user_info(MsimSession *session, PurpleNotifyUserInfo *user_info, MsimUser *user, gboolean full)
95 { 95 {
96 PurplePresence *presence; 96 PurplePresence *presence;
97 gchar *str; 97 gchar *str;
98 guint uid;
99 guint cv; 98 guint cv;
100 99
101 /* Useful to identify the account the tooltip refers to. 100 /* Useful to identify the account the tooltip refers to.
102 * Other prpls show this. */ 101 * Other prpls show this. */
103 if (user->username) { 102 if (user->username) {
104 purple_notify_user_info_add_pair(user_info, _("User"), user->username); 103 purple_notify_user_info_add_pair(user_info, _("User"), user->username);
105 } 104 }
106
107 uid = purple_blist_node_get_int(&user->buddy->node, "UserID");
108
109 if (full) {
110 /* TODO: link to username, if available */
111 if (uid) {
112 char *profile = g_strdup_printf("<a href=\"http://myspace.com/%d\">http://myspace.com/%d</a>",
113 uid, uid);
114 purple_notify_user_info_add_pair(user_info, _("Profile"), profile);
115 g_free(profile);
116 }
117 }
118
119 105
120 /* a/s/l...the vitals */ 106 /* a/s/l...the vitals */
121 if (user->age) { 107 if (user->age) {
122 char age[16]; 108 char age[16];
123 g_snprintf(age, sizeof(age), "%d", user->age); 109 g_snprintf(age, sizeof(age), "%d", user->age);
135 /* Other information */ 121 /* Other information */
136 if (user->headline && *user->headline) { 122 if (user->headline && *user->headline) {
137 purple_notify_user_info_add_pair(user_info, _("Headline"), user->headline); 123 purple_notify_user_info_add_pair(user_info, _("Headline"), user->headline);
138 } 124 }
139 125
140 presence = purple_buddy_get_presence(user->buddy); 126 if (user->buddy != NULL) {
141 127 presence = purple_buddy_get_presence(user->buddy);
142 if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) { 128
143 PurpleStatus *status; 129 if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
144 const char *artist, *title; 130 PurpleStatus *status;
145 131 const char *artist, *title;
146 status = purple_presence_get_status(presence, "tune"); 132
147 title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE); 133 status = purple_presence_get_status(presence, "tune");
148 artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST); 134 title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE);
149 135 artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST);
150 str = msim_format_now_playing(artist, title); 136
151 if (str && *str) { 137 str = msim_format_now_playing(artist, title);
152 purple_notify_user_info_add_pair(user_info, _("Song"), str); 138 if (str && *str) {
153 } 139 purple_notify_user_info_add_pair(user_info, _("Song"), str);
154 g_free(str); 140 }
141 g_free(str);
142 }
155 } 143 }
156 144
157 /* Note: total friends only available if looked up by uid, not username. */ 145 /* Note: total friends only available if looked up by uid, not username. */
158 if (user->total_friends) { 146 if (user->total_friends) {
159 char friends[16]; 147 char friends[16];
177 } 165 }
178 if (client && *client) 166 if (client && *client)
179 purple_notify_user_info_add_pair(user_info, _("Client Version"), client); 167 purple_notify_user_info_add_pair(user_info, _("Client Version"), client);
180 g_free(client); 168 g_free(client);
181 } 169 }
182 } 170
183 171 if (full && user->id) {
184 /** Set the currently playing song artist and or title. 172 /* TODO: link to username, if available */
173 char *profile;
174 purple_notify_user_info_add_section_break(user_info);
175 if (user->buddy != NULL)
176 profile = g_strdup_printf("<a href=\"http://myspace.com/%s\">%s</a>",
177 purple_buddy_get_name(user->buddy), _("View web profile"));
178 else
179 profile = g_strdup_printf("<a href=\"http://myspace.com/%d\">%s</a>",
180 user->id, _("View web profile"));
181 purple_notify_user_info_add_pair(user_info, NULL, profile);
182 g_free(profile);
183 }
184 }
185
186 /**
187 * Callback for when a buddy icon finished being downloaded.
188 */
189 static void
190 msim_downloaded_buddy_icon(PurpleUtilFetchUrlData *url_data,
191 gpointer user_data,
192 const gchar *url_text,
193 gsize len,
194 const gchar *error_message)
195 {
196 MsimUser *user;
197
198 user = (MsimUser *)user_data;
199
200 purple_debug_info("msim_downloaded_buddy_icon",
201 "Downloaded %" G_GSIZE_FORMAT " bytes\n", len);
202
203 if (!url_text) {
204 purple_debug_info("msim_downloaded_buddy_icon",
205 "failed to download icon for %s",
206 user->buddy->name);
207 return;
208 }
209
210 purple_buddy_icons_set_for_user(user->buddy->account,
211 user->buddy->name,
212 g_memdup((gchar *)url_text, len), len,
213 /* Use URL itself as buddy icon "checksum" (TODO: ETag) */
214 user->image_url); /* checksum */
215 }
216
217 /**
218 * Set the currently playing song artist and or title.
185 * 219 *
186 * @param user User associated with the now playing information. 220 * @param user User associated with the now playing information.
187 * 221 *
188 * @param new_artist New artist to set, or NULL/empty to not change artist. 222 * @param new_artist New artist to set, or NULL/empty to not change artist.
189 * 223 *
197 static void msim_set_artist_or_title(MsimUser *user, const char *new_artist, const char *new_title) 231 static void msim_set_artist_or_title(MsimUser *user, const char *new_artist, const char *new_title)
198 { 232 {
199 PurplePresence *presence; 233 PurplePresence *presence;
200 const char *prev_artist, *prev_title; 234 const char *prev_artist, *prev_title;
201 235
236 if (user->buddy == NULL)
237 /* User not on buddy list so nothing to do */
238 return;
239
202 prev_artist = NULL; 240 prev_artist = NULL;
203 prev_title = NULL; 241 prev_title = NULL;
204 242
205 if (new_artist && !strlen(new_artist)) 243 if (new_artist && !*new_artist)
206 new_artist = NULL; 244 new_artist = NULL;
207 if (new_title && !strlen(new_title)) 245 if (new_title && !*new_title)
208 new_title = NULL; 246 new_title = NULL;
209 247
210 if (!new_artist && !new_title) { 248 if (!new_artist && !new_title) {
211 purple_prpl_got_user_status_deactive(user->buddy->account, user->buddy->name, "tune"); 249 purple_prpl_got_user_status_deactive(user->buddy->account, user->buddy->name, "tune");
212 return; 250 return;
214 252
215 presence = purple_buddy_get_presence(user->buddy); 253 presence = purple_buddy_get_presence(user->buddy);
216 254
217 if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) { 255 if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
218 PurpleStatus *status; 256 PurpleStatus *status;
219 257
220 status = purple_presence_get_status(presence, "tune"); 258 status = purple_presence_get_status(presence, "tune");
221 prev_title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE); 259 prev_title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE);
222 prev_artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST); 260 prev_artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST);
223 } 261 }
224 262
225 if (!new_artist) 263 if (!new_artist)
226 new_artist = prev_artist; 264 new_artist = prev_artist;
227 265
228 if (!new_title) 266 if (!new_title)
229 new_title = prev_title; 267 new_title = prev_title;
230 268
231 purple_prpl_got_user_status(user->buddy->account, user->buddy->name, "tune", 269 purple_prpl_got_user_status(user->buddy->account, user->buddy->name, "tune",
232 PURPLE_TUNE_TITLE, new_title, 270 PURPLE_TUNE_TITLE, new_title,
233 PURPLE_TUNE_ARTIST, new_artist, 271 PURPLE_TUNE_ARTIST, new_artist,
234 NULL); 272 NULL);
235 } 273 }
236 274
237 /** Store a field of information about a buddy. 275 /**
276 * Store a field of information about a buddy.
238 * 277 *
239 * @param key_str Key to store. 278 * @param key_str Key to store.
240 * @param value_str Value string, either user takes ownership of this string 279 * @param value_str Value string, either user takes ownership of this string
241 * or it is freed if MsimUser doesn't store the string. 280 * or it is freed if MsimUser doesn't store the string.
242 * @param user User to store data in. Existing data will be replaced. 281 * @param user User to store data in. Existing data will be replaced.
243 * */ 282 */
244 void 283 static void
245 msim_store_user_info_each(const gchar *key_str, gchar *value_str, MsimUser *user) 284 msim_store_user_info_each(const gchar *key_str, gchar *value_str, MsimUser *user)
246 { 285 {
247 if (g_str_equal(key_str, "UserID") || g_str_equal(key_str, "ContactID")) { 286 if (g_str_equal(key_str, "UserID") || g_str_equal(key_str, "ContactID")) {
248 /* Save to buddy list, if it exists, for quick cached uid lookup with msim_uid2username_from_blist(). */ 287 /* Save to buddy list, if it exists, for quick cached uid lookup with msim_uid2username_from_blist(). */
288 user->id = atol(value_str);
289 g_free(value_str);
249 if (user->buddy) 290 if (user->buddy)
250 { 291 {
251 purple_debug_info("msim", "associating uid %s with username %s\n", key_str, user->buddy->name); 292 purple_debug_info("msim", "associating uid %s with username %s\n", key_str, user->buddy->name);
252 purple_blist_node_set_int(&user->buddy->node, "UserID", atol(value_str)); 293 purple_blist_node_set_int(&user->buddy->node, "UserID", user->id);
253 } 294 }
254 /* Need to store in MsimUser, too? What if not on blist? */ 295 /* Need to store in MsimUser, too? What if not on blist? */
255 } else if (g_str_equal(key_str, "Age")) { 296 } else if (g_str_equal(key_str, "Age")) {
256 user->age = atol(value_str); 297 user->age = atol(value_str);
257 g_free(value_str); 298 g_free(value_str);
261 } else if (g_str_equal(key_str, "Location")) { 302 } else if (g_str_equal(key_str, "Location")) {
262 g_free(user->location); 303 g_free(user->location);
263 user->location = value_str; 304 user->location = value_str;
264 } else if (g_str_equal(key_str, "TotalFriends")) { 305 } else if (g_str_equal(key_str, "TotalFriends")) {
265 user->total_friends = atol(value_str); 306 user->total_friends = atol(value_str);
307 g_free(value_str);
266 } else if (g_str_equal(key_str, "DisplayName")) { 308 } else if (g_str_equal(key_str, "DisplayName")) {
267 g_free(user->display_name); 309 g_free(user->display_name);
268 user->display_name = value_str; 310 user->display_name = value_str;
269 } else if (g_str_equal(key_str, "BandName")) { 311 } else if (g_str_equal(key_str, "BandName")) {
270 msim_set_artist_or_title(user, value_str, NULL); 312 msim_set_artist_or_title(user, value_str, NULL);
313 g_free(value_str);
271 } else if (g_str_equal(key_str, "SongName")) { 314 } else if (g_str_equal(key_str, "SongName")) {
272 msim_set_artist_or_title(user, NULL, value_str); 315 msim_set_artist_or_title(user, NULL, value_str);
316 g_free(value_str);
273 } else if (g_str_equal(key_str, "UserName") || g_str_equal(key_str, "IMName") || g_str_equal(key_str, "NickName")) { 317 } else if (g_str_equal(key_str, "UserName") || g_str_equal(key_str, "IMName") || g_str_equal(key_str, "NickName")) {
274 /* Ignore because PurpleBuddy knows this already */ 318 /* Ignore because PurpleBuddy knows this already */
275 g_free(value_str); 319 g_free(value_str);
276 } else if (g_str_equal(key_str, "ImageURL") || g_str_equal(key_str, "AvatarURL")) { 320 } else if (g_str_equal(key_str, "ImageURL") || g_str_equal(key_str, "AvatarURL")) {
277 const gchar *previous_url; 321 const gchar *previous_url;
278 322
279 if (user->temporary_user) { 323 if (user->temporary_user) {
280 /* This user will be destroyed soon; don't try to look up its image or avatar, 324 /* This user will be destroyed soon; don't try to look up its image or avatar,
281 * since that won't return immediately and we will end up accessing freed data. 325 * since that won't return immediately and we will end up accessing freed data.
282 */ 326 */
283 g_free(value_str); 327 g_free(value_str);
284 return; 328 return;
285 } 329 }
286 330
287 if (user->temporary_user) { 331 if (user->temporary_user) {
288 /* This user will be destroyed soon; don't try to look up its image or avatar, 332 /* This user will be destroyed soon; don't try to look up its image or avatar,
289 * since that won't return immediately and we will end up accessing freed data. 333 * since that won't return immediately and we will end up accessing freed data.
290 */ 334 */
291 g_free(value_str); 335 g_free(value_str);
292 return; 336 return;
293 } 337 }
331 375
332 g_free(msg); 376 g_free(msg);
333 } 377 }
334 } 378 }
335 379
336 /** Save buddy information to the buddy list from a user info reply message. 380 /**
381 * Save buddy information to the buddy list from a user info reply message.
337 * 382 *
338 * @param session 383 * @param session
339 * @param msg The user information reply, with any amount of information. 384 * @param msg The user information reply, with any amount of information.
340 * @param user The structure to save to, or NULL to save in PurpleBuddy->proto_data. 385 * @param user The structure to save to, or NULL to save in PurpleBuddy->proto_data.
341 * 386 *
343 * information (UserID) is stored in the blist node of the buddy list (and 388 * information (UserID) is stored in the blist node of the buddy list (and
344 * ends up in blist.xml, persisted to disk) if it exists. 389 * ends up in blist.xml, persisted to disk) if it exists.
345 * 390 *
346 * If the function has no buddy information, this function 391 * If the function has no buddy information, this function
347 * is a no-op (and returns FALSE). 392 * is a no-op (and returns FALSE).
348 * 393 */
349 */ 394 gboolean
350 gboolean 395 msim_store_user_info(MsimSession *session, const MsimMessage *msg, MsimUser *user)
351 msim_store_user_info(MsimSession *session, MsimMessage *msg, MsimUser *user)
352 { 396 {
353 gchar *username; 397 gchar *username;
354 MsimMessage *body, *body_node; 398 MsimMessage *body, *body_node;
355 399
356 g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); 400 g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE);
359 body = msim_msg_get_dictionary(msg, "body"); 403 body = msim_msg_get_dictionary(msg, "body");
360 if (!body) { 404 if (!body) {
361 return FALSE; 405 return FALSE;
362 } 406 }
363 407
408 if (msim_msg_get_integer(msg, "dsn") == MG_OWN_IM_INFO_DSN &&
409 msim_msg_get_integer(msg, "lid") == MG_OWN_IM_INFO_LID) {
410 /*
411 * Some of this info will be available on the buddy list if the
412 * has themselves as their own buddy.
413 *
414 * Much of the info is already available in MsimSession,
415 * stored in msim_we_are_logged_on().
416 */
417 gchar *tmpstr;
418
419 tmpstr = msim_msg_get_string(body, "ShowOnlyToList");
420 if (tmpstr != NULL) {
421 session->show_only_to_list = g_str_equal(tmpstr, "True");
422 g_free(tmpstr);
423 }
424
425 session->privacy_mode = msim_msg_get_integer(body, "PrivacyMode");
426 session->offline_message_mode = msim_msg_get_integer(body, "OfflineMessageMode");
427
428 msim_send(session,
429 "blocklist", MSIM_TYPE_BOOLEAN, TRUE,
430 "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
431 "idlist", MSIM_TYPE_STRING,
432 g_strdup_printf("w%d|c%d",
433 session->show_only_to_list ? 1 : 0,
434 session->privacy_mode),
435 NULL);
436 } else if (msim_msg_get_integer(msg, "dsn") == MG_OWN_MYSPACE_INFO_DSN &&
437 msim_msg_get_integer(msg, "lid") == MG_OWN_MYSPACE_INFO_LID) {
438 /* TODO: same as above, but for MySpace info. */
439 }
440
364 username = msim_msg_get_string(body, "UserName"); 441 username = msim_msg_get_string(body, "UserName");
365 442
366 if (!username) { 443 if (!username) {
367 purple_debug_info("msim", 444 purple_debug_info("msim",
368 "msim_process_reply: not caching body, no UserName\n"); 445 "msim_process_reply: not caching body, no UserName\n");
369 msim_msg_free(body); 446 msim_msg_free(body);
370 g_free(username); 447 g_free(username);
371 return FALSE; 448 return FALSE;
372 } 449 }
373 450
374 /* Null user = find and store in PurpleBuddy's proto_data */ 451 /* Null user = find and store in PurpleBuddy's proto_data */
375 if (!user) { 452 if (!user) {
376 user = msim_find_user(session, username); 453 user = msim_find_user(session, username);
377 if (!user) { 454 if (!user) {
378 msim_msg_free(body); 455 msim_msg_free(body);
380 return FALSE; 457 return FALSE;
381 } 458 }
382 } 459 }
383 460
384 /* TODO: make looping over MsimMessage's easier. */ 461 /* TODO: make looping over MsimMessage's easier. */
385 for (body_node = body; 462 for (body_node = body;
386 body_node != NULL; 463 body_node != NULL;
387 body_node = msim_msg_get_next_element_node(body_node)) 464 body_node = msim_msg_get_next_element_node(body_node))
388 { 465 {
389 const gchar *key_str; 466 const gchar *key_str;
390 gchar *value_str; 467 gchar *value_str;
391 MsimMessageElement *elem; 468 MsimMessageElement *elem;
395 472
396 value_str = msim_msg_get_string_from_element(elem); 473 value_str = msim_msg_get_string_from_element(elem);
397 msim_store_user_info_each(key_str, value_str, user); 474 msim_store_user_info_each(key_str, value_str, user);
398 } 475 }
399 476
400 if (msim_msg_get_integer(msg, "dsn") == MG_OWN_IM_INFO_DSN &&
401 msim_msg_get_integer(msg, "lid") == MG_OWN_IM_INFO_LID) {
402 /* TODO: do something with our own IM info, if we need it for some
403 * specific purpose. Otherwise it is available on the buddy list,
404 * if the user has themselves as their own buddy.
405 *
406 * However, much of the info is already available in MsimSession,
407 * stored in msim_we_are_logged_on(). */
408 } else if (msim_msg_get_integer(msg, "dsn") == MG_OWN_MYSPACE_INFO_DSN &&
409 msim_msg_get_integer(msg, "lid") == MG_OWN_MYSPACE_INFO_LID) {
410 /* TODO: same as above, but for MySpace info. */
411 }
412
413 msim_msg_free(body); 477 msim_msg_free(body);
414 g_free(username); 478 g_free(username);
415 479
416 return TRUE; 480 return TRUE;
481 }
482
483 #if 0
484 /**
485 * Return whether a given username is syntactically valid.
486 * Note: does not actually check that the user exists.
487 */
488 static gboolean
489 msim_is_valid_username(const gchar *user)
490 {
491 return !msim_is_userid(user) && /* Not all numeric */
492 strlen(user) <= MSIM_MAX_USERNAME_LENGTH
493 && strspn(user, "0123456789"
494 "abcdefghijklmnopqrstuvwxyz"
495 "_"
496 "ABCDEFGHIJKLMNOPQRSTUVWXYZ") == strlen(user);
497 }
498 #endif
499
500 /**
501 * Check if a string is a userid (all numeric).
502 *
503 * @param user The user id, email, or name.
504 *
505 * @return TRUE if is userid, FALSE if not.
506 */
507 gboolean
508 msim_is_userid(const gchar *user)
509 {
510 g_return_val_if_fail(user != NULL, FALSE);
511
512 return strspn(user, "0123456789") == strlen(user);
513 }
514
515 /**
516 * Check if a string is an email address (contains an @).
517 *
518 * @param user The user id, email, or name.
519 *
520 * @return TRUE if is an email, FALSE if not.
521 *
522 * This function is not intended to be used as a generic
523 * means of validating email addresses, but to distinguish
524 * between a user represented by an email address from
525 * other forms of identification.
526 */
527 static gboolean
528 msim_is_email(const gchar *user)
529 {
530 g_return_val_if_fail(user != NULL, FALSE);
531
532 return strchr(user, '@') != NULL;
417 } 533 }
418 534
419 /** 535 /**
420 * Asynchronously lookup user information, calling callback when receive result. 536 * Asynchronously lookup user information, calling callback when receive result.
421 * 537 *
423 * @param user The user id, email address, or username. Not freed. 539 * @param user The user id, email address, or username. Not freed.
424 * @param cb Callback, called with user information when available. 540 * @param cb Callback, called with user information when available.
425 * @param data An arbitray data pointer passed to the callback. 541 * @param data An arbitray data pointer passed to the callback.
426 */ 542 */
427 /* TODO: change to not use callbacks */ 543 /* TODO: change to not use callbacks */
428 void 544 void
429 msim_lookup_user(MsimSession *session, const gchar *user, MSIM_USER_LOOKUP_CB cb, gpointer data) 545 msim_lookup_user(MsimSession *session, const gchar *user, MSIM_USER_LOOKUP_CB cb, gpointer data)
430 { 546 {
431 MsimMessage *body; 547 MsimMessage *body;
432 gchar *field_name; 548 gchar *field_name;
433 guint rid, cmd, dsn, lid; 549 guint rid, cmd, dsn, lid;
438 /*g_return_if_fail(cb != NULL);*/ 554 /*g_return_if_fail(cb != NULL);*/
439 555
440 purple_debug_info("msim", "msim_lookup_userid: " 556 purple_debug_info("msim", "msim_lookup_userid: "
441 "asynchronously looking up <%s>\n", user); 557 "asynchronously looking up <%s>\n", user);
442 558
443 msim_msg_dump("msim_lookup_user: data=%s\n", (MsimMessage *)data);
444
445 /* Setup callback. Response will be associated with request using 'rid'. */ 559 /* Setup callback. Response will be associated with request using 'rid'. */
446 rid = msim_new_reply_callback(session, cb, data); 560 rid = msim_new_reply_callback(session, cb, data);
447 561
448 /* Send request */ 562 /* Send request */
449 563
450 cmd = MSIM_CMD_GET; 564 cmd = MSIM_CMD_GET;
451 565
452 if (msim_is_userid(user)) { 566 if (msim_is_userid(user)) {
453 field_name = "UserID"; 567 field_name = "UserID";
454 dsn = MG_MYSPACE_INFO_BY_ID_DSN; 568 dsn = MG_MYSPACE_INFO_BY_ID_DSN;
455 lid = MG_MYSPACE_INFO_BY_ID_LID; 569 lid = MG_MYSPACE_INFO_BY_ID_LID;
456 } else if (msim_is_email(user)) { 570 } else if (msim_is_email(user)) {
457 field_name = "Email"; 571 field_name = "Email";
458 dsn = MG_MYSPACE_INFO_BY_STRING_DSN; 572 dsn = MG_MYSPACE_INFO_BY_STRING_DSN;
459 lid = MG_MYSPACE_INFO_BY_STRING_LID; 573 lid = MG_MYSPACE_INFO_BY_STRING_LID;
460 } else { 574 } else {
475 "uid", MSIM_TYPE_INTEGER, session->userid, 589 "uid", MSIM_TYPE_INTEGER, session->userid,
476 "lid", MSIM_TYPE_INTEGER, lid, 590 "lid", MSIM_TYPE_INTEGER, lid,
477 "rid", MSIM_TYPE_INTEGER, rid, 591 "rid", MSIM_TYPE_INTEGER, rid,
478 "body", MSIM_TYPE_DICTIONARY, body, 592 "body", MSIM_TYPE_DICTIONARY, body,
479 NULL)); 593 NULL));
480 } 594 }
481 595
482 596 /**
483 /** 597 * Called after username is set.
484 * Check if a string is a userid (all numeric). 598 */
485 * 599 static void msim_username_is_set_cb(MsimSession *session, const MsimMessage *userinfo, gpointer data)
486 * @param user The user id, email, or name. 600 {
487 * 601 gchar *username;
488 * @return TRUE if is userid, FALSE if not. 602 const gchar *errmsg;
489 */ 603 MsimMessage *body;
490 gboolean 604
491 msim_is_userid(const gchar *user) 605 guint rid;
492 { 606 gint cmd,dsn,uid,lid,code;
493 g_return_val_if_fail(user != NULL, FALSE); 607 /* \persistr\\cmd\258\dsn\9\uid\204084363\lid\14\rid\369\body\UserName=TheAlbinoRhino1.Code=0\final\ */
494 608
495 return strspn(user, "0123456789") == strlen(user); 609 purple_debug_info("msim","username_is_set made\n");
496 }
497
498 /** Return whether a given username is syntactically valid.
499 * Note: does not actually check that the user exists. */
500 gboolean
501 msim_is_valid_username(const gchar *user)
502 {
503 return !msim_is_userid(user) && /* Not all numeric */
504 strlen(user) <= MSIM_MAX_USERNAME_LENGTH
505 && strspn(user, "0123456789"
506 "abcdefghijklmnopqrstuvwxyz"
507 "_"
508 "ABCDEFGHIJKLMNOPQRSTUVWXYZ") == strlen(user);
509 }
510
511 /**
512 * Check if a string is an email address (contains an @).
513 *
514 * @param user The user id, email, or name.
515 *
516 * @return TRUE if is an email, FALSE if not.
517 *
518 * This function is not intended to be used as a generic
519 * means of validating email addresses, but to distinguish
520 * between a user represented by an email address from
521 * other forms of identification.
522 */
523 gboolean
524 msim_is_email(const gchar *user)
525 {
526 g_return_val_if_fail(user != NULL, FALSE);
527
528 return strchr(user, '@') != NULL;
529 }
530
531
532 /** Callback for when a buddy icon finished being downloaded. */
533 static void
534 msim_downloaded_buddy_icon(PurpleUtilFetchUrlData *url_data,
535 gpointer user_data,
536 const gchar *url_text,
537 gsize len,
538 const gchar *error_message)
539 {
540 MsimUser *user;
541
542 user = (MsimUser *)user_data;
543
544 purple_debug_info("msim_downloaded_buddy_icon",
545 "Downloaded %" G_GSIZE_FORMAT " bytes\n", len);
546
547 if (!url_text) {
548 purple_debug_info("msim_downloaded_buddy_icon",
549 "failed to download icon for %s",
550 user->buddy->name);
551 return;
552 }
553
554 purple_buddy_icons_set_for_user(user->buddy->account,
555 user->buddy->name,
556 g_memdup((gchar *)url_text, len), len,
557 /* Use URL itself as buddy icon "checksum" (TODO: ETag) */
558 user->image_url); /* checksum */
559 }
560
561 /***
562 * If they hit cancel or no at any point in the Setting Username process, we come here. *
563 * Currently.. We're safe letting them get by without setting it.. Unless we hear otherwise.. *
564 * So for now, give them a menu.. If this becomes an issue with the Official client.. boot them here */
565 void msim_do_not_set_username_cb(PurpleConnection *gc) {
566 purple_debug_info("msim", "Don't set username");
567
568 /* Protocol won't log in now without a username set.. Disconnect */
569 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("No username set"));
570 }
571
572 /** They've decided to set a username! Yay! */
573 void msim_set_username_cb(PurpleConnection *gc) {
574 g_return_if_fail(gc != NULL);
575 purple_debug_info("msim","Set username\n");
576 purple_request_input(gc, _("MySpaceIM - Please Set a Username"),
577 _("Please enter a username to check its availability:"),
578 NULL,
579 "", FALSE, FALSE, NULL,
580 _("OK"), G_CALLBACK(msim_check_username_availability_cb),
581 _("Cancel"), G_CALLBACK(msim_do_not_set_username_cb),
582 purple_connection_get_account(gc),
583 NULL,
584 NULL,
585 gc);
586 }
587
588 /** Once they've submitted their desired new username,
589 * check if it is available here. */
590 static void msim_check_username_availability_cb(PurpleConnection *gc, const char *username_to_check)
591 {
592 MsimMessage *user_msg;
593 MsimSession *session;
594
595 g_return_if_fail(gc != NULL);
596
597 session = (MsimSession *)gc->proto_data;
598 610
599 g_return_if_fail(MSIM_SESSION_VALID(session)); 611 g_return_if_fail(MSIM_SESSION_VALID(session));
600 612
601 purple_debug_info("msim_check_username_availability_cb", "Checking username: %s\n", username_to_check); 613 cmd = msim_msg_get_integer(userinfo, "cmd");
602 614 dsn = msim_msg_get_integer(userinfo, "dsn");
603 user_msg = msim_msg_new( 615 uid = msim_msg_get_integer(userinfo, "uid");
604 "user", MSIM_TYPE_STRING, g_strdup(username_to_check), 616 lid = msim_msg_get_integer(userinfo, "lid");
605 NULL);
606
607 /* 25 characters: letters, numbers, underscores */
608 /* TODO: VERIFY ABOVE */
609
610 /* \persist\1\sesskey\288500516\cmd\1\dsn\5\uid\204084363\lid\7\rid\367\body\UserName=Jaywalker\final\ */
611 /* Official client uses a standard lookup... So do we! */
612 msim_lookup_user(session, username_to_check, msim_username_is_available_cb, user_msg);
613 }
614
615 /** This is where we do a bit more than merely prompt the user.
616 * Now we have some real data to tell us the state of their requested username
617 * \persistr\\cmd\257\dsn\5\uid\204084363\lid\7\rid\367\body\UserName=TheAlbinoRhino1\final\ */
618 static void msim_username_is_available_cb(MsimSession *session, MsimMessage *userinfo, gpointer data)
619 {
620 MsimMessage *msg;
621 gchar *username;
622 MsimMessage *body;
623 gint userid;
624
625 purple_debug_info("msim_username_is_available_cb", "Look up username callback made\n");
626
627 msg = (MsimMessage *)data;
628 g_return_if_fail(MSIM_SESSION_VALID(session));
629 g_return_if_fail(msg != NULL);
630
631 username = msim_msg_get_string(msg, "user");
632 body = msim_msg_get_dictionary(userinfo, "body"); 617 body = msim_msg_get_dictionary(userinfo, "body");
618 /* XXX: Mark for translation */
619 errmsg = ("An error occurred while trying to set the username.\n"
620 "Please try again, or visit http://editprofile.myspace.com/index.cfm?"
621 "fuseaction=profile.username to set your username.");
633 622
634 if (!body) { 623 if (!body) {
635 purple_debug_info("msim_username_is_available_cb", "No body for %s?!\n", username); 624 purple_debug_info("msim_username_is_set_cb", "No body");
636 purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, 625 /* Error: No body! */
637 "An error occurred while trying to set the username.\n" 626 purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg);
638 "Please try again, or visit http://editprofile.myspace.com/index.cfm?" 627 }
639 "fuseaction=profile.username to set your username."); 628 username = msim_msg_get_string(body, "UserName");
640 return; 629 code = msim_msg_get_integer(body,"Code");
641 } 630
642
643 userid = msim_msg_get_integer(body, "UserID");
644
645 purple_debug_info("msim_username_is_available_cb", "Returned username is %s and userid is %d\n", username, userid);
646 msim_msg_free(body); 631 msim_msg_free(body);
647 msim_msg_free(msg); 632
648 633 purple_debug_info("msim_username_is_set_cb",
649 /* The response for a free username will ONLY have the UserName in it.. 634 "cmd = %d, dsn = %d, lid = %d, code = %d, username = %s\n",
650 * thus making UserID return 0 when we msg_get_integer it */ 635 cmd, dsn, lid, code, username);
651 if (userid == 0) { 636
652 /* This username is currently unused */ 637 if (cmd == (MSIM_CMD_BIT_REPLY | MSIM_CMD_PUT)
653 purple_debug_info("msim_username_is_available_cb", "Username available. Prompting to Confirm.\n"); 638 && dsn == MC_SET_USERNAME_DSN
654 msim_username_to_set = g_strdup(username); 639 && lid == MC_SET_USERNAME_LID)
655 g_free(username); 640 {
656 purple_request_yes_no(session->gc, 641 purple_debug_info("msim_username_is_set_cb", "Proper cmd,dsn,lid for username_is_set!\n");
657 _("MySpaceIM - Username Available"), 642 purple_debug_info("msim_username_is_set_cb", "Username Set with return code %d\n",code);
658 _("This username is available. Would you like to set it?"), 643 if (code == 0) {
659 _("ONCE SET, THIS CANNOT BE CHANGED!"), 644 /* Good! */
660 0, 645 session->username = username;
661 session->account, 646 msim_we_are_logged_on(session);
662 NULL, 647 } else {
663 NULL, 648 purple_debug_info("msim_username_is_set", "code is %d",code);
664 session->gc, 649 /* TODO: what to do here? */
665 G_CALLBACK(msim_set_username_confirmed_cb), 650 }
666 G_CALLBACK(msim_do_not_set_username_cb)); 651 } else if (cmd == (MSIM_CMD_BIT_REPLY | MSIM_CMD_GET)
652 && dsn == MG_MYSPACE_INFO_BY_STRING_DSN
653 && lid == MG_MYSPACE_INFO_BY_STRING_LID) {
654 /* Not quite done... ONE MORE STEP :) */
655 rid = msim_new_reply_callback(session, msim_username_is_set_cb, data);
656 body = msim_msg_new("UserName", MSIM_TYPE_STRING, g_strdup(username), NULL);
657 if (!msim_send(session, "persist", MSIM_TYPE_INTEGER, 1,
658 "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
659 "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_PUT,
660 "dsn", MSIM_TYPE_INTEGER, MC_SET_USERNAME_DSN,
661 "uid", MSIM_TYPE_INTEGER, session->userid,
662 "lid", MSIM_TYPE_INTEGER, MC_SET_USERNAME_LID,
663 "rid", MSIM_TYPE_INTEGER, rid,
664 "body", MSIM_TYPE_DICTIONARY, body,
665 NULL)) {
666 /* Error! */
667 /* Can't set... Disconnect */
668 purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg);
669 }
670
667 } else { 671 } else {
668 /* Looks like its in use or we have an invalid response */ 672 /* Error! */
669 purple_debug_info("msim_username_is_available_cb", "Username unavaiable. Prompting for new entry.\n"); 673 purple_debug_info("msim","username_is_set Error: Invalid cmd/dsn/lid combination");
670 purple_request_input(session->gc, _("MySpaceIM - Please Set a Username"), 674 purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg);
671 _("This username is unavailable."), 675 }
672 _("Please try another username:"),
673 "", FALSE, FALSE, NULL,
674 _("OK"), G_CALLBACK(msim_check_username_availability_cb),
675 _("Cancel"), G_CALLBACK(msim_do_not_set_username_cb),
676 session->account,
677 NULL,
678 NULL,
679 session->gc);
680 }
681 }
682
683 /* They've confirmed that username that was available, Lets make the call to set it */
684 static void msim_set_username_confirmed_cb(PurpleConnection *gc)
685 {
686 MsimMessage *user_msg;
687 MsimSession *session;
688
689 g_return_if_fail(gc != NULL);
690
691 session = (MsimSession *)gc->proto_data;
692
693 g_return_if_fail(MSIM_SESSION_VALID(session));
694
695
696 user_msg = msim_msg_new(
697 "user", MSIM_TYPE_STRING, g_strdup(msim_username_to_set),
698 NULL);
699
700 purple_debug_info("msim_set_username_confirmed_cb", "Setting username to %s\n", msim_username_to_set);
701
702 /* Sets our username... keep your fingers crossed :) */
703 msim_set_username(session, msim_username_to_set, msim_username_is_set_cb, user_msg);
704 g_free(msim_username_to_set);
705 } 676 }
706 677
707 /** 678 /**
708 * Asynchronously set new username, calling callback when receive result. 679 * Asynchronously set new username, calling callback when receive result.
709 * 680 *
710 * @param session 681 * @param session
711 * @param username The username we're setting for ourselves. Not freed. 682 * @param username The username we're setting for ourselves. Not freed.
712 * @param cb Callback, called with user information when available. 683 * @param cb Callback, called with user information when available.
713 * @param data An arbitray data pointer passed to the callback. 684 * @param data An arbitray data pointer passed to the callback.
714 */ 685 */
715 static void 686 static void
716 msim_set_username(MsimSession *session, const gchar *username, 687 msim_set_username(MsimSession *session, const gchar *username,
717 MSIM_USER_LOOKUP_CB cb, gpointer data) 688 MSIM_USER_LOOKUP_CB cb, gpointer data)
718 { 689 {
719 MsimMessage *body; 690 MsimMessage *body;
720 guint rid; 691 guint rid;
723 g_return_if_fail(username != NULL); 694 g_return_if_fail(username != NULL);
724 g_return_if_fail(cb != NULL); 695 g_return_if_fail(cb != NULL);
725 696
726 purple_debug_info("msim", "msim_set_username: " 697 purple_debug_info("msim", "msim_set_username: "
727 "Setting username %s\n", username); 698 "Setting username %s\n", username);
728
729 msim_msg_dump("msim_set_username: data=%s\n", (MsimMessage *)data);
730 699
731 /* Setup callback. Response will be associated with request using 'rid'. */ 700 /* Setup callback. Response will be associated with request using 'rid'. */
732 rid = msim_new_reply_callback(session, cb, data); 701 rid = msim_new_reply_callback(session, cb, data);
733 702
734 /* TODO: I dont know if the ContactType is -/ALWAYS/- 1 */ 703 /* TODO: I dont know if the ContactType is -/ALWAYS/- 1 */
754 "rid", MSIM_TYPE_INTEGER, rid, 723 "rid", MSIM_TYPE_INTEGER, rid,
755 "body", MSIM_TYPE_DICTIONARY, body, 724 "body", MSIM_TYPE_DICTIONARY, body,
756 NULL)); 725 NULL));
757 } 726 }
758 727
759 /** Called after username is set. */ 728 /**
760 static void msim_username_is_set_cb(MsimSession *session, MsimMessage *userinfo, gpointer data) 729 * They've confirmed that username that was available, Lets make the call to set it
761 { 730 */
762 gchar *username, *errmsg; 731 static void msim_set_username_confirmed_cb(PurpleConnection *gc)
732 {
733 MsimMessage *user_msg;
734 MsimSession *session;
735
736 g_return_if_fail(gc != NULL);
737
738 session = (MsimSession *)gc->proto_data;
739
740 g_return_if_fail(MSIM_SESSION_VALID(session));
741
742
743 user_msg = msim_msg_new(
744 "user", MSIM_TYPE_STRING, g_strdup(msim_username_to_set),
745 NULL);
746
747 purple_debug_info("msim_set_username_confirmed_cb", "Setting username to %s\n", msim_username_to_set);
748
749 /* Sets our username... keep your fingers crossed :) */
750 msim_set_username(session, msim_username_to_set, msim_username_is_set_cb, user_msg);
751 g_free(msim_username_to_set);
752 }
753
754 /**
755 * This is where we do a bit more than merely prompt the user.
756 * Now we have some real data to tell us the state of their requested username
757 * \persistr\\cmd\257\dsn\5\uid\204084363\lid\7\rid\367\body\UserName=TheAlbinoRhino1\final\
758 */
759 static void msim_username_is_available_cb(MsimSession *session, const MsimMessage *userinfo, gpointer data)
760 {
761 MsimMessage *msg;
762 gchar *username;
763 MsimMessage *body; 763 MsimMessage *body;
764 764 gint userid;
765 guint rid; 765
766 gint cmd,dsn,uid,lid,code; 766 purple_debug_info("msim_username_is_available_cb", "Look up username callback made\n");
767 /* \persistr\\cmd\258\dsn\9\uid\204084363\lid\14\rid\369\body\UserName=TheAlbinoRhino1.Code=0\final\ */ 767
768 768 msg = (MsimMessage *)data;
769 purple_debug_info("msim","username_is_set made\n");
770
771 g_return_if_fail(MSIM_SESSION_VALID(session)); 769 g_return_if_fail(MSIM_SESSION_VALID(session));
772 770 g_return_if_fail(msg != NULL);
773 771
774 msim_msg_dump("username_is_set message is: %s\n", userinfo); 772 username = msim_msg_get_string(msg, "user");
775 cmd = msim_msg_get_integer(userinfo, "cmd");
776 dsn = msim_msg_get_integer(userinfo, "dsn");
777 uid = msim_msg_get_integer(userinfo, "uid");
778 lid = msim_msg_get_integer(userinfo, "lid");
779 body = msim_msg_get_dictionary(userinfo, "body"); 773 body = msim_msg_get_dictionary(userinfo, "body");
780 errmsg = g_strdup("An error occurred while trying to set the username.\n" 774
781 "Please try again, or visit http://editprofile.myspace.com/index.cfm?"
782 "fuseaction=profile.username to set your username.");
783
784 if (!body) { 775 if (!body) {
785 purple_debug_info("msim_username_is_set_cb", "No body"); 776 purple_debug_info("msim_username_is_available_cb", "No body for %s?!\n", username);
786 /* Error: No body! */ 777 purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
787 purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg); 778 "An error occurred while trying to set the username.\n"
788 } 779 "Please try again, or visit http://editprofile.myspace.com/index.cfm?"
789 username = msim_msg_get_string(body, "UserName"); 780 "fuseaction=profile.username to set your username.");
790 code = msim_msg_get_integer(body,"Code"); 781 return;
791 782 }
783
784 userid = msim_msg_get_integer(body, "UserID");
785
786 purple_debug_info("msim_username_is_available_cb", "Returned username is %s and userid is %d\n", username, userid);
792 msim_msg_free(body); 787 msim_msg_free(body);
793 788 msim_msg_free(msg);
794 purple_debug_info("msim_username_is_set_cb", 789
795 "cmd = %d, dsn = %d, lid = %d, code = %d, username = %s\n", 790 /* The response for a free username will ONLY have the UserName in it..
796 cmd, dsn, lid, code, username); 791 * thus making UserID return 0 when we msg_get_integer it */
797 792 if (userid == 0) {
798 if (cmd == (MSIM_CMD_BIT_REPLY | MSIM_CMD_PUT) 793 /* This username is currently unused */
799 && dsn == MC_SET_USERNAME_DSN 794 purple_debug_info("msim_username_is_available_cb", "Username available. Prompting to Confirm.\n");
800 && lid == MC_SET_USERNAME_LID) { 795 msim_username_to_set = g_strdup(username);
801 purple_debug_info("msim_username_is_set_cb", "Proper cmd,dsn,lid for username_is_set!\n"); 796 g_free(username);
802 purple_debug_info("msim_username_is_set_cb", "Username Set with return code %d\n",code); 797 purple_request_yes_no(session->gc,
803 if (code == 0) { 798 _("MySpaceIM - Username Available"),
804 /* Good! */ 799 _("This username is available. Would you like to set it?"),
805 session->username = username; 800 _("ONCE SET, THIS CANNOT BE CHANGED!"),
806 msim_we_are_logged_on(session); 801 0,
807 } else { 802 session->account,
808 purple_debug_info("msim_username_is_set", "code is %d",code); 803 NULL,
809 /* TODO: what to do here? */ 804 NULL,
810 } 805 session->gc,
811 } else if (cmd == (MSIM_CMD_BIT_REPLY | MSIM_CMD_GET) 806 G_CALLBACK(msim_set_username_confirmed_cb),
812 && dsn == MG_MYSPACE_INFO_BY_STRING_DSN 807 G_CALLBACK(msim_do_not_set_username_cb));
813 && lid == MG_MYSPACE_INFO_BY_STRING_LID) {
814 /* Not quite done... ONE MORE STEP :) */
815 rid = msim_new_reply_callback(session, msim_username_is_set_cb, data);
816 body = msim_msg_new("UserName", MSIM_TYPE_STRING, g_strdup(username), NULL);
817 if (!msim_send(session, "persist", MSIM_TYPE_INTEGER, 1,
818 "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
819 "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_PUT,
820 "dsn", MSIM_TYPE_INTEGER, MC_SET_USERNAME_DSN,
821 "uid", MSIM_TYPE_INTEGER, session->userid,
822 "lid", MSIM_TYPE_INTEGER, MC_SET_USERNAME_LID,
823 "rid", MSIM_TYPE_INTEGER, rid,
824 "body", MSIM_TYPE_DICTIONARY, body,
825 NULL)) {
826 /* Error! */
827 /* Can't set... Disconnect */
828 purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg);
829 }
830
831 } else { 808 } else {
832 /* Error! */ 809 /* Looks like its in use or we have an invalid response */
833 purple_debug_info("msim","username_is_set Error: Invalid cmd/dsn/lid combination"); 810 purple_debug_info("msim_username_is_available_cb", "Username unavaiable. Prompting for new entry.\n");
834 purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg); 811 purple_request_input(session->gc, _("MySpaceIM - Please Set a Username"),
835 } 812 _("This username is unavailable."),
836 g_free(errmsg); 813 _("Please try another username:"),
837 } 814 "", FALSE, FALSE, NULL,
815 _("OK"), G_CALLBACK(msim_check_username_availability_cb),
816 _("Cancel"), G_CALLBACK(msim_do_not_set_username_cb),
817 session->account,
818 NULL,
819 NULL,
820 session->gc);
821 }
822 }
823
824 /**
825 * Once they've submitted their desired new username,
826 * check if it is available here.
827 */
828 static void msim_check_username_availability_cb(PurpleConnection *gc, const char *username_to_check)
829 {
830 MsimMessage *user_msg;
831 MsimSession *session;
832
833 g_return_if_fail(gc != NULL);
834
835 session = (MsimSession *)gc->proto_data;
836
837 g_return_if_fail(MSIM_SESSION_VALID(session));
838
839 purple_debug_info("msim_check_username_availability_cb", "Checking username: %s\n", username_to_check);
840
841 user_msg = msim_msg_new(
842 "user", MSIM_TYPE_STRING, g_strdup(username_to_check),
843 NULL);
844
845 /* 25 characters: letters, numbers, underscores */
846 /* TODO: VERIFY ABOVE */
847
848 /* \persist\1\sesskey\288500516\cmd\1\dsn\5\uid\204084363\lid\7\rid\367\body\UserName=Jaywalker\final\ */
849 /* Official client uses a standard lookup... So do we! */
850 msim_lookup_user(session, username_to_check, msim_username_is_available_cb, user_msg);
851 }
852
853 /***
854 * If they hit cancel or no at any point in the Setting Username process,
855 * we come here. Currently we're safe letting them get by without
856 * setting it, unless we hear otherwise. So for now give them a menu.
857 * If this becomes an issue with the official client then boot them here.
858 */
859 void msim_do_not_set_username_cb(PurpleConnection *gc)
860 {
861 purple_debug_info("msim", "Don't set username");
862
863 /* Protocol won't log in now without a username set.. Disconnect */
864 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("No username set"));
865 }
866
867 /**
868 * They've decided to set a username! Yay!
869 */
870 void msim_set_username_cb(PurpleConnection *gc)
871 {
872 g_return_if_fail(gc != NULL);
873 purple_debug_info("msim","Set username\n");
874 purple_request_input(gc, _("MySpaceIM - Please Set a Username"),
875 _("Please enter a username to check its availability:"),
876 NULL,
877 "", FALSE, FALSE, NULL,
878 _("OK"), G_CALLBACK(msim_check_username_availability_cb),
879 _("Cancel"), G_CALLBACK(msim_do_not_set_username_cb),
880 purple_connection_get_account(gc),
881 NULL,
882 NULL,
883 gc);
884 }