5309
|
1 /**
|
|
2 * @file notification.c Notification server functions
|
|
3 *
|
|
4 * gaim
|
|
5 *
|
|
6 * Copyright (C) 2003 Christian Hammond <chipx86@gnupdate.org>
|
|
7 *
|
|
8 * This program is free software; you can redistribute it and/or modify
|
|
9 * it under the terms of the GNU General Public License as published by
|
|
10 * the Free Software Foundation; either version 2 of the License, or
|
|
11 * (at your option) any later version.
|
|
12 *
|
|
13 * This program is distributed in the hope that it will be useful,
|
|
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
16 * GNU General Public License for more details.
|
|
17 *
|
|
18 * You should have received a copy of the GNU General Public License
|
|
19 * along with this program; if not, write to the Free Software
|
|
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
21 */
|
|
22 #include "msn.h"
|
|
23 #include "notification.h"
|
|
24 #include "away.h"
|
|
25 #include "error.h"
|
|
26 #include "utils.h"
|
|
27
|
|
28 typedef struct
|
|
29 {
|
|
30 struct gaim_connection *gc;
|
|
31 MsnUser *user;
|
|
32
|
|
33 } MsnPermitAdd;
|
|
34
|
|
35 static GHashTable *notification_commands = NULL;
|
|
36 static GHashTable *notification_msg_types = NULL;
|
|
37
|
|
38 /**************************************************************************
|
|
39 * Callbacks
|
|
40 **************************************************************************/
|
|
41 static void
|
|
42 msn_accept_add_cb(MsnPermitAdd *pa)
|
|
43 {
|
|
44 if (g_slist_find(connections, pa->gc) != NULL) {
|
|
45 MsnSession *session = pa->gc->proto_data;
|
|
46 char outparams[MSN_BUF_LEN];
|
|
47
|
|
48 g_snprintf(outparams, sizeof(outparams), "AL %s %s",
|
|
49 msn_user_get_passport(pa->user),
|
|
50 msn_url_encode(msn_user_get_name(pa->user)));
|
|
51
|
|
52 if (msn_servconn_send_command(session->notification_conn,
|
|
53 "ADD", outparams) <= 0) {
|
|
54 hide_login_progress(pa->gc, _("Write error"));
|
|
55 signoff(pa->gc);
|
|
56 return;
|
|
57 }
|
|
58
|
|
59 gaim_privacy_permit_add(pa->gc->account,
|
|
60 msn_user_get_passport(pa->user));
|
|
61 build_allow_list();
|
|
62
|
|
63 show_got_added(pa->gc, NULL, msn_user_get_passport(pa->user),
|
|
64 msn_user_get_name(pa->user), NULL);
|
|
65 }
|
|
66
|
|
67 msn_user_destroy(pa->user);
|
|
68 g_free(pa);
|
|
69 }
|
|
70
|
|
71 static void
|
|
72 msn_cancel_add_cb(MsnPermitAdd *pa)
|
|
73 {
|
|
74 if (g_slist_find(connections, pa->gc) != NULL) {
|
|
75 MsnSession *session = pa->gc->proto_data;
|
|
76 char outparams[MSN_BUF_LEN];
|
|
77
|
|
78 g_snprintf(outparams, sizeof(outparams), "BL %s %s",
|
|
79 msn_user_get_passport(pa->user),
|
|
80 msn_url_encode(msn_user_get_name(pa->user)));
|
|
81
|
|
82 if (msn_servconn_send_command(session->notification_conn,
|
|
83 "ADD", outparams) <= 0) {
|
|
84 hide_login_progress(pa->gc, _("Write error"));
|
|
85 signoff(pa->gc);
|
|
86 return;
|
|
87 }
|
|
88
|
|
89 gaim_privacy_deny_add(pa->gc->account,
|
|
90 msn_user_get_passport(pa->user));
|
|
91 build_block_list();
|
|
92 }
|
|
93
|
|
94 msn_user_destroy(pa->user);
|
|
95 g_free(pa);
|
|
96 }
|
|
97
|
|
98 /**************************************************************************
|
|
99 * Catch-all commands
|
|
100 **************************************************************************/
|
|
101 static gboolean
|
|
102 __blank_cmd(MsnServConn *servconn, const char *command, const char **params,
|
|
103 size_t param_count)
|
|
104 {
|
|
105 return TRUE;
|
|
106 }
|
|
107
|
|
108 static gboolean
|
|
109 __unknown_cmd(MsnServConn *servconn, const char *command, const char **params,
|
|
110 size_t param_count)
|
|
111 {
|
|
112 struct gaim_connection *gc = servconn->session->account->gc;
|
|
113
|
|
114 if (isdigit(*command)) {
|
|
115 hide_login_progress(gc, (char *)msn_error_get_text(atoi(command)));
|
|
116 }
|
|
117 else
|
|
118 hide_login_progress(gc, _("Unable to parse message."));
|
|
119
|
|
120 signoff(gc);
|
|
121
|
|
122 return FALSE;
|
|
123 }
|
|
124
|
|
125
|
|
126 /**************************************************************************
|
|
127 * Login
|
|
128 **************************************************************************/
|
|
129 static gboolean
|
|
130 __ver_cmd(MsnServConn *servconn, const char *command, const char **params,
|
|
131 size_t param_count)
|
|
132 {
|
|
133 struct gaim_connection *gc = servconn->session->account->gc;
|
|
134 size_t i;
|
|
135 gboolean msnp5_found = FALSE;
|
|
136
|
|
137 for (i = 1; i < param_count; i++) {
|
|
138 if (!strcmp(params[i], "MSNP5")) {
|
|
139 msnp5_found = TRUE;
|
|
140 break;
|
|
141 }
|
|
142 }
|
|
143
|
|
144 if (!msnp5_found) {
|
|
145 hide_login_progress(gc, _("Protocol not supported"));
|
|
146 signoff(gc);
|
|
147
|
|
148 return FALSE;
|
|
149 }
|
|
150
|
|
151 if (!msn_servconn_send_command(servconn, "INF", NULL)) {
|
|
152 hide_login_progress(gc, _("Unable to request INF"));
|
|
153 signoff(gc);
|
|
154
|
|
155 return FALSE;
|
|
156 }
|
|
157
|
|
158 return TRUE;
|
|
159 }
|
|
160
|
|
161 static gboolean
|
|
162 __inf_cmd(MsnServConn *servconn, const char *command, const char **params,
|
|
163 size_t param_count)
|
|
164 {
|
|
165 struct gaim_connection *gc = servconn->session->account->gc;
|
|
166 char outparams[MSN_BUF_LEN];
|
|
167
|
|
168 if (strcmp(params[1], "MD5")) {
|
|
169 hide_login_progress(gc, _("Unable to login using MD5"));
|
|
170 signoff(gc);
|
|
171
|
|
172 return FALSE;
|
|
173 }
|
|
174
|
|
175 g_snprintf(outparams, sizeof(outparams), "MD5 I %s", gc->username);
|
|
176
|
|
177 if (!msn_servconn_send_command(servconn, "USR", outparams)) {
|
|
178 hide_login_progress(gc, _("Unable to send USR"));
|
|
179 signoff(gc);
|
|
180
|
|
181 return FALSE;
|
|
182 }
|
|
183
|
|
184 set_login_progress(gc, 3, _("Requesting to send password"));
|
|
185
|
|
186 return TRUE;
|
|
187 }
|
|
188
|
|
189 static gboolean
|
|
190 __usr_cmd(MsnServConn *servconn, const char *command, const char **params,
|
|
191 size_t param_count)
|
|
192 {
|
|
193 struct gaim_connection *gc = servconn->session->account->gc;
|
|
194 char outparams[MSN_BUF_LEN];
|
|
195
|
|
196 /* We're either getting the challenge or the OK. Let's find out. */
|
|
197 if (!g_ascii_strcasecmp(params[1], "OK")) {
|
|
198 /* OK */
|
|
199
|
|
200 if (!msn_servconn_send_command(servconn, "SYN", "0")) {
|
|
201 hide_login_progress(gc, _("Unable to write"));
|
|
202 signoff(gc);
|
|
203
|
|
204 return FALSE;
|
|
205 }
|
|
206 }
|
|
207 else {
|
|
208 /* Challenge */
|
|
209 const char *challenge = params[3];
|
|
210 char buf[MSN_BUF_LEN];
|
|
211 md5_state_t st;
|
|
212 md5_byte_t di[16];
|
|
213 int i;
|
|
214
|
|
215 g_snprintf(buf, sizeof(buf), "%s%s", challenge, gc->password);
|
|
216
|
|
217 md5_init(&st);
|
|
218 md5_append(&st, (const md5_byte_t *)buf, strlen(buf));
|
|
219 md5_finish(&st, di);
|
|
220
|
|
221 g_snprintf(outparams, sizeof(outparams), "MD5 S ");
|
|
222
|
|
223 for (i = 0; i < 16; i++) {
|
|
224 g_snprintf(buf, sizeof(buf), "%02x", di[i]);
|
|
225 strcat(outparams, buf);
|
|
226 }
|
|
227
|
|
228 if (!msn_servconn_send_command(servconn, "USR", outparams)) {
|
|
229 hide_login_progress(gc, _("Unable to send password"));
|
|
230 signoff(gc);
|
|
231
|
|
232 return FALSE;
|
|
233 }
|
|
234
|
|
235 set_login_progress(gc, 4, _("Password sent"));
|
|
236 }
|
|
237
|
|
238 return TRUE;
|
|
239 }
|
|
240
|
|
241 /**************************************************************************
|
|
242 * Log out
|
|
243 **************************************************************************/
|
|
244 static gboolean
|
|
245 __out_cmd(MsnServConn *servconn, const char *command, const char **params,
|
|
246 size_t param_count)
|
|
247 {
|
|
248 struct gaim_connection *gc = servconn->session->account->gc;
|
|
249
|
|
250 if (!g_ascii_strcasecmp(params[0], "OTH")) {
|
|
251 hide_login_progress(gc,
|
|
252 _("You have been disconnected. You have "
|
|
253 "signed on from another location."));
|
|
254 signoff(gc);
|
|
255 }
|
|
256 else if (!g_ascii_strcasecmp(params[0], "SSD")) {
|
|
257 hide_login_progress(gc,
|
|
258 _("You have been disconnected. The MSN servers "
|
|
259 "are going down temporarily."));
|
|
260 signoff(gc);
|
|
261 }
|
|
262
|
|
263 return FALSE;
|
|
264 }
|
|
265
|
|
266 /**************************************************************************
|
|
267 * Messages
|
|
268 **************************************************************************/
|
|
269 static gboolean
|
|
270 __msg_cmd(MsnServConn *servconn, const char *command, const char **params,
|
|
271 size_t param_count)
|
|
272 {
|
|
273 gaim_debug(GAIM_DEBUG_INFO, "msn", "Found message. Parsing.\n");
|
|
274
|
|
275 servconn->parsing_msg = TRUE;
|
|
276 servconn->msg_passport = g_strdup(params[0]);
|
|
277 servconn->msg_friendly = g_strdup(params[1]);
|
|
278 servconn->msg_len = atoi(params[2]);
|
|
279
|
|
280 return TRUE;
|
|
281 }
|
|
282
|
|
283 /**************************************************************************
|
|
284 * Challenges
|
|
285 **************************************************************************/
|
|
286 static gboolean
|
|
287 __chl_cmd(MsnServConn *servconn, const char *command, const char **params,
|
|
288 size_t param_count)
|
|
289 {
|
|
290 struct gaim_connection *gc = servconn->session->account->gc;
|
|
291 char buf[MSN_BUF_LEN];
|
|
292 char buf2[3];
|
|
293 md5_state_t st;
|
|
294 md5_byte_t di[16];
|
|
295 int i;
|
|
296
|
|
297 md5_init(&st);
|
|
298 md5_append(&st, (const md5_byte_t *)params[1], strlen(params[1]));
|
|
299 md5_append(&st, (const md5_byte_t *)"Q1P7W2E4J9R8U3S5",
|
|
300 strlen("Q1P7W2E4J9R8U3S5"));
|
|
301 md5_finish(&st, di);
|
|
302
|
|
303 g_snprintf(buf, sizeof(buf),
|
|
304 "QRY %u msmsgs@msnmsgr.com 32\r\n",
|
|
305 servconn->session->trId++);
|
|
306
|
|
307 for (i = 0; i < 16; i++) {
|
|
308 g_snprintf(buf2, sizeof(buf2), "%02x", di[i]);
|
|
309 strcat(buf, buf2);
|
|
310 }
|
|
311
|
|
312 if (msn_servconn_write(servconn, buf, strlen(buf)) <= 0) {
|
|
313 hide_login_progress(gc, _("Unable to write to server"));
|
|
314 signoff(gc);
|
|
315 }
|
|
316
|
|
317 return TRUE;
|
|
318 }
|
|
319
|
|
320 /**************************************************************************
|
|
321 * Buddy Lists
|
|
322 **************************************************************************/
|
|
323 static gboolean
|
|
324 __add_cmd(MsnServConn *servconn, const char *command, const char **params,
|
|
325 size_t param_count)
|
|
326 {
|
|
327 MsnSession *session = servconn->session;
|
|
328 struct gaim_connection *gc = session->account->gc;
|
|
329 MsnPermitAdd *pa;
|
|
330 GSList *sl;
|
|
331 const char *list, *passport;
|
|
332 char *friend;
|
|
333 char msg[MSN_BUF_LEN];
|
|
334
|
|
335 list = params[1];
|
|
336 passport = params[3];
|
|
337
|
|
338 friend = msn_url_decode(params[4]);
|
|
339
|
|
340 if (g_ascii_strcasecmp(list, "RL"))
|
|
341 return TRUE;
|
|
342
|
|
343 for (sl = gc->account->permit; sl != NULL; sl = sl->next) {
|
|
344 if (!gaim_utf8_strcasecmp(sl->data, passport))
|
|
345 return TRUE;
|
|
346 }
|
|
347
|
|
348 pa = g_new0(MsnPermitAdd, 1);
|
|
349 pa->user = msn_user_new(session, passport, friend);
|
|
350 pa->gc = gc;
|
|
351
|
|
352 g_snprintf(msg, sizeof(msg),
|
|
353 _("The user %s (%s) wants to add %s to his or her buddy list."),
|
|
354 passport, friend, gc->username);
|
|
355
|
|
356 do_ask_dialog(msg, NULL, pa,
|
|
357 _("Authorize"), msn_accept_add_cb,
|
|
358 _("Deny"), msn_cancel_add_cb,
|
|
359 session->prpl->handle, FALSE);
|
|
360
|
|
361 return TRUE;
|
|
362 }
|
|
363
|
|
364 static gboolean
|
|
365 __blp_cmd(MsnServConn *servconn, const char *command, const char **params,
|
|
366 size_t param_count)
|
|
367 {
|
|
368 struct gaim_connection *gc = servconn->session->account->gc;
|
|
369
|
|
370 if (!g_ascii_strcasecmp(params[2], "AL")) {
|
|
371 /*
|
|
372 * If the current setting is AL, messages from users who
|
|
373 * are not in BL will be delivered.
|
|
374 *
|
|
375 * In other words, deny some.
|
|
376 */
|
|
377 gc->account->permdeny = DENY_SOME;
|
|
378 }
|
|
379 else {
|
|
380 /* If the current setting is BL, only messages from people
|
|
381 * who are in the AL will be delivered.
|
|
382 *
|
|
383 * In other words, permit some.
|
|
384 */
|
|
385 gc->account->permdeny = PERMIT_SOME;
|
|
386 }
|
|
387
|
|
388 return TRUE;
|
|
389 }
|
|
390
|
|
391 static gboolean
|
|
392 __fln_cmd(MsnServConn *servconn, const char *command, const char **params,
|
|
393 size_t param_count)
|
|
394 {
|
|
395 struct gaim_connection *gc = servconn->session->account->gc;
|
|
396
|
|
397 serv_got_update(gc, (char *)params[0], 0, 0, 0, 0, 0);
|
|
398
|
|
399 return TRUE;
|
|
400 }
|
|
401
|
|
402 static gboolean
|
|
403 __iln_cmd(MsnServConn *servconn, const char *command, const char **params,
|
|
404 size_t param_count)
|
|
405 {
|
|
406 struct gaim_connection *gc = servconn->session->account->gc;
|
|
407 int status = 0;
|
|
408 const char *state, *passport, *friend;
|
|
409
|
|
410 state = params[1];
|
|
411 passport = params[2];
|
|
412 friend = msn_url_decode(params[3]);
|
|
413
|
|
414 serv_got_alias(gc, (char *)passport, (char *)friend);
|
|
415
|
|
416 if (!g_ascii_strcasecmp(state, "BSY"))
|
|
417 status |= UC_UNAVAILABLE | (MSN_BUSY << 1);
|
|
418 else if (!g_ascii_strcasecmp(state, "IDL"))
|
|
419 status |= UC_UNAVAILABLE | (MSN_IDLE << 1);
|
|
420 else if (!g_ascii_strcasecmp(state, "BRB"))
|
|
421 status |= UC_UNAVAILABLE | (MSN_BRB << 1);
|
|
422 else if (!g_ascii_strcasecmp(state, "AWY"))
|
|
423 status |= UC_UNAVAILABLE | (MSN_AWAY << 1);
|
|
424 else if (!g_ascii_strcasecmp(state, "PHN"))
|
|
425 status |= UC_UNAVAILABLE | (MSN_PHONE << 1);
|
|
426 else if (!g_ascii_strcasecmp(state, "LUN"))
|
|
427 status |= UC_UNAVAILABLE | (MSN_LUNCH << 1);
|
|
428
|
|
429 serv_got_update(gc, (char *)passport, 1, 0, 0, 0, status);
|
|
430
|
|
431 return TRUE;
|
|
432 }
|
|
433
|
|
434 static gboolean
|
|
435 __lsg_cmd(MsnServConn *servconn, const char *command, const char **params,
|
|
436 size_t param_count)
|
|
437 {
|
|
438 MsnSession *session = servconn->session;
|
|
439 struct group *g;
|
|
440 const char *name;
|
|
441 int group_num, num_groups, group_id;
|
|
442
|
|
443 group_num = atoi(params[2]);
|
|
444 num_groups = atoi(params[3]);
|
|
445 group_id = atoi(params[4]);
|
|
446 name = msn_url_decode(params[5]);
|
|
447
|
|
448 if (group_num == 1) {
|
|
449 session->groups = g_hash_table_new_full(g_int_hash, g_int_equal,
|
|
450 NULL, g_free);
|
|
451 }
|
|
452
|
|
453 g_hash_table_insert(session->groups, GINT_TO_POINTER(group_id),
|
|
454 g_strdup(name));
|
|
455
|
|
456 if ((g = gaim_find_group(name)) == NULL) {
|
|
457 g = gaim_group_new(name);
|
|
458 gaim_blist_add_group(g, NULL);
|
|
459 }
|
|
460
|
|
461 return TRUE;
|
|
462 }
|
|
463
|
|
464 static gboolean
|
|
465 __lst_cmd(MsnServConn *servconn, const char *command, const char **params,
|
|
466 size_t param_count)
|
|
467 {
|
|
468 MsnSession *session = servconn->session;
|
|
469 struct gaim_connection *gc = session->account->gc;
|
|
470 int user_num;
|
|
471 int num_users;
|
|
472 const char *type;
|
|
473 const char *passport;
|
|
474 const char *friend;
|
|
475
|
|
476 user_num = atoi(params[3]);
|
|
477 num_users = atoi(params[4]);
|
|
478
|
|
479 if (user_num == 0 && num_users == 0)
|
|
480 return TRUE; /* There are no users on this list. */
|
|
481
|
|
482 type = params[1];
|
|
483 passport = params[5];
|
|
484 friend = msn_url_decode(params[6]);
|
|
485
|
|
486 if (!g_ascii_strcasecmp(type, "FL") && user_num != 0) {
|
|
487 /* These are users on our contact list. */
|
|
488 MsnUser *user;
|
|
489
|
|
490 user = msn_user_new(session, passport, friend);
|
|
491
|
|
492 if (param_count == 8)
|
|
493 msn_user_set_group_id(user, atoi(params[7]));
|
|
494
|
|
495 session->lists.forward = g_slist_append(session->lists.forward, user);
|
|
496 }
|
|
497 else if (!g_ascii_strcasecmp(type, "AL") && user_num != 0) {
|
|
498 /* These are users who are allowed to see our status. */
|
|
499 if (g_slist_find_custom(gc->account->deny, passport,
|
|
500 (GCompareFunc)strcmp)) {
|
|
501
|
|
502 gaim_debug(GAIM_DEBUG_INFO, "msn",
|
|
503 "Moving user from deny list to permit: %s (%s)\n",
|
|
504 passport, friend);
|
|
505
|
|
506 gaim_privacy_deny_remove(gc->account, passport);
|
|
507 }
|
|
508
|
|
509 gaim_privacy_permit_add(gc->account, passport);
|
|
510 }
|
|
511 else if (!g_ascii_strcasecmp(type, "BL") && user_num != 0) {
|
|
512 /* These are users who are not allowed to see our status. */
|
|
513 gaim_privacy_deny_add(gc->account, passport);
|
|
514 }
|
|
515 else if (!g_ascii_strcasecmp(type, "RL")) {
|
|
516 /* These are users who have us on their contact list. */
|
|
517 if (user_num > 0) {
|
|
518 gboolean new_entry = TRUE;
|
|
519
|
|
520 if (g_slist_find_custom(gc->account->permit, passport,
|
|
521 (GCompareFunc)g_ascii_strcasecmp)) {
|
|
522 new_entry = FALSE;
|
|
523 }
|
|
524
|
|
525 if (g_slist_find_custom(gc->account->deny, passport,
|
|
526 (GCompareFunc)g_ascii_strcasecmp)) {
|
|
527 new_entry = FALSE;
|
|
528 }
|
|
529
|
|
530 if (new_entry) {
|
|
531 MsnPermitAdd *pa;
|
|
532 char msg[MSN_BUF_LEN];
|
|
533
|
|
534 gaim_debug(GAIM_DEBUG_WARNING, "msn",
|
|
535 "Unresolved MSN RL entry: %s\n", passport);
|
|
536
|
|
537 pa = g_new0(MsnPermitAdd, 1);
|
|
538 pa->user = msn_user_new(session, passport, friend);
|
|
539 pa->gc = gc;
|
|
540
|
|
541 g_snprintf(msg, sizeof(msg),
|
|
542 _("The user %s (%s) wants to add you to their "
|
|
543 "buddy list."),
|
|
544 msn_user_get_passport(pa->user),
|
|
545 msn_user_get_name(pa->user));
|
|
546
|
|
547 do_ask_dialog(msg, NULL, pa,
|
|
548 _("Authorize"), msn_accept_add_cb,
|
|
549 _("Deny"), msn_cancel_add_cb,
|
|
550 session->prpl->handle, FALSE);
|
|
551 }
|
|
552 }
|
|
553
|
|
554 if (user_num != num_users)
|
|
555 return TRUE; /* This isn't the last one in the RL. */
|
|
556
|
|
557 if (!msn_servconn_send_command(servconn, "CHG", "NLN")) {
|
|
558 hide_login_progress(gc, _("Unable to write"));
|
|
559 signoff(gc);
|
|
560
|
|
561 return FALSE;
|
|
562 }
|
|
563
|
|
564 account_online(gc);
|
|
565 serv_finish_login(gc);
|
|
566
|
|
567 session->lists.allow = g_slist_copy(gc->account->permit);
|
|
568 session->lists.block = g_slist_copy(gc->account->deny);
|
|
569
|
|
570 while (session->lists.forward != NULL) {
|
|
571 MsnUser *user = session->lists.forward->data;
|
|
572 struct buddy *b;
|
|
573
|
|
574 b = gaim_find_buddy(gc->account, msn_user_get_passport(user));
|
|
575
|
|
576 session->lists.forward = g_slist_remove(session->lists.forward,
|
|
577 user);
|
|
578
|
|
579 if (b == NULL) {
|
|
580 struct group *g = NULL;
|
|
581 const char *group_name = NULL;
|
|
582 int group_id;
|
|
583
|
|
584 group_id = msn_user_get_group_id(user);
|
|
585
|
|
586 if (group_id > -1) {
|
|
587 group_name = g_hash_table_lookup(session->groups,
|
|
588 GINT_TO_POINTER(group_id));
|
|
589 }
|
|
590
|
|
591 if (group_name == NULL) {
|
|
592 gaim_debug(GAIM_DEBUG_WARNING, "msn",
|
|
593 "Group ID %d for user %s was not defined.\n",
|
|
594 group_id, passport);
|
|
595 }
|
|
596 else if ((g = gaim_find_group(group_name)) == NULL) {
|
|
597 gaim_debug(GAIM_DEBUG_ERROR, "msn",
|
|
598 "Group '%s' appears in server-side "
|
|
599 "buddy list, but not here!",
|
|
600 group_name);
|
|
601 }
|
|
602
|
|
603 if (g == NULL) {
|
|
604 if ((g = gaim_find_group(_("Buddies"))) == NULL) {
|
|
605 g = gaim_group_new(_("Buddies"));
|
|
606 gaim_blist_add_group(g, NULL);
|
|
607 }
|
|
608 }
|
|
609
|
|
610 b = gaim_buddy_new(gc->account,
|
|
611 msn_user_get_passport(user), NULL);
|
|
612
|
|
613 gaim_blist_add_buddy(b, g, NULL);
|
|
614 }
|
|
615
|
|
616 serv_got_alias(gc, (char *)msn_user_get_passport(user),
|
|
617 (char *)msn_user_get_name(user));
|
|
618
|
|
619 msn_user_destroy(user);
|
|
620 }
|
|
621 }
|
|
622
|
|
623 return TRUE;
|
|
624 }
|
|
625
|
|
626 static gboolean
|
|
627 __nln_cmd(MsnServConn *servconn, const char *command, const char **params,
|
|
628 size_t param_count)
|
|
629 {
|
|
630 MsnSession *session = servconn->session;
|
|
631 struct gaim_connection *gc = session->account->gc;
|
|
632 const char *state;
|
|
633 const char *passport;
|
|
634 const char *friend;
|
|
635 int status = 0;
|
|
636
|
|
637 state = params[0];
|
|
638 passport = params[1];
|
|
639 friend = msn_url_decode(params[2]);
|
|
640
|
|
641 serv_got_alias(gc, (char *)passport, (char *)friend);
|
|
642
|
|
643 if (!g_ascii_strcasecmp(state, "BSY"))
|
|
644 status |= UC_UNAVAILABLE | (MSN_BUSY << 1);
|
|
645 else if (!g_ascii_strcasecmp(state, "IDL"))
|
|
646 status |= UC_UNAVAILABLE | (MSN_IDLE << 1);
|
|
647 else if (!g_ascii_strcasecmp(state, "BRB"))
|
|
648 status |= UC_UNAVAILABLE | (MSN_BRB << 1);
|
|
649 else if (!g_ascii_strcasecmp(state, "AWY"))
|
|
650 status |= UC_UNAVAILABLE | (MSN_AWAY << 1);
|
|
651 else if (!g_ascii_strcasecmp(state, "PHN"))
|
|
652 status |= UC_UNAVAILABLE | (MSN_PHONE << 1);
|
|
653 else if (!g_ascii_strcasecmp(state, "LUN"))
|
|
654 status |= UC_UNAVAILABLE | (MSN_LUNCH << 1);
|
|
655
|
|
656 serv_got_update(gc, (char *)passport, 1, 0, 0, 0, status);
|
|
657
|
|
658 return TRUE;
|
|
659 }
|
|
660
|
|
661 static gboolean
|
|
662 __rea_cmd(MsnServConn *servconn, const char *command, const char **params,
|
|
663 size_t param_count)
|
|
664 {
|
|
665 MsnSession *session = servconn->session;
|
|
666 struct gaim_connection *gc = session->account->gc;
|
|
667 char *friend;
|
|
668
|
|
669 friend = msn_url_decode(params[2]);
|
|
670
|
|
671 g_snprintf(gc->displayname, sizeof(gc->displayname), "%s", friend);
|
|
672
|
|
673 return TRUE;
|
|
674 }
|
|
675
|
|
676 /**************************************************************************
|
|
677 * Misc commands
|
|
678 **************************************************************************/
|
|
679 static gboolean
|
|
680 __url_cmd(MsnServConn *servconn, const char *command, const char **params,
|
|
681 size_t param_count)
|
|
682 {
|
|
683 MsnSession *session = servconn->session;
|
|
684 struct gaim_connection *gc = session->account->gc;
|
|
685 const char *rru;
|
|
686 const char *url;
|
|
687 md5_state_t st;
|
|
688 md5_byte_t di[16];
|
|
689 FILE *fd;
|
|
690 char buf[2048];
|
|
691 char buf2[3];
|
|
692 char sendbuf[64];
|
|
693 int i;
|
|
694
|
|
695 rru = params[1];
|
|
696 url = params[2];
|
|
697
|
|
698 g_snprintf(buf, sizeof(buf), "%s%lu%s",
|
|
699 session->passport_info.mspauth,
|
|
700 time(NULL) - session->passport_info.sl, gc->password);
|
|
701
|
|
702 md5_init(&st);
|
|
703 md5_append(&st, (const md5_byte_t *)buf, strlen(buf));
|
|
704 md5_finish(&st, di);
|
|
705
|
|
706 memset(sendbuf, 0, sizeof(sendbuf));
|
|
707
|
|
708 for (i = 0; i < 16; i++) {
|
|
709 g_snprintf(buf2, sizeof(buf2), "%02x", di[i]);
|
|
710 strcat(sendbuf, buf2);
|
|
711 }
|
|
712
|
|
713 if (session->passport_info.file != NULL) {
|
|
714 unlink(session->passport_info.file);
|
|
715 g_free(session->passport_info.file);
|
|
716 }
|
|
717
|
|
718 if ((fd = gaim_mkstemp(&session->passport_info.file)) == NULL) {
|
|
719 gaim_debug(GAIM_DEBUG_ERROR, "msn",
|
|
720 "Error opening temp passport file: %s\n",
|
|
721 strerror(errno));
|
|
722 }
|
|
723 else {
|
|
724 fputs("<html>\n"
|
|
725 "<head>\n"
|
|
726 "<noscript>\n"
|
|
727 "<meta http-equiv=\"Refresh\" content=\"0; "
|
|
728 "url=http://www.hotmail.com\">\n"
|
|
729 "</noscript>\n"
|
|
730 "</head>\n\n",
|
|
731 fd);
|
|
732
|
|
733 fprintf(fd, "<body onload=\"document.pform.submit(); \">\n");
|
|
734 fprintf(fd, "<form name=\"pform\" action=\"%s\" method=\"POST\">\n\n",
|
|
735 url);
|
|
736 fprintf(fd, "<input type=\"hidden\" name=\"mode\" value=\"ttl\">\n");
|
|
737 fprintf(fd, "<input type=\"hidden\" name=\"login\" value=\"%s\">\n",
|
|
738 gc->username);
|
|
739 fprintf(fd, "<input type=\"hidden\" name=\"username\" value=\"%s\">\n",
|
|
740 gc->username);
|
|
741 fprintf(fd, "<input type=\"hidden\" name=\"sid\" value=\"%s\">\n",
|
|
742 session->passport_info.sid);
|
|
743 fprintf(fd, "<input type=\"hidden\" name=\"kv\" value=\"%s\">\n",
|
|
744 session->passport_info.kv);
|
|
745 fprintf(fd, "<input type=\"hidden\" name=\"id\" value=\"2\">\n");
|
|
746 fprintf(fd, "<input type=\"hidden\" name=\"sl\" value=\"%ld\">\n",
|
|
747 time(NULL) - session->passport_info.sl);
|
|
748 fprintf(fd, "<input type=\"hidden\" name=\"rru\" value=\"%s\">\n",
|
|
749 rru);
|
|
750 fprintf(fd, "<input type=\"hidden\" name=\"auth\" value=\"%s\">\n",
|
|
751 session->passport_info.mspauth);
|
|
752 fprintf(fd, "<input type=\"hidden\" name=\"creds\" value=\"%s\">\n",
|
|
753 sendbuf); /* TODO Digest me (huh? -- ChipX86) */
|
|
754 fprintf(fd, "<input type=\"hidden\" name=\"svc\" value=\"mail\">\n");
|
|
755 fprintf(fd, "<input type=\"hiden\" name=\"js\" value=\"yes\">\n");
|
|
756 fprintf(fd, "</form></body>\n");
|
|
757 fprintf(fd, "</html>\n");
|
|
758
|
|
759 if (fclose(fd)) {
|
|
760 gaim_debug(GAIM_DEBUG_ERROR, "msn",
|
|
761 "Error closing temp passport file: %s\n",
|
|
762 strerror(errno));
|
|
763
|
|
764 unlink(session->passport_info.file);
|
|
765 g_free(session->passport_info.file);
|
|
766 }
|
|
767 else {
|
|
768 /*
|
|
769 * Renaming file with .html extension, so that the
|
|
770 * win32 open_url will work.
|
|
771 */
|
|
772 char *tmp;
|
|
773
|
|
774 if ((tmp = g_strdup_printf("%s.html",
|
|
775 session->passport_info.file)) != NULL) {
|
|
776
|
|
777 if (rename(session->passport_info.file, tmp) == 0) {
|
|
778 g_free(session->passport_info.file);
|
|
779 session->passport_info.file = tmp;
|
|
780 }
|
|
781 else
|
|
782 g_free(tmp);
|
|
783 }
|
|
784 }
|
|
785 }
|
|
786
|
|
787 return TRUE;
|
|
788 }
|
|
789 /**************************************************************************
|
|
790 * Switchboards
|
|
791 **************************************************************************/
|
|
792 static gboolean
|
|
793 __rng_cmd(MsnServConn *servconn, const char *command, const char **params,
|
|
794 size_t param_count)
|
|
795 {
|
|
796 MsnSession *session = servconn->session;
|
|
797 MsnSwitchBoard *swboard;
|
|
798 MsnUser *user;
|
|
799 const char *session_id;
|
|
800 char *host, *c;
|
|
801 int port;
|
|
802
|
|
803 session_id = params[0];
|
|
804
|
|
805 host = g_strdup(params[1]);
|
|
806
|
|
807 if ((c = strchr(host, ':')) != NULL) {
|
|
808 *c = '\0';
|
|
809 port = atoi(c + 1);
|
|
810 }
|
|
811 else
|
|
812 port = 1863;
|
|
813
|
|
814 swboard = msn_switchboard_new(session);
|
|
815
|
|
816 user = msn_user_new(session, params[4], NULL);
|
|
817
|
|
818 msn_switchboard_set_invited(swboard, TRUE);
|
|
819 msn_switchboard_set_session_id(swboard, params[0]);
|
|
820 msn_switchboard_set_auth_key(swboard, params[3]);
|
|
821 msn_switchboard_set_user(swboard, user);
|
|
822
|
|
823 if (!msn_switchboard_connect(swboard, host, port)) {
|
|
824 gaim_debug(GAIM_DEBUG_ERROR, "msn",
|
|
825 "Unable to connect to switchboard on %s, port %d\n",
|
|
826 host, port);
|
|
827
|
|
828 g_free(host);
|
|
829
|
|
830 return FALSE;
|
|
831 }
|
|
832
|
|
833 g_free(host);
|
|
834
|
|
835 return TRUE;
|
|
836 }
|
|
837
|
|
838 static gboolean
|
|
839 __xfr_cmd(MsnServConn *servconn, const char *command, const char **params,
|
|
840 size_t param_count)
|
|
841 {
|
|
842 MsnSession *session = servconn->session;
|
|
843 MsnSwitchBoard *swboard;
|
|
844 struct gaim_connection *gc = session->account->gc;
|
|
845 char *host;
|
|
846 char *c;
|
|
847 int port;
|
|
848
|
|
849 if (strcmp(params[1], "SB")) {
|
|
850 hide_login_progress(gc, _("Got invalid XFR"));
|
|
851 signoff(gc);
|
|
852
|
|
853 return FALSE;
|
|
854 }
|
|
855
|
|
856 host = g_strdup(params[2]);
|
|
857
|
|
858 if ((c = strchr(host, ':')) != NULL) {
|
|
859 *c = '\0';
|
|
860 port = atoi(c + 1);
|
|
861 }
|
|
862 else
|
|
863 port = 1863;
|
|
864
|
|
865 swboard = msn_session_find_unused_switch(session);
|
|
866
|
|
867 if (swboard == NULL) {
|
|
868 gaim_debug(GAIM_DEBUG_ERROR, "msn",
|
|
869 "Received an XFR SB request when there's no unused "
|
|
870 "switchboards!\n");
|
|
871 }
|
|
872
|
|
873 msn_switchboard_set_auth_key(swboard, params[4]);
|
|
874
|
|
875 if (!msn_switchboard_connect(swboard, host, port)) {
|
|
876 gaim_debug(GAIM_DEBUG_ERROR, "msn",
|
|
877 "Unable to connect to switchboard on %s, port %d\n",
|
|
878 host, port);
|
|
879
|
|
880 g_free(host);
|
|
881
|
|
882 return FALSE;
|
|
883 }
|
|
884
|
|
885 g_free(host);
|
|
886
|
|
887 return TRUE;
|
|
888 }
|
|
889
|
|
890 /**************************************************************************
|
|
891 * Message Types
|
|
892 **************************************************************************/
|
|
893 static gboolean
|
|
894 __profile_msg(MsnServConn *servconn, const MsnMessage *msg)
|
|
895 {
|
|
896 MsnSession *session = servconn->session;
|
|
897 const char *value;
|
|
898
|
|
899 if ((value = msn_message_get_attr(msg, "kv")) != NULL)
|
|
900 session->passport_info.kv = g_strdup(value);
|
|
901
|
|
902 if ((value = msn_message_get_attr(msg, "sid")) != NULL)
|
|
903 session->passport_info.sid = g_strdup(value);
|
|
904
|
|
905 if ((value = msn_message_get_attr(msg, "MSPAuth")) != NULL)
|
|
906 session->passport_info.mspauth = g_strdup(value);
|
|
907
|
|
908 return TRUE;
|
|
909 }
|
|
910
|
|
911 static gboolean
|
|
912 __initial_email_msg(MsnServConn *servconn, const MsnMessage *msg)
|
|
913 {
|
|
914 MsnSession *session = servconn->session;
|
|
915 struct gaim_connection *gc = session->account->gc;
|
|
916 GHashTable *table;
|
|
917 const char *unread;
|
|
918
|
|
919 table = msn_message_get_hashtable_from_body(msg);
|
|
920
|
|
921 unread = g_hash_table_lookup(table, "Inbox-Unread");
|
|
922
|
|
923 if (unread != NULL)
|
|
924 connection_has_mail(gc, atoi(unread), NULL, NULL,
|
|
925 session->passport_info.file);
|
|
926
|
|
927 g_hash_table_destroy(table);
|
|
928
|
|
929 return TRUE;
|
|
930 }
|
|
931
|
|
932 static gboolean
|
|
933 __email_msg(MsnServConn *servconn, const MsnMessage *msg)
|
|
934 {
|
|
935 MsnSession *session = servconn->session;
|
|
936 struct gaim_connection *gc = session->account->gc;
|
|
937 GHashTable *table;
|
|
938 const char *from, *subject;
|
|
939
|
|
940 table = msn_message_get_hashtable_from_body(msg);
|
|
941
|
|
942 from = g_hash_table_lookup(table, "From");
|
|
943 subject = g_hash_table_lookup(table, "Subject");
|
|
944
|
|
945 if (from == NULL || subject == NULL) {
|
|
946 connection_has_mail(gc, 1, NULL, NULL, session->passport_info.file);
|
|
947 }
|
|
948 else {
|
|
949 connection_has_mail(gc, -1, from, subject,
|
|
950 session->passport_info.file);
|
|
951 }
|
|
952
|
|
953 g_hash_table_destroy(table);
|
|
954
|
|
955 return TRUE;
|
|
956 }
|
|
957
|
|
958 static gboolean
|
|
959 __connect_cb(gpointer data, gint source, GaimInputCondition cond)
|
|
960 {
|
|
961 MsnServConn *notification = data;
|
|
962 MsnSession *session = notification->session;
|
|
963 struct gaim_connection *gc = session->account->gc;
|
|
964
|
|
965 if (source == -1) {
|
|
966 hide_login_progress(session->account->gc, _("Unable to connect"));
|
|
967 signoff(session->account->gc);
|
|
968 return FALSE;
|
|
969 }
|
|
970
|
|
971 if (notification->fd != source)
|
|
972 notification->fd = source;
|
|
973
|
|
974 if (!msn_servconn_send_command(notification, "VER",
|
|
975 "MSNP6 MSNP5 MSNP4 CVR0")) {
|
|
976 hide_login_progress(gc, _("Unable to write to server"));
|
|
977 signoff(gc);
|
|
978 return FALSE;
|
|
979 }
|
|
980
|
|
981 set_login_progress(session->account->gc, 2, _("Syncing with server"));
|
|
982
|
|
983 return TRUE;
|
|
984 }
|
|
985
|
|
986 static void
|
|
987 __failed_read_cb(gpointer data, gint source, GaimInputCondition cond)
|
|
988 {
|
|
989 MsnServConn *notification = data;
|
|
990 struct gaim_connection *gc;
|
|
991
|
|
992 gc = notification->session->account->gc;
|
|
993
|
|
994 hide_login_progress(gc, _("Error reading from server"));
|
|
995 signoff(gc);
|
|
996 }
|
|
997
|
|
998 MsnServConn *
|
|
999 msn_notification_new(MsnSession *session, const char *server, int port)
|
|
1000 {
|
|
1001 MsnServConn *notification;
|
|
1002
|
|
1003 notification = msn_servconn_new(session);
|
|
1004
|
|
1005 msn_servconn_set_server(notification, server, port);
|
|
1006 msn_servconn_set_connect_cb(notification, __connect_cb);
|
|
1007 msn_servconn_set_failed_read_cb(notification, __failed_read_cb);
|
|
1008
|
|
1009 if (notification_commands == NULL) {
|
|
1010 /* Register the command callbacks. */
|
|
1011 msn_servconn_register_command(notification, "ADD", __add_cmd);
|
|
1012 msn_servconn_register_command(notification, "BLP", __blp_cmd);
|
|
1013 msn_servconn_register_command(notification, "BPR", __blank_cmd);
|
|
1014 msn_servconn_register_command(notification, "CHG", __blank_cmd);
|
|
1015 msn_servconn_register_command(notification, "CHL", __chl_cmd);
|
|
1016 msn_servconn_register_command(notification, "FLN", __fln_cmd);
|
|
1017 msn_servconn_register_command(notification, "GTC", __blank_cmd);
|
|
1018 msn_servconn_register_command(notification, "ILN", __iln_cmd);
|
|
1019 msn_servconn_register_command(notification, "INF", __inf_cmd);
|
|
1020 msn_servconn_register_command(notification, "LSG", __lsg_cmd);
|
|
1021 msn_servconn_register_command(notification, "LST", __lst_cmd);
|
|
1022 msn_servconn_register_command(notification, "MSG", __msg_cmd);
|
|
1023 msn_servconn_register_command(notification, "NLN", __nln_cmd);
|
|
1024 msn_servconn_register_command(notification, "OUT", __out_cmd);
|
|
1025 msn_servconn_register_command(notification, "PRP", __blank_cmd);
|
|
1026 msn_servconn_register_command(notification, "QNG", __blank_cmd);
|
|
1027 msn_servconn_register_command(notification, "QRY", __blank_cmd);
|
|
1028 msn_servconn_register_command(notification, "REA", __rea_cmd);
|
|
1029 msn_servconn_register_command(notification, "REM", __blank_cmd);
|
|
1030 msn_servconn_register_command(notification, "RNG", __rng_cmd);
|
|
1031 msn_servconn_register_command(notification, "SYN", __blank_cmd);
|
|
1032 msn_servconn_register_command(notification, "URL", __url_cmd);
|
|
1033 msn_servconn_register_command(notification, "USR", __usr_cmd);
|
|
1034 msn_servconn_register_command(notification, "VER", __ver_cmd);
|
|
1035 msn_servconn_register_command(notification, "XFR", __xfr_cmd);
|
|
1036 msn_servconn_register_command(notification, "_unknown_", __unknown_cmd);
|
|
1037
|
|
1038 /* Register the message type callbacks. */
|
|
1039 msn_servconn_register_msg_type(notification, "text/x-msmsgsprofile",
|
|
1040 __profile_msg);
|
|
1041 msn_servconn_register_msg_type(notification,
|
|
1042 "text/x-msmsgsinitialemailnotification",
|
|
1043 __initial_email_msg);
|
|
1044 msn_servconn_register_msg_type(notification,
|
|
1045 "text/x-msmsgsemailnotification",
|
|
1046 __email_msg);
|
|
1047
|
|
1048 /* Save these for future use. */
|
|
1049 notification_commands = notification->commands;
|
|
1050 notification_msg_types = notification->msg_types;
|
|
1051 }
|
|
1052 else {
|
|
1053 g_hash_table_destroy(notification->commands);
|
|
1054 g_hash_table_destroy(notification->msg_types);
|
|
1055
|
|
1056 notification->commands = notification_commands;
|
|
1057 notification->msg_types = notification_msg_types;
|
|
1058 }
|
|
1059
|
|
1060 return notification;
|
|
1061 }
|