mlwmohawk               Sat Jan 28 02:29:55 2006 UTC

  Added files:                 
    /php-src/ext/xmldbx CREDITS config.m4 php_xmldbx.h sessionxml.php 
                        xmldbx.c xmldbx.h xmldbx.php 
  Log:
  Added
  
  
http://cvs.php.net/viewcvs.cgi/php-src/ext/xmldbx/config.m4?view=markup&rev=1.1
Index: php-src/ext/xmldbx/config.m4
+++ php-src/ext/xmldbx/config.m4
dnl
dnl $Id: config.m4,v 1.1 2006/01/28 02:29:54 mlwmohawk Exp $
dnl

PHP_ARG_ENABLE(xmldbx,whether to enable XMLdbX support,
[  --enable-xmldbx           Enable XMLdbX support.])

if test "$PHP_XMLDBX" != "no"; then
  if test "$ext_shared" != "yes" && test "$enable_xml" = "no"; then
    AC_MSG_WARN(Activating XML)
    enable_xml=yes
  fi
  AC_DEFINE(HAVE_XMLDBX, 1, [ ])
  PHP_NEW_EXTENSION(xmldbx, xmldbx.c, $ext_shared)
fi

http://cvs.php.net/viewcvs.cgi/php-src/ext/xmldbx/php_xmldbx.h?view=markup&rev=1.1
Index: php-src/ext/xmldbx/php_xmldbx.h
+++ php-src/ext/xmldbx/php_xmldbx.h
/*
   +----------------------------------------------------------------------+
   | PHP Version 4                                                        |
   +----------------------------------------------------------------------+
   | Copyright (c) 1997-2003 The PHP Group                                |
   +----------------------------------------------------------------------+
   | This source file is subject to version 2.02 of the PHP license,      |
   | that is bundled with this package in the file LICENSE, and is        |
   | available at through the world-wide-web at                           |
   | http://www.php.net/license/2_02.txt.                                 |
   | If you did not receive a copy of the PHP license and are unable to   |
   | obtain it through the world-wide-web, please send a note to          |
   | [EMAIL PROTECTED] so we can mail you a copy immediately.               |
   +----------------------------------------------------------------------+
   | Credits: Andrei Zmievski <[EMAIL PROTECTED]> (wddx)                     |
   | Author: Mark Woodward <markw@mohawksoft.com>                         |
   +----------------------------------------------------------------------+
 */

/* $Id: php_xmldbx.h,v 1.1 2006/01/28 02:29:54 mlwmohawk Exp $ */

#ifndef PHP_XMLDBX_H
#define PHP_XMLDBX_H

#if HAVE_XMLDBX

extern zend_module_entry xmldbx_module_entry;
#define xmldbx_module_ptr &xmldbx_module_entry

PHP_FUNCTION(xmldbx_serialize);
PHP_FUNCTION(xmldbx_deserialize);

int xmldbx_deserialize_xml(zval **zret, const char *value, int vallen);
char *xmldbx_serialize_xml(char *name, zval **obj);

#define XMLDBX_MOHAWK

#else

#define xmldbx_module_ptr NULL

#endif /* HAVE_XMLDBX */

#define phpext_xmldbx_ptr xmldbx_module_ptr

#endif /* !PHP_XMLDBX_H */

http://cvs.php.net/viewcvs.cgi/php-src/ext/xmldbx/sessionxml.php?view=markup&rev=1.1
Index: php-src/ext/xmldbx/sessionxml.php
+++ php-src/ext/xmldbx/sessionxml.php
<?
#       sessionxml.php
#       Test xmldbx session serializer
#
class MyClass
{
        var $count;
        var $mybool;
        var $mystring;
        
        function print_vars()
        {
                print "count = " . $this->count . "<br>\n";
                print "bybool = " . $this->mybool . "<br>\n";
                print "mystring = " . $this->mystring . "<br>\n";

                $this->count++;
                if($this->mybool == True)
                        $this->mybool = False;
                else
                        $this->mybool = True;
                $this->mystring = $this->mystring . "+";
        }
};
                
        
# Start sessions, this will set a cookie.
session_start();

session_register("count");
session_register("setarray");
session_register("mycls");
session_register("myinit");


if(!$myinit)
{
        $mycls = new MyClass();
        $myinit = true;
}

$count++;
if($count < 2)
{
        $_SESSION['setarray'] = array();
        $_SESSION['setarray']['time']=time();
        $_SESSION['setarray']['name1'] = 'xml_test1';
        $_SESSION['setarray']['name2'] = 'xml_test2';
        $_SESSION['setarray']['name3'] = 'xml_test3';
        $_SESSION['setarray']['name4'] = 'xml_test4';
        $_SESSION['setarray']['name5'] = 'xml_test5';
        $_SESSION['setarray']['name6'] = 'xml_test6';
        $_SESSION['setarray']['name7'] = 'xml_test7';
}

echo $_SESSION['setarray']['name1'] . "<br>\n";
echo $_SESSION['setarray']['name2'] . "<br>\n";
echo $_SESSION['setarray']['name3'] . "<br>\n";
echo $_SESSION['setarray']['name4'] . "<br>\n";
echo $_SESSION['setarray']['name5'] . "<br>\n";
echo $_SESSION['setarray']['name6'] . "<br>\n";
echo $_SESSION['setarray']['name7']  . "<br>\n";


$mycls->print_vars();

# Output some information.
echo "sid: " . $sid . "<br>\n";
echo "Session Count: " . $count . "<br>\n";


?>


http://cvs.php.net/viewcvs.cgi/php-src/ext/xmldbx/xmldbx.c?view=markup&rev=1.1
Index: php-src/ext/xmldbx/xmldbx.c
+++ php-src/ext/xmldbx/xmldbx.c
/*
   +----------------------------------------------------------------------+
   | XMLDBX 1.0                                                           |
   +----------------------------------------------------------------------+
   | Copyright (c) 1997-2003 The PHP Group                                |
   +----------------------------------------------------------------------+
   | This source file is subject to version 2.02 of the PHP license,      |
   | that is bundled with this package in the file LICENSE, and is        |
   | available at through the world-wide-web at                           |
   | http://www.php.net/license/2_02.txt.                                 |
   | If you did not receive a copy of the PHP license and are unable to   |
   | obtain it through the world-wide-web, please send a note to          |
   | [EMAIL PROTECTED] so we can mail you a copy immediately.               |
   +----------------------------------------------------------------------+
   | Credits: Andrei Zmievski <[EMAIL PROTECTED]> (wddx)                     |
   | Author: Mark Woodward <markw@mohawksoft.com>                         |
   +----------------------------------------------------------------------+
 */
/*
 XMLDBX is a virtually complete re-write of WDDX.
 The problem wddx tried to address, XML PHP session storage, is a 
 valid one, only that wddx failed to provide much more than a 
 theoretical proof that it could be done. I have to applaud Andrei 
 for the work he did, writing a serializer must be a PITA if you do 
 not deal with Zend on a day to day basis. I used wddx extensively as
 a reference while writing xmldbx.

 When all is said and done, the wddx code was not exactly what I 
 needed. I have a very different coding style and found the original 
 wddx code lacking some basic modularity. My needs were more extensive, 
 first, the wddx module was too verbose. This was really a problem if 
 you had large amounts of session information, most of the actual data 
 storage was XML formatting. XMLDBX does a few things differently, it 
 flatens types to a single XML tag, using attributes for meta data. 
 Second, it uses the variable name as the tag, not the type. The type is 
 added as an attribute. One thing that is done that is questionable is 
 using a value ("v") attribute to convey the value. This is nothing more 
 than a space saver, and can be altered by removeing the XMLDBX_COMPACT_VARS 
 define value, this will force all data to be put between "begin" and 
 "end" tags.

 Mark L. Woodward <markw@mohawksoft.com>, 2005
 Documentation and new version can be found at:
 http://www.mohawksoft.org

 1/19/2006
 Add "REFERENCE" type to XML stream and it should be ignored by all but PHP
 I guess. It seems Squirrelmail uses self referencing data strutuctures for
 session information.
 My management of reference types is imperfect as it relys on a parent child 
 relationship to multiple references of a single variable, parallel references 
 are not found, although that could be done if I replace the stack paradigm
 with a list and keep track of each and every variable on serialize and
 deserialize. Yuck!!
 
 1/26/2006
 Finally got a grip on zval referencing crap, I had to add a total
 of 3 new attributes, REFCOUNT, ISREF, and REFERENCE. I Use the hex address of
 a zval as its reference id and send that out in XML. Each subsequent reference
 to the same value emits a REFERENCE type with the hex reference id. At the
 xml decoder stage, if a variable has a REFERENCE attribute, it is pushed on the
 zval stack and later searched when a REFERENCE type is encountered in the XML
 stream.

*/

/* $Id: xmldbx.c,v 1.1 2006/01/28 02:29:54 mlwmohawk Exp $ */

// Needed to compile on PHP
#define XMLDBX_USING_PHP
// Enable PHP callable functions
#define HAS_PHP_XMLDBX_FUNCTIONS
// Enable debugging messages
// #define ERR_DEBUG_EXTRA
// #define ERR_DEBUG
// #define DUMP_DEBUG
// #define EMBED_DEBUG
// #define ZVAL_DEBUG
#define LOG_BAD_PARSE

#include "php.h"
#include "php_xmldbx.h"

#if !defined (HAVE_LIBEXPAT) && !defined(LIBXML_EXPAT_COMPAT) 
#ifndef PHP_EXPAT_COMPAT_H
#include <expat.h>
#endif
#endif

#if HAVE_XMLDBX
#include "xmldbx.h"
#define PHP_XML_INTERNAL
#ifndef XmlParse_INCLUDED
#include "ext/xml/php_xml.h"
#endif
#include "ext/standard/php_incomplete_class.h"
#include "ext/standard/base64.h"
#include "ext/standard/info.h"
#include "ext/standard/php_smart_str.h"
#include "ext/standard/html.h"
#include "ext/standard/php_string.h"
// #include "ext/standard/php_parsedate.h"

// Forwards
static int EnumArray(zval *obj, EnumArrayCallback fn, void *p1, void *p2);
static void     xmldbx_data_handler(void *user_data, const XML_Char *s, int 
len);
static void     xmldbx_start(XMLDBXBUF *xmlbuf);
static void     xmldbx_end(XMLDBXBUF *xmlbuf);
static XMLDBXBUF *xmldbx_constructor(void);
static void     xmldbx_destructor(XMLDBXBUF *xmlbuf);
static void     xmldbx_serialize_var(XMLDBXBUF *xmlbuf, zval *var, char *name, 
int name_len TSRMLS_DC);
static char *   xmldbx_open_var(XMLDBXBUF *xmlbuf, int ntype, char *name, char 
*classname, int len, char *entra);
static void     xmldbx_close_var(XMLDBXBUF *xmlbuf, char *name);
static int xmldbx_bad_name(char *src);

static char *xmldbx_types[]={
        XT_NULL,                // 0
        XT_LONG,                // 1
        XT_DOUBLE,              // 2
        XT_STRING,              // 3
        XT_ARRAY,               // 4
        XT_OBJECT,              // 5
        XT_BOOLEAN,             // 6
        XT_RESOURCE,            // 7
        XT_CONSTANT,            // 8
        XT_CONSTANT_ARRAY,      // 9
        XT_REFERENCE,           // 10
        XT_NAME,                // 11
        XT_IGNORE               // 12
};

static char xmldbx_empty_string[]="";

#define ALLOCMEM(cb)    emalloc(cb)
#define PALLOCMEM(cb)   pemalloc(cb,0)
#define FREEMEM(p)      efree(p);       
#define PFREEMEM(p)     pefree(p,0);

#define ZDTOR(z)        zval_dtor(z)
#define ZDTORP(z)       zval_ptr_dtor(z)

/* {{{ xmldbx_functions[]
 */
function_entry xmldbx_functions[] = {
#ifdef HAS_PHP_XMLDBX_FUNCTIONS
        PHP_FE(xmldbx_serialize, NULL)
        PHP_FE(xmldbx_deserialize, NULL)
#endif
        {NULL, NULL, NULL}
};
/* }}} */
PHP_MINIT_FUNCTION(xmldbx);
PHP_MINFO_FUNCTION(xmldbx);
/* {{{ xmldbx_module_entry
 */
zend_module_entry xmldbx_module_entry = {
        STANDARD_MODULE_HEADER,
        "xmldbx",
        xmldbx_functions,
        PHP_MINIT(xmldbx),
        NULL,
        NULL,
        NULL,
        PHP_MINFO(xmldbx),
        NO_VERSION_YET,
        STANDARD_MODULE_PROPERTIES
};
/* }}} */

/* {{{ dynamically loadable module stuff */
#ifdef COMPILE_DL_XMLDBX
ZEND_GET_MODULE(xmldbx)
#endif /* COMPILE_DL_XMLDBX */
/* }}} */

/* {{{ xmldbx_logf
 * Uses printf syntax to write to php_log_err
 * Must remain in ERR_DEBUG ifdef to ensure it
 * does not get compiled into release code
 */
static void xmldbx_logf(char *fmt, ...)
{
        va_list arglist;
        static char buffer[4096];
        va_start(arglist, fmt);
        vsnprintf(buffer, sizeof(buffer), fmt, arglist);
        va_end(arglist);
        php_log_err(buffer);
}
/* }}} */

/* {{{ xmldbx_append_strf
 * Writes to a string using printf syntax
 */
void xmldbx_append_strf(XMLDBXBUF *xmlbuf, char *fmt, ...)
{
        va_list arglist;
        char buffer[XMLDBX_BUF_LEN];
        va_start(arglist, fmt);
        vsnprintf(buffer, sizeof(buffer), fmt, arglist);
        va_end(arglist);
        smart_str_appends(&xmlbuf->str, buffer);
}
/* }}} */


/* {{{ xmldbx_zentry_init
 * Initialize the zval stack
 */     
static int xmldbx_zentry_init(ZVAL_ENTRIES *pzentry)
{
        pzentry->zvals = ALLOCMEM(sizeof(ZVAL_ENTRY) * XMLDBX_ZSTACK_SIZE);
        if(!pzentry->zvals){
                return FAILURE;
        }
        else {
                pzentry->nzvals = 0;
                pzentry->maxzvals = XMLDBX_ZSTACK_SIZE;
                return SUCCESS;
        }
}
/* }}} */
/* {{{ xmldbx_zentry_destory
 * Destory the zval stack
 */     
static int xmldbx_zentry_destroy(ZVAL_ENTRIES *pzentry)
{
        int i;
        for(i=0; i < pzentry->nzvals; i++){
                if(pzentry->zvals[i].name)
                        FREEMEM(pzentry->zvals[i].name);
        }
        FREEMEM(pzentry->zvals);
}       
/* }}} */


/* {{{ xmldbx_push_zval
 * Push zval onto zval stack
 */     
static int xmldbx_push_zval(ZVAL_ENTRIES *pzentry, char *name, zval *obj)
{
        if (pzentry->nzvals >= pzentry->maxzvals) {     /* we need to allocate 
more memory */
                int newmax = pzentry->maxzvals * 2;
                pzentry->zvals = (ZVAL_ENTRY 
*)erealloc(pzentry->zvals,(sizeof(ZVAL_ENTRY)* newmax));
                if (!pzentry->zvals) {
                        php_error(E_WARNING, "Did not allocate ZVAL stack");
                        return FAILURE;
                }
                else 
                        pzentry->maxzvals = newmax;
        }
        if(!name)
                name="";
#ifdef ZVAL_DEBUG
        xmldbx_logf("xmldbx_push_zval name:%s address:%X entry:%d refcount:%d 
is_ref:%d", 
        name, obj, pzentry->nzvals, obj->refcount, obj->is_ref);
#endif
        pzentry->zvals[pzentry->nzvals].name = estrdup(name);
        pzentry->zvals[pzentry->nzvals].obj = obj;
        pzentry->nzvals++;
        return SUCCESS;
}
/* }}} */

/* {{{ xmldbx_find_dupzval
 * Find a duplicate in the zval stack
 */     
static int xmldbx_find_dupzval(ZVAL_ENTRIES *pzentry, char *name, zval *var)
{
        int i;
        for(i=0; i < pzentry->nzvals; i++)
        {
                if(pzentry->zvals[i].obj == var){
#ifdef ZVAL_DEBUG
                        xmldbx_logf("found duplicate %X, %s is_ref:%d, 
refcount:%d", 
                                var, name, var->is_ref, var->refcount);
#endif
                        return 1;
                }
        }
        return 0;
}
/* }}} */

/* {{{ xmldbx_stack_init
 * Initialize the XML decode stack
 */     
static int xmldbx_stack_init(xmldbx_stack *stack)
{
        int cb = sizeof(xmldbx_tag) * XMLDBX_STACK_SIZE;

        memset(stack, 0, sizeof(xmldbx_stack));
        stack->tags = (xmldbx_tag *) ALLOCMEM(cb);

        xmldbx_zentry_init(&stack->zentry);

        if (!stack->tags) {
                return FAILURE;
        } else {
                memset(stack->tags, 0, cb);
                stack->max = XMLDBX_STACK_SIZE;
                stack->state = XPS_IDLE;
                return SUCCESS;
        }
}
/* }}} */
/* {{{ xmldbx_stack_set_return
 * Sets the return value in the decode stack
 */
static void xmldbx_stack_set_return(xmldbx_stack *stack, xmldbx_tag *tag)
{
        ELOG_FUNC("xmldbx_stack_set_return");
        stack->retval = tag->data;
        tag->data = NULL; // Make sure, no double deletes
        stack->state = XPS_DONE;
}
/* }}} */
/* {{{ xmldbx_stack_get_return
 * Returns the value stored in the decode stack
 */
static zval *xmldbx_stack_get_return(xmldbx_stack *stack)
{
        return stack->retval;
}
/* }}} */
/* {{{ xmldbx_stack_push
 * Push a tag onto the decode stack
 */
static int xmldbx_stack_push(xmldbx_stack *stack, xmldbx_tag *tag)
{
        ELOG_FUNC("xmldbx_stack_push");
#ifdef ERR_DEBUG_ENTRA
        if(tag->vname)
                ELOG(tag->vname);
#endif
        if (stack->top >= stack->max) {         /* we need to allocate more 
memory */
                int newmax = stack->max+XMLDBX_STACK_SIZE;
                stack->tags = (xmldbx_tag *) 
erealloc(stack->tags,(sizeof(xmldbx_tag)* newmax));
                if (!stack->tags) {
                        return FAILURE;
                }
                else {
                        stack->max = newmax;
                }
        }
        stack->top++;
        stack->tags[stack->top] = *tag;
        return stack->top;
}
/* }}} */
/* {{{ xmldbx_stack_pop
 * Pop a tag from the decode stack
 */
static int xmldbx_stack_pop(xmldbx_stack *stack, xmldbx_tag *tag)
{
        ELOG_FUNC("xmldbx_stack_pop");
        if(stack->top > 0)
        {
                if(tag)
                {
                        *tag = stack->tags[stack->top];
                        // Avoid double deletes
                        stack->tags[stack->top].data = NULL;
                        stack->tags[stack->top].xname = NULL;
                        stack->tags[stack->top].vname = NULL;
                }
                stack->top--;
        }
        return stack->top;
}
/* }}} */

/* {{{ xmldbx_stack_curr
 * Returns a pointer to the current stack entry
 */
static int xmldbx_stack_curr(xmldbx_stack *stack, xmldbx_tag **tag)
{
        ELOG_FUNC("xmldbx_stack_curr");
        if (stack->top > 0) {
                *tag = &stack->tags[stack->top];
                return SUCCESS;
        } else {
                *tag = NULL;
                return FAILURE;
        }
}
/* }}} */
/* {{{ xmldbx_stack_is_empty
 * Return non-zero is the decode stack is empty
 */
static int xmldbx_stack_is_empty(xmldbx_stack *stack)
{
        ELOG_FUNC("xmldbx_stack_is_empty");
        if (stack->top == 0) {
                return 1;
        } else {
                return 0;
        }
}
/* }}} */
/* {{{ xmldbx_clear_tag
 * Clears a tag
 */
static void xmldbx_clear_tag(xmldbx_tag *tag)
{
        if(tag->vname != tag->xname) {
                if(tag->vname) {
                        FREEMEM(tag->vname);
                        tag->vname = NULL;
                }
                
        }
        if(tag->xname)
        {
                FREEMEM(tag->xname);
                tag->xname = NULL;
        }
}
/* }}} */
/* {{{ xmldbx_stack_destroy
 * Clean up the decode stack
 */
static int xmldbx_stack_destroy(xmldbx_stack *stack)
{
        ELOG_FUNC("xmldbx_stack_destroy");
        register int i;
        if (stack->tags) {
                for (i = 1; i < stack->top; i++) {
                        xmldbx_clear_tag(&stack->tags[i]);
                }               
                FREEMEM(stack->tags);
                stack->tags=NULL;
        }
        xmldbx_zentry_destroy(&stack->zentry);
        return SUCCESS;
}
/* }}} */

/* {{{ xmldbx_find_attr
 * Returns the value of the XML attribute specified or NULL.
 */
static XML_Char * xmldbx_find_attr(XML_Char *attrib, const XML_Char **atts)
{
        int i;
        ELOG_FUNC("xmldbx_find_attr");
        for(i=0; atts[i]; i+=2)
        {
                if(!strcmp(attrib, atts[i]))
                {
                        int ndx = i+1;
                        if(atts[ndx] && strlen(atts[ndx]))
                                return (XML_Char *)atts[ndx];
                }
        }
        return NULL;
}
/* }}} */
/* {{{ xmldbx_log_string
 * Creates a file based on prefix, processid, and static count
 * and writes string to it.
 */
static xmldbx_log_string(char *prefix, const char *string)
{
        static int n=0;
        char buffer[1024];
        FILE *f;
        pid_t p = getpid();
        
        sprintf(buffer, "/tmp/%s%d_%d.xml", prefix, p,n++);

        ELOG(buffer);

        f = fopen(buffer, "w+");

        if(f)
                fwrite(string, strlen(string), 1, f);

        fclose(f);
}
/* }}} */

#include "ext/session/php_session.h"
#if HAVE_PHP_SESSION
/* {{{ PS_SERIALIZER_ENCODE_FUNC
 */
PS_SERIALIZER_ENCODE_FUNC(xmldbx)
{
        XMLDBXBUF *xmlbuf=NULL;
        char *xname=NULL;

        PS_ENCODE_VARS;

        ELOG_FUNC("SERIALIZER_ENCODE_FUNC");

        xmlbuf = xmldbx_constructor();
        if (!xmlbuf)
                return FAILURE;

        xmldbx_start(xmlbuf);
        
        xname = xmldbx_open_var(xmlbuf, ST_OBJECT, XST_DATA, NULL, 0, NULL);
        
        PS_ENCODE_LOOP(
                xmldbx_serialize_var(xmlbuf, *struc, key, key_length TSRMLS_CC);
        );

        xmldbx_close_var(xmlbuf,xname);

        xmldbx_end(xmlbuf);
        *newstr = estrndup(xmlbuf->str.c, xmlbuf->str.len);
        xmldbx_destructor(xmlbuf);
        
#ifdef DUMP_DEBUG
        xmldbx_log_string("encode_", *newstr);
#endif
        if (newlen)
                *newlen = strlen(*newstr);

        return SUCCESS;
}
/* }}} */

/* {{{ aeSetSessionVars(ArrayEnumStruct *ae)
 * Set the enumerated variables into the session array 
 */
static int aeSetSessionVars(ArrayEnumStruct *ae)
{
        zval *lent;
        char key[128];
        int cbkey;
        ELOG("aeSetSessionVars");

#ifdef ERR_DEBUG
        assert(ae);
#endif
        if(ae->ent && *ae->ent) {
                switch (ae->type) {
                        case HASH_KEY_IS_LONG:
                                E2LOG(key);
                                E2LOG("HASH_KEY_IS_LONG");
                                cbkey = snprintf(key, sizeof(key),"%ld", 
ae->physndx);
                                php_set_session_var(key, cbkey, *ae->ent, NULL 
TSRMLS_CC);
                                PS_ADD_VAR(key);
                                break;
                        case HASH_KEY_IS_STRING:
                                E2LOG("HASH_KEY_IS_STRING");
                                E2LOG(ae->key);
                                php_set_session_var(ae->key, ae->keylen-1, 
*ae->ent, NULL TSRMLS_CC);
                                PS_ADD_VAR(ae->key);
                                break;
#ifdef ERR_DEBUG_EXTRA
                        default:
                                E2LOG("Unknown type");
                                break;
#endif
                }
        }
        return 1;
}
/* }}} */
/* {{{ PS_SERIALIZER_DECODE_FUNC
 */
PS_SERIALIZER_DECODE_FUNC(xmldbx)
{
        zval *zret;
        int ret = FAILURE;

        ELOG_FUNC("SERIALIZER_DECODE_FUNC");

        if (vallen <= 0) 
                return SUCCESS;
#ifdef DUMP_DEBUG
        xmldbx_log_string("decode_", val);
#endif
        if ((ret = xmldbx_deserialize_xml(&zret,val,vallen)) == SUCCESS) {
                E2LOG("xmldbx_deserialize_xml == SUCCESS");
                if(zret)
                        EnumArray(zret, aeSetSessionVars, NULL, NULL);
        }
        return ret;
}
/* }}} */
#endif

/* {{{ PHP_MINIT_FUNCTION
 */
static int xmldbx_modnum;

PHP_MINIT_FUNCTION(xmldbx)
{
        int i;
        ELOG_FUNC("PHP_MINIT_FUNCTION");
#if HAVE_PHP_SESSION
        E2LOG("Calling register_serializer");
        i = php_session_register_serializer("xmldbx",
                PS_SERIALIZER_ENCODE_NAME(xmldbx), 
PS_SERIALIZER_DECODE_NAME(xmldbx));
#endif  
        return SUCCESS;
}
/* }}} */

/* {{{ PHP_MINFO_FUNCTION
 */
PHP_MINFO_FUNCTION(xmldbx)
{
        ELOG_FUNC("PHP_MINFO_FUNCTION");
        php_info_print_table_start();
#if HAVE_PHP_SESSION
        E2LOG("HAVE_PHP_SESSION");
        php_info_print_table_header(2, "XMLDBX Support", "enabled" );
        php_info_print_table_row(2, "XMLDBX Session Serializer", "enabled" );
#else
        E2LOG("no PHP_SESSION");
        php_info_print_table_row(2, "XMLDBX Support", "enabled" );
#endif
        php_info_print_table_end();
}
/* }}} */
/* {{{ xmldbx_get_refattrs
 * Create a string of reference attributes
 */
static void xmldbx_get_refattrs(char *buffer, int cbbuf, zval *var)
{
        int cb=0;
        if(var && (var->is_ref || var->refcount > 1)) {
#ifdef ERR_DEBUG
                xmldbx_logf("REFATTR: %X, is_ref:%d, refcount: %d", 
                        var, var->is_ref, var->refcount);
#endif 
                cb = snprintf(buffer, cbbuf, XMLDBX_ATTRX, XA_REFERENCE, var);
                cbbuf -= cb;
                buffer+= cb;

                if(var->is_ref){
                        cb = snprintf(buffer, cbbuf, XMLDBX_ATTRN, XA_ISREF, 1);
                        cbbuf -= cb;
                        buffer+= cb;
                }
                if(var->refcount > 1){
                        cb = snprintf(buffer, cbbuf, XMLDBX_ATTRN, XA_REFCOUNT, 
var->refcount);
                        cbbuf -= cb;
                        buffer+= cb;
                }
        }
        *buffer = 0;
}
/* }}} */

/* {{{ xmldbx_write_var
 */
static void xmldbx_write_var(XMLDBXBUF *xmlbuf, int ntype, char *name, char 
*value, int len)
{
        char *type = (ntype >= ST_IGNORE) ? XT_IGNORE :  xmldbx_types[ntype];
        char xmlname[2048];
        char refattrs[128];
        char *xname = name;
#ifdef ERR_DEBUG
        xmldbx_logf("xmldbx_write_var(%s,%s,%s - isref:%d refcount:%d)", 
                type, name, value, xmlbuf->zvalCurr->is_ref, 
xmlbuf->zvalCurr->refcount);
#endif
        if(!len)
                len = strlen(value);

        // Open var with name or translated name
        if(xmldbx_bad_name(name)){
                xmldbx_append_strf(xmlbuf, XMLDBX_OPEN_START, XST_XMLARG, type);
                xmldbx_append_strf(xmlbuf, XMLDBX_ATTRS, XA_NAME, name);
                xname = XST_XMLARG;
        }
        else {
                xmldbx_append_strf(xmlbuf, XMLDBX_OPEN_START, name, type);
                xname = name;
        }
        // <name [n='xname'] t='type' 
        if(ntype == ST_REFERENCE)
        {
                // A reference is a string.
                xmldbx_append_strf(xmlbuf, XMLDBX_ATTRS, XA_VALUE, value);
                xmldbx_append_strf(xmlbuf, XMLDBX_OPEN_END_DEF);
                return;
        }
        xmldbx_get_refattrs(refattrs, sizeof(refattrs), xmlbuf->zvalCurr);
        smart_str_appends(&xmlbuf->str, refattrs);      
        xmldbx_append_strf(xmlbuf, XMLDBX_ATTRS, XA_VALUE, value);
        xmldbx_append_strf(xmlbuf, XMLDBX_OPEN_END_DEF);
}
/* }}} */
/* {{{ xmldbx_open_var
 */
static char *xmldbx_open_var(XMLDBXBUF *xmlbuf, int ntype, char *name, char 
*classname, int len, char *extra)
{
        char *type = (ntype >= ST_IGNORE) ?ST_NULL :  xmldbx_types[ntype];
        char xmlname[1024];
        char refattrs[128];
        char *xname = name;

#ifdef ERR_DEBUG_EXTRA
        xmldbx_logf("xmldbx_open_var(%s,%s,%s) [%d]", type, name, classname, 
need_attrib);
#endif
        // Open var with name or translated name
        if(xmldbx_bad_name(name)){
                xmldbx_append_strf(xmlbuf, XMLDBX_OPEN_START , XST_XMLARG, 
type);
                xmldbx_append_strf(xmlbuf, XMLDBX_ATTRS, XA_NAME, name);
                xname = XST_XMLARG;
        }
        else {
                xmldbx_append_strf(xmlbuf, XMLDBX_OPEN_START, name, type);
                xname = name;
        }
        xmldbx_get_refattrs(refattrs, sizeof(refattrs), xmlbuf->zvalCurr);
        smart_str_appends(&xmlbuf->str, refattrs);      

        if(len)
                xmldbx_append_strf(xmlbuf, XMLDBX_ATTRN, XA_LEN, len);

        if(classname)
                xmldbx_append_strf(xmlbuf, XMLDBX_ATTRS, XA_CLASSNAME, 
classname);

        if(extra)
                xmldbx_append_strf(xmlbuf, XMLDBX_ATTRS, XA_EXTRA, extra);

        xmldbx_append_strf(xmlbuf, ">");
        E2LOG(xmlbuf->str.c);
        return xname;
}
/* }}} */
/* {{{ xmldbx_close_var
 */
static void xmldbx_close_var(XMLDBXBUF *xmlbuf, char *name)
{
        xmldbx_append_strf(xmlbuf, XMLDBX_VAR_E, name);
}

/* }}} */
/* {{{ xmldbx_start
 */
static void xmldbx_start(XMLDBXBUF *xmlbuf)
{
        ELOG_FUNC("xmldbx_start");
        smart_str_appends(&xmlbuf->str, XMLDBX_NAME_S);
}
/* }}} */

/* {{{ xmldbx_end
 */
static void xmldbx_end(XMLDBXBUF *xmlbuf)
{
        ELOG_FUNC("xmldbx_end");
        smart_str_appends(&xmlbuf->str, XMLDBX_NAME_E); 
}
/* }}} */
/***************** Serialize functions for basic types *******************/

static int xmldbx_bad_xmlchar(int c)
{
        if(isalnum(c) || (c=='_') )
                return 0;
        else if(c == '_')
                return 0;

        return 1;
}
static int xmldbx_bad_char(int c)
{
        return (xmldbx_bad_xmlchar(c)==0 || c==' ') ? 0 : 1;
}

/* xmldbx_bad_name
 * Test is name not good for XML tag
 */
static int xmldbx_bad_name(char *src)
{
        if(isdigit(*src))
                return 1;
        while(*src){
                if(xmldbx_bad_xmlchar(*src))
                        return 1;
                src++;
        }
        return 0;
}
/* }}} */
/* xmldbx_bad_string
 * Test is string not good inside XML tag
 */
static int xmldbx_bad_string(char *src)
{
        while(*src){
                if(xmldbx_bad_char(*src))
                        return 1;
                src++;
        }
        return 0;
}
/* }}} */


/* {{{ xmldbx_serialize_string
 */
static void xmldbx_serialize_string(XMLDBXBUF *xmlbuf, char *name, zval *var)
{
        ELOG_FUNC("xmldbx_serialize_string");

        if(var){

        int     cbsz = Z_STRLEN_P(var);
        char *  value= Z_STRVAL_P(var);
        int cdata = 0;
        int i;

        if(cbsz == 0)   // No string, no translate
                return;

        for(i=0; i < cbsz; i++){
                if(xmldbx_bad_char(value[i])){
                        cdata = 1;
                        break;
                }
        }

        if(cdata==0 && cbsz <XMLDBX_SMALLSZ){           // Small easy string, 
go for more efficienct one tag
                xmldbx_write_var(xmlbuf, ST_STRING, name, value, cbsz);
        }
        else { // Embed string in a CDATA to avoid parsing
                char *xname = xmldbx_open_var(xmlbuf, ST_STRING, name, NULL, 0, 
NULL);
                smart_str_appends(&xmlbuf->str, "<![CDATA[");
                smart_str_appendl(&xmlbuf->str, value, cbsz);
                smart_str_appends(&xmlbuf->str, "]]>");
                xmldbx_close_var(xmlbuf, xname);
        }
        }
}
/* }}} */

static void CopyZvalString(char *dest, zval *src, int cbdest)
{
        zval tmp;
        ELOG_FUNC("CopyZvalString");
        tmp = *src;
        zval_copy_ctor(&tmp);
        convert_to_string(&tmp);
        strncpy(dest, Z_STRVAL(tmp), cbdest);   
        ZDTOR(&tmp);
}
/* {{{ xmldbx_serialize_number
 */
static void xmldbx_serialize_number(XMLDBXBUF *xmlbuf, char *name,zval *var)
{
        char buf[XMLDBX_BUF_LEN];
        CopyZvalString(buf, var, sizeof(buf));
        xmldbx_write_var(xmlbuf, ST_LONG, name, buf, 0);
}
/* }}} */
/* {{{ xmldbx_serialize_float
 */
static void xmldbx_serialize_float(XMLDBXBUF *xmlbuf, char *name,zval *var)
{
        char buf[XMLDBX_BUF_LEN];
        CopyZvalString(buf, var, sizeof(buf));
        xmldbx_write_var(xmlbuf, ST_DOUBLE, name, buf, 0);
}
/* }}} */
/* {{{ xmldbx_serialize_boolean
 */
static void xmldbx_serialize_boolean(XMLDBXBUF *xmlbuf, char *name, zval *var)
{
        ELOG_FUNC("xmldbx_serialize_boolean");
        xmldbx_write_var(xmlbuf, ST_BOOLEAN, name,Z_LVAL_P(var) ? "t" : "f", 0);
}
/* }}} */
/* {{{ xmldbx_serialize_unset
 */
static void xmldbx_serialize_unset(XMLDBXBUF *xmlbuf, char *name)
{
        ELOG_FUNC("xmldbx_serialize_unset");
        xmldbx_write_var(xmlbuf, ST_NULL, name,XT_NULL, 0);
}
/* }}} */
/************ Functions serialize aggrgate object ********************/

#define ENUMA_START     -1
#define ENUMA_END       -2

// Enumerates all elements on an object or array
static int EnumArray(zval *obj, EnumArrayCallback fn, void *p1, void *p2)
{
        ArrayEnumStruct ae;
        // Initialize the structure
        ae.obj = obj;
        ae.ent = NULL;
        ae.hash = HASH_OF(obj);
        ae.pointer = NULL;
        ae.key = NULL;
        ae.keylen = 0;
        ae.p1 = p1;
        ae.p2 = p2;
        ae.private = NULL;
        int count=0;

        if(ae.hash)
        {
                E2LOG("Array Enum:Start");
                /* call before enumeration */
                ae.physndx = ae.ndx= ENUMA_START;
                if(!(*fn)(&ae)) 
                        return ae.ndx;
                ae.physndx = ae.ndx= 0;


                /* Enumerate all objects */
                for (zend_hash_internal_pointer_reset_ex(ae.hash, &ae.pointer);
                         zend_hash_get_current_data_ex(ae.hash, 
(void**)&ae.ent, &ae.pointer) == SUCCESS;
                         zend_hash_move_forward_ex(ae.hash, &ae.pointer)) 
                {
                        ae.type = zend_hash_get_current_key_ex(ae.hash, 
&ae.key, &ae.keylen, &ae.ndx, 0, &ae.pointer);
                        if(ae.ent)
                        {
                                if(*ae.ent != obj){
                                        if(!(*fn)(&ae))
                                                break;
                                        ae.physndx++;
                                }
                        }
                }
                count = ae.physndx;

                /* call after enumeration */
                ae.physndx = ae.ndx= ENUMA_END;
                ae.ent = NULL;
                if(!(*fn)(&ae)) 
                        return ae.ndx;

                /* return count of objects */
                E2LOG("Array Enum:End");
        }
        return count;
}

/* Checks if there are non-numerical indexes in the array */
/* p1 is xmlbuf, p2 is NULL */
static int eaIsStruct(ArrayEnumStruct *ae)
{
        ELOG("aeIsStruct");
        int *is_struct = (int *) ae->p2;
        if(ae->ent) {
                if (ae->type == HASH_KEY_IS_STRING) {
                        *is_struct = ST_OBJECT;
                        return 0; // Done
                }
                if (ae->ndx != ae->physndx) {
                        *is_struct = ST_OBJECT;
                        return 0; // Done
                }
        }
        return 1;
}

/* Serializes array variable. */
/* p1 is xmlbuf, p2 is NULL */
static int aeSerializeVar(ArrayEnumStruct *ae)
{
        ELOG("aeSerializeVar");
        if(ae->ent && (*ae->ent != ae->obj) && (*ae->ent != ae->p2))
        {
                XMLDBXBUF *xmlbuf = (XMLDBXBUF *) ae->p1;
                xmldbx_serialize_var(xmlbuf, *ae->ent, NULL, 0 TSRMLS_CC);
        }
        return 1;
}

/* Serializes a structure variable */
/* p1 is xmlbuf, p2 is NULL */
static int aeSerializeArrayVar(ArrayEnumStruct *ae)
{
        ELOG("aeSerializeArrayVar");
        XMLDBXBUF *xmlbuf = (XMLDBXBUF *) ae->p1;
        if(ae->ent && *ae->ent != ae->obj && *ae->ent != ae->p2) {
                if (ae->type == HASH_KEY_IS_STRING) {
                        ELOG("HASH_KEY_IS_STRING");
                        xmldbx_serialize_var(xmlbuf, *ae->ent, ae->key, 
ae->keylen TSRMLS_CC);
                } else {
                        char tmp_buf[XMLDBX_BUF_LEN];
                        ae->keylen = snprintf(tmp_buf, sizeof(tmp_buf),"%ld", 
ae->ndx);
                        xmldbx_serialize_var(xmlbuf, *ae->ent, tmp_buf, 
ae->keylen TSRMLS_CC);
                }
        }
        return 1;
}
/* Serialize an object */
/* p1 is xmlbuf, p2 is parent object */
static int aeSerializeObjectVar(ArrayEnumStruct *ae)
{
        ELOG("aeSerializeObjectVar");
        zval *lent;
        char *varname = Z_STRVAL_PP(ae->ent);
        int varlen = (varname) ? strlen(varname)+1 : 0;
        if(ae->ent && *ae->ent != ae->obj && *ae->ent != ae->p2) {
                XMLDBXBUF *xmlbuf = (XMLDBXBUF *) ae->p1;
                if (Z_TYPE_PP(ae->ent) != IS_STRING) {
                        php_error(E_NOTICE, 
                        "__sleep should return an array only containing the 
names of instance-variables to serialize.");
                }
                else if (zend_hash_find(HASH_OF(((zval 
*)ae->p2)),varname,varlen,(void **)&lent) == SUCCESS) {
                        xmldbx_serialize_var(xmlbuf, lent, varname, varlen 
TSRMLS_CC);
                }
        }
        return 1;
}

/* {{{ xmldbx_serialize_array
 */
static void xmldbx_serialize_array(XMLDBXBUF *xmlbuf, char *name, zval *arr)
{
        int is_struct = ST_ARRAY; 
        char *xname=NULL;
        int count;
        char *extra=NULL;
        TSRMLS_FETCH();

        ELOG_FUNC("xmldbx_serialize_array");

        /* discover if array containes string keys! */
        count = EnumArray(arr, eaIsStruct, xmlbuf, (void *)&is_struct);

#ifdef DUMP_DEBUG
        if(is_struct)
                extra = "st";
        else
                extra = "var";
#endif
        xname = xmldbx_open_var(xmlbuf, is_struct, name, NULL, count, extra);

        if(is_struct)
                EnumArray(arr, aeSerializeArrayVar, (void *) xmlbuf, NULL);
        else
                EnumArray(arr, aeSerializeVar, (void *) xmlbuf, NULL);

        xmldbx_close_var(xmlbuf, xname);
}
/* }}} */

/* {{{ xmldbx_serialize_object
 */
static void xmldbx_serialize_object(XMLDBXBUF *xmlbuf, char *name, zval *obj)
{
        zval *fname=NULL;
        zval *varnames=NULL;
        char *xname=NULL;
        char *extra = NULL;

        TSRMLS_FETCH();

        MAKE_STD_ZVAL(fname);
        ZVAL_STRING(fname, "__sleep", 1);

        ELOG_FUNC("xmldbx_serialize_object");
        /* We try to call __sleep() method on object. It's supposed to return an
         * array of property names to be serialized.  We will walk the array of 
names
         * not the array itself*/
        if (call_user_function_ex(CG(function_table), &obj, fname, &varnames, 
0, 0, 1, NULL TSRMLS_CC) != SUCCESS) 
                varnames = NULL;

        PHP_CLASS_ATTRIBUTES;
                        
        PHP_SET_CLASS_ATTRIBUTES(obj);

        E2LOG(class_name);
        E2LOG(name);

#ifdef DUMP_DEBUG
        if(varnames && HASH_OF(varnames))
                extra = "HASHOF_varnames";
        else if(varnames)
                extra = "varnames";
        else
                extra = "obj";
#endif
        xname = xmldbx_open_var(xmlbuf, ST_OBJECT, name,  class_name, 0, extra);

        PHP_CLEANUP_CLASS_ATTRIBUTES();
                        
        if(varnames && HASH_OF(varnames))
                EnumArray(varnames, aeSerializeObjectVar, (void *) xmlbuf, obj);
        else
                EnumArray(obj, aeSerializeArrayVar, (void *) xmlbuf, obj);
                        
        xmldbx_close_var(xmlbuf, xname);

        ZDTOR(fname);
        FREE_ZVAL(fname);

}
/* }}} */
/* {{{ xmldbx_find_type
 * Returns a static type
 */
static int xmldbx_find_ztype(int ztype)
{
#if 0
        /* Remove, re-aligned values with Zend */
        int type=ST_NULL;
        switch(ztype) {
                case IS_NULL:
                        type = ST_NULL;
                        break;
                case IS_BOOL:
                        type = ST_BOOLEAN;
                        break;
                case IS_LONG:
                        type = ST_LONG;
                        break;
                case IS_DOUBLE:
                        type = ST_DOUBLE;
                        break;
                case IS_STRING:
                        type = ST_STRING;
                        break;
                case IS_RESOURCE:
                        type = ST_RESOURCE;
                        break;
                case IS_ARRAY:
                        type = ST_ARRAY;
                        break;
                case IS_OBJECT:
                        type = ST_OBJECT;
                        break;
        }
        return type;
#else
        if(ztype >= IS_NULL && ztype <= IS_RESOURCE)
                return ztype;

#ifdef ERR_DEBUG
        xmldbx_logf("TYPE Error: %d", ztype);
#endif
        return ST_STRING;
#endif
}


/* {{{ xmldbx_serialize_var
 * All variables start here!!
 */
void xmldbx_serialize_var(XMLDBXBUF *xmlbuf, zval *var, char *name, int 
name_len TSRMLS_DC)
{
        char *name_esc=NULL;
        int name_esc_len;
        int ntype;
        int ztype = Z_TYPE_P(var);
        int i;

        ELOG_FUNC("xmldbx_serialize_var");
        ntype = xmldbx_find_ztype(ztype);

        xmlbuf->zvalCurr = var;

        if (name) {
                name_esc = php_escape_html_entities(name, name_len, 
&name_esc_len, 0, ENT_QUOTES, NULL TSRMLS_CC);
                name = name_esc;
        } else {
                name = XST_UNNAMED;
        }
        if(var->refcount > 1 || var->is_ref){
                if(xmldbx_find_dupzval(&xmlbuf->zentry, name, var)) {
                        char buffer[64];
                        int len = snprintf(buffer, sizeof(buffer), "%X", var);
                        xmldbx_write_var(xmlbuf, ST_REFERENCE, name, buffer, 
len);
                        return ;
                }
                xmldbx_push_zval(&xmlbuf->zentry, name, var);
        }
        switch(ztype) {
                case IS_BOOL:
                        xmldbx_serialize_boolean(xmlbuf, name, var);
                        break;
                case IS_NULL:
                        xmldbx_serialize_unset(xmlbuf, name);
                        break;
                case IS_LONG:
                        xmldbx_serialize_number(xmlbuf, name, var);
                        break;
                case IS_DOUBLE:
                        xmldbx_serialize_float(xmlbuf, name, var);
                        break;
                case IS_STRING:
                        xmldbx_serialize_string(xmlbuf, name, var);
                        break;
                case IS_OBJECT:
                        xmldbx_serialize_object(xmlbuf, name, var);
                        break;
                case IS_ARRAY:
                        xmldbx_serialize_array(xmlbuf, name, var);
                        break;
#ifdef ERR_DEBUG
                case IS_RESOURCE:
                        ELOG("ERROR: Serializing a resource");
                        break;
#endif
                default:
                        xmldbx_logf("Error: Serialize unknown type: %d", ztype);
                        xmldbx_write_var(xmlbuf, ST_IGNORE, name, NULL, 0);
                        break;
        }

        if(name_esc)
                FREEMEM(name_esc);
}
/* }}} */

/* {{{ xmldbx_add_var
 * Recusively calls itself on complex types
 * Basically php interface for xmldbx_serialize_var
 */
static void xmldbx_add_var(XMLDBXBUF *xmlbuf, zval *name_var)
{
        zval **val=NULL;
        HashTable *target_hash=NULL;
        TSRMLS_FETCH();
        
        ELOG_FUNC("xmldbx_add_var");
        if (Z_TYPE_P(name_var) == IS_STRING)
        {
                if (zend_hash_find(EG(active_symbol_table), 
Z_STRVAL_P(name_var),
                                                        Z_STRLEN_P(name_var)+1, 
(void**)&val) != FAILURE) {
                        xmldbx_serialize_var(xmlbuf, *val, 
Z_STRVAL_P(name_var), Z_STRLEN_P(name_var) TSRMLS_CC);
                }               
        }
        else if (Z_TYPE_P(name_var) == IS_ARRAY || Z_TYPE_P(name_var) == 
IS_OBJECT)
        {
                target_hash = HASH_OF(name_var);
                zend_hash_internal_pointer_reset(target_hash);
                while(zend_hash_get_current_data(target_hash, (void**)&val) == 
SUCCESS) {
                        xmldbx_add_var(xmlbuf, *val);
                        zend_hash_move_forward(target_hash);
                }
        }
}
/* {{{ xmldbx_set_classname
 * Sets the class name/type of an object
 */
static void xmldbx_set_classname(zval ** data, char *classname)
{
        ELOG_FUNC("xmldbx_set_classname");
        zend_bool empty_class = 0;
        zend_class_entry *ce=NULL;
        zval *obj=NULL;
        zval *tmp=NULL;
        int cbcls = strlen(classname);

        zend_str_tolower(classname, cbcls);
#ifdef ERR_DEBUG
        xmldbx_logf("classname: classname: %s, namelen: %d", classname, cbcls);
#endif
        if(zend_hash_find(EG(class_table), classname, cbcls+1, (void **)&ce) == 
FAILURE) {
                ce = PHP_IC_ENTRY;
                empty_class = 1;
        }

        MAKE_STD_ZVAL(obj);
        INIT_PZVAL(obj);
        object_init_ex(obj,ce);

        zend_hash_merge(Z_OBJPROP_P(obj), Z_ARRVAL_P(*data),
                (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *), 
0);

        if(empty_class)
                php_store_class_name(obj, classname, cbcls TSRMLS_CC);

        ZDTORP(data);
        *data = obj;
}
/* }}} */
/* {{{ xmldbx_start_handler
 * This function takes the information in the XML bracket, and extracts the 
type from
 * the atributes.
 */
static void xmldbx_start_handler(void *data, const XML_Char *name, const 
XML_Char **atts)
{
        xmldbx_tag ent;
        ELOG_FUNC("xmldbx_start_handler");

        xmldbx_stack * stack = (xmldbx_stack *) data;

        /* Get atributes */
        XML_Char *xml_type      = xmldbx_find_attr(XA_TYPE, atts);
        XML_Char *xml_value     = xmldbx_find_attr(XA_VALUE, atts);
        XML_Char *xml_vname     = xmldbx_find_attr(XA_NAME, atts);
        XML_Char *xml_classname = xmldbx_find_attr(XA_CLASSNAME, atts);
        XML_Char *xml_isref     = xmldbx_find_attr(XA_ISREF, atts);
        XML_Char *xml_zref      = xmldbx_find_attr(XA_REFERENCE, atts);
        XML_Char *xml_rcnt      = xmldbx_find_attr(XA_REFCOUNT, atts);

        if(!xml_type)
                xml_type = XT_IGNORE;

        ent.type  = ST_IGNORE;
        ent.data  = NULL;
        ent.items = 0;
        ent.xname = (name) ? estrdup(name) : NULL;
        ent.vname = (xml_vname) ? estrdup(xml_vname) : ent.xname;

#ifdef ZVAL_DEBUG
        xmldbx_logf("push: %d, %s(%s):%s[%s] zref:%s rcnt:%s", 
                stack->top, 
                ent.xname, 
                ent.vname, 
                xml_type, 
                (xml_value) ? xml_value : "",
                (xml_zref) ? xml_zref : "", 
                (xml_rcnt) ? xml_rcnt : "");
#endif
        if(stack->state == XPS_IDLE){   // We haven't started yet
                E2LOG("State is idle");
                if(!strcmp(name, XST_NAME)) { // Should be the beginning xmlbuf!
                        char *version = xmldbx_find_attr(XA_VERSION, atts);
                        if(strcmp(version, XMLDBX_VERSION)) // Bad version, 
what to do?
                                xmldbx_logf("Bad data format: xmldbx 
version=%s, not %s\n", version, XMLDBX_VERSION);
                        else 
                                stack->state = XPS_XMLDBX; // We are processing 
xmldbx data
                        memset(&ent,0,sizeof(ent));
                        ent.type = ST_NAME;
                        ent.data = NULL;
                        E2LOG("ST_NAME");
                }
        } else if (!strcmp(xml_type, XT_STRING)) {      // A standard string
                ent.type = ST_STRING;
                ALLOC_ZVAL(ent.data);
                INIT_PZVAL(ent.data);
                Z_TYPE_P(ent.data) = IS_STRING;
                Z_STRVAL_P(ent.data) = xmldbx_empty_string;
                Z_STRLEN_P(ent.data) = 0;
                E2LOG("ST_STRING");
        } else if (!strcmp(xml_type, XT_LONG)) {        // A number 
                ent.type = ST_LONG;
                ALLOC_ZVAL(ent.data);
                INIT_PZVAL(ent.data);
                Z_TYPE_P(ent.data) = IS_LONG;
                E2LOG("ST_LONG");
        } else if (!strcmp(xml_type, XT_DOUBLE)) {      // A number 
                ent.type = ST_DOUBLE;
                ALLOC_ZVAL(ent.data);
                INIT_PZVAL(ent.data);
                Z_TYPE_P(ent.data) = IS_DOUBLE;
                E2LOG("ST_LONG");
        } else if (!strcmp(xml_type, XT_BOOLEAN)) {
                ent.type = ST_BOOLEAN;
                ALLOC_ZVAL(ent.data);
                INIT_PZVAL(ent.data);
                Z_TYPE_P(ent.data) = IS_BOOL;
                E2LOG("ST_BOOLEAN");
        } else if (!strcmp(xml_type, XT_NULL)) {
                ent.type = ST_NULL;
                ALLOC_ZVAL(ent.data);
                INIT_PZVAL(ent.data);
                ZVAL_NULL(ent.data);
                E2LOG("ST_NULL");
        } else if (!strcmp(xml_type, XT_ARRAY)) {
                ent.type = ST_ARRAY;
                ALLOC_ZVAL(ent.data);
                array_init(ent.data);
                INIT_PZVAL(ent.data);
                E2LOG("ST_ARRAY");
        } else if (!strcmp(xml_type, XT_OBJECT)) {
                ent.type = ST_OBJECT;
                ALLOC_ZVAL(ent.data);
                array_init(ent.data);
                INIT_PZVAL(ent.data);
                E2LOG("ST_OBJECT");
        }
        else if(!strcmp(xml_type, XT_REFERENCE)) {
                // Ignore indexes greater than 1 as they are generally ignored 
in
                // PHP itself.
                ent.type = ST_REFERENCE;
                ent.data = NULL;
                int i;
#ifdef ZVAL_DEBUG
                xmldbx_logf("Read XML REFERENCE offset %s", xml_value);
#endif
                if(xml_value){
                        // Make sure we don't do something to the value
                        for(i=0; i < stack->zentry.nzvals; i++) {
                                if(!strcmp(stack->zentry.zvals[i].name, 
xml_value)) {
#ifdef ZVAL_DEBUG
                                        xmldbx_logf("Found a reference!!! %s, 
%s", ent.vname, xml_value);
#endif
                                        ent.data = stack->zentry.zvals[i].obj;
                                        break;
                                }
                        }
#ifdef ZVAL_DEBUG
                        // This should be a bug, but I think NULL values are 
valid, this will
                        // just make them go away.
                        if(!ent.data)
                                php_error(E_WARNING, "XML REFERENCE not found 
ignoring:%s", xml_value);
#endif
                }
                else 
                        php_error(E_WARNING, "Bogus XML REFERENCE");
                xml_value = NULL;
        }
#ifdef ERR_DEBUG
        else {
                xmldbx_logf("Unknown type %s", xml_type);
        }
#endif
        if(ent.type != ST_REFERENCE && ent.data){
                if(xml_isref)
                        ent.data->is_ref = 1;
                if(xml_rcnt)
                        ent.data->refcount=atoi(xml_rcnt);
                if(xml_zref)
                        xmldbx_push_zval(&stack->zentry, xml_zref, ent.data);
        }
        if(xml_classname && (ent.type == ST_ARRAY || ent.type == ST_OBJECT))
                xmldbx_set_classname(&ent.data, xml_classname);
        xmldbx_stack_push(stack, &ent);
        if(ent.type != ST_IGNORE && xml_value){
                xmldbx_data_handler(stack, xml_value, strlen(xml_value));
        }
}
/* }}} */


/* {{{ xmldbx_end_handler
 * Called at the end of an XML tag, decides what to do with it.
 */
static void xmldbx_end_handler(void *user_data, const XML_Char *name)
{
        xmldbx_tag                      entCurr;
        xmldbx_tag              *       pentParent=NULL;
        HashTable               *       target_hash=NULL;
        xmldbx_stack            *       stack = (xmldbx_stack *)user_data;

        TSRMLS_FETCH();

        ELOG_FUNC("xmldbx_end_handler");

        if(stack->top == 0)
        {
#ifdef ERR_DEBUG
                xmldbx_logf("Top of stack: %s", (name) ? name : "unknown");
#endif  
                return;
        }
        // Pop var off stack
        xmldbx_stack_pop(stack, &entCurr);
        // Get parent stack entry
        xmldbx_stack_curr(stack, &pentParent);

        if(entCurr.xname && strcmp(name, entCurr.xname)){
                xmldbx_logf("Warning: name and xname out of sync! \"%s\" != 
\"%s\"", 
                        name, (entCurr.xname) ? entCurr.xname : "NULL" );
        }
        if((entCurr.type == ST_IGNORE) || (entCurr.data == NULL))
        {
                xmldbx_clear_tag(&entCurr);
                return;
        }       
#ifdef ERR_DEBUG
        if(((int)name) < 65536) {
                xmldbx_logf("Really funky pointer:%X !!", name);
        }
        xmldbx_logf("pop: %d, name %s, entCurr:%s, pentParent:%s", 
                        stack->top, name, entCurr.vname, (pentParent) ? 
pentParent->vname : "NULL");
        if(pentParent) {
                xmldbx_logf("pentParent: %X, pentParent->data: %X", pentParent, 
pentParent->data);
        }
#endif
        /* Call __wakeup() method on the object. */
        if (Z_TYPE_P(entCurr.data) == IS_OBJECT) {
                zval *fname = NULL;
                zval *retval = NULL;

                MAKE_STD_ZVAL(fname);
                ZVAL_STRING(fname, "__wakeup", 1);

                call_user_function_ex(NULL, &entCurr.data, fname, &retval, 0, 
0, 0, NULL TSRMLS_CC);

                ZDTOR(fname);
                FREE_ZVAL(fname);
                if (retval)
                        ZDTOR(retval);
        }

        if(!pentParent){
                ELOG("Last tagfound");
                xmldbx_stack_set_return(stack, &entCurr);
        }
        else {
                if(pentParent->type == ST_NAME || stack->top == 1) {
                        ELOG("Parent found");
                        xmldbx_stack_set_return(stack, &entCurr);
                } else if (pentParent->data) {
                        // This is the main method by which data is returned.
                        // Discrete objects MUST be part of some sort of 
container
                        // If the parent is a container!
                        if (Z_TYPE_P(pentParent->data) == IS_ARRAY || 
Z_TYPE_P(pentParent->data) == IS_OBJECT) {
                                target_hash = HASH_OF(pentParent->data);
                                if (strcmp(entCurr.vname, XST_UNNAMED)) { // If 
it is a named entry
                                        zend_hash_update(target_hash, 
entCurr.vname, strlen(entCurr.vname)+1, 
                                                &entCurr.data, sizeof(zval *), 
NULL);
                                } else  {       // Does not have a name
                                        
zend_hash_next_index_insert(target_hash, &entCurr.data, sizeof(zval *), NULL);
                                }
                        }
                }
#ifdef ERR_DEBUG
                else {
                        ELOG("Parent type not ST_NAME and no data, data lost");
                }
#endif
        } 
        xmldbx_clear_tag(&entCurr);
}
/* }}} */

/* {{{ xmldbx_data_handler
 * Interprets the type on the stack and applys data accordingly
 */
static void xmldbx_data_handler(void *user_data, const XML_Char *s, int len)
{
        xmldbx_tag *ent=NULL;
        xmldbx_stack *stack = (xmldbx_stack *)user_data;
        char *decoded=NULL;
        int decoded_len;
        TSRMLS_FETCH();

        ELOG_FUNC("xmldbx_data_handler");

        if(stack->state == XPS_DONE)    // We be done, just walk away
                return;
        ELOG_FUNC("xmldbx_data_handler");
        if (!xmldbx_stack_is_empty(stack)) {
                xmldbx_stack_curr(stack, &ent);
                switch (ent->type) {
                        case ST_STRING: 
                                ELOG("xml->string");
                                decoded = (char *)xml_utf8_decode(s, len, 
&decoded_len, "ISO-8859-1");
                                if(decoded)
                                {
                                        if (Z_STRLEN_P(ent->data) == 0) {
                                                Z_STRVAL_P(ent->data) = 
estrndup(decoded, decoded_len);
                                                Z_STRLEN_P(ent->data) = 
decoded_len;
                                        } else {
                                                Z_STRVAL_P(ent->data) = 
erealloc(Z_STRVAL_P(ent->data),
                                                        Z_STRLEN_P(ent->data) + 
decoded_len + 1);
                                                
strncpy(Z_STRVAL_P(ent->data)+Z_STRLEN_P(ent->data), decoded, decoded_len);
                                                Z_STRLEN_P(ent->data) += 
decoded_len;
                                                
Z_STRVAL_P(ent->data)[Z_STRLEN_P(ent->data)] = '\0';
                                        }
                                        FREEMEM(decoded);
                                }
                                break;
                        case ST_DOUBLE:
                                ELOG("xml->double");
                                Z_TYPE_P(ent->data) = IS_STRING;
                                Z_STRLEN_P(ent->data) = len;
                                Z_STRVAL_P(ent->data) = estrndup(s, len);
                                convert_to_double(ent->data);
                                break;
                        case ST_LONG:
                                ELOG("xml->long");
                                Z_TYPE_P(ent->data) = IS_STRING;
                                Z_STRLEN_P(ent->data) = len;
                                Z_STRVAL_P(ent->data) = estrndup(s, len);
                                convert_to_long(ent->data);
                                break;
                        case ST_BOOLEAN:
                                ELOG("xml->bool");
                                Z_LVAL_P(ent->data) = (*s == 't') ? 1 : 0;
                                break;
                        default:
                                break;
                }
        }
}
/* }}} */

/* {{{ xmldbx_deserialize_xml
 * Called to deserialize
 */
int xmldbx_deserialize_xml(zval **zret, const char *value, int vallen)
{
        xmldbx_stack stack;
        XML_Parser parser;
        xmldbx_tag *ent=NULL;
        int retval;
        
        ELOG_FUNC("xmldbx_deserialize_xml");
        
        xmldbx_stack_init(&stack);
        MAKE_STD_ZVAL(stack.retval);

        stack.endtag = XST_DATA;

        parser = XML_ParserCreate("ISO-8859-1");

        XML_SetUserData(parser, &stack);
        XML_SetElementHandler(parser, xmldbx_start_handler, xmldbx_end_handler);
        XML_SetCharacterDataHandler(parser, xmldbx_data_handler);
        if(XML_Parse(parser, value, vallen, 1)==0)
        {
                char buffer[1024];
                int ec = XML_GetErrorCode(parser);
                char *s = (char *)XML_ErrorString(ec);
                snprintf(buffer, sizeof(buffer), "XML Parsing Error: %s", s);
                php_error(E_WARNING, buffer);
#ifdef LOG_BAD_PARSE
                xmldbx_log_string("parse_err_", value);
#endif
        }
        XML_ParserFree(parser);

        *zret = xmldbx_stack_get_return(&stack);

        xmldbx_stack_destroy(&stack);

        if(*zret)
        {
                ELOG("xmldbx_deserialize_xml SUCCESS");
                return SUCCESS;
        }
        else
        {
                ELOG("xmldbx_deserialize_xml FAILURE");
                return FAILURE;
        }
}
/* }}} */
/* {{{ xmldbx_constructor
 */
static XMLDBXBUF *xmldbx_constructor(void)
{
        XMLDBXBUF *xmlbuf=NULL;
        ELOG_FUNC("xmldbx_constructor");
        xmlbuf = (XMLDBXBUF *)ALLOCMEM(sizeof(XMLDBXBUF));
        memset(xmlbuf, 0, sizeof(XMLDBXBUF));
        xmldbx_zentry_init(&xmlbuf->zentry);
        return xmlbuf;
}
/* }}} */

/* {{{ xmldbx_destructor
 */
static void xmldbx_destructor(XMLDBXBUF *xmlbuf)
{
        ELOG_FUNC("xmldbx_destructor");
        smart_str_free(&xmlbuf->str);
        xmldbx_zentry_destroy(&xmlbuf->zentry);
        FREEMEM(xmlbuf);
}
/* }}} */

char *xmldbx_serialize_xml(char *name, zval **obj)
{
        XMLDBXBUF *xmlbuf=xmldbx_constructor();
        if (!xmlbuf) {
                return NULL;
        }
        else {
                xmldbx_start(xmlbuf);
                xmldbx_serialize_var(xmlbuf, *obj, name, strlen(name) 
TSRMLS_DC);
                xmldbx_end(xmlbuf);
                name = estrndup(xmlbuf->str.c, xmlbuf->str.len);
                xmldbx_destructor(xmlbuf);
                ELOG(name);
                return name;    
        }
}
#ifdef HAS_PHP_XMLDBX_FUNCTIONS
/* {{{ proto string xmldbx_serialize(string varname, mixed object)
   Creates a new xmlbuf and serializes given variables into a struct */
PHP_FUNCTION(xmldbx_serialize)
{
        int argc, i;
        char *xname=NULL;
        zval **obj;
        zval **name;
                
        ELOG_FUNC("PHP_FUNCTION(xmldbx_serialize)");
        argc = ZEND_NUM_ARGS();
        if (argc != 2) {
                php_error(E_WARNING, "%s() array to be serialized, 0 given",
                                  get_active_function_name(TSRMLS_C));
                return;
        }

        if (zend_get_parameters_ex(2, &name, &obj) == FAILURE) {
                RETURN_FALSE;
        }
                
        convert_to_string_ex(name);
        xname = Z_STRVAL_PP(name);

        xname = xmldbx_serialize_xml(Z_STRVAL_PP(name), obj);

        if(xname)
        {
                RETURN_STRING(xname,0)
        }
}
/* }}} */


/* {{{ proto mixed xmldbx_deserialize(string xmlbuf) 
   Deserializes given xmlbuf and returns a PHP value */
PHP_FUNCTION(xmldbx_deserialize)
{
        char *xmlbuf=NULL;
        int xmlbuf_len;
        xmldbx_stack stack;
        zval **zxml;
        zval *zret;

        ELOG_FUNC("PHP_FUNCTION(xmldbx_deserialize)");
        
        if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &zxml) == FAILURE)
        {
                WRONG_PARAM_COUNT;
        }
        convert_to_string_ex(zxml);

        xmlbuf = Z_STRVAL_PP(zxml);
        xmlbuf_len = strlen(xmlbuf);

        if (xmlbuf_len == 0)
                return;
                
        xmldbx_deserialize_xml(&zret, xmlbuf, xmlbuf_len);

        *return_value = *zret;
}
/* }}} */
#endif // HAS_PHP_XMLDBX_FUNCTIONS

#endif /* HAVE_LIBEXPAT */

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: sw=4 ts=4 fdm=marker
 * vim<600: sw=4 ts=4
 */

http://cvs.php.net/viewcvs.cgi/php-src/ext/xmldbx/xmldbx.h?view=markup&rev=1.1
Index: php-src/ext/xmldbx/xmldbx.h
+++ php-src/ext/xmldbx/xmldbx.h
/* 
   +----------------------------------------------------------------------+
   | PHP Version 4                                                        |
   +----------------------------------------------------------------------+
   | Copyright (c) 1997-2003 The PHP Group                                |
   +----------------------------------------------------------------------+
   | This source file is subject to version 2.02 of the PHP license,      |
   | that is bundled with this package in the file LICENSE, and is        |
   | available at through the world-wide-web at                           |
   | http://www.php.net/license/2_02.txt.                                 |
   | If you did not receive a copy of the PHP license and are unable to   |
   | obtain it through the world-wide-web, please send a note to          |
   | [EMAIL PROTECTED] so we can mail you a copy immediately.               |
   +----------------------------------------------------------------------+
   | Author:  markw@mohawksoft.com                                        |
   +----------------------------------------------------------------------+
 */

#ifndef PHP_XMLDBX_API_H
#define PHP_XMLDBX_API_H

#ifdef XMLDBX_USING_PHP
#include "ext/standard/php_smart_str.h"
#endif

// Generic XML header
#define XMLDBX_NAME_S           "<xmldbx version='1.0'>"
#define XMLDBX_NAME_E           "</xmldbx>"
#define XMLDBX_VERSION          "1.0"

// XML String ags
#define XST_UNNAMED             "unnamed"
#define XST_DATA                "data"
#define XST_NAME                "xmldbx"
#define XST_XMLARG              "xag"

// Value tag variants
// Many probably unused
#define XMLDBX_OPEN_START       "<%s t='%s' "
#define XMLDBX_OPEN_END_DEF     "/>"
#define XMLDBX_OPEN_END         ">"
#define XMLDBX_VAR_S            "<%s>"
#define XMLDBX_VAR_ST           "<%s t='%s'>"
#define XMLDBX_VAR_STAN         "<%s t='%s' %s='%d'>"
#define XMLDBX_VAR_STA          "<%s t='%s' %s='%s'>"
#define XMLDBX_VAR_STAA         "<%s t='%s' %s='%s' %s='%s'>"
#define XMLDBX_VAR_STAAN        "<%s t='%s' %s='%s' %s='%d'>"
#define XMLDBX_VAR_STN          "<%s t='%s' len='%d'>"
#define XMLDBX_VAR_E            "</%s>"
#define XMLDBX_VAR_STV          "<%s t='%s' v='%s'/>"
#define XMLDBX_VAR_STVAN        "<%s t='%s' v='%s' %s='%d'/>"
#define XMLDBX_VAR_STVA         "<%s t='%s' v='%s' %s='%s'/>"
#define XMLDBX_ATTRS            "%s='%s' "
#define XMLDBX_ATTRN            "%s='%d' "
#define XMLDBX_ATTRX            "%s='%X' "

// XML Attributes
#define XA_VALUE                "v"
#define XA_VERSION              "version"
#define XA_TYPE                 "t"
#define XA_CLASSNAME            "cn"
#define XA_NAME                 "nm"
#define XA_LEN                  "cb"
#define XA_EXTRA                "ex"
#define XA_REFERENCE            "R"
#define XA_REFCOUNT             "C"
#define XA_ISREF                "I"

// XML Types
#define XT_NULL                 "null"
#define XT_LONG                 "l"
#define XT_DOUBLE               "f"
#define XT_STRING               "sz"
#define XT_ARRAY                "a"
#define XT_OBJECT               "o"
#define XT_BOOLEAN              "b"
#define XT_RESOURCE             "rc"
#define XT_CONSTANT             "cn"
#define XT_CONSTANT_ARRAY       "cna"
#define XT_REFERENCE            "r"
#define XT_NAME                 "n"
#define XT_IGNORE               "ig"

// This enum matches the above set of XML Types
enum XMLDBX_data_types{
        ST_NULL,                /* 0 */
        ST_LONG,                /* 1 */
        ST_DOUBLE,              /* 2 */
        ST_STRING,              /* 3 */
        ST_ARRAY,               /* 4 */
        ST_OBJECT,              /* 5 */
        ST_BOOLEAN,             /* 6 */
        ST_RESOURCE,            /* 7 */
        ST_CONSTANT,            /* 8 */
        ST_CONSTANT_ARRAY,      /* 9 */
        ST_REFERENCE,           /* 10 */
        ST_NAME,                /* 11 */
        ST_IGNORE               /* 12 */
};

/** Standard operation definitions */
#define XMLDBX_BUF_LEN          1024    
#define XMLDBX_SMALLSZ          (XMLDBX_BUF_LEN/4)
/** starting size  of zval stack */
#define XMLDBX_ZSTACK_SIZE      256
/** Starting size of XML stack */
#define XMLDBX_STACK_SIZE       32

/** The state of the XML parser */
enum PROC_STATE {
        XPS_IDLE,
        XPS_XMLDBX,
        XPS_DONE,
        XPS_UNKNOWN
};

/** XML Parser tags */
typedef struct _xmldbx_stack_tags{
        int             type;                   // Data type
        int             items;                  // How many items have been 
added
        char *          xname;                  // XML Name of variable
        char *          vname;                  // Real Var name
        zval *          data;                   // Eventual data
} xmldbx_tag;

/** Types for zval stack */
typedef struct _xmldbx_zvals
{
        zval *          obj;
        char *          name;
}ZVAL_ENTRY;

typedef struct _xmldbx_zval_array
{
        int             nzvals;
        int             maxzvals;
        ZVAL_ENTRY      *zvals;
}ZVAL_ENTRIES;


/** XML parse stack */
typedef struct {
        int             top;            // Top of stack 
        int             max;            // Max depth
        int             state;          // Where we are and what we're doing
        zval*           retval;         // Data hash
        char *          endtag;         // The tag we are looking for (optional)
        ZVAL_ENTRIES    zentry;         // Track zvals 
        xmldbx_tag *    tags;           // XML tag stack
} xmldbx_stack;

/** Types for Array enumeration */
typedef struct _ArrayEnumStruct
{
        zval *          obj;            // The object ebing enumerated
        zval **         ent;            // The current entry
        HashTable *     hash;           // The HASH_OF pointer
        HashPosition    pointer;        // The current position
        char    *       key;            // The Current key
        int             keylen;         // The current key length
        ulong           ndx;            // The retrieved index number
        ulong           physndx;        // The "natural" loop index
        int             type;           // The returned type
        void *          p1;             // Passed parameter 1
        void *          p2;             // Passed parameter 2
        void *          private;        // Private data for function
}ArrayEnumStruct;
typedef int (*EnumArrayCallback)(ArrayEnumStruct *ae); 


typedef struct _xmldbx_xmlbuf
{
        smart_str       str;            // The smart string for XML creation
        zval *          zvalCurr;       // Current zval
        ZVAL_ENTRIES    zentry;         // Track zvals 
}XMLDBXBUF;

/* Make sure Zend agrees!
#define IS_NULL         0
#define IS_LONG         1
#define IS_DOUBLE       2
#define IS_STRING       3
#define IS_ARRAY        4
#define IS_OBJECT       5
#define IS_BOOL         6
#define IS_RESOURCE     7
#define IS_CONSTANT     8
#define IS_CONSTANT_ARRAY       9
*/

/* Good old fashioned debugging */
#ifdef ERR_DEBUG
#define ELOG_FUNC( str )        xmldbx_logf("%s,%d (%s)", 
__FILE__,__LINE__,str)        
#define ELOG( str )             xmldbx_logf("%s,%d (%s)", 
__FILE__,__LINE__,str)        
#else
#define ELOG_FUNC( str )
#define ELOG( str )
#endif
#ifdef ERR_DEBUG_EXTRA
#define E2LOG_FUNC( str )       xmldbx_logf("%s,%d (%s)", 
__FILE__,__LINE__,str)        
#define E2LOG( str )            xmldbx_logf("%s,%d (%s)", 
__FILE__,__LINE__,str)        
#else
#define E2LOG_FUNC( str )
#define E2LOG( str )
#endif


typedef smart_str xmldbx_buffer;

#endif /* PHP_XMLDBX_API_H */

http://cvs.php.net/viewcvs.cgi/php-src/ext/xmldbx/xmldbx.php?view=markup&rev=1.1
Index: php-src/ext/xmldbx/xmldbx.php
+++ php-src/ext/xmldbx/xmldbx.php
<?
#       xmldbx.php
#       Test xmldbx session serializer
#
class MyClass
{
        var $count;
        var $mybool;
        var $mystring;
        
        function print_vars()
        {
                print "count = " . $this->count . "<br>\n";
                print "bybool = " . $this->mybool . "<br>\n";
                print "mystring = " . $this->mystring . "<br>\n";

                $this->count++;
                if($this->mybool == True)
                        $this->mybool = False;
                else
                        $this->mybool = True;
                $this->mystring = $this->mystring . "+";
        }
};
                
        
# Start sessions, this will set a cookie.
session_start();

$sid = $HTTP_COOKIE_VARS["PHPSESSID"];

session_register("count");
session_register("setarray");
session_register("mycls");
session_register("myinit");
session_register("mybool");
session_register("myfloat");
session_register("myint");

if(!$myinit)
{
        $mycls = new MyClass();
        $myinit = true;
        $mybool = true;
        $myfloat = 1.1;
        $myint = 1;
}

if($mybool)
        $mybool = false;
else
        $mybool = true;

echo "mybool: ". $mybool . "<br>";

$myfloat = $myfloat + 1.1;
$myint = $myint + 1;
echo "myfloat: ". $myfloat . "<br>";
echo "myint: ". $myint . "<br>";




$count++;

if($count < 2)
{
        $_SESSION['setarray'] = array();
        $_SESSION['setarray']['time']=time();
        $_SESSION['setarray']['name1'] = 'xml_test1';
        $_SESSION['setarray']['name2'] = 'xml_test2';
        $_SESSION['setarray']['name3'] = 'xml_test3';
        $_SESSION['setarray']['name4'] = 'xml_test4';
        $_SESSION['setarray']['name5'] = 'xml_test5';
        $_SESSION['setarray']['name6'] = 'xml_test6';
        $_SESSION['setarray']['name7'] = 'xml_test7';
}

echo $_SESSION['setarray']['name1'] . "<br>\n";
echo $_SESSION['setarray']['name2'] . "<br>\n";
echo $_SESSION['setarray']['name3'] . "<br>\n";
echo $_SESSION['setarray']['name4'] . "<br>\n";
echo $_SESSION['setarray']['name5'] . "<br>\n";
echo $_SESSION['setarray']['name6'] . "<br>\n";
echo $_SESSION['setarray']['name7']  . "<br>\n";


$mycls->print_vars();

# Output some information.
echo "sid: " . $sid . "<br>\n";
echo "Session Count: " . $count . "<br>\n";


$xmlbuf = xmldbx_serialize("MyClass", $mycls);

echo "XMLBUF: <xmp>" . $xmlbuf . "</xmp><BR>\n";

$test = xmldbx_deserialize($xmlbuf);

$test->print_vars();

?>


-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to