comparison libpurple/protocols/msn/notification.c @ 20394:4a099e4d0d09

propagate from branch 'im.pidgin.pidgin' (head 98b6b547b29ea1192b73cc4e1de1e674edef4328) to branch 'im.pidgin.rlaager.merging.msnp13-and-pidgin' (head 4d82c29e56bd33cd6f94302e343dfeb5d68ab3eb)
author Richard Laager <rlaager@wiktel.com>
date Sun, 15 Apr 2007 03:43:17 +0000
parents fa8aeab4ca5a
children 6f986caeab59
comparison
equal deleted inserted replaced
20393:40a04930b233 20394:4a099e4d0d09
1 /**
2 * @file notification.c Notification server 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 #include "msn.h"
25 #include "notification.h"
26 #include "state.h"
27 #include "error.h"
28 #include "msnutils.h"
29 #include "page.h"
30
31 #include "userlist.h"
32 #include "sync.h"
33 #include "slplink.h"
34
35 static MsnTable *cbs_table;
36
37 /****************************************************************************
38 * Local Function Prototype
39 ****************************************************************************/
40
41 static void msn_notification_fqy_yahoo(MsnSession *session, const char *passport);
42 static void msn_notification_post_adl(MsnCmdProc *cmdproc, char *payload, int payload_len);
43 static void msn_add_contact_xml(xmlnode *mlNode, const char *passport, int list_op, int type);
44
45 /**************************************************************************
46 * Main
47 **************************************************************************/
48
49 static void
50 destroy_cb(MsnServConn *servconn)
51 {
52 MsnNotification *notification;
53
54 notification = servconn->cmdproc->data;
55 g_return_if_fail(notification != NULL);
56
57 msn_notification_destroy(notification);
58 }
59
60 MsnNotification *
61 msn_notification_new(MsnSession *session)
62 {
63 MsnNotification *notification;
64 MsnServConn *servconn;
65
66 g_return_val_if_fail(session != NULL, NULL);
67
68 notification = g_new0(MsnNotification, 1);
69
70 notification->session = session;
71 notification->servconn = servconn = msn_servconn_new(session, MSN_SERVCONN_NS);
72 msn_servconn_set_destroy_cb(servconn, destroy_cb);
73
74 notification->cmdproc = servconn->cmdproc;
75 notification->cmdproc->data = notification;
76 notification->cmdproc->cbs_table = cbs_table;
77
78 return notification;
79 }
80
81 void
82 msn_notification_destroy(MsnNotification *notification)
83 {
84 notification->cmdproc->data = NULL;
85
86 msn_servconn_set_destroy_cb(notification->servconn, NULL);
87
88 msn_servconn_destroy(notification->servconn);
89
90 g_free(notification);
91 }
92
93 /**************************************************************************
94 * Connect
95 **************************************************************************/
96
97 static void
98 connect_cb(MsnServConn *servconn)
99 {
100 MsnCmdProc *cmdproc;
101 MsnSession *session;
102 PurpleAccount *account;
103 char **a, **c, *vers;
104 int i;
105
106 g_return_if_fail(servconn != NULL);
107
108 cmdproc = servconn->cmdproc;
109 session = servconn->session;
110 account = session->account;
111
112 /* Allocate an array for CVR0, NULL, and all the versions */
113 // a = c = g_new0(char *, session->protocol_ver - WLM_MIN_PROTOCOL + 3);
114 a = c = g_new0(char *, WLM_MAX_PROTOCOL - WLM_MIN_PROTOCOL + 3);
115
116 // for (i = session->protocol_ver; i >= WLM_MIN_PROTOCOL; i--)
117 for (i = WLM_MAX_PROTOCOL; i >= WLM_MIN_PROTOCOL; i--)
118 *c++ = g_strdup_printf("MSNP%d", i);
119
120 *c++ = g_strdup("CVR0");
121
122 vers = g_strjoinv(" ", a);
123
124 if (session->login_step == MSN_LOGIN_STEP_START){
125 msn_session_set_login_step(session, MSN_LOGIN_STEP_HANDSHAKE);
126 }else{
127 msn_session_set_login_step(session, MSN_LOGIN_STEP_HANDSHAKE2);
128 }
129
130 msn_cmdproc_send(cmdproc, "VER", "%s", vers);
131
132 g_strfreev(a);
133 g_free(vers);
134 }
135
136 gboolean
137 msn_notification_connect(MsnNotification *notification, const char *host, int port)
138 {
139 MsnServConn *servconn;
140
141 g_return_val_if_fail(notification != NULL, FALSE);
142
143 servconn = notification->servconn;
144
145 msn_servconn_set_connect_cb(servconn, connect_cb);
146 notification->in_use = msn_servconn_connect(servconn, host, port);
147
148 return notification->in_use;
149 }
150
151 void
152 msn_notification_disconnect(MsnNotification *notification)
153 {
154 g_return_if_fail(notification != NULL);
155 g_return_if_fail(notification->in_use);
156
157 msn_servconn_disconnect(notification->servconn);
158
159 notification->in_use = FALSE;
160 }
161
162 /**************************************************************************
163 * Util
164 **************************************************************************/
165
166 static void
167 group_error_helper(MsnSession *session, const char *msg, const char *group_id, int error)
168 {
169 PurpleAccount *account;
170 PurpleConnection *gc;
171 char *reason = NULL;
172 char *title = NULL;
173
174 account = session->account;
175 gc = purple_account_get_connection(account);
176
177 if (error == 224){
178 if (group_id == 0){
179 return;
180 }else{
181 const char *group_name;
182 group_name = msn_userlist_find_group_name(session->userlist,group_id);
183 reason = g_strdup_printf(_("%s is not a valid group."),
184 group_name);
185 }
186 }else{
187 reason = g_strdup(_("Unknown error."));
188 }
189
190 title = g_strdup_printf(_("%s on %s (%s)"), msg,
191 purple_account_get_username(account),
192 purple_account_get_protocol_name(account));
193 purple_notify_error(gc, NULL, title, reason);
194 g_free(title);
195 g_free(reason);
196 }
197
198 /**************************************************************************
199 * Login
200 **************************************************************************/
201
202 void
203 msn_got_login_params(MsnSession *session, const char *login_params)
204 {
205 MsnCmdProc *cmdproc;
206
207 cmdproc = session->notification->cmdproc;
208
209 msn_session_set_login_step(session, MSN_LOGIN_STEP_AUTH_END);
210
211 msn_cmdproc_send(cmdproc, "USR", "TWN S %s", login_params);
212 }
213
214 static void
215 cvr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
216 {
217 PurpleAccount *account;
218
219 account = cmdproc->session->account;
220 msn_cmdproc_send(cmdproc, "USR", "TWN I %s",
221 purple_account_get_username(account));
222 }
223
224 static void
225 usr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
226 {
227 MsnSession *session;
228 PurpleAccount *account;
229 PurpleConnection *gc;
230
231 session = cmdproc->session;
232 account = session->account;
233 gc = purple_account_get_connection(account);
234
235 if (!g_ascii_strcasecmp(cmd->params[1], "OK")){
236 /* authenticate OK */
237 /* friendly name part no longer true in msnp11 */
238 #if 0
239 const char *friendly = purple_url_decode(cmd->params[3]);
240
241 purple_connection_set_display_name(gc, friendly);
242 #endif
243 msn_session_set_login_step(session, MSN_LOGIN_STEP_SYN);
244
245 // msn_cmdproc_send(cmdproc, "SYN", "%s", "0");
246 //TODO we should use SOAP contact to fetch contact list
247 } else if (!g_ascii_strcasecmp(cmd->params[1], "TWN")){
248 /* Passport authentication */
249 char **elems, **cur, **tokens;
250
251 session->nexus = msn_nexus_new(session);
252
253 /* Parse the challenge data. */
254 session->nexus->challenge_data_str = g_strdup(cmd->params[3]);
255 elems = g_strsplit(cmd->params[3], ",", 0);
256
257 for (cur = elems; *cur != NULL; cur++){
258 tokens = g_strsplit(*cur, "=", 2);
259 if(tokens[0]&&tokens[1]){
260 purple_debug_info("MaYuan","challenge %p,key:%s,value:%s\n",
261 session->nexus->challenge_data,tokens[0],tokens[1]);
262 g_hash_table_insert(session->nexus->challenge_data, tokens[0], tokens[1]);
263 }
264 /* Don't free each of the tokens, only the array. */
265 g_free(tokens);
266 }
267
268 g_strfreev(elems);
269
270 msn_session_set_login_step(session, MSN_LOGIN_STEP_AUTH_START);
271
272 msn_nexus_connect(session->nexus);
273 }
274 }
275
276 static void
277 usr_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
278 {
279 MsnErrorType msnerr = 0;
280
281 switch (error)
282 {
283 case 500:
284 case 601:
285 case 910:
286 case 921:
287 msnerr = MSN_ERROR_SERV_UNAVAILABLE;
288 break;
289 case 911:
290 msnerr = MSN_ERROR_AUTH;
291 break;
292 default:
293 return;
294 break;
295 }
296
297 msn_session_set_error(cmdproc->session, msnerr, NULL);
298 }
299
300 static void
301 ver_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
302 {
303 MsnSession *session;
304 PurpleAccount *account;
305 gboolean protocol_supported = FALSE;
306 char proto_str[8];
307 size_t i;
308
309 session = cmdproc->session;
310 account = session->account;
311
312 g_snprintf(proto_str, sizeof(proto_str), "MSNP%d", session->protocol_ver);
313
314 for (i = 1; i < cmd->param_count; i++)
315 {
316 if (!strcmp(cmd->params[i], proto_str))
317 {
318 protocol_supported = TRUE;
319 break;
320 }
321 }
322
323 if (!protocol_supported)
324 {
325 msn_session_set_error(session, MSN_ERROR_UNSUPPORTED_PROTOCOL,
326 NULL);
327 return;
328 }
329
330 /*
331 * Windows Live Messenger 8.0
332 * Notice :CVR String discriminate!
333 * reference of http://www.microsoft.com/globaldev/reference/oslocversion.mspx
334 * to see the Local ID
335 */
336 msn_cmdproc_send(cmdproc, "CVR",
337 // "0x0409 winnt 5.1 i386 MSG80BETA 8.0.0689 msmsgs %s",
338 "0x0804 winnt 5.1 i386 MSNMSGR 8.0.0792 msmsgs %s",
339 purple_account_get_username(account));
340 }
341
342 /**************************************************************************
343 * Log out
344 **************************************************************************/
345
346 static void
347 out_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
348 {
349 if (!g_ascii_strcasecmp(cmd->params[0], "OTH"))
350 msn_session_set_error(cmdproc->session, MSN_ERROR_SIGN_OTHER,
351 NULL);
352 else if (!g_ascii_strcasecmp(cmd->params[0], "SSD"))
353 msn_session_set_error(cmdproc->session, MSN_ERROR_SERV_DOWN, NULL);
354 }
355
356 void
357 msn_notification_close(MsnNotification *notification)
358 {
359 g_return_if_fail(notification != NULL);
360
361 if (!notification->in_use)
362 return;
363
364 msn_cmdproc_send_quick(notification->cmdproc, "OUT", NULL, NULL);
365
366 msn_notification_disconnect(notification);
367 }
368
369 /**************************************************************************
370 * Messages
371 **************************************************************************/
372
373 static void
374 msg_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
375 size_t len)
376 {
377 MsnMessage *msg;
378
379 msg = msn_message_new_from_cmd(cmdproc->session, cmd);
380
381 msn_message_parse_payload(msg, payload, len,MSG_LINE_DEM,MSG_BODY_DEM);
382 #ifdef MSN_DEBUG_NS
383 msn_message_show_readable(msg, "Notification", TRUE);
384 #endif
385
386 msn_cmdproc_process_msg(cmdproc, msg);
387
388 msn_message_destroy(msg);
389 }
390
391 static void
392 msg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
393 {
394 purple_debug_info("MaYuan","Processing MSG... \n");
395 if(cmd->payload_len == 0){
396 return;
397 }
398 /* NOTE: cmd is not always cmdproc->last_cmd, sometimes cmd is a queued
399 * command and we are processing it */
400 if (cmd->payload == NULL)
401 {
402 cmdproc->last_cmd->payload_cb = msg_cmd_post;
403 cmdproc->servconn->payload_len = atoi(cmd->params[2]);
404 }
405 else
406 {
407 g_return_if_fail(cmd->payload_cb != NULL);
408
409 purple_debug_info("MaYuan","MSG payload:{%s}\n",cmd->payload);
410 cmd->payload_cb(cmdproc, cmd, cmd->payload, cmd->payload_len);
411 }
412 }
413
414 /*send Message to Yahoo Messenger*/
415 void
416 uum_send_msg(MsnSession *session,MsnMessage *msg)
417 {
418 MsnCmdProc *cmdproc;
419 MsnTransaction *trans;
420 char *payload;
421 gsize payload_len;
422 int type;
423
424 cmdproc = session->notification->cmdproc;
425 g_return_if_fail(msg != NULL);
426 payload = msn_message_gen_payload(msg, &payload_len);
427 purple_debug_info("MaYuan","send UUM,payload{%s},strlen:%d,len:%d\n",
428 payload,strlen(payload),payload_len);
429 type = msg->type;
430 trans = msn_transaction_new(cmdproc, "UUM","%s 32 %d %d",msg->remote_user,type,payload_len);
431 msn_transaction_set_payload(trans, payload, strlen(payload));
432 msn_cmdproc_send_trans(cmdproc, trans);
433 }
434
435 static void
436 ubm_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
437 size_t len)
438 {
439 MsnMessage *msg;
440 PurpleConnection *gc;
441 const char *passport;
442 const char *content_type;
443
444 purple_debug_info("MaYuan","Process UBM payload:%s\n",payload);
445 msg = msn_message_new_from_cmd(cmdproc->session, cmd);
446
447 msn_message_parse_payload(msg, payload, len,MSG_LINE_DEM,MSG_BODY_DEM);
448 #ifdef MSN_DEBUG_NS
449 msn_message_show_readable(msg, "Notification", TRUE);
450 #endif
451
452 gc = cmdproc->session->account->gc;
453 passport = msg->remote_user;
454
455 content_type = msn_message_get_content_type(msg);
456 purple_debug_info("MaYuan","type:%d\n",content_type);
457 if(!strcmp(content_type,"text/plain")){
458 const char *value;
459 const char *body;
460 char *body_str;
461 char *body_enc;
462 char *body_final = NULL;
463 size_t body_len;
464
465 body = msn_message_get_bin_data(msg, &body_len);
466 body_str = g_strndup(body, body_len);
467 body_enc = g_markup_escape_text(body_str, -1);
468 g_free(body_str);
469
470 if ((value = msn_message_get_attr(msg, "X-MMS-IM-Format")) != NULL) {
471 char *pre, *post;
472
473 msn_parse_format(value, &pre, &post);
474 body_final = g_strdup_printf("%s%s%s", pre ? pre : "",
475 body_enc ? body_enc : "", post ? post : "");
476 g_free(pre);
477 g_free(post);
478 g_free(body_enc);
479 }
480 serv_got_im(gc, passport, body_final, 0, time(NULL));
481 }
482 if(!strcmp(content_type,"text/x-msmsgscontrol")){
483 if(msn_message_get_attr(msg, "TypingUser") != NULL){
484 serv_got_typing(gc, passport, MSN_TYPING_RECV_TIMEOUT,
485 PURPLE_TYPING);
486 }
487 }
488 if(!strcmp(content_type,"text/x-msnmsgr-datacast")){
489 char *username, *str;
490 PurpleAccount *account;
491 PurpleBuddy *buddy;
492 const char *user;
493
494 account = cmdproc->session->account;
495 user = msg->remote_user;
496
497 if ((buddy = purple_find_buddy(account, user)) != NULL){
498 username = g_markup_escape_text(purple_buddy_get_alias(buddy), -1);
499 }else{
500 username = g_markup_escape_text(user, -1);
501 }
502
503 str = g_strdup_printf(_("%s just sent you a Nudge!"), username);
504 g_free(username);
505 msn_session_report_user(cmdproc->session,user,str,PURPLE_MESSAGE_SYSTEM);
506 g_free(str);
507 }
508 msn_message_destroy(msg);
509 }
510
511 /*Yahoo msg process*/
512 static void
513 ubm_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
514 {
515 purple_debug_info("MaYuan","Processing UBM... \n");
516 if(cmd->payload_len == 0){
517 return;
518 }
519 /* NOTE: cmd is not always cmdproc->last_cmd, sometimes cmd is a queued
520 * command and we are processing it */
521 if (cmd->payload == NULL){
522 cmdproc->last_cmd->payload_cb = ubm_cmd_post;
523 cmdproc->servconn->payload_len = atoi(cmd->params[2]);
524 }else{
525 g_return_if_fail(cmd->payload_cb != NULL);
526
527 purple_debug_info("MaYuan","UBM payload:{%s}\n",cmd->payload);
528 ubm_cmd_post(cmdproc, cmd, cmd->payload, cmd->payload_len);
529 }
530 }
531
532 /**************************************************************************
533 * Challenges
534 * we use MD5 to caculate the Chanllenges
535 **************************************************************************/
536 static void
537 chl_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
538 {
539 MsnTransaction *trans;
540 char buf[33];
541
542 #if 0
543 cipher = purple_ciphers_find_cipher("md5");
544 context = purple_cipher_context_new(cipher, NULL);
545 purple_cipher_context_append(context, (const guchar *)cmd->params[1],
546 strlen(cmd->params[1]));
547 challenge_resp = MSNP13_WLM_PRODUCT_KEY;
548
549 purple_cipher_context_append(context, (const guchar *)challenge_resp,
550 strlen(challenge_resp));
551 purple_cipher_context_digest(context, sizeof(digest), digest, NULL);
552 purple_cipher_context_destroy(context);
553
554 for (i = 0; i < 16; i++){
555 g_snprintf(buf + (i*2), 3, "%02x", digest[i]);
556 }
557 #else
558 msn_handle_chl(cmd->params[1], buf);
559 #endif
560 // purple_debug_info("MaYuan","<<challenge:{%s}:{%s}\n",cmd->params[1],buf);
561 trans = msn_transaction_new(cmdproc, "QRY", "%s 32", MSNP13_WLM_PRODUCT_ID);
562
563 msn_transaction_set_payload(trans, buf, 32);
564
565 msn_cmdproc_send_trans(cmdproc, trans);
566 }
567
568 /**************************************************************************
569 * Buddy Lists
570 **************************************************************************/
571 /* add contact to xmlnode */
572 static void
573 msn_add_contact_xml(xmlnode *mlNode,const char *passport,int list_op,int type)
574 {
575 xmlnode *d_node,*c_node;
576 char **tokens;
577 char *email,*domain;
578 char *list_op_str,*type_str;
579
580 purple_debug_info("MaYuan","passport:%s\n",passport);
581 tokens = g_strsplit(passport, "@", 2);
582 email = tokens[0];
583 domain = tokens[1];
584
585 /*find a domain Node*/
586 for(d_node = xmlnode_get_child(mlNode,"d"); d_node; d_node = xmlnode_get_next_twin(d_node)){
587 const char * attr = NULL;
588 purple_debug_info("MaYuan","d_node:%s\n",d_node->name);
589 attr = xmlnode_get_attrib(d_node,"n");
590 if(attr == NULL){
591 continue;
592 }
593 if(!strcmp(attr,domain)){
594 break;
595 }
596 }
597 if(d_node == NULL){
598 /*domain not found, create a new domain Node*/
599 purple_debug_info("MaYuan","get No d_node\n");
600 d_node = xmlnode_new("d");
601 xmlnode_set_attrib(d_node,"n",domain);
602 xmlnode_insert_child(mlNode,d_node);
603 }
604
605 /*create contact node*/
606 c_node = xmlnode_new("c");
607 xmlnode_set_attrib(c_node,"n",email);
608
609 list_op_str = g_strdup_printf("%d",list_op);
610 purple_debug_info("MaYuan","list_op:%d\n",list_op_str);
611 xmlnode_set_attrib(c_node,"l",list_op_str);
612 g_free(list_op_str);
613 #if 0
614 type_str = g_strdup_printf("%d",type);
615 xmlnode_set_attrib(c_node,"t",type_str);
616 #else
617 if(g_strrstr(domain,"yahoo") != NULL){
618 type_str = g_strdup_printf("32");
619 }else{
620 /*passport*/
621 type_str = g_strdup_printf("1");
622 }
623 /*mobile*/
624 //type_str = g_strdup_printf("4");
625 xmlnode_set_attrib(c_node,"t",type_str);
626 g_free(type_str);
627 #endif
628 xmlnode_insert_child(d_node, c_node);
629
630 g_free(tokens);
631 }
632
633 static void
634 msn_notification_post_adl(MsnCmdProc *cmdproc, char *payload, int payload_len)
635 {
636 MsnTransaction *trans;
637
638 purple_debug_info("MaYuan","Send ADL{%s}\n",payload);
639 trans = msn_transaction_new(cmdproc, "ADL","%d",strlen(payload));
640 msn_transaction_set_payload(trans, payload, strlen(payload));
641 msn_cmdproc_send_trans(cmdproc, trans);
642 }
643
644 /*dump contact info to NS*/
645 void
646 msn_notification_dump_contact(MsnSession *session)
647 {
648 MsnUserList *userlist;
649 MsnUser *user;
650 GList *l;
651 xmlnode *adl_node;
652 char *payload;
653 int payload_len;
654 const char *display_name;
655
656 userlist = session->userlist;
657 adl_node = xmlnode_new("ml");
658 adl_node->child = NULL;
659 xmlnode_set_attrib(adl_node, "l", "1");
660
661 /*get the userlist*/
662 for (l = userlist->users; l != NULL; l = l->next){
663 user = l->data;
664 msn_add_contact_xml(adl_node,user->passport,user->list_op&MSN_LIST_OP_MASK,user->type);
665 }
666
667 payload = xmlnode_to_str(adl_node,&payload_len);
668 xmlnode_free(adl_node);
669
670 msn_notification_post_adl(session->notification->cmdproc,payload,payload_len);
671
672 display_name = purple_connection_get_display_name(session->account->gc);
673 if (display_name && strcmp(display_name,
674 purple_account_get_username(session->account))) {
675 msn_act_id(session->account->gc, display_name);
676 }
677
678 }
679
680 /*Post FQY to NS,Inform add a Yahoo User*/
681 static void
682 msn_notification_fqy_yahoo(MsnSession *session, const char *passport)
683 {
684 MsnTransaction *trans;
685 MsnCmdProc *cmdproc;
686 char* email,*domain,*payload;
687 char **tokens;
688
689 cmdproc = session->notification->cmdproc;
690
691 tokens = g_strsplit(passport, "@", 2);
692 email = tokens[0];
693 domain = tokens[1];
694
695 payload = g_strdup_printf("<ml><d n=\"%s\"><c n=\"%s\"/></d></ml>",domain,email);
696 trans = msn_transaction_new(cmdproc, "FQY","%d",strlen(payload));
697 msn_transaction_set_payload(trans, payload, strlen(payload));
698 msn_cmdproc_send_trans(cmdproc, trans);
699
700 g_free(payload);
701 g_free(tokens);
702 }
703
704 static void
705 blp_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
706 {
707 purple_debug_info("MaYuan","Process BLP\n");
708 }
709
710 static void
711 adl_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
712 {
713 purple_debug_info("MaYuan","Process ADL\n");
714 }
715
716 static void
717 fqy_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
718 size_t len)
719 {
720 purple_debug_info("MaYuan","FQY payload{%s}\n",payload);
721 msn_notification_post_adl(cmdproc,payload,len);
722 }
723
724 static void
725 fqy_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
726 {
727 purple_debug_info("MaYuan","Process FQY\n");
728 cmdproc->last_cmd->payload_cb = fqy_cmd_post;
729 }
730
731 static void
732 rml_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
733 {
734 #if 0
735 MsnTransaction *trans;
736 char * payload;
737 #endif
738
739 purple_debug_info("MaYuan","Process ADL\n");
740 #if 0
741 trans = msn_transaction_new(cmdproc, "RML","");
742
743 msn_transaction_set_payload(trans, payload, strlen(payload));
744
745 msn_cmdproc_send_trans(cmdproc, trans);
746 #endif
747 }
748
749 static void
750 add_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
751 {
752 MsnSession *session;
753 PurpleAccount *account;
754 PurpleConnection *gc;
755 const char *list, *passport;
756 char *reason = NULL;
757 char *msg = NULL;
758 char **params;
759
760 session = cmdproc->session;
761 account = session->account;
762 gc = purple_account_get_connection(account);
763 params = g_strsplit(trans->params, " ", 0);
764
765 list = params[0];
766 passport = params[1];
767
768 if (!strcmp(list, "FL"))
769 msg = g_strdup_printf(_("Unable to add user on %s (%s)"),
770 purple_account_get_username(account),
771 purple_account_get_protocol_name(account));
772 else if (!strcmp(list, "BL"))
773 msg = g_strdup_printf(_("Unable to block user on %s (%s)"),
774 purple_account_get_username(account),
775 purple_account_get_protocol_name(account));
776 else if (!strcmp(list, "AL"))
777 msg = g_strdup_printf(_("Unable to permit user on %s (%s)"),
778 purple_account_get_username(account),
779 purple_account_get_protocol_name(account));
780
781 if (!strcmp(list, "FL"))
782 {
783 if (error == 210)
784 {
785 reason = g_strdup_printf(_("%s could not be added because "
786 "your buddy list is full."), passport);
787 }
788 }
789
790 if (reason == NULL)
791 {
792 if (error == 208)
793 {
794 reason = g_strdup_printf(_("%s is not a valid passport account."),
795 passport);
796 }
797 else if (error == 500)
798 {
799 reason = g_strdup(_("Service Temporarily Unavailable."));
800 }
801 else
802 {
803 reason = g_strdup(_("Unknown error."));
804 }
805 }
806
807 if (msg != NULL)
808 {
809 purple_notify_error(gc, NULL, msg, reason);
810 g_free(msg);
811 }
812
813 if (!strcmp(list, "FL"))
814 {
815 PurpleBuddy *buddy;
816
817 buddy = purple_find_buddy(account, passport);
818
819 if (buddy != NULL)
820 purple_blist_remove_buddy(buddy);
821 }
822
823 g_free(reason);
824
825 g_strfreev(params);
826 }
827
828 static void
829 adg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
830 {
831 MsnSession *session;
832 gint group_id;
833 const char *group_name;
834
835 session = cmdproc->session;
836
837 group_id = atoi(cmd->params[3]);
838
839 group_name = purple_url_decode(cmd->params[2]);
840
841 msn_group_new(session->userlist, cmd->params[3], group_name);
842
843 /* There is a user that must me moved to this group */
844 if (cmd->trans->data)
845 {
846 /* msn_userlist_move_buddy(); */
847 MsnUserList *userlist = cmdproc->session->userlist;
848 MsnMoveBuddy *data = cmd->trans->data;
849
850 if (data->old_group_name != NULL)
851 {
852 msn_userlist_rem_buddy(userlist, data->who, MSN_LIST_FL, data->old_group_name);
853 g_free(data->old_group_name);
854 }
855
856 msn_userlist_add_buddy(userlist, data->who, MSN_LIST_FL, group_name);
857 g_free(data->who);
858
859 }
860 }
861
862 static void
863 fln_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
864 {
865 MsnSlpLink *slplink;
866 MsnUser *user;
867
868 user = msn_userlist_find_user(cmdproc->session->userlist, cmd->params[0]);
869
870 user->status = "offline";
871 msn_user_update(user);
872
873 slplink = msn_session_find_slplink(cmdproc->session, cmd->params[0]);
874
875 if (slplink != NULL)
876 msn_slplink_destroy(slplink);
877
878 }
879
880 static void
881 iln_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
882 {
883 MsnSession *session;
884 PurpleAccount *account;
885 PurpleConnection *gc;
886 MsnUser *user;
887 MsnObject *msnobj;
888 int wlmclient;
889 const char *state, *passport, *friendly;
890
891 session = cmdproc->session;
892 account = session->account;
893 gc = purple_account_get_connection(account);
894
895 state = cmd->params[1];
896 passport = cmd->params[2];
897 /*if a contact is actually on the WLM part or the yahoo part*/
898 wlmclient = atoi(cmd->params[3]);
899 friendly = purple_url_decode(cmd->params[4]);
900
901 user = msn_userlist_find_user(session->userlist, passport);
902
903 serv_got_alias(gc, passport, friendly);
904
905 msn_user_set_friendly_name(user, friendly);
906
907 if (session->protocol_ver >= 9 && cmd->param_count == 8)
908 {
909 msnobj = msn_object_new_from_string(purple_url_decode(cmd->params[5]));
910 msn_user_set_object(user, msnobj);
911 }
912
913 msn_user_set_state(user, state);
914 msn_user_update(user);
915 }
916
917 static void
918 ipg_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len)
919 {
920 #if 0
921 purple_debug_misc("msn", "Incoming Page: {%s}\n", payload);
922 #endif
923 }
924
925 static void
926 ipg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
927 {
928 cmdproc->servconn->payload_len = atoi(cmd->params[0]);
929 cmdproc->last_cmd->payload_cb = ipg_cmd_post;
930 }
931
932 static void
933 nln_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
934 {
935 MsnSession *session;
936 PurpleAccount *account;
937 PurpleConnection *gc;
938 MsnUser *user;
939 MsnObject *msnobj;
940 int clientid;
941 int wlmclient;
942 const char *state, *passport, *friendly, *old_friendly;
943
944 session = cmdproc->session;
945 account = session->account;
946 gc = purple_account_get_connection(account);
947
948 state = cmd->params[0];
949 passport = cmd->params[1];
950 wlmclient = atoi(cmd->params[2]);
951 friendly = purple_url_decode(cmd->params[3]);
952
953 user = msn_userlist_find_user(session->userlist, passport);
954
955 old_friendly = msn_user_get_friendly_name(user);
956 if (!old_friendly || (old_friendly && strcmp(old_friendly, friendly)))
957 {
958 serv_got_alias(gc, passport, friendly);
959 msn_user_set_friendly_name(user, friendly);
960 }
961
962 if (session->protocol_ver >= 9)
963 {
964 if (cmd->param_count == 7)
965 {
966 msnobj =
967 msn_object_new_from_string(purple_url_decode(cmd->params[4]));
968 msn_user_set_object(user, msnobj);
969 }
970 else
971 {
972 msn_user_set_object(user, NULL);
973 }
974 }
975
976 clientid = atoi(cmd->params[4]);
977 user->mobile = (clientid & MSN_CLIENT_CAP_MSNMOBILE);
978
979 msn_user_set_state(user, state);
980 msn_user_update(user);
981 }
982
983 #if 0
984 static void
985 chg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
986 {
987 char *state = cmd->params[1];
988 int state_id = 0;
989
990 if (!strcmp(state, "NLN"))
991 state_id = MSN_ONLINE;
992 else if (!strcmp(state, "BSY"))
993 state_id = MSN_BUSY;
994 else if (!strcmp(state, "IDL"))
995 state_id = MSN_IDLE;
996 else if (!strcmp(state, "BRB"))
997 state_id = MSN_BRB;
998 else if (!strcmp(state, "AWY"))
999 state_id = MSN_AWAY;
1000 else if (!strcmp(state, "PHN"))
1001 state_id = MSN_PHONE;
1002 else if (!strcmp(state, "LUN"))
1003 state_id = MSN_LUNCH;
1004 else if (!strcmp(state, "HDN"))
1005 state_id = MSN_HIDDEN;
1006
1007 cmdproc->session->state = state_id;
1008 }
1009 #endif
1010
1011
1012 static void
1013 not_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len)
1014 {
1015 #if 0
1016 MSN_SET_PARAMS("NOT %d\r\n%s", cmdproc->servconn->payload, payload);
1017 purple_debug_misc("msn", "Notification: {%s}\n", payload);
1018 #endif
1019 }
1020
1021 static void
1022 not_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
1023 {
1024 cmdproc->servconn->payload_len = atoi(cmd->params[0]);
1025 cmdproc->last_cmd->payload_cb = not_cmd_post;
1026 }
1027
1028 static void
1029 rea_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
1030 {
1031 /* TODO: This might be for us too */
1032
1033 MsnSession *session;
1034 PurpleConnection *gc;
1035 const char *friendly;
1036
1037 session = cmdproc->session;
1038 gc = session->account->gc;
1039 friendly = purple_url_decode(cmd->params[3]);
1040
1041 purple_connection_set_display_name(gc, friendly);
1042 }
1043
1044 static void
1045 prp_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
1046 {
1047 MsnSession *session = cmdproc->session;
1048 const char *type, *value;
1049
1050 g_return_if_fail(cmd->param_count >= 3);
1051
1052 type = cmd->params[2];
1053
1054 if (cmd->param_count == 4)
1055 {
1056 value = cmd->params[3];
1057 if (!strcmp(type, "PHH"))
1058 msn_user_set_home_phone(session->user, purple_url_decode(value));
1059 else if (!strcmp(type, "PHW"))
1060 msn_user_set_work_phone(session->user, purple_url_decode(value));
1061 else if (!strcmp(type, "PHM"))
1062 msn_user_set_mobile_phone(session->user, purple_url_decode(value));
1063 }
1064 else
1065 {
1066 if (!strcmp(type, "PHH"))
1067 msn_user_set_home_phone(session->user, NULL);
1068 else if (!strcmp(type, "PHW"))
1069 msn_user_set_work_phone(session->user, NULL);
1070 else if (!strcmp(type, "PHM"))
1071 msn_user_set_mobile_phone(session->user, NULL);
1072 else if (!strcmp(type, "MFM")) {
1073 type = cmd->params[1];
1074 purple_connection_set_display_name(
1075 purple_account_get_connection(session->account),
1076 purple_url_decode(cmd->params[2]));
1077 }
1078 }
1079 }
1080
1081 static void
1082 reg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
1083 {
1084 MsnSession *session;
1085 const char *group_id, *group_name;
1086
1087 session = cmdproc->session;
1088 group_id = cmd->params[2];
1089 group_name = purple_url_decode(cmd->params[3]);
1090
1091 msn_userlist_rename_group_id(session->userlist, group_id, group_name);
1092 }
1093
1094 static void
1095 reg_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
1096 {
1097 const char * group_id;
1098 char **params;
1099
1100 params = g_strsplit(trans->params, " ", 0);
1101
1102 group_id = params[0];
1103
1104 group_error_helper(cmdproc->session, _("Unable to rename group"), group_id, error);
1105
1106 g_strfreev(params);
1107 }
1108
1109 static void
1110 rem_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
1111 {
1112 MsnSession *session;
1113 MsnUser *user;
1114 const char *group_id, *list, *passport;
1115 MsnListId list_id;
1116
1117 session = cmdproc->session;
1118 list = cmd->params[1];
1119 passport = cmd->params[3];
1120 user = msn_userlist_find_user(session->userlist, passport);
1121
1122 g_return_if_fail(user != NULL);
1123
1124 list_id = msn_get_list_id(list);
1125
1126 if (cmd->param_count == 5)
1127 group_id = cmd->params[4];
1128 else
1129 group_id = NULL;
1130
1131 msn_got_rem_user(session, user, list_id, group_id);
1132 msn_user_update(user);
1133 }
1134
1135 static void
1136 rmg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
1137 {
1138 MsnSession *session;
1139 const char *group_id;
1140
1141 session = cmdproc->session;
1142 group_id = cmd->params[2];
1143
1144 msn_userlist_remove_group_id(session->userlist, group_id);
1145 }
1146
1147 static void
1148 rmg_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
1149 {
1150 const char *group_id;
1151 char **params;
1152
1153 params = g_strsplit(trans->params, " ", 0);
1154
1155 group_id = atoi(params[0]);
1156
1157 group_error_helper(cmdproc->session, _("Unable to delete group"), group_id, error);
1158
1159 g_strfreev(params);
1160 }
1161
1162 static void
1163 syn_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
1164 {
1165 MsnSession *session;
1166 int total_users;
1167
1168 session = cmdproc->session;
1169
1170 if (cmd->param_count == 2)
1171 {
1172 /*
1173 * This can happen if we sent a SYN with an up-to-date
1174 * buddy list revision, but we send 0 to get a full list.
1175 * So, error out.
1176 */
1177
1178 msn_session_set_error(cmdproc->session, MSN_ERROR_BAD_BLIST, NULL);
1179 return;
1180 }
1181
1182 total_users = atoi(cmd->params[2]);
1183
1184 if (total_users == 0)
1185 {
1186 msn_session_finish_login(session);
1187 }
1188 else
1189 {
1190 /* syn_table */
1191 MsnSync *sync;
1192
1193 sync = msn_sync_new(session);
1194 sync->total_users = total_users;
1195 sync->old_cbs_table = cmdproc->cbs_table;
1196
1197 session->sync = sync;
1198 cmdproc->cbs_table = sync->cbs_table;
1199 }
1200 }
1201
1202 /**************************************************************************
1203 * Misc commands
1204 **************************************************************************/
1205
1206 static void
1207 url_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
1208 {
1209 MsnSession *session;
1210 PurpleAccount *account;
1211 const char *rru;
1212 const char *url;
1213 PurpleCipher *cipher;
1214 PurpleCipherContext *context;
1215 guchar digest[16];
1216 FILE *fd;
1217 char *buf;
1218 char buf2[3];
1219 char sendbuf[64];
1220 int i;
1221
1222 session = cmdproc->session;
1223 account = session->account;
1224
1225 rru = cmd->params[1];
1226 url = cmd->params[2];
1227
1228 buf = g_strdup_printf("%s%lu%s",
1229 session->passport_info.mspauth,
1230 time(NULL) - session->passport_info.sl,
1231 purple_connection_get_password(account->gc));
1232
1233 cipher = purple_ciphers_find_cipher("md5");
1234 context = purple_cipher_context_new(cipher, NULL);
1235
1236 purple_cipher_context_append(context, (const guchar *)buf, strlen(buf));
1237 purple_cipher_context_digest(context, sizeof(digest), digest, NULL);
1238 purple_cipher_context_destroy(context);
1239
1240 g_free(buf);
1241
1242 memset(sendbuf, 0, sizeof(sendbuf));
1243
1244 for (i = 0; i < 16; i++)
1245 {
1246 g_snprintf(buf2, sizeof(buf2), "%02x", digest[i]);
1247 strcat(sendbuf, buf2);
1248 }
1249
1250 if (session->passport_info.file != NULL)
1251 {
1252 g_unlink(session->passport_info.file);
1253 g_free(session->passport_info.file);
1254 }
1255
1256 if ((fd = purple_mkstemp(&session->passport_info.file, FALSE)) == NULL)
1257 {
1258 purple_debug_error("msn",
1259 "Error opening temp passport file: %s\n",
1260 strerror(errno));
1261 }
1262 else
1263 {
1264 fputs("<html>\n"
1265 "<head>\n"
1266 "<noscript>\n"
1267 "<meta http-equiv=\"Refresh\" content=\"0; "
1268 "url=http://www.hotmail.com\">\n"
1269 "</noscript>\n"
1270 "</head>\n\n",
1271 fd);
1272
1273 fprintf(fd, "<body onload=\"document.pform.submit(); \">\n");
1274 fprintf(fd, "<form name=\"pform\" action=\"%s\" method=\"POST\">\n\n",
1275 url);
1276 fprintf(fd, "<input type=\"hidden\" name=\"mode\" value=\"ttl\">\n");
1277 fprintf(fd, "<input type=\"hidden\" name=\"login\" value=\"%s\">\n",
1278 purple_account_get_username(account));
1279 fprintf(fd, "<input type=\"hidden\" name=\"username\" value=\"%s\">\n",
1280 purple_account_get_username(account));
1281 if (session->passport_info.sid != NULL)
1282 fprintf(fd, "<input type=\"hidden\" name=\"sid\" value=\"%s\">\n",
1283 session->passport_info.sid);
1284 if (session->passport_info.kv != NULL)
1285 fprintf(fd, "<input type=\"hidden\" name=\"kv\" value=\"%s\">\n",
1286 session->passport_info.kv);
1287 fprintf(fd, "<input type=\"hidden\" name=\"id\" value=\"2\">\n");
1288 fprintf(fd, "<input type=\"hidden\" name=\"sl\" value=\"%ld\">\n",
1289 time(NULL) - session->passport_info.sl);
1290 fprintf(fd, "<input type=\"hidden\" name=\"rru\" value=\"%s\">\n",
1291 rru);
1292 if (session->passport_info.mspauth != NULL)
1293 fprintf(fd, "<input type=\"hidden\" name=\"auth\" value=\"%s\">\n",
1294 session->passport_info.mspauth);
1295 fprintf(fd, "<input type=\"hidden\" name=\"creds\" value=\"%s\">\n",
1296 sendbuf); /* TODO Digest me (huh? -- ChipX86) */
1297 fprintf(fd, "<input type=\"hidden\" name=\"svc\" value=\"mail\">\n");
1298 fprintf(fd, "<input type=\"hidden\" name=\"js\" value=\"yes\">\n");
1299 fprintf(fd, "</form></body>\n");
1300 fprintf(fd, "</html>\n");
1301
1302 if (fclose(fd))
1303 {
1304 purple_debug_error("msn",
1305 "Error closing temp passport file: %s\n",
1306 strerror(errno));
1307
1308 g_unlink(session->passport_info.file);
1309 g_free(session->passport_info.file);
1310 session->passport_info.file = NULL;
1311 }
1312 #ifdef _WIN32
1313 else
1314 {
1315 /*
1316 * Renaming file with .html extension, so that the
1317 * win32 open_url will work.
1318 */
1319 char *tmp;
1320
1321 if ((tmp =
1322 g_strdup_printf("%s.html",
1323 session->passport_info.file)) != NULL)
1324 {
1325 if (g_rename(session->passport_info.file,
1326 tmp) == 0)
1327 {
1328 g_free(session->passport_info.file);
1329 session->passport_info.file = tmp;
1330 }
1331 else
1332 g_free(tmp);
1333 }
1334 }
1335 #endif
1336 }
1337 }
1338 /**************************************************************************
1339 * Switchboards
1340 **************************************************************************/
1341
1342 static void
1343 rng_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
1344 {
1345 MsnSession *session;
1346 MsnSwitchBoard *swboard;
1347 const char *session_id;
1348 char *host;
1349 int port;
1350
1351 session = cmdproc->session;
1352 session_id = cmd->params[0];
1353
1354 msn_parse_socket(cmd->params[1], &host, &port);
1355
1356 if (session->http_method)
1357 port = 80;
1358
1359 swboard = msn_switchboard_new(session);
1360
1361 msn_switchboard_set_invited(swboard, TRUE);
1362 msn_switchboard_set_session_id(swboard, cmd->params[0]);
1363 msn_switchboard_set_auth_key(swboard, cmd->params[3]);
1364 swboard->im_user = g_strdup(cmd->params[4]);
1365 /* msn_switchboard_add_user(swboard, cmd->params[4]); */
1366
1367 if (!msn_switchboard_connect(swboard, host, port))
1368 msn_switchboard_destroy(swboard);
1369
1370 g_free(host);
1371 }
1372
1373 static void
1374 xfr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
1375 {
1376 char *host;
1377 int port;
1378
1379 if (strcmp(cmd->params[1], "SB") && strcmp(cmd->params[1], "NS"))
1380 {
1381 /* Maybe we can have a generic bad command error. */
1382 purple_debug_error("msn", "Bad XFR command (%s)\n", cmd->params[1]);
1383 return;
1384 }
1385
1386 msn_parse_socket(cmd->params[2], &host, &port);
1387
1388 if (!strcmp(cmd->params[1], "SB"))
1389 {
1390 purple_debug_error("msn", "This shouldn't be handled here.\n");
1391 }
1392 else if (!strcmp(cmd->params[1], "NS"))
1393 {
1394 MsnSession *session;
1395
1396 session = cmdproc->session;
1397
1398 msn_session_set_login_step(session, MSN_LOGIN_STEP_TRANSFER);
1399
1400 msn_notification_connect(session->notification, host, port);
1401 }
1402
1403 g_free(host);
1404 }
1405
1406 static void
1407 gcf_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
1408 size_t len)
1409 {
1410 /*get the payload content*/
1411 purple_debug_info("MaYuan","GCF{%s}\n",cmd->payload);
1412 }
1413
1414 static void
1415 gcf_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
1416 {
1417 purple_debug_info("MaYuan","Processing GCF... \n");
1418 cmdproc->last_cmd->payload_cb = gcf_cmd_post;
1419 return;
1420 }
1421
1422 static void
1423 sbs_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
1424 {
1425 purple_debug_info("MaYuan","Processing SBS... \n");
1426 if(cmd->payload_len == 0){
1427 return;
1428 }
1429 /*get the payload content*/
1430 }
1431
1432 /*
1433 * Get the UBX's PSM info
1434 * Post it to the User status
1435 * Thanks for Chris <ukdrizzle@yahoo.co.uk>'s code
1436 */
1437 static void
1438 ubx_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
1439 size_t len)
1440 {
1441 MsnSession *session;
1442 PurpleAccount *account;
1443 PurpleConnection *gc;
1444 MsnUser *user;
1445 const char *passport;
1446 char *psm_str;
1447
1448 /*get the payload content*/
1449 // purple_debug_info("MaYuan","UBX {%s} payload{%s}\n",cmd->params[0], cmd->payload);
1450
1451 session = cmdproc->session;
1452 account = session->account;
1453 gc = purple_account_get_connection(account);
1454
1455 passport = cmd->params[0];
1456 user = msn_userlist_find_user(session->userlist, passport);
1457
1458 psm_str = msn_get_psm(cmd->payload,len);
1459 msn_user_set_statusline(user, psm_str);
1460 msn_user_update(user);
1461
1462 g_free(psm_str);
1463 }
1464
1465 static void
1466 ubx_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
1467 {
1468 purple_debug_info("MaYuan","UBX... \n");
1469 if(cmd->payload_len == 0){
1470 return;
1471 }
1472 cmdproc->last_cmd->payload_cb = ubx_cmd_post;
1473 }
1474
1475 static void
1476 uux_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
1477 {
1478 purple_debug_info("MaYuan","UUX... \n");
1479 }
1480
1481 /**************************************************************************
1482 * Message Types
1483 **************************************************************************/
1484
1485 static void
1486 profile_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
1487 {
1488 MsnSession *session;
1489 const char *value;
1490 const char *clLastChange;
1491
1492 purple_debug_info("MaYuan","profile_msg... \n");
1493 session = cmdproc->session;
1494
1495 if (strcmp(msg->remote_user, "Hotmail"))
1496 /* This isn't an official message. */
1497 return;
1498
1499 if ((value = msn_message_get_attr(msg, "kv")) != NULL)
1500 {
1501 if (session->passport_info.kv != NULL)
1502 g_free(session->passport_info.kv);
1503
1504 session->passport_info.kv = g_strdup(value);
1505 }
1506
1507 if ((value = msn_message_get_attr(msg, "sid")) != NULL)
1508 {
1509 if (session->passport_info.sid != NULL)
1510 g_free(session->passport_info.sid);
1511
1512 session->passport_info.sid = g_strdup(value);
1513 }
1514
1515 if ((value = msn_message_get_attr(msg, "MSPAuth")) != NULL)
1516 {
1517 if (session->passport_info.mspauth != NULL)
1518 g_free(session->passport_info.mspauth);
1519
1520 purple_debug_info("MaYuan","MSPAuth:%s\n",value);
1521 session->passport_info.mspauth = g_strdup(value);
1522 }
1523
1524 if ((value = msn_message_get_attr(msg, "ClientIP")) != NULL)
1525 {
1526 if (session->passport_info.client_ip != NULL)
1527 g_free(session->passport_info.client_ip);
1528
1529 session->passport_info.client_ip = g_strdup(value);
1530 }
1531
1532 if ((value = msn_message_get_attr(msg, "ClientPort")) != NULL)
1533 {
1534 session->passport_info.client_port = ntohs(atoi(value));
1535 }
1536
1537 if ((value = msn_message_get_attr(msg, "LoginTime")) != NULL)
1538 session->passport_info.sl = atol(value);
1539
1540 /*starting retrieve the contact list*/
1541 msn_userlist_load(session);
1542
1543 msn_session_set_bnode(session);
1544 session->contact = msn_contact_new(session);
1545 clLastChange = purple_blist_node_get_string(msn_session_get_bnode(session),"CLLastChange");
1546 msn_get_contact_list(session->contact, clLastChange);
1547 // msn_contact_connect(session->contact);
1548 }
1549
1550 static void
1551 initial_email_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
1552 {
1553 MsnSession *session;
1554 PurpleConnection *gc;
1555 GHashTable *table;
1556 const char *unread;
1557
1558 session = cmdproc->session;
1559 gc = session->account->gc;
1560
1561 if (strcmp(msg->remote_user, "Hotmail"))
1562 /* This isn't an official message. */
1563 return;
1564
1565 if (session->passport_info.file == NULL)
1566 {
1567 MsnTransaction *trans;
1568 trans = msn_transaction_new(cmdproc, "URL", "%s", "INBOX");
1569 msn_transaction_queue_cmd(trans, msg->cmd);
1570
1571 msn_cmdproc_send_trans(cmdproc, trans);
1572
1573 return;
1574 }
1575
1576 if (!purple_account_get_check_mail(session->account))
1577 return;
1578
1579 table = msn_message_get_hashtable_from_body(msg);
1580
1581 unread = g_hash_table_lookup(table, "Inbox-Unread");
1582
1583 if (unread != NULL)
1584 {
1585 int count = atoi(unread);
1586
1587 if (count > 0)
1588 {
1589 const char *passport;
1590 const char *url;
1591
1592 passport = msn_user_get_passport(session->user);
1593 url = session->passport_info.file;
1594
1595 purple_notify_emails(gc, atoi(unread), FALSE, NULL, NULL,
1596 &passport, &url, NULL, NULL);
1597 }
1598 }
1599
1600 g_hash_table_destroy(table);
1601 }
1602
1603 /*offline Message notification process*/
1604 static void
1605 initial_mdata_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
1606 {
1607 MsnSession *session;
1608 char **elems, **cur, **tokens;
1609
1610 // purple_debug_info("MaYuan","mdata...{%s} \n",msg->body);
1611
1612 // /*time debug*/
1613 {
1614 const char *timestr;
1615 time_t t;
1616 struct tm *tm;
1617 char datestr[]="2006-07-15T07:21:26+0700";
1618 GDate *date;
1619 time(&t);
1620 tm = gmtime(&t);
1621 timestr = purple_utf8_strftime("%a, %d %b %Y %T %Z", tm);
1622 // strftime(datestr,strlen(datestr),"%a",tm);
1623 date = g_date_new();
1624 g_date_set_parse(date,datestr);
1625 purple_debug_info("MaYuan","date is NULL?date valid%d\n",g_date_valid(date));
1626 g_date_free(date);
1627 purple_debug_info("MaYuan","utf8 time:{%s}\n",timestr);
1628 }
1629
1630 /*new a oim session*/
1631 session = cmdproc->session;
1632 session->oim = msn_oim_new(session);
1633 // msn_oim_connect(session->oim);
1634
1635 /*parse offline message data*/
1636 elems = g_strsplit(msg->body, "\r\n", 0);
1637 for (cur = elems; *cur != NULL; cur++){
1638 const char *key, *value;
1639
1640 // purple_debug_info("MaYuan","cur:{%s}\n",*cur);
1641 tokens = g_strsplit(*cur, ": ", 2);
1642
1643 key = tokens[0];
1644 value = tokens[1];
1645
1646 /*if not MIME content ,then return*/
1647 if ((key != NULL) && (!strcmp(key, "Mail-Data")) ){
1648 // purple_debug_info("MaYuan","data:{%s}\n",value);
1649 msn_parse_oim_msg(session->oim,value);
1650 g_strfreev(tokens);
1651 break;
1652 }
1653
1654 g_strfreev(tokens);
1655 }
1656
1657 g_strfreev(elems);
1658 /* test code for add group*/
1659 // msn_add_group(session,"hello");
1660 }
1661
1662 /*offline Message Notification*/
1663 static void
1664 delete_oim_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
1665 {
1666 }
1667
1668 static void
1669 email_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
1670 {
1671 MsnSession *session;
1672 PurpleConnection *gc;
1673 GHashTable *table;
1674 char *from, *subject, *tmp;
1675
1676 session = cmdproc->session;
1677 gc = session->account->gc;
1678
1679 if (strcmp(msg->remote_user, "Hotmail"))
1680 /* This isn't an official message. */
1681 return;
1682
1683 if (session->passport_info.file == NULL)
1684 {
1685 MsnTransaction *trans;
1686 trans = msn_transaction_new(cmdproc, "URL", "%s", "INBOX");
1687 msn_transaction_queue_cmd(trans, msg->cmd);
1688
1689 msn_cmdproc_send_trans(cmdproc, trans);
1690
1691 return;
1692 }
1693
1694 if (!purple_account_get_check_mail(session->account))
1695 return;
1696
1697 table = msn_message_get_hashtable_from_body(msg);
1698
1699 from = subject = NULL;
1700
1701 tmp = g_hash_table_lookup(table, "From");
1702 if (tmp != NULL)
1703 from = purple_mime_decode_field(tmp);
1704
1705 tmp = g_hash_table_lookup(table, "Subject");
1706 if (tmp != NULL)
1707 subject = purple_mime_decode_field(tmp);
1708
1709 purple_notify_email(gc,
1710 (subject != NULL ? subject : ""),
1711 (from != NULL ? from : ""),
1712 msn_user_get_passport(session->user),
1713 session->passport_info.file, NULL, NULL);
1714
1715 if (from != NULL)
1716 g_free(from);
1717
1718 if (subject != NULL)
1719 g_free(subject);
1720
1721 g_hash_table_destroy(table);
1722 }
1723
1724 static void
1725 system_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
1726 {
1727 GHashTable *table;
1728 const char *type_s;
1729
1730 if (strcmp(msg->remote_user, "Hotmail"))
1731 /* This isn't an official message. */
1732 return;
1733
1734 table = msn_message_get_hashtable_from_body(msg);
1735
1736 if ((type_s = g_hash_table_lookup(table, "Type")) != NULL)
1737 {
1738 int type = atoi(type_s);
1739 char buf[MSN_BUF_LEN];
1740 int minutes;
1741
1742 switch (type)
1743 {
1744 case 1:
1745 minutes = atoi(g_hash_table_lookup(table, "Arg1"));
1746 g_snprintf(buf, sizeof(buf), ngettext(
1747 "The MSN server will shut down for maintenance "
1748 "in %d minute. You will automatically be "
1749 "signed out at that time. Please finish any "
1750 "conversations in progress.\n\nAfter the "
1751 "maintenance has been completed, you will be "
1752 "able to successfully sign in.",
1753 "The MSN server will shut down for maintenance "
1754 "in %d minutes. You will automatically be "
1755 "signed out at that time. Please finish any "
1756 "conversations in progress.\n\nAfter the "
1757 "maintenance has been completed, you will be "
1758 "able to successfully sign in.", minutes),
1759 minutes);
1760 default:
1761 break;
1762 }
1763
1764 if (*buf != '\0')
1765 purple_notify_info(cmdproc->session->account->gc, NULL, buf, NULL);
1766 }
1767
1768 g_hash_table_destroy(table);
1769 }
1770
1771 void
1772 msn_notification_add_buddy(MsnNotification *notification, const char *list,
1773 const char *who, const char *store_name,
1774 const char *group_id)
1775 {
1776 MsnCmdProc *cmdproc;
1777 xmlnode *adl_node;
1778 char *payload;
1779 int payload_len;
1780
1781 cmdproc = notification->servconn->cmdproc;
1782
1783 adl_node = xmlnode_new("ml");
1784 adl_node->child = NULL;
1785
1786 msn_add_contact_xml(adl_node,who,1,1);
1787
1788 payload = xmlnode_to_str(adl_node,&payload_len);
1789 xmlnode_free(adl_node);
1790 if (msn_user_is_yahoo(notification->session->account,who))
1791 {
1792 msn_notification_fqy_yahoo(notification->session, who);
1793 }
1794 else
1795 {
1796 msn_notification_post_adl(notification->servconn->cmdproc,
1797 payload,payload_len);
1798 }
1799 }
1800
1801 void
1802 msn_notification_rem_buddy(MsnNotification *notification, const char *list,
1803 const char *who, const char *group_id)
1804 {
1805 MsnCmdProc *cmdproc;
1806 MsnTransaction *trans;
1807 xmlnode *rml_node;
1808 char *payload;
1809 int payload_len;
1810
1811 cmdproc = notification->servconn->cmdproc;
1812
1813 rml_node = xmlnode_new("ml");
1814 rml_node->child = NULL;
1815
1816 msn_add_contact_xml(rml_node,who,1,1);
1817
1818 payload = xmlnode_to_str(rml_node,&payload_len);
1819 xmlnode_free(rml_node);
1820
1821 purple_debug_info("MaYuan","RML{%s}\n",payload);
1822 trans = msn_transaction_new(cmdproc, "RML","%d",strlen(payload));
1823 msn_transaction_set_payload(trans, payload, strlen(payload));
1824 msn_cmdproc_send_trans(cmdproc, trans);
1825 }
1826
1827 /**************************************************************************
1828 * Init
1829 **************************************************************************/
1830 void
1831 msn_notification_init(void)
1832 {
1833 /* TODO: check prp, blp */
1834
1835 cbs_table = msn_table_new();
1836
1837 /* Synchronous */
1838 msn_table_add_cmd(cbs_table, "CHG", "CHG", NULL);
1839 msn_table_add_cmd(cbs_table, "CHG", "ILN", iln_cmd);
1840 msn_table_add_cmd(cbs_table, "ADL", "ILN", iln_cmd);
1841 msn_table_add_cmd(cbs_table, "REM", "REM", rem_cmd);
1842 msn_table_add_cmd(cbs_table, "USR", "USR", usr_cmd);
1843 msn_table_add_cmd(cbs_table, "USR", "XFR", xfr_cmd);
1844 msn_table_add_cmd(cbs_table, "USR", "GCF", gcf_cmd);
1845 msn_table_add_cmd(cbs_table, "SYN", "SYN", syn_cmd);
1846 msn_table_add_cmd(cbs_table, "CVR", "CVR", cvr_cmd);
1847 msn_table_add_cmd(cbs_table, "VER", "VER", ver_cmd);
1848 msn_table_add_cmd(cbs_table, "REA", "REA", rea_cmd);
1849 msn_table_add_cmd(cbs_table, "PRP", "PRP", prp_cmd);
1850 msn_table_add_cmd(cbs_table, "BLP", "BLP", blp_cmd);
1851 // msn_table_add_cmd(cbs_table, "BLP", "BLP", NULL);
1852 msn_table_add_cmd(cbs_table, "REG", "REG", reg_cmd);
1853 msn_table_add_cmd(cbs_table, "ADG", "ADG", adg_cmd);
1854 msn_table_add_cmd(cbs_table, "RMG", "RMG", rmg_cmd);
1855 msn_table_add_cmd(cbs_table, "XFR", "XFR", xfr_cmd);
1856
1857 /* Asynchronous */
1858 msn_table_add_cmd(cbs_table, NULL, "IPG", ipg_cmd);
1859 msn_table_add_cmd(cbs_table, NULL, "MSG", msg_cmd);
1860 msn_table_add_cmd(cbs_table, NULL, "UBM", ubm_cmd);
1861 msn_table_add_cmd(cbs_table, NULL, "GCF", gcf_cmd);
1862 msn_table_add_cmd(cbs_table, NULL, "SBS", sbs_cmd);
1863 msn_table_add_cmd(cbs_table, NULL, "NOT", not_cmd);
1864
1865 msn_table_add_cmd(cbs_table, NULL, "CHL", chl_cmd);
1866 msn_table_add_cmd(cbs_table, NULL, "RML", rml_cmd);
1867 msn_table_add_cmd(cbs_table, NULL, "ADL", adl_cmd);
1868 msn_table_add_cmd(cbs_table, NULL, "FQY", fqy_cmd);
1869
1870 msn_table_add_cmd(cbs_table, NULL, "QRY", NULL);
1871 msn_table_add_cmd(cbs_table, NULL, "QNG", NULL);
1872 msn_table_add_cmd(cbs_table, NULL, "FLN", fln_cmd);
1873 msn_table_add_cmd(cbs_table, NULL, "NLN", nln_cmd);
1874 msn_table_add_cmd(cbs_table, NULL, "ILN", iln_cmd);
1875 msn_table_add_cmd(cbs_table, NULL, "OUT", out_cmd);
1876 msn_table_add_cmd(cbs_table, NULL, "RNG", rng_cmd);
1877
1878 msn_table_add_cmd(cbs_table, NULL, "UBX", ubx_cmd);
1879 msn_table_add_cmd(cbs_table, NULL, "UUX", uux_cmd);
1880
1881 msn_table_add_cmd(cbs_table, NULL, "URL", url_cmd);
1882
1883 msn_table_add_cmd(cbs_table, "fallback", "XFR", xfr_cmd);
1884
1885 msn_table_add_error(cbs_table, "ADD", add_error);
1886 msn_table_add_error(cbs_table, "REG", reg_error);
1887 msn_table_add_error(cbs_table, "RMG", rmg_error);
1888 /* msn_table_add_error(cbs_table, "REA", rea_error); */
1889 msn_table_add_error(cbs_table, "USR", usr_error);
1890
1891 msn_table_add_msg_type(cbs_table,
1892 "text/x-msmsgsprofile",
1893 profile_msg);
1894 /*initial OIM notification*/
1895 msn_table_add_msg_type(cbs_table,
1896 "text/x-msmsgsinitialmdatanotification",
1897 initial_mdata_msg);
1898 /*OIM notification when user online*/
1899 msn_table_add_msg_type(cbs_table,
1900 "text/x-msmsgsoimnotification",
1901 initial_mdata_msg);
1902 msn_table_add_msg_type(cbs_table,
1903 "text/x-msmsgsinitialemailnotification",
1904 initial_email_msg);
1905 msn_table_add_msg_type(cbs_table,
1906 "text/x-msmsgsemailnotification",
1907 email_msg);
1908 /*delete an offline Message notification*/
1909 msn_table_add_msg_type(cbs_table,
1910 "text/x-msmsgsactivemailnotification",
1911 delete_oim_msg);
1912 msn_table_add_msg_type(cbs_table,
1913 "application/x-msmsgssystemmessage",
1914 system_msg);
1915 }
1916
1917 void
1918 msn_notification_end(void)
1919 {
1920 msn_table_destroy(cbs_table);
1921 }
1922