Mercurial > pidgin.yaz
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 } |