plugins/jabber/jabber.c

changeset 1345
51a8dbeadbef
parent 1344
db71cfb65383
child 1347
6fa6aa0d4d6e
--- a/plugins/jabber/jabber.c	Thu Dec 21 10:31:42 2000 +0000
+++ b/plugins/jabber/jabber.c	Thu Dec 21 13:54:22 2000 +0000
@@ -58,27 +58,26 @@
 #define IQ_AUTH 0
 #define IQ_ROSTER 1
 
-typedef struct gjconn_struct
-{
-        /* Core structure */
-        pool        p;             /* Memory allocation pool */
-        int         state;     /* Connection state flag */
-        int         fd;            /* Connection file descriptor */
-        jid         user;      /* User info */
-        char        *pass;     /* User passwd */
+typedef struct gjconn_struct {
+	/* Core structure */
+	pool p;			/* Memory allocation pool */
+	int state;		/* Connection state flag */
+	int fd;			/* Connection file descriptor */
+	jid user;		/* User info */
+	char *pass;		/* User passwd */
 
-        /* Stream stuff */
-        int         id;        /* id counter for jab_getid() function */
-        char        idbuf[9];  /* temporary storage for jab_getid() */
-        char        *sid;      /* stream id from server, for digest auth */
-        XML_Parser  parser;    /* Parser instance */
-        xmlnode     current;   /* Current node in parsing instance.. */
+	/* Stream stuff */
+	int id;			/* id counter for jab_getid() function */
+	char idbuf[9];		/* temporary storage for jab_getid() */
+	char *sid;		/* stream id from server, for digest auth */
+	XML_Parser parser;	/* Parser instance */
+	xmlnode current;	/* Current node in parsing instance.. */
 
-        /* Event callback ptrs */
-        void (*on_state)(struct gjconn_struct *j, int state);
-        void (*on_packet)(struct gjconn_struct *j, jpacket p);
+	/* Event callback ptrs */
+	void (*on_state) (struct gjconn_struct * j, int state);
+	void (*on_packet) (struct gjconn_struct * j, jpacket p);
 
-        void *priv;
+	void *priv;
 
 } *gjconn, gjconn_struct;
 
@@ -101,18 +100,21 @@
 static char *gjab_auth(gjconn j);
 
 struct jabber_data {
-        gjconn jc;
+	gjconn jc;
 };
 
-static char *jabber_name() {
+static char *jabber_name()
+{
 	return "Jabber";
 }
 
-char *name() {
+char *name()
+{
 	return "Jabber";
 }
 
-char *description() {
+char *description()
+{
 	return "Allows gaim to use the Jabber protocol";
 }
 
@@ -120,547 +122,648 @@
 
 static gjconn gjab_new(char *user, char *pass, void *priv)
 {
-    pool p;
-    gjconn j;
+	pool p;
+	gjconn j;
 
-    if(!user) 
-            return(NULL);
+	if (!user)
+		return (NULL);
 
-    p = pool_new();
-    if(!p) 
-            return(NULL);
-    j = pmalloc_x(p, sizeof(gjconn_struct), 0);
-    if(!j) 
-            return(NULL);
-    j->p = p;
+	p = pool_new();
+	if (!p)
+		return (NULL);
+	j = pmalloc_x(p, sizeof(gjconn_struct), 0);
+	if (!j)
+		return (NULL);
+	j->p = p;
 
-    j->user = jid_new(p, user);
-    j->pass = pstrdup(p, pass);
+	j->user = jid_new(p, user);
+	j->pass = pstrdup(p, pass);
 
-    j->state = JCONN_STATE_OFF;
-    j->id = 1;
-    j->fd = -1;
+	j->state = JCONN_STATE_OFF;
+	j->id = 1;
+	j->fd = -1;
 
-    j->priv = priv;
+	j->priv = priv;
 
-    return j;
+	return j;
 }
 
 static void gjab_delete(gjconn j)
 {
-    if(!j) 
-            return;
+	if (!j)
+		return;
 
-    gjab_stop(j);
-    pool_free(j->p);
+	gjab_stop(j);
+	pool_free(j->p);
 }
 
 static void gjab_state_handler(gjconn j, gjconn_state_h h)
 {
-    if(!j)      
-            return;
+	if (!j)
+		return;
 
-    j->on_state = h;
+	j->on_state = h;
 }
 
 static void gjab_packet_handler(gjconn j, gjconn_packet_h h)
 {
-    if(!j)
-            return;
+	if (!j)
+		return;
 
-    j->on_packet = h;
+	j->on_packet = h;
 }
 
 static void gjab_stop(gjconn j)
 {
-    if(!j || j->state == JCONN_STATE_OFF) 
-            return;
+	if (!j || j->state == JCONN_STATE_OFF)
+		return;
 
-    j->state = JCONN_STATE_OFF;
-    close(j->fd);
-    j->fd = -1;
-    XML_ParserFree(j->parser);
+	j->state = JCONN_STATE_OFF;
+	gjab_send_raw(j, "</stream:stream>");
+	close(j->fd);
+	j->fd = -1;
+	XML_ParserFree(j->parser);
 }
 
 static int gjab_getfd(gjconn j)
 {
-    if(j)
-        return j->fd;
-    else
-        return -1;
+	if (j)
+		return j->fd;
+	else
+		return -1;
 }
 
 static jid gjab_getjid(gjconn j)
 {
-    if(j)
-        return(j->user);
-    else
-        return NULL;
+	if (j)
+		return (j->user);
+	else
+		return NULL;
 }
 
 static char *gjab_getsid(gjconn j)
 {
-    if(j)
-        return(j->sid);
-    else
-        return NULL;
+	if (j)
+		return (j->sid);
+	else
+		return NULL;
 }
 
 static char *gjab_getid(gjconn j)
 {
-    snprintf(j->idbuf, 8, "%d", j->id++);
-    return &j->idbuf[0];
+	snprintf(j->idbuf, 8, "%d", j->id++);
+	return &j->idbuf[0];
 }
 
 static void gjab_send(gjconn j, xmlnode x)
 {
-    if (j && j->state != JCONN_STATE_OFF) {
-            char *buf = xmlnode2str(x);
-            if (buf) 
-                    write(j->fd, buf, strlen(buf));
-            debug_printf("gjab_send: %s\n", buf);
-    }
+	if (j && j->state != JCONN_STATE_OFF) {
+		char *buf = xmlnode2str(x);
+		if (buf)
+			write(j->fd, buf, strlen(buf));
+		debug_printf("gjab_send: %s\n", buf);
+	}
 }
 
 static void gjab_send_raw(gjconn j, const char *str)
 {
-        if (j && j->state != JCONN_STATE_OFF) {
-                write(j->fd, str, strlen(str));
-                debug_printf("gjab_send_raw: %s\n", str);
-        }
+	if (j && j->state != JCONN_STATE_OFF) {
+		write(j->fd, str, strlen(str));
+		debug_printf("gjab_send_raw: %s\n", str);
+	}
 }
 
 static void gjab_reqroster(gjconn j)
 {
-        xmlnode x;
-        char *id;
+	xmlnode x;
+	char *id;
 
-        x = jutil_iqnew(JPACKET__GET, NS_ROSTER);
-        id = gjab_getid(j);
-        xmlnode_put_attrib(x, "id", id);
+	x = jutil_iqnew(JPACKET__GET, NS_ROSTER);
+	id = gjab_getid(j);
+	xmlnode_put_attrib(x, "id", id);
 
-        gjab_send(j, x);
-        xmlnode_free(x);
+	gjab_send(j, x);
+	xmlnode_free(x);
 }
 
 static char *gjab_auth(gjconn j)
 {
-    xmlnode x,y,z;
-    char *hash, *user, *id;
+	xmlnode x, y, z;
+	char *hash, *user, *id;
 
-    if(!j) 
-            return NULL;
+	if (!j)
+		return NULL;
 
-    x = jutil_iqnew(JPACKET__SET, NS_AUTH);
-    id = gjab_getid(j);
-    xmlnode_put_attrib(x, "id", id);
-    y = xmlnode_get_tag(x,"query");
+	x = jutil_iqnew(JPACKET__SET, NS_AUTH);
+	id = gjab_getid(j);
+	xmlnode_put_attrib(x, "id", id);
+	y = xmlnode_get_tag(x, "query");
 
-    user = j->user->user;
+	user = j->user->user;
 
-    if (user) {
-            z = xmlnode_insert_tag(y, "username");
-            xmlnode_insert_cdata(z, user, -1);
-    }
+	if (user) {
+		z = xmlnode_insert_tag(y, "username");
+		xmlnode_insert_cdata(z, user, -1);
+	}
 
-    z = xmlnode_insert_tag(y, "resource");
-    xmlnode_insert_cdata(z, j->user->resource, -1);
+	z = xmlnode_insert_tag(y, "resource");
+	xmlnode_insert_cdata(z, j->user->resource, -1);
 
-    if (j->sid) {
-            z = xmlnode_insert_tag(y, "digest");
-            hash = pmalloc(x->p, strlen(j->sid)+strlen(j->pass)+1);
-            strcpy(hash, j->sid);
-            strcat(hash, j->pass);
-            hash = shahash(hash);
-            xmlnode_insert_cdata(z, hash, 40);
-    } else {
-            z = xmlnode_insert_tag(y, "password");
-            xmlnode_insert_cdata(z, j->pass, -1);
-    }
+	if (j->sid) {
+		z = xmlnode_insert_tag(y, "digest");
+		hash = pmalloc(x->p, strlen(j->sid) + strlen(j->pass) + 1);
+		strcpy(hash, j->sid);
+		strcat(hash, j->pass);
+		hash = shahash(hash);
+		xmlnode_insert_cdata(z, hash, 40);
+	} else {
+		z = xmlnode_insert_tag(y, "password");
+		xmlnode_insert_cdata(z, j->pass, -1);
+	}
 
-    gjab_send(j, x);
-    xmlnode_free(x);
+	gjab_send(j, x);
+	xmlnode_free(x);
 
-    return id;
+	return id;
 }
 
 static void gjab_recv(gjconn j)
 {
-        static char buf[4096];
-        int len;
+	static char buf[4096];
+	int len;
 
-        if(!j || j->state == JCONN_STATE_OFF)
-                return;
+	if (!j || j->state == JCONN_STATE_OFF)
+		return;
 
-        if ((len = read(j->fd, buf, sizeof(buf)-1))) {
-                buf[len] = '\0';
-                debug_printf("input: %s\n", buf);
-                XML_Parse(j->parser, buf, len, 0);
-        } else if (len < 0) {
-                STATE_EVT(JCONN_STATE_OFF);
-                gjab_stop(j);
-        }
+	if ((len = read(j->fd, buf, sizeof(buf) - 1))) {
+		buf[len] = '\0';
+		debug_printf("input: %s\n", buf);
+		XML_Parse(j->parser, buf, len, 0);
+	} else if (len < 0) {
+		STATE_EVT(JCONN_STATE_OFF);
+		gjab_stop(j);
+	}
 }
 
 static void startElement(void *userdata, const char *name, const char **attribs)
 {
-    xmlnode x;
-    gjconn j = (gjconn)userdata;
+	xmlnode x;
+	gjconn j = (gjconn) userdata;
 
-    if(j->current) {
-            /* Append the node to the current one */
-            x = xmlnode_insert_tag(j->current, name);
-            xmlnode_put_expat_attribs(x, attribs);
+	if (j->current) {
+		/* Append the node to the current one */
+		x = xmlnode_insert_tag(j->current, name);
+		xmlnode_put_expat_attribs(x, attribs);
 
-            j->current = x;
-    } else {
-            x = xmlnode_new_tag(name);
-            xmlnode_put_expat_attribs(x, attribs);
-            if(strcmp(name, "stream:stream") == 0) {
-                    /* special case: name == stream:stream */
-                    /* id attrib of stream is stored for digest auth */
-                    j->sid = xmlnode_get_attrib(x, "id");
-                    /* STATE_EVT(JCONN_STATE_AUTH) */
-            } else {
-                    j->current = x;
-            }
-    }
+		j->current = x;
+	} else {
+		x = xmlnode_new_tag(name);
+		xmlnode_put_expat_attribs(x, attribs);
+		if (strcmp(name, "stream:stream") == 0) {
+			/* special case: name == stream:stream */
+			/* id attrib of stream is stored for digest auth */
+			j->sid = xmlnode_get_attrib(x, "id");
+			/* STATE_EVT(JCONN_STATE_AUTH) */
+		} else {
+			j->current = x;
+		}
+	}
 }
 
 static void endElement(void *userdata, const char *name)
 {
-    gjconn j = (gjconn)userdata;
-    xmlnode x;
-    jpacket p;
+	gjconn j = (gjconn) userdata;
+	xmlnode x;
+	jpacket p;
 
-    if(j->current == NULL) {
-        /* we got </stream:stream> */
-        STATE_EVT(JCONN_STATE_OFF)
-        return;
-    }
+	if (j->current == NULL) {
+		/* we got </stream:stream> */
+		STATE_EVT(JCONN_STATE_OFF)
+		    return;
+	}
 
-    x = xmlnode_get_parent(j->current);
+	x = xmlnode_get_parent(j->current);
 
-    if(!x) {
-            /* it is time to fire the event */
-            p = jpacket_new(j->current);
+	if (!x) {
+		/* it is time to fire the event */
+		p = jpacket_new(j->current);
 
-            if(j->on_packet)
-                    (j->on_packet)(j, p);
-            else
-                    xmlnode_free(j->current);
-    }
+		if (j->on_packet)
+			(j->on_packet) (j, p);
+		else
+			xmlnode_free(j->current);
+	}
 
-    j->current = x;
+	j->current = x;
 }
 
 static void charData(void *userdata, const char *s, int slen)
 {
-    gjconn j = (gjconn)userdata;
+	gjconn j = (gjconn) userdata;
 
-    if (j->current)
-        xmlnode_insert_cdata(j->current, s, slen);
+	if (j->current)
+		xmlnode_insert_cdata(j->current, s, slen);
 }
 
 static void gjab_start(gjconn j)
 {
-    xmlnode x;
-    char *t,*t2;
+	xmlnode x;
+	char *t, *t2;
 
-    if(!j || j->state != JCONN_STATE_OFF) 
-            return;
+	if (!j || j->state != JCONN_STATE_OFF)
+		return;
 
-    j->parser = XML_ParserCreate(NULL);
-    XML_SetUserData(j->parser, (void *)j);
-    XML_SetElementHandler(j->parser, startElement, endElement);
-    XML_SetCharacterDataHandler(j->parser, charData);
+	j->parser = XML_ParserCreate(NULL);
+	XML_SetUserData(j->parser, (void *)j);
+	XML_SetElementHandler(j->parser, startElement, endElement);
+	XML_SetCharacterDataHandler(j->parser, charData);
 
-    j->fd = make_netsocket(5222, j->user->server, NETSOCKET_CLIENT);
-    if(j->fd < 0) {
-        STATE_EVT(JCONN_STATE_OFF)
-        return;
-    }
-    j->state = JCONN_STATE_CONNECTED;
-    STATE_EVT(JCONN_STATE_CONNECTED)
+	j->fd = make_netsocket(5222, j->user->server, NETSOCKET_CLIENT);
+	if (j->fd < 0) {
+		STATE_EVT(JCONN_STATE_OFF)
+		    return;
+	}
+	j->state = JCONN_STATE_CONNECTED;
+	STATE_EVT(JCONN_STATE_CONNECTED)
 
-    /* start stream */
-    x = jutil_header(NS_CLIENT, j->user->server);
-    t = xmlnode2str(x);
-    /* this is ugly, we can create the string here instead of jutil_header */
-    /* what do you think about it? -madcat */
-    t2 = strstr(t,"/>");
-    *t2++ = '>';
-    *t2 = '\0';
-    gjab_send_raw(j,"<?xml version='1.0'?>");
-    gjab_send_raw(j,t);
-    xmlnode_free(x);
+	    /* start stream */
+	    x = jutil_header(NS_CLIENT, j->user->server);
+	t = xmlnode2str(x);
+	/* this is ugly, we can create the string here instead of jutil_header */
+	/* what do you think about it? -madcat */
+	t2 = strstr(t, "/>");
+	*t2++ = '>';
+	*t2 = '\0';
+	gjab_send_raw(j, "<?xml version='1.0'?>");
+	gjab_send_raw(j, t);
+	xmlnode_free(x);
 
-    j->state = JCONN_STATE_ON;
-    STATE_EVT(JCONN_STATE_ON)
+	j->state = JCONN_STATE_ON;
+	STATE_EVT(JCONN_STATE_ON)
 }
 
-static void jabber_callback(gpointer data, gint source, GdkInputCondition condition) {
+static void jabber_callback(gpointer data, gint source, GdkInputCondition condition)
+{
 	struct gaim_connection *gc = (struct gaim_connection *)data;
 	struct jabber_data *jd = (struct jabber_data *)gc->proto_data;
 
-        debug_printf("jabber_callback!\n");
-
-        gjab_recv(jd->jc);
+	gjab_recv(jd->jc);
 }
 
 static void jabber_handlemessage(gjconn j, jpacket p)
 {
-  xmlnode y;
-
-  char *from = NULL, *msg = NULL;
+	xmlnode y;
 
-  from = jid_full(p->from);
-  if ((y = xmlnode_get_tag(p->x, "body"))) {
-    msg = xmlnode_get_data(y);
-  }
+	char *from = NULL, *msg = NULL;
 
-  if (!from || !msg) {
-    return;
-  }
+	from = jid_full(p->from);
+	if ((y = xmlnode_get_tag(p->x, "body"))) {
+		msg = xmlnode_get_data(y);
+	}
 
-  debug_printf("jabber: msg from %s: %s\n", from, msg);
+	if (!from || !msg) {
+		return;
+	}
 
-  serv_got_im(GJ_GC(j), from, msg, 0);
+	serv_got_im(GJ_GC(j), from, msg, 0);
 
-  return;
+	return;
 }
 
 static void jabber_handlepresence(gjconn j, jpacket p)
 {
-  char *to, *from, *type;
-  struct buddy *b;
+	char *to, *from, *type;
+	struct buddy *b;
+	jid who;
+	char *buddy;
+
+	to = xmlnode_get_attrib(p->x, "to");
+	from = xmlnode_get_attrib(p->x, "from");
+	type = xmlnode_get_attrib(p->x, "type");
 
-  to = xmlnode_get_attrib(p->x, "to");
-  from = xmlnode_get_attrib(p->x, "from");
-  type = xmlnode_get_attrib(p->x, "type");
+	debug_printf("jabber: presence: %s, %s %s\n", to, from, type);
+	who = jid_new(j->p, from);
+	if (who->user == NULL) {
+		/* FIXME: transport */
+		debug_printf("user was NULL in handlepresence!\n");
+		return;
+	}
 
-  debug_printf("jabber: presence: %s, %s %s\n", to, from, type);
+	buddy = g_strdup_printf("%s@%s", who->user, who->server);
 
-  if (!(b = find_buddy(GJ_GC(j), from))) {
-          add_buddy(GJ_GC(j), "Buddies", from, from);
-	  do_export(NULL, NULL);
-  }
+	if (!(b = find_buddy(GJ_GC(j), buddy))) {
+		add_buddy(GJ_GC(j), "Buddies", buddy, buddy);
+		build_edit_tree();
+		do_export(NULL, NULL);
+	}
 
-  if (type && (strcasecmp(type, "unavailable") == 0))
-          serv_got_update(GJ_GC(j), from, 0, 0, 0, 0, 0, 0);
-  else
-          serv_got_update(GJ_GC(j), from, 1, 0, 0, 0, 0, 0);
+	if (type && (strcasecmp(type, "unavailable") == 0))
+		serv_got_update(GJ_GC(j), buddy, 0, 0, 0, 0, 0, 0);
+	else
+		serv_got_update(GJ_GC(j), buddy, 1, 0, 0, 0, 0, 0);
 
-  return;
+	g_free(buddy);
+
+	return;
+}
+
+static void jabber_handles10n(gjconn j, jpacket p)
+{
 }
 
 static void jabber_handleroster(gjconn j, xmlnode querynode)
 {
-        xmlnode x;
+	xmlnode x;
 
-        x = xmlnode_get_firstchild(querynode);
-        while (x) {
-                xmlnode g;
-                char *jid, *name, *sub, *ask;
+	x = xmlnode_get_firstchild(querynode);
+	while (x) {
+		xmlnode g;
+		char *Jid, *name, *sub, *ask;
+		jid who;
+
+		Jid = xmlnode_get_attrib(x, "jid");
+		name = xmlnode_get_attrib(x, "name");
+		sub = xmlnode_get_attrib(x, "subscription");
+		ask = xmlnode_get_attrib(x, "ask");
 
-                jid = xmlnode_get_attrib(x, "jid");
-                name = xmlnode_get_attrib(x, "name");
-                if (name)
-                        debug_printf("name = %s\n", name);
-                sub = xmlnode_get_attrib(x, "subscription");
-                ask = xmlnode_get_attrib(x, "ask");
+		if (ask) {
+			/* XXX do something
+			debug_printf("jabber: unhandled subscription request (%s/%s/%s/%s)\n", Jid, name,
+				     sub, ask);
+			*/
+		}
 
-                if (ask) {
-                        /* XXX do something */
-                        debug_printf("jabber: unhandled subscription request (%s/%s/%s/%s)\n", jid, name, sub, ask);
-                }
-
-                if ((g = xmlnode_get_firstchild(x))) {
-                        while (g) {
-                                if (strncasecmp(xmlnode_get_name(g), "group", 5) == 0) {
-                                        struct buddy *b;
-                                        char *groupname;
+		if ((g = xmlnode_get_firstchild(x))) {
+			while (g) {
+				if (strncasecmp(xmlnode_get_name(g), "group", 5) == 0) {
+					struct buddy *b;
+					char *groupname, *buddyname;
 
-                                        groupname = xmlnode_get_data(xmlnode_get_firstchild(g));
-                                        if (!(b = find_buddy(GJ_GC(j), jid))) {
-                                                debug_printf("adding buddy: %s\n", jid);
-                                                b = add_buddy(GJ_GC(j), groupname, jid, name?name:jid);
+					groupname = xmlnode_get_data(xmlnode_get_firstchild(g));
+					who = jid_new(j->p, Jid);
+					if (who->user == NULL) {
+						/* FIXME: transport */
+						debug_printf("user was NULL in handleroster!\n");
+						g = xmlnode_get_nextsibling(g);
+						continue;
+					}
+					buddyname = g_strdup_printf("%s@%s", who->user, who->server);
+					if (!(b = find_buddy(GJ_GC(j), buddyname))) {
+						debug_printf("adding buddy: %s\n", buddyname);
+						b =
+						    add_buddy(GJ_GC(j), groupname, buddyname,
+							      name ? name : buddyname);
+						build_edit_tree();
 						do_export(0, 0);
-                                        } else {
-                                                debug_printf("updating buddy: %s/%s\n", jid, name);
-                                                g_snprintf(b->name, sizeof(b->name), "%s", jid);
-                                                g_snprintf(b->show, sizeof(b->show), "%s", name?name:jid);
-                                        }
-                                        //serv_got_update(GJ_GC(j), b->name, 1, 0, 0, 0, 0, 0);
-                                }
-                                g = xmlnode_get_nextsibling(g);
-                        }
-                } else {
-                        struct buddy *b;
-                        if (!(b = find_buddy(GJ_GC(j), jid))) {
-                                b = add_buddy(GJ_GC(j), "Buddies", jid, name?name:jid);
+					} else {
+						debug_printf("updating buddy: %s/%s\n", buddyname, name);
+						g_snprintf(b->name, sizeof(b->name), "%s", buddyname);
+						g_snprintf(b->show, sizeof(b->show), "%s",
+							   name ? name : buddyname);
+					}
+					g_free(buddyname);
+				}
+				g = xmlnode_get_nextsibling(g);
+			}
+		} else {
+			struct buddy *b;
+			char *buddyname;
+
+			who = jid_new(j->p, Jid);
+			if (who->user == NULL) {
+				/* FIXME: transport */
+				debug_printf("user was NULL in handleroster!\n");
+				x = xmlnode_get_nextsibling(x);
+				continue;
+			}
+			buddyname = g_strdup_printf("%s@%s", who->user, who->server);
+			if (!(b = find_buddy(GJ_GC(j), buddyname))) {
+				b = add_buddy(GJ_GC(j), "Buddies", buddyname, name ? name : Jid);
+				build_edit_tree();
 				do_export(0, 0);
-                        }
-                }
+			}
+			g_free(buddyname);
+		}
 
-                x = xmlnode_get_nextsibling(x);
-        }
+		x = xmlnode_get_nextsibling(x);
+	}
 
-	x = jutil_presnew(0, NULL, NULL);
+	x = jutil_presnew(0, NULL, "Online");
 	gjab_send(j, x);
 	xmlnode_free(x);
 }
 
 static void jabber_handlepacket(gjconn j, jpacket p)
 {
-  switch (p->type) {
-  case JPACKET_MESSAGE:
-          jabber_handlemessage(j, p);
-          break;
-  case JPACKET_PRESENCE:
-          jabber_handlepresence(j, p);
-          break;
-  case JPACKET_IQ: {
-
-          if (jpacket_subtype(p) == JPACKET__RESULT) {
-                  xmlnode querynode;
-                  char *xmlns;
+	switch (p->type) {
+	case JPACKET_MESSAGE:
+		jabber_handlemessage(j, p);
+		break;
+	case JPACKET_PRESENCE:
+		jabber_handlepresence(j, p);
+		break;
+	case JPACKET_IQ:
+		debug_printf("jpacket_subtype: %d\n", jpacket_subtype(p));
 
-                  querynode = xmlnode_get_tag(p->x, "query");
-                  xmlns = xmlnode_get_attrib(querynode, "xmlns");
+		if (jpacket_subtype(p) == JPACKET__SET) {
+		} else if (jpacket_subtype(p) == JPACKET__RESULT) {
+			xmlnode querynode;
+			char *xmlns;
+
+			querynode = xmlnode_get_tag(p->x, "query");
+			xmlns = xmlnode_get_attrib(querynode, "xmlns");
 
-                  if (!xmlns || NSCHECK(querynode, NS_AUTH)) {
-                          debug_printf("auth success\n");
-                          
-                          account_online(GJ_GC(j));
-                          serv_finish_login(GJ_GC(j));
+			if (!xmlns || NSCHECK(querynode, NS_AUTH)) {
+				debug_printf("auth success\n");
 
-			  if (bud_list_cache_exists(GJ_GC(j)))
-				  do_import(NULL, GJ_GC(j));
-                          
-                          gjab_reqroster(j);
+				account_online(GJ_GC(j));
+				serv_finish_login(GJ_GC(j));
+
+				if (bud_list_cache_exists(GJ_GC(j)))
+					do_import(NULL, GJ_GC(j));
+
+				gjab_reqroster(j);
 
-                  } else if (NSCHECK(querynode, NS_ROSTER)) {
-                          jabber_handleroster(j, querynode);
-                  } else {
-                          debug_printf("jabber:iq:query: %s\n", xmlns);
-                  }
+			} else if (NSCHECK(querynode, NS_ROSTER)) {
+				jabber_handleroster(j, querynode);
+			} else {
+				/* debug_printf("jabber:iq:query: %s\n", xmlns); */
+			}
+		} else {
+			xmlnode x;
 
-          } else {
-                  xmlnode x;
+			debug_printf("auth failed\n");
+			x = xmlnode_get_tag(p->x, "error");
+			if (x) {
+				debug_printf("error %d: %s\n\n",
+					     atoi(xmlnode_get_attrib(x, "code")),
+					     xmlnode_get_data(xmlnode_get_firstchild(x)));
+				hide_login_progress(GJ_GC(j),
+						    xmlnode_get_data(xmlnode_get_firstchild(x)));
 
-                  debug_printf("auth failed\n");
-                  x = xmlnode_get_tag(p->x, "error");
-                  if (x) {
-                          debug_printf("error %d: %s\n\n", 
-                                       atoi(xmlnode_get_attrib(x, "code")), 
-                                       xmlnode_get_data(xmlnode_get_firstchild(x)));
-                          hide_login_progress(GJ_GC(j), xmlnode_get_data(xmlnode_get_firstchild(x)));
-
-                  } else
-                          hide_login_progress(GJ_GC(j), "unknown error");
+			} else
+				hide_login_progress(GJ_GC(j), "unknown error");
 
-                  signoff(GJ_GC(j));
-          }
-          break;
-  }
-  default:
-          debug_printf("jabber: packet type %d (%s)\n", p->type, xmlnode2str(p->x));
-  }
+			signoff(GJ_GC(j));
+		}
+		break;
+	case JPACKET_S10N:
+		jabber_handles10n(j, p);
+		break;
+	default:
+		debug_printf("jabber: packet type %d (%s)\n", p->type, xmlnode2str(p->x));
+	}
 
-  xmlnode_free(p->x);
+	xmlnode_free(p->x);
 
-  return;
+	return;
 }
 
 static void jabber_handlestate(gjconn j, int state)
 {
-  switch (state) {
-  case JCONN_STATE_OFF:
-          debug_printf("jabber: connection closed\n");
-          hide_login_progress(GJ_GC(j), "Unable to connect");
-          signoff(GJ_GC(j));
-          break;
-  case JCONN_STATE_CONNECTED:
-          debug_printf("jabber: connected.\n");
-          set_login_progress(GJ_GC(j), 3, "Connected");
-          break;
-  case JCONN_STATE_ON:
-          debug_printf("jabber: logging in...\n");
-          set_login_progress(GJ_GC(j), 5, "Logging in...");
-          gjab_auth(j);
-          break;
-  default:
-          debug_printf("state change: %d\n", state);
-  }
-  return;
+	switch (state) {
+	case JCONN_STATE_OFF:
+		hide_login_progress(GJ_GC(j), "Unable to connect");
+		signoff(GJ_GC(j));
+		break;
+	case JCONN_STATE_CONNECTED:
+		set_login_progress(GJ_GC(j), 3, "Connected");
+		break;
+	case JCONN_STATE_ON:
+		set_login_progress(GJ_GC(j), 5, "Logging in...");
+		gjab_auth(j);
+		break;
+	default:
+		debug_printf("state change: %d\n", state);
+	}
+	return;
 }
 
-static void jabber_login(struct aim_user *user) {
+static void jabber_login(struct aim_user *user)
+{
 	struct gaim_connection *gc = new_gaim_conn(user);
 	struct jabber_data *jd = gc->proto_data = g_new0(struct jabber_data, 1);
 
 	set_login_progress(gc, 1, "Connecting");
 
-        if (!(jd->jc = gjab_new(user->username, user->password, gc))) {
+	if (!(jd->jc = gjab_new(user->username, user->password, gc))) {
 		debug_printf("jabber: unable to connect (jab_new failed)\n");
 		hide_login_progress(gc, "Unable to connect");
 		signoff(gc);
-                return;
-        }
+		return;
+	}
 
-        gjab_state_handler(jd->jc, jabber_handlestate);
-        gjab_packet_handler(jd->jc, jabber_handlepacket);
-        gjab_start(jd->jc);
+	gjab_state_handler(jd->jc, jabber_handlestate);
+	gjab_packet_handler(jd->jc, jabber_handlepacket);
+	gjab_start(jd->jc);
 
 
-	gc->inpa = gdk_input_add(jd->jc->fd, 
-                                 GDK_INPUT_READ | GDK_INPUT_EXCEPTION,
-                                 jabber_callback, gc);
+	gc->inpa = gdk_input_add(jd->jc->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, jabber_callback, gc);
 
-        return;
+	return;
 }
 
-static void jabber_close(struct gaim_connection *gc) {
+static void jabber_close(struct gaim_connection *gc)
+{
 	struct jabber_data *jd = gc->proto_data;
 	gdk_input_remove(gc->inpa);
 	gjab_stop(jd->jc);
 	g_free(jd);
 }
 
-static void jabber_send_im(struct gaim_connection *gc, char *who, char *message, int away) {
-        xmlnode x, y;
+static void jabber_send_im(struct gaim_connection *gc, char *who, char *message, int away)
+{
+	xmlnode x, y;
 	char *realwho;
 	gjconn j = ((struct jabber_data *)gc->proto_data)->jc;
 
-        if (!who || !message)
-                return;
+	if (!who || !message)
+		return;
 
-        x = xmlnode_new_tag("message");
+	x = xmlnode_new_tag("message");
 	if (!strchr(who, '@'))
 		realwho = g_strdup_printf("%s@%s", who, j->user->server);
 	else
 		realwho = g_strdup(who);
-        xmlnode_put_attrib(x, "to", realwho);
+	xmlnode_put_attrib(x, "to", realwho);
 	g_free(realwho);
 
-        xmlnode_put_attrib(x, "type", "chat");
+	xmlnode_put_attrib(x, "type", "chat");
+
+	if (message && strlen(message)) {
+		y = xmlnode_insert_tag(x, "body");
+		xmlnode_insert_cdata(y, message, -1);
+	}
+
+	gjab_send(((struct jabber_data *)gc->proto_data)->jc, x);
+}
+
+static void jabber_add_buddy(struct gaim_connection *gc, char *name)
+{
+	xmlnode x;
+	char *realwho;
+	gjconn j = ((struct jabber_data *)gc->proto_data)->jc;
+
+	if (!name)
+		return;
+
+	x = xmlnode_new_tag("presence");
 
-        if (message && strlen(message)) {
-                y = xmlnode_insert_tag(x, "body");
-                xmlnode_insert_cdata(y, message, -1);
-        }
+	if (!strchr(name, '@'))
+		realwho = g_strdup_printf("%s@%s", name, j->user->server);
+	else {
+		jid who = jid_new(j->p, name);
+		if (who->user == NULL) {
+			/* FIXME: transport */
+			debug_printf("user was NULL in add_buddy!\n");
+			return;
+		}
+		realwho = g_strdup_printf("%s@%s", who->user, who->server);
+	}
+	xmlnode_put_attrib(x, "to", realwho);
+	g_free(realwho);
+
+	xmlnode_put_attrib(x, "type", "subscribe");
+
+	gjab_send(((struct jabber_data *)gc->proto_data)->jc, x);
+}
 
-        gjab_send(((struct jabber_data *)gc->proto_data)->jc, x);
+static void jabber_remove_buddy(struct gaim_connection *gc, char *name)
+{
+	xmlnode x;
+	char *realwho;
+	gjconn j = ((struct jabber_data *)gc->proto_data)->jc;
+
+	if (!name)
+		return;
+
+	x = xmlnode_new_tag("presence");
+
+	if (!strchr(name, '@'))
+		realwho = g_strdup_printf("%s@%s", name, j->user->server);
+	else
+		realwho = g_strdup(name);
+	xmlnode_put_attrib(x, "to", realwho);
+	g_free(realwho);
+
+	xmlnode_put_attrib(x, "type", "unsubscribe");
+
+	gjab_send(((struct jabber_data *)gc->proto_data)->jc, x);
+}
+
+static char **jabber_list_icon(int uc)
+{
+	return available_xpm;
 }
 
 static struct prpl *my_protocol = NULL;
 
-void Jabber_init(struct prpl *ret) {
+void Jabber_init(struct prpl *ret)
+{
 	/* the NULL's aren't required but they're nice to have */
 	ret->protocol = PROTO_JABBER;
 	ret->name = jabber_name;
-	ret->list_icon = NULL;
+	ret->list_icon = jabber_list_icon;
 	ret->action_menu = NULL;
 	ret->user_opts = NULL;
 	ret->login = jabber_login;
@@ -675,9 +778,9 @@
 	ret->dir_search = NULL;
 	ret->set_idle = NULL;
 	ret->change_passwd = NULL;
-	ret->add_buddy = NULL;
+	ret->add_buddy = jabber_add_buddy;
 	ret->add_buddies = NULL;
-	ret->remove_buddy = NULL;
+	ret->remove_buddy = jabber_remove_buddy;
 	ret->add_permit = NULL;
 	ret->add_deny = NULL;
 	ret->rem_permit = NULL;
@@ -695,12 +798,14 @@
 	my_protocol = ret;
 }
 
-char *gaim_plugin_init(GModule *handle) {
+char *gaim_plugin_init(GModule *handle)
+{
 	load_protocol(Jabber_init);
 	return NULL;
 }
 
-void gaim_plugin_remove() {
+void gaim_plugin_remove()
+{
 	struct prpl *p = find_prpl(PROTO_JABBER);
 	if (p == my_protocol)
 		unload_protocol(p);

mercurial