View Issue Details

IDProjectCategoryView StatusLast Update
0000326LDMud 3.3Efunspublic2009-10-06 04:37
ReporterlarsAssigned To 
PrioritynormalSeverityfeatureReproducibilityN/A
Status closedResolutionwon't fix 
Summary0000326: XML Support
DescriptionA question was asked whether it would be feasible to add XML support to the driver.

As it turns out, Gawain has done work in that direction - the resulting diff is attached.
Additional InformationChristian wrote:

There is already an implementation of xml parser for ldmud.
The code can be found here : http://rb.mud.de/~gawain/xml3.diff
The patch uses the iksemel library for parsing the xml and provides
some methods to the mud to geh access to the parser.
The patch was orginally develeloped at the time, as we discussed
about jabber as new intermud-protocol.
The code was written by Peng or Dafire, i cant remember exactly,
i only did some cleanup and comments.
This patch also supports the handling of xml-streams after RFC 3920.

Bastian added:

The main intention to create the patch was the stream feature of the iksemel
library. With this patch it's really easy to connect to an xmpp server to
communicate to other clients :) A really small lpc jabber client is included
;)

There are also mapping2xml-string and xmlstring2mapping functions and the
library is also error checking the xml data.

What I always wanted to add is that the driver opens a port and connections
to that connections to this port get bound to an lpc object but since the
jabber-intermud idea was going down I stopped development of the patch and
went over to my driver-sqlite patch :)
TagsNo tags attached.

Relationships

related to 0000538 resolvedGnomi New Package pkg-iksemel for driver that adds xml_parse() as well as xml_generate() (using libiksemel) 

Activities

2004-12-18 15:11

 

xml3.diff (31,545 bytes)   
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
xml3.diff (31,545 bytes)   

lynx

2009-05-22 03:43

reporter   ~0001128

psyclpc also has a pkg-expat, so you can choose which XML/XMPP engine to use.

Fell free to merge that back into LDMUD...

fufu

2009-05-23 15:47

manager   ~0001146

That would be our third xml package now. (see 0000538)

I'm inclined to close this bug as wontfix.

Gnomi

2009-05-23 18:32

manager   ~0001150

This is different as it supports XML streams. It's not about different libraries for parsing XML, but about another interface. And as such I don't like it. (If anything at all, then XML stream support should be incorporated into the comm.c subsystem as a special input parsing routine.)

So I agree closing this as wontfix.

Issue History

Date Modified Username Field Change
2004-12-18 15:11 lars New Issue
2004-12-18 15:11 lars File Added: xml3.diff
2008-12-14 10:34 Gnomi Relationship added related to 0000538
2009-05-22 03:43 lynx Note Added: 0001128
2009-05-23 15:47 fufu Note Added: 0001146
2009-05-23 18:32 Gnomi Note Added: 0001150
2009-06-01 07:39 zesstra Project LDMud => LDMud 3.3
2009-10-06 04:37 zesstra Status new => closed
2009-10-06 04:37 zesstra Resolution open => won't fix