comparison src/protocols/jabber/jabber.c @ 3630:9682c0e022c6

[gaim-migrate @ 3753] Yeah this will probably break a lot of shit knowing my luck. But hey, I really don't care what people thnk. committer: Tailor Script <tailor@pidgin.im>
author Rob Flynn <gaim@robflynn.com>
date Fri, 11 Oct 2002 03:14:01 +0000
parents 95669ff6dc3b
children 5e50f6746509
comparison
equal deleted inserted replaced
3629:afc5bb164c5a 3630:9682c0e022c6
18 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software 19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * 21 *
22 */ 22 */
23
24 #ifdef HAVE_CONFIG_H 23 #ifdef HAVE_CONFIG_H
25 #include "config.h" 24 #include <config.h>
26 #endif 25 #endif
27 26
28 27 #ifndef _WIN32
29 #include <netdb.h> 28 #include <netdb.h>
30 #include <unistd.h>
31 #include <errno.h>
32 #include <netinet/in.h> 29 #include <netinet/in.h>
33 #include <arpa/inet.h> 30 #include <arpa/inet.h>
31 #include <sys/socket.h>
32 #include <sys/utsname.h>
33 #include <unistd.h>
34 #else
35 #include <winsock.h>
36 #include "utsname.h"
37 #endif
38
39 #include <errno.h>
34 #include <string.h> 40 #include <string.h>
35 #include <stdlib.h> 41 #include <stdlib.h>
36 #include <stdio.h> 42 #include <stdio.h>
37 #include <time.h> 43 #include <time.h>
38 #include <sys/socket.h>
39 #include <sys/utsname.h>
40 #include <sys/stat.h> 44 #include <sys/stat.h>
41 #include "multi.h" 45 #include "multi.h"
42 #include "prpl.h" 46 #include "prpl.h"
43 #include "gaim.h" 47 #include "gaim.h"
44 #ifdef MAX 48 #ifdef MAX
48 #undef MIN 52 #undef MIN
49 #endif 53 #endif
50 #include "jabber.h" 54 #include "jabber.h"
51 #include "proxy.h" 55 #include "proxy.h"
52 56
57 #ifdef _WIN32
58 #include "win32dep.h"
59 #endif
60
53 #include "pixmaps/protocols/jabber/available.xpm" 61 #include "pixmaps/protocols/jabber/available.xpm"
54 #include "pixmaps/protocols/jabber/available-away.xpm" 62 #include "pixmaps/protocols/jabber/available-away.xpm"
55 #include "pixmaps/protocols/jabber/available-chat.xpm" 63 #include "pixmaps/protocols/jabber/available-chat.xpm"
56 #include "pixmaps/protocols/jabber/available-xa.xpm" 64 #include "pixmaps/protocols/jabber/available-xa.xpm"
57 #include "pixmaps/protocols/jabber/available-dnd.xpm" 65 #include "pixmaps/protocols/jabber/available-dnd.xpm"
58 #include "pixmaps/protocols/jabber/available-error.xpm" 66 #include "pixmaps/protocols/jabber/available-error.xpm"
67
68 /* for win32 compatability */
69 G_MODULE_IMPORT GSList *connections;
59 70
60 /* The priv member of gjconn's is a gaim_connection for now. */ 71 /* The priv member of gjconn's is a gaim_connection for now. */
61 #define GJ_GC(x) ((struct gaim_connection *)(x)->priv) 72 #define GJ_GC(x) ((struct gaim_connection *)(x)->priv)
62 73
63 #define IQID_AUTH "__AUTH__" 74 #define IQID_AUTH "__AUTH__"
138 gboolean did_import; 149 gboolean did_import;
139 GSList *chats; 150 GSList *chats;
140 time_t idle; 151 time_t idle;
141 gboolean die; 152 gboolean die;
142 GHashTable *buddies; 153 GHashTable *buddies;
154 GSList *file_transfers;
143 }; 155 };
144 156
145 /* 157 /*
146 * Used in jabber_buddy_data.invisible, below 158 * Used in jabber_buddy_data.invisible, below
147 */ 159 */
226 238
227 239
228 #define STATE_EVT(arg) if(gjc->on_state) { (gjc->on_state)(gjc, (arg) ); } 240 #define STATE_EVT(arg) if(gjc->on_state) { (gjc->on_state)(gjc, (arg) ); }
229 241
230 static void jabber_handlevcard(gjconn, xmlnode, char *); 242 static void jabber_handlevcard(gjconn, xmlnode, char *);
243
244 static char *jabber_normalize(const char *s);
231 245
232 static char *create_valid_jid(const char *given, char *server, char *resource) 246 static char *create_valid_jid(const char *given, char *server, char *resource)
233 { 247 {
234 char *valid; 248 char *valid;
235 249
490 return; 504 return;
491 505
492 gjab_send_raw(gjc, "</stream:stream>"); 506 gjab_send_raw(gjc, "</stream:stream>");
493 gjc->state = JCONN_STATE_OFF; 507 gjc->state = JCONN_STATE_OFF;
494 gjc->was_connected = 0; 508 gjc->was_connected = 0;
509 #ifndef _WIN32
495 close(gjc->fd); 510 close(gjc->fd);
511 #else
512 closesocket(gjc->fd);
513 #endif
496 gjc->fd = -1; 514 gjc->fd = -1;
497 XML_ParserFree(gjc->parser); 515 XML_ParserFree(gjc->parser);
498 gjc->parser = NULL; 516 gjc->parser = NULL;
499 } 517 }
500 518
533 static void gjab_send(gjconn gjc, xmlnode x) 551 static void gjab_send(gjconn gjc, xmlnode x)
534 { 552 {
535 if (gjc && gjc->state != JCONN_STATE_OFF) { 553 if (gjc && gjc->state != JCONN_STATE_OFF) {
536 char *buf = xmlnode2str(x); 554 char *buf = xmlnode2str(x);
537 if (buf) 555 if (buf)
556 #ifndef _WIN32
538 write(gjc->fd, buf, strlen(buf)); 557 write(gjc->fd, buf, strlen(buf));
558 #else
559 send(gjc->fd, buf, strlen(buf), 0);
560 #endif
539 debug_printf("gjab_send: %s\n", buf); 561 debug_printf("gjab_send: %s\n", buf);
540 } 562 }
541 } 563 }
542 564
543 static void gjab_send_raw(gjconn gjc, const char *str) 565 static void gjab_send_raw(gjconn gjc, const char *str)
544 { 566 {
545 if (gjc && gjc->state != JCONN_STATE_OFF) { 567 if (gjc && gjc->state != JCONN_STATE_OFF) {
546 /* 568 /*
547 * JFIXME: No error detection?!?! 569 * JFIXME: No error detection?!?!
548 */ 570 */
571 #ifndef _WIN32
549 if(write(gjc->fd, str, strlen(str)) < 0) { 572 if(write(gjc->fd, str, strlen(str)) < 0) {
573 #else
574 if(send(gjc->fd, str, strlen(str), 0) < 0) {
575 #endif
550 fprintf(stderr, "DBG: Problem sending. Error: %d\n", errno); 576 fprintf(stderr, "DBG: Problem sending. Error: %d\n", errno);
551 fflush(stderr); 577 fflush(stderr);
552 } 578 }
553 debug_printf("gjab_send_raw: %s\n", str); 579 debug_printf("gjab_send_raw: %s\n", str);
554 } 580 }
634 static char buf[4096]; 660 static char buf[4096];
635 int len; 661 int len;
636 662
637 if (!gjc || gjc->state == JCONN_STATE_OFF) 663 if (!gjc || gjc->state == JCONN_STATE_OFF)
638 return; 664 return;
639 665 #ifndef _WIN32
640 if ((len = read(gjc->fd, buf, sizeof(buf) - 1)) > 0) { 666 if ((len = read(gjc->fd, buf, sizeof(buf) - 1)) > 0) {
667 #else
668 if ((len = recv(gjc->fd, buf, sizeof(buf) - 1, 0)) > 0) {
669 #endif
641 struct jabber_data *jd = GJ_GC(gjc)->proto_data; 670 struct jabber_data *jd = GJ_GC(gjc)->proto_data;
642 buf[len] = '\0'; 671 buf[len] = '\0';
643 debug_printf("input (len %d): %s\n", len, buf); 672 debug_printf("input (len %d): %s\n", len, buf);
644 XML_Parse(gjc->parser, buf, len, 0); 673 XML_Parse(gjc->parser, buf, len, 0);
645 if (jd->die) 674 if (jd->die)
725 struct gaim_connection *gc = data; 754 struct gaim_connection *gc = data;
726 struct jabber_data *jd; 755 struct jabber_data *jd;
727 gjconn gjc; 756 gjconn gjc;
728 757
729 if (!g_slist_find(connections, gc)) { 758 if (!g_slist_find(connections, gc)) {
759 #ifndef _WIN32
730 close(source); 760 close(source);
761 #else
762 closesocket(source);
763 #endif
731 return; 764 return;
732 } 765 }
733 766
734 jd = gc->proto_data; 767 jd = gc->proto_data;
735 gjc = jd->gjc; 768 gjc = jd->gjc;
1899 gjab_send(gjc, x); 1932 gjab_send(gjc, x);
1900 1933
1901 xmlnode_free(x); 1934 xmlnode_free(x);
1902 } 1935 }
1903 1936
1937 struct jabber_file_transfer {
1938 enum { JFT_SENDFILE_IN, JFT_SENDFILE_OUT } type;
1939 struct file_transfer *xfer;
1940 char *from;
1941 struct g_url *url;
1942 char *name;
1943 GString *headers;
1944
1945 int len;
1946 int fd;
1947 int watcher;
1948
1949 gboolean sentreq;
1950 gboolean newline;
1951 gboolean startsaving;
1952
1953 struct gaim_connection *gc;
1954 };
1955
1956 static struct jabber_file_transfer *find_jft_by_xfer(struct gaim_connection *gc,
1957 struct file_transfer *xfer) {
1958 GSList *g = ((struct jabber_data *)gc->proto_data)->file_transfers;
1959 struct jabber_file_transfer *f = NULL;
1960
1961 while(g) {
1962 f = (struct jabber_file_transfer *)g->data;
1963 if(f->xfer == xfer)
1964 break;
1965 g = g->next;
1966 f = NULL;
1967 }
1968
1969 return f;
1970 }
1971
1972 static void jabber_http_recv_callback(gpointer data, gint source, GaimInputCondition condition) {
1973 struct jabber_file_transfer *jft = data;
1974 char test;
1975
1976 jft->fd = source;
1977 if(!jft->sentreq) {
1978 char buf[1024];
1979 g_snprintf(buf, sizeof(buf), "GET /%s HTTP/1.1\r\nHost: %s\r\n\r\n", jft->url->page, jft->url->address);
1980 write(source, buf, strlen(buf));
1981 fcntl(source, F_SETFL, O_NONBLOCK);
1982 jft->sentreq = TRUE;
1983 jft->watcher = gaim_input_add(source, GAIM_INPUT_READ, jabber_http_recv_callback,data);
1984 return;
1985 }
1986
1987 if(!jft->startsaving) {
1988 if(read(source, &test, sizeof(test)) > 0 || errno == EWOULDBLOCK) {
1989 if(errno == EWOULDBLOCK) {
1990 errno = 0;
1991 return;
1992 }
1993
1994 jft->headers = g_string_append_c(jft->headers, test);
1995 if(test == '\r')
1996 return;
1997 if(test == '\n') {
1998 if(jft->newline) {
1999 gchar *lenstr = strstr(jft->headers->str, "Content-Length: ");
2000 if(lenstr) {
2001 sscanf(lenstr, "Content-Length: %d", &jft->len);
2002 }
2003 jft->startsaving = TRUE;
2004 } else
2005 jft->newline = TRUE;
2006 return;
2007 }
2008 jft->newline = FALSE;
2009 return;
2010 } else {
2011 gaim_input_remove(jft->watcher);
2012 close(source);
2013 //FIXME: ft_cancel(NULL, jft->xfer);
2014 }
2015 return;
2016 }
2017
2018 /* we've parsed the headers, gotten the size, all is good. now we pass the reception of
2019 * the file off to the core, and leave it in it's capable...err...hands?? */
2020 gaim_input_remove(jft->watcher);
2021 jft->watcher = 0;
2022 transfer_in_do(jft->xfer, jft->fd, jft->name, jft->len);
2023 }
2024
2025 static void jabber_file_transfer_cancel(struct gaim_connection *gc, struct file_transfer *xfer) {
2026 struct jabber_data *jd = gc->proto_data;
2027 struct jabber_file_transfer *jft = find_jft_by_xfer(gc, xfer);\
2028 xmlnode x,y;
2029
2030 jd->file_transfers = g_slist_remove(jd->file_transfers, jft);
2031
2032 gaim_input_remove(jft->watcher);
2033 close(jft->fd);
2034
2035 x = xmlnode_new_tag("iq");
2036 xmlnode_put_attrib(x, "type", "error");
2037 xmlnode_put_attrib(x, "to", jft->from);
2038 y = xmlnode_insert_tag(x, "error");
2039 /* FIXME: need to handle other kinds of errors here */
2040 xmlnode_put_attrib(y, "code", "406");
2041 xmlnode_insert_cdata(y, "File Transfer Refused", -1);
2042
2043 gjab_send(jd->gjc, x);
2044
2045 xmlnode_free(x);
2046
2047 g_string_free(jft->headers, TRUE);
2048 g_free(jft->from);
2049 g_free(jft->url);
2050 g_free(jft->name);
2051
2052 g_free(jft);
2053 }
2054
2055 static void jabber_file_transfer_done(struct gaim_connection *gc, struct file_transfer *xfer) {
2056 struct jabber_data *jd = gc->proto_data;
2057 struct jabber_file_transfer *jft = find_jft_by_xfer(gc, xfer);
2058 xmlnode x;
2059
2060 jd->file_transfers = g_slist_remove(jd->file_transfers, jft);
2061
2062 gaim_input_remove(jft->watcher);
2063 close(jft->fd);
2064
2065 x = xmlnode_new_tag("iq");
2066 xmlnode_put_attrib(x, "type", "result");
2067 xmlnode_put_attrib(x, "to", jft->from);
2068
2069 gjab_send(jd->gjc, x);
2070
2071 xmlnode_free(x);
2072
2073 g_string_free(jft->headers, TRUE);
2074 g_free(jft->from);
2075 g_free(jft->url);
2076 g_free(jft->name);
2077
2078 g_free(jft);
2079 }
2080
2081 static void jabber_file_transfer_in(struct gaim_connection *gc, struct file_transfer *xfer, int offset) {
2082 struct jabber_file_transfer *jft = find_jft_by_xfer(gc, xfer);
2083
2084 proxy_connect(jft->url->address, jft->url->port, jabber_http_recv_callback, jft);
2085 }
2086
2087 static void jabber_handleoob(gjconn gjc, xmlnode iqnode) {
2088 struct jabber_file_transfer *jft;
2089 struct jabber_data *jd = GJ_GC(gjc)->proto_data;
2090 char *msg = NULL;
2091 xmlnode querynode = xmlnode_get_tag(iqnode, "query");
2092 xmlnode urlnode,descnode;
2093
2094 if(!querynode)
2095 return;
2096 urlnode = xmlnode_get_tag(querynode, "url");
2097 if(!urlnode)
2098 return;
2099 descnode = xmlnode_get_tag(querynode, "desc");
2100 if(descnode)
2101 msg = xmlnode_get_data(descnode);
2102
2103 jft = g_new0(struct jabber_file_transfer, 1);
2104 jft->type = JFT_SENDFILE_IN;
2105 jft->gc = GJ_GC(gjc);
2106 jft->url = parse_url(xmlnode_get_data(urlnode));
2107 jft->from = g_strdup(xmlnode_get_attrib(iqnode, "from"));
2108 jft->name = g_strdup(g_strrstr(jft->url->page,"/"));
2109 if (!jft->name)
2110 jft->name = g_strdup(jft->url->page);
2111 jft->headers = g_string_new("");
2112 jft->len = -1;
2113
2114 jd->file_transfers = g_slist_append(jd->file_transfers, jft);
2115
2116 jft->xfer = transfer_in_add(GJ_GC(gjc), jft->from, jft->name, jft->len, 1, msg);
2117 }
2118
1904 static void jabber_handlelast(gjconn gjc, xmlnode iqnode) { 2119 static void jabber_handlelast(gjconn gjc, xmlnode iqnode) {
1905 xmlnode x, querytag; 2120 xmlnode x, querytag;
1906 char *id, *from; 2121 char *id, *from;
1907 struct jabber_data *jd = GJ_GC(gjc)->proto_data; 2122 struct jabber_data *jd = GJ_GC(gjc)->proto_data;
1908 char idle_time[32]; 2123 char idle_time[32];
1909 2124
1910 id = xmlnode_get_attrib(iqnode, "id"); 2125 id = xmlnode_get_attrib(iqnode, "id");
1911 from = xmlnode_get_attrib(iqnode, "from"); 2126 from = xmlnode_get_attrib(iqnode, "from");
1912 2127
1913 x = jutil_iqnew(JPACKET__RESULT, "jabber:iq:last"); 2128 x = jutil_iqnew(JPACKET__RESULT, "jabber:iq:last");
1914 2129
1977 if (jpacket_subtype(p) == JPACKET__SET) { 2192 if (jpacket_subtype(p) == JPACKET__SET) {
1978 xmlnode querynode; 2193 xmlnode querynode;
1979 querynode = xmlnode_get_tag(p->x, "query"); 2194 querynode = xmlnode_get_tag(p->x, "query");
1980 if (NSCHECK(querynode, "jabber:iq:roster")) { 2195 if (NSCHECK(querynode, "jabber:iq:roster")) {
1981 jabber_handlebuddy(gjc, xmlnode_get_firstchild(querynode)); 2196 jabber_handlebuddy(gjc, xmlnode_get_firstchild(querynode));
2197 } else if(NSCHECK(querynode, "jabber:iq:oob")) {
2198 jabber_handleoob(gjc, p->x);
1982 } 2199 }
1983 } else if (jpacket_subtype(p) == JPACKET__GET) { 2200 } else if (jpacket_subtype(p) == JPACKET__GET) {
1984 xmlnode querynode; 2201 xmlnode querynode;
1985 querynode = xmlnode_get_tag(p->x, "query"); 2202 querynode = xmlnode_get_tag(p->x, "query");
1986 if (NSCHECK(querynode, NS_VERSION)) { 2203 if (NSCHECK(querynode, NS_VERSION)) {
2259 y = xmlnode_insert_tag(x, "x"); 2476 y = xmlnode_insert_tag(x, "x");
2260 xmlnode_put_attrib(y, "xmlns", "jabber:x:event"); 2477 xmlnode_put_attrib(y, "xmlns", "jabber:x:event");
2261 xmlnode_insert_tag(y, "composing"); 2478 xmlnode_insert_tag(y, "composing");
2262 2479
2263 if (message && strlen(message)) { 2480 if (message && strlen(message)) {
2264 char *utf8 = str_to_utf8(message); 2481 char *utf8 = str_to_utf8((char*)message);
2265 y = xmlnode_insert_tag(x, "body"); 2482 y = xmlnode_insert_tag(x, "body");
2266 xmlnode_insert_cdata(y, utf8, -1); 2483 xmlnode_insert_cdata(y, utf8, -1);
2267 g_free(utf8); 2484 g_free(utf8);
2268 } 2485 }
2269 2486
2746 subject = g_strdup_printf("%s@%s", jc->gjid->user, jc->gjid->server); 2963 subject = g_strdup_printf("%s@%s", jc->gjid->user, jc->gjid->server);
2747 xmlnode_put_attrib(y, "jid", subject); 2964 xmlnode_put_attrib(y, "jid", subject);
2748 g_free(subject); 2965 g_free(subject);
2749 2966
2750 if (message && strlen(message)) { 2967 if (message && strlen(message)) {
2751 char *utf8 = str_to_utf8(message); 2968 char *utf8 = str_to_utf8((char*)message);
2752 y = xmlnode_insert_tag(x, "body"); 2969 y = xmlnode_insert_tag(x, "body");
2753 xmlnode_insert_cdata(y, utf8, -1); 2970 xmlnode_insert_cdata(y, utf8, -1);
2754 g_free(utf8); 2971 g_free(utf8);
2755 } 2972 }
2756 2973
3958 return m; 4175 return m;
3959 } 4176 }
3960 4177
3961 static struct prpl *my_protocol = NULL; 4178 static struct prpl *my_protocol = NULL;
3962 4179
3963 void jabber_init(struct prpl *ret) 4180 G_MODULE_EXPORT void jabber_init(struct prpl *ret)
3964 { 4181 {
3965 /* the NULL's aren't required but they're nice to have */ 4182 /* the NULL's aren't required but they're nice to have */
3966 struct proto_user_opt *puo; 4183 struct proto_user_opt *puo;
3967 ret->protocol = PROTO_JABBER; 4184 ret->protocol = PROTO_JABBER;
3968 ret->options = OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_CHAT_TOPIC; 4185 ret->options = OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_CHAT_TOPIC;
4007 ret->alias_buddy = jabber_alias_buddy; 4224 ret->alias_buddy = jabber_alias_buddy;
4008 ret->group_buddy = jabber_group_change; 4225 ret->group_buddy = jabber_group_change;
4009 ret->send_typing = jabber_send_typing; 4226 ret->send_typing = jabber_send_typing;
4010 ret->convo_closed = jabber_convo_closed; 4227 ret->convo_closed = jabber_convo_closed;
4011 ret->rename_group = jabber_rename_group; 4228 ret->rename_group = jabber_rename_group;
4012 4229 ret->file_transfer_out = NULL; /* TODO */
4230 ret->file_transfer_in = jabber_file_transfer_in;
4231 ret->file_transfer_data_chunk = NULL; /* TODO */
4232 ret->file_transfer_done = jabber_file_transfer_done;
4233 ret->file_transfer_cancel = jabber_file_transfer_cancel;
4234
4013 puo = g_new0(struct proto_user_opt, 1); 4235 puo = g_new0(struct proto_user_opt, 1);
4014 puo->label = g_strdup("Port:"); 4236 puo->label = g_strdup("Port:");
4015 puo->def = g_strdup("5222"); 4237 puo->def = g_strdup("5222");
4016 puo->pos = USEROPT_PORT; 4238 puo->pos = USEROPT_PORT;
4017 ret->user_opts = g_list_append(ret->user_opts, puo); 4239 ret->user_opts = g_list_append(ret->user_opts, puo);
4019 my_protocol = ret; 4241 my_protocol = ret;
4020 } 4242 }
4021 4243
4022 #ifndef STATIC 4244 #ifndef STATIC
4023 4245
4024 void *gaim_prpl_init(struct prpl *prpl) 4246 G_MODULE_EXPORT void gaim_prpl_init(struct prpl *prpl)
4025 { 4247 {
4026 jabber_init(prpl); 4248 jabber_init(prpl);
4027 prpl->plug->desc.api_version = PLUGIN_API_VERSION; 4249 prpl->plug->desc.api_version = PLUGIN_API_VERSION;
4028 } 4250 }
4029 4251