libpurple/protocols/msnp9/session.c

changeset 21481
d52b697eaae7
child 21513
02642f4cb3df
equal deleted inserted replaced
21480:3fdf3e905e24 21481:d52b697eaae7
1 /**
2 * @file session.c MSN session functions
3 *
4 * purple
5 *
6 * Purple is the legal property of its developers, whose names are too numerous
7 * to list here. Please refer to the COPYRIGHT file distributed with this
8 * source distribution.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
23 */
24 #include "msn.h"
25 #include "session.h"
26 #include "notification.h"
27
28 #include "dialog.h"
29
30 MsnSession *
31 msn_session_new(PurpleAccount *account)
32 {
33 MsnSession *session;
34
35 g_return_val_if_fail(account != NULL, NULL);
36
37 session = g_new0(MsnSession, 1);
38
39 session->account = account;
40 session->notification = msn_notification_new(session);
41 session->userlist = msn_userlist_new(session);
42
43 session->user = msn_user_new(session->userlist,
44 purple_account_get_username(account), NULL);
45
46 session->protocol_ver = 9;
47 session->conv_seq = 1;
48
49 return session;
50 }
51
52 void
53 msn_session_destroy(MsnSession *session)
54 {
55 g_return_if_fail(session != NULL);
56
57 session->destroying = TRUE;
58
59 if (session->connected)
60 msn_session_disconnect(session);
61
62 if (session->notification != NULL)
63 msn_notification_destroy(session->notification);
64
65 while (session->switches != NULL)
66 msn_switchboard_destroy(session->switches->data);
67
68 while (session->slplinks != NULL)
69 msn_slplink_destroy(session->slplinks->data);
70
71 msn_userlist_destroy(session->userlist);
72
73 g_free(session->passport_info.kv);
74 g_free(session->passport_info.sid);
75 g_free(session->passport_info.mspauth);
76 g_free(session->passport_info.client_ip);
77
78 if (session->passport_info.file != NULL)
79 {
80 g_unlink(session->passport_info.file);
81 g_free(session->passport_info.file);
82 }
83
84 if (session->sync != NULL)
85 msn_sync_destroy(session->sync);
86
87 if (session->nexus != NULL)
88 msn_nexus_destroy(session->nexus);
89
90 if (session->user != NULL)
91 msn_user_destroy(session->user);
92
93 g_free(session);
94 }
95
96 gboolean
97 msn_session_connect(MsnSession *session, const char *host, int port,
98 gboolean http_method)
99 {
100 g_return_val_if_fail(session != NULL, FALSE);
101 g_return_val_if_fail(!session->connected, TRUE);
102
103 session->connected = TRUE;
104 session->http_method = http_method;
105
106 if (session->notification == NULL)
107 {
108 purple_debug_error("msn", "This shouldn't happen\n");
109 g_return_val_if_reached(FALSE);
110 }
111
112 if (msn_notification_connect(session->notification, host, port))
113 {
114 return TRUE;
115 }
116
117 return FALSE;
118 }
119
120 void
121 msn_session_disconnect(MsnSession *session)
122 {
123 g_return_if_fail(session != NULL);
124 g_return_if_fail(session->connected);
125
126 session->connected = FALSE;
127
128 while (session->switches != NULL)
129 msn_switchboard_close(session->switches->data);
130
131 if (session->notification != NULL)
132 msn_notification_close(session->notification);
133 }
134
135 /* TODO: This must go away when conversation is redesigned */
136 MsnSwitchBoard *
137 msn_session_find_swboard(MsnSession *session, const char *username)
138 {
139 GList *l;
140
141 g_return_val_if_fail(session != NULL, NULL);
142 g_return_val_if_fail(username != NULL, NULL);
143
144 for (l = session->switches; l != NULL; l = l->next)
145 {
146 MsnSwitchBoard *swboard;
147
148 swboard = l->data;
149
150 if ((swboard->im_user != NULL) && !strcmp(username, swboard->im_user))
151 return swboard;
152 }
153
154 return NULL;
155 }
156
157 MsnSwitchBoard *
158 msn_session_find_swboard_with_conv(MsnSession *session, PurpleConversation *conv)
159 {
160 GList *l;
161
162 g_return_val_if_fail(session != NULL, NULL);
163 g_return_val_if_fail(conv != NULL, NULL);
164
165 for (l = session->switches; l != NULL; l = l->next)
166 {
167 MsnSwitchBoard *swboard;
168
169 swboard = l->data;
170
171 if (swboard->conv == conv)
172 return swboard;
173 }
174
175 return NULL;
176 }
177
178 MsnSwitchBoard *
179 msn_session_find_swboard_with_id(const MsnSession *session, int chat_id)
180 {
181 GList *l;
182
183 g_return_val_if_fail(session != NULL, NULL);
184 g_return_val_if_fail(chat_id >= 0, NULL);
185
186 for (l = session->switches; l != NULL; l = l->next)
187 {
188 MsnSwitchBoard *swboard;
189
190 swboard = l->data;
191
192 if (swboard->chat_id == chat_id)
193 return swboard;
194 }
195
196 return NULL;
197 }
198
199 MsnSwitchBoard *
200 msn_session_get_swboard(MsnSession *session, const char *username,
201 MsnSBFlag flag)
202 {
203 MsnSwitchBoard *swboard;
204
205 g_return_val_if_fail(session != NULL, NULL);
206
207 swboard = msn_session_find_swboard(session, username);
208
209 if (swboard == NULL)
210 {
211 swboard = msn_switchboard_new(session);
212 swboard->im_user = g_strdup(username);
213 msn_switchboard_request(swboard);
214 msn_switchboard_request_add_user(swboard, username);
215 }
216
217 swboard->flag |= flag;
218
219 return swboard;
220 }
221
222 static void
223 msn_session_sync_users(MsnSession *session)
224 {
225 PurpleBlistNode *gnode, *cnode, *bnode;
226 PurpleConnection *gc = purple_account_get_connection(session->account);
227
228 g_return_if_fail(gc != NULL);
229
230 /* The core used to use msn_add_buddy to add all buddies before
231 * being logged in. This no longer happens, so we manually iterate
232 * over the whole buddy list to identify sync issues. */
233
234 for (gnode = purple_blist_get_root(); gnode; gnode = gnode->next) {
235 PurpleGroup *group = (PurpleGroup *)gnode;
236 const char *group_name = group->name;
237 if(!PURPLE_BLIST_NODE_IS_GROUP(gnode))
238 continue;
239 for(cnode = gnode->child; cnode; cnode = cnode->next) {
240 if(!PURPLE_BLIST_NODE_IS_CONTACT(cnode))
241 continue;
242 for(bnode = cnode->child; bnode; bnode = bnode->next) {
243 PurpleBuddy *b;
244 if(!PURPLE_BLIST_NODE_IS_BUDDY(bnode))
245 continue;
246 b = (PurpleBuddy *)bnode;
247 if(purple_buddy_get_account(b) == purple_connection_get_account(gc)) {
248 MsnUser *remote_user;
249 gboolean found = FALSE;
250
251 remote_user = msn_userlist_find_user(session->userlist, purple_buddy_get_name(b));
252
253 if ((remote_user != NULL) && (remote_user->list_op & MSN_LIST_FL_OP))
254 {
255 int group_id;
256 GList *l;
257
258 group_id = msn_userlist_find_group_id(remote_user->userlist,
259 group_name);
260
261 for (l = remote_user->group_ids; l != NULL; l = l->next)
262 {
263 if (group_id == GPOINTER_TO_INT(l->data))
264 {
265 found = TRUE;
266 break;
267 }
268 }
269
270 }
271
272 if (!found)
273 {
274 /* The user was not on the server list or not in that group
275 * on the server list */
276 msn_show_sync_issue(session, purple_buddy_get_name(b), group_name);
277 }
278 }
279 }
280 }
281 }
282 }
283
284 void
285 msn_session_set_error(MsnSession *session, MsnErrorType error,
286 const char *info)
287 {
288 PurpleConnection *gc;
289 char *msg;
290
291 gc = purple_account_get_connection(session->account);
292
293 switch (error)
294 {
295 case MSN_ERROR_SERVCONN:
296 msg = g_strdup(info);
297 break;
298 case MSN_ERROR_UNSUPPORTED_PROTOCOL:
299 msg = g_strdup(_("Our protocol is not supported by the "
300 "server."));
301 break;
302 case MSN_ERROR_HTTP_MALFORMED:
303 msg = g_strdup(_("Error parsing HTTP."));
304 break;
305 case MSN_ERROR_SIGN_OTHER:
306 gc->wants_to_die = TRUE;
307 msg = g_strdup(_("You have signed on from another location."));
308 break;
309 case MSN_ERROR_SERV_UNAVAILABLE:
310 msg = g_strdup(_("The MSN servers are temporarily "
311 "unavailable. Please wait and try "
312 "again."));
313 break;
314 case MSN_ERROR_SERV_DOWN:
315 msg = g_strdup(_("The MSN servers are going down "
316 "temporarily."));
317 break;
318 case MSN_ERROR_AUTH:
319 gc->wants_to_die = TRUE;
320 msg = g_strdup_printf(_("Unable to authenticate: %s"),
321 (info == NULL ) ?
322 _("Unknown error") : info);
323 break;
324 case MSN_ERROR_BAD_BLIST:
325 msg = g_strdup(_("Your MSN buddy list is temporarily "
326 "unavailable. Please wait and try "
327 "again."));
328 break;
329 default:
330 msg = g_strdup(_("Unknown error."));
331 break;
332 }
333
334 msn_session_disconnect(session);
335
336 purple_connection_error(gc, msg);
337
338 g_free(msg);
339 }
340
341 static const char *
342 get_login_step_text(MsnSession *session)
343 {
344 const char *steps_text[] = {
345 _("Connecting"),
346 _("Handshaking"),
347 _("Transferring"),
348 _("Handshaking"),
349 _("Starting authentication"),
350 _("Getting cookie"),
351 _("Authenticating"),
352 _("Sending cookie"),
353 _("Retrieving buddy list")
354 };
355
356 return steps_text[session->login_step];
357 }
358
359 void
360 msn_session_set_login_step(MsnSession *session, MsnLoginStep step)
361 {
362 PurpleConnection *gc;
363
364 /* Prevent the connection progress going backwards, eg. if we get
365 * transferred several times during login */
366 if (session->login_step > step)
367 return;
368
369 /* If we're already logged in, we're probably here because of a
370 * mid-session XFR from the notification server, so we don't want to
371 * popup the connection progress dialog */
372 if (session->logged_in)
373 return;
374
375 gc = session->account->gc;
376
377 session->login_step = step;
378
379 purple_connection_update_progress(gc, get_login_step_text(session), step,
380 MSN_LOGIN_STEPS);
381 }
382
383 void
384 msn_session_finish_login(MsnSession *session)
385 {
386 PurpleAccount *account;
387 PurpleConnection *gc;
388 PurpleStoredImage *img;
389 const char *passport;
390
391 if (session->logged_in)
392 return;
393
394 account = session->account;
395 gc = purple_account_get_connection(account);
396
397 img = purple_buddy_icons_find_account_icon(session->account);
398 msn_user_set_buddy_icon(session->user, img);
399 purple_imgstore_unref(img);
400
401 session->logged_in = TRUE;
402
403 msn_change_status(session);
404
405 purple_connection_set_state(gc, PURPLE_CONNECTED);
406
407 /* Sync users */
408 msn_session_sync_users(session);
409 /* It seems that some accounts that haven't accessed hotmail for a while
410 * and @msn.com accounts don't automatically get the initial email
411 * notification so we always request it on login
412 */
413
414 passport = purple_normalize(account, purple_account_get_username(account));
415
416 if ((strstr(passport, "@hotmail.") != NULL) ||
417 (strstr(passport, "@msn.com") != NULL))
418 {
419 msn_cmdproc_send(session->notification->cmdproc, "URL", "%s", "INBOX");
420 }
421 }

mercurial