Mercurial > pidgin
comparison src/protocols/simple/simple.c @ 14069:d594f0466585
[gaim-migrate @ 16690]
Fix CID 221
I also fixed an imperial ton of leaks. It was quite amazing, actually.
There is also some other cleanup stuff in here too.
committer: Tailor Script <tailor@pidgin.im>
| author | Daniel Atallah <daniel.atallah@gmail.com> |
|---|---|
| date | Thu, 10 Aug 2006 23:42:17 +0000 |
| parents | 91a4cc3ee221 |
| children | 72660065eb3e |
comparison
equal
deleted
inserted
replaced
| 14068:6cb8bdc3366f | 14069:d594f0466585 |
|---|---|
| 128 entry = entry->next; | 128 entry = entry->next; |
| 129 } | 129 } |
| 130 return NULL; | 130 return NULL; |
| 131 } | 131 } |
| 132 | 132 |
| 133 static struct simple_watcher *watcher_find(struct simple_account_data *sip, gchar *name) { | 133 static struct simple_watcher *watcher_find(struct simple_account_data *sip, |
| 134 const gchar *name) { | |
| 134 struct simple_watcher *watcher; | 135 struct simple_watcher *watcher; |
| 135 GSList *entry = sip->watcher; | 136 GSList *entry = sip->watcher; |
| 136 while(entry) { | 137 while(entry) { |
| 137 watcher = entry->data; | 138 watcher = entry->data; |
| 138 if(!strcmp(name, watcher->name)) return watcher; | 139 if(!strcmp(name, watcher->name)) return watcher; |
| 139 entry = entry->next; | 140 entry = entry->next; |
| 140 } | 141 } |
| 141 return NULL; | 142 return NULL; |
| 142 } | 143 } |
| 143 | 144 |
| 144 static struct simple_watcher *watcher_create(struct simple_account_data *sip, gchar *name, gchar *callid, gchar *ourtag, gchar *theirtag, int needsxpidf) { | 145 static struct simple_watcher *watcher_create(struct simple_account_data *sip, |
| 146 const gchar *name, const gchar *callid, const gchar *ourtag, | |
| 147 const gchar *theirtag, gboolean needsxpidf) { | |
| 145 struct simple_watcher *watcher = g_new0(struct simple_watcher, 1); | 148 struct simple_watcher *watcher = g_new0(struct simple_watcher, 1); |
| 146 watcher->name = g_strdup(name); | 149 watcher->name = g_strdup(name); |
| 147 watcher->dialog.callid = g_strdup(callid); | 150 watcher->dialog.callid = g_strdup(callid); |
| 148 watcher->dialog.ourtag = g_strdup(ourtag); | 151 watcher->dialog.ourtag = g_strdup(ourtag); |
| 149 watcher->dialog.theirtag = g_strdup(theirtag); | 152 watcher->dialog.theirtag = g_strdup(theirtag); |
| 150 watcher->needsxpidf = needsxpidf; | 153 watcher->needsxpidf = needsxpidf; |
| 151 sip->watcher = g_slist_append(sip->watcher, watcher); | 154 sip->watcher = g_slist_append(sip->watcher, watcher); |
| 152 return watcher; | 155 return watcher; |
| 153 } | 156 } |
| 154 | 157 |
| 155 static void watcher_remove(struct simple_account_data *sip, gchar *name) { | 158 static void watcher_remove(struct simple_account_data *sip, const gchar *name) { |
| 156 struct simple_watcher *watcher = watcher_find(sip, name); | 159 struct simple_watcher *watcher = watcher_find(sip, name); |
| 157 sip->watcher = g_slist_remove(sip->watcher, watcher); | 160 sip->watcher = g_slist_remove(sip->watcher, watcher); |
| 158 g_free(watcher->name); | 161 g_free(watcher->name); |
| 159 g_free(watcher->dialog.callid); | 162 g_free(watcher->dialog.callid); |
| 160 g_free(watcher->dialog.ourtag); | 163 g_free(watcher->dialog.ourtag); |
| 297 ret = g_strdup_printf("Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", nc=\"%s\", response=\"%s\"\r\n", authuser, auth->realm, auth->nonce, target, noncecount, response); | 300 ret = g_strdup_printf("Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", nc=\"%s\", response=\"%s\"\r\n", authuser, auth->realm, auth->nonce, target, noncecount, response); |
| 298 g_free(response); | 301 g_free(response); |
| 299 return ret; | 302 return ret; |
| 300 } | 303 } |
| 301 | 304 |
| 302 static char *parse_attribute(const char *attrname, char *source) { | 305 static char *parse_attribute(const char *attrname, const char *source) { |
| 303 char *tmp, *tmp2, *retval = NULL; | 306 const char *tmp, *tmp2; |
| 307 char *retval = NULL; | |
| 304 int len = strlen(attrname); | 308 int len = strlen(attrname); |
| 305 | 309 |
| 306 if(!strncmp(source, attrname, len)) { | 310 if(!strncmp(source, attrname, len)) { |
| 307 tmp = source + len; | 311 tmp = source + len; |
| 308 tmp2 = g_strstr_len(tmp, strlen(tmp), "\""); | 312 tmp2 = g_strstr_len(tmp, strlen(tmp), "\""); |
| 522 g_string_append_printf(outstr, "\r\n%s", msg->body ? msg->body : ""); | 526 g_string_append_printf(outstr, "\r\n%s", msg->body ? msg->body : ""); |
| 523 sendout_pkt(sip->gc, outstr->str); | 527 sendout_pkt(sip->gc, outstr->str); |
| 524 g_string_free(outstr, TRUE); | 528 g_string_free(outstr, TRUE); |
| 525 } | 529 } |
| 526 | 530 |
| 527 static void send_sip_response(GaimConnection *gc, struct sipmsg *msg, int code, char *text, char *body) { | 531 static void send_sip_response(GaimConnection *gc, struct sipmsg *msg, int code, |
| 532 const char *text, const char *body) { | |
| 528 GSList *tmp = msg->headers; | 533 GSList *tmp = msg->headers; |
| 529 gchar *name; | 534 gchar *name; |
| 530 gchar *value; | 535 gchar *value; |
| 531 GString *outstr = g_string_new(""); | 536 GString *outstr = g_string_new(""); |
| 532 | 537 |
| 558 if(trans->msg) sipmsg_free(trans->msg); | 563 if(trans->msg) sipmsg_free(trans->msg); |
| 559 sip->transactions = g_slist_remove(sip->transactions, trans); | 564 sip->transactions = g_slist_remove(sip->transactions, trans); |
| 560 g_free(trans); | 565 g_free(trans); |
| 561 } | 566 } |
| 562 | 567 |
| 563 static void transactions_add_buf(struct simple_account_data *sip, gchar *buf, void *callback) { | 568 static void transactions_add_buf(struct simple_account_data *sip, const gchar *buf, void *callback) { |
| 564 struct transaction *trans = g_new0(struct transaction, 1); | 569 struct transaction *trans = g_new0(struct transaction, 1); |
| 565 trans->time = time(NULL); | 570 trans->time = time(NULL); |
| 566 trans->msg = sipmsg_parse_msg(buf); | 571 trans->msg = sipmsg_parse_msg(buf); |
| 567 trans->cseq = sipmsg_find_header(trans->msg, "CSeq"); | 572 trans->cseq = sipmsg_find_header(trans->msg, "CSeq"); |
| 568 trans->callback = callback; | 573 trans->callback = callback; |
| 591 struct simple_account_data *sip = gc->proto_data; | 596 struct simple_account_data *sip = gc->proto_data; |
| 592 char *callid = dialog ? g_strdup(dialog->callid) : gencallid(); | 597 char *callid = dialog ? g_strdup(dialog->callid) : gencallid(); |
| 593 char *auth = ""; | 598 char *auth = ""; |
| 594 const char *addh = ""; | 599 const char *addh = ""; |
| 595 gchar *branch = genbranch(); | 600 gchar *branch = genbranch(); |
| 601 gchar *tag = NULL; | |
| 596 char *buf; | 602 char *buf; |
| 597 | 603 |
| 598 if(!strcmp(method, "REGISTER")) { | 604 if(!strcmp(method, "REGISTER")) { |
| 599 if(sip->regcallid) { | 605 if(sip->regcallid) { |
| 600 g_free(callid); | 606 g_free(callid); |
| 615 buf = auth_header(sip, &sip->proxy, method, url); | 621 buf = auth_header(sip, &sip->proxy, method, url); |
| 616 auth = g_strdup_printf("Proxy-Authorization: %s", buf); | 622 auth = g_strdup_printf("Proxy-Authorization: %s", buf); |
| 617 g_free(buf); | 623 g_free(buf); |
| 618 gaim_debug(GAIM_DEBUG_MISC, "simple", "header %s", auth); | 624 gaim_debug(GAIM_DEBUG_MISC, "simple", "header %s", auth); |
| 619 } | 625 } |
| 626 | |
| 627 if (!dialog) | |
| 628 tag = gentag(); | |
| 620 | 629 |
| 621 buf = g_strdup_printf("%s %s SIP/2.0\r\n" | 630 buf = g_strdup_printf("%s %s SIP/2.0\r\n" |
| 622 "Via: SIP/2.0/%s %s:%d;branch=%s\r\n" | 631 "Via: SIP/2.0/%s %s:%d;branch=%s\r\n" |
| 623 /* Don't know what epid is, but LCS wants it */ | 632 /* Don't know what epid is, but LCS wants it */ |
| 624 "From: <sip:%s@%s>;tag=%s;epid=1234567890\r\n" | 633 "From: <sip:%s@%s>;tag=%s;epid=1234567890\r\n" |
| 635 gaim_network_get_my_ip(-1), | 644 gaim_network_get_my_ip(-1), |
| 636 sip->listenport, | 645 sip->listenport, |
| 637 branch, | 646 branch, |
| 638 sip->username, | 647 sip->username, |
| 639 sip->servername, | 648 sip->servername, |
| 640 dialog ? dialog->ourtag : gentag(), | 649 dialog ? dialog->ourtag : tag, |
| 641 to, | 650 to, |
| 642 dialog ? ";tag=" : "", | 651 dialog ? ";tag=" : "", |
| 643 dialog ? dialog->theirtag : "", | 652 dialog ? dialog->theirtag : "", |
| 644 ++sip->cseq, | 653 ++sip->cseq, |
| 645 method, | 654 method, |
| 646 callid, | 655 callid, |
| 647 auth, | 656 auth, |
| 648 addh, | 657 addh, |
| 649 strlen(body), | 658 strlen(body), |
| 650 body); | 659 body); |
| 660 | |
| 661 g_free(tag); | |
| 662 g_free(auth); | |
| 651 g_free(branch); | 663 g_free(branch); |
| 652 g_free(callid); | 664 g_free(callid); |
| 653 | 665 |
| 654 /* add to ongoing transactions */ | 666 /* add to ongoing transactions */ |
| 655 | 667 |
| 689 | 701 |
| 690 static void do_register(struct simple_account_data *sip) { | 702 static void do_register(struct simple_account_data *sip) { |
| 691 do_register_exp(sip, sip->registerexpire); | 703 do_register_exp(sip, sip->registerexpire); |
| 692 } | 704 } |
| 693 | 705 |
| 694 static gchar *parse_from(gchar *hdr) { | 706 static gchar *parse_from(const gchar *hdr) { |
| 695 gchar *from = hdr; | 707 gchar *from; |
| 696 gchar *tmp; | 708 const gchar *tmp, *tmp2 = hdr; |
| 697 | 709 |
| 698 if(!from) return NULL; | 710 if(!hdr) return NULL; |
| 699 gaim_debug_info("simple", "parsing address out of %s\n", from); | 711 gaim_debug_info("simple", "parsing address out of %s\n", hdr); |
| 700 tmp = strchr(from, '<'); | 712 tmp = strchr(hdr, '<'); |
| 701 | 713 |
| 702 /* i hate the different SIP UA behaviours... */ | 714 /* i hate the different SIP UA behaviours... */ |
| 703 if(tmp) { /* sip address in <...> */ | 715 if(tmp) { /* sip address in <...> */ |
| 704 from = tmp+1; | 716 tmp2 = tmp + 1; |
| 705 tmp = strchr(from, '>'); | 717 tmp = strchr(tmp2, '>'); |
| 706 if(tmp) { | 718 if(tmp) { |
| 707 from = g_strndup(from, tmp-from); | 719 from = g_strndup(tmp2, tmp - tmp2); |
| 708 } else { | 720 } else { |
| 709 gaim_debug_info("simple", "found < without > in From\n"); | 721 gaim_debug_info("simple", "found < without > in From\n"); |
| 710 return NULL; | 722 return NULL; |
| 711 } | 723 } |
| 712 } else { | 724 } else { |
| 713 tmp = strchr(from, ';'); | 725 tmp = strchr(tmp2, ';'); |
| 714 if(tmp) { | 726 if(tmp) { |
| 715 from = g_strndup(from, tmp-from); | 727 from = g_strndup(tmp2, tmp - tmp2); |
| 716 } else { | 728 } else { |
| 717 from = g_strdup(from); | 729 from = g_strdup(tmp2); |
| 718 } | 730 } |
| 719 } | 731 } |
| 720 gaim_debug_info("simple", "got %s\n", from); | 732 gaim_debug_info("simple", "got %s\n", from); |
| 721 return from; | 733 return from; |
| 722 } | 734 } |
| 723 | 735 |
| 724 static gboolean process_subscribe_response(struct simple_account_data *sip, struct sipmsg *msg, struct transaction *tc) { | 736 static gboolean process_subscribe_response(struct simple_account_data *sip, struct sipmsg *msg, struct transaction *tc) { |
| 725 gchar *to = parse_from(sipmsg_find_header(tc->msg, "To")); /* cant be NULL since it is our own msg */ | 737 gchar *to; |
| 726 | 738 |
| 727 if(msg->response == 200 || msg->response == 202) { | 739 if(msg->response == 200 || msg->response == 202) { |
| 728 return TRUE; | 740 return TRUE; |
| 729 } | 741 } |
| 742 | |
| 743 to = parse_from(sipmsg_find_header(tc->msg, "To")); /* cant be NULL since it is our own msg */ | |
| 730 | 744 |
| 731 /* we can not subscribe -> user is offline (TODO unknown status?) */ | 745 /* we can not subscribe -> user is offline (TODO unknown status?) */ |
| 732 | 746 |
| 733 gaim_prpl_got_user_status(sip->account, to, "offline", NULL); | 747 gaim_prpl_got_user_status(sip->account, to, "offline", NULL); |
| 734 g_free(to); | 748 g_free(to); |
| 738 static void simple_subscribe(struct simple_account_data *sip, struct simple_buddy *buddy) { | 752 static void simple_subscribe(struct simple_account_data *sip, struct simple_buddy *buddy) { |
| 739 gchar *contact = "Expires: 1200\r\nAccept: application/pidf+xml, application/xpidf+xml\r\nEvent: presence\r\n"; | 753 gchar *contact = "Expires: 1200\r\nAccept: application/pidf+xml, application/xpidf+xml\r\nEvent: presence\r\n"; |
| 740 gchar *to; | 754 gchar *to; |
| 741 gchar *tmp; | 755 gchar *tmp; |
| 742 | 756 |
| 743 if(strstr(buddy->name,"sip:")) | 757 if(strstr(buddy->name, "sip:")) |
| 744 to = g_strdup(buddy->name); | 758 to = g_strdup(buddy->name); |
| 745 else | 759 else |
| 746 to = g_strdup_printf("sip:%s", buddy->name); | 760 to = g_strdup_printf("sip:%s", buddy->name); |
| 747 | 761 |
| 748 tmp = get_contact(sip); | 762 tmp = get_contact(sip); |
| 766 static gboolean simple_add_lcs_contacts(struct simple_account_data *sip, struct sipmsg *msg, struct transaction *tc) { | 780 static gboolean simple_add_lcs_contacts(struct simple_account_data *sip, struct sipmsg *msg, struct transaction *tc) { |
| 767 gchar *tmp; | 781 gchar *tmp; |
| 768 xmlnode *item, *group, *isc; | 782 xmlnode *item, *group, *isc; |
| 769 const char *name_group; | 783 const char *name_group; |
| 770 GaimBuddy *b; | 784 GaimBuddy *b; |
| 771 GaimGroup *g; | 785 GaimGroup *g = NULL; |
| 772 struct simple_buddy *bs; | 786 struct simple_buddy *bs; |
| 773 int len = msg->bodylen; | 787 int len = msg->bodylen; |
| 774 | 788 |
| 775 | 789 |
| 776 tmp = sipmsg_find_header(msg, "Event"); | 790 tmp = sipmsg_find_header(msg, "Event"); |
| 777 if(tmp && !strncmp(tmp,"vnd-microsoft-roaming-contacts",30)){ | 791 if(tmp && !strncmp(tmp, "vnd-microsoft-roaming-contacts", 30)){ |
| 778 | 792 |
| 779 gaim_debug_info("simple","simple_add_lcs_contacts->%s-%d\n",msg->body, len); | 793 gaim_debug_info("simple", "simple_add_lcs_contacts->%s-%d\n", msg->body, len); |
| 780 /*Convert the contact from XML to Gaim Buddies*/ | 794 /*Convert the contact from XML to Gaim Buddies*/ |
| 781 isc = xmlnode_from_str(msg->body, len); | 795 isc = xmlnode_from_str(msg->body, len); |
| 782 | 796 |
| 783 /* ToDo. Find for all groups */ | 797 /* ToDo. Find for all groups */ |
| 784 group = xmlnode_get_child(isc, "group"); | 798 if ((group = xmlnode_get_child(isc, "group"))) { |
| 785 name_group = xmlnode_get_attrib(group, "name"); | 799 name_group = xmlnode_get_attrib(group, "name"); |
| 786 gaim_debug_info("simple","name_group->%s\n",name_group); | 800 gaim_debug_info("simple", "name_group->%s\n", name_group); |
| 787 g = gaim_find_group(name_group); | 801 g = gaim_find_group(name_group); |
| 788 if(!g) { | 802 if(!g) |
| 803 g = gaim_group_new(name_group); | |
| 804 } | |
| 805 | |
| 806 if (!g) { | |
| 789 g = gaim_find_group("Buddies"); | 807 g = gaim_find_group("Buddies"); |
| 790 if(!g){ | 808 if(!g) |
| 791 g = gaim_group_new("Buddies"); | 809 g = gaim_group_new("Buddies"); |
| 792 } | |
| 793 }else{ | |
| 794 g = gaim_group_new(name_group); | |
| 795 } | 810 } |
| 796 | 811 |
| 797 for(item = xmlnode_get_child(isc, "contact"); item; item = xmlnode_get_next_twin(item)) | 812 for(item = xmlnode_get_child(isc, "contact"); item; item = xmlnode_get_next_twin(item)) |
| 798 { | 813 { |
| 799 const char *uri, *name, *groups; | 814 const char *uri, *name, *groups; |
| 815 char *buddy_name; | |
| 800 uri = xmlnode_get_attrib(item, "uri"); | 816 uri = xmlnode_get_attrib(item, "uri"); |
| 801 name = xmlnode_get_attrib(item, "name"); | 817 name = xmlnode_get_attrib(item, "name"); |
| 802 groups = xmlnode_get_attrib(item, "groups"); | 818 groups = xmlnode_get_attrib(item, "groups"); |
| 803 gaim_debug_info("simple","URI->%s\n",uri); | 819 gaim_debug_info("simple", "URI->%s\n", uri); |
| 804 b = gaim_find_buddy(sip->account, g_strdup_printf("sip:%s",uri)); | 820 |
| 821 buddy_name = g_strdup_printf("sip:%s", uri); | |
| 822 | |
| 823 b = gaim_find_buddy(sip->account, buddy_name); | |
| 805 if(!b){ | 824 if(!b){ |
| 806 b = gaim_buddy_new(sip->account, g_strdup_printf("sip:%s",uri), uri); | 825 b = gaim_buddy_new(sip->account, buddy_name, uri); |
| 807 } | 826 } |
| 827 g_free(buddy_name); | |
| 828 | |
| 808 gaim_blist_add_buddy(b, NULL, g, NULL); | 829 gaim_blist_add_buddy(b, NULL, g, NULL); |
| 809 gaim_blist_alias_buddy(b, uri); | 830 gaim_blist_alias_buddy(b, uri); |
| 810 bs = g_new0(struct simple_buddy, 1); | 831 bs = g_new0(struct simple_buddy, 1); |
| 811 bs->name = g_strdup(b->name); | 832 bs->name = g_strdup(b->name); |
| 812 g_hash_table_insert(sip->buddies, bs->name, bs); | 833 g_hash_table_insert(sip->buddies, bs->name, bs); |
| 819 static void simple_subscribe_buddylist(struct simple_account_data *sip) { | 840 static void simple_subscribe_buddylist(struct simple_account_data *sip) { |
| 820 gchar *contact = "Event: vnd-microsoft-roaming-contacts\r\nAccept: application/vnd-microsoft-roaming-contacts+xml\r\nSupported: com.microsoft.autoextend\r\nSupported: ms-benotify\r\nProxy-Require: ms-benotify\r\nSupported: ms-piggyback-first-notify\r\n"; | 841 gchar *contact = "Event: vnd-microsoft-roaming-contacts\r\nAccept: application/vnd-microsoft-roaming-contacts+xml\r\nSupported: com.microsoft.autoextend\r\nSupported: ms-benotify\r\nProxy-Require: ms-benotify\r\nSupported: ms-piggyback-first-notify\r\n"; |
| 821 gchar *to; | 842 gchar *to; |
| 822 gchar *tmp; | 843 gchar *tmp; |
| 823 to = g_strdup_printf("sip:%s@%s", sip->username, sip->servername); | 844 to = g_strdup_printf("sip:%s@%s", sip->username, sip->servername); |
| 824 | 845 |
| 825 tmp = get_contact(sip); | 846 tmp = get_contact(sip); |
| 826 | 847 |
| 827 contact = g_strdup_printf("%sContact: %s\r\n", contact, tmp); | 848 contact = g_strdup_printf("%sContact: %s\r\n", contact, tmp); |
| 828 g_free(tmp); | 849 g_free(tmp); |
| 829 | 850 |
| 830 send_sip_request(sip->gc, "SUBSCRIBE",to, to, contact, "", NULL, simple_add_lcs_contacts); | 851 send_sip_request(sip->gc, "SUBSCRIBE", to, to, contact, "", NULL, simple_add_lcs_contacts); |
| 831 | 852 |
| 832 g_free(to); | 853 g_free(to); |
| 833 g_free(contact); | 854 g_free(contact); |
| 834 } | 855 } |
| 835 | 856 |
| 951 | 972 |
| 952 statedata = xmlnode_get_data(state); | 973 statedata = xmlnode_get_data(state); |
| 953 if(statedata) { | 974 if(statedata) { |
| 954 if(strstr(statedata, "active")) serv_got_typing(sip->gc, from, 0, GAIM_TYPING); | 975 if(strstr(statedata, "active")) serv_got_typing(sip->gc, from, 0, GAIM_TYPING); |
| 955 else serv_got_typing_stopped(sip->gc, from); | 976 else serv_got_typing_stopped(sip->gc, from); |
| 977 | |
| 978 g_free(statedata); | |
| 956 } | 979 } |
| 957 xmlnode_free(isc); | 980 xmlnode_free(isc); |
| 958 send_sip_response(sip->gc, msg, 200, "OK", NULL); | 981 send_sip_response(sip->gc, msg, 200, "OK", NULL); |
| 959 found = TRUE; | 982 found = TRUE; |
| 960 } | 983 } |
| 982 /* get buddies from blist */ | 1005 /* get buddies from blist */ |
| 983 simple_get_buddies(sip->gc); | 1006 simple_get_buddies(sip->gc); |
| 984 | 1007 |
| 985 subscribe_timeout(sip); | 1008 subscribe_timeout(sip); |
| 986 tmp = sipmsg_find_header(msg, "Allow-Events"); | 1009 tmp = sipmsg_find_header(msg, "Allow-Events"); |
| 987 if(tmp && strstr(tmp,"vnd-microsoft-provisioning")){ | 1010 if(tmp && strstr(tmp, "vnd-microsoft-provisioning")){ |
| 988 simple_subscribe_buddylist(sip); | 1011 simple_subscribe_buddylist(sip); |
| 989 } | 1012 } |
| 990 | 1013 |
| 991 break; | 1014 break; |
| 992 case 401: | 1015 case 401: |
| 1041 } | 1064 } |
| 1042 | 1065 |
| 1043 if(strstr(tmp2, "open")) { | 1066 if(strstr(tmp2, "open")) { |
| 1044 isonline = TRUE; | 1067 isonline = TRUE; |
| 1045 } | 1068 } |
| 1069 | |
| 1070 g_free(tmp2); | |
| 1046 | 1071 |
| 1047 if(isonline) gaim_prpl_got_user_status(sip->account, from, "available", NULL); | 1072 if(isonline) gaim_prpl_got_user_status(sip->account, from, "available", NULL); |
| 1048 else gaim_prpl_got_user_status(sip->account, from, "offline", NULL); | 1073 else gaim_prpl_got_user_status(sip->account, from, "offline", NULL); |
| 1049 | 1074 |
| 1050 xmlnode_free(pidf); | 1075 xmlnode_free(pidf); |
| 1082 * then return 0 instead. | 1107 * then return 0 instead. |
| 1083 */ | 1108 */ |
| 1084 return 1; | 1109 return 1; |
| 1085 } | 1110 } |
| 1086 | 1111 |
| 1087 static gchar *find_tag(gchar *hdr) { | 1112 static gchar *find_tag(const gchar *hdr) { |
| 1088 gchar *tmp = strstr(hdr, ";tag="); | 1113 const gchar *tmp = strstr(hdr, ";tag="), *tmp2; |
| 1089 gchar *tmp2; | 1114 |
| 1090 if(!tmp) return NULL; | 1115 if(!tmp) return NULL; |
| 1091 tmp += 5; | 1116 tmp += 5; |
| 1092 if((tmp2 = strchr(tmp, ';'))) { | 1117 if((tmp2 = strchr(tmp, ';'))) { |
| 1093 tmp2[0] = '\0'; | 1118 return g_strndup(tmp, tmp2 - tmp); |
| 1094 tmp = g_strdup(tmp); | |
| 1095 tmp2[0] = ';'; | |
| 1096 return tmp; | |
| 1097 } | 1119 } |
| 1098 return g_strdup(tmp); | 1120 return g_strdup(tmp); |
| 1099 } | 1121 } |
| 1100 | 1122 |
| 1101 static gchar* gen_xpidf(struct simple_account_data *sip) { | 1123 static gchar* gen_xpidf(struct simple_account_data *sip) { |
| 1160 send_sip_request(sip->gc, "PUBLISH", uri, uri, | 1182 send_sip_request(sip->gc, "PUBLISH", uri, uri, |
| 1161 "Expires: 600\r\nEvent: presence\r\n" | 1183 "Expires: 600\r\nEvent: presence\r\n" |
| 1162 "Content-Type: application/pidf+xml\r\n", | 1184 "Content-Type: application/pidf+xml\r\n", |
| 1163 doc, NULL, process_publish_response); | 1185 doc, NULL, process_publish_response); |
| 1164 sip->republish = time(NULL) + 500; | 1186 sip->republish = time(NULL) + 500; |
| 1187 g_free(uri); | |
| 1165 g_free(doc); | 1188 g_free(doc); |
| 1166 } | 1189 } |
| 1167 | 1190 |
| 1168 static void process_incoming_subscribe(struct simple_account_data *sip, struct sipmsg *msg) { | 1191 static void process_incoming_subscribe(struct simple_account_data *sip, struct sipmsg *msg) { |
| 1169 gchar *from = parse_from(sipmsg_find_header(msg, "From")); | 1192 const char *from_hdr = sipmsg_find_header(msg, "From"); |
| 1170 gchar *theirtag = find_tag(sipmsg_find_header(msg, "From")); | 1193 gchar *from = parse_from(from_hdr); |
| 1194 gchar *theirtag = find_tag(from_hdr); | |
| 1171 gchar *ourtag = find_tag(sipmsg_find_header(msg, "To")); | 1195 gchar *ourtag = find_tag(sipmsg_find_header(msg, "To")); |
| 1172 gboolean tagadded = FALSE; | 1196 gboolean tagadded = FALSE; |
| 1173 gchar *callid = sipmsg_find_header(msg, "Call-ID"); | 1197 gchar *callid = sipmsg_find_header(msg, "Call-ID"); |
| 1174 gchar *expire = sipmsg_find_header(msg, "Expire"); | 1198 gchar *expire = sipmsg_find_header(msg, "Expire"); |
| 1175 gchar *tmp; | 1199 gchar *tmp; |
| 1178 tagadded = TRUE; | 1202 tagadded = TRUE; |
| 1179 ourtag = gentag(); | 1203 ourtag = gentag(); |
| 1180 } | 1204 } |
| 1181 if(!watcher) { /* new subscription */ | 1205 if(!watcher) { /* new subscription */ |
| 1182 gchar *acceptheader = sipmsg_find_header(msg, "Accept"); | 1206 gchar *acceptheader = sipmsg_find_header(msg, "Accept"); |
| 1183 int needsxpidf = 0; | 1207 gboolean needsxpidf = FALSE; |
| 1184 if(!gaim_privacy_check(sip->account, from)) { | 1208 if(!gaim_privacy_check(sip->account, from)) { |
| 1185 send_sip_response(sip->gc, msg, 202, "Ok", NULL); | 1209 send_sip_response(sip->gc, msg, 202, "Ok", NULL); |
| 1186 goto privend; | 1210 goto privend; |
| 1187 } | 1211 } |
| 1188 if(acceptheader) { | 1212 if(acceptheader) { |
| 1190 int foundpidf = 0; | 1214 int foundpidf = 0; |
| 1191 int foundxpidf = 0; | 1215 int foundxpidf = 0; |
| 1192 while(tmp && tmp < acceptheader + strlen(acceptheader)) { | 1216 while(tmp && tmp < acceptheader + strlen(acceptheader)) { |
| 1193 gchar *tmp2 = strchr(tmp, ','); | 1217 gchar *tmp2 = strchr(tmp, ','); |
| 1194 if(tmp2) *tmp2 = '\0'; | 1218 if(tmp2) *tmp2 = '\0'; |
| 1195 if(!strcmp("application/pidf+xml",tmp)) | 1219 if(!strcmp("application/pidf+xml", tmp)) |
| 1196 foundpidf = 1; | 1220 foundpidf = 1; |
| 1197 if(!strcmp("application/xpidf+xml",tmp)) | 1221 if(!strcmp("application/xpidf+xml", tmp)) |
| 1198 foundxpidf = 1; | 1222 foundxpidf = 1; |
| 1199 if(tmp2) { | 1223 if(tmp2) { |
| 1200 *tmp2 = ','; | 1224 *tmp2 = ','; |
| 1201 tmp = tmp2; | 1225 tmp = tmp2; |
| 1202 while(*tmp == ' ') tmp++; | 1226 while(*tmp == ' ') tmp++; |
| 1203 } else | 1227 } else |
| 1204 tmp = 0; | 1228 tmp = 0; |
| 1205 } | 1229 } |
| 1206 if(!foundpidf && foundxpidf) needsxpidf = 1; | 1230 if(!foundpidf && foundxpidf) needsxpidf = TRUE; |
| 1207 g_free(acceptheader); | 1231 g_free(acceptheader); |
| 1208 } | 1232 } |
| 1209 watcher = watcher_create(sip, from, callid, ourtag, theirtag, needsxpidf); | 1233 watcher = watcher_create(sip, from, callid, ourtag, theirtag, needsxpidf); |
| 1210 } | 1234 } |
| 1211 if(tagadded) { | 1235 if(tagadded) { |
| 1212 gchar *to = g_strdup_printf("%s;tag=%s", sipmsg_find_header(msg, "To"), ourtag); | 1236 gchar *to = g_strdup_printf("%s;tag=%s", sipmsg_find_header(msg, "To"), ourtag); |
| 1213 sipmsg_remove_header(msg, "To"); | 1237 sipmsg_remove_header(msg, "To"); |
| 1214 sipmsg_add_header(msg, "To", to); | 1238 sipmsg_add_header(msg, "To", to); |
| 1239 g_free(to); | |
| 1215 } | 1240 } |
| 1216 if(expire) | 1241 if(expire) |
| 1217 watcher->expire = time(NULL) + strtol(expire, NULL, 10); | 1242 watcher->expire = time(NULL) + strtol(expire, NULL, 10); |
| 1218 else | 1243 else |
| 1219 watcher->expire = time(NULL) + 600; | 1244 watcher->expire = time(NULL) + 600; |
| 1220 sipmsg_remove_header(msg, "Contact"); | 1245 sipmsg_remove_header(msg, "Contact"); |
| 1221 tmp = get_contact(sip); | 1246 tmp = get_contact(sip); |
| 1222 sipmsg_add_header(msg, "Contact", tmp); | 1247 sipmsg_add_header(msg, "Contact", tmp); |
| 1223 g_free(tmp); | 1248 g_free(tmp); |
| 1224 gaim_debug_info("simple","got subscribe: name %s ourtag %s theirtag %s callid %s\n", watcher->name, watcher->dialog.ourtag, watcher->dialog.theirtag, watcher->dialog.callid); | 1249 gaim_debug_info("simple", "got subscribe: name %s ourtag %s theirtag %s callid %s\n", watcher->name, watcher->dialog.ourtag, watcher->dialog.theirtag, watcher->dialog.callid); |
| 1225 send_sip_response(sip->gc, msg, 200, "Ok", NULL); | 1250 send_sip_response(sip->gc, msg, 200, "Ok", NULL); |
| 1226 send_notify(sip, watcher); | 1251 send_notify(sip, watcher); |
| 1227 privend: | 1252 privend: |
| 1228 g_free(from); | 1253 g_free(from); |
| 1229 g_free(theirtag); | 1254 g_free(theirtag); |
| 1272 if(msg->response == 100) { | 1297 if(msg->response == 100) { |
| 1273 /* ignore provisional response */ | 1298 /* ignore provisional response */ |
| 1274 gaim_debug_info("simple", "got trying response\n"); | 1299 gaim_debug_info("simple", "got trying response\n"); |
| 1275 } else { | 1300 } else { |
| 1276 sip->proxy.retries = 0; | 1301 sip->proxy.retries = 0; |
| 1277 if(!strcmp(trans->msg->method,"REGISTER")) { | 1302 if(!strcmp(trans->msg->method, "REGISTER")) { |
| 1278 if(msg->response == 401) sip->registrar.retries++; | 1303 if(msg->response == 401) sip->registrar.retries++; |
| 1279 else sip->registrar.retries = 0; | 1304 else sip->registrar.retries = 0; |
| 1280 } else { | 1305 } else { |
| 1281 if(msg->response == 401) { | 1306 if(msg->response == 401) { |
| 1282 gchar *resend, *auth, *ptmp; | 1307 gchar *resend, *auth, *ptmp; |
| 1325 /* according to the RFC remove CRLF at the beginning */ | 1350 /* according to the RFC remove CRLF at the beginning */ |
| 1326 while(*cur == '\r' || *cur == '\n') { | 1351 while(*cur == '\r' || *cur == '\n') { |
| 1327 cur++; | 1352 cur++; |
| 1328 } | 1353 } |
| 1329 if(cur != conn->inbuf) { | 1354 if(cur != conn->inbuf) { |
| 1330 memmove(conn->inbuf, cur, conn->inbufused-(cur-conn->inbuf)); | 1355 memmove(conn->inbuf, cur, conn->inbufused - (cur - conn->inbuf)); |
| 1331 conn->inbufused = strlen(conn->inbuf); | 1356 conn->inbufused = strlen(conn->inbuf); |
| 1332 } | 1357 } |
| 1333 | 1358 |
| 1334 /* Received a full Header? */ | 1359 /* Received a full Header? */ |
| 1335 if((cur = strstr(conn->inbuf, "\r\n\r\n")) != NULL) { | 1360 if((cur = strstr(conn->inbuf, "\r\n\r\n")) != NULL) { |
| 1338 cur[0] = '\0'; | 1363 cur[0] = '\0'; |
| 1339 gaim_debug_info("simple", "\n\nreceived - %s\n######\n%s\n#######\n\n", ctime(&currtime), conn->inbuf); | 1364 gaim_debug_info("simple", "\n\nreceived - %s\n######\n%s\n#######\n\n", ctime(&currtime), conn->inbuf); |
| 1340 msg = sipmsg_parse_header(conn->inbuf); | 1365 msg = sipmsg_parse_header(conn->inbuf); |
| 1341 cur[0] = '\r'; | 1366 cur[0] = '\r'; |
| 1342 cur += 2; | 1367 cur += 2; |
| 1343 restlen = conn->inbufused - (cur-conn->inbuf); | 1368 restlen = conn->inbufused - (cur - conn->inbuf); |
| 1344 if(restlen >= msg->bodylen) { | 1369 if(restlen >= msg->bodylen) { |
| 1345 dummy = g_malloc(msg->bodylen + 1); | 1370 dummy = g_malloc(msg->bodylen + 1); |
| 1346 memcpy(dummy, cur, msg->bodylen); | 1371 memcpy(dummy, cur, msg->bodylen); |
| 1347 dummy[msg->bodylen] = '\0'; | 1372 dummy[msg->bodylen] = '\0'; |
| 1348 msg->body = dummy; | 1373 msg->body = dummy; |
