diff options
Diffstat (limited to 'ext/wddx')
-rw-r--r-- | ext/wddx/CREDITS | 2 | ||||
-rw-r--r-- | ext/wddx/config.m4 | 60 | ||||
-rw-r--r-- | ext/wddx/config.w32 | 13 | ||||
-rw-r--r-- | ext/wddx/package.xml | 43 | ||||
-rw-r--r-- | ext/wddx/php_wddx.h | 44 | ||||
-rw-r--r-- | ext/wddx/php_wddx_api.h | 67 | ||||
-rw-r--r-- | ext/wddx/tests/001-64bit.phpt | 62 | ||||
-rw-r--r-- | ext/wddx/tests/001.phpt | 62 | ||||
-rw-r--r-- | ext/wddx/tests/002.phpt | 21 | ||||
-rw-r--r-- | ext/wddx/tests/003.phpt | 26 | ||||
-rw-r--r-- | ext/wddx/tests/004.phpt | 63 | ||||
-rw-r--r-- | ext/wddx/tests/005.phpt | 74 | ||||
-rw-r--r-- | ext/wddx/tests/bug27287.phpt | 20 | ||||
-rw-r--r-- | ext/wddx/tests/bug34306.phpt | 14 | ||||
-rw-r--r-- | ext/wddx/tests/bug35410.phpt | 76 | ||||
-rw-r--r-- | ext/wddx/tests/bug35410_64bit.phpt | 76 | ||||
-rw-r--r-- | ext/wddx/tests/bug37569.phpt | 784 | ||||
-rw-r--r-- | ext/wddx/tests/bug37587.phpt | 34 | ||||
-rw-r--r-- | ext/wddx/tests/bug41283.phpt | 27 | ||||
-rw-r--r-- | ext/wddx/tests/bug41527.phpt | 22 | ||||
-rw-r--r-- | ext/wddx/tests/bug45901.phpt | 18 | ||||
-rw-r--r-- | ext/wddx/tests/bug48562.phpt | 34 | ||||
-rw-r--r-- | ext/wddx/tests/bug52468.phpt | 26 | ||||
-rw-r--r-- | ext/wddx/tests/wddx.xml | 60 | ||||
-rw-r--r-- | ext/wddx/wddx.c | 1367 |
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 + */ |