diff -Naur 3-3.orig/mudlib/jabber.c 3-3/mudlib/jabber.c
--- 3-3.orig/mudlib/jabber.c	1970-01-01 01:00:00.000000000 +0100
+++ 3-3/mudlib/jabber.c	2004-07-13 09:17:38.000000000 +0200
@@ -0,0 +1,214 @@
+#include "sys/input_to.h"
+
+#define OUT(x) tell_object(this_object(),x)
+
+mapping roster=([]);
+#define R_NAME 0
+#define R_SUBS 1
+#define R_GROUP 2
+#define R_STAT 3
+
+int stat;
+// 0 not connected
+// 1 connected 
+// 2 logged in / unav
+// 3 logged in / av
+
+void send(string name, mapping send)
+{
+  xml_send(name,send);
+}
+
+void pass(string password,string username)
+{
+  send("iq",([ "type":"set";1, 
+        "id":"authme";1, 
+        "query":(["xmlns":"jabber:iq:auth";1,
+                 "username":username;0,
+                 "password":password;0,
+                 "resource":"ldjabber";0,
+                 ]);0 
+     ]));
+     OUT("\n");
+}
+
+int f_login(string str)
+{
+  OUT("Username: "+str+"\n");
+  input_to("pass",INPUT_PROMPT|INPUT_NOECHO,"Password: ",str); 
+  return 1;
+}
+
+void splitjid(string jid, string name, string server, string res)
+{
+   sscanf(jid,"%s@%s/%s",name,server,res);
+}
+
+void got_presence(mapping data)
+{
+  string name,server,res,sjid;
+  splitjid(data["from"],&name,&server,&res);
+  sjid=name+"@"+server;
+  switch(data["type"]) {
+    case "unavailable":
+      if (member(roster,sjid))
+        {
+           OUT(sprintf("%s(%s) ist nun unavailable.\n",roster[sjid,R_NAME],data["from"])); 
+           roster[sjid,R_STAT]=0;
+        } else {
+           OUT(sprintf("%s ist nun unavailable.\n",data["from"])); 
+        }
+
+    break;
+    default:
+      if (member(roster,sjid))
+        {
+           OUT(sprintf("%s(%s) ist nun %s\n",roster[sjid,R_NAME],data["from"],data["status"])); 
+           roster[sjid,R_STAT]=data["status"];
+        } else {
+           OUT(sprintf("%s ist nun %s\n",data["from"],data["status"])); 
+        }
+
+    //  OUT(sprintf("PRESENCE: (%O)  %O\n",data["status"],data));
+  }
+}
+
+void got_iq(mapping data)
+{
+  switch(data["type"])
+  {
+    case "error":
+      OUT(sprintf("Fehler %s : %s\n",data["error"]["code"],data["error"]["_"]));
+      break;
+    case "result":
+      if (data["id"]=="authme")
+      {
+        stat=2;
+        OUT("angemeldet\nStatus: unavailable\nLade Roster...\n");
+        send("presence",([ "type":"unavailable";1 ]));
+        send("iq",([ "type":"get";1, "id":"daroster";1, "query":(["xmlns":"jabber:iq:roster";1]);0 ]));
+      }
+      if (data["id"]=="daroster")
+      {
+         if(mappingp(data["query"]["item"]))
+         {
+            roster+=([ data["query"]["item"]["jid"] : data["query"]["item"]["name"];data["query"]["item"]["subscription"];data["query"]["item"]["group"];0  ]); 
+         }
+         if (pointerp(data["query"]["item"]))
+         {
+            foreach(mapping item:data["query"]["item"])
+              roster+=([ item["jid"] : item["name"];item["subscription"];item["group"];0  ]);
+         }
+         OUT("Roster geladen.\n");
+      }
+      break;
+      default:
+       OUT(sprintf("IQ: (%s|%s)  %O\n",data["type"],data["id"],data)); 
+   
+   }
+}
+
+
+void callback(mixed typ,string name,mixed data)
+{
+ // tell_object(this_object(),sprintf("C:%O %O %O\n",typ,name,data));
+  OUT(sprintf("CB: %d %s\n",typ,name));
+  switch (typ)
+  {
+    case 0:
+      OUT("Verbunden mit Server.\n");
+      stat=1;
+      break;
+    case 1:
+      call_other(this_object(),"got_"+name,data);
+      break;
+    break;
+  }
+}
+
+string prompt()
+{
+  switch (stat)
+  {
+    case 0:
+      return "disconnected> ";
+    case 1:
+      return "connected> ";
+    case 2:
+      return "unavailable> ";
+    case 3: 
+      return "avaible> ";
+    default:
+      return "> ";
+  }
+}    
+
+static nomask mixed logon ()
+{
+    set_max_commands(3);
+    debug_message(sprintf("%O: logon()\n", this_object()));
+    enable_commands();
+    add_action("f_help", "help");
+    add_action("f_quit", "quit");
+    add_action("f_connect","connect");
+    add_action("f_login","login");
+    add_action("f_roster","roster");
+    add_action("f_online","available",-2);
+    add_action("f_offline","unavailable",-4);
+    set_prompt(#'prompt);
+  //   write("init: "+xml_new_stream("jabber:client",#'callback)+"\n");
+  
+    xml_new_stream("jabber:client",#'callback);
+    return 1; // To verify that the connection was accepted.
+}
+
+int f_online()
+{
+  OUT("Sende Presence 'Online'\n");
+  send("presence",([ "priority":"1" ]));  
+  stat=3;
+  return 1;
+}
+
+int f_offline()
+{
+  OUT("Sende Presence 'Unavailable'\n");
+  send("presence",([ "type":"unavailable";1 ]));  
+  stat=2;
+  return 1;
+}
+
+int f_roster()
+{
+  OUT(sprintf("%O\n",roster));
+  return 1;
+}
+
+int f_connect()
+{
+   write("connect neoagency.org:"+xml_connect("neoagency.org",5222)+"\n");
+   return 1;
+}
+
+
+int f_help (string arg)
+{
+    debug_message(sprintf("%O: f_help()\n", this_object()));
+    write(
+"  help     - Prints this message\n"
+"  quit     - terminates the connection, but leaves the driver running\n"
+"  connect roster avaiable unavaiable \n"
+    );
+    return 1;
+}
+int f_quit (string arg)
+
+// The 'quit' command.
+
+{
+    debug_message(sprintf("%O: f_quit()\n", this_object()));
+    write("Bye-bye.\n");
+    destruct(this_object());
+    return 1;
+}
+
diff -Naur 3-3.orig/mudlib/jabbermaster.c 3-3/mudlib/jabbermaster.c
--- 3-3.orig/mudlib/jabbermaster.c	1970-01-01 01:00:00.000000000 +0100
+++ 3-3/mudlib/jabbermaster.c	2004-07-13 09:17:38.000000000 +0200
@@ -0,0 +1,153 @@
+/* Test Master.c
+ *
+ * Minimal master.c to provide a very rudimentary test of the gamedriver.
+ * To perform the test, cd to the directory this file is in and give the
+ * command
+ *    driver -N -e -m. -Mtest_master.c -s-1 -sv-1 4242
+ * (this assumes that you called the gamedriver 'driver' and that it is
+ * in your searchpath).
+ * Once it's running, telnet to localhost, port 4242. You should be
+ * connected to the driver now and be able to enter commands.
+ * The command 'help' will list you the commands available.
+ *
+ * A second test consists of the simple command
+ *    driver --version
+ * The driver shall just print the version and exit immediately.
+ */
+
+//---------------------------------------------------------------------------
+void inaugurate_master (int arg)
+
+// Initialise the master object.
+// We have to set the uid hooks, otherwise we can't clone a login object.
+
+{
+    set_driver_hook(2, unbound_lambda(({}), "uid"));
+    set_driver_hook(3, unbound_lambda(({}), "uid"));
+    set_driver_hook(10, "What?\n");
+#ifdef NOECHO
+    set_driver_hook(13, "telnetneg");
+    set_driver_hook(14, "set_noecho");
+#endif
+}
+
+//---------------------------------------------------------------------------
+int old_flag;
+
+void set_noecho(int flag)
+{
+    if (flag & ~old_flag & 1)
+    {
+        write("sending IAC WILL ECHO\n");
+        binary_message(({ 0xff, 0xfb, 0x01 })); // IAC WILL ECHO
+    }
+    else if (old_flag & ~flag & 1)
+    {
+        write("sending IAC WONT ECHO\n");
+        binary_message(({ 0xff, 0xfc, 0x01 })); // IAC WONT ECHO
+    }
+    if (flag & ~old_flag & 2)
+    {
+        write("sending IAC WILL+DO SGA\n");
+        binary_message(({ 0xff, 0xfb, 0x03 })); // IAC WILL SGA
+        binary_message(({ 0xff, 0xfd, 0x03 })); // IAC DO SGA
+    }
+    else if (old_flag & ~flag & 2)
+    {
+        write("sending IAC WONT+DONT SGA\n");
+        binary_message(({ 0xff, 0xfc, 0x03 })); // IAC WONT SGA
+        binary_message(({ 0xff, 0xfe, 0x03 })); // IAC DONT SGA
+    }
+    old_flag = flag;
+} /* set_noecho() */
+
+void telnetneg(int a, int b, int* c)
+{
+    // just ignore, should work with linux telnet
+    printf("got %d %d %O\n", a,b,c);
+}
+
+//---------------------------------------------------------------------------
+string get_master_uid()
+
+// Return the master uid.
+{
+    return " R O O T ";
+}
+
+//---------------------------------------------------------------------------
+
+void callback(mixed typ,mixed xml)
+{
+  debug_message(sprintf("\n\nCALLBACK %O:%O\n\n",typ,xml));  
+}
+
+void flag (string arg)
+
+// Evaluate an argument given as option '-f' to the driver.
+
+{
+    if (arg == "test")
+    {
+        /* Insert your test code here */
+        return;
+    }
+ 
+    if (arg == "gc")
+    {
+        garbage_collection();
+        return;
+    }
+
+    if (arg == "dhry")
+    {
+        limited( (: load_object("dhrystone")->main(1000) :) );
+        shutdown();
+        return;
+    }
+
+    if (arg == "dhry2")
+    {
+        limited( (: load_object("dhrystone2")->main(1000) :) );
+        shutdown();
+        return;
+    }
+
+    if (arg == "shutdown")
+    {
+        shutdown();
+        return;
+    }
+    write ("master: Unknown flag "+arg+"\n");
+}
+
+//---------------------------------------------------------------------------
+mixed prepare_destruct (object obj)
+
+// Prepare the destruction of the object.
+
+{
+    debug_message(sprintf("%O: prepare_destruct(%O)\n", this_object(), obj));
+    return 0;
+}
+
+//---------------------------------------------------------------------------
+object connect ()
+
+// Handle the request for a new connection.
+// We simply return a clone of ourself (we can't simply return this object
+// unfortunately), the gamedriver will then call logon() here.
+
+{
+    object obj;
+    debug_message(sprintf("%O: connect()\n", this_object()));
+    obj = clone_object("jabber.c");
+    return obj;
+}
+
+//---------------------------------------------------------------------------
+
+int privilege_violation (string op, mixed who, mixed arg, mixed arg2)
+{
+  return 1;
+}
diff -Naur 3-3.orig/mudlib/test_master.c 3-3/mudlib/test_master.c
--- 3-3.orig/mudlib/test_master.c	2003-03-26 07:55:29.000000000 +0100
+++ 3-3/mudlib/test_master.c	2004-07-13 09:17:38.000000000 +0200
@@ -68,27 +68,20 @@
 }
 
 //---------------------------------------------------------------------------
-string get_simul_efun ()
-
-// Load the simul-efun object "/sefun" if existing and return its pathname.
+string get_master_uid()
 
+// Return the master uid.
 {
-    object sefun;
-
-    if (!catch(sefun = load_object("/sefun")))
-        return object_name(sefun);
-    return 0;
+    return " R O O T ";
 }
 
 //---------------------------------------------------------------------------
-string get_master_uid()
 
-// Return the master uid.
+void callback(mixed typ,mixed xml)
 {
-    return " R O O T ";
+  debug_message(sprintf("\n\nCALLBACK %O:%O\n\n",typ,xml));  
 }
 
-//---------------------------------------------------------------------------
 void flag (string arg)
 
 // Evaluate an argument given as option '-f' to the driver.
@@ -99,7 +92,30 @@
         /* Insert your test code here */
         return;
     }
+ 
+    if (arg == "xml3")
+    {
+	    printf("\n%O\n\n",xml_generate( "message",(["unode":(["un1":1,"un2":2]),"b":"6","x":0]) ));
+	    return;
+    }
 
+    if (arg == "xml2")
+    {
+       string s;
+       s="<message from='a@b' to='c@d'><body>blah></body></message>";
+       printf("\n%O\n\n",xml_parse(s));
+      return;
+    }
+    if (arg == "xml")
+    {
+      string s;
+      s="<message type='chat' from='bob@bd.com'><subject>song lyric</subject><priority>high</priority>"
+        "<body><em style='underline'>here is the correct version:</em>i just don't see why i should even care"
+        "it s not dark yet, but it's getting there</body></message>";
+	    printf("\n%O\n\n",xml_parse(s));
+	    return;
+    }
+    
     if (arg == "gc")
     {
         garbage_collection();
diff -Naur 3-3.orig/src/autoconf/acconfig.h 3-3/src/autoconf/acconfig.h
--- 3-3.orig/src/autoconf/acconfig.h	2004-05-16 20:12:38.000000000 +0200
+++ 3-3/src/autoconf/acconfig.h	2004-07-13 08:28:12.000000000 +0200
@@ -90,6 +90,9 @@
 /* Does the machine's iconv take a non-const 'char**' as first arg? */
 #undef HAS_ICONV_NONCONST_IN
 
+/* Does the machine offer iksemel? */
+#undef HAS_IKSEMEL
+
 /* Does the machine offer mySQL? */
 #undef HAS_MYSQL
 
diff -Naur 3-3.orig/src/autoconf/configure.in 3-3/src/autoconf/configure.in
--- 3-3.orig/src/autoconf/configure.in	2004-05-24 06:12:36.000000000 +0200
+++ 3-3/src/autoconf/configure.in	2004-07-13 09:09:55.000000000 +0200
@@ -122,6 +122,7 @@
 AC_MY_ARG_ENABLE(use-pgsql,no,,[Enables PostgreSQL support])
 AC_MY_ARG_ENABLE(use-pthreads,no,,[enable using of threads for socket writes])
 AC_MY_ARG_ENABLE(use-pcre,yes,,[Enables PCRE instead of traditional regexps])
+AC_MY_ARG_ENABLE(use-iksemel,no,,[Enables usage of libiksemel for XML parsing])
 AC_MY_ARG_ENABLE(use-deprecated,yes,,[Enables obsolete and deprecated efuns])
 AC_MY_ARG_ENABLE(use-structs,yes,,[Enables structs])
 AC_MY_ARG_ENABLE(use-tls,no,,[Enables Transport Layer Security over Telnet: no/gnu/ssl/yes])
@@ -302,6 +303,7 @@
 AC_CDEF_FROM_ENABLE(use_alists)
 AC_CDEF_FROM_ENABLE(use_mccp)
 AC_CDEF_FROM_ENABLE(use_pcre)
+AC_CDEF_FROM_ENABLE(use_iksemel)
 AC_CDEF_FROM_ENABLE(use_pthreads)
 AC_CDEF_FROM_ENABLE(use_ipv6)
 AC_CDEF_FROM_ENABLE(use_deprecated)
@@ -982,6 +984,68 @@
     CFLAGS="$saveflags"
 ))
 
+# --- iksemel ---
+
+AC_CACHE_CHECK(for iksemel,lp_cv_has_iksemel,
+    saveflags="$CFLAGS"
+    AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <iksemel.h>
+
+int foo(void)
+{
+    return IKS_OK;
+}
+    ],,lp_cv_has_iksemel=yes,
+    lp_cv_has_iksemel=no
+    CFLAGS="$saveflags"
+))
+
+if test $lp_cv_has_iksemel = yes; then
+    saveflags="$CFLAGS"
+    savelibs="$LIBS"
+
+    AC_DEFINE(HAS_IKSEMEL)
+
+    AC_CACHE_CHECK(if -liksemel needed, lp_cv_need_lib_iksemel,
+        AC_TRY_RUN([
+#include <sys/types.h>
+#include <iksemel.h>
+#include <stdio.h>
+void t (void)
+{
+    size_t len;
+    len = iks_strlen(NULL);
+}
+int main(void)
+{
+    return 0;
+}
+        ],
+        lp_cv_need_lib_iksemel=no,
+        lp_cv_need_lib_iksemel=yes
+    ))
+    if test "$lp_cv_need_lib_iksemel" = "yes"; then
+        lp_cv_has_lib_iksemel=no
+        AC_CHECK_LIB(iksemel,exit,
+                     LIBS="$savelibs -liksemel"
+                     lp_cv_has_lib_iksemel=yes
+                    )
+    fi
+
+    if test $enable_use_iksemel = no; then
+        LIBS="$savelibs"
+    fi
+
+else
+    if test $enable_use_iksemel = yes; then
+        echo "iksemel not supported - disabling iksemel support."
+        AC_NOT_AVAILABLE(use-iksemel)
+    fi
+    cdef_use_iksemel="#undef"
+    enable_use_iksemel=no
+fi
+
 # --- iconv ---
 
 AC_CACHE_CHECK(for mySQL,lp_cv_has_iconv,
@@ -2385,6 +2449,7 @@
 AC_SUBST(cdef_use_alists)
 AC_SUBST(cdef_use_mccp)
 AC_SUBST(cdef_use_pcre)
+AC_SUBST(cdef_use_iksemel)
 AC_SUBST(cdef_use_deprecated)
 AC_SUBST(cdef_use_structs)
 AC_SUBST(cdef_use_tls)
diff -Naur 3-3.orig/src/comm.c 3-3/src/comm.c
--- 3-3.orig/src/comm.c	2004-07-13 08:15:14.000000000 +0200
+++ 3-3/src/comm.c	2004-07-13 09:17:38.000000000 +0200
@@ -128,6 +128,7 @@
 #include "object.h"
 #include "pkg-mccp.h"
 #include "pkg-pgsql.h"
+#include "pkg-iksemel.h"
 #ifdef USE_TLS
 #include "pkg-tls.h"
 #endif
@@ -2550,6 +2551,10 @@
             pg_setfds(&readfds, &writefds, &nfds);
 #endif
 
+#ifdef USE_IKSEMEL
+            iks_setfds(&readfds, &writefds, &nfds);
+#endif
+
             /* select() until time is up or there is data */
 
             for (retries = 6;;)
@@ -2631,6 +2636,10 @@
             pg_process_all();
 #endif
 
+#ifdef USE_IKSEMEL
+            iks_process_all(&readfds);
+#endif
+
             /* Initialise the user scan */
             CmdsGiven = 0;
             NextCmdGiver = StartCmdGiver;
diff -Naur 3-3.orig/src/config.h.in 3-3/src/config.h.in
--- 3-3.orig/src/config.h.in	2004-05-26 05:32:18.000000000 +0200
+++ 3-3/src/config.h.in	2004-07-13 09:17:38.000000000 +0200
@@ -341,6 +345,10 @@
  */
 @cdef_use_pcre@ USE_PCRE
 
+/* Define this if you want iksemel library support.
+ */
+@cdef_use_iksemel@ USE_IKSEMEL
+
 /* Define this if you want the obsolete and deprecated efuns.
  */
 @cdef_use_deprecated@ USE_DEPRECATED
diff -Naur 3-3.orig/src/func_spec 3-3/src/func_spec
--- 3-3.orig/src/func_spec	2004-05-23 09:08:21.000000000 +0200
+++ 3-3/src/func_spec	2004-07-13 09:17:38.000000000 +0200
@@ -680,6 +680,18 @@
 #endif /* USE_MCCP */
 
 
+#ifdef USE_IKSEMEL
+
+string  xml_generate(string,mapping);
+mapping xml_parse(string);
+int     xml_new_stream(string,string|closure, ...);
+int     xml_connect(string,int);
+int     xml_disconnect();
+int     xml_send(string,mapping);
+
+#endif /* USE_IKSEMEL */
+
+
 #ifdef USE_MYSQL
 
 int     db_affected_rows(int);
diff -Naur 3-3.orig/src/Makefile.in 3-3/src/Makefile.in
--- 3-3.orig/src/Makefile.in	2004-07-13 08:15:14.000000000 +0200
+++ 3-3/src/Makefile.in	2004-07-13 09:18:33.000000000 +0200
@@ -82,8 +82,8 @@
       interpret.c \
       lex.c main.c mapping.c md5.c mempools.c mregex.c mstrings.c object.c \
       otable.c\
-      parser.c parse.c pkg-alists.c pkg-mccp.c pkg-mysql.c pkg-pcre.c \
-      pkg-pgsql.c pkg-tls.c \
+      parser.c parse.c pkg-alists.c pkg-iksemel.c pkg-mccp.c pkg-mysql.c \
+      pkg-pcre.c pkg-pgsql.c pkg-tls.c \
       ptmalloc.c port.c ptrtable.c \
       random.c regexp.c sha1.c simulate.c simul_efun.c stdstrings.c \
       strfuns.c structs.c sprintf.c swap.c wiz_list.c xalloc.c 
@@ -93,8 +93,8 @@
       interpret.o \
       lex.o main.o mapping.o md5.o mempools.o mregex.o mstrings.o object.o \
       otable.o \
-      parser.o parse.o pkg-alists.o pkg-mccp.o pkg-mysql.o pkg-pcre.o \
-      pkg-pgsql.o pkg-tls.o \
+      parser.o parse.o pkg-alists.o pkg-iksemel.o pkg-mccp.o pkg-mysql.o \
+      pkg-pcre.o pkg-pgsql.o pkg-tls.o \
       ptmalloc.o port.o ptrtable.o \
       random.o regexp.o sha1.o simulate.o simul_efun.o stdstrings.o \
       strfuns.o structs.o sprintf.o swap.o wiz_list.o xalloc.o @ALLOCA@ 
diff -Naur 3-3.orig/src/pkg-iksemel.c 3-3/src/pkg-iksemel.c
--- 3-3.orig/src/pkg-iksemel.c	1970-01-01 01:00:00.000000000 +0100
+++ 3-3/src/pkg-iksemel.c	2004-07-13 09:17:38.000000000 +0200
@@ -0,0 +1,569 @@
+#include "config.h"
+#ifdef USE_IKSEMEL
+
+#include <stdio.h>
+#include <iksemel.h>
+#include "typedefs.h"
+#include "my-alloca.h"
+#include <errno.h>
+#include <stddef.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdio.h>
+#include "actions.h"
+#include "array.h"
+#include "interpret.h"
+#include "mstrings.h"
+#include "simulate.h"
+#include "svalue.h"
+#include "xalloc.h"
+#include "object.h"
+#include "stdstrings.h"
+#include "mapping.h"
+
+void parse_node(svalue_t *sp, iks *node, int flag);
+iks *xml_generate(char *name, mapping_t *map,iks *parentnode);
+int xml_callback(void *userdata,int typ,iks *node);
+
+void 
+add_str_to_map(mapping_t *map,char *skey,char *sval,int flag)
+{
+  svalue_t key,*value;
+  vector_t *vec;
+  put_c_string(&key,skey);
+  value = get_map_lvalue(map,&key);
+  free_svalue(&key);
+  switch(value->type)
+  {
+    case T_NUMBER:
+      put_c_string(value,sval);
+      break; 
+    case T_STRING:
+      vec = allocate_array(2);
+      vec->item[0]=*value;
+      put_c_string(&vec->item[1],sval);
+      put_array(value,vec);
+      break;
+    case T_POINTER:
+      vec = allocate_array(1);
+      put_c_string(&vec->item[0],sval);
+      put_array(value,add_array(value->u.vec,vec));
+      break;
+    default:
+      printf("___BAAAAD____BAAAAD____astm\n");
+  }
+}
+
+void add_node_to_map(mapping_t *map,char *skey,iks *node,int flag)
+{
+  svalue_t key,*value;
+  vector_t *vec;
+  put_c_string(&key,skey);
+  value = get_map_lvalue(map,&key);
+  free_svalue(&key);
+  switch(value->type)
+  {
+    case T_NUMBER:
+      parse_node(value,node,flag);
+      break;
+    case T_STRING:
+    case T_MAPPING:
+      vec = allocate_array(2);
+      vec->item[0]=*value;
+      parse_node(&vec->item[1],node,flag);
+      put_array(value,vec);
+      break;
+    case T_POINTER:
+      vec = allocate_array(1);
+      parse_node(&vec->item[0],node,flag);
+      put_array(value,add_array(value->u.vec,vec));
+      break;
+    default:
+      printf("___BAAAAD____BAAAAD____antm\n");
+  }
+}
+
+void 
+parse_node(svalue_t *sp, iks *node,int flag)
+{
+	mapping_t *map=NULL;
+	int children=0;
+	int attribs=0;
+	iks *child;
+	iks *attrib;
+
+  if ((attrib=iks_attrib(node)))
+  {
+    attribs=1; 
+    while((attrib=iks_next(attrib)))
+	     ++attribs;
+  }  	
+	
+	if ((child=iks_child(node)))
+	{
+	   children=1;
+	   while((child=iks_next(child)))
+	     ++children;
+	}
+	     	   
+	if ((child=iks_child(node)))
+	{
+
+      while(child)
+      {
+   	   switch(iks_type(child))
+	      {
+	         case IKS_CDATA:
+	            if ((children==1)&&(attribs==0))
+	            {
+	               put_c_string(sp,iks_cdata(child));
+	            } else {
+	               if (!map) map=allocate_mapping(children+attribs,1);
+	               add_str_to_map(map,"_",iks_cdata(child),flag);
+	            }
+	            break;
+   	      case IKS_TAG:
+         	   if (!map) map=allocate_mapping(children+attribs,1);
+         	   add_node_to_map(map,iks_name(child),child,flag);       	   
+	           put_mapping(sp,map);
+   	         break;
+	      }
+	      child=iks_next(child);
+	     }
+	    }
+	     if ((attrib=iks_attrib(node)))
+        {
+	      while(attrib)
+        {
+   	      switch(iks_type(attrib))
+	          {
+	             case IKS_CDATA:
+                 if (!map) map=allocate_mapping(children+attribs,1);
+                 add_str_to_map(map,"content",iks_cdata(attrib),flag);
+                 break;
+   	           case IKS_TAG:
+            	   if (!map) map=allocate_mapping(children+attribs,1);
+            	   add_node_to_map(map,iks_name(attrib),attrib,flag);       	   
+	               put_mapping(sp,map);
+   	             break;
+   	           case IKS_ATTRIBUTE:
+   	             if (!map) map=allocate_mapping(children+attribs,1);
+   	             add_str_to_map(map,iks_name(attrib),iks_cdata(attrib),flag);       	   
+	               put_mapping(sp,map);
+	               break;
+	          } 
+	      
+	      attrib=iks_next(attrib);
+	     }
+	}
+}
+
+typedef struct mapwalk_extra_s mapwalk_extra_t;
+
+struct mapwalk_extra_s {
+  iks *node;
+  int size;
+};
+
+void xml_generate_helper(svalue_t *key, svalue_t *val, void *pextra)
+{
+  char buf[1024];
+  char *ckey=NULL;
+  int dfree=0,i;
+  mapwalk_extra_t *extra=pextra;
+  
+  buf[sizeof(buf)-1] = '\0';
+  
+  switch(key->type)
+  {
+    case T_NUMBER:
+      ckey=malloc(1024*sizeof(char));
+      dfree=1;
+      ckey[sizeof(ckey)-1] = '\0';
+      sprintf(ckey,"%ld", key->u.number);
+      if (ckey[sizeof(ckey)-1] != '\0')
+          fatal("Buffer overflow in xml_generate(): "
+                "int number too big.\n");
+      break;
+    case T_STRING:
+      ckey=get_txt(key->u.str);
+      break;
+    default:
+    // error waere nicht schlecht aber dann leaken wir :/
+      return;
+  }
+  
+  switch(val->type)
+  {
+    case T_NUMBER:
+      if (val->u.number==0)
+      {
+        iks_insert(extra->node, ckey);
+      } else {
+        sprintf(buf,"%ld", val->u.number);
+        if (buf[sizeof(buf)-1] != '\0')
+            fatal("Buffer overflow in xml_generate(): "
+                  "int number too big.\n");
+        iks_insert_cdata(iks_insert(extra->node, ckey),buf,0);
+      }
+      break;
+    case T_STRING:
+      if ((extra->size>1)&&((val+1)->type==T_NUMBER)&&((val+1)->u.number==1))
+      {
+      	iks_insert_attrib(extra->node,ckey,get_txt(val->u.str));
+      } else {
+        iks_insert_cdata(iks_insert(extra->node, ckey),get_txt(val->u.str),0);
+      }
+      break;
+    case T_MAPPING:
+      xml_generate(ckey,val->u.map,extra->node);
+      break;
+    case T_POINTER:
+      for (i=val->u.vec->size;i--;)
+      {
+       	xml_generate_helper(key,&val->u.vec->item[i],extra->node);
+      }
+      break;
+    default:
+      printf("_________BAD:(________\n");
+  }
+  
+  if (dfree) free(ckey);
+  
+}
+
+void xml_gen_walk_mapping(mapping_t *m,void *node)
+{
+   mapwalk_extra_t *extra;
+   extra=malloc(sizeof(mapwalk_extra_t));
+   extra->node=node;
+   extra->size=m->num_values;
+   walk_mapping (m,&xml_generate_helper,extra);
+   free(extra);
+}
+
+iks *xml_generate(char *name, mapping_t *map,iks *parentnode)
+{
+  iks *node;
+  if (parentnode)
+    node=iks_insert(parentnode,name);
+  else 
+    node=iks_new(name);
+  xml_gen_walk_mapping (map,node);
+  return node;
+}
+
+svalue_t *
+f_xml_generate(svalue_t *sp)
+{
+  iks *node;
+  char *name;
+  name=get_txt((sp-1)->u.str);
+  node=xml_generate(name,sp->u.map,NULL);
+  free_svalue(sp);
+  --sp;
+  free_svalue(sp);
+  put_c_string(sp,iks_string(iks_stack(node),node));
+  iks_delete(node);
+  return sp;
+}
+
+svalue_t *
+f_xml_parse(svalue_t * sp)
+{
+  iks *x = NULL;
+  iksparser *p;
+
+  // TODO:
+  int flag=0;
+  
+  p=iks_dom_new(&x);
+  if (IKS_OK!=iks_parse(p,get_txt(sp->u.str),0,1)) {
+    printf("parse error\n");
+  }
+  if (x)
+  {
+     if (iks_child(x)) 
+     {
+       free_svalue(sp);
+       parse_node(sp,x,flag);
+     }
+  }
+  iks_delete(x);
+  return sp;
+} 
+
+/*****************************************************************************/
+/*                                xml stream zeugs                             */
+/*****************************************************************************/
+
+typedef struct xml_parser_s xml_parser_t;
+
+struct xml_parser_s 
+{
+    iksparser    *parser;
+    int           fd;
+    callback_t    callback;
+    xml_parser_t *next;
+};
+
+static xml_parser_t *head = NULL;
+
+xml_parser_t 
+*alloc_xml_parser(char *namespace, callback_t cb)
+{
+  xml_parser_t *tmp;
+  
+  memsafe(tmp = xalloc(sizeof(*tmp)), sizeof(*tmp), "new xml iksparser");
+  tmp->next=head;
+  tmp->parser=iks_stream_new(namespace,tmp,&xml_callback);
+  tmp->callback=cb;  
+  tmp->fd=-1;
+  head=tmp;
+  return tmp;
+}
+
+void
+loghook(void* user_data, const char* data, size_t size, int is_incoming)
+{
+   printf("\n--- %d\n%s\n---\n",is_incoming,data); 
+}
+
+void
+dealloc_xml_parser(xml_parser_t *del)
+{
+    xml_parser_t *ptr;
+
+    if (!del)
+      return;
+
+    free_callback(&del->callback);
+
+    if (del == head)
+    {
+        head = head->next;
+    }
+    else
+    {
+        ptr = head;
+        while (ptr->next && (ptr->next != del))
+            ptr = ptr->next;
+        if (ptr->next)
+            ptr->next = ptr->next->next;
+    }
+    
+    //TODO: bei fd>0 erst connection closen ?
+    
+  //  iks_free(del->parser);
+
+    iks_parser_delete(del->parser);
+    xfree(del);
+}
+
+
+xml_parser_t *
+find_parser (object_t * obj) 
+{
+    xml_parser_t *tmp=NULL;
+    if (!head) return NULL;
+    else tmp = head;
+ 
+    while (tmp)
+    {
+       if (obj==callback_object(&tmp->callback)) return tmp;
+       tmp=tmp->next;
+    }
+    return NULL;
+}
+
+
+int 
+xml_callback(void *userdata,int typ,iks *node)
+{
+   xml_parser_t *xml=userdata;
+   char *xmlstr;
+   current_object = callback_object(&xml->callback);
+   if (!current_object) return 0;
+   command_giver = 0;
+   current_interactive = 0;
+   push_number(inter_sp,typ);
+   push_c_string(inter_sp,iks_name(node));
+   xmlstr=iks_string(iks_stack(node),node);
+   parse_node(++inter_sp,node,0);
+   iks_delete(node);
+   (void)apply_callback(&xml->callback,3);
+   return IKS_OK;
+}
+
+svalue_t *
+v_xml_new_stream(svalue_t *sp, int num_arg)
+{
+  char *namespace;
+  int error_index;
+  callback_t  cb;
+  object_t   *cb_object;
+  svalue_t   *arg = sp - num_arg + 1;
+    /* Get the callback information */
+
+    error_index = setup_efun_callback(&cb, arg+1, num_arg-1);
+
+    if (error_index >= 0)
+    {
+        vefun_bad_arg(error_index+2, arg);
+        /* NOTREACHED */
+        return arg;
+    }
+    inter_sp = sp = arg+1;
+    put_callback(sp, &cb);
+
+    cb_object = callback_object(&cb);
+    if (!cb_object)
+    {
+        free_callback(&cb);
+        error("...(): Callback object is destructed.\n");
+        /* NOTREACHED */
+        return arg;
+    }
+    
+    namespace=get_txt(arg[0].u.str);
+    free_svalue(arg);
+
+    alloc_xml_parser(namespace,cb);
+
+    put_number(arg,0);
+
+    return arg;
+}
+
+svalue_t *
+f_xml_connect(svalue_t *sp)
+{
+  xml_parser_t *xml;
+  char *server;
+  int port;
+  
+  port=sp->u.number;
+  free_svalue(sp);
+  --sp;
+  server=get_txt(sp->u.str);
+  free_svalue(sp);
+  
+  if (!(xml=find_parser(current_object)))
+  {
+     put_number(sp,1);
+     return sp;  
+  }
+
+  if (xml->fd > -1)
+  {
+     put_number(sp,2);
+     return sp;  
+  }  
+
+  iks_connect_tcp(xml->parser,server,port);
+  
+  xml->fd=iks_fd(xml->parser);
+  
+  //TODO TEMP:
+  iks_set_log_hook(xml->parser,&loghook);
+  
+  put_number(sp,0);
+  return sp;
+}
+
+svalue_t *
+f_xml_send(svalue_t *sp)
+{
+  iks *node;
+  char *name;
+  xml_parser_t *xml;
+  
+  if (!(xml=find_parser(current_object)))
+  {
+     error("xml_send: not initialised & not connected\n");  
+     return sp;  
+  }
+
+  if (xml->fd < 0)
+  {
+     error("xml_send: not connected\n");  
+     return sp;  
+  }  
+  
+  name=get_txt((sp-1)->u.str);
+  node=xml_generate(name,sp->u.map,NULL);
+  free_svalue(sp);
+  --sp;
+  free_svalue(sp);
+  iks_send(xml->parser,node);
+  iks_delete(node);
+  return sp;
+}
+
+
+svalue_t *
+f_xml_disconnect(svalue_t *sp)
+{
+  printf("TODO:\n");
+  put_number(sp,1);
+  return sp;
+}
+
+void
+iks_setfds (fd_set *readfds, fd_set *writefds, int *nfds)
+
+/* Called from the get_message() loop in comm.c, this function has to add
+ * the fds of the database connections to the fd sets.
+ */
+
+{
+  xml_parser_t *ptr;
+  for (ptr = head; ptr != NULL; ptr = ptr->next)
+    if (ptr->fd>0)
+      FD_SET(ptr->fd, readfds);
+}
+
+void
+iks_process_all (fd_set *readfds)
+
+/* Called from the get_message() loop in comm.c, this function checks
+ * all known database connections for their status and takes appropriate
+ * actions.
+ */
+
+{
+  Bool got_dead = MY_FALSE;
+  xml_parser_t *ptr;
+  object_t *obj;
+  ptr=head;
+  while (ptr)
+  {
+    // Something to read ?
+  
+    obj=callback_object(&ptr->callback);
+    
+    if (!obj) got_dead=MY_TRUE;
+    
+    if (ptr->fd>0) // geht nicht :( : &&FD_ISSET(ptr->fd,readfds))
+      iks_recv(ptr->parser,0);
+      
+    ptr = ptr->next;     
+  }  
+  
+  if (got_dead)
+  {
+    ptr = head;
+    while (ptr)
+    {
+      if (!callback_object(&ptr->callback))
+      {
+        dealloc_xml_parser(ptr);
+        ptr=NULL;
+      }
+      else 
+        ptr = ptr->next;
+    }
+  }
+}
+
+#endif /* USE_IKSEMEL */
diff -Naur 3-3.orig/src/pkg-iksemel.h 3-3/src/pkg-iksemel.h
--- 3-3.orig/src/pkg-iksemel.h	1970-01-01 01:00:00.000000000 +0100
+++ 3-3/src/pkg-iksemel.h	2004-07-13 09:17:38.000000000 +0200
@@ -0,0 +1,14 @@
+#ifndef PKG_IKSEMEL_H__
+#define PKG_IKSEMEL_H__ 1
+
+#include "driver.h"
+
+#ifdef USE_IKSEMEL
+
+extern void iks_setfds(fd_set *readfds, fd_set *writefds, int *nfds);
+extern void iks_process_all(fd_set *readfds);
+
+#endif /* USE_IKSEMEL */
+
+#endif /* PKG_IKSEMEL_H__ */
+
diff -Naur 3-3.orig/src/main.c 3-3/src/main.c
--- 3-3.orig/src/main.c 2004-07-11 05:44:48.000000000 +0200
+++ 3-3/src/main.c      2004-07-13 10:25:01.000000000 +0200
@@ -1658,6 +1658,9 @@
     /* Print the package options, nicely indented. */
     {
         char * optstrings[] = { "" /* have at least one string in here */
+#ifdef USE_IKSEMEL
+                              , "iksemel supported\n"
+#endif
 #ifdef USE_IPV6
                               , "IPv6 supported\n"
 #endif
