Mercurial > pidgin
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); |