summaryrefslogtreecommitdiff
path: root/ext/wddx
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2013-03-14 05:42:27 +0000
committer <>2013-04-03 16:25:08 +0000
commitc4dd7a1a684490673e25aaf4fabec5df138854c4 (patch)
tree4d57c44caae4480efff02b90b9be86f44bf25409 /ext/wddx
downloadphp2-c4dd7a1a684490673e25aaf4fabec5df138854c4.tar.gz
Imported from /home/lorry/working-area/delta_php2/php-5.4.13.tar.bz2.HEADphp-5.4.13master
Diffstat (limited to 'ext/wddx')
-rw-r--r--ext/wddx/CREDITS2
-rw-r--r--ext/wddx/config.m460
-rw-r--r--ext/wddx/config.w3213
-rw-r--r--ext/wddx/package.xml43
-rw-r--r--ext/wddx/php_wddx.h44
-rw-r--r--ext/wddx/php_wddx_api.h67
-rw-r--r--ext/wddx/tests/001-64bit.phpt62
-rw-r--r--ext/wddx/tests/001.phpt62
-rw-r--r--ext/wddx/tests/002.phpt21
-rw-r--r--ext/wddx/tests/003.phpt26
-rw-r--r--ext/wddx/tests/004.phpt63
-rw-r--r--ext/wddx/tests/005.phpt74
-rw-r--r--ext/wddx/tests/bug27287.phpt20
-rw-r--r--ext/wddx/tests/bug34306.phpt14
-rw-r--r--ext/wddx/tests/bug35410.phpt76
-rw-r--r--ext/wddx/tests/bug35410_64bit.phpt76
-rw-r--r--ext/wddx/tests/bug37569.phpt784
-rw-r--r--ext/wddx/tests/bug37587.phpt34
-rw-r--r--ext/wddx/tests/bug41283.phpt27
-rw-r--r--ext/wddx/tests/bug41527.phpt22
-rw-r--r--ext/wddx/tests/bug45901.phpt18
-rw-r--r--ext/wddx/tests/bug48562.phpt34
-rw-r--r--ext/wddx/tests/bug52468.phpt26
-rw-r--r--ext/wddx/tests/wddx.xml60
-rw-r--r--ext/wddx/wddx.c1367
25 files changed, 3095 insertions, 0 deletions
diff --git a/ext/wddx/CREDITS b/ext/wddx/CREDITS
new file mode 100644
index 0000000..4c98513
--- /dev/null
+++ b/ext/wddx/CREDITS
@@ -0,0 +1,2 @@
+WDDX
+Andrei Zmievski
diff --git a/ext/wddx/config.m4 b/ext/wddx/config.m4
new file mode 100644
index 0000000..2b02a92
--- /dev/null
+++ b/ext/wddx/config.m4
@@ -0,0 +1,60 @@
+dnl
+dnl $Id$
+dnl
+
+PHP_ARG_ENABLE(wddx,whether to enable WDDX support,
+[ --enable-wddx Enable WDDX support])
+
+if test -z "$PHP_LIBXML_DIR"; then
+ PHP_ARG_WITH(libxml-dir, libxml2 install dir,
+ [ --with-libxml-dir=DIR WDDX: libxml2 install prefix], no, no)
+fi
+
+PHP_ARG_WITH(libexpat-dir, libexpat dir for WDDX,
+[ --with-libexpat-dir=DIR WDDX: libexpat dir for XMLRPC-EPI (deprecated)],no,no)
+
+if test "$PHP_WDDX" != "no"; then
+
+ dnl
+ dnl Default to libxml2 if --with-libexpat-dir is not used
+ dnl
+ if test "$PHP_LIBEXPAT_DIR" = "no"; then
+ if test "$PHP_LIBXML" = "no"; then
+ AC_MSG_ERROR([WDDX extension requires LIBXML extension, add --enable-libxml])
+ fi
+
+ PHP_SETUP_LIBXML(WDDX_SHARED_LIBADD, [
+ if test "$PHP_XML" = "no"; then
+ PHP_ADD_SOURCES(ext/xml, compat.c)
+ PHP_ADD_BUILD_DIR(ext/xml)
+ fi
+ ], [
+ AC_MSG_ERROR([xml2-config not found. Use --with-libxml-dir=<DIR>])
+ ])
+ fi
+
+ dnl
+ dnl Check for expat only if --with-libexpat-dir is used.
+ dnl
+ if test "$PHP_LIBEXPAT_DIR" != "no"; then
+ for i in $PHP_XML $PHP_LIBEXPAT_DIR /usr /usr/local; do
+ if test -f "$i/$PHP_LIBDIR/libexpat.a" || test -f "$i/$PHP_LIBDIR/libexpat.$SHLIB_SUFFIX_NAME"; then
+ EXPAT_DIR=$i
+ break
+ fi
+ done
+
+ if test -z "$EXPAT_DIR"; then
+ AC_MSG_ERROR([not found. Please reinstall the expat distribution.])
+ fi
+
+ PHP_ADD_INCLUDE($EXPAT_DIR/include)
+ PHP_ADD_LIBRARY_WITH_PATH(expat, $EXPAT_DIR/$PHP_LIBDIR, WDDX_SHARED_LIBADD)
+ AC_DEFINE(HAVE_LIBEXPAT, 1, [ ])
+ fi
+
+ AC_DEFINE(HAVE_WDDX, 1, [ ])
+ PHP_NEW_EXTENSION(wddx, wddx.c, $ext_shared)
+ PHP_ADD_EXTENSION_DEP(wddx, libxml)
+ PHP_SUBST(XMLRPC_SHARED_LIBADD)
+fi
diff --git a/ext/wddx/config.w32 b/ext/wddx/config.w32
new file mode 100644
index 0000000..7b8483d
--- /dev/null
+++ b/ext/wddx/config.w32
@@ -0,0 +1,13 @@
+// $Id$
+// vim:ft=javascript
+
+ARG_WITH("wddx", "WDDX support", "yes");
+
+if (PHP_WDDX == "yes" && PHP_LIBXML == "yes") {
+ EXTENSION("wddx", "wddx.c");
+ AC_DEFINE("HAVE_WDDX", 1, "WDDX support");
+ ADD_EXTENSION_DEP('wddx', 'libxml');
+ CHECK_HEADER_ADD_INCLUDE("timelib_config.h", "CFLAGS_WDDX", "ext/date/lib");
+}
+
+
diff --git a/ext/wddx/package.xml b/ext/wddx/package.xml
new file mode 100644
index 0000000..9656ed1
--- /dev/null
+++ b/ext/wddx/package.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE package SYSTEM "../pear/package.dtd">
+<package>
+ <name>wddx</name>
+ <summary>WDDX serialization functions</summary>
+ <maintainers>
+ <maintainer>
+ <user>andrei</user>
+ <name>Andrei Zmievski</name>
+ <email>andrei@php.net</email>
+ <role>lead</role>
+ </maintainer>
+ </maintainers>
+ <description>
+These functions are intended for work with WDDX (http://www.openwddx.org/)
+ </description>
+ <license>PHP</license>
+ <release>
+ <state>beta</state>
+ <version>5.0.0rc1</version>
+ <date>2004-03-19</date>
+ <notes>
+package.xml added to support installation using pear installer
+ </notes>
+ <filelist>
+ <file role="doc" name="CREDITS"/>
+ <file role="src" name="config.m4"/>
+ <file role="src" name="config.w32"/>
+ <file role="src" name="wddx.c"/>
+ <file role="src" name="php_wddx.h"/>
+ <file role="src" name="php_wddx_api.h"/>
+ <file role="test" name="tests/001.phpt"/>
+ <file role="test" name="tests/wddx.xml"/>
+ <file role="test" name="tests/bug27287.phpt"/>
+ </filelist>
+ <deps>
+ <dep type="php" rel="ge" version="5" />
+ </deps>
+ </release>
+</package>
+<!--
+vim:et:ts=1:sw=1
+-->
diff --git a/ext/wddx/php_wddx.h b/ext/wddx/php_wddx.h
new file mode 100644
index 0000000..923816a
--- /dev/null
+++ b/ext/wddx/php_wddx.h
@@ -0,0 +1,44 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.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 |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Andrei Zmievski <andrei@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifndef PHP_WDDX_H
+#define PHP_WDDX_H
+
+#if HAVE_WDDX
+
+extern zend_module_entry wddx_module_entry;
+#define wddx_module_ptr &wddx_module_entry
+
+PHP_FUNCTION(wddx_serialize_value);
+PHP_FUNCTION(wddx_serialize_vars);
+PHP_FUNCTION(wddx_packet_start);
+PHP_FUNCTION(wddx_packet_end);
+PHP_FUNCTION(wddx_add_vars);
+PHP_FUNCTION(wddx_deserialize);
+
+#else
+
+#define wddx_module_ptr NULL
+
+#endif /* HAVE_WDDX */
+
+#define phpext_wddx_ptr wddx_module_ptr
+
+#endif /* !PHP_WDDX_H */
diff --git a/ext/wddx/php_wddx_api.h b/ext/wddx/php_wddx_api.h
new file mode 100644
index 0000000..1a01945
--- /dev/null
+++ b/ext/wddx/php_wddx_api.h
@@ -0,0 +1,67 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.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 |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Andrei Zmievski <andrei@ispi.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifndef PHP_WDDX_API_H
+#define PHP_WDDX_API_H
+
+#include "ext/standard/php_smart_str.h"
+
+#define WDDX_ARRAY_S "<array length='%d'>"
+#define WDDX_ARRAY_E "</array>"
+#define WDDX_BINARY_S "<binary>"
+#define WDDX_BINARY_E "</binary>"
+#define WDDX_BOOLEAN_TRUE "<boolean value='true'/>"
+#define WDDX_BOOLEAN_FALSE "<boolean value='false'/>"
+#define WDDX_CHAR "<char code='%02X'/>"
+#define WDDX_COMMENT_S "<comment>"
+#define WDDX_COMMENT_E "</comment>"
+#define WDDX_DATA_S "<data>"
+#define WDDX_DATA_E "</data>"
+#define WDDX_HEADER "<header/>"
+#define WDDX_HEADER_S "<header>"
+#define WDDX_HEADER_E "</header>"
+#define WDDX_NULL "<null/>"
+#define WDDX_NUMBER "<number>%s</number>"
+#define WDDX_PACKET_S "<wddxPacket version='1.0'>"
+#define WDDX_PACKET_E "</wddxPacket>"
+#define WDDX_STRING_S "<string>"
+#define WDDX_STRING_E "</string>"
+#define WDDX_STRUCT_S "<struct>"
+#define WDDX_STRUCT_E "</struct>"
+#define WDDX_VAR_S "<var name='%s'>"
+#define WDDX_VAR_E "</var>"
+
+#define php_wddx_add_chunk(packet, str) smart_str_appends(packet, str)
+#define php_wddx_add_chunk_ex(packet, str, len) smart_str_appendl(packet, str, len)
+#define php_wddx_add_chunk_static(packet, str) smart_str_appendl(packet, str, sizeof(str)-1)
+
+typedef smart_str wddx_packet;
+
+wddx_packet* php_wddx_constructor(void);
+void php_wddx_destructor(wddx_packet *packet);
+
+void php_wddx_packet_start(wddx_packet *packet, char *comment, int comment_len);
+void php_wddx_packet_end(wddx_packet *packet);
+
+void php_wddx_serialize_var(wddx_packet *packet, zval *var, char *name, int name_len TSRMLS_DC);
+int php_wddx_deserialize_ex(char *, int, zval *return_value);
+#define php_wddx_gather(packet) estrndup(packet->c, packet->len)
+
+#endif /* PHP_WDDX_API_H */
diff --git a/ext/wddx/tests/001-64bit.phpt b/ext/wddx/tests/001-64bit.phpt
new file mode 100644
index 0000000..78b1dc9
--- /dev/null
+++ b/ext/wddx/tests/001-64bit.phpt
@@ -0,0 +1,62 @@
+--TEST--
+wddx deserialization test (64-bit)
+--SKIPIF--
+<?php if (!extension_loaded("wddx")) print "skip"; ?>
+<?php echo PHP_INT_SIZE != 8 ? "skip 64-bit only" : "OK" ?>
+--INI--
+precision=14
+--FILE--
+<?php
+ $path = dirname(__FILE__);
+ var_dump(wddx_deserialize(file_get_contents("{$path}/wddx.xml")));
+?>
+--EXPECT--
+array(11) {
+ ["aNull"]=>
+ NULL
+ ["aString"]=>
+ string(8) "a string"
+ ["aNumber"]=>
+ float(-12.456)
+ ["aDateTime"]=>
+ int(897625932)
+ ["aDateTime2"]=>
+ int(329632332)
+ ["aDateTime3"]=>
+ int(2223088332)
+ ["aBoolean"]=>
+ bool(true)
+ ["anArray"]=>
+ array(2) {
+ [0]=>
+ int(10)
+ [1]=>
+ string(14) "second element"
+ }
+ ["aBinary"]=>
+ string(11) "binary data"
+ ["anObject"]=>
+ array(2) {
+ ["s"]=>
+ string(8) "a string"
+ ["n"]=>
+ float(-12.456)
+ }
+ ["aRecordset"]=>
+ array(2) {
+ ["NAME"]=>
+ array(2) {
+ [0]=>
+ string(8) "John Doe"
+ [1]=>
+ string(8) "Jane Doe"
+ }
+ ["AGE"]=>
+ array(2) {
+ [0]=>
+ int(34)
+ [1]=>
+ int(31)
+ }
+ }
+}
diff --git a/ext/wddx/tests/001.phpt b/ext/wddx/tests/001.phpt
new file mode 100644
index 0000000..e1aafd0
--- /dev/null
+++ b/ext/wddx/tests/001.phpt
@@ -0,0 +1,62 @@
+--TEST--
+wddx deserialization test (32-bit)
+--SKIPIF--
+<?php if (!extension_loaded("wddx")) print "skip"; ?>
+<?php echo PHP_INT_SIZE == 8 ? "skip 32-bit only" : "OK" ?>
+--INI--
+precision=14
+--FILE--
+<?php
+ $path = dirname(__FILE__);
+ var_dump(wddx_deserialize(file_get_contents("{$path}/wddx.xml")));
+?>
+--EXPECT--
+array(11) {
+ ["aNull"]=>
+ NULL
+ ["aString"]=>
+ string(8) "a string"
+ ["aNumber"]=>
+ float(-12.456)
+ ["aDateTime"]=>
+ int(897625932)
+ ["aDateTime2"]=>
+ int(329632332)
+ ["aDateTime3"]=>
+ string(22) "2040-06-12T04:32:12+00"
+ ["aBoolean"]=>
+ bool(true)
+ ["anArray"]=>
+ array(2) {
+ [0]=>
+ int(10)
+ [1]=>
+ string(14) "second element"
+ }
+ ["aBinary"]=>
+ string(11) "binary data"
+ ["anObject"]=>
+ array(2) {
+ ["s"]=>
+ string(8) "a string"
+ ["n"]=>
+ float(-12.456)
+ }
+ ["aRecordset"]=>
+ array(2) {
+ ["NAME"]=>
+ array(2) {
+ [0]=>
+ string(8) "John Doe"
+ [1]=>
+ string(8) "Jane Doe"
+ }
+ ["AGE"]=>
+ array(2) {
+ [0]=>
+ int(34)
+ [1]=>
+ int(31)
+ }
+ }
+}
diff --git a/ext/wddx/tests/002.phpt b/ext/wddx/tests/002.phpt
new file mode 100644
index 0000000..692bfa8
--- /dev/null
+++ b/ext/wddx/tests/002.phpt
@@ -0,0 +1,21 @@
+--TEST--
+wddx packet construction using wddx ressource
+--SKIPIF--
+<?php if (!extension_loaded("wddx")) print "skip"; ?>
+--INI--
+precision=14
+--FILE--
+<?php
+ $pkt = wddx_packet_start('TEST comment');
+
+ $var1 = NULL;
+ $var2 = 'some string';
+ $var3 = 756;
+ $var4 = true;
+
+ // add vars to packet
+ wddx_add_vars($pkt, 'var1', 'var2', array('var3', 'var4'));
+ echo wddx_packet_end($pkt);
+?>
+--EXPECT--
+<wddxPacket version='1.0'><header><comment>TEST comment</comment></header><data><struct><var name='var1'><null/></var><var name='var2'><string>some string</string></var><var name='var3'><number>756</number></var><var name='var4'><boolean value='true'/></var></struct></data></wddxPacket>
diff --git a/ext/wddx/tests/003.phpt b/ext/wddx/tests/003.phpt
new file mode 100644
index 0000000..3240e43
--- /dev/null
+++ b/ext/wddx/tests/003.phpt
@@ -0,0 +1,26 @@
+--TEST--
+wddx deserialize from ressource
+--SKIPIF--
+<?php if (!extension_loaded("wddx")) print "skip"; ?>
+--INI--
+precision=14
+--FILE--
+<?php
+ $path = dirname(__FILE__);
+ $fp = fopen("php://temp", 'w+');
+ fputs($fp, "<wddxPacket version='1.0'><header><comment>TEST comment</comment></header><data><struct><var name='var1'><null/></var><var name='var2'><string>some string</string></var><var name='var3'><number>756</number></var><var name='var4'><boolean value='true'/></var></struct></data></wddxPacket>");
+ rewind($fp);
+ var_dump(wddx_deserialize($fp));
+ fclose($fp);
+?>
+--EXPECT--
+array(4) {
+ ["var1"]=>
+ NULL
+ ["var2"]=>
+ string(11) "some string"
+ ["var3"]=>
+ int(756)
+ ["var4"]=>
+ bool(true)
+}
diff --git a/ext/wddx/tests/004.phpt b/ext/wddx/tests/004.phpt
new file mode 100644
index 0000000..ae5a6b4
--- /dev/null
+++ b/ext/wddx/tests/004.phpt
@@ -0,0 +1,63 @@
+--TEST--
+wddx session serializer handler (serialize)
+--SKIPIF--
+<?php
+ if (!extension_loaded("wddx")) die("skip Wddx module not loaded");
+ if (!extension_loaded('session')) die('skip Session module not enabled');
+
+ // following test code stolen from ext/session/skipif.inc
+ $save_path = ini_get("session.save_path");
+ if ($save_path) {
+ if (!file_exists($save_path)) {
+ die("skip Session save_path doesn't exist");
+ }
+
+ if ($save_path && !@is_writable($save_path)) {
+ if (($p = strpos($save_path, ';')) !== false) {
+ $save_path = substr($save_path, ++$p);
+ }
+ if (!@is_writable($save_path)) {
+ die("skip\n");
+ }
+ }
+ }
+?>
+--INI--
+precision=14
+session.serialize_handler=wddx
+session.use_cookies=0
+session.cache_limiter=
+session.save_handler=files
+--FILE--
+<?php
+ class foo {
+ public $bar = "ok";
+ public $invisible = 'you don\'t see me!';
+
+ function method() { $this->yes = "done"; }
+
+ public function __sleep() { return array('bar', 'yes'); }
+ }
+
+ session_start();
+
+ $_SESSION['data'] = array(
+ 'test1' => true,
+ 'test2' => 'some string',
+ 'test3' => 654321,
+ 'test4' => array(
+ 'some string',
+ true,
+ null
+ ),
+ );
+
+ $_SESSION['class'] = new foo();
+ $_SESSION['class']->method();
+
+ var_dump(session_encode());
+
+ session_destroy();
+?>
+--EXPECT--
+string(550) "<wddxPacket version='1.0'><header/><data><struct><var name='data'><struct><var name='test1'><boolean value='true'/></var><var name='test2'><string>some string</string></var><var name='test3'><number>654321</number></var><var name='test4'><array length='3'><string>some string</string><boolean value='true'/><null/></array></var></struct></var><var name='class'><struct><var name='php_class_name'><string>foo</string></var><var name='bar'><string>ok</string></var><var name='yes'><string>done</string></var></struct></var></struct></data></wddxPacket>"
diff --git a/ext/wddx/tests/005.phpt b/ext/wddx/tests/005.phpt
new file mode 100644
index 0000000..99e7a9e
--- /dev/null
+++ b/ext/wddx/tests/005.phpt
@@ -0,0 +1,74 @@
+--TEST--
+wddx session serializer handler (deserialize)
+--SKIPIF--
+<?php
+ if (!extension_loaded("wddx")) die("skip Wddx module not loaded");
+ if (!extension_loaded('session')) die('skip Session module not enabled');
+
+ // following test code stolen from ext/session/skipif.inc
+ $save_path = ini_get("session.save_path");
+ if ($save_path) {
+ if (!file_exists($save_path)) {
+ die("skip Session save_path doesn't exist");
+ }
+
+ if ($save_path && !@is_writable($save_path)) {
+ if (($p = strpos($save_path, ';')) !== false) {
+ $save_path = substr($save_path, ++$p);
+ }
+ if (!@is_writable($save_path)) {
+ die("skip\n");
+ }
+ }
+ }
+?>
+--INI--
+precision=14
+session.serialize_handler=wddx
+session.use_cookies=0
+session.cache_limiter=
+session.save_handler=files
+--FILE--
+<?php
+ class foo {
+ public $bar = "ok";
+
+ function method() { $this->yes = "done"; }
+ }
+
+ session_start();
+
+ session_decode("<wddxPacket version='1.0'><header/><data><struct><var name='data'><struct><var name='test1'><boolean value='true'/></var><var name='test2'><string>some string</string></var><var name='test3'><number>654321</number></var><var name='test4'><array length='3'><string>some string</string><boolean value='true'/><null/></array></var></struct></var><var name='class'><struct><var name='php_class_name'><string>foo</string></var><var name='bar'><string>ok</string></var><var name='yes'><string>done</string></var></struct></var></struct></data></wddxPacket>");
+
+ var_dump($_SESSION);
+
+ session_destroy();
+?>
+--EXPECT--
+array(2) {
+ ["data"]=>
+ array(4) {
+ ["test1"]=>
+ bool(true)
+ ["test2"]=>
+ string(11) "some string"
+ ["test3"]=>
+ int(654321)
+ ["test4"]=>
+ array(3) {
+ [0]=>
+ string(11) "some string"
+ [1]=>
+ bool(true)
+ [2]=>
+ NULL
+ }
+ }
+ ["class"]=>
+ object(foo)#1 (2) {
+ ["bar"]=>
+ string(2) "ok"
+ ["yes"]=>
+ string(4) "done"
+ }
+}
diff --git a/ext/wddx/tests/bug27287.phpt b/ext/wddx/tests/bug27287.phpt
new file mode 100644
index 0000000..72ac317
--- /dev/null
+++ b/ext/wddx/tests/bug27287.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Bug #27287 (segfault with deserializing object data)
+--SKIPIF--
+<?php if (!extension_loaded("wddx")) print "skip"; ?>
+--FILE--
+<?php
+
+ class foo {
+ }
+ $foo = new foo();
+ $foo->abc = 'def';
+
+ $string = wddx_serialize_value($foo);
+ $bar = wddx_deserialize($string);
+
+ echo "OK\n";
+
+?>
+--EXPECT--
+OK
diff --git a/ext/wddx/tests/bug34306.phpt b/ext/wddx/tests/bug34306.phpt
new file mode 100644
index 0000000..5f1a0df
--- /dev/null
+++ b/ext/wddx/tests/bug34306.phpt
@@ -0,0 +1,14 @@
+--TEST--
+#34306 (wddx_serialize_value() crashes with long array keys)
+--SKIPIF--
+<?php if (!extension_loaded("wddx")) print "skip"; ?>
+--FILE--
+<?php
+
+$var = array('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa12345678901234567890123456789012345678901234567890ba12345678901234567890123456789012345678901234567890ba12345678901234567890123456789012345678901234567890ba12345678901234567890123456789012345678901234567890b12345678901234567891234567890123123121231211111' => 1);
+$buf = wddx_serialize_value($var, 'name');
+echo "OK\n";
+
+?>
+--EXPECT--
+OK
diff --git a/ext/wddx/tests/bug35410.phpt b/ext/wddx/tests/bug35410.phpt
new file mode 100644
index 0000000..3b4b9b6
--- /dev/null
+++ b/ext/wddx/tests/bug35410.phpt
@@ -0,0 +1,76 @@
+--TEST--
+#35410 (wddx_deserialize() doesn't handle large ints as keys properly)
+--SKIPIF--
+<?php
+ if (!extension_loaded("wddx")) print "skip";
+ if (PHP_INT_SIZE != 4) die("skip this test is for 32bit platform only");
+?>
+--FILE--
+<?php
+$wddx = <<<WDX
+<wddxpacket version="1.0">
+<header>
+<comment>Content Configuration File</comment>
+</header>
+<data>
+<struct>
+<var name="content_queries">
+<struct>
+<var name="content_113300831086270200">
+<struct>
+<var name="113301888545229100">
+<struct>
+<var name="max">
+<number>10</number>
+</var>
+<var name="cache">
+<number>4</number>
+</var>
+<var name="order">
+<struct>
+<var name="content_113300831086270200">
+<struct>
+<var name="CMS_BUILD">
+<string>desc</string>
+</var>
+</struct>
+</var>
+</struct>
+</var>
+</struct>
+</var>
+</struct>
+</var>
+</struct>
+</var>
+</struct>
+</data>
+</wddxpacket>
+WDX;
+
+var_dump(wddx_deserialize($wddx));
+?>
+--EXPECT--
+array(1) {
+ ["content_queries"]=>
+ array(1) {
+ ["content_113300831086270200"]=>
+ array(1) {
+ ["113301888545229100"]=>
+ array(3) {
+ ["max"]=>
+ int(10)
+ ["cache"]=>
+ int(4)
+ ["order"]=>
+ array(1) {
+ ["content_113300831086270200"]=>
+ array(1) {
+ ["CMS_BUILD"]=>
+ string(4) "desc"
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/ext/wddx/tests/bug35410_64bit.phpt b/ext/wddx/tests/bug35410_64bit.phpt
new file mode 100644
index 0000000..15377b1
--- /dev/null
+++ b/ext/wddx/tests/bug35410_64bit.phpt
@@ -0,0 +1,76 @@
+--TEST--
+#35410 (wddx_deserialize() doesn't handle large ints as keys properly)
+--SKIPIF--
+<?php
+ if (!extension_loaded("wddx")) print "skip";
+ if (PHP_INT_SIZE != 8) die("skip this test is for 64bit platform only");
+?>
+--FILE--
+<?php
+$wddx = <<<WDX
+<wddxpacket version="1.0">
+<header>
+<comment>Content Configuration File</comment>
+</header>
+<data>
+<struct>
+<var name="content_queries">
+<struct>
+<var name="content_113300831086270200">
+<struct>
+<var name="113301888545229100">
+<struct>
+<var name="max">
+<number>10</number>
+</var>
+<var name="cache">
+<number>4</number>
+</var>
+<var name="order">
+<struct>
+<var name="content_113300831086270200">
+<struct>
+<var name="CMS_BUILD">
+<string>desc</string>
+</var>
+</struct>
+</var>
+</struct>
+</var>
+</struct>
+</var>
+</struct>
+</var>
+</struct>
+</var>
+</struct>
+</data>
+</wddxpacket>
+WDX;
+
+var_dump(wddx_deserialize($wddx));
+?>
+--EXPECT--
+array(1) {
+ ["content_queries"]=>
+ array(1) {
+ ["content_113300831086270200"]=>
+ array(1) {
+ [113301888545229100]=>
+ array(3) {
+ ["max"]=>
+ int(10)
+ ["cache"]=>
+ int(4)
+ ["order"]=>
+ array(1) {
+ ["content_113300831086270200"]=>
+ array(1) {
+ ["CMS_BUILD"]=>
+ string(4) "desc"
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/ext/wddx/tests/bug37569.phpt b/ext/wddx/tests/bug37569.phpt
new file mode 100644
index 0000000..45cd68a
--- /dev/null
+++ b/ext/wddx/tests/bug37569.phpt
@@ -0,0 +1,784 @@
+--TEST--
+Bug #37569 (WDDX incorrectly encodes high-ascii characters)
+--SKIPIF--
+<?php if (!extension_loaded("wddx")) print "skip"; ?>
+--FILE--
+<?php
+for ($i = 65; $i < 256; $i++) {
+ if ($i >= 0xc0) {
+ $v = chr(0xc3) . chr($i - 64);
+ } elseif ($i >= 0x80) {
+ $v = chr(0xc2) . chr($i);
+ } else {
+ $v = chr($i); // make it UTF-8
+ }
+ $ret = wddx_serialize_value($v);
+ echo $ret . "\n";
+ var_dump(bin2hex($v), bin2hex(wddx_deserialize($ret)), $v == wddx_deserialize($ret));
+}
+?>
+--EXPECT--
+<wddxPacket version='1.0'><header/><data><string>A</string></data></wddxPacket>
+string(2) "41"
+string(2) "41"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>B</string></data></wddxPacket>
+string(2) "42"
+string(2) "42"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>C</string></data></wddxPacket>
+string(2) "43"
+string(2) "43"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>D</string></data></wddxPacket>
+string(2) "44"
+string(2) "44"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>E</string></data></wddxPacket>
+string(2) "45"
+string(2) "45"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>F</string></data></wddxPacket>
+string(2) "46"
+string(2) "46"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>G</string></data></wddxPacket>
+string(2) "47"
+string(2) "47"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>H</string></data></wddxPacket>
+string(2) "48"
+string(2) "48"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>I</string></data></wddxPacket>
+string(2) "49"
+string(2) "49"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>J</string></data></wddxPacket>
+string(2) "4a"
+string(2) "4a"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>K</string></data></wddxPacket>
+string(2) "4b"
+string(2) "4b"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>L</string></data></wddxPacket>
+string(2) "4c"
+string(2) "4c"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>M</string></data></wddxPacket>
+string(2) "4d"
+string(2) "4d"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>N</string></data></wddxPacket>
+string(2) "4e"
+string(2) "4e"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>O</string></data></wddxPacket>
+string(2) "4f"
+string(2) "4f"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>P</string></data></wddxPacket>
+string(2) "50"
+string(2) "50"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Q</string></data></wddxPacket>
+string(2) "51"
+string(2) "51"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>R</string></data></wddxPacket>
+string(2) "52"
+string(2) "52"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>S</string></data></wddxPacket>
+string(2) "53"
+string(2) "53"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>T</string></data></wddxPacket>
+string(2) "54"
+string(2) "54"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>U</string></data></wddxPacket>
+string(2) "55"
+string(2) "55"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>V</string></data></wddxPacket>
+string(2) "56"
+string(2) "56"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>W</string></data></wddxPacket>
+string(2) "57"
+string(2) "57"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>X</string></data></wddxPacket>
+string(2) "58"
+string(2) "58"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Y</string></data></wddxPacket>
+string(2) "59"
+string(2) "59"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Z</string></data></wddxPacket>
+string(2) "5a"
+string(2) "5a"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>[</string></data></wddxPacket>
+string(2) "5b"
+string(2) "5b"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>\</string></data></wddxPacket>
+string(2) "5c"
+string(2) "5c"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>]</string></data></wddxPacket>
+string(2) "5d"
+string(2) "5d"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>^</string></data></wddxPacket>
+string(2) "5e"
+string(2) "5e"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>_</string></data></wddxPacket>
+string(2) "5f"
+string(2) "5f"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>`</string></data></wddxPacket>
+string(2) "60"
+string(2) "60"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>a</string></data></wddxPacket>
+string(2) "61"
+string(2) "61"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>b</string></data></wddxPacket>
+string(2) "62"
+string(2) "62"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>c</string></data></wddxPacket>
+string(2) "63"
+string(2) "63"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>d</string></data></wddxPacket>
+string(2) "64"
+string(2) "64"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>e</string></data></wddxPacket>
+string(2) "65"
+string(2) "65"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>f</string></data></wddxPacket>
+string(2) "66"
+string(2) "66"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>g</string></data></wddxPacket>
+string(2) "67"
+string(2) "67"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>h</string></data></wddxPacket>
+string(2) "68"
+string(2) "68"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>i</string></data></wddxPacket>
+string(2) "69"
+string(2) "69"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>j</string></data></wddxPacket>
+string(2) "6a"
+string(2) "6a"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>k</string></data></wddxPacket>
+string(2) "6b"
+string(2) "6b"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>l</string></data></wddxPacket>
+string(2) "6c"
+string(2) "6c"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>m</string></data></wddxPacket>
+string(2) "6d"
+string(2) "6d"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>n</string></data></wddxPacket>
+string(2) "6e"
+string(2) "6e"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>o</string></data></wddxPacket>
+string(2) "6f"
+string(2) "6f"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>p</string></data></wddxPacket>
+string(2) "70"
+string(2) "70"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>q</string></data></wddxPacket>
+string(2) "71"
+string(2) "71"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>r</string></data></wddxPacket>
+string(2) "72"
+string(2) "72"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>s</string></data></wddxPacket>
+string(2) "73"
+string(2) "73"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>t</string></data></wddxPacket>
+string(2) "74"
+string(2) "74"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>u</string></data></wddxPacket>
+string(2) "75"
+string(2) "75"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>v</string></data></wddxPacket>
+string(2) "76"
+string(2) "76"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>w</string></data></wddxPacket>
+string(2) "77"
+string(2) "77"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>x</string></data></wddxPacket>
+string(2) "78"
+string(2) "78"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>y</string></data></wddxPacket>
+string(2) "79"
+string(2) "79"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>z</string></data></wddxPacket>
+string(2) "7a"
+string(2) "7a"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>{</string></data></wddxPacket>
+string(2) "7b"
+string(2) "7b"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>|</string></data></wddxPacket>
+string(2) "7c"
+string(2) "7c"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>}</string></data></wddxPacket>
+string(2) "7d"
+string(2) "7d"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>~</string></data></wddxPacket>
+string(2) "7e"
+string(2) "7e"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string></string></data></wddxPacket>
+string(2) "7f"
+string(2) "7f"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>€</string></data></wddxPacket>
+string(4) "c280"
+string(4) "c280"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string></string></data></wddxPacket>
+string(4) "c281"
+string(4) "c281"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>‚</string></data></wddxPacket>
+string(4) "c282"
+string(4) "c282"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>ƒ</string></data></wddxPacket>
+string(4) "c283"
+string(4) "c283"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>„</string></data></wddxPacket>
+string(4) "c284"
+string(4) "c284"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>…</string></data></wddxPacket>
+string(4) "c285"
+string(4) "c285"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>†</string></data></wddxPacket>
+string(4) "c286"
+string(4) "c286"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>‡</string></data></wddxPacket>
+string(4) "c287"
+string(4) "c287"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>ˆ</string></data></wddxPacket>
+string(4) "c288"
+string(4) "c288"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>‰</string></data></wddxPacket>
+string(4) "c289"
+string(4) "c289"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Š</string></data></wddxPacket>
+string(4) "c28a"
+string(4) "c28a"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>‹</string></data></wddxPacket>
+string(4) "c28b"
+string(4) "c28b"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Œ</string></data></wddxPacket>
+string(4) "c28c"
+string(4) "c28c"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string></string></data></wddxPacket>
+string(4) "c28d"
+string(4) "c28d"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Ž</string></data></wddxPacket>
+string(4) "c28e"
+string(4) "c28e"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string></string></data></wddxPacket>
+string(4) "c28f"
+string(4) "c28f"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string></string></data></wddxPacket>
+string(4) "c290"
+string(4) "c290"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>‘</string></data></wddxPacket>
+string(4) "c291"
+string(4) "c291"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>’</string></data></wddxPacket>
+string(4) "c292"
+string(4) "c292"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>“</string></data></wddxPacket>
+string(4) "c293"
+string(4) "c293"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>”</string></data></wddxPacket>
+string(4) "c294"
+string(4) "c294"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>•</string></data></wddxPacket>
+string(4) "c295"
+string(4) "c295"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>–</string></data></wddxPacket>
+string(4) "c296"
+string(4) "c296"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>—</string></data></wddxPacket>
+string(4) "c297"
+string(4) "c297"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>˜</string></data></wddxPacket>
+string(4) "c298"
+string(4) "c298"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>™</string></data></wddxPacket>
+string(4) "c299"
+string(4) "c299"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>š</string></data></wddxPacket>
+string(4) "c29a"
+string(4) "c29a"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>›</string></data></wddxPacket>
+string(4) "c29b"
+string(4) "c29b"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>œ</string></data></wddxPacket>
+string(4) "c29c"
+string(4) "c29c"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string></string></data></wddxPacket>
+string(4) "c29d"
+string(4) "c29d"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>ž</string></data></wddxPacket>
+string(4) "c29e"
+string(4) "c29e"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Ÿ</string></data></wddxPacket>
+string(4) "c29f"
+string(4) "c29f"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string> </string></data></wddxPacket>
+string(4) "c2a0"
+string(4) "c2a0"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>¡</string></data></wddxPacket>
+string(4) "c2a1"
+string(4) "c2a1"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>¢</string></data></wddxPacket>
+string(4) "c2a2"
+string(4) "c2a2"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>£</string></data></wddxPacket>
+string(4) "c2a3"
+string(4) "c2a3"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>¤</string></data></wddxPacket>
+string(4) "c2a4"
+string(4) "c2a4"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>¥</string></data></wddxPacket>
+string(4) "c2a5"
+string(4) "c2a5"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>¦</string></data></wddxPacket>
+string(4) "c2a6"
+string(4) "c2a6"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>§</string></data></wddxPacket>
+string(4) "c2a7"
+string(4) "c2a7"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>¨</string></data></wddxPacket>
+string(4) "c2a8"
+string(4) "c2a8"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>©</string></data></wddxPacket>
+string(4) "c2a9"
+string(4) "c2a9"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>ª</string></data></wddxPacket>
+string(4) "c2aa"
+string(4) "c2aa"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>«</string></data></wddxPacket>
+string(4) "c2ab"
+string(4) "c2ab"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>¬</string></data></wddxPacket>
+string(4) "c2ac"
+string(4) "c2ac"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>­</string></data></wddxPacket>
+string(4) "c2ad"
+string(4) "c2ad"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>®</string></data></wddxPacket>
+string(4) "c2ae"
+string(4) "c2ae"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>¯</string></data></wddxPacket>
+string(4) "c2af"
+string(4) "c2af"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>°</string></data></wddxPacket>
+string(4) "c2b0"
+string(4) "c2b0"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>±</string></data></wddxPacket>
+string(4) "c2b1"
+string(4) "c2b1"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>²</string></data></wddxPacket>
+string(4) "c2b2"
+string(4) "c2b2"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>³</string></data></wddxPacket>
+string(4) "c2b3"
+string(4) "c2b3"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>´</string></data></wddxPacket>
+string(4) "c2b4"
+string(4) "c2b4"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>µ</string></data></wddxPacket>
+string(4) "c2b5"
+string(4) "c2b5"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>¶</string></data></wddxPacket>
+string(4) "c2b6"
+string(4) "c2b6"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>·</string></data></wddxPacket>
+string(4) "c2b7"
+string(4) "c2b7"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>¸</string></data></wddxPacket>
+string(4) "c2b8"
+string(4) "c2b8"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>¹</string></data></wddxPacket>
+string(4) "c2b9"
+string(4) "c2b9"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>º</string></data></wddxPacket>
+string(4) "c2ba"
+string(4) "c2ba"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>»</string></data></wddxPacket>
+string(4) "c2bb"
+string(4) "c2bb"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>¼</string></data></wddxPacket>
+string(4) "c2bc"
+string(4) "c2bc"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>½</string></data></wddxPacket>
+string(4) "c2bd"
+string(4) "c2bd"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>¾</string></data></wddxPacket>
+string(4) "c2be"
+string(4) "c2be"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>¿</string></data></wddxPacket>
+string(4) "c2bf"
+string(4) "c2bf"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>À</string></data></wddxPacket>
+string(4) "c380"
+string(4) "c380"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Á</string></data></wddxPacket>
+string(4) "c381"
+string(4) "c381"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Â</string></data></wddxPacket>
+string(4) "c382"
+string(4) "c382"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Ã</string></data></wddxPacket>
+string(4) "c383"
+string(4) "c383"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Ä</string></data></wddxPacket>
+string(4) "c384"
+string(4) "c384"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Å</string></data></wddxPacket>
+string(4) "c385"
+string(4) "c385"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Æ</string></data></wddxPacket>
+string(4) "c386"
+string(4) "c386"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Ç</string></data></wddxPacket>
+string(4) "c387"
+string(4) "c387"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>È</string></data></wddxPacket>
+string(4) "c388"
+string(4) "c388"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>É</string></data></wddxPacket>
+string(4) "c389"
+string(4) "c389"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Ê</string></data></wddxPacket>
+string(4) "c38a"
+string(4) "c38a"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Ë</string></data></wddxPacket>
+string(4) "c38b"
+string(4) "c38b"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Ì</string></data></wddxPacket>
+string(4) "c38c"
+string(4) "c38c"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Í</string></data></wddxPacket>
+string(4) "c38d"
+string(4) "c38d"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Î</string></data></wddxPacket>
+string(4) "c38e"
+string(4) "c38e"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Ï</string></data></wddxPacket>
+string(4) "c38f"
+string(4) "c38f"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Ð</string></data></wddxPacket>
+string(4) "c390"
+string(4) "c390"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Ñ</string></data></wddxPacket>
+string(4) "c391"
+string(4) "c391"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Ò</string></data></wddxPacket>
+string(4) "c392"
+string(4) "c392"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Ó</string></data></wddxPacket>
+string(4) "c393"
+string(4) "c393"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Ô</string></data></wddxPacket>
+string(4) "c394"
+string(4) "c394"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Õ</string></data></wddxPacket>
+string(4) "c395"
+string(4) "c395"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Ö</string></data></wddxPacket>
+string(4) "c396"
+string(4) "c396"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>×</string></data></wddxPacket>
+string(4) "c397"
+string(4) "c397"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Ø</string></data></wddxPacket>
+string(4) "c398"
+string(4) "c398"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Ù</string></data></wddxPacket>
+string(4) "c399"
+string(4) "c399"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Ú</string></data></wddxPacket>
+string(4) "c39a"
+string(4) "c39a"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Û</string></data></wddxPacket>
+string(4) "c39b"
+string(4) "c39b"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Ü</string></data></wddxPacket>
+string(4) "c39c"
+string(4) "c39c"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Ý</string></data></wddxPacket>
+string(4) "c39d"
+string(4) "c39d"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>Þ</string></data></wddxPacket>
+string(4) "c39e"
+string(4) "c39e"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>ß</string></data></wddxPacket>
+string(4) "c39f"
+string(4) "c39f"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>à</string></data></wddxPacket>
+string(4) "c3a0"
+string(4) "c3a0"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>á</string></data></wddxPacket>
+string(4) "c3a1"
+string(4) "c3a1"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>â</string></data></wddxPacket>
+string(4) "c3a2"
+string(4) "c3a2"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>ã</string></data></wddxPacket>
+string(4) "c3a3"
+string(4) "c3a3"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>ä</string></data></wddxPacket>
+string(4) "c3a4"
+string(4) "c3a4"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>å</string></data></wddxPacket>
+string(4) "c3a5"
+string(4) "c3a5"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>æ</string></data></wddxPacket>
+string(4) "c3a6"
+string(4) "c3a6"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>ç</string></data></wddxPacket>
+string(4) "c3a7"
+string(4) "c3a7"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>è</string></data></wddxPacket>
+string(4) "c3a8"
+string(4) "c3a8"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>é</string></data></wddxPacket>
+string(4) "c3a9"
+string(4) "c3a9"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>ê</string></data></wddxPacket>
+string(4) "c3aa"
+string(4) "c3aa"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>ë</string></data></wddxPacket>
+string(4) "c3ab"
+string(4) "c3ab"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>ì</string></data></wddxPacket>
+string(4) "c3ac"
+string(4) "c3ac"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>í</string></data></wddxPacket>
+string(4) "c3ad"
+string(4) "c3ad"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>î</string></data></wddxPacket>
+string(4) "c3ae"
+string(4) "c3ae"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>ï</string></data></wddxPacket>
+string(4) "c3af"
+string(4) "c3af"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>ð</string></data></wddxPacket>
+string(4) "c3b0"
+string(4) "c3b0"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>ñ</string></data></wddxPacket>
+string(4) "c3b1"
+string(4) "c3b1"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>ò</string></data></wddxPacket>
+string(4) "c3b2"
+string(4) "c3b2"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>ó</string></data></wddxPacket>
+string(4) "c3b3"
+string(4) "c3b3"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>ô</string></data></wddxPacket>
+string(4) "c3b4"
+string(4) "c3b4"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>õ</string></data></wddxPacket>
+string(4) "c3b5"
+string(4) "c3b5"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>ö</string></data></wddxPacket>
+string(4) "c3b6"
+string(4) "c3b6"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>÷</string></data></wddxPacket>
+string(4) "c3b7"
+string(4) "c3b7"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>ø</string></data></wddxPacket>
+string(4) "c3b8"
+string(4) "c3b8"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>ù</string></data></wddxPacket>
+string(4) "c3b9"
+string(4) "c3b9"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>ú</string></data></wddxPacket>
+string(4) "c3ba"
+string(4) "c3ba"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>û</string></data></wddxPacket>
+string(4) "c3bb"
+string(4) "c3bb"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>ü</string></data></wddxPacket>
+string(4) "c3bc"
+string(4) "c3bc"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>ý</string></data></wddxPacket>
+string(4) "c3bd"
+string(4) "c3bd"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>þ</string></data></wddxPacket>
+string(4) "c3be"
+string(4) "c3be"
+bool(true)
+<wddxPacket version='1.0'><header/><data><string>ÿ</string></data></wddxPacket>
+string(4) "c3bf"
+string(4) "c3bf"
+bool(true)
diff --git a/ext/wddx/tests/bug37587.phpt b/ext/wddx/tests/bug37587.phpt
new file mode 100644
index 0000000..7780355
--- /dev/null
+++ b/ext/wddx/tests/bug37587.phpt
@@ -0,0 +1,34 @@
+--TEST--
+Bug #37587 (var without attribute causes segfault)
+--SKIPIF--
+<?php if (!extension_loaded("wddx")) print "skip"; ?>
+--FILE--
+<?php
+
+var_dump(wddx_deserialize(<<<EOF
+<wddxPacket version='1.0'>
+<header/>
+<data>
+ <array length='1'>
+ <var>
+ <struct>
+ <var name='test'><string>Hello World</string></var>
+ </struct>
+ </var>
+ </array>
+</data>
+</wddxPacket>
+EOF
+));
+
+?>
+===DONE===
+--EXPECT--
+array(1) {
+ [0]=>
+ array(1) {
+ ["test"]=>
+ string(11) "Hello World"
+ }
+}
+===DONE===
diff --git a/ext/wddx/tests/bug41283.phpt b/ext/wddx/tests/bug41283.phpt
new file mode 100644
index 0000000..af716d1
--- /dev/null
+++ b/ext/wddx/tests/bug41283.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Bug #41283 (Bug with serializing array key that are doubles or floats)
+--SKIPIF--
+<?php if (!extension_loaded("wddx")) print "skip"; ?>
+--FILE--
+<?php
+$data = array(
+ 'somearray' => array('1.1' => 'One 1','1.2' => 'One 2', '1.0' => 'Three')
+);
+
+var_dump(wddx_deserialize(wddx_serialize_vars('data')));
+?>
+--EXPECT--
+array(1) {
+ ["data"]=>
+ array(1) {
+ ["somearray"]=>
+ array(3) {
+ ["1.1"]=>
+ string(5) "One 1"
+ ["1.2"]=>
+ string(5) "One 2"
+ ["1.0"]=>
+ string(5) "Three"
+ }
+ }
+}
diff --git a/ext/wddx/tests/bug41527.phpt b/ext/wddx/tests/bug41527.phpt
new file mode 100644
index 0000000..447bfc3
--- /dev/null
+++ b/ext/wddx/tests/bug41527.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Bug #41527 (WDDX deserialize numeric string array keys)
+--SKIPIF--
+<?php if (!extension_loaded("wddx")) print "skip"; ?>
+--FILE--
+<?php
+$data = array('01' => 'Zero', '+1' => 'Plus sign', ' 1' => 'Space');
+
+var_dump(wddx_deserialize(wddx_serialize_vars('data')));
+?>
+--EXPECT--
+array(1) {
+ ["data"]=>
+ array(3) {
+ ["01"]=>
+ string(4) "Zero"
+ ["+1"]=>
+ string(9) "Plus sign"
+ [" 1"]=>
+ string(5) "Space"
+ }
+}
diff --git a/ext/wddx/tests/bug45901.phpt b/ext/wddx/tests/bug45901.phpt
new file mode 100644
index 0000000..4084ccb
--- /dev/null
+++ b/ext/wddx/tests/bug45901.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Bug #45901 (wddx_serialize_value crash with SimpleXMLElement object)
+--SKIPIF--
+<?php
+if (!extension_loaded("wddx")) print "skip";
+if (!extension_loaded("simplexml")) print "skip SimpleXML not present";
+?>
+--FILE--
+<?php
+
+$xml = new SimpleXMLElement('<data></data>');
+$xml->addChild('test');
+echo wddx_serialize_value($xml, 'Variables') . "\n";
+echo "DONE";
+?>
+--EXPECTF--
+<wddxPacket version='1.0'><header><comment>Variables</comment></header><data><struct><var name='php_class_name'><string>SimpleXMLElement</string></var><var name='test'><struct><var name='php_class_name'><string>SimpleXMLElement</string></var></struct></var></struct></data></wddxPacket>
+DONE \ No newline at end of file
diff --git a/ext/wddx/tests/bug48562.phpt b/ext/wddx/tests/bug48562.phpt
new file mode 100644
index 0000000..ee9f271
--- /dev/null
+++ b/ext/wddx/tests/bug48562.phpt
@@ -0,0 +1,34 @@
+--TEST--
+Bug #48562 (Reference recursion causes segfault when used in wddx_serialize_vars())
+--SKIPIF--
+<?php
+if (!extension_loaded('wddx')) {
+ die('skip. wddx not available');
+}
+?>
+--FILE--
+<?php
+
+$foo = 'bar';
+
+$a['x'] = 'foo';
+$a['x'] = &$a;
+
+var_dump(wddx_serialize_vars($a));
+
+// replace $a - the recursion detection seems to be causing $a to be not an array here, maybe its internally a pointer
+// replacing $a with a new array() allows this test to still check for 2 things
+// 1. recursion detection in &$a;
+// 2. recursion detection in adding $a to itself and then serializing $a
+// the one thing the test won't check is using $a as an array after doing &$a; which isn't really a wddx problem.
+$a = array();
+$a['x'] = 'foo';
+$a['x'] = $a;
+
+var_dump(wddx_serialize_vars($a));
+
+?>
+--EXPECTF--
+Warning: wddx_serialize_vars(): recursion detected in %s on line %d
+string(78) "<wddxPacket version='1.0'><header/><data><struct></struct></data></wddxPacket>"
+string(120) "<wddxPacket version='1.0'><header/><data><struct><var name='foo'><string>bar</string></var></struct></data></wddxPacket>"
diff --git a/ext/wddx/tests/bug52468.phpt b/ext/wddx/tests/bug52468.phpt
new file mode 100644
index 0000000..b0d8eb3
--- /dev/null
+++ b/ext/wddx/tests/bug52468.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Bug #52468 (wddx_deserialize corrupts integer field value when left empty)
+--SKIPIF--
+<?php
+if (!extension_loaded('wddx')) {
+ die('skip. wddx not available');
+}
+?>
+--FILE--
+<?php
+
+$message = "<wddxPacket version='1.0'><header><comment>my_command</comment></header><data><struct><var name='handle'><number></number></var></struct></data></wddxPacket>";
+
+print_r(wddx_deserialize($message));
+print_r(wddx_deserialize($message));
+
+?>
+--EXPECT--
+Array
+(
+ [handle] => 0
+)
+Array
+(
+ [handle] => 0
+)
diff --git a/ext/wddx/tests/wddx.xml b/ext/wddx/tests/wddx.xml
new file mode 100644
index 0000000..0085709
--- /dev/null
+++ b/ext/wddx/tests/wddx.xml
@@ -0,0 +1,60 @@
+<?xml version='1.0'?>
+<!DOCTYPE wddxPacket SYSTEM 'wddx_0100.dtd'>
+<wddxPacket version='1.0'>
+<header/>
+ <data>
+ <struct>
+ <var name='aNull'>
+ <null/>
+ </var>
+ <var name='aString'>
+ <string>a string</string>
+ </var>
+ <var name='aNumber'>
+ <number>-12.456</number>
+ </var>
+ <var name='aDateTime'>
+ <dateTime>1998-06-12T04:32:12+00</dateTime>
+ </var>
+ <var name='aDateTime2'>
+ <dateTime>1980-06-12T04:32:12+00</dateTime>
+ </var>
+ <var name='aDateTime3'>
+ <dateTime>2040-06-12T04:32:12+00</dateTime>
+ </var>
+ <var name='aBoolean'>
+ <boolean value='true'/>
+ </var>
+ <var name='anArray'>
+ <array length='2'>
+ <number>10</number>
+ <string>second element</string>
+ </array>
+ </var>
+ <var name='aBinary'>
+ <binary length='11'>YmluYXJ5IGRhdGE=</binary>
+ </var>
+ <var name='anObject'>
+ <struct>
+ <var name='s'>
+ <string>a string</string>
+ </var>
+ <var name='n'>
+ <number>-12.456</number>
+ </var>
+ </struct>
+ </var>
+ <var name='aRecordset'>
+ <recordset rowCount='2' fieldNames='NAME,AGE'>
+ <field name='NAME'>
+ <string>John Doe</string>
+ <string>Jane Doe</string>
+ </field>
+ <field name='AGE'>
+ <number>34</number>
+ <number>31</number>
+ </field>
+ </recordset>
+ </struct>
+ </data>
+</wddxPacket>
diff --git a/ext/wddx/wddx.c b/ext/wddx/wddx.c
new file mode 100644
index 0000000..967da6a
--- /dev/null
+++ b/ext/wddx/wddx.c
@@ -0,0 +1,1367 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.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 |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Andrei Zmievski <andrei@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+
+#if HAVE_WDDX
+
+#include "ext/xml/expat_compat.h"
+#include "php_wddx.h"
+#include "php_wddx_api.h"
+
+#define PHP_XML_INTERNAL
+#include "ext/xml/php_xml.h"
+#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/date/php_date.h"
+#include "zend_globals.h"
+
+#define WDDX_BUF_LEN 256
+#define PHP_CLASS_NAME_VAR "php_class_name"
+
+#define EL_ARRAY "array"
+#define EL_BINARY "binary"
+#define EL_BOOLEAN "boolean"
+#define EL_CHAR "char"
+#define EL_CHAR_CODE "code"
+#define EL_NULL "null"
+#define EL_NUMBER "number"
+#define EL_PACKET "wddxPacket"
+#define EL_STRING "string"
+#define EL_STRUCT "struct"
+#define EL_VALUE "value"
+#define EL_VAR "var"
+#define EL_NAME "name"
+#define EL_VERSION "version"
+#define EL_RECORDSET "recordset"
+#define EL_FIELD "field"
+#define EL_DATETIME "dateTime"
+
+#define php_wddx_deserialize(a,b) \
+ php_wddx_deserialize_ex((a)->value.str.val, (a)->value.str.len, (b))
+
+#define SET_STACK_VARNAME \
+ if (stack->varname) { \
+ ent.varname = estrdup(stack->varname); \
+ efree(stack->varname); \
+ stack->varname = NULL; \
+ } else \
+ ent.varname = NULL; \
+
+static int le_wddx;
+
+typedef struct {
+ zval *data;
+ enum {
+ ST_ARRAY,
+ ST_BOOLEAN,
+ ST_NULL,
+ ST_NUMBER,
+ ST_STRING,
+ ST_BINARY,
+ ST_STRUCT,
+ ST_RECORDSET,
+ ST_FIELD,
+ ST_DATETIME
+ } type;
+ char *varname;
+} st_entry;
+
+typedef struct {
+ int top, max;
+ char *varname;
+ zend_bool done;
+ void **elements;
+} wddx_stack;
+
+
+static void php_wddx_process_data(void *user_data, const XML_Char *s, int len);
+
+/* {{{ arginfo */
+ZEND_BEGIN_ARG_INFO_EX(arginfo_wddx_serialize_value, 0, 0, 1)
+ ZEND_ARG_INFO(0, var)
+ ZEND_ARG_INFO(0, comment)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_wddx_serialize_vars, 0, 0, 1)
+ ZEND_ARG_INFO(0, var_name)
+ ZEND_ARG_INFO(0, ...)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_wddx_serialize_start, 0, 0, 0)
+ ZEND_ARG_INFO(0, comment)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_wddx_packet_end, 0, 0, 1)
+ ZEND_ARG_INFO(0, packet_id)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_wddx_add_vars, 0, 0, 2)
+ ZEND_ARG_INFO(0, packet_id)
+ ZEND_ARG_INFO(0, var_name)
+ ZEND_ARG_INFO(0, ...)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_wddx_deserialize, 0, 0, 1)
+ ZEND_ARG_INFO(0, packet)
+ZEND_END_ARG_INFO()
+/* }}} */
+
+/* {{{ wddx_functions[]
+ */
+const zend_function_entry wddx_functions[] = {
+ PHP_FE(wddx_serialize_value, arginfo_wddx_serialize_value)
+ PHP_FE(wddx_serialize_vars, arginfo_wddx_serialize_vars)
+ PHP_FE(wddx_packet_start, arginfo_wddx_serialize_start)
+ PHP_FE(wddx_packet_end, arginfo_wddx_packet_end)
+ PHP_FE(wddx_add_vars, arginfo_wddx_add_vars)
+ PHP_FE(wddx_deserialize, arginfo_wddx_deserialize)
+ PHP_FE_END
+};
+/* }}} */
+
+PHP_MINIT_FUNCTION(wddx);
+PHP_MINFO_FUNCTION(wddx);
+
+/* {{{ dynamically loadable module stuff */
+#ifdef COMPILE_DL_WDDX
+ZEND_GET_MODULE(wddx)
+#endif /* COMPILE_DL_WDDX */
+/* }}} */
+
+/* {{{ wddx_module_entry
+ */
+zend_module_entry wddx_module_entry = {
+ STANDARD_MODULE_HEADER,
+ "wddx",
+ wddx_functions,
+ PHP_MINIT(wddx),
+ NULL,
+ NULL,
+ NULL,
+ PHP_MINFO(wddx),
+ NO_VERSION_YET,
+ STANDARD_MODULE_PROPERTIES
+};
+/* }}} */
+
+/* {{{ wddx_stack_init
+ */
+static int wddx_stack_init(wddx_stack *stack)
+{
+ stack->top = 0;
+ stack->elements = (void **) safe_emalloc(sizeof(void **), STACK_BLOCK_SIZE, 0);
+ stack->max = STACK_BLOCK_SIZE;
+ stack->varname = NULL;
+ stack->done = 0;
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ wddx_stack_push
+ */
+static int wddx_stack_push(wddx_stack *stack, void *element, int size)
+{
+ if (stack->top >= stack->max) { /* we need to allocate more memory */
+ stack->elements = (void **) erealloc(stack->elements,
+ (sizeof(void **) * (stack->max += STACK_BLOCK_SIZE)));
+ }
+ stack->elements[stack->top] = (void *) emalloc(size);
+ memcpy(stack->elements[stack->top], element, size);
+ return stack->top++;
+}
+/* }}} */
+
+/* {{{ wddx_stack_top
+ */
+static int wddx_stack_top(wddx_stack *stack, void **element)
+{
+ if (stack->top > 0) {
+ *element = stack->elements[stack->top - 1];
+ return SUCCESS;
+ } else {
+ *element = NULL;
+ return FAILURE;
+ }
+}
+/* }}} */
+
+/* {{{ wddx_stack_is_empty
+ */
+static int wddx_stack_is_empty(wddx_stack *stack)
+{
+ if (stack->top == 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+/* }}} */
+
+/* {{{ wddx_stack_destroy
+ */
+static int wddx_stack_destroy(wddx_stack *stack)
+{
+ register int i;
+
+ if (stack->elements) {
+ for (i = 0; i < stack->top; i++) {
+ if (((st_entry *)stack->elements[i])->data) {
+ zval_ptr_dtor(&((st_entry *)stack->elements[i])->data);
+ }
+ if (((st_entry *)stack->elements[i])->varname) {
+ efree(((st_entry *)stack->elements[i])->varname);
+ }
+ efree(stack->elements[i]);
+ }
+ efree(stack->elements);
+ }
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ release_wddx_packet_rsrc
+ */
+static void release_wddx_packet_rsrc(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+{
+ smart_str *str = (smart_str *)rsrc->ptr;
+ smart_str_free(str);
+ efree(str);
+}
+/* }}} */
+
+#include "ext/session/php_session.h"
+
+#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
+/* {{{ PS_SERIALIZER_ENCODE_FUNC
+ */
+PS_SERIALIZER_ENCODE_FUNC(wddx)
+{
+ wddx_packet *packet;
+ PS_ENCODE_VARS;
+
+ packet = php_wddx_constructor();
+
+ php_wddx_packet_start(packet, NULL, 0);
+ php_wddx_add_chunk_static(packet, WDDX_STRUCT_S);
+
+ PS_ENCODE_LOOP(
+ php_wddx_serialize_var(packet, *struc, key, key_length TSRMLS_CC);
+ );
+
+ php_wddx_add_chunk_static(packet, WDDX_STRUCT_E);
+ php_wddx_packet_end(packet);
+ *newstr = php_wddx_gather(packet);
+ php_wddx_destructor(packet);
+
+ if (newlen) {
+ *newlen = strlen(*newstr);
+ }
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PS_SERIALIZER_DECODE_FUNC
+ */
+PS_SERIALIZER_DECODE_FUNC(wddx)
+{
+ zval *retval;
+ zval **ent;
+ char *key;
+ uint key_length;
+ char tmp[128];
+ ulong idx;
+ int hash_type;
+ int ret;
+
+ if (vallen == 0) {
+ return SUCCESS;
+ }
+
+ MAKE_STD_ZVAL(retval);
+
+ if ((ret = php_wddx_deserialize_ex((char *)val, vallen, retval)) == SUCCESS) {
+
+ for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(retval));
+ zend_hash_get_current_data(Z_ARRVAL_P(retval), (void **) &ent) == SUCCESS;
+ zend_hash_move_forward(Z_ARRVAL_P(retval))) {
+ hash_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(retval), &key, &key_length, &idx, 0, NULL);
+
+ switch (hash_type) {
+ case HASH_KEY_IS_LONG:
+ key_length = slprintf(tmp, sizeof(tmp), "%ld", idx) + 1;
+ key = tmp;
+ /* fallthru */
+ case HASH_KEY_IS_STRING:
+ php_set_session_var(key, key_length-1, *ent, NULL TSRMLS_CC);
+ PS_ADD_VAR(key);
+ }
+ }
+ }
+
+ zval_ptr_dtor(&retval);
+
+ return ret;
+}
+/* }}} */
+#endif
+
+/* {{{ PHP_MINIT_FUNCTION
+ */
+PHP_MINIT_FUNCTION(wddx)
+{
+ le_wddx = zend_register_list_destructors_ex(release_wddx_packet_rsrc, NULL, "wddx", module_number);
+
+#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
+ php_session_register_serializer("wddx",
+ PS_SERIALIZER_ENCODE_NAME(wddx),
+ PS_SERIALIZER_DECODE_NAME(wddx));
+#endif
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MINFO_FUNCTION
+ */
+PHP_MINFO_FUNCTION(wddx)
+{
+ php_info_print_table_start();
+#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
+ php_info_print_table_header(2, "WDDX Support", "enabled" );
+ php_info_print_table_row(2, "WDDX Session Serializer", "enabled" );
+#else
+ php_info_print_table_row(2, "WDDX Support", "enabled" );
+#endif
+ php_info_print_table_end();
+}
+/* }}} */
+
+/* {{{ php_wddx_packet_start
+ */
+void php_wddx_packet_start(wddx_packet *packet, char *comment, int comment_len)
+{
+ php_wddx_add_chunk_static(packet, WDDX_PACKET_S);
+ if (comment) {
+ php_wddx_add_chunk_static(packet, WDDX_HEADER_S);
+ php_wddx_add_chunk_static(packet, WDDX_COMMENT_S);
+ php_wddx_add_chunk_ex(packet, comment, comment_len);
+ php_wddx_add_chunk_static(packet, WDDX_COMMENT_E);
+ php_wddx_add_chunk_static(packet, WDDX_HEADER_E);
+ } else {
+ php_wddx_add_chunk_static(packet, WDDX_HEADER);
+ }
+ php_wddx_add_chunk_static(packet, WDDX_DATA_S);
+}
+/* }}} */
+
+/* {{{ php_wddx_packet_end
+ */
+void php_wddx_packet_end(wddx_packet *packet)
+{
+ php_wddx_add_chunk_static(packet, WDDX_DATA_E);
+ php_wddx_add_chunk_static(packet, WDDX_PACKET_E);
+}
+/* }}} */
+
+#define FLUSH_BUF() \
+ if (l > 0) { \
+ php_wddx_add_chunk_ex(packet, buf, l); \
+ l = 0; \
+ }
+
+/* {{{ php_wddx_serialize_string
+ */
+static void php_wddx_serialize_string(wddx_packet *packet, zval *var TSRMLS_DC)
+{
+ php_wddx_add_chunk_static(packet, WDDX_STRING_S);
+
+ if (Z_STRLEN_P(var) > 0) {
+ char *buf;
+ int buf_len;
+
+ buf = php_escape_html_entities(Z_STRVAL_P(var), Z_STRLEN_P(var), &buf_len, 0, ENT_QUOTES, NULL TSRMLS_CC);
+
+ php_wddx_add_chunk_ex(packet, buf, buf_len);
+
+ efree(buf);
+ }
+ php_wddx_add_chunk_static(packet, WDDX_STRING_E);
+}
+/* }}} */
+
+/* {{{ php_wddx_serialize_number
+ */
+static void php_wddx_serialize_number(wddx_packet *packet, zval *var)
+{
+ char tmp_buf[WDDX_BUF_LEN];
+ zval tmp;
+
+ tmp = *var;
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ snprintf(tmp_buf, sizeof(tmp_buf), WDDX_NUMBER, Z_STRVAL(tmp));
+ zval_dtor(&tmp);
+
+ php_wddx_add_chunk(packet, tmp_buf);
+}
+/* }}} */
+
+/* {{{ php_wddx_serialize_boolean
+ */
+static void php_wddx_serialize_boolean(wddx_packet *packet, zval *var)
+{
+ php_wddx_add_chunk(packet, Z_LVAL_P(var) ? WDDX_BOOLEAN_TRUE : WDDX_BOOLEAN_FALSE);
+}
+/* }}} */
+
+/* {{{ php_wddx_serialize_unset
+ */
+static void php_wddx_serialize_unset(wddx_packet *packet)
+{
+ php_wddx_add_chunk_static(packet, WDDX_NULL);
+}
+/* }}} */
+
+/* {{{ php_wddx_serialize_object
+ */
+static void php_wddx_serialize_object(wddx_packet *packet, zval *obj)
+{
+/* OBJECTS_FIXME */
+ zval **ent, *fname, **varname;
+ zval *retval = NULL;
+ const char *key;
+ ulong idx;
+ char tmp_buf[WDDX_BUF_LEN];
+ HashTable *objhash, *sleephash;
+ TSRMLS_FETCH();
+
+ MAKE_STD_ZVAL(fname);
+ ZVAL_STRING(fname, "__sleep", 1);
+
+ /*
+ * We try to call __sleep() method on object. It's supposed to return an
+ * array of property names to be serialized.
+ */
+ if (call_user_function_ex(CG(function_table), &obj, fname, &retval, 0, 0, 1, NULL TSRMLS_CC) == SUCCESS) {
+ if (retval && (sleephash = HASH_OF(retval))) {
+ PHP_CLASS_ATTRIBUTES;
+
+ PHP_SET_CLASS_ATTRIBUTES(obj);
+
+ php_wddx_add_chunk_static(packet, WDDX_STRUCT_S);
+ snprintf(tmp_buf, WDDX_BUF_LEN, WDDX_VAR_S, PHP_CLASS_NAME_VAR);
+ php_wddx_add_chunk(packet, tmp_buf);
+ php_wddx_add_chunk_static(packet, WDDX_STRING_S);
+ php_wddx_add_chunk_ex(packet, class_name, name_len);
+ php_wddx_add_chunk_static(packet, WDDX_STRING_E);
+ php_wddx_add_chunk_static(packet, WDDX_VAR_E);
+
+ PHP_CLEANUP_CLASS_ATTRIBUTES();
+
+ objhash = HASH_OF(obj);
+
+ for (zend_hash_internal_pointer_reset(sleephash);
+ zend_hash_get_current_data(sleephash, (void **)&varname) == SUCCESS;
+ zend_hash_move_forward(sleephash)) {
+ if (Z_TYPE_PP(varname) != IS_STRING) {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "__sleep should return an array only containing the names of instance-variables to serialize.");
+ continue;
+ }
+
+ if (zend_hash_find(objhash, Z_STRVAL_PP(varname), Z_STRLEN_PP(varname)+1, (void **)&ent) == SUCCESS) {
+ php_wddx_serialize_var(packet, *ent, Z_STRVAL_PP(varname), Z_STRLEN_PP(varname) TSRMLS_CC);
+ }
+ }
+
+ php_wddx_add_chunk_static(packet, WDDX_STRUCT_E);
+ }
+ } else {
+ uint key_len;
+
+ PHP_CLASS_ATTRIBUTES;
+
+ PHP_SET_CLASS_ATTRIBUTES(obj);
+
+ php_wddx_add_chunk_static(packet, WDDX_STRUCT_S);
+ snprintf(tmp_buf, WDDX_BUF_LEN, WDDX_VAR_S, PHP_CLASS_NAME_VAR);
+ php_wddx_add_chunk(packet, tmp_buf);
+ php_wddx_add_chunk_static(packet, WDDX_STRING_S);
+ php_wddx_add_chunk_ex(packet, class_name, name_len);
+ php_wddx_add_chunk_static(packet, WDDX_STRING_E);
+ php_wddx_add_chunk_static(packet, WDDX_VAR_E);
+
+ PHP_CLEANUP_CLASS_ATTRIBUTES();
+
+ objhash = HASH_OF(obj);
+ for (zend_hash_internal_pointer_reset(objhash);
+ zend_hash_get_current_data(objhash, (void**)&ent) == SUCCESS;
+ zend_hash_move_forward(objhash)) {
+ if (*ent == obj) {
+ continue;
+ }
+
+ if (zend_hash_get_current_key_ex(objhash, &key, &key_len, &idx, 0, NULL) == HASH_KEY_IS_STRING) {
+ const char *class_name, *prop_name;
+
+ zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name);
+ php_wddx_serialize_var(packet, *ent, prop_name, strlen(prop_name)+1 TSRMLS_CC);
+ } else {
+ key_len = slprintf(tmp_buf, sizeof(tmp_buf), "%ld", idx);
+ php_wddx_serialize_var(packet, *ent, tmp_buf, key_len TSRMLS_CC);
+ }
+ }
+ php_wddx_add_chunk_static(packet, WDDX_STRUCT_E);
+ }
+
+ zval_dtor(fname);
+ FREE_ZVAL(fname);
+
+ if (retval) {
+ zval_ptr_dtor(&retval);
+ }
+}
+/* }}} */
+
+/* {{{ php_wddx_serialize_array
+ */
+static void php_wddx_serialize_array(wddx_packet *packet, zval *arr)
+{
+ zval **ent;
+ char *key;
+ uint key_len;
+ int is_struct = 0, ent_type;
+ ulong idx;
+ HashTable *target_hash;
+ char tmp_buf[WDDX_BUF_LEN];
+ ulong ind = 0;
+ int type;
+ TSRMLS_FETCH();
+
+ target_hash = HASH_OF(arr);
+
+ for (zend_hash_internal_pointer_reset(target_hash);
+ zend_hash_get_current_data(target_hash, (void**)&ent) == SUCCESS;
+ zend_hash_move_forward(target_hash)) {
+
+ type = zend_hash_get_current_key(target_hash, &key, &idx, 0);
+
+ if (type == HASH_KEY_IS_STRING) {
+ is_struct = 1;
+ break;
+ }
+
+ if (idx != ind) {
+ is_struct = 1;
+ break;
+ }
+
+ ind++;
+ }
+
+ if (is_struct) {
+ php_wddx_add_chunk_static(packet, WDDX_STRUCT_S);
+ } else {
+ snprintf(tmp_buf, sizeof(tmp_buf), WDDX_ARRAY_S, zend_hash_num_elements(target_hash));
+ php_wddx_add_chunk(packet, tmp_buf);
+ }
+
+ for (zend_hash_internal_pointer_reset(target_hash);
+ zend_hash_get_current_data(target_hash, (void**)&ent) == SUCCESS;
+ zend_hash_move_forward(target_hash)) {
+ if (*ent == arr) {
+ continue;
+ }
+
+ if (is_struct) {
+ ent_type = zend_hash_get_current_key_ex(target_hash, &key, &key_len, &idx, 0, NULL);
+
+ if (ent_type == HASH_KEY_IS_STRING) {
+ php_wddx_serialize_var(packet, *ent, key, key_len TSRMLS_CC);
+ } else {
+ key_len = slprintf(tmp_buf, sizeof(tmp_buf), "%ld", idx);
+ php_wddx_serialize_var(packet, *ent, tmp_buf, key_len TSRMLS_CC);
+ }
+ } else {
+ php_wddx_serialize_var(packet, *ent, NULL, 0 TSRMLS_CC);
+ }
+ }
+
+ if (is_struct) {
+ php_wddx_add_chunk_static(packet, WDDX_STRUCT_E);
+ } else {
+ php_wddx_add_chunk_static(packet, WDDX_ARRAY_E);
+ }
+}
+/* }}} */
+
+/* {{{ php_wddx_serialize_var
+ */
+void php_wddx_serialize_var(wddx_packet *packet, zval *var, char *name, int name_len TSRMLS_DC)
+{
+ char *tmp_buf;
+ char *name_esc;
+ int name_esc_len;
+ HashTable *ht;
+
+ if (name) {
+ name_esc = php_escape_html_entities(name, name_len, &name_esc_len, 0, ENT_QUOTES, NULL TSRMLS_CC);
+ tmp_buf = emalloc(name_esc_len + sizeof(WDDX_VAR_S));
+ snprintf(tmp_buf, name_esc_len + sizeof(WDDX_VAR_S), WDDX_VAR_S, name_esc);
+ php_wddx_add_chunk(packet, tmp_buf);
+ efree(tmp_buf);
+ efree(name_esc);
+ }
+
+ switch(Z_TYPE_P(var)) {
+ case IS_STRING:
+ php_wddx_serialize_string(packet, var TSRMLS_CC);
+ break;
+
+ case IS_LONG:
+ case IS_DOUBLE:
+ php_wddx_serialize_number(packet, var);
+ break;
+
+ case IS_BOOL:
+ php_wddx_serialize_boolean(packet, var);
+ break;
+
+ case IS_NULL:
+ php_wddx_serialize_unset(packet);
+ break;
+
+ case IS_ARRAY:
+ ht = Z_ARRVAL_P(var);
+ if (ht->nApplyCount > 1) {
+ php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "WDDX doesn't support circular references");
+ return;
+ }
+ ht->nApplyCount++;
+ php_wddx_serialize_array(packet, var);
+ ht->nApplyCount--;
+ break;
+
+ case IS_OBJECT:
+ ht = Z_OBJPROP_P(var);
+ if (ht->nApplyCount > 1) {
+ php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "WDDX doesn't support circular references");
+ return;
+ }
+ ht->nApplyCount++;
+ php_wddx_serialize_object(packet, var);
+ ht->nApplyCount--;
+ break;
+ }
+
+ if (name) {
+ php_wddx_add_chunk_static(packet, WDDX_VAR_E);
+ }
+}
+/* }}} */
+
+/* {{{ php_wddx_add_var
+ */
+static void php_wddx_add_var(wddx_packet *packet, zval *name_var)
+{
+ zval **val;
+ HashTable *target_hash;
+ TSRMLS_FETCH();
+
+ if (Z_TYPE_P(name_var) == IS_STRING) {
+ if (!EG(active_symbol_table)) {
+ zend_rebuild_symbol_table(TSRMLS_C);
+ }
+ if (zend_hash_find(EG(active_symbol_table), Z_STRVAL_P(name_var),
+ Z_STRLEN_P(name_var)+1, (void**)&val) != FAILURE) {
+ php_wddx_serialize_var(packet, *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) {
+ int is_array = Z_TYPE_P(name_var) == IS_ARRAY;
+
+ target_hash = HASH_OF(name_var);
+
+ if (is_array && target_hash->nApplyCount > 1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
+ return;
+ }
+
+ zend_hash_internal_pointer_reset(target_hash);
+
+ while(zend_hash_get_current_data(target_hash, (void**)&val) == SUCCESS) {
+ if (is_array) {
+ target_hash->nApplyCount++;
+ }
+
+ php_wddx_add_var(packet, *val);
+
+ if (is_array) {
+ target_hash->nApplyCount--;
+ }
+ zend_hash_move_forward(target_hash);
+ }
+ }
+}
+/* }}} */
+
+/* {{{ php_wddx_push_element
+ */
+static void php_wddx_push_element(void *user_data, const XML_Char *name, const XML_Char **atts)
+{
+ st_entry ent;
+ wddx_stack *stack = (wddx_stack *)user_data;
+
+ if (!strcmp(name, EL_PACKET)) {
+ int i;
+
+ if (atts) for (i=0; atts[i]; i++) {
+ if (!strcmp(atts[i], EL_VERSION)) {
+ /* nothing for now */
+ }
+ }
+ } else if (!strcmp(name, EL_STRING)) {
+ ent.type = ST_STRING;
+ SET_STACK_VARNAME;
+
+ ALLOC_ZVAL(ent.data);
+ INIT_PZVAL(ent.data);
+ Z_TYPE_P(ent.data) = IS_STRING;
+ Z_STRVAL_P(ent.data) = STR_EMPTY_ALLOC();
+ Z_STRLEN_P(ent.data) = 0;
+ wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
+ } else if (!strcmp(name, EL_BINARY)) {
+ ent.type = ST_BINARY;
+ SET_STACK_VARNAME;
+
+ ALLOC_ZVAL(ent.data);
+ INIT_PZVAL(ent.data);
+ Z_TYPE_P(ent.data) = IS_STRING;
+ Z_STRVAL_P(ent.data) = STR_EMPTY_ALLOC();
+ Z_STRLEN_P(ent.data) = 0;
+ wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
+ } else if (!strcmp(name, EL_CHAR)) {
+ int i;
+
+ if (atts) for (i = 0; atts[i]; i++) {
+ if (!strcmp(atts[i], EL_CHAR_CODE) && atts[++i] && atts[i][0]) {
+ char tmp_buf[2];
+
+ snprintf(tmp_buf, sizeof(tmp_buf), "%c", (char)strtol(atts[i], NULL, 16));
+ php_wddx_process_data(user_data, tmp_buf, strlen(tmp_buf));
+ break;
+ }
+ }
+ } else if (!strcmp(name, EL_NUMBER)) {
+ ent.type = ST_NUMBER;
+ SET_STACK_VARNAME;
+
+ ALLOC_ZVAL(ent.data);
+ INIT_PZVAL(ent.data);
+ Z_TYPE_P(ent.data) = IS_LONG;
+ Z_LVAL_P(ent.data) = 0;
+ wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
+ } else if (!strcmp(name, EL_BOOLEAN)) {
+ int i;
+
+ if (atts) for (i = 0; atts[i]; i++) {
+ if (!strcmp(atts[i], EL_VALUE) && atts[++i] && atts[i][0]) {
+ ent.type = ST_BOOLEAN;
+ SET_STACK_VARNAME;
+
+ ALLOC_ZVAL(ent.data);
+ INIT_PZVAL(ent.data);
+ Z_TYPE_P(ent.data) = IS_BOOL;
+ wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
+ php_wddx_process_data(user_data, atts[i], strlen(atts[i]));
+ break;
+ }
+ }
+ } else if (!strcmp(name, EL_NULL)) {
+ ent.type = ST_NULL;
+ SET_STACK_VARNAME;
+
+ ALLOC_ZVAL(ent.data);
+ INIT_PZVAL(ent.data);
+ ZVAL_NULL(ent.data);
+
+ wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
+ } else if (!strcmp(name, EL_ARRAY)) {
+ ent.type = ST_ARRAY;
+ SET_STACK_VARNAME;
+
+ ALLOC_ZVAL(ent.data);
+ array_init(ent.data);
+ INIT_PZVAL(ent.data);
+ wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
+ } else if (!strcmp(name, EL_STRUCT)) {
+ ent.type = ST_STRUCT;
+ SET_STACK_VARNAME;
+
+ ALLOC_ZVAL(ent.data);
+ array_init(ent.data);
+ INIT_PZVAL(ent.data);
+ wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
+ } else if (!strcmp(name, EL_VAR)) {
+ int i;
+
+ if (atts) for (i = 0; atts[i]; i++) {
+ if (!strcmp(atts[i], EL_NAME) && atts[++i] && atts[i][0]) {
+ stack->varname = estrdup(atts[i]);
+ break;
+ }
+ }
+ } else if (!strcmp(name, EL_RECORDSET)) {
+ int i;
+
+ ent.type = ST_RECORDSET;
+ SET_STACK_VARNAME;
+ MAKE_STD_ZVAL(ent.data);
+ array_init(ent.data);
+
+ if (atts) for (i = 0; atts[i]; i++) {
+ if (!strcmp(atts[i], "fieldNames") && atts[++i] && atts[i][0]) {
+ zval *tmp;
+ char *key;
+ char *p1, *p2, *endp;
+
+ endp = (char *)atts[i] + strlen(atts[i]);
+ p1 = (char *)atts[i];
+ while ((p2 = php_memnstr(p1, ",", sizeof(",")-1, endp)) != NULL) {
+ key = estrndup(p1, p2 - p1);
+ MAKE_STD_ZVAL(tmp);
+ array_init(tmp);
+ add_assoc_zval_ex(ent.data, key, p2 - p1 + 1, tmp);
+ p1 = p2 + sizeof(",")-1;
+ efree(key);
+ }
+
+ if (p1 <= endp) {
+ MAKE_STD_ZVAL(tmp);
+ array_init(tmp);
+ add_assoc_zval_ex(ent.data, p1, endp - p1 + 1, tmp);
+ }
+
+ break;
+ }
+ }
+
+ wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
+ } else if (!strcmp(name, EL_FIELD)) {
+ int i;
+ st_entry ent;
+
+ ent.type = ST_FIELD;
+ ent.varname = NULL;
+ ent.data = NULL;
+
+ if (atts) for (i = 0; atts[i]; i++) {
+ if (!strcmp(atts[i], EL_NAME) && atts[++i] && atts[i][0]) {
+ st_entry *recordset;
+ zval **field;
+
+ if (wddx_stack_top(stack, (void**)&recordset) == SUCCESS &&
+ recordset->type == ST_RECORDSET &&
+ zend_hash_find(Z_ARRVAL_P(recordset->data), (char*)atts[i], strlen(atts[i])+1, (void**)&field) == SUCCESS) {
+ ent.data = *field;
+ }
+
+ break;
+ }
+ }
+
+ wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
+ } else if (!strcmp(name, EL_DATETIME)) {
+ ent.type = ST_DATETIME;
+ SET_STACK_VARNAME;
+
+ ALLOC_ZVAL(ent.data);
+ INIT_PZVAL(ent.data);
+ Z_TYPE_P(ent.data) = IS_LONG;
+ wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
+ }
+}
+/* }}} */
+
+/* {{{ php_wddx_pop_element
+ */
+static void php_wddx_pop_element(void *user_data, const XML_Char *name)
+{
+ st_entry *ent1, *ent2;
+ wddx_stack *stack = (wddx_stack *)user_data;
+ HashTable *target_hash;
+ zend_class_entry **pce;
+ zval *obj;
+ zval *tmp;
+ TSRMLS_FETCH();
+
+/* OBJECTS_FIXME */
+ if (stack->top == 0) {
+ return;
+ }
+
+ if (!strcmp(name, EL_STRING) || !strcmp(name, EL_NUMBER) ||
+ !strcmp(name, EL_BOOLEAN) || !strcmp(name, EL_NULL) ||
+ !strcmp(name, EL_ARRAY) || !strcmp(name, EL_STRUCT) ||
+ !strcmp(name, EL_RECORDSET) || !strcmp(name, EL_BINARY) ||
+ !strcmp(name, EL_DATETIME)) {
+ wddx_stack_top(stack, (void**)&ent1);
+
+ if (!strcmp(name, EL_BINARY)) {
+ int new_len=0;
+ unsigned char *new_str;
+
+ new_str = php_base64_decode(Z_STRVAL_P(ent1->data), Z_STRLEN_P(ent1->data), &new_len);
+ STR_FREE(Z_STRVAL_P(ent1->data));
+ Z_STRVAL_P(ent1->data) = new_str;
+ Z_STRLEN_P(ent1->data) = new_len;
+ }
+
+ /* Call __wakeup() method on the object. */
+ if (Z_TYPE_P(ent1->data) == IS_OBJECT) {
+ zval *fname, *retval = NULL;
+
+ MAKE_STD_ZVAL(fname);
+ ZVAL_STRING(fname, "__wakeup", 1);
+
+ call_user_function_ex(NULL, &ent1->data, fname, &retval, 0, 0, 0, NULL TSRMLS_CC);
+
+ zval_dtor(fname);
+ FREE_ZVAL(fname);
+ if (retval) {
+ zval_ptr_dtor(&retval);
+ }
+ }
+
+ if (stack->top > 1) {
+ stack->top--;
+ wddx_stack_top(stack, (void**)&ent2);
+
+ /* if non-existent field */
+ if (ent2->type == ST_FIELD && ent2->data == NULL) {
+ zval_ptr_dtor(&ent1->data);
+ efree(ent1);
+ return;
+ }
+
+ if (Z_TYPE_P(ent2->data) == IS_ARRAY || Z_TYPE_P(ent2->data) == IS_OBJECT) {
+ target_hash = HASH_OF(ent2->data);
+
+ if (ent1->varname) {
+ if (!strcmp(ent1->varname, PHP_CLASS_NAME_VAR) &&
+ Z_TYPE_P(ent1->data) == IS_STRING && Z_STRLEN_P(ent1->data)) {
+ zend_bool incomplete_class = 0;
+
+ zend_str_tolower(Z_STRVAL_P(ent1->data), Z_STRLEN_P(ent1->data));
+ if (zend_hash_find(EG(class_table), Z_STRVAL_P(ent1->data),
+ Z_STRLEN_P(ent1->data)+1, (void **) &pce)==FAILURE) {
+ incomplete_class = 1;
+ pce = &PHP_IC_ENTRY;
+ }
+
+ /* Initialize target object */
+ MAKE_STD_ZVAL(obj);
+ object_init_ex(obj, *pce);
+
+ /* Merge current hashtable with object's default properties */
+ zend_hash_merge(Z_OBJPROP_P(obj),
+ Z_ARRVAL_P(ent2->data),
+ (void (*)(void *)) zval_add_ref,
+ (void *) &tmp, sizeof(zval *), 0);
+
+ if (incomplete_class) {
+ php_store_class_name(obj, Z_STRVAL_P(ent1->data), Z_STRLEN_P(ent1->data));
+ }
+
+ /* Clean up old array entry */
+ zval_ptr_dtor(&ent2->data);
+
+ /* Set stack entry to point to the newly created object */
+ ent2->data = obj;
+
+ /* Clean up class name var entry */
+ zval_ptr_dtor(&ent1->data);
+ } else if (Z_TYPE_P(ent2->data) == IS_OBJECT) {
+ zend_class_entry *old_scope = EG(scope);
+
+ EG(scope) = Z_OBJCE_P(ent2->data);
+ Z_DELREF_P(ent1->data);
+ add_property_zval(ent2->data, ent1->varname, ent1->data);
+ EG(scope) = old_scope;
+ } else {
+ zend_symtable_update(target_hash, ent1->varname, strlen(ent1->varname)+1, &ent1->data, sizeof(zval *), NULL);
+ }
+ efree(ent1->varname);
+ } else {
+ zend_hash_next_index_insert(target_hash, &ent1->data, sizeof(zval *), NULL);
+ }
+ }
+ efree(ent1);
+ } else {
+ stack->done = 1;
+ }
+ } else if (!strcmp(name, EL_VAR) && stack->varname) {
+ efree(stack->varname);
+ } else if (!strcmp(name, EL_FIELD)) {
+ st_entry *ent;
+ wddx_stack_top(stack, (void **)&ent);
+ efree(ent);
+ stack->top--;
+ }
+}
+/* }}} */
+
+/* {{{ php_wddx_process_data
+ */
+static void php_wddx_process_data(void *user_data, const XML_Char *s, int len)
+{
+ st_entry *ent;
+ wddx_stack *stack = (wddx_stack *)user_data;
+ TSRMLS_FETCH();
+
+ if (!wddx_stack_is_empty(stack) && !stack->done) {
+ wddx_stack_top(stack, (void**)&ent);
+ switch (Z_TYPE_P(ent)) {
+ case ST_STRING:
+ if (Z_STRLEN_P(ent->data) == 0) {
+ STR_FREE(Z_STRVAL_P(ent->data));
+ Z_STRVAL_P(ent->data) = estrndup(s, len);
+ Z_STRLEN_P(ent->data) = len;
+ } else {
+ Z_STRVAL_P(ent->data) = erealloc(Z_STRVAL_P(ent->data), Z_STRLEN_P(ent->data) + len + 1);
+ memcpy(Z_STRVAL_P(ent->data) + Z_STRLEN_P(ent->data), s, len);
+ Z_STRLEN_P(ent->data) += len;
+ Z_STRVAL_P(ent->data)[Z_STRLEN_P(ent->data)] = '\0';
+ }
+ break;
+
+ case ST_BINARY:
+ if (Z_STRLEN_P(ent->data) == 0) {
+ STR_FREE(Z_STRVAL_P(ent->data));
+ Z_STRVAL_P(ent->data) = estrndup(s, len + 1);
+ } else {
+ Z_STRVAL_P(ent->data) = erealloc(Z_STRVAL_P(ent->data), Z_STRLEN_P(ent->data) + len + 1);
+ memcpy(Z_STRVAL_P(ent->data) + Z_STRLEN_P(ent->data), s, len);
+ }
+ Z_STRLEN_P(ent->data) += len;
+ Z_STRVAL_P(ent->data)[Z_STRLEN_P(ent->data)] = '\0';
+ break;
+
+ case ST_NUMBER:
+ Z_TYPE_P(ent->data) = IS_STRING;
+ Z_STRLEN_P(ent->data) = len;
+ Z_STRVAL_P(ent->data) = estrndup(s, len);
+ convert_scalar_to_number(ent->data TSRMLS_CC);
+ break;
+
+ case ST_BOOLEAN:
+ if (!strcmp(s, "true")) {
+ Z_LVAL_P(ent->data) = 1;
+ } else if (!strcmp(s, "false")) {
+ Z_LVAL_P(ent->data) = 0;
+ } else {
+ stack->top--;
+ zval_ptr_dtor(&ent->data);
+ if (ent->varname)
+ efree(ent->varname);
+ efree(ent);
+ }
+ break;
+
+ case ST_DATETIME: {
+ char *tmp;
+
+ tmp = emalloc(len + 1);
+ memcpy(tmp, s, len);
+ tmp[len] = '\0';
+
+ Z_LVAL_P(ent->data) = php_parse_date(tmp, NULL);
+ /* date out of range < 1969 or > 2038 */
+ if (Z_LVAL_P(ent->data) == -1) {
+ Z_TYPE_P(ent->data) = IS_STRING;
+ Z_STRLEN_P(ent->data) = len;
+ Z_STRVAL_P(ent->data) = estrndup(s, len);
+ }
+ efree(tmp);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+/* }}} */
+
+/* {{{ php_wddx_deserialize_ex
+ */
+int php_wddx_deserialize_ex(char *value, int vallen, zval *return_value)
+{
+ wddx_stack stack;
+ XML_Parser parser;
+ st_entry *ent;
+ int retval;
+
+ wddx_stack_init(&stack);
+ parser = XML_ParserCreate("UTF-8");
+
+ XML_SetUserData(parser, &stack);
+ XML_SetElementHandler(parser, php_wddx_push_element, php_wddx_pop_element);
+ XML_SetCharacterDataHandler(parser, php_wddx_process_data);
+
+ XML_Parse(parser, value, vallen, 1);
+
+ XML_ParserFree(parser);
+
+ if (stack.top == 1) {
+ wddx_stack_top(&stack, (void**)&ent);
+ *return_value = *(ent->data);
+ zval_copy_ctor(return_value);
+ retval = SUCCESS;
+ } else {
+ retval = FAILURE;
+ }
+
+ wddx_stack_destroy(&stack);
+
+ return retval;
+}
+/* }}} */
+
+/* {{{ proto string wddx_serialize_value(mixed var [, string comment])
+ Creates a new packet and serializes the given value */
+PHP_FUNCTION(wddx_serialize_value)
+{
+ zval *var;
+ char *comment = NULL;
+ int comment_len = 0;
+ wddx_packet *packet;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|s", &var, &comment, &comment_len) == FAILURE) {
+ return;
+ }
+
+ packet = php_wddx_constructor();
+
+ php_wddx_packet_start(packet, comment, comment_len);
+ php_wddx_serialize_var(packet, var, NULL, 0 TSRMLS_CC);
+ php_wddx_packet_end(packet);
+
+ ZVAL_STRINGL(return_value, packet->c, packet->len, 1);
+ smart_str_free(packet);
+ efree(packet);
+}
+/* }}} */
+
+/* {{{ proto string wddx_serialize_vars(mixed var_name [, mixed ...])
+ Creates a new packet and serializes given variables into a struct */
+PHP_FUNCTION(wddx_serialize_vars)
+{
+ int num_args, i;
+ wddx_packet *packet;
+ zval ***args = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &num_args) == FAILURE) {
+ return;
+ }
+
+ packet = php_wddx_constructor();
+
+ php_wddx_packet_start(packet, NULL, 0);
+ php_wddx_add_chunk_static(packet, WDDX_STRUCT_S);
+
+ for (i=0; i<num_args; i++) {
+ if (Z_TYPE_PP(args[i]) != IS_ARRAY && Z_TYPE_PP(args[i]) != IS_OBJECT) {
+ convert_to_string_ex(args[i]);
+ }
+ php_wddx_add_var(packet, *args[i]);
+ }
+
+ php_wddx_add_chunk_static(packet, WDDX_STRUCT_E);
+ php_wddx_packet_end(packet);
+
+ efree(args);
+
+ ZVAL_STRINGL(return_value, packet->c, packet->len, 1);
+ smart_str_free(packet);
+ efree(packet);
+}
+/* }}} */
+
+/* {{{ php_wddx_constructor
+ */
+wddx_packet *php_wddx_constructor(void)
+{
+ smart_str *packet;
+
+ packet = (smart_str *)emalloc(sizeof(smart_str));
+ packet->c = NULL;
+
+ return packet;
+}
+/* }}} */
+
+/* {{{ php_wddx_destructor
+ */
+void php_wddx_destructor(wddx_packet *packet)
+{
+ smart_str_free(packet);
+ efree(packet);
+}
+/* }}} */
+
+/* {{{ proto resource wddx_packet_start([string comment])
+ Starts a WDDX packet with optional comment and returns the packet id */
+PHP_FUNCTION(wddx_packet_start)
+{
+ char *comment = NULL;
+ int comment_len = 0;
+ wddx_packet *packet;
+
+ comment = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &comment, &comment_len) == FAILURE) {
+ return;
+ }
+
+ packet = php_wddx_constructor();
+
+ php_wddx_packet_start(packet, comment, comment_len);
+ php_wddx_add_chunk_static(packet, WDDX_STRUCT_S);
+
+ ZEND_REGISTER_RESOURCE(return_value, packet, le_wddx);
+}
+/* }}} */
+
+/* {{{ proto string wddx_packet_end(resource packet_id)
+ Ends specified WDDX packet and returns the string containing the packet */
+PHP_FUNCTION(wddx_packet_end)
+{
+ zval *packet_id;
+ wddx_packet *packet = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &packet_id) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(packet, wddx_packet *, &packet_id, -1, "WDDX packet ID", le_wddx);
+
+ php_wddx_add_chunk_static(packet, WDDX_STRUCT_E);
+
+ php_wddx_packet_end(packet);
+
+ ZVAL_STRINGL(return_value, packet->c, packet->len, 1);
+
+ zend_list_delete(Z_LVAL_P(packet_id));
+}
+/* }}} */
+
+/* {{{ proto int wddx_add_vars(resource packet_id, mixed var_names [, mixed ...])
+ Serializes given variables and adds them to packet given by packet_id */
+PHP_FUNCTION(wddx_add_vars)
+{
+ int num_args, i;
+ zval ***args = NULL;
+ zval *packet_id;
+ wddx_packet *packet = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r+", &packet_id, &args, &num_args) == FAILURE) {
+ return;
+ }
+
+ if (!ZEND_FETCH_RESOURCE_NO_RETURN(packet, wddx_packet *, &packet_id, -1, "WDDX packet ID", le_wddx)) {
+ efree(args);
+ RETURN_FALSE;
+ }
+
+ if (!packet) {
+ efree(args);
+ RETURN_FALSE;
+ }
+
+ for (i=0; i<num_args; i++) {
+ if (Z_TYPE_PP(args[i]) != IS_ARRAY && Z_TYPE_PP(args[i]) != IS_OBJECT) {
+ convert_to_string_ex(args[i]);
+ }
+ php_wddx_add_var(packet, (*args[i]));
+ }
+
+ efree(args);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto mixed wddx_deserialize(mixed packet)
+ Deserializes given packet and returns a PHP value */
+PHP_FUNCTION(wddx_deserialize)
+{
+ zval *packet;
+ char *payload;
+ int payload_len;
+ php_stream *stream = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &packet) == FAILURE) {
+ return;
+ }
+
+ if (Z_TYPE_P(packet) == IS_STRING) {
+ payload = Z_STRVAL_P(packet);
+ payload_len = Z_STRLEN_P(packet);
+ } else if (Z_TYPE_P(packet) == IS_RESOURCE) {
+ php_stream_from_zval(stream, &packet);
+ if (stream) {
+ payload_len = php_stream_copy_to_mem(stream, &payload, PHP_STREAM_COPY_ALL, 0);
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expecting parameter 1 to be a string or a stream");
+ return;
+ }
+
+ if (payload_len == 0) {
+ return;
+ }
+
+ php_wddx_deserialize_ex(payload, payload_len, return_value);
+
+ if (stream) {
+ pefree(payload, 0);
+ }
+}
+/* }}} */
+
+#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
+ */