comparison src/protocols/msn/msn.c @ 2738:01f0497fe6c8

[gaim-migrate @ 2751] this is so ugly committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Sat, 17 Nov 2001 21:55:49 +0000
parents 98b1ac8ddea3
children 7aeedbf29a96
comparison
equal deleted inserted replaced
2737:f61c1f3a6afa 2738:01f0497fe6c8
36 36
37 struct msn_data { 37 struct msn_data {
38 int fd; 38 int fd;
39 int trId; 39 int trId;
40 int inpa; 40 int inpa;
41
42 char *rxqueue;
43 int rxlen;
44 gboolean msg;
45 char *msguser;
46 int msglen;
47
41 GSList *switches; 48 GSList *switches;
42 GSList *fl; 49 GSList *fl;
43 GSList *permit; 50 GSList *permit;
44 GSList *deny; 51 GSList *deny;
45 }; 52 };
47 struct msn_switchboard { 54 struct msn_switchboard {
48 struct gaim_connection *gc; 55 struct gaim_connection *gc;
49 struct conversation *chat; 56 struct conversation *chat;
50 int fd; 57 int fd;
51 int inpa; 58 int inpa;
59
60 char *rxqueue;
61 int rxlen;
62 gboolean msg;
63 char *msguser;
64 int msglen;
65
52 char *sessid; 66 char *sessid;
53 char *auth; 67 char *auth;
54 int trId; 68 int trId;
55 int total; 69 int total;
56 char *user; 70 char *user;
340 struct msn_data *md = gc->proto_data; 354 struct msn_data *md = gc->proto_data;
341 355
342 if (ms->inpa) 356 if (ms->inpa)
343 gaim_input_remove(ms->inpa); 357 gaim_input_remove(ms->inpa);
344 close(ms->fd); 358 close(ms->fd);
359 g_free(ms->rxqueue);
360 if (ms->msg)
361 g_free(ms->msguser);
345 if (ms->sessid) 362 if (ms->sessid)
346 g_free(ms->sessid); 363 g_free(ms->sessid);
347 g_free(ms->auth); 364 g_free(ms->auth);
348 if (ms->user) 365 if (ms->user)
349 g_free(ms->user); 366 g_free(ms->user);
357 md->switches = g_slist_remove(md->switches, ms); 374 md->switches = g_slist_remove(md->switches, ms);
358 375
359 g_free(ms); 376 g_free(ms);
360 } 377 }
361 378
362 static void msn_switchboard_callback(gpointer data, gint source, GaimInputCondition cond) 379 static int msn_process_switch(struct msn_switchboard *ms, char *buf)
363 { 380 {
364 struct msn_switchboard *ms = data;
365 struct gaim_connection *gc = ms->gc; 381 struct gaim_connection *gc = ms->gc;
366 char buf[MSN_BUF_LEN]; 382 char sendbuf[MSN_BUF_LEN];
367 static int id = 0; 383 static int id = 0;
368 int i = 0;
369
370 bzero(buf, sizeof(buf));
371 while ((read(ms->fd, buf + i, 1) > 0) && (buf[i++] != '\n'))
372 if (i == sizeof(buf))
373 i--; /* yes i know this loses data but we shouldn't get messages this long
374 and it's better than possibly writing past our buffer */
375 if (i == 0 || buf[i - 1] != '\n') {
376 msn_kill_switch(ms);
377 return;
378 }
379 debug_printf("MSN S: %s", buf);
380 g_strchomp(buf);
381 384
382 if (!g_strncasecmp(buf, "ACK", 3)) { 385 if (!g_strncasecmp(buf, "ACK", 3)) {
383 } else if (!g_strncasecmp(buf, "ANS", 3)) { 386 } else if (!g_strncasecmp(buf, "ANS", 3)) {
384 if (ms->chat) 387 if (ms->chat)
385 add_chat_buddy(ms->chat, gc->username); 388 add_chat_buddy(ms->chat, gc->username);
387 if (ms->chat) { 390 if (ms->chat) {
388 char *user, *tmp = buf; 391 char *user, *tmp = buf;
389 GET_NEXT(tmp); 392 GET_NEXT(tmp);
390 user = tmp; 393 user = tmp;
391 remove_chat_buddy(ms->chat, user); 394 remove_chat_buddy(ms->chat, user);
392 } else 395 } else {
393 msn_kill_switch(ms); 396 msn_kill_switch(ms);
397 return 0;
398 }
394 } else if (!g_strncasecmp(buf, "CAL", 3)) { 399 } else if (!g_strncasecmp(buf, "CAL", 3)) {
395 } else if (!g_strncasecmp(buf, "IRO", 3)) { 400 } else if (!g_strncasecmp(buf, "IRO", 3)) {
396 char *tot, *user, *tmp = buf; 401 char *tot, *user, *tmp = buf;
397 402
398 GET_NEXT(tmp); 403 GET_NEXT(tmp);
427 ms->total++; 432 ms->total++;
428 while (ms->txqueue) { 433 while (ms->txqueue) {
429 char *send = add_cr(ms->txqueue->data); 434 char *send = add_cr(ms->txqueue->data);
430 char *utf8 = str_to_utf8(send); 435 char *utf8 = str_to_utf8(send);
431 g_free(send); 436 g_free(send);
432 g_snprintf(buf, sizeof(buf), "MSG %d N %d\r\n%s%s", ++ms->trId, 437 g_snprintf(sendbuf, sizeof(sendbuf), "MSG %d N %d\r\n%s%s", ++ms->trId,
433 strlen(MIME_HEADER) + strlen(utf8), 438 strlen(MIME_HEADER) + strlen(utf8),
434 MIME_HEADER, utf8); 439 MIME_HEADER, utf8);
435 g_free(utf8); 440 g_free(utf8);
436 g_free(ms->txqueue->data); 441 g_free(ms->txqueue->data);
437 ms->txqueue = g_slist_remove(ms->txqueue, ms->txqueue->data); 442 ms->txqueue = g_slist_remove(ms->txqueue, ms->txqueue->data);
438 if (msn_write(ms->fd, buf, strlen(buf)) < 0) { 443 if (msn_write(ms->fd, sendbuf, strlen(sendbuf)) < 0) {
439 msn_kill_switch(ms); 444 msn_kill_switch(ms);
440 return; 445 return 0;
441 } 446 }
442 debug_printf("\n"); 447 debug_printf("\n");
443 } 448 }
444 } else if (!g_strncasecmp(buf, "MSG", 3)) { 449 } else if (!g_strncasecmp(buf, "MSG", 3)) {
445 char *user, *tmp = buf; 450 char *user, *tmp = buf;
446 int length, len, r; 451 int length;
447 char *msg, *content, *agent, *utf;
448 int flags = 0;
449 452
450 GET_NEXT(tmp); 453 GET_NEXT(tmp);
451 user = tmp; 454 user = tmp;
452 455
453 GET_NEXT(tmp); 456 GET_NEXT(tmp);
454 457
455 GET_NEXT(tmp); 458 GET_NEXT(tmp);
456 length = atoi(tmp); 459 length = atoi(tmp);
457 460
458 msg = g_malloc0(length + 1); 461 ms->msg = TRUE;
459 462 ms->msguser = g_strdup(user);
460 for (len = 0; len < length; len += r) { 463 ms->msglen = length;
461 if ((r = read(ms->fd, msg+len, length-len)) <= 0) {
462 g_free(msg);
463 hide_login_progress(gc, "Unable to read message");
464 signoff(gc);
465 return;
466 }
467 }
468
469 agent = strstr(msg, "User-Agent: ");
470 if (agent) {
471 if (!g_strncasecmp(agent, "User-Agent: Gaim", strlen("User-Agent: Gaim")))
472 flags |= IM_FLAG_GAIMUSER;
473 }
474 content = strstr(msg, "Content-Type: ");
475 if (!content) {
476 g_free(msg);
477 return;
478 }
479 if (!g_strncasecmp(content, "Content-Type: text/plain",
480 strlen("Content-Type: text/plain"))) {
481 char *skiphead;
482 skiphead = strstr(msg, "\r\n\r\n");
483 if (!skiphead || !skiphead[4]) {
484 g_free(msg);
485 return;
486 }
487 skiphead += 4;
488 utf = utf8_to_str(skiphead);
489 strip_linefeed(utf);
490
491 if (ms->chat)
492 serv_got_chat_in(gc, ms->chat->id, user, flags, utf, time(NULL));
493 else
494 serv_got_im(gc, user, utf, flags, time(NULL));
495
496 g_free(utf);
497 }
498 g_free(msg);
499 } else if (!g_strncasecmp(buf, "NAK", 3)) { 464 } else if (!g_strncasecmp(buf, "NAK", 3)) {
500 do_error_dialog("A message may not have been received.", "MSN Error"); 465 do_error_dialog("A message may not have been received.", "MSN Error");
501 } else if (!g_strncasecmp(buf, "NLN", 3)) { 466 } else if (!g_strncasecmp(buf, "NLN", 3)) {
502 } else if (!g_strncasecmp(buf, "OUT", 3)) { 467 } else if (!g_strncasecmp(buf, "OUT", 3)) {
503 if (ms->chat) 468 if (ms->chat)
504 serv_got_chat_left(gc, ms->chat->id); 469 serv_got_chat_left(gc, ms->chat->id);
505 msn_kill_switch(ms); 470 msn_kill_switch(ms);
471 return 0;
506 } else if (!g_strncasecmp(buf, "USR", 3)) { 472 } else if (!g_strncasecmp(buf, "USR", 3)) {
507 /* good, we got USR, now we need to find out who we want to talk to */ 473 /* good, we got USR, now we need to find out who we want to talk to */
508 struct msn_switchboard *ms = msn_find_writable_switch(gc); 474 struct msn_switchboard *ms = msn_find_writable_switch(gc);
509 475
510 if (!ms) 476 if (!ms)
511 return; 477 return 0;
512 478
513 g_snprintf(buf, sizeof(buf), "CAL %d %s\r\n", ++ms->trId, ms->user); 479 g_snprintf(sendbuf, sizeof(sendbuf), "CAL %d %s\r\n", ++ms->trId, ms->user);
514 if (msn_write(ms->fd, buf, strlen(buf)) < 0) 480 if (msn_write(ms->fd, sendbuf, strlen(sendbuf)) < 0) {
515 msn_kill_switch(ms); 481 msn_kill_switch(ms);
482 return 0;
483 }
516 } else if (isdigit(*buf)) { 484 } else if (isdigit(*buf)) {
517 handle_errcode(buf, TRUE); 485 handle_errcode(buf, TRUE);
518 } else { 486 } else {
519 debug_printf("Unhandled message!\n"); 487 debug_printf("Unhandled message!\n");
488 }
489
490 return 1;
491 }
492
493 static void msn_process_switch_msg(struct msn_switchboard *ms, char *msg)
494 {
495 char *content, *agent, *utf;
496 int flags = 0;
497
498 agent = strstr(msg, "User-Agent: ");
499 if (agent) {
500 if (!g_strncasecmp(agent, "User-Agent: Gaim", strlen("User-Agent: Gaim")))
501 flags |= IM_FLAG_GAIMUSER;
502 }
503 content = strstr(msg, "Content-Type: ");
504 if (!content)
505 return;
506 if (!g_strncasecmp(content, "Content-Type: text/plain",
507 strlen("Content-Type: text/plain"))) {
508 char *skiphead;
509 skiphead = strstr(msg, "\r\n\r\n");
510 if (!skiphead || !skiphead[4]) {
511 return;
512 }
513 skiphead += 4;
514 utf = utf8_to_str(skiphead);
515 strip_linefeed(utf);
516
517 if (ms->chat)
518 serv_got_chat_in(ms->gc, ms->chat->id, ms->msguser, flags, utf, time(NULL));
519 else
520 serv_got_im(ms->gc, ms->msguser, utf, flags, time(NULL));
521
522 g_free(utf);
523 }
524 }
525
526 static void msn_switchboard_callback(gpointer data, gint source, GaimInputCondition cond)
527 {
528 struct msn_switchboard *ms = data;
529 char buf[MSN_BUF_LEN];
530 int cont = 1;
531 int len;
532
533 len = read(ms->fd, buf, sizeof(buf));
534
535 if (len <= 0) {
536 msn_kill_switch(ms);
537 return;
538 }
539
540 ms->rxqueue = g_realloc(ms->rxqueue, len + ms->rxlen);
541 memcpy(ms->rxqueue + ms->rxlen, buf, len);
542 ms->rxlen += len;
543
544 while (cont) {
545 if (!ms->rxlen)
546 return;
547
548 if (ms->msg) {
549 char *msg;
550 if (ms->msglen > ms->rxlen)
551 return;
552 msg = ms->rxqueue;
553 ms->rxlen -= ms->msglen;
554 if (ms->rxlen) {
555 ms->rxqueue = g_memdup(msg + ms->msglen, ms->rxlen);
556 } else {
557 ms->rxqueue = NULL;
558 msg = g_realloc(msg, ms->msglen + 1);
559 }
560 msg[ms->msglen] = 0;
561 ms->msglen = 0;
562 ms->msg = FALSE;
563
564 msn_process_switch_msg(ms, msg);
565
566 g_free(ms->msguser);
567 g_free(msg);
568 } else {
569 char *end = ms->rxqueue;
570 int cmdlen;
571 char *cmd;
572 int i = 0;
573
574 while (i + 1 < ms->rxlen) {
575 if (*end == '\r' && end[1] == '\n')
576 break;
577 end++; i++;
578 }
579 if (i + 1 == ms->rxlen)
580 return;
581
582 cmdlen = end - ms->rxqueue + 2;
583 cmd = ms->rxqueue;
584 ms->rxlen -= cmdlen;
585 if (ms->rxlen) {
586 ms->rxqueue = g_memdup(cmd + cmdlen, ms->rxlen);
587 } else {
588 ms->rxqueue = NULL;
589 cmd = g_realloc(cmd, cmdlen + 1);
590 }
591 cmd[cmdlen] = 0;
592
593 debug_printf("MSN S: %s", cmd);
594 g_strchomp(cmd);
595 cont = msn_process_switch(ms, cmd);
596
597 g_free(cmd);
598 }
520 } 599 }
521 } 600 }
522 601
523 static void msn_rng_connect(gpointer data, gint source, GaimInputCondition cond) 602 static void msn_rng_connect(gpointer data, gint source, GaimInputCondition cond)
524 { 603 {
608 g_free(map->user); 687 g_free(map->user);
609 g_free(map->friend); 688 g_free(map->friend);
610 g_free(map); 689 g_free(map);
611 } 690 }
612 691
613 static void msn_callback(gpointer data, gint source, GaimInputCondition cond) 692 static int msn_process_main(struct gaim_connection *gc, char *buf)
614 { 693 {
615 struct gaim_connection *gc = data; 694 struct msn_data *md = gc->proto_data;
616 struct msn_data *md = gc->proto_data; 695 char sendbuf[MSN_BUF_LEN];
617 char buf[MSN_BUF_LEN];
618 int i = 0;
619
620 bzero(buf, sizeof(buf));
621 while ((read(md->fd, buf + i, 1) > 0) && (buf[i++] != '\n'))
622 if (i == sizeof(buf))
623 i--; /* yes i know this loses data but we shouldn't get messages this long
624 and it's better than possibly writing past our buffer */
625 if (i == 0 || buf[i - 1] != '\n') {
626 hide_login_progress(gc, "Error reading from server");
627 signoff(gc);
628 return;
629 }
630 debug_printf("MSN S: %s", buf);
631 g_strchomp(buf);
632 696
633 if (!g_strncasecmp(buf, "ADD", 3)) { 697 if (!g_strncasecmp(buf, "ADD", 3)) {
634 char *list, *user, *friend, *tmp = buf; 698 char *list, *user, *friend, *tmp = buf;
635 struct msn_add_permit *ap; 699 struct msn_add_permit *ap;
636 GSList *perm = gc->permit; 700 GSList *perm = gc->permit;
646 710
647 GET_NEXT(tmp); 711 GET_NEXT(tmp);
648 friend = tmp; 712 friend = tmp;
649 713
650 if (g_strcasecmp(list, "RL")) 714 if (g_strcasecmp(list, "RL"))
651 return; 715 return 1;
652 716
653 while (perm) { 717 while (perm) {
654 if (!g_strcasecmp(perm->data, user)) 718 if (!g_strcasecmp(perm->data, user))
655 return; 719 return 1;
656 perm = perm->next; 720 perm = perm->next;
657 } 721 }
658 722
659 ap = g_new0(struct msn_add_permit, 1); 723 ap = g_new0(struct msn_add_permit, 1);
660 ap->user = g_strdup(user); 724 ap->user = g_strdup(user);
702 md5_init(&st); 766 md5_init(&st);
703 md5_append(&st, (const md5_byte_t *)hash, strlen(hash)); 767 md5_append(&st, (const md5_byte_t *)hash, strlen(hash));
704 md5_append(&st, (const md5_byte_t *)"Q1P7W2E4J9R8U3S5", strlen("Q1P7W2E4J9R8U3S5")); 768 md5_append(&st, (const md5_byte_t *)"Q1P7W2E4J9R8U3S5", strlen("Q1P7W2E4J9R8U3S5"));
705 md5_finish(&st, di); 769 md5_finish(&st, di);
706 770
707 g_snprintf(buf, sizeof(buf), "QRY %d msmsgs@msnmsgr.com 32\r\n", ++md->trId); 771 g_snprintf(sendbuf, sizeof(sendbuf), "QRY %d msmsgs@msnmsgr.com 32\r\n", ++md->trId);
708 for (i = 0; i < 16; i++) { 772 for (i = 0; i < 16; i++) {
709 g_snprintf(buf2, sizeof(buf2), "%02x", di[i]); 773 g_snprintf(buf2, sizeof(buf2), "%02x", di[i]);
710 strcat(buf, buf2); 774 strcat(sendbuf, buf2);
711 } 775 }
712 776
713 if (msn_write(md->fd, buf, strlen(buf)) < 0) { 777 if (msn_write(md->fd, sendbuf, strlen(sendbuf)) < 0) {
714 hide_login_progress(gc, "Unable to write to server"); 778 hide_login_progress(gc, "Unable to write to server");
715 signoff(gc); 779 signoff(gc);
716 } 780 }
717 781
718 debug_printf("\n"); 782 debug_printf("\n");
788 gc->permit = g_slist_append(gc->permit, g_strdup(who)); 852 gc->permit = g_slist_append(gc->permit, g_strdup(who));
789 } else if (!g_strcasecmp(which, "BL") && pos) { 853 } else if (!g_strcasecmp(which, "BL") && pos) {
790 gc->deny = g_slist_append(gc->deny, g_strdup(who)); 854 gc->deny = g_slist_append(gc->deny, g_strdup(who));
791 } else if (!g_strcasecmp(which, "RL")) { 855 } else if (!g_strcasecmp(which, "RL")) {
792 if (pos != tot) 856 if (pos != tot)
793 return; 857 return 1;
794 858
795 g_snprintf(buf, sizeof(buf), "CHG %d NLN\r\n", ++md->trId); 859 g_snprintf(sendbuf, sizeof(sendbuf), "CHG %d NLN\r\n", ++md->trId);
796 if (msn_write(md->fd, buf, strlen(buf)) < 0) { 860 if (msn_write(md->fd, sendbuf, strlen(sendbuf)) < 0) {
797 hide_login_progress(gc, "Unable to write"); 861 hide_login_progress(gc, "Unable to write");
798 signoff(gc); 862 signoff(gc);
799 return; 863 return 0;
800 } 864 }
801 865
802 account_online(gc); 866 account_online(gc);
803 serv_finish_login(gc); 867 serv_finish_login(gc);
804 868
806 md->deny = g_slist_copy(gc->deny); 870 md->deny = g_slist_copy(gc->deny);
807 871
808 if (bud_list_cache_exists(gc)) 872 if (bud_list_cache_exists(gc))
809 do_import(gc, NULL); 873 do_import(gc, NULL);
810 else { 874 else {
811 g_snprintf(buf, sizeof(buf), "BLP %d AL\r\n", ++md->trId); 875 g_snprintf(sendbuf, sizeof(sendbuf), "BLP %d AL\r\n", ++md->trId);
812 if (msn_write(md->fd, buf, strlen(buf)) < 0) { 876 if (msn_write(md->fd, sendbuf, strlen(sendbuf)) < 0) {
813 hide_login_progress(gc, "Unable to write"); 877 hide_login_progress(gc, "Unable to write");
814 signoff(gc); 878 signoff(gc);
815 return; 879 return 0;
816 } 880 }
817 } 881 }
818 while (md->fl) { 882 while (md->fl) {
819 struct msn_buddy *mb = md->fl->data; 883 struct msn_buddy *mb = md->fl->data;
820 struct buddy *b; 884 struct buddy *b;
831 } 895 }
832 } 896 }
833 } else if (!g_strncasecmp(buf, "MSG", 3)) { 897 } else if (!g_strncasecmp(buf, "MSG", 3)) {
834 char *user, *tmp = buf; 898 char *user, *tmp = buf;
835 int length; 899 int length;
836 char *msg, *skiphead, *utf;
837 int len, r;
838 900
839 GET_NEXT(tmp); 901 GET_NEXT(tmp);
840 user = tmp; 902 user = tmp;
841 903
842 GET_NEXT(tmp); 904 GET_NEXT(tmp);
843 905
844 GET_NEXT(tmp); 906 GET_NEXT(tmp);
845 length = atoi(tmp); 907 length = atoi(tmp);
846 908
847 msg = g_new0(char, MAX(length + 1, MSN_BUF_LEN)); 909 md->msg = TRUE;
848 910 md->msguser = g_strdup(user);
849 for (len = 0; len < length; len += r) { 911 md->msglen = length;
850 if ((r = read(md->fd, msg+len, length-len)) <= 0) {
851 g_free(msg);
852 hide_login_progress(gc, "Unable to read message");
853 signoff(gc);
854 return;
855 }
856 }
857
858 if (!g_strcasecmp(user, "hotmail")) {
859 handle_hotmail(gc, msg);
860 g_free(msg);
861 return;
862 }
863
864 skiphead = strstr(msg, "\r\n\r\n");
865 if (!skiphead || !skiphead[4]) {
866 g_free(msg);
867 return;
868 }
869 skiphead += 4;
870 utf = utf8_to_str(skiphead);
871 strip_linefeed(utf);
872
873 serv_got_im(gc, user, utf, 0, time(NULL));
874
875 g_free(utf);
876 g_free(msg);
877 } else if (!g_strncasecmp(buf, "NLN", 3)) { 912 } else if (!g_strncasecmp(buf, "NLN", 3)) {
878 char *state, *user, *friend, *tmp = buf; 913 char *state, *user, *friend, *tmp = buf;
879 struct buddy *b; 914 struct buddy *b;
880 int status = 0; 915 int status = 0;
881 916
955 990
956 ms = g_new0(struct msn_switchboard, 1); 991 ms = g_new0(struct msn_switchboard, 1);
957 ms->fd = proxy_connect(ssaddr, port, msn_rng_connect, ms); 992 ms->fd = proxy_connect(ssaddr, port, msn_rng_connect, ms);
958 if (ms->fd < 0) { 993 if (ms->fd < 0) {
959 g_free(ms); 994 g_free(ms);
960 return; 995 return 1;
961 } 996 }
962 ms->user = g_strdup(user); 997 ms->user = g_strdup(user);
963 ms->sessid = g_strdup(sessid); 998 ms->sessid = g_strdup(sessid);
964 ms->auth = g_strdup(auth); 999 ms->auth = g_strdup(auth);
965 ms->gc = gc; 1000 ms->gc = gc;
975 if (!host) { 1010 if (!host) {
976 host = strstr(buf, "NS"); 1011 host = strstr(buf, "NS");
977 if (!host) { 1012 if (!host) {
978 hide_login_progress(gc, "Got invalid XFR\n"); 1013 hide_login_progress(gc, "Got invalid XFR\n");
979 signoff(gc); 1014 signoff(gc);
980 return; 1015 return 0;
981 } 1016 }
982 switchboard = FALSE; 1017 switchboard = FALSE;
983 } 1018 }
984 1019
985 GET_NEXT(host); 1020 GET_NEXT(host);
997 } 1032 }
998 1033
999 if (switchboard) { 1034 if (switchboard) {
1000 struct msn_switchboard *ms = msn_find_writable_switch(gc); 1035 struct msn_switchboard *ms = msn_find_writable_switch(gc);
1001 if (!ms) 1036 if (!ms)
1002 return; 1037 return 1;
1003 1038
1004 GET_NEXT(tmp); 1039 GET_NEXT(tmp);
1005 1040
1006 ms->fd = proxy_connect(host, port, msn_ss_xfr_connect, ms); 1041 ms->fd = proxy_connect(host, port, msn_ss_xfr_connect, ms);
1007 if (ms->fd < 0) { 1042 if (ms->fd < 0) {
1008 msn_kill_switch(ms); 1043 msn_kill_switch(ms);
1009 return; 1044 return 1;
1010 } 1045 }
1011 ms->auth = g_strdup(tmp); 1046 ms->auth = g_strdup(tmp);
1012 } else { 1047 } else {
1013 close(md->fd); 1048 close(md->fd);
1014 gaim_input_remove(md->inpa); 1049 gaim_input_remove(md->inpa);
1022 } else if (isdigit(*buf)) { 1057 } else if (isdigit(*buf)) {
1023 handle_errcode(buf, TRUE); 1058 handle_errcode(buf, TRUE);
1024 } else { 1059 } else {
1025 debug_printf("Unhandled message!\n"); 1060 debug_printf("Unhandled message!\n");
1026 } 1061 }
1062
1063 return 1;
1064 }
1065
1066 static void msn_process_main_msg(struct gaim_connection *gc, char *msg)
1067 {
1068 struct msn_data *md = gc->proto_data;
1069 char *skiphead, *utf;
1070
1071 if (!g_strcasecmp(md->msguser, "hotmail")) {
1072 handle_hotmail(gc, msg);
1073 return;
1074 }
1075
1076 skiphead = strstr(msg, "\r\n\r\n");
1077 if (!skiphead || !skiphead[4])
1078 return;
1079 skiphead += 4;
1080 utf = utf8_to_str(skiphead);
1081 strip_linefeed(utf);
1082
1083 serv_got_im(gc, md->msguser, utf, 0, time(NULL));
1084
1085 g_free(utf);
1086 }
1087
1088 static void msn_callback(gpointer data, gint source, GaimInputCondition cond)
1089 {
1090 struct gaim_connection *gc = data;
1091 struct msn_data *md = gc->proto_data;
1092 char buf[MSN_BUF_LEN];
1093 int cont = 1;
1094 int len;
1095
1096 len = read(md->fd, buf, sizeof(buf));
1097
1098 if (len <= 0) {
1099 hide_login_progress(gc, "Error reading from server");
1100 signoff(gc);
1101 return;
1102 }
1103
1104 md->rxqueue = g_realloc(md->rxqueue, len + md->rxlen);
1105 memcpy(md->rxqueue + md->rxlen, buf, len);
1106 md->rxlen += len;
1107
1108 while (cont) {
1109 if (!md->rxlen)
1110 return;
1111
1112 if (md->msg) {
1113 char *msg;
1114 if (md->msglen > md->rxlen)
1115 return;
1116 msg = md->rxqueue;
1117 md->rxlen -= md->msglen;
1118 if (md->rxlen) {
1119 md->rxqueue = g_memdup(msg + md->msglen, md->rxlen);
1120 } else {
1121 md->rxqueue = NULL;
1122 msg = g_realloc(msg, md->msglen + 1);
1123 }
1124 msg[md->msglen] = 0;
1125 md->msglen = 0;
1126 md->msg = FALSE;
1127
1128 msn_process_main_msg(gc, msg);
1129
1130 g_free(md->msguser);
1131 g_free(msg);
1132 } else {
1133 char *end = md->rxqueue;
1134 int cmdlen;
1135 char *cmd;
1136 int i = 0;
1137
1138 while (i + 1 < md->rxlen) {
1139 if (*end == '\r' && end[1] == '\n')
1140 break;
1141 end++; i++;
1142 }
1143 if (i + 1 == md->rxlen)
1144 return;
1145
1146 cmdlen = end - md->rxqueue + 2;
1147 cmd = md->rxqueue;
1148 md->rxlen -= cmdlen;
1149 if (md->rxlen) {
1150 md->rxqueue = g_memdup(cmd + cmdlen, md->rxlen);
1151 } else {
1152 md->rxqueue = NULL;
1153 cmd = g_realloc(cmd, cmdlen + 1);
1154 }
1155 cmd[cmdlen] = 0;
1156
1157 debug_printf("MSN S: %s", cmd);
1158 g_strchomp(cmd);
1159 cont = msn_process_main(gc, cmd);
1160
1161 g_free(cmd);
1162 }
1163 }
1027 } 1164 }
1028 1165
1029 static void msn_login_xfr_connect(gpointer data, gint source, GaimInputCondition cond) 1166 static void msn_login_xfr_connect(gpointer data, gint source, GaimInputCondition cond)
1030 { 1167 {
1031 struct gaim_connection *gc = data; 1168 struct gaim_connection *gc = data;
1056 } 1193 }
1057 1194
1058 md->inpa = gaim_input_add(md->fd, GAIM_INPUT_READ, msn_login_callback, gc); 1195 md->inpa = gaim_input_add(md->fd, GAIM_INPUT_READ, msn_login_callback, gc);
1059 } 1196 }
1060 1197
1061 static void msn_login_callback(gpointer data, gint source, GaimInputCondition cond) 1198 static int msn_process_login(struct gaim_connection *gc, char *buf)
1062 { 1199 {
1063 struct gaim_connection *gc = data; 1200 struct msn_data *md = gc->proto_data;
1064 struct msn_data *md = gc->proto_data; 1201 char sendbuf[MSN_BUF_LEN];
1065 char buf[MSN_BUF_LEN];
1066 int i = 0;
1067
1068 bzero(buf, sizeof(buf));
1069 while ((read(md->fd, buf + i, 1) > 0) && (buf[i++] != '\n'))
1070 if (i == sizeof(buf))
1071 i--; /* yes i know this loses data but we shouldn't get messages this long
1072 and it's better than possibly writing past our buffer */
1073 if (i == 0 || buf[i - 1] != '\n') {
1074 hide_login_progress(gc, "Error reading from server");
1075 signoff(gc);
1076 return;
1077 }
1078 debug_printf("MSN S: %s", buf);
1079 g_strchomp(buf);
1080 1202
1081 if (!g_strncasecmp(buf, "VER", 3)) { 1203 if (!g_strncasecmp(buf, "VER", 3)) {
1082 /* we got VER, check to see that MSNP5 is in the list, then send INF */ 1204 /* we got VER, check to see that MSNP5 is in the list, then send INF */
1083 if (!strstr(buf, "MSNP5")) { 1205 if (!strstr(buf, "MSNP5")) {
1084 hide_login_progress(gc, "Protocol not supported"); 1206 hide_login_progress(gc, "Protocol not supported");
1085 signoff(gc); 1207 signoff(gc);
1086 return; 1208 return 0;
1087 } 1209 }
1088 1210
1089 g_snprintf(buf, sizeof(buf), "INF %d\r\n", ++md->trId); 1211 g_snprintf(sendbuf, sizeof(sendbuf), "INF %d\r\n", ++md->trId);
1090 if (msn_write(md->fd, buf, strlen(buf)) < 0) { 1212 if (msn_write(md->fd, sendbuf, strlen(sendbuf)) < 0) {
1091 hide_login_progress(gc, "Unable to request INF\n"); 1213 hide_login_progress(gc, "Unable to request INF\n");
1092 signoff(gc); 1214 signoff(gc);
1093 return; 1215 return 0;
1094 } 1216 }
1095 } else if (!g_strncasecmp(buf, "INF", 3)) { 1217 } else if (!g_strncasecmp(buf, "INF", 3)) {
1096 /* check to make sure we can use md5 */ 1218 /* check to make sure we can use md5 */
1097 if (!strstr(buf, "MD5")) { 1219 if (!strstr(buf, "MD5")) {
1098 hide_login_progress(gc, "Unable to login using MD5"); 1220 hide_login_progress(gc, "Unable to login using MD5");
1099 signoff(gc); 1221 signoff(gc);
1100 return; 1222 return 0;
1101 } 1223 }
1102 1224
1103 g_snprintf(buf, sizeof(buf), "USR %d MD5 I %s\r\n", ++md->trId, gc->username); 1225 g_snprintf(sendbuf, sizeof(sendbuf), "USR %d MD5 I %s\r\n", ++md->trId, gc->username);
1104 if (msn_write(md->fd, buf, strlen(buf)) < 0) { 1226 if (msn_write(md->fd, sendbuf, strlen(sendbuf)) < 0) {
1105 hide_login_progress(gc, "Unable to send USR\n"); 1227 hide_login_progress(gc, "Unable to send USR\n");
1106 signoff(gc); 1228 signoff(gc);
1107 return; 1229 return 0;
1108 } 1230 }
1109 1231
1110 set_login_progress(gc, 3, "Requesting to send password"); 1232 set_login_progress(gc, 3, "Requesting to send password");
1111 } else if (!g_strncasecmp(buf, "USR", 3)) { 1233 } else if (!g_strncasecmp(buf, "USR", 3)) {
1112 char *resp, *friend, *tmp = buf; 1234 char *resp, *friend, *tmp = buf;
1122 1244
1123 /* so here, we're either getting the challenge or the OK */ 1245 /* so here, we're either getting the challenge or the OK */
1124 if (!g_strcasecmp(resp, "OK")) { 1246 if (!g_strcasecmp(resp, "OK")) {
1125 g_snprintf(gc->displayname, sizeof(gc->displayname), "%s", friend); 1247 g_snprintf(gc->displayname, sizeof(gc->displayname), "%s", friend);
1126 1248
1127 g_snprintf(buf, sizeof(buf), "SYN %d 0\r\n", ++md->trId); 1249 g_snprintf(sendbuf, sizeof(sendbuf), "SYN %d 0\r\n", ++md->trId);
1128 if (msn_write(md->fd, buf, strlen(buf)) < 0) { 1250 if (msn_write(md->fd, sendbuf, strlen(sendbuf)) < 0) {
1129 hide_login_progress(gc, "Unable to write"); 1251 hide_login_progress(gc, "Unable to write");
1130 signoff(gc); 1252 signoff(gc);
1131 return; 1253 return 0;
1132 } 1254 }
1133 1255
1134 gaim_input_remove(md->inpa); 1256 gaim_input_remove(md->inpa);
1135 md->inpa = gaim_input_add(md->fd, GAIM_INPUT_READ, msn_callback, gc); 1257 md->inpa = gaim_input_add(md->fd, GAIM_INPUT_READ, msn_callback, gc);
1136 } else if (!g_strcasecmp(resp, "MD5")) { 1258 } else if (!g_strcasecmp(resp, "MD5")) {
1143 1265
1144 md5_init(&st); 1266 md5_init(&st);
1145 md5_append(&st, (const md5_byte_t *)buf2, strlen(buf2)); 1267 md5_append(&st, (const md5_byte_t *)buf2, strlen(buf2));
1146 md5_finish(&st, di); 1268 md5_finish(&st, di);
1147 1269
1148 g_snprintf(buf, sizeof(buf), "USR %d MD5 S ", ++md->trId); 1270 g_snprintf(sendbuf, sizeof(sendbuf), "USR %d MD5 S ", ++md->trId);
1149 for (i = 0; i < 16; i++) { 1271 for (i = 0; i < 16; i++) {
1150 g_snprintf(buf2, sizeof(buf2), "%02x", di[i]); 1272 g_snprintf(buf2, sizeof(buf2), "%02x", di[i]);
1151 strcat(buf, buf2); 1273 strcat(sendbuf, buf2);
1152 } 1274 }
1153 strcat(buf, "\n"); 1275 strcat(sendbuf, "\n");
1154 1276
1155 if (msn_write(md->fd, buf, strlen(buf)) < 0) { 1277 if (msn_write(md->fd, sendbuf, strlen(sendbuf)) < 0) {
1156 hide_login_progress(gc, "Unable to send password"); 1278 hide_login_progress(gc, "Unable to send password");
1157 signoff(gc); 1279 signoff(gc);
1158 return; 1280 return 0;
1159 } 1281 }
1160 1282
1161 set_login_progress(gc, 4, "Password sent"); 1283 set_login_progress(gc, 4, "Password sent");
1162 } 1284 }
1163 } else if (!g_strncasecmp(buf, "XFR", 3)) { 1285 } else if (!g_strncasecmp(buf, "XFR", 3)) {
1166 int i = 0; 1288 int i = 0;
1167 1289
1168 if (!host) { 1290 if (!host) {
1169 hide_login_progress(gc, "Got invalid XFR\n"); 1291 hide_login_progress(gc, "Got invalid XFR\n");
1170 signoff(gc); 1292 signoff(gc);
1171 return; 1293 return 0;
1172 } 1294 }
1173 1295
1174 GET_NEXT(host); 1296 GET_NEXT(host);
1175 while (host[i] && host[i] != ':') i++; 1297 while (host[i] && host[i] != ':') i++;
1176 if (host[i] == ':') { 1298 if (host[i] == ':') {
1187 md->fd = proxy_connect(host, port, msn_login_xfr_connect, gc); 1309 md->fd = proxy_connect(host, port, msn_login_xfr_connect, gc);
1188 if (md->fd < 0) { 1310 if (md->fd < 0) {
1189 hide_login_progress(gc, "Unable to transfer"); 1311 hide_login_progress(gc, "Unable to transfer");
1190 signoff(gc); 1312 signoff(gc);
1191 } 1313 }
1314 return 0;
1192 } else { 1315 } else {
1193 if (isdigit(*buf)) 1316 if (isdigit(*buf))
1194 hide_login_progress(gc, handle_errcode(buf, FALSE)); 1317 hide_login_progress(gc, handle_errcode(buf, FALSE));
1195 else 1318 else
1196 hide_login_progress(gc, "Unable to parse message"); 1319 hide_login_progress(gc, "Unable to parse message");
1197 signoff(gc); 1320 signoff(gc);
1198 return; 1321 return 0;
1322 }
1323
1324 return 1;
1325 }
1326
1327 static void msn_login_callback(gpointer data, gint source, GaimInputCondition cond)
1328 {
1329 struct gaim_connection *gc = data;
1330 struct msn_data *md = gc->proto_data;
1331 char buf[MSN_BUF_LEN];
1332 int cont = 1;
1333 int len;
1334
1335 len = read(md->fd, buf, sizeof(buf));
1336
1337 if (len <= 0) {
1338 hide_login_progress(gc, "Error reading from server");
1339 signoff(gc);
1340 return;
1341 }
1342
1343 md->rxqueue = g_realloc(md->rxqueue, len + md->rxlen);
1344 memcpy(md->rxqueue + md->rxlen, buf, len);
1345 md->rxlen += len;
1346
1347 while (cont) {
1348 char *end = md->rxqueue;
1349 int cmdlen;
1350 char *cmd;
1351 int i = 0;
1352
1353 if (!md->rxlen)
1354 return;
1355
1356 while (i + 1 < md->rxlen) {
1357 if (*end == '\r' && end[1] == '\n')
1358 break;
1359 end++; i++;
1360 }
1361 if (i + 1 == md->rxlen)
1362 return;
1363
1364 cmdlen = end - md->rxqueue + 2;
1365 cmd = md->rxqueue;
1366 md->rxlen -= cmdlen;
1367 if (md->rxlen) {
1368 md->rxqueue = g_memdup(cmd + cmdlen, md->rxlen);
1369 } else {
1370 md->rxqueue = NULL;
1371 cmd = g_realloc(cmd, cmdlen + 1);
1372 }
1373 cmd[cmdlen] = 0;
1374
1375 debug_printf("MSN S: %s", cmd);
1376 g_strchomp(cmd);
1377 cont = msn_process_login(gc, cmd);
1378
1379 g_free(cmd);
1199 } 1380 }
1200 } 1381 }
1201 1382
1202 static void msn_login_connect(gpointer data, gint source, GaimInputCondition cond) 1383 static void msn_login_connect(gpointer data, gint source, GaimInputCondition cond)
1203 { 1384 {
1252 { 1433 {
1253 struct msn_data *md = gc->proto_data; 1434 struct msn_data *md = gc->proto_data;
1254 close(md->fd); 1435 close(md->fd);
1255 if (md->inpa) 1436 if (md->inpa)
1256 gaim_input_remove(md->inpa); 1437 gaim_input_remove(md->inpa);
1438 g_free(md->rxqueue);
1439 if (md->msg)
1440 g_free(md->msguser);
1257 while (md->switches) 1441 while (md->switches)
1258 msn_kill_switch(md->switches->data); 1442 msn_kill_switch(md->switches->data);
1259 while (md->fl) { 1443 while (md->fl) {
1260 struct msn_buddy *tmp = md->fl->data; 1444 struct msn_buddy *tmp = md->fl->data;
1261 md->fl = g_slist_remove(md->fl, tmp); 1445 md->fl = g_slist_remove(md->fl, tmp);