Mercurial > pidgin.yaz
comparison src/protocols/msn/msn.c @ 4150:1bd663beada5
[gaim-migrate @ 4369]
potato chip
file receive in msn
committer: Tailor Script <tailor@pidgin.im>
author | Rob Flynn <gaim@robflynn.com> |
---|---|
date | Sat, 28 Dec 2002 05:15:43 +0000 |
parents | 474265997752 |
children | 9615c6996348 |
comparison
equal
deleted
inserted
replaced
4149:baf9d94e0128 | 4150:1bd663beada5 |
---|---|
6 #include <winsock.h> | 6 #include <winsock.h> |
7 #include <io.h> | 7 #include <io.h> |
8 #endif | 8 #endif |
9 | 9 |
10 | 10 |
11 #include <sys/stat.h> | |
11 #include <stdlib.h> | 12 #include <stdlib.h> |
12 #include <string.h> | 13 #include <string.h> |
13 #include <errno.h> | 14 #include <errno.h> |
14 #include <stdio.h> | 15 #include <stdio.h> |
15 #include <ctype.h> | 16 #include <ctype.h> |
56 #define MSN_PORT 1863 | 57 #define MSN_PORT 1863 |
57 | 58 |
58 #define MSN_TYPING_RECV_TIMEOUT 6 | 59 #define MSN_TYPING_RECV_TIMEOUT 6 |
59 #define MSN_TYPING_SEND_TIMEOUT 4 | 60 #define MSN_TYPING_SEND_TIMEOUT 4 |
60 | 61 |
61 | 62 struct msn_file_transfer { |
62 | 63 enum { MFT_SENDFILE_IN, MFT_SENDFILE_OUT } type; |
63 struct msn_data { | 64 struct file_transfer *xfer; |
65 struct gaim_connection *gc; | |
66 | |
64 int fd; | 67 int fd; |
65 int trId; | |
66 int inpa; | 68 int inpa; |
69 | |
70 char *filename; | |
71 | |
72 char *sn; | |
73 char ip[16]; | |
74 int port; | |
75 | |
76 unsigned long cookie; | |
77 unsigned long authcookie; | |
78 | |
79 int len; | |
67 | 80 |
68 char *rxqueue; | 81 char *rxqueue; |
69 int rxlen; | 82 int rxlen; |
70 gboolean msg; | 83 gboolean msg; |
71 char *msguser; | 84 char *msguser; |
72 int msglen; | 85 int msglen; |
86 }; | |
87 | |
88 struct msn_data { | |
89 int fd; | |
90 int trId; | |
91 int inpa; | |
92 | |
93 char *rxqueue; | |
94 int rxlen; | |
95 gboolean msg; | |
96 char *msguser; | |
97 int msglen; | |
73 | 98 |
74 GSList *switches; | 99 GSList *switches; |
75 GSList *fl; | 100 GSList *fl; |
76 GSList *permit; | 101 GSList *permit; |
77 GSList *deny; | 102 GSList *deny; |
103 GSList *file_transfers; | |
78 | 104 |
79 char *kv; | 105 char *kv; |
80 char *sid; | 106 char *sid; |
81 char *mspauth; | 107 char *mspauth; |
82 unsigned long sl; | 108 unsigned long sl; |
109 char *friend; | 135 char *friend; |
110 }; | 136 }; |
111 | 137 |
112 static void msn_login_callback(gpointer, gint, GaimInputCondition); | 138 static void msn_login_callback(gpointer, gint, GaimInputCondition); |
113 static void msn_login_xfr_connect(gpointer, gint, GaimInputCondition); | 139 static void msn_login_xfr_connect(gpointer, gint, GaimInputCondition); |
140 static struct msn_file_transfer *find_mft_by_cookie(struct gaim_connection *gc, | |
141 unsigned long cookie); | |
142 static struct msn_file_transfer *find_mft_by_xfer(struct gaim_connection *gc, | |
143 struct file_transfer *xfer); | |
114 | 144 |
115 #define GET_NEXT(tmp) while (*(tmp) && *(tmp) != ' ') \ | 145 #define GET_NEXT(tmp) while (*(tmp) && *(tmp) != ' ') \ |
116 (tmp)++; \ | 146 (tmp)++; \ |
117 *(tmp)++ = 0; \ | 147 *(tmp)++ = 0; \ |
118 while (*(tmp) && *(tmp) == ' ') \ | 148 while (*(tmp) && *(tmp) == ' ') \ |
595 | 625 |
596 cur = url_decode(ret->str); | 626 cur = url_decode(ret->str); |
597 g_string_free(ret, TRUE); | 627 g_string_free(ret, TRUE); |
598 return cur; | 628 return cur; |
599 } | 629 } |
600 | 630 |
601 | 631 static int msn_process_msnftp(struct msn_file_transfer *mft, char *buf) |
632 { | |
633 struct gaim_connection *gc = mft->gc; | |
634 char sendbuf[MSN_BUF_LEN]; | |
635 | |
636 if (!g_strncasecmp(buf, "VER MSNFTP", 10)) { | |
637 | |
638 /* Send the USR string. */ | |
639 g_snprintf(sendbuf, sizeof(sendbuf), "USR %s %ld\r\n", | |
640 gc->username, mft->authcookie); | |
641 | |
642 if (msn_write(mft->fd, sendbuf, strlen(sendbuf)) < 0) { | |
643 /* TODO: Clean up */ | |
644 return 0; | |
645 } | |
646 } | |
647 else if (!g_strncasecmp(buf, "FIL", 3)) { | |
648 | |
649 char *tmp = buf; | |
650 | |
651 GET_NEXT(tmp); | |
652 | |
653 mft->len = atoi(tmp); | |
654 | |
655 /* Send the TFR string, to request a start of transfer. */ | |
656 g_snprintf(sendbuf, sizeof(sendbuf), "TFR\r\n"); | |
657 | |
658 gaim_input_remove(mft->inpa); | |
659 mft->inpa = 0; | |
660 | |
661 if (msn_write(mft->fd, sendbuf, strlen(sendbuf)) < 0) { | |
662 /* TODO: Clean up */ | |
663 return 0; | |
664 } | |
665 | |
666 if (transfer_in_do(mft->xfer, mft->fd, mft->filename, mft->len)) { | |
667 debug_printf("MSN: transfer_in_do failed\n"); | |
668 } | |
669 } | |
670 | |
671 return 1; | |
672 } | |
673 | |
674 static void msn_msnftp_callback(gpointer data, gint source, | |
675 GaimInputCondition cond) | |
676 { | |
677 struct msn_file_transfer *mft = (struct msn_file_transfer *)data; | |
678 char buf[MSN_BUF_LEN]; | |
679 int cont = 1; | |
680 int len; | |
681 | |
682 if (mft->fd != source) | |
683 mft->fd = source; | |
684 | |
685 len = read(mft->fd, buf, sizeof(buf)); | |
686 | |
687 if (len <= 0) { | |
688 /* TODO: Kill mft. */ | |
689 return; | |
690 } | |
691 | |
692 mft->rxqueue = g_realloc(mft->rxqueue, len + mft->rxlen); | |
693 memcpy(mft->rxqueue + mft->rxlen, buf, len); | |
694 mft->rxlen += len; | |
695 | |
696 while (cont) { | |
697 char *end = mft->rxqueue; | |
698 int cmdlen; | |
699 char *cmd; | |
700 int i = 0; | |
701 | |
702 if (!mft->rxlen) | |
703 return; | |
704 | |
705 while (i + 1 < mft->rxlen) { | |
706 if (*end == '\r' && end[1] == '\n') | |
707 break; | |
708 end++; i++; | |
709 } | |
710 if (i + 1 == mft->rxlen) | |
711 return; | |
712 | |
713 cmdlen = end - mft->rxqueue + 2; | |
714 cmd = mft->rxqueue; | |
715 mft->rxlen -= cmdlen; | |
716 if (mft->rxlen) { | |
717 mft->rxqueue = g_memdup(cmd + cmdlen, mft->rxlen); | |
718 } else { | |
719 mft->rxqueue = NULL; | |
720 cmd = g_realloc(cmd, cmdlen + 1); | |
721 } | |
722 cmd[cmdlen] = 0; | |
723 | |
724 g_strchomp(cmd); | |
725 cont = msn_process_msnftp(mft, cmd); | |
726 | |
727 g_free(cmd); | |
728 } | |
729 } | |
730 | |
731 static void msn_msnftp_connect(gpointer data, gint source, | |
732 GaimInputCondition cond) | |
733 { | |
734 struct msn_file_transfer *mft = (struct msn_file_transfer *)data; | |
735 struct gaim_connection *gc = mft->gc; | |
736 char buf[MSN_BUF_LEN]; | |
737 | |
738 if (source == -1 || !g_slist_find(connections, gc)) { | |
739 debug_printf("Error establishing MSNFTP connection\n"); | |
740 close(source); | |
741 /* TODO: Clean up */ | |
742 return; | |
743 } | |
744 | |
745 if (mft->fd != source) | |
746 mft->fd = source; | |
747 | |
748 g_snprintf(buf, sizeof(buf), "VER MSNFTP\r\n"); | |
749 | |
750 if (msn_write(mft->fd, buf, strlen(buf)) < 0) { | |
751 /* TODO: Clean up */ | |
752 return; | |
753 } | |
754 | |
755 mft->inpa = gaim_input_add(mft->fd, GAIM_INPUT_READ, | |
756 msn_msnftp_callback, mft); | |
757 } | |
758 | |
759 static void msn_process_ft_msg(struct msn_switchboard *ms, char *msg) | |
760 { | |
761 struct msn_file_transfer *mft; | |
762 struct msn_data *md = ms->gc->proto_data; | |
763 char *tmp = msg; | |
764 | |
765 if (strstr(msg, "Application-Name: File Transfer") && | |
766 strstr(msg, "Invitation-Command: INVITE")) { | |
767 | |
768 /* | |
769 * First invitation message, requesting an ACCEPT or CANCEL from | |
770 * the recipient. Used in incoming file transfers. | |
771 */ | |
772 | |
773 char *filename; | |
774 char *cookie_s, *filesize_s; | |
775 size_t filesize; | |
776 | |
777 tmp = strstr(msg, "Invitation-Cookie"); | |
778 GET_NEXT(tmp); | |
779 cookie_s = tmp; | |
780 GET_NEXT(tmp); | |
781 GET_NEXT(tmp); | |
782 filename = tmp; | |
783 | |
784 /* Needed for filenames with spaces */ | |
785 tmp = strchr(tmp, '\r'); | |
786 *tmp = '\0'; | |
787 tmp += 2; | |
788 | |
789 GET_NEXT(tmp); | |
790 filesize_s = tmp; | |
791 GET_NEXT(tmp); | |
792 | |
793 mft = g_new0(struct msn_file_transfer, 1); | |
794 mft->gc = ms->gc; | |
795 mft->type = MFT_SENDFILE_IN; | |
796 mft->sn = g_strdup(ms->msguser); | |
797 mft->cookie = atoi(cookie_s); | |
798 mft->filename = g_strdup(filename); | |
799 | |
800 filesize = atoi(filesize_s); | |
801 | |
802 md->file_transfers = g_slist_append(md->file_transfers, mft); | |
803 | |
804 mft->xfer = transfer_in_add(ms->gc, ms->msguser, | |
805 mft->filename, filesize, 1, NULL); | |
806 } | |
807 else if (strstr(msg, "Invitation-Command: ACCEPT")) { | |
808 | |
809 /* | |
810 * XXX I hope these checks don't return false positives, but they | |
811 * seem like they should work. The only issue is alternative | |
812 * protocols, *maybe*. | |
813 */ | |
814 | |
815 if (strstr(msg, "AuthCookie:")) { | |
816 | |
817 /* | |
818 * Second invitation request, sent after the recipient accepts | |
819 * the request. Used in incoming file transfers. | |
820 */ | |
821 | |
822 char *cookie_s, *ip, *port_s, *authcookie_s; | |
823 | |
824 tmp = strstr(msg, "Invitation-Cookie"); | |
825 GET_NEXT(tmp); | |
826 cookie_s = tmp; | |
827 GET_NEXT(tmp); | |
828 GET_NEXT(tmp); | |
829 ip = tmp; | |
830 GET_NEXT(tmp); | |
831 GET_NEXT(tmp); | |
832 port_s = tmp; | |
833 GET_NEXT(tmp); | |
834 GET_NEXT(tmp); | |
835 authcookie_s = tmp; | |
836 GET_NEXT(tmp); | |
837 | |
838 mft = find_mft_by_cookie(ms->gc, atoi(cookie_s)); | |
839 | |
840 if (!mft) | |
841 { | |
842 debug_printf("MSN: Cookie not found. File transfer aborted.\n"); | |
843 return; | |
844 } | |
845 | |
846 strncpy(mft->ip, ip, 16); | |
847 mft->port = atoi(port_s); | |
848 mft->authcookie = atoi(authcookie_s); | |
849 | |
850 mft->fd = proxy_connect(mft->ip, mft->port, msn_msnftp_connect, mft); | |
851 | |
852 if (ms->fd < 0) { | |
853 md->file_transfers = g_slist_remove(md->file_transfers, mft); | |
854 return; | |
855 } | |
856 } | |
857 else | |
858 { | |
859 /* | |
860 * An accept message from the recipient. Used in outgoing | |
861 * file transfers. | |
862 */ | |
863 } | |
864 } | |
865 } | |
866 | |
602 static void msn_process_switch_msg(struct msn_switchboard *ms, char *msg) | 867 static void msn_process_switch_msg(struct msn_switchboard *ms, char *msg) |
603 { | 868 { |
604 char *content, *agent, *format; | 869 char *content, *agent, *format; |
605 char *message = NULL; | 870 char *message = NULL; |
606 int flags = 0; | 871 int flags = 0; |
625 strlen( "Content-Type: text/x-msmsgscontrol\r\n"))) { | 890 strlen( "Content-Type: text/x-msmsgscontrol\r\n"))) { |
626 if (strstr(content,"TypingUser: ") && !ms->chat) { | 891 if (strstr(content,"TypingUser: ") && !ms->chat) { |
627 serv_got_typing(ms->gc, ms->msguser, MSN_TYPING_RECV_TIMEOUT, TYPING); | 892 serv_got_typing(ms->gc, ms->msguser, MSN_TYPING_RECV_TIMEOUT, TYPING); |
628 return; | 893 return; |
629 } | 894 } |
895 | |
896 } else if (!g_strncasecmp(content, "Content-Type: text/x-msmsgsinvite;", | |
897 strlen("Content-Type: text/x-msmsgsinvite;"))) { | |
898 | |
899 /* | |
900 * NOTE: Other things, such as voice communication, would go in | |
901 * here too (since they send the same Content-Type). However, | |
902 * this is the best check for file transfer messages, so I'm | |
903 * calling msn_process_ft_invite_msg(). If anybody adds support | |
904 * for anything else that sends a text/x-msmsgsinvite, perhaps | |
905 * this should be changed. For now, it stays. | |
906 */ | |
907 msn_process_ft_msg(ms, content); | |
630 | 908 |
631 } else if (!g_strncasecmp(content, "Content-Type: text/plain", | 909 } else if (!g_strncasecmp(content, "Content-Type: text/plain", |
632 strlen("Content-Type: text/plain"))) { | 910 strlen("Content-Type: text/plain"))) { |
633 | 911 |
634 | 912 |
1773 if (msn_write(ms->fd, buf, strlen(buf)) < 0) | 2051 if (msn_write(ms->fd, buf, strlen(buf)) < 0) |
1774 msn_kill_switch(ms); | 2052 msn_kill_switch(ms); |
1775 return MSN_TYPING_SEND_TIMEOUT; | 2053 return MSN_TYPING_SEND_TIMEOUT; |
1776 } | 2054 } |
1777 | 2055 |
2056 /* XXX Don't blame me. I stole this from the oscar module! */ | |
2057 static struct msn_file_transfer *find_mft_by_xfer(struct gaim_connection *gc, | |
2058 struct file_transfer *xfer) | |
2059 { | |
2060 GSList *g = ((struct msn_data *)gc->proto_data)->file_transfers; | |
2061 struct msn_file_transfer *f = NULL; | |
2062 | |
2063 while (g) { | |
2064 f = (struct msn_file_transfer *)g->data; | |
2065 if (f->xfer == xfer) | |
2066 break; | |
2067 | |
2068 g = g->next; | |
2069 f = NULL; | |
2070 } | |
2071 | |
2072 return f; | |
2073 } | |
2074 | |
2075 /* XXX Don't blame me. I stole this from the oscar module! */ | |
2076 static struct msn_file_transfer *find_mft_by_cookie(struct gaim_connection *gc, | |
2077 unsigned long cookie) | |
2078 { | |
2079 GSList *g = ((struct msn_data *)gc->proto_data)->file_transfers; | |
2080 struct msn_file_transfer *f = NULL; | |
2081 | |
2082 while (g) { | |
2083 f = (struct msn_file_transfer *)g->data; | |
2084 if (f->cookie == cookie) | |
2085 break; | |
2086 | |
2087 g = g->next; | |
2088 f = NULL; | |
2089 } | |
2090 | |
2091 return f; | |
2092 } | |
2093 | |
2094 static void msn_file_transfer_cancel(struct gaim_connection *gc, | |
2095 struct file_transfer *xfer) | |
2096 { | |
2097 struct msn_data *md = gc->proto_data; | |
2098 struct msn_file_transfer *mft = find_mft_by_xfer(gc, xfer); | |
2099 struct msn_switchboard *ms = msn_find_switch(gc, mft->sn); | |
2100 char header[MSN_BUF_LEN]; | |
2101 char buf[MSN_BUF_LEN]; | |
2102 | |
2103 if (!ms || !mft) | |
2104 { | |
2105 debug_printf("Eep! Returning from msn_file_transfer_cancel early"); | |
2106 return; | |
2107 } | |
2108 | |
2109 g_snprintf(header, sizeof(header), | |
2110 "MIME-Version: 1.0\r\n" | |
2111 "Content-Type: text/x-msmsgsinvite; charset=UTF-8\r\n\r\n" | |
2112 "Invitation-Command: CANCEL\r\n" | |
2113 "Invitation-Cookie: %ld\r\n" | |
2114 "Cancel-Code: REJECT\r\n", | |
2115 mft->cookie); | |
2116 | |
2117 g_snprintf(buf, sizeof(buf), "MSG %d N %d\r\n%s\r\n\r\n", | |
2118 ++ms->trId, strlen(header) + strlen("\r\n\r\n"), | |
2119 header); | |
2120 | |
2121 md->file_transfers = g_slist_remove(md->file_transfers, mft); | |
2122 | |
2123 if (msn_write(ms->fd, buf, strlen(buf)) < 0) | |
2124 { | |
2125 debug_printf("Uh oh! Killing switch.\n"); | |
2126 msn_kill_switch(ms); | |
2127 } | |
2128 } | |
2129 | |
2130 static void msn_file_transfer_in(struct gaim_connection *gc, | |
2131 struct file_transfer *xfer, int offset) | |
2132 { | |
2133 struct msn_data *md = gc->proto_data; | |
2134 struct msn_file_transfer *mft = find_mft_by_xfer(gc, xfer); | |
2135 struct msn_switchboard *ms = msn_find_switch(gc, mft->sn); | |
2136 char header[MSN_BUF_LEN]; | |
2137 char buf[MSN_BUF_LEN]; | |
2138 | |
2139 if (!ms || !mft) | |
2140 { | |
2141 debug_printf("Eep! Returning from msn_file_transfer_in early"); | |
2142 return; | |
2143 } | |
2144 | |
2145 g_snprintf(header, sizeof(header), | |
2146 "MIME-Version: 1.0\r\n" | |
2147 "Content-Type: text/x-msmsgsinvite; charset=UTF-8\r\n\r\n" | |
2148 "Invitation-Command: ACCEPT\r\n" | |
2149 "Invitation-Cookie: %ld\r\n" | |
2150 "Launch-Application: FALSE\r\n" | |
2151 "Request-Data: IP-Address:\r\n", | |
2152 mft->cookie); | |
2153 | |
2154 g_snprintf(buf, sizeof(buf), "MSG %d N %d\r\n%s\r\n\r\n", | |
2155 ++ms->trId, strlen(header) + strlen("\r\n\r\n"), | |
2156 header); | |
2157 | |
2158 if (msn_write(ms->fd, buf, strlen(buf)) < 0) { | |
2159 msn_kill_switch(ms); | |
2160 return; | |
2161 } | |
2162 | |
2163 mft->xfer = xfer; | |
2164 } | |
2165 | |
2166 static void msn_file_transfer_out(struct gaim_connection *gc, | |
2167 struct file_transfer *xfer, | |
2168 const char *name, int totfiles, int totsize) | |
2169 { | |
2170 struct msn_file_transfer *mft = find_mft_by_xfer(gc, xfer); | |
2171 struct msn_switchboard *ms = msn_find_switch(gc, mft->sn); | |
2172 char header[MSN_BUF_LEN]; | |
2173 char buf[MSN_BUF_LEN]; | |
2174 struct stat sb; | |
2175 | |
2176 if (!ms) | |
2177 return; | |
2178 | |
2179 if (totfiles > 1) | |
2180 return; | |
2181 | |
2182 if (stat(name, &sb) == -1) | |
2183 return; | |
2184 | |
2185 mft->cookie = 1 + (int)(sizeof(unsigned long) * rand() / (RAND_MAX + 1.0)); | |
2186 | |
2187 g_snprintf(header, sizeof(header), | |
2188 "MIME-Version: 1.0\r\n" | |
2189 "Content-Type: text/x-msmsgsinvite; charset=UTF-8\r\n" | |
2190 "Application-Name: File Transfer\r\n" | |
2191 "Application-GUID: {5D3E02AB-6190-11d3-BBBB-00C04F795683}\r\n" | |
2192 "Invitation-Command: INVITE\r\n" | |
2193 "Invitation-Cookie: %ld\r\n" | |
2194 "Application-File: %s\r\n" | |
2195 "Application-FileSize: %ld\r\n", | |
2196 mft->cookie, name, sb.st_size); | |
2197 | |
2198 g_snprintf(buf, sizeof(buf), "MSG %d A %d\r\n%s\r\n\r\n", | |
2199 ++ms->trId, | |
2200 strlen(header) + strlen("\r\n\r\n"), | |
2201 header); | |
2202 | |
2203 if (msn_write(ms->fd, buf, strlen(buf)) < 0) | |
2204 msn_kill_switch(ms); | |
2205 | |
2206 debug_printf("\n"); | |
2207 } | |
2208 | |
2209 static void msn_file_transfer_done(struct gaim_connection *gc, | |
2210 struct file_transfer *xfer) | |
2211 { | |
2212 struct msn_data *md = (struct msn_data *)gc->proto_data; | |
2213 struct msn_file_transfer *mft = find_mft_by_xfer(gc, xfer); | |
2214 struct msn_switchboard *ms = msn_find_switch(gc, mft->sn); | |
2215 char buf[MSN_BUF_LEN]; | |
2216 | |
2217 g_snprintf(buf, sizeof(buf), "BYE 16777989\r\n"); | |
2218 | |
2219 msn_write(mft->fd, buf, strlen(buf)); | |
2220 | |
2221 md->file_transfers = g_slist_remove(md->file_transfers, mft); | |
2222 | |
2223 gaim_input_remove(mft->inpa); | |
2224 | |
2225 close(mft->fd); | |
2226 | |
2227 g_free(mft->filename); | |
2228 g_free(mft->sn); | |
2229 g_free(mft); | |
2230 } | |
2231 | |
2232 static size_t msn_file_transfer_read(struct gaim_connection *gc, | |
2233 struct file_transfer *xfer, int fd, | |
2234 char **buf) | |
2235 { | |
2236 unsigned char header[3]; | |
2237 size_t len, size; | |
2238 | |
2239 if (read(fd, header, sizeof(header)) < 3) | |
2240 return 0; | |
2241 | |
2242 if (header[0] != 0) { | |
2243 debug_printf("Invalid header[0]: %d. Aborting.\n", header[0]); | |
2244 return 0; | |
2245 } | |
2246 | |
2247 size = header[1] | (header[2] << 8); | |
2248 | |
2249 *buf = g_new0(char, size); | |
2250 | |
2251 for (len = 0; len < size; len += read(fd, *buf + len, size - len)); | |
2252 | |
2253 return len; | |
2254 } | |
2255 | |
1778 static int msn_send_im(struct gaim_connection *gc, char *who, char *message, int len, int flags) | 2256 static int msn_send_im(struct gaim_connection *gc, char *who, char *message, int len, int flags) |
1779 { | 2257 { |
1780 struct msn_data *md = gc->proto_data; | 2258 struct msn_data *md = gc->proto_data; |
1781 struct msn_switchboard *ms = msn_find_switch(gc, who); | 2259 struct msn_switchboard *ms = msn_find_switch(gc, who); |
1782 char buf[MSN_BUF_LEN]; | 2260 char buf[MSN_BUF_LEN]; |
1987 return; | 2465 return; |
1988 g_snprintf(b->show, sizeof(b->show), "%s", (char *)b->proto_data); | 2466 g_snprintf(b->show, sizeof(b->show), "%s", (char *)b->proto_data); |
1989 handle_buddy_rename(b, b->name); | 2467 handle_buddy_rename(b, b->name); |
1990 } | 2468 } |
1991 | 2469 |
2470 static void msn_ask_send_file(struct gaim_connection *gc, char *destsn) | |
2471 { | |
2472 struct msn_data *md = (struct msn_data *)gc->proto_data; | |
2473 struct msn_file_transfer *mft = g_new0(struct msn_file_transfer, 1); | |
2474 | |
2475 mft->type = MFT_SENDFILE_OUT; | |
2476 mft->sn = g_strdup(destsn); | |
2477 mft->gc = gc; | |
2478 | |
2479 md->file_transfers = g_slist_append(md->file_transfers, mft); | |
2480 | |
2481 mft->xfer = transfer_out_add(gc, mft->sn); | |
2482 } | |
2483 | |
1992 static GList *msn_buddy_menu(struct gaim_connection *gc, char *who) | 2484 static GList *msn_buddy_menu(struct gaim_connection *gc, char *who) |
1993 { | 2485 { |
1994 GList *m = NULL; | 2486 GList *m = NULL; |
1995 struct proto_buddy_menu *pbm; | 2487 struct proto_buddy_menu *pbm; |
1996 struct buddy *b = find_buddy(gc, who); | 2488 struct buddy *b = find_buddy(gc, who); |
1997 static char buf[MSN_BUF_LEN]; | 2489 static char buf[MSN_BUF_LEN]; |
1998 | 2490 |
1999 pbm = g_new0(struct proto_buddy_menu, 1); | 2491 pbm = g_new0(struct proto_buddy_menu, 1); |
2000 pbm->label = _("Reset friendly name"); | 2492 pbm->label = _("Reset friendly name"); |
2001 pbm->callback = msn_reset_friend; | 2493 pbm->callback = msn_reset_friend; |
2494 pbm->gc = gc; | |
2495 m = g_list_append(m, pbm); | |
2496 | |
2497 pbm = g_new0(struct proto_buddy_menu, 1); | |
2498 pbm->label = _("Send File"); | |
2499 pbm->callback = msn_ask_send_file; | |
2002 pbm->gc = gc; | 2500 pbm->gc = gc; |
2003 m = g_list_append(m, pbm); | 2501 m = g_list_append(m, pbm); |
2004 | 2502 |
2005 if (!b || !(b->uc >> 1)) | 2503 if (!b || !(b->uc >> 1)) |
2006 return m; | 2504 return m; |
2395 ret->add_permit = msn_add_permit; | 2893 ret->add_permit = msn_add_permit; |
2396 ret->rem_permit = msn_rem_permit; | 2894 ret->rem_permit = msn_rem_permit; |
2397 ret->add_deny = msn_add_deny; | 2895 ret->add_deny = msn_add_deny; |
2398 ret->rem_deny = msn_rem_deny; | 2896 ret->rem_deny = msn_rem_deny; |
2399 ret->buddy_free = msn_buddy_free; | 2897 ret->buddy_free = msn_buddy_free; |
2898 ret->file_transfer_cancel = msn_file_transfer_cancel; | |
2899 ret->file_transfer_in = msn_file_transfer_in; | |
2900 ret->file_transfer_out = msn_file_transfer_out; | |
2901 ret->file_transfer_done = msn_file_transfer_done; | |
2902 ret->file_transfer_read = msn_file_transfer_read; | |
2400 | 2903 |
2401 puo = g_new0(struct proto_user_opt, 1); | 2904 puo = g_new0(struct proto_user_opt, 1); |
2402 puo->label = g_strdup(_("Server:")); | 2905 puo->label = g_strdup(_("Server:")); |
2403 puo->def = g_strdup(MSN_SERVER); | 2906 puo->def = g_strdup(MSN_SERVER); |
2404 puo->pos = USEROPT_MSNSERVER; | 2907 puo->pos = USEROPT_MSNSERVER; |