Index: protocols/jabber/Makefile
===================================================================
--- protocols/jabber/Makefile	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ protocols/jabber/Makefile	(revision 0fd8559c4a6ad84ad0852e07c4ba2e50b2fdf0ad)
@@ -10,5 +10,5 @@
 
 # [SH] Program variables
-objects = expat.o hashtable.o jid.o jpacket.o jutil.o log.o pool.o str.o xmlnode.o xmlparse.o xmlrole.o xmltok.o jabber.o
+objects = io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o xmltree.o
 
 CFLAGS += -Wall
Index: protocols/jabber/asciitab.h
===================================================================
--- protocols/jabber/asciitab.h	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,62 +1,0 @@
-/*
-The contents of this file are subject to the Mozilla Public License
-Version 1.1 (the "License"); you may not use this file except in
-compliance with the License. You may obtain a copy of the License at
-http://www.mozilla.org/MPL/
-
-Software distributed under the License is distributed on an "AS IS"
-basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
-License for the specific language governing rights and limitations
-under the License.
-
-The Original Code is expat.
-
-The Initial Developer of the Original Code is James Clark.
-Portions created by James Clark are Copyright (C) 1998, 1999
-James Clark. All Rights Reserved.
-
-Contributor(s):
-
-Alternatively, the contents of this file may be used under the terms
-of the GNU General Public License (the "GPL"), in which case the
-provisions of the GPL are applicable instead of those above.  If you
-wish to allow use of your version of this file only under the terms of
-the GPL and not to allow others to use your version of this file under
-the MPL, indicate your decision by deleting the provisions above and
-replace them with the notice and other provisions required by the
-GPL. If you do not delete the provisions above, a recipient may use
-your version of this file under either the MPL or the GPL.
-*/
-
-/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
-/* 0x0C */ BT_NONXML, BT_CR, BT_NONXML, BT_NONXML,
-/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
-/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
-/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
-/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
-/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
-/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
-/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
-/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
-/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
-/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
-/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
-/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
-/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
-/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
-/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
-/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
Index: protocols/jabber/expat.c
===================================================================
--- protocols/jabber/expat.c	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,54 +1,0 @@
-/* --------------------------------------------------------------------------
- *
- * License
- *
- * The contents of this file are subject to the Jabber Open Source License
- * Version 1.0 (the "JOSL").  You may not copy or use this file, in either
- * source code or executable form, except in compliance with the JOSL. You
- * may obtain a copy of the JOSL at http://www.jabber.org/ or at
- * http://www.opensource.org/.  
- *
- * Software distributed under the JOSL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the JOSL
- * for the specific language governing rights and limitations under the
- * JOSL.
- *
- * Copyrights
- * 
- * Portions created by or assigned to Jabber.com, Inc. are 
- * Copyright (c) 1999-2002 Jabber.com, Inc.  All Rights Reserved.  Contact
- * information for Jabber.com, Inc. is available at http://www.jabber.com/.
- *
- * Portions Copyright (c) 1998-1999 Jeremie Miller.
- * 
- * Acknowledgements
- * 
- * Special thanks to the Jabber Open Source Contributors for their
- * suggestions and support of Jabber.
- * 
- * Alternatively, the contents of this file may be used under the terms of the
- * GNU General Public License Version 2 or later (the "GPL"), in which case
- * the provisions of the GPL are applicable instead of those above.  If you
- * wish to allow use of your version of this file only under the terms of the
- * GPL and not to allow others to use your version of this file under the JOSL,
- * indicate your decision by deleting the provisions above and replace them
- * with the notice and other provisions required by the GPL.  If you do not
- * delete the provisions above, a recipient may use your version of this file
- * under either the JOSL or the GPL. 
- * 
- * 
- * --------------------------------------------------------------------------*/
-
-#include "lib.h"
-#include <glib.h>
-
-void xmlnode_put_expat_attribs(xmlnode owner, const char** atts)
-{
-    int i = 0;
-    if (atts == NULL) return;
-    while (atts[i] != '\0')
-    {
-        xmlnode_put_attrib(owner, atts[i], atts[i+1]);
-        i += 2;
-    }
-}
Index: protocols/jabber/hashtable.c
===================================================================
--- protocols/jabber/hashtable.c	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,142 +1,0 @@
-/*
-The contents of this file are subject to the Mozilla Public License
-Version 1.1 (the "License"); you may not use this file except in
-csompliance with the License. You may obtain a copy of the License at
-http://www.mozilla.org/MPL/
-
-Software distributed under the License is distributed on an "AS IS"
-basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
-License for the specific language governing rights and limitations
-under the License.
-
-The Original Code is expat.
-
-The Initial Developer of the Original Code is James Clark.
-Portions created by James Clark are Copyright (C) 1998, 1999
-James Clark. All Rights Reserved.
-
-Contributor(s):
-
-*/
-
-#include "xmldef.h"
-
-#ifdef XML_UNICODE_WCHAR_T
-#ifndef XML_UNICODE
-#define XML_UNICODE
-#endif
-#endif
-
-#include "hashtable.h"
-
-#define INIT_SIZE 64
-
-static
-int keyeq(KEY s1, KEY s2)
-{
-    for (; *s1 == *s2; s1++, s2++)
-        if (*s1 == 0)
-            return 1;
-    return 0;
-}
-
-static
-unsigned long hash(KEY s)
-{
-    unsigned long h = 0;
-    while (*s)
-        h = (h << 5) + h + (unsigned char)*s++;
-    return h;
-}
-
-NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize)
-{
-    size_t i;
-    if (table->size == 0) {
-        if (!createSize)
-            return 0;
-        table->v = calloc(INIT_SIZE, sizeof(NAMED *));
-        if (!table->v)
-            return 0;
-        table->size = INIT_SIZE;
-        table->usedLim = INIT_SIZE / 2;
-        i = hash(name) & (table->size - 1);
-    }
-    else {
-        unsigned long h = hash(name);
-        for (i = h & (table->size - 1);
-                table->v[i];
-                i == 0 ? i = table->size - 1 : --i) {
-            if (keyeq(name, table->v[i]->name))
-                return table->v[i];
-        }
-        if (!createSize)
-            return 0;
-        if (table->used == table->usedLim) {
-            /* check for overflow */
-            size_t newSize = table->size * 2;
-            NAMED **newV = calloc(newSize, sizeof(NAMED *));
-            if (!newV)
-                return 0;
-            for (i = 0; i < table->size; i++)
-                if (table->v[i]) {
-                    size_t j;
-                    for (j = hash(table->v[i]->name) & (newSize - 1);
-                            newV[j];
-                            j == 0 ? j = newSize - 1 : --j)
-                        ;
-                    newV[j] = table->v[i];
-                }
-            g_free(table->v);
-            table->v = newV;
-            table->size = newSize;
-            table->usedLim = newSize/2;
-            for (i = h & (table->size - 1);
-                    table->v[i];
-                    i == 0 ? i = table->size - 1 : --i)
-                ;
-        }
-    }
-    table->v[i] = calloc(1, createSize);
-    if (!table->v[i])
-        return 0;
-    table->v[i]->name = name;
-    (table->used)++;
-    return table->v[i];
-}
-
-void hashTableDestroy(HASH_TABLE *table)
-{
-    size_t i;
-    for (i = 0; i < table->size; i++) {
-        NAMED *p = table->v[i];
-        if (p)
-            g_free(p);
-    }
-    g_free(table->v);
-}
-
-void hashTableInit(HASH_TABLE *p)
-{
-    p->size = 0;
-    p->usedLim = 0;
-    p->used = 0;
-    p->v = 0;
-}
-
-void hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
-{
-    iter->p = table->v;
-    iter->end = iter->p + table->size;
-}
-
-NAMED *hashTableIterNext(HASH_TABLE_ITER *iter)
-{
-    while (iter->p != iter->end) {
-        NAMED *tem = *(iter->p)++;
-        if (tem)
-            return tem;
-    }
-    return 0;
-}
-
Index: protocols/jabber/hashtable.h
===================================================================
--- protocols/jabber/hashtable.h	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,69 +1,0 @@
-/*
-The contents of this file are subject to the Mozilla Public License
-Version 1.1 (the "License"); you may not use this file except in
-compliance with the License. You may obtain a copy of the License at
-http://www.mozilla.org/MPL/
-
-Software distributed under the License is distributed on an "AS IS"
-basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
-License for the specific language governing rights and limitations
-under the License.
-
-The Original Code is expat.
-
-The Initial Developer of the Original Code is James Clark.
-Portions created by James Clark are Copyright (C) 1998, 1999
-James Clark. All Rights Reserved.
-
-Contributor(s):
-
-Alternatively, the contents of this file may be used under the terms
-of the GNU General Public License (the "GPL"), in which case the
-provisions of the GPL are applicable instead of those above.  If you
-wish to allow use of your version of this file only under the terms of
-the GPL and not to allow others to use your version of this file under
-the MPL, indicate your decision by deleting the provisions above and
-replace them with the notice and other provisions required by the
-GPL. If you do not delete the provisions above, a recipient may use
-your version of this file under either the MPL or the GPL.
-*/
-
-
-#include <stddef.h>
-
-#ifdef XML_UNICODE
-
-#ifdef XML_UNICODE_WCHAR_T
-typedef const wchar_t *KEY;
-#else /* not XML_UNICODE_WCHAR_T */
-typedef const unsigned short *KEY;
-#endif /* not XML_UNICODE_WCHAR_T */
-
-#else /* not XML_UNICODE */
-
-typedef const char *KEY;
-
-#endif /* not XML_UNICODE */
-
-typedef struct {
-  KEY name;
-} NAMED;
-
-typedef struct {
-  NAMED **v;
-  size_t size;
-  size_t used;
-  size_t usedLim;
-} HASH_TABLE;
-
-NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize);
-void hashTableInit(HASH_TABLE *);
-void hashTableDestroy(HASH_TABLE *);
-
-typedef struct {
-  NAMED **p;
-  NAMED **end;
-} HASH_TABLE_ITER;
-
-void hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
-NAMED *hashTableIterNext(HASH_TABLE_ITER *);
Index: protocols/jabber/iasciitab.h
===================================================================
--- protocols/jabber/iasciitab.h	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,63 +1,0 @@
-/*
-The contents of this file are subject to the Mozilla Public License
-Version 1.1 (the "License"); you may not use this file except in
-compliance with the License. You may obtain a copy of the License at
-http://www.mozilla.org/MPL/
-
-Software distributed under the License is distributed on an "AS IS"
-basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
-License for the specific language governing rights and limitations
-under the License.
-
-The Original Code is expat.
-
-The Initial Developer of the Original Code is James Clark.
-Portions created by James Clark are Copyright (C) 1998, 1999
-James Clark. All Rights Reserved.
-
-Contributor(s):
-
-Alternatively, the contents of this file may be used under the terms
-of the GNU General Public License (the "GPL"), in which case the
-provisions of the GPL are applicable instead of those above.  If you
-wish to allow use of your version of this file only under the terms of
-the GPL and not to allow others to use your version of this file under
-the MPL, indicate your decision by deleting the provisions above and
-replace them with the notice and other provisions required by the
-GPL. If you do not delete the provisions above, a recipient may use
-your version of this file under either the MPL or the GPL.
-*/
-
-/* Like asciitab.h, except that 0xD has code BT_S rather than BT_CR */
-/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
-/* 0x0C */ BT_NONXML, BT_S, BT_NONXML, BT_NONXML,
-/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
-/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
-/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
-/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
-/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
-/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
-/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
-/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
-/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
-/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
-/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
-/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
-/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
-/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
-/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
-/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
Index: protocols/jabber/io.c
===================================================================
--- protocols/jabber/io.c	(revision 0fd8559c4a6ad84ad0852e07c4ba2e50b2fdf0ad)
+++ protocols/jabber/io.c	(revision 0fd8559c4a6ad84ad0852e07c4ba2e50b2fdf0ad)
@@ -0,0 +1,550 @@
+/***************************************************************************\
+*                                                                           *
+*  BitlBee - An IRC to IM gateway                                           *
+*  Jabber module - I/O stuff (plain, SSL), queues, etc                      *
+*                                                                           *
+*  Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net>                   *
+*                                                                           *
+*  This program is free software; you can redistribute it and/or modify     *
+*  it under the terms of the GNU General Public License as published by     *
+*  the Free Software Foundation; either version 2 of the License, or        *
+*  (at your option) any later version.                                      *
+*                                                                           *
+*  This program is distributed in the hope that it will be useful,          *
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
+*  GNU General Public License for more details.                             *
+*                                                                           *
+*  You should have received a copy of the GNU General Public License along  *
+*  with this program; if not, write to the Free Software Foundation, Inc.,  *
+*  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.              *
+*                                                                           *
+\***************************************************************************/
+
+#include "jabber.h"
+#include "ssl_client.h"
+
+static gboolean jabber_write_callback( gpointer data, gint fd, b_input_condition cond );
+static gboolean jabber_write_queue( struct gaim_connection *gc );
+
+int jabber_write_packet( struct gaim_connection *gc, struct xt_node *node )
+{
+	char *buf;
+	int st;
+	
+	buf = xt_to_string( node );
+	st = jabber_write( gc, buf, strlen( buf ) );
+	g_free( buf );
+	
+	return st;
+}
+
+int jabber_write( struct gaim_connection *gc, char *buf, int len )
+{
+	struct jabber_data *jd = gc->proto_data;
+	gboolean ret;
+	
+	if( jd->tx_len == 0 )
+	{
+		/* If the queue is empty, allocate a new buffer. */
+		jd->tx_len = len;
+		jd->txq = g_memdup( buf, len );
+		
+		/* Try if we can write it immediately so we don't have to do
+		   it via the event handler. If not, add the handler. (In
+		   most cases it probably won't be necessary.) */
+		if( ( ret = jabber_write_queue( gc ) ) && jd->tx_len > 0 )
+			jd->w_inpa = b_input_add( jd->fd, GAIM_INPUT_WRITE, jabber_write_callback, gc );
+	}
+	else
+	{
+		/* Just add it to the buffer if it's already filled. The
+		   event handler is already set. */
+		jd->txq = g_renew( char, jd->txq, jd->tx_len + len );
+		memcpy( jd->txq + jd->tx_len, buf, len );
+		jd->tx_len += len;
+		
+		/* The return value for write() doesn't necessarily mean
+		   that everything got sent, it mainly means that the
+		   connection (officially) still exists and can still
+		   be accessed without hitting SIGSEGV. IOW: */
+		ret = TRUE;
+	}
+	
+	return ret;
+}
+
+/* Splitting up in two separate functions: One to use as a callback and one
+   to use in the function above to escape from having to wait for the event
+   handler to call us, if possible.
+   
+   Two different functions are necessary because of the return values: The
+   callback should only return TRUE if the write was successful AND if the
+   buffer is not empty yet (ie. if the handler has to be called again when
+   the socket is ready for more data). */
+static gboolean jabber_write_callback( gpointer data, gint fd, b_input_condition cond )
+{
+	struct jabber_data *jd = ((struct gaim_connection *)data)->proto_data;
+	
+	return jd->fd != -1 &&
+	       jabber_write_queue( data ) &&
+	       jd->tx_len > 0;
+}
+
+static gboolean jabber_write_queue( struct gaim_connection *gc )
+{
+	struct jabber_data *jd = gc->proto_data;
+	int st;
+	
+	if( jd->ssl )
+		st = ssl_write( jd->ssl, jd->txq, jd->tx_len );
+	else
+		st = write( jd->fd, jd->txq, jd->tx_len );
+	
+	if( st == jd->tx_len )
+	{
+		/* We wrote everything, clear the buffer. */
+		g_free( jd->txq );
+		jd->txq = NULL;
+		jd->tx_len = 0;
+		
+		return TRUE;
+	}
+	else if( st == 0 || ( st < 0 && !sockerr_again() ) )
+	{
+		/* Set fd to -1 to make sure we won't write to it anymore. */
+		closesocket( jd->fd );	/* Shouldn't be necessary after errors? */
+		jd->fd = -1;
+		
+		hide_login_progress_error( gc, "Short write() to server" );
+		signoff( gc );
+		return FALSE;
+	}
+	else if( st > 0 )
+	{
+		char *s;
+		
+		s = g_memdup( jd->txq + st, jd->tx_len - st );
+		jd->tx_len -= st;
+		g_free( jd->txq );
+		jd->txq = s;
+		
+		return TRUE;
+	}
+	else
+	{
+		/* Just in case we had EINPROGRESS/EAGAIN: */
+		
+		return TRUE;
+	}
+}
+
+static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition cond )
+{
+	struct gaim_connection *gc = data;
+	struct jabber_data *jd = gc->proto_data;
+	char buf[512];
+	int st;
+	
+	if( jd->fd == -1 )
+		return FALSE;
+	
+	if( jd->ssl )
+		st = ssl_read( jd->ssl, buf, sizeof( buf ) );
+	else
+		st = read( jd->fd, buf, sizeof( buf ) );
+	
+	if( st > 0 )
+	{
+		/* Parse. */
+		if( xt_feed( jd->xt, buf, st ) < 0 )
+		{
+			hide_login_progress_error( gc, "XML stream error" );
+			signoff( gc );
+			return FALSE;
+		}
+		
+		/* Execute all handlers. */
+		if( !xt_handle( jd->xt, NULL, 1 ) )
+		{
+			/* Don't do anything, the handlers should have
+			   aborted the connection already. */
+			return FALSE;
+		}
+		
+		if( jd->flags & JFLAG_STREAM_RESTART )
+		{
+			jd->flags &= ~JFLAG_STREAM_RESTART;
+			jabber_start_stream( gc );
+		}
+		
+		/* Garbage collection. */
+		xt_cleanup( jd->xt, NULL, 1 );
+		
+		/* This is a bit hackish, unfortunately. Although xmltree
+		   has nifty event handler stuff, it only calls handlers
+		   when nodes are complete. Since the server should only
+		   send an opening <stream:stream> tag, we have to check
+		   this by hand. :-( */
+		if( !( jd->flags & JFLAG_STREAM_STARTED ) && jd->xt && jd->xt->root )
+		{
+			if( g_strcasecmp( jd->xt->root->name, "stream:stream" ) == 0 )
+			{
+				jd->flags |= JFLAG_STREAM_STARTED;
+				
+				/* If there's no version attribute, assume
+				   this is an old server that can't do SASL
+				   authentication. */
+				if( !sasl_supported( gc ) )
+				{
+					/* If there's no version= tag, we suppose
+					   this server does NOT implement: XMPP 1.0,
+					   SASL and TLS. */
+					if( set_getbool( &gc->acc->set, "tls" ) )
+					{
+						hide_login_progress( gc, "TLS is turned on for this "
+						          "account, but is not supported by this server" );
+						signoff( gc );
+						return FALSE;
+					}
+					else
+					{
+						return jabber_init_iq_auth( gc );
+					}
+				}
+			}
+			else
+			{
+				hide_login_progress( gc, "XML stream error" );
+				signoff( gc );
+				return FALSE;
+			}
+		}
+	}
+	else if( st == 0 || ( st < 0 && !sockerr_again() ) )
+	{
+		closesocket( jd->fd );
+		jd->fd = -1;
+		
+		hide_login_progress_error( gc, "Error while reading from server" );
+		signoff( gc );
+		return FALSE;
+	}
+	
+	/* EAGAIN/etc or a successful read. */
+	return TRUE;
+}
+
+gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition cond )
+{
+	struct gaim_connection *gc = data;
+	
+	if( source == -1 )
+	{
+		hide_login_progress( gc, "Could not connect to server" );
+		signoff( gc );
+		return FALSE;
+	}
+	
+	set_login_progress( gc, 1, "Connected to server, logging in" );
+	
+	return jabber_start_stream( gc );
+}
+
+gboolean jabber_connected_ssl( gpointer data, void *source, b_input_condition cond )
+{
+	struct gaim_connection *gc = data;
+	struct jabber_data *jd = gc->proto_data;
+	
+	if( source == NULL )
+	{
+		/* The SSL connection will be cleaned up by the SSL lib
+		   already, set it to NULL here to prevent a double cleanup: */
+		jd->ssl = NULL;
+		
+		hide_login_progress( gc, "Could not connect to server" );
+		signoff( gc );
+		return FALSE;
+	}
+	
+	set_login_progress( gc, 1, "Connected to server, logging in" );
+	
+	return jabber_start_stream( gc );
+}
+
+static xt_status jabber_end_of_stream( struct xt_node *node, gpointer data )
+{
+	signoff( data );
+	return XT_ABORT;
+}
+
+static xt_status jabber_pkt_features( struct xt_node *node, gpointer data )
+{
+	struct gaim_connection *gc = data;
+	struct jabber_data *jd = gc->proto_data;
+	struct xt_node *c, *reply;
+	int trytls;
+	
+	trytls = g_strcasecmp( set_getstr( &gc->acc->set, "tls" ), "try" ) == 0;
+	c = xt_find_node( node->children, "starttls" );
+	if( c && !jd->ssl )
+	{
+		/* If the server advertises the STARTTLS feature and if we're
+		   not in a secure connection already: */
+		
+		c = xt_find_node( c->children, "required" );
+		
+		if( c && ( !trytls && !set_getbool( &gc->acc->set, "tls" ) ) )
+		{
+			hide_login_progress( gc, "Server requires TLS connections, but TLS is turned off for this account" );
+			signoff( gc );
+			
+			return XT_ABORT;
+		}
+		
+		/* Only run this if the tls setting is set to true or try: */
+		if( ( trytls || set_getbool( &gc->acc->set, "tls" ) ) )
+		{
+			reply = xt_new_node( "starttls", NULL, NULL );
+			xt_add_attr( reply, "xmlns", XMLNS_TLS );
+			if( !jabber_write_packet( gc, reply ) )
+			{
+				xt_free_node( reply );
+				return XT_ABORT;
+			}
+			xt_free_node( reply );
+			
+			return XT_HANDLED;
+		}
+	}
+	else if( !c && !jd->ssl )
+	{
+		/* If the server does not advertise the STARTTLS feature and
+		   we're not in a secure connection already: (Servers have a
+		   habit of not advertising <starttls/> anymore when already
+		   using SSL/TLS. */
+		
+		if( !trytls && set_getbool( &gc->acc->set, "tls" ) )
+		{
+			hide_login_progress( gc, "TLS is turned on for this account, but is not supported by this server" );
+			signoff( gc );
+			
+			return XT_ABORT;
+		}
+	}
+	
+	/* This one used to be in jabber_handlers[], but it has to be done
+	   from here to make sure the TLS session will be initialized
+	   properly before we attempt SASL authentication. */
+	if( ( c = xt_find_node( node->children, "mechanisms" ) ) )
+	{
+		if( sasl_pkt_mechanisms( c, data ) == XT_ABORT )
+			return XT_ABORT;
+	}
+	/* If the server *SEEMS* to support SASL authentication but doesn't
+	   support it after all, we should try to do authentication the
+	   other way. jabber.com doesn't seem to do SASL while it pretends
+	   to be XMPP 1.0 compliant! */
+	else if( !( jd->flags & JFLAG_AUTHENTICATED ) && sasl_supported( gc ) )
+	{
+		if( !jabber_init_iq_auth( gc ) )
+			return XT_ABORT;
+	}
+	
+	if( ( c = xt_find_node( node->children, "bind" ) ) )
+	{
+		reply = xt_new_node( "bind", NULL, xt_new_node( "resource", set_getstr( &gc->acc->set, "resource" ), NULL ) );
+		xt_add_attr( reply, "xmlns", XMLNS_BIND );
+		reply = jabber_make_packet( "iq", "set", NULL, reply );
+		jabber_cache_add( gc, reply, jabber_pkt_bind_sess );
+		
+		if( !jabber_write_packet( gc, reply ) )
+			return XT_ABORT;
+		
+		jd->flags |= JFLAG_WAIT_BIND;
+	}
+	
+	if( ( c = xt_find_node( node->children, "session" ) ) )
+	{
+		reply = xt_new_node( "session", NULL, NULL );
+		xt_add_attr( reply, "xmlns", XMLNS_SESSION );
+		reply = jabber_make_packet( "iq", "set", NULL, reply );
+		jabber_cache_add( gc, reply, jabber_pkt_bind_sess );
+		
+		if( !jabber_write_packet( gc, reply ) )
+			return XT_ABORT;
+		
+		jd->flags |= JFLAG_WAIT_SESSION;
+	}
+	
+	/* This flag is already set if we authenticated via SASL, so now
+	   we can resume the session in the new stream, if we don't have
+	   to bind/initialize the session. */
+	if( jd->flags & JFLAG_AUTHENTICATED && ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 )
+	{
+		if( !jabber_get_roster( gc ) )
+			return XT_ABORT;
+	}
+	
+	return XT_HANDLED;
+}
+
+static xt_status jabber_pkt_proceed_tls( struct xt_node *node, gpointer data )
+{
+	struct gaim_connection *gc = data;
+	struct jabber_data *jd = gc->proto_data;
+	char *xmlns;
+	
+	xmlns = xt_find_attr( node, "xmlns" );
+	
+	/* Just ignore it when it doesn't seem to be TLS-related (is that at
+	   all possible??). */
+	if( !xmlns || strcmp( xmlns, XMLNS_TLS ) != 0 )
+		return XT_HANDLED;
+	
+	/* We don't want event handlers to touch our TLS session while it's
+	   still initializing! */
+	b_event_remove( jd->r_inpa );
+	if( jd->tx_len > 0 )
+	{
+		/* Actually the write queue should be empty here, but just
+		   to be sure... */
+		b_event_remove( jd->w_inpa );
+		g_free( jd->txq );
+		jd->txq = NULL;
+		jd->tx_len = 0;
+	}
+	jd->w_inpa = jd->r_inpa = 0;
+	
+	set_login_progress( gc, 1, "Converting stream to TLS" );
+	
+	jd->ssl = ssl_starttls( jd->fd, jabber_connected_ssl, gc );
+	
+	return XT_HANDLED;
+}
+
+static xt_status jabber_pkt_stream_error( struct xt_node *node, gpointer data )
+{
+	struct gaim_connection *gc = data;
+	struct xt_node *c;
+	char *s, *type = NULL, *text = NULL;
+	
+	for( c = node->children; c; c = c->next )
+	{
+		if( !( s = xt_find_attr( c, "xmlns" ) ) ||
+		    strcmp( s, XMLNS_STREAM_ERROR ) != 0 )
+			continue;
+		
+		if( strcmp( c->name, "text" ) != 0 )
+		{
+			type = c->name;
+		}
+		/* Only use the text if it doesn't have an xml:lang attribute,
+		   if it's empty or if it's set to something English. */
+		else if( !( s = xt_find_attr( c, "xml:lang" ) ) ||
+		         !*s || strncmp( s, "en", 2 ) == 0 )
+		{
+			text = c->text;
+		}
+	}
+	
+	/* Tssk... */
+	if( type == NULL )
+	{
+		hide_login_progress_error( gc, "Unknown stream error reported by server" );
+		signoff( gc );
+		return XT_ABORT;
+	}
+	
+	/* We know that this is a fatal error. If it's a "conflict" error, we
+	   should turn off auto-reconnect to make sure we won't get some nasty
+	   infinite loop! */
+	if( strcmp( type, "conflict" ) == 0 )
+	{
+		hide_login_progress( gc, "Account and resource used from a different location" );
+		gc->wants_to_die = TRUE;
+	}
+	else
+	{
+		s = g_strdup_printf( "Stream error: %s%s%s", type, text ? ": " : "", text ? text : "" );
+		hide_login_progress_error( gc, s );
+		g_free( s );
+	}
+	
+	signoff( gc );
+	
+	return XT_ABORT;
+}
+
+static xt_status jabber_pkt_misc( struct xt_node *node, gpointer data )
+{
+	printf( "Received unknown packet:\n" );
+	xt_print( node );
+	
+	return XT_HANDLED;
+}
+
+static const struct xt_handler_entry jabber_handlers[] = {
+	{ "stream:stream",      "<root>",               jabber_end_of_stream },
+	{ "message",            "stream:stream",        jabber_pkt_message },
+	{ "presence",           "stream:stream",        jabber_pkt_presence },
+	{ "iq",                 "stream:stream",        jabber_pkt_iq },
+	{ "stream:features",    "stream:stream",        jabber_pkt_features },
+	{ "stream:error",       "stream:stream",        jabber_pkt_stream_error },
+	{ "proceed",            "stream:stream",        jabber_pkt_proceed_tls },
+	{ "challenge",          "stream:stream",        sasl_pkt_challenge },
+	{ "success",            "stream:stream",        sasl_pkt_result },
+	{ "failure",            "stream:stream",        sasl_pkt_result },
+	{ NULL,                 "stream:stream",        jabber_pkt_misc },
+	{ NULL,                 NULL,                   NULL }
+};
+
+gboolean jabber_start_stream( struct gaim_connection *gc )
+{
+	struct jabber_data *jd = gc->proto_data;
+	int st;
+	char *greet;
+	
+	/* We'll start our stream now, so prepare everything to receive one
+	   from the server too. */
+	xt_free( jd->xt );	/* In case we're RE-starting. */
+	jd->xt = xt_new( gc );
+	jd->xt->handlers = (struct xt_handler_entry*) jabber_handlers;
+	
+	if( jd->r_inpa <= 0 )
+		jd->r_inpa = b_input_add( jd->fd, GAIM_INPUT_READ, jabber_read_callback, gc );
+	
+	greet = g_strdup_printf( "<?xml version='1.0' ?>"
+	                         "<stream:stream to=\"%s\" xmlns=\"jabber:client\" "
+	                          "xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\">", jd->server );
+	
+	st = jabber_write( gc, greet, strlen( greet ) );
+	
+	g_free( greet );
+	
+	return st;
+}
+
+void jabber_end_stream( struct gaim_connection *gc )
+{
+	struct jabber_data *jd = gc->proto_data;
+	
+	/* Let's only do this if the queue is currently empty, otherwise it'd
+	   take too long anyway. */
+	if( jd->tx_len == 0 )
+	{
+		char eos[] = "</stream:stream>";
+		struct xt_node *node;
+		int st = 1;
+		
+		if( gc->flags & OPT_LOGGED_IN )
+		{
+			node = jabber_make_packet( "presence", "unavailable", NULL, NULL );
+			st = jabber_write_packet( gc, node );
+			xt_free_node( node );
+		}
+		
+		if( st )
+			jabber_write( gc, eos, strlen( eos ) );
+	}
+}
Index: protocols/jabber/iq.c
===================================================================
--- protocols/jabber/iq.c	(revision 0fd8559c4a6ad84ad0852e07c4ba2e50b2fdf0ad)
+++ protocols/jabber/iq.c	(revision 0fd8559c4a6ad84ad0852e07c4ba2e50b2fdf0ad)
@@ -0,0 +1,585 @@
+/***************************************************************************\
+*                                                                           *
+*  BitlBee - An IRC to IM gateway                                           *
+*  Jabber module - IQ packets                                               *
+*                                                                           *
+*  Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net>                   *
+*                                                                           *
+*  This program is free software; you can redistribute it and/or modify     *
+*  it under the terms of the GNU General Public License as published by     *
+*  the Free Software Foundation; either version 2 of the License, or        *
+*  (at your option) any later version.                                      *
+*                                                                           *
+*  This program is distributed in the hope that it will be useful,          *
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
+*  GNU General Public License for more details.                             *
+*                                                                           *
+*  You should have received a copy of the GNU General Public License along  *
+*  with this program; if not, write to the Free Software Foundation, Inc.,  *
+*  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.              *
+*                                                                           *
+\***************************************************************************/
+
+#include "jabber.h"
+
+static xt_status jabber_parse_roster( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig );
+static xt_status jabber_iq_display_vcard( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig );
+
+xt_status jabber_pkt_iq( struct xt_node *node, gpointer data )
+{
+	struct gaim_connection *gc = data;
+	struct jabber_data *jd = gc->proto_data;
+	struct xt_node *c, *reply = NULL;
+	char *type, *s;
+	int st, pack = 1;
+	
+	type = xt_find_attr( node, "type" );
+	
+	if( !type )
+	{
+		hide_login_progress_error( gc, "Received IQ packet without type." );
+		signoff( gc );
+		return XT_ABORT;
+	}
+	
+	if( strcmp( type, "result" ) == 0 || strcmp( type, "error" ) == 0 )
+	{
+		struct jabber_cache_entry *entry;
+		
+		if( ( s = xt_find_attr( node, "id" ) ) == NULL ||
+		    strncmp( s, JABBER_CACHED_ID, strlen( JABBER_CACHED_ID ) ) != 0 )
+		{
+			/* Silently ignore it, without an ID (or a non-cache
+			   ID) we don't know how to handle the packet and we
+			   probably don't have to. */
+			return XT_HANDLED;
+		}
+		
+		entry = g_hash_table_lookup( jd->node_cache, s );
+		
+		if( entry == NULL )
+			serv_got_crap( gc, "WARNING: Received IQ-%s packet with unknown/expired ID %s!", type, s );
+		else if( entry->func )
+			return entry->func( gc, node, entry->node );
+	}
+	else if( strcmp( type, "get" ) == 0 )
+	{
+		if( !( c = xt_find_node( node->children, "query" ) ) ||
+		    !( s = xt_find_attr( c, "xmlns" ) ) )
+		{
+			serv_got_crap( gc, "WARNING: Received incomplete IQ-%s packet", type );
+			return XT_HANDLED;
+		}
+		
+		reply = xt_new_node( "query", NULL, NULL );
+		xt_add_attr( reply, "xmlns", s );
+		
+		/* Of course this is a very essential query to support. ;-) */
+		if( strcmp( s, XMLNS_VERSION ) == 0 )
+		{
+			xt_add_child( reply, xt_new_node( "name", "BitlBee", NULL ) );
+			xt_add_child( reply, xt_new_node( "version", BITLBEE_VERSION, NULL ) );
+			xt_add_child( reply, xt_new_node( "os", ARCH, NULL ) );
+		}
+		else if( strcmp( s, XMLNS_TIME ) == 0 )
+		{
+			time_t time_ep;
+			char buf[1024];
+			
+			buf[sizeof(buf)-1] = 0;
+			time_ep = time( NULL );
+			
+			strftime( buf, sizeof( buf ) - 1, "%Y%m%dT%H:%M:%S", gmtime( &time_ep ) );
+			xt_add_child( reply, xt_new_node( "utc", buf, NULL ) );
+			
+			strftime( buf, sizeof( buf ) - 1, "%Z", localtime( &time_ep ) );
+			xt_add_child( reply, xt_new_node( "tz", buf, NULL ) );
+		}
+		else if( strcmp( s, XMLNS_DISCOVER ) == 0 )
+		{
+			c = xt_new_node( "identity", NULL, NULL );
+			xt_add_attr( c, "category", "client" );
+			xt_add_attr( c, "type", "pc" );
+			xt_add_attr( c, "name", "BitlBee" );
+			xt_add_child( reply, c );
+			
+			c = xt_new_node( "feature", NULL, NULL );
+			xt_add_attr( c, "var", XMLNS_VERSION );
+			xt_add_child( reply, c );
+			
+			c = xt_new_node( "feature", NULL, NULL );
+			xt_add_attr( c, "var", XMLNS_TIME );
+			xt_add_child( reply, c );
+			
+			c = xt_new_node( "feature", NULL, NULL );
+			xt_add_attr( c, "var", XMLNS_CHATSTATES );
+			xt_add_child( reply, c );
+			
+			/* Later this can be useful to announce things like
+			   MUC support. */
+		}
+		else
+		{
+			xt_free_node( reply );
+			reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel" );
+			pack = 0;
+		}
+	}
+	else if( strcmp( type, "set" ) == 0 )
+	{
+		if( !( c = xt_find_node( node->children, "query" ) ) ||
+		    !( s = xt_find_attr( c, "xmlns" ) ) )
+		{
+			serv_got_crap( gc, "WARNING: Received incomplete IQ-%s packet", type );
+			return XT_HANDLED;
+		}
+		
+		/* This is a roster push. XMPP servers send this when someone
+		   was added to (or removed from) the buddy list. AFAIK they're
+		   sent even if we added this buddy in our own session. */
+		if( strcmp( s, XMLNS_ROSTER ) == 0 )
+		{
+			int bare_len = strlen( gc->acc->user );
+			
+			if( ( s = xt_find_attr( node, "from" ) ) == NULL ||
+			    ( strncmp( s, gc->acc->user, bare_len ) == 0 &&
+			      ( s[bare_len] == 0 || s[bare_len] == '/' ) ) )
+			{
+				jabber_parse_roster( gc, node, NULL );
+				
+				/* Should we generate a reply here? Don't think it's
+				   very important... */
+			}
+			else
+			{
+				serv_got_crap( gc, "WARNING: %s tried to fake a roster push!", s ? s : "(unknown)" );
+				
+				xt_free_node( reply );
+				reply = jabber_make_error_packet( node, "not-allowed", "cancel" );
+				pack = 0;
+			}
+		}
+		else
+		{
+			xt_free_node( reply );
+			reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel" );
+			pack = 0;
+		}
+	}
+	
+	/* If we recognized the xmlns and managed to generate a reply,
+	   finish and send it. */
+	if( reply )
+	{
+		/* Normally we still have to pack it into an iq-result
+		   packet, but for errors, for example, we don't. */
+		if( pack )
+		{
+			reply = jabber_make_packet( "iq", "result", xt_find_attr( node, "from" ), reply );
+			if( ( s = xt_find_attr( node, "id" ) ) )
+				xt_add_attr( reply, "id", s );
+		}
+		
+		st = jabber_write_packet( gc, reply );
+		xt_free_node( reply );
+		if( !st )
+			return XT_ABORT;
+	}
+	
+	return XT_HANDLED;
+}
+
+static xt_status jabber_do_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig );
+static xt_status jabber_finish_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig );
+
+int jabber_init_iq_auth( struct gaim_connection *gc )
+{
+	struct jabber_data *jd = gc->proto_data;
+	struct xt_node *node;
+	int st;
+	
+	node = xt_new_node( "query", NULL, xt_new_node( "username", jd->username, NULL ) );
+	xt_add_attr( node, "xmlns", XMLNS_AUTH );
+	node = jabber_make_packet( "iq", "get", NULL, node );
+	
+	jabber_cache_add( gc, node, jabber_do_iq_auth );
+	st = jabber_write_packet( gc, node );
+	
+	return st;
+}
+
+static xt_status jabber_do_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig )
+{
+	struct jabber_data *jd = gc->proto_data;
+	struct xt_node *reply, *query;
+	xt_status st;
+	char *s;
+	
+	if( !( query = xt_find_node( node->children, "query" ) ) )
+	{
+		serv_got_crap( gc, "WARNING: Received incomplete IQ packet while authenticating" );
+		signoff( gc );
+		return XT_HANDLED;
+	}
+	
+	/* Time to authenticate ourselves! */
+	reply = xt_new_node( "query", NULL, NULL );
+	xt_add_attr( reply, "xmlns", XMLNS_AUTH );
+	xt_add_child( reply, xt_new_node( "username", jd->username, NULL ) );
+	xt_add_child( reply, xt_new_node( "resource", set_getstr( &gc->acc->set, "resource" ), NULL ) );
+	
+	if( xt_find_node( query->children, "digest" ) && ( s = xt_find_attr( jd->xt->root, "id" ) ) )
+	{
+		/* We can do digest authentication, it seems, and of
+		   course we prefer that. */
+		SHA_CTX sha;
+		char hash_hex[41];
+		unsigned char hash[20];
+		int i;
+		
+		shaInit( &sha );
+		shaUpdate( &sha, (unsigned char*) s, strlen( s ) );
+		shaUpdate( &sha, (unsigned char*) gc->acc->pass, strlen( gc->acc->pass ) );
+		shaFinal( &sha, hash );
+		
+		for( i = 0; i < 20; i ++ )
+			sprintf( hash_hex + i * 2, "%02x", hash[i] );
+		
+		xt_add_child( reply, xt_new_node( "digest", hash_hex, NULL ) );
+	}
+	else if( xt_find_node( query->children, "password" ) )
+	{
+		/* We'll have to stick with plaintext. Let's hope we're using SSL/TLS... */
+		xt_add_child( reply, xt_new_node( "password", gc->acc->pass, NULL ) );
+	}
+	else
+	{
+		xt_free_node( reply );
+		
+		hide_login_progress( gc, "Can't find suitable authentication method" );
+		signoff( gc );
+		return XT_ABORT;
+	}
+	
+	reply = jabber_make_packet( "iq", "set", NULL, reply );
+	jabber_cache_add( gc, reply, jabber_finish_iq_auth );
+	st = jabber_write_packet( gc, reply );
+	
+	return st ? XT_HANDLED : XT_ABORT;
+}
+
+static xt_status jabber_finish_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig )
+{
+	struct jabber_data *jd = gc->proto_data;
+	char *type;
+	
+	if( !( type = xt_find_attr( node, "type" ) ) )
+	{
+		serv_got_crap( gc, "WARNING: Received incomplete IQ packet while authenticating" );
+		signoff( gc );
+		return XT_HANDLED;
+	}
+	
+	if( strcmp( type, "error" ) == 0 )
+	{
+		hide_login_progress( gc, "Authentication failure" );
+		signoff( gc );
+		return XT_ABORT;
+	}
+	else if( strcmp( type, "result" ) == 0 )
+	{
+		/* This happens when we just successfully authenticated the
+		   old (non-SASL) way. */
+		jd->flags |= JFLAG_AUTHENTICATED;
+		if( !jabber_get_roster( gc ) )
+			return XT_ABORT;
+	}
+	
+	return XT_HANDLED;
+}
+
+xt_status jabber_pkt_bind_sess( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig )
+{
+	struct jabber_data *jd = gc->proto_data;
+	struct xt_node *c;
+	char *s;
+	
+	if( ( c = xt_find_node( node->children, "bind" ) ) )
+	{
+		c = xt_find_node( c->children, "jid" );
+		if( c && c->text_len && ( s = strchr( c->text, '/' ) ) &&
+		    strcmp( s + 1, set_getstr( &gc->acc->set, "resource" ) ) != 0 )
+			serv_got_crap( gc, "Server changed session resource string to `%s'", s + 1 );
+		
+		jd->flags &= ~JFLAG_WAIT_BIND;
+	}
+	else
+	{
+		jd->flags &= ~JFLAG_WAIT_SESSION;
+	}
+	
+	if( ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 )
+	{
+		if( !jabber_get_roster( gc ) )
+			return XT_ABORT;
+	}
+	
+	return XT_HANDLED;
+}
+
+int jabber_get_roster( struct gaim_connection *gc )
+{
+	struct xt_node *node;
+	int st;
+	
+	set_login_progress( gc, 1, "Authenticated, requesting buddy list" );
+	
+	node = xt_new_node( "query", NULL, NULL );
+	xt_add_attr( node, "xmlns", XMLNS_ROSTER );
+	node = jabber_make_packet( "iq", "get", NULL, node );
+	
+	jabber_cache_add( gc, node, jabber_parse_roster );
+	st = jabber_write_packet( gc, node );
+	
+	return st;
+}
+
+static xt_status jabber_parse_roster( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig )
+{
+	struct xt_node *query, *c;
+	int initial = ( orig != NULL );
+	
+	if( !( query = xt_find_node( node->children, "query" ) ) )
+	{
+		serv_got_crap( gc, "WARNING: Received NULL roster packet" );
+		return XT_HANDLED;
+	}
+	
+	c = query->children;
+	while( ( c = xt_find_node( c, "item" ) ) )
+	{
+		char *jid = xt_find_attr( c, "jid" );
+		char *name = xt_find_attr( c, "name" );
+		char *sub = xt_find_attr( c, "subscription" );
+		
+		if( !jid || !sub )
+		{
+			/* Maybe warn. But how likely is this to happen in the first place? */
+		}
+		else if( initial )
+		{
+			if( ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) )
+				add_buddy( gc, NULL, jid, name );
+		}
+		else
+		{
+			/* This is a roster push item. Find out what changed exactly. */
+			if( ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) )
+			{
+				if( find_buddy( gc, jid ) == NULL )
+					add_buddy( gc, NULL, jid, name );
+				else if( name )
+					serv_buddy_rename( gc, jid, name );
+			}
+			else if( strcmp( sub, "remove" ) == 0 )
+			{
+				/* Don't have any API call for this yet! So let's
+				   just try to handle this as well as we can. */
+				jabber_buddy_remove_bare( gc, jid );
+				serv_got_update( gc, jid, 0, 0, 0, 0, 0, 0 );
+				/* FIXME! */
+			}
+		}
+		
+		c = c->next;
+	}
+	
+	if( initial )
+		account_online( gc );
+	
+	return XT_HANDLED;
+}
+
+int jabber_get_vcard( struct gaim_connection *gc, char *bare_jid )
+{
+	struct xt_node *node;
+	
+	if( strchr( bare_jid, '/' ) )
+		return 1;	/* This was an error, but return 0 should only be done if the connection died... */
+	
+	node = xt_new_node( "vCard", NULL, NULL );
+	xt_add_attr( node, "xmlns", XMLNS_VCARD );
+	node = jabber_make_packet( "iq", "get", bare_jid, node );
+	
+	jabber_cache_add( gc, node, jabber_iq_display_vcard );
+	return jabber_write_packet( gc, node );
+}
+
+static xt_status jabber_iq_display_vcard( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig )
+{
+	struct xt_node *vc, *c, *sc; /* subchild, gc is already in use ;-) */
+	GString *reply;
+	char *s;
+	
+	if( ( s = xt_find_attr( node, "type" ) ) == NULL ||
+	    strcmp( s, "result" ) != 0 ||
+	    ( vc = xt_find_node( node->children, "vCard" ) ) == NULL )
+	{
+		s = xt_find_attr( orig, "to" ); /* If this returns NULL something's wrong.. */
+		serv_got_crap( gc, "Could not retrieve vCard of %s", s ? s : "(NULL)" );
+		return XT_HANDLED;
+	}
+	
+	s = xt_find_attr( orig, "to" );
+	reply = g_string_new( "vCard information for " );
+	reply = g_string_append( reply, s ? s : "(NULL)" );
+	reply = g_string_append( reply, ":\n" );
+	
+	/* I hate this format, I really do... */
+	
+	if( ( c = xt_find_node( vc->children, "FN" ) ) && c->text_len )
+		g_string_append_printf( reply, "Name: %s\n", c->text );
+	
+	if( ( c = xt_find_node( vc->children, "N" ) ) && c->children )
+	{
+		reply = g_string_append( reply, "Full name:" );
+		
+		if( ( sc = xt_find_node( c->children, "PREFIX" ) ) && sc->text_len )
+			g_string_append_printf( reply, " %s", sc->text );
+		if( ( sc = xt_find_node( c->children, "GIVEN" ) ) && sc->text_len )
+			g_string_append_printf( reply, " %s", sc->text );
+		if( ( sc = xt_find_node( c->children, "MIDDLE" ) ) && sc->text_len )
+			g_string_append_printf( reply, " %s", sc->text );
+		if( ( sc = xt_find_node( c->children, "FAMILY" ) ) && sc->text_len )
+			g_string_append_printf( reply, " %s", sc->text );
+		if( ( sc = xt_find_node( c->children, "SUFFIX" ) ) && sc->text_len )
+			g_string_append_printf( reply, " %s", sc->text );
+		
+		reply = g_string_append_c( reply, '\n' );
+	}
+	
+	if( ( c = xt_find_node( vc->children, "NICKNAME" ) ) && c->text_len )
+		g_string_append_printf( reply, "Nickname: %s\n", c->text );
+	
+	if( ( c = xt_find_node( vc->children, "BDAY" ) ) && c->text_len )
+		g_string_append_printf( reply, "Date of birth: %s\n", c->text );
+	
+	/* Slightly alternative use of for... ;-) */
+	for( c = vc->children; ( c = xt_find_node( c, "EMAIL" ) ); c = c->next )
+	{
+		if( ( sc = xt_find_node( c->children, "USERID" ) ) == NULL || sc->text_len == 0 )
+			continue;
+		
+		if( xt_find_node( c->children, "HOME" ) )
+			s = "Home";
+		else if( xt_find_node( c->children, "WORK" ) )
+			s = "Work";
+		else
+			s = "Misc.";
+		
+		g_string_append_printf( reply, "%s e-mail address: %s\n", s, sc->text );
+	}
+	
+	if( ( c = xt_find_node( vc->children, "URL" ) ) && c->text_len )
+		g_string_append_printf( reply, "Homepage: %s\n", c->text );
+	
+	/* Slightly alternative use of for... ;-) */
+	for( c = vc->children; ( c = xt_find_node( c, "ADR" ) ); c = c->next )
+	{
+		if( xt_find_node( c->children, "HOME" ) )
+			s = "Home";
+		else if( xt_find_node( c->children, "WORK" ) )
+			s = "Work";
+		else
+			s = "Misc.";
+		
+		g_string_append_printf( reply, "%s address: ", s );
+		
+		if( ( sc = xt_find_node( c->children, "STREET" ) ) && sc->text_len )
+			g_string_append_printf( reply, "%s ", sc->text );
+		if( ( sc = xt_find_node( c->children, "EXTADR" ) ) && sc->text_len )
+			g_string_append_printf( reply, "%s, ", sc->text );
+		if( ( sc = xt_find_node( c->children, "PCODE" ) ) && sc->text_len )
+			g_string_append_printf( reply, "%s, ", sc->text );
+		if( ( sc = xt_find_node( c->children, "LOCALITY" ) ) && sc->text_len )
+			g_string_append_printf( reply, "%s, ", sc->text );
+		if( ( sc = xt_find_node( c->children, "REGION" ) ) && sc->text_len )
+			g_string_append_printf( reply, "%s, ", sc->text );
+		if( ( sc = xt_find_node( c->children, "CTRY" ) ) && sc->text_len )
+			g_string_append_printf( reply, "%s", sc->text );
+		
+		if( reply->str[reply->len-2] == ',' )
+			reply = g_string_truncate( reply, reply->len-2 );
+		
+		reply = g_string_append_c( reply, '\n' );
+	}
+	
+	for( c = vc->children; ( c = xt_find_node( c, "TEL" ) ); c = c->next )
+	{
+		if( ( sc = xt_find_node( c->children, "NUMBER" ) ) == NULL || sc->text_len == 0 )
+			continue;
+		
+		if( xt_find_node( c->children, "HOME" ) )
+			s = "Home";
+		else if( xt_find_node( c->children, "WORK" ) )
+			s = "Work";
+		else
+			s = "Misc.";
+		
+		g_string_append_printf( reply, "%s phone number: %s\n", s, sc->text );
+	}
+	
+	if( ( c = xt_find_node( vc->children, "DESC" ) ) && c->text_len )
+		g_string_append_printf( reply, "Other information:\n%s", c->text );
+	
+	/* *sigh* */
+	
+	serv_got_crap( gc, reply->str );
+	g_string_free( reply, TRUE );
+	
+	return XT_HANDLED;
+}
+
+int jabber_add_to_roster( struct gaim_connection *gc, char *handle, char *name )
+{
+	struct xt_node *node;
+	int st;
+	
+	/* Build the item entry */
+	node = xt_new_node( "item", NULL, NULL );
+	xt_add_attr( node, "jid", handle );
+	if( name )
+		xt_add_attr( node, "name", name );
+	
+	/* And pack it into a roster-add packet */
+	node = xt_new_node( "query", NULL, node );
+	xt_add_attr( node, "xmlns", XMLNS_ROSTER );
+	node = jabber_make_packet( "iq", "set", NULL, node );
+	
+	st = jabber_write_packet( gc, node );
+	
+	xt_free_node( node );
+	return st;
+}
+
+int jabber_remove_from_roster( struct gaim_connection *gc, char *handle )
+{
+	struct xt_node *node;
+	int st;
+	
+	/* Build the item entry */
+	node = xt_new_node( "item", NULL, NULL );
+	xt_add_attr( node, "jid", handle );
+	xt_add_attr( node, "subscription", "remove" );
+	
+	/* And pack it into a roster-add packet */
+	node = xt_new_node( "query", NULL, node );
+	xt_add_attr( node, "xmlns", XMLNS_ROSTER );
+	node = jabber_make_packet( "iq", "set", NULL, node );
+	
+	st = jabber_write_packet( gc, node );
+	
+	xt_free_node( node );
+	return st;
+}
Index: protocols/jabber/jabber.c
===================================================================
--- protocols/jabber/jabber.c	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ protocols/jabber/jabber.c	(revision 0fd8559c4a6ad84ad0852e07c4ba2e50b2fdf0ad)
@@ -1,1500 +1,37 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * gaim
- *
- * Some code copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
- * libfaim code copyright 1998, 1999 Adam Fritzler <afritz@auk.cx>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#ifndef _WIN32
-#include <sys/utsname.h>
-#endif
-#include <errno.h>
+/***************************************************************************\
+*                                                                           *
+*  BitlBee - An IRC to IM gateway                                           *
+*  Jabber module - Main file                                                *
+*                                                                           *
+*  Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net>                   *
+*                                                                           *
+*  This program is free software; you can redistribute it and/or modify     *
+*  it under the terms of the GNU General Public License as published by     *
+*  the Free Software Foundation; either version 2 of the License, or        *
+*  (at your option) any later version.                                      *
+*                                                                           *
+*  This program is distributed in the hope that it will be useful,          *
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
+*  GNU General Public License for more details.                             *
+*                                                                           *
+*  You should have received a copy of the GNU General Public License along  *
+*  with this program; if not, write to the Free Software Foundation, Inc.,  *
+*  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.              *
+*                                                                           *
+\***************************************************************************/
+
+#include <glib.h>
 #include <string.h>
-#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
 #include <stdio.h>
-#include <time.h>
-#include <sys/stat.h>
+
+#include "ssl_client.h"
+#include "xmltree.h"
+#include "bitlbee.h"
 #include "jabber.h"
-#include "nogaim.h"
-#include "bitlbee.h"
-#include "proxy.h"
-#include "ssl_client.h"
-
-/* The priv member of gjconn's is a gaim_connection for now. */
-#define GJ_GC(x) ((struct gaim_connection *)(x)->priv)
-
-#define IQID_AUTH "__AUTH__"
-
-#define IQ_NONE -1
-#define IQ_AUTH 0
-#define IQ_ROSTER 1
-
-#define UC_AWAY (0x02 | UC_UNAVAILABLE)
-#define UC_CHAT  0x04
-#define UC_XA   (0x08 | UC_UNAVAILABLE)
-#define UC_DND  (0x10 | UC_UNAVAILABLE)
-
-#define DEFAULT_SERVER "jabber.org"
-#define DEFAULT_GROUPCHAT "conference.jabber.org"
-#define DEFAULT_PORT 5222
-#define DEFAULT_PORT_SSL 5223
-#define JABBER_PORT_MIN 5220
-#define JABBER_PORT_MAX 5229
-
-#define JABBER_GROUP "Friends"
-
-/* i18n disabled - Bitlbee */
-#define N_(String) String
-
-/*
- * Note: "was_connected" may seem redundant, but it was needed and I
- * didn't want to touch the Jabber state stuff not specific to Gaim.
- */
-typedef struct gjconn_struct {
-	/* Core structure */
-	pool p;			/* Memory allocation pool */
-	int state;		/* Connection state flag */
-	int was_connected;	/* We were once connected */
-	int fd;			/* Connection file descriptor */
-	void *ssl;		/* SSL connection */
-	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.. */
-
-	/* Event callback ptrs */
-	void (*on_state)(struct gjconn_struct *gjc, int state);
-	void (*on_packet)(struct gjconn_struct *gjc, jpacket p);
-
-	GHashTable *queries;	/* query tracker */
-
-	void *priv;
-} *gjconn, gjconn_struct;
-
-typedef void (*gjconn_state_h)(gjconn gjc, int state);
-typedef void (*gjconn_packet_h)(gjconn gjc, jpacket p);
-
-static gjconn gjab_new(char *user, char *pass, void *priv);
-static void gjab_delete(gjconn gjc);
-static void gjab_state_handler(gjconn gjc, gjconn_state_h h);
-static void gjab_packet_handler(gjconn gjc, gjconn_packet_h h);
-static void gjab_start(gjconn gjc);
-static void gjab_stop(gjconn gjc);
-/*
-static int gjab_getfd(gjconn gjc);
-static jid gjab_getjid(gjconn gjc);
-static char *gjab_getsid(gjconn gjc);
-*/
-static char *gjab_getid(gjconn gjc);
-static void gjab_send(gjconn gjc, xmlnode x);
-static void gjab_send_raw(gjconn gjc, const char *str);
-static void gjab_recv(gjconn gjc);
-static void gjab_auth(gjconn gjc);
-
-/*
- * It is *this* to which we point the gaim_connection proto_data
- */
-struct jabber_data {
-	gjconn gjc;
-	gboolean did_import;
-	GSList *chats;
-	GHashTable *hash;
-	time_t idle;
-	gboolean die;
-};
-
-/*
- * Jabber "chat group" info.  Pointers to these go in jabber_data
- * pending and existing chats lists.
- */
-struct jabber_chat {
-	jid Jid;
-	struct gaim_connection *gc;
-	struct conversation *b;
-	int id;
-	int state;
-};
-
-/*
- * Jabber chat states...
- *
- * Note: due to a bug in one version of the Jabber server, subscriptions
- * to chat groups aren't (always?) properly removed at the server.  The
- * result is clients receive Jabber "presence" notifications for JIDs
- * they no longer care about.  The problem with such vestigial notifies is
- * that we really have no way of telling if it's vestigial or if it's a
- * valid "buddy" presence notification.  So we keep jabber_chat structs
- * around after leaving a chat group and simply mark them "closed."  That
- * way we can test for such errant presence notifications.  I.e.: if we
- * get a presence notfication from a JID that matches a chat group JID,
- * we disregard it.
- */
-#define JCS_PENDING 1	/* pending */
-#define JCS_ACTIVE  2	/* active */
-#define JCS_CLOSED  3	/* closed */
-
-
-#define STATE_EVT(arg) if(gjc->on_state) { (gjc->on_state)(gjc, (arg) ); }
-
-static void jabber_remove_buddy(struct gaim_connection *gc, char *name, char *group);
-static void jabber_handlevcard(gjconn gjc, xmlnode querynode, char *from);
-
-static char *create_valid_jid(const char *given, char *server, char *resource)
-{
-	char *valid;
-
-	if (!strchr(given, '@'))
-		valid = g_strdup_printf("%s@%s/%s", given, server, resource);
-	else if (!strchr(strchr(given, '@'), '/'))
-		valid = g_strdup_printf("%s/%s", given, resource);
-	else
-		valid = g_strdup(given);
-
-	return valid;
-}
-
-static gjconn gjab_new(char *user, char *pass, void *priv)
-{
-	pool p;
-	gjconn gjc;
-
-	if (!user)
-		return (NULL);
-
-	p = pool_new();
-	if (!p)
-		return (NULL);
-	gjc = pmalloc_x(p, sizeof(gjconn_struct), 0);
-	if (!gjc) {
-		pool_free(p);	/* no need for this anymore! */
-		return (NULL);
-	}
-	gjc->p = p;
-
-	if((gjc->user = jid_new(p, user)) == NULL) {
-		pool_free(p);	/* no need for this anymore! */
-		return (NULL);
-	}
-	gjc->pass = pstrdup(p, pass);
-
-	gjc->state = JCONN_STATE_OFF;
-	gjc->was_connected = 0;
-	gjc->id = 1;
-	gjc->fd = -1;
-
-	gjc->priv = priv;
-
-	return gjc;
-}
-
-static void gjab_delete(gjconn gjc)
-{
-	if (!gjc)
-		return;
-
-	gjab_stop(gjc);
-	pool_free(gjc->p);
-}
-
-static void gjab_state_handler(gjconn gjc, gjconn_state_h h)
-{
-	if (!gjc)
-		return;
-
-	gjc->on_state = h;
-}
-
-static void gjab_packet_handler(gjconn gjc, gjconn_packet_h h)
-{
-	if (!gjc)
-		return;
-
-	gjc->on_packet = h;
-}
-
-static void gjab_stop(gjconn gjc)
-{
-	if (!gjc || gjc->state == JCONN_STATE_OFF)
-		return;
-
-	gjab_send_raw(gjc, "</stream:stream>");
-	gjc->state = JCONN_STATE_OFF;
-	gjc->was_connected = 0;
-	if (gjc->ssl) {
-		ssl_disconnect(gjc->ssl);
-		gjc->ssl = NULL;
-	} else {
-		closesocket(gjc->fd);
-	}
-	gjc->fd = -1;
-	XML_ParserFree(gjc->parser);
-	gjc->parser = NULL;
-}
-
-/*
-static int gjab_getfd(gjconn gjc)
-{
-	if (gjc)
-		return gjc->fd;
-	else
-		return -1;
-}
-
-static jid gjab_getjid(gjconn gjc)
-{
-	if (gjc)
-		return (gjc->user);
-	else
-		return NULL;
-}
-
-static char *gjab_getsid(gjconn gjc)
-{
-	if (gjc)
-		return (gjc->sid);
-	else
-		return NULL;
-}
-*/
-
-static char *gjab_getid(gjconn gjc)
-{
-	g_snprintf(gjc->idbuf, 8, "%d", gjc->id++);
-	return &gjc->idbuf[0];
-}
-
-static void gjab_send(gjconn gjc, xmlnode x)
-{
-	if (gjc && gjc->state != JCONN_STATE_OFF) {
-		char *buf = xmlnode2str(x);
-		if (!buf)
-			return;
-		else if (gjc->ssl)
-			ssl_write(gjc->ssl, buf, strlen(buf));
-		else
-			write(gjc->fd, buf, strlen(buf));
-	}
-}
-
-static void gjab_send_raw(gjconn gjc, const char *str)
-{
-	if (gjc && gjc->state != JCONN_STATE_OFF) {
-		int len;
-		
-		/*
-		 * JFIXME: No error detection?!?!
-		 */
-		if (gjc->ssl)
-			len = ssl_write(gjc->ssl, str, strlen(str));
-		else
-			len = write(gjc->fd, str, strlen(str));
-			
-		if(len < 0) {
-			/* Do NOT write to stdout/stderr directly, IRC clients
-			   might get confused, and we don't want that...
-			fprintf(stderr, "DBG: Problem sending.  Error: %d\n", errno);
-			fflush(stderr); */
-		}
-	}
-}
-
-static void gjab_reqroster(gjconn gjc)
-{
-	xmlnode x;
-
-	x = jutil_iqnew(JPACKET__GET, NS_ROSTER);
-	xmlnode_put_attrib(x, "id", gjab_getid(gjc));
-
-	gjab_send(gjc, x);
-	xmlnode_free(x);
-}
-
-static void gjab_reqauth(gjconn gjc)
-{
-	xmlnode x, y, z;
-	char *user;
-
-	if (!gjc)
-		return;
-
-	x = jutil_iqnew(JPACKET__GET, NS_AUTH);
-	xmlnode_put_attrib(x, "id", IQID_AUTH);
-	y = xmlnode_get_tag(x, "query");
-
-	user = gjc->user->user;
-
-	if (user) {
-		z = xmlnode_insert_tag(y, "username");
-		xmlnode_insert_cdata(z, user, -1);
-	}
-
-	gjab_send(gjc, x);
-	xmlnode_free(x);
-}
-
-static void gjab_auth(gjconn gjc)
-{
-	xmlnode x, y, z;
-	char *hash, *user;
-
-	if (!gjc)
-		return;
-
-	x = jutil_iqnew(JPACKET__SET, NS_AUTH);
-	xmlnode_put_attrib(x, "id", IQID_AUTH);
-	y = xmlnode_get_tag(x, "query");
-
-	user = gjc->user->user;
-
-	if (user) {
-		z = xmlnode_insert_tag(y, "username");
-		xmlnode_insert_cdata(z, user, -1);
-	}
-
-	z = xmlnode_insert_tag(y, "resource");
-	xmlnode_insert_cdata(z, gjc->user->resource, -1);
-
-	if (gjc->sid) {
-		z = xmlnode_insert_tag(y, "digest");
-		hash = pmalloc(x->p, strlen(gjc->sid) + strlen(gjc->pass) + 1);
-		strcpy(hash, gjc->sid);
-		strcat(hash, gjc->pass);
-		hash = shahash(hash);
-		xmlnode_insert_cdata(z, hash, 40);
-	} else {
-		z = xmlnode_insert_tag(y, "password");
-		xmlnode_insert_cdata(z, gjc->pass, -1);
-	}
-
-	gjab_send(gjc, x);
-	xmlnode_free(x);
-
-	return;
-}
-
-static void gjab_recv(gjconn gjc)
-{
-	static char buf[4096];
-	int len;
-
-	if (!gjc || gjc->state == JCONN_STATE_OFF)
-		return;
-	
-	if (gjc->ssl)
-		len = ssl_read(gjc->ssl, buf, sizeof(buf) - 1);
-	else
-		len = read(gjc->fd, buf, sizeof(buf) - 1);
-	
-	if (len > 0) {
-		struct jabber_data *jd = GJ_GC(gjc)->proto_data;
-		buf[len] = '\0';
-		XML_Parse(gjc->parser, buf, len, 0);
-		if (jd->die)
-			signoff(GJ_GC(gjc));
-	} else if (len == 0 || (len < 0 && (!sockerr_again() || gjc->ssl))) {
-		STATE_EVT(JCONN_STATE_OFF)
-	}
-}
-
-static void startElement(void *userdata, const char *name, const char **attribs)
-{
-	xmlnode x;
-	gjconn gjc = (gjconn) userdata;
-
-	if (gjc->current) {
-		/* Append the node to the current one */
-		x = xmlnode_insert_tag(gjc->current, name);
-		xmlnode_put_expat_attribs(x, attribs);
-
-		gjc->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 */
-			gjc->sid = g_strdup(xmlnode_get_attrib(x, "id"));
-			/* STATE_EVT(JCONN_STATE_AUTH) */
-			xmlnode_free(x);
-		} else {
-			gjc->current = x;
-		}
-	}
-}
-
-static void endElement(void *userdata, const char *name)
-{
-	gjconn gjc = (gjconn) userdata;
-	xmlnode x;
-	jpacket p;
-
-	if (gjc->current == NULL) {
-		/* we got </stream:stream> */
-		STATE_EVT(JCONN_STATE_OFF)
-		    return;
-	}
-
-	x = xmlnode_get_parent(gjc->current);
-
-	if (!x) {
-		/* it is time to fire the event */
-		p = jpacket_new(gjc->current);
-
-		if (gjc->on_packet)
-			(gjc->on_packet) (gjc, p);
-		else
-			xmlnode_free(gjc->current);
-	}
-
-	gjc->current = x;
-}
-
-static gboolean jabber_callback(gpointer data, gint source, b_input_condition condition)
-{
-	struct gaim_connection *gc = (struct gaim_connection *)data;
-	struct jabber_data *jd = (struct jabber_data *)gc->proto_data;
-
-	gjab_recv(jd->gjc);
-	
-	return TRUE;
-}
-
-static void charData(void *userdata, const char *s, int slen)
-{
-	gjconn gjc = (gjconn) userdata;
-
-	if (gjc->current)
-		xmlnode_insert_cdata(gjc->current, s, slen);
-}
-
-static gboolean gjab_connected(gpointer data, gint source, b_input_condition cond)
-{
-	xmlnode x;
-	char *t, *t2;
-	struct gaim_connection *gc = data;
-	struct jabber_data *jd;
-	gjconn gjc;
-
-	if (!g_slist_find(get_connections(), gc)) {
-		closesocket(source);
-		return FALSE;
-	}
-
-	jd = gc->proto_data;
-	gjc = jd->gjc;
-
-	if (gjc->fd != source)
-		gjc->fd = source;
-
-	if (source == -1) {
-		STATE_EVT(JCONN_STATE_OFF)
-		return FALSE;
-	}
-
-	gjc->state = JCONN_STATE_CONNECTED;
-	STATE_EVT(JCONN_STATE_CONNECTED)
-
-	/* start stream */
-	x = jutil_header(NS_CLIENT, gjc->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(gjc, "<?xml version='1.0'?>");
-	gjab_send_raw(gjc, t);
-	xmlnode_free(x);
-
-	gjc->state = JCONN_STATE_ON;
-	STATE_EVT(JCONN_STATE_ON);
-
-	gc = GJ_GC(gjc);
-	gc->inpa = b_input_add(gjc->fd, GAIM_INPUT_READ, jabber_callback, gc);
-	
-	return FALSE;
-}
-
-static gboolean gjab_connected_ssl(gpointer data, void *source, b_input_condition cond)
-{
-	struct gaim_connection *gc = data;
-	struct jabber_data *jd;
-	gjconn gjc;
-	
-	jd = gc->proto_data;
-	gjc = jd->gjc;
-	
-	if (source == NULL) {
-		STATE_EVT(JCONN_STATE_OFF)
-		return FALSE;
-	}
-	
-	if (!g_slist_find(get_connections(), gc)) {
-		ssl_disconnect(source);
-		return FALSE;
-	}
-	
-	return gjab_connected(data, gjc->fd, cond);
-}
-
-static void gjab_start(gjconn gjc)
-{
-	account_t *acc;
-	int port = -1, ssl = 0;
-	char *server = NULL;
-
-	if (!gjc || gjc->state != JCONN_STATE_OFF)
-		return;
-
-	acc = GJ_GC(gjc)->acc;
-	server = acc->server;
-	port = set_getint(&acc->set, "port");
-	ssl = set_getbool(&acc->set, "ssl");
-	
-	if (port < JABBER_PORT_MIN || port > JABBER_PORT_MAX) {
-		serv_got_crap(GJ_GC(gjc), "For security reasons, the Jabber port number must be in the %d-%d range.", JABBER_PORT_MIN, JABBER_PORT_MAX);
-		STATE_EVT(JCONN_STATE_OFF)
-		return;
-	}
-	
-	if (server == NULL)
-		server = g_strdup(gjc->user->server);
-
-	gjc->parser = XML_ParserCreate(NULL);
-	XML_SetUserData(gjc->parser, (void *)gjc);
-	XML_SetElementHandler(gjc->parser, startElement, endElement);
-	XML_SetCharacterDataHandler(gjc->parser, charData);
-	
-	if (ssl) {
-		if ((gjc->ssl = ssl_connect(server, port, gjab_connected_ssl, GJ_GC(gjc))))
-			gjc->fd = ssl_getfd(gjc->ssl);
-		else
-			gjc->fd = -1;
-	} else {
-		gjc->fd = proxy_connect(server, port, gjab_connected, GJ_GC(gjc));
-	}
-	
-	if (!acc->gc || (gjc->fd < 0)) {
-		STATE_EVT(JCONN_STATE_OFF)
-		return;
-	}
-}
-
-/*
- * Find existing/active Jabber chat
- */
-static struct jabber_chat *find_existing_chat(struct gaim_connection *gc, jid chat)
-{
-	GSList *jcs = ((struct jabber_data *)gc->proto_data)->chats;
-	struct jabber_chat *jc = NULL;
-
-	while (jcs) {
-		jc = jcs->data;
-		if (jc->state == JCS_ACTIVE && !jid_cmpx(chat, jc->Jid, JID_USER | JID_SERVER))
-			break;
-		jc = NULL;
-		jcs = jcs->next;
-	}
-
-	return jc;
-}
-
-/*
- * Find pending chat
- */
-static struct jabber_chat *find_pending_chat(struct gaim_connection *gc, jid chat)
-{
-	GSList *jcs = ((struct jabber_data *)gc->proto_data)->chats;
-	struct jabber_chat *jc = NULL;
-
-	while (jcs) {
-		jc = jcs->data;
-		if (jc->state == JCS_PENDING && !jid_cmpx(chat, jc->Jid, JID_USER | JID_SERVER))
-			break;
-		jc = NULL;
-		jcs = jcs->next;
-	}
-
-	return jc;
-}
-
-static gboolean find_chat_buddy(struct conversation *b, char *name)
-{
-	GList *m = b->in_room;
-
-	while (m) {
-		if (!strcmp(m->data, name))
-			return TRUE;
-		m = m->next;
-	}
-
-	return FALSE;
-}
-
-/*
- * Remove a buddy from the (gaim) buddylist (if he's on it)
- */
-static void jabber_remove_gaim_buddy(struct gaim_connection *gc, char *buddyname)
-{
-	struct buddy *b;
-
-	if ((b = find_buddy(gc, buddyname)) != NULL) {
-		/* struct group *group;
-
-		group = find_group_by_buddy(gc, buddyname);
-		remove_buddy(gc, group, b); */
-		jabber_remove_buddy(gc, b->name, JABBER_GROUP);
-	}
-}
-
-/*
- * keep track of away msg same as yahoo plugin
- */
-static void jabber_track_away(gjconn gjc, jpacket p, char *name, char *type)
-{
-	struct jabber_data *jd = GJ_GC(gjc)->proto_data;
-	gpointer val = g_hash_table_lookup(jd->hash, name);
-	char *show;
-	char *vshow = NULL;
-	char *status = NULL;
-	char *msg = NULL;
-
-	if (type && (g_strcasecmp(type, "unavailable") == 0)) {
-		vshow = _("Unavailable");
-	} else {
-		if((show = xmlnode_get_tag_data(p->x, "show")) != NULL) {
-			if (!g_strcasecmp(show, "away")) {
-				vshow = _("Away");
-			} else if (!g_strcasecmp(show, "chat")) {
-				vshow = _("Online");
-			} else if (!g_strcasecmp(show, "xa")) {
-				vshow = _("Extended Away");
-			} else if (!g_strcasecmp(show, "dnd")) {
-				vshow = _("Do Not Disturb");
-			}
-		}
-	}
-
-	status = xmlnode_get_tag_data(p->x, "status");
-
-	if(vshow != NULL || status != NULL ) {
-		/* kinda hokey, but it works :-) */
-		msg = g_strdup_printf("%s%s%s",
-			(vshow == NULL? "" : vshow),
-			(vshow == NULL || status == NULL? "" : ": "),
-			(status == NULL? "" : status));
-	} else {
-		msg = g_strdup(_("Online"));
-	}
-
-	if (val) {
-		g_free(val);
-		g_hash_table_insert(jd->hash, name, msg);
-	} else {
-		g_hash_table_insert(jd->hash, g_strdup(name), msg);
-	}
-}
-
-static time_t iso8601_to_time(char *timestamp)
-{
-	struct tm t;
-	time_t retval = 0;
-
-	if(sscanf(timestamp,"%04d%02d%02dT%02d:%02d:%02d",
-		&t.tm_year, &t.tm_mon, &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec))
-	{
-		t.tm_year -= 1900;
-		t.tm_mon -= 1;
-		t.tm_isdst = 0;
-		retval = mktime(&t);
-#		ifdef HAVE_TM_GMTOFF
-			retval += t.tm_gmtoff;
-#		else
-#		        ifdef HAVE_TIMEZONE
-				tzset();	/* making sure */
-				retval -= timezone;
-#		        endif
-#		endif
-	}
-
-	return retval;
-}
-
-static void jabber_handlemessage(gjconn gjc, jpacket p)
-{
-	xmlnode y, xmlns, z;
-	time_t time_sent = time(NULL);
-
-	char *from = NULL, *msg = NULL, *type = NULL;
-	char m[BUF_LONG * 2];
-
-	type = xmlnode_get_attrib(p->x, "type");
-
-	z = xmlnode_get_firstchild(p->x);
-
-	while(z)
-	{
-	   if(NSCHECK(z,NS_DELAY))
-	   {
-	      char *timestamp = xmlnode_get_attrib(z,"stamp");
-	      time_sent = iso8601_to_time(timestamp);
-	   }
-	   z = xmlnode_get_nextsibling(z);
-	}
-
-	if (!type || !g_strcasecmp(type, "normal") || !g_strcasecmp(type, "chat")) {
-
-		/* XXX namespaces could be handled better. (mid) */
-		if ((xmlns = xmlnode_get_tag(p->x, "x")))
-			type = xmlnode_get_attrib(xmlns, "xmlns");
-
-		from = jid_full(p->from);
-		/*
-		if ((y = xmlnode_get_tag(p->x, "html"))) {
-			msg = xmlnode_get_data(y);
-		} else
-		*/
-		if ((y = xmlnode_get_tag(p->x, "body"))) {
-			msg = xmlnode_get_data(y);
-		}
-
-
-		if (!from)
-			return;
-
-		if (type && !g_strcasecmp(type, "jabber:x:conference")) {
-			/* do nothing */
-		} else if (msg) { /* whisper */
-			struct jabber_chat *jc;
-			g_snprintf(m, sizeof(m), "%s", msg);
-			if (((jc = find_existing_chat(GJ_GC(gjc), p->from)) != NULL) && jc->b)
-				serv_got_chat_in(GJ_GC(gjc), jc->b->id, p->from->resource, 1, m, time_sent);
-			else {
-				int flags = 0;
-				
-				if(p->from->user) {
-				    from = g_strdup_printf("%s@%s", p->from->user, p->from->server);
-				} else {
-				    /* server message? */
-				    from = g_strdup(p->from->server);
-				}
-				serv_got_im(GJ_GC(gjc), from, m, flags, time_sent, -1);
-				g_free(from);
-			}
-		}
-
-	} else if (!g_strcasecmp(type, "error")) {
-		if ((y = xmlnode_get_tag(p->x, "error"))) {
-			type = xmlnode_get_attrib(y, "code");
-			msg = xmlnode_get_data(y);
-		}
-
-		if (msg) {
-			from = g_strdup_printf("Error %s", type ? type : "");
-			do_error_dialog(GJ_GC(gjc), msg, from);
-			g_free(from);
-		}
-	} else if (!g_strcasecmp(type, "headline")) {
-		char *subject, *body, *url;
-		
-		y = xmlnode_get_tag( p->x, "body" );
-		body = y ? g_strdup( xmlnode_get_data( y ) ) : NULL;
-		
-		y = xmlnode_get_tag( p->x, "subject" );
-		subject = y ? g_strdup( xmlnode_get_data( y ) ) : NULL;
-		
-		url = NULL;
-		z = xmlnode_get_firstchild(p->x);
-		while( z )
-		{
-			char *xtype = xmlnode_get_attrib( z, "xmlns" );
-			
-			if( xtype && g_strcasecmp( xtype, "jabber:x:oob" ) == 0 &&
-			             ( y = xmlnode_get_tag( z, "url" ) ) )
-			{
-				url = g_strdup( xmlnode_get_data( y ) );
-				break;
-			}
-			
-			z = xmlnode_get_nextsibling( z );
-		}
-		
-		g_snprintf( m, BUF_LONG, "Subject: %s\nURL: %s\nMessage:\n%s", subject ? subject : "(none)",
-		                     url ? url : "(none)", body ? body : "(none)" );
-
-		if( p->from->user )
-			from = g_strdup_printf( "%s@%s", p->from->user, p->from->server );
-		else
-			from = g_strdup( p->from->server );
-		
-		serv_got_im( GJ_GC(gjc), from, m, 0, time_sent, -1 );
-		
-		g_free( from );
-		g_free( subject );
-		g_free( body );
-		g_free( url );
-	}
-}
-	   
-static void jabber_handlepresence(gjconn gjc, jpacket p)
-{
-	char *to, *from, *type;
-	struct buddy *b = NULL;
-	jid who;
-	char *buddy;
-	xmlnode y;
-	char *show;
-	int state = 0;
-	GSList *resources;
-	char *res;
-	struct conversation *cnv = NULL;
-	struct jabber_chat *jc = NULL;
-
-	to = xmlnode_get_attrib(p->x, "to");
-	from = xmlnode_get_attrib(p->x, "from");
-	type = xmlnode_get_attrib(p->x, "type");
-	
-	if (type && g_strcasecmp(type, "error") == 0) {
-		return;
-	}
-	else if ((y = xmlnode_get_tag(p->x, "show"))) {
-		show = xmlnode_get_data(y);
-		if (!show) {
-			state = 0;
-		} else if (!g_strcasecmp(show, "away")) {
-			state = UC_AWAY;
-		} else if (!g_strcasecmp(show, "chat")) {
-			state = UC_CHAT;
-		} else if (!g_strcasecmp(show, "xa")) {
-			state = UC_XA;
-		} else if (!g_strcasecmp(show, "dnd")) {
-			state = UC_DND;
-		}
-	} else {
-		state = 0;
-	}
-
-	who = jid_new(gjc->p, from);
-	if (who->user == NULL) {
-		/* FIXME: transport */
-		return;
-	}
-
-	buddy = g_strdup_printf("%s@%s", who->user, who->server);
-
-	/* um. we're going to check if it's a chat. if it isn't, and there are pending
-	 * chats, create the chat. if there aren't pending chats and we don't have the
-	 * buddy on our list, simply bail out. */
-	if ((cnv = NULL) == NULL) {
-		static int i = 0x70;
-		if ((jc = find_pending_chat(GJ_GC(gjc), who)) != NULL) {
-			jc->b = cnv = serv_got_joined_chat(GJ_GC(gjc), i++, who->user);
-			jc->id = jc->b->id;
-			jc->state = JCS_ACTIVE;
-		} else if ((b = find_buddy(GJ_GC(gjc), buddy)) == NULL) {
-			g_free(buddy);
-			return;
-		}
-	}
-
-	if (!cnv) {
-		resources = b->proto_data;
-		res = who->resource;
-		if (res)
-			while (resources) {
-				if (!strcmp(res, resources->data))
-					break;
-				resources = resources->next;
-			}
-
-		/* keep track of away msg same as yahoo plugin */
-		jabber_track_away(gjc, p, normalize(b->name), type);
-
-		if (type && (g_strcasecmp(type, "unavailable") == 0)) {
-			if (resources) {
-				g_free(resources->data);
-				b->proto_data = g_slist_remove(b->proto_data, resources->data);
-			}
-			if (!b->proto_data) {
-				serv_got_update(GJ_GC(gjc), buddy, 0, 0, 0, 0, 0, 0);
-			}
-		} else {
-			if (!resources) {
-				b->proto_data = g_slist_append(b->proto_data, g_strdup(res));
-			}
-
-			serv_got_update(GJ_GC(gjc), buddy, 1, 0, b->signon, b->idle, state, 0);
-
-		}
-	} else {
-		if (who->resource) {
-			char *buf;
-
-			buf = g_strdup_printf("%s@%s/%s", who->user, who->server, who->resource);
-			jabber_track_away(gjc, p, buf, type);
-			g_free(buf);
-
-			if (type && !g_strcasecmp(type, "unavailable")) {
-				struct jabber_data *jd;
-				if (!jc && !(jc = find_existing_chat(GJ_GC(gjc), who))) {
-					g_free(buddy);
-					return;
-				}
-				jd = jc->gc->proto_data;
-				/* if it's not ourselves...*/
-				if (strcmp(who->resource, jc->Jid->resource) && jc->b) {
-					remove_chat_buddy(jc->b, who->resource, NULL);
-					g_free(buddy);
-					return;
-				}
-
-				jc->state = JCS_CLOSED;
-				serv_got_chat_left(GJ_GC(gjc), jc->id);
-				/*
-				 * TBD: put back some day?
-				jd->chats = g_slist_remove(jd->chats, jc);
-				g_free(jc);
-				 */
-			} else {
-				if ((!jc && !(jc = find_existing_chat(GJ_GC(gjc), who))) || !jc->b) {
-					g_free(buddy);
-					return;
-				}
-				if (!find_chat_buddy(jc->b, who->resource)) {
-					add_chat_buddy(jc->b, who->resource);
-				}
-			}
-		}
-	}
-
-	g_free(buddy);
-
-	return;
-}
-
-/*
- * Used only by Jabber accept/deny add stuff just below
- */
-struct jabber_add_permit {
-	gjconn gjc;
-	gchar *user;
-};
-
-/*
- * Common part for Jabber accept/deny adds
- *
- * "type" says whether we'll permit/deny the subscribe request
- */
-static void jabber_accept_deny_add(struct jabber_add_permit *jap, const char *type)
-{
-	xmlnode g = xmlnode_new_tag("presence");
-
-	xmlnode_put_attrib(g, "to", jap->user);
-	xmlnode_put_attrib(g, "type", type);
-	gjab_send(jap->gjc, g);
-
-	xmlnode_free(g);
-}
-
-/*
- * Callback from "accept" in do_ask_dialog() invoked by jabber_handles10n()
- */
-static void jabber_accept_add(gpointer w, struct jabber_add_permit *jap)
-{
-	jabber_accept_deny_add(jap, "subscribed");
-	/*
-	 * If we don't already have the buddy on *our* buddylist,
-	 * ask if we want him or her added.
-	 */
-	if(find_buddy(GJ_GC(jap->gjc), jap->user) == NULL) {
-		show_got_added(GJ_GC(jap->gjc), jap->user, NULL);
-	}
-	g_free(jap->user);
-	g_free(jap);
-}
-
-/*
- * Callback from "deny/cancel" in do_ask_dialog() invoked by jabber_handles10n()
- */
-static void jabber_deny_add(gpointer w, struct jabber_add_permit *jap)
-{
-	jabber_accept_deny_add(jap, "unsubscribed");
-	g_free(jap->user);
-	g_free(jap);
-}
-
-/*
- * Handle subscription requests
- */
-static void jabber_handles10n(gjconn gjc, jpacket p)
-{
-	xmlnode g;
-	char *Jid = xmlnode_get_attrib(p->x, "from");
-	char *type = xmlnode_get_attrib(p->x, "type");
-
-	g = xmlnode_new_tag("presence");
-	xmlnode_put_attrib(g, "to", Jid);
-
-	if (!strcmp(type, "subscribe")) {
-		/*
-		 * A "subscribe to us" request was received - put up the approval dialog
-		 */
-		struct jabber_add_permit *jap = g_new0(struct jabber_add_permit, 1);
-		gchar *msg = g_strdup_printf(_("The user %s wants to add you to his/her buddy list."),
-				Jid);
-
-		jap->gjc = gjc;
-		jap->user = g_strdup(Jid);
-		do_ask_dialog(GJ_GC(gjc), msg, jap, jabber_accept_add, jabber_deny_add);
-
-		g_free(msg);
-		xmlnode_free(g);	/* Never needed it here anyway */
-		return;
-
-	} else if (!strcmp(type, "unsubscribe")) {
-		/*
-		 * An "unsubscribe to us" was received - simply "approve" it
-		 */
-		xmlnode_put_attrib(g, "type", "unsubscribed");
-	} else {
-		/*
-		 * Did we attempt to subscribe to somebody and they do not exist?
-		 */
-		if (!strcmp(type, "unsubscribed")) {
-			xmlnode y;
-			char *status;
-			if((y = xmlnode_get_tag(p->x, "status")) && (status = xmlnode_get_data(y)) &&
-					!strcmp(status, "Not Found")) {
-				char *msg = g_strdup_printf("%s: \"%s\"", _("No such user"), 
-					xmlnode_get_attrib(p->x, "from"));
-				do_error_dialog(GJ_GC(gjc), msg, _("Jabber Error"));
-				g_free(msg);
-			}
-		}
-
-		xmlnode_free(g);
-		return;
-	}
-
-	gjab_send(gjc, g);
-	xmlnode_free(g);
-}
-
-/*
- * Pending subscription to a buddy?
- */
-#define BUD_SUB_TO_PEND(sub, ask) ((!g_strcasecmp((sub), "none") || !g_strcasecmp((sub), "from")) && \
-					(ask) != NULL && !g_strcasecmp((ask), "subscribe")) 
-
-/*
- * Subscribed to a buddy?
- */
-#define BUD_SUBD_TO(sub, ask) ((!g_strcasecmp((sub), "to") || !g_strcasecmp((sub), "both")) && \
-					((ask) == NULL || !g_strcasecmp((ask), "subscribe")))
-
-/*
- * Pending unsubscription to a buddy?
- */
-#define BUD_USUB_TO_PEND(sub, ask) ((!g_strcasecmp((sub), "to") || !g_strcasecmp((sub), "both")) && \
-					(ask) != NULL && !g_strcasecmp((ask), "unsubscribe")) 
-
-/*
- * Unsubscribed to a buddy?
- */
-#define BUD_USUBD_TO(sub, ask) ((!g_strcasecmp((sub), "none") || !g_strcasecmp((sub), "from")) && \
-					((ask) == NULL || !g_strcasecmp((ask), "unsubscribe")))
-
-/*
- * If a buddy is added or removed from the roster on another resource
- * jabber_handlebuddy is called
- *
- * Called with roster item node.
- */
-static void jabber_handlebuddy(gjconn gjc, xmlnode x)
-{
-	xmlnode g;
-	char *Jid, *name, *sub, *ask;
-	jid who;
-	struct buddy *b = NULL;
-	char *buddyname, *groupname = NULL;
-
-	Jid = xmlnode_get_attrib(x, "jid");
-	name = xmlnode_get_attrib(x, "name");
-	sub = xmlnode_get_attrib(x, "subscription");
-	ask = xmlnode_get_attrib(x, "ask");
-	who = jid_new(gjc->p, Jid);
-
-	/* JFIXME: jabber_handleroster() had a "FIXME: transport" at this
-	 * equivilent point.  So...
-	 *
-	 * We haven't allocated any memory or done anything interesting to
-	 * this point, so we'll violate Good Coding Structure here by
-	 * simply bailing out.
-	 */
-	if (!who || !who->user) {
-		return;
-	}
-
-	buddyname = g_strdup_printf("%s@%s", who->user, who->server);
-
-	if((g = xmlnode_get_tag(x, "group")) != NULL) {
-		groupname = xmlnode_get_data(g);
-	}
-
-	/*
-	 * Add or remove a buddy?  Change buddy's alias or group?
-	 */
-	if (BUD_SUB_TO_PEND(sub, ask) || BUD_SUBD_TO(sub, ask)) {
-		if ((b = find_buddy(GJ_GC(gjc), buddyname)) == NULL) {
-			add_buddy(GJ_GC(gjc), groupname ? groupname : _("Buddies"), buddyname,
-				name ? name : buddyname);
-		} else {
-			/* struct group *c_grp = find_group_by_buddy(GJ_GC(gjc), buddyname); */
-
-			/* 
-			 * If the buddy's in a new group or his/her alias is changed...
-			 */
-			if(groupname) {
-				int present = b->present;	/* save presence state */
-				int uc = b->uc;			/* and away state (?) */
-				int idle = b->idle;
-				int signon = b->signon;
-
-				/*
-				 * seems rude, but it seems to be the only way...
-				 */
-				/* remove_buddy(GJ_GC(gjc), c_grp, b); */
-				jabber_remove_buddy(GJ_GC(gjc), b->name, JABBER_GROUP);
-				
-				add_buddy(GJ_GC(gjc), groupname, buddyname,
-					name ? name : buddyname);
-				if(present) {
-					serv_got_update(GJ_GC(gjc), buddyname, 1, 0, signon, idle, uc, 0);
-				}
-			} else if(name != NULL && strcmp(b->show, name)) {
-				strncpy(b->show, name, BUDDY_ALIAS_MAXLEN);
-				b->show[BUDDY_ALIAS_MAXLEN - 1] = '\0';	/* cheap safety feature */
-				serv_buddy_rename(GJ_GC(gjc), buddyname, b->show);
-			}
-		}
-	}  else if (BUD_USUB_TO_PEND(sub, ask) || BUD_USUBD_TO(sub, ask) || !g_strcasecmp(sub, "remove")) {
-		jabber_remove_gaim_buddy(GJ_GC(gjc), buddyname);
-	}
-	g_free(buddyname);
-
-}
-
-static void jabber_handleroster(gjconn gjc, xmlnode querynode)
-{
-	xmlnode x;
-
-	x = xmlnode_get_firstchild(querynode);
-	while (x) {
-		jabber_handlebuddy(gjc, x);
-		x = xmlnode_get_nextsibling(x);
-	}
-
-	account_online(GJ_GC(gjc));
-}
-
-static void jabber_handleauthresp(gjconn gjc, jpacket p)
-{
-	if (jpacket_subtype(p) == JPACKET__RESULT) {
-		if (xmlnode_has_children(p->x)) {
-			xmlnode query = xmlnode_get_tag(p->x, "query");
-			set_login_progress(GJ_GC(gjc), 4, _("Authenticating"));
-			if (!xmlnode_get_tag(query, "digest")) {
-				g_free(gjc->sid);
-				gjc->sid = NULL;
-			}
-			gjab_auth(gjc);
-		} else {
-			gjab_reqroster(gjc);
-			
-			((struct jabber_data *)GJ_GC(gjc)->proto_data)->did_import = TRUE;
-		}
-	} else {
-		xmlnode xerr;
-		char *errmsg = NULL;
-		int errcode = 0;
-		struct jabber_data *jd = GJ_GC(gjc)->proto_data;
-
-		xerr = xmlnode_get_tag(p->x, "error");
-		if (xerr) {
-			char msg[BUF_LONG];
-			errmsg = xmlnode_get_data(xerr);
-			if (xmlnode_get_attrib(xerr, "code")) {
-				errcode = atoi(xmlnode_get_attrib(xerr, "code"));
-				g_snprintf(msg, sizeof(msg), "Error %d: %s", errcode, errmsg ? errmsg : "Unknown error");
-			} else
-				g_snprintf(msg, sizeof(msg), "%s", errmsg);
-			hide_login_progress(GJ_GC(gjc), msg);
-		} else {
-			hide_login_progress(GJ_GC(gjc), _("Unknown login error"));
-		}
-
-		jd->die = TRUE;
-	}
-}
-
-static void jabber_handleversion(gjconn gjc, xmlnode iqnode) {
-	xmlnode querynode, x;
-	char *id, *from;
-	char os[1024];
-#ifndef _WIN32
-	struct utsname osinfo;
-
-	uname(&osinfo);
-	g_snprintf(os, sizeof os, "%s %s %s", osinfo.sysname, osinfo.release, osinfo.machine);
-#else
-	g_snprintf(os, sizeof os, "Windows %d %d", _winmajor, _winminor);
-#endif
-
-
-	id = xmlnode_get_attrib(iqnode, "id");
-	from = xmlnode_get_attrib(iqnode, "from");
-
-	x = jutil_iqnew(JPACKET__RESULT, NS_VERSION);
-
-	xmlnode_put_attrib(x, "to", from);
-	xmlnode_put_attrib(x, "id", id);
-	querynode = xmlnode_get_tag(x, "query");
-	xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "name"), PACKAGE, -1);
-	xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "version"), BITLBEE_VERSION, -1);
-	xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "os"), os, -1);
-
-	gjab_send(gjc, x);
-
-	xmlnode_free(x);
-}
-
-static void jabber_handletime(gjconn gjc, xmlnode iqnode) {
-	xmlnode querynode, x;
-	char *id, *from;
-	time_t now_t; 
-	struct tm *now;
-	char buf[1024];
-
-	time(&now_t);
-	now = localtime(&now_t);
-
-	id = xmlnode_get_attrib(iqnode, "id");
-	from = xmlnode_get_attrib(iqnode, "from");
-
-	x = jutil_iqnew(JPACKET__RESULT, NS_TIME);
-
-	xmlnode_put_attrib(x, "to", from);
-	xmlnode_put_attrib(x, "id", id);
-	querynode = xmlnode_get_tag(x, "query");
-
-	strftime(buf, 1024, "%Y%m%dT%T", now);
-	xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "utc"), buf, -1);
-	strftime(buf, 1024, "%Z", now);
-	xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "tz"), buf, -1);
-	strftime(buf, 1024, "%d %b %Y %T", now);
-	xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "display"), buf, -1);
-	
-	gjab_send(gjc, x);
-
-	xmlnode_free(x);
-}
-
-static void jabber_handlelast(gjconn gjc, xmlnode iqnode) {
-   	xmlnode x, querytag;
-	char *id, *from;
-	struct jabber_data *jd = GJ_GC(gjc)->proto_data;
-	char idle_time[32];
-	
-	id = xmlnode_get_attrib(iqnode, "id");
-	from = xmlnode_get_attrib(iqnode, "from");
-
-	x = jutil_iqnew(JPACKET__RESULT, "jabber:iq:last");
-
-	xmlnode_put_attrib(x, "to", from);
-	xmlnode_put_attrib(x, "id", id);
-	querytag = xmlnode_get_tag(x, "query");
-	g_snprintf(idle_time, sizeof idle_time, "%ld", jd->idle ? time(NULL) - jd->idle : 0);
-	xmlnode_put_attrib(querytag, "seconds", idle_time);
-
-	gjab_send(gjc, x);
-	xmlnode_free(x);
-}
-
-/*
- * delete == TRUE: delete found entry
- *
- * returns pointer to (local) copy of value if found, NULL otherwise
- *
- * Note: non-reentrant!  Local static storage re-used on subsequent calls.
- * If you're going to need to keep the returned value, make a copy!
- */
-static gchar *jabber_track_queries(GHashTable *queries, gchar *key, gboolean delete)
-{
-	gpointer my_key, my_val;
-	static gchar *ret_val = NULL;
-
-	if(ret_val != NULL) {
-		g_free(ret_val);
-		ret_val = NULL;
-	}
-
-	/* self-protection */
-	if(queries != NULL && key != NULL) {
-		if(g_hash_table_lookup_extended(queries, key, &my_key, &my_val)) {
-			ret_val = g_strdup((gchar *) my_val);
-			if(delete) {
-				g_hash_table_remove(queries, key);
-				g_free(my_key);
-				g_free(my_val);
-			}
-		}
-	}
-
-	return(ret_val);
-}
-
-static void jabber_handlepacket(gjconn gjc, jpacket p)
-{
-	char *id;
-	switch (p->type) {
-	case JPACKET_MESSAGE:
-		jabber_handlemessage(gjc, p);
-		break;
-	case JPACKET_PRESENCE:
-		jabber_handlepresence(gjc, p);
-		break;
-	case JPACKET_IQ:
-		id = xmlnode_get_attrib(p->x, "id");
-		if (id != NULL && !strcmp(id, IQID_AUTH)) {
-			jabber_handleauthresp(gjc, p);
-			break;
-		}
-
-		if (jpacket_subtype(p) == JPACKET__SET) {
-			xmlnode querynode;
-			querynode = xmlnode_get_tag(p->x, "query");
-			if (NSCHECK(querynode, "jabber:iq:roster")) {
-				jabber_handlebuddy(gjc, xmlnode_get_firstchild(querynode));
-			}
-		} else if (jpacket_subtype(p) == JPACKET__GET) {
-		   	xmlnode querynode;
-			querynode = xmlnode_get_tag(p->x, "query");
-		   	if (NSCHECK(querynode, NS_VERSION)) {
-			   	jabber_handleversion(gjc, p->x);
-			} else if (NSCHECK(querynode, NS_TIME)) {
-			   	jabber_handletime(gjc, p->x);
-			} else if (NSCHECK(querynode, "jabber:iq:last")) {
-			   	jabber_handlelast(gjc, p->x);
-			}
-		} else if (jpacket_subtype(p) == JPACKET__RESULT) {
-			xmlnode querynode, vcard;
-			/* char *xmlns; */
-			char *from;
-
-			/*
-			 * TBD: ISTM maybe this part could use a serious re-work?
-			 */
-			from = xmlnode_get_attrib(p->x, "from");
-			querynode = xmlnode_get_tag(p->x, "query");
-			vcard = xmlnode_get_tag(p->x, "vCard");
-			if (!vcard)
-				vcard = xmlnode_get_tag(p->x, "VCARD");
-
-			if (NSCHECK(querynode, NS_ROSTER)) {
-				jabber_handleroster(gjc, querynode);
-			} else if (NSCHECK(querynode, NS_VCARD)) {
-				jabber_track_queries(gjc->queries, id, TRUE);	/* delete query track */
-                                jabber_handlevcard(gjc, querynode, from);
-			} else if (vcard) {
-				jabber_track_queries(gjc->queries, id, TRUE);	/* delete query track */
-                                jabber_handlevcard(gjc, vcard, from);
-			} else {
-				char *val;
-
-				/* handle "null" query results */
-				if((val = jabber_track_queries(gjc->queries, id, TRUE)) != NULL) {
-					if (!g_strncasecmp(val, "vcard", 5)) {
-						jabber_handlevcard(gjc, NULL, from);
-					}
-
-					/* No-op */
-				}
-			}
-
-		} else if (jpacket_subtype(p) == JPACKET__ERROR) {
-			xmlnode xerr;
-			char *from, *errmsg = NULL;
-			int errcode = 0;
-
-			from = xmlnode_get_attrib(p->x, "from");
-			xerr = xmlnode_get_tag(p->x, "error");
-			if (xerr) {
-				errmsg = xmlnode_get_data(xerr);
-				if (xmlnode_get_attrib(xerr, "code"))
-					errcode = atoi(xmlnode_get_attrib(xerr, "code"));
-			}
-
-			from = g_strdup_printf("Error %d (%s)", errcode, from);
-			do_error_dialog(GJ_GC(gjc), errmsg, from);
-			g_free(from);
-
-		}
-
-		break;
-	case JPACKET_S10N:
-		jabber_handles10n(gjc, p);
-		break;
-	}
-
-	xmlnode_free(p->x);
-
-	return;
-}
-
-static void jabber_handlestate(gjconn gjc, int state)
-{
-	switch (state) {
-	case JCONN_STATE_OFF:
-		if(gjc->was_connected) {
-			hide_login_progress_error(GJ_GC(gjc), _("Connection lost"));
-		} else {
-			hide_login_progress(GJ_GC(gjc), _("Unable to connect"));
-		}
-		signoff(GJ_GC(gjc));
-		break;
-	case JCONN_STATE_CONNECTED:
-		gjc->was_connected = 1;
-		set_login_progress(GJ_GC(gjc), 2, _("Connected"));
-		break;
-	case JCONN_STATE_ON:
-		set_login_progress(GJ_GC(gjc), 3, _("Requesting Authentication Method"));
-		gjab_reqauth(gjc);
-		break;
-	}
-	return;
-}
-
-static void jabber_acc_init(account_t *acc)
+
+static void jabber_acc_init( account_t *acc )
 {
 	set_t *s;
@@ -1503,7 +40,11 @@
 	s->flags |= ACC_SET_OFFLINE_ONLY;
 	
+	s = set_add( &acc->set, "priority", "0", set_eval_priority, acc );
+	
 	s = set_add( &acc->set, "resource", "BitlBee", NULL, acc );
 	s->flags |= ACC_SET_OFFLINE_ONLY;
 	
+	s = set_add( &acc->set, "resource_select", "priority", NULL, acc );
+	
 	s = set_add( &acc->set, "server", NULL, set_eval_account, acc );
 	s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY;
@@ -1511,882 +52,345 @@
 	s = set_add( &acc->set, "ssl", "false", set_eval_bool, acc );
 	s->flags |= ACC_SET_OFFLINE_ONLY;
-}
-
-static void jabber_login(account_t *acc)
-{
-	struct gaim_connection *gc;
-	struct jabber_data *jd;
-	char *resource, *loginname;
-	
-	/* Time to move some data/things from the old syntax to the new one: */
-	if (acc->server) {
-		char *s, *tmp_server;
-		int port;
-		
-		if (g_strcasecmp(acc->server, "ssl") == 0) {
-			set_setstr(&acc->set, "server", "");
-			set_setint(&acc->set, "port", DEFAULT_PORT_SSL);
-			set_setstr(&acc->set, "ssl", "true");
-			
-			g_free(acc->server);
-			acc->server = NULL;
-		} else if ((s = strchr(acc->server, ':'))) {
-			if (strstr(acc->server, ":ssl")) {
-				set_setint(&acc->set, "port", DEFAULT_PORT_SSL);
-				set_setstr(&acc->set, "ssl", "true");
-			}
-			if (isdigit(s[1])) {
-				if (sscanf(s + 1, "%d", &port) == 1)
-					set_setint(&acc->set, "port", port);
-			}
-			tmp_server = g_strndup(acc->server, s - acc->server);
-			set_setstr(&acc->set, "server", tmp_server);
-			g_free(tmp_server);
-		}
-	}
-	
-	gc = new_gaim_conn(acc);
-	jd = gc->proto_data = g_new0(struct jabber_data, 1);
-	
-	if( strchr( acc->user, '@' ) == NULL )
-	{
-		hide_login_progress( gc, "Invalid account name" );
+	
+	s = set_add( &acc->set, "tls", "try", set_eval_tls, acc );
+	s->flags |= ACC_SET_OFFLINE_ONLY;
+}
+
+static void jabber_login( account_t *acc )
+{
+	struct gaim_connection *gc = new_gaim_conn( acc );
+	struct jabber_data *jd = g_new0( struct jabber_data, 1 );
+	struct ns_srv_reply *srv = NULL;
+	char *connect_to, *s;
+	
+	jd->gc = gc;
+	gc->proto_data = jd;
+	
+	jd->username = g_strdup( acc->user );
+	jd->server = strchr( jd->username, '@' );
+	
+	if( jd->server == NULL )
+	{
+		hide_login_progress( gc, "Incomplete account name (format it like <username@jabberserver.name>)" );
 		signoff( gc );
 		return;
 	}
 	
-	resource = set_getstr(&acc->set, "resource");
-	loginname = create_valid_jid(acc->user, DEFAULT_SERVER, resource);
-	
-	jd->hash = g_hash_table_new(g_str_hash, g_str_equal);
-	jd->chats = NULL;	/* we have no chats yet */
-
-	set_login_progress(gc, 1, _("Connecting"));
-
-	if (!(jd->gjc = gjab_new(loginname, acc->pass, gc))) {
-		g_free(loginname);
-		hide_login_progress(gc, _("Unable to connect"));
-		signoff(gc);
-		return;
-	}
-
-	g_free(loginname);
-	gjab_state_handler(jd->gjc, jabber_handlestate);
-	gjab_packet_handler(jd->gjc, jabber_handlepacket);
-	jd->gjc->queries = g_hash_table_new(g_str_hash, g_str_equal);
-	gjab_start(jd->gjc);
-}
-
-static gboolean jabber_destroy_hash(gpointer key, gpointer val, gpointer data) {
-   	g_free(key);
-	g_free(val);
-	return TRUE;
-}
-
-static gboolean jabber_free(gpointer data, gint fd, b_input_condition cond)
-{
-	struct jabber_data *jd = data;
-
-	if(jd->gjc != NULL) {
-		gjab_delete(jd->gjc);
-		/* YAY for modules with their own memory pool managers!...
-		g_free(jd->gjc->sid);
-		And a less sarcastic yay for valgrind. :-) */
-		jd->gjc = NULL;
-	}
-	g_free(jd);
-
-	return FALSE;
-}
-
-static void jabber_close(struct gaim_connection *gc)
-{
-	struct jabber_data *jd = gc->proto_data;
-
-	if(jd) {
-		GSList *jcs = jd->chats;
-
-		/* Free-up the jabber_chat struct allocs and the list */
-		while (jcs) {
-			g_free(jcs->data);
-			jcs = jcs->next;
+	/* So don't think of free()ing jd->server.. :-) */
+	*jd->server = 0;
+	jd->server ++;
+	
+	if( ( s = strchr( jd->server, '/' ) ) )
+	{
+		*s = 0;
+		set_setstr( &acc->set, "resource", s + 1 );
+		
+		/* Also remove the /resource from the original variable so we
+		   won't have to do this again every time. */
+		s = strchr( acc->user, '/' );
+		*s = 0;
+	}
+	
+	/* This code isn't really pretty. Backwards compatibility never is... */
+	s = acc->server;
+	while( s )
+	{
+		static int had_port = 0;
+		
+		if( strncmp( s, "ssl", 3 ) == 0 )
+		{
+			set_setstr( &acc->set, "ssl", "true" );
+			
+			/* Flush this part so that (if this was the first
+			   part of the server string) acc->server gets
+			   flushed. We don't want to have to do this another
+			   time. :-) */
+			*s = 0;
+			s ++;
+			
+			/* Only set this if the user didn't specify a custom
+			   port number already... */
+			if( !had_port )
+				set_setint( &acc->set, "port", 5223 );
 		}
-		g_slist_free(jd->chats);
-
-		/* Free-up the away status memories and the list */
-		if(jd->hash != NULL) {
-			g_hash_table_foreach_remove(jd->hash, jabber_destroy_hash, NULL);
-			g_hash_table_destroy(jd->hash);
-			jd->hash = NULL;
+		else if( isdigit( *s ) )
+		{
+			int i;
+			
+			/* The first character is a digit. It could be an
+			   IP address though. Only accept this as a port#
+			   if there are only digits. */
+			for( i = 0; isdigit( s[i] ); i ++ );
+			
+			/* If the first non-digit character is a colon or
+			   the end of the string, save the port number
+			   where it should be. */
+			if( s[i] == ':' || s[i] == 0 )
+			{
+				sscanf( s, "%d", &i );
+				set_setint( &acc->set, "port", i );
+				
+				/* See above. */
+				*s = 0;
+				s ++;
+			}
+			
+			had_port = 1;
 		}
-
-		/* Free-up the pending queries memories and the list */
-		if(jd->gjc != NULL && jd->gjc->queries != NULL) {
-			g_hash_table_foreach_remove(jd->gjc->queries, jabber_destroy_hash, NULL);
-			g_hash_table_destroy(jd->gjc->queries);
-			jd->gjc->queries = NULL;
+		
+		s = strchr( s, ':' );
+		if( s )
+		{
+			*s = 0;
+			s ++;
 		}
 	}
-	if (gc->inpa)
-		b_event_remove(gc->inpa);
-
-	if(jd) {
-		b_timeout_add(50, jabber_free, jd);
-		if(jd->gjc != NULL)
-			xmlnode_free(jd->gjc->current);
-	}
-	gc->proto_data = NULL;
-}
-
-static int jabber_send_im(struct gaim_connection *gc, char *who, char *message, int len, int flags)
-{
-	xmlnode x, y;
-	char *realwho;
-	gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc;
-
-	if (!who || !message)
+	
+	jd->node_cache = g_hash_table_new_full( g_str_hash, g_str_equal, NULL, jabber_cache_entry_free );
+	jd->buddies = g_hash_table_new( g_str_hash, g_str_equal );
+	
+	/* Figure out the hostname to connect to. */
+	if( acc->server && *acc->server )
+		connect_to = acc->server;
+	else if( ( srv = srv_lookup( "xmpp-client", "tcp", jd->server ) ) ||
+		 ( srv = srv_lookup( "jabber-client", "tcp", jd->server ) ) )
+		connect_to = srv->name;
+	else
+		connect_to = jd->server;
+	
+	set_login_progress( gc, 0, "Connecting" );
+	
+	/* For non-SSL connections we can try to use the port # from the SRV
+	   reply, but let's not do that when using SSL, SSL usually runs on
+	   non-standard ports... */
+	if( set_getbool( &acc->set, "ssl" ) )
+	{
+		jd->ssl = ssl_connect( connect_to, set_getint( &acc->set, "port" ), jabber_connected_ssl, gc );
+		jd->fd = jd->ssl ? ssl_getfd( jd->ssl ) : -1;
+	}
+	else
+	{
+		jd->fd = proxy_connect( connect_to, srv ? srv->port : set_getint( &acc->set, "port" ), jabber_connected_plain, gc );
+	}
+	g_free( srv );
+	
+	if( jd->fd == -1 )
+	{
+		hide_login_progress( gc, "Could not connect to server" );
+		signoff( gc );
+	}
+}
+
+static void jabber_close( struct gaim_connection *gc )
+{
+	struct jabber_data *jd = gc->proto_data;
+	
+	jabber_end_stream( gc );
+	
+	if( jd->r_inpa >= 0 )
+		b_event_remove( jd->r_inpa );
+	if( jd->w_inpa >= 0 )
+		b_event_remove( jd->w_inpa );
+	
+	if( jd->ssl )
+		ssl_disconnect( jd->ssl );
+	if( jd->fd >= 0 )
+		closesocket( jd->fd );
+	
+	if( jd->tx_len )
+		g_free( jd->txq );
+	
+	g_hash_table_destroy( jd->node_cache );
+	
+	xt_free( jd->xt );
+	
+	g_free( jd->away_message );
+	g_free( jd->username );
+	g_free( jd );
+}
+
+static int jabber_send_im( struct gaim_connection *gc, char *who, char *message, int len, int away )
+{
+	struct jabber_data *jd = gc->proto_data;
+	struct jabber_buddy *bud;
+	struct xt_node *node;
+	int st;
+	
+	bud = jabber_buddy_by_jid( gc, who, 0 );
+	
+	node = xt_new_node( "body", message, NULL );
+	node = jabber_make_packet( "message", "chat", bud ? bud->full_jid : who, node );
+	
+	if( bud && ( jd->flags & JFLAG_WANT_TYPING ) &&
+	    ( ( bud->flags & JBFLAG_DOES_XEP85 ) ||
+	     !( bud->flags & JBFLAG_PROBED_XEP85 ) ) )
+	{
+		struct xt_node *act;
+		
+		/* If the user likes typing notification and if we don't know
+		   (and didn't probe before) if this resource supports XEP85,
+		   include a probe in this packet now. Also, if we know this
+		   buddy does support XEP85, we have to send this <active/>
+		   tag to tell that the user stopped typing (well, that's what
+		   we guess when s/he pressed Enter...). */
+		act = xt_new_node( "active", NULL, NULL );
+		xt_add_attr( act, "xmlns", XMLNS_CHATSTATES );
+		xt_add_child( node, act );
+		
+		/* Just make sure we do this only once. */
+		bud->flags |= JBFLAG_PROBED_XEP85;
+	}
+	
+	st = jabber_write_packet( gc, node );
+	xt_free_node( node );
+	
+	return st;
+}
+
+static GList *jabber_away_states( struct gaim_connection *gc )
+{
+	static GList *l = NULL;
+	int i;
+	
+	if( l == NULL )
+		for( i = 0; jabber_away_state_list[i].full_name; i ++ )
+			l = g_list_append( l, (void*) jabber_away_state_list[i].full_name );
+	
+	return l;
+}
+
+static void jabber_get_info( struct gaim_connection *gc, char *who )
+{
+	struct jabber_data *jd = gc->proto_data;
+	struct jabber_buddy *bud;
+	
+	if( strchr( who, '/' ) )
+		bud = jabber_buddy_by_jid( gc, who, 0 );
+	else
+	{
+		char *s = jabber_normalize( who );
+		bud = g_hash_table_lookup( jd->buddies, s );
+		g_free( s );
+	}
+	
+	while( bud )
+	{
+		serv_got_crap( gc, "Buddy %s (%d) information:\nAway state: %s\nAway message: %s",
+		                   bud->full_jid, bud->priority,
+		                   bud->away_state ? bud->away_state->full_name : "(none)",
+		                   bud->away_message ? : "(none)" );
+		bud = bud->next;
+	}
+	
+	jabber_get_vcard( gc, bud ? bud->full_jid : who );
+}
+
+static void jabber_set_away( struct gaim_connection *gc, char *state_txt, char *message )
+{
+	struct jabber_data *jd = gc->proto_data;
+	struct jabber_away_state *state;
+	
+	/* Save all this info. We need it, for example, when changing the priority setting. */
+	state = (void *) jabber_away_state_by_name( state_txt );
+	jd->away_state = state ? state : (void *) jabber_away_state_list; /* Fall back to "Away" if necessary. */
+	g_free( jd->away_message );
+	jd->away_message = ( message && *message ) ? g_strdup( message ) : NULL;
+	
+	presence_send_update( gc );
+}
+
+static void jabber_add_buddy( struct gaim_connection *gc, char *who )
+{
+	if( jabber_add_to_roster( gc, who, NULL ) )
+		presence_send_request( gc, who, "subscribe" );
+}
+
+static void jabber_remove_buddy( struct gaim_connection *gc, char *who, char *group )
+{
+	/* We should always do this part. Clean up our administration a little bit. */
+	jabber_buddy_remove_bare( gc, who );
+	
+	if( jabber_remove_from_roster( gc, who ) )
+		presence_send_request( gc, who, "unsubscribe" );
+}
+
+static void jabber_keepalive( struct gaim_connection *gc )
+{
+	/* Just any whitespace character is enough as a keepalive for XMPP sessions. */
+	jabber_write( gc, "\n", 1 );
+	
+	/* This runs the garbage collection every minute, which means every packet
+	   is in the cache for about a minute (which should be enough AFAIK). */
+	jabber_cache_clean( gc );
+}
+
+static int jabber_send_typing( struct gaim_connection *gc, char *who, int typing )
+{
+	struct jabber_data *jd = gc->proto_data;
+	struct jabber_buddy *bud;
+	
+	/* Enable typing notification related code from now. */
+	jd->flags |= JFLAG_WANT_TYPING;
+	
+	if( ( bud = jabber_buddy_by_jid( gc, who, 0 ) ) == NULL )
+	{
+		/* Sending typing notifications to unknown buddies is
+		   unsupported for now. Shouldn't be a problem, I think. */
 		return 0;
-
-	x = xmlnode_new_tag("message");
-	/* Bare username and "username" not the server itself? */
-	if (!strchr(who, '@') && strcmp(who, gjc->user->server) != 0)
-		realwho = g_strdup_printf("%s@%s", who, gjc->user->server);
-	else
-		realwho = g_strdup(who);
-	xmlnode_put_attrib(x, "to", realwho);
-	g_free(realwho);
-
-	xmlnode_insert_tag(x, "bitlbee");
-	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)->gjc, x);
-	xmlnode_free(x);
+	}
+	
+	if( bud->flags & JBFLAG_DOES_XEP85 )
+	{
+		/* We're only allowed to send this stuff if we know the other
+		   side supports it. */
+		
+		struct xt_node *node;
+		char *type;
+		int st;
+		
+		if( typing == 0 )
+			type = "active";
+		else if( typing == 2 )
+			type = "paused";
+		else /* if( typing == 1 ) */
+			type = "composing";
+		
+		node = xt_new_node( type, NULL, NULL );
+		xt_add_attr( node, "xmlns", XMLNS_CHATSTATES );
+		node = jabber_make_packet( "message", "chat", bud->full_jid, node );
+		
+		st = jabber_write_packet( gc, node );
+		xt_free_node( node );
+		
+		return st;
+	}
+	
 	return 1;
 }
 
-/*
- * Add/update buddy's roster entry on server
- */
-static void jabber_roster_update(struct gaim_connection *gc, char *name)
-{
-	xmlnode x, y;
-	char *realwho;
-	gjconn gjc;
-	struct buddy *buddy = NULL;
-	/* struct group *buddy_group = NULL; */
-	
-	if(gc && gc->proto_data && ((struct jabber_data *)gc->proto_data)->gjc && name) {
-		gjc = ((struct jabber_data *)gc->proto_data)->gjc;
-
-		if (!strchr(name, '@'))
-			realwho = g_strdup_printf("%s@%s", name, gjc->user->server);
-		else {
-			jid who = jid_new(gjc->p, name);
-			if (who->user == NULL) {
-				/* FIXME: transport */
-				return;
-			}
-			realwho = g_strdup_printf("%s@%s", who->user, who->server);
-		}
-
-
-		x = jutil_iqnew(JPACKET__SET, NS_ROSTER);
-		y = xmlnode_insert_tag(xmlnode_get_tag(x, "query"), "item");
-		xmlnode_put_attrib(y, "jid", realwho);
-
-
-		/* If we can find the buddy, there's an alias for him, it's not 0-length
-		 * and it doesn't match his JID, add the "name" attribute.
-		 */
-		if((buddy = find_buddy(gc, realwho)) != NULL &&
-			buddy->show != NULL && buddy->show[0] != '\0' && strcmp(realwho, buddy->show)) {
-
-			xmlnode_put_attrib(y, "name", buddy->show);
-		}
-
-		/*
-		 * Find out what group the buddy's in and send that along
-		 * with the roster item.
-		 */
-		/* ** Bitlbee disabled **
-		if((buddy_group = NULL) != NULL) {
-			xmlnode z;
-			z = xmlnode_insert_tag(y, "group");
-			xmlnode_insert_cdata(z, buddy_group->name, -1);
-		}
-		** End - Bitlbee ** */
-
-		gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x);
-
-		xmlnode_free(x);
-		g_free(realwho);
-	}
-}
-
-/*
- * Change buddy's group on server roster
- */
-static void jabber_group_change(struct gaim_connection *gc, char *name, char *old_group, char *new_group)
-{
-	if(strcmp(old_group, new_group)) {
-		jabber_roster_update(gc, name);
-	}
-}
-
-static void jabber_add_buddy(struct gaim_connection *gc, char *name)
-{
-	xmlnode x;
-	char *realwho;
-	gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc;
-
-	if (!((struct jabber_data *)gc->proto_data)->did_import)
-		return;
-
-	if (!name)
-		return;
-
-	if (!strcmp(gc->username, name))
-		return;
-
-	if (!strchr(name, '@'))
-		realwho = g_strdup_printf("%s@%s", name, gjc->user->server);
-	else {
-		jid who;
-		
-		if((who = jid_new(gjc->p, name)) == NULL) {
-			char *msg = g_strdup_printf("%s: \"%s\"", _("Invalid Jabber I.D."), name);
-			do_error_dialog(GJ_GC(gjc), msg, _("Jabber Error"));
-			g_free(msg);
-			jabber_remove_gaim_buddy(gc, name);
-			return;
-		}
-		if (who->user == NULL) {
-			/* FIXME: transport */
-			return;
-		}
-		realwho = g_strdup_printf("%s@%s", who->user, who->server);
-	}
-
-	x = xmlnode_new_tag("presence");
-	xmlnode_put_attrib(x, "to", realwho);
-	xmlnode_put_attrib(x, "type", "subscribe");
-	gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x);
-	xmlnode_free(x);
-
-	jabber_roster_update(gc, realwho);
-
-	g_free(realwho);
-}
-
-static void jabber_remove_buddy(struct gaim_connection *gc, char *name, char *group)
-{
-	xmlnode x;
-	char *realwho;
-	gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc;
-
-	if (!name)
-		return;
-
-	if (!strchr(name, '@'))
-		realwho = g_strdup_printf("%s@%s", name, gjc->user->server);
-	else
-		realwho = g_strdup(name);
-
-	x = xmlnode_new_tag("presence");
-	xmlnode_put_attrib(x, "to", realwho);
-	xmlnode_put_attrib(x, "type", "unsubscribe");
-	gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x);
-	g_free(realwho);
-	xmlnode_free(x);
-}
-
-static void jabber_get_info(struct gaim_connection *gc, char *who) {
-	xmlnode x;
-	char *id;
-	char *realwho;
-	struct jabber_data *jd = gc->proto_data;
-	gjconn gjc = jd->gjc;
-
-	x = jutil_iqnew(JPACKET__GET, NS_VCARD);
-	/* Bare username? */
-	if (!strchr(who, '@')) {
-		realwho = g_strdup_printf("%s@%s", who, gjc->user->server);
-	} else {
-		realwho = g_strdup(who);
-	}
-	xmlnode_put_attrib(x, "to", realwho);
-	g_free(realwho);
-
-	id = gjab_getid(gjc);
-	xmlnode_put_attrib(x, "id", id);
-
-	g_hash_table_insert(jd->gjc->queries, g_strdup(id), g_strdup("vCard"));
-
-	gjab_send(gjc, x);
-
-	xmlnode_free(x);
-	
-}
-
-static void jabber_get_away_msg(struct gaim_connection *gc, char *who) {
-	struct jabber_data *jd = gc->proto_data;
-	gjconn gjc = jd->gjc;
-	char *status;
-
-	/* space for all elements: Jabber I.D. + "status" + NULL (list terminator) */
-	gchar **str_arr = (gchar **) g_new(gpointer, 3);
-	gchar **ap = str_arr;
-	gchar *realwho, *final;
-
-	/* Bare username? */
-	if (!strchr(who, '@')) {
-		realwho = g_strdup_printf("%s@%s", who, gjc->user->server);
-	} else {
-		realwho = g_strdup(who);
-	}
-	*ap++ = g_strdup_printf("<B>Jabber ID:</B> %s<BR>\n", realwho);
-
-	if((status = g_hash_table_lookup(jd->hash, realwho)) == NULL) {
-		status = _("Unknown");
-	}
-	*ap++ = g_strdup_printf("<B>Status:</B> %s<BR>\n", status);
-
-	*ap = NULL;
-
-	final= g_strjoinv(NULL, str_arr);
-	g_strfreev(str_arr);
-
-	g_free(realwho);
-	g_free(final);
-	
-}
-
-static GList *jabber_away_states(struct gaim_connection *gc) {
-	GList *m = NULL;
-
-	m = g_list_append(m, "Online");
-	m = g_list_append(m, "Chatty");
-	m = g_list_append(m, "Away");
-	m = g_list_append(m, "Extended Away");
-	m = g_list_append(m, "Do Not Disturb");
-
-	return m;
-}
-
-static void jabber_set_away(struct gaim_connection *gc, char *state, char *message)
-{
-	xmlnode x, y;
-	struct jabber_data *jd = gc->proto_data;
-	gjconn gjc = jd->gjc;
-
-	gc->away = NULL; /* never send an auto-response */
-
-	x = xmlnode_new_tag("presence");
-
-	if (!strcmp(state, GAIM_AWAY_CUSTOM)) {
-		/* oh goody. Gaim is telling us what to do. */
-		if (message) {
-			/* Gaim wants us to be away */
-			y = xmlnode_insert_tag(x, "show");
-			xmlnode_insert_cdata(y, "away", -1);
-			y = xmlnode_insert_tag(x, "status");
-			xmlnode_insert_cdata(y, message, -1);
-			gc->away = "";
-		} else {
-			/* Gaim wants us to not be away */
-			/* but for Jabber, we can just send presence with no other information. */
-		}
-	} else {
-		/* state is one of our own strings. it won't be NULL. */
-		if (!g_strcasecmp(state, "Online")) {
-			/* once again, we don't have to put anything here */
-		} else if (!g_strcasecmp(state, "Chatty")) {
-			y = xmlnode_insert_tag(x, "show");
-			xmlnode_insert_cdata(y, "chat", -1);
-		} else if (!g_strcasecmp(state, "Away")) {
-			y = xmlnode_insert_tag(x, "show");
-			xmlnode_insert_cdata(y, "away", -1);
-			gc->away = "";
-		} else if (!g_strcasecmp(state, "Extended Away")) {
-			y = xmlnode_insert_tag(x, "show");
-			xmlnode_insert_cdata(y, "xa", -1);
-			gc->away = "";
-		} else if (!g_strcasecmp(state, "Do Not Disturb")) {
-			y = xmlnode_insert_tag(x, "show");
-			xmlnode_insert_cdata(y, "dnd", -1);
-			gc->away = "";
-		}
-	}
-
-	gjab_send(gjc, x);
-	xmlnode_free(x);
-}
-
-static void jabber_keepalive(struct gaim_connection *gc) {
-	struct jabber_data *jd = (struct jabber_data *)gc->proto_data;
-	gjab_send_raw(jd->gjc, "  \t  ");
-}
-
-/*---------------------------------------*/
-/* Jabber "set info" (vCard) support     */
-/*---------------------------------------*/
-
-/*
- * V-Card format:
- *
- *  <vCard prodid='' version='' xmlns=''>
- *    <FN></FN>
- *    <N>
- *	<FAMILY/>
- *	<GIVEN/>
- *    </N>
- *    <NICKNAME/>
- *    <URL/>
- *    <ADR>
- *	<STREET/>
- *	<EXTADD/>
- *	<LOCALITY/>
- *	<REGION/>
- *	<PCODE/>
- *	<COUNTRY/>
- *    </ADR>
- *    <TEL/>
- *    <EMAIL/>
- *    <ORG>
- *	<ORGNAME/>
- *	<ORGUNIT/>
- *    </ORG>
- *    <TITLE/>
- *    <ROLE/>
- *    <DESC/>
- *    <BDAY/>
- *  </vCard>
- *
- * See also:
- *
- *	http://docs.jabber.org/proto/html/vcard-temp.html
- *	http://www.vcard-xml.org/dtd/vCard-XML-v2-20010520.dtd
- */
-
-/*
- * Cross-reference user-friendly V-Card entry labels to vCard XML tags
- * and attributes.
- *
- * Order is (or should be) unimportant.  For example: we have no way of
- * knowing in what order real data will arrive.
- *
- * Format: Label, Pre-set text, "visible" flag, "editable" flag, XML tag
- *         name, XML tag's parent tag "path" (relative to vCard node).
- *
- *         List is terminated by a NULL label pointer.
- *
- *	   Entries with no label text, but with XML tag and parent tag
- *	   entries, are used by V-Card XML construction routines to
- *	   "automagically" construct the appropriate XML node tree.
- *
- * Thoughts on future direction/expansion
- *
- *	This is a "simple" vCard.
- *
- *	It is possible for nodes other than the "vCard" node to have
- *      attributes.  Should that prove necessary/desirable, add an
- *      "attributes" pointer to the vcard_template struct, create the
- *      necessary tag_attr structs, and add 'em to the vcard_dflt_data
- *      array.
- *
- *	The above changes will (obviously) require changes to the vCard
- *      construction routines.
- */
-
-static struct vcard_template {
-	char *label;			/* label text pointer */
-	char *text;			/* entry text pointer */
-	int  visible;			/* should entry field be "visible?" */
-	int  editable;			/* should entry field be editable? */
-	char *tag;			/* tag text */
-	char *ptag;			/* parent tag "path" text */
-	char *url;			/* vCard display format if URL */
-} vcard_template_data[] = {
-	{N_("Full Name"),          NULL, TRUE, TRUE, "FN",        NULL,  NULL},
-	{N_("Family Name"),        NULL, TRUE, TRUE, "FAMILY",    "N",   NULL},
-	{N_("Given Name"),         NULL, TRUE, TRUE, "GIVEN",     "N",   NULL},
-	{N_("Nickname"),           NULL, TRUE, TRUE, "NICKNAME",  NULL,  NULL},
-	{N_("URL"),                NULL, TRUE, TRUE, "URL",       NULL,  "<A HREF=\"%s\">%s</A>"},
-	{N_("Street Address"),     NULL, TRUE, TRUE, "STREET",    "ADR", NULL},
-	{N_("Extended Address"),   NULL, TRUE, TRUE, "EXTADD",    "ADR", NULL},
-	{N_("Locality"),           NULL, TRUE, TRUE, "LOCALITY",  "ADR", NULL},
-	{N_("Region"),             NULL, TRUE, TRUE, "REGION",    "ADR", NULL},
-	{N_("Postal Code"),        NULL, TRUE, TRUE, "PCODE",     "ADR", NULL},
-	{N_("Country"),            NULL, TRUE, TRUE, "COUNTRY",   "ADR", NULL},
-	{N_("Telephone"),          NULL, TRUE, TRUE, "TELEPHONE", NULL,  NULL},
-	{N_("Email"),              NULL, TRUE, TRUE, "EMAIL",     NULL,  "<A HREF=\"mailto:%s\">%s</A>"},
-	{N_("Organization Name"),  NULL, TRUE, TRUE, "ORGNAME",   "ORG", NULL},
-	{N_("Organization Unit"),  NULL, TRUE, TRUE, "ORGUNIT",   "ORG", NULL},
-	{N_("Title"),              NULL, TRUE, TRUE, "TITLE",     NULL,  NULL},
-	{N_("Role"),               NULL, TRUE, TRUE, "ROLE",      NULL,  NULL},
-	{N_("Birthday"),           NULL, TRUE, TRUE, "BDAY",      NULL,  NULL},
-	{N_("Description"),        NULL, TRUE, TRUE, "DESC",      NULL,  NULL},
-	{"", NULL, TRUE, TRUE, "N",     NULL, NULL},
-	{"", NULL, TRUE, TRUE, "ADR",   NULL, NULL},
-	{"", NULL, TRUE, TRUE, "ORG",   NULL, NULL},
-	{NULL, NULL, 0, 0, NULL, NULL, NULL}
-};
-
-/*
- * Used by routines to parse an XML-encoded string into an xmlnode tree
- */
-typedef struct {
-	XML_Parser parser;
-	xmlnode current;
-} *xmlstr2xmlnode_parser, xmlstr2xmlnode_parser_struct;
-
-
-/*
- * Used by XML_Parse on parsing CDATA
- */
-static void xmlstr2xmlnode_charData(void *userdata, const char *s, int slen)
-{
-	xmlstr2xmlnode_parser xmlp = (xmlstr2xmlnode_parser) userdata;
-
-	if (xmlp->current)
-		xmlnode_insert_cdata(xmlp->current, s, slen);
-}
-
-/*
- * Used by XML_Parse to start or append to an xmlnode
- */
-static void xmlstr2xmlnode_startElement(void *userdata, const char *name, const char **attribs)
-{
-	xmlnode x;
-	xmlstr2xmlnode_parser xmlp = (xmlstr2xmlnode_parser) userdata;
-
-	if (xmlp->current) {
-		/* Append the node to the current one */
-		x = xmlnode_insert_tag(xmlp->current, name);
-		xmlnode_put_expat_attribs(x, attribs);
-
-		xmlp->current = x;
-	} else {
-		x = xmlnode_new_tag(name);
-		xmlnode_put_expat_attribs(x, attribs);
-		xmlp->current = x;
-	}
-}
-
-/*
- * Used by XML_Parse to end an xmlnode
- */
-static void xmlstr2xmlnode_endElement(void *userdata, const char *name)
-{
-	xmlstr2xmlnode_parser xmlp = (xmlstr2xmlnode_parser) userdata;
-	xmlnode x;
-
-	if (xmlp->current != NULL && (x = xmlnode_get_parent(xmlp->current)) != NULL) {
-		xmlp->current = x;
-	}
-}
-
-/*
- * Parse an XML-encoded string into an xmlnode tree
- *
- * Caller is responsible for freeing the returned xmlnode
- */
-static xmlnode xmlstr2xmlnode(char *xmlstring)
-{
-	xmlstr2xmlnode_parser my_parser = g_new(xmlstr2xmlnode_parser_struct, 1);
-	xmlnode x = NULL;
-
-	my_parser->parser = XML_ParserCreate(NULL);
-	my_parser->current = NULL;
-
-	XML_SetUserData(my_parser->parser, (void *)my_parser);
-	XML_SetElementHandler(my_parser->parser, xmlstr2xmlnode_startElement, xmlstr2xmlnode_endElement);
-	XML_SetCharacterDataHandler(my_parser->parser, xmlstr2xmlnode_charData);
-	XML_Parse(my_parser->parser, xmlstring, strlen(xmlstring), 0);
-
-	x = my_parser->current;
-
-	XML_ParserFree(my_parser->parser);
-	g_free(my_parser);
-
-	return(x);
-}
-
-/*
- * Insert a tag node into an xmlnode tree, recursively inserting parent tag
- * nodes as necessary
- *
- * Returns pointer to inserted node
- *
- * Note to hackers: this code is designed to be re-entrant (it's recursive--it
- * calls itself), so don't put any "static"s in here!
- */
-static xmlnode insert_tag_to_parent_tag(xmlnode start, const char *parent_tag, const char *new_tag)
-{
-	xmlnode x = NULL;
-
-	/*
-	 * If the parent tag wasn't specified, see if we can get it
-	 * from the vCard template struct.
-	 */
-	if(parent_tag == NULL) {
-		struct vcard_template *vc_tp = vcard_template_data;
-
-		while(vc_tp->label != NULL) {
-			if(strcmp(vc_tp->tag, new_tag) == 0) {
-				parent_tag = vc_tp->ptag;
-				break;
-			}
-			++vc_tp;
-		}
-	}
-
-	/*
-	 * If we have a parent tag...
-	 */
-	if(parent_tag != NULL ) {
-		/*
-		 * Try to get the parent node for a tag
-		 */
-		if((x = xmlnode_get_tag(start, parent_tag)) == NULL) {
-			/*
-			 * Descend?
-			 */
-			char *grand_parent = strcpy(g_malloc(strlen(parent_tag) + 1), parent_tag);
-			char *parent;
-
-			if((parent = strrchr(grand_parent, '/')) != NULL) {
-				*(parent++) = '\0';
-				x = insert_tag_to_parent_tag(start, grand_parent, parent);
-			} else {
-				x = xmlnode_insert_tag(start, grand_parent);
-			}
-			g_free(grand_parent);
-		} else {
-			/*
-			 * We found *something* to be the parent node.
-			 * Note: may be the "root" node!
-			 */
-			xmlnode y;
-			if((y = xmlnode_get_tag(x, new_tag)) != NULL) {
-				return(y);
-			}
-		}
-	}
-
-	/*
-	 * insert the new tag into its parent node
-	 */
-	return(xmlnode_insert_tag((x == NULL? start : x), new_tag));
-}
-
-/*
- * Send vCard info to Jabber server
- */
-static void jabber_set_info(struct gaim_connection *gc, char *info)
-{
-	xmlnode x, vc_node;
-	char *id;
-	struct jabber_data *jd = gc->proto_data;
-	gjconn gjc = jd->gjc;
-
-	x = xmlnode_new_tag("iq");
-	xmlnode_put_attrib(x,"type","set");
-
-	id = gjab_getid(gjc);
-	
-	xmlnode_put_attrib(x, "id", id);
-
-	/*
-	 * Send only if there's actually any *information* to send
-	 */
-	if((vc_node = xmlstr2xmlnode(info)) != NULL && xmlnode_get_name(vc_node) != NULL &&
-			g_strncasecmp(xmlnode_get_name(vc_node), "vcard", 5) == 0) {
-		xmlnode_insert_tag_node(x, vc_node);
-		gjab_send(gjc, x);
-	}
-
-	xmlnode_free(x);
-}
-
-/*
- * displays a Jabber vCard
- */
-static void jabber_handlevcard(gjconn gjc, xmlnode querynode, char *from)
-{
-	struct jabber_data *jd = GJ_GC(gjc)->proto_data;
-	jid who = jid_new(gjc->p, from);
-	char *status = NULL, *text = NULL;
-	GString *str = g_string_sized_new(100);
-	xmlnode child;
-
-	gchar *buddy = NULL;
-	
-	if(querynode == NULL) {
-		serv_got_crap(GJ_GC(gjc), "%s - Received empty info reply from %s", _("User Info"), from);
-		return;
-	}
-
-	if(who->resource != NULL && (who->resource)[0] != '\0') {
-		buddy = g_strdup_printf("%s@%s/%s", who->user, who->server, who->resource);
-	} else {
-		buddy = g_strdup_printf("%s@%s", who->user, who->server);
-	}
-
-	if((status = g_hash_table_lookup(jd->hash, buddy)) == NULL) {
-		status = _("Unknown");
-	}
-
-	g_string_sprintfa(str, "%s: %s - %s: %s", _("Jabber ID"), buddy, _("Status"),
-	                       status);
-
-	for(child = querynode->firstchild; child; child = child->next)
-	{
-		xmlnode child2;
-
-		if(child->type != NTYPE_TAG)
-			continue;
-
-		text = xmlnode_get_data(child);
-		if(text && !strcmp(child->name, "FN")) {
-			info_string_append(str, "\n", _("Full Name"), text);
-		} else if (!strcmp(child->name, "N")) {
-			for (child2 = child->firstchild; child2; child2 = child2->next) {
-				char *text2 = NULL;
-
-				if (child2->type != NTYPE_TAG)
-					continue;
-
-				text2 = xmlnode_get_data(child2);
-				if (text2 && !strcmp(child2->name, "FAMILY")) {
-					info_string_append(str, "\n", _("Family Name"), text2);
-				} else if (text2 && !strcmp(child2->name, "GIVEN")) {
-					info_string_append(str, "\n", _("Given Name"), text2);
-				} else if (text2 && !strcmp(child2->name, "MIDDLE")) {
-					info_string_append(str, "\n", _("Middle Name"), text2);
-				}
-			}
-		} else if (text && !strcmp(child->name, "NICKNAME")) {
-			info_string_append(str, "\n", _("Nickname"), text);
-		} else if (text && !strcmp(child->name, "BDAY")) {
-			info_string_append(str, "\n", _("Birthday"), text);
-		} else if (!strcmp(child->name, "ADR")) {
-			/* show wich address it is */
-			/* Just for the beauty of bitlbee 
-			if (child->firstchild)
-				g_string_sprintfa(str, "%s:\n", _("Address"));
-			*/
-			for(child2 = child->firstchild; child2; child2 = child2->next) {
-				char *text2 = NULL;
-
-				if(child2->type != NTYPE_TAG)
-					continue;
-
-				text2 = xmlnode_get_data(child2);
-				if(text2 && !strcmp(child2->name, "POBOX")) {
-					info_string_append(str, "\n",
-							_("P.O. Box"), text2);
-				} else if(text2 && !strcmp(child2->name, "EXTADR")) {
-					info_string_append(str, "\n",
-							_("Extended Address"), text2);
-				} else if(text2 && !strcmp(child2->name, "STREET")) {
-					info_string_append(str, "\n",
-							_("Street Address"), text2);
-				} else if(text2 && !strcmp(child2->name, "LOCALITY")) {
-					info_string_append(str, "\n",
-							_("Locality"), text2);
-				} else if(text2 && !strcmp(child2->name, "REGION")) {
-					info_string_append(str, "\n",
-							_("Region"), text2);
-				} else if(text2 && !strcmp(child2->name, "PCODE")) {
-					info_string_append(str, "\n",
-							_("Postal Code"), text2);
-				} else if(text2 && (!strcmp(child2->name, "CTRY")
-							|| !strcmp(child2->name, "COUNTRY"))) {
-					info_string_append(str, "\n", _("Country"), text2);
-				}
-			}
-		} else if(!strcmp(child->name, "TEL")) {
-			char *number = NULL;
-			if ((child2 = xmlnode_get_tag(child, "NUMBER"))) {
-				/* show what kind of number it is */
-				number = xmlnode_get_data(child2);
-				if(number) {
-					info_string_append(str, "\n", _("Telephone"), number);
-				}
-			} else if((number = xmlnode_get_data(child))) {
-				/* lots of clients (including gaim) do this,
-				 * but it's out of spec */
-				info_string_append(str, "\n", _("Telephone"), number);
-			}
-		} else if(!strcmp(child->name, "EMAIL")) {
-			char *userid = NULL;
-			if((child2 = xmlnode_get_tag(child, "USERID"))) {
-				/* show what kind of email it is */
-				userid = xmlnode_get_data(child2);
-				if(userid) {
-					info_string_append(str, "\n", _("Email"), userid);
-				}
-			} else if((userid = xmlnode_get_data(child))) {
-				/* lots of clients (including gaim) do this,
-				 * but it's out of spec */
-				info_string_append(str, "\n", _("Email"), userid);
-			}
-		} else if(!strcmp(child->name, "ORG")) {
-			for(child2 = child->firstchild; child2; child2 = child2->next) {
-				char *text2 = NULL;
-
-				if(child2->type != NTYPE_TAG)
-					continue;
-
-				text2 = xmlnode_get_data(child2);
-				if(text2 && !strcmp(child2->name, "ORGNAME")) {
-					info_string_append(str, "\n", _("Organization Name"), text2);
-				} else if(text2 && !strcmp(child2->name, "ORGUNIT")) {
-					info_string_append(str, "\n", _("Organization Unit"), text2);
-				}
-			}
-		} else if(text && !strcmp(child->name, "TITLE")) {
-			info_string_append(str, "\n", _("Title"), text);
-		} else if(text && !strcmp(child->name, "ROLE")) {
-			info_string_append(str, "\n", _("Role"), text);
-		} else if(text && !strcmp(child->name, "DESC")) {
-			g_string_sprintfa(str, "\n%s:\n%s\n%s", _("Description"), 
-					text, _("End of Description"));
-		}
-	}
-
-	serv_got_crap(GJ_GC(gjc), "%s\n%s", _("User Info"), str->str);
-
-	g_free(buddy);
-	g_string_free(str, TRUE);
-}
-
 void jabber_init()
 {
-	struct prpl *ret = g_new0(struct prpl, 1);
-
+	struct prpl *ret = g_new0( struct prpl, 1 );
+	
 	ret->name = "jabber";
-	ret->away_states = jabber_away_states;
+	ret->login = jabber_login;
 	ret->acc_init = jabber_acc_init;
-	ret->login = jabber_login;
 	ret->close = jabber_close;
 	ret->send_im = jabber_send_im;
-	ret->set_info = jabber_set_info;
+	ret->away_states = jabber_away_states;
+//	ret->get_status_string = jabber_get_status_string;
+	ret->set_away = jabber_set_away;
+//	ret->set_info = jabber_set_info;
 	ret->get_info = jabber_get_info;
-	ret->set_away = jabber_set_away;
-	ret->get_away = jabber_get_away_msg;
 	ret->add_buddy = jabber_add_buddy;
 	ret->remove_buddy = jabber_remove_buddy;
+//	ret->chat_send = jabber_chat_send;
+//	ret->chat_invite = jabber_chat_invite;
+//	ret->chat_leave = jabber_chat_leave;
+//	ret->chat_open = jabber_chat_open;
 	ret->keepalive = jabber_keepalive;
-	ret->alias_buddy = jabber_roster_update;
-	ret->group_buddy = jabber_group_change;
+	ret->send_typing = jabber_send_typing;
 	ret->handle_cmp = g_strcasecmp;
 
-	register_protocol (ret);
-}
+	register_protocol( ret );
+}
Index: protocols/jabber/jabber.h
===================================================================
--- protocols/jabber/jabber.h	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ protocols/jabber/jabber.h	(revision 0fd8559c4a6ad84ad0852e07c4ba2e50b2fdf0ad)
@@ -1,315 +1,191 @@
-/*
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- *  Jabber
- *  Copyright (C) 1998-1999 The Jabber Team http://jabber.org/
- */
+/***************************************************************************\
+*                                                                           *
+*  BitlBee - An IRC to IM gateway                                           *
+*  Jabber module - Main file                                                *
+*                                                                           *
+*  Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net>                   *
+*                                                                           *
+*  This program is free software; you can redistribute it and/or modify     *
+*  it under the terms of the GNU General Public License as published by     *
+*  the Free Software Foundation; either version 2 of the License, or        *
+*  (at your option) any later version.                                      *
+*                                                                           *
+*  This program is distributed in the hope that it will be useful,          *
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
+*  GNU General Public License for more details.                             *
+*                                                                           *
+*  You should have received a copy of the GNU General Public License along  *
+*  with this program; if not, write to the Free Software Foundation, Inc.,  *
+*  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.              *
+*                                                                           *
+\***************************************************************************/
 
-#include <string.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <stdio.h>
-#include <setjmp.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <time.h>
-#include <ctype.h>
-#ifdef _WIN32
-#undef DATADIR
-#include "sock.h"
+#ifndef _JABBER_H
+#define _JABBER_H
+
+#include <glib.h>
+
+#include "xmltree.h"
+#include "bitlbee.h"
+
+typedef enum
+{
+	JFLAG_STREAM_STARTED = 1,	/* Set when we detected the beginning of the stream
+	                                   and want to do auth. */
+	JFLAG_AUTHENTICATED = 2,	/* Set when we're successfully authenticatd. */
+	JFLAG_STREAM_RESTART = 4,	/* Set when we want to restart the stream (after
+	                                   SASL or TLS). */
+	JFLAG_WAIT_SESSION = 8,		/* Set if we sent a <session> tag and need a reply
+	                                   before we continue. */
+	JFLAG_WAIT_BIND = 16,		/* ... for <bind> tag. */
+	JFLAG_WANT_TYPING = 32,		/* Set if we ever sent a typing notification, this
+	                                   activates all XEP-85 related code. */
+} jabber_flags_t;
+
+typedef enum
+{
+	JBFLAG_PROBED_XEP85 = 1,	/* Set this when we sent our probe packet to make
+	                                   sure it gets sent only once. */
+	JBFLAG_DOES_XEP85 = 2,		/* Set this when the resource seems to support
+	                                   XEP85 (typing notification shite). */
+} jabber_buddy_flags_t;
+
+struct jabber_data
+{
+	struct gaim_connection *gc;
+	
+	int fd;
+	void *ssl;
+	char *txq;
+	int tx_len;
+	int r_inpa, w_inpa;
+	
+	struct xt_parser *xt;
+	jabber_flags_t flags;
+	
+	char *username;		/* USERNAME@server */
+	char *server;		/* username@SERVER -=> server/domain, not hostname */
+	
+	/* After changing one of these two (or the priority setting), call
+	   presence_send_update() to inform the server about the changes. */
+	struct jabber_away_state *away_state;
+	char *away_message;
+	
+	GHashTable *node_cache;
+	GHashTable *buddies;
+};
+
+struct jabber_away_state
+{
+	char code[5];
+	char *full_name;
+};
+
+typedef xt_status (*jabber_cache_event) ( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig );
+
+struct jabber_cache_entry
+{
+	struct xt_node *node;
+	jabber_cache_event func;
+};
+
+struct jabber_buddy
+{
+	char *bare_jid;
+	char *full_jid;
+	char *resource;
+	
+	int priority;
+	struct jabber_away_state *away_state;
+	char *away_message;
+	
+	time_t last_act;
+	jabber_buddy_flags_t flags;
+	
+	struct jabber_buddy *next;
+};
+
+/* Prefixes to use for packet IDs (mainly for IQ packets ATM). Usually the
+   first one should be used, but when storing a packet in the cache, a
+   "special" kind of ID is assigned to make it easier later to figure out
+   if we have to do call an event handler for the response packet. */
+#define JABBER_PACKET_ID "BeeP"
+#define JABBER_CACHED_ID "BeeC"
+
+/* RFC 392[01] stuff */
+#define XMLNS_TLS          "urn:ietf:params:xml:ns:xmpp-tls"
+#define XMLNS_SASL         "urn:ietf:params:xml:ns:xmpp-sasl"
+#define XMLNS_BIND         "urn:ietf:params:xml:ns:xmpp-bind"
+#define XMLNS_SESSION      "urn:ietf:params:xml:ns:xmpp-session"
+#define XMLNS_STANZA_ERROR "urn:ietf:params:xml:ns:xmpp-stanzas"
+#define XMLNS_STREAM_ERROR "urn:ietf:params:xml:ns:xmpp-streams"
+#define XMLNS_ROSTER       "jabber:iq:roster"
+
+/* Some supported extensions/legacy stuff */
+#define XMLNS_AUTH         "jabber:iq:auth"                     /* XEP-0078 */
+#define XMLNS_VERSION      "jabber:iq:version"                  /* XEP-0092 */
+#define XMLNS_TIME         "jabber:iq:time"                     /* XEP-0090 */
+#define XMLNS_VCARD        "vcard-temp"                         /* XEP-0054 */
+#define XMLNS_CHATSTATES   "http://jabber.org/protocol/chatstates"  /* 0085 */
+#define XMLNS_DISCOVER     "http://jabber.org/protocol/disco#info"  /* 0030 */
+
+/* iq.c */
+xt_status jabber_pkt_iq( struct xt_node *node, gpointer data );
+int jabber_init_iq_auth( struct gaim_connection *gc );
+xt_status jabber_pkt_bind_sess( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig );
+int jabber_get_roster( struct gaim_connection *gc );
+int jabber_get_vcard( struct gaim_connection *gc, char *bare_jid );
+int jabber_add_to_roster( struct gaim_connection *gc, char *handle, char *name );
+int jabber_remove_from_roster( struct gaim_connection *gc, char *handle );
+
+/* message.c */
+xt_status jabber_pkt_message( struct xt_node *node, gpointer data );
+
+/* presence.c */
+xt_status jabber_pkt_presence( struct xt_node *node, gpointer data );
+int presence_send_update( struct gaim_connection *gc );
+int presence_send_request( struct gaim_connection *gc, char *handle, char *request );
+
+/* jabber_util.c */
+char *set_eval_priority( set_t *set, char *value );
+char *set_eval_tls( set_t *set, char *value );
+struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children );
+struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type );
+void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node, jabber_cache_event func );
+struct xt_node *jabber_cache_get( struct gaim_connection *gc, char *id );
+void jabber_cache_entry_free( gpointer entry );
+void jabber_cache_clean( struct gaim_connection *gc );
+const struct jabber_away_state *jabber_away_state_by_code( char *code );
+const struct jabber_away_state *jabber_away_state_by_name( char *name );
+void jabber_buddy_ask( struct gaim_connection *gc, char *handle );
+char *jabber_normalize( char *orig );
+
+typedef enum
+{
+	GET_BUDDY_CREAT = 1,	/* Try to create it, if necessary. */
+	GET_BUDDY_EXACT = 2,	/* Get an exact message (only makes sense with bare JIDs). */
+} get_buddy_flags_t;
+
+struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_jid );
+struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid, get_buddy_flags_t flags );
+int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid );
+int jabber_buddy_remove_bare( struct gaim_connection *gc, char *bare_jid );
+
+extern const struct jabber_away_state jabber_away_state_list[];
+
+/* io.c */
+int jabber_write_packet( struct gaim_connection *gc, struct xt_node *node );
+int jabber_write( struct gaim_connection *gc, char *buf, int len );
+gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition cond );
+gboolean jabber_connected_ssl( gpointer data, void *source, b_input_condition cond );
+gboolean jabber_start_stream( struct gaim_connection *gc );
+void jabber_end_stream( struct gaim_connection *gc );
+
+/* sasl.c */
+xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data );
+xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data );
+xt_status sasl_pkt_result( struct xt_node *node, gpointer data );
+gboolean sasl_supported( struct gaim_connection *gc );
+
 #endif
-
-#include "lib.h"
-
-
-#ifndef INCL_JABBER_H
-#define INCL_JABBER_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* --------------------------------------------------------- */
-/*                                                           */
-/* JID structures & constants                                */
-/*                                                           */
-/* --------------------------------------------------------- */
-#define JID_RESOURCE 1
-#define JID_USER     2
-#define JID_SERVER   4
-
-typedef struct jid_struct
-{ 
-    pool               p;
-    char*              resource;
-    char*              user;
-    char*              server;
-    char*              full;
-    struct jid_struct *next; /* for lists of jids */
-} *jid;
-  
-jid     jid_new(pool p, char *idstr);	       /* Creates a jabber id from the idstr */
-void    jid_set(jid id, char *str, int item);  /* Individually sets jid components */
-char*   jid_full(jid id);		       /* Builds a string type=user/resource@server from the jid data */
-int     jid_cmp(jid a, jid b);		       /* Compares two jid's, returns 0 for perfect match */
-int     jid_cmpx(jid a, jid b, int parts);     /* Compares just the parts specified as JID_|JID_ */
-jid     jid_append(jid a, jid b);	       /* Appending b to a (list), no dups */
-xmlnode jid_xres(jid id);		       /* Returns xmlnode representation of the resource?query=string */
-xmlnode jid_nodescan(jid id, xmlnode x);       /* Scans the children of the node for a matching jid attribute */
-jid     jid_user(jid a);                       /* returns the same jid but just of the user@host part */
-
-
-/* --------------------------------------------------------- */
-/*                                                           */
-/* JPacket structures & constants                            */
-/*                                                           */
-/* --------------------------------------------------------- */
-#define JPACKET_UNKNOWN   0x00
-#define JPACKET_MESSAGE   0x01
-#define JPACKET_PRESENCE  0x02
-#define JPACKET_IQ        0x04
-#define JPACKET_S10N      0x08
-
-#define JPACKET__UNKNOWN      0
-#define JPACKET__NONE         1
-#define JPACKET__ERROR        2
-#define JPACKET__CHAT         3
-#define JPACKET__GROUPCHAT    4
-#define JPACKET__GET          5
-#define JPACKET__SET          6
-#define JPACKET__RESULT       7
-#define JPACKET__SUBSCRIBE    8
-#define JPACKET__SUBSCRIBED   9
-#define JPACKET__UNSUBSCRIBE  10
-#define JPACKET__UNSUBSCRIBED 11
-#define JPACKET__AVAILABLE    12
-#define JPACKET__UNAVAILABLE  13
-#define JPACKET__PROBE        14
-#define JPACKET__HEADLINE     15
-#define JPACKET__INVISIBLE    16
-
-typedef struct jpacket_struct
-{
-    unsigned char type;
-    int           subtype;
-    int           flag;
-    void*         aux1;
-    xmlnode       x;
-    jid           to;
-    jid           from;
-    char*         iqns;
-    xmlnode       iq;
-    pool          p;
-} *jpacket, _jpacket;
- 
-jpacket jpacket_new(xmlnode x);	    /* Creates a jabber packet from the xmlnode */
-int     jpacket_subtype(jpacket p); /* Returns the subtype value (looks at xmlnode for it) */
-
-
-/* --------------------------------------------------------- */
-/*                                                           */
-/* Presence Proxy DB structures & constants                  */
-/*                                                           */
-/* --------------------------------------------------------- */
-typedef struct ppdb_struct
-{			      
-    jid     id;		       /* entry data */
-    int     pri;
-    xmlnode x;
-    struct ppdb_struct* user;  /* linked list for user@server */
-    pool                p;     /* db-level data */
-    struct ppdb_struct* next;
-} _ppdb, *ppdb;
-
-ppdb    ppdb_insert(ppdb db, jid id, xmlnode x); /* Inserts presence into the proxy */
-xmlnode ppdb_primary(ppdb db, jid id);		 /* Fetches the matching primary presence for the id */
-void    ppdb_free(ppdb db);			 /* Frees the db and all entries */
-xmlnode ppdb_get(ppdb db, jid id);		 /* Called successively to return each presence xmlnode */
-						 /*   for the id and children, returns NULL at the end */
-
-
-/* --------------------------------------------------------- */
-/*                                                           */
-/* Simple Jabber Rate limit functions                        */
-/*                                                           */
-/* --------------------------------------------------------- */
-typedef struct jlimit_struct
-{
-    char *key;
-    int start;
-    int points;
-    int maxt, maxp;
-    pool p;
-} *jlimit, _jlimit;
- 
-jlimit jlimit_new(int maxt, int maxp);
-void jlimit_free(jlimit r);
-int jlimit_check(jlimit r, char *key, int points);
-
-
-/* --------------------------------------------------------- */
-/*                                                           */
-/* Error structures & constants                              */
-/*                                                           */
-/* --------------------------------------------------------- */
-typedef struct terror_struct
-{
-    int  code;
-    char msg[64];
-} terror;
-
-#define TERROR_BAD           (terror){400,"Bad Request"}
-#define TERROR_AUTH          (terror){401,"Unauthorized"}
-#define TERROR_PAY           (terror){402,"Payment Required"}
-#define TERROR_FORBIDDEN     (terror){403,"Forbidden"}
-#define TERROR_NOTFOUND      (terror){404,"Not Found"}
-#define TERROR_NOTALLOWED    (terror){405,"Not Allowed"}
-#define TERROR_NOTACCEPTABLE (terror){406,"Not Acceptable"}
-#define TERROR_REGISTER      (terror){407,"Registration Required"}
-#define TERROR_REQTIMEOUT    (terror){408,"Request Timeout"}
-#define TERROR_CONFLICT      (terror){409,"Conflict"}
-
-#define TERROR_INTERNAL   (terror){500,"Internal Server Error"}
-#define TERROR_NOTIMPL    (terror){501,"Not Implemented"}
-#define TERROR_EXTERNAL   (terror){502,"Remote Server Error"}
-#define TERROR_UNAVAIL    (terror){503,"Service Unavailable"}
-#define TERROR_EXTTIMEOUT (terror){504,"Remote Server Timeout"}
-#define TERROR_DISCONNECTED (terror){510,"Disconnected"}
-
-/* --------------------------------------------------------- */
-/*                                                           */
-/* Namespace constants                                       */
-/*                                                           */
-/* --------------------------------------------------------- */
-#define NSCHECK(x,n) (j_strcmp(xmlnode_get_attrib(x,"xmlns"),n) == 0)
-
-#define NS_CLIENT    "jabber:client"
-#define NS_SERVER    "jabber:server"
-#define NS_AUTH      "jabber:iq:auth"
-#define NS_REGISTER  "jabber:iq:register"
-#define NS_ROSTER    "jabber:iq:roster"
-#define NS_OFFLINE   "jabber:x:offline"
-#define NS_AGENT     "jabber:iq:agent"
-#define NS_AGENTS    "jabber:iq:agents"
-#define NS_DELAY     "jabber:x:delay"
-#define NS_VERSION   "jabber:iq:version"
-#define NS_TIME      "jabber:iq:time"
-#define NS_VCARD     "vcard-temp"
-#define NS_PRIVATE   "jabber:iq:private"
-#define NS_SEARCH    "jabber:iq:search"
-#define NS_OOB       "jabber:iq:oob"
-#define NS_XOOB      "jabber:x:oob"
-#define NS_ADMIN     "jabber:iq:admin"
-#define NS_FILTER    "jabber:iq:filter"
-#define NS_AUTH_0K   "jabber:iq:auth:0k"
-
-
-/* --------------------------------------------------------- */
-/*                                                           */
-/* Message Types                                             */
-/*                                                           */
-/* --------------------------------------------------------- */
-#define TMSG_NORMAL	"normal"
-#define TMSG_ERROR	"error"
-#define TMSG_CHAT	"chat"
-#define TMSG_GROUPCHAT	"groupchat"
-#define TMSG_HEADLINE	"headline"
-
-
-/* --------------------------------------------------------- */
-/*                                                           */
-/* JUtil functions                                           */
-/*                                                           */
-/* --------------------------------------------------------- */
-xmlnode jutil_presnew(int type, char *to, char *status); /* Create a skeleton presence packet */
-xmlnode jutil_iqnew(int type, char *ns);		 /* Create a skeleton iq packet */
-xmlnode jutil_msgnew(char *type, char *to, char *subj, char *body);
-							 /* Create a skeleton message packet */
-xmlnode jutil_header(char* xmlns, char* server);	 /* Create a skeleton stream packet */
-int     jutil_priority(xmlnode x);			 /* Determine priority of this packet */
-void    jutil_tofrom(xmlnode x);			 /* Swaps to/from fields on a packet */
-xmlnode jutil_iqresult(xmlnode x);			 /* Generate a skeleton iq/result, given a iq/query */
-char*   jutil_timestamp(void);				 /* Get stringified timestamp */
-void    jutil_error(xmlnode x, terror E);		 /* Append an <error> node to x */
-void    jutil_delay(xmlnode msg, char *reason);		 /* Append a delay packet to msg */
-char*   jutil_regkey(char *key, char *seed);		 /* pass a seed to generate a key, pass the key again to validate (returns it) */
-
-
-/* --------------------------------------------------------- */
-/*                                                           */
-/* JConn structures & functions                              */
-/*                                                           */
-/* --------------------------------------------------------- */
-#define JCONN_STATE_OFF       0
-#define JCONN_STATE_CONNECTED 1
-#define JCONN_STATE_ON        2
-#define JCONN_STATE_AUTH      3
-
-typedef struct jconn_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.. */
-
-    /* Event callback ptrs */
-    void (*on_state)(struct jconn_struct *j, int state);
-    void (*on_packet)(struct jconn_struct *j, jpacket p);
-
-} *jconn, jconn_struct;
-
-typedef void (*jconn_state_h)(jconn j, int state);
-typedef void (*jconn_packet_h)(jconn j, jpacket p);
-
-
-jconn jab_new(char *user, char *pass);
-void jab_delete(jconn j);
-void jab_state_handler(jconn j, jconn_state_h h);
-void jab_packet_handler(jconn j, jconn_packet_h h);
-void jab_start(jconn j);
-void jab_stop(jconn j);
-
-int jab_getfd(jconn j);
-jid jab_getjid(jconn j);
-char *jab_getsid(jconn j);
-char *jab_getid(jconn j);
-
-void jab_send(jconn j, xmlnode x);
-void jab_send_raw(jconn j, const char *str);
-void jab_recv(jconn j);
-void jab_poll(jconn j, int timeout);
-
-char *jab_auth(jconn j);
-char *jab_reg(jconn j);
-
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif	/* INCL_JABBER_H */
Index: protocols/jabber/jabber_util.c
===================================================================
--- protocols/jabber/jabber_util.c	(revision 0fd8559c4a6ad84ad0852e07c4ba2e50b2fdf0ad)
+++ protocols/jabber/jabber_util.c	(revision 0fd8559c4a6ad84ad0852e07c4ba2e50b2fdf0ad)
@@ -0,0 +1,532 @@
+/***************************************************************************\
+*                                                                           *
+*  BitlBee - An IRC to IM gateway                                           *
+*  Jabber module - Misc. stuff                                              *
+*                                                                           *
+*  Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net>                   *
+*                                                                           *
+*  This program is free software; you can redistribute it and/or modify     *
+*  it under the terms of the GNU General Public License as published by     *
+*  the Free Software Foundation; either version 2 of the License, or        *
+*  (at your option) any later version.                                      *
+*                                                                           *
+*  This program is distributed in the hope that it will be useful,          *
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
+*  GNU General Public License for more details.                             *
+*                                                                           *
+*  You should have received a copy of the GNU General Public License along  *
+*  with this program; if not, write to the Free Software Foundation, Inc.,  *
+*  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.              *
+*                                                                           *
+\***************************************************************************/
+
+#include "jabber.h"
+
+static unsigned int next_id = 1;
+
+char *set_eval_priority( set_t *set, char *value )
+{
+	account_t *acc = set->data;
+	int i;
+	
+	if( sscanf( value, "%d", &i ) == 1 )
+	{
+		/* Priority is a signed 8-bit integer, according to RFC 3921. */
+		if( i < -128 || i > 127 )
+			return NULL;
+	}
+	else
+		return NULL;
+	
+	/* Only run this stuff if the account is online ATM,
+	   and if the setting seems to be acceptable. */
+	if( acc->gc )
+	{
+		/* Although set_eval functions usually are very nice and
+		   convenient, they have one disadvantage: If I would just
+		   call p_s_u() now to send the new prio setting, it would
+		   send the old setting because the set->value gets changed
+		   when the eval returns a non-NULL value.
+		   
+		   So now I can choose between implementing post-set
+		   functions next to evals, or just do this little hack: */
+		
+		g_free( set->value );
+		set->value = g_strdup( value );
+		
+		/* (Yes, sorry, I prefer the hack. :-P) */
+		
+		presence_send_update( acc->gc );
+	}
+	
+	return value;
+}
+
+char *set_eval_tls( set_t *set, char *value )
+{
+	if( g_strcasecmp( value, "try" ) == 0 )
+		return value;
+	else
+		return set_eval_bool( set, value );
+}
+
+struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children )
+{
+	struct xt_node *node;
+	
+	node = xt_new_node( name, NULL, children );
+	
+	if( type )
+		xt_add_attr( node, "type", type );
+	if( to )
+		xt_add_attr( node, "to", to );
+	
+	/* IQ packets should always have an ID, so let's generate one. It
+	   might get overwritten by jabber_cache_add() if this packet has
+	   to be saved until we receive a response. Cached packets get
+	   slightly different IDs so we can recognize them. */
+	if( strcmp( name, "iq" ) == 0 )
+	{
+		char *id = g_strdup_printf( "%s%05x", JABBER_PACKET_ID, ( next_id++ ) & 0xfffff );
+		xt_add_attr( node, "id", id );
+		g_free( id );
+	}
+	
+	return node;
+}
+
+struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type )
+{
+	struct xt_node *node, *c;
+	char *to;
+	
+	/* Create the "defined-condition" tag. */
+	c = xt_new_node( err_cond, NULL, NULL );
+	xt_add_attr( c, "xmlns", XMLNS_STANZA_ERROR );
+	
+	/* Put it in an <error> tag. */
+	c = xt_new_node( "error", NULL, c );
+	xt_add_attr( c, "type", err_type );
+	
+	/* To make the actual error packet, we copy the original packet and
+	   add our <error>/type="error" tag. Including the original packet
+	   is recommended, so let's just do it. */
+	node = xt_dup( orig );
+	xt_add_child( node, c );
+	xt_add_attr( node, "type", "error" );
+	
+	/* Return to sender. */
+	if( ( to = xt_find_attr( node, "from" ) ) )
+	{
+		xt_add_attr( node, "to", to );
+		xt_remove_attr( node, "from" );
+	}
+		
+	return node;
+}
+
+/* Cache a node/packet for later use. Mainly useful for IQ packets if you need
+   them when you receive the response. Use this BEFORE sending the packet so
+   it'll get a new id= tag, and do NOT free() the packet after writing it! */
+void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node, jabber_cache_event func )
+{
+	struct jabber_data *jd = gc->proto_data;
+	char *id = g_strdup_printf( "%s%05x", JABBER_CACHED_ID, ( next_id++ ) & 0xfffff );
+	struct jabber_cache_entry *entry = g_new0( struct jabber_cache_entry, 1 );
+	
+	xt_add_attr( node, "id", id );
+	g_free( id );
+	
+	entry->node = node;
+	entry->func = func;
+	g_hash_table_insert( jd->node_cache, xt_find_attr( node, "id" ), entry );
+}
+
+void jabber_cache_entry_free( gpointer data )
+{
+	struct jabber_cache_entry *entry = data;
+	
+	xt_free_node( entry->node );
+	g_free( entry );
+}
+
+gboolean jabber_cache_clean_entry( gpointer key, gpointer entry, gpointer nullpointer );
+
+/* This one should be called from time to time (from keepalive, in this case)
+   to make sure things don't stay in the node cache forever. By marking nodes
+   during the first run and deleting marked nodes during a next run, every
+   node should be available in the cache for at least a minute (assuming the
+   function is indeed called every minute). */
+void jabber_cache_clean( struct gaim_connection *gc )
+{
+	struct jabber_data *jd = gc->proto_data;
+	
+	g_hash_table_foreach_remove( jd->node_cache, jabber_cache_clean_entry, NULL );
+}
+
+gboolean jabber_cache_clean_entry( gpointer key, gpointer entry_, gpointer nullpointer )
+{
+	struct jabber_cache_entry *entry = entry_;
+	struct xt_node *node = entry->node;
+	
+	if( node->flags & XT_SEEN )
+		return TRUE;
+	else
+	{
+		node->flags |= XT_SEEN;
+		return FALSE;
+	}
+}
+
+const struct jabber_away_state jabber_away_state_list[] =
+{
+	{ "away",  "Away" },
+	{ "chat",  "Free for Chat" },
+	{ "dnd",   "Do not Disturb" },
+	{ "xa",    "Extended Away" },
+	{ "",      "Online" },
+	{ "",      NULL }
+};
+
+const struct jabber_away_state *jabber_away_state_by_code( char *code )
+{
+	int i;
+	
+	for( i = 0; jabber_away_state_list[i].full_name; i ++ )
+		if( g_strcasecmp( jabber_away_state_list[i].code, code ) == 0 )
+			return jabber_away_state_list + i;
+	
+	return NULL;
+}
+
+const struct jabber_away_state *jabber_away_state_by_name( char *name )
+{
+	int i;
+	
+	for( i = 0; jabber_away_state_list[i].full_name; i ++ )
+		if( g_strcasecmp( jabber_away_state_list[i].full_name, name ) == 0 )
+			return jabber_away_state_list + i;
+	
+	return NULL;
+}
+
+struct jabber_buddy_ask_data
+{
+	struct gaim_connection *gc;
+	char *handle;
+	char *realname;
+};
+
+static void jabber_buddy_ask_yes( gpointer w, struct jabber_buddy_ask_data *bla )
+{
+	presence_send_request( bla->gc, bla->handle, "subscribed" );
+	
+	if( find_buddy( bla->gc, bla->handle ) == NULL )
+		show_got_added( bla->gc, bla->handle, NULL );
+	
+	g_free( bla->handle );
+	g_free( bla );
+}
+
+static void jabber_buddy_ask_no( gpointer w, struct jabber_buddy_ask_data *bla )
+{
+	presence_send_request( bla->gc, bla->handle, "subscribed" );
+	
+	g_free( bla->handle );
+	g_free( bla );
+}
+
+void jabber_buddy_ask( struct gaim_connection *gc, char *handle )
+{
+	struct jabber_buddy_ask_data *bla = g_new0( struct jabber_buddy_ask_data, 1 );
+	char *buf;
+	
+	bla->gc = gc;
+	bla->handle = g_strdup( handle );
+	
+	buf = g_strdup_printf( "The user %s wants to add you to his/her buddy list.", handle );
+	do_ask_dialog( gc, buf, bla, jabber_buddy_ask_yes, jabber_buddy_ask_no );
+	g_free( buf );
+}
+
+/* Returns a new string. Don't leak it! */
+char *jabber_normalize( char *orig )
+{
+	int len, i;
+	char *new;
+	
+	len = strlen( orig );
+	new = g_new( char, len + 1 );
+	for( i = 0; i < len; i ++ )
+		new[i] = tolower( orig[i] );
+	
+	new[i] = 0;
+	return new;
+}
+
+/* Adds a buddy/resource to our list. Returns NULL if full_jid is not really a
+   FULL jid or if we already have this buddy/resource. XXX: No, great, actually
+   buddies from transports don't (usually) have resources. So we'll really have
+   to deal with that properly. Set their ->resource property to NULL. Do *NOT*
+   allow to mix this stuff, though... */
+struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_jid_ )
+{
+	struct jabber_data *jd = gc->proto_data;
+	struct jabber_buddy *bud, *new, *bi;
+	char *s, *full_jid;
+	
+	full_jid = jabber_normalize( full_jid_ );
+	
+	if( ( s = strchr( full_jid, '/' ) ) )
+		*s = 0;
+	
+	new = g_new0( struct jabber_buddy, 1 );
+	
+	if( ( bud = g_hash_table_lookup( jd->buddies, full_jid ) ) )
+	{
+		/* If this is a transport buddy or whatever, it can't have more
+		   than one instance, so this is always wrong: */
+		if( s == NULL || bud->resource == NULL )
+		{
+			if( s ) *s = '/';
+			g_free( new );
+			g_free( full_jid );
+			return NULL;
+		}
+		
+		new->bare_jid = bud->bare_jid;
+		
+		/* We already have another resource for this buddy, add the
+		   new one to the list. */
+		for( bi = bud; bi; bi = bi->next )
+		{
+			/* Check for dupes. */
+			if( g_strcasecmp( bi->resource, s + 1 ) == 0 )
+			{
+				*s = '/';
+				g_free( new );
+				g_free( full_jid );
+				return NULL;
+			}
+			/* Append the new item to the list. */
+			else if( bi->next == NULL )
+			{
+				bi->next = new;
+				break;
+			}
+		}
+	}
+	else
+	{
+		new->bare_jid = g_strdup( full_jid );
+		g_hash_table_insert( jd->buddies, new->bare_jid, new );
+	}
+	
+	if( s )
+	{
+		*s = '/';
+		new->full_jid = full_jid;
+		new->resource = strchr( new->full_jid, '/' ) + 1;
+	}
+	else
+	{
+		/* Let's waste some more bytes of RAM instead of to make
+		   memory management a total disaster here.. */
+		new->full_jid = full_jid;
+	}
+	
+	return new;
+}
+
+/* Finds a buddy from our structures. Can find both full- and bare JIDs. When
+   asked for a bare JID, it uses the "resource_select" setting to see which
+   resource to pick. */
+struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid_, get_buddy_flags_t flags )
+{
+	struct jabber_data *jd = gc->proto_data;
+	struct jabber_buddy *bud;
+	char *s, *jid;
+	
+	jid = jabber_normalize( jid_ );
+	
+	if( ( s = strchr( jid, '/' ) ) )
+	{
+		*s = 0;
+		if( ( bud = g_hash_table_lookup( jd->buddies, jid ) ) )
+		{
+			/* Is this one of those no-resource buddies? */
+			if( bud->resource == NULL )
+			{
+				g_free( jid );
+				return NULL;
+			}
+			else
+			{
+				/* See if there's an exact match. */
+				for( ; bud; bud = bud->next )
+					if( g_strcasecmp( bud->resource, s + 1 ) == 0 )
+						break;
+			}
+		}
+		
+		if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && find_buddy( gc, jid ) )
+		{
+			*s = '/';
+			bud = jabber_buddy_add( gc, jid );
+		}
+		
+		g_free( jid );
+		return bud;
+	}
+	else
+	{
+		struct jabber_buddy *best_prio, *best_time;
+		char *set;
+		
+		bud = g_hash_table_lookup( jd->buddies, jid );
+		
+		g_free( jid );
+		
+		if( bud == NULL )
+			/* No match. Create it now? */
+			return ( ( flags & GET_BUDDY_CREAT ) && find_buddy( gc, jid_ ) ) ?
+			           jabber_buddy_add( gc, jid_ ) : NULL;
+		else if( bud->resource && ( flags & GET_BUDDY_EXACT ) )
+			/* We want an exact match, so in thise case there shouldn't be a /resource. */
+			return NULL;
+		else if( ( bud->resource == NULL || bud->next == NULL ) )
+			/* No need for selection if there's only one option. */
+			return bud;
+		
+		best_prio = best_time = bud;
+		for( ; bud; bud = bud->next )
+		{
+			if( bud->priority > best_prio->priority )
+				best_prio = bud;
+			if( bud->last_act > best_time->last_act )
+				best_time = bud;
+		}
+		
+		if( ( set = set_getstr( &gc->acc->set, "resource_select" ) ) == NULL )
+			return NULL;
+		else if( strcmp( set, "activity" ) == 0 )
+			return best_time;
+		else /* if( strcmp( set, "priority" ) == 0 ) */
+			return best_prio;
+	}
+}
+
+/* Remove one specific full JID from our list. Use this when a buddy goes
+   off-line (because (s)he can still be online from a different location.
+   XXX: See above, we should accept bare JIDs too... */
+int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid_ )
+{
+	struct jabber_data *jd = gc->proto_data;
+	struct jabber_buddy *bud, *prev, *bi;
+	char *s, *full_jid;
+	
+	full_jid = jabber_normalize( full_jid_ );
+	
+	if( ( s = strchr( full_jid, '/' ) ) )
+		*s = 0;
+	
+	if( ( bud = g_hash_table_lookup( jd->buddies, full_jid ) ) )
+	{
+		/* If there's only one item in the list (and if the resource
+		   matches), removing it is simple. (And the hash reference
+		   should be removed too!) */
+		if( bud->next == NULL && ( ( s == NULL || bud->resource == NULL ) || g_strcasecmp( bud->resource, s + 1 ) == 0 ) )
+		{
+			g_hash_table_remove( jd->buddies, bud->bare_jid );
+			g_free( bud->bare_jid );
+			g_free( bud->full_jid );
+			g_free( bud->away_message );
+			g_free( bud );
+			
+			g_free( full_jid );
+			
+			return 1;
+		}
+		else if( s == NULL || bud->resource == NULL )
+		{
+			/* Tried to remove a bare JID while this JID does seem
+			   to have resources... (Or the opposite.) *sigh* */
+			g_free( full_jid );
+			return 0;
+		}
+		else
+		{
+			for( bi = bud, prev = NULL; bi; bi = (prev=bi)->next )
+				if( g_strcasecmp( bi->resource, s + 1 ) == 0 )
+					break;
+			
+			g_free( full_jid );
+			
+			if( bi )
+			{
+				if( prev )
+					prev->next = bi->next;
+				else
+					/* The hash table should point at the second
+					   item, because we're removing the first. */
+					g_hash_table_replace( jd->buddies, bi->bare_jid, bi->next );
+				
+				g_free( bi->full_jid );
+				g_free( bi->away_message );
+				g_free( bi );
+				
+				return 1;
+			}
+			else
+			{
+				return 0;
+			}
+		}
+	}
+	else
+	{
+		g_free( full_jid );
+		return 0;
+	}
+}
+
+/* Remove a buddy completely; removes all resources that belong to the
+   specified bare JID. Use this when removing someone from the contact
+   list, for example. */
+int jabber_buddy_remove_bare( struct gaim_connection *gc, char *bare_jid_ )
+{
+	struct jabber_data *jd = gc->proto_data;
+	struct jabber_buddy *bud, *next;
+	char *bare_jid;
+	
+	if( strchr( bare_jid_, '/' ) )
+		return 0;
+	
+	bare_jid = jabber_normalize( bare_jid_ );
+	
+	if( ( bud = g_hash_table_lookup( jd->buddies, bare_jid ) ) )
+	{
+		/* Most important: Remove the hash reference. We don't know
+		   this buddy anymore. */
+		g_hash_table_remove( jd->buddies, bud->bare_jid );
+		
+		/* Deallocate the linked list of resources. */
+		while( bud )
+		{
+			next = bud->next;
+			g_free( bud->full_jid );
+			g_free( bud->away_message );
+			g_free( bud );
+			bud = next;
+		}
+		
+		g_free( bare_jid );
+		return 1;
+	}
+	else
+	{
+		g_free( bare_jid );
+		return 0;
+	}
+}
Index: protocols/jabber/jid.c
===================================================================
--- protocols/jabber/jid.c	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,170 +1,0 @@
-/* --------------------------------------------------------------------------
- *
- * License
- *
- * The contents of this file are subject to the Jabber Open Source License
- * Version 1.0 (the "JOSL").  You may not copy or use this file, in either
- * source code or executable form, except in compliance with the JOSL. You
- * may obtain a copy of the JOSL at http://www.jabber.org/ or at
- * http://www.opensource.org/.  
- *
- * Software distributed under the JOSL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the JOSL
- * for the specific language governing rights and limitations under the
- * JOSL.
- *
- * Copyrights
- * 
- * Portions created by or assigned to Jabber.com, Inc. are 
- * Copyright (c) 1999-2002 Jabber.com, Inc.  All Rights Reserved.  Contact
- * information for Jabber.com, Inc. is available at http://www.jabber.com/.
- *
- * Portions Copyright (c) 1998-1999 Jeremie Miller.
- * 
- * Acknowledgements
- * 
- * Special thanks to the Jabber Open Source Contributors for their
- * suggestions and support of Jabber.
- * 
- * Alternatively, the contents of this file may be used under the terms of the
- * GNU General Public License Version 2 or later (the "GPL"), in which case
- * the provisions of the GPL are applicable instead of those above.  If you
- * wish to allow use of your version of this file only under the terms of the
- * GPL and not to allow others to use your version of this file under the JOSL,
- * indicate your decision by deleting the provisions above and replace them
- * with the notice and other provisions required by the GPL.  If you do not
- * delete the provisions above, a recipient may use your version of this file
- * under either the JOSL or the GPL. 
- * 
- * 
- * --------------------------------------------------------------------------*/
-
-#include "jabber.h"
-#include <glib.h>
-
-static jid jid_safe(jid id)
-{
-    char *str;
-
-    if(strlen(id->server) == 0 || strlen(id->server) > 255)
-        return NULL;
-
-    /* lowercase the hostname, make sure it's valid characters */
-    for(str = id->server; *str != '\0'; str++)
-    {
-        *str = tolower(*str);
-        if(!(isalnum(*str) || *str == '.' || *str == '-' || *str == '_')) return NULL;
-    }
-
-    /* cut off the user */
-    if(id->user != NULL && strlen(id->user) > 64)
-        id->user[64] = '\0';
-
-    /* check for low and invalid ascii characters in the username */
-    if(id->user != NULL)
-        for(str = id->user; *str != '\0'; str++)
-            if(*str <= 32 || *str == ':' || *str == '@' || *str == '<' || *str == '>' || *str == '\'' || *str == '"' || *str == '&') return NULL;
-
-    return id;
-}
-
-jid jid_new(pool p, char *idstr)
-{
-    char *server, *resource, *type, *str;
-    jid id;
-
-    if(p == NULL || idstr == NULL || strlen(idstr) == 0)
-        return NULL;
-
-    /* user@server/resource */
-
-    str = pstrdup(p, idstr);
-
-    id = pmalloco(p,sizeof(struct jid_struct));
-    id->p = p;
-
-    resource = strstr(str,"/");
-    if(resource != NULL)
-    {
-        *resource = '\0';
-        ++resource;
-        if(strlen(resource) > 0)
-            id->resource = resource;
-    }else{
-        resource = str + strlen(str); /* point to end */
-    }
-
-    type = strstr(str,":");
-    if(type != NULL && type < resource)
-    {
-        *type = '\0';
-        ++type;
-        str = type; /* ignore the type: prefix */
-    }
-
-    server = strstr(str,"@");
-    if(server == NULL || server > resource)
-    { /* if there's no @, it's just the server address */
-        id->server = str;
-    }else{
-        *server = '\0';
-        ++server;
-        id->server = server;
-        if(strlen(str) > 0)
-            id->user = str;
-    }
-
-    return jid_safe(id);
-}
-
-char *jid_full(jid id)
-{
-    spool s;
-
-    if(id == NULL)
-        return NULL;
-
-    /* use cached copy */
-    if(id->full != NULL)
-        return id->full;
-
-    s = spool_new(id->p);
-
-    if(id->user != NULL)
-        spooler(s, id->user,"@",s);
-
-    spool_add(s, id->server);
-
-    if(id->resource != NULL)
-        spooler(s, "/",id->resource,s);
-
-    id->full = spool_print(s);
-    return id->full;
-}
-
-/* local utils */
-static int _jid_nullstrcmp(char *a, char *b)
-{
-    if(a == NULL && b == NULL) return 0;
-    if(a == NULL || b == NULL) return -1;
-    return strcmp(a,b);
-}
-static int _jid_nullstrcasecmp(char *a, char *b)
-{
-    if(a == NULL && b == NULL) return 0;
-    if(a == NULL || b == NULL) return -1;
-    return g_strcasecmp(a,b);
-}
-
-/* suggested by Anders Qvist <quest@valdez.netg.se> */
-int jid_cmpx(jid a, jid b, int parts)
-{
-    if(a == NULL || b == NULL)
-        return -1;
-
-    if(parts & JID_RESOURCE && _jid_nullstrcmp(a->resource, b->resource) != 0) return -1;
-    if(parts & JID_USER && _jid_nullstrcasecmp(a->user, b->user) != 0) return -1;
-    if(parts & JID_SERVER && _jid_nullstrcmp(a->server, b->server) != 0) return -1;
-
-    return 0;
-}
Index: protocols/jabber/jpacket.c
===================================================================
--- protocols/jabber/jpacket.c	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,159 +1,0 @@
-/* --------------------------------------------------------------------------
- *
- * License
- *
- * The contents of this file are subject to the Jabber Open Source License
- * Version 1.0 (the "JOSL").  You may not copy or use this file, in either
- * source code or executable form, except in compliance with the JOSL. You
- * may obtain a copy of the JOSL at http://www.jabber.org/ or at
- * http://www.opensource.org/.  
- *
- * Software distributed under the JOSL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the JOSL
- * for the specific language governing rights and limitations under the
- * JOSL.
- *
- * Copyrights
- * 
- * Portions created by or assigned to Jabber.com, Inc. are 
- * Copyright (c) 1999-2002 Jabber.com, Inc.  All Rights Reserved.  Contact
- * information for Jabber.com, Inc. is available at http://www.jabber.com/.
- *
- * Portions Copyright (c) 1998-1999 Jeremie Miller.
- * 
- * Acknowledgements
- * 
- * Special thanks to the Jabber Open Source Contributors for their
- * suggestions and support of Jabber.
- * 
- * Alternatively, the contents of this file may be used under the terms of the
- * GNU General Public License Version 2 or later (the "GPL"), in which case
- * the provisions of the GPL are applicable instead of those above.  If you
- * wish to allow use of your version of this file only under the terms of the
- * GPL and not to allow others to use your version of this file under the JOSL,
- * indicate your decision by deleting the provisions above and replace them
- * with the notice and other provisions required by the GPL.  If you do not
- * delete the provisions above, a recipient may use your version of this file
- * under either the JOSL or the GPL. 
- * 
- * 
- * --------------------------------------------------------------------------*/
-
-#include "jabber.h"
-static jpacket jpacket_reset(jpacket p);
-
-jpacket jpacket_new(xmlnode x)
-{
-    jpacket p;
-
-    if(x == NULL)
-        return NULL;
-
-    p = pmalloc(xmlnode_pool(x),sizeof(_jpacket));
-    p->x = x;
-
-    return jpacket_reset(p);
-}
-
-static jpacket jpacket_reset(jpacket p)
-{
-    char *val;
-    xmlnode x;
-
-    x = p->x;
-    memset(p,0,sizeof(_jpacket));
-    p->x = x;
-    p->p = xmlnode_pool(x);
-
-    if(strncmp(xmlnode_get_name(x),"message",7) == 0)
-    {
-        p->type = JPACKET_MESSAGE;
-    }else if(strncmp(xmlnode_get_name(x),"presence",8) == 0)
-    {
-        p->type = JPACKET_PRESENCE;
-        val = xmlnode_get_attrib(x, "type");
-        if(val == NULL)
-            p->subtype = JPACKET__AVAILABLE;
-        else if(strcmp(val,"unavailable") == 0)
-            p->subtype = JPACKET__UNAVAILABLE;
-        else if(strcmp(val,"probe") == 0)
-            p->subtype = JPACKET__PROBE;
-        else if(strcmp(val,"error") == 0)
-            p->subtype = JPACKET__ERROR;
-        else if(strcmp(val,"invisible") == 0)
-            p->subtype = JPACKET__INVISIBLE;
-        else if(*val == 's' || *val == 'u')
-            p->type = JPACKET_S10N;
-        else if(strcmp(val,"available") == 0)
-        { /* someone is using type='available' which is frowned upon */
-            xmlnode_hide_attrib(x,"type");
-            p->subtype = JPACKET__AVAILABLE;
-        }else
-            p->type = JPACKET_UNKNOWN;
-    }else if(strncmp(xmlnode_get_name(x),"iq",2) == 0)
-    {
-        p->type = JPACKET_IQ;
-        p->iq = xmlnode_get_tag(x,"?xmlns");
-        p->iqns = xmlnode_get_attrib(p->iq,"xmlns");
-    }
-
-    /* set up the jids if any, flag packet as unknown if they are unparseable */
-    val = xmlnode_get_attrib(x,"to");
-    if(val != NULL)
-        if((p->to = jid_new(p->p, val)) == NULL)
-            p->type = JPACKET_UNKNOWN;
-    val = xmlnode_get_attrib(x,"from");
-    if(val != NULL)
-        if((p->from = jid_new(p->p, val)) == NULL)
-            p->type = JPACKET_UNKNOWN;
-
-    return p;
-}
-
-
-int jpacket_subtype(jpacket p)
-{
-    char *type;
-    int ret = p->subtype;
-
-    if(ret != JPACKET__UNKNOWN)
-        return ret;
-
-    ret = JPACKET__NONE; /* default, when no type attrib is specified */
-    type = xmlnode_get_attrib(p->x, "type");
-    if(j_strcmp(type,"error") == 0)
-        ret = JPACKET__ERROR;
-    else
-        switch(p->type)
-        {
-        case JPACKET_MESSAGE:
-            if(j_strcmp(type,"chat") == 0)
-                ret = JPACKET__CHAT;
-            else if(j_strcmp(type,"groupchat") == 0)
-                ret = JPACKET__GROUPCHAT;
-            else if(j_strcmp(type,"headline") == 0)
-                ret = JPACKET__HEADLINE;
-            break;
-        case JPACKET_S10N:
-            if(j_strcmp(type,"subscribe") == 0)
-                ret = JPACKET__SUBSCRIBE;
-            else if(j_strcmp(type,"subscribed") == 0)
-                ret = JPACKET__SUBSCRIBED;
-            else if(j_strcmp(type,"unsubscribe") == 0)
-                ret = JPACKET__UNSUBSCRIBE;
-            else if(j_strcmp(type,"unsubscribed") == 0)
-                ret = JPACKET__UNSUBSCRIBED;
-            break;
-        case JPACKET_IQ:
-            if(j_strcmp(type,"get") == 0)
-                ret = JPACKET__GET;
-            else if(j_strcmp(type,"set") == 0)
-                ret = JPACKET__SET;
-            else if(j_strcmp(type,"result") == 0)
-                ret = JPACKET__RESULT;
-            break;
-        }
-
-    p->subtype = ret;
-    return ret;
-}
Index: protocols/jabber/jutil.c
===================================================================
--- protocols/jabber/jutil.c	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,122 +1,0 @@
-/* --------------------------------------------------------------------------
- *
- * License
- *
- * The contents of this file are subject to the Jabber Open Source License
- * Version 1.0 (the "JOSL").  You may not copy or use this file, in either
- * source code or executable form, except in compliance with the JOSL. You
- * may obtain a copy of the JOSL at http://www.jabber.org/ or at
- * http://www.opensource.org/.  
- *
- * Software distributed under the JOSL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the JOSL
- * for the specific language governing rights and limitations under the
- * JOSL.
- *
- * Copyrights
- * 
- * Portions created by or assigned to Jabber.com, Inc. are 
- * Copyright (c) 1999-2002 Jabber.com, Inc.  All Rights Reserved.  Contact
- * information for Jabber.com, Inc. is available at http://www.jabber.com/.
- *
- * Portions Copyright (c) 1998-1999 Jeremie Miller.
- * 
- * Acknowledgements
- * 
- * Special thanks to the Jabber Open Source Contributors for their
- * suggestions and support of Jabber.
- * 
- * Alternatively, the contents of this file may be used under the terms of the
- * GNU General Public License Version 2 or later (the "GPL"), in which case
- * the provisions of the GPL are applicable instead of those above.  If you
- * wish to allow use of your version of this file only under the terms of the
- * GPL and not to allow others to use your version of this file under the JOSL,
- * indicate your decision by deleting the provisions above and replace them
- * with the notice and other provisions required by the GPL.  If you do not
- * delete the provisions above, a recipient may use your version of this file
- * under either the JOSL or the GPL. 
- * 
- * 
- * --------------------------------------------------------------------------*/
-
-#include "jabber.h"
-#include <glib.h>
-#include "nogaim.h"
-
-/* util for making presence packets */
-xmlnode jutil_presnew(int type, char *to, char *status)
-{
-    xmlnode pres;
-
-    pres = xmlnode_new_tag("presence");
-    switch(type)
-    {
-    case JPACKET__SUBSCRIBE:
-        xmlnode_put_attrib(pres,"type","subscribe");
-        break;
-    case JPACKET__UNSUBSCRIBE:
-        xmlnode_put_attrib(pres,"type","unsubscribe");
-        break;
-    case JPACKET__SUBSCRIBED:
-        xmlnode_put_attrib(pres,"type","subscribed");
-        break;
-    case JPACKET__UNSUBSCRIBED:
-        xmlnode_put_attrib(pres,"type","unsubscribed");
-        break;
-    case JPACKET__PROBE:
-        xmlnode_put_attrib(pres,"type","probe");
-        break;
-    case JPACKET__UNAVAILABLE:
-        xmlnode_put_attrib(pres,"type","unavailable");
-        break;
-    case JPACKET__INVISIBLE:
-        xmlnode_put_attrib(pres,"type","invisible");
-        break;
-    }
-    if(to != NULL)
-        xmlnode_put_attrib(pres,"to",to);
-    if(status != NULL)
-        xmlnode_insert_cdata(xmlnode_insert_tag(pres,"status"),status,strlen(status));
-
-    return pres;
-}
-
-/* util for making IQ packets */
-xmlnode jutil_iqnew(int type, char *ns)
-{
-    xmlnode iq;
-
-    iq = xmlnode_new_tag("iq");
-    switch(type)
-    {
-    case JPACKET__GET:
-        xmlnode_put_attrib(iq,"type","get");
-        break;
-    case JPACKET__SET:
-        xmlnode_put_attrib(iq,"type","set");
-        break;
-    case JPACKET__RESULT:
-        xmlnode_put_attrib(iq,"type","result");
-        break;
-    case JPACKET__ERROR:
-        xmlnode_put_attrib(iq,"type","error");
-        break;
-    }
-    xmlnode_put_attrib(xmlnode_insert_tag(iq,"query"),"xmlns",ns);
-
-    return iq;
-}
-
-/* util for making stream packets */
-xmlnode jutil_header(char* xmlns, char* server)
-{
-     xmlnode result;
-     if ((xmlns == NULL)||(server == NULL))
-	  return NULL;
-     result = xmlnode_new_tag("stream:stream");
-     xmlnode_put_attrib(result, "xmlns:stream", "http://etherx.jabber.org/streams");
-     xmlnode_put_attrib(result, "xmlns", xmlns);
-     xmlnode_put_attrib(result, "to", server);
-
-     return result;
-}
Index: protocols/jabber/latin1tab.h
===================================================================
--- protocols/jabber/latin1tab.h	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,62 +1,0 @@
-/*
-The contents of this file are subject to the Mozilla Public License
-Version 1.1 (the "License"); you may not use this file except in
-compliance with the License. You may obtain a copy of the License at
-http://www.mozilla.org/MPL/
-
-Software distributed under the License is distributed on an "AS IS"
-basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
-License for the specific language governing rights and limitations
-under the License.
-
-The Original Code is expat.
-
-The Initial Developer of the Original Code is James Clark.
-Portions created by James Clark are Copyright (C) 1998, 1999
-James Clark. All Rights Reserved.
-
-Contributor(s):
-
-Alternatively, the contents of this file may be used under the terms
-of the GNU General Public License (the "GPL"), in which case the
-provisions of the GPL are applicable instead of those above.  If you
-wish to allow use of your version of this file only under the terms of
-the GPL and not to allow others to use your version of this file under
-the MPL, indicate your decision by deleting the provisions above and
-replace them with the notice and other provisions required by the
-GPL. If you do not delete the provisions above, a recipient may use
-your version of this file under either the MPL or the GPL.
-*/
-
-/* 0x80 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
-/* 0x84 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
-/* 0x88 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
-/* 0x8C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
-/* 0x90 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
-/* 0x94 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
-/* 0x98 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
-/* 0x9C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
-/* 0xA0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
-/* 0xA4 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
-/* 0xA8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
-/* 0xAC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
-/* 0xB0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
-/* 0xB4 */ BT_OTHER, BT_NMSTRT, BT_OTHER, BT_NAME,
-/* 0xB8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
-/* 0xBC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
-/* 0xC0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0xC4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0xC8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0xCC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0xD0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0xD4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
-/* 0xD8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0xDC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0xE0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0xE4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0xE8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0xEC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0xF0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0xF4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
-/* 0xF8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0xFC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
Index: protocols/jabber/lib.h
===================================================================
--- protocols/jabber/lib.h	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,343 +1,0 @@
-
-#include <string.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <stdio.h>
-#include <setjmp.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <time.h>
-
-#include "xmlparse.h"
-
-int j_strcmp(const char *a, const char *b);
-
-/*
-**  Arrange to use either varargs or stdargs
-*/
-
-#define MAXSHORTSTR	203		/* max short string length */
-#define QUAD_T	unsigned long long
-
-#if defined(__STDC__) || defined(_WIN32)
-
-#include <stdarg.h>
-
-# define VA_LOCAL_DECL	va_list ap;
-# define VA_START(f)	va_start(ap, f)
-# define VA_END		va_end(ap)
-
-#else /* __STDC__ */
-
-# include <varargs.h>
-
-# define VA_LOCAL_DECL	va_list ap;
-# define VA_START(f)	va_start(ap)
-# define VA_END		va_end(ap)
-
-#endif /* __STDC__ */
-
-
-#ifndef INCL_LIB_H
-#define INCL_LIB_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* --------------------------------------------------------- */
-/*                                                           */
-/* Pool-based memory management routines                     */
-/*                                                           */
-/* --------------------------------------------------------- */
-
-#undef POOL_DEBUG
-/*
- flip these, this should be a prime number for top # of pools debugging
-#define POOL_DEBUG 40009 
-*/
-
-/* pheap - singular allocation of memory */
-struct pheap
-{
-    void *block;
-    int size, used;
-};
-
-/* pool_cleaner - callback type which is associated
-   with a pool entry; invoked when the pool entry is 
-   free'd */
-typedef void (*pool_cleaner)(void *arg);
-
-/* pfree - a linked list node which stores an
-   allocation chunk, plus a callback */
-struct pfree
-{
-    pool_cleaner f;
-    void *arg;
-    struct pheap *heap;
-    struct pfree *next;
-};
-
-/* pool - base node for a pool. Maintains a linked list
-   of pool entries (pfree) */
-typedef struct pool_struct
-{
-    int size;
-    struct pfree *cleanup;
-    struct pheap *heap;
-#ifdef POOL_DEBUG
-    char name[8], zone[32];
-    int lsize;
-} _pool, *pool;
-#define pool_new() _pool_new(ZONE) 
-#define pool_heap(i) _pool_new_heap(i,ZONE) 
-#else
-} _pool, *pool;
-#define pool_heap(i) _pool_new_heap(i,NULL) 
-#define pool_new() _pool_new(NULL)
-#endif
-
-pool _pool_new(char *zone); /* new pool :) */
-pool _pool_new_heap(int size, char *zone); /* creates a new memory pool with an initial heap size */
-void *pmalloc(pool p, int size); /* wrapper around malloc, takes from the pool, cleaned up automatically */
-void *pmalloc_x(pool p, int size, char c); /* Wrapper around pmalloc which prefils buffer with c */
-void *pmalloco(pool p, int size); /* YAPW for zeroing the block */
-char *pstrdup(pool p, const char *src); /* wrapper around strdup, gains mem from pool */
-void pool_stat(int full); /* print to stderr the changed pools and reset */
-void pool_cleanup(pool p, pool_cleaner f, void *arg); /* calls f(arg) before the pool is freed during cleanup */
-void pool_free(pool p); /* calls the cleanup functions, frees all the data on the pool, and deletes the pool itself */
-
-
-
-
-/* --------------------------------------------------------- */
-/*                                                           */
-/* Socket helper stuff                                       */
-/*                                                           */
-/* --------------------------------------------------------- */
-#ifndef MAXHOSTNAMELEN
-#define MAXHOSTNAMELEN 64
-#endif
-
-#define NETSOCKET_SERVER 0
-#define NETSOCKET_CLIENT 1
-#define NETSOCKET_UDP 2
-
-#ifndef WIN32
-int make_netsocket(u_short port, char *host, int type);
-struct in_addr *make_addr(char *host);
-int set_fd_close_on_exec(int fd, int flag);
-#endif
-
-
-/* --------------------------------------------------------- */
-/*                                                           */
-/* Hashtable functions                                       */
-/*                                                           */
-/* --------------------------------------------------------- */
-typedef struct xhn_struct
-{
-    struct xhn_struct *next;
-    const char *key;
-    void *val;
-} *xhn, _xhn;
-
-char *strescape(pool p, char *);
-
-
-/* --------------------------------------------------------- */
-/*                                                           */
-/* String pools (spool) functions                            */
-/*                                                           */
-/* --------------------------------------------------------- */
-struct spool_node
-{
-    char *c;
-    struct spool_node *next;
-};
-
-typedef struct spool_struct
-{
-    pool p;
-    int len;
-    struct spool_node *last;
-    struct spool_node *first;
-} *spool;
-
-spool spool_new(pool p); /* create a string pool */
-void spooler(spool s, ...); /* append all the char * args to the pool, terminate args with s again */
-char *spool_print(spool s); /* return a big string */
-void spool_add(spool s, char *str); /* add a single char to the pool */
-
-
-/* --------------------------------------------------------- */
-/*                                                           */
-/* xmlnodes - Document Object Model                          */
-/*                                                           */
-/* --------------------------------------------------------- */
-#define NTYPE_TAG    0
-#define NTYPE_ATTRIB 1
-#define NTYPE_CDATA  2
-
-#define NTYPE_LAST   2
-#define NTYPE_UNDEF  -1
-
-/* -------------------------------------------------------------------------- 
-   Node structure. Do not use directly! Always use accessor macros 
-   and methods!
-   -------------------------------------------------------------------------- */
-typedef struct xmlnode_t
-{
-     char*               name;
-     unsigned short      type;
-     char*               data;
-     int                 data_sz;
-     int                 complete;
-     pool               p;
-     struct xmlnode_t*  parent;
-     struct xmlnode_t*  firstchild; 
-     struct xmlnode_t*  lastchild;
-     struct xmlnode_t*  prev; 
-     struct xmlnode_t*  next;
-     struct xmlnode_t*  firstattrib;
-     struct xmlnode_t*  lastattrib;
-} _xmlnode, *xmlnode;
-
-/* Node creation routines */
-xmlnode  xmlnode_wrap(xmlnode x,const char* wrapper);
-xmlnode  xmlnode_new_tag(const char* name);
-xmlnode  xmlnode_new_tag_pool(pool p, const char* name);
-xmlnode  xmlnode_insert_tag(xmlnode parent, const char* name); 
-xmlnode  xmlnode_insert_cdata(xmlnode parent, const char* CDATA, unsigned int size);
-xmlnode  xmlnode_insert_tag_node(xmlnode parent, xmlnode node);
-xmlnode  xmlnode_str(char *str, int len);
-xmlnode  xmlnode_dup(xmlnode x); /* duplicate x */
-xmlnode  xmlnode_dup_pool(pool p, xmlnode x);
-
-/* Node Memory Pool */
-pool xmlnode_pool(xmlnode node);
-
-/* Node editing */
-void xmlnode_hide(xmlnode child);
-void xmlnode_hide_attrib(xmlnode parent, const char *name);
-
-/* Node deletion routine, also frees the node pool! */
-void xmlnode_free(xmlnode node);
-
-/* Locates a child tag by name and returns it */
-xmlnode  xmlnode_get_tag(xmlnode parent, const char* name);
-char* xmlnode_get_tag_data(xmlnode parent, const char* name);
-
-/* Attribute accessors */
-void     xmlnode_put_attrib(xmlnode owner, const char* name, const char* value);
-char*    xmlnode_get_attrib(xmlnode owner, const char* name);
-void     xmlnode_put_expat_attribs(xmlnode owner, const char** atts);
-
-/* Bastard am I, but these are fun for internal use ;-) */
-void     xmlnode_put_vattrib(xmlnode owner, const char* name, void *value);
-void*    xmlnode_get_vattrib(xmlnode owner, const char* name);
-
-/* Node traversal routines */
-xmlnode  xmlnode_get_firstchild(xmlnode parent);
-xmlnode  xmlnode_get_lastchild(xmlnode parent);
-xmlnode  xmlnode_get_nextsibling(xmlnode sibling);
-xmlnode  xmlnode_get_prevsibling(xmlnode sibling);
-xmlnode  xmlnode_get_parent(xmlnode node);
-
-/* Node information routines */
-char*    xmlnode_get_name(xmlnode node);
-char*    xmlnode_get_data(xmlnode node);
-
-int      xmlnode_has_children(xmlnode node);
-
-/* Node-to-string translation */
-char*    xmlnode2str(xmlnode node);
-
-/********** END OLD libxode.h BEGIN OLD jabber.h *************/
-
-
-// #define KARMA_DEBUG
-// default to disable karma 
-#define KARMA_READ_MAX(k) (abs(k)*100) /* how much you are allowed to read off the sock */
-#define KARMA_INIT 5   /* internal "init" value */
-#define KARMA_HEARTBEAT 2 /* seconds to register for heartbeat */
-#define KARMA_MAX 10     /* total max karma you can have */
-#define KARMA_INC 1      /* how much to increment every KARMA_HEARTBEAT seconds */
-#define KARMA_DEC 0      /* how much to penalize for reading KARMA_READ_MAX in
-                            KARMA_HEARTBEAT seconds */
-#define KARMA_PENALTY -5 /* where you go when you hit 0 karma */
-#define KARMA_RESTORE 5  /* where you go when you payed your penelty or INIT */
-#define KARMA_RESETMETER 0 /* Reset byte meter on restore default is falst */
-
-struct karma
-{
-    int init; /* struct initialized */
-    int reset_meter; /* reset the byte meter on restore */
-    int val; /* current karma value */
-    long bytes; /* total bytes read (in that time period) */
-    int max;  /* max karma you can have */
-    int inc,dec; /* how much to increment/decrement */
-    int penalty,restore; /* what penalty (<0) or restore (>0) */
-    time_t last_update; /* time this was last incremented */
-};
-
-struct karma *karma_new(pool p); /* creates a new karma object, with default values */
-void karma_copy(struct karma *new, struct karma *old); /* makes a copy of old in new */
-void karma_increment(struct karma *k);          /* inteligently increments karma */
-void karma_decrement(struct karma *k, long bytes_read); /* inteligently decrements karma */
-int karma_check(struct karma *k,long bytes_read); /* checks to see if we have good karma */
-
-
-
-/* --------------------------------------------------------- */
-/*                                                           */
-/* Namespace constants                                       */
-/*                                                           */
-/* --------------------------------------------------------- */
-#define NSCHECK(x,n) (j_strcmp(xmlnode_get_attrib(x,"xmlns"),n) == 0)
-
-#define NS_CLIENT    "jabber:client"
-#define NS_SERVER    "jabber:server"
-#define NS_AUTH      "jabber:iq:auth"
-#define NS_REGISTER  "jabber:iq:register"
-#define NS_ROSTER    "jabber:iq:roster"
-#define NS_OFFLINE   "jabber:x:offline"
-#define NS_AGENT     "jabber:iq:agent"
-#define NS_AGENTS    "jabber:iq:agents"
-#define NS_DELAY     "jabber:x:delay"
-#define NS_VERSION   "jabber:iq:version"
-#define NS_TIME      "jabber:iq:time"
-#define NS_VCARD     "vcard-temp"
-#define NS_PRIVATE   "jabber:iq:private"
-#define NS_SEARCH    "jabber:iq:search"
-#define NS_OOB       "jabber:iq:oob"
-#define NS_XOOB      "jabber:x:oob"
-#define NS_ADMIN     "jabber:iq:admin"
-#define NS_FILTER    "jabber:iq:filter"
-#define NS_AUTH_0K   "jabber:iq:auth:0k"
-#define NS_BROWSE    "jabber:iq:browse"
-#define NS_EVENT     "jabber:x:event"
-#define NS_CONFERENCE "jabber:iq:conference"
-#define NS_SIGNED    "jabber:x:signed"
-#define NS_ENCRYPTED "jabber:x:encrypted"
-#define NS_GATEWAY   "jabber:iq:gateway"
-#define NS_LAST      "jabber:iq:last"
-#define NS_ENVELOPE  "jabber:x:envelope"
-#define NS_EXPIRE    "jabber:x:expire"
-#define NS_XHTML     "http://www.w3.org/1999/xhtml"
-
-#define NS_XDBGINSERT "jabber:xdb:ginsert"
-#define NS_XDBNSLIST  "jabber:xdb:nslist"
-
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif	/* INCL_LIB_H */
Index: protocols/jabber/libxode.h
===================================================================
--- protocols/jabber/libxode.h	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,398 +1,0 @@
-#include <string.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <stdio.h>
-#include <setjmp.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <signal.h>
-#include <syslog.h>
-#include <strings.h>
-#include <unistd.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-
-#ifndef __CYGWIN__
-#include <arpa/nameser.h>
-#include <resolv.h>
-#endif
-
-#include <sys/time.h>
-#include <time.h>
-
-#include "xmlparse.h"
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-/*
-**  Arrange to use either varargs or stdargs
-*/
-
-#define MAXSHORTSTR	203		/* max short string length */
-#define QUAD_T	unsigned long long
-
-#ifdef __STDC__
-
-#include <stdarg.h>
-
-# define VA_LOCAL_DECL	va_list ap;
-# define VA_START(f)	va_start(ap, f)
-# define VA_END		va_end(ap)
-
-#else /* __STDC__ */
-
-# include <varargs.h>
-
-# define VA_LOCAL_DECL	va_list ap;
-# define VA_START(f)	va_start(ap)
-# define VA_END		va_end(ap)
-
-#endif /* __STDC__ */
-
-
-#ifndef INCL_LIBXODE_H
-#define INCL_LIBXODE_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#ifndef HAVE_SNPRINTF
-extern int ap_snprintf(char *, size_t, const char *, ...);
-#define snprintf ap_snprintf
-#endif
-
-#ifndef HAVE_VSNPRINTF
-extern int ap_vsnprintf(char *, size_t, const char *, va_list ap);
-#define vsnprintf ap_vsnprintf
-#endif
-
-#define ZONE zonestr(__FILE__,__LINE__)
-char *zonestr(char *file, int line);
-
-/* --------------------------------------------------------- */
-/*                                                           */
-/* Pool-based memory management routines                     */
-/*                                                           */
-/* --------------------------------------------------------- */
-
-#undef POOL_DEBUG
-/*
- flip these, this should be a prime number for top # of pools debugging
-#define POOL_DEBUG 40009 
-*/
-
-/* pheap - singular allocation of memory */
-struct pheap
-{
-    void *block;
-    int size, used;
-};
-
-/* pool_cleaner - callback type which is associated
-   with a pool entry; invoked when the pool entry is 
-   free'd */
-typedef void (*pool_cleaner)(void *arg);
-
-/* pfree - a linked list node which stores an
-   allocation chunk, plus a callback */
-struct pfree
-{
-    pool_cleaner f;
-    void *arg;
-    struct pheap *heap;
-    struct pfree *next;
-};
-
-/* pool - base node for a pool. Maintains a linked list
-   of pool entries (pfree) */
-typedef struct pool_struct
-{
-    int size;
-    struct pfree *cleanup;
-    struct pheap *heap;
-#ifdef POOL_DEBUG
-    char name[8], zone[32];
-    int lsize;
-} _pool, *pool;
-#define pool_new() _pool_new(ZONE) 
-#define pool_heap(i) _pool_new_heap(i,ZONE) 
-#else
-} _pool, *pool;
-#define pool_heap(i) _pool_new_heap(i,NULL) 
-#define pool_new() _pool_new(NULL)
-#endif
-
-pool _pool_new(char *zone); /* new pool :) */
-pool _pool_new_heap(int size, char *zone); /* creates a new memory pool with an initial heap size */
-void *pmalloc(pool p, int size); /* wrapper around malloc, takes from the pool, cleaned up automatically */
-void *pmalloc_x(pool p, int size, char c); /* Wrapper around pmalloc which prefils buffer with c */
-void *pmalloco(pool p, int size); /* YAPW for zeroing the block */
-char *pstrdup(pool p, const char *src); /* wrapper around strdup, gains mem from pool */
-void pool_stat(int full); /* print to stderr the changed pools and reset */
-void pool_cleanup(pool p, pool_cleaner f, void *arg); /* calls f(arg) before the pool is freed during cleanup */
-void pool_free(pool p); /* calls the cleanup functions, frees all the data on the pool, and deletes the pool itself */
-
-
-
-
-/* --------------------------------------------------------- */
-/*                                                           */
-/* Socket helper stuff                                       */
-/*                                                           */
-/* --------------------------------------------------------- */
-#ifndef MAXHOSTNAMELEN
-#define MAXHOSTNAMELEN 64
-#endif
-
-#define NETSOCKET_SERVER 0
-#define NETSOCKET_CLIENT 1
-#define NETSOCKET_UDP 2
-
-#ifndef WIN32
-int make_netsocket(u_short port, char *host, int type);
-struct in_addr *make_addr(char *host);
-int set_fd_close_on_exec(int fd, int flag);
-#endif
-
-
-/* --------------------------------------------------------- */
-/*                                                           */
-/* SHA calculations                                          */
-/*                                                           */
-/* --------------------------------------------------------- */
-#if (SIZEOF_INT == 4)
-typedef unsigned int uint32;
-#elif (SIZEOF_SHORT == 4)
-typedef unsigned short uint32;
-#else
-typedef unsigned int uint32;
-#endif /* HAVEUINT32 */
-
-int sha_hash(int *data, int *hash);
-int sha_init(int *hash);
-char *shahash(char *str);	/* NOT THREAD SAFE */
-void shahash_r(const char* str, char hashbuf[40]); /* USE ME */
-
-int strprintsha(char *dest, int *hashval);
-
-
-/* --------------------------------------------------------- */
-/*                                                           */
-/* Hashtable functions                                       */
-/*                                                           */
-/* --------------------------------------------------------- */
-typedef int (*KEYHASHFUNC)(const void *key);
-typedef int (*KEYCOMPAREFUNC)(const void *key1, const void *key2);
-typedef int (*TABLEWALKFUNC)(void *user_data, const void *key, void *data);
-
-typedef void *HASHTABLE;
-
-HASHTABLE ghash_create(int buckets, KEYHASHFUNC hash, KEYCOMPAREFUNC cmp);
-void ghash_destroy(HASHTABLE tbl);
-void *ghash_get(HASHTABLE tbl, const void *key);
-int ghash_put(HASHTABLE tbl, const void *key, void *value);
-int ghash_remove(HASHTABLE tbl, const void *key);
-int ghash_walk(HASHTABLE tbl, TABLEWALKFUNC func, void *user_data);
-int str_hash_code(const char *s);
-
-
-/* --------------------------------------------------------- */
-/*                                                           */
-/* XML escaping utils                                        */
-/*                                                           */
-/* --------------------------------------------------------- */
-char *strescape(pool p, char *buf); /* Escape <>&'" chars */
-
-
-/* --------------------------------------------------------- */
-/*                                                           */
-/* String pools (spool) functions                            */
-/*                                                           */
-/* --------------------------------------------------------- */
-struct spool_node
-{
-    char *c;
-    struct spool_node *next;
-};
-
-typedef struct spool_struct
-{
-    pool p;
-    int len;
-    struct spool_node *last;
-    struct spool_node *first;
-} *spool;
-
-spool spool_new(pool p); /* create a string pool */
-void spooler(spool s, ...); /* append all the char * args to the pool, terminate args with s again */
-char *spool_print(spool s); /* return a big string */
-void spool_add(spool s, char *str); /* add a single char to the pool */
-char *spools(pool p, ...); /* wrap all the spooler stuff in one function, the happy fun ball! */
-
-
-/* --------------------------------------------------------- */
-/*                                                           */
-/* xmlnodes - Document Object Model                          */
-/*                                                           */
-/* --------------------------------------------------------- */
-#define NTYPE_TAG    0
-#define NTYPE_ATTRIB 1
-#define NTYPE_CDATA  2
-
-#define NTYPE_LAST   2
-#define NTYPE_UNDEF  -1
-
-/* -------------------------------------------------------------------------- 
-   Node structure. Do not use directly! Always use accessor macros 
-   and methods!
-   -------------------------------------------------------------------------- */
-typedef struct xmlnode_t
-{
-     char*               name;
-     unsigned short      type;
-     char*               data;
-     int                 data_sz;
-     int                 complete;
-     pool               p;
-     struct xmlnode_t*  parent;
-     struct xmlnode_t*  firstchild; 
-     struct xmlnode_t*  lastchild;
-     struct xmlnode_t*  prev; 
-     struct xmlnode_t*  next;
-     struct xmlnode_t*  firstattrib;
-     struct xmlnode_t*  lastattrib;
-} _xmlnode, *xmlnode;
-
-/* Node creation routines */
-xmlnode  xmlnode_wrap(xmlnode x,const char* wrapper);
-xmlnode  xmlnode_new_tag(const char* name);
-xmlnode  xmlnode_new_tag_pool(pool p, const char* name);
-xmlnode  xmlnode_insert_tag(xmlnode parent, const char* name); 
-xmlnode  xmlnode_insert_cdata(xmlnode parent, const char* CDATA, unsigned int size);
-xmlnode  xmlnode_insert_tag_node(xmlnode parent, xmlnode node);
-void     xmlnode_insert_node(xmlnode parent, xmlnode node);
-xmlnode  xmlnode_str(char *str, int len);
-xmlnode  xmlnode_file(char *file);
-xmlnode  xmlnode_dup(xmlnode x); /* duplicate x */
-xmlnode  xmlnode_dup_pool(pool p, xmlnode x);
-
-/* Node Memory Pool */
-pool xmlnode_pool(xmlnode node);
-xmlnode _xmlnode_new(pool p, const char *name, unsigned int type);
-
-/* Node editing */
-void xmlnode_hide(xmlnode child);
-void xmlnode_hide_attrib(xmlnode parent, const char *name);
-
-/* Node deletion routine, also frees the node pool! */
-void xmlnode_free(xmlnode node);
-
-/* Locates a child tag by name and returns it */
-xmlnode  xmlnode_get_tag(xmlnode parent, const char* name);
-char* xmlnode_get_tag_data(xmlnode parent, const char* name);
-
-/* Attribute accessors */
-void     xmlnode_put_attrib(xmlnode owner, const char* name, const char* value);
-char*    xmlnode_get_attrib(xmlnode owner, const char* name);
-void     xmlnode_put_expat_attribs(xmlnode owner, const char** atts);
-
-/* Bastard am I, but these are fun for internal use ;-) */
-void     xmlnode_put_vattrib(xmlnode owner, const char* name, void *value);
-void*    xmlnode_get_vattrib(xmlnode owner, const char* name);
-
-/* Node traversal routines */
-xmlnode  xmlnode_get_firstattrib(xmlnode parent);
-xmlnode  xmlnode_get_firstchild(xmlnode parent);
-xmlnode  xmlnode_get_lastchild(xmlnode parent);
-xmlnode  xmlnode_get_nextsibling(xmlnode sibling);
-xmlnode  xmlnode_get_prevsibling(xmlnode sibling);
-xmlnode  xmlnode_get_parent(xmlnode node);
-
-/* Node information routines */
-char*    xmlnode_get_name(xmlnode node);
-char*    xmlnode_get_data(xmlnode node);
-int      xmlnode_get_datasz(xmlnode node);
-int      xmlnode_get_type(xmlnode node);
-
-int      xmlnode_has_children(xmlnode node);
-int      xmlnode_has_attribs(xmlnode node);
-
-/* Node-to-string translation */
-char*    xmlnode2str(xmlnode node);
-
-/* Node-to-terminated-string translation 
-   -- useful for interfacing w/ scripting langs */
-char*    xmlnode2tstr(xmlnode node);
-
-int      xmlnode_cmp(xmlnode a, xmlnode b); /* compares a and b for equality */
-
-int      xmlnode2file(char *file, xmlnode node); /* writes node to file */
-
-/* Expat callbacks */
-void expat_startElement(void* userdata, const char* name, const char** atts);
-void expat_endElement(void* userdata, const char* name);
-void expat_charData(void* userdata, const char* s, int len);
-
-/* SHA.H */
-/* 
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is SHA 180-1 Header File
- * 
- * The Initial Developer of the Original Code is Paul Kocher of
- * Cryptography Research.  Portions created by Paul Kocher are 
- * Copyright (C) 1995-9 by Cryptography Research, Inc.  All
- * Rights Reserved.
- * 
- * Contributor(s):
- *
- *     Paul Kocher
- * 
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL"), in which case the provisions of the GPL are applicable 
- * instead of those above.  If you wish to allow use of your 
- * version of this file only under the terms of the GPL and not to
- * allow others to use your version of this file under the MPL,
- * indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by
- * the GPL.  If you do not delete the provisions above, a recipient
- * may use your version of this file under either the MPL or the
- * GPL.
- */
-
-typedef struct {
-  unsigned long H[5];
-  unsigned long W[80];
-  int lenW;
-  unsigned long sizeHi,sizeLo;
-} SHA_CTX;
-
-
-void shaInit(SHA_CTX *ctx);
-void shaUpdate(SHA_CTX *ctx, unsigned char *dataIn, int len);
-void shaFinal(SHA_CTX *ctx, unsigned char hashout[20]);
-void shaBlock(unsigned char *dataIn, int len, unsigned char hashout[20]);
-
-
-/* END SHA.H */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* INCL_LIBXODE_H */
Index: protocols/jabber/log.c
===================================================================
--- protocols/jabber/log.c	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,44 +1,0 @@
-/*
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- *  Jabber
- *  Copyright (C) 1998-1999 The Jabber Team http://jabber.org/
- */
-
-#include "jabber.h"
-#include "log.h"
-
-#ifdef DEBUG
-
-void jdebug(char *zone, const char *msgfmt, ...)
-{
-    va_list ap;
-    static char loghdr[LOGSIZE_HDR];
-    static char logmsg[LOGSIZE_TAIL];
-    static int size;
-
-    /* XXX: We may want to check the sizes eventually */
-    size = g_snprintf(loghdr, LOGSIZE_HDR, "debug/%s %s\n", zone, msgfmt);
-
-    va_start(ap, msgfmt);
-    size = vsnprintf(logmsg, LOGSIZE_TAIL, loghdr, ap);
-
-    fprintf(stderr,"%s",logmsg);
-
-    return;
-}
-
-
-#endif  /* DEBUG */
Index: protocols/jabber/log.h
===================================================================
--- protocols/jabber/log.h	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,36 +1,0 @@
-/*
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- *  Jabber
- *  Copyright (C) 1998-1999 The Jabber Team http://jabber.org/
- */
-
-#ifndef INCL_LOG_H
-#define INCL_LOG_H
-
-#define LOGSIZE_HDR 1024
-#define LOGSIZE_TAIL 2048
-
-
-#ifdef DEBUG
-	void jdebug(char *zone, const char *msgfmt, ...);
-#else
-	#define jdebug if(0) warn
-#endif
-
-
-
-#endif	/* INCL_LOG_H */
-
Index: protocols/jabber/message.c
===================================================================
--- protocols/jabber/message.c	(revision 0fd8559c4a6ad84ad0852e07c4ba2e50b2fdf0ad)
+++ protocols/jabber/message.c	(revision 0fd8559c4a6ad84ad0852e07c4ba2e50b2fdf0ad)
@@ -0,0 +1,105 @@
+/***************************************************************************\
+*                                                                           *
+*  BitlBee - An IRC to IM gateway                                           *
+*  Jabber module - Handling of message(s) (tags), etc                       *
+*                                                                           *
+*  Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net>                   *
+*                                                                           *
+*  This program is free software; you can redistribute it and/or modify     *
+*  it under the terms of the GNU General Public License as published by     *
+*  the Free Software Foundation; either version 2 of the License, or        *
+*  (at your option) any later version.                                      *
+*                                                                           *
+*  This program is distributed in the hope that it will be useful,          *
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
+*  GNU General Public License for more details.                             *
+*                                                                           *
+*  You should have received a copy of the GNU General Public License along  *
+*  with this program; if not, write to the Free Software Foundation, Inc.,  *
+*  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.              *
+*                                                                           *
+\***************************************************************************/
+
+#include "jabber.h"
+
+xt_status jabber_pkt_message( struct xt_node *node, gpointer data )
+{
+	struct gaim_connection *gc = data;
+	char *from = xt_find_attr( node, "from" );
+	char *type = xt_find_attr( node, "type" );
+	struct xt_node *body = xt_find_node( node->children, "body" ), *c;
+	char *s;
+	
+	if( type && strcmp( type, "error" ) == 0 )
+	{
+		/* Handle type=error packet. */
+	}
+	else if( type && strcmp( type, "groupchat" ) == 0 )
+	{
+		/* TODO! */
+	}
+	else /* "chat", "normal", "headline", no-type or whatever. Should all be pretty similar. */
+	{
+		struct jabber_buddy *bud = NULL;
+		GString *fullmsg = g_string_new( "" );
+		
+		if( ( s = strchr( from, '/' ) ) )
+		{
+			if( ( bud = jabber_buddy_by_jid( gc, from, GET_BUDDY_EXACT ) ) )
+				bud->last_act = time( NULL );
+			else
+				*s = 0; /* We need to generate a bare JID now. */
+		}
+		
+		if( type && strcmp( type, "headline" ) == 0 )
+		{
+			c = xt_find_node( node->children, "subject" );
+			g_string_append_printf( fullmsg, "Headline: %s\n", c && c->text_len > 0 ? c->text : "" );
+			
+			/* <x xmlns="jabber:x:oob"><url>http://....</url></x> can contain a URL, it seems. */
+			for( c = node->children; c; c = c->next )
+			{
+				struct xt_node *url;
+				
+				if( ( url = xt_find_node( c->children, "url" ) ) && url->text_len > 0 )
+					g_string_append_printf( fullmsg, "URL: %s\n", url->text );
+			}
+		}
+		else if( ( c = xt_find_node( node->children, "subject" ) ) && c->text_len > 0 )
+		{
+			g_string_append_printf( fullmsg, "<< \002BitlBee\002 - Message with subject: %s >>\n", c->text );
+		}
+		
+		if( body && body->text_len > 0 ) /* Could be just a typing notification. */
+			fullmsg = g_string_append( fullmsg, body->text );
+		
+		if( fullmsg->len > 0 )
+			serv_got_im( gc, bud ? bud->bare_jid : from, fullmsg->str, 0, 0, fullmsg->len );
+		
+		g_string_free( fullmsg, TRUE );
+		
+		/* Handling of incoming typing notifications. */
+		if( xt_find_node( node->children, "composing" ) )
+		{
+			bud->flags |= JBFLAG_DOES_XEP85;
+			serv_got_typing( gc, bud ? bud->bare_jid : from, 0, 1 );
+		}
+		/* No need to send a "stopped typing" signal when there's a message. */
+		else if( xt_find_node( node->children, "active" ) && ( body == NULL ) )
+		{
+			bud->flags |= JBFLAG_DOES_XEP85;
+			serv_got_typing( gc, bud ? bud->bare_jid : from, 0, 0 );
+		}
+		else if( xt_find_node( node->children, "paused" ) )
+		{
+			bud->flags |= JBFLAG_DOES_XEP85;
+			serv_got_typing( gc, bud ? bud->bare_jid : from, 0, 2 );
+		}
+		
+		if( s )
+			*s = '/'; /* And convert it back to a full JID. */
+	}
+	
+	return XT_HANDLED;
+}
Index: protocols/jabber/nametab.h
===================================================================
--- protocols/jabber/nametab.h	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,150 +1,0 @@
-static const unsigned namingBitmap[] = {
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
-0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
-0x00000000, 0x04000000, 0x87FFFFFE, 0x07FFFFFE,
-0x00000000, 0x00000000, 0xFF7FFFFF, 0xFF7FFFFF,
-0xFFFFFFFF, 0x7FF3FFFF, 0xFFFFFDFE, 0x7FFFFFFF,
-0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE00F, 0xFC31FFFF,
-0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF,
-0xFFFFFFFF, 0xF80001FF, 0x00000003, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0xFFFFD740, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD,
-0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF,
-0xFFFF0003, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF,
-0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE,
-0x0000007F, 0x00000000, 0xFFFF0000, 0x000707FF,
-0x00000000, 0x07FFFFFE, 0x000007FE, 0xFFFE0000,
-0xFFFFFFFF, 0x7CFFFFFF, 0x002F7FFF, 0x00000060,
-0xFFFFFFE0, 0x23FFFFFF, 0xFF000000, 0x00000003,
-0xFFF99FE0, 0x03C5FDFF, 0xB0000000, 0x00030003,
-0xFFF987E0, 0x036DFDFF, 0x5E000000, 0x001C0000,
-0xFFFBAFE0, 0x23EDFDFF, 0x00000000, 0x00000001,
-0xFFF99FE0, 0x23CDFDFF, 0xB0000000, 0x00000003,
-0xD63DC7E0, 0x03BFC718, 0x00000000, 0x00000000,
-0xFFFDDFE0, 0x03EFFDFF, 0x00000000, 0x00000003,
-0xFFFDDFE0, 0x03EFFDFF, 0x40000000, 0x00000003,
-0xFFFDDFE0, 0x03FFFDFF, 0x00000000, 0x00000003,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0xFFFFFFFE, 0x000D7FFF, 0x0000003F, 0x00000000,
-0xFEF02596, 0x200D6CAE, 0x0000001F, 0x00000000,
-0x00000000, 0x00000000, 0xFFFFFEFF, 0x000003FF,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0xFFFFFFFF, 0xFFFF003F, 0x007FFFFF,
-0x0007DAED, 0x50000000, 0x82315001, 0x002C62AB,
-0x40000000, 0xF580C900, 0x00000007, 0x02010800,
-0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
-0x0FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x03FFFFFF,
-0x3F3FFFFF, 0xFFFFFFFF, 0xAAFF3F3F, 0x3FFFFFFF,
-0xFFFFFFFF, 0x5FDFFFFF, 0x0FCF1FDC, 0x1FDC1FFF,
-0x00000000, 0x00004C40, 0x00000000, 0x00000000,
-0x00000007, 0x00000000, 0x00000000, 0x00000000,
-0x00000080, 0x000003FE, 0xFFFFFFFE, 0xFFFFFFFF,
-0x001FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x07FFFFFF,
-0xFFFFFFE0, 0x00001FFF, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
-0xFFFFFFFF, 0x0000003F, 0x00000000, 0x00000000,
-0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
-0xFFFFFFFF, 0x0000000F, 0x00000000, 0x00000000,
-0x00000000, 0x07FF6000, 0x87FFFFFE, 0x07FFFFFE,
-0x00000000, 0x00800000, 0xFF7FFFFF, 0xFF7FFFFF,
-0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF,
-0xFFFFFFFF, 0xF80001FF, 0x00030003, 0x00000000,
-0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000003,
-0xFFFFD7C0, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD,
-0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF,
-0xFFFF007B, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF,
-0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE,
-0xFFFE007F, 0xBBFFFFFB, 0xFFFF0016, 0x000707FF,
-0x00000000, 0x07FFFFFE, 0x0007FFFF, 0xFFFF03FF,
-0xFFFFFFFF, 0x7CFFFFFF, 0xFFEF7FFF, 0x03FF3DFF,
-0xFFFFFFEE, 0xF3FFFFFF, 0xFF1E3FFF, 0x0000FFCF,
-0xFFF99FEE, 0xD3C5FDFF, 0xB080399F, 0x0003FFCF,
-0xFFF987E4, 0xD36DFDFF, 0x5E003987, 0x001FFFC0,
-0xFFFBAFEE, 0xF3EDFDFF, 0x00003BBF, 0x0000FFC1,
-0xFFF99FEE, 0xF3CDFDFF, 0xB0C0398F, 0x0000FFC3,
-0xD63DC7EC, 0xC3BFC718, 0x00803DC7, 0x0000FF80,
-0xFFFDDFEE, 0xC3EFFDFF, 0x00603DDF, 0x0000FFC3,
-0xFFFDDFEC, 0xC3EFFDFF, 0x40603DDF, 0x0000FFC3,
-0xFFFDDFEC, 0xC3FFFDFF, 0x00803DCF, 0x0000FFC3,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0xFFFFFFFE, 0x07FF7FFF, 0x03FF7FFF, 0x00000000,
-0xFEF02596, 0x3BFF6CAE, 0x03FF3F5F, 0x00000000,
-0x03000000, 0xC2A003FF, 0xFFFFFEFF, 0xFFFE03FF,
-0xFEBF0FDF, 0x02FE3FFF, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x1FFF0000, 0x00000002,
-0x000000A0, 0x003EFFFE, 0xFFFFFFFE, 0xFFFFFFFF,
-0x661FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x77FFFFFF,
-};
-static const unsigned char nmstrtPages[] = {
-0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00,
-0x00, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13,
-0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-static const unsigned char namePages[] = {
-0x19, 0x03, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x00,
-0x00, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
-0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13,
-0x26, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x27, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
Index: protocols/jabber/pool.c
===================================================================
--- protocols/jabber/pool.c	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,247 +1,0 @@
-/* --------------------------------------------------------------------------
- *
- * License
- *
- * The contents of this file are subject to the Jabber Open Source License
- * Version 1.0 (the "JOSL").  You may not copy or use this file, in either
- * source code or executable form, except in compliance with the JOSL. You
- * may obtain a copy of the JOSL at http://www.jabber.org/ or at
- * http://www.opensource.org/.  
- *
- * Software distributed under the JOSL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the JOSL
- * for the specific language governing rights and limitations under the
- * JOSL.
- *
- * Copyrights
- * 
- * Portions created by or assigned to Jabber.com, Inc. are 
- * Copyright (c) 1999-2002 Jabber.com, Inc.  All Rights Reserved.  Contact
- * information for Jabber.com, Inc. is available at http://www.jabber.com/.
- *
- * Portions Copyright (c) 1998-1999 Jeremie Miller.
- * 
- * Acknowledgements
- * 
- * Special thanks to the Jabber Open Source Contributors for their
- * suggestions and support of Jabber.
- * 
- * Alternatively, the contents of this file may be used under the terms of the
- * GNU General Public License Version 2 or later (the "GPL"), in which case
- * the provisions of the GPL are applicable instead of those above.  If you
- * wish to allow use of your version of this file only under the terms of the
- * GPL and not to allow others to use your version of this file under the JOSL,
- * indicate your decision by deleting the provisions above and replace them
- * with the notice and other provisions required by the GPL.  If you do not
- * delete the provisions above, a recipient may use your version of this file
- * under either the JOSL or the GPL. 
- * 
- * 
- * --------------------------------------------------------------------------*/
-
-#include "jabber.h"
-#include "bitlbee.h"
-#include <glib.h>
-
-
-#ifdef POOL_DEBUG
-int pool__total = 0;
-int pool__ltotal = 0;
-HASHTABLE pool__disturbed = NULL;
-void *_pool__malloc(size_t size)
-{
-    pool__total++;
-    return g_malloc(size);
-}
-void _pool__free(void *block)
-{
-    pool__total--;
-    g_free(block);
-}
-#else
-#define _pool__malloc g_malloc
-#define _pool__free g_free
-#endif
-
-
-/* make an empty pool */
-pool _pool_new(char *zone)
-{
-    pool p;
-    while((p = _pool__malloc(sizeof(_pool))) == NULL) sleep(1);
-    p->cleanup = NULL;
-    p->heap = NULL;
-    p->size = 0;
-
-#ifdef POOL_DEBUG
-    p->lsize = -1;
-    p->zone[0] = '\0';
-    strcat(p->zone,zone);
-    sprintf(p->name,"%X",p);
-
-    if(pool__disturbed == NULL)
-    {
-        pool__disturbed = 1; /* reentrancy flag! */
-        pool__disturbed = ghash_create(POOL_DEBUG,(KEYHASHFUNC)str_hash_code,(KEYCOMPAREFUNC)j_strcmp);
-    }
-    if(pool__disturbed != 1)
-        ghash_put(pool__disturbed,p->name,p);
-#endif
-
-    return p;
-}
-
-/* free a heap */
-static void _pool_heap_free(void *arg)
-{
-    struct pheap *h = (struct pheap *)arg;
-
-    _pool__free(h->block);
-    _pool__free(h);
-}
-
-/* mem should always be freed last */
-static void _pool_cleanup_append(pool p, struct pfree *pf)
-{
-    struct pfree *cur;
-
-    if(p->cleanup == NULL)
-    {
-        p->cleanup = pf;
-        return;
-    }
-
-    /* fast forward to end of list */
-    for(cur = p->cleanup; cur->next != NULL; cur = cur->next);
-
-    cur->next = pf;
-}
-
-/* create a cleanup tracker */
-static struct pfree *_pool_free(pool p, pool_cleaner f, void *arg)
-{
-    struct pfree *ret;
-
-    /* make the storage for the tracker */
-    while((ret = _pool__malloc(sizeof(struct pfree))) == NULL) sleep(1);
-    ret->f = f;
-    ret->arg = arg;
-    ret->next = NULL;
-
-    return ret;
-}
-
-/* create a heap and make sure it get's cleaned up */
-static struct pheap *_pool_heap(pool p, int size)
-{
-    struct pheap *ret;
-    struct pfree *clean;
-
-    /* make the return heap */
-    while((ret = _pool__malloc(sizeof(struct pheap))) == NULL) sleep(1);
-    while((ret->block = _pool__malloc(size)) == NULL) sleep(1);
-    ret->size = size;
-    p->size += size;
-    ret->used = 0;
-
-    /* append to the cleanup list */
-    clean = _pool_free(p, _pool_heap_free, (void *)ret);
-    clean->heap = ret; /* for future use in finding used mem for pstrdup */
-    _pool_cleanup_append(p, clean);
-
-    return ret;
-}
-
-pool _pool_new_heap(int size, char *zone)
-{
-    pool p;
-    p = _pool_new(zone);
-    p->heap = _pool_heap(p,size);
-    return p;
-}
-
-void *pmalloc(pool p, int size)
-{
-    void *block;
-
-    if(p == NULL)
-    {
-        fprintf(stderr,"Memory Leak! [pmalloc received NULL pool, unable to track allocation, exiting]\n");
-        abort();
-    }
-
-    /* if there is no heap for this pool or it's a big request, just raw, I like how we clean this :) */
-    if(p->heap == NULL || size > (p->heap->size / 2))
-    {
-        while((block = _pool__malloc(size)) == NULL) sleep(1);
-        p->size += size;
-        _pool_cleanup_append(p, _pool_free(p, _pool__free, block));
-        return block;
-    }
-
-    /* we have to preserve boundaries, long story :) */
-    if(size >= 4)
-        while(p->heap->used&7) p->heap->used++;
-
-    /* if we don't fit in the old heap, replace it */
-    if(size > (p->heap->size - p->heap->used))
-        p->heap = _pool_heap(p, p->heap->size);
-
-    /* the current heap has room */
-    block = (char *)p->heap->block + p->heap->used;
-    p->heap->used += size;
-    return block;
-}
-
-void *pmalloc_x(pool p, int size, char c)
-{
-   void* result = pmalloc(p, size);
-   if (result != NULL)
-           memset(result, c, size);
-   return result;
-}  
-
-/* easy safety utility (for creating blank mem for structs, etc) */
-void *pmalloco(pool p, int size)
-{
-    void *block = pmalloc(p, size);
-    memset(block, 0, size);
-    return block;
-}  
-
-/* XXX efficient: move this to const char * and then loop throug the existing heaps to see if src is within a block in this pool */
-char *pstrdup(pool p, const char *src)
-{
-    char *ret;
-
-    if(src == NULL)
-        return NULL;
-
-    ret = pmalloc(p,strlen(src) + 1);
-    strcpy(ret,src);
-
-    return ret;
-}
-
-void pool_free(pool p)
-{
-    struct pfree *cur, *stub;
-
-    if(p == NULL) return;
-
-    cur = p->cleanup;
-    while(cur != NULL)
-    {
-        (*cur->f)(cur->arg);
-        stub = cur->next;
-        _pool__free(cur);
-        cur = stub;
-    }
-
-#ifdef POOL_DEBUG
-    ghash_remove(pool__disturbed,p->name);
-#endif
-
-    _pool__free(p);
-
-}
Index: protocols/jabber/presence.c
===================================================================
--- protocols/jabber/presence.c	(revision 0fd8559c4a6ad84ad0852e07c4ba2e50b2fdf0ad)
+++ protocols/jabber/presence.c	(revision 0fd8559c4a6ad84ad0852e07c4ba2e50b2fdf0ad)
@@ -0,0 +1,166 @@
+/***************************************************************************\
+*                                                                           *
+*  BitlBee - An IRC to IM gateway                                           *
+*  Jabber module - Handling of presence (tags), etc                         *
+*                                                                           *
+*  Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net>                   *
+*                                                                           *
+*  This program is free software; you can redistribute it and/or modify     *
+*  it under the terms of the GNU General Public License as published by     *
+*  the Free Software Foundation; either version 2 of the License, or        *
+*  (at your option) any later version.                                      *
+*                                                                           *
+*  This program is distributed in the hope that it will be useful,          *
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
+*  GNU General Public License for more details.                             *
+*                                                                           *
+*  You should have received a copy of the GNU General Public License along  *
+*  with this program; if not, write to the Free Software Foundation, Inc.,  *
+*  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.              *
+*                                                                           *
+\***************************************************************************/
+
+#include "jabber.h"
+
+xt_status jabber_pkt_presence( struct xt_node *node, gpointer data )
+{
+	struct gaim_connection *gc = data;
+	char *from = xt_find_attr( node, "from" );
+	char *type = xt_find_attr( node, "type" );	/* NULL should mean the person is online. */
+	struct xt_node *c;
+	struct jabber_buddy *bud;
+	char *s;
+	
+	if( !from )
+		return XT_HANDLED;
+	
+	if( type == NULL )
+	{
+		if( !( bud = jabber_buddy_by_jid( gc, from, GET_BUDDY_EXACT | GET_BUDDY_CREAT ) ) )
+		{
+			serv_got_crap( gc, "WARNING: Could not handle presence information from JID: %s", from );
+			return XT_HANDLED;
+		}
+		
+		g_free( bud->away_message );
+		if( ( c = xt_find_node( node->children, "status" ) ) && c->text_len > 0 )
+			bud->away_message = g_strdup( c->text );
+		else
+			bud->away_message = NULL;
+		
+		if( ( c = xt_find_node( node->children, "show" ) ) && c->text_len > 0 )
+			bud->away_state = (void*) jabber_away_state_by_code( c->text );
+		else
+		{
+			bud->away_state = NULL;
+			/* Let's only set last_act if there's *no* away state,
+			   since it could be some auto-away thingy. */
+			bud->last_act = time( NULL );
+		}
+		
+		if( ( c = xt_find_node( node->children, "priority" ) ) && c->text_len > 0 )
+			bud->priority = atoi( c->text );
+		else
+			bud->priority = 0;
+		
+		serv_got_update( gc, bud->bare_jid, 1, 0, 0, 0,
+		                 bud->away_state ? UC_UNAVAILABLE : 0, 0 );
+	}
+	else if( strcmp( type, "unavailable" ) == 0 )
+	{
+		if( jabber_buddy_by_jid( gc, from, GET_BUDDY_EXACT ) == NULL )
+		{
+			serv_got_crap( gc, "WARNING: Received presence information from unknown JID: %s", from );
+			return XT_HANDLED;
+		}
+		
+		jabber_buddy_remove( gc, from );
+		
+		if( ( s = strchr( from, '/' ) ) )
+		{
+			*s = 0;
+		
+			/* Only count this as offline if there's no other resource
+			   available anymore. */
+			if( jabber_buddy_by_jid( gc, from, 0 ) == NULL )
+				serv_got_update( gc, from, 0, 0, 0, 0, 0, 0 );
+			
+			*s = '/';
+		}
+		else
+		{
+			serv_got_update( gc, from, 0, 0, 0, 0, 0, 0 );
+		}
+	}
+	else if( strcmp( type, "subscribe" ) == 0 )
+	{
+		jabber_buddy_ask( gc, from );
+	}
+	else if( strcmp( type, "subscribed" ) == 0 )
+	{
+		/* Not sure about this one, actually... */
+		serv_got_crap( gc, "%s just accepted your authorization request", from );
+	}
+	else if( strcmp( type, "unsubscribe" ) == 0 || strcmp( type, "unsubscribed" ) == 0 )
+	{
+		/* Do nothing here. Plenty of control freaks or over-curious
+		   souls get excited when they can see who still has them in
+		   their buddy list and who finally removed them. Somehow I
+		   got the impression that those are the people who get
+		   removed from many buddy lists for "some" reason...
+		   
+		   If you're one of those people, this is your chance to write
+		   your first line of code in C... */
+	}
+	else if( strcmp( type, "error" ) == 0 )
+	{
+		/* What to do with it? */
+	}
+	else
+	{
+		printf( "Received PRES from %s:\n", from );
+		xt_print( node );
+	}
+	
+	return XT_HANDLED;
+}
+
+/* Whenever presence information is updated, call this function to inform the
+   server. */
+int presence_send_update( struct gaim_connection *gc )
+{
+	struct jabber_data *jd = gc->proto_data;
+	struct xt_node *node;
+	char *show = jd->away_state->code;
+	char *status = jd->away_message;
+	int st;
+	
+	node = jabber_make_packet( "presence", NULL, NULL, NULL );
+	xt_add_child( node, xt_new_node( "priority", set_getstr( &gc->acc->set, "priority" ), NULL ) );
+	if( show && *show )
+		xt_add_child( node, xt_new_node( "show", show, NULL ) );
+	if( status )
+		xt_add_child( node, xt_new_node( "status", status, NULL ) );
+	
+	st = jabber_write_packet( gc, node );
+	
+	xt_free_node( node );
+	return st;
+}
+
+/* Send a subscribe/unsubscribe request to a buddy. */
+int presence_send_request( struct gaim_connection *gc, char *handle, char *request )
+{
+	struct xt_node *node;
+	int st;
+	
+	node = jabber_make_packet( "presence", NULL, NULL, NULL );
+	xt_add_attr( node, "to", handle );
+	xt_add_attr( node, "type", request );
+	
+	st = jabber_write_packet( gc, node );
+	
+	xt_free_node( node );
+	return st;
+}
Index: protocols/jabber/sasl.c
===================================================================
--- protocols/jabber/sasl.c	(revision 0fd8559c4a6ad84ad0852e07c4ba2e50b2fdf0ad)
+++ protocols/jabber/sasl.c	(revision 0fd8559c4a6ad84ad0852e07c4ba2e50b2fdf0ad)
@@ -0,0 +1,332 @@
+/***************************************************************************\
+*                                                                           *
+*  BitlBee - An IRC to IM gateway                                           *
+*  Jabber module - SASL authentication                                      *
+*                                                                           *
+*  Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net>                   *
+*                                                                           *
+*  This program is free software; you can redistribute it and/or modify     *
+*  it under the terms of the GNU General Public License as published by     *
+*  the Free Software Foundation; either version 2 of the License, or        *
+*  (at your option) any later version.                                      *
+*                                                                           *
+*  This program is distributed in the hope that it will be useful,          *
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
+*  GNU General Public License for more details.                             *
+*                                                                           *
+*  You should have received a copy of the GNU General Public License along  *
+*  with this program; if not, write to the Free Software Foundation, Inc.,  *
+*  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.              *
+*                                                                           *
+\***************************************************************************/
+
+#include "jabber.h"
+#include "base64.h"
+
+xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data )
+{
+	struct gaim_connection *gc = data;
+	struct jabber_data *jd = gc->proto_data;
+	struct xt_node *c, *reply;
+	char *s;
+	int sup_plain = 0, sup_digest = 0;
+	
+	if( !sasl_supported( gc ) )
+	{
+		/* Should abort this now, since we should already be doing
+		   IQ authentication. Strange things happen when you try
+		   to do both... */
+		serv_got_crap( gc, "XMPP 1.0 non-compliant server seems to support SASL, please report this as a BitlBee bug!" );
+		return XT_HANDLED;
+	}
+	
+	s = xt_find_attr( node, "xmlns" );
+	if( !s || strcmp( s, XMLNS_SASL ) != 0 )
+	{
+		signoff( gc );
+		return XT_ABORT;
+	}
+	
+	c = node->children;
+	while( ( c = xt_find_node( c, "mechanism" ) ) )
+	{
+		if( c->text && g_strcasecmp( c->text, "PLAIN" ) == 0 )
+			sup_plain = 1;
+		if( c->text && g_strcasecmp( c->text, "DIGEST-MD5" ) == 0 )
+			sup_digest = 1;
+		
+		c = c->next;
+	}
+	
+	if( !sup_plain && !sup_digest )
+	{
+		hide_login_progress( gc, "No known SASL authentication schemes supported" );
+		signoff( gc );
+		return XT_ABORT;
+	}
+	
+	reply = xt_new_node( "auth", NULL, NULL );
+	xt_add_attr( reply, "xmlns", XMLNS_SASL );
+	
+	if( sup_digest )
+	{
+		xt_add_attr( reply, "mechanism", "DIGEST-MD5" );
+		
+		/* The rest will be done later, when we receive a <challenge/>. */
+	}
+	else if( sup_plain )
+	{
+		int len;
+		
+		xt_add_attr( reply, "mechanism", "PLAIN" );
+		
+		/* With SASL PLAIN in XMPP, the text should be b64(\0user\0pass) */
+		len = strlen( jd->username ) + strlen( gc->acc->pass ) + 2;
+		s = g_malloc( len + 1 );
+		s[0] = 0;
+		strcpy( s + 1, jd->username );
+		strcpy( s + 2 + strlen( jd->username ), gc->acc->pass );
+		reply->text = base64_encode( s, len );
+		reply->text_len = strlen( reply->text );
+		g_free( s );
+	}
+	
+	if( !jabber_write_packet( gc, reply ) )
+	{
+		xt_free_node( reply );
+		return XT_ABORT;
+	}
+	xt_free_node( reply );
+	
+	/* To prevent classic authentication from happening. */
+	jd->flags |= JFLAG_STREAM_STARTED;
+	
+	return XT_HANDLED;
+}
+
+static char *sasl_get_part( char *data, char *field )
+{
+	int i, len;
+	
+	len = strlen( field );
+	
+	if( g_strncasecmp( data, field, len ) == 0 && data[len] == '=' )
+	{
+		i = strlen( field ) + 1;
+	}
+	else
+	{
+		for( i = 0; data[i]; i ++ )
+		{
+			/* If we have a ", skip until it's closed again. */
+			if( data[i] == '"' )
+			{
+				i ++;
+				while( data[i] != '"' || data[i-1] == '\\' )
+					i ++;
+			}
+			
+			/* If we got a comma, we got a new field. Check it. */
+			if( data[i] == ',' &&
+			    g_strncasecmp( data + i + 1, field, len ) == 0 &&
+			    data[i+len+1] == '=' )
+			{
+				i += len + 2;
+				break;
+			}
+		}
+	}
+	
+	if( data[i] == '"' )
+	{
+		int j;
+		char *ret;
+		
+		i ++;
+		len = 0;
+		while( data[i+len] != '"' || data[i+len-1] == '\\' )
+			len ++;
+		
+		ret = g_strndup( data + i, len );
+		for( i = j = 0; ret[i]; i ++ )
+		{
+			if( ret[i] == '\\' )
+			{
+				ret[j++] = ret[++i];
+			}
+			else
+			{
+				ret[j++] = ret[i];
+			}
+		}
+		ret[j] = 0;
+		
+		return ret;
+	}
+	else if( data[i] )
+	{
+		len = 0;
+		while( data[i+len] && data[i+len] != ',' )
+			len ++;
+		
+		return g_strndup( data + i, len );
+	}
+	else
+	{
+		return NULL;
+	}
+}
+
+xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data )
+{
+	struct gaim_connection *gc = data;
+	struct jabber_data *jd = gc->proto_data;
+	struct xt_node *reply = NULL;
+	char *nonce = NULL, *realm = NULL, *cnonce = NULL, cnonce_bin[30];
+	char *digest_uri = NULL;
+	char *dec = NULL;
+	char *s = NULL;
+	xt_status ret = XT_ABORT;
+	
+	if( node->text_len == 0 )
+		goto error;
+	
+	dec = frombase64( node->text );
+	
+	if( !( s = sasl_get_part( dec, "rspauth" ) ) )
+	{
+		/* See RFC 2831 for for information. */
+		md5_state_t A1, A2, H;
+		md5_byte_t A1r[16], A2r[16], Hr[16];
+		char A1h[33], A2h[33], Hh[33];
+		int i;
+		
+		nonce = sasl_get_part( dec, "nonce" );
+		realm = sasl_get_part( dec, "realm" );
+		
+		if( !nonce )
+			goto error;
+		
+		/* Jabber.Org considers the realm part optional and doesn't
+		   specify one. Oh well, actually they're right, but still,
+		   don't know if this is right... */
+		if( !realm )
+			realm = g_strdup( jd->server );
+		
+		random_bytes( (unsigned char *) cnonce_bin, sizeof( cnonce_bin ) );
+		cnonce = base64_encode( cnonce_bin, sizeof( cnonce_bin ) );
+		digest_uri = g_strdup_printf( "%s/%s", "xmpp", jd->server );
+		
+		/* Generate the MD5 hash of username:realm:password,
+		   I decided to call it H. */
+		md5_init( &H );
+		s = g_strdup_printf( "%s:%s:%s", jd->username, realm, gc->acc->pass );
+		md5_append( &H, (unsigned char *) s, strlen( s ) );
+		g_free( s );
+		md5_finish( &H, Hr );
+		
+		/* Now generate the hex. MD5 hash of H:nonce:cnonce, called A1. */
+		md5_init( &A1 );
+		s = g_strdup_printf( ":%s:%s", nonce, cnonce );
+		md5_append( &A1, Hr, 16 );
+		md5_append( &A1, (unsigned char *) s, strlen( s ) );
+		g_free( s );
+		md5_finish( &A1, A1r );
+		for( i = 0; i < 16; i ++ )
+			sprintf( A1h + i * 2, "%02x", A1r[i] );
+		
+		/* A2... */
+		md5_init( &A2 );
+		s = g_strdup_printf( "%s:%s", "AUTHENTICATE", digest_uri );
+		md5_append( &A2, (unsigned char *) s, strlen( s ) );
+		g_free( s );
+		md5_finish( &A2, A2r );
+		for( i = 0; i < 16; i ++ )
+			sprintf( A2h + i * 2, "%02x", A2r[i] );
+		
+		/* Final result: A1:nonce:00000001:cnonce:auth:A2. Let's reuse H for it. */
+		md5_init( &H );
+		s = g_strdup_printf( "%s:%s:%s:%s:%s:%s", A1h, nonce, "00000001", cnonce, "auth", A2h );
+		md5_append( &H, (unsigned char *) s, strlen( s ) );
+		g_free( s );
+		md5_finish( &H, Hr );
+		for( i = 0; i < 16; i ++ )
+			sprintf( Hh + i * 2, "%02x", Hr[i] );
+		
+		/* Now build the SASL response string: */
+		g_free( dec );
+		dec = g_strdup_printf( "username=\"%s\",realm=\"%s\",nonce=\"%s\",cnonce=\"%s\","
+		                       "nc=%08x,qop=auth,digest-uri=\"%s\",response=%s,charset=%s",
+		                       jd->username, realm, nonce, cnonce, 1, digest_uri, Hh, "utf-8" );
+		s = tobase64( dec );
+	}
+	else
+	{
+		/* We found rspauth, but don't really care... */
+		g_free( s );
+		s = NULL;
+	}
+	
+	reply = xt_new_node( "response", s, NULL );
+	xt_add_attr( reply, "xmlns", XMLNS_SASL );
+	
+	if( !jabber_write_packet( gc, reply ) )
+		goto silent_error;
+	
+	ret = XT_HANDLED;
+	goto silent_error;
+
+error:
+	hide_login_progress( gc, "Incorrect SASL challenge received" );
+	signoff( gc );
+
+silent_error:
+	g_free( digest_uri );
+	g_free( cnonce );
+	g_free( nonce );
+	g_free( realm );
+	g_free( dec );
+	g_free( s );
+	xt_free_node( reply );
+	
+	return ret;
+}
+
+xt_status sasl_pkt_result( struct xt_node *node, gpointer data )
+{
+	struct gaim_connection *gc = data;
+	struct jabber_data *jd = gc->proto_data;
+	char *s;
+	
+	s = xt_find_attr( node, "xmlns" );
+	if( !s || strcmp( s, XMLNS_SASL ) != 0 )
+	{
+		signoff( gc );
+		return XT_ABORT;
+	}
+	
+	if( strcmp( node->name, "success" ) == 0 )
+	{
+		set_login_progress( gc, 1, "Authentication finished" );
+		jd->flags |= JFLAG_AUTHENTICATED | JFLAG_STREAM_RESTART;
+	}
+	else if( strcmp( node->name, "failure" ) == 0 )
+	{
+		hide_login_progress( gc, "Authentication failure" );
+		signoff( gc );
+		return XT_ABORT;
+	}
+	
+	return XT_HANDLED;
+}
+
+/* This one is needed to judge if we'll do authentication using IQ or SASL.
+   It's done by checking if the <stream:stream> from the server has a
+   version attribute. I don't know if this is the right way though... */
+gboolean sasl_supported( struct gaim_connection *gc )
+{
+	struct jabber_data *jd = gc->proto_data;
+	
+	return ( (void*) ( jd->xt && jd->xt->root && xt_find_attr( jd->xt->root, "version" ) ) ) != NULL;
+}
Index: protocols/jabber/str.c
===================================================================
--- protocols/jabber/str.c	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,215 +1,0 @@
-/* --------------------------------------------------------------------------
- *
- * License
- *
- * The contents of this file are subject to the Jabber Open Source License
- * Version 1.0 (the "JOSL").  You may not copy or use this file, in either
- * source code or executable form, except in compliance with the JOSL. You
- * may obtain a copy of the JOSL at http://www.jabber.org/ or at
- * http://www.opensource.org/.  
- *
- * Software distributed under the JOSL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the JOSL
- * for the specific language governing rights and limitations under the
- * JOSL.
- *
- * Copyrights
- * 
- * Portions created by or assigned to Jabber.com, Inc. are 
- * Copyright (c) 1999-2002 Jabber.com, Inc.  All Rights Reserved.  Contact
- * information for Jabber.com, Inc. is available at http://www.jabber.com/.
- *
- * Portions Copyright (c) 1998-1999 Jeremie Miller.
- * 
- * Acknowledgements
- * 
- * Special thanks to the Jabber Open Source Contributors for their
- * suggestions and support of Jabber.
- * 
- * Alternatively, the contents of this file may be used under the terms of the
- * GNU General Public License Version 2 or later (the "GPL"), in which case
- * the provisions of the GPL are applicable instead of those above.  If you
- * wish to allow use of your version of this file only under the terms of the
- * GPL and not to allow others to use your version of this file under the JOSL,
- * indicate your decision by deleting the provisions above and replace them
- * with the notice and other provisions required by the GPL.  If you do not
- * delete the provisions above, a recipient may use your version of this file
- * under either the JOSL or the GPL. 
- * 
- * 
- * --------------------------------------------------------------------------*/
-
-#include "jabber.h"
-#include <glib.h>
-
-static char *j_strcat(char *dest, char *txt)
-{
-    if(!txt) return(dest);
-
-    while(*txt)
-        *dest++ = *txt++;
-    *dest = '\0';
-
-    return(dest);
-}
-
-int j_strcmp(const char *a, const char *b)
-{
-    if(a == NULL || b == NULL)
-        return -1;
-
-    while(*a == *b && *a != '\0' && *b != '\0'){ a++; b++; }
-
-    if(*a == *b) return 0;
-
-    return -1;
-}
-
-spool spool_new(pool p)
-{
-    spool s;
-
-    s = pmalloc(p, sizeof(struct spool_struct));
-    s->p = p;
-    s->len = 0;
-    s->last = NULL;
-    s->first = NULL;
-    return s;
-}
-
-void spool_add(spool s, char *str)
-{
-    struct spool_node *sn;
-    int len;
-
-    if(str == NULL)
-        return;
-
-    len = strlen(str);
-    if(len == 0)
-        return;
-
-    sn = pmalloc(s->p, sizeof(struct spool_node));
-    sn->c = pstrdup(s->p, str);
-    sn->next = NULL;
-
-    s->len += len;
-    if(s->last != NULL)
-        s->last->next = sn;
-    s->last = sn;
-    if(s->first == NULL)
-        s->first = sn;
-}
-
-void spooler(spool s, ...)
-{
-    va_list ap;
-    char *arg = NULL;
-
-    if(s == NULL)
-        return;
-
-    VA_START(s);
-
-    /* loop till we hfit our end flag, the first arg */
-    while(1)
-    {
-        arg = va_arg(ap,char *);
-        if((spool)arg == s)
-            break;
-        else
-            spool_add(s, arg);
-    }
-
-    va_end(ap);
-}
-
-char *spool_print(spool s)
-{
-    char *ret,*tmp;
-    struct spool_node *next;
-
-    if(s == NULL || s->len == 0 || s->first == NULL)
-        return NULL;
-
-    ret = pmalloc(s->p, s->len + 1);
-    *ret = '\0';
-
-    next = s->first;
-    tmp = ret;
-    while(next != NULL)
-    {
-        tmp = j_strcat(tmp,next->c);
-        next = next->next;
-    }
-
-    return ret;
-}
-
-char *strescape(pool p, char *buf)
-{
-    int i,j,oldlen,newlen;
-    char *temp;
-
-    if (p == NULL || buf == NULL) return(NULL);
-
-    oldlen = newlen = strlen(buf);
-    for(i=0;i<oldlen;i++)
-    {
-        switch(buf[i])
-        {
-        case '&':
-            newlen+=5;
-            break;
-        case '\'':
-            newlen+=6;
-            break;
-        case '\"':
-            newlen+=6;
-            break;
-        case '<':
-            newlen+=4;
-            break;
-        case '>':
-            newlen+=4;
-            break;
-        }
-    }
-
-    if(oldlen == newlen) return buf;
-
-    temp = pmalloc(p,newlen+1);
-
-    if (temp==NULL) return(NULL);
-
-    for(i=j=0;i<oldlen;i++)
-    {
-        switch(buf[i])
-        {
-        case '&':
-            memcpy(&temp[j],"&amp;",5);
-            j += 5;
-            break;
-        case '\'':
-            memcpy(&temp[j],"&apos;",6);
-            j += 6;
-            break;
-        case '\"':
-            memcpy(&temp[j],"&quot;",6);
-            j += 6;
-            break;
-        case '<':
-            memcpy(&temp[j],"&lt;",4);
-            j += 4;
-            break;
-        case '>':
-            memcpy(&temp[j],"&gt;",4);
-            j += 4;
-            break;
-        default:
-            temp[j++] = buf[i];
-        }
-    }
-    temp[j] = '\0';
-    return temp;
-}
Index: protocols/jabber/utf8tab.h
===================================================================
--- protocols/jabber/utf8tab.h	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,63 +1,0 @@
-/*
-The contents of this file are subject to the Mozilla Public License
-Version 1.1 (the "License"); you may not use this file except in
-compliance with the License. You may obtain a copy of the License at
-http://www.mozilla.org/MPL/
-
-Software distributed under the License is distributed on an "AS IS"
-basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
-License for the specific language governing rights and limitations
-under the License.
-
-The Original Code is expat.
-
-The Initial Developer of the Original Code is James Clark.
-Portions created by James Clark are Copyright (C) 1998, 1999
-James Clark. All Rights Reserved.
-
-Contributor(s):
-
-Alternatively, the contents of this file may be used under the terms
-of the GNU General Public License (the "GPL"), in which case the
-provisions of the GPL are applicable instead of those above.  If you
-wish to allow use of your version of this file only under the terms of
-the GPL and not to allow others to use your version of this file under
-the MPL, indicate your decision by deleting the provisions above and
-replace them with the notice and other provisions required by the
-GPL. If you do not delete the provisions above, a recipient may use
-your version of this file under either the MPL or the GPL.
-*/
-
-
-/* 0x80 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0x84 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0x88 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0x8C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0x90 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0x94 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0x98 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0x9C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0xA0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0xA4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0xA8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0xAC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0xB0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0xB4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0xB8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0xBC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0xC0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
-/* 0xC4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
-/* 0xC8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
-/* 0xCC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
-/* 0xD0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
-/* 0xD4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
-/* 0xD8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
-/* 0xDC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
-/* 0xE0 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
-/* 0xE4 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
-/* 0xE8 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
-/* 0xEC */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
-/* 0xF0 */ BT_LEAD4, BT_LEAD4, BT_LEAD4, BT_LEAD4,
-/* 0xF4 */ BT_LEAD4, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0xF8 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0xFC */ BT_NONXML, BT_NONXML, BT_MALFORM, BT_MALFORM,
Index: protocols/jabber/xmldef.h
===================================================================
--- protocols/jabber/xmldef.h	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,34 +1,0 @@
-/*
-The contents of this file are subject to the Mozilla Public License
-Version 1.1 (the "License"); you may not use this file except in
-compliance with the License. You may obtain a copy of the License at
-http://www.mozilla.org/MPL/
-
-Software distributed under the License is distributed on an "AS IS"
-basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
-License for the specific language governing rights and limitations
-under the License.
-
-The Original Code is expat.
-
-The Initial Developer of the Original Code is James Clark.
-Portions created by James Clark are Copyright (C) 1998, 1999
-James Clark. All Rights Reserved.
-
-Contributor(s):
-
-Alternatively, the contents of this file may be used under the terms
-of the GNU General Public License (the "GPL"), in which case the
-provisions of the GPL are applicable instead of those above.  If you
-wish to allow use of your version of this file only under the terms of
-the GPL and not to allow others to use your version of this file under
-the MPL, indicate your decision by deleting the provisions above and
-replace them with the notice and other provisions required by the
-GPL. If you do not delete the provisions above, a recipient may use
-your version of this file under either the MPL or the GPL.
-*/
-
-#include <glib.h>
-#include <string.h>
-#include <stdlib.h>
-
Index: protocols/jabber/xmlnode.c
===================================================================
--- protocols/jabber/xmlnode.c	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,705 +1,0 @@
-/* --------------------------------------------------------------------------
- *
- * License
- *
- * The contents of this file are subject to the Jabber Open Source License
- * Version 1.0 (the "JOSL").  You may not copy or use this file, in either
- * source code or executable form, except in compliance with the JOSL. You
- * may obtain a copy of the JOSL at http://www.jabber.org/ or at
- * http://www.opensource.org/.  
- *
- * Software distributed under the JOSL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the JOSL
- * for the specific language governing rights and limitations under the
- * JOSL.
- *
- * Copyrights
- * 
- * Portions created by or assigned to Jabber.com, Inc. are 
- * Copyright (c) 1999-2002 Jabber.com, Inc.  All Rights Reserved.  Contact
- * information for Jabber.com, Inc. is available at http://www.jabber.com/.
- *
- * Portions Copyright (c) 1998-1999 Jeremie Miller.
- * 
- * Acknowledgements
- * 
- * Special thanks to the Jabber Open Source Contributors for their
- * suggestions and support of Jabber.
- * 
- * Alternatively, the contents of this file may be used under the terms of the
- * GNU General Public License Version 2 or later (the "GPL"), in which case
- * the provisions of the GPL are applicable instead of those above.  If you
- * wish to allow use of your version of this file only under the terms of the
- * GPL and not to allow others to use your version of this file under the JOSL,
- * indicate your decision by deleting the provisions above and replace them
- * with the notice and other provisions required by the GPL.  If you do not
- * delete the provisions above, a recipient may use your version of this file
- * under either the JOSL or the GPL. 
- * 
- * 
- * --------------------------------------------------------------------------*/
-
-#include "jabber.h"
-#include <glib.h>
-
-static xmlnode xmlnode_get_firstattrib(xmlnode parent);
-static int xmlnode_get_type(xmlnode node);
-static void xmlnode_insert_node(xmlnode parent, xmlnode node);
-
-/* Internal routines */
-static xmlnode _xmlnode_new(pool p, const char* name, unsigned int type)
-{
-    xmlnode result = NULL;
-    if (type > NTYPE_LAST)
-        return NULL;
-
-    if (type != NTYPE_CDATA && name == NULL)
-        return NULL;
-
-    if (p == NULL)
-    {
-        p = pool_heap(1*1024);
-    }
-
-    /* Allocate & zero memory */
-    result = (xmlnode)pmalloco(p, sizeof(_xmlnode));
-
-    /* Initialize fields */
-    if (type != NTYPE_CDATA)
-        result->name = pstrdup(p,name);
-    result->type = type;
-    result->p = p;
-    return result;
-}
-
-static xmlnode _xmlnode_append_sibling(xmlnode lastsibling, const char* name, unsigned int type)
-{
-    xmlnode result;
-
-    result = _xmlnode_new(xmlnode_pool(lastsibling), name, type);
-    if (result != NULL)
-    {
-        /* Setup sibling pointers */
-        result->prev = lastsibling;
-        lastsibling->next = result;
-    }
-    return result;
-}
-
-static xmlnode _xmlnode_insert(xmlnode parent, const char* name, unsigned int type)
-{
-    xmlnode result;
-
-    if(parent == NULL || (type != NTYPE_CDATA && name == NULL)) return NULL;
-
-    /* If parent->firstchild is NULL, simply create a new node for the first child */
-    if (parent->firstchild == NULL)
-    {
-        result = _xmlnode_new(parent->p, name, type);
-        parent->firstchild = result;
-    }
-    /* Otherwise, append this to the lastchild */
-    else
-    {
-        result= _xmlnode_append_sibling(parent->lastchild, name, type);
-    }
-    result->parent = parent;
-    parent->lastchild = result;
-    return result;
-
-}
-
-static xmlnode _xmlnode_search(xmlnode firstsibling, const char* name, unsigned int type)
-{
-    xmlnode current;
-
-    /* Walk the sibling list, looking for a NTYPE_TAG xmlnode with
-    the specified name */
-    current = firstsibling;
-    while (current != NULL)
-    {
-        if ((current->type == type) && (j_strcmp(current->name, name) == 0))
-            return current;
-        else
-            current = current->next;
-    }
-    return NULL;
-}
-
-static void _xmlnode_merge(xmlnode data)
-{
-    xmlnode cur;
-    char *merge, *scur;
-    int imerge;
-
-    /* get total size of all merged cdata */
-    imerge = 0;
-    for(cur = data; cur != NULL && cur->type == NTYPE_CDATA; cur = cur->next)
-        imerge += cur->data_sz;
-
-    /* copy in current data and then spin through all of them and merge */
-    scur = merge = pmalloc(data->p,imerge + 1);
-    for(cur = data; cur != NULL && cur->type == NTYPE_CDATA; cur = cur->next)
-    {
-        memcpy(scur,cur->data,cur->data_sz);
-        scur += cur->data_sz;
-    }
-    *scur = '\0';
-
-    /* this effectively hides all of the merged-in chunks */
-    data->next = cur;
-    if(cur == NULL)
-        data->parent->lastchild = data;
-    else
-        cur->prev = data;
-
-    /* reset data */
-    data->data = merge;
-    data->data_sz = imerge;
-    
-}
-
-static void _xmlnode_hide_sibling(xmlnode child)
-{
-    if(child == NULL)
-        return;
-
-    if(child->prev != NULL)
-        child->prev->next = child->next;
-    if(child->next != NULL)
-        child->next->prev = child->prev;
-}
-
-static void _xmlnode_tag2str(spool s, xmlnode node, int flag)
-{
-    xmlnode tmp;
-
-    if(flag==0 || flag==1)
-    {
-	    spooler(s,"<",xmlnode_get_name(node),s);
-	    tmp = xmlnode_get_firstattrib(node);
-	    while(tmp) {
-	        spooler(s," ",xmlnode_get_name(tmp),"='",strescape(xmlnode_pool(node),xmlnode_get_data(tmp)),"'",s);
-	        tmp = xmlnode_get_nextsibling(tmp);
-	    }
-	    if(flag==0)
-	        spool_add(s,"/>");
-	    else
-	        spool_add(s,">");
-    }
-    else
-    {
-	    spooler(s,"</",xmlnode_get_name(node),">",s);
-    }
-}
-
-static spool _xmlnode2spool(xmlnode node)
-{
-    spool s;
-    int level=0,dir=0;
-    xmlnode tmp;
-
-    if(!node || xmlnode_get_type(node)!=NTYPE_TAG)
-        return NULL;
-
-    s = spool_new(xmlnode_pool(node));
-    if(!s) return(NULL);
-
-    while(1)
-    {
-        if(dir==0)
-        {
-    	    if(xmlnode_get_type(node) == NTYPE_TAG)
-            {
-                if(xmlnode_has_children(node))
-                {
-                    _xmlnode_tag2str(s,node,1);
-                    node = xmlnode_get_firstchild(node);
-                    level++;
-                    continue;
-                }else{
-                    _xmlnode_tag2str(s,node,0);
-                }
-            }else{
-                spool_add(s,strescape(xmlnode_pool(node),xmlnode_get_data(node)));
-            }
-        }
-
-    	tmp = xmlnode_get_nextsibling(node);
-        if(!tmp)
-        {
-            node = xmlnode_get_parent(node);
-            level--;
-            if(level>=0) _xmlnode_tag2str(s,node,2);
-            if(level<1) break;
-            dir = 1;
-        }else{
-            node = tmp;
-            dir = 0;
-        }
-    }
-
-    return s;
-}
-
-
-/* External routines */
-
-
-/*
- *  xmlnode_new_tag -- create a tag node
- *  Automatically creates a memory pool for the node.
- *
- *  parameters
- *      name -- name of the tag
- *
- *  returns
- *      a pointer to the tag node
- *      or NULL if it was unsuccessfull
- */
-xmlnode xmlnode_new_tag(const char* name)
-{
-    return _xmlnode_new(NULL, name, NTYPE_TAG);
-}
-
-
-/*
- *  xmlnode_insert_tag -- append a child tag to a tag
- *
- *  parameters
- *      parent -- pointer to the parent tag
- *      name -- name of the child tag
- *
- *  returns
- *      a pointer to the child tag node
- *      or NULL if it was unsuccessfull
- */
-xmlnode xmlnode_insert_tag(xmlnode parent, const char* name)
-{
-    return _xmlnode_insert(parent, name, NTYPE_TAG);
-}
-
-
-/*
- *  xmlnode_insert_cdata -- append character data to a tag
- *
- *  parameters
- *      parent -- parent tag
- *      CDATA -- character data
- *      size -- size of CDATA
- *              or -1 for null-terminated CDATA strings
- *
- *  returns
- *      a pointer to the child CDATA node
- *      or NULL if it was unsuccessfull
- */
-xmlnode xmlnode_insert_cdata(xmlnode parent, const char* CDATA, unsigned int size)
-{
-    xmlnode result;
-
-    if(CDATA == NULL || parent == NULL)
-        return NULL;
-
-    if(size == -1)
-        size = strlen(CDATA);
-
-    result = _xmlnode_insert(parent, NULL, NTYPE_CDATA);
-    if (result != NULL)
-    {
-        result->data = (char*)pmalloc(result->p, size + 1);
-        memcpy(result->data, CDATA, size);
-        result->data[size] = '\0';
-        result->data_sz = size;
-    }
-
-    return result;
-}
-
-
-/*
- *  xmlnode_get_tag -- find given tag in an xmlnode tree
- *
- *  parameters
- *      parent -- pointer to the parent tag
- *      name -- "name" for the child tag of that name
- *              "name/name" for a sub child (recurses)
- *              "?attrib" to match the first tag with that attrib defined
- *              "?attrib=value" to match the first tag with that attrib and value
- *              "=cdata" to match the cdata contents of the child
- *              or any combination: "name/name/?attrib", "name=cdata", etc
- *
- *  results
- *      a pointer to the tag matching search criteria
- *      or NULL if search was unsuccessfull
- */
-xmlnode xmlnode_get_tag(xmlnode parent, const char* name)
-{
-    char *str, *slash, *qmark, *equals;
-    xmlnode step, ret;
-
-
-    if(parent == NULL || parent->firstchild == NULL || name == NULL || name == '\0') return NULL;
-
-    if(strstr(name, "/") == NULL && strstr(name,"?") == NULL && strstr(name, "=") == NULL)
-        return _xmlnode_search(parent->firstchild, name, NTYPE_TAG);
-
-    str = g_strdup(name);
-    slash = strstr(str, "/");
-    qmark = strstr(str, "?");
-    equals = strstr(str, "=");
-
-    if(equals != NULL && (slash == NULL || equals < slash) && (qmark == NULL || equals < qmark))
-    { /* of type =cdata */
-
-        *equals = '\0';
-        equals++;
-
-        for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step))
-        {
-            if(xmlnode_get_type(step) != NTYPE_TAG)
-                continue;
-
-            if(*str != '\0')
-                if(j_strcmp(xmlnode_get_name(step),str) != 0)
-                    continue;
-
-            if(j_strcmp(xmlnode_get_data(step),equals) != 0)
-                continue;
-
-            break;
-        }
-
-        g_free(str);
-        return step;
-    }
-
-
-    if(qmark != NULL && (slash == NULL || qmark < slash))
-    { /* of type ?attrib */
-
-        *qmark = '\0';
-        qmark++;
-        if(equals != NULL)
-        {
-            *equals = '\0';
-            equals++;
-        }
-
-        for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step))
-        {
-            if(xmlnode_get_type(step) != NTYPE_TAG)
-                continue;
-
-            if(*str != '\0')
-                if(j_strcmp(xmlnode_get_name(step),str) != 0)
-                    continue;
-
-            if(xmlnode_get_attrib(step,qmark) == NULL)
-                continue;
-
-            if(equals != NULL && j_strcmp(xmlnode_get_attrib(step,qmark),equals) != 0)
-                continue;
-
-            break;
-        }
-
-        g_free(str);
-        return step;
-    }
-
-
-    *slash = '\0';
-    ++slash;
-
-    for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step))
-    {
-        if(xmlnode_get_type(step) != NTYPE_TAG) continue;
-
-        if(j_strcmp(xmlnode_get_name(step),str) != 0)
-            continue;
-
-        ret = xmlnode_get_tag(step, slash);
-        if(ret != NULL)
-        {
-            g_free(str);
-            return ret;
-        }
-    }
-
-    g_free(str);
-    return NULL;
-}
-
-
-/* return the cdata from any tag */
-char *xmlnode_get_tag_data(xmlnode parent, const char *name)
-{
-    xmlnode tag;
-
-    tag = xmlnode_get_tag(parent, name);
-    if(tag == NULL) return NULL;
-
-    return xmlnode_get_data(tag);
-}
-
-
-void xmlnode_put_attrib(xmlnode owner, const char* name, const char* value)
-{
-    xmlnode attrib;
-
-    if(owner == NULL || name == NULL || value == NULL) return;
-
-    /* If there are no existing attributs, allocate a new one to start
-    the list */
-    if (owner->firstattrib == NULL)
-    {
-        attrib = _xmlnode_new(owner->p, name, NTYPE_ATTRIB);
-        owner->firstattrib = attrib;
-        owner->lastattrib  = attrib;
-    }
-    else
-    {
-        attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB);
-        if(attrib == NULL)
-        {
-            attrib = _xmlnode_append_sibling(owner->lastattrib, name, NTYPE_ATTRIB);
-            owner->lastattrib = attrib;
-        }
-    }
-    /* Update the value of the attribute */
-    attrib->data_sz = strlen(value);
-    attrib->data    = pstrdup(owner->p, value);
-
-}
-
-char* xmlnode_get_attrib(xmlnode owner, const char* name)
-{
-    xmlnode attrib;
-
-    if (owner != NULL && owner->firstattrib != NULL)
-    {
-        attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB);
-        if (attrib != NULL)
-            return (char*)attrib->data;
-    }
-    return NULL;
-}
-
-static xmlnode xmlnode_get_firstattrib(xmlnode parent)
-{
-    if (parent != NULL)
-        return parent->firstattrib;
-    return NULL;
-}
-
-xmlnode xmlnode_get_firstchild(xmlnode parent)
-{
-    if (parent != NULL)
-        return parent->firstchild;
-    return NULL;
-}
-
-xmlnode xmlnode_get_nextsibling(xmlnode sibling)
-{
-    if (sibling != NULL)
-        return sibling->next;
-    return NULL;
-}
-
-xmlnode xmlnode_get_parent(xmlnode node)
-{
-    if (node != NULL)
-        return node->parent;
-    return NULL;
-}
-
-char* xmlnode_get_name(xmlnode node)
-{
-    if (node != NULL)
-        return node->name;
-    return NULL;
-}
-
-char* xmlnode_get_data(xmlnode node)
-{
-    if(xmlnode_get_type(node) == NTYPE_TAG) /* loop till we find a CDATA in the children */
-        for(node = xmlnode_get_firstchild(node); node != NULL; node = xmlnode_get_nextsibling(node))
-            if(xmlnode_get_type(node) == NTYPE_CDATA) break;
-
-    if(node == NULL) return NULL;
-
-    /* check for a dirty node w/ unassembled cdata chunks */
-    if(xmlnode_get_type(node->next) == NTYPE_CDATA)
-        _xmlnode_merge(node);
-
-    return node->data;
-}
-
-static int xmlnode_get_datasz(xmlnode node)
-{
-    if(xmlnode_get_type(node) != NTYPE_CDATA) return 0;
-
-    /* check for a dirty node w/ unassembled cdata chunks */
-    if(xmlnode_get_type(node->next) == NTYPE_CDATA)
-        _xmlnode_merge(node);
-    return node->data_sz;
-}
-
-static int xmlnode_get_type(xmlnode node)
-{
-    if (node != NULL)
-        return node->type;
-    return NTYPE_UNDEF;
-}
-
-int xmlnode_has_children(xmlnode node)
-{
-    if ((node != NULL) && (node->firstchild != NULL))
-        return 1;
-    return 0;
-}
-
-static int xmlnode_has_attribs(xmlnode node)
-{
-    if ((node != NULL) && (node->firstattrib != NULL))
-        return 1;
-    return 0;
-}
-
-pool xmlnode_pool(xmlnode node)
-{
-    if (node != NULL)
-        return node->p;
-    return (pool)NULL;
-}
-
-void xmlnode_hide_attrib(xmlnode parent, const char *name)
-{
-    xmlnode attrib;
-
-    if(parent == NULL || parent->firstattrib == NULL || name == NULL)
-        return;
-
-    attrib = _xmlnode_search(parent->firstattrib, name, NTYPE_ATTRIB);
-    if(attrib == NULL)
-        return;
-
-    /* first fix up at the child level */
-    _xmlnode_hide_sibling(attrib);
-
-    /* next fix up at the parent level */
-    if(parent->firstattrib == attrib)
-        parent->firstattrib = attrib->next;
-    if(parent->lastattrib == attrib)
-        parent->lastattrib = attrib->prev;
-}
-
-
-
-/*
- *  xmlnode2str -- convert given xmlnode tree into a string
- *
- *  parameters
- *      node -- pointer to the xmlnode structure
- *
- *  results
- *      a pointer to the created string
- *      or NULL if it was unsuccessfull
- */
-char *xmlnode2str(xmlnode node)
-{
-     return spool_print(_xmlnode2spool(node));
-}
-
-/* loop through both a and b comparing everything, attribs, cdata, children, etc */
-static int xmlnode_cmp(xmlnode a, xmlnode b)
-{
-    int ret = 0;
-
-    while(1)
-    {
-        if(a == NULL && b == NULL)
-            return 0;
-
-        if(a == NULL || b == NULL)
-            return -1;
-
-        if(xmlnode_get_type(a) != xmlnode_get_type(b))
-            return -1;
-
-        switch(xmlnode_get_type(a))
-        {
-        case NTYPE_ATTRIB:
-            ret = j_strcmp(xmlnode_get_name(a), xmlnode_get_name(b));
-            if(ret != 0)
-                return -1;
-            ret = j_strcmp(xmlnode_get_data(a), xmlnode_get_data(b));
-            if(ret != 0)
-                return -1;
-            break;
-        case NTYPE_TAG:
-            ret = j_strcmp(xmlnode_get_name(a), xmlnode_get_name(b));
-            if(ret != 0)
-                return -1;
-            ret = xmlnode_cmp(xmlnode_get_firstattrib(a), xmlnode_get_firstattrib(b));
-            if(ret != 0)
-                return -1;
-            ret = xmlnode_cmp(xmlnode_get_firstchild(a), xmlnode_get_firstchild(b));
-            if(ret != 0)
-                return -1;
-            break;
-        case NTYPE_CDATA:
-            ret = j_strcmp(xmlnode_get_data(a), xmlnode_get_data(b));
-            if(ret != 0)
-                return -1;
-        }
-        a = xmlnode_get_nextsibling(a);
-        b = xmlnode_get_nextsibling(b);
-    }
-}
-
-
-xmlnode xmlnode_insert_tag_node(xmlnode parent, xmlnode node)
-{
-    xmlnode child;
-
-    child = xmlnode_insert_tag(parent, xmlnode_get_name(node));
-    if (xmlnode_has_attribs(node))
-        xmlnode_insert_node(child, xmlnode_get_firstattrib(node));
-    if (xmlnode_has_children(node))
-        xmlnode_insert_node(child, xmlnode_get_firstchild(node));
-
-    return child;
-}
-
-/* places copy of node and node's siblings in parent */
-static void xmlnode_insert_node(xmlnode parent, xmlnode node)
-{
-    if(node == NULL || parent == NULL)
-        return;
-
-    while(node != NULL)
-    {
-        switch(xmlnode_get_type(node))
-        {
-        case NTYPE_ATTRIB:
-            xmlnode_put_attrib(parent, xmlnode_get_name(node), xmlnode_get_data(node));
-            break;
-        case NTYPE_TAG:
-            xmlnode_insert_tag_node(parent, node);
-            break;
-        case NTYPE_CDATA:
-            xmlnode_insert_cdata(parent, xmlnode_get_data(node), xmlnode_get_datasz(node));
-        }
-        node = xmlnode_get_nextsibling(node);
-    }
-}
-
-
-void xmlnode_free(xmlnode node)
-{
-    if(node == NULL)
-        return;
-
-    pool_free(node->p);
-}
Index: protocols/jabber/xmlparse.c
===================================================================
--- protocols/jabber/xmlparse.c	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,2640 +1,0 @@
-/*
-The contents of this file are subject to the Mozilla Public License
-Version 1.1 (the "License"); you may not use this file except in
-compliance with the License. You may obtain a copy of the License at
-http://www.mozilla.org/MPL/
-
-Software distributed under the License is distributed on an "AS IS"
-basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
-License for the specific language governing rights and limitations
-under the License.
-
-The Original Code is expat.
-
-The Initial Developer of the Original Code is James Clark.
-Portions created by James Clark are Copyright (C) 1998, 1999
-James Clark. All Rights Reserved.
-
-Contributor(s):
-
-*/
-
-#include "xmldef.h"
-#include "xmlparse.h"
-
-#ifdef XML_UNICODE
-#define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
-#define XmlConvert XmlUtf16Convert
-#define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
-#define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
-#define XmlEncode XmlUtf16Encode
-#define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((unsigned long)s) & 1))
-typedef unsigned short ICHAR;
-#else
-#define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
-#define XmlConvert XmlUtf8Convert
-#define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
-#define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
-#define XmlEncode XmlUtf8Encode
-#define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
-typedef char ICHAR;
-#endif
-
-
-#ifndef XML_NS
-
-#define XmlInitEncodingNS XmlInitEncoding
-#define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
-#undef XmlGetInternalEncodingNS
-#define XmlGetInternalEncodingNS XmlGetInternalEncoding
-#define XmlParseXmlDeclNS XmlParseXmlDecl
-
-#endif
-
-
-#ifdef XML_UNICODE_WCHAR_T
-#define XML_T(x) L ## x
-#else
-#define XML_T(x) x
-#endif
-
-/* Round up n to be a multiple of sz, where sz is a power of 2. */
-#define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
-
-#include "xmltok.h"
-#include "xmlrole.h"
-#include "hashtable.h"
-
-#define INIT_TAG_BUF_SIZE 32  /* must be a multiple of sizeof(XML_Char) */
-#define INIT_DATA_BUF_SIZE 1024
-#define INIT_ATTS_SIZE 16
-#define INIT_BLOCK_SIZE 1024
-#define INIT_BUFFER_SIZE 1024
-
-#define EXPAND_SPARE 24
-
-typedef struct binding {
-    struct prefix *prefix;
-    struct binding *nextTagBinding;
-    struct binding *prevPrefixBinding;
-    const struct attribute_id *attId;
-    XML_Char *uri;
-    int uriLen;
-    int uriAlloc;
-} BINDING;
-
-typedef struct prefix {
-    const XML_Char *name;
-    BINDING *binding;
-} PREFIX;
-
-typedef struct {
-    const XML_Char *str;
-    const XML_Char *localPart;
-    int uriLen;
-} TAG_NAME;
-
-typedef struct tag {
-    struct tag *parent;
-    const char *rawName;
-    int rawNameLength;
-    TAG_NAME name;
-    char *buf;
-    char *bufEnd;
-    BINDING *bindings;
-} TAG;
-
-typedef struct {
-    const XML_Char *name;
-    const XML_Char *textPtr;
-    int textLen;
-    const XML_Char *systemId;
-    const XML_Char *base;
-    const XML_Char *publicId;
-    const XML_Char *notation;
-    char open;
-} ENTITY;
-
-typedef struct block {
-    struct block *next;
-    int size;
-    XML_Char s[1];
-} BLOCK;
-
-typedef struct {
-    BLOCK *blocks;
-    BLOCK *freeBlocks;
-    const XML_Char *end;
-    XML_Char *ptr;
-    XML_Char *start;
-} STRING_POOL;
-
-/* The XML_Char before the name is used to determine whether
-an attribute has been specified. */
-typedef struct attribute_id {
-    XML_Char *name;
-    PREFIX *prefix;
-    char maybeTokenized;
-    char xmlns;
-} ATTRIBUTE_ID;
-
-typedef struct {
-    const ATTRIBUTE_ID *id;
-    char isCdata;
-    const XML_Char *value;
-} DEFAULT_ATTRIBUTE;
-
-typedef struct {
-    const XML_Char *name;
-    PREFIX *prefix;
-    int nDefaultAtts;
-    int allocDefaultAtts;
-    DEFAULT_ATTRIBUTE *defaultAtts;
-} ELEMENT_TYPE;
-
-typedef struct {
-    HASH_TABLE generalEntities;
-    HASH_TABLE elementTypes;
-    HASH_TABLE attributeIds;
-    HASH_TABLE prefixes;
-    STRING_POOL pool;
-    int complete;
-    int standalone;
-    const XML_Char *base;
-    PREFIX defaultPrefix;
-} DTD;
-
-typedef struct open_internal_entity {
-    const char *internalEventPtr;
-    const char *internalEventEndPtr;
-    struct open_internal_entity *next;
-    ENTITY *entity;
-} OPEN_INTERNAL_ENTITY;
-
-typedef enum XML_Error Processor(XML_Parser parser,
-                                 const char *start,
-                                 const char *end,
-                                 const char **endPtr);
-
-static Processor prologProcessor;
-static Processor prologInitProcessor;
-static Processor contentProcessor;
-static Processor cdataSectionProcessor;
-static Processor epilogProcessor;
-
-static enum XML_Error
-handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
-static enum XML_Error
-processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *, const char *);
-static enum XML_Error
-initializeEncoding(XML_Parser parser);
-static enum XML_Error
-doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
-          const char *start, const char *end, const char **endPtr);
-static enum XML_Error
-doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, const char **nextPtr);
-static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *, const char *s,
-                                TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
-static
-int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr);
-static int
-defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, int isCdata, const XML_Char *dfltValue);
-static enum XML_Error
-storeAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *,
-                    STRING_POOL *);
-static enum XML_Error
-appendAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *,
-                     STRING_POOL *);
-static ATTRIBUTE_ID *
-getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
-static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
-static enum XML_Error
-storeEntityValue(XML_Parser parser, const char *start, const char *end);
-static int
-reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
-static int
-reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
-static void
-reportDefault(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
-
-static const XML_Char *getContext(XML_Parser parser);
-static void normalizePublicId(XML_Char *s);
-static int dtdInit(DTD *);
-static void dtdDestroy(DTD *);
-static void poolInit(STRING_POOL *);
-static void poolClear(STRING_POOL *);
-static void poolDestroy(STRING_POOL *);
-static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
-                            const char *ptr, const char *end);
-static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
-                                 const char *ptr, const char *end);
-static int poolGrow(STRING_POOL *pool);
-static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s);
-static void *XML_GetBuffer(XML_Parser parser, int len);
-static int XML_ParseBuffer(XML_Parser parser, int len, int isFinal);
-
-#define poolStart(pool) ((pool)->start)
-#define poolEnd(pool) ((pool)->ptr)
-#define poolLength(pool) ((pool)->ptr - (pool)->start)
-#define poolChop(pool) ((void)--(pool->ptr))
-#define poolLastChar(pool) (((pool)->ptr)[-1])
-#define poolDiscard(pool) ((pool)->ptr = (pool)->start)
-#define poolFinish(pool) ((pool)->start = (pool)->ptr)
-#define poolAppendChar(pool, c) \
-  (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
-   ? 0 \
-   : ((*((pool)->ptr)++ = c), 1))
-
-typedef struct {
-    /* The first member must be userData so that the XML_GetUserData macro works. */
-    void *m_userData;
-    void *m_handlerArg;
-    char *m_buffer;
-    /* first character to be parsed */
-    const char *m_bufferPtr;
-    /* past last character to be parsed */
-    char *m_bufferEnd;
-    /* allocated end of buffer */
-    const char *m_bufferLim;
-    long m_parseEndByteIndex;
-    const char *m_parseEndPtr;
-    XML_Char *m_dataBuf;
-    XML_Char *m_dataBufEnd;
-    XML_StartElementHandler m_startElementHandler;
-    XML_EndElementHandler m_endElementHandler;
-    XML_CharacterDataHandler m_characterDataHandler;
-    XML_ProcessingInstructionHandler m_processingInstructionHandler;
-    XML_CommentHandler m_commentHandler;
-    XML_StartCdataSectionHandler m_startCdataSectionHandler;
-    XML_EndCdataSectionHandler m_endCdataSectionHandler;
-    XML_DefaultHandler m_defaultHandler;
-    XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
-    XML_NotationDeclHandler m_notationDeclHandler;
-    XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
-    XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
-    XML_NotStandaloneHandler m_notStandaloneHandler;
-    XML_ExternalEntityRefHandler m_externalEntityRefHandler;
-    void *m_externalEntityRefHandlerArg;
-    XML_UnknownEncodingHandler m_unknownEncodingHandler;
-    const ENCODING *m_encoding;
-    INIT_ENCODING m_initEncoding;
-    const XML_Char *m_protocolEncodingName;
-    int m_ns;
-    void *m_unknownEncodingMem;
-    void *m_unknownEncodingData;
-    void *m_unknownEncodingHandlerData;
-    void (*m_unknownEncodingRelease)(void *);
-    PROLOG_STATE m_prologState;
-    Processor *m_processor;
-    enum XML_Error m_errorCode;
-    const char *m_eventPtr;
-    const char *m_eventEndPtr;
-    const char *m_positionPtr;
-    OPEN_INTERNAL_ENTITY *m_openInternalEntities;
-    int m_defaultExpandInternalEntities;
-    int m_tagLevel;
-    ENTITY *m_declEntity;
-    const XML_Char *m_declNotationName;
-    const XML_Char *m_declNotationPublicId;
-    ELEMENT_TYPE *m_declElementType;
-    ATTRIBUTE_ID *m_declAttributeId;
-    char m_declAttributeIsCdata;
-    DTD m_dtd;
-    TAG *m_tagStack;
-    TAG *m_freeTagList;
-    BINDING *m_inheritedBindings;
-    BINDING *m_freeBindingList;
-    int m_attsSize;
-    int m_nSpecifiedAtts;
-    ATTRIBUTE *m_atts;
-    POSITION m_position;
-    STRING_POOL m_tempPool;
-    STRING_POOL m_temp2Pool;
-    char *m_groupConnector;
-    unsigned m_groupSize;
-    int m_hadExternalDoctype;
-    XML_Char m_namespaceSeparator;
-} Parser;
-
-#define userData (((Parser *)parser)->m_userData)
-#define handlerArg (((Parser *)parser)->m_handlerArg)
-#define startElementHandler (((Parser *)parser)->m_startElementHandler)
-#define endElementHandler (((Parser *)parser)->m_endElementHandler)
-#define characterDataHandler (((Parser *)parser)->m_characterDataHandler)
-#define processingInstructionHandler (((Parser *)parser)->m_processingInstructionHandler)
-#define commentHandler (((Parser *)parser)->m_commentHandler)
-#define startCdataSectionHandler (((Parser *)parser)->m_startCdataSectionHandler)
-#define endCdataSectionHandler (((Parser *)parser)->m_endCdataSectionHandler)
-#define defaultHandler (((Parser *)parser)->m_defaultHandler)
-#define unparsedEntityDeclHandler (((Parser *)parser)->m_unparsedEntityDeclHandler)
-#define notationDeclHandler (((Parser *)parser)->m_notationDeclHandler)
-#define startNamespaceDeclHandler (((Parser *)parser)->m_startNamespaceDeclHandler)
-#define endNamespaceDeclHandler (((Parser *)parser)->m_endNamespaceDeclHandler)
-#define notStandaloneHandler (((Parser *)parser)->m_notStandaloneHandler)
-#define externalEntityRefHandler (((Parser *)parser)->m_externalEntityRefHandler)
-#define externalEntityRefHandlerArg (((Parser *)parser)->m_externalEntityRefHandlerArg)
-#define unknownEncodingHandler (((Parser *)parser)->m_unknownEncodingHandler)
-#define encoding (((Parser *)parser)->m_encoding)
-#define initEncoding (((Parser *)parser)->m_initEncoding)
-#define unknownEncodingMem (((Parser *)parser)->m_unknownEncodingMem)
-#define unknownEncodingData (((Parser *)parser)->m_unknownEncodingData)
-#define unknownEncodingHandlerData \
-  (((Parser *)parser)->m_unknownEncodingHandlerData)
-#define unknownEncodingRelease (((Parser *)parser)->m_unknownEncodingRelease)
-#define protocolEncodingName (((Parser *)parser)->m_protocolEncodingName)
-#define ns (((Parser *)parser)->m_ns)
-#define prologState (((Parser *)parser)->m_prologState)
-#define processor (((Parser *)parser)->m_processor)
-#define errorCode (((Parser *)parser)->m_errorCode)
-#define eventPtr (((Parser *)parser)->m_eventPtr)
-#define eventEndPtr (((Parser *)parser)->m_eventEndPtr)
-#define positionPtr (((Parser *)parser)->m_positionPtr)
-#define position (((Parser *)parser)->m_position)
-#define openInternalEntities (((Parser *)parser)->m_openInternalEntities)
-#define defaultExpandInternalEntities (((Parser *)parser)->m_defaultExpandInternalEntities)
-#define tagLevel (((Parser *)parser)->m_tagLevel)
-#define buffer (((Parser *)parser)->m_buffer)
-#define bufferPtr (((Parser *)parser)->m_bufferPtr)
-#define bufferEnd (((Parser *)parser)->m_bufferEnd)
-#define parseEndByteIndex (((Parser *)parser)->m_parseEndByteIndex)
-#define parseEndPtr (((Parser *)parser)->m_parseEndPtr)
-#define bufferLim (((Parser *)parser)->m_bufferLim)
-#define dataBuf (((Parser *)parser)->m_dataBuf)
-#define dataBufEnd (((Parser *)parser)->m_dataBufEnd)
-#define dtd (((Parser *)parser)->m_dtd)
-#define declEntity (((Parser *)parser)->m_declEntity)
-#define declNotationName (((Parser *)parser)->m_declNotationName)
-#define declNotationPublicId (((Parser *)parser)->m_declNotationPublicId)
-#define declElementType (((Parser *)parser)->m_declElementType)
-#define declAttributeId (((Parser *)parser)->m_declAttributeId)
-#define declAttributeIsCdata (((Parser *)parser)->m_declAttributeIsCdata)
-#define freeTagList (((Parser *)parser)->m_freeTagList)
-#define freeBindingList (((Parser *)parser)->m_freeBindingList)
-#define inheritedBindings (((Parser *)parser)->m_inheritedBindings)
-#define tagStack (((Parser *)parser)->m_tagStack)
-#define atts (((Parser *)parser)->m_atts)
-#define attsSize (((Parser *)parser)->m_attsSize)
-#define nSpecifiedAtts (((Parser *)parser)->m_nSpecifiedAtts)
-#define tempPool (((Parser *)parser)->m_tempPool)
-#define temp2Pool (((Parser *)parser)->m_temp2Pool)
-#define groupConnector (((Parser *)parser)->m_groupConnector)
-#define groupSize (((Parser *)parser)->m_groupSize)
-#define hadExternalDoctype (((Parser *)parser)->m_hadExternalDoctype)
-#define namespaceSeparator (((Parser *)parser)->m_namespaceSeparator)
-
-#ifdef _MSC_VER
-#ifdef _DEBUG
-Parser *asParser(XML_Parser parser)
-{
-    return parser;
-}
-#endif
-#endif
-
-XML_Parser XML_ParserCreate(const XML_Char *encodingName)
-{
-    XML_Parser parser = malloc(sizeof(Parser));
-    if (!parser)
-        return parser;
-    processor = prologInitProcessor;
-    XmlPrologStateInit(&prologState);
-    userData = 0;
-    handlerArg = 0;
-    startElementHandler = 0;
-    endElementHandler = 0;
-    characterDataHandler = 0;
-    processingInstructionHandler = 0;
-    commentHandler = 0;
-    startCdataSectionHandler = 0;
-    endCdataSectionHandler = 0;
-    defaultHandler = 0;
-    unparsedEntityDeclHandler = 0;
-    notationDeclHandler = 0;
-    startNamespaceDeclHandler = 0;
-    endNamespaceDeclHandler = 0;
-    notStandaloneHandler = 0;
-    externalEntityRefHandler = 0;
-    externalEntityRefHandlerArg = parser;
-    unknownEncodingHandler = 0;
-    buffer = 0;
-    bufferPtr = 0;
-    bufferEnd = 0;
-    parseEndByteIndex = 0;
-    parseEndPtr = 0;
-    bufferLim = 0;
-    declElementType = 0;
-    declAttributeId = 0;
-    declEntity = 0;
-    declNotationName = 0;
-    declNotationPublicId = 0;
-    memset(&position, 0, sizeof(POSITION));
-    errorCode = XML_ERROR_NONE;
-    eventPtr = 0;
-    eventEndPtr = 0;
-    positionPtr = 0;
-    openInternalEntities = 0;
-    tagLevel = 0;
-    tagStack = 0;
-    freeTagList = 0;
-    freeBindingList = 0;
-    inheritedBindings = 0;
-    attsSize = INIT_ATTS_SIZE;
-    atts = malloc(attsSize * sizeof(ATTRIBUTE));
-    nSpecifiedAtts = 0;
-    dataBuf = malloc(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
-    groupSize = 0;
-    groupConnector = 0;
-    hadExternalDoctype = 0;
-    unknownEncodingMem = 0;
-    unknownEncodingRelease = 0;
-    unknownEncodingData = 0;
-    unknownEncodingHandlerData = 0;
-    namespaceSeparator = '!';
-    ns = 0;
-    poolInit(&tempPool);
-    poolInit(&temp2Pool);
-    protocolEncodingName = encodingName ? poolCopyString(&tempPool, encodingName) : 0;
-    if (!dtdInit(&dtd) || !atts || !dataBuf
-            || (encodingName && !protocolEncodingName)) {
-        XML_ParserFree(parser);
-        return 0;
-    }
-    dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
-    XmlInitEncoding(&initEncoding, &encoding, 0);
-    return parser;
-}
-
-static
-void destroyBindings(BINDING *bindings)
-{
-    for (;;) {
-        BINDING *b = bindings;
-        if (!b)
-            break;
-        bindings = b->nextTagBinding;
-        g_free(b->uri);
-        g_free(b);
-    }
-}
-
-void XML_ParserFree(XML_Parser parser)
-{
-    for (;;) {
-        TAG *p;
-        if (tagStack == 0) {
-            if (freeTagList == 0)
-                break;
-            tagStack = freeTagList;
-            freeTagList = 0;
-        }
-        p = tagStack;
-        tagStack = tagStack->parent;
-        g_free(p->buf);
-        destroyBindings(p->bindings);
-        g_free(p);
-    }
-    destroyBindings(freeBindingList);
-    destroyBindings(inheritedBindings);
-    poolDestroy(&tempPool);
-    poolDestroy(&temp2Pool);
-    dtdDestroy(&dtd);
-    g_free((void *)atts);
-    g_free(groupConnector);
-    g_free(buffer);
-    g_free(dataBuf);
-    g_free(unknownEncodingMem);
-    if (unknownEncodingRelease)
-        unknownEncodingRelease(unknownEncodingData);
-    g_free(parser);
-}
-
-void XML_SetUserData(XML_Parser parser, void *p)
-{
-    if (handlerArg == userData)
-        handlerArg = userData = p;
-    else
-        userData = p;
-}
-
-void XML_SetElementHandler(XML_Parser parser,
-                           XML_StartElementHandler start,
-                           XML_EndElementHandler end)
-{
-    startElementHandler = start;
-    endElementHandler = end;
-}
-
-void XML_SetCharacterDataHandler(XML_Parser parser,
-                                 XML_CharacterDataHandler handler)
-{
-    characterDataHandler = handler;
-}
-
-int XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
-{
-    if (len == 0) {
-        if (!isFinal)
-            return 1;
-        positionPtr = bufferPtr;
-        errorCode = processor(parser, bufferPtr, parseEndPtr = bufferEnd, 0);
-        if (errorCode == XML_ERROR_NONE)
-            return 1;
-        eventEndPtr = eventPtr;
-        return 0;
-    }
-    else if (bufferPtr == bufferEnd) {
-        const char *end;
-        int nLeftOver;
-        parseEndByteIndex += len;
-        positionPtr = s;
-        if (isFinal) {
-            errorCode = processor(parser, s, parseEndPtr = s + len, 0);
-            if (errorCode == XML_ERROR_NONE)
-                return 1;
-            eventEndPtr = eventPtr;
-            return 0;
-        }
-        errorCode = processor(parser, s, parseEndPtr = s + len, &end);
-        if (errorCode != XML_ERROR_NONE) {
-            eventEndPtr = eventPtr;
-            return 0;
-        }
-        XmlUpdatePosition(encoding, positionPtr, end, &position);
-        nLeftOver = s + len - end;
-        if (nLeftOver) {
-            if (buffer == 0 || nLeftOver > bufferLim - buffer) {
-                /* FIXME avoid integer overflow */
-                buffer = buffer == 0 ? malloc(len * 2) : realloc(buffer, len * 2);
-                if (!buffer) {
-                    errorCode = XML_ERROR_NO_MEMORY;
-                    eventPtr = eventEndPtr = 0;
-                    return 0;
-                }
-                bufferLim = buffer + len * 2;
-            }
-            memcpy(buffer, end, nLeftOver);
-            bufferPtr = buffer;
-            bufferEnd = buffer + nLeftOver;
-        }
-        return 1;
-    }
-    else {
-        memcpy(XML_GetBuffer(parser, len), s, len);
-        return XML_ParseBuffer(parser, len, isFinal);
-    }
-}
-
-static int XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
-{
-    const char *start = bufferPtr;
-    positionPtr = start;
-    bufferEnd += len;
-    parseEndByteIndex += len;
-    errorCode = processor(parser, start, parseEndPtr = bufferEnd,
-                          isFinal ? (const char **)0 : &bufferPtr);
-    if (errorCode == XML_ERROR_NONE) {
-        if (!isFinal)
-            XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
-        return 1;
-    }
-    else {
-        eventEndPtr = eventPtr;
-        return 0;
-    }
-}
-
-static void *XML_GetBuffer(XML_Parser parser, int len)
-{
-    if (len > bufferLim - bufferEnd) {
-        /* FIXME avoid integer overflow */
-        int neededSize = len + (bufferEnd - bufferPtr);
-        if (neededSize  <= bufferLim - buffer) {
-            memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
-            bufferEnd = buffer + (bufferEnd - bufferPtr);
-            bufferPtr = buffer;
-        }
-        else {
-            char *newBuf;
-            int bufferSize = bufferLim - bufferPtr;
-            if (bufferSize == 0)
-                bufferSize = INIT_BUFFER_SIZE;
-            do {
-                bufferSize *= 2;
-            } while (bufferSize < neededSize);
-            newBuf = malloc(bufferSize);
-            if (newBuf == 0) {
-                errorCode = XML_ERROR_NO_MEMORY;
-                return 0;
-            }
-            bufferLim = newBuf + bufferSize;
-            if (bufferPtr) {
-                memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
-                g_free(buffer);
-            }
-            bufferEnd = newBuf + (bufferEnd - bufferPtr);
-            bufferPtr = buffer = newBuf;
-        }
-    }
-    return bufferEnd;
-}
-
-static
-enum XML_Error contentProcessor(XML_Parser parser,
-                                const char *start,
-                                const char *end,
-                                const char **endPtr)
-{
-    return doContent(parser, 0, encoding, start, end, endPtr);
-}
-
-static enum XML_Error
-doContent(XML_Parser parser,
-          int startTagLevel,
-          const ENCODING *enc,
-          const char *s,
-          const char *end,
-          const char **nextPtr)
-{
-    const ENCODING *internalEnc = ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding();
-    const char **eventPP;
-    const char **eventEndPP;
-    if (enc == encoding) {
-        eventPP = &eventPtr;
-        eventEndPP = &eventEndPtr;
-    }
-    else {
-        eventPP = &(openInternalEntities->internalEventPtr);
-        eventEndPP = &(openInternalEntities->internalEventEndPtr);
-    }
-    *eventPP = s;
-    for (;;) {
-        const char *next = s; /* XmlContentTok doesn't always set the last arg */
-        int tok = XmlContentTok(enc, s, end, &next);
-        *eventEndPP = next;
-        switch (tok) {
-        case XML_TOK_TRAILING_CR:
-            if (nextPtr) {
-                *nextPtr = s;
-                return XML_ERROR_NONE;
-            }
-            *eventEndPP = end;
-            if (characterDataHandler) {
-                XML_Char c = 0xA;
-                characterDataHandler(handlerArg, &c, 1);
-            }
-            else if (defaultHandler)
-                reportDefault(parser, enc, s, end);
-            if (startTagLevel == 0)
-                return XML_ERROR_NO_ELEMENTS;
-            if (tagLevel != startTagLevel)
-                return XML_ERROR_ASYNC_ENTITY;
-            return XML_ERROR_NONE;
-        case XML_TOK_NONE:
-            if (nextPtr) {
-                *nextPtr = s;
-                return XML_ERROR_NONE;
-            }
-            if (startTagLevel > 0) {
-                if (tagLevel != startTagLevel)
-                    return XML_ERROR_ASYNC_ENTITY;
-                return XML_ERROR_NONE;
-            }
-            return XML_ERROR_NO_ELEMENTS;
-        case XML_TOK_INVALID:
-            *eventPP = next;
-            return XML_ERROR_INVALID_TOKEN;
-        case XML_TOK_PARTIAL:
-            if (nextPtr) {
-                *nextPtr = s;
-                return XML_ERROR_NONE;
-            }
-            return XML_ERROR_UNCLOSED_TOKEN;
-        case XML_TOK_PARTIAL_CHAR:
-            if (nextPtr) {
-                *nextPtr = s;
-                return XML_ERROR_NONE;
-            }
-            return XML_ERROR_PARTIAL_CHAR;
-        case XML_TOK_ENTITY_REF:
-            {
-                const XML_Char *name;
-                ENTITY *entity;
-                XML_Char ch = XmlPredefinedEntityName(enc,
-                                                      s + enc->minBytesPerChar,
-                                                      next - enc->minBytesPerChar);
-                if (ch) {
-                    if (characterDataHandler)
-                        characterDataHandler(handlerArg, &ch, 1);
-                    else if (defaultHandler)
-                        reportDefault(parser, enc, s, next);
-                    break;
-                }
-                name = poolStoreString(&dtd.pool, enc,
-                                       s + enc->minBytesPerChar,
-                                       next - enc->minBytesPerChar);
-                if (!name)
-                    return XML_ERROR_NO_MEMORY;
-                entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0);
-                poolDiscard(&dtd.pool);
-                if (!entity) {
-                    if (dtd.complete || dtd.standalone)
-                        return XML_ERROR_UNDEFINED_ENTITY;
-                    if (defaultHandler)
-                        reportDefault(parser, enc, s, next);
-                    break;
-                }
-                if (entity->open)
-                    return XML_ERROR_RECURSIVE_ENTITY_REF;
-                if (entity->notation)
-                    return XML_ERROR_BINARY_ENTITY_REF;
-                if (entity) {
-                    if (entity->textPtr) {
-                        enum XML_Error result;
-                        OPEN_INTERNAL_ENTITY openEntity;
-                        if (defaultHandler && !defaultExpandInternalEntities) {
-                            reportDefault(parser, enc, s, next);
-                            break;
-                        }
-                        entity->open = 1;
-                        openEntity.next = openInternalEntities;
-                        openInternalEntities = &openEntity;
-                        openEntity.entity = entity;
-                        openEntity.internalEventPtr = 0;
-                        openEntity.internalEventEndPtr = 0;
-                        result = doContent(parser,
-                                           tagLevel,
-                                           internalEnc,
-                                           (char *)entity->textPtr,
-                                           (char *)(entity->textPtr + entity->textLen),
-                                           0);
-                        entity->open = 0;
-                        openInternalEntities = openEntity.next;
-                        if (result)
-                            return result;
-                    }
-                    else if (externalEntityRefHandler) {
-                        const XML_Char *context;
-                        entity->open = 1;
-                        context = getContext(parser);
-                        entity->open = 0;
-                        if (!context)
-                            return XML_ERROR_NO_MEMORY;
-                        if (!externalEntityRefHandler(externalEntityRefHandlerArg,
-                                                      context,
-                                                      dtd.base,
-                                                      entity->systemId,
-                                                      entity->publicId))
-                            return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
-                        poolDiscard(&tempPool);
-                    }
-                    else if (defaultHandler)
-                        reportDefault(parser, enc, s, next);
-                }
-                break;
-            }
-        case XML_TOK_START_TAG_WITH_ATTS:
-            if (!startElementHandler) {
-                enum XML_Error result = storeAtts(parser, enc, s, 0, 0);
-                if (result)
-                    return result;
-            }
-            /* fall through */
-        case XML_TOK_START_TAG_NO_ATTS:
-            {
-                TAG *tag;
-                if (freeTagList) {
-                    tag = freeTagList;
-                    freeTagList = freeTagList->parent;
-                }
-                else {
-                    tag = malloc(sizeof(TAG));
-                    if (!tag)
-                        return XML_ERROR_NO_MEMORY;
-                    tag->buf = malloc(INIT_TAG_BUF_SIZE);
-                    if (!tag->buf)
-                        return XML_ERROR_NO_MEMORY;
-                    tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
-                }
-                tag->bindings = 0;
-                tag->parent = tagStack;
-                tagStack = tag;
-                tag->name.localPart = 0;
-                tag->rawName = s + enc->minBytesPerChar;
-                tag->rawNameLength = XmlNameLength(enc, tag->rawName);
-                if (nextPtr) {
-                    /* Need to guarantee that:
-                       tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)) <= tag->bufEnd - sizeof(XML_Char) */
-                    if (tag->rawNameLength + (int)(sizeof(XML_Char) - 1) + (int)sizeof(XML_Char) > tag->bufEnd - tag->buf) {
-                        int bufSize = tag->rawNameLength * 4;
-                        bufSize = ROUND_UP(bufSize, sizeof(XML_Char));
-                        tag->buf = realloc(tag->buf, bufSize);
-                        if (!tag->buf)
-                            return XML_ERROR_NO_MEMORY;
-                        tag->bufEnd = tag->buf + bufSize;
-                    }
-                    memcpy(tag->buf, tag->rawName, tag->rawNameLength);
-                    tag->rawName = tag->buf;
-                }
-                ++tagLevel;
-                if (startElementHandler) {
-                    enum XML_Error result;
-                    XML_Char *toPtr;
-                    for (;;) {
-                        const char *rawNameEnd = tag->rawName + tag->rawNameLength;
-                        const char *fromPtr = tag->rawName;
-                        int bufSize;
-                        if (nextPtr)
-                            toPtr = (XML_Char *)(tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)));
-                        else
-                            toPtr = (XML_Char *)tag->buf;
-                        tag->name.str = toPtr;
-                        XmlConvert(enc,
-                                   &fromPtr, rawNameEnd,
-                                   (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
-                        if (fromPtr == rawNameEnd)
-                            break;
-                        bufSize = (tag->bufEnd - tag->buf) << 1;
-                        tag->buf = realloc(tag->buf, bufSize);
-                        if (!tag->buf)
-                            return XML_ERROR_NO_MEMORY;
-                        tag->bufEnd = tag->buf + bufSize;
-                        if (nextPtr)
-                            tag->rawName = tag->buf;
-                    }
-                    *toPtr = XML_T('\0');
-                    result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
-                    if (result)
-                        return result;
-                    startElementHandler(handlerArg, tag->name.str, (const XML_Char **)atts);
-                    poolClear(&tempPool);
-                }
-                else {
-                    tag->name.str = 0;
-                    if (defaultHandler)
-                        reportDefault(parser, enc, s, next);
-                }
-                break;
-            }
-        case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
-            if (!startElementHandler) {
-                enum XML_Error result = storeAtts(parser, enc, s, 0, 0);
-                if (result)
-                    return result;
-            }
-            /* fall through */
-        case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
-            if (startElementHandler || endElementHandler) {
-                const char *rawName = s + enc->minBytesPerChar;
-                enum XML_Error result;
-                BINDING *bindings = 0;
-                TAG_NAME name;
-                name.str = poolStoreString(&tempPool, enc, rawName,
-                                           rawName + XmlNameLength(enc, rawName));
-                if (!name.str)
-                    return XML_ERROR_NO_MEMORY;
-                poolFinish(&tempPool);
-                result = storeAtts(parser, enc, s, &name, &bindings);
-                if (result)
-                    return result;
-                poolFinish(&tempPool);
-                if (startElementHandler)
-                    startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
-                if (endElementHandler) {
-                    if (startElementHandler)
-                        *eventPP = *eventEndPP;
-                    endElementHandler(handlerArg, name.str);
-                }
-                poolClear(&tempPool);
-                while (bindings) {
-                    BINDING *b = bindings;
-                    if (endNamespaceDeclHandler)
-                        endNamespaceDeclHandler(handlerArg, b->prefix->name);
-                    bindings = bindings->nextTagBinding;
-                    b->nextTagBinding = freeBindingList;
-                    freeBindingList = b;
-                    b->prefix->binding = b->prevPrefixBinding;
-                }
-            }
-            else if (defaultHandler)
-                reportDefault(parser, enc, s, next);
-            if (tagLevel == 0)
-                return epilogProcessor(parser, next, end, nextPtr);
-            break;
-        case XML_TOK_END_TAG:
-            if (tagLevel == startTagLevel)
-                return XML_ERROR_ASYNC_ENTITY;
-            else {
-                int len;
-                const char *rawName;
-                TAG *tag = tagStack;
-                tagStack = tag->parent;
-                tag->parent = freeTagList;
-                freeTagList = tag;
-                rawName = s + enc->minBytesPerChar*2;
-                len = XmlNameLength(enc, rawName);
-                if (len != tag->rawNameLength
-                        || memcmp(tag->rawName, rawName, len) != 0) {
-                    *eventPP = rawName;
-                    return XML_ERROR_TAG_MISMATCH;
-                }
-                --tagLevel;
-                if (endElementHandler && tag->name.str) {
-                    if (tag->name.localPart) {
-                        XML_Char *to = (XML_Char *)tag->name.str + tag->name.uriLen;
-                        const XML_Char *from = tag->name.localPart;
-                        while ((*to++ = *from++) != 0)
-                            ;
-                    }
-                    endElementHandler(handlerArg, tag->name.str);
-                }
-                else if (defaultHandler)
-                    reportDefault(parser, enc, s, next);
-                while (tag->bindings) {
-                    BINDING *b = tag->bindings;
-                    if (endNamespaceDeclHandler)
-                        endNamespaceDeclHandler(handlerArg, b->prefix->name);
-                    tag->bindings = tag->bindings->nextTagBinding;
-                    b->nextTagBinding = freeBindingList;
-                    freeBindingList = b;
-                    b->prefix->binding = b->prevPrefixBinding;
-                }
-                if (tagLevel == 0)
-                    return epilogProcessor(parser, next, end, nextPtr);
-            }
-            break;
-        case XML_TOK_CHAR_REF:
-            {
-                int n = XmlCharRefNumber(enc, s);
-                if (n < 0)
-                    return XML_ERROR_BAD_CHAR_REF;
-                if (characterDataHandler) {
-                    XML_Char buf[XML_ENCODE_MAX];
-                    characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
-                }
-                else if (defaultHandler)
-                    reportDefault(parser, enc, s, next);
-            }
-            break;
-        case XML_TOK_XML_DECL:
-            return XML_ERROR_MISPLACED_XML_PI;
-        case XML_TOK_DATA_NEWLINE:
-            if (characterDataHandler) {
-                XML_Char c = 0xA;
-                characterDataHandler(handlerArg, &c, 1);
-            }
-            else if (defaultHandler)
-                reportDefault(parser, enc, s, next);
-            break;
-        case XML_TOK_CDATA_SECT_OPEN:
-            {
-                enum XML_Error result;
-                if (startCdataSectionHandler)
-                    startCdataSectionHandler(handlerArg);
-#if 0
-                /* Suppose you doing a transformation on a document that involves
-                   changing only the character data.  You set up a defaultHandler
-                   and a characterDataHandler.  The defaultHandler simply copies
-                   characters through.  The characterDataHandler does the transformation
-                   and writes the characters out escaping them as necessary.  This case
-                   will fail to work if we leave out the following two lines (because &
-                   and < inside CDATA sections will be incorrectly escaped).
-
-                   However, now we have a start/endCdataSectionHandler, so it seems
-                   easier to let the user deal with this. */
-
-                else if (characterDataHandler)
-                    characterDataHandler(handlerArg, dataBuf, 0);
-#endif
-                else if (defaultHandler)
-                    reportDefault(parser, enc, s, next);
-                result = doCdataSection(parser, enc, &next, end, nextPtr);
-                if (!next) {
-                    processor = cdataSectionProcessor;
-                    return result;
-                }
-            }
-            break;
-        case XML_TOK_TRAILING_RSQB:
-            if (nextPtr) {
-                *nextPtr = s;
-                return XML_ERROR_NONE;
-            }
-            if (characterDataHandler) {
-                if (MUST_CONVERT(enc, s)) {
-                    ICHAR *dataPtr = (ICHAR *)dataBuf;
-                    XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
-                    characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
-                }
-                else
-                    characterDataHandler(handlerArg,
-                                         (XML_Char *)s,
-                                         (XML_Char *)end - (XML_Char *)s);
-            }
-            else if (defaultHandler)
-                reportDefault(parser, enc, s, end);
-            if (startTagLevel == 0) {
-                *eventPP = end;
-                return XML_ERROR_NO_ELEMENTS;
-            }
-            if (tagLevel != startTagLevel) {
-                *eventPP = end;
-                return XML_ERROR_ASYNC_ENTITY;
-            }
-            return XML_ERROR_NONE;
-        case XML_TOK_DATA_CHARS:
-            if (characterDataHandler) {
-                if (MUST_CONVERT(enc, s)) {
-                    for (;;) {
-                        ICHAR *dataPtr = (ICHAR *)dataBuf;
-                        XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
-                        *eventEndPP = s;
-                        characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
-                        if (s == next)
-                            break;
-                        *eventPP = s;
-                    }
-                }
-                else
-                    characterDataHandler(handlerArg,
-                                         (XML_Char *)s,
-                                         (XML_Char *)next - (XML_Char *)s);
-            }
-            else if (defaultHandler)
-                reportDefault(parser, enc, s, next);
-            break;
-        case XML_TOK_PI:
-            if (!reportProcessingInstruction(parser, enc, s, next))
-                return XML_ERROR_NO_MEMORY;
-            break;
-        case XML_TOK_COMMENT:
-            if (!reportComment(parser, enc, s, next))
-                return XML_ERROR_NO_MEMORY;
-            break;
-        default:
-            if (defaultHandler)
-                reportDefault(parser, enc, s, next);
-            break;
-        }
-        *eventPP = s = next;
-    }
-    /* not reached */
-}
-
-/* If tagNamePtr is non-null, build a real list of attributes,
-otherwise just check the attributes for well-formedness. */
-
-static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *enc,
-                                const char *s, TAG_NAME *tagNamePtr,
-                                BINDING **bindingsPtr)
-{
-    ELEMENT_TYPE *elementType = 0;
-    int nDefaultAtts = 0;
-    const XML_Char **appAtts;
-    int attIndex = 0;
-    int i;
-    int n;
-    int nPrefixes = 0;
-    BINDING *binding;
-    const XML_Char *localPart;
-
-    if (tagNamePtr) {
-        elementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, tagNamePtr->str, 0);
-        if (!elementType) {
-            tagNamePtr->str = poolCopyString(&dtd.pool, tagNamePtr->str);
-            if (!tagNamePtr->str)
-                return XML_ERROR_NO_MEMORY;
-            elementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, tagNamePtr->str, sizeof(ELEMENT_TYPE));
-            if (!elementType)
-                return XML_ERROR_NO_MEMORY;
-            if (ns && !setElementTypePrefix(parser, elementType))
-                return XML_ERROR_NO_MEMORY;
-        }
-        nDefaultAtts = elementType->nDefaultAtts;
-    }
-    n = XmlGetAttributes(enc, s, attsSize, atts);
-    if (n + nDefaultAtts > attsSize) {
-        int oldAttsSize = attsSize;
-        attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
-        atts = realloc((void *)atts, attsSize * sizeof(ATTRIBUTE));
-        if (!atts)
-            return XML_ERROR_NO_MEMORY;
-        if (n > oldAttsSize)
-            XmlGetAttributes(enc, s, n, atts);
-    }
-    appAtts = (const XML_Char **)atts;
-    for (i = 0; i < n; i++) {
-        ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name,
-                                             atts[i].name
-                                             + XmlNameLength(enc, atts[i].name));
-        if (!attId)
-            return XML_ERROR_NO_MEMORY;
-        if ((attId->name)[-1]) {
-            if (enc == encoding)
-                eventPtr = atts[i].name;
-            return XML_ERROR_DUPLICATE_ATTRIBUTE;
-        }
-        (attId->name)[-1] = 1;
-        appAtts[attIndex++] = attId->name;
-        if (!atts[i].normalized) {
-            enum XML_Error result;
-            int isCdata = 1;
-
-            if (attId->maybeTokenized) {
-                int j;
-                for (j = 0; j < nDefaultAtts; j++) {
-                    if (attId == elementType->defaultAtts[j].id) {
-                        isCdata = elementType->defaultAtts[j].isCdata;
-                        break;
-                    }
-                }
-            }
-
-            result = storeAttributeValue(parser, enc, isCdata,
-                                         atts[i].valuePtr, atts[i].valueEnd,
-                                         &tempPool);
-            if (result)
-                return result;
-            if (tagNamePtr) {
-                appAtts[attIndex] = poolStart(&tempPool);
-                poolFinish(&tempPool);
-            }
-            else
-                poolDiscard(&tempPool);
-        }
-        else if (tagNamePtr) {
-            appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr, atts[i].valueEnd);
-            if (appAtts[attIndex] == 0)
-                return XML_ERROR_NO_MEMORY;
-            poolFinish(&tempPool);
-        }
-        if (attId->prefix && tagNamePtr) {
-            if (attId->xmlns) {
-                if (!addBinding(parser, attId->prefix, attId, appAtts[attIndex], bindingsPtr))
-                    return XML_ERROR_NO_MEMORY;
-                --attIndex;
-            }
-            else {
-                attIndex++;
-                nPrefixes++;
-                (attId->name)[-1] = 2;
-            }
-        }
-        else
-            attIndex++;
-    }
-    nSpecifiedAtts = attIndex;
-    if (tagNamePtr) {
-        int j;
-        for (j = 0; j < nDefaultAtts; j++) {
-            const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + j;
-            if (!(da->id->name)[-1] && da->value) {
-                if (da->id->prefix) {
-                    if (da->id->xmlns) {
-                        if (!addBinding(parser, da->id->prefix, da->id, da->value, bindingsPtr))
-                            return XML_ERROR_NO_MEMORY;
-                    }
-                    else {
-                        (da->id->name)[-1] = 2;
-                        nPrefixes++;
-                        appAtts[attIndex++] = da->id->name;
-                        appAtts[attIndex++] = da->value;
-                    }
-                }
-                else {
-                    (da->id->name)[-1] = 1;
-                    appAtts[attIndex++] = da->id->name;
-                    appAtts[attIndex++] = da->value;
-                }
-            }
-        }
-        appAtts[attIndex] = 0;
-    }
-    i = 0;
-    if (nPrefixes) {
-        for (; i < attIndex; i += 2) {
-            if (appAtts[i][-1] == 2) {
-                ATTRIBUTE_ID *id;
-                ((XML_Char *)(appAtts[i]))[-1] = 0;
-                id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, appAtts[i], 0);
-                if (id->prefix->binding) {
-                    int j;
-                    const BINDING *b = id->prefix->binding;
-                    const XML_Char *s = appAtts[i];
-                    for (j = 0; j < b->uriLen; j++) {
-                        if (!poolAppendChar(&tempPool, b->uri[j]))
-                            return XML_ERROR_NO_MEMORY;
-                    }
-                    while (*s++ != ':')
-                        ;
-                    do {
-                        if (!poolAppendChar(&tempPool, *s))
-                            return XML_ERROR_NO_MEMORY;
-                    } while (*s++);
-                    appAtts[i] = poolStart(&tempPool);
-                    poolFinish(&tempPool);
-                }
-                if (!--nPrefixes)
-                    break;
-            }
-            else
-                ((XML_Char *)(appAtts[i]))[-1] = 0;
-        }
-    }
-    for (; i < attIndex; i += 2)
-        ((XML_Char *)(appAtts[i]))[-1] = 0;
-    if (!tagNamePtr)
-        return XML_ERROR_NONE;
-    for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
-        binding->attId->name[-1] = 0;
-    if (elementType->prefix) {
-        binding = elementType->prefix->binding;
-        if (!binding)
-            return XML_ERROR_NONE;
-        localPart = tagNamePtr->str;
-        while (*localPart++ != XML_T(':'))
-            ;
-    }
-    else if (dtd.defaultPrefix.binding) {
-        binding = dtd.defaultPrefix.binding;
-        localPart = tagNamePtr->str;
-    }
-    else
-        return XML_ERROR_NONE;
-    tagNamePtr->localPart = localPart;
-    tagNamePtr->uriLen = binding->uriLen;
-    i = binding->uriLen;
-    do {
-        if (i == binding->uriAlloc) {
-            binding->uri = realloc(binding->uri, binding->uriAlloc *= 2);
-            if (!binding->uri)
-                return XML_ERROR_NO_MEMORY;
-        }
-        binding->uri[i++] = *localPart;
-    } while (*localPart++);
-    tagNamePtr->str = binding->uri;
-    return XML_ERROR_NONE;
-}
-
-static
-int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr)
-{
-    BINDING *b;
-    int len;
-    for (len = 0; uri[len]; len++)
-        ;
-    if (namespaceSeparator)
-        len++;
-    if (freeBindingList) {
-        b = freeBindingList;
-        if (len > b->uriAlloc) {
-            b->uri = realloc(b->uri, len + EXPAND_SPARE);
-            if (!b->uri)
-                return 0;
-            b->uriAlloc = len + EXPAND_SPARE;
-        }
-        freeBindingList = b->nextTagBinding;
-    }
-    else {
-        b = malloc(sizeof(BINDING));
-        if (!b)
-            return 0;
-        b->uri = malloc(sizeof(XML_Char) * len + EXPAND_SPARE);
-        if (!b->uri) {
-            g_free(b);
-            return 0;
-        }
-        b->uriAlloc = len;
-    }
-    b->uriLen = len;
-    memcpy(b->uri, uri, len * sizeof(XML_Char));
-    if (namespaceSeparator)
-        b->uri[len - 1] = namespaceSeparator;
-    b->prefix = prefix;
-    b->attId = attId;
-    b->prevPrefixBinding = prefix->binding;
-    if (*uri == XML_T('\0') && prefix == &dtd.defaultPrefix)
-        prefix->binding = 0;
-    else
-        prefix->binding = b;
-    b->nextTagBinding = *bindingsPtr;
-    *bindingsPtr = b;
-    if (startNamespaceDeclHandler)
-        startNamespaceDeclHandler(handlerArg, prefix->name,
-                                  prefix->binding ? uri : 0);
-    return 1;
-}
-
-/* The idea here is to avoid using stack for each CDATA section when
-the whole file is parsed with one call. */
-
-static
-enum XML_Error cdataSectionProcessor(XML_Parser parser,
-                                     const char *start,
-                                     const char *end,
-                                     const char **endPtr)
-{
-    enum XML_Error result = doCdataSection(parser, encoding, &start, end, endPtr);
-    if (start) {
-        processor = contentProcessor;
-        return contentProcessor(parser, start, end, endPtr);
-    }
-    return result;
-}
-
-/* startPtr gets set to non-null is the section is closed, and to null if
-the section is not yet closed. */
-
-static
-enum XML_Error doCdataSection(XML_Parser parser,
-                              const ENCODING *enc,
-                              const char **startPtr,
-                              const char *end,
-                              const char **nextPtr)
-{
-    const char *s = *startPtr;
-    const char **eventPP;
-    const char **eventEndPP;
-    if (enc == encoding) {
-        eventPP = &eventPtr;
-        *eventPP = s;
-        eventEndPP = &eventEndPtr;
-    }
-    else {
-        eventPP = &(openInternalEntities->internalEventPtr);
-        eventEndPP = &(openInternalEntities->internalEventEndPtr);
-    }
-    *eventPP = s;
-    *startPtr = 0;
-    for (;;) {
-        const char *next;
-        int tok = XmlCdataSectionTok(enc, s, end, &next);
-        *eventEndPP = next;
-        switch (tok) {
-        case XML_TOK_CDATA_SECT_CLOSE:
-            if (endCdataSectionHandler)
-                endCdataSectionHandler(handlerArg);
-#if 0
-            /* see comment under XML_TOK_CDATA_SECT_OPEN */
-            else if (characterDataHandler)
-                characterDataHandler(handlerArg, dataBuf, 0);
-#endif
-            else if (defaultHandler)
-                reportDefault(parser, enc, s, next);
-            *startPtr = next;
-            return XML_ERROR_NONE;
-        case XML_TOK_DATA_NEWLINE:
-            if (characterDataHandler) {
-                XML_Char c = 0xA;
-                characterDataHandler(handlerArg, &c, 1);
-            }
-            else if (defaultHandler)
-                reportDefault(parser, enc, s, next);
-            break;
-        case XML_TOK_DATA_CHARS:
-            if (characterDataHandler) {
-                if (MUST_CONVERT(enc, s)) {
-                    for (;;) {
-                        ICHAR *dataPtr = (ICHAR *)dataBuf;
-                        XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
-                        *eventEndPP = next;
-                        characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
-                        if (s == next)
-                            break;
-                        *eventPP = s;
-                    }
-                }
-                else
-                    characterDataHandler(handlerArg,
-                                         (XML_Char *)s,
-                                         (XML_Char *)next - (XML_Char *)s);
-            }
-            else if (defaultHandler)
-                reportDefault(parser, enc, s, next);
-            break;
-        case XML_TOK_INVALID:
-            *eventPP = next;
-            return XML_ERROR_INVALID_TOKEN;
-        case XML_TOK_PARTIAL_CHAR:
-            if (nextPtr) {
-                *nextPtr = s;
-                return XML_ERROR_NONE;
-            }
-            return XML_ERROR_PARTIAL_CHAR;
-        case XML_TOK_PARTIAL:
-        case XML_TOK_NONE:
-            if (nextPtr) {
-                *nextPtr = s;
-                return XML_ERROR_NONE;
-            }
-            return XML_ERROR_UNCLOSED_CDATA_SECTION;
-        default:
-            abort();
-        }
-        *eventPP = s = next;
-    }
-    /* not reached */
-}
-
-static enum XML_Error
-initializeEncoding(XML_Parser parser)
-{
-    const char *s;
-#ifdef XML_UNICODE
-    char encodingBuf[128];
-    if (!protocolEncodingName)
-        s = 0;
-    else {
-        int i;
-        for (i = 0; protocolEncodingName[i]; i++) {
-            if (i == sizeof(encodingBuf) - 1
-                    || protocolEncodingName[i] >= 0x80
-                    || protocolEncodingName[i] < 0) {
-                encodingBuf[0] = '\0';
-                break;
-            }
-            encodingBuf[i] = (char)protocolEncodingName[i];
-        }
-        encodingBuf[i] = '\0';
-        s = encodingBuf;
-    }
-#else
-s = protocolEncodingName;
-#endif
-    if (ns ? XmlInitEncodingNS(&initEncoding, &encoding, s) : XmlInitEncoding(&initEncoding, &encoding, s))
-        return XML_ERROR_NONE;
-    return handleUnknownEncoding(parser, protocolEncodingName);
-}
-
-static enum XML_Error
-processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
-               const char *s, const char *next)
-{
-    const char *encodingName = 0;
-    const ENCODING *newEncoding = 0;
-    const char *version;
-    int standalone = -1;
-    if (!(ns
-            ? XmlParseXmlDeclNS(isGeneralTextEntity,
-                               encoding,
-                               s,
-                               next,
-                               &eventPtr,
-                               &version,
-                               &encodingName,
-                               &newEncoding,
-                               &standalone)
-            : XmlParseXmlDecl(isGeneralTextEntity,
-                               encoding,
-                               s,
-                               next,
-                               &eventPtr,
-                               &version,
-                               &encodingName,
-                               &newEncoding,
-                               &standalone)))
-        return XML_ERROR_SYNTAX;
-    if (!isGeneralTextEntity && standalone == 1)
-        dtd.standalone = 1;
-    if (defaultHandler)
-        reportDefault(parser, encoding, s, next);
-    if (!protocolEncodingName) {
-        if (newEncoding) {
-            if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
-                eventPtr = encodingName;
-                return XML_ERROR_INCORRECT_ENCODING;
-            }
-            encoding = newEncoding;
-        }
-        else if (encodingName) {
-            enum XML_Error result;
-            const XML_Char *s = poolStoreString(&tempPool,
-                                                encoding,
-                                                encodingName,
-                                                encodingName
-                                                + XmlNameLength(encoding, encodingName));
-            if (!s)
-                return XML_ERROR_NO_MEMORY;
-            result = handleUnknownEncoding(parser, s);
-            poolDiscard(&tempPool);
-            if (result == XML_ERROR_UNKNOWN_ENCODING)
-                eventPtr = encodingName;
-            return result;
-        }
-    }
-    return XML_ERROR_NONE;
-}
-
-static enum XML_Error
-handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
-{
-    if (unknownEncodingHandler) {
-        XML_Encoding info;
-        int i;
-        for (i = 0; i < 256; i++)
-            info.map[i] = -1;
-        info.convert = 0;
-        info.data = 0;
-        info.release = 0;
-        if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName, &info)) {
-            ENCODING *enc;
-            unknownEncodingMem = malloc(XmlSizeOfUnknownEncoding());
-            if (!unknownEncodingMem) {
-                if (info.release)
-                    info.release(info.data);
-                return XML_ERROR_NO_MEMORY;
-            }
-            enc = (ns
-                   ? XmlInitUnknownEncodingNS(unknownEncodingMem,
-                                             info.map,
-                                             info.convert,
-                                             info.data)
-                   : XmlInitUnknownEncoding(unknownEncodingMem,
-                                             info.map,
-                                             info.convert,
-                                             info.data));
-            if (enc) {
-                unknownEncodingData = info.data;
-                unknownEncodingRelease = info.release;
-                encoding = enc;
-                return XML_ERROR_NONE;
-            }
-        }
-        if (info.release)
-            info.release(info.data);
-    }
-    return XML_ERROR_UNKNOWN_ENCODING;
-}
-
-static enum XML_Error
-prologInitProcessor(XML_Parser parser,
-                    const char *s,
-                    const char *end,
-                    const char **nextPtr)
-{
-    enum XML_Error result = initializeEncoding(parser);
-    if (result != XML_ERROR_NONE)
-        return result;
-    processor = prologProcessor;
-    return prologProcessor(parser, s, end, nextPtr);
-}
-
-static enum XML_Error
-prologProcessor(XML_Parser parser,
-                const char *s,
-                const char *end,
-                const char **nextPtr)
-{
-    for (;;) {
-        const char *next;
-        int tok = XmlPrologTok(encoding, s, end, &next);
-        if (tok <= 0) {
-            if (nextPtr != 0 && tok != XML_TOK_INVALID) {
-                *nextPtr = s;
-                return XML_ERROR_NONE;
-            }
-            switch (tok) {
-            case XML_TOK_INVALID:
-                eventPtr = next;
-                return XML_ERROR_INVALID_TOKEN;
-            case XML_TOK_NONE:
-                return XML_ERROR_NO_ELEMENTS;
-            case XML_TOK_PARTIAL:
-                return XML_ERROR_UNCLOSED_TOKEN;
-            case XML_TOK_PARTIAL_CHAR:
-                return XML_ERROR_PARTIAL_CHAR;
-            case XML_TOK_TRAILING_CR:
-                eventPtr = s + encoding->minBytesPerChar;
-                return XML_ERROR_NO_ELEMENTS;
-            default:
-                abort();
-            }
-        }
-        switch (XmlTokenRole(&prologState, tok, s, next, encoding)) {
-        case XML_ROLE_XML_DECL:
-            {
-                enum XML_Error result = processXmlDecl(parser, 0, s, next);
-                if (result != XML_ERROR_NONE)
-                    return result;
-            }
-            break;
-        case XML_ROLE_DOCTYPE_SYSTEM_ID:
-            if (!dtd.standalone
-                    && notStandaloneHandler
-                    && !notStandaloneHandler(handlerArg))
-                return XML_ERROR_NOT_STANDALONE;
-            hadExternalDoctype = 1;
-            break;
-        case XML_ROLE_DOCTYPE_PUBLIC_ID:
-        case XML_ROLE_ENTITY_PUBLIC_ID:
-            if (!XmlIsPublicId(encoding, s, next, &eventPtr))
-                return XML_ERROR_SYNTAX;
-            if (declEntity) {
-                XML_Char *tem = poolStoreString(&dtd.pool,
-                                                encoding,
-                                                s + encoding->minBytesPerChar,
-                                                next - encoding->minBytesPerChar);
-                if (!tem)
-                    return XML_ERROR_NO_MEMORY;
-                normalizePublicId(tem);
-                declEntity->publicId = tem;
-                poolFinish(&dtd.pool);
-            }
-            break;
-        case XML_ROLE_INSTANCE_START:
-            processor = contentProcessor;
-            if (hadExternalDoctype)
-                dtd.complete = 0;
-            return contentProcessor(parser, s, end, nextPtr);
-        case XML_ROLE_ATTLIST_ELEMENT_NAME:
-            {
-                const XML_Char *name = poolStoreString(&dtd.pool, encoding, s, next);
-                if (!name)
-                    return XML_ERROR_NO_MEMORY;
-                declElementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, name, sizeof(ELEMENT_TYPE));
-                if (!declElementType)
-                    return XML_ERROR_NO_MEMORY;
-                if (declElementType->name != name)
-                    poolDiscard(&dtd.pool);
-                else {
-                    poolFinish(&dtd.pool);
-                    if (!setElementTypePrefix(parser, declElementType))
-                        return XML_ERROR_NO_MEMORY;
-                }
-                break;
-            }
-        case XML_ROLE_ATTRIBUTE_NAME:
-            declAttributeId = getAttributeId(parser, encoding, s, next);
-            if (!declAttributeId)
-                return XML_ERROR_NO_MEMORY;
-            declAttributeIsCdata = 0;
-            break;
-        case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
-            declAttributeIsCdata = 1;
-            break;
-        case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
-        case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
-            if (dtd.complete
-                    && !defineAttribute(declElementType, declAttributeId, declAttributeIsCdata, 0))
-                return XML_ERROR_NO_MEMORY;
-            break;
-        case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
-        case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
-            {
-                const XML_Char *attVal;
-                enum XML_Error result
-                = storeAttributeValue(parser, encoding, declAttributeIsCdata,
-                                      s + encoding->minBytesPerChar,
-                                      next - encoding->minBytesPerChar,
-                                      &dtd.pool);
-                if (result)
-                    return result;
-                attVal = poolStart(&dtd.pool);
-                poolFinish(&dtd.pool);
-                if (dtd.complete
-                        && !defineAttribute(declElementType, declAttributeId, declAttributeIsCdata, attVal))
-                    return XML_ERROR_NO_MEMORY;
-                break;
-            }
-        case XML_ROLE_ENTITY_VALUE:
-            {
-                enum XML_Error result = storeEntityValue(parser, s, next);
-                if (result != XML_ERROR_NONE)
-                    return result;
-            }
-            break;
-        case XML_ROLE_ENTITY_SYSTEM_ID:
-            if (declEntity) {
-                declEntity->systemId = poolStoreString(&dtd.pool, encoding,
-                                                       s + encoding->minBytesPerChar,
-                                                       next - encoding->minBytesPerChar);
-                if (!declEntity->systemId)
-                    return XML_ERROR_NO_MEMORY;
-                declEntity->base = dtd.base;
-                poolFinish(&dtd.pool);
-            }
-            break;
-        case XML_ROLE_ENTITY_NOTATION_NAME:
-            if (declEntity) {
-                declEntity->notation = poolStoreString(&dtd.pool, encoding, s, next);
-                if (!declEntity->notation)
-                    return XML_ERROR_NO_MEMORY;
-                poolFinish(&dtd.pool);
-                if (unparsedEntityDeclHandler) {
-                    eventPtr = eventEndPtr = s;
-                    unparsedEntityDeclHandler(handlerArg,
-                                              declEntity->name,
-                                              declEntity->base,
-                                              declEntity->systemId,
-                                              declEntity->publicId,
-                                              declEntity->notation);
-                }
-
-            }
-            break;
-        case XML_ROLE_GENERAL_ENTITY_NAME:
-            {
-                const XML_Char *name;
-                if (XmlPredefinedEntityName(encoding, s, next)) {
-                    declEntity = 0;
-                    break;
-                }
-                name = poolStoreString(&dtd.pool, encoding, s, next);
-                if (!name)
-                    return XML_ERROR_NO_MEMORY;
-                if (dtd.complete) {
-                    declEntity = (ENTITY *)lookup(&dtd.generalEntities, name, sizeof(ENTITY));
-                    if (!declEntity)
-                        return XML_ERROR_NO_MEMORY;
-                    if (declEntity->name != name) {
-                        poolDiscard(&dtd.pool);
-                        declEntity = 0;
-                    }
-                    else
-                        poolFinish(&dtd.pool);
-                }
-                else {
-                    poolDiscard(&dtd.pool);
-                    declEntity = 0;
-                }
-            }
-            break;
-        case XML_ROLE_PARAM_ENTITY_NAME:
-            declEntity = 0;
-            break;
-        case XML_ROLE_NOTATION_NAME:
-            declNotationPublicId = 0;
-            declNotationName = 0;
-            if (notationDeclHandler) {
-                declNotationName = poolStoreString(&tempPool, encoding, s, next);
-                if (!declNotationName)
-                    return XML_ERROR_NO_MEMORY;
-                poolFinish(&tempPool);
-            }
-            break;
-        case XML_ROLE_NOTATION_PUBLIC_ID:
-            if (!XmlIsPublicId(encoding, s, next, &eventPtr))
-                return XML_ERROR_SYNTAX;
-            if (declNotationName) {
-                XML_Char *tem = poolStoreString(&tempPool,
-                                                encoding,
-                                                s + encoding->minBytesPerChar,
-                                                next - encoding->minBytesPerChar);
-                if (!tem)
-                    return XML_ERROR_NO_MEMORY;
-                normalizePublicId(tem);
-                declNotationPublicId = tem;
-                poolFinish(&tempPool);
-            }
-            break;
-        case XML_ROLE_NOTATION_SYSTEM_ID:
-            if (declNotationName && notationDeclHandler) {
-                const XML_Char *systemId
-                = poolStoreString(&tempPool, encoding,
-                                  s + encoding->minBytesPerChar,
-                                  next - encoding->minBytesPerChar);
-                if (!systemId)
-                    return XML_ERROR_NO_MEMORY;
-                eventPtr = eventEndPtr = s;
-                notationDeclHandler(handlerArg,
-                                    declNotationName,
-                                    dtd.base,
-                                    systemId,
-                                    declNotationPublicId);
-            }
-            poolClear(&tempPool);
-            break;
-        case XML_ROLE_NOTATION_NO_SYSTEM_ID:
-            if (declNotationPublicId && notationDeclHandler) {
-                eventPtr = eventEndPtr = s;
-                notationDeclHandler(handlerArg,
-                                    declNotationName,
-                                    dtd.base,
-                                    0,
-                                    declNotationPublicId);
-            }
-            poolClear(&tempPool);
-            break;
-        case XML_ROLE_ERROR:
-            eventPtr = s;
-            switch (tok) {
-            case XML_TOK_PARAM_ENTITY_REF:
-                return XML_ERROR_PARAM_ENTITY_REF;
-            case XML_TOK_XML_DECL:
-                return XML_ERROR_MISPLACED_XML_PI;
-            default:
-                return XML_ERROR_SYNTAX;
-            }
-        case XML_ROLE_GROUP_OPEN:
-            if (prologState.level >= groupSize) {
-                if (groupSize)
-                    groupConnector = realloc(groupConnector, groupSize *= 2);
-                else
-                    groupConnector = malloc(groupSize = 32);
-                if (!groupConnector)
-                    return XML_ERROR_NO_MEMORY;
-            }
-            groupConnector[prologState.level] = 0;
-            break;
-        case XML_ROLE_GROUP_SEQUENCE:
-            if (groupConnector[prologState.level] == '|') {
-                eventPtr = s;
-                return XML_ERROR_SYNTAX;
-            }
-            groupConnector[prologState.level] = ',';
-            break;
-        case XML_ROLE_GROUP_CHOICE:
-            if (groupConnector[prologState.level] == ',') {
-                eventPtr = s;
-                return XML_ERROR_SYNTAX;
-            }
-            groupConnector[prologState.level] = '|';
-            break;
-        case XML_ROLE_PARAM_ENTITY_REF:
-            if (!dtd.standalone
-                    && notStandaloneHandler
-                    && !notStandaloneHandler(handlerArg))
-                return XML_ERROR_NOT_STANDALONE;
-            dtd.complete = 0;
-            break;
-        case XML_ROLE_NONE:
-            switch (tok) {
-            case XML_TOK_PI:
-                eventPtr = s;
-                eventEndPtr = next;
-                if (!reportProcessingInstruction(parser, encoding, s, next))
-                    return XML_ERROR_NO_MEMORY;
-                break;
-            case XML_TOK_COMMENT:
-                eventPtr = s;
-                eventEndPtr = next;
-                if (!reportComment(parser, encoding, s, next))
-                    return XML_ERROR_NO_MEMORY;
-                break;
-            }
-            break;
-        }
-        if (defaultHandler) {
-            switch (tok) {
-            case XML_TOK_PI:
-            case XML_TOK_COMMENT:
-            case XML_TOK_BOM:
-            case XML_TOK_XML_DECL:
-                break;
-            default:
-                eventPtr = s;
-                eventEndPtr = next;
-                reportDefault(parser, encoding, s, next);
-            }
-        }
-        s = next;
-    }
-    /* not reached */
-}
-
-static
-enum XML_Error epilogProcessor(XML_Parser parser,
-                               const char *s,
-                               const char *end,
-                               const char **nextPtr)
-{
-    processor = epilogProcessor;
-    eventPtr = s;
-    for (;;) {
-        const char *next;
-        int tok = XmlPrologTok(encoding, s, end, &next);
-        eventEndPtr = next;
-        switch (tok) {
-        case XML_TOK_TRAILING_CR:
-            if (defaultHandler) {
-                eventEndPtr = end;
-                reportDefault(parser, encoding, s, end);
-            }
-            /* fall through */
-        case XML_TOK_NONE:
-            if (nextPtr)
-                *nextPtr = end;
-            return XML_ERROR_NONE;
-        case XML_TOK_PROLOG_S:
-            if (defaultHandler)
-                reportDefault(parser, encoding, s, next);
-            break;
-        case XML_TOK_PI:
-            if (!reportProcessingInstruction(parser, encoding, s, next))
-                return XML_ERROR_NO_MEMORY;
-            break;
-        case XML_TOK_COMMENT:
-            if (!reportComment(parser, encoding, s, next))
-                return XML_ERROR_NO_MEMORY;
-            break;
-        case XML_TOK_INVALID:
-            eventPtr = next;
-            return XML_ERROR_INVALID_TOKEN;
-        case XML_TOK_PARTIAL:
-            if (nextPtr) {
-                *nextPtr = s;
-                return XML_ERROR_NONE;
-            }
-            return XML_ERROR_UNCLOSED_TOKEN;
-        case XML_TOK_PARTIAL_CHAR:
-            if (nextPtr) {
-                *nextPtr = s;
-                return XML_ERROR_NONE;
-            }
-            return XML_ERROR_PARTIAL_CHAR;
-        default:
-            return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
-        }
-        eventPtr = s = next;
-    }
-}
-
-static enum XML_Error
-storeAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata,
-                    const char *ptr, const char *end,
-                    STRING_POOL *pool)
-{
-    enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr, end, pool);
-    if (result)
-        return result;
-    if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
-        poolChop(pool);
-    if (!poolAppendChar(pool, XML_T('\0')))
-        return XML_ERROR_NO_MEMORY;
-    return XML_ERROR_NONE;
-}
-
-static enum XML_Error
-appendAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata,
-                     const char *ptr, const char *end,
-                     STRING_POOL *pool)
-{
-    const ENCODING *internalEnc = ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding();
-    for (;;) {
-        const char *next;
-        int tok = XmlAttributeValueTok(enc, ptr, end, &next);
-        switch (tok) {
-        case XML_TOK_NONE:
-            return XML_ERROR_NONE;
-        case XML_TOK_INVALID:
-            if (enc == encoding)
-                eventPtr = next;
-            return XML_ERROR_INVALID_TOKEN;
-        case XML_TOK_PARTIAL:
-            if (enc == encoding)
-                eventPtr = ptr;
-            return XML_ERROR_INVALID_TOKEN;
-        case XML_TOK_CHAR_REF:
-            {
-                XML_Char buf[XML_ENCODE_MAX];
-                int i;
-                int n = XmlCharRefNumber(enc, ptr);
-                if (n < 0) {
-                    if (enc == encoding)
-                        eventPtr = ptr;
-                    return XML_ERROR_BAD_CHAR_REF;
-                }
-                if (!isCdata
-                        && n == 0x20 /* space */
-                        && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
-                    break;
-                n = XmlEncode(n, (ICHAR *)buf);
-                if (!n) {
-                    if (enc == encoding)
-                        eventPtr = ptr;
-                    return XML_ERROR_BAD_CHAR_REF;
-                }
-                for (i = 0; i < n; i++) {
-                    if (!poolAppendChar(pool, buf[i]))
-                        return XML_ERROR_NO_MEMORY;
-                }
-            }
-            break;
-        case XML_TOK_DATA_CHARS:
-            if (!poolAppend(pool, enc, ptr, next))
-                return XML_ERROR_NO_MEMORY;
-            break;
-            break;
-        case XML_TOK_TRAILING_CR:
-            next = ptr + enc->minBytesPerChar;
-            /* fall through */
-        case XML_TOK_ATTRIBUTE_VALUE_S:
-        case XML_TOK_DATA_NEWLINE:
-            if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
-                break;
-            if (!poolAppendChar(pool, 0x20))
-                return XML_ERROR_NO_MEMORY;
-            break;
-        case XML_TOK_ENTITY_REF:
-            {
-                const XML_Char *name;
-                ENTITY *entity;
-                XML_Char ch = XmlPredefinedEntityName(enc,
-                                                      ptr + enc->minBytesPerChar,
-                                                      next - enc->minBytesPerChar);
-                if (ch) {
-                    if (!poolAppendChar(pool, ch))
-                        return XML_ERROR_NO_MEMORY;
-                    break;
-                }
-                name = poolStoreString(&temp2Pool, enc,
-                                       ptr + enc->minBytesPerChar,
-                                       next - enc->minBytesPerChar);
-                if (!name)
-                    return XML_ERROR_NO_MEMORY;
-                entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0);
-                poolDiscard(&temp2Pool);
-                if (!entity) {
-                    if (dtd.complete) {
-                        if (enc == encoding)
-                            eventPtr = ptr;
-                        return XML_ERROR_UNDEFINED_ENTITY;
-                    }
-                }
-                else if (entity->open) {
-                    if (enc == encoding)
-                        eventPtr = ptr;
-                    return XML_ERROR_RECURSIVE_ENTITY_REF;
-                }
-                else if (entity->notation) {
-                    if (enc == encoding)
-                        eventPtr = ptr;
-                    return XML_ERROR_BINARY_ENTITY_REF;
-                }
-                else if (!entity->textPtr) {
-                    if (enc == encoding)
-                        eventPtr = ptr;
-                    return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
-                }
-                else {
-                    enum XML_Error result;
-                    const XML_Char *textEnd = entity->textPtr + entity->textLen;
-                    entity->open = 1;
-                    result = appendAttributeValue(parser, internalEnc, isCdata, (char *)entity->textPtr, (char *)textEnd, pool);
-                    entity->open = 0;
-                    if (result)
-                        return result;
-                }
-            }
-            break;
-        default:
-            abort();
-        }
-        ptr = next;
-    }
-    /* not reached */
-}
-
-static
-enum XML_Error storeEntityValue(XML_Parser parser,
-                                const char *entityTextPtr,
-                                const char *entityTextEnd)
-{
-    const ENCODING *internalEnc;
-    STRING_POOL *pool = &(dtd.pool);
-    entityTextPtr += encoding->minBytesPerChar;
-    entityTextEnd -= encoding->minBytesPerChar;
-    internalEnc = ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding();
-    for (;;) {
-        const char *next;
-        int tok = XmlEntityValueTok(encoding, entityTextPtr, entityTextEnd, &next);
-        switch (tok) {
-        case XML_TOK_PARAM_ENTITY_REF:
-            eventPtr = entityTextPtr;
-            return XML_ERROR_SYNTAX;
-        case XML_TOK_NONE:
-            if (declEntity) {
-                declEntity->textPtr = pool->start;
-                declEntity->textLen = pool->ptr - pool->start;
-                poolFinish(pool);
-            }
-            else
-                poolDiscard(pool);
-            return XML_ERROR_NONE;
-        case XML_TOK_ENTITY_REF:
-        case XML_TOK_DATA_CHARS:
-            if (!poolAppend(pool, encoding, entityTextPtr, next))
-                return XML_ERROR_NO_MEMORY;
-            break;
-        case XML_TOK_TRAILING_CR:
-            next = entityTextPtr + encoding->minBytesPerChar;
-            /* fall through */
-        case XML_TOK_DATA_NEWLINE:
-            if (pool->end == pool->ptr && !poolGrow(pool))
-                return XML_ERROR_NO_MEMORY;
-            *(pool->ptr)++ = 0xA;
-            break;
-        case XML_TOK_CHAR_REF:
-            {
-                XML_Char buf[XML_ENCODE_MAX];
-                int i;
-                int n = XmlCharRefNumber(encoding, entityTextPtr);
-                if (n < 0) {
-                    eventPtr = entityTextPtr;
-                    return XML_ERROR_BAD_CHAR_REF;
-                }
-                n = XmlEncode(n, (ICHAR *)buf);
-                if (!n) {
-                    eventPtr = entityTextPtr;
-                    return XML_ERROR_BAD_CHAR_REF;
-                }
-                for (i = 0; i < n; i++) {
-                    if (pool->end == pool->ptr && !poolGrow(pool))
-                        return XML_ERROR_NO_MEMORY;
-                    *(pool->ptr)++ = buf[i];
-                }
-            }
-            break;
-        case XML_TOK_PARTIAL:
-            eventPtr = entityTextPtr;
-            return XML_ERROR_INVALID_TOKEN;
-        case XML_TOK_INVALID:
-            eventPtr = next;
-            return XML_ERROR_INVALID_TOKEN;
-        default:
-            abort();
-        }
-        entityTextPtr = next;
-    }
-    /* not reached */
-}
-
-static void
-normalizeLines(XML_Char *s)
-{
-    XML_Char *p;
-    for (;; s++) {
-        if (*s == XML_T('\0'))
-            return;
-        if (*s == 0xD)
-            break;
-    }
-    p = s;
-    do {
-        if (*s == 0xD) {
-            *p++ = 0xA;
-            if (*++s == 0xA)
-                s++;
-        }
-        else
-            *p++ = *s++;
-    } while (*s);
-    *p = XML_T('\0');
-}
-
-static int
-reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
-{
-    const XML_Char *target;
-    XML_Char *data;
-    const char *tem;
-    if (!processingInstructionHandler) {
-        if (defaultHandler)
-            reportDefault(parser, enc, start, end);
-        return 1;
-    }
-    start += enc->minBytesPerChar * 2;
-    tem = start + XmlNameLength(enc, start);
-    target = poolStoreString(&tempPool, enc, start, tem);
-    if (!target)
-        return 0;
-    poolFinish(&tempPool);
-    data = poolStoreString(&tempPool, enc,
-                           XmlSkipS(enc, tem),
-                           end - enc->minBytesPerChar*2);
-    if (!data)
-        return 0;
-    normalizeLines(data);
-    processingInstructionHandler(handlerArg, target, data);
-    poolClear(&tempPool);
-    return 1;
-}
-
-static int
-reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
-{
-    XML_Char *data;
-    if (!commentHandler) {
-        if (defaultHandler)
-            reportDefault(parser, enc, start, end);
-        return 1;
-    }
-    data = poolStoreString(&tempPool,
-                           enc,
-                           start + enc->minBytesPerChar * 4,
-                           end - enc->minBytesPerChar * 3);
-    if (!data)
-        return 0;
-    normalizeLines(data);
-    commentHandler(handlerArg, data);
-    poolClear(&tempPool);
-    return 1;
-}
-
-static void
-reportDefault(XML_Parser parser, const ENCODING *enc, const char *s, const char *end)
-{
-    if (MUST_CONVERT(enc, s)) {
-        const char **eventPP;
-        const char **eventEndPP;
-        if (enc == encoding) {
-            eventPP = &eventPtr;
-            eventEndPP = &eventEndPtr;
-        }
-        else {
-            eventPP = &(openInternalEntities->internalEventPtr);
-            eventEndPP = &(openInternalEntities->internalEventEndPtr);
-        }
-        do {
-            ICHAR *dataPtr = (ICHAR *)dataBuf;
-            XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
-            *eventEndPP = s;
-            defaultHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
-            *eventPP = s;
-        } while (s != end);
-    }
-    else
-        defaultHandler(handlerArg, (XML_Char *)s, (XML_Char *)end - (XML_Char *)s);
-}
-
-
-static int
-defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, int isCdata, const XML_Char *value)
-{
-    DEFAULT_ATTRIBUTE *att;
-    if (type->nDefaultAtts == type->allocDefaultAtts) {
-        if (type->allocDefaultAtts == 0) {
-            type->allocDefaultAtts = 8;
-            type->defaultAtts = malloc(type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE));
-        }
-        else {
-            type->allocDefaultAtts *= 2;
-            type->defaultAtts = realloc(type->defaultAtts,
-                                        type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE));
-        }
-        if (!type->defaultAtts)
-            return 0;
-    }
-    att = type->defaultAtts + type->nDefaultAtts;
-    att->id = attId;
-    att->value = value;
-    att->isCdata = isCdata;
-    if (!isCdata)
-        attId->maybeTokenized = 1;
-    type->nDefaultAtts += 1;
-    return 1;
-}
-
-static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
-{
-    const XML_Char *name;
-    for (name = elementType->name; *name; name++) {
-        if (*name == XML_T(':')) {
-            PREFIX *prefix;
-            const XML_Char *s;
-            for (s = elementType->name; s != name; s++) {
-                if (!poolAppendChar(&dtd.pool, *s))
-                    return 0;
-            }
-            if (!poolAppendChar(&dtd.pool, XML_T('\0')))
-                return 0;
-            prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
-            if (!prefix)
-                return 0;
-            if (prefix->name == poolStart(&dtd.pool))
-                poolFinish(&dtd.pool);
-            else
-                poolDiscard(&dtd.pool);
-            elementType->prefix = prefix;
-
-        }
-    }
-    return 1;
-}
-
-static ATTRIBUTE_ID *
-getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
-{
-    ATTRIBUTE_ID *id;
-    const XML_Char *name;
-    if (!poolAppendChar(&dtd.pool, XML_T('\0')))
-        return 0;
-    name = poolStoreString(&dtd.pool, enc, start, end);
-    if (!name)
-        return 0;
-    ++name;
-    id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, name, sizeof(ATTRIBUTE_ID));
-    if (!id)
-        return 0;
-    if (id->name != name)
-        poolDiscard(&dtd.pool);
-    else {
-        poolFinish(&dtd.pool);
-        if (!ns)
-            ;
-        else if (name[0] == 'x'
-                 && name[1] == 'm'
-                 && name[2] == 'l'
-                 && name[3] == 'n'
-                 && name[4] == 's'
-                 && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) {
-            if (name[5] == '\0')
-                id->prefix = &dtd.defaultPrefix;
-            else
-                id->prefix = (PREFIX *)lookup(&dtd.prefixes, name + 6, sizeof(PREFIX));
-            id->xmlns = 1;
-        }
-        else {
-            int i;
-            for (i = 0; name[i]; i++) {
-                if (name[i] == XML_T(':')) {
-                    int j;
-                    for (j = 0; j < i; j++) {
-                        if (!poolAppendChar(&dtd.pool, name[j]))
-                            return 0;
-                    }
-                    if (!poolAppendChar(&dtd.pool, XML_T('\0')))
-                        return 0;
-                    id->prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
-                    if (id->prefix->name == poolStart(&dtd.pool))
-                        poolFinish(&dtd.pool);
-                    else
-                        poolDiscard(&dtd.pool);
-                    break;
-                }
-            }
-        }
-    }
-    return id;
-}
-
-#define CONTEXT_SEP XML_T('\f')
-
-static
-const XML_Char *getContext(XML_Parser parser)
-{
-    HASH_TABLE_ITER iter;
-    int needSep = 0;
-
-    if (dtd.defaultPrefix.binding) {
-        int i;
-        int len;
-        if (!poolAppendChar(&tempPool, XML_T('=')))
-            return 0;
-        len = dtd.defaultPrefix.binding->uriLen;
-        if (namespaceSeparator != XML_T('\0'))
-            len--;
-        for (i = 0; i < len; i++)
-            if (!poolAppendChar(&tempPool, dtd.defaultPrefix.binding->uri[i]))
-                return 0;
-        needSep = 1;
-    }
-
-    hashTableIterInit(&iter, &(dtd.prefixes));
-    for (;;) {
-        int i;
-        int len;
-        const XML_Char *s;
-        PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
-        if (!prefix)
-            break;
-        if (!prefix->binding)
-            continue;
-        if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
-            return 0;
-        for (s = prefix->name; *s; s++)
-            if (!poolAppendChar(&tempPool, *s))
-                return 0;
-        if (!poolAppendChar(&tempPool, XML_T('=')))
-            return 0;
-        len = prefix->binding->uriLen;
-        if (namespaceSeparator != XML_T('\0'))
-            len--;
-        for (i = 0; i < len; i++)
-            if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
-                return 0;
-        needSep = 1;
-    }
-
-
-    hashTableIterInit(&iter, &(dtd.generalEntities));
-    for (;;) {
-        const XML_Char *s;
-        ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
-        if (!e)
-            break;
-        if (!e->open)
-            continue;
-        if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
-            return 0;
-        for (s = e->name; *s; s++)
-            if (!poolAppendChar(&tempPool, *s))
-                return 0;
-        needSep = 1;
-    }
-
-    if (!poolAppendChar(&tempPool, XML_T('\0')))
-        return 0;
-    return tempPool.start;
-}
-
-static
-void normalizePublicId(XML_Char *publicId)
-{
-    XML_Char *p = publicId;
-    XML_Char *s;
-    for (s = publicId; *s; s++) {
-        switch (*s) {
-        case 0x20:
-        case 0xD:
-        case 0xA:
-            if (p != publicId && p[-1] != 0x20)
-                *p++ = 0x20;
-            break;
-        default:
-            *p++ = *s;
-        }
-    }
-    if (p != publicId && p[-1] == 0x20)
-        --p;
-    *p = XML_T('\0');
-}
-
-static int dtdInit(DTD *p)
-{
-    poolInit(&(p->pool));
-    hashTableInit(&(p->generalEntities));
-    hashTableInit(&(p->elementTypes));
-    hashTableInit(&(p->attributeIds));
-    hashTableInit(&(p->prefixes));
-    p->complete = 1;
-    p->standalone = 0;
-    p->base = 0;
-    p->defaultPrefix.name = 0;
-    p->defaultPrefix.binding = 0;
-    return 1;
-}
-
-static void dtdDestroy(DTD *p)
-{
-    HASH_TABLE_ITER iter;
-    hashTableIterInit(&iter, &(p->elementTypes));
-    for (;;) {
-        ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
-        if (!e)
-            break;
-        if (e->allocDefaultAtts != 0)
-            g_free(e->defaultAtts);
-    }
-    hashTableDestroy(&(p->generalEntities));
-    hashTableDestroy(&(p->elementTypes));
-    hashTableDestroy(&(p->attributeIds));
-    hashTableDestroy(&(p->prefixes));
-    poolDestroy(&(p->pool));
-}
-
-static
-void poolInit(STRING_POOL *pool)
-{
-    pool->blocks = 0;
-    pool->freeBlocks = 0;
-    pool->start = 0;
-    pool->ptr = 0;
-    pool->end = 0;
-}
-
-static
-void poolClear(STRING_POOL *pool)
-{
-    if (!pool->freeBlocks)
-        pool->freeBlocks = pool->blocks;
-    else {
-        BLOCK *p = pool->blocks;
-        while (p) {
-            BLOCK *tem = p->next;
-            p->next = pool->freeBlocks;
-            pool->freeBlocks = p;
-            p = tem;
-        }
-    }
-    pool->blocks = 0;
-    pool->start = 0;
-    pool->ptr = 0;
-    pool->end = 0;
-}
-
-static
-void poolDestroy(STRING_POOL *pool)
-{
-    BLOCK *p = pool->blocks;
-    while (p) {
-        BLOCK *tem = p->next;
-        g_free(p);
-        p = tem;
-    }
-    pool->blocks = 0;
-    p = pool->freeBlocks;
-    while (p) {
-        BLOCK *tem = p->next;
-        g_free(p);
-        p = tem;
-    }
-    pool->freeBlocks = 0;
-    pool->ptr = 0;
-    pool->start = 0;
-    pool->end = 0;
-}
-
-static
-XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
-                     const char *ptr, const char *end)
-{
-    if (!pool->ptr && !poolGrow(pool))
-        return 0;
-    for (;;) {
-        XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
-        if (ptr == end)
-            break;
-        if (!poolGrow(pool))
-            return 0;
-    }
-    return pool->start;
-}
-
-static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s)
-{
-    do {
-        if (!poolAppendChar(pool, *s))
-            return 0;
-    } while (*s++);
-    s = pool->start;
-    poolFinish(pool);
-    return s;
-}
-
-static
-XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
-                          const char *ptr, const char *end)
-{
-    if (!poolAppend(pool, enc, ptr, end))
-        return 0;
-    if (pool->ptr == pool->end && !poolGrow(pool))
-        return 0;
-    *(pool->ptr)++ = 0;
-    return pool->start;
-}
-
-static
-int poolGrow(STRING_POOL *pool)
-{
-    if (pool->freeBlocks) {
-        if (pool->start == 0) {
-            pool->blocks = pool->freeBlocks;
-            pool->freeBlocks = pool->freeBlocks->next;
-            pool->blocks->next = 0;
-            pool->start = pool->blocks->s;
-            pool->end = pool->start + pool->blocks->size;
-            pool->ptr = pool->start;
-            return 1;
-        }
-        if (pool->end - pool->start < pool->freeBlocks->size) {
-            BLOCK *tem = pool->freeBlocks->next;
-            pool->freeBlocks->next = pool->blocks;
-            pool->blocks = pool->freeBlocks;
-            pool->freeBlocks = tem;
-            memcpy(pool->blocks->s, pool->start, (pool->end - pool->start) * sizeof(XML_Char));
-            pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
-            pool->start = pool->blocks->s;
-            pool->end = pool->start + pool->blocks->size;
-            return 1;
-        }
-    }
-    if (pool->blocks && pool->start == pool->blocks->s) {
-        int blockSize = (pool->end - pool->start)*2;
-        pool->blocks = realloc(pool->blocks, offsetof(BLOCK, s) + blockSize * sizeof(XML_Char));
-        if (!pool->blocks)
-            return 0;
-        pool->blocks->size = blockSize;
-        pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
-        pool->start = pool->blocks->s;
-        pool->end = pool->start + blockSize;
-    }
-    else {
-        BLOCK *tem;
-        int blockSize = pool->end - pool->start;
-        if (blockSize < INIT_BLOCK_SIZE)
-            blockSize = INIT_BLOCK_SIZE;
-        else
-            blockSize *= 2;
-        tem = malloc(offsetof(BLOCK, s) + blockSize * sizeof(XML_Char));
-        if (!tem)
-            return 0;
-        tem->size = blockSize;
-        tem->next = pool->blocks;
-        pool->blocks = tem;
-        memcpy(tem->s, pool->start, (pool->ptr - pool->start) * sizeof(XML_Char));
-        pool->ptr = tem->s + (pool->ptr - pool->start);
-        pool->start = tem->s;
-        pool->end = tem->s + blockSize;
-    }
-    return 1;
-}
Index: protocols/jabber/xmlparse.h
===================================================================
--- protocols/jabber/xmlparse.h	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,476 +1,0 @@
-/*
-The contents of this file are subject to the Mozilla Public License
-Version 1.1 (the "License"); you may not use this file except in
-compliance with the License. You may obtain a copy of the License at
-http://www.mozilla.org/MPL/
-
-Software distributed under the License is distributed on an "AS IS"
-basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
-License for the specific language governing rights and limitations
-under the License.
-
-The Original Code is expat.
-
-The Initial Developer of the Original Code is James Clark.
-Portions created by James Clark are Copyright (C) 1998, 1999
-James Clark. All Rights Reserved.
-
-Contributor(s):
-
-Alternatively, the contents of this file may be used under the terms
-of the GNU General Public License (the "GPL"), in which case the
-provisions of the GPL are applicable instead of those above.  If you
-wish to allow use of your version of this file only under the terms of
-the GPL and not to allow others to use your version of this file under
-the MPL, indicate your decision by deleting the provisions above and
-replace them with the notice and other provisions required by the
-GPL. If you do not delete the provisions above, a recipient may use
-your version of this file under either the MPL or the GPL.
-*/
-
-#ifndef XmlParse_INCLUDED
-#define XmlParse_INCLUDED 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef XMLPARSEAPI
-#define XMLPARSEAPI /* as nothing */
-#endif
-
-typedef void *XML_Parser;
-
-#ifdef XML_UNICODE_WCHAR_T
-
-/* XML_UNICODE_WCHAR_T will work only if sizeof(wchar_t) == 2 and wchar_t
-uses Unicode. */
-/* Information is UTF-16 encoded as wchar_ts */
-
-#ifndef XML_UNICODE
-#define XML_UNICODE
-#endif
-
-#include <stddef.h>
-typedef wchar_t XML_Char;
-typedef wchar_t XML_LChar;
-
-#else /* not XML_UNICODE_WCHAR_T */
-
-#ifdef XML_UNICODE
-
-/* Information is UTF-16 encoded as unsigned shorts */
-typedef unsigned short XML_Char;
-typedef char XML_LChar;
-
-#else /* not XML_UNICODE */
-
-/* Information is UTF-8 encoded. */
-typedef char XML_Char;
-typedef char XML_LChar;
-
-#endif /* not XML_UNICODE */
-
-#endif /* not XML_UNICODE_WCHAR_T */
-
-
-/* Constructs a new parser; encoding is the encoding specified by the external
-protocol or null if there is none specified. */
-
-XML_Parser XMLPARSEAPI
-XML_ParserCreate(const XML_Char *encoding);
-
-/* Constructs a new parser and namespace processor.  Element type names
-and attribute names that belong to a namespace will be expanded;
-unprefixed attribute names are never expanded; unprefixed element type
-names are expanded only if there is a default namespace. The expanded
-name is the concatenation of the namespace URI, the namespace separator character,
-and the local part of the name.  If the namespace separator is '\0' then
-the namespace URI and the local part will be concatenated without any
-separator.  When a namespace is not declared, the name and prefix will be
-passed through without expansion. */
-
-XML_Parser XMLPARSEAPI
-XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator);
-
-
-/* atts is array of name/value pairs, terminated by 0;
-   names and values are 0 terminated. */
-
-typedef void (*XML_StartElementHandler)(void *userData,
-					const XML_Char *name,
-					const XML_Char **atts);
-
-typedef void (*XML_EndElementHandler)(void *userData,
-				      const XML_Char *name);
-
-/* s is not 0 terminated. */
-typedef void (*XML_CharacterDataHandler)(void *userData,
-					 const XML_Char *s,
-					 int len);
-
-/* target and data are 0 terminated */
-typedef void (*XML_ProcessingInstructionHandler)(void *userData,
-						 const XML_Char *target,
-						 const XML_Char *data);
-
-/* data is 0 terminated */
-typedef void (*XML_CommentHandler)(void *userData, const XML_Char *data);
-
-typedef void (*XML_StartCdataSectionHandler)(void *userData);
-typedef void (*XML_EndCdataSectionHandler)(void *userData);
-
-/* This is called for any characters in the XML document for
-which there is no applicable handler.  This includes both
-characters that are part of markup which is of a kind that is
-not reported (comments, markup declarations), or characters
-that are part of a construct which could be reported but
-for which no handler has been supplied. The characters are passed
-exactly as they were in the XML document except that
-they will be encoded in UTF-8.  Line boundaries are not normalized.
-Note that a byte order mark character is not passed to the default handler.
-There are no guarantees about how characters are divided between calls
-to the default handler: for example, a comment might be split between
-multiple calls. */
-
-typedef void (*XML_DefaultHandler)(void *userData,
-				   const XML_Char *s,
-				   int len);
-
-/* This is called for a declaration of an unparsed (NDATA)
-entity.  The base argument is whatever was set by XML_SetBase.
-The entityName, systemId and notationName arguments will never be null.
-The other arguments may be. */
-
-typedef void (*XML_UnparsedEntityDeclHandler)(void *userData,
-					      const XML_Char *entityName,
-					      const XML_Char *base,
-					      const XML_Char *systemId,
-					      const XML_Char *publicId,
-					      const XML_Char *notationName);
-
-/* This is called for a declaration of notation.
-The base argument is whatever was set by XML_SetBase.
-The notationName will never be null.  The other arguments can be. */
-
-typedef void (*XML_NotationDeclHandler)(void *userData,
-					const XML_Char *notationName,
-					const XML_Char *base,
-					const XML_Char *systemId,
-					const XML_Char *publicId);
-
-/* When namespace processing is enabled, these are called once for
-each namespace declaration. The call to the start and end element
-handlers occur between the calls to the start and end namespace
-declaration handlers. For an xmlns attribute, prefix will be null.
-For an xmlns="" attribute, uri will be null. */
-
-typedef void (*XML_StartNamespaceDeclHandler)(void *userData,
-					      const XML_Char *prefix,
-					      const XML_Char *uri);
-
-typedef void (*XML_EndNamespaceDeclHandler)(void *userData,
-					    const XML_Char *prefix);
-
-/* This is called if the document is not standalone (it has an
-external subset or a reference to a parameter entity, but does not
-have standalone="yes"). If this handler returns 0, then processing
-will not continue, and the parser will return a
-XML_ERROR_NOT_STANDALONE error. */
-
-typedef int (*XML_NotStandaloneHandler)(void *userData);
-
-/* This is called for a reference to an external parsed general entity.
-The referenced entity is not automatically parsed.
-The application can parse it immediately or later using
-XML_ExternalEntityParserCreate.
-The parser argument is the parser parsing the entity containing the reference;
-it can be passed as the parser argument to XML_ExternalEntityParserCreate.
-The systemId argument is the system identifier as specified in the entity declaration;
-it will not be null.
-The base argument is the system identifier that should be used as the base for
-resolving systemId if systemId was relative; this is set by XML_SetBase;
-it may be null.
-The publicId argument is the public identifier as specified in the entity declaration,
-or null if none was specified; the whitespace in the public identifier
-will have been normalized as required by the XML spec.
-The context argument specifies the parsing context in the format
-expected by the context argument to
-XML_ExternalEntityParserCreate; context is valid only until the handler
-returns, so if the referenced entity is to be parsed later, it must be copied.
-The handler should return 0 if processing should not continue because of
-a fatal error in the handling of the external entity.
-In this case the calling parser will return an XML_ERROR_EXTERNAL_ENTITY_HANDLING
-error.
-Note that unlike other handlers the first argument is the parser, not userData. */
-
-typedef int (*XML_ExternalEntityRefHandler)(XML_Parser parser,
-					    const XML_Char *context,
-					    const XML_Char *base,
-					    const XML_Char *systemId,
-					    const XML_Char *publicId);
-
-/* This structure is filled in by the XML_UnknownEncodingHandler
-to provide information to the parser about encodings that are unknown
-to the parser.
-The map[b] member gives information about byte sequences
-whose first byte is b.
-If map[b] is c where c is >= 0, then b by itself encodes the Unicode scalar value c.
-If map[b] is -1, then the byte sequence is malformed.
-If map[b] is -n, where n >= 2, then b is the first byte of an n-byte
-sequence that encodes a single Unicode scalar value.
-The data member will be passed as the first argument to the convert function.
-The convert function is used to convert multibyte sequences;
-s will point to a n-byte sequence where map[(unsigned char)*s] == -n.
-The convert function must return the Unicode scalar value
-represented by this byte sequence or -1 if the byte sequence is malformed.
-The convert function may be null if the encoding is a single-byte encoding,
-that is if map[b] >= -1 for all bytes b.
-When the parser is finished with the encoding, then if release is not null,
-it will call release passing it the data member;
-once release has been called, the convert function will not be called again.
-
-Expat places certain restrictions on the encodings that are supported
-using this mechanism.
-
-1. Every ASCII character that can appear in a well-formed XML document,
-other than the characters
-
-  $@\^`{}~
-
-must be represented by a single byte, and that byte must be the
-same byte that represents that character in ASCII.
-
-2. No character may require more than 4 bytes to encode.
-
-3. All characters encoded must have Unicode scalar values <= 0xFFFF,
-(ie characters that would be encoded by surrogates in UTF-16
-are  not allowed).  Note that this restriction doesn't apply to
-the built-in support for UTF-8 and UTF-16.
-
-4. No Unicode character may be encoded by more than one distinct sequence
-of bytes. */
-
-typedef struct {
-  int map[256];
-  void *data;
-  int (*convert)(void *data, const char *s);
-  void (*release)(void *data);
-} XML_Encoding;
-
-/* This is called for an encoding that is unknown to the parser.
-The encodingHandlerData argument is that which was passed as the
-second argument to XML_SetUnknownEncodingHandler.
-The name argument gives the name of the encoding as specified in
-the encoding declaration.
-If the callback can provide information about the encoding,
-it must fill in the XML_Encoding structure, and return 1.
-Otherwise it must return 0.
-If info does not describe a suitable encoding,
-then the parser will return an XML_UNKNOWN_ENCODING error. */
-
-typedef int (*XML_UnknownEncodingHandler)(void *encodingHandlerData,
-					  const XML_Char *name,
-					  XML_Encoding *info);
-
-void XMLPARSEAPI
-XML_SetElementHandler(XML_Parser parser,
-		      XML_StartElementHandler start,
-		      XML_EndElementHandler end);
-
-void XMLPARSEAPI
-XML_SetCharacterDataHandler(XML_Parser parser,
-			    XML_CharacterDataHandler handler);
-
-void XMLPARSEAPI
-XML_SetProcessingInstructionHandler(XML_Parser parser,
-				    XML_ProcessingInstructionHandler handler);
-void XMLPARSEAPI
-XML_SetCommentHandler(XML_Parser parser,
-                      XML_CommentHandler handler);
-
-void XMLPARSEAPI
-XML_SetCdataSectionHandler(XML_Parser parser,
-			   XML_StartCdataSectionHandler start,
-			   XML_EndCdataSectionHandler end);
-
-/* This sets the default handler and also inhibits expansion of internal entities.
-The entity reference will be passed to the default handler. */
-
-void XMLPARSEAPI
-XML_SetDefaultHandler(XML_Parser parser,
-		      XML_DefaultHandler handler);
-
-/* This sets the default handler but does not inhibit expansion of internal entities.
-The entity reference will not be passed to the default handler. */
-
-void XMLPARSEAPI
-XML_SetDefaultHandlerExpand(XML_Parser parser,
-		            XML_DefaultHandler handler);
-
-void XMLPARSEAPI
-XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
-				 XML_UnparsedEntityDeclHandler handler);
-
-void XMLPARSEAPI
-XML_SetNotationDeclHandler(XML_Parser parser,
-			   XML_NotationDeclHandler handler);
-
-void XMLPARSEAPI
-XML_SetNamespaceDeclHandler(XML_Parser parser,
-			    XML_StartNamespaceDeclHandler start,
-			    XML_EndNamespaceDeclHandler end);
-
-void XMLPARSEAPI
-XML_SetNotStandaloneHandler(XML_Parser parser,
-			    XML_NotStandaloneHandler handler);
-
-void XMLPARSEAPI
-XML_SetExternalEntityRefHandler(XML_Parser parser,
-				XML_ExternalEntityRefHandler handler);
-
-/* If a non-null value for arg is specified here, then it will be passed
-as the first argument to the external entity ref handler instead
-of the parser object. */
-void XMLPARSEAPI
-XML_SetExternalEntityRefHandlerArg(XML_Parser, void *arg);
-
-void XMLPARSEAPI
-XML_SetUnknownEncodingHandler(XML_Parser parser,
-			      XML_UnknownEncodingHandler handler,
-			      void *encodingHandlerData);
-
-/* This can be called within a handler for a start element, end element,
-processing instruction or character data.  It causes the corresponding
-markup to be passed to the default handler. */
-void XMLPARSEAPI XML_DefaultCurrent(XML_Parser parser);
-
-/* This value is passed as the userData argument to callbacks. */
-void XMLPARSEAPI
-XML_SetUserData(XML_Parser parser, void *userData);
-
-/* Returns the last value set by XML_SetUserData or null. */
-#define XML_GetUserData(parser) (*(void **)(parser))
-
-/* This is equivalent to supplying an encoding argument
-to XML_CreateParser. It must not be called after XML_Parse
-or XML_ParseBuffer. */
-
-int XMLPARSEAPI
-XML_SetEncoding(XML_Parser parser, const XML_Char *encoding);
-
-/* If this function is called, then the parser will be passed
-as the first argument to callbacks instead of userData.
-The userData will still be accessible using XML_GetUserData. */
-
-void XMLPARSEAPI
-XML_UseParserAsHandlerArg(XML_Parser parser);
-
-/* Sets the base to be used for resolving relative URIs in system identifiers in
-declarations.  Resolving relative identifiers is left to the application:
-this value will be passed through as the base argument to the
-XML_ExternalEntityRefHandler, XML_NotationDeclHandler
-and XML_UnparsedEntityDeclHandler. The base argument will be copied.
-Returns zero if out of memory, non-zero otherwise. */
-
-int XMLPARSEAPI
-XML_SetBase(XML_Parser parser, const XML_Char *base);
-
-const XML_Char XMLPARSEAPI *
-XML_GetBase(XML_Parser parser);
-
-/* Returns the number of the attributes passed in last call to the
-XML_StartElementHandler that were specified in the start-tag rather
-than defaulted. */
-
-int XMLPARSEAPI XML_GetSpecifiedAttributeCount(XML_Parser parser);
-
-/* Parses some input. Returns 0 if a fatal error is detected.
-The last call to XML_Parse must have isFinal true;
-len may be zero for this call (or any other). */
-int XMLPARSEAPI
-XML_Parse(XML_Parser parser, const char *s, int len, int isFinal);
-
-/* Creates an XML_Parser object that can parse an external general entity;
-context is a '\0'-terminated string specifying the parse context;
-encoding is a '\0'-terminated string giving the name of the externally specified encoding,
-or null if there is no externally specified encoding.
-The context string consists of a sequence of tokens separated by formfeeds (\f);
-a token consisting of a name specifies that the general entity of the name
-is open; a token of the form prefix=uri specifies the namespace for a particular
-prefix; a token of the form =uri specifies the default namespace.
-This can be called at any point after the first call to an ExternalEntityRefHandler
-so longer as the parser has not yet been freed.
-The new parser is completely independent and may safely be used in a separate thread.
-The handlers and userData are initialized from the parser argument.
-Returns 0 if out of memory.  Otherwise returns a new XML_Parser object. */
-XML_Parser XMLPARSEAPI
-XML_ExternalEntityParserCreate(XML_Parser parser,
-			       const XML_Char *context,
-			       const XML_Char *encoding);
-
-enum XML_Error {
-  XML_ERROR_NONE,
-  XML_ERROR_NO_MEMORY,
-  XML_ERROR_SYNTAX,
-  XML_ERROR_NO_ELEMENTS,
-  XML_ERROR_INVALID_TOKEN,
-  XML_ERROR_UNCLOSED_TOKEN,
-  XML_ERROR_PARTIAL_CHAR,
-  XML_ERROR_TAG_MISMATCH,
-  XML_ERROR_DUPLICATE_ATTRIBUTE,
-  XML_ERROR_JUNK_AFTER_DOC_ELEMENT,
-  XML_ERROR_PARAM_ENTITY_REF,
-  XML_ERROR_UNDEFINED_ENTITY,
-  XML_ERROR_RECURSIVE_ENTITY_REF,
-  XML_ERROR_ASYNC_ENTITY,
-  XML_ERROR_BAD_CHAR_REF,
-  XML_ERROR_BINARY_ENTITY_REF,
-  XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF,
-  XML_ERROR_MISPLACED_XML_PI,
-  XML_ERROR_UNKNOWN_ENCODING,
-  XML_ERROR_INCORRECT_ENCODING,
-  XML_ERROR_UNCLOSED_CDATA_SECTION,
-  XML_ERROR_EXTERNAL_ENTITY_HANDLING,
-  XML_ERROR_NOT_STANDALONE
-};
-
-/* If XML_Parse or XML_ParseBuffer have returned 0, then XML_GetErrorCode
-returns information about the error. */
-
-enum XML_Error XMLPARSEAPI XML_GetErrorCode(XML_Parser parser);
-
-/* These functions return information about the current parse location.
-They may be called when XML_Parse or XML_ParseBuffer return 0;
-in this case the location is the location of the character at which
-the error was detected.
-They may also be called from any other callback called to report
-some parse event; in this the location is the location of the first
-of the sequence of characters that generated the event. */
-
-int XMLPARSEAPI XML_GetCurrentLineNumber(XML_Parser parser);
-int XMLPARSEAPI XML_GetCurrentColumnNumber(XML_Parser parser);
-long XMLPARSEAPI XML_GetCurrentByteIndex(XML_Parser parser);
-
-/* Return the number of bytes in the current event.
-Returns 0 if the event is in an internal entity. */
-
-int XMLPARSEAPI XML_GetCurrentByteCount(XML_Parser parser);
-
-/* For backwards compatibility with previous versions. */
-#define XML_GetErrorLineNumber XML_GetCurrentLineNumber
-#define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber
-#define XML_GetErrorByteIndex XML_GetCurrentByteIndex
-
-/* Frees memory used by the parser. */
-void XMLPARSEAPI
-XML_ParserFree(XML_Parser parser);
-
-/* Returns a string describing the error. */
-const XML_LChar XMLPARSEAPI *XML_ErrorString(int code);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* not XmlParse_INCLUDED */
Index: protocols/jabber/xmlrole.c
===================================================================
--- protocols/jabber/xmlrole.c	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,1104 +1,0 @@
-/*
-The contents of this file are subject to the Mozilla Public License
-Version 1.1 (the "License"); you may not use this file except in
-compliance with the License. You may obtain a copy of the License at
-http://www.mozilla.org/MPL/
-
-Software distributed under the License is distributed on an "AS IS"
-basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
-License for the specific language governing rights and limitations
-under the License.
-
-The Original Code is expat.
-
-The Initial Developer of the Original Code is James Clark.
-Portions created by James Clark are Copyright (C) 1998, 1999
-James Clark. All Rights Reserved.
-
-Contributor(s):
-
-*/
-
-#include "xmldef.h"
-#include "xmlrole.h"
-
-/* Doesn't check:
-
- that ,| are not mixed in a model group
- content of literals
-
-*/
-
-#ifndef MIN_BYTES_PER_CHAR
-#define MIN_BYTES_PER_CHAR(enc) ((enc)->minBytesPerChar)
-#endif
-
-typedef int PROLOG_HANDLER(struct prolog_state *state,
-                           int tok,
-                           const char *ptr,
-                           const char *end,
-                           const ENCODING *enc);
-
-static PROLOG_HANDLER
-prolog0, prolog1, prolog2,
-doctype0, doctype1, doctype2, doctype3, doctype4, doctype5,
-internalSubset,
-entity0, entity1, entity2, entity3, entity4, entity5, entity6,
-entity7, entity8, entity9,
-notation0, notation1, notation2, notation3, notation4,
-attlist0, attlist1, attlist2, attlist3, attlist4, attlist5, attlist6,
-attlist7, attlist8, attlist9,
-element0, element1, element2, element3, element4, element5, element6,
-element7,
-declClose,
-error;
-
-static
-int syntaxError(PROLOG_STATE *);
-
-static
-int prolog0(PROLOG_STATE *state,
-            int tok,
-            const char *ptr,
-            const char *end,
-            const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        state->handler = prolog1;
-        return XML_ROLE_NONE;
-    case XML_TOK_XML_DECL:
-        state->handler = prolog1;
-        return XML_ROLE_XML_DECL;
-    case XML_TOK_PI:
-        state->handler = prolog1;
-        return XML_ROLE_NONE;
-    case XML_TOK_COMMENT:
-        state->handler = prolog1;
-    case XML_TOK_BOM:
-        return XML_ROLE_NONE;
-    case XML_TOK_DECL_OPEN:
-        if (!XmlNameMatchesAscii(enc,
-                                 ptr + 2 * MIN_BYTES_PER_CHAR(enc),
-                                 "DOCTYPE"))
-            break;
-        state->handler = doctype0;
-        return XML_ROLE_NONE;
-    case XML_TOK_INSTANCE_START:
-        state->handler = error;
-        return XML_ROLE_INSTANCE_START;
-    }
-    return syntaxError(state);
-}
-
-static
-int prolog1(PROLOG_STATE *state,
-            int tok,
-            const char *ptr,
-            const char *end,
-            const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_PI:
-    case XML_TOK_COMMENT:
-    case XML_TOK_BOM:
-        return XML_ROLE_NONE;
-    case XML_TOK_DECL_OPEN:
-        if (!XmlNameMatchesAscii(enc,
-                                 ptr + 2 * MIN_BYTES_PER_CHAR(enc),
-                                 "DOCTYPE"))
-            break;
-        state->handler = doctype0;
-        return XML_ROLE_NONE;
-    case XML_TOK_INSTANCE_START:
-        state->handler = error;
-        return XML_ROLE_INSTANCE_START;
-    }
-    return syntaxError(state);
-}
-
-static
-int prolog2(PROLOG_STATE *state,
-            int tok,
-            const char *ptr,
-            const char *end,
-            const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_PI:
-    case XML_TOK_COMMENT:
-        return XML_ROLE_NONE;
-    case XML_TOK_INSTANCE_START:
-        state->handler = error;
-        return XML_ROLE_INSTANCE_START;
-    }
-    return syntaxError(state);
-}
-
-static
-int doctype0(PROLOG_STATE *state,
-             int tok,
-             const char *ptr,
-             const char *end,
-             const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_NAME:
-    case XML_TOK_PREFIXED_NAME:
-        state->handler = doctype1;
-        return XML_ROLE_DOCTYPE_NAME;
-    }
-    return syntaxError(state);
-}
-
-static
-int doctype1(PROLOG_STATE *state,
-             int tok,
-             const char *ptr,
-             const char *end,
-             const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_OPEN_BRACKET:
-        state->handler = internalSubset;
-        return XML_ROLE_NONE;
-    case XML_TOK_DECL_CLOSE:
-        state->handler = prolog2;
-        return XML_ROLE_DOCTYPE_CLOSE;
-    case XML_TOK_NAME:
-        if (XmlNameMatchesAscii(enc, ptr, "SYSTEM")) {
-            state->handler = doctype3;
-            return XML_ROLE_NONE;
-        }
-        if (XmlNameMatchesAscii(enc, ptr, "PUBLIC")) {
-            state->handler = doctype2;
-            return XML_ROLE_NONE;
-        }
-        break;
-    }
-    return syntaxError(state);
-}
-
-static
-int doctype2(PROLOG_STATE *state,
-             int tok,
-             const char *ptr,
-             const char *end,
-             const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_LITERAL:
-        state->handler = doctype3;
-        return XML_ROLE_DOCTYPE_PUBLIC_ID;
-    }
-    return syntaxError(state);
-}
-
-static
-int doctype3(PROLOG_STATE *state,
-             int tok,
-             const char *ptr,
-             const char *end,
-             const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_LITERAL:
-        state->handler = doctype4;
-        return XML_ROLE_DOCTYPE_SYSTEM_ID;
-    }
-    return syntaxError(state);
-}
-
-static
-int doctype4(PROLOG_STATE *state,
-             int tok,
-             const char *ptr,
-             const char *end,
-             const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_OPEN_BRACKET:
-        state->handler = internalSubset;
-        return XML_ROLE_NONE;
-    case XML_TOK_DECL_CLOSE:
-        state->handler = prolog2;
-        return XML_ROLE_DOCTYPE_CLOSE;
-    }
-    return syntaxError(state);
-}
-
-static
-int doctype5(PROLOG_STATE *state,
-             int tok,
-             const char *ptr,
-             const char *end,
-             const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_DECL_CLOSE:
-        state->handler = prolog2;
-        return XML_ROLE_DOCTYPE_CLOSE;
-    }
-    return syntaxError(state);
-}
-
-static
-int internalSubset(PROLOG_STATE *state,
-                   int tok,
-                   const char *ptr,
-                   const char *end,
-                   const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_DECL_OPEN:
-        if (XmlNameMatchesAscii(enc,
-                                ptr + 2 * MIN_BYTES_PER_CHAR(enc),
-                                "ENTITY")) {
-            state->handler = entity0;
-            return XML_ROLE_NONE;
-        }
-        if (XmlNameMatchesAscii(enc,
-                                ptr + 2 * MIN_BYTES_PER_CHAR(enc),
-                                "ATTLIST")) {
-            state->handler = attlist0;
-            return XML_ROLE_NONE;
-        }
-        if (XmlNameMatchesAscii(enc,
-                                ptr + 2 * MIN_BYTES_PER_CHAR(enc),
-                                "ELEMENT")) {
-            state->handler = element0;
-            return XML_ROLE_NONE;
-        }
-        if (XmlNameMatchesAscii(enc,
-                                ptr + 2 * MIN_BYTES_PER_CHAR(enc),
-                                "NOTATION")) {
-            state->handler = notation0;
-            return XML_ROLE_NONE;
-        }
-        break;
-    case XML_TOK_PI:
-    case XML_TOK_COMMENT:
-        return XML_ROLE_NONE;
-    case XML_TOK_PARAM_ENTITY_REF:
-        return XML_ROLE_PARAM_ENTITY_REF;
-    case XML_TOK_CLOSE_BRACKET:
-        state->handler = doctype5;
-        return XML_ROLE_NONE;
-    }
-    return syntaxError(state);
-}
-
-static
-int entity0(PROLOG_STATE *state,
-            int tok,
-            const char *ptr,
-            const char *end,
-            const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_PERCENT:
-        state->handler = entity1;
-        return XML_ROLE_NONE;
-    case XML_TOK_NAME:
-        state->handler = entity2;
-        return XML_ROLE_GENERAL_ENTITY_NAME;
-    }
-    return syntaxError(state);
-}
-
-static
-int entity1(PROLOG_STATE *state,
-            int tok,
-            const char *ptr,
-            const char *end,
-            const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_NAME:
-        state->handler = entity7;
-        return XML_ROLE_PARAM_ENTITY_NAME;
-    }
-    return syntaxError(state);
-}
-
-static
-int entity2(PROLOG_STATE *state,
-            int tok,
-            const char *ptr,
-            const char *end,
-            const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_NAME:
-        if (XmlNameMatchesAscii(enc, ptr, "SYSTEM")) {
-            state->handler = entity4;
-            return XML_ROLE_NONE;
-        }
-        if (XmlNameMatchesAscii(enc, ptr, "PUBLIC")) {
-            state->handler = entity3;
-            return XML_ROLE_NONE;
-        }
-        break;
-    case XML_TOK_LITERAL:
-        state->handler = declClose;
-        return XML_ROLE_ENTITY_VALUE;
-    }
-    return syntaxError(state);
-}
-
-static
-int entity3(PROLOG_STATE *state,
-            int tok,
-            const char *ptr,
-            const char *end,
-            const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_LITERAL:
-        state->handler = entity4;
-        return XML_ROLE_ENTITY_PUBLIC_ID;
-    }
-    return syntaxError(state);
-}
-
-
-static
-int entity4(PROLOG_STATE *state,
-            int tok,
-            const char *ptr,
-            const char *end,
-            const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_LITERAL:
-        state->handler = entity5;
-        return XML_ROLE_ENTITY_SYSTEM_ID;
-    }
-    return syntaxError(state);
-}
-
-static
-int entity5(PROLOG_STATE *state,
-            int tok,
-            const char *ptr,
-            const char *end,
-            const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_DECL_CLOSE:
-        state->handler = internalSubset;
-        return XML_ROLE_NONE;
-    case XML_TOK_NAME:
-        if (XmlNameMatchesAscii(enc, ptr, "NDATA")) {
-            state->handler = entity6;
-            return XML_ROLE_NONE;
-        }
-        break;
-    }
-    return syntaxError(state);
-}
-
-static
-int entity6(PROLOG_STATE *state,
-            int tok,
-            const char *ptr,
-            const char *end,
-            const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_NAME:
-        state->handler = declClose;
-        return XML_ROLE_ENTITY_NOTATION_NAME;
-    }
-    return syntaxError(state);
-}
-
-static
-int entity7(PROLOG_STATE *state,
-            int tok,
-            const char *ptr,
-            const char *end,
-            const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_NAME:
-        if (XmlNameMatchesAscii(enc, ptr, "SYSTEM")) {
-            state->handler = entity9;
-            return XML_ROLE_NONE;
-        }
-        if (XmlNameMatchesAscii(enc, ptr, "PUBLIC")) {
-            state->handler = entity8;
-            return XML_ROLE_NONE;
-        }
-        break;
-    case XML_TOK_LITERAL:
-        state->handler = declClose;
-        return XML_ROLE_ENTITY_VALUE;
-    }
-    return syntaxError(state);
-}
-
-static
-int entity8(PROLOG_STATE *state,
-            int tok,
-            const char *ptr,
-            const char *end,
-            const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_LITERAL:
-        state->handler = entity9;
-        return XML_ROLE_ENTITY_PUBLIC_ID;
-    }
-    return syntaxError(state);
-}
-
-static
-int entity9(PROLOG_STATE *state,
-            int tok,
-            const char *ptr,
-            const char *end,
-            const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_LITERAL:
-        state->handler = declClose;
-        return XML_ROLE_ENTITY_SYSTEM_ID;
-    }
-    return syntaxError(state);
-}
-
-static
-int notation0(PROLOG_STATE *state,
-              int tok,
-              const char *ptr,
-              const char *end,
-              const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_NAME:
-        state->handler = notation1;
-        return XML_ROLE_NOTATION_NAME;
-    }
-    return syntaxError(state);
-}
-
-static
-int notation1(PROLOG_STATE *state,
-              int tok,
-              const char *ptr,
-              const char *end,
-              const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_NAME:
-        if (XmlNameMatchesAscii(enc, ptr, "SYSTEM")) {
-            state->handler = notation3;
-            return XML_ROLE_NONE;
-        }
-        if (XmlNameMatchesAscii(enc, ptr, "PUBLIC")) {
-            state->handler = notation2;
-            return XML_ROLE_NONE;
-        }
-        break;
-    }
-    return syntaxError(state);
-}
-
-static
-int notation2(PROLOG_STATE *state,
-              int tok,
-              const char *ptr,
-              const char *end,
-              const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_LITERAL:
-        state->handler = notation4;
-        return XML_ROLE_NOTATION_PUBLIC_ID;
-    }
-    return syntaxError(state);
-}
-
-static
-int notation3(PROLOG_STATE *state,
-              int tok,
-              const char *ptr,
-              const char *end,
-              const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_LITERAL:
-        state->handler = declClose;
-        return XML_ROLE_NOTATION_SYSTEM_ID;
-    }
-    return syntaxError(state);
-}
-
-static
-int notation4(PROLOG_STATE *state,
-              int tok,
-              const char *ptr,
-              const char *end,
-              const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_LITERAL:
-        state->handler = declClose;
-        return XML_ROLE_NOTATION_SYSTEM_ID;
-    case XML_TOK_DECL_CLOSE:
-        state->handler = internalSubset;
-        return XML_ROLE_NOTATION_NO_SYSTEM_ID;
-    }
-    return syntaxError(state);
-}
-
-static
-int attlist0(PROLOG_STATE *state,
-             int tok,
-             const char *ptr,
-             const char *end,
-             const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_NAME:
-    case XML_TOK_PREFIXED_NAME:
-        state->handler = attlist1;
-        return XML_ROLE_ATTLIST_ELEMENT_NAME;
-    }
-    return syntaxError(state);
-}
-
-static
-int attlist1(PROLOG_STATE *state,
-             int tok,
-             const char *ptr,
-             const char *end,
-             const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_DECL_CLOSE:
-        state->handler = internalSubset;
-        return XML_ROLE_NONE;
-    case XML_TOK_NAME:
-    case XML_TOK_PREFIXED_NAME:
-        state->handler = attlist2;
-        return XML_ROLE_ATTRIBUTE_NAME;
-    }
-    return syntaxError(state);
-}
-
-static
-int attlist2(PROLOG_STATE *state,
-             int tok,
-             const char *ptr,
-             const char *end,
-             const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_NAME:
-        {
-            static const char *types[] = {
-                "CDATA",
-                "ID",
-                "IDREF",
-                "IDREFS",
-                "ENTITY",
-                "ENTITIES",
-                "NMTOKEN",
-                "NMTOKENS",
-            };
-            int i;
-            for (i = 0; i < (int)(sizeof(types)/sizeof(types[0])); i++)
-                if (XmlNameMatchesAscii(enc, ptr, types[i])) {
-                    state->handler = attlist8;
-                    return XML_ROLE_ATTRIBUTE_TYPE_CDATA + i;
-                }
-        }
-        if (XmlNameMatchesAscii(enc, ptr, "NOTATION")) {
-            state->handler = attlist5;
-            return XML_ROLE_NONE;
-        }
-        break;
-    case XML_TOK_OPEN_PAREN:
-        state->handler = attlist3;
-        return XML_ROLE_NONE;
-    }
-    return syntaxError(state);
-}
-
-static
-int attlist3(PROLOG_STATE *state,
-             int tok,
-             const char *ptr,
-             const char *end,
-             const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_NMTOKEN:
-    case XML_TOK_NAME:
-    case XML_TOK_PREFIXED_NAME:
-        state->handler = attlist4;
-        return XML_ROLE_ATTRIBUTE_ENUM_VALUE;
-    }
-    return syntaxError(state);
-}
-
-static
-int attlist4(PROLOG_STATE *state,
-             int tok,
-             const char *ptr,
-             const char *end,
-             const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_CLOSE_PAREN:
-        state->handler = attlist8;
-        return XML_ROLE_NONE;
-    case XML_TOK_OR:
-        state->handler = attlist3;
-        return XML_ROLE_NONE;
-    }
-    return syntaxError(state);
-}
-
-static
-int attlist5(PROLOG_STATE *state,
-             int tok,
-             const char *ptr,
-             const char *end,
-             const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_OPEN_PAREN:
-        state->handler = attlist6;
-        return XML_ROLE_NONE;
-    }
-    return syntaxError(state);
-}
-
-
-static
-int attlist6(PROLOG_STATE *state,
-             int tok,
-             const char *ptr,
-             const char *end,
-             const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_NAME:
-        state->handler = attlist7;
-        return XML_ROLE_ATTRIBUTE_NOTATION_VALUE;
-    }
-    return syntaxError(state);
-}
-
-static
-int attlist7(PROLOG_STATE *state,
-             int tok,
-             const char *ptr,
-             const char *end,
-             const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_CLOSE_PAREN:
-        state->handler = attlist8;
-        return XML_ROLE_NONE;
-    case XML_TOK_OR:
-        state->handler = attlist6;
-        return XML_ROLE_NONE;
-    }
-    return syntaxError(state);
-}
-
-/* default value */
-static
-int attlist8(PROLOG_STATE *state,
-             int tok,
-             const char *ptr,
-             const char *end,
-             const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_POUND_NAME:
-        if (XmlNameMatchesAscii(enc,
-                                ptr + MIN_BYTES_PER_CHAR(enc),
-                                "IMPLIED")) {
-            state->handler = attlist1;
-            return XML_ROLE_IMPLIED_ATTRIBUTE_VALUE;
-        }
-        if (XmlNameMatchesAscii(enc,
-                                ptr + MIN_BYTES_PER_CHAR(enc),
-                                "REQUIRED")) {
-            state->handler = attlist1;
-            return XML_ROLE_REQUIRED_ATTRIBUTE_VALUE;
-        }
-        if (XmlNameMatchesAscii(enc,
-                                ptr + MIN_BYTES_PER_CHAR(enc),
-                                "FIXED")) {
-            state->handler = attlist9;
-            return XML_ROLE_NONE;
-        }
-        break;
-    case XML_TOK_LITERAL:
-        state->handler = attlist1;
-        return XML_ROLE_DEFAULT_ATTRIBUTE_VALUE;
-    }
-    return syntaxError(state);
-}
-
-static
-int attlist9(PROLOG_STATE *state,
-             int tok,
-             const char *ptr,
-             const char *end,
-             const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_LITERAL:
-        state->handler = attlist1;
-        return XML_ROLE_FIXED_ATTRIBUTE_VALUE;
-    }
-    return syntaxError(state);
-}
-
-static
-int element0(PROLOG_STATE *state,
-             int tok,
-             const char *ptr,
-             const char *end,
-             const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_NAME:
-    case XML_TOK_PREFIXED_NAME:
-        state->handler = element1;
-        return XML_ROLE_ELEMENT_NAME;
-    }
-    return syntaxError(state);
-}
-
-static
-int element1(PROLOG_STATE *state,
-             int tok,
-             const char *ptr,
-             const char *end,
-             const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_NAME:
-        if (XmlNameMatchesAscii(enc, ptr, "EMPTY")) {
-            state->handler = declClose;
-            return XML_ROLE_CONTENT_EMPTY;
-        }
-        if (XmlNameMatchesAscii(enc, ptr, "ANY")) {
-            state->handler = declClose;
-            return XML_ROLE_CONTENT_ANY;
-        }
-        break;
-    case XML_TOK_OPEN_PAREN:
-        state->handler = element2;
-        state->level = 1;
-        return XML_ROLE_GROUP_OPEN;
-    }
-    return syntaxError(state);
-}
-
-static
-int element2(PROLOG_STATE *state,
-             int tok,
-             const char *ptr,
-             const char *end,
-             const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_POUND_NAME:
-        if (XmlNameMatchesAscii(enc,
-                                ptr + MIN_BYTES_PER_CHAR(enc),
-                                "PCDATA")) {
-            state->handler = element3;
-            return XML_ROLE_CONTENT_PCDATA;
-        }
-        break;
-    case XML_TOK_OPEN_PAREN:
-        state->level = 2;
-        state->handler = element6;
-        return XML_ROLE_GROUP_OPEN;
-    case XML_TOK_NAME:
-    case XML_TOK_PREFIXED_NAME:
-        state->handler = element7;
-        return XML_ROLE_CONTENT_ELEMENT;
-    case XML_TOK_NAME_QUESTION:
-        state->handler = element7;
-        return XML_ROLE_CONTENT_ELEMENT_OPT;
-    case XML_TOK_NAME_ASTERISK:
-        state->handler = element7;
-        return XML_ROLE_CONTENT_ELEMENT_REP;
-    case XML_TOK_NAME_PLUS:
-        state->handler = element7;
-        return XML_ROLE_CONTENT_ELEMENT_PLUS;
-    }
-    return syntaxError(state);
-}
-
-static
-int element3(PROLOG_STATE *state,
-             int tok,
-             const char *ptr,
-             const char *end,
-             const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_CLOSE_PAREN:
-    case XML_TOK_CLOSE_PAREN_ASTERISK:
-        state->handler = declClose;
-        return XML_ROLE_GROUP_CLOSE_REP;
-    case XML_TOK_OR:
-        state->handler = element4;
-        return XML_ROLE_NONE;
-    }
-    return syntaxError(state);
-}
-
-static
-int element4(PROLOG_STATE *state,
-             int tok,
-             const char *ptr,
-             const char *end,
-             const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_NAME:
-    case XML_TOK_PREFIXED_NAME:
-        state->handler = element5;
-        return XML_ROLE_CONTENT_ELEMENT;
-    }
-    return syntaxError(state);
-}
-
-static
-int element5(PROLOG_STATE *state,
-             int tok,
-             const char *ptr,
-             const char *end,
-             const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_CLOSE_PAREN_ASTERISK:
-        state->handler = declClose;
-        return XML_ROLE_GROUP_CLOSE_REP;
-    case XML_TOK_OR:
-        state->handler = element4;
-        return XML_ROLE_NONE;
-    }
-    return syntaxError(state);
-}
-
-static
-int element6(PROLOG_STATE *state,
-             int tok,
-             const char *ptr,
-             const char *end,
-             const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_OPEN_PAREN:
-        state->level += 1;
-        return XML_ROLE_GROUP_OPEN;
-    case XML_TOK_NAME:
-    case XML_TOK_PREFIXED_NAME:
-        state->handler = element7;
-        return XML_ROLE_CONTENT_ELEMENT;
-    case XML_TOK_NAME_QUESTION:
-        state->handler = element7;
-        return XML_ROLE_CONTENT_ELEMENT_OPT;
-    case XML_TOK_NAME_ASTERISK:
-        state->handler = element7;
-        return XML_ROLE_CONTENT_ELEMENT_REP;
-    case XML_TOK_NAME_PLUS:
-        state->handler = element7;
-        return XML_ROLE_CONTENT_ELEMENT_PLUS;
-    }
-    return syntaxError(state);
-}
-
-static
-int element7(PROLOG_STATE *state,
-             int tok,
-             const char *ptr,
-             const char *end,
-             const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_CLOSE_PAREN:
-        state->level -= 1;
-        if (state->level == 0)
-            state->handler = declClose;
-        return XML_ROLE_GROUP_CLOSE;
-    case XML_TOK_CLOSE_PAREN_ASTERISK:
-        state->level -= 1;
-        if (state->level == 0)
-            state->handler = declClose;
-        return XML_ROLE_GROUP_CLOSE_REP;
-    case XML_TOK_CLOSE_PAREN_QUESTION:
-        state->level -= 1;
-        if (state->level == 0)
-            state->handler = declClose;
-        return XML_ROLE_GROUP_CLOSE_OPT;
-    case XML_TOK_CLOSE_PAREN_PLUS:
-        state->level -= 1;
-        if (state->level == 0)
-            state->handler = declClose;
-        return XML_ROLE_GROUP_CLOSE_PLUS;
-    case XML_TOK_COMMA:
-        state->handler = element6;
-        return XML_ROLE_GROUP_SEQUENCE;
-    case XML_TOK_OR:
-        state->handler = element6;
-        return XML_ROLE_GROUP_CHOICE;
-    }
-    return syntaxError(state);
-}
-
-static
-int declClose(PROLOG_STATE *state,
-              int tok,
-              const char *ptr,
-              const char *end,
-              const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_PROLOG_S:
-        return XML_ROLE_NONE;
-    case XML_TOK_DECL_CLOSE:
-        state->handler = internalSubset;
-        return XML_ROLE_NONE;
-    }
-    return syntaxError(state);
-}
-
-#if 0
-
-static
-int ignore(PROLOG_STATE *state,
-           int tok,
-           const char *ptr,
-           const char *end,
-           const ENCODING *enc)
-{
-    switch (tok) {
-    case XML_TOK_DECL_CLOSE:
-        state->handler = internalSubset;
-        return 0;
-    default:
-        return XML_ROLE_NONE;
-    }
-    return syntaxError(state);
-}
-#endif
-
-static
-int error(PROLOG_STATE *state,
-          int tok,
-          const char *ptr,
-          const char *end,
-          const ENCODING *enc)
-{
-    return XML_ROLE_NONE;
-}
-
-static
-int syntaxError(PROLOG_STATE *state)
-{
-    state->handler = error;
-    return XML_ROLE_ERROR;
-}
-
-void XmlPrologStateInit(PROLOG_STATE *state)
-{
-    state->handler = prolog0;
-}
Index: protocols/jabber/xmlrole.h
===================================================================
--- protocols/jabber/xmlrole.h	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,111 +1,0 @@
-/*
-The contents of this file are subject to the Mozilla Public License
-Version 1.1 (the "License"); you may not use this file except in
-compliance with the License. You may obtain a copy of the License at
-http://www.mozilla.org/MPL/
-
-Software distributed under the License is distributed on an "AS IS"
-basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
-License for the specific language governing rights and limitations
-under the License.
-
-The Original Code is expat.
-
-The Initial Developer of the Original Code is James Clark.
-Portions created by James Clark are Copyright (C) 1998, 1999
-James Clark. All Rights Reserved.
-
-Contributor(s):
-
-Alternatively, the contents of this file may be used under the terms
-of the GNU General Public License (the "GPL"), in which case the
-provisions of the GPL are applicable instead of those above.  If you
-wish to allow use of your version of this file only under the terms of
-the GPL and not to allow others to use your version of this file under
-the MPL, indicate your decision by deleting the provisions above and
-replace them with the notice and other provisions required by the
-GPL. If you do not delete the provisions above, a recipient may use
-your version of this file under either the MPL or the GPL.
-*/
-
-#ifndef XmlRole_INCLUDED
-#define XmlRole_INCLUDED 1
-
-#include "xmltok.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-enum {
-  XML_ROLE_ERROR = -1,
-  XML_ROLE_NONE = 0,
-  XML_ROLE_XML_DECL,
-  XML_ROLE_INSTANCE_START,
-  XML_ROLE_DOCTYPE_NAME,
-  XML_ROLE_DOCTYPE_SYSTEM_ID,
-  XML_ROLE_DOCTYPE_PUBLIC_ID,
-  XML_ROLE_DOCTYPE_CLOSE,
-  XML_ROLE_GENERAL_ENTITY_NAME,
-  XML_ROLE_PARAM_ENTITY_NAME,
-  XML_ROLE_ENTITY_VALUE,
-  XML_ROLE_ENTITY_SYSTEM_ID,
-  XML_ROLE_ENTITY_PUBLIC_ID,
-  XML_ROLE_ENTITY_NOTATION_NAME,
-  XML_ROLE_NOTATION_NAME,
-  XML_ROLE_NOTATION_SYSTEM_ID,
-  XML_ROLE_NOTATION_NO_SYSTEM_ID,
-  XML_ROLE_NOTATION_PUBLIC_ID,
-  XML_ROLE_ATTRIBUTE_NAME,
-  XML_ROLE_ATTRIBUTE_TYPE_CDATA,
-  XML_ROLE_ATTRIBUTE_TYPE_ID,
-  XML_ROLE_ATTRIBUTE_TYPE_IDREF,
-  XML_ROLE_ATTRIBUTE_TYPE_IDREFS,
-  XML_ROLE_ATTRIBUTE_TYPE_ENTITY,
-  XML_ROLE_ATTRIBUTE_TYPE_ENTITIES,
-  XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN,
-  XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS,
-  XML_ROLE_ATTRIBUTE_ENUM_VALUE,
-  XML_ROLE_ATTRIBUTE_NOTATION_VALUE,
-  XML_ROLE_ATTLIST_ELEMENT_NAME,
-  XML_ROLE_IMPLIED_ATTRIBUTE_VALUE,
-  XML_ROLE_REQUIRED_ATTRIBUTE_VALUE,
-  XML_ROLE_DEFAULT_ATTRIBUTE_VALUE,
-  XML_ROLE_FIXED_ATTRIBUTE_VALUE,
-  XML_ROLE_ELEMENT_NAME,
-  XML_ROLE_CONTENT_ANY,
-  XML_ROLE_CONTENT_EMPTY,
-  XML_ROLE_CONTENT_PCDATA,
-  XML_ROLE_GROUP_OPEN,
-  XML_ROLE_GROUP_CLOSE,
-  XML_ROLE_GROUP_CLOSE_REP,
-  XML_ROLE_GROUP_CLOSE_OPT,
-  XML_ROLE_GROUP_CLOSE_PLUS,
-  XML_ROLE_GROUP_CHOICE,
-  XML_ROLE_GROUP_SEQUENCE,
-  XML_ROLE_CONTENT_ELEMENT,
-  XML_ROLE_CONTENT_ELEMENT_REP,
-  XML_ROLE_CONTENT_ELEMENT_OPT,
-  XML_ROLE_CONTENT_ELEMENT_PLUS,
-  XML_ROLE_PARAM_ENTITY_REF
-};
-
-typedef struct prolog_state {
-  int (*handler)(struct prolog_state *state,
-	         int tok,
-		 const char *ptr,
-		 const char *end,
-		 const ENCODING *enc);
-  unsigned level;
-} PROLOG_STATE;
-
-void XMLTOKAPI XmlPrologStateInit(PROLOG_STATE *);
-
-#define XmlTokenRole(state, tok, ptr, end, enc) \
- (((state)->handler)(state, tok, ptr, end, enc))
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* not XmlRole_INCLUDED */
Index: protocols/jabber/xmltok.c
===================================================================
--- protocols/jabber/xmltok.c	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,1518 +1,0 @@
-/*
-The contents of this file are subject to the Mozilla Public License
-Version 1.1 (the "License"); you may not use this file except in
-compliance with the License. You may obtain a copy of the License at
-http://www.mozilla.org/MPL/
-
-Software distributed under the License is distributed on an "AS IS"
-basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
-License for the specific language governing rights and limitations
-under the License.
-
-The Original Code is expat.
-
-The Initial Developer of the Original Code is James Clark.
-Portions created by James Clark are Copyright (C) 1998, 1999
-James Clark. All Rights Reserved.
-
-Contributor(s):
-
-*/
-
-#include "xmldef.h"
-#include "xmltok.h"
-#include "nametab.h"
-
-#define VTABLE1 \
-  { PREFIX(prologTok), PREFIX(contentTok), PREFIX(cdataSectionTok) }, \
-  { PREFIX(attributeValueTok), PREFIX(entityValueTok) }, \
-  PREFIX(sameName), \
-  PREFIX(nameMatchesAscii), \
-  PREFIX(nameLength), \
-  PREFIX(skipS), \
-  PREFIX(getAtts), \
-  PREFIX(charRefNumber), \
-  PREFIX(predefinedEntityName), \
-  PREFIX(updatePosition), \
-  PREFIX(isPublicId)
-
-#define VTABLE VTABLE1, PREFIX(toUtf8), PREFIX(toUtf16)
-
-#define UCS2_GET_NAMING(pages, hi, lo) \
-   (namingBitmap[(pages[hi] << 3) + ((lo) >> 5)] & (1 << ((lo) & 0x1F)))
-
-/* A 2 byte UTF-8 representation splits the characters 11 bits
-between the bottom 5 and 6 bits of the bytes.
-We need 8 bits to index into pages, 3 bits to add to that index and
-5 bits to generate the mask. */
-#define UTF8_GET_NAMING2(pages, byte) \
-    (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3) \
-                      + ((((byte)[0]) & 3) << 1) \
-                      + ((((byte)[1]) >> 5) & 1)] \
-         & (1 << (((byte)[1]) & 0x1F)))
-
-/* A 3 byte UTF-8 representation splits the characters 16 bits
-between the bottom 4, 6 and 6 bits of the bytes.
-We need 8 bits to index into pages, 3 bits to add to that index and
-5 bits to generate the mask. */
-#define UTF8_GET_NAMING3(pages, byte) \
-  (namingBitmap[((pages)[((((byte)[0]) & 0xF) << 4) \
-                             + ((((byte)[1]) >> 2) & 0xF)] \
-               << 3) \
-                      + ((((byte)[1]) & 3) << 1) \
-                      + ((((byte)[2]) >> 5) & 1)] \
-         & (1 << (((byte)[2]) & 0x1F)))
-
-#define UTF8_GET_NAMING(pages, p, n) \
-  ((n) == 2 \
-  ? UTF8_GET_NAMING2(pages, (const unsigned char *)(p)) \
-  : ((n) == 3 \
-     ? UTF8_GET_NAMING3(pages, (const unsigned char *)(p)) \
-     : 0))
-
-#define UTF8_INVALID3(p) \
-  ((*p) == 0xED \
-  ? (((p)[1] & 0x20) != 0) \
-  : ((*p) == 0xEF \
-     ? ((p)[1] == 0xBF && ((p)[2] == 0xBF || (p)[2] == 0xBE)) \
-     : 0))
-
-#define UTF8_INVALID4(p) ((*p) == 0xF4 && ((p)[1] & 0x30) != 0)
-
-static
-int isNever(const ENCODING *enc, const char *p)
-{
-    return 0;
-}
-
-static
-int utf8_isName2(const ENCODING *enc, const char *p)
-{
-    return UTF8_GET_NAMING2(namePages, (const unsigned char *)p);
-}
-
-static
-int utf8_isName3(const ENCODING *enc, const char *p)
-{
-    return UTF8_GET_NAMING3(namePages, (const unsigned char *)p);
-}
-
-#define utf8_isName4 isNever
-
-static
-int utf8_isNmstrt2(const ENCODING *enc, const char *p)
-{
-    return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p);
-}
-
-static
-int utf8_isNmstrt3(const ENCODING *enc, const char *p)
-{
-    return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p);
-}
-
-#define utf8_isNmstrt4 isNever
-
-#define utf8_isInvalid2 isNever
-
-static
-int utf8_isInvalid3(const ENCODING *enc, const char *p)
-{
-    return UTF8_INVALID3((const unsigned char *)p);
-}
-
-static
-int utf8_isInvalid4(const ENCODING *enc, const char *p)
-{
-    return UTF8_INVALID4((const unsigned char *)p);
-}
-
-struct normal_encoding {
-    ENCODING enc;
-    unsigned char type[256];
-#ifdef XML_MIN_SIZE
-    int (*byteType)(const ENCODING *, const char *);
-    int (*isNameMin)(const ENCODING *, const char *);
-    int (*isNmstrtMin)(const ENCODING *, const char *);
-    int (*byteToAscii)(const ENCODING *, const char *);
-    int (*charMatches)(const ENCODING *, const char *, int);
-#endif /* XML_MIN_SIZE */
-    int (*isName2)(const ENCODING *, const char *);
-    int (*isName3)(const ENCODING *, const char *);
-    int (*isName4)(const ENCODING *, const char *);
-    int (*isNmstrt2)(const ENCODING *, const char *);
-    int (*isNmstrt3)(const ENCODING *, const char *);
-    int (*isNmstrt4)(const ENCODING *, const char *);
-    int (*isInvalid2)(const ENCODING *, const char *);
-    int (*isInvalid3)(const ENCODING *, const char *);
-    int (*isInvalid4)(const ENCODING *, const char *);
-};
-
-#ifdef XML_MIN_SIZE
-
-#define STANDARD_VTABLE(E) \
- E ## byteType, \
- E ## isNameMin, \
- E ## isNmstrtMin, \
- E ## byteToAscii, \
- E ## charMatches,
-
-#else
-
-#define STANDARD_VTABLE(E) /* as nothing */
-
-#endif
-
-#define NORMAL_VTABLE(E) \
- E ## isName2, \
- E ## isName3, \
- E ## isName4, \
- E ## isNmstrt2, \
- E ## isNmstrt3, \
- E ## isNmstrt4, \
- E ## isInvalid2, \
- E ## isInvalid3, \
- E ## isInvalid4
-
-static int checkCharRefNumber(int);
-
-#include "xmltok_impl.h"
-
-#ifdef XML_MIN_SIZE
-#define sb_isNameMin isNever
-#define sb_isNmstrtMin isNever
-#endif
-
-#ifdef XML_MIN_SIZE
-#define MINBPC(enc) ((enc)->minBytesPerChar)
-#else
-/* minimum bytes per character */
-#define MINBPC(enc) 1
-#endif
-
-#define SB_BYTE_TYPE(enc, p) \
-  (((struct normal_encoding *)(enc))->type[(unsigned char)*(p)])
-
-#ifdef XML_MIN_SIZE
-static
-int sb_byteType(const ENCODING *enc, const char *p)
-{
-    return SB_BYTE_TYPE(enc, p);
-}
-#define BYTE_TYPE(enc, p) \
- (((const struct normal_encoding *)(enc))->byteType(enc, p))
-#else
-#define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p)
-#endif
-
-#ifdef XML_MIN_SIZE
-#define BYTE_TO_ASCII(enc, p) \
- (((const struct normal_encoding *)(enc))->byteToAscii(enc, p))
-static
-int sb_byteToAscii(const ENCODING *enc, const char *p)
-{
-    return *p;
-}
-#else
-#define BYTE_TO_ASCII(enc, p) (*p)
-#endif
-
-#define IS_NAME_CHAR(enc, p, n) \
- (((const struct normal_encoding *)(enc))->isName ## n(enc, p))
-#define IS_NMSTRT_CHAR(enc, p, n) \
- (((const struct normal_encoding *)(enc))->isNmstrt ## n(enc, p))
-#define IS_INVALID_CHAR(enc, p, n) \
- (((const struct normal_encoding *)(enc))->isInvalid ## n(enc, p))
-
-#ifdef XML_MIN_SIZE
-#define IS_NAME_CHAR_MINBPC(enc, p) \
- (((const struct normal_encoding *)(enc))->isNameMin(enc, p))
-#define IS_NMSTRT_CHAR_MINBPC(enc, p) \
- (((const struct normal_encoding *)(enc))->isNmstrtMin(enc, p))
-#else
-#define IS_NAME_CHAR_MINBPC(enc, p) (0)
-#define IS_NMSTRT_CHAR_MINBPC(enc, p) (0)
-#endif
-
-#ifdef XML_MIN_SIZE
-#define CHAR_MATCHES(enc, p, c) \
- (((const struct normal_encoding *)(enc))->charMatches(enc, p, c))
-static
-int sb_charMatches(const ENCODING *enc, const char *p, int c)
-{
-    return *p == c;
-}
-#else
-/* c is an ASCII character */
-#define CHAR_MATCHES(enc, p, c) (*(p) == c)
-#endif
-
-#define PREFIX(ident) normal_ ## ident
-#include "xmltok_impl.c"
-
-#undef MINBPC
-#undef BYTE_TYPE
-#undef BYTE_TO_ASCII
-#undef CHAR_MATCHES
-#undef IS_NAME_CHAR
-#undef IS_NAME_CHAR_MINBPC
-#undef IS_NMSTRT_CHAR
-#undef IS_NMSTRT_CHAR_MINBPC
-#undef IS_INVALID_CHAR
-
-enum {  /* UTF8_cvalN is value of masked first byte of N byte sequence */
-    UTF8_cval1 = 0x00,
-    UTF8_cval2 = 0xc0,
-    UTF8_cval3 = 0xe0,
-    UTF8_cval4 = 0xf0
-};
-
-static
-void utf8_toUtf8(const ENCODING *enc,
-                 const char **fromP, const char *fromLim,
-                 char **toP, const char *toLim)
-{
-    char *to;
-    const char *from;
-    if (fromLim - *fromP > toLim - *toP) {
-        /* Avoid copying partial characters. */
-        for (fromLim = *fromP + (toLim - *toP); fromLim > *fromP; fromLim--)
-            if (((unsigned char)fromLim[-1] & 0xc0) != 0x80)
-                break;
-    }
-    for (to = *toP, from = *fromP; from != fromLim; from++, to++)
-        *to = *from;
-    *fromP = from;
-    *toP = to;
-}
-
-static
-void utf8_toUtf16(const ENCODING *enc,
-                  const char **fromP, const char *fromLim,
-                  unsigned short **toP, const unsigned short *toLim)
-{
-    unsigned short *to = *toP;
-    const char *from = *fromP;
-    while (from != fromLim && to != toLim) {
-        switch (((struct normal_encoding *)enc)->type[(unsigned char)*from]) {
-        case BT_LEAD2:
-            *to++ = ((from[0] & 0x1f) << 6) | (from[1] & 0x3f);
-            from += 2;
-            break;
-        case BT_LEAD3:
-            *to++ = ((from[0] & 0xf) << 12) | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f);
-            from += 3;
-            break;
-        case BT_LEAD4:
-            {
-                unsigned long n;
-                if (to + 1 == toLim)
-                    break;
-                n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12) | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f);
-                n -= 0x10000;
-                to[0] = (unsigned short)((n >> 10) | 0xD800);
-                to[1] = (unsigned short)((n & 0x3FF) | 0xDC00);
-                to += 2;
-                from += 4;
-            }
-            break;
-        default:
-            *to++ = *from++;
-            break;
-        }
-    }
-    *fromP = from;
-    *toP = to;
-}
-
-#ifdef XML_NS
-static const struct normal_encoding utf8_encoding_ns = {
-        { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
-            {
-#include "asciitab.h"
-#include "utf8tab.h"
-            },
-            STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
-        };
-#endif
-
-static const struct normal_encoding utf8_encoding = {
-        { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
-            {
-#define BT_COLON BT_NMSTRT
-#include "asciitab.h"
-#undef BT_COLON
-#include "utf8tab.h"
-            },
-            STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
-        };
-
-#ifdef XML_NS
-
-static const struct normal_encoding internal_utf8_encoding_ns = {
-        { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
-            {
-#include "iasciitab.h"
-#include "utf8tab.h"
-            },
-            STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
-        };
-
-#endif
-
-static const struct normal_encoding internal_utf8_encoding = {
-        { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
-            {
-#define BT_COLON BT_NMSTRT
-#include "iasciitab.h"
-#undef BT_COLON
-#include "utf8tab.h"
-            },
-            STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
-        };
-
-static
-void latin1_toUtf8(const ENCODING *enc,
-                   const char **fromP, const char *fromLim,
-                   char **toP, const char *toLim)
-{
-    for (;;) {
-        unsigned char c;
-        if (*fromP == fromLim)
-            break;
-        c = (unsigned char)**fromP;
-        if (c & 0x80) {
-            if (toLim - *toP < 2)
-                break;
-            *(*toP)++ = ((c >> 6) | UTF8_cval2);
-            *(*toP)++ = ((c & 0x3f) | 0x80);
-            (*fromP)++;
-        }
-        else {
-            if (*toP == toLim)
-                break;
-            *(*toP)++ = *(*fromP)++;
-        }
-    }
-}
-
-static
-void latin1_toUtf16(const ENCODING *enc,
-                    const char **fromP, const char *fromLim,
-                    unsigned short **toP, const unsigned short *toLim)
-{
-    while (*fromP != fromLim && *toP != toLim)
-        *(*toP)++ = (unsigned char)*(*fromP)++;
-}
-
-#ifdef XML_NS
-
-static const struct normal_encoding latin1_encoding_ns = {
-        { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 },
-            {
-#include "asciitab.h"
-#include "latin1tab.h"
-            },
-            STANDARD_VTABLE(sb_)
-        };
-
-#endif
-
-static const struct normal_encoding latin1_encoding = {
-        { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 },
-            {
-#define BT_COLON BT_NMSTRT
-#include "asciitab.h"
-#undef BT_COLON
-#include "latin1tab.h"
-            },
-            STANDARD_VTABLE(sb_)
-        };
-
-static
-void ascii_toUtf8(const ENCODING *enc,
-                  const char **fromP, const char *fromLim,
-                  char **toP, const char *toLim)
-{
-    while (*fromP != fromLim && *toP != toLim)
-        *(*toP)++ = *(*fromP)++;
-}
-
-#ifdef XML_NS
-
-static const struct normal_encoding ascii_encoding_ns = {
-        { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 },
-            {
-#include "asciitab.h"
-                /* BT_NONXML == 0 */
-            },
-            STANDARD_VTABLE(sb_)
-        };
-
-#endif
-
-static const struct normal_encoding ascii_encoding = {
-        { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 },
-            {
-#define BT_COLON BT_NMSTRT
-#include "asciitab.h"
-#undef BT_COLON
-                /* BT_NONXML == 0 */
-            },
-            STANDARD_VTABLE(sb_)
-        };
-
-static int unicode_byte_type(char hi, char lo)
-{
-    switch ((unsigned char)hi) {
-case 0xD8: case 0xD9: case 0xDA: case 0xDB:
-        return BT_LEAD4;
-case 0xDC: case 0xDD: case 0xDE: case 0xDF:
-        return BT_TRAIL;
-    case 0xFF:
-        switch ((unsigned char)lo) {
-        case 0xFF:
-        case 0xFE:
-            return BT_NONXML;
-        }
-        break;
-    }
-    return BT_NONASCII;
-}
-
-#define DEFINE_UTF16_TO_UTF8(E) \
-static \
-void E ## toUtf8(const ENCODING *enc, \
-         const char **fromP, const char *fromLim, \
-         char **toP, const char *toLim) \
-{ \
-  const char *from; \
-  for (from = *fromP; from != fromLim; from += 2) { \
-    int plane; \
-    unsigned char lo2; \
-    unsigned char lo = GET_LO(from); \
-    unsigned char hi = GET_HI(from); \
-    switch (hi) { \
-    case 0: \
-      if (lo < 0x80) { \
-        if (*toP == toLim) { \
-          *fromP = from; \
-      return; \
-        } \
-        *(*toP)++ = lo; \
-        break; \
-      } \
-      /* fall through */ \
-    case 0x1: case 0x2: case 0x3: \
-    case 0x4: case 0x5: case 0x6: case 0x7: \
-      if (toLim -  *toP < 2) { \
-        *fromP = from; \
-    return; \
-      } \
-      *(*toP)++ = ((lo >> 6) | (hi << 2) |  UTF8_cval2); \
-      *(*toP)++ = ((lo & 0x3f) | 0x80); \
-      break; \
-    default: \
-      if (toLim -  *toP < 3)  { \
-        *fromP = from; \
-    return; \
-      } \
-      /* 16 bits divided 4, 6, 6 amongst 3 bytes */ \
-      *(*toP)++ = ((hi >> 4) | UTF8_cval3); \
-      *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80); \
-      *(*toP)++ = ((lo & 0x3f) | 0x80); \
-      break; \
-    case 0xD8: case 0xD9: case 0xDA: case 0xDB: \
-      if (toLim -  *toP < 4) { \
-    *fromP = from; \
-    return; \
-      } \
-      plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1; \
-      *(*toP)++ = ((plane >> 2) | UTF8_cval4); \
-      *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80); \
-      from += 2; \
-      lo2 = GET_LO(from); \
-      *(*toP)++ = (((lo & 0x3) << 4) \
-               | ((GET_HI(from) & 0x3) << 2) \
-           | (lo2 >> 6) \
-           | 0x80); \
-      *(*toP)++ = ((lo2 & 0x3f) | 0x80); \
-      break; \
-    } \
-  } \
-  *fromP = from; \
-}
-
-#define DEFINE_UTF16_TO_UTF16(E) \
-static \
-void E ## toUtf16(const ENCODING *enc, \
-          const char **fromP, const char *fromLim, \
-          unsigned short **toP, const unsigned short *toLim) \
-{ \
-  /* Avoid copying first half only of surrogate */ \
-  if (fromLim - *fromP > ((toLim - *toP) << 1) \
-      && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) \
-    fromLim -= 2; \
-  for (; *fromP != fromLim && *toP != toLim; *fromP += 2) \
-    *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP); \
-}
-
-#define SET2(ptr, ch) \
-  (((ptr)[0] = ((ch) & 0xff)), ((ptr)[1] = ((ch) >> 8)))
-#define GET_LO(ptr) ((unsigned char)(ptr)[0])
-#define GET_HI(ptr) ((unsigned char)(ptr)[1])
-
-DEFINE_UTF16_TO_UTF8(little2_)
-DEFINE_UTF16_TO_UTF16(little2_)
-
-#undef SET2
-#undef GET_LO
-#undef GET_HI
-
-#define SET2(ptr, ch) \
-  (((ptr)[0] = ((ch) >> 8)), ((ptr)[1] = ((ch) & 0xFF)))
-#define GET_LO(ptr) ((unsigned char)(ptr)[1])
-#define GET_HI(ptr) ((unsigned char)(ptr)[0])
-
-DEFINE_UTF16_TO_UTF8(big2_)
-DEFINE_UTF16_TO_UTF16(big2_)
-
-#undef SET2
-#undef GET_LO
-#undef GET_HI
-
-#define LITTLE2_BYTE_TYPE(enc, p) \
- ((p)[1] == 0 \
-  ? ((struct normal_encoding *)(enc))->type[(unsigned char)*(p)] \
-  : unicode_byte_type((p)[1], (p)[0]))
-#define LITTLE2_BYTE_TO_ASCII(enc, p) ((p)[1] == 0 ? (p)[0] : -1)
-#define LITTLE2_CHAR_MATCHES(enc, p, c) ((p)[1] == 0 && (p)[0] == c)
-#define LITTLE2_IS_NAME_CHAR_MINBPC(enc, p) \
-  UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0])
-#define LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p) \
-  UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[1], (unsigned char)p[0])
-
-#ifdef XML_MIN_SIZE
-
-static
-int little2_byteType(const ENCODING *enc, const char *p)
-{
-    return LITTLE2_BYTE_TYPE(enc, p);
-}
-
-static
-int little2_byteToAscii(const ENCODING *enc, const char *p)
-{
-    return LITTLE2_BYTE_TO_ASCII(enc, p);
-}
-
-static
-int little2_charMatches(const ENCODING *enc, const char *p, int c)
-{
-    return LITTLE2_CHAR_MATCHES(enc, p, c);
-}
-
-static
-int little2_isNameMin(const ENCODING *enc, const char *p)
-{
-    return LITTLE2_IS_NAME_CHAR_MINBPC(enc, p);
-}
-
-static
-int little2_isNmstrtMin(const ENCODING *enc, const char *p)
-{
-    return LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p);
-}
-
-#undef VTABLE
-#define VTABLE VTABLE1, little2_toUtf8, little2_toUtf16
-
-#else /* not XML_MIN_SIZE */
-
-#undef PREFIX
-#define PREFIX(ident) little2_ ## ident
-#define MINBPC(enc) 2
-/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
-#define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p)
-#define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(enc, p) 
-#define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(enc, p, c)
-#define IS_NAME_CHAR(enc, p, n) 0
-#define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(enc, p)
-#define IS_NMSTRT_CHAR(enc, p, n) (0)
-#define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p)
-
-#include "xmltok_impl.c"
-
-#undef MINBPC
-#undef BYTE_TYPE
-#undef BYTE_TO_ASCII
-#undef CHAR_MATCHES
-#undef IS_NAME_CHAR
-#undef IS_NAME_CHAR_MINBPC
-#undef IS_NMSTRT_CHAR
-#undef IS_NMSTRT_CHAR_MINBPC
-#undef IS_INVALID_CHAR
-
-#endif /* not XML_MIN_SIZE */
-
-#ifdef XML_NS
-
-static const struct normal_encoding little2_encoding_ns = {
-            { VTABLE, 2, 0,
-#if XML_BYTE_ORDER == 12
-                1
-#else
-0
-#endif
-            },
-            {
-#include "asciitab.h"
-#include "latin1tab.h"
-            },
-            STANDARD_VTABLE(little2_)
-        };
-
-#endif
-
-static const struct normal_encoding little2_encoding = {
-            { VTABLE, 2, 0,
-#if XML_BYTE_ORDER == 12
-                1
-#else
-                0
-#endif
-            },
-            {
-#define BT_COLON BT_NMSTRT
-#include "asciitab.h"
-#undef BT_COLON
-#include "latin1tab.h"
-            },
-            STANDARD_VTABLE(little2_)
-        };
-
-#if XML_BYTE_ORDER != 21
-
-#ifdef XML_NS
-
-static const struct normal_encoding internal_little2_encoding_ns = {
-        { VTABLE, 2, 0, 1 },
-            {
-#include "iasciitab.h"
-#include "latin1tab.h"
-            },
-            STANDARD_VTABLE(little2_)
-        };
-
-#endif
-
-static const struct normal_encoding internal_little2_encoding = {
-        { VTABLE, 2, 0, 1 },
-            {
-#define BT_COLON BT_NMSTRT
-#include "iasciitab.h"
-#undef BT_COLON
-#include "latin1tab.h"
-            },
-            STANDARD_VTABLE(little2_)
-        };
-
-#endif
-
-
-#define BIG2_BYTE_TYPE(enc, p) \
- ((p)[0] == 0 \
-  ? ((struct normal_encoding *)(enc))->type[(unsigned char)(p)[1]] \
-  : unicode_byte_type((p)[0], (p)[1]))
-#define BIG2_BYTE_TO_ASCII(enc, p) ((p)[0] == 0 ? (p)[1] : -1)
-#define BIG2_CHAR_MATCHES(enc, p, c) ((p)[0] == 0 && (p)[1] == c)
-#define BIG2_IS_NAME_CHAR_MINBPC(enc, p) \
-  UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1])
-#define BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p) \
-  UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[0], (unsigned char)p[1])
-
-#ifdef XML_MIN_SIZE
-
-static
-int big2_byteType(const ENCODING *enc, const char *p)
-{
-    return BIG2_BYTE_TYPE(enc, p);
-}
-
-static
-int big2_byteToAscii(const ENCODING *enc, const char *p)
-{
-    return BIG2_BYTE_TO_ASCII(enc, p);
-}
-
-static
-int big2_charMatches(const ENCODING *enc, const char *p, int c)
-{
-    return BIG2_CHAR_MATCHES(enc, p, c);
-}
-
-static
-int big2_isNameMin(const ENCODING *enc, const char *p)
-{
-    return BIG2_IS_NAME_CHAR_MINBPC(enc, p);
-}
-
-static
-int big2_isNmstrtMin(const ENCODING *enc, const char *p)
-{
-    return BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p);
-}
-
-#undef VTABLE
-#define VTABLE VTABLE1, big2_toUtf8, big2_toUtf16
-
-#else /* not XML_MIN_SIZE */
-
-#undef PREFIX
-#define PREFIX(ident) big2_ ## ident
-#define MINBPC(enc) 2
-/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
-#define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p)
-#define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(enc, p) 
-#define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(enc, p, c)
-#define IS_NAME_CHAR(enc, p, n) 0
-#define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(enc, p)
-#define IS_NMSTRT_CHAR(enc, p, n) (0)
-#define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p)
-
-#include "xmltok_impl.c"
-
-#undef MINBPC
-#undef BYTE_TYPE
-#undef BYTE_TO_ASCII
-#undef CHAR_MATCHES
-#undef IS_NAME_CHAR
-#undef IS_NAME_CHAR_MINBPC
-#undef IS_NMSTRT_CHAR
-#undef IS_NMSTRT_CHAR_MINBPC
-#undef IS_INVALID_CHAR
-
-#endif /* not XML_MIN_SIZE */
-
-#ifdef XML_NS
-
-static const struct normal_encoding big2_encoding_ns = {
-            { VTABLE, 2, 0,
-#if XML_BYTE_ORDER == 21
-                1
-#else
-0
-#endif
-            },
-            {
-#include "asciitab.h"
-#include "latin1tab.h"
-            },
-            STANDARD_VTABLE(big2_)
-        };
-
-#endif
-
-static const struct normal_encoding big2_encoding = {
-            { VTABLE, 2, 0,
-#if XML_BYTE_ORDER == 21
-                1
-#else
-                0
-#endif
-            },
-            {
-#define BT_COLON BT_NMSTRT
-#include "asciitab.h"
-#undef BT_COLON
-#include "latin1tab.h"
-            },
-            STANDARD_VTABLE(big2_)
-        };
-
-#if XML_BYTE_ORDER != 12
-
-#ifdef XML_NS
-
-static const struct normal_encoding internal_big2_encoding_ns = {
-        { VTABLE, 2, 0, 1 },
-            {
-#include "iasciitab.h"
-#include "latin1tab.h"
-            },
-            STANDARD_VTABLE(big2_)
-        };
-
-#endif
-
-static const struct normal_encoding internal_big2_encoding = {
-        { VTABLE, 2, 0, 1 },
-            {
-#define BT_COLON BT_NMSTRT
-#include "iasciitab.h"
-#undef BT_COLON
-#include "latin1tab.h"
-            },
-            STANDARD_VTABLE(big2_)
-        };
-
-#endif
-
-#undef PREFIX
-
-static
-int streqci(const char *s1, const char *s2)
-{
-    for (;;) {
-        char c1 = *s1++;
-        char c2 = *s2++;
-        if ('a' <= c1 && c1 <= 'z')
-            c1 += 'A' - 'a';
-        if ('a' <= c2 && c2 <= 'z')
-            c2 += 'A' - 'a';
-        if (c1 != c2)
-            return 0;
-        if (!c1)
-            break;
-    }
-    return 1;
-}
-
-static
-void initUpdatePosition(const ENCODING *enc, const char *ptr,
-                        const char *end, POSITION *pos)
-{
-    normal_updatePosition(&utf8_encoding.enc, ptr, end, pos);
-}
-
-static
-int toAscii(const ENCODING *enc, const char *ptr, const char *end)
-{
-    char buf[1];
-    char *p = buf;
-    XmlUtf8Convert(enc, &ptr, end, &p, p + 1);
-    if (p == buf)
-        return -1;
-    else
-        return buf[0];
-}
-
-static
-int isSpace(int c)
-{
-    switch (c) {
-    case 0x20:
-    case 0xD:
-    case 0xA:
-    case 0x9:
-        return 1;
-    }
-    return 0;
-}
-
-/* Return 1 if there's just optional white space
-or there's an S followed by name=val. */
-static
-int parsePseudoAttribute(const ENCODING *enc,
-                         const char *ptr,
-                         const char *end,
-                         const char **namePtr,
-                         const char **valPtr,
-                         const char **nextTokPtr)
-{
-    int c;
-    char open;
-    if (ptr == end) {
-        *namePtr = 0;
-        return 1;
-    }
-    if (!isSpace(toAscii(enc, ptr, end))) {
-        *nextTokPtr = ptr;
-        return 0;
-    }
-    do {
-        ptr += enc->minBytesPerChar;
-    } while (isSpace(toAscii(enc, ptr, end)));
-    if (ptr == end) {
-        *namePtr = 0;
-        return 1;
-    }
-    *namePtr = ptr;
-    for (;;) {
-        c = toAscii(enc, ptr, end);
-        if (c == -1) {
-            *nextTokPtr = ptr;
-            return 0;
-        }
-        if (c == '=')
-            break;
-        if (isSpace(c)) {
-            do {
-                ptr += enc->minBytesPerChar;
-            } while (isSpace(c = toAscii(enc, ptr, end)));
-            if (c != '=') {
-                *nextTokPtr = ptr;
-                return 0;
-            }
-            break;
-        }
-        ptr += enc->minBytesPerChar;
-    }
-    if (ptr == *namePtr) {
-        *nextTokPtr = ptr;
-        return 0;
-    }
-    ptr += enc->minBytesPerChar;
-    c = toAscii(enc, ptr, end);
-    while (isSpace(c)) {
-        ptr += enc->minBytesPerChar;
-        c = toAscii(enc, ptr, end);
-    }
-    if (c != '"' && c != '\'') {
-        *nextTokPtr = ptr;
-        return 0;
-    }
-    open = c;
-    ptr += enc->minBytesPerChar;
-    *valPtr = ptr;
-    for (;; ptr += enc->minBytesPerChar) {
-        c = toAscii(enc, ptr, end);
-        if (c == open)
-            break;
-        if (!('a' <= c && c <= 'z')
-                && !('A' <= c && c <= 'Z')
-                && !('0' <= c && c <= '9')
-                && c != '.'
-                && c != '-'
-                && c != '_') {
-            *nextTokPtr = ptr;
-            return 0;
-        }
-    }
-    *nextTokPtr = ptr + enc->minBytesPerChar;
-    return 1;
-}
-
-static
-int doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *,
-                   const char *,
-                   const char *),
-                   int isGeneralTextEntity,
-                   const ENCODING *enc,
-                   const char *ptr,
-                   const char *end,
-                   const char **badPtr,
-                   const char **versionPtr,
-                   const char **encodingName,
-                   const ENCODING **encoding,
-                   int *standalone)
-{
-    const char *val = 0;
-    const char *name = 0;
-    ptr += 5 * enc->minBytesPerChar;
-    end -= 2 * enc->minBytesPerChar;
-    if (!parsePseudoAttribute(enc, ptr, end, &name, &val, &ptr) || !name) {
-        *badPtr = ptr;
-        return 0;
-    }
-    if (!XmlNameMatchesAscii(enc, name, "version")) {
-        if (!isGeneralTextEntity) {
-            *badPtr = name;
-            return 0;
-        }
-    }
-    else {
-        if (versionPtr)
-            *versionPtr = val;
-        if (!parsePseudoAttribute(enc, ptr, end, &name, &val, &ptr)) {
-            *badPtr = ptr;
-            return 0;
-        }
-        if (!name) {
-            if (isGeneralTextEntity) {
-                /* a TextDecl must have an EncodingDecl */
-                *badPtr = ptr;
-                return 0;
-            }
-            return 1;
-        }
-    }
-    if (XmlNameMatchesAscii(enc, name, "encoding")) {
-        int c = toAscii(enc, val, end);
-        if (!('a' <= c && c <= 'z') && !('A' <= c && c <= 'Z')) {
-            *badPtr = val;
-            return 0;
-        }
-        if (encodingName)
-            *encodingName = val;
-        if (encoding)
-            *encoding = encodingFinder(enc, val, ptr - enc->minBytesPerChar);
-        if (!parsePseudoAttribute(enc, ptr, end, &name, &val, &ptr)) {
-            *badPtr = ptr;
-            return 0;
-        }
-        if (!name)
-            return 1;
-    }
-    if (!XmlNameMatchesAscii(enc, name, "standalone") || isGeneralTextEntity) {
-        *badPtr = name;
-        return 0;
-    }
-    if (XmlNameMatchesAscii(enc, val, "yes")) {
-        if (standalone)
-            *standalone = 1;
-    }
-    else if (XmlNameMatchesAscii(enc, val, "no")) {
-        if (standalone)
-            *standalone = 0;
-    }
-    else {
-        *badPtr = val;
-        return 0;
-    }
-    while (isSpace(toAscii(enc, ptr, end)))
-        ptr += enc->minBytesPerChar;
-    if (ptr != end) {
-        *badPtr = ptr;
-        return 0;
-    }
-    return 1;
-}
-
-static
-int checkCharRefNumber(int result)
-{
-    switch (result >> 8) {
-case 0xD8: case 0xD9: case 0xDA: case 0xDB:
-case 0xDC: case 0xDD: case 0xDE: case 0xDF:
-        return -1;
-    case 0:
-        if (latin1_encoding.type[result] == BT_NONXML)
-            return -1;
-        break;
-    case 0xFF:
-        if (result == 0xFFFE || result == 0xFFFF)
-            return -1;
-        break;
-    }
-    return result;
-}
-
-int XmlUtf8Encode(int c, char *buf)
-{
-    enum {
-        /* minN is minimum legal resulting value for N byte sequence */
-        min2 = 0x80,
-        min3 = 0x800,
-        min4 = 0x10000
-    };
-
-    if (c < 0)
-        return 0;
-    if (c < min2) {
-        buf[0] = (c | UTF8_cval1);
-        return 1;
-    }
-    if (c < min3) {
-        buf[0] = ((c >> 6) | UTF8_cval2);
-        buf[1] = ((c & 0x3f) | 0x80);
-        return 2;
-    }
-    if (c < min4) {
-        buf[0] = ((c >> 12) | UTF8_cval3);
-        buf[1] = (((c >> 6) & 0x3f) | 0x80);
-        buf[2] = ((c & 0x3f) | 0x80);
-        return 3;
-    }
-    if (c < 0x110000) {
-        buf[0] = ((c >> 18) | UTF8_cval4);
-        buf[1] = (((c >> 12) & 0x3f) | 0x80);
-        buf[2] = (((c >> 6) & 0x3f) | 0x80);
-        buf[3] = ((c & 0x3f) | 0x80);
-        return 4;
-    }
-    return 0;
-}
-
-int XmlUtf16Encode(int charNum, unsigned short *buf)
-{
-    if (charNum < 0)
-        return 0;
-    if (charNum < 0x10000) {
-        buf[0] = charNum;
-        return 1;
-    }
-    if (charNum < 0x110000) {
-        charNum -= 0x10000;
-        buf[0] = (charNum >> 10) + 0xD800;
-        buf[1] = (charNum & 0x3FF) + 0xDC00;
-        return 2;
-    }
-    return 0;
-}
-
-struct unknown_encoding {
-    struct normal_encoding normal;
-    int (*convert)(void *userData, const char *p);
-    void *userData;
-    unsigned short utf16[256];
-    char utf8[256][4];
-};
-
-int XmlSizeOfUnknownEncoding()
-{
-    return sizeof(struct unknown_encoding);
-}
-
-static
-int unknown_isName(const ENCODING *enc, const char *p)
-{
-    int c = ((const struct unknown_encoding *)enc)
-            ->convert(((const struct unknown_encoding *)enc)->userData, p);
-    if (c & ~0xFFFF)
-        return 0;
-    return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF);
-}
-
-static
-int unknown_isNmstrt(const ENCODING *enc, const char *p)
-{
-    int c = ((const struct unknown_encoding *)enc)
-            ->convert(((const struct unknown_encoding *)enc)->userData, p);
-    if (c & ~0xFFFF)
-        return 0;
-    return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF);
-}
-
-static
-int unknown_isInvalid(const ENCODING *enc, const char *p)
-{
-    int c = ((const struct unknown_encoding *)enc)
-            ->convert(((const struct unknown_encoding *)enc)->userData, p);
-    return (c & ~0xFFFF) || checkCharRefNumber(c) < 0;
-}
-
-static
-void unknown_toUtf8(const ENCODING *enc,
-                    const char **fromP, const char *fromLim,
-                    char **toP, const char *toLim)
-{
-    char buf[XML_UTF8_ENCODE_MAX];
-    for (;;) {
-        const char *utf8;
-        int n;
-        if (*fromP == fromLim)
-            break;
-        utf8 = ((const struct unknown_encoding *)enc)->utf8[(unsigned char)**fromP];
-        n = *utf8++;
-        if (n == 0) {
-            int c = ((const struct unknown_encoding *)enc)
-                    ->convert(((const struct unknown_encoding *)enc)->userData, *fromP);
-            n = XmlUtf8Encode(c, buf);
-            if (n > toLim - *toP)
-                break;
-            utf8 = buf;
-            *fromP += ((const struct normal_encoding *)enc)->type[(unsigned char)**fromP]
-                      - (BT_LEAD2 - 2);
-        }
-        else {
-            if (n > toLim - *toP)
-                break;
-            (*fromP)++;
-        }
-        do {
-            *(*toP)++ = *utf8++;
-        } while (--n != 0);
-    }
-}
-
-static
-void unknown_toUtf16(const ENCODING *enc,
-                     const char **fromP, const char *fromLim,
-                     unsigned short **toP, const unsigned short *toLim)
-{
-    while (*fromP != fromLim && *toP != toLim) {
-        unsigned short c
-        = ((const struct unknown_encoding *)enc)->utf16[(unsigned char)**fromP];
-        if (c == 0) {
-            c = (unsigned short)((const struct unknown_encoding *)enc)
-                ->convert(((const struct unknown_encoding *)enc)->userData, *fromP);
-            *fromP += ((const struct normal_encoding *)enc)->type[(unsigned char)**fromP]
-                      - (BT_LEAD2 - 2);
-        }
-        else
-            (*fromP)++;
-        *(*toP)++ = c;
-    }
-}
-
-ENCODING *
-XmlInitUnknownEncoding(void *mem,
-                       int *table,
-                       int (*convert)(void *userData, const char *p),
-                       void *userData)
-{
-    int i;
-    struct unknown_encoding *e = mem;
-    for (i = 0; i < sizeof(struct normal_encoding); i++)
-        ((char *)mem)[i] = ((char *)&latin1_encoding)[i];
-    for (i = 0; i < 128; i++)
-        if (latin1_encoding.type[i] != BT_OTHER
-                && latin1_encoding.type[i] != BT_NONXML
-                && table[i] != i)
-            return 0;
-    for (i = 0; i < 256; i++) {
-        int c = table[i];
-        if (c == -1) {
-            e->normal.type[i] = BT_MALFORM;
-            /* This shouldn't really get used. */
-            e->utf16[i] = 0xFFFF;
-            e->utf8[i][0] = 1;
-            e->utf8[i][1] = 0;
-        }
-        else if (c < 0) {
-            if (c < -4)
-                return 0;
-            e->normal.type[i] = BT_LEAD2 - (c + 2);
-            e->utf8[i][0] = 0;
-            e->utf16[i] = 0;
-        }
-        else if (c < 0x80) {
-            if (latin1_encoding.type[c] != BT_OTHER
-                    && latin1_encoding.type[c] != BT_NONXML
-                    && c != i)
-                return 0;
-            e->normal.type[i] = latin1_encoding.type[c];
-            e->utf8[i][0] = 1;
-            e->utf8[i][1] = (char)c;
-            e->utf16[i] = c == 0 ? 0xFFFF : c;
-        }
-        else if (checkCharRefNumber(c) < 0) {
-            e->normal.type[i] = BT_NONXML;
-            /* This shouldn't really get used. */
-            e->utf16[i] = 0xFFFF;
-            e->utf8[i][0] = 1;
-            e->utf8[i][1] = 0;
-        }
-        else {
-            if (c > 0xFFFF)
-                return 0;
-            if (UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xff))
-                e->normal.type[i] = BT_NMSTRT;
-            else if (UCS2_GET_NAMING(namePages, c >> 8, c & 0xff))
-                e->normal.type[i] = BT_NAME;
-            else
-                e->normal.type[i] = BT_OTHER;
-            e->utf8[i][0] = (char)XmlUtf8Encode(c, e->utf8[i] + 1);
-            e->utf16[i] = c;
-        }
-    }
-    e->userData = userData;
-    e->convert = convert;
-    if (convert) {
-        e->normal.isName2 = unknown_isName;
-        e->normal.isName3 = unknown_isName;
-        e->normal.isName4 = unknown_isName;
-        e->normal.isNmstrt2 = unknown_isNmstrt;
-        e->normal.isNmstrt3 = unknown_isNmstrt;
-        e->normal.isNmstrt4 = unknown_isNmstrt;
-        e->normal.isInvalid2 = unknown_isInvalid;
-        e->normal.isInvalid3 = unknown_isInvalid;
-        e->normal.isInvalid4 = unknown_isInvalid;
-    }
-    e->normal.enc.utf8Convert = unknown_toUtf8;
-    e->normal.enc.utf16Convert = unknown_toUtf16;
-    return &(e->normal.enc);
-}
-
-/* If this enumeration is changed, getEncodingIndex and encodings
-must also be changed. */
-enum {
-    UNKNOWN_ENC = -1,
-    ISO_8859_1_ENC = 0,
-    US_ASCII_ENC,
-    UTF_8_ENC,
-    UTF_16_ENC,
-    UTF_16BE_ENC,
-    UTF_16LE_ENC,
-    /* must match encodingNames up to here */
-    NO_ENC
-};
-
-static
-int getEncodingIndex(const char *name)
-{
-    static const char *encodingNames[] = {
-        "ISO-8859-1",
-        "US-ASCII",
-        "UTF-8",
-        "UTF-16",
-        "UTF-16BE"
-        "UTF-16LE",
-    };
-    int i;
-    if (name == 0)
-        return NO_ENC;
-    for (i = 0; i < sizeof(encodingNames)/sizeof(encodingNames[0]); i++)
-        if (streqci(name, encodingNames[i]))
-            return i;
-    return UNKNOWN_ENC;
-}
-
-/* For binary compatibility, we store the index of the encoding specified
-at initialization in the isUtf16 member. */
-
-#define INIT_ENC_INDEX(enc) ((enc)->initEnc.isUtf16)
-
-/* This is what detects the encoding.
-encodingTable maps from encoding indices to encodings;
-INIT_ENC_INDEX(enc) is the index of the external (protocol) specified encoding;
-state is XML_CONTENT_STATE if we're parsing an external text entity,
-and XML_PROLOG_STATE otherwise.
-*/
-
-
-static
-int initScan(const ENCODING **encodingTable,
-             const INIT_ENCODING *enc,
-             int state,
-             const char *ptr,
-             const char *end,
-             const char **nextTokPtr)
-{
-    const ENCODING **encPtr;
-
-    if (ptr == end)
-        return XML_TOK_NONE;
-    encPtr = enc->encPtr;
-    if (ptr + 1 == end) {
-        /* only a single byte available for auto-detection */
-        /* a well-formed document entity must have more than one byte */
-        if (state != XML_CONTENT_STATE)
-            return XML_TOK_PARTIAL;
-        /* so we're parsing an external text entity... */
-        /* if UTF-16 was externally specified, then we need at least 2 bytes */
-        switch (INIT_ENC_INDEX(enc)) {
-        case UTF_16_ENC:
-        case UTF_16LE_ENC:
-        case UTF_16BE_ENC:
-            return XML_TOK_PARTIAL;
-        }
-        switch ((unsigned char)*ptr) {
-        case 0xFE:
-        case 0xFF:
-        case 0xEF: /* possibly first byte of UTF-8 BOM */
-            if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
-                    && state == XML_CONTENT_STATE)
-                break;
-            /* fall through */
-        case 0x00:
-        case 0x3C:
-            return XML_TOK_PARTIAL;
-        }
-    }
-    else {
-        switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) {
-        case 0xFEFF:
-            if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
-                    && state == XML_CONTENT_STATE)
-                break;
-            *nextTokPtr = ptr + 2;
-            *encPtr = encodingTable[UTF_16BE_ENC];
-            return XML_TOK_BOM;
-            /* 00 3C is handled in the default case */
-        case 0x3C00:
-            if ((INIT_ENC_INDEX(enc) == UTF_16BE_ENC
-                    || INIT_ENC_INDEX(enc) == UTF_16_ENC)
-                    && state == XML_CONTENT_STATE)
-                break;
-            *encPtr = encodingTable[UTF_16LE_ENC];
-            return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
-        case 0xFFFE:
-            if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
-                    && state == XML_CONTENT_STATE)
-                break;
-            *nextTokPtr = ptr + 2;
-            *encPtr = encodingTable[UTF_16LE_ENC];
-            return XML_TOK_BOM;
-        case 0xEFBB:
-            /* Maybe a UTF-8 BOM (EF BB BF) */
-            /* If there's an explicitly specified (external) encoding
-               of ISO-8859-1 or some flavour of UTF-16
-               and this is an external text entity,
-            don't look for the BOM,
-               because it might be a legal data. */
-            if (state == XML_CONTENT_STATE) {
-                int e = INIT_ENC_INDEX(enc);
-                if (e == ISO_8859_1_ENC || e == UTF_16BE_ENC || e == UTF_16LE_ENC || e == UTF_16_ENC)
-                    break;
-            }
-            if (ptr + 2 == end)
-                return XML_TOK_PARTIAL;
-            if ((unsigned char)ptr[2] == 0xBF) {
-                *encPtr = encodingTable[UTF_8_ENC];
-                return XML_TOK_BOM;
-            }
-            break;
-        default:
-            if (ptr[0] == '\0') {
-                /* 0 isn't a legal data character. Furthermore a document entity can only
-                   start with ASCII characters.  So the only way this can fail to be big-endian
-                   UTF-16 if it it's an external parsed general entity that's labelled as
-                   UTF-16LE. */
-                if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC)
-                    break;
-                *encPtr = encodingTable[UTF_16BE_ENC];
-                return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
-            }
-            else if (ptr[1] == '\0') {
-                /* We could recover here in the case:
-                    - parsing an external entity
-                    - second byte is 0
-                    - no externally specified encoding
-                    - no encoding declaration
-                   by assuming UTF-16LE.  But we don't, because this would mean when
-                   presented just with a single byte, we couldn't reliably determine
-                   whether we needed further bytes. */
-                if (state == XML_CONTENT_STATE)
-                    break;
-                *encPtr = encodingTable[UTF_16LE_ENC];
-                return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
-            }
-            break;
-        }
-    }
-    *encPtr = encodingTable[(int)INIT_ENC_INDEX(enc)];
-    return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
-}
-
-
-#define NS(x) x
-#define ns(x) x
-#include "xmltok_ns.c"
-#undef NS
-#undef ns
-
-#ifdef XML_NS
-
-#define NS(x) x ## NS
-#define ns(x) x ## _ns
-
-#include "xmltok_ns.c"
-
-#undef NS
-#undef ns
-
-ENCODING *
-XmlInitUnknownEncodingNS(void *mem,
-                         int *table,
-                         int (*convert)(void *userData, const char *p),
-                         void *userData)
-{
-    ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData);
-    if (enc)
-        ((struct normal_encoding *)enc)->type[':'] = BT_COLON;
-    return enc;
-}
-
-#endif /* XML_NS */
Index: protocols/jabber/xmltok.h
===================================================================
--- protocols/jabber/xmltok.h	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,307 +1,0 @@
-/*
-The contents of this file are subject to the Mozilla Public License
-Version 1.1 (the "License"); you may not use this file except in
-compliance with the License. You may obtain a copy of the License at
-http://www.mozilla.org/MPL/
-
-Software distributed under the License is distributed on an "AS IS"
-basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
-License for the specific language governing rights and limitations
-under the License.
-
-The Original Code is expat.
-
-The Initial Developer of the Original Code is James Clark.
-Portions created by James Clark are Copyright (C) 1998, 1999
-James Clark. All Rights Reserved.
-
-Contributor(s):
-
-Alternatively, the contents of this file may be used under the terms
-of the GNU General Public License (the "GPL"), in which case the
-provisions of the GPL are applicable instead of those above.  If you
-wish to allow use of your version of this file only under the terms of
-the GPL and not to allow others to use your version of this file under
-the MPL, indicate your decision by deleting the provisions above and
-replace them with the notice and other provisions required by the
-GPL. If you do not delete the provisions above, a recipient may use
-your version of this file under either the MPL or the GPL.
-*/
-
-#ifndef XmlTok_INCLUDED
-#define XmlTok_INCLUDED 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef XMLTOKAPI
-#define XMLTOKAPI /* as nothing */
-#endif
-
-/* The following token may be returned by XmlContentTok */
-#define XML_TOK_TRAILING_RSQB -5 /* ] or ]] at the end of the scan; might be start of
-                                    illegal ]]> sequence */
-/* The following tokens may be returned by both XmlPrologTok and XmlContentTok */
-#define XML_TOK_NONE -4    /* The string to be scanned is empty */
-#define XML_TOK_TRAILING_CR -3 /* A CR at the end of the scan;
-                                  might be part of CRLF sequence */ 
-#define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */
-#define XML_TOK_PARTIAL -1 /* only part of a token */
-#define XML_TOK_INVALID 0
-
-/* The following tokens are returned by XmlContentTok; some are also
-  returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok */
-
-#define XML_TOK_START_TAG_WITH_ATTS 1
-#define XML_TOK_START_TAG_NO_ATTS 2
-#define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag <e/> */
-#define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4
-#define XML_TOK_END_TAG 5
-#define XML_TOK_DATA_CHARS 6
-#define XML_TOK_DATA_NEWLINE 7
-#define XML_TOK_CDATA_SECT_OPEN 8
-#define XML_TOK_ENTITY_REF 9
-#define XML_TOK_CHAR_REF 10     /* numeric character reference */
-
-/* The following tokens may be returned by both XmlPrologTok and XmlContentTok */
-#define XML_TOK_PI 11      /* processing instruction */
-#define XML_TOK_XML_DECL 12 /* XML decl or text decl */
-#define XML_TOK_COMMENT 13
-#define XML_TOK_BOM 14     /* Byte order mark */
-
-/* The following tokens are returned only by XmlPrologTok */
-#define XML_TOK_PROLOG_S 15
-#define XML_TOK_DECL_OPEN 16 /* <!foo */
-#define XML_TOK_DECL_CLOSE 17 /* > */
-#define XML_TOK_NAME 18
-#define XML_TOK_NMTOKEN 19
-#define XML_TOK_POUND_NAME 20 /* #name */
-#define XML_TOK_OR 21 /* | */
-#define XML_TOK_PERCENT 22
-#define XML_TOK_OPEN_PAREN 23
-#define XML_TOK_CLOSE_PAREN 24
-#define XML_TOK_OPEN_BRACKET 25
-#define XML_TOK_CLOSE_BRACKET 26
-#define XML_TOK_LITERAL 27
-#define XML_TOK_PARAM_ENTITY_REF 28
-#define XML_TOK_INSTANCE_START 29
-
-/* The following occur only in element type declarations */
-#define XML_TOK_NAME_QUESTION 30 /* name? */
-#define XML_TOK_NAME_ASTERISK 31 /* name* */
-#define XML_TOK_NAME_PLUS 32 /* name+ */
-#define XML_TOK_COND_SECT_OPEN 33 /* <![ */
-#define XML_TOK_COND_SECT_CLOSE 34 /* ]]> */
-#define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */
-#define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */
-#define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */
-#define XML_TOK_COMMA 38
-
-/* The following token is returned only by XmlAttributeValueTok */
-#define XML_TOK_ATTRIBUTE_VALUE_S 39
-
-/* The following token is returned only by XmlCdataSectionTok */
-#define XML_TOK_CDATA_SECT_CLOSE 40
-
-/* With namespace processing this is returned by XmlPrologTok
-   for a name with a colon. */
-#define XML_TOK_PREFIXED_NAME 41
-
-#define XML_N_STATES 3
-#define XML_PROLOG_STATE 0
-#define XML_CONTENT_STATE 1
-#define XML_CDATA_SECTION_STATE 2
-
-#define XML_N_LITERAL_TYPES 2
-#define XML_ATTRIBUTE_VALUE_LITERAL 0
-#define XML_ENTITY_VALUE_LITERAL 1
-
-/* The size of the buffer passed to XmlUtf8Encode must be at least this. */
-#define XML_UTF8_ENCODE_MAX 4
-/* The size of the buffer passed to XmlUtf16Encode must be at least this. */
-#define XML_UTF16_ENCODE_MAX 2
-
-typedef struct position {
-  /* first line and first column are 0 not 1 */
-  unsigned long lineNumber;
-  unsigned long columnNumber;
-} POSITION;
-
-typedef struct {
-  const char *name;
-  const char *valuePtr;
-  const char *valueEnd;
-  char normalized;
-} ATTRIBUTE;
-
-struct encoding;
-typedef struct encoding ENCODING;
-
-struct encoding {
-  int (*scanners[XML_N_STATES])(const ENCODING *,
-			        const char *,
-			        const char *,
-			        const char **);
-  int (*literalScanners[XML_N_LITERAL_TYPES])(const ENCODING *,
-					      const char *,
-					      const char *,
-					      const char **);
-  int (*sameName)(const ENCODING *,
-	          const char *, const char *);
-  int (*nameMatchesAscii)(const ENCODING *,
-			  const char *, const char *);
-  int (*nameLength)(const ENCODING *, const char *);
-  const char *(*skipS)(const ENCODING *, const char *);
-  int (*getAtts)(const ENCODING *enc, const char *ptr,
-	         int attsMax, ATTRIBUTE *atts);
-  int (*charRefNumber)(const ENCODING *enc, const char *ptr);
-  int (*predefinedEntityName)(const ENCODING *, const char *, const char *);
-  void (*updatePosition)(const ENCODING *,
-			 const char *ptr,
-			 const char *end,
-			 POSITION *);
-  int (*isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
-		    const char **badPtr);
-  void (*utf8Convert)(const ENCODING *enc,
-		      const char **fromP,
-		      const char *fromLim,
-		      char **toP,
-		      const char *toLim);
-  void (*utf16Convert)(const ENCODING *enc,
-		       const char **fromP,
-		       const char *fromLim,
-		       unsigned short **toP,
-		       const unsigned short *toLim);
-  int minBytesPerChar;
-  char isUtf8;
-  char isUtf16;
-};
-
-/*
-Scan the string starting at ptr until the end of the next complete token,
-but do not scan past eptr.  Return an integer giving the type of token.
-
-Return XML_TOK_NONE when ptr == eptr; nextTokPtr will not be set.
-
-Return XML_TOK_PARTIAL when the string does not contain a complete token;
-nextTokPtr will not be set.
-
-Return XML_TOK_INVALID when the string does not start a valid token; nextTokPtr
-will be set to point to the character which made the token invalid.
-
-Otherwise the string starts with a valid token; nextTokPtr will be set to point
-to the character following the end of that token.
-
-Each data character counts as a single token, but adjacent data characters
-may be returned together.  Similarly for characters in the prolog outside
-literals, comments and processing instructions.
-*/
-
-
-#define XmlTok(enc, state, ptr, end, nextTokPtr) \
-  (((enc)->scanners[state])(enc, ptr, end, nextTokPtr))
-
-#define XmlPrologTok(enc, ptr, end, nextTokPtr) \
-   XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr)
-
-#define XmlContentTok(enc, ptr, end, nextTokPtr) \
-   XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr)
-
-#define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \
-   XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr)
-
-/* This is used for performing a 2nd-level tokenization on
-the content of a literal that has already been returned by XmlTok. */ 
-
-#define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \
-  (((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr))
-
-#define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \
-   XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr)
-
-#define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \
-   XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr)
-
-#define XmlSameName(enc, ptr1, ptr2) (((enc)->sameName)(enc, ptr1, ptr2))
-
-#define XmlNameMatchesAscii(enc, ptr1, ptr2) \
-  (((enc)->nameMatchesAscii)(enc, ptr1, ptr2))
-
-#define XmlNameLength(enc, ptr) \
-  (((enc)->nameLength)(enc, ptr))
-
-#define XmlSkipS(enc, ptr) \
-  (((enc)->skipS)(enc, ptr))
-
-#define XmlGetAttributes(enc, ptr, attsMax, atts) \
-  (((enc)->getAtts)(enc, ptr, attsMax, atts))
-
-#define XmlCharRefNumber(enc, ptr) \
-  (((enc)->charRefNumber)(enc, ptr))
-
-#define XmlPredefinedEntityName(enc, ptr, end) \
-  (((enc)->predefinedEntityName)(enc, ptr, end))
-
-#define XmlUpdatePosition(enc, ptr, end, pos) \
-  (((enc)->updatePosition)(enc, ptr, end, pos))
-
-#define XmlIsPublicId(enc, ptr, end, badPtr) \
-  (((enc)->isPublicId)(enc, ptr, end, badPtr))
-
-#define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \
-  (((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim))
-
-#define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \
-  (((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim))
-
-typedef struct {
-  ENCODING initEnc;
-  const ENCODING **encPtr;
-} INIT_ENCODING;
-
-int XMLTOKAPI XmlParseXmlDecl(int isGeneralTextEntity,
-			      const ENCODING *enc,
-			      const char *ptr,
-	  		      const char *end,
-			      const char **badPtr,
-			      const char **versionPtr,
-			      const char **encodingNamePtr,
-			      const ENCODING **namedEncodingPtr,
-			      int *standalonePtr);
-
-int XMLTOKAPI XmlInitEncoding(INIT_ENCODING *, const ENCODING **, const char *name);
-const ENCODING XMLTOKAPI *XmlGetUtf8InternalEncoding();
-const ENCODING XMLTOKAPI *XmlGetUtf16InternalEncoding();
-int XMLTOKAPI XmlUtf8Encode(int charNumber, char *buf);
-int XMLTOKAPI XmlUtf16Encode(int charNumber, unsigned short *buf);
-
-int XMLTOKAPI XmlSizeOfUnknownEncoding();
-ENCODING XMLTOKAPI *
-XmlInitUnknownEncoding(void *mem,
-		       int *table,
-		       int (*conv)(void *userData, const char *p),
-		       void *userData);
-
-int XMLTOKAPI XmlParseXmlDeclNS(int isGeneralTextEntity,
-			        const ENCODING *enc,
-			        const char *ptr,
-	  		        const char *end,
-			        const char **badPtr,
-			        const char **versionPtr,
-			        const char **encodingNamePtr,
-			        const ENCODING **namedEncodingPtr,
-			        int *standalonePtr);
-int XMLTOKAPI XmlInitEncodingNS(INIT_ENCODING *, const ENCODING **, const char *name);
-const ENCODING XMLTOKAPI *XmlGetUtf8InternalEncodingNS();
-const ENCODING XMLTOKAPI *XmlGetUtf16InternalEncodingNS();
-ENCODING XMLTOKAPI *
-XmlInitUnknownEncodingNS(void *mem,
-		         int *table,
-		         int (*conv)(void *userData, const char *p),
-		         void *userData);
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* not XmlTok_INCLUDED */
Index: protocols/jabber/xmltok_impl.c
===================================================================
--- protocols/jabber/xmltok_impl.c	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,1737 +1,0 @@
-/*
-The contents of this file are subject to the Mozilla Public License
-Version 1.1 (the "License"); you may not use this file except in
-compliance with the License. You may obtain a copy of the License at
-http://www.mozilla.org/MPL/
-
-Software distributed under the License is distributed on an "AS IS"
-basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
-License for the specific language governing rights and limitations
-under the License.
-
-The Original Code is expat.
-
-The Initial Developer of the Original Code is James Clark.
-Portions created by James Clark are Copyright (C) 1998, 1999
-James Clark. All Rights Reserved.
-
-Contributor(s):
-
-*/
-
-#ifndef IS_INVALID_CHAR
-#define IS_INVALID_CHAR(enc, ptr, n) (0)
-#endif
-
-#define INVALID_LEAD_CASE(n, ptr, nextTokPtr) \
-    case BT_LEAD ## n: \
-      if (end - ptr < n) \
-    return XML_TOK_PARTIAL_CHAR; \
-      if (IS_INVALID_CHAR(enc, ptr, n)) { \
-        *(nextTokPtr) = (ptr); \
-        return XML_TOK_INVALID; \
-      } \
-      ptr += n; \
-      break;
-
-#define INVALID_CASES(ptr, nextTokPtr) \
-  INVALID_LEAD_CASE(2, ptr, nextTokPtr) \
-  INVALID_LEAD_CASE(3, ptr, nextTokPtr) \
-  INVALID_LEAD_CASE(4, ptr, nextTokPtr) \
-  case BT_NONXML: \
-  case BT_MALFORM: \
-  case BT_TRAIL: \
-    *(nextTokPtr) = (ptr); \
-    return XML_TOK_INVALID;
-
-#define CHECK_NAME_CASE(n, enc, ptr, end, nextTokPtr) \
-   case BT_LEAD ## n: \
-     if (end - ptr < n) \
-       return XML_TOK_PARTIAL_CHAR; \
-     if (!IS_NAME_CHAR(enc, ptr, n)) { \
-       *nextTokPtr = ptr; \
-       return XML_TOK_INVALID; \
-     } \
-     ptr += n; \
-     break;
-
-#define CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) \
-  case BT_NONASCII: \
-    if (!IS_NAME_CHAR_MINBPC(enc, ptr)) { \
-      *nextTokPtr = ptr; \
-      return XML_TOK_INVALID; \
-    } \
-  case BT_NMSTRT: \
-  case BT_HEX: \
-  case BT_DIGIT: \
-  case BT_NAME: \
-  case BT_MINUS: \
-    ptr += MINBPC(enc); \
-    break; \
-  CHECK_NAME_CASE(2, enc, ptr, end, nextTokPtr) \
-  CHECK_NAME_CASE(3, enc, ptr, end, nextTokPtr) \
-  CHECK_NAME_CASE(4, enc, ptr, end, nextTokPtr)
-
-#define CHECK_NMSTRT_CASE(n, enc, ptr, end, nextTokPtr) \
-   case BT_LEAD ## n: \
-     if (end - ptr < n) \
-       return XML_TOK_PARTIAL_CHAR; \
-     if (!IS_NMSTRT_CHAR(enc, ptr, n)) { \
-       *nextTokPtr = ptr; \
-       return XML_TOK_INVALID; \
-     } \
-     ptr += n; \
-     break;
-
-#define CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) \
-  case BT_NONASCII: \
-    if (!IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { \
-      *nextTokPtr = ptr; \
-      return XML_TOK_INVALID; \
-    } \
-  case BT_NMSTRT: \
-  case BT_HEX: \
-    ptr += MINBPC(enc); \
-    break; \
-  CHECK_NMSTRT_CASE(2, enc, ptr, end, nextTokPtr) \
-  CHECK_NMSTRT_CASE(3, enc, ptr, end, nextTokPtr) \
-  CHECK_NMSTRT_CASE(4, enc, ptr, end, nextTokPtr)
-
-#ifndef PREFIX
-#define PREFIX(ident) ident
-#endif
-
-/* ptr points to character following "<!-" */
-
-static
-int PREFIX(scanComment)(const ENCODING *enc, const char *ptr, const char *end,
-                        const char **nextTokPtr)
-{
-    if (ptr != end) {
-        if (!CHAR_MATCHES(enc, ptr, '-')) {
-            *nextTokPtr = ptr;
-            return XML_TOK_INVALID;
-        }
-        ptr += MINBPC(enc);
-        while (ptr != end) {
-            switch (BYTE_TYPE(enc, ptr)) {
-                INVALID_CASES(ptr, nextTokPtr)
-            case BT_MINUS:
-                if ((ptr += MINBPC(enc)) == end)
-                    return XML_TOK_PARTIAL;
-                if (CHAR_MATCHES(enc, ptr, '-')) {
-                    if ((ptr += MINBPC(enc)) == end)
-                        return XML_TOK_PARTIAL;
-                    if (!CHAR_MATCHES(enc, ptr, '>')) {
-                        *nextTokPtr = ptr;
-                        return XML_TOK_INVALID;
-                    }
-                    *nextTokPtr = ptr + MINBPC(enc);
-                    return XML_TOK_COMMENT;
-                }
-                break;
-            default:
-                ptr += MINBPC(enc);
-                break;
-            }
-        }
-    }
-    return XML_TOK_PARTIAL;
-}
-
-/* ptr points to character following "<!" */
-
-static
-int PREFIX(scanDecl)(const ENCODING *enc, const char *ptr, const char *end,
-                     const char **nextTokPtr)
-{
-    if (ptr == end)
-        return XML_TOK_PARTIAL;
-    switch (BYTE_TYPE(enc, ptr)) {
-    case BT_MINUS:
-        return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr);
-    case BT_LSQB:
-        *nextTokPtr = ptr + MINBPC(enc);
-        return XML_TOK_COND_SECT_OPEN;
-    case BT_NMSTRT:
-    case BT_HEX:
-        ptr += MINBPC(enc);
-        break;
-    default:
-        *nextTokPtr = ptr;
-        return XML_TOK_INVALID;
-    }
-    while (ptr != end) {
-        switch (BYTE_TYPE(enc, ptr)) {
-        case BT_PERCNT:
-            if (ptr + MINBPC(enc) == end)
-                return XML_TOK_PARTIAL;
-            /* don't allow <!ENTITY% foo "whatever"> */
-            switch (BYTE_TYPE(enc, ptr + MINBPC(enc))) {
-case BT_S: case BT_CR: case BT_LF: case BT_PERCNT:
-                *nextTokPtr = ptr;
-                return XML_TOK_INVALID;
-            }
-            /* fall through */
-case BT_S: case BT_CR: case BT_LF:
-            *nextTokPtr = ptr;
-            return XML_TOK_DECL_OPEN;
-        case BT_NMSTRT:
-        case BT_HEX:
-            ptr += MINBPC(enc);
-            break;
-        default:
-            *nextTokPtr = ptr;
-            return XML_TOK_INVALID;
-        }
-    }
-    return XML_TOK_PARTIAL;
-}
-
-static
-int PREFIX(checkPiTarget)(const ENCODING *enc, const char *ptr, const char *end, int *tokPtr)
-{
-    int upper = 0;
-    *tokPtr = XML_TOK_PI;
-    if (end - ptr != MINBPC(enc)*3)
-        return 1;
-    switch (BYTE_TO_ASCII(enc, ptr)) {
-    case 'x':
-        break;
-    case 'X':
-        upper = 1;
-        break;
-    default:
-        return 1;
-    }
-    ptr += MINBPC(enc);
-    switch (BYTE_TO_ASCII(enc, ptr)) {
-    case 'm':
-        break;
-    case 'M':
-        upper = 1;
-        break;
-    default:
-        return 1;
-    }
-    ptr += MINBPC(enc);
-    switch (BYTE_TO_ASCII(enc, ptr)) {
-    case 'l':
-        break;
-    case 'L':
-        upper = 1;
-        break;
-    default:
-        return 1;
-    }
-    if (upper)
-        return 0;
-    *tokPtr = XML_TOK_XML_DECL;
-    return 1;
-}
-
-/* ptr points to character following "<?" */
-
-static
-int PREFIX(scanPi)(const ENCODING *enc, const char *ptr, const char *end,
-                   const char **nextTokPtr)
-{
-    int tok;
-    const char *target = ptr;
-    if (ptr == end)
-        return XML_TOK_PARTIAL;
-    switch (BYTE_TYPE(enc, ptr)) {
-        CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
-    default:
-        *nextTokPtr = ptr;
-        return XML_TOK_INVALID;
-    }
-    while (ptr != end) {
-        switch (BYTE_TYPE(enc, ptr)) {
-            CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
-case BT_S: case BT_CR: case BT_LF:
-            if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) {
-                *nextTokPtr = ptr;
-                return XML_TOK_INVALID;
-            }
-            ptr += MINBPC(enc);
-            while (ptr != end) {
-                switch (BYTE_TYPE(enc, ptr)) {
-                    INVALID_CASES(ptr, nextTokPtr)
-                case BT_QUEST:
-                    ptr += MINBPC(enc);
-                    if (ptr == end)
-                        return XML_TOK_PARTIAL;
-                    if (CHAR_MATCHES(enc, ptr, '>')) {
-                        *nextTokPtr = ptr + MINBPC(enc);
-                        return tok;
-                    }
-                    break;
-                default:
-                    ptr += MINBPC(enc);
-                    break;
-                }
-            }
-            return XML_TOK_PARTIAL;
-        case BT_QUEST:
-            if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) {
-                *nextTokPtr = ptr;
-                return XML_TOK_INVALID;
-            }
-            ptr += MINBPC(enc);
-            if (ptr == end)
-                return XML_TOK_PARTIAL;
-            if (CHAR_MATCHES(enc, ptr, '>')) {
-                *nextTokPtr = ptr + MINBPC(enc);
-                return tok;
-            }
-            /* fall through */
-        default:
-            *nextTokPtr = ptr;
-            return XML_TOK_INVALID;
-        }
-    }
-    return XML_TOK_PARTIAL;
-}
-
-
-static
-int PREFIX(scanCdataSection)(const ENCODING *enc, const char *ptr, const char *end,
-                             const char **nextTokPtr)
-{
-    int i;
-    /* CDATA[ */
-    if (end - ptr < 6 * MINBPC(enc))
-        return XML_TOK_PARTIAL;
-    for (i = 0; i < 6; i++, ptr += MINBPC(enc)) {
-        if (!CHAR_MATCHES(enc, ptr, "CDATA["[i])) {
-            *nextTokPtr = ptr;
-            return XML_TOK_INVALID;
-        }
-    }
-    *nextTokPtr = ptr;
-    return XML_TOK_CDATA_SECT_OPEN;
-}
-
-static
-int PREFIX(cdataSectionTok)(const ENCODING *enc, const char *ptr, const char *end,
-                            const char **nextTokPtr)
-{
-    if (ptr == end)
-        return XML_TOK_NONE;
-    if (MINBPC(enc) > 1) {
-        size_t n = end - ptr;
-        if (n & (MINBPC(enc) - 1)) {
-            n &= ~(MINBPC(enc) - 1);
-            if (n == 0)
-                return XML_TOK_PARTIAL;
-            end = ptr + n;
-        }
-    }
-    switch (BYTE_TYPE(enc, ptr)) {
-    case BT_RSQB:
-        ptr += MINBPC(enc);
-        if (ptr == end)
-            return XML_TOK_PARTIAL;
-        if (!CHAR_MATCHES(enc, ptr, ']'))
-            break;
-        ptr += MINBPC(enc);
-        if (ptr == end)
-            return XML_TOK_PARTIAL;
-        if (!CHAR_MATCHES(enc, ptr, '>')) {
-            ptr -= MINBPC(enc);
-            break;
-        }
-        *nextTokPtr = ptr + MINBPC(enc);
-        return XML_TOK_CDATA_SECT_CLOSE;
-    case BT_CR:
-        ptr += MINBPC(enc);
-        if (ptr == end)
-            return XML_TOK_PARTIAL;
-        if (BYTE_TYPE(enc, ptr) == BT_LF)
-            ptr += MINBPC(enc);
-        *nextTokPtr = ptr;
-        return XML_TOK_DATA_NEWLINE;
-    case BT_LF:
-        *nextTokPtr = ptr + MINBPC(enc);
-        return XML_TOK_DATA_NEWLINE;
-        INVALID_CASES(ptr, nextTokPtr)
-    default:
-        ptr += MINBPC(enc);
-        break;
-    }
-    while (ptr != end) {
-        switch (BYTE_TYPE(enc, ptr)) {
-#define LEAD_CASE(n) \
-    case BT_LEAD ## n: \
-      if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \
-    *nextTokPtr = ptr; \
-    return XML_TOK_DATA_CHARS; \
-      } \
-      ptr += n; \
-      break;
-            LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
-#undef LEAD_CASE
-        case BT_NONXML:
-        case BT_MALFORM:
-        case BT_TRAIL:
-        case BT_CR:
-        case BT_LF:
-        case BT_RSQB:
-            *nextTokPtr = ptr;
-            return XML_TOK_DATA_CHARS;
-        default:
-            ptr += MINBPC(enc);
-            break;
-        }
-    }
-    *nextTokPtr = ptr;
-    return XML_TOK_DATA_CHARS;
-}
-
-/* ptr points to character following "</" */
-
-static
-int PREFIX(scanEndTag)(const ENCODING *enc, const char *ptr, const char *end,
-                       const char **nextTokPtr)
-{
-    if (ptr == end)
-        return XML_TOK_PARTIAL;
-    switch (BYTE_TYPE(enc, ptr)) {
-        CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
-    default:
-        *nextTokPtr = ptr;
-        return XML_TOK_INVALID;
-    }
-    while (ptr != end) {
-        switch (BYTE_TYPE(enc, ptr)) {
-            CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
-case BT_S: case BT_CR: case BT_LF:
-            for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
-                switch (BYTE_TYPE(enc, ptr)) {
-        case BT_S: case BT_CR: case BT_LF:
-                    break;
-                case BT_GT:
-                    *nextTokPtr = ptr + MINBPC(enc);
-                    return XML_TOK_END_TAG;
-                default:
-                    *nextTokPtr = ptr;
-                    return XML_TOK_INVALID;
-                }
-            }
-            return XML_TOK_PARTIAL;
-#ifdef XML_NS
-        case BT_COLON:
-            /* no need to check qname syntax here, since end-tag must match exactly */
-            ptr += MINBPC(enc);
-            break;
-#endif
-        case BT_GT:
-            *nextTokPtr = ptr + MINBPC(enc);
-            return XML_TOK_END_TAG;
-        default:
-            *nextTokPtr = ptr;
-            return XML_TOK_INVALID;
-        }
-    }
-    return XML_TOK_PARTIAL;
-}
-
-/* ptr points to character following "&#X" */
-
-static
-int PREFIX(scanHexCharRef)(const ENCODING *enc, const char *ptr, const char *end,
-                           const char **nextTokPtr)
-{
-    if (ptr != end) {
-        switch (BYTE_TYPE(enc, ptr)) {
-        case BT_DIGIT:
-        case BT_HEX:
-            break;
-        default:
-            *nextTokPtr = ptr;
-            return XML_TOK_INVALID;
-        }
-        for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
-            switch (BYTE_TYPE(enc, ptr)) {
-            case BT_DIGIT:
-            case BT_HEX:
-                break;
-            case BT_SEMI:
-                *nextTokPtr = ptr + MINBPC(enc);
-                return XML_TOK_CHAR_REF;
-            default:
-                *nextTokPtr = ptr;
-                return XML_TOK_INVALID;
-            }
-        }
-    }
-    return XML_TOK_PARTIAL;
-}
-
-/* ptr points to character following "&#" */
-
-static
-int PREFIX(scanCharRef)(const ENCODING *enc, const char *ptr, const char *end,
-                        const char **nextTokPtr)
-{
-    if (ptr != end) {
-        if (CHAR_MATCHES(enc, ptr, 'x'))
-            return PREFIX(scanHexCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
-        switch (BYTE_TYPE(enc, ptr)) {
-        case BT_DIGIT:
-            break;
-        default:
-            *nextTokPtr = ptr;
-            return XML_TOK_INVALID;
-        }
-        for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
-            switch (BYTE_TYPE(enc, ptr)) {
-            case BT_DIGIT:
-                break;
-            case BT_SEMI:
-                *nextTokPtr = ptr + MINBPC(enc);
-                return XML_TOK_CHAR_REF;
-            default:
-                *nextTokPtr = ptr;
-                return XML_TOK_INVALID;
-            }
-        }
-    }
-    return XML_TOK_PARTIAL;
-}
-
-/* ptr points to character following "&" */
-
-static
-int PREFIX(scanRef)(const ENCODING *enc, const char *ptr, const char *end,
-                    const char **nextTokPtr)
-{
-    if (ptr == end)
-        return XML_TOK_PARTIAL;
-    switch (BYTE_TYPE(enc, ptr)) {
-        CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
-    case BT_NUM:
-        return PREFIX(scanCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
-    default:
-        *nextTokPtr = ptr;
-        return XML_TOK_INVALID;
-    }
-    while (ptr != end) {
-        switch (BYTE_TYPE(enc, ptr)) {
-            CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
-        case BT_SEMI:
-            *nextTokPtr = ptr + MINBPC(enc);
-            return XML_TOK_ENTITY_REF;
-        default:
-            *nextTokPtr = ptr;
-            return XML_TOK_INVALID;
-        }
-    }
-    return XML_TOK_PARTIAL;
-}
-
-/* ptr points to character following first character of attribute name */
-
-static
-int PREFIX(scanAtts)(const ENCODING *enc, const char *ptr, const char *end,
-                     const char **nextTokPtr)
-{
-#ifdef XML_NS
-    int hadColon = 0;
-#endif
-    while (ptr != end) {
-        switch (BYTE_TYPE(enc, ptr)) {
-            CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
-#ifdef XML_NS
-        case BT_COLON:
-            if (hadColon) {
-                *nextTokPtr = ptr;
-                return XML_TOK_INVALID;
-            }
-            hadColon = 1;
-            ptr += MINBPC(enc);
-            if (ptr == end)
-                return XML_TOK_PARTIAL;
-            switch (BYTE_TYPE(enc, ptr)) {
-                CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
-            default:
-                *nextTokPtr = ptr;
-                return XML_TOK_INVALID;
-            }
-            break;
-#endif
-case BT_S: case BT_CR: case BT_LF:
-            for (;;) {
-                int t;
-
-                ptr += MINBPC(enc);
-                if (ptr == end)
-                    return XML_TOK_PARTIAL;
-                t = BYTE_TYPE(enc, ptr);
-                if (t == BT_EQUALS)
-                    break;
-                switch (t) {
-                case BT_S:
-                case BT_LF:
-                case BT_CR:
-                    break;
-                default:
-                    *nextTokPtr = ptr;
-                    return XML_TOK_INVALID;
-                }
-            }
-            /* fall through */
-        case BT_EQUALS:
-            {
-                int open;
-#ifdef XML_NS
-                hadColon = 0;
-#endif
-                for (;;) {
-
-                    ptr += MINBPC(enc);
-                    if (ptr == end)
-                        return XML_TOK_PARTIAL;
-                    open = BYTE_TYPE(enc, ptr);
-                    if (open == BT_QUOT || open == BT_APOS)
-                        break;
-                    switch (open) {
-                    case BT_S:
-                    case BT_LF:
-                    case BT_CR:
-                        break;
-                    default:
-                        *nextTokPtr = ptr;
-                        return XML_TOK_INVALID;
-                    }
-                }
-                ptr += MINBPC(enc);
-                /* in attribute value */
-                for (;;) {
-                    int t;
-                    if (ptr == end)
-                        return XML_TOK_PARTIAL;
-                    t = BYTE_TYPE(enc, ptr);
-                    if (t == open)
-                        break;
-                    switch (t) {
-                        INVALID_CASES(ptr, nextTokPtr)
-                    case BT_AMP:
-                        {
-                            int tok = PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, &ptr);
-                            if (tok <= 0) {
-                                if (tok == XML_TOK_INVALID)
-                                    *nextTokPtr = ptr;
-                                return tok;
-                            }
-                            break;
-                        }
-                    case BT_LT:
-                        *nextTokPtr = ptr;
-                        return XML_TOK_INVALID;
-                    default:
-                        ptr += MINBPC(enc);
-                        break;
-                    }
-                }
-                ptr += MINBPC(enc);
-                if (ptr == end)
-                    return XML_TOK_PARTIAL;
-                switch (BYTE_TYPE(enc, ptr)) {
-                case BT_S:
-                case BT_CR:
-                case BT_LF:
-                    break;
-                case BT_SOL:
-                    goto sol;
-                case BT_GT:
-                    goto gt;
-                default:
-                    *nextTokPtr = ptr;
-                    return XML_TOK_INVALID;
-                }
-                /* ptr points to closing quote */
-                for (;;) {
-                    ptr += MINBPC(enc);
-                    if (ptr == end)
-                        return XML_TOK_PARTIAL;
-                    switch (BYTE_TYPE(enc, ptr)) {
-                        CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
-            case BT_S: case BT_CR: case BT_LF:
-                        continue;
-                    case BT_GT:
-gt:
-                        *nextTokPtr = ptr + MINBPC(enc);
-                        return XML_TOK_START_TAG_WITH_ATTS;
-                    case BT_SOL:
-sol:
-                        ptr += MINBPC(enc);
-                        if (ptr == end)
-                            return XML_TOK_PARTIAL;
-                        if (!CHAR_MATCHES(enc, ptr, '>')) {
-                            *nextTokPtr = ptr;
-                            return XML_TOK_INVALID;
-                        }
-                        *nextTokPtr = ptr + MINBPC(enc);
-                        return XML_TOK_EMPTY_ELEMENT_WITH_ATTS;
-                    default:
-                        *nextTokPtr = ptr;
-                        return XML_TOK_INVALID;
-                    }
-                    break;
-                }
-                break;
-            }
-        default:
-            *nextTokPtr = ptr;
-            return XML_TOK_INVALID;
-        }
-    }
-    return XML_TOK_PARTIAL;
-}
-
-/* ptr points to character following "<" */
-
-static
-int PREFIX(scanLt)(const ENCODING *enc, const char *ptr, const char *end,
-                   const char **nextTokPtr)
-{
-#ifdef XML_NS
-    int hadColon;
-#endif
-    if (ptr == end)
-        return XML_TOK_PARTIAL;
-    switch (BYTE_TYPE(enc, ptr)) {
-        CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
-    case BT_EXCL:
-        if ((ptr += MINBPC(enc)) == end)
-            return XML_TOK_PARTIAL;
-        switch (BYTE_TYPE(enc, ptr)) {
-        case BT_MINUS:
-            return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr);
-        case BT_LSQB:
-            return PREFIX(scanCdataSection)(enc, ptr + MINBPC(enc), end, nextTokPtr);
-        }
-        *nextTokPtr = ptr;
-        return XML_TOK_INVALID;
-    case BT_QUEST:
-        return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr);
-    case BT_SOL:
-        return PREFIX(scanEndTag)(enc, ptr + MINBPC(enc), end, nextTokPtr);
-    default:
-        *nextTokPtr = ptr;
-        return XML_TOK_INVALID;
-    }
-#ifdef XML_NS
-    hadColon = 0;
-#endif
-    /* we have a start-tag */
-    while (ptr != end) {
-        switch (BYTE_TYPE(enc, ptr)) {
-            CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
-#ifdef XML_NS
-        case BT_COLON:
-            if (hadColon) {
-                *nextTokPtr = ptr;
-                return XML_TOK_INVALID;
-            }
-            hadColon = 1;
-            ptr += MINBPC(enc);
-            if (ptr == end)
-                return XML_TOK_PARTIAL;
-            switch (BYTE_TYPE(enc, ptr)) {
-                CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
-            default:
-                *nextTokPtr = ptr;
-                return XML_TOK_INVALID;
-            }
-            break;
-#endif
-case BT_S: case BT_CR: case BT_LF:
-            {
-                ptr += MINBPC(enc);
-                while (ptr != end) {
-                    switch (BYTE_TYPE(enc, ptr)) {
-                        CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
-                    case BT_GT:
-                        goto gt;
-                    case BT_SOL:
-                        goto sol;
-            case BT_S: case BT_CR: case BT_LF:
-                        ptr += MINBPC(enc);
-                        continue;
-                    default:
-                        *nextTokPtr = ptr;
-                        return XML_TOK_INVALID;
-                    }
-                    return PREFIX(scanAtts)(enc, ptr, end, nextTokPtr);
-                }
-                return XML_TOK_PARTIAL;
-            }
-        case BT_GT:
-gt:
-            *nextTokPtr = ptr + MINBPC(enc);
-            return XML_TOK_START_TAG_NO_ATTS;
-        case BT_SOL:
-sol:
-            ptr += MINBPC(enc);
-            if (ptr == end)
-                return XML_TOK_PARTIAL;
-            if (!CHAR_MATCHES(enc, ptr, '>')) {
-                *nextTokPtr = ptr;
-                return XML_TOK_INVALID;
-            }
-            *nextTokPtr = ptr + MINBPC(enc);
-            return XML_TOK_EMPTY_ELEMENT_NO_ATTS;
-        default:
-            *nextTokPtr = ptr;
-            return XML_TOK_INVALID;
-        }
-    }
-    return XML_TOK_PARTIAL;
-}
-
-static
-int PREFIX(contentTok)(const ENCODING *enc, const char *ptr, const char *end,
-                       const char **nextTokPtr)
-{
-    if (ptr == end)
-        return XML_TOK_NONE;
-    if (MINBPC(enc) > 1) {
-        size_t n = end - ptr;
-        if (n & (MINBPC(enc) - 1)) {
-            n &= ~(MINBPC(enc) - 1);
-            if (n == 0)
-                return XML_TOK_PARTIAL;
-            end = ptr + n;
-        }
-    }
-    switch (BYTE_TYPE(enc, ptr)) {
-    case BT_LT:
-        return PREFIX(scanLt)(enc, ptr + MINBPC(enc), end, nextTokPtr);
-    case BT_AMP:
-        return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
-    case BT_CR:
-        ptr += MINBPC(enc);
-        if (ptr == end)
-            return XML_TOK_TRAILING_CR;
-        if (BYTE_TYPE(enc, ptr) == BT_LF)
-            ptr += MINBPC(enc);
-        *nextTokPtr = ptr;
-        return XML_TOK_DATA_NEWLINE;
-    case BT_LF:
-        *nextTokPtr = ptr + MINBPC(enc);
-        return XML_TOK_DATA_NEWLINE;
-    case BT_RSQB:
-        ptr += MINBPC(enc);
-        if (ptr == end)
-            return XML_TOK_TRAILING_RSQB;
-        if (!CHAR_MATCHES(enc, ptr, ']'))
-            break;
-        ptr += MINBPC(enc);
-        if (ptr == end)
-            return XML_TOK_TRAILING_RSQB;
-        if (!CHAR_MATCHES(enc, ptr, '>')) {
-            ptr -= MINBPC(enc);
-            break;
-        }
-        *nextTokPtr = ptr;
-        return XML_TOK_INVALID;
-        INVALID_CASES(ptr, nextTokPtr)
-    default:
-        ptr += MINBPC(enc);
-        break;
-    }
-    while (ptr != end) {
-        switch (BYTE_TYPE(enc, ptr)) {
-#define LEAD_CASE(n) \
-    case BT_LEAD ## n: \
-      if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \
-    *nextTokPtr = ptr; \
-    return XML_TOK_DATA_CHARS; \
-      } \
-      ptr += n; \
-      break;
-            LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
-#undef LEAD_CASE
-        case BT_RSQB:
-            if (ptr + MINBPC(enc) != end) {
-                if (!CHAR_MATCHES(enc, ptr + MINBPC(enc), ']')) {
-                    ptr += MINBPC(enc);
-                    break;
-                }
-                if (ptr + 2*MINBPC(enc) != end) {
-                    if (!CHAR_MATCHES(enc, ptr + 2*MINBPC(enc), '>')) {
-                        ptr += MINBPC(enc);
-                        break;
-                    }
-                    *nextTokPtr = ptr + 2*MINBPC(enc);
-                    return XML_TOK_INVALID;
-                }
-            }
-            /* fall through */
-        case BT_AMP:
-        case BT_LT:
-        case BT_NONXML:
-        case BT_MALFORM:
-        case BT_TRAIL:
-        case BT_CR:
-        case BT_LF:
-            *nextTokPtr = ptr;
-            return XML_TOK_DATA_CHARS;
-        default:
-            ptr += MINBPC(enc);
-            break;
-        }
-    }
-    *nextTokPtr = ptr;
-    return XML_TOK_DATA_CHARS;
-}
-
-/* ptr points to character following "%" */
-
-static
-int PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end,
-                        const char **nextTokPtr)
-{
-    if (ptr == end)
-        return XML_TOK_PARTIAL;
-    switch (BYTE_TYPE(enc, ptr)) {
-        CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
-case BT_S: case BT_LF: case BT_CR: case BT_PERCNT:
-        *nextTokPtr = ptr;
-        return XML_TOK_PERCENT;
-    default:
-        *nextTokPtr = ptr;
-        return XML_TOK_INVALID;
-    }
-    while (ptr != end) {
-        switch (BYTE_TYPE(enc, ptr)) {
-            CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
-        case BT_SEMI:
-            *nextTokPtr = ptr + MINBPC(enc);
-            return XML_TOK_PARAM_ENTITY_REF;
-        default:
-            *nextTokPtr = ptr;
-            return XML_TOK_INVALID;
-        }
-    }
-    return XML_TOK_PARTIAL;
-}
-
-static
-int PREFIX(scanPoundName)(const ENCODING *enc, const char *ptr, const char *end,
-                          const char **nextTokPtr)
-{
-    if (ptr == end)
-        return XML_TOK_PARTIAL;
-    switch (BYTE_TYPE(enc, ptr)) {
-        CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
-    default:
-        *nextTokPtr = ptr;
-        return XML_TOK_INVALID;
-    }
-    while (ptr != end) {
-        switch (BYTE_TYPE(enc, ptr)) {
-            CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
-case BT_CR: case BT_LF: case BT_S:
-case BT_RPAR: case BT_GT: case BT_PERCNT: case BT_VERBAR:
-            *nextTokPtr = ptr;
-            return XML_TOK_POUND_NAME;
-        default:
-            *nextTokPtr = ptr;
-            return XML_TOK_INVALID;
-        }
-    }
-    return XML_TOK_PARTIAL;
-}
-
-static
-int PREFIX(scanLit)(int open, const ENCODING *enc,
-                    const char *ptr, const char *end,
-                    const char **nextTokPtr)
-{
-    while (ptr != end) {
-        int t = BYTE_TYPE(enc, ptr);
-        switch (t) {
-            INVALID_CASES(ptr, nextTokPtr)
-        case BT_QUOT:
-        case BT_APOS:
-            ptr += MINBPC(enc);
-            if (t != open)
-                break;
-            if (ptr == end)
-                return XML_TOK_PARTIAL;
-            *nextTokPtr = ptr;
-            switch (BYTE_TYPE(enc, ptr)) {
-    case BT_S: case BT_CR: case BT_LF:
-    case BT_GT: case BT_PERCNT: case BT_LSQB:
-                return XML_TOK_LITERAL;
-            default:
-                return XML_TOK_INVALID;
-            }
-        default:
-            ptr += MINBPC(enc);
-            break;
-        }
-    }
-    return XML_TOK_PARTIAL;
-}
-
-static
-int PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end,
-                      const char **nextTokPtr)
-{
-    int tok;
-    if (ptr == end)
-        return XML_TOK_NONE;
-    if (MINBPC(enc) > 1) {
-        size_t n = end - ptr;
-        if (n & (MINBPC(enc) - 1)) {
-            n &= ~(MINBPC(enc) - 1);
-            if (n == 0)
-                return XML_TOK_PARTIAL;
-            end = ptr + n;
-        }
-    }
-    switch (BYTE_TYPE(enc, ptr)) {
-    case BT_QUOT:
-        return PREFIX(scanLit)(BT_QUOT, enc, ptr + MINBPC(enc), end, nextTokPtr);
-    case BT_APOS:
-        return PREFIX(scanLit)(BT_APOS, enc, ptr + MINBPC(enc), end, nextTokPtr);
-    case BT_LT:
-        {
-            ptr += MINBPC(enc);
-            if (ptr == end)
-                return XML_TOK_PARTIAL;
-            switch (BYTE_TYPE(enc, ptr)) {
-            case BT_EXCL:
-                return PREFIX(scanDecl)(enc, ptr + MINBPC(enc), end, nextTokPtr);
-            case BT_QUEST:
-                return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr);
-            case BT_NMSTRT:
-            case BT_HEX:
-            case BT_NONASCII:
-            case BT_LEAD2:
-            case BT_LEAD3:
-            case BT_LEAD4:
-                *nextTokPtr = ptr - MINBPC(enc);
-                return XML_TOK_INSTANCE_START;
-            }
-            *nextTokPtr = ptr;
-            return XML_TOK_INVALID;
-        }
-    case BT_CR:
-        if (ptr + MINBPC(enc) == end)
-            return XML_TOK_TRAILING_CR;
-        /* fall through */
-case BT_S: case BT_LF:
-        for (;;) {
-            ptr += MINBPC(enc);
-            if (ptr == end)
-                break;
-            switch (BYTE_TYPE(enc, ptr)) {
-        case BT_S: case BT_LF:
-                break;
-            case BT_CR:
-                /* don't split CR/LF pair */
-                if (ptr + MINBPC(enc) != end)
-                    break;
-                /* fall through */
-            default:
-                *nextTokPtr = ptr;
-                return XML_TOK_PROLOG_S;
-            }
-        }
-        *nextTokPtr = ptr;
-        return XML_TOK_PROLOG_S;
-    case BT_PERCNT:
-        return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr);
-    case BT_COMMA:
-        *nextTokPtr = ptr + MINBPC(enc);
-        return XML_TOK_COMMA;
-    case BT_LSQB:
-        *nextTokPtr = ptr + MINBPC(enc);
-        return XML_TOK_OPEN_BRACKET;
-    case BT_RSQB:
-        ptr += MINBPC(enc);
-        if (ptr == end)
-            return XML_TOK_PARTIAL;
-        if (CHAR_MATCHES(enc, ptr, ']')) {
-            if (ptr + MINBPC(enc) == end)
-                return XML_TOK_PARTIAL;
-            if (CHAR_MATCHES(enc, ptr + MINBPC(enc), '>')) {
-                *nextTokPtr = ptr + 2*MINBPC(enc);
-                return XML_TOK_COND_SECT_CLOSE;
-            }
-        }
-        *nextTokPtr = ptr;
-        return XML_TOK_CLOSE_BRACKET;
-    case BT_LPAR:
-        *nextTokPtr = ptr + MINBPC(enc);
-        return XML_TOK_OPEN_PAREN;
-    case BT_RPAR:
-        ptr += MINBPC(enc);
-        if (ptr == end)
-            return XML_TOK_PARTIAL;
-        switch (BYTE_TYPE(enc, ptr)) {
-        case BT_AST:
-            *nextTokPtr = ptr + MINBPC(enc);
-            return XML_TOK_CLOSE_PAREN_ASTERISK;
-        case BT_QUEST:
-            *nextTokPtr = ptr + MINBPC(enc);
-            return XML_TOK_CLOSE_PAREN_QUESTION;
-        case BT_PLUS:
-            *nextTokPtr = ptr + MINBPC(enc);
-            return XML_TOK_CLOSE_PAREN_PLUS;
-case BT_CR: case BT_LF: case BT_S:
-case BT_GT: case BT_COMMA: case BT_VERBAR:
-        case BT_RPAR:
-            *nextTokPtr = ptr;
-            return XML_TOK_CLOSE_PAREN;
-        }
-        *nextTokPtr = ptr;
-        return XML_TOK_INVALID;
-    case BT_VERBAR:
-        *nextTokPtr = ptr + MINBPC(enc);
-        return XML_TOK_OR;
-    case BT_GT:
-        *nextTokPtr = ptr + MINBPC(enc);
-        return XML_TOK_DECL_CLOSE;
-    case BT_NUM:
-        return PREFIX(scanPoundName)(enc, ptr + MINBPC(enc), end, nextTokPtr);
-#define LEAD_CASE(n) \
-  case BT_LEAD ## n: \
-    if (end - ptr < n) \
-      return XML_TOK_PARTIAL_CHAR; \
-    if (IS_NMSTRT_CHAR(enc, ptr, n)) { \
-      ptr += n; \
-      tok = XML_TOK_NAME; \
-      break; \
-    } \
-    if (IS_NAME_CHAR(enc, ptr, n)) { \
-      ptr += n; \
-      tok = XML_TOK_NMTOKEN; \
-      break; \
-    } \
-    *nextTokPtr = ptr; \
-    return XML_TOK_INVALID;
-        LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
-#undef LEAD_CASE
-    case BT_NMSTRT:
-    case BT_HEX:
-        tok = XML_TOK_NAME;
-        ptr += MINBPC(enc);
-        break;
-    case BT_DIGIT:
-    case BT_NAME:
-    case BT_MINUS:
-#ifdef XML_NS
-    case BT_COLON:
-#endif
-        tok = XML_TOK_NMTOKEN;
-        ptr += MINBPC(enc);
-        break;
-    case BT_NONASCII:
-        if (IS_NMSTRT_CHAR_MINBPC(enc, ptr)) {
-            ptr += MINBPC(enc);
-            tok = XML_TOK_NAME;
-            break;
-        }
-        if (IS_NAME_CHAR_MINBPC(enc, ptr)) {
-            ptr += MINBPC(enc);
-            tok = XML_TOK_NMTOKEN;
-            break;
-        }
-        /* fall through */
-    default:
-        *nextTokPtr = ptr;
-        return XML_TOK_INVALID;
-    }
-    while (ptr != end) {
-        switch (BYTE_TYPE(enc, ptr)) {
-            CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
-case BT_GT: case BT_RPAR: case BT_COMMA:
-case BT_VERBAR: case BT_LSQB: case BT_PERCNT:
-case BT_S: case BT_CR: case BT_LF:
-            *nextTokPtr = ptr;
-            return tok;
-#ifdef XML_NS
-        case BT_COLON:
-            ptr += MINBPC(enc);
-            switch (tok) {
-            case XML_TOK_NAME:
-                if (ptr == end)
-                    return XML_TOK_PARTIAL;
-                tok = XML_TOK_PREFIXED_NAME;
-                switch (BYTE_TYPE(enc, ptr)) {
-                    CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
-                default:
-                    tok = XML_TOK_NMTOKEN;
-                    break;
-                }
-                break;
-            case XML_TOK_PREFIXED_NAME:
-                tok = XML_TOK_NMTOKEN;
-                break;
-            }
-            break;
-#endif
-        case BT_PLUS:
-            if (tok == XML_TOK_NMTOKEN)  {
-                *nextTokPtr = ptr;
-                return XML_TOK_INVALID;
-            }
-            *nextTokPtr = ptr + MINBPC(enc);
-            return XML_TOK_NAME_PLUS;
-        case BT_AST:
-            if (tok == XML_TOK_NMTOKEN)  {
-                *nextTokPtr = ptr;
-                return XML_TOK_INVALID;
-            }
-            *nextTokPtr = ptr + MINBPC(enc);
-            return XML_TOK_NAME_ASTERISK;
-        case BT_QUEST:
-            if (tok == XML_TOK_NMTOKEN)  {
-                *nextTokPtr = ptr;
-                return XML_TOK_INVALID;
-            }
-            *nextTokPtr = ptr + MINBPC(enc);
-            return XML_TOK_NAME_QUESTION;
-        default:
-            *nextTokPtr = ptr;
-            return XML_TOK_INVALID;
-        }
-    }
-    return XML_TOK_PARTIAL;
-}
-
-static
-int PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr, const char *end,
-                              const char **nextTokPtr)
-{
-    const char *start;
-    if (ptr == end)
-        return XML_TOK_NONE;
-    start = ptr;
-    while (ptr != end) {
-        switch (BYTE_TYPE(enc, ptr)) {
-#define LEAD_CASE(n) \
-    case BT_LEAD ## n: ptr += n; break;
-            LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
-#undef LEAD_CASE
-        case BT_AMP:
-            if (ptr == start)
-                return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
-            *nextTokPtr = ptr;
-            return XML_TOK_DATA_CHARS;
-        case BT_LT:
-            /* this is for inside entity references */
-            *nextTokPtr = ptr;
-            return XML_TOK_INVALID;
-        case BT_LF:
-            if (ptr == start) {
-                *nextTokPtr = ptr + MINBPC(enc);
-                return XML_TOK_DATA_NEWLINE;
-            }
-            *nextTokPtr = ptr;
-            return XML_TOK_DATA_CHARS;
-        case BT_CR:
-            if (ptr == start) {
-                ptr += MINBPC(enc);
-                if (ptr == end)
-                    return XML_TOK_TRAILING_CR;
-                if (BYTE_TYPE(enc, ptr) == BT_LF)
-                    ptr += MINBPC(enc);
-                *nextTokPtr = ptr;
-                return XML_TOK_DATA_NEWLINE;
-            }
-            *nextTokPtr = ptr;
-            return XML_TOK_DATA_CHARS;
-        case BT_S:
-            if (ptr == start) {
-                *nextTokPtr = ptr + MINBPC(enc);
-                return XML_TOK_ATTRIBUTE_VALUE_S;
-            }
-            *nextTokPtr = ptr;
-            return XML_TOK_DATA_CHARS;
-        default:
-            ptr += MINBPC(enc);
-            break;
-        }
-    }
-    *nextTokPtr = ptr;
-    return XML_TOK_DATA_CHARS;
-}
-
-static
-int PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr, const char *end,
-                           const char **nextTokPtr)
-{
-    const char *start;
-    if (ptr == end)
-        return XML_TOK_NONE;
-    start = ptr;
-    while (ptr != end) {
-        switch (BYTE_TYPE(enc, ptr)) {
-#define LEAD_CASE(n) \
-    case BT_LEAD ## n: ptr += n; break;
-            LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
-#undef LEAD_CASE
-        case BT_AMP:
-            if (ptr == start)
-                return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
-            *nextTokPtr = ptr;
-            return XML_TOK_DATA_CHARS;
-        case BT_PERCNT:
-            if (ptr == start)
-                return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr);
-            *nextTokPtr = ptr;
-            return XML_TOK_DATA_CHARS;
-        case BT_LF:
-            if (ptr == start) {
-                *nextTokPtr = ptr + MINBPC(enc);
-                return XML_TOK_DATA_NEWLINE;
-            }
-            *nextTokPtr = ptr;
-            return XML_TOK_DATA_CHARS;
-        case BT_CR:
-            if (ptr == start) {
-                ptr += MINBPC(enc);
-                if (ptr == end)
-                    return XML_TOK_TRAILING_CR;
-                if (BYTE_TYPE(enc, ptr) == BT_LF)
-                    ptr += MINBPC(enc);
-                *nextTokPtr = ptr;
-                return XML_TOK_DATA_NEWLINE;
-            }
-            *nextTokPtr = ptr;
-            return XML_TOK_DATA_CHARS;
-        default:
-            ptr += MINBPC(enc);
-            break;
-        }
-    }
-    *nextTokPtr = ptr;
-    return XML_TOK_DATA_CHARS;
-}
-
-static
-int PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
-                       const char **badPtr)
-{
-    ptr += MINBPC(enc);
-    end -= MINBPC(enc);
-    for (; ptr != end; ptr += MINBPC(enc)) {
-        switch (BYTE_TYPE(enc, ptr)) {
-        case BT_DIGIT:
-        case BT_HEX:
-        case BT_MINUS:
-        case BT_APOS:
-        case BT_LPAR:
-        case BT_RPAR:
-        case BT_PLUS:
-        case BT_COMMA:
-        case BT_SOL:
-        case BT_EQUALS:
-        case BT_QUEST:
-        case BT_CR:
-        case BT_LF:
-        case BT_SEMI:
-        case BT_EXCL:
-        case BT_AST:
-        case BT_PERCNT:
-        case BT_NUM:
-#ifdef XML_NS
-        case BT_COLON:
-#endif
-            break;
-        case BT_S:
-            if (CHAR_MATCHES(enc, ptr, '\t')) {
-                *badPtr = ptr;
-                return 0;
-            }
-            break;
-        case BT_NAME:
-        case BT_NMSTRT:
-            if (!(BYTE_TO_ASCII(enc, ptr) & ~0x7f))
-                break;
-        default:
-            switch (BYTE_TO_ASCII(enc, ptr)) {
-            case 0x24: /* $ */
-            case 0x40: /* @ */
-                break;
-            default:
-                *badPtr = ptr;
-                return 0;
-            }
-            break;
-        }
-    }
-    return 1;
-}
-
-/* This must only be called for a well-formed start-tag or empty element tag.
-Returns the number of attributes.  Pointers to the first attsMax attributes 
-are stored in atts. */
-
-static
-int PREFIX(getAtts)(const ENCODING *enc, const char *ptr,
-                    int attsMax, ATTRIBUTE *atts)
-{
-    enum { other, inName, inValue } state = inName;
-    int nAtts = 0;
-    int open = 0;
-
-    for (ptr += MINBPC(enc);; ptr += MINBPC(enc)) {
-        switch (BYTE_TYPE(enc, ptr)) {
-#define START_NAME \
-      if (state == other) { \
-    if (nAtts < attsMax) { \
-      atts[nAtts].name = ptr; \
-      atts[nAtts].normalized = 1; \
-    } \
-    state = inName; \
-      }
-#define LEAD_CASE(n) \
-    case BT_LEAD ## n: START_NAME ptr += (n - MINBPC(enc)); break;
-            LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
-#undef LEAD_CASE
-        case BT_NONASCII:
-        case BT_NMSTRT:
-        case BT_HEX:
-            START_NAME
-            break;
-#undef START_NAME
-        case BT_QUOT:
-            if (state != inValue) {
-                if (nAtts < attsMax)
-                    atts[nAtts].valuePtr = ptr + MINBPC(enc);
-                state = inValue;
-                open = BT_QUOT;
-            }
-            else if (open == BT_QUOT) {
-                state = other;
-                if (nAtts < attsMax)
-                    atts[nAtts].valueEnd = ptr;
-                nAtts++;
-            }
-            break;
-        case BT_APOS:
-            if (state != inValue) {
-                if (nAtts < attsMax)
-                    atts[nAtts].valuePtr = ptr + MINBPC(enc);
-                state = inValue;
-                open = BT_APOS;
-            }
-            else if (open == BT_APOS) {
-                state = other;
-                if (nAtts < attsMax)
-                    atts[nAtts].valueEnd = ptr;
-                nAtts++;
-            }
-            break;
-        case BT_AMP:
-            if (nAtts < attsMax)
-                atts[nAtts].normalized = 0;
-            break;
-        case BT_S:
-            if (state == inName)
-                state = other;
-            else if (state == inValue
-                     && nAtts < attsMax
-                     && atts[nAtts].normalized
-                     && (ptr == atts[nAtts].valuePtr
-                         || BYTE_TO_ASCII(enc, ptr) != ' '
-                         || BYTE_TO_ASCII(enc, ptr + MINBPC(enc)) == ' '
-                         || BYTE_TYPE(enc, ptr + MINBPC(enc)) == open))
-                atts[nAtts].normalized = 0;
-            break;
-    case BT_CR: case BT_LF:
-            /* This case ensures that the first attribute name is counted
-               Apart from that we could just change state on the quote. */
-            if (state == inName)
-                state = other;
-            else if (state == inValue && nAtts < attsMax)
-                atts[nAtts].normalized = 0;
-            break;
-        case BT_GT:
-        case BT_SOL:
-            if (state != inValue)
-                return nAtts;
-            break;
-        default:
-            break;
-        }
-    }
-    /* not reached */
-}
-
-static
-int PREFIX(charRefNumber)(const ENCODING *enc, const char *ptr)
-{
-    int result = 0;
-    /* skip &# */
-    ptr += 2*MINBPC(enc);
-    if (CHAR_MATCHES(enc, ptr, 'x')) {
-        for (ptr += MINBPC(enc); !CHAR_MATCHES(enc, ptr, ';'); ptr += MINBPC(enc)) {
-            int c = BYTE_TO_ASCII(enc, ptr);
-            switch (c) {
-case '0': case '1': case '2': case '3': case '4':
-case '5': case '6': case '7': case '8': case '9':
-                result <<= 4;
-                result |= (c - '0');
-                break;
-case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
-                result <<= 4;
-                result += 10 + (c - 'A');
-                break;
-case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
-                result <<= 4;
-                result += 10 + (c - 'a');
-                break;
-            }
-            if (result >= 0x110000)
-                return -1;
-        }
-    }
-    else {
-        for (; !CHAR_MATCHES(enc, ptr, ';'); ptr += MINBPC(enc)) {
-            int c = BYTE_TO_ASCII(enc, ptr);
-            result *= 10;
-            result += (c - '0');
-            if (result >= 0x110000)
-                return -1;
-        }
-    }
-    return checkCharRefNumber(result);
-}
-
-static
-int PREFIX(predefinedEntityName)(const ENCODING *enc, const char *ptr, const char *end)
-{
-    switch ((end - ptr)/MINBPC(enc)) {
-    case 2:
-        if (CHAR_MATCHES(enc, ptr + MINBPC(enc), 't')) {
-            switch (BYTE_TO_ASCII(enc, ptr)) {
-            case 'l':
-                return '<';
-            case 'g':
-                return '>';
-            }
-        }
-        break;
-    case 3:
-        if (CHAR_MATCHES(enc, ptr, 'a')) {
-            ptr += MINBPC(enc);
-            if (CHAR_MATCHES(enc, ptr, 'm')) {
-                ptr += MINBPC(enc);
-                if (CHAR_MATCHES(enc, ptr, 'p'))
-                    return '&';
-            }
-        }
-        break;
-    case 4:
-        switch (BYTE_TO_ASCII(enc, ptr)) {
-        case 'q':
-            ptr += MINBPC(enc);
-            if (CHAR_MATCHES(enc, ptr, 'u')) {
-                ptr += MINBPC(enc);
-                if (CHAR_MATCHES(enc, ptr, 'o')) {
-                    ptr += MINBPC(enc);
-                    if (CHAR_MATCHES(enc, ptr, 't'))
-                        return '"';
-                }
-            }
-            break;
-        case 'a':
-            ptr += MINBPC(enc);
-            if (CHAR_MATCHES(enc, ptr, 'p')) {
-                ptr += MINBPC(enc);
-                if (CHAR_MATCHES(enc, ptr, 'o')) {
-                    ptr += MINBPC(enc);
-                    if (CHAR_MATCHES(enc, ptr, 's'))
-                        return '\'';
-                }
-            }
-            break;
-        }
-    }
-    return 0;
-}
-
-static
-int PREFIX(sameName)(const ENCODING *enc, const char *ptr1, const char *ptr2)
-{
-    for (;;) {
-        switch (BYTE_TYPE(enc, ptr1)) {
-#define LEAD_CASE(n) \
-    case BT_LEAD ## n: \
-      if (*ptr1++ != *ptr2++) \
-    return 0;
-            LEAD_CASE(4) LEAD_CASE(3) LEAD_CASE(2)
-#undef LEAD_CASE
-            /* fall through */
-            if (*ptr1++ != *ptr2++)
-                return 0;
-            break;
-        case BT_NONASCII:
-        case BT_NMSTRT:
-#ifdef XML_NS
-        case BT_COLON:
-#endif
-        case BT_HEX:
-        case BT_DIGIT:
-        case BT_NAME:
-        case BT_MINUS:
-            if (*ptr2++ != *ptr1++)
-                return 0;
-            if (MINBPC(enc) > 1) {
-                if (*ptr2++ != *ptr1++)
-                    return 0;
-                if (MINBPC(enc) > 2) {
-                    if (*ptr2++ != *ptr1++)
-                        return 0;
-                    if (MINBPC(enc) > 3) {
-                        if (*ptr2++ != *ptr1++)
-                            return 0;
-                    }
-                }
-            }
-            break;
-        default:
-            if (MINBPC(enc) == 1 && *ptr1 == *ptr2)
-                return 1;
-            switch (BYTE_TYPE(enc, ptr2)) {
-            case BT_LEAD2:
-            case BT_LEAD3:
-            case BT_LEAD4:
-            case BT_NONASCII:
-            case BT_NMSTRT:
-#ifdef XML_NS
-            case BT_COLON:
-#endif
-            case BT_HEX:
-            case BT_DIGIT:
-            case BT_NAME:
-            case BT_MINUS:
-                return 0;
-            default:
-                return 1;
-            }
-        }
-    }
-    /* not reached */
-}
-
-static
-int PREFIX(nameMatchesAscii)(const ENCODING *enc, const char *ptr1, const char *ptr2)
-{
-    for (; *ptr2; ptr1 += MINBPC(enc), ptr2++) {
-        if (!CHAR_MATCHES(enc, ptr1, *ptr2))
-            return 0;
-    }
-    switch (BYTE_TYPE(enc, ptr1)) {
-    case BT_LEAD2:
-    case BT_LEAD3:
-    case BT_LEAD4:
-    case BT_NONASCII:
-    case BT_NMSTRT:
-#ifdef XML_NS
-    case BT_COLON:
-#endif
-    case BT_HEX:
-    case BT_DIGIT:
-    case BT_NAME:
-    case BT_MINUS:
-        return 0;
-    default:
-        return 1;
-    }
-}
-
-static
-int PREFIX(nameLength)(const ENCODING *enc, const char *ptr)
-{
-    const char *start = ptr;
-    for (;;) {
-        switch (BYTE_TYPE(enc, ptr)) {
-#define LEAD_CASE(n) \
-    case BT_LEAD ## n: ptr += n; break;
-            LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
-#undef LEAD_CASE
-        case BT_NONASCII:
-        case BT_NMSTRT:
-#ifdef XML_NS
-        case BT_COLON:
-#endif
-        case BT_HEX:
-        case BT_DIGIT:
-        case BT_NAME:
-        case BT_MINUS:
-            ptr += MINBPC(enc);
-            break;
-        default:
-            return ptr - start;
-        }
-    }
-}
-
-static
-const char *PREFIX(skipS)(const ENCODING *enc, const char *ptr)
-{
-    for (;;) {
-        switch (BYTE_TYPE(enc, ptr)) {
-        case BT_LF:
-        case BT_CR:
-        case BT_S:
-            ptr += MINBPC(enc);
-            break;
-        default:
-            return ptr;
-        }
-    }
-}
-
-static
-void PREFIX(updatePosition)(const ENCODING *enc,
-                            const char *ptr,
-                            const char *end,
-                            POSITION *pos)
-{
-    while (ptr != end) {
-        switch (BYTE_TYPE(enc, ptr)) {
-#define LEAD_CASE(n) \
-    case BT_LEAD ## n: \
-      ptr += n; \
-      break;
-            LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
-#undef LEAD_CASE
-        case BT_LF:
-            pos->columnNumber = (unsigned)-1;
-            pos->lineNumber++;
-            ptr += MINBPC(enc);
-            break;
-        case BT_CR:
-            pos->lineNumber++;
-            ptr += MINBPC(enc);
-            if (ptr != end && BYTE_TYPE(enc, ptr) == BT_LF)
-                ptr += MINBPC(enc);
-            pos->columnNumber = (unsigned)-1;
-            break;
-        default:
-            ptr += MINBPC(enc);
-            break;
-        }
-        pos->columnNumber++;
-    }
-}
-
-#undef DO_LEAD_CASE
-#undef MULTIBYTE_CASES
-#undef INVALID_CASES
-#undef CHECK_NAME_CASE
-#undef CHECK_NAME_CASES
-#undef CHECK_NMSTRT_CASE
-#undef CHECK_NMSTRT_CASES
Index: protocols/jabber/xmltok_impl.h
===================================================================
--- protocols/jabber/xmltok_impl.h	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,71 +1,0 @@
-/*
-The contents of this file are subject to the Mozilla Public License
-Version 1.1 (the "License"); you may not use this file except in
-compliance with the License. You may obtain a copy of the License at
-http://www.mozilla.org/MPL/
-
-Software distributed under the License is distributed on an "AS IS"
-basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
-License for the specific language governing rights and limitations
-under the License.
-
-The Original Code is expat.
-
-The Initial Developer of the Original Code is James Clark.
-Portions created by James Clark are Copyright (C) 1998, 1999
-James Clark. All Rights Reserved.
-
-Contributor(s):
-
-Alternatively, the contents of this file may be used under the terms
-of the GNU General Public License (the "GPL"), in which case the
-provisions of the GPL are applicable instead of those above.  If you
-wish to allow use of your version of this file only under the terms of
-the GPL and not to allow others to use your version of this file under
-the MPL, indicate your decision by deleting the provisions above and
-replace them with the notice and other provisions required by the
-GPL. If you do not delete the provisions above, a recipient may use
-your version of this file under either the MPL or the GPL.
-*/
-
-enum {
-  BT_NONXML,
-  BT_MALFORM,
-  BT_LT,
-  BT_AMP,
-  BT_RSQB,
-  BT_LEAD2,
-  BT_LEAD3,
-  BT_LEAD4,
-  BT_TRAIL,
-  BT_CR,
-  BT_LF,
-  BT_GT,
-  BT_QUOT,
-  BT_APOS,
-  BT_EQUALS,
-  BT_QUEST,
-  BT_EXCL,
-  BT_SOL,
-  BT_SEMI,
-  BT_NUM,
-  BT_LSQB,
-  BT_S,
-  BT_NMSTRT,
-  BT_COLON,
-  BT_HEX,
-  BT_DIGIT,
-  BT_NAME,
-  BT_MINUS,
-  BT_OTHER, /* known not to be a name or name start character */
-  BT_NONASCII, /* might be a name or name start character */
-  BT_PERCNT,
-  BT_LPAR,
-  BT_RPAR,
-  BT_AST,
-  BT_PLUS,
-  BT_COMMA,
-  BT_VERBAR
-};
-
-#include <stddef.h>
Index: protocols/jabber/xmltok_ns.c
===================================================================
--- protocols/jabber/xmltok_ns.c	(revision a51be6448b7a6aa100f27873ce40b835068a66a7)
+++ 	(revision )
@@ -1,117 +1,0 @@
-/*
-The contents of this file are subject to the Mozilla Public License
-Version 1.1 (the "License"); you may not use this file except in
-compliance with the License. You may obtain a copy of the License at
-http://www.mozilla.org/MPL/
-
-Software distributed under the License is distributed on an "AS IS"
-basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
-License for the specific language governing rights and limitations
-under the License.
-
-The Original Code is expat.
-
-The Initial Developer of the Original Code is James Clark.
-Portions created by James Clark are Copyright (C) 1998, 1999
-James Clark. All Rights Reserved.
-
-Contributor(s):
-
-*/
-
-const ENCODING *NS(XmlGetUtf8InternalEncoding)()
-{
-    return &ns(internal_utf8_encoding).enc;
-}
-
-const ENCODING *NS(XmlGetUtf16InternalEncoding)()
-{
-#if XML_BYTE_ORDER == 12
-    return &ns(internal_little2_encoding).enc;
-#elif XML_BYTE_ORDER == 21
-return &ns(internal_big2_encoding).enc;
-#else
-const short n = 1;
-    return *(const char *)&n ? &ns(internal_little2_encoding).enc : &ns(internal_big2_encoding).enc;
-#endif
-}
-
-static
-const ENCODING *NS(encodings)[] = {
-    &ns(latin1_encoding).enc,
-    &ns(ascii_encoding).enc,
-    &ns(utf8_encoding).enc,
-    &ns(big2_encoding).enc,
-    &ns(big2_encoding).enc,
-    &ns(little2_encoding).enc,
-    &ns(utf8_encoding).enc /* NO_ENC */
-};
-
-static
-int NS(initScanProlog)(const ENCODING *enc, const char *ptr, const char *end,
-                       const char **nextTokPtr)
-{
-    return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_PROLOG_STATE, ptr, end, nextTokPtr);
-}
-
-static
-int NS(initScanContent)(const ENCODING *enc, const char *ptr, const char *end,
-                        const char **nextTokPtr)
-{
-    return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_CONTENT_STATE, ptr, end, nextTokPtr);
-}
-
-int NS(XmlInitEncoding)(INIT_ENCODING *p, const ENCODING **encPtr, const char *name)
-{
-    int i = getEncodingIndex(name);
-    if (i == UNKNOWN_ENC)
-        return 0;
-    INIT_ENC_INDEX(p) = (char)i;
-    p->initEnc.scanners[XML_PROLOG_STATE] = NS(initScanProlog);
-    p->initEnc.scanners[XML_CONTENT_STATE] = NS(initScanContent);
-    p->initEnc.updatePosition = initUpdatePosition;
-    p->encPtr = encPtr;
-    *encPtr = &(p->initEnc);
-    return 1;
-}
-
-static
-const ENCODING *NS(findEncoding)(const ENCODING *enc, const char *ptr, const char *end)
-{
-#define ENCODING_MAX 128
-    char buf[ENCODING_MAX];
-    char *p = buf;
-    int i;
-    XmlUtf8Convert(enc, &ptr, end, &p, p + ENCODING_MAX - 1);
-    if (ptr != end)
-        return 0;
-    *p = 0;
-    if (streqci(buf, "UTF-16") && enc->minBytesPerChar == 2)
-        return enc;
-    i = getEncodingIndex(buf);
-    if (i == UNKNOWN_ENC)
-        return 0;
-    return NS(encodings)[i];
-}
-
-int NS(XmlParseXmlDecl)(int isGeneralTextEntity,
-                        const ENCODING *enc,
-                        const char *ptr,
-                        const char *end,
-                        const char **badPtr,
-                        const char **versionPtr,
-                        const char **encodingName,
-                        const ENCODING **encoding,
-                        int *standalone)
-{
-    return doParseXmlDecl(NS(findEncoding),
-                          isGeneralTextEntity,
-                          enc,
-                          ptr,
-                          end,
-                          badPtr,
-                          versionPtr,
-                          encodingName,
-                          encoding,
-                          standalone);
-}
Index: protocols/jabber/xmltree.c
===================================================================
--- protocols/jabber/xmltree.c	(revision 0fd8559c4a6ad84ad0852e07c4ba2e50b2fdf0ad)
+++ protocols/jabber/xmltree.c	(revision 0fd8559c4a6ad84ad0852e07c4ba2e50b2fdf0ad)
@@ -0,0 +1,587 @@
+/***************************************************************************\
+*                                                                           *
+*  BitlBee - An IRC to IM gateway                                           *
+*  Simple XML (stream) parse tree handling code (Jabber/XMPP, mainly)       *
+*                                                                           *
+*  Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net>                   *
+*                                                                           *
+*  This library is free software; you can redistribute it and/or            *
+*  modify it under the terms of the GNU Lesser General Public               *
+*  License as published by the Free Software Foundation, version            *
+*  2.1.                                                                     *
+*                                                                           *
+*  This library is distributed in the hope that it will be useful,          *
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU        *
+*  Lesser General Public License for more details.                          *
+*                                                                           *
+*  You should have received a copy of the GNU Lesser General Public License *
+*  along with this library; if not, write to the Free Software Foundation,  *
+*  Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA           *
+*                                                                           *
+****************************************************************************/
+
+#include <glib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdio.h>
+
+#include "xmltree.h"
+
+static void xt_start_element( GMarkupParseContext *ctx, const gchar *element_name, const gchar **attr_names, const gchar **attr_values, gpointer data, GError **error )
+{
+	struct xt_parser *xt = data;
+	struct xt_node *node = g_new0( struct xt_node, 1 ), *nt;
+	int i;
+	
+	node->parent = xt->cur;
+	node->name = g_strdup( element_name );
+	
+	/* First count the number of attributes */
+	for( i = 0; attr_names[i]; i ++ );
+	
+	/* Then allocate a NULL-terminated array. */
+	node->attr = g_new0( struct xt_attr, i + 1 );
+	
+	/* And fill it, saving one variable by starting at the end. */
+	for( i --; i >= 0; i -- )
+	{
+		node->attr[i].key = g_strdup( attr_names[i] );
+		node->attr[i].value = g_strdup( attr_values[i] );
+	}
+	
+	/* Add it to the linked list of children nodes, if we have a current
+	   node yet. */
+	if( xt->cur )
+	{
+		if( xt->cur->children )
+		{
+			for( nt = xt->cur->children; nt->next; nt = nt->next );
+			nt->next = node;
+		}
+		else
+		{
+			xt->cur->children = node;
+		}
+	}
+	else if( xt->root )
+	{
+		/* ERROR situation: A second root-element??? */
+	}
+	
+	/* Now this node will be the new current node. */
+	xt->cur = node;
+	/* And maybe this is the root? */
+	if( xt->root == NULL )
+		xt->root = node;
+}
+
+static void xt_text( GMarkupParseContext *ctx, const gchar *text, gsize text_len, gpointer data, GError **error )
+{
+	struct xt_parser *xt = data;
+	struct xt_node *node = xt->cur;
+	
+	if( node == NULL )
+		return;
+	
+	/* FIXME: Does g_renew also OFFICIALLY accept NULL arguments? */
+	node->text = g_renew( char, node->text, node->text_len + text_len + 1 );
+	memcpy( node->text + node->text_len, text, text_len );
+	node->text_len += text_len;
+	/* Zero termination is always nice to have. */
+	node->text[node->text_len] = 0;
+}
+
+static void xt_end_element( GMarkupParseContext *ctx, const gchar *element_name, gpointer data, GError **error )
+{
+	struct xt_parser *xt = data;
+	
+	xt->cur->flags |= XT_COMPLETE;
+	xt->cur = xt->cur->parent;
+}
+
+GMarkupParser xt_parser_funcs =
+{
+	xt_start_element,
+	xt_end_element,
+	xt_text,
+	NULL,
+	NULL
+};
+
+struct xt_parser *xt_new( gpointer data )
+{
+	struct xt_parser *xt = g_new0( struct xt_parser, 1 );
+	
+	xt->data = data;
+	xt_reset( xt );
+	
+	return xt;
+}
+
+/* Reset the parser, flush everything we have so far. For example, we need
+   this for XMPP when doing TLS/SASL to restart the stream. */
+void xt_reset( struct xt_parser *xt )
+{
+	if( xt->parser )
+		g_markup_parse_context_free( xt->parser );
+	
+	xt->parser = g_markup_parse_context_new( &xt_parser_funcs, 0, xt, NULL );
+	
+	if( xt->root )
+	{
+		xt_free_node( xt->root );
+		xt->root = NULL;
+		xt->cur = NULL;
+	}
+}
+
+/* Feed the parser, don't execute any handler. Returns -1 on errors, 0 on
+   end-of-stream and 1 otherwise. */
+int xt_feed( struct xt_parser *xt, char *text, int text_len )
+{
+	if( !g_markup_parse_context_parse( xt->parser, text, text_len, &xt->gerr ) )
+	{
+		return -1;
+	}
+	
+	return !( xt->root && xt->root->flags & XT_COMPLETE );
+}
+
+/* Find completed nodes and see if a handler has to be called. Passing
+   a node isn't necessary if you want to start at the root, just pass
+   NULL. This second argument is needed for recursive calls. */
+int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth )
+{
+	struct xt_node *c;
+	xt_status st;
+	int i;
+	
+	/* Just in case someone likes infinite loops... */
+	if( xt->root == NULL )
+		return 0;
+	
+	if( node == NULL )
+		return xt_handle( xt, xt->root, depth );
+	
+	if( depth != 0 )
+		for( c = node->children; c; c = c->next )
+			if( !xt_handle( xt, c, depth > 0 ? depth - 1 : depth ) )
+				return 0;
+	
+	if( node->flags & XT_COMPLETE && !( node->flags & XT_SEEN ) )
+	{
+		for( i = 0; xt->handlers[i].func; i ++ )
+		{
+			/* This one is fun! \o/ */
+			
+						/* If handler.name == NULL it means it should always match. */
+			if( ( xt->handlers[i].name == NULL || 
+						/* If it's not, compare. There should always be a name. */
+			      g_strcasecmp( xt->handlers[i].name, node->name ) == 0 ) &&
+						/* If handler.parent == NULL, it's a match. */
+			    ( xt->handlers[i].parent == NULL ||
+						/* If there's a parent node, see if the name matches. */
+			      ( node->parent ? g_strcasecmp( xt->handlers[i].parent, node->parent->name ) == 0 : 
+						/* If there's no parent, the handler should mention <root> as a parent. */
+			                       g_strcasecmp( xt->handlers[i].parent, "<root>" ) == 0 ) ) )
+			{
+				st = xt->handlers[i].func( node, xt->data );
+				
+				if( st == XT_ABORT )
+					return 0;
+				else if( st != XT_NEXT )
+					break;
+			}
+		}
+		
+		node->flags |= XT_SEEN;
+	}
+	
+	return 1;
+}
+
+/* Garbage collection: Cleans up all nodes that are handled. Useful for
+   streams because there's no reason to keep a complete packet history
+   in memory. */
+void xt_cleanup( struct xt_parser *xt, struct xt_node *node, int depth )
+{
+	struct xt_node *c, *prev;
+	
+	if( !xt || !xt->root )
+		return;
+	
+	if( node == NULL )
+		return xt_cleanup( xt, xt->root, depth );
+	
+	if( node->flags & XT_SEEN && node == xt->root )
+	{
+		xt_free_node( xt->root );
+		xt->root = xt->cur = NULL;
+		/* xt->cur should be NULL already, BTW... */
+		
+		return;
+	}
+	
+	/* c contains the current node, prev the previous node (or NULL).
+	   I admit, this one's pretty horrible. */
+	for( c = node->children, prev = NULL; c; prev = c, c = c ? c->next : node->children )
+	{
+		if( c->flags & XT_SEEN )
+		{
+			/* Remove the node from the linked list. */
+			if( prev )
+				prev->next = c->next;
+			else
+				node->children = c->next;
+			
+			xt_free_node( c );
+			
+			/* Since the for loop wants to get c->next, make sure
+			   c points at something that exists (and that c->next
+			   will actually be the next item we should check). c
+			   can be NULL now, if we just removed the first item.
+			   That explains the ? thing in for(). */
+			c = prev;
+		}
+		else
+		{
+			/* This node can't be cleaned up yet, but maybe a
+			   subnode can. */
+			if( depth != 0 )
+				xt_cleanup( xt, c, depth > 0 ? depth - 1 : depth );
+		}
+	}
+}
+
+static void xt_to_string_real( struct xt_node *node, GString *str )
+{
+	char *buf;
+	struct xt_node *c;
+	int i;
+	
+	g_string_append_printf( str, "<%s", node->name );
+	
+	for( i = 0; node->attr[i].key; i ++ )
+	{
+		buf = g_markup_printf_escaped( " %s=\"%s\"", node->attr[i].key, node->attr[i].value );
+		g_string_append( str, buf );
+		g_free( buf );
+	}
+	
+	if( node->text == NULL && node->children == NULL )
+	{
+		g_string_append( str, "/>" );
+		return;
+	}
+	
+	g_string_append( str, ">" );
+	if( node->text_len > 0 )
+	{
+		buf = g_markup_escape_text( node->text, node->text_len );
+		g_string_append( str, buf );
+		g_free( buf );
+	}
+	
+	for( c = node->children; c; c = c->next )
+		xt_to_string_real( c, str );
+	
+	g_string_append_printf( str, "</%s>", node->name );
+}
+
+char *xt_to_string( struct xt_node *node )
+{
+	GString *ret;
+	char *real;
+	
+	ret = g_string_new( "" );
+	xt_to_string_real( node, ret );
+	
+	real = ret->str;
+	g_string_free( ret, FALSE );
+	
+	return real;
+}
+
+void xt_print( struct xt_node *node )
+{
+	int i;
+	struct xt_node *c;
+	
+	/* Indentation */
+	for( c = node; c->parent; c = c->parent )
+		printf( "\t" );
+	
+	/* Start the tag */
+	printf( "<%s", node->name );
+	
+	/* Print the attributes */
+	for( i = 0; node->attr[i].key; i ++ )
+		printf( " %s=\"%s\"", node->attr[i].key, g_markup_escape_text( node->attr[i].value, -1 ) );
+	
+	/* /> in case there's really *nothing* inside this tag, otherwise
+	   just >. */
+	/* If this tag doesn't have any content at all... */
+	if( node->text == NULL && node->children == NULL )
+	{
+		printf( "/>\n" );
+		return;
+		/* Then we're finished! */
+	}
+	
+	/* Otherwise... */
+	printf( ">" );
+	
+	/* Only print the text if it contains more than whitespace (TEST). */
+	if( node->text_len > 0 )
+	{
+		for( i = 0; node->text[i] && isspace( node->text[i] ); i ++ );
+		if( node->text[i] )
+			printf( "%s", g_markup_escape_text( node->text, -1 ) );
+	}
+	
+	if( node->children )
+		printf( "\n" );
+	
+	for( c = node->children; c; c = c->next )
+		xt_print( c );
+	
+	if( node->children )
+		for( c = node; c->parent; c = c->parent )
+			printf( "\t" );
+	
+	/* Non-empty tag is now finished. */
+	printf( "</%s>\n", node->name );
+}
+
+struct xt_node *xt_dup( struct xt_node *node )
+{
+	struct xt_node *dup = g_new0( struct xt_node, 1 );
+	struct xt_node *c, *dc = NULL;
+	int i;
+	
+	/* Let's NOT copy the parent element here BTW! Only do it for children. */
+	
+	dup->name = g_strdup( node->name );
+	dup->flags = node->flags;
+	if( node->text )
+	{
+		dup->text = g_memdup( node->text, node->text_len + 1 );
+		dup->text_len = node->text_len;
+	}
+	
+	/* Count the number of attributes and allocate the new array. */
+	for( i = 0; node->attr[i].key; i ++ );
+	dup->attr = g_new0( struct xt_attr, i + 1 );
+	
+	/* Copy them all! */
+	for( i --; i >= 0; i -- )
+	{
+		dup->attr[i].key = g_strdup( node->attr[i].key );
+		dup->attr[i].value = g_strdup( node->attr[i].value );
+	}
+	
+	/* This nice mysterious loop takes care of the children. */
+	for( c = node->children; c; c = c->next )
+	{
+		if( dc == NULL )
+			dc = dup->children = xt_dup( c );
+		else
+			dc = ( dc->next = xt_dup( c ) );
+		
+		dc->parent = dup;
+	}
+	
+	return dup;
+}
+
+/* Frees a node. This doesn't clean up references to itself from parents! */
+void xt_free_node( struct xt_node *node )
+{
+	int i;
+	
+	if( !node )
+		return;
+	
+	g_free( node->name );
+	g_free( node->text );
+	
+	for( i = 0; node->attr[i].key; i ++ )
+	{
+		g_free( node->attr[i].key );
+		g_free( node->attr[i].value );
+	}
+	g_free( node->attr );
+	
+	while( node->children )
+	{
+		struct xt_node *next = node->children->next;
+		
+		xt_free_node( node->children );
+		node->children = next;
+	}
+	
+	g_free( node );
+}
+
+void xt_free( struct xt_parser *xt )
+{
+	if( !xt )
+		return;
+	
+	if( xt->root )
+		xt_free_node( xt->root );
+	
+	g_markup_parse_context_free( xt->parser );
+	
+	g_free( xt );
+}
+
+/* To find a node's child with a specific name, pass the node's children
+   list, not the node itself! The reason you have to do this by hand: So
+   that you can also use this function as a find-next. */
+struct xt_node *xt_find_node( struct xt_node *node, char *name )
+{
+	while( node )
+	{
+		if( g_strcasecmp( node->name, name ) == 0 )
+			break;
+		
+		node = node->next;
+	}
+	
+	return node;
+}
+
+char *xt_find_attr( struct xt_node *node, char *key )
+{
+	int i;
+	
+	if( !node )
+		return NULL;
+	
+	for( i = 0; node->attr[i].key; i ++ )
+		if( g_strcasecmp( node->attr[i].key, key ) == 0 )
+			break;
+	
+	return node->attr[i].value;
+}
+
+struct xt_node *xt_new_node( char *name, char *text, struct xt_node *children )
+{
+	struct xt_node *node, *c;
+	
+	node = g_new0( struct xt_node, 1 );
+	node->name = g_strdup( name );
+	node->children = children;
+	node->attr = g_new0( struct xt_attr, 1 );
+	
+	if( text )
+	{
+		node->text_len = strlen( text );
+		node->text = g_memdup( text, node->text_len + 1 );
+	}
+	
+	for( c = children; c; c = c->next )
+	{
+		if( c->parent != NULL )
+		{
+			/* ERROR CONDITION: They seem to have a parent already??? */
+		}
+		
+		c->parent = node;
+	}
+	
+	return node;
+}
+
+void xt_add_child( struct xt_node *parent, struct xt_node *child )
+{
+	struct xt_node *node;
+	
+	/* This function can actually be used to add more than one child, so
+	   do handle this properly. */
+	for( node = child; node; node = node->next )
+	{
+		if( node->parent != NULL )
+		{
+			/* ERROR CONDITION: They seem to have a parent already??? */
+		}
+		
+		node->parent = parent;
+	}
+	
+	if( parent->children == NULL )
+	{
+		parent->children = child;
+	}
+	else
+	{
+		for( node = parent->children; node->next; node = node->next );
+		node->next = child;
+	}
+}
+
+void xt_add_attr( struct xt_node *node, char *key, char *value )
+{
+	int i;
+	
+	/* Now actually it'd be nice if we can also change existing attributes
+	   (which actually means this function doesn't have the right name).
+	   So let's find out if we have this attribute already... */
+	for( i = 0; node->attr[i].key; i ++ )
+		if( strcmp( node->attr[i].key, key ) == 0 )
+			break;
+	
+	if( node->attr[i].key == NULL )
+	{
+		/* If not, allocate space for a new attribute. */
+		node->attr = g_renew( struct xt_attr, node->attr, i + 2 );
+		node->attr[i].key = g_strdup( key );
+		node->attr[i+1].key = NULL;
+	}
+	else
+	{
+		/* Otherwise, free the old value before setting the new one. */
+		g_free( node->attr[i].value );
+	}
+	
+	node->attr[i].value = g_strdup( value );
+}
+
+int xt_remove_attr( struct xt_node *node, char *key )
+{
+	int i, last;
+	
+	for( i = 0; node->attr[i].key; i ++ )
+		if( strcmp( node->attr[i].key, key ) == 0 )
+			break;
+	
+	/* If we didn't find the attribute... */
+	if( node->attr[i].key == NULL )
+		return 0;
+	
+	g_free( node->attr[i].key );
+	g_free( node->attr[i].value );
+	
+	/* If it's the last, this is easy: */
+	if( node->attr[i+1].key == NULL )
+	{
+		node->attr[i].key = node->attr[i].value = NULL;
+	}
+	else /* It's also pretty easy, actually. */
+	{
+		/* Find the last item. */
+		for( last = i + 1; node->attr[last+1].key; last ++ );
+		
+		node->attr[i] = node->attr[last];
+		node->attr[last].key = NULL;
+		node->attr[last].value = NULL;
+	}
+	
+	/* Let's not bother with reallocating memory here. It takes time and
+	   most packets don't stay in memory for long anyway. */
+	
+	return 1;
+}
Index: protocols/jabber/xmltree.h
===================================================================
--- protocols/jabber/xmltree.h	(revision 0fd8559c4a6ad84ad0852e07c4ba2e50b2fdf0ad)
+++ protocols/jabber/xmltree.h	(revision 0fd8559c4a6ad84ad0852e07c4ba2e50b2fdf0ad)
@@ -0,0 +1,97 @@
+/***************************************************************************\
+*                                                                           *
+*  BitlBee - An IRC to IM gateway                                           *
+*  Simple XML (stream) parse tree handling code (Jabber/XMPP, mainly)       *
+*                                                                           *
+*  Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net>                   *
+*                                                                           *
+*  This library is free software; you can redistribute it and/or            *
+*  modify it under the terms of the GNU Lesser General Public               *
+*  License as published by the Free Software Foundation, version            *
+*  2.1.                                                                     *
+*                                                                           *
+*  This library is distributed in the hope that it will be useful,          *
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU        *
+*  Lesser General Public License for more details.                          *
+*                                                                           *
+*  You should have received a copy of the GNU Lesser General Public License *
+*  along with this library; if not, write to the Free Software Foundation,  *
+*  Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA           *
+*                                                                           *
+****************************************************************************/
+
+#ifndef _XMLTREE_H
+#define _XMLTREE_H
+
+typedef enum
+{
+	XT_COMPLETE	= 1,	/* </tag> reached */
+	XT_SEEN		= 2,	/* Handler called (or not defined) */
+} xt_flags;
+
+typedef enum
+{
+	XT_ABORT,		/* Abort, don't handle the rest anymore */
+	XT_HANDLED,		/* Handled this tag properly, go to the next one */
+	XT_NEXT			/* Try if there's another matching handler */
+} xt_status;
+
+struct xt_attr
+{
+	char *key, *value;
+};
+
+struct xt_node
+{
+	struct xt_node *parent;
+	struct xt_node *children;
+	
+	char *name;
+	struct xt_attr *attr;
+	char *text;
+	int text_len;
+	
+	struct xt_node *next;
+	xt_flags flags;
+};
+
+typedef xt_status (*xt_handler_func) ( struct xt_node *node, gpointer data );
+
+struct xt_handler_entry
+{
+	char *name, *parent;
+	xt_handler_func func;
+};
+
+struct xt_parser
+{
+	GMarkupParseContext *parser;
+	struct xt_node *root;
+	struct xt_node *cur;
+	
+	struct xt_handler_entry *handlers;
+	gpointer data;
+	
+	GError *gerr;
+};
+
+struct xt_parser *xt_new( gpointer data );
+void xt_reset( struct xt_parser *xt );
+int xt_feed( struct xt_parser *xt, char *text, int text_len );
+int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth );
+void xt_cleanup( struct xt_parser *xt, struct xt_node *node, int depth );
+char *xt_to_string( struct xt_node *node );
+void xt_print( struct xt_node *node );
+struct xt_node *xt_dup( struct xt_node *node );
+void xt_free_node( struct xt_node *node );
+void xt_free( struct xt_parser *xt );
+struct xt_node *xt_find_node( struct xt_node *node, char *name );
+char *xt_find_attr( struct xt_node *node, char *key );
+
+struct xt_node *xt_new_node( char *name, char *text, struct xt_node *children );
+void xt_add_child( struct xt_node *parent, struct xt_node *child );
+void xt_add_attr( struct xt_node *node, char *key, char *value );
+int xt_remove_attr( struct xt_node *node, char *key );
+
+#endif
