From 79f14997b447f5917f16138d00d9877f1eeabae0 Mon Sep 17 00:00:00 2001 From: SVN Migration Date: Wed, 26 Apr 2006 11:08:11 +0000 Subject: This commit was manufactured by cvs2svn to create tag 'php_5_1_2'. --- Zend/tests/bug36006.phpt | 30 + Zend/tests/bug36037.phpt | 14 + Zend/tests/bug36071.phpt | 13 + Zend/tests/bug36268.phpt | 14 + Zend/tests/bug36303.phpt | 12 + Zend/tests/bug36513.phpt | 22 + Zend/tests/bug36568.phpt | 15 + Zend/tests/bug37046.phpt | 23 + Zend/tests/bug37138.phpt | 21 + Zend/tests/zend_strtod.phpt | 19 + ext/com_dotnet/tests/bug34272.phpt | 22 + ext/date/tests/bug36224.phpt | 13 + ext/date/tests/bug36510.phpt | 14 + ext/date/tests/bug36599.phpt | 12 + ext/date/tests/bug36988.phpt | 12 + ext/date/tests/bug37017.phpt | 16 + ext/dba/tests/bug36436.phpt | 34 + ext/dom/tests/bug36756.phpt | 35 + ext/dom/tests/dom007.phpt | 99 +++ ext/gd/tests/bug36697.phpt | 31 + ext/mysqli/tests/bug36420.phpt | 25 + ext/mysqli/tests/bug36745.phpt | 23 + ext/mysqli/tests/bug36802.phpt | 42 + ext/oci8/tests/bind_long.phpt | 38 + ext/oci8/tests/bind_long_raw.phpt | 38 + ext/oci8/tests/bind_raw.phpt | 39 + ext/oci8/tests/bug36010.phpt | 26 + ext/oci8/tests/bug36096.phpt | 28 + ext/oci8/tests/lob_019.phpt | Bin 0 -> 1548 bytes ext/oci8/tests/lob_020.phpt | Bin 0 -> 1597 bytes ext/oci8/tests/test.gif | Bin 0 -> 2523 bytes ext/pcre/pcrelib/pcre_printint.src | 466 ++++++++++ ext/pcre/pcrelib/pcre_ucp_searchfuncs.c | 175 ++++ ext/pcre/pcrelib/pcrecpparg.h | 171 ++++ ext/pdo/tests/bug_35671.phpt | 45 + ext/pdo_pgsql/tests/bug36727.phpt | 23 + ext/pgsql/tests/80_bug36625.phpt | 49 ++ ext/reflection/tests/007.phpt | 162 ++++ ext/reflection/tests/bug29986.phpt | 41 + ext/reflection/tests/bug36308.phpt | 22 + ext/reflection/tests/bug36337.phpt | 30 + ext/reflection/tests/bug36434.phpt | 33 + ext/reflection/tests/parameters_002.phpt | 209 +++++ ext/session/tests/bug36459.phpt | 41 + ext/simplexml/tests/009b.phpt | 35 + ext/simplexml/tests/026.phpt | 40 + ext/simplexml/tests/027.phpt | 74 ++ ext/simplexml/tests/028.phpt | 42 + ext/simplexml/tests/029.phpt | 40 + ext/simplexml/tests/030.phpt | 44 + ext/simplexml/tests/031.phpt | 57 ++ ext/simplexml/tests/032.phpt | 45 + ext/simplexml/tests/033.phpt | 137 +++ ext/simplexml/tests/bug36611.phpt | 28 + ext/soap/tests/bugs/bug36226.phpt | 139 +++ ext/soap/tests/bugs/bug36575.phpt | 52 ++ ext/soap/tests/bugs/bug36575.wsdl | 87 ++ ext/soap/tests/bugs/bug36614.phpt | 13 + ext/soap/tests/bugs/bug36614.wsdl | 204 +++++ ext/soap/tests/bugs/bug36629.phpt | 53 ++ ext/soap/tests/classmap003.phpt | 54 ++ ext/soap/tests/classmap003.wsdl | 51 ++ ext/soap/tests/server023.phpt | 37 + ext/soap/tests/server024.phpt | 49 ++ ext/soap/tests/server025.phpt | 46 + ext/soap/tests/server025.wsdl | 55 ++ ext/spl/tests/array_019.phpt | 32 + ext/spl/tests/array_020.phpt | 66 ++ ext/spl/tests/array_021.phpt | 31 + ext/spl/tests/array_022.phpt | 94 +++ ext/spl/tests/bug36258.phpt | 21 + ext/spl/tests/bug36287.phpt | 40 + ext/spl/tests/bug36825.phpt | 33 + ext/spl/tests/bug36941.phpt | 46 + ext/spl/tests/iterator_030.phpt | 46 + ext/spl/tests/iterator_031.phpt | 118 +++ ext/spl/tests/iterator_032.phpt | 52 ++ ext/spl/tests/iterator_033.phpt | 46 + ext/spl/tests/iterator_034.phpt | 190 +++++ ext/spl/tests/iterator_035.phpt | 17 + ext/spl/tests/spl_autoload_008.phpt | 131 +++ ext/spl/tests/sxe_005.phpt | 46 + ext/standard/tests/file/bug37158.phpt | 39 + ext/standard/tests/filters/read.phpt | 72 ++ ext/standard/tests/general_functions/bug36011.phpt | 46 + ext/standard/tests/strings/bug33605.phpt | 11 + ext/standard/tests/strings/bug36148.phpt | 29 + ext/standard/tests/strings/bug36306.phpt | 15 + ext/standard/tests/strings/bug36944.phpt | 26 + ext/standard/tests/strings/substr_compare.phpt | 39 + ext/xmlreader/tests/011.phpt | 34 + ext/xmlreader/tests/012.dtd | 2 + ext/xmlreader/tests/012.phpt | 69 ++ ext/xmlreader/tests/012.xml | 3 + ext/xmlreader/tests/bug36743.phpt | 25 + ext/xmlrpc/tests/bug37057.phpt | 62 ++ sapi/cgi/fastcgi.c | 938 +++++++++++++++++++++ sapi/cgi/fastcgi.h | 183 ++++ 98 files changed, 6181 insertions(+) create mode 100755 Zend/tests/bug36006.phpt create mode 100755 Zend/tests/bug36037.phpt create mode 100755 Zend/tests/bug36071.phpt create mode 100755 Zend/tests/bug36268.phpt create mode 100755 Zend/tests/bug36303.phpt create mode 100755 Zend/tests/bug36513.phpt create mode 100755 Zend/tests/bug36568.phpt create mode 100755 Zend/tests/bug37046.phpt create mode 100755 Zend/tests/bug37138.phpt create mode 100644 Zend/tests/zend_strtod.phpt create mode 100644 ext/com_dotnet/tests/bug34272.phpt create mode 100644 ext/date/tests/bug36224.phpt create mode 100644 ext/date/tests/bug36510.phpt create mode 100644 ext/date/tests/bug36599.phpt create mode 100644 ext/date/tests/bug36988.phpt create mode 100644 ext/date/tests/bug37017.phpt create mode 100755 ext/dba/tests/bug36436.phpt create mode 100644 ext/dom/tests/bug36756.phpt create mode 100644 ext/dom/tests/dom007.phpt create mode 100644 ext/gd/tests/bug36697.phpt create mode 100644 ext/mysqli/tests/bug36420.phpt create mode 100644 ext/mysqli/tests/bug36745.phpt create mode 100644 ext/mysqli/tests/bug36802.phpt create mode 100644 ext/oci8/tests/bind_long.phpt create mode 100644 ext/oci8/tests/bind_long_raw.phpt create mode 100644 ext/oci8/tests/bind_raw.phpt create mode 100644 ext/oci8/tests/bug36010.phpt create mode 100644 ext/oci8/tests/bug36096.phpt create mode 100644 ext/oci8/tests/lob_019.phpt create mode 100644 ext/oci8/tests/lob_020.phpt create mode 100644 ext/oci8/tests/test.gif create mode 100644 ext/pcre/pcrelib/pcre_printint.src create mode 100644 ext/pcre/pcrelib/pcre_ucp_searchfuncs.c create mode 100644 ext/pcre/pcrelib/pcrecpparg.h create mode 100644 ext/pdo/tests/bug_35671.phpt create mode 100644 ext/pdo_pgsql/tests/bug36727.phpt create mode 100755 ext/pgsql/tests/80_bug36625.phpt create mode 100755 ext/reflection/tests/007.phpt create mode 100644 ext/reflection/tests/bug29986.phpt create mode 100755 ext/reflection/tests/bug36308.phpt create mode 100644 ext/reflection/tests/bug36337.phpt create mode 100644 ext/reflection/tests/bug36434.phpt create mode 100755 ext/reflection/tests/parameters_002.phpt create mode 100644 ext/session/tests/bug36459.phpt create mode 100755 ext/simplexml/tests/009b.phpt create mode 100755 ext/simplexml/tests/026.phpt create mode 100755 ext/simplexml/tests/027.phpt create mode 100755 ext/simplexml/tests/028.phpt create mode 100755 ext/simplexml/tests/029.phpt create mode 100644 ext/simplexml/tests/030.phpt create mode 100644 ext/simplexml/tests/031.phpt create mode 100755 ext/simplexml/tests/032.phpt create mode 100755 ext/simplexml/tests/033.phpt create mode 100644 ext/simplexml/tests/bug36611.phpt create mode 100755 ext/soap/tests/bugs/bug36226.phpt create mode 100755 ext/soap/tests/bugs/bug36575.phpt create mode 100755 ext/soap/tests/bugs/bug36575.wsdl create mode 100755 ext/soap/tests/bugs/bug36614.phpt create mode 100755 ext/soap/tests/bugs/bug36614.wsdl create mode 100755 ext/soap/tests/bugs/bug36629.phpt create mode 100755 ext/soap/tests/classmap003.phpt create mode 100755 ext/soap/tests/classmap003.wsdl create mode 100755 ext/soap/tests/server023.phpt create mode 100755 ext/soap/tests/server024.phpt create mode 100755 ext/soap/tests/server025.phpt create mode 100755 ext/soap/tests/server025.wsdl create mode 100755 ext/spl/tests/array_019.phpt create mode 100755 ext/spl/tests/array_020.phpt create mode 100755 ext/spl/tests/array_021.phpt create mode 100755 ext/spl/tests/array_022.phpt create mode 100644 ext/spl/tests/bug36258.phpt create mode 100755 ext/spl/tests/bug36287.phpt create mode 100644 ext/spl/tests/bug36825.phpt create mode 100755 ext/spl/tests/bug36941.phpt create mode 100755 ext/spl/tests/iterator_030.phpt create mode 100755 ext/spl/tests/iterator_031.phpt create mode 100755 ext/spl/tests/iterator_032.phpt create mode 100755 ext/spl/tests/iterator_033.phpt create mode 100755 ext/spl/tests/iterator_034.phpt create mode 100644 ext/spl/tests/iterator_035.phpt create mode 100755 ext/spl/tests/spl_autoload_008.phpt create mode 100755 ext/spl/tests/sxe_005.phpt create mode 100644 ext/standard/tests/file/bug37158.phpt create mode 100644 ext/standard/tests/filters/read.phpt create mode 100755 ext/standard/tests/general_functions/bug36011.phpt create mode 100644 ext/standard/tests/strings/bug33605.phpt create mode 100644 ext/standard/tests/strings/bug36148.phpt create mode 100644 ext/standard/tests/strings/bug36306.phpt create mode 100644 ext/standard/tests/strings/bug36944.phpt create mode 100644 ext/standard/tests/strings/substr_compare.phpt create mode 100644 ext/xmlreader/tests/011.phpt create mode 100755 ext/xmlreader/tests/012.dtd create mode 100755 ext/xmlreader/tests/012.phpt create mode 100755 ext/xmlreader/tests/012.xml create mode 100644 ext/xmlreader/tests/bug36743.phpt create mode 100644 ext/xmlrpc/tests/bug37057.phpt create mode 100644 sapi/cgi/fastcgi.c create mode 100644 sapi/cgi/fastcgi.h diff --git a/Zend/tests/bug36006.phpt b/Zend/tests/bug36006.phpt new file mode 100755 index 0000000000..79f9897d13 --- /dev/null +++ b/Zend/tests/bug36006.phpt @@ -0,0 +1,30 @@ +--TEST-- +Bug #36006 (Problem with $this in __destruct()) +--FILE-- +dad = null; /* no segfault if this is commented out */ + } +} + +class Dad extends Person { + public $son; + public function __construct() { + $this->son = new Person; + $this->son->dad = $this; /* no segfault if this is commented out */ + } + public function __destruct() { + $this->son = null; + parent::__destruct(); /* segfault here */ + } +} + +$o = new Dad; +unset($o); +echo "ok\n"; +?> +--EXPECT-- +ok diff --git a/Zend/tests/bug36037.phpt b/Zend/tests/bug36037.phpt new file mode 100755 index 0000000000..3ccebf652d --- /dev/null +++ b/Zend/tests/bug36037.phpt @@ -0,0 +1,14 @@ +--TEST-- +Bug #36037 (heredoc adds extra line number) +--FILE-- + +--EXPECT-- +2 +7 diff --git a/Zend/tests/bug36071.phpt b/Zend/tests/bug36071.phpt new file mode 100755 index 0000000000..3b8e05dfab --- /dev/null +++ b/Zend/tests/bug36071.phpt @@ -0,0 +1,13 @@ +--TEST-- +Bug #36071 (Engine Crash related with 'clone') +--INI-- +error_reporting=4095 +--FILE-- +b = 0; +echo "ok\n"; +?> +--EXPECTF-- +Warning: __clone method called on non-object in %sbug36071.php on line 2 +ok \ No newline at end of file diff --git a/Zend/tests/bug36268.phpt b/Zend/tests/bug36268.phpt new file mode 100755 index 0000000000..5276d50d48 --- /dev/null +++ b/Zend/tests/bug36268.phpt @@ -0,0 +1,14 @@ +--TEST-- +Bug #36268 (Object destructors called even after fatal errors) +--FILE-- + +--EXPECTF-- +Fatal error: Call to undefined function bar() in %sbug36268.php on line 8 diff --git a/Zend/tests/bug36303.phpt b/Zend/tests/bug36303.phpt new file mode 100755 index 0000000000..612022ad56 --- /dev/null +++ b/Zend/tests/bug36303.phpt @@ -0,0 +1,12 @@ +--TEST-- +Bug #36303 (foreach on error_zval produces segfault) +--FILE-- +a->b as &$v) { +} +echo "ok\n"; +?> +--EXPECTF-- +Warning: Invalid argument supplied for foreach() in %sbug36303.php on line 3 +ok diff --git a/Zend/tests/bug36513.phpt b/Zend/tests/bug36513.phpt new file mode 100755 index 0000000000..f46da4efc5 --- /dev/null +++ b/Zend/tests/bug36513.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #36513 (comment will be outputed in last line) +--FILE-- +5'); +echo "\n"; + +//test('5'); +?> +--EXPECT-- +135 +'5' diff --git a/Zend/tests/bug36568.phpt b/Zend/tests/bug36568.phpt new file mode 100755 index 0000000000..d621491a4c --- /dev/null +++ b/Zend/tests/bug36568.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #36568 (memory_limit has no effect) +--SKIPIF-- + +--INI-- +memory_limit=16M +--FILE-- + +--EXPECT-- +32M diff --git a/Zend/tests/bug37046.phpt b/Zend/tests/bug37046.phpt new file mode 100755 index 0000000000..09b8f0cb5d --- /dev/null +++ b/Zend/tests/bug37046.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #37046 (foreach breaks static scope) +--FILE-- + $function) { + echo "op1 $k\n"; + if ($k == 0) { + foreach (s() as $k => $function) { + echo "op2 $k\n"; + } + } +} +?> +--EXPECT-- +op1 0 +op2 0 +op2 1 +op1 1 diff --git a/Zend/tests/bug37138.phpt b/Zend/tests/bug37138.phpt new file mode 100755 index 0000000000..f8503f8da9 --- /dev/null +++ b/Zend/tests/bug37138.phpt @@ -0,0 +1,21 @@ +--TEST-- +Bug #37138 (__autoload tries to load callback'ed self and parent) +--FILE-- + +--EXPECT-- +EHLO +EHLO +EHLO + diff --git a/Zend/tests/zend_strtod.phpt b/Zend/tests/zend_strtod.phpt new file mode 100644 index 0000000000..1b11be0388 --- /dev/null +++ b/Zend/tests/zend_strtod.phpt @@ -0,0 +1,19 @@ +--TEST-- +zend_strtod() leaks on big doubles +--INI-- +precision=14 +--FILE-- + +--EXPECTF-- +float(-100) +float(808792757210) +float(-4.5646456464565E+27) +float(-11276204760067000) +Done diff --git a/ext/com_dotnet/tests/bug34272.phpt b/ext/com_dotnet/tests/bug34272.phpt new file mode 100644 index 0000000000..3a65e2ce28 --- /dev/null +++ b/ext/com_dotnet/tests/bug34272.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #34272 (empty array onto COM object blows up) +--SKIPIF-- + +--FILE-- +add('foo', array()); + print sizeof($dict['foo'])."\n"; + $dict->add('bar', array(23)); + print sizeof($dict['bar'])." \n"; +} catch (Exception $e) { + print $e; +} +?> +--EXPECT-- +0 +1 diff --git a/ext/date/tests/bug36224.phpt b/ext/date/tests/bug36224.phpt new file mode 100644 index 0000000000..1690f4e7b2 --- /dev/null +++ b/ext/date/tests/bug36224.phpt @@ -0,0 +1,13 @@ +--TEST-- +Bug #36224 (date(DATE_ATOM) gives wrong resulsts) +--FILE-- + +--EXPECT-- +2006-01-31T20:23:56+01:00 +2006-01-31T19:23:56+01:00 diff --git a/ext/date/tests/bug36510.phpt b/ext/date/tests/bug36510.phpt new file mode 100644 index 0000000000..ea8bb028b2 --- /dev/null +++ b/ext/date/tests/bug36510.phpt @@ -0,0 +1,14 @@ +--TEST-- +Bug #36510 (strtotime() fails to parse date strings with tabs) +--FILE-- + +--EXPECT-- +int(1140966188) +int(1140966188) diff --git a/ext/date/tests/bug36599.phpt b/ext/date/tests/bug36599.phpt new file mode 100644 index 0000000000..b34a7c288f --- /dev/null +++ b/ext/date/tests/bug36599.phpt @@ -0,0 +1,12 @@ +--TEST-- +Bug #36599 (DATE_W3C format constant incorrect). +--FILE-- + +--EXPECT-- +2006-03-03T08:47:55+00:00 +2006-03-03T08:47:55+00:00 diff --git a/ext/date/tests/bug36988.phpt b/ext/date/tests/bug36988.phpt new file mode 100644 index 0000000000..d35e58939a --- /dev/null +++ b/ext/date/tests/bug36988.phpt @@ -0,0 +1,12 @@ +--TEST-- +Bug #36988 (mktime freezes on long numbers) +--INI-- +date.timezone=GMT +--FILE-- + +--EXPECT-- +smaller than one second diff --git a/ext/date/tests/bug37017.phpt b/ext/date/tests/bug37017.phpt new file mode 100644 index 0000000000..61dc8ba383 --- /dev/null +++ b/ext/date/tests/bug37017.phpt @@ -0,0 +1,16 @@ +--TEST-- +Bug #37017 (strtotime fails before 13:00:00 with some time zones identifiers). +--INI-- +date.timezone=GMT +--FILE-- + +--EXPECT-- +1147453201 +1147453200 +1147453199 +1147438799 diff --git a/ext/dba/tests/bug36436.phpt b/ext/dba/tests/bug36436.phpt new file mode 100755 index 0000000000..e85cf85282 --- /dev/null +++ b/ext/dba/tests/bug36436.phpt @@ -0,0 +1,34 @@ +--TEST-- +Bug #36436 DBA problem with Berkeley DB4 +--SKIPIF-- + +--FILE-- + +===DONE=== +--EXPECTF-- +resource(%d) of type (dba persistent) +string(3) "XYZ" +string(1) "X" +string(1) "Y" +===DONE=== diff --git a/ext/dom/tests/bug36756.phpt b/ext/dom/tests/bug36756.phpt new file mode 100644 index 0000000000..e24f9f0804 --- /dev/null +++ b/ext/dom/tests/bug36756.phpt @@ -0,0 +1,35 @@ +--TEST-- +Bug #36756: (DOMDocument::removeChild corrupts node) +--SKIPIF-- + +--FILE-- +loadXML(''); +$xpath = new DOMXpath($dom); +$node = $xpath->query('/root')->item(0); +echo $node->nodeName . "\n"; +$dom->removeChild($GLOBALS['dom']->firstChild); +echo "nodeType: " . $node->nodeType . "\n"; + +/* Node gets destroyed during removeChild */ +$dom->loadXML(''); +$xpath = new DOMXpath($dom); +$node = $xpath->query('//child')->item(0); +echo $node->nodeName . "\n"; +$GLOBALS['dom']->removeChild($GLOBALS['dom']->firstChild); + +echo "nodeType: " . $node->nodeType . "\n"; + +?> +--EXPECTF-- +root +nodeType: 1 +child + +Warning: Couldn't fetch DOMElement. Node no longer exists in %sbug36756.php on line %d + +Notice: Undefined property: DOMElement::$nodeType in %sbug36756.php on line %d +nodeType: diff --git a/ext/dom/tests/dom007.phpt b/ext/dom/tests/dom007.phpt new file mode 100644 index 0000000000..649d630336 --- /dev/null +++ b/ext/dom/tests/dom007.phpt @@ -0,0 +1,99 @@ +--TEST-- +Test 7: DTD tests +--SKIPIF-- + +--FILE-- + + + + + + + + + + + + +]> + + + Basic Languages + Introduction to Languages + + + French I + Introduction to French + + + + +EOXML; + +$dom = new DOMDocument(); +$dom->loadXML($xml); + +$dtd = $dom->doctype; + +/* Notation Tests */ +$nots = $dtd->notations; + +$length = $nots->length; +echo "Length: ".$length."\n"; + +foreach ($nots AS $key=>$node) { + echo "Key $key: ".$node->nodeName." (".$node->systemId.") (".$node->publicId.")\n"; +} +print "\n"; +for($x=0; $x < $length; $x++) { + echo "Index $x: ".$nots->item($x)->nodeName." (".$nots->item($x)->systemId.") (".$nots->item($x)->publicId.")\n"; +} + +echo "\n"; +$node = $nots->getNamedItem('xxx'); +var_dump($node); + +echo "\n"; +/* Entity Decl Tests */ +$ents = $dtd->entities; +$length = $ents->length; +echo "Length: ".$length."\n"; +foreach ($ents AS $key=>$node) { + echo "Key: $key Name: ".$node->nodeName."\n"; +} +echo "\n"; +for($x=0; $x < $length; $x++) { + echo "Index $x: ".$ents->item($x)->nodeName."\n"; +} + +echo "\n"; +$node = $ents->item(3); +var_dump($node); +$node = $ents->getNamedItem('xxx'); +var_dump($node); + + +--EXPECT-- +Length: 1 +Key GIF: GIF (image/gif) (-) + +Index 0: GIF (image/gif) (-) + +NULL + +Length: 3 +Key: test Name: test +Key: rdf Name: rdf +Key: myimage Name: myimage + +Index 0: test +Index 1: rdf +Index 2: myimage + +NULL +NULL diff --git a/ext/gd/tests/bug36697.phpt b/ext/gd/tests/bug36697.phpt new file mode 100644 index 0000000000..b257f63e25 --- /dev/null +++ b/ext/gd/tests/bug36697.phpt @@ -0,0 +1,31 @@ +--TEST-- +Bug #36697 (TrueColor transparency with GIF palette output). +--SKIPIF-- + +--FILE-- + +--EXPECT-- +255 0 0 diff --git a/ext/mysqli/tests/bug36420.phpt b/ext/mysqli/tests/bug36420.phpt new file mode 100644 index 0000000000..d35485e7fd --- /dev/null +++ b/ext/mysqli/tests/bug36420.phpt @@ -0,0 +1,25 @@ +--TEST-- +bug #36420 (segfault when access result->num_rows after calling result->close()) +--SKIPIF-- + +--FILE-- +query('select 1'); + +$result->close(); +echo $result->num_rows; + +$mysqli->close(); +echo $result->num_rows; + +echo "Done\n"; +?> +--EXPECTF-- +Warning: main(): Couldn't fetch mysqli_result in %s on line %d + +Warning: main(): Couldn't fetch mysqli_result in %s on line %d +Done diff --git a/ext/mysqli/tests/bug36745.phpt b/ext/mysqli/tests/bug36745.phpt new file mode 100644 index 0000000000..7bbfe8180c --- /dev/null +++ b/ext/mysqli/tests/bug36745.phpt @@ -0,0 +1,23 @@ +--TEST-- +bug #36745 : LOAD DATA LOCAL INFILE doesn't return correct error message +--SKIPIF-- + +--FILE-- +query("DROP TABLE IF EXISTS litest"); + $mysql->query("CREATE TABLE litest (a VARCHAR(20))"); + + $mysql->query("LOAD DATA LOCAL INFILE 'filenotfound' INTO TABLE litest"); + var_dump($mysql->error); + + $mysql->close(); + printf("Done"); +?> +--EXPECT-- +string(31) "Can't find file 'filenotfound'." +Done diff --git a/ext/mysqli/tests/bug36802.phpt b/ext/mysqli/tests/bug36802.phpt new file mode 100644 index 0000000000..69ef56bba0 --- /dev/null +++ b/ext/mysqli/tests/bug36802.phpt @@ -0,0 +1,42 @@ +--TEST-- +bug #36802 : crashes with mysql_init +--SKIPIF-- + +--FILE-- +set_charset('utf8'); + $x[1] = @$mysql->query("SELECT 'foo' FROM DUAL"); + + /* following operations should work */ + $x[2] = ($mysql->client_version > 0); + $x[3] = $mysql->errno; + $mysql->close(); + + + + var_dump($x); +?> +--EXPECT-- +array(4) { + [0]=> + NULL + [1]=> + NULL + [2]=> + bool(true) + [3]=> + int(0) +} diff --git a/ext/oci8/tests/bind_long.phpt b/ext/oci8/tests/bind_long.phpt new file mode 100644 index 0000000000..58590f145a --- /dev/null +++ b/ext/oci8/tests/bind_long.phpt @@ -0,0 +1,38 @@ +--TEST-- +bind LONG field +--SKIPIF-- + +--FILE-- + +--EXPECT-- +string(32) "d04e7036e2f4221abc88fd14e960a45b" +int(2523) +Done diff --git a/ext/oci8/tests/bind_long_raw.phpt b/ext/oci8/tests/bind_long_raw.phpt new file mode 100644 index 0000000000..2a9962eace --- /dev/null +++ b/ext/oci8/tests/bind_long_raw.phpt @@ -0,0 +1,38 @@ +--TEST-- +bind LONG RAW field +--SKIPIF-- + +--FILE-- + +--EXPECT-- +string(32) "614fcbba1effb7caa27ef0ef25c27fcf" +int(2523) +Done diff --git a/ext/oci8/tests/bind_raw.phpt b/ext/oci8/tests/bind_raw.phpt new file mode 100644 index 0000000000..c9087e552b --- /dev/null +++ b/ext/oci8/tests/bind_raw.phpt @@ -0,0 +1,39 @@ +--TEST-- +bind RAW field +--SKIPIF-- + +--FILE-- + +--EXPECT-- +string(32) "88b274d7a257ac6f70435b83abd4e26e" +int(300) +Done diff --git a/ext/oci8/tests/bug36010.phpt b/ext/oci8/tests/bug36010.phpt new file mode 100644 index 0000000000..ef435496a8 --- /dev/null +++ b/ext/oci8/tests/bug36010.phpt @@ -0,0 +1,26 @@ +--TEST-- +bug #36010 (Crash when executing SQL statment with lob parameter twice) +--SKIPIF-- + +--FILE-- + +--EXPECT-- +Done diff --git a/ext/oci8/tests/bug36096.phpt b/ext/oci8/tests/bug36096.phpt new file mode 100644 index 0000000000..44b3a6ddca --- /dev/null +++ b/ext/oci8/tests/bug36096.phpt @@ -0,0 +1,28 @@ +--TEST-- +Bug #36096 (oci_result() returns garbage after oci_fetch() failed) +--SKIPIF-- + +--FILE-- +1"; +$stmt = oci_parse($c, $sql); + +if(oci_execute($stmt, OCI_COMMIT_ON_SUCCESS)){ + var_dump(oci_fetch($stmt)); + var_dump(oci_result($stmt, 1)); + var_dump(oci_field_name($stmt, 1)); + var_dump(oci_field_type($stmt, 1)); +} + +echo "Done\n"; + +?> +--EXPECT-- +bool(false) +bool(false) +string(5) "'ABC'" +string(4) "CHAR" +Done diff --git a/ext/oci8/tests/lob_019.phpt b/ext/oci8/tests/lob_019.phpt new file mode 100644 index 0000000000..fb9a3c8188 Binary files /dev/null and b/ext/oci8/tests/lob_019.phpt differ diff --git a/ext/oci8/tests/lob_020.phpt b/ext/oci8/tests/lob_020.phpt new file mode 100644 index 0000000000..edd0f02490 Binary files /dev/null and b/ext/oci8/tests/lob_020.phpt differ diff --git a/ext/oci8/tests/test.gif b/ext/oci8/tests/test.gif new file mode 100644 index 0000000000..f352c7308f Binary files /dev/null and b/ext/oci8/tests/test.gif differ diff --git a/ext/pcre/pcrelib/pcre_printint.src b/ext/pcre/pcrelib/pcre_printint.src new file mode 100644 index 0000000000..34f52d114d --- /dev/null +++ b/ext/pcre/pcrelib/pcre_printint.src @@ -0,0 +1,466 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2005 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains a PCRE private debugging function for printing out the +internal form of a compiled regular expression, along with some supporting +local functions. This source file is used in two places: + +(1) It is #included by pcre_compile.c when it is compiled in debugging mode +(DEBUG defined in pcre_internal.h). It is not included in production compiles. + +(2) It is always #included by pcretest.c, which can be asked to print out a +compiled regex for debugging purposes. */ + + +static const char *OP_names[] = { OP_NAME_LIST }; + + +/************************************************* +* Print single- or multi-byte character * +*************************************************/ + +static int +print_char(FILE *f, uschar *ptr, BOOL utf8) +{ +int c = *ptr; + +if (!utf8 || (c & 0xc0) != 0xc0) + { + if (isprint(c)) fprintf(f, "%c", c); else fprintf(f, "\\x%02x", c); + return 0; + } +else + { + int i; + int a = _pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */ + int s = 6*a; + c = (c & _pcre_utf8_table3[a]) << s; + for (i = 1; i <= a; i++) + { + /* This is a check for malformed UTF-8; it should only occur if the sanity + check has been turned off. Rather than swallow random bytes, just stop if + we hit a bad one. Print it with \X instead of \x as an indication. */ + + if ((ptr[i] & 0xc0) != 0x80) + { + fprintf(f, "\\X{%x}", c); + return i - 1; + } + + /* The byte is OK */ + + s -= 6; + c |= (ptr[i] & 0x3f) << s; + } + if (c < 128) fprintf(f, "\\x%02x", c); else fprintf(f, "\\x{%x}", c); + return a; + } +} + + + +/************************************************* +* Find Unicode property name * +*************************************************/ + +static const char * +get_ucpname(int ptype, int pvalue) +{ +#ifdef SUPPORT_UCP +int i; +for (i = _pcre_utt_size; i >= 0; i--) + { + if (ptype == _pcre_utt[i].type && pvalue == _pcre_utt[i].value) break; + } +return (i >= 0)? _pcre_utt[i].name : "??"; +#else +ptype = ptype; /* Avoid compiler warning */ +pvalue = pvalue; +return "??"; +#endif +} + + + +/************************************************* +* Print compiled regex * +*************************************************/ + +/* Make this function work for a regex with integers either byte order. +However, we assume that what we are passed is a compiled regex. */ + +static void +pcre_printint(pcre *external_re, FILE *f) +{ +real_pcre *re = (real_pcre *)external_re; +uschar *codestart, *code; +BOOL utf8; + +unsigned int options = re->options; +int offset = re->name_table_offset; +int count = re->name_count; +int size = re->name_entry_size; + +if (re->magic_number != MAGIC_NUMBER) + { + offset = ((offset << 8) & 0xff00) | ((offset >> 8) & 0xff); + count = ((count << 8) & 0xff00) | ((count >> 8) & 0xff); + size = ((size << 8) & 0xff00) | ((size >> 8) & 0xff); + options = ((options << 24) & 0xff000000) | + ((options << 8) & 0x00ff0000) | + ((options >> 8) & 0x0000ff00) | + ((options >> 24) & 0x000000ff); + } + +code = codestart = (uschar *)re + offset + count * size; +utf8 = (options & PCRE_UTF8) != 0; + +for(;;) + { + uschar *ccode; + int c; + int extra = 0; + + fprintf(f, "%3d ", (int)(code - codestart)); + + if (*code >= OP_BRA) + { + if (*code - OP_BRA > EXTRACT_BASIC_MAX) + fprintf(f, "%3d Bra extra\n", GET(code, 1)); + else + fprintf(f, "%3d Bra %d\n", GET(code, 1), *code - OP_BRA); + code += _pcre_OP_lengths[OP_BRA]; + continue; + } + + switch(*code) + { + case OP_END: + fprintf(f, " %s\n", OP_names[*code]); + fprintf(f, "------------------------------------------------------------------\n"); + return; + + case OP_OPT: + fprintf(f, " %.2x %s", code[1], OP_names[*code]); + break; + + case OP_CHAR: + { + fprintf(f, " "); + do + { + code++; + code += 1 + print_char(f, code, utf8); + } + while (*code == OP_CHAR); + fprintf(f, "\n"); + continue; + } + break; + + case OP_CHARNC: + { + fprintf(f, " NC "); + do + { + code++; + code += 1 + print_char(f, code, utf8); + } + while (*code == OP_CHARNC); + fprintf(f, "\n"); + continue; + } + break; + + case OP_KETRMAX: + case OP_KETRMIN: + case OP_ALT: + case OP_KET: + case OP_ASSERT: + case OP_ASSERT_NOT: + case OP_ASSERTBACK: + case OP_ASSERTBACK_NOT: + case OP_ONCE: + case OP_COND: + case OP_REVERSE: + fprintf(f, "%3d %s", GET(code, 1), OP_names[*code]); + break; + + case OP_BRANUMBER: + printf("%3d %s", GET2(code, 1), OP_names[*code]); + break; + + case OP_CREF: + if (GET2(code, 1) == CREF_RECURSE) + fprintf(f, " Cond recurse"); + else + fprintf(f, "%3d %s", GET2(code,1), OP_names[*code]); + break; + + case OP_STAR: + case OP_MINSTAR: + case OP_PLUS: + case OP_MINPLUS: + case OP_QUERY: + case OP_MINQUERY: + case OP_TYPESTAR: + case OP_TYPEMINSTAR: + case OP_TYPEPLUS: + case OP_TYPEMINPLUS: + case OP_TYPEQUERY: + case OP_TYPEMINQUERY: + fprintf(f, " "); + if (*code >= OP_TYPESTAR) + { + fprintf(f, "%s", OP_names[code[1]]); + if (code[1] == OP_PROP || code[1] == OP_NOTPROP) + { + fprintf(f, " %s ", get_ucpname(code[2], code[3])); + extra = 2; + } + } + else extra = print_char(f, code+1, utf8); + fprintf(f, "%s", OP_names[*code]); + break; + + case OP_EXACT: + case OP_UPTO: + case OP_MINUPTO: + fprintf(f, " "); + extra = print_char(f, code+3, utf8); + fprintf(f, "{"); + if (*code != OP_EXACT) fprintf(f, ","); + fprintf(f, "%d}", GET2(code,1)); + if (*code == OP_MINUPTO) fprintf(f, "?"); + break; + + case OP_TYPEEXACT: + case OP_TYPEUPTO: + case OP_TYPEMINUPTO: + fprintf(f, " %s", OP_names[code[3]]); + if (code[3] == OP_PROP || code[3] == OP_NOTPROP) + { + fprintf(f, " %s ", get_ucpname(code[4], code[5])); + extra = 2; + } + fprintf(f, "{"); + if (*code != OP_TYPEEXACT) fprintf(f, "0,"); + fprintf(f, "%d}", GET2(code,1)); + if (*code == OP_TYPEMINUPTO) fprintf(f, "?"); + break; + + case OP_NOT: + if (isprint(c = code[1])) fprintf(f, " [^%c]", c); + else fprintf(f, " [^\\x%02x]", c); + break; + + case OP_NOTSTAR: + case OP_NOTMINSTAR: + case OP_NOTPLUS: + case OP_NOTMINPLUS: + case OP_NOTQUERY: + case OP_NOTMINQUERY: + if (isprint(c = code[1])) fprintf(f, " [^%c]", c); + else fprintf(f, " [^\\x%02x]", c); + fprintf(f, "%s", OP_names[*code]); + break; + + case OP_NOTEXACT: + case OP_NOTUPTO: + case OP_NOTMINUPTO: + if (isprint(c = code[3])) fprintf(f, " [^%c]{", c); + else fprintf(f, " [^\\x%02x]{", c); + if (*code != OP_NOTEXACT) fprintf(f, "0,"); + fprintf(f, "%d}", GET2(code,1)); + if (*code == OP_NOTMINUPTO) fprintf(f, "?"); + break; + + case OP_RECURSE: + fprintf(f, "%3d %s", GET(code, 1), OP_names[*code]); + break; + + case OP_REF: + fprintf(f, " \\%d", GET2(code,1)); + ccode = code + _pcre_OP_lengths[*code]; + goto CLASS_REF_REPEAT; + + case OP_CALLOUT: + fprintf(f, " %s %d %d %d", OP_names[*code], code[1], GET(code,2), + GET(code, 2 + LINK_SIZE)); + break; + + case OP_PROP: + case OP_NOTPROP: + fprintf(f, " %s %s", OP_names[*code], get_ucpname(code[1], code[2])); + break; + + /* OP_XCLASS can only occur in UTF-8 mode. However, there's no harm in + having this code always here, and it makes it less messy without all those + #ifdefs. */ + + case OP_CLASS: + case OP_NCLASS: + case OP_XCLASS: + { + int i, min, max; + BOOL printmap; + + fprintf(f, " ["); + + if (*code == OP_XCLASS) + { + extra = GET(code, 1); + ccode = code + LINK_SIZE + 1; + printmap = (*ccode & XCL_MAP) != 0; + if ((*ccode++ & XCL_NOT) != 0) fprintf(f, "^"); + } + else + { + printmap = TRUE; + ccode = code + 1; + } + + /* Print a bit map */ + + if (printmap) + { + for (i = 0; i < 256; i++) + { + if ((ccode[i/8] & (1 << (i&7))) != 0) + { + int j; + for (j = i+1; j < 256; j++) + if ((ccode[j/8] & (1 << (j&7))) == 0) break; + if (i == '-' || i == ']') fprintf(f, "\\"); + if (isprint(i)) fprintf(f, "%c", i); else fprintf(f, "\\x%02x", i); + if (--j > i) + { + if (j != i + 1) fprintf(f, "-"); + if (j == '-' || j == ']') fprintf(f, "\\"); + if (isprint(j)) fprintf(f, "%c", j); else fprintf(f, "\\x%02x", j); + } + i = j; + } + } + ccode += 32; + } + + /* For an XCLASS there is always some additional data */ + + if (*code == OP_XCLASS) + { + int ch; + while ((ch = *ccode++) != XCL_END) + { + if (ch == XCL_PROP) + { + int ptype = *ccode++; + int pvalue = *ccode++; + fprintf(f, "\\p{%s}", get_ucpname(ptype, pvalue)); + } + else if (ch == XCL_NOTPROP) + { + int ptype = *ccode++; + int pvalue = *ccode++; + fprintf(f, "\\P{%s}", get_ucpname(ptype, pvalue)); + } + else + { + ccode += 1 + print_char(f, ccode, TRUE); + if (ch == XCL_RANGE) + { + fprintf(f, "-"); + ccode += 1 + print_char(f, ccode, TRUE); + } + } + } + } + + /* Indicate a non-UTF8 class which was created by negation */ + + fprintf(f, "]%s", (*code == OP_NCLASS)? " (neg)" : ""); + + /* Handle repeats after a class or a back reference */ + + CLASS_REF_REPEAT: + switch(*ccode) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRPLUS: + case OP_CRMINPLUS: + case OP_CRQUERY: + case OP_CRMINQUERY: + fprintf(f, "%s", OP_names[*ccode]); + extra += _pcre_OP_lengths[*ccode]; + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + min = GET2(ccode,1); + max = GET2(ccode,3); + if (max == 0) fprintf(f, "{%d,}", min); + else fprintf(f, "{%d,%d}", min, max); + if (*ccode == OP_CRMINRANGE) fprintf(f, "?"); + extra += _pcre_OP_lengths[*ccode]; + break; + + /* Do nothing if it's not a repeat; this code stops picky compilers + warning about the lack of a default code path. */ + + default: + break; + } + } + break; + + /* Anything else is just an item with no data*/ + + default: + fprintf(f, " %s", OP_names[*code]); + break; + } + + code += _pcre_OP_lengths[*code] + extra; + fprintf(f, "\n"); + } +} + +/* End of pcre_printint.src */ diff --git a/ext/pcre/pcrelib/pcre_ucp_searchfuncs.c b/ext/pcre/pcrelib/pcre_ucp_searchfuncs.c new file mode 100644 index 0000000000..ac964ca903 --- /dev/null +++ b/ext/pcre/pcrelib/pcre_ucp_searchfuncs.c @@ -0,0 +1,175 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2006 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains code for searching the table of Unicode character +properties. */ + +#include "pcre_internal.h" + +#include "ucp.h" /* Category definitions */ +#include "ucpinternal.h" /* Internal table details */ +#include "ucptable.c" /* The table itself */ + + +/* Table to translate from particular type value to the general value. */ + +static int ucp_gentype[] = { + ucp_C, ucp_C, ucp_C, ucp_C, ucp_C, /* Cc, Cf, Cn, Co, Cs */ + ucp_L, ucp_L, ucp_L, ucp_L, ucp_L, /* Ll, Lu, Lm, Lo, Lt */ + ucp_M, ucp_M, ucp_M, /* Mc, Me, Mn */ + ucp_N, ucp_N, ucp_N, /* Nd, Nl, No */ + ucp_P, ucp_P, ucp_P, ucp_P, ucp_P, /* Pc, Pd, Pe, Pf, Pi */ + ucp_P, ucp_P, /* Ps, Po */ + ucp_S, ucp_S, ucp_S, ucp_S, /* Sc, Sk, Sm, So */ + ucp_Z, ucp_Z, ucp_Z /* Zl, Zp, Zs */ +}; + + + +/************************************************* +* Search table and return type * +*************************************************/ + +/* Three values are returned: the category is ucp_C, ucp_L, etc. The detailed +character type is ucp_Lu, ucp_Nd, etc. The script is ucp_Latin, etc. + +Arguments: + c the character value + type_ptr the detailed character type is returned here + script_ptr the script is returned here + +Returns: the character type category +*/ + +int +_pcre_ucp_findprop(const int c, int *type_ptr, int *script_ptr) +{ +int bot = 0; +int top = sizeof(ucp_table)/sizeof(cnode); +int mid; + +/* The table is searched using a binary chop. You might think that using +intermediate variables to hold some of the common expressions would speed +things up, but tests with gcc 3.4.4 on Linux showed that, on the contrary, it +makes things a lot slower. */ + +for (;;) + { + if (top <= bot) + { + *type_ptr = ucp_Cn; + *script_ptr = ucp_Common; + return ucp_C; + } + mid = (bot + top) >> 1; + if (c == (ucp_table[mid].f0 & f0_charmask)) break; + if (c < (ucp_table[mid].f0 & f0_charmask)) top = mid; + else + { + if ((ucp_table[mid].f0 & f0_rangeflag) != 0 && + c <= (ucp_table[mid].f0 & f0_charmask) + + (ucp_table[mid].f1 & f1_rangemask)) break; + bot = mid + 1; + } + } + +/* Found an entry in the table. Set the script and detailed type values, and +return the general type. */ + +*script_ptr = (ucp_table[mid].f0 & f0_scriptmask) >> f0_scriptshift; +*type_ptr = (ucp_table[mid].f1 & f1_typemask) >> f1_typeshift; + +return ucp_gentype[*type_ptr]; +} + + + +/************************************************* +* Search table and return other case * +*************************************************/ + +/* If the given character is a letter, and there is another case for the +letter, return the other case. Otherwise, return -1. + +Arguments: + c the character value + +Returns: the other case or -1 if none +*/ + +int +_pcre_ucp_othercase(const int c) +{ +int bot = 0; +int top = sizeof(ucp_table)/sizeof(cnode); +int mid, offset; + +/* The table is searched using a binary chop. You might think that using +intermediate variables to hold some of the common expressions would speed +things up, but tests with gcc 3.4.4 on Linux showed that, on the contrary, it +makes things a lot slower. */ + +for (;;) + { + if (top <= bot) return -1; + mid = (bot + top) >> 1; + if (c == (ucp_table[mid].f0 & f0_charmask)) break; + if (c < (ucp_table[mid].f0 & f0_charmask)) top = mid; + else + { + if ((ucp_table[mid].f0 & f0_rangeflag) != 0 && + c <= (ucp_table[mid].f0 & f0_charmask) + + (ucp_table[mid].f1 & f1_rangemask)) break; + bot = mid + 1; + } + } + +/* Found an entry in the table. Return -1 for a range entry. Otherwise return +the other case if there is one, else -1. */ + +if ((ucp_table[mid].f0 & f0_rangeflag) != 0) return -1; + +offset = ucp_table[mid].f1 & f1_casemask; +if ((offset & f1_caseneg) != 0) offset |= f1_caseneg; +return (offset == 0)? -1 : c + offset; +} + + +/* End of pcre_ucp_searchfuncs.c */ diff --git a/ext/pcre/pcrelib/pcrecpparg.h b/ext/pcre/pcrelib/pcrecpparg.h new file mode 100644 index 0000000000..323dde58e5 --- /dev/null +++ b/ext/pcre/pcrelib/pcrecpparg.h @@ -0,0 +1,171 @@ +// Copyright (c) 2005, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: Sanjay Ghemawat + +#ifndef _PCRECPPARG_H +#define _PCRECPPARG_H + +#include // for NULL +#include + +namespace pcrecpp { + +class StringPiece; + +// Hex/Octal/Binary? + +// Special class for parsing into objects that define a ParseFrom() method +template +class _RE_MatchObject { + public: + static inline bool Parse(const char* str, int n, void* dest) { + T* object = reinterpret_cast(dest); + return object->ParseFrom(str, n); + } +}; + +class Arg { + public: + // Empty constructor so we can declare arrays of Arg + Arg(); + + // Constructor specially designed for NULL arguments + Arg(void*); + + typedef bool (*Parser)(const char* str, int n, void* dest); + +// Type-specific parsers +#define PCRE_MAKE_PARSER(type,name) \ + Arg(type* p) : arg_(p), parser_(name) { } \ + Arg(type* p, Parser parser) : arg_(p), parser_(parser) { } + + + PCRE_MAKE_PARSER(char, parse_char); + PCRE_MAKE_PARSER(unsigned char, parse_uchar); + PCRE_MAKE_PARSER(short, parse_short); + PCRE_MAKE_PARSER(unsigned short, parse_ushort); + PCRE_MAKE_PARSER(int, parse_int); + PCRE_MAKE_PARSER(unsigned int, parse_uint); + PCRE_MAKE_PARSER(long, parse_long); + PCRE_MAKE_PARSER(unsigned long, parse_ulong); +#if 1 + PCRE_MAKE_PARSER(long long, parse_longlong); +#endif +#if 1 + PCRE_MAKE_PARSER(unsigned long long, parse_ulonglong); +#endif + PCRE_MAKE_PARSER(float, parse_float); + PCRE_MAKE_PARSER(double, parse_double); + PCRE_MAKE_PARSER(std::string, parse_string); + PCRE_MAKE_PARSER(StringPiece, parse_stringpiece); + +#undef PCRE_MAKE_PARSER + + // Generic constructor + template Arg(T*, Parser parser); + // Generic constructor template + template Arg(T* p) + : arg_(p), parser_(_RE_MatchObject::Parse) { + } + + // Parse the data + bool Parse(const char* str, int n) const; + + private: + void* arg_; + Parser parser_; + + static bool parse_null (const char* str, int n, void* dest); + static bool parse_char (const char* str, int n, void* dest); + static bool parse_uchar (const char* str, int n, void* dest); + static bool parse_float (const char* str, int n, void* dest); + static bool parse_double (const char* str, int n, void* dest); + static bool parse_string (const char* str, int n, void* dest); + static bool parse_stringpiece (const char* str, int n, void* dest); + +#define PCRE_DECLARE_INTEGER_PARSER(name) \ + private: \ + static bool parse_ ## name(const char* str, int n, void* dest); \ + static bool parse_ ## name ## _radix( \ + const char* str, int n, void* dest, int radix); \ + public: \ + static bool parse_ ## name ## _hex(const char* str, int n, void* dest); \ + static bool parse_ ## name ## _octal(const char* str, int n, void* dest); \ + static bool parse_ ## name ## _cradix(const char* str, int n, void* dest) + + PCRE_DECLARE_INTEGER_PARSER(short); + PCRE_DECLARE_INTEGER_PARSER(ushort); + PCRE_DECLARE_INTEGER_PARSER(int); + PCRE_DECLARE_INTEGER_PARSER(uint); + PCRE_DECLARE_INTEGER_PARSER(long); + PCRE_DECLARE_INTEGER_PARSER(ulong); + PCRE_DECLARE_INTEGER_PARSER(longlong); + PCRE_DECLARE_INTEGER_PARSER(ulonglong); + +#undef PCRE_DECLARE_INTEGER_PARSER +}; + +inline Arg::Arg() : arg_(NULL), parser_(parse_null) { } +inline Arg::Arg(void* p) : arg_(p), parser_(parse_null) { } + +inline bool Arg::Parse(const char* str, int n) const { + return (*parser_)(str, n, arg_); +} + +// This part of the parser, appropriate only for ints, deals with bases +#define MAKE_INTEGER_PARSER(type, name) \ + inline Arg Hex(type* ptr) { \ + return Arg(ptr, Arg::parse_ ## name ## _hex); } \ + inline Arg Octal(type* ptr) { \ + return Arg(ptr, Arg::parse_ ## name ## _octal); } \ + inline Arg CRadix(type* ptr) { \ + return Arg(ptr, Arg::parse_ ## name ## _cradix); } + +MAKE_INTEGER_PARSER(short, short); +MAKE_INTEGER_PARSER(unsigned short, ushort); +MAKE_INTEGER_PARSER(int, int); +MAKE_INTEGER_PARSER(unsigned int, uint); +MAKE_INTEGER_PARSER(long, long); +MAKE_INTEGER_PARSER(unsigned long, ulong); +#if 1 +MAKE_INTEGER_PARSER(long long, longlong); +#endif +#if 1 +MAKE_INTEGER_PARSER(unsigned long long, ulonglong); +#endif + +#undef PCRE_IS_SET +#undef PCRE_SET_OR_CLEAR +#undef MAKE_INTEGER_PARSER + +} // namespace pcrecpp + + +#endif /* _PCRECPPARG_H */ diff --git a/ext/pdo/tests/bug_35671.phpt b/ext/pdo/tests/bug_35671.phpt new file mode 100644 index 0000000000..768773f90d --- /dev/null +++ b/ext/pdo/tests/bug_35671.phpt @@ -0,0 +1,45 @@ +--TEST-- +PDO Common: PHP Bug #35671: binding by name breakage +--SKIPIF-- + +--FILE-- +exec('CREATE TABLE test (field1 VARCHAR(32), field2 VARCHAR(32), field3 VARCHAR(32))'); +$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + +$insert = $db->prepare("insert into test (field1, field2, field3) values (:value1, :value2, :value3)"); + +$parm = array( + ":value1" => 15, + ":value2" => 20, + ":value3" => 25 +); + +$insert->execute($parm); +$insert = null; + +var_dump($db->query("SELECT * from test")->fetchAll(PDO::FETCH_ASSOC)); + +?> +--EXPECT-- +array(1) { + [0]=> + array(3) { + ["field1"]=> + string(2) "15" + ["field2"]=> + string(2) "20" + ["field3"]=> + string(2) "25" + } +} diff --git a/ext/pdo_pgsql/tests/bug36727.phpt b/ext/pdo_pgsql/tests/bug36727.phpt new file mode 100644 index 0000000000..c6f7c8a80f --- /dev/null +++ b/ext/pdo_pgsql/tests/bug36727.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #36727 (segfault in bindValue() when no parameters are defined) +--SKIPIF-- + +--FILE-- +prepare('SELECT * FROM child'); +var_dump($stmt->bindValue(':test', 1, PDO::PARAM_INT)); + +echo "Done\n"; +?> +--EXPECT-- +bool(false) +Done diff --git a/ext/pgsql/tests/80_bug36625.phpt b/ext/pgsql/tests/80_bug36625.phpt new file mode 100755 index 0000000000..a95cea7110 --- /dev/null +++ b/ext/pgsql/tests/80_bug36625.phpt @@ -0,0 +1,49 @@ +--TEST-- +Bug #36625 (pg_trace() does not work) +--SKIPIF-- + +--FILE-- + 0); +var_dump(file_exists($tracefile)); + +?> +===DONE=== +--CLEAN-- + +--EXPECTF-- +bool(false) +resource(%d) of type (pgsql result) +bool(true) +bool(true) +===DONE=== diff --git a/ext/reflection/tests/007.phpt b/ext/reflection/tests/007.phpt new file mode 100755 index 0000000000..83764e5515 --- /dev/null +++ b/ext/reflection/tests/007.phpt @@ -0,0 +1,162 @@ +--TEST-- +ReflectionClass::newInstance[Args] +--SKIPIF-- + +--FILE-- +$class\n"; + try + { + $ref = new ReflectionClass($class); + } + catch (ReflectionException $e) + { + var_dump($e->getMessage()); + return; // only here + } + + echo "====>newInstance()\n"; + try + { + var_dump($ref->newInstance()); + } + catch (ReflectionException $e) + { + var_dump($e->getMessage()); + } + + echo "====>newInstance(25)\n"; + try + { + var_dump($ref->newInstance(25)); + } + catch (ReflectionException $e) + { + var_dump($e->getMessage()); + } + + echo "====>newInstance(25, 42)\n"; + try + { + var_dump($ref->newInstance(25, 42)); + } + catch (ReflectionException $e) + { + var_dump($e->getMessage()); + } + + echo "\n"; +} + +function __autoload($class) +{ + echo __FUNCTION__ . "($class)\n"; +} + +test('Class_does_not_exist'); + +Class NoCtor +{ +} + +test('NoCtor'); + +Class WithCtor +{ + function __construct() + { + echo __METHOD__ . "()\n"; + var_dump(func_get_args()); + } +} + +test('WithCtor'); + +Class WithCtorWithArgs +{ + function __construct($arg) + { + echo __METHOD__ . "($arg)\n"; + var_dump(func_get_args()); + } +} + +test('WithCtorWithArgs'); + +?> +===DONE=== + +--EXPECTF-- + +====>Class_does_not_exist +__autoload(Class_does_not_exist) +string(41) "Class Class_does_not_exist does not exist" +====>NoCtor +====>newInstance() +object(NoCtor)#%d (0) { +} +====>newInstance(25) +string(86) "Class NoCtor does not have a constructor, so you cannot pass any constructor arguments" +====>newInstance(25, 42) +string(86) "Class NoCtor does not have a constructor, so you cannot pass any constructor arguments" + +====>WithCtor +====>newInstance() +WithCtor::__construct() +array(0) { +} +object(WithCtor)#%d (0) { +} +====>newInstance(25) +WithCtor::__construct() +array(1) { + [0]=> + int(25) +} +object(WithCtor)#%d (0) { +} +====>newInstance(25, 42) +WithCtor::__construct() +array(2) { + [0]=> + int(25) + [1]=> + int(42) +} +object(WithCtor)#%d (0) { +} + +====>WithCtorWithArgs +====>newInstance() + +Warning: Missing argument 1 for WithCtorWithArgs::__construct() in %s007.php on line %d + +Notice: Undefined variable: arg in %s007.php on line %d +WithCtorWithArgs::__construct() +array(0) { +} +object(WithCtorWithArgs)#%d (0) { +} +====>newInstance(25) +WithCtorWithArgs::__construct(25) +array(1) { + [0]=> + int(25) +} +object(WithCtorWithArgs)#%d (0) { +} +====>newInstance(25, 42) +WithCtorWithArgs::__construct(25) +array(2) { + [0]=> + int(25) + [1]=> + int(42) +} +object(WithCtorWithArgs)#%d (0) { +} + +===DONE=== diff --git a/ext/reflection/tests/bug29986.phpt b/ext/reflection/tests/bug29986.phpt new file mode 100644 index 0000000000..85bad6d6ec --- /dev/null +++ b/ext/reflection/tests/bug29986.phpt @@ -0,0 +1,41 @@ +--TEST-- +Reflection Bug #29986 (Class constants won't work with predefined constants when using ReflectionClass) +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Class [ class just_constants ] { + @@ %s + + - Constants [5] { + Constant [ boolean BOOLEAN_CONSTANT ] { } + Constant [ null NULL_CONSTANT ] { } + Constant [ string STRING_CONSTANT ] { } + Constant [ integer INTEGER_CONSTANT ] { } + Constant [ double FLOAT_CONSTANT ] { } + } + + - Static properties [0] { + } + + - Static methods [0] { + } + + - Properties [0] { + } + + - Methods [0] { + } +} diff --git a/ext/reflection/tests/bug36308.phpt b/ext/reflection/tests/bug36308.phpt new file mode 100755 index 0000000000..52717b474a --- /dev/null +++ b/ext/reflection/tests/bug36308.phpt @@ -0,0 +1,22 @@ +--TEST-- +Reflection Bug #36308 (ReflectionProperty::getDocComment() does not reflect extended class commentary) +--SKIPIF-- + +--FILE-- +getProperties(); +echo $props[0]->getDocComment(); +?> +--EXPECT-- +/** Extended commentary */ \ No newline at end of file diff --git a/ext/reflection/tests/bug36337.phpt b/ext/reflection/tests/bug36337.phpt new file mode 100644 index 0000000000..8ec928fc89 --- /dev/null +++ b/ext/reflection/tests/bug36337.phpt @@ -0,0 +1,30 @@ +--TEST-- +Reflection Bug #36337 (ReflectionProperty fails to return correct visibility) +--SKIPIF-- + +--FILE-- +isProtected()); + } + +} + +final class myEnum extends enum { + public $_values = array( + 0 => 'No value', + ); +} + +$x = new myEnum(); + +echo "Done\n"; +?> +--EXPECT-- +bool(false) +Done diff --git a/ext/reflection/tests/bug36434.phpt b/ext/reflection/tests/bug36434.phpt new file mode 100644 index 0000000000..e305c657a8 --- /dev/null +++ b/ext/reflection/tests/bug36434.phpt @@ -0,0 +1,33 @@ +--TEST-- +Reflection Bug #36434 (Properties from parent class fail to indetify their true origin) +--SKIPIF-- + +--FILE-- +ancester; + } +} +class foo extends ancester +{ +public $bar = "1"; + function foo() + { + return $this->bar; + } +} + +$r = new ReflectionClass('foo'); +foreach ($r->GetProperties() as $p) +{ + echo $p->getName(). " ". $p->getDeclaringClass()->getName()."\n"; +} + +?> +--EXPECT-- +bar foo +ancester ancester diff --git a/ext/reflection/tests/parameters_002.phpt b/ext/reflection/tests/parameters_002.phpt new file mode 100755 index 0000000000..6f911448c2 --- /dev/null +++ b/ext/reflection/tests/parameters_002.phpt @@ -0,0 +1,209 @@ +--TEST-- +ReflectionParameter::getClass(), getDeclaringClass(), getDeclaringFunction() +--SKIPIF-- + +--FILE-- +$f(); + echo $f . ': ' . ($c ? ($c instanceof ReflectionMethod ? $c->class . '::' : '') . $c->name : 'NULL') . "()\n"; +} + +function check_params_decl_class($r, $f) +{ + $c = $r->$f(); + echo $f . ': ' . ($c ? $c->name : 'NULL') . "\n"; +} + +function check_params_func($r, $f) +{ + echo $f . ': '; + $v = $r->$f(); + var_dump($v); +} + +function check_params($r) +{ + echo "#####" . ($r instanceof ReflectionMethod ? $r->class . '::' : '') . $r->name . "()#####\n"; + $i = 0; + foreach($r->getParameters() as $p) + { + echo "===" . $i . "===\n"; + $i++; + check_params_func($p, 'getName'); + check_params_func($p, 'isPassedByReference'); + try + { + check_params_decl_class($p, 'getClass'); + } + catch(ReflectionException $e) + { + echo $e->getMessage() . "\n"; + } + check_params_decl_class($p, 'getDeclaringClass'); +// check_params_decl_func($p, 'getDeclaringFunction'); + check_params_func($p, 'isArray'); + check_params_func($p, 'allowsNull'); + check_params_func($p, 'isOptional'); + check_params_func($p, 'isDefaultValueAvailable'); + if ($p->isOptional()) + { + check_params_func($p, 'getDefaultValue'); + } + } +} + +check_params(new ReflectionFunction('test')); + +check_params(new ReflectionMethod('test::test')); + +?> +===DONE=== + +--EXPECT-- +#####test()##### +===0=== +getName: string(3) "nix" +isPassedByReference: bool(false) +getClass: NULL +getDeclaringClass: NULL +isArray: bool(false) +allowsNull: bool(true) +isOptional: bool(false) +isDefaultValueAvailable: bool(false) +===1=== +getName: string(2) "ar" +isPassedByReference: bool(false) +getClass: NULL +getDeclaringClass: NULL +isArray: bool(true) +allowsNull: bool(false) +isOptional: bool(false) +isDefaultValueAvailable: bool(false) +===2=== +getName: string(3) "ref" +isPassedByReference: bool(true) +getClass: NULL +getDeclaringClass: NULL +isArray: bool(false) +allowsNull: bool(true) +isOptional: bool(false) +isDefaultValueAvailable: bool(false) +===3=== +getName: string(3) "std" +isPassedByReference: bool(false) +getClass: stdClass +getDeclaringClass: NULL +isArray: bool(false) +allowsNull: bool(false) +isOptional: bool(false) +isDefaultValueAvailable: bool(false) +===4=== +getName: string(2) "na" +isPassedByReference: bool(false) +Class NonExistingClass does not exist +getDeclaringClass: NULL +isArray: bool(false) +allowsNull: bool(false) +isOptional: bool(false) +isDefaultValueAvailable: bool(false) +===5=== +getName: string(3) "opt" +isPassedByReference: bool(true) +getClass: stdClass +getDeclaringClass: NULL +isArray: bool(false) +allowsNull: bool(true) +isOptional: bool(true) +isDefaultValueAvailable: bool(true) +getDefaultValue: NULL +===6=== +getName: string(3) "def" +isPassedByReference: bool(false) +getClass: NULL +getDeclaringClass: NULL +isArray: bool(false) +allowsNull: bool(true) +isOptional: bool(true) +isDefaultValueAvailable: bool(true) +getDefaultValue: string(6) "FooBar" +#####test::test()##### +===0=== +getName: string(3) "nix" +isPassedByReference: bool(false) +getClass: NULL +getDeclaringClass: test +isArray: bool(false) +allowsNull: bool(true) +isOptional: bool(false) +isDefaultValueAvailable: bool(false) +===1=== +getName: string(2) "ar" +isPassedByReference: bool(false) +getClass: NULL +getDeclaringClass: test +isArray: bool(true) +allowsNull: bool(false) +isOptional: bool(false) +isDefaultValueAvailable: bool(false) +===2=== +getName: string(3) "ref" +isPassedByReference: bool(true) +getClass: NULL +getDeclaringClass: test +isArray: bool(false) +allowsNull: bool(true) +isOptional: bool(false) +isDefaultValueAvailable: bool(false) +===3=== +getName: string(3) "std" +isPassedByReference: bool(false) +getClass: stdClass +getDeclaringClass: test +isArray: bool(false) +allowsNull: bool(false) +isOptional: bool(false) +isDefaultValueAvailable: bool(false) +===4=== +getName: string(2) "na" +isPassedByReference: bool(false) +Class NonExistingClass does not exist +getDeclaringClass: test +isArray: bool(false) +allowsNull: bool(false) +isOptional: bool(false) +isDefaultValueAvailable: bool(false) +===5=== +getName: string(3) "opt" +isPassedByReference: bool(false) +getClass: stdClass +getDeclaringClass: test +isArray: bool(false) +allowsNull: bool(true) +isOptional: bool(true) +isDefaultValueAvailable: bool(true) +getDefaultValue: NULL +===6=== +getName: string(3) "def" +isPassedByReference: bool(false) +getClass: NULL +getDeclaringClass: test +isArray: bool(false) +allowsNull: bool(true) +isOptional: bool(true) +isDefaultValueAvailable: bool(true) +getDefaultValue: string(6) "FooBar" +===DONE=== diff --git a/ext/session/tests/bug36459.phpt b/ext/session/tests/bug36459.phpt new file mode 100644 index 0000000000..30c94f81d9 --- /dev/null +++ b/ext/session/tests/bug36459.phpt @@ -0,0 +1,41 @@ +--TEST-- +bug #31454 (Incorrect adding PHPSESSID to links, which contains \r\n) +--SKIPIF-- + +--FILE-- + + + + Bug #36459 Incorrect adding PHPSESSID to links, which contains \r\n + + +

See source html code

+ incorrect link
+
+ correct link + + +--EXPECTF-- + + + Bug #36459 Incorrect adding PHPSESSID to links, which contains \r\n + + +

See source html code

+ incorrect link
+
+ correct link + + diff --git a/ext/simplexml/tests/009b.phpt b/ext/simplexml/tests/009b.phpt new file mode 100755 index 0000000000..dba300c72f --- /dev/null +++ b/ext/simplexml/tests/009b.phpt @@ -0,0 +1,35 @@ +--TEST-- +SimpleXML: foreach +--SKIPIF-- + +--FILE-- + + + + Plain text. + Bla bla 1. + Here we have some text data. + + Bla bla 2. + +EOF +); +var_dump($sxe->children()); +?> +===DONE=== + +--EXPECTF-- +object(SimpleXMLElement)#%d (3) { + ["@attributes"]=> + array(1) { + ["id"]=> + string(5) "elem1" + } + ["elem1"]=> + string(10) "Bla bla 1." + ["elem11"]=> + string(10) "Bla bla 2." +} +===DONE=== diff --git a/ext/simplexml/tests/026.phpt b/ext/simplexml/tests/026.phpt new file mode 100755 index 0000000000..d6de94be3d --- /dev/null +++ b/ext/simplexml/tests/026.phpt @@ -0,0 +1,40 @@ +--TEST-- +SimpleXML: getName() +--SKIPIF-- + +--FILE-- + + Jane + +EOF; + +function traverse_xml($xml, $pad = '') +{ + $name = $xml->getName(); + echo "$pad<$name"; + foreach($xml->attributes() as $attr => $value) + { + echo " $attr=\"$value\""; + } + echo ">" . trim($xml) . "\n"; + foreach($xml->children() as $node) + { + traverse_xml($node, $pad.' '); + } + echo $pad."\n"; +} + + +$people = simplexml_load_string($xml); +traverse_xml($people); + +?> +===DONE=== +--EXPECTF-- + + Jane + + +===DONE=== diff --git a/ext/simplexml/tests/027.phpt b/ext/simplexml/tests/027.phpt new file mode 100755 index 0000000000..f32786c7cc --- /dev/null +++ b/ext/simplexml/tests/027.phpt @@ -0,0 +1,74 @@ +--TEST-- +SimpleXML: Adding an elements +--SKIPIF-- + +--FILE-- + +EOF; + +function traverse_xml($xml, $pad = '') +{ + $name = $xml->getName(); + echo "$pad<$name"; + foreach($xml->attributes() as $attr => $value) + { + echo " $attr=\"$value\""; + } + echo ">" . trim($xml) . "\n"; + foreach($xml->children() as $node) + { + traverse_xml($node, $pad.' '); + } + echo $pad."\n"; +} + + +$people = simplexml_load_string($xml); +traverse_xml($people); +$people->person = 'Joe'; +$people->person['gender'] = 'male'; +traverse_xml($people); +$people->person = 'Jane'; +traverse_xml($people); +$people->person['gender'] = 'female'; +$people->person[1] = 'Joe'; +$people->person[1]['gender'] = 'male'; +traverse_xml($people); +$people->person[3] = 'Minni-me'; +$people->person[2]['gender'] = 'male'; +traverse_xml($people); +$people->person[3]['gender'] = 'error'; + +?> +===DONE=== +--EXPECTF-- + + + + Joe + + + + Jane + + + + Jane + + Joe + + + +Warning: main(): Cannot add element person number 3 when only 2 such elements exist in %s027.php on line %d + + Jane + + Joe + + Minni-me + + + +Fatal error: Objects used as arrays in post/pre increment/decrement must return values by reference in %s027.php on line %d diff --git a/ext/simplexml/tests/028.phpt b/ext/simplexml/tests/028.phpt new file mode 100755 index 0000000000..753056b9ad --- /dev/null +++ b/ext/simplexml/tests/028.phpt @@ -0,0 +1,42 @@ +--TEST-- +SimpleXML: Adding an elements without text +--SKIPIF-- + +--FILE-- + +EOF; + +function traverse_xml($xml, $pad = '') +{ + $name = $xml->getName(); + echo "$pad<$name"; + foreach($xml->attributes() as $attr => $value) + { + echo " $attr=\"$value\""; + } + echo ">" . trim($xml) . "\n"; + foreach($xml->children() as $node) + { + traverse_xml($node, $pad.' '); + } + echo $pad."\n"; +} + + +$people = simplexml_load_string($xml); +traverse_xml($people); +$people->person['name'] = 'John'; +traverse_xml($people); + +?> +===DONE=== +--EXPECTF-- + + + + + + +===DONE=== diff --git a/ext/simplexml/tests/029.phpt b/ext/simplexml/tests/029.phpt new file mode 100755 index 0000000000..86a4f308e3 --- /dev/null +++ b/ext/simplexml/tests/029.phpt @@ -0,0 +1,40 @@ +--TEST-- +SimpleXML: foreach and count +--SKIPIF-- + +--FILE-- + + + + + + + + + +EOF; + +$people = simplexml_load_string($xml); + +foreach($people as $person) +{ + var_dump((string)$person['name']); + var_dump(count($people)); + var_dump(count($person)); +} + +?> +===DONE=== +--EXPECTF-- +string(3) "Joe" +int(3) +int(0) +string(4) "John" +int(3) +int(1) +string(4) "Jane" +int(3) +int(0) +===DONE=== diff --git a/ext/simplexml/tests/030.phpt b/ext/simplexml/tests/030.phpt new file mode 100644 index 0000000000..774a5f1459 --- /dev/null +++ b/ext/simplexml/tests/030.phpt @@ -0,0 +1,44 @@ +--TEST-- +SimpleXML: isset and unset by offset +--SKIPIF-- + +--FILE-- + + test + test 2 + + +EOF; + +$sxe = simplexml_load_string($xml); + +echo $sxe->child1[0]."\n"; +echo $sxe->child1[1]."\n\n"; + +var_dump(isset($sxe->child1[1])); +unset($sxe->child1[1]); +var_dump(isset($sxe->child1[1])); +echo "\n"; + +$atts = $sxe->attributes("urn::test"); +var_dump(isset($atts[0])); +unset($atts[0]); +var_dump(isset($atts[0])); +var_dump(isset($atts[TRUE])); + +?> +===DONE=== +--EXPECT-- +test +test 2 + +bool(true) +bool(false) + +bool(true) +bool(false) +bool(false) +===DONE=== diff --git a/ext/simplexml/tests/031.phpt b/ext/simplexml/tests/031.phpt new file mode 100644 index 0000000000..cd2d266ba1 --- /dev/null +++ b/ext/simplexml/tests/031.phpt @@ -0,0 +1,57 @@ +--TEST-- +SimpleXML: addChild and addAttribute +--SKIPIF-- + +--FILE-- + + test + test 2 + + +EOF; + +$sxe = simplexml_load_string($xml); + +/* Add new attribute in a new namespace */ +$sxe->addAttribute('v:att11', 'xxx', 'urn::test-v'); + +/* Try to add attribute again -> display warning as method is for new Attr only */ +$sxe->addAttribute('v:att11', 'xxx', 'urn::test-v'); + +/* Add new attribute w/o namespace */ +$sxe->addAttribute('att2', 'no-ns'); + +$d = $sxe->attributes(); +/* Try to add element to attribute -> display warning and do not add */ +$d->addChild('m:test', 'myval', 'urn::test'); + + +/* Test adding elements in various configurations */ +$sxe->addChild('m:test1', 'myval', 'urn::test'); + +/* New namespace test */ +$n = $sxe->addChild('m:test2', 'myval', 'urn::testnew'); + +$sxe->addChild('test3', 'myval', 'urn::testnew'); +$sxe->addChild('test4', 'myval'); + +/* Does not add prefix here although name is valid (but discouraged) - change behavior? */ +$sxe->addChild('s:test5', 'myval'); + +echo $sxe->asXML(); +?> +===DONE=== +--EXPECTF-- +Warning: SimpleXMLElement::addAttribute(): Attribute already exists in %s031.php on line %d + +Warning: SimpleXMLElement::addChild(): Cannot add element to attributes in %s031.php on line %d + + + test + test 2 + +myvalmyvalmyvalmyvalmyval +===DONE=== diff --git a/ext/simplexml/tests/032.phpt b/ext/simplexml/tests/032.phpt new file mode 100755 index 0000000000..5c2225146a --- /dev/null +++ b/ext/simplexml/tests/032.phpt @@ -0,0 +1,45 @@ +--TEST-- +SimpleXML: comparing instances +--SKIPIF-- + +--FILE-- + + + + + + + + + +EOF; + +$xml1 =<< + + + + + + + +EOF; + + +$people = simplexml_load_string($xml); +$people1 = simplexml_load_string($xml); +$people2 = simplexml_load_string($xml1); + +var_dump($people1 == $people); +var_dump($people2 == $people); +var_dump($people2 == $people1); + +?> +===DONE=== +--EXPECTF-- +bool(true) +bool(false) +bool(false) +===DONE=== diff --git a/ext/simplexml/tests/033.phpt b/ext/simplexml/tests/033.phpt new file mode 100755 index 0000000000..ba01b21555 --- /dev/null +++ b/ext/simplexml/tests/033.phpt @@ -0,0 +1,137 @@ +--TEST-- +SimpleXML: casting instances +--SKIPIF-- + +--FILE-- + +test + + + + + + + + +EOF; + +$foo = simplexml_load_string( "" ); +$people = simplexml_load_string($xml); + +var_dump((bool)$foo); +var_dump((bool)$people); +var_dump((int)$foo); +var_dump((int)$people); +var_dump((double)$foo); +var_dump((double)$people); +var_dump((string)$foo); +var_dump((string)$people); +var_dump((array)$foo); +var_dump((array)$people); +var_dump((object)$foo); +var_dump((object)$people); + +?> +===DONE=== +--EXPECTF-- +bool(false) +bool(true) +int(0) +int(0) +float(0) +float(0) +string(0) "" +string(15) " +test + + + +" +array(0) { +} +array(1) { + ["person"]=> + array(3) { + [0]=> + object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(1) { + ["name"]=> + string(3) "Joe" + } + } + [1]=> + object(SimpleXMLElement)#%d (2) { + ["@attributes"]=> + array(1) { + ["name"]=> + string(4) "John" + } + ["children"]=> + object(SimpleXMLElement)#%d (1) { + ["person"]=> + object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(1) { + ["name"]=> + string(3) "Joe" + } + } + } + } + [2]=> + object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(1) { + ["name"]=> + string(4) "Jane" + } + } + } +} +object(SimpleXMLElement)#%d (0) { +} +object(SimpleXMLElement)#%d (1) { + ["person"]=> + array(3) { + [0]=> + object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(1) { + ["name"]=> + string(3) "Joe" + } + } + [1]=> + object(SimpleXMLElement)#%d (2) { + ["@attributes"]=> + array(1) { + ["name"]=> + string(4) "John" + } + ["children"]=> + object(SimpleXMLElement)#%d (1) { + ["person"]=> + object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(1) { + ["name"]=> + string(3) "Joe" + } + } + } + } + [2]=> + object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(1) { + ["name"]=> + string(4) "Jane" + } + } + } +} +===DONE=== diff --git a/ext/simplexml/tests/bug36611.phpt b/ext/simplexml/tests/bug36611.phpt new file mode 100644 index 0000000000..fdfed0d019 --- /dev/null +++ b/ext/simplexml/tests/bug36611.phpt @@ -0,0 +1,28 @@ +--TEST-- +Bug #36611 (assignment to SimpleXML object attribute changes argument type to string) +--FILE-- + + + + + + +EOD; + +$xml = simplexml_load_string ($xml_str) ; + +$val = 1; + +var_dump($val); +$obj->pos["act_idx"] = $val; +var_dump($val) ; + +echo "Done\n"; +?> +--EXPECT-- +int(1) +int(1) +Done diff --git a/ext/soap/tests/bugs/bug36226.phpt b/ext/soap/tests/bugs/bug36226.phpt new file mode 100755 index 0000000000..c88d969f29 --- /dev/null +++ b/ext/soap/tests/bugs/bug36226.phpt @@ -0,0 +1,139 @@ +--TEST-- +Bug #36226 SOAP Inconsistent handling when passing potential arrays. +--SKIPIF-- + +--INI-- +soap.wsdl_cache_enabled=0 +--FILE-- +server = new SoapServer($wsdl, $options); + $this->server->addFunction('PostEvents'); + } + + function __doRequest($request, $location, $action, $version) { + echo "$request\n"; + $this->server->handle($request); + return $response; + } + +} + +$soapClient = new TestSoapClient($wsdl, + array('trace' => 1, 'exceptions' => 0, + 'classmap' => array('logOnEvent' => 'LogOnEvent', + 'logOffEvent' => 'LogOffEvent', + 'events' => 'IVREvents'), + 'features' => SOAP_SINGLE_ELEMENT_ARRAYS)); + +$logOnEvent = new LogOnEvent(34567, $timestamp); +$logOffEvents[] = new LogOffEvent(34567, $timestamp, "Smoked"); +$logOffEvents[] = new LogOffEvent(34568, $timestamp, "SmokeFree"); +$ivrEvents = new IVREvents("1.0", 101, 12345, 'IVR', $logOnEvent, $logOffEvents); + +$result = $soapClient->PostEvents($ivrEvents); + +class LogOffEvent { + public $audienceMemberId; + public $timestamp; + public $smokeStatus; + public $callInitiator; + + function __construct($audienceMemberId, $timestamp, $smokeStatus) { + $this->audienceMemberId = $audienceMemberId; + $this->timestamp = $timestamp; + $this->smokeStatus = $smokeStatus; + $this->callInitiator = "IVR"; + } +} + +class LogOnEvent { + public $audienceMemberId; + public $timestamp; + + function __construct($audienceMemberId, $timestamp) { + $this->audienceMemberId = $audienceMemberId; + $this->timestamp = $timestamp; + } +} + +class IVREvents { + public $version; + public $activityId; + public $messageId; + public $source; + public $logOnEvent; + public $logOffEvent; + + function __construct($version, $activityId, $messageId, $source, $logOnEvent=NULL, $logOffEvent=NULL) { + $this->version = $version; + $this->activityId = $activityId; + $this->messageId = $messageId; + $this->source = $source; + $this->logOnEvent = $logOnEvent; + $this->logOffEvent = $logOffEvent; + } +} +?> +--EXPECTF-- + + + +object(IVREvents)#%d (6) { + ["version"]=> + string(3) "1.0" + ["activityId"]=> + int(101) + ["messageId"]=> + int(12345) + ["source"]=> + string(3) "IVR" + ["logOnEvent"]=> + array(1) { + [0]=> + object(LogOnEvent)#10 (2) { + ["audienceMemberId"]=> + int(34567) + ["timestamp"]=> + string(25) "2005-11-08T11:22:07+03:00" + } + } + ["logOffEvent"]=> + array(2) { + [0]=> + object(LogOffEvent)#%d (4) { + ["audienceMemberId"]=> + int(34567) + ["timestamp"]=> + string(25) "2005-11-08T11:22:07+03:00" + ["smokeStatus"]=> + string(6) "Smoked" + ["callInitiator"]=> + string(3) "IVR" + } + [1]=> + object(LogOffEvent)#%d (4) { + ["audienceMemberId"]=> + int(34568) + ["timestamp"]=> + string(25) "2005-11-08T11:22:07+03:00" + ["smokeStatus"]=> + string(9) "SmokeFree" + ["callInitiator"]=> + string(3) "IVR" + } + } +} diff --git a/ext/soap/tests/bugs/bug36575.phpt b/ext/soap/tests/bugs/bug36575.phpt new file mode 100755 index 0000000000..aad8fcad6a --- /dev/null +++ b/ext/soap/tests/bugs/bug36575.phpt @@ -0,0 +1,52 @@ +--TEST-- +Bug #36575 (Incorrect complex type instantiation with hierarchies) +--SKIPIF-- + +--INI-- +soap.wsdl_cache_enabled=0 +--FILE-- +var1 = $a1->var1; + $a3->var2 = "var two"; + $a3->var3 = "var three"; + return $a3; +} + +$classMap = array("A1" => "CT_A1", "A2" => "CT_A2", "A3" => "CT_A3"); + +$client = new SoapClient(dirname(__FILE__)."/bug36575.wsdl", array("trace" => 1, "exceptions" => 0, "classmap" => $classMap)); +$a2 = new CT_A2(); +$a2->var1 = "one"; +$a2->var2 = "two"; +$client->test($a2); + +$soapRequest = $client->__getLastRequest(); + +echo $soapRequest; + +$server = new SoapServer(dirname(__FILE__)."/bug36575.wsdl", array("classmap" => $classMap)); +$server->addFunction("test"); +$server->handle($soapRequest); +echo "ok\n"; +?> +--EXPECT-- + +onetwo + +onevar twovar three +ok diff --git a/ext/soap/tests/bugs/bug36575.wsdl b/ext/soap/tests/bugs/bug36575.wsdl new file mode 100755 index 0000000000..0f1899bcd5 --- /dev/null +++ b/ext/soap/tests/bugs/bug36575.wsdl @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/soap/tests/bugs/bug36614.phpt b/ext/soap/tests/bugs/bug36614.phpt new file mode 100755 index 0000000000..ba6734812d --- /dev/null +++ b/ext/soap/tests/bugs/bug36614.phpt @@ -0,0 +1,13 @@ +--TEST-- +Bug #36614 (Segfault when using Soap) +--SKIPIF-- + +--INI-- +soap.wsdl_cache_enabled=0 +--FILE-- + +--EXPECT-- +ok diff --git a/ext/soap/tests/bugs/bug36614.wsdl b/ext/soap/tests/bugs/bug36614.wsdl new file mode 100755 index 0000000000..ecf1b1b2fe --- /dev/null +++ b/ext/soap/tests/bugs/bug36614.wsdl @@ -0,0 +1,204 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/soap/tests/bugs/bug36629.phpt b/ext/soap/tests/bugs/bug36629.phpt new file mode 100755 index 0000000000..08b74a5fca --- /dev/null +++ b/ext/soap/tests/bugs/bug36629.phpt @@ -0,0 +1,53 @@ +--TEST-- +Bug #36629 (SoapServer::handle() exits on SOAP faults) +--SKIPIF-- + +--FILE-- +"http://testuri.org")); +$server->addfunction(array("test1","test2")); + +$HTTP_RAW_POST_DATA = << + + + + + +EOF; +$server->handle(); + +$HTTP_RAW_POST_DATA = << + + + + + +EOF; +$server->handle(); +echo "ok\n"; +?> +--EXPECT-- + +SOAP-ENV:Servertest1 + +SOAP-ENV:Servertest2 +ok diff --git a/ext/soap/tests/classmap003.phpt b/ext/soap/tests/classmap003.phpt new file mode 100755 index 0000000000..ac87a1682e --- /dev/null +++ b/ext/soap/tests/classmap003.phpt @@ -0,0 +1,54 @@ +--TEST-- +SOAP Classmap 3: encoding of inherited objects +--SKIPIF-- + +--FILE-- +x = $a; + } +} + +class B extends A { + public $y; + function __construct($a){ + parent::__construct($a); + $this->y = $a + 1; + } +} + +function f(){ + return new B(5); +} + +class LocalSoapClient extends SoapClient { + + function __construct($wsdl, $options) { + parent::__construct($wsdl, $options); + $this->server = new SoapServer($wsdl, $options); + $this->server->addFunction("f"); + } + + function __doRequest($request, $location, $action, $version) { + ob_start(); + $this->server->handle($request); + $response = ob_get_contents(); + ob_end_clean(); + return $response; + } +} + +$client = new LocalSoapClient(dirname(__FILE__)."/classmap003.wsdl", + array('classmap'=>array('A'=>'A','B'=>'B'))); +print_r($client->f()); +?> +--EXPECT-- +B Object +( + [y] => 6 + [x] => 5 +) diff --git a/ext/soap/tests/classmap003.wsdl b/ext/soap/tests/classmap003.wsdl new file mode 100755 index 0000000000..494c41864e --- /dev/null +++ b/ext/soap/tests/classmap003.wsdl @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/soap/tests/server023.phpt b/ext/soap/tests/server023.phpt new file mode 100755 index 0000000000..c227204d33 --- /dev/null +++ b/ext/soap/tests/server023.phpt @@ -0,0 +1,37 @@ +--TEST-- +SOAP Server 23: Send SOAP headers those were not received +--SKIPIF-- + +--FILE-- +addSoapHeader(new SoapHeader("http://testuri.org", "Test1", "Hello Header!")); + $server->addSoapHeader(new SoapHeader("http://testuri.org", "Test2", "Hello Header!")); + return "Hello Body!"; +} + +$server = new soapserver(null,array('uri'=>"http://testuri.org")); +$server->addfunction("test"); + +$HTTP_RAW_POST_DATA = << + + + + + +EOF; + +$server->handle(); +echo "ok\n"; +?> +--EXPECT-- + +Hello Header!Hello Header!Hello Body! +ok diff --git a/ext/soap/tests/server024.phpt b/ext/soap/tests/server024.phpt new file mode 100755 index 0000000000..0ddd9cec39 --- /dev/null +++ b/ext/soap/tests/server024.phpt @@ -0,0 +1,49 @@ +--TEST-- +SOAP Server 24: Send SOAP headers those were not received +--SKIPIF-- + +--FILE-- +addSoapHeader(new TestHeader1("Hello Header!")); + $server->addSoapHeader(new TestHeader2("Hello Header!")); + return "Hello Body!"; +} + +$server = new soapserver(null,array('uri'=>"http://testuri.org")); +$server->addfunction("test"); + +$HTTP_RAW_POST_DATA = << + + + + + +EOF; + +$server->handle(); +echo "ok\n"; +?> +--EXPECT-- + +Hello Header!Hello Header!Hello Body! +ok diff --git a/ext/soap/tests/server025.phpt b/ext/soap/tests/server025.phpt new file mode 100755 index 0000000000..0a98b4108a --- /dev/null +++ b/ext/soap/tests/server025.phpt @@ -0,0 +1,46 @@ +--TEST-- +SOAP Server 25: One-way SOAP headers encoding using WSDL +--SKIPIF-- + +--FILE-- +addSoapHeader(new TestHeader1("Hello Header!")); + $server->addSoapHeader(new TestHeader2("Hello Header!")); + return "Hello Body!"; +} + +$server = new soapserver(dirname(__FILE__)."/server025.wsdl"); +$server->addfunction("test"); + +$HTTP_RAW_POST_DATA = << + + + + + +EOF; + +$server->handle(); +echo "ok\n"; +?> +--EXPECT-- + +Hello Header!Hello Header!Hello Body! +ok diff --git a/ext/soap/tests/server025.wsdl b/ext/soap/tests/server025.wsdl new file mode 100755 index 0000000000..2870f4e70d --- /dev/null +++ b/ext/soap/tests/server025.wsdl @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/spl/tests/array_019.phpt b/ext/spl/tests/array_019.phpt new file mode 100755 index 0000000000..1416d8407d --- /dev/null +++ b/ext/spl/tests/array_019.phpt @@ -0,0 +1,32 @@ +--TEST-- +SPL: ArrayIterator and foreach by reference +--SKIPIF-- + +--FILE-- + +===DONE=== + +--EXPECTF-- +int(1) +int(2) +int(3) +int(4) +int(5) +===DONE=== diff --git a/ext/spl/tests/array_020.phpt b/ext/spl/tests/array_020.phpt new file mode 100755 index 0000000000..cdeb4a216c --- /dev/null +++ b/ext/spl/tests/array_020.phpt @@ -0,0 +1,66 @@ +--TEST-- +SPL: ArrayIterator overloading +--SKIPIF-- + +--FILE-- + $v) +{ + var_dump($k); + var_dump($v); +} + +?> +===DONE=== + +--EXPECTF-- +ArrayIteratorEx::rewind +ArrayIteratorEx::valid +ArrayIteratorEx::current +ArrayIteratorEx::key +int(0) +int(1) +ArrayIteratorEx::next +ArrayIteratorEx::valid +ArrayIteratorEx::current +ArrayIteratorEx::key +int(1) +int(2) +ArrayIteratorEx::next +ArrayIteratorEx::valid +===DONE=== diff --git a/ext/spl/tests/array_021.phpt b/ext/spl/tests/array_021.phpt new file mode 100755 index 0000000000..f2ae0c87e5 --- /dev/null +++ b/ext/spl/tests/array_021.phpt @@ -0,0 +1,31 @@ +--TEST-- +SPL: ArrayObject::seek() and exceptions +--FILE-- +seek('bar'); +} +catch (Exception $e) +{ + echo "got exception\n"; +} + +?> +===DONE=== +--EXPECT-- +foo::seek(bar) +got exception +===DONE=== diff --git a/ext/spl/tests/array_022.phpt b/ext/spl/tests/array_022.phpt new file mode 100755 index 0000000000..d1eafd677c --- /dev/null +++ b/ext/spl/tests/array_022.phpt @@ -0,0 +1,94 @@ +--TEST-- +SPL: ArrayObject/Iterator and reference to self +--FILE-- +==ArrayObject=== + +==ArrayIterator=== + +===DONE=== +--EXPECTF-- +==ArrayObject=== +object(MyArrayObject)#%d (1) { + ["bar"]=> + string(3) "baz" +} +object(MyArrayObject)#%d (2) { + ["bar"]=> + string(3) "baz" + ["baz"]=> + string(3) "Foo" +} +==ArrayIterator=== +object(MyArrayIterator)#%d (1) { + ["bar"]=> + string(3) "baz" +} +object(MyArrayIterator)#%d (2) { + ["bar"]=> + string(3) "baz" + ["baz"]=> + string(3) "Foo" +} +===DONE=== +--UEXPECTF-- +==ArrayObject=== +object(MyArrayObject)#%d (1) { + [u"bar"]=> + unicode(3) "baz" +} +object(MyArrayObject)#%d (2) { + [u"bar"]=> + unicode(3) "baz" + [u"baz"]=> + unicode(3) "Foo" +} +==ArrayIterator=== +object(MyArrayIterator)#%d (1) { + [u"bar"]=> + unicode(3) "baz" +} +object(MyArrayIterator)#%d (2) { + [u"bar"]=> + unicode(3) "baz" + [u"baz"]=> + unicode(3) "Foo" +} +===DONE=== diff --git a/ext/spl/tests/bug36258.phpt b/ext/spl/tests/bug36258.phpt new file mode 100644 index 0000000000..297c7f5978 --- /dev/null +++ b/ext/spl/tests/bug36258.phpt @@ -0,0 +1,21 @@ +--TEST-- +Bug #36258 (SplFileObject::getPath() may lead to segfault) +--SKIPIF-- + +--FILE-- + $file) { + var_dump($file->getFilename()); + var_dump($file->getPath()); + break; +} + +echo "Done\n"; +?> +--EXPECTF-- +string(%d) "%s" +string(%d) "%s" +Done diff --git a/ext/spl/tests/bug36287.phpt b/ext/spl/tests/bug36287.phpt new file mode 100755 index 0000000000..29ae0e2c9d --- /dev/null +++ b/ext/spl/tests/bug36287.phpt @@ -0,0 +1,40 @@ +--TEST-- +Bug #36287 +--SKIPIF-- + +--FILE-- +getFilename()); + } + echo "Second\n"; + if($file != "." && $file != "..") + { + var_dump($file->getFilename()); + } + if (++$idx > 1) + { + break; + } +} + +?> +===DONE=== +--EXPECTF-- +First +string(%d) "%s" +Second +string(%d) "%s" +First +string(%d) "%s" +Second +string(%d) "%s" +===DONE=== diff --git a/ext/spl/tests/bug36825.phpt b/ext/spl/tests/bug36825.phpt new file mode 100644 index 0000000000..503ec43a43 --- /dev/null +++ b/ext/spl/tests/bug36825.phpt @@ -0,0 +1,33 @@ +--TEST-- +Bug #36825 (Exceptions thrown in ArrayObject::offsetGet cause segfault) +--SKIPIF-- + +--FILE-- + +===DONE=== +--EXPECT-- +foo::offsetGet(bar) +got exception +===DONE=== diff --git a/ext/spl/tests/bug36941.phpt b/ext/spl/tests/bug36941.phpt new file mode 100755 index 0000000000..528ba4a462 --- /dev/null +++ b/ext/spl/tests/bug36941.phpt @@ -0,0 +1,46 @@ +--TEST-- +Bug #36941 (ArrayIterator does not clone itself) +--FILE-- +===ArrayObject=== + +===ArrayIterator=== + +===DONE=== +--EXPECT-- +===ArrayObject=== +int(1) +int(1) +int(1) +int(2) +int(1) +int(3) +===ArrayIterator=== +int(1) +int(1) +int(2) +int(2) +int(3) +int(3) +===DONE=== diff --git a/ext/spl/tests/iterator_030.phpt b/ext/spl/tests/iterator_030.phpt new file mode 100755 index 0000000000..6ed8035ac1 --- /dev/null +++ b/ext/spl/tests/iterator_030.phpt @@ -0,0 +1,46 @@ +--TEST-- +SPL: EmptyIterator access +--SKIPIF-- + +--FILE-- +valid()); +$it->rewind(); +var_dump($it->valid()); +$it->next(); +var_dump($it->valid()); + +try +{ + var_dump($it->key()); +} +catch(BadMethodCallException $e) +{ + echo $e->getMessage() . "\n"; +} + +try +{ + var_dump($it->current()); +} +catch(BadMethodCallException $e) +{ + echo $e->getMessage() . "\n"; +} + +var_dump($it->valid()); + +?> +===DONE=== + +--EXPECT-- +bool(false) +bool(false) +bool(false) +Accessing the key of an EmptyIterator +Accessing the value of an EmptyIterator +bool(false) +===DONE=== diff --git a/ext/spl/tests/iterator_031.phpt b/ext/spl/tests/iterator_031.phpt new file mode 100755 index 0000000000..00afa61850 --- /dev/null +++ b/ext/spl/tests/iterator_031.phpt @@ -0,0 +1,118 @@ +--TEST-- +SPL: AppendIterator::append() rewinds when neccessary +--SKIPIF-- + +--FILE-- +$v) +{ + echo "$k=>$v\n"; +} + +class MyAppendIterator extends AppendIterator +{ + function __construct() + { + echo __METHOD__ . "\n"; + } + + function rewind() + { + echo __METHOD__ . "\n"; + parent::rewind(); + } + + function valid() + { + echo __METHOD__ . "\n"; + return parent::valid(); + } + + function append(Iterator $what) + { + echo __METHOD__ . "\n"; + parent::append($what); + } + + function parent__construct() + { + parent::__construct(); + } +} + +$ap = new MyAppendIterator; + +try +{ + $ap->append($it); +} +catch(BadMethodCallException $e) +{ + echo $e->getMessage() . "\n"; +} + +$ap->parent__construct(); + +try +{ + $ap->parent__construct($it); +} +catch(BadMethodCallException $e) +{ + echo $e->getMessage() . "\n"; +} + +$ap->append($it); +$ap->append($it); +$ap->append($it); + +foreach($ap as $k=>$v) +{ + echo "$k=>$v\n"; +} + +?> +===DONE=== + +--EXPECT-- +MyArrayIterator::rewind +0=>1 +1=>2 +MyAppendIterator::__construct +MyAppendIterator::append +Classes derived from AppendIterator must call AppendIterator::__construct() +AppendIterator::getIterator() must be called exactly once per instance +MyAppendIterator::append +MyArrayIterator::rewind +MyAppendIterator::append +MyAppendIterator::append +MyAppendIterator::rewind +MyArrayIterator::rewind +MyAppendIterator::valid +0=>1 +MyAppendIterator::valid +1=>2 +MyArrayIterator::rewind +MyAppendIterator::valid +0=>1 +MyAppendIterator::valid +1=>2 +MyArrayIterator::rewind +MyAppendIterator::valid +0=>1 +MyAppendIterator::valid +1=>2 +MyAppendIterator::valid +===DONE=== diff --git a/ext/spl/tests/iterator_032.phpt b/ext/spl/tests/iterator_032.phpt new file mode 100755 index 0000000000..86695d4af8 --- /dev/null +++ b/ext/spl/tests/iterator_032.phpt @@ -0,0 +1,52 @@ +--TEST-- +SPL: LimitIterator::getPosition() +--SKIPIF-- + +--FILE-- +$v) +{ + echo "$k=>$v\n"; + var_dump($it->getPosition()); +} + +try +{ + $it->seek(0); +} +catch(OutOfBoundsException $e) +{ + echo $e->getMessage() . "\n"; +} + +$it->seek(2); +var_dump($it->current()); + +try +{ + $it->seek(3); +} +catch(OutOfBoundsException $e) +{ + echo $e->getMessage() . "\n"; +} + +$it->next(); +var_dump($it->valid()); + +?> +===DONE=== + +--EXPECT-- +1=>2 +int(1) +2=>3 +int(2) +Cannot seek to 0 which is below the offset 1 +int(3) +Cannot seek to 3 which is behind offest 1 plus count 2 +bool(false) +===DONE=== diff --git a/ext/spl/tests/iterator_033.phpt b/ext/spl/tests/iterator_033.phpt new file mode 100755 index 0000000000..c1880cb2fb --- /dev/null +++ b/ext/spl/tests/iterator_033.phpt @@ -0,0 +1,46 @@ +--TEST-- +SPL: ParentIterator +--SKIPIF-- + +--FILE-- +$v) +{ + var_dump($k); + var_dump($v); +} + +echo "==SECOND==\n"; + +foreach(new RecursiveIteratorIterator($it, 1) as $k=>$v) +{ + var_dump($k); + var_dump($v); +} + +?> +===DONE=== + +--EXPECT-- +==SECOND== +int(1) +array(3) { + [0]=> + int(21) + [1]=> + int(22) + [2]=> + array(1) { + [0]=> + int(231) + } +} +int(2) +array(1) { + [0]=> + int(231) +} +===DONE=== diff --git a/ext/spl/tests/iterator_034.phpt b/ext/spl/tests/iterator_034.phpt new file mode 100755 index 0000000000..b81c6d970e --- /dev/null +++ b/ext/spl/tests/iterator_034.phpt @@ -0,0 +1,190 @@ +--TEST-- +SPL: RecursiveIteratorIterator and break deep +--SKIPIF-- + +--FILE-- +max_depth = $max_depth; + parent::__construct($it); + } + + function rewind() + { + echo __METHOD__ . "() - BEGIN\n"; + parent::rewind(); + echo __METHOD__ . "() - DONE\n"; + } + + function valid() + { + echo __METHOD__ . "()\n"; + return parent::valid(); + } + + function current() + { + echo __METHOD__ . "()\n"; + return parent::current(); + } + + function key() + { + echo __METHOD__ . "()\n"; + return parent::key(); + } + + function next() + { + echo __METHOD__ . "()\n"; + parent::next(); + } + + function callHasChildren() + { + $has = parent::callHasChildren(); + $res = $this->getDepth() < $this->max_depth && $has; + echo __METHOD__ . "(".$this->getDepth().") = ".($res?"yes":"no")."/".($has?"yes":"no")."\n"; + return $res; + } + + function beginChildren() + { + echo __METHOD__ . "(".$this->getDepth().")\n"; + parent::beginChildren(); + } + + function endChildren() + { + echo __METHOD__ . "(".$this->getDepth().")\n"; + parent::endChildren(); + } +} + +$p = 0; +$it = new RecursiveArrayIteratorIterator(new MyRecursiveArrayIterator(array("a", array("ba", array("bba", "bbb"), array(array("bcaa"), array("bcba"))), array("ca"), "d")), 2); +foreach($it as $k=>$v) +{ + if (is_array($v)) $v = join('',$v); + echo "$k=>$v\n"; + if ($p++ == 5) + { + echo "===BREAK===\n"; + break; + } +} + +echo "===FOREND===\n"; + +$it->rewind(); + +echo "===CHECK===\n"; + +var_dump($it->valid()); +var_dump($it->current() == "a"); + +?> +===DONE=== + +--EXPECT-- +RecursiveArrayIteratorIterator::rewind() - BEGIN +MyRecursiveArrayIterator::rewind() +RecursiveArrayIteratorIterator::callHasChildren(0) = no/no +RecursiveArrayIteratorIterator::rewind() - DONE +RecursiveArrayIteratorIterator::valid() +RecursiveArrayIteratorIterator::current() +RecursiveArrayIteratorIterator::key() +0=>a +RecursiveArrayIteratorIterator::next() +RecursiveArrayIteratorIterator::callHasChildren(0) = yes/yes +MyRecursiveArrayIterator::getChildren() +MyRecursiveArrayIterator::rewind() +RecursiveArrayIteratorIterator::beginChildren(1) +RecursiveArrayIteratorIterator::callHasChildren(1) = no/no +RecursiveArrayIteratorIterator::valid() +RecursiveArrayIteratorIterator::current() +RecursiveArrayIteratorIterator::key() +0=>ba +RecursiveArrayIteratorIterator::next() +RecursiveArrayIteratorIterator::callHasChildren(1) = yes/yes +MyRecursiveArrayIterator::getChildren() +MyRecursiveArrayIterator::rewind() +RecursiveArrayIteratorIterator::beginChildren(2) +RecursiveArrayIteratorIterator::callHasChildren(2) = no/no +RecursiveArrayIteratorIterator::valid() +RecursiveArrayIteratorIterator::current() +RecursiveArrayIteratorIterator::key() +0=>bba +RecursiveArrayIteratorIterator::next() +RecursiveArrayIteratorIterator::callHasChildren(2) = no/no +RecursiveArrayIteratorIterator::valid() +RecursiveArrayIteratorIterator::current() +RecursiveArrayIteratorIterator::key() +1=>bbb +RecursiveArrayIteratorIterator::next() +MyRecursiveArrayIterator::valid() = false +RecursiveArrayIteratorIterator::endChildren(2) +RecursiveArrayIteratorIterator::callHasChildren(1) = yes/yes +MyRecursiveArrayIterator::getChildren() +MyRecursiveArrayIterator::rewind() +RecursiveArrayIteratorIterator::beginChildren(2) +RecursiveArrayIteratorIterator::callHasChildren(2) = no/yes +RecursiveArrayIteratorIterator::valid() +RecursiveArrayIteratorIterator::current() +RecursiveArrayIteratorIterator::key() +0=>bcaa +RecursiveArrayIteratorIterator::next() +RecursiveArrayIteratorIterator::callHasChildren(2) = no/yes +RecursiveArrayIteratorIterator::valid() +RecursiveArrayIteratorIterator::current() +RecursiveArrayIteratorIterator::key() +1=>bcba +===BREAK=== +===FOREND=== +RecursiveArrayIteratorIterator::rewind() - BEGIN +RecursiveArrayIteratorIterator::endChildren(1) +RecursiveArrayIteratorIterator::endChildren(0) +MyRecursiveArrayIterator::rewind() +RecursiveArrayIteratorIterator::callHasChildren(0) = no/no +RecursiveArrayIteratorIterator::rewind() - DONE +===CHECK=== +RecursiveArrayIteratorIterator::valid() +bool(true) +RecursiveArrayIteratorIterator::current() +bool(true) +===DONE=== diff --git a/ext/spl/tests/iterator_035.phpt b/ext/spl/tests/iterator_035.phpt new file mode 100644 index 0000000000..eebc7f22a4 --- /dev/null +++ b/ext/spl/tests/iterator_035.phpt @@ -0,0 +1,17 @@ +--TEST-- +SPL: ArrayIterator and values assigned by reference +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Fatal error: Objects used as arrays in post/pre increment/decrement must return values by reference in %s on line %d diff --git a/ext/spl/tests/spl_autoload_008.phpt b/ext/spl/tests/spl_autoload_008.phpt new file mode 100755 index 0000000000..bafd26d877 --- /dev/null +++ b/ext/spl/tests/spl_autoload_008.phpt @@ -0,0 +1,131 @@ +--TEST-- +SPL: spl_autoload() with exceptions +--SKIPIF-- + +--INI-- +include_path=. +--FILE-- + $func) +{ + echo "====$idx====\n"; + + try + { + var_dump($func); + spl_autoload_register($func); + if (count(spl_autoload_functions())) + { + echo "registered\n"; + + var_dump(class_exists("NoExistingTestClass", true)); + } + } + catch (Exception $e) + { + echo get_class($e) . ": " . $e->getMessage() . "\n"; + } + + spl_autoload_unregister($func); + var_dump(count(spl_autoload_functions())); +} + +?> +===DONE=== + +--EXPECTF-- +====0==== +string(10) "MyAutoLoad" +registered +MyAutoLoad(NoExistingTestClass) +Exception: Bla +int(0) +====1==== +string(22) "MyAutoLoader::autoLoad" +registered +MyAutoLoader::autoLoad(NoExistingTestClass) +Exception: Bla +int(0) +====2==== +string(22) "MyAutoLoader::dynaLoad" +LogicException: Function 'MyAutoLoader::dynaLoad' not callable +int(0) +====3==== +array(2) { + [0]=> + string(12) "MyAutoLoader" + [1]=> + string(8) "autoLoad" +} +registered +MyAutoLoader::autoLoad(NoExistingTestClass) +Exception: Bla +int(0) +====4==== +array(2) { + [0]=> + string(12) "MyAutoLoader" + [1]=> + string(8) "dynaLoad" +} +LogicException: Passed array specifies a non static method but no object +int(0) +====5==== +array(2) { + [0]=> + object(MyAutoLoader)#%d (0) { + } + [1]=> + string(8) "autoLoad" +} +registered +MyAutoLoader::autoLoad(NoExistingTestClass) +Exception: Bla +int(0) +====6==== +array(2) { + [0]=> + object(MyAutoLoader)#%d (0) { + } + [1]=> + string(8) "dynaLoad" +} +registered +MyAutoLoader::dynaLoad(NoExistingTestClass) +Exception: Bla +int(0) +===DONE=== diff --git a/ext/spl/tests/sxe_005.phpt b/ext/spl/tests/sxe_005.phpt new file mode 100755 index 0000000000..2efd0a6bee --- /dev/null +++ b/ext/spl/tests/sxe_005.phpt @@ -0,0 +1,46 @@ +--TEST-- +SPL: SimpleXMLIterator and getChildren() +--SKIPIF-- + +--FILE-- + + + + + + +EOF; + +class SXETest extends SimpleXMLIterator +{ + function count() + { + echo __METHOD__ . "\n"; + return parent::count(); + } +} + +$sxe = new SXETest($xml); + +var_dump(count($sxe)); +var_dump(count($sxe->elem1)); +var_dump(count($sxe->elem2)); + +?> +===DONE=== +--EXPECT-- +SXETest::count +int(3) +SXETest::count +int(1) +SXETest::count +int(2) +===DONE=== diff --git a/ext/standard/tests/file/bug37158.phpt b/ext/standard/tests/file/bug37158.phpt new file mode 100644 index 0000000000..48df46cc63 --- /dev/null +++ b/ext/standard/tests/file/bug37158.phpt @@ -0,0 +1,39 @@ +--TEST-- +Bug #37158 (if userspace stream is present, fread() reads in 8192 max, otherwise it works) +--FILE-- + +--EXPECT-- +string(26) "size of contents 1 = 20000" +string(26) "size of contents 2 = 40960" +Done diff --git a/ext/standard/tests/filters/read.phpt b/ext/standard/tests/filters/read.phpt new file mode 100644 index 0000000000..a2372cf8f9 --- /dev/null +++ b/ext/standard/tests/filters/read.phpt @@ -0,0 +1,72 @@ +--TEST-- +stream filter - reading +--FILE-- +data = strtoupper($bucket->data); + $consumed += $bucket->datalen; + stream_bucket_append($out, $bucket); + $output = 1; + } + if ($closing) { + $bucket = stream_bucket_new($this->stream, "\n===close===\n"); + stream_bucket_append($out, $bucket); + $output = 1; + } + return $output ? PSFS_PASS_ON : PSFS_FEED_ME; + } +} +stream_filter_register("strtoupper", "filter") + or die("Failed to register filter"); + +if ($f = fopen(__FILE__, "rb")) { + stream_filter_append($f, "strtoupper"); + while (!feof($f)) { + echo fread($f, 8192); + } + fclose($f); +} +echo "Done\n"; +?> +--EXPECTF-- +%sTEST +DATA = STRTOUPPER($BUCKET->DATA); + $CONSUMED += $BUCKET->DATALEN; + STREAM_BUCKET_APPEND($OUT, $BUCKET); + $OUTPUT = 1; + } + IF ($CLOSING) { + $BUCKET = STREAM_BUCKET_NEW($THIS->STREAM, "\N===CLOSE===\N"); + STREAM_BUCKET_APPEND($OUT, $BUCKET); + $OUTPUT = 1; + } + RETURN $OUTPUT ? PSFS_PASS_ON : PSFS_FEED_ME; + } +} +STREAM_FILTER_REGISTER("STRTOUPPER", "FILTER") + OR DIE("FAILED TO REGISTER FILTER"); + +IF ($F = FOPEN(__FILE__, "RB")) { + STREAM_FILTER_APPEND($F, "STRTOUPPER"); + WHILE (!FEOF($F)) { + ECHO FREAD($F, 8192); + } + FCLOSE($F); +} +ECHO "DONE\N"; +?> + +===close=== +Done diff --git a/ext/standard/tests/general_functions/bug36011.phpt b/ext/standard/tests/general_functions/bug36011.phpt new file mode 100755 index 0000000000..08a45014f2 --- /dev/null +++ b/ext/standard/tests/general_functions/bug36011.phpt @@ -0,0 +1,46 @@ +--TEST-- +Bug #36011 (Strict errormsg wrong for call_user_func() and the likes) +--FILE-- +whee(); +$a->whee4(); +$a->whee5(); + +TestClass::whee5(); + +?> +===DONE=== +--EXPECTF-- +TestClass::test() +TestClass::test() +TestClass::test() +TestClass::test() +TestClass::test() +===DONE=== diff --git a/ext/standard/tests/strings/bug33605.phpt b/ext/standard/tests/strings/bug33605.phpt new file mode 100644 index 0000000000..f0c49eb18f --- /dev/null +++ b/ext/standard/tests/strings/bug33605.phpt @@ -0,0 +1,11 @@ +--TEST-- +Bug #33605 (substr_compare crashes) +--FILE-- + +--EXPECTF-- +Warning: substr_compare(): The length must be greater than zero in %s on line %d +bool(false) diff --git a/ext/standard/tests/strings/bug36148.phpt b/ext/standard/tests/strings/bug36148.phpt new file mode 100644 index 0000000000..06caac3334 --- /dev/null +++ b/ext/standard/tests/strings/bug36148.phpt @@ -0,0 +1,29 @@ +--TEST-- +Bug #36148 (unpack("H*hex", $data) is adding an extra character to the end of the string) +--FILE-- + +--EXPECT-- +a: array(1) { + [1]=> + string(2) "a0" +} +aa: array(1) { + [1]=> + string(2) "aa" +} +aaa: array(1) { + [1]=> + string(4) "aaa0" +} +aaaa: array(1) { + [1]=> + string(4) "aaaa" +} diff --git a/ext/standard/tests/strings/bug36306.phpt b/ext/standard/tests/strings/bug36306.phpt new file mode 100644 index 0000000000..ff6279a2d3 --- /dev/null +++ b/ext/standard/tests/strings/bug36306.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #36306 crc32() 64bit +--FILE-- + +--EXPECT-- +ccd9fe66 diff --git a/ext/standard/tests/strings/bug36944.phpt b/ext/standard/tests/strings/bug36944.phpt new file mode 100644 index 0000000000..2a43d060e2 --- /dev/null +++ b/ext/standard/tests/strings/bug36944.phpt @@ -0,0 +1,26 @@ +--TEST-- +Bug #36944 (strncmp & strncasecmp do not return false on negative string length) +--FILE-- + +--EXPECTF-- +Warning: Length must be greater than or equal to 0 in %s on line %d +bool(false) +int(%d) +int(0) + +Warning: Length must be greater than or equal to 0 in %s on line %d +bool(false) +int(%d) +int(0) +Done diff --git a/ext/standard/tests/strings/substr_compare.phpt b/ext/standard/tests/strings/substr_compare.phpt new file mode 100644 index 0000000000..594aed1735 --- /dev/null +++ b/ext/standard/tests/strings/substr_compare.phpt @@ -0,0 +1,39 @@ +--TEST-- +substr_compare() +--FILE-- + +--EXPECTF-- +int(0) +int(0) +int(0) +int(1) +int(-1) + +Warning: substr_compare(): The start position cannot exceed initial string length in %s on line %d +bool(false) + +Warning: substr_compare() expects parameter 5 to be boolean, object given in %s on line %d +bool(false) +Test + +Warning: substr_compare(): The length must be greater than zero in %s on line %d +bool(false) + +Warning: substr_compare() expects parameter 4 to be long, string given in %s on line %d +bool(false) +Done diff --git a/ext/xmlreader/tests/011.phpt b/ext/xmlreader/tests/011.phpt new file mode 100644 index 0000000000..89599232fc --- /dev/null +++ b/ext/xmlreader/tests/011.phpt @@ -0,0 +1,34 @@ +--TEST-- +XMLReader: libxml2 XML Reader, string data +--SKIPIF-- + +--FILE-- + +test'; + +$reader = new XMLReader(); +$reader->XML($xmlstring); +$reader->read(); +echo $reader->readInnerXml(); +echo "\n"; +$reader->close(); + + +$reader = new XMLReader(); +$reader->XML($xmlstring); +$reader->read(); +echo $reader->readOuterXml(); +echo "\n"; +$reader->close(); +?> +===DONE=== +--EXPECT-- +test +test +===DONE=== diff --git a/ext/xmlreader/tests/012.dtd b/ext/xmlreader/tests/012.dtd new file mode 100755 index 0000000000..b65412af0e --- /dev/null +++ b/ext/xmlreader/tests/012.dtd @@ -0,0 +1,2 @@ + + diff --git a/ext/xmlreader/tests/012.phpt b/ext/xmlreader/tests/012.phpt new file mode 100755 index 0000000000..e420bb7a17 --- /dev/null +++ b/ext/xmlreader/tests/012.phpt @@ -0,0 +1,69 @@ +--TEST-- +XMLReader: accessing empty and non existing attributes +--SKIPIF-- + +--FILE-- + + +EOF; + +$reader = new XMLReader(); +$reader->XML($xmlstring); +$reader->read(); +var_dump($reader->getAttribute('bar')); +var_dump($reader->getAttribute('baz')); +$reader->close(); + +$xmlstring =<< + + +EOF; + +$xmlstring = str_replace('012.dtd', dirname(__FILE__).'/012.dtd', $xmlstring); + +$reader = new XMLReader(); +$reader->XML($xmlstring); +$reader->setParserProperty(XMLReader::DEFAULTATTRS, true); +while($reader->read() && $reader->nodeType != XMLReader::ELEMENT); +var_dump($reader->getAttribute('bar')); +var_dump($reader->getAttribute('baz')); +$reader->close(); + +?> +===FILE=== +open(dirname(__FILE__) . '/012.xml'); +//$reader->setParserProperty(XMLReader::DEFAULTATTRS, true); +while($reader->read() && $reader->nodeType != XMLReader::ELEMENT); +var_dump($reader->getAttribute('bar')); +var_dump($reader->getAttribute('baz')); +$reader->close(); + +$reader = new XMLReader(); +$reader->open(dirname(__FILE__) . '/012.xml'); +$reader->setParserProperty(XMLReader::DEFAULTATTRS, true); +while($reader->read() && $reader->nodeType != XMLReader::ELEMENT); +var_dump($reader->getAttribute('bar')); +var_dump($reader->getAttribute('baz')); +$reader->close(); + +?> +===DONE=== +--EXPECT-- +string(0) "" +NULL +string(0) "" +string(0) "" +===FILE=== +string(0) "" +NULL +string(0) "" +string(0) "" +===DONE=== diff --git a/ext/xmlreader/tests/012.xml b/ext/xmlreader/tests/012.xml new file mode 100755 index 0000000000..5012bd5eff --- /dev/null +++ b/ext/xmlreader/tests/012.xml @@ -0,0 +1,3 @@ + + + diff --git a/ext/xmlreader/tests/bug36743.phpt b/ext/xmlreader/tests/bug36743.phpt new file mode 100644 index 0000000000..45747d49f1 --- /dev/null +++ b/ext/xmlreader/tests/bug36743.phpt @@ -0,0 +1,25 @@ +--TEST-- +Bug #36743 (In a class extending XMLReader array properties are not writable) +--FILE-- +testArr[] = 1; + var_dump($this->testArr); + } +} + +$t = new test; + +echo "Done\n"; +?> +--EXPECT-- +array(1) { + [0]=> + int(1) +} +Done diff --git a/ext/xmlrpc/tests/bug37057.phpt b/ext/xmlrpc/tests/bug37057.phpt new file mode 100644 index 0000000000..0764d8af67 --- /dev/null +++ b/ext/xmlrpc/tests/bug37057.phpt @@ -0,0 +1,62 @@ +--TEST-- +Bug #37057 (xmlrpc_decode() may produce arrays with numeric string keys which are unaccessible) +--FILE-- + + + + + + + + 50 + 0.29 + + + + + +'; + +$retval=xmlrpc_decode($response); +var_dump($retval); +var_dump($retval["50"]); +var_dump($retval[50]); + +$response=' + + + + + + + 0 + 0.29 + + + + + +'; + +$retval=xmlrpc_decode($response); +var_dump($retval); +var_dump($retval["0"]); +var_dump($retval[0]); + +echo "Done\n"; +?> +--EXPECT-- +array(1) { + [50]=> + string(4) "0.29" +} +string(4) "0.29" +string(4) "0.29" +array(1) { + [0]=> + string(4) "0.29" +} +string(4) "0.29" +string(4) "0.29" +Done diff --git a/sapi/cgi/fastcgi.c b/sapi/cgi/fastcgi.c new file mode 100644 index 0000000000..afa5271d0e --- /dev/null +++ b/sapi/cgi/fastcgi.c @@ -0,0 +1,938 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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. | + +----------------------------------------------------------------------+ + | Authors: Dmitry Stogov | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#include "fastcgi.h" +#include "php.h" + +#include +#include +#include +#include +#include + +#ifdef _WIN32 + +#include + + typedef unsigned int size_t; + + struct sockaddr_un { + short sun_family; + char sun_path[MAXPATHLEN]; + }; + + static HANDLE fcgi_accept_mutex = INVALID_HANDLE_VALUE; + static int is_impersonate = 0; + +#define FCGI_LOCK(fd) \ + if (fcgi_accept_mutex != INVALID_HANDLE_VALUE) { \ + DWORD ret; \ + while ((ret = WaitForSingleObject(fcgi_accept_mutex, 1000)) == WAIT_TIMEOUT) { \ + if (in_shutdown) return -1; \ + } \ + if (ret == WAIT_FAILED) { \ + fprintf(stderr, "WaitForSingleObject() failed\n"); \ + return -1; \ + } \ + } + +#define FCGI_UNLOCK(fd) \ + if (fcgi_accept_mutex != INVALID_HANDLE_VALUE) { \ + ReleaseMutex(fcgi_accept_mutex); \ + } + +#else + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +#ifndef INADDR_NONE +#define INADDR_NONE ((unsigned long) -1) +#endif + +# ifndef HAVE_SOCKLEN_T + typedef unsigned int socklen_t; +# endif + +# ifdef USE_LOCKING +# define FCGI_LOCK(fd) \ + do { \ + struct flock lock; \ + lock.l_type = F_WRLCK; \ + lock.l_start = 0; \ + lock.l_whence = SEEK_SET; \ + lock.l_len = 0; \ + if (fcntl(fd, F_SETLKW, &lock) != -1) { \ + break; \ + } else if (errno != EINTR || in_shutdown) { \ + return -1; \ + } \ + } while (1) + +# define FCGI_UNLOCK(fd) \ + do { \ + int orig_errno = errno; \ + while (1) { \ + struct flock lock; \ + lock.l_type = F_UNLCK; \ + lock.l_start = 0; \ + lock.l_whence = SEEK_SET; \ + lock.l_len = 0; \ + if (fcntl(fd, F_SETLK, &lock) != -1) { \ + break; \ + } else if (errno != EINTR) { \ + return -1; \ + } \ + } \ + errno = orig_errno; \ + } while (0) +# else +# define FCGI_LOCK(fd) +# define FCGI_UNLOCK(fd) +# endif + +#endif + +typedef union _sa_t { + struct sockaddr sa; + struct sockaddr_un sa_unix; + struct sockaddr_in sa_inet; +} sa_t; + +typedef struct _fcgi_mgmt_rec { + char* name; + char val; +} fcgi_mgmt_rec; + +static const fcgi_mgmt_rec fcgi_mgmt_vars[] = { + {"FCGI_MAX_CONNS", 1}, + {"FCGI_MAX_REQS", 1}, + {"FCGI_MPXS_CONNS", 0} +}; + + +static int is_initialized = 0; +static int is_fastcgi = 0; +static int in_shutdown = 0; + +static inline char* fcgi_strndup(const char *str, int len) +{ + char *s = malloc(len+1); + memcpy(s, str, len+1); + return s; +} + +#ifdef _WIN32 + +static DWORD WINAPI fcgi_shutdown_thread(LPVOID arg) +{ + HANDLE shutdown_event = (HANDLE) arg; + WaitForSingleObject(shutdown_event, INFINITE); + in_shutdown = 1; + return 0; +} + +#else + +static void fcgi_signal_handler(int signo) +{ + if (signo == SIGUSR1 || signo == SIGTERM) { + in_shutdown = 1; + } +} + +#endif + +int fcgi_init(void) +{ + if (!is_initialized) { +#ifdef _WIN32 +# if 0 + /* TODO: Support for TCP sockets */ + WSADATA wsaData; + + if (WSAStartup(MAKEWORD(2,0), &wsaData)) { + fprintf(stderr, "Error starting Windows Sockets. Error: %d", WSAGetLastError()); + return 0; + } +# endif + is_initialized = 1; + + if ((GetStdHandle(STD_OUTPUT_HANDLE) == INVALID_HANDLE_VALUE) && + (GetStdHandle(STD_ERROR_HANDLE) == INVALID_HANDLE_VALUE) && + (GetStdHandle(STD_INPUT_HANDLE) != INVALID_HANDLE_VALUE)) { + char *str; + DWORD pipe_mode = PIPE_READMODE_BYTE | PIPE_WAIT; + HANDLE pipe = GetStdHandle(STD_INPUT_HANDLE); + + SetNamedPipeHandleState(pipe, &pipe_mode, NULL, NULL); + + str = getenv("_FCGI_SHUTDOWN_EVENT_"); + if (str != NULL) { + HANDLE shutdown_event = (HANDLE) atoi(str); + if (!CreateThread(NULL, 0, fcgi_shutdown_thread, + shutdown_event, 0, NULL)) { + return -1; + } + } + str = getenv("_FCGI_MUTEX_"); + if (str != NULL) { + fcgi_accept_mutex = (HANDLE) atoi(str); + } + return is_fastcgi = 1; + } else { + return is_fastcgi = 0; + } +#else + sa_t sa; + socklen_t len = sizeof(sa); + + is_initialized = 1; + errno = 0; + if (getpeername(0, (struct sockaddr *)&sa, &len) != 0 && errno == ENOTCONN) { + struct sigaction new_sa, old_sa; + + sigemptyset(&new_sa.sa_mask); + new_sa.sa_flags = 0; + new_sa.sa_handler = fcgi_signal_handler; + sigaction(SIGUSR1, &new_sa, NULL); + sigaction(SIGTERM, &new_sa, NULL); + sigaction(SIGPIPE, NULL, &old_sa); + if (old_sa.sa_handler == SIG_DFL) { + sigaction(SIGPIPE, &new_sa, NULL); + } + + return is_fastcgi = 1; + } else { + return is_fastcgi = 0; + } +#endif + } + return is_fastcgi; +} + + +int fcgi_is_fastcgi(void) +{ + if (!is_initialized) { + return fcgi_init(); + } else { + return is_fastcgi; + } +} + +int fcgi_listen(const char *path, int backlog) +{ +#ifdef _WIN32 + /* TODO: Support for manual binding on TCP sockets (php -b ) */ + return -1; +#else + char *s; + int tcp = 0; + char host[MAXPATHLEN]; + short port = 0; + int listen_socket; + sa_t sa; + socklen_t sa_len; + + if ((s = strchr(path, ':'))) { + port = atoi(s+1); + if (port != 0 && (s-path) < MAXPATHLEN) { + strncpy(host, path, s-path); + host[s-path] = '\0'; + tcp = 1; + } + } + + /* Prepare socket address */ + if (tcp) { + memset(&sa.sa_inet, 0, sizeof(sa.sa_inet)); + sa.sa_inet.sin_family = AF_INET; + sa.sa_inet.sin_port = htons(port); + sa_len = sizeof(sa.sa_inet); + + if (!*host || !strncmp(host, "*", sizeof("*")-1)) { + sa.sa_inet.sin_addr.s_addr = htonl(INADDR_ANY); + } else { + sa.sa_inet.sin_addr.s_addr = inet_addr(host); + if (sa.sa_inet.sin_addr.s_addr == INADDR_NONE) { + struct hostent *hep; + + hep = gethostbyname(host); + if (!hep || hep->h_addrtype != AF_INET || !hep->h_addr_list[0]) { + fprintf(stderr, "Cannot resolve host name '%s'!\n", host); + return -1; + } else if (hep->h_addr_list[1]) { + fprintf(stderr, "Host '%s' has multiple addresses. You must choose one explicitly!\n", host); + return -1; + } + sa.sa_inet.sin_addr.s_addr = ((struct in_addr*)hep->h_addr_list[0])->s_addr; + } + } + } else { + int path_len = strlen(path); + + if (path_len >= sizeof(sa.sa_unix.sun_path)) { + fprintf(stderr, "Listening socket's path name is too long.\n"); + return -1; + } + + memset(&sa.sa_unix, 0, sizeof(sa.sa_unix)); + sa.sa_unix.sun_family = AF_UNIX; + memcpy(sa.sa_unix.sun_path, path, path_len + 1); + sa_len = (size_t)(((struct sockaddr_un *)0)->sun_path) + path_len; +#ifdef HAVE_SOCKADDR_UN_SUN_LEN + sa.sa_unix.sun_len = sa_len; +#endif + unlink(path); + } + + /* Create, bind socket and start listen on it */ + if ((listen_socket = socket(sa.sa.sa_family, SOCK_STREAM, 0)) < 0 || + bind(listen_socket, (struct sockaddr *) &sa, sa_len) < 0 || + listen(listen_socket, backlog) < 0) { + + fprintf(stderr, "Cannot bind/listen socket - [%d] %s.\n",errno, strerror(errno)); + return -1; + } + + if (!tcp) { + chmod(path, 0777); + } + + if (!is_initialized) { + fcgi_init(); + } + is_fastcgi = 1; + return listen_socket; +#endif +} + +void fcgi_init_request(fcgi_request *req, int listen_socket) +{ + memset(req, 0, sizeof(fcgi_request)); + req->listen_socket = listen_socket; + req->fd = -1; + req->id = -1; + + req->in_len = 0; + req->in_pad = 0; + + req->out_hdr = NULL; + req->out_pos = req->out_buf; +} + +static inline ssize_t safe_write(fcgi_request *req, const void *buf, size_t count) +{ + int ret; + size_t n = 0; + + do { + ret = write(req->fd, ((char*)buf)+n, count-n); + if (ret > 0) { + n += ret; + } else if (ret <= 0 && errno != 0 && errno != EINTR) { + return ret; + } + } while (n != count); + return n; +} + +static inline ssize_t safe_read(fcgi_request *req, const void *buf, size_t count) +{ + int ret; + size_t n = 0; + + do { + ret = read(req->fd, ((char*)buf)+n, count-n); + if (ret > 0) { + n += ret; + } else if (ret == 0 && errno == 0) { + return n; + } else if (ret <= 0 && errno != 0 && errno != EINTR) { + return ret; + } + } while (n != count); + return n; +} + +static inline int fcgi_make_header(fcgi_header *hdr, fcgi_request_type type, int req_id, int len) +{ + int pad = ((len + 7) & ~7) - len; + + hdr->contentLengthB0 = (unsigned char)(len & 0xff); + hdr->contentLengthB1 = (unsigned char)((len >> 8) & 0xff); + hdr->paddingLength = (unsigned char)pad; + hdr->requestIdB0 = (unsigned char)(req_id & 0xff); + hdr->requestIdB1 = (unsigned char)((req_id >> 8) & 0xff); + hdr->reserved = 0; + hdr->type = type; + hdr->version = FCGI_VERSION_1; + return pad; +} + +static int fcgi_get_params(fcgi_request *req, unsigned char *p, unsigned char *end, int n) +{ + int name_len, val_len; + char *s; + + while (p < end) { + name_len = *p++; + if (name_len >= 128) { + name_len = ((name_len & 0x7f) << 24); + name_len |= (*p++ << 16); + name_len |= (*p++ << 8); + name_len |= *p++; + } + val_len = *p++; + if (val_len >= 128) { + val_len = ((val_len & 0x7f) << 24); + val_len |= (*p++ << 16); + val_len |= (*p++ << 8); + val_len |= *p++; + } + req->env[n] = s = malloc(name_len + val_len + 2); + memcpy(s, p, name_len); + p += name_len; + s[name_len] = '='; + memcpy(s+name_len+1, p, val_len); + p += val_len; + s[name_len+1+val_len] = '\0'; + n++; + if (n > sizeof(req->env)/sizeof(req->env[0])) { + /* TODO: to many environment variables */ + return n; + } + } + return n; +} + +static int fcgi_read_request(fcgi_request *req) +{ + fcgi_header hdr; + int len, padding; + int n = 1; + char *s; + unsigned char buf[FCGI_MAX_LENGTH+8]; + + req->keep = 0; + req->in_len = 0; + req->out_hdr = NULL; + req->out_pos = req->out_buf; + memset(req->env, 0, sizeof(req->env)); + + if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || + hdr.version < FCGI_VERSION_1) { + return 0; + } + + len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; + padding = hdr.paddingLength; + + while (hdr.type == FCGI_STDIN && len == 0) { + if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || + hdr.version < FCGI_VERSION_1) { + return 0; + } + + len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; + padding = hdr.paddingLength; + } + + req->id = (hdr.requestIdB1 << 8) + hdr.requestIdB0; + + if (hdr.type == FCGI_BEGIN_REQUEST && len == sizeof(fcgi_begin_request)) { + if (safe_read(req, buf, len+padding) != len+padding) { + return 0; + } + + req->keep = (((fcgi_begin_request*)buf)->flags & FCGI_KEEP_CONN); + switch ((((fcgi_begin_request*)buf)->roleB1 << 8) + ((fcgi_begin_request*)buf)->roleB0) { + case FCGI_RESPONDER: + req->env[0] = fcgi_strndup("FCGI_ROLE=RESPONDER", sizeof("FCGI_ROLE=RESPONDER")-1); + break; + case FCGI_AUTHORIZER: + req->env[0] = fcgi_strndup("FCGI_ROLE=AUTHORIZER", sizeof("FCGI_ROLE=AUTHORIZER")-1); + break; + case FCGI_FILTER: + req->env[0] = fcgi_strndup("FCGI_ROLE=FILTER", sizeof("FCGI_ROLE=FILTER")-1); + break; + default: + return 0; + } + + if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || + hdr.version < FCGI_VERSION_1) { + return 0; + } + + len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; + padding = hdr.paddingLength; + + while (hdr.type == FCGI_PARAMS && len > 0) { + if (safe_read(req, buf, len+padding) != len+padding) { + req->keep = 0; + return 0; + } + n = fcgi_get_params(req, buf, buf+len, n); + + if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || + hdr.version < FCGI_VERSION_1) { + req->keep = 0; + return 0; + } + len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; + padding = hdr.paddingLength; + } + } else if (hdr.type == FCGI_GET_VALUES) { + int i, j; + int name_len; + unsigned char *p = buf + sizeof(fcgi_header); + + if (safe_read(req, buf, len+padding) != len+padding) { + return 0; + } + n = fcgi_get_params(req, buf, buf+len, 0); + for (i = 0; i < n; i++) { + if ((s = strchr(req->env[i], '=')) != NULL) { + *s = '\0'; + name_len = s - req->env[i]; + } else { + name_len = strlen(req->env[i]); + } + for (j = 0; j < sizeof(fcgi_mgmt_vars)/sizeof(fcgi_mgmt_vars[0]); j++) { + if (strncmp(req->env[i], fcgi_mgmt_vars[j].name, name_len) == 0) { + sprintf((char*)p, "%c%c%s%c", name_len, 1, fcgi_mgmt_vars[j].name, fcgi_mgmt_vars[j].val); + p += name_len+3; + } + } + } + len = p - buf - sizeof(fcgi_header); + len += fcgi_make_header((fcgi_header*)buf, FCGI_GET_VALUES_RESULT, 0, len); + if (safe_write(req, buf, sizeof(fcgi_header)+len) != (int)sizeof(fcgi_header)+len) { + return 0; + } + return 0; + } else { + return 0; + } + + return 1; +} + +int fcgi_read(fcgi_request *req, char *str, int len) +{ + int ret, n, rest; + fcgi_header hdr; + unsigned char buf[8]; + + n = 0; + rest = len; + while (rest > 0) { + if (req->in_len == 0) { + if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || + hdr.version < FCGI_VERSION_1 || + hdr.type != FCGI_STDIN) { + req->keep = 0; + return 0; + } + req->in_len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; + req->in_pad = hdr.paddingLength; + if (req->in_len == 0) { + return n; + } + } + + if (req->in_len >= rest) { + ret = safe_read(req, str, rest); + } else { + ret = safe_read(req, str, req->in_len); + } + if (ret < 0) { + req->keep = 0; + return ret; + } else if (ret > 0) { + req->in_len -= ret; + rest -= ret; + n += ret; + str += ret; + if (req->in_len == 0) { + if (req->in_pad) { + if (safe_read(req, buf, req->in_pad) != req->in_pad) { + req->keep = 0; + return ret; + } + } + } else { + return n; + } + } else { + return n; + } + } + return n; +} + +static inline void fcgi_close(fcgi_request *req, int force, int destroy) +{ + if (destroy) { + char **env = req->env; + while (*env) { + free(*env++); + } + } + if ((force || !req->keep) && req->fd >= 0) { +#ifdef _WIN32 + HANDLE pipe = (HANDLE)_get_osfhandle(req->fd); + + if (!force) { + FlushFileBuffers(pipe); + } + DisconnectNamedPipe(pipe); + if (is_impersonate) { + RevertToSelf(); + } +#else +#if 1 + shutdown(req->fd, 2); +#else + close(req->fd); +#endif +#endif + req->fd = -1; + } +} + +int fcgi_accept_request(fcgi_request *req) +{ +#ifdef _WIN32 + HANDLE pipe; + OVERLAPPED ov; +#endif + fcgi_finish_request(req); + + while (1) { + if (req->fd < 0) { + while (1) { + if (in_shutdown) { + return -1; + } +#ifdef _WIN32 + pipe = (HANDLE)_get_osfhandle(req->listen_socket); + + FCGI_LOCK(req->listen_socket); + ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (!ConnectNamedPipe(pipe, &ov)) { + errno = GetLastError(); + if (errno == ERROR_IO_PENDING) { + while (WaitForSingleObject(ov.hEvent, 1000) == WAIT_TIMEOUT) { + if (in_shutdown) { + CloseHandle(ov.hEvent); + FCGI_UNLOCK(req->listen_socket); + return -1; + } + } + } else if (errno != ERROR_PIPE_CONNECTED) { + } + } + CloseHandle(ov.hEvent); + if (is_impersonate && !ImpersonateNamedPipeClient(pipe)) { + DisconnectNamedPipe(pipe); + req->fd = -1; + } else { + req->fd = req->listen_socket; + } + FCGI_UNLOCK(req->listen_socket); +#else + sa_t sa; + socklen_t len = sizeof(sa); + + FCGI_LOCK(req->listen_socket); + req->fd = accept(req->listen_socket, (struct sockaddr *)&sa, &len); + FCGI_UNLOCK(req->listen_socket); +#endif + + if (req->fd < 0 && (in_shutdown || errno != EINTR)) { + return -1; + } + +#ifdef _WIN32 + break; +#else + if (req->fd >= 0) { + struct timeval tv = {1,0}; + fd_set set; + + FD_ZERO(&set); + FD_SET(req->fd, &set); +try_again: + errno = 0; + if (select(req->fd + 1, &set, NULL, NULL, &tv) >= 0 && FD_ISSET(req->fd, &set)) { + break; + } + if (errno == EINTR) goto try_again; + fcgi_close(req, 1, 0); + } +#endif + } + } else if (in_shutdown) { + return -1; + } + if (fcgi_read_request(req)) { + return req->fd; + } else { + fcgi_close(req, 1, 1); + } + } +} + +static inline fcgi_header* open_packet(fcgi_request *req, fcgi_request_type type) +{ + req->out_hdr = (fcgi_header*) req->out_pos; + req->out_hdr->type = type; + req->out_pos += sizeof(fcgi_header); + return req->out_hdr; +} + +static inline void close_packet(fcgi_request *req) +{ + if (req->out_hdr) { + int len = req->out_pos - ((unsigned char*)req->out_hdr + sizeof(fcgi_header)); + + req->out_pos += fcgi_make_header(req->out_hdr, req->out_hdr->type, req->id, len); + req->out_hdr = NULL; + } +} + +int fcgi_flush(fcgi_request *req, int close) +{ + int len; + + close_packet(req); + + len = req->out_pos - req->out_buf; + + if (close) { + fcgi_end_request_rec *rec = (fcgi_end_request_rec*)(req->out_pos); + + fcgi_make_header(&rec->hdr, FCGI_END_REQUEST, req->id, sizeof(fcgi_end_request)); + rec->body.appStatusB3 = 0; + rec->body.appStatusB2 = 0; + rec->body.appStatusB1 = 0; + rec->body.appStatusB0 = 0; + rec->body.protocolStatus = FCGI_REQUEST_COMPLETE; + len += sizeof(fcgi_end_request_rec); + } + + if (safe_write(req, req->out_buf, len) != len) { + req->keep = 0; + return 0; + } + + req->out_pos = req->out_buf; + return 1; +} + +int fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int len) +{ + int limit, rest; + + if (len <= 0) { + return 0; + } + + if (req->out_hdr && req->out_hdr->type != type) { + close_packet(req); + } + rest = len; +#if 0 + /* Unoptinmzed, but clear version */ + while (rest > 0) { + limit = sizeof(req->out_buf) - (req->out_pos - req->out_buf); + + if (!req->out_hdr) { + if (limit < sizeof(fcgi_header)) { + fcgi_flush(req, 0); + } + open_packet(req, type); + } + limit = sizeof(req->out_buf) - (req->out_pos - req->out_buf); + if (rest < limit) { + memcpy(req->out_pos, str, rest); + req->out_pos += rest; + return len; + } else { + memcpy(req->out_pos, str, limit); + req->out_pos += limit; + rest -= limit; + str += limit; + fcgi_flush(req, 0); + } + } +#else + /* Optinmzed version */ + if (!req->out_hdr) { + rest += sizeof(fcgi_header); + } + limit = sizeof(req->out_buf) - (req->out_pos - req->out_buf); + + if (rest < limit) { + if (!req->out_hdr) { + open_packet(req, type); + } + memcpy(req->out_pos, str, len); + req->out_pos += len; + } else if (rest - limit < sizeof(req->out_buf) - sizeof(fcgi_header)) { + if (!req->out_hdr) { + open_packet(req, type); + } + memcpy(req->out_pos, str, limit); + req->out_pos += limit; + fcgi_flush(req, 0); + open_packet(req, type); + memcpy(req->out_pos, str + limit, len - limit); + req->out_pos += len - limit; + } else { + int pos = 0; + int pad; + + close_packet(req); + while ((len - pos) > 0xffff) { + open_packet(req, type); + fcgi_make_header(req->out_hdr, type, req->id, 0xfff8); + req->out_hdr = NULL; + fcgi_flush(req, 0); + if (safe_write(req, str + pos, 0xfff8) != 0xfff8) { + req->keep = 0; + return -1; + } + pos += 0xfff8; + } + + pad = (((len - pos) + 7) & ~7) - (len - pos); + rest = pad ? 8 - pad : 0; + + open_packet(req, type); + fcgi_make_header(req->out_hdr, type, req->id, (len - pos) - rest); + req->out_hdr = NULL; + fcgi_flush(req, 0); + if (safe_write(req, str + pos, (len - pos) - rest) != (len - pos) - rest) { + req->keep = 0; + return -1; + } + if (pad) { + open_packet(req, type); + memcpy(req->out_pos, str + len - rest, rest); + req->out_pos += rest; + } + } +#endif + return len; +} + +int fcgi_finish_request(fcgi_request *req) +{ + fcgi_flush(req, 1); + fcgi_close(req, 0, 1); + return 1; +} + +char* fcgi_getenv_helper(char** env, const char *name, int len) +{ + if (name && env) { + while (*env) { + if ((strncmp(name, *env, len) == 0) && ((*env)[len] == '=')) { + return *env+len+1; + } + env++; + } + } + return NULL; +} + +char* fcgi_getenv(fcgi_request *req, const char* var, int var_len) +{ + if (!req) return NULL; + return fcgi_getenv_helper(req->env, var, var_len); +} + +void fcgi_putenv(fcgi_request *req, char* var, int var_len) +{ + if (var && req) { + char **env = req->env; + char *s = strchr(var, '='); + int len; + + if (!s) return ; + len = s - var + 1; + while (*env) { + if ((strncmp(var, *env, len) == 0)) { + free(*env); + *env = fcgi_strndup(var, var_len); + return; + } + env++; + } + *env = fcgi_strndup(var, var_len); + } +} + +int FCGX_FPrintF(FCGX_Stream stream, const char *format, ...) +{ + int result; + va_list args; + char buf[4096]; + + va_start(args, format); + result = vsnprintf(buf, sizeof(buf), format, args); + va_end(args); + + fcgi_write(stream.req, stream.type, buf, result); + return result; +} + +#ifdef _WIN32 +void OS_SetImpersonate(void) +{ + char *os_name; + + os_name = getenv("OS"); + if (os_name && stricmp(os_name, "Windows_NT") == 0) { + is_impersonate = 1; + } +} +#endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/sapi/cgi/fastcgi.h b/sapi/cgi/fastcgi.h new file mode 100644 index 0000000000..7c910e1abb --- /dev/null +++ b/sapi/cgi/fastcgi.h @@ -0,0 +1,183 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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. | + +----------------------------------------------------------------------+ + | Authors: Dmitry Stogov | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +/* FastCGI protocol */ + +#define FCGI_VERSION_1 1 + +#define FCGI_MAX_LENGTH 0xffff + +#define FCGI_KEEP_CONN 1 + +typedef enum _fcgi_role { + FCGI_RESPONDER = 1, + FCGI_AUTHORIZER = 2, + FCGI_FILTER = 3 +} fcgi_role; + +typedef enum _fcgi_request_type { + FCGI_BEGIN_REQUEST = 1, /* [in] */ + FCGI_ABORT_REQUEST = 2, /* [in] (not supported) */ + FCGI_END_REQUEST = 3, /* [out] */ + FCGI_PARAMS = 4, /* [in] environment variables */ + FCGI_STDIN = 5, /* [in] post data */ + FCGI_STDOUT = 6, /* [out] response */ + FCGI_STDERR = 7, /* [out] errors */ + FCGI_DATA = 8, /* [in] filter data (not supported) */ + FCGI_GET_VALUES = 9, /* [in] */ + FCGI_GET_VALUES_RESULT = 10 /* [out] */ +} fcgi_request_type; + +typedef enum _fcgi_protocol_status { + FCGI_REQUEST_COMPLETE = 0, + FCGI_CANT_MPX_CONN = 1, + FCGI_OVERLOADED = 2, + FCGI_UNKNOWN_ROLE = 3 +} dcgi_protocol_status; + +typedef struct _fcgi_header { + unsigned char version; + unsigned char type; + unsigned char requestIdB1; + unsigned char requestIdB0; + unsigned char contentLengthB1; + unsigned char contentLengthB0; + unsigned char paddingLength; + unsigned char reserved; +} fcgi_header; + +typedef struct _fcgi_begin_request { + unsigned char roleB1; + unsigned char roleB0; + unsigned char flags; + unsigned char reserved[5]; +} fcgi_begin_request; + +typedef struct _fcgi_begin_request_rec { + fcgi_header hdr; + fcgi_begin_request body; +} fcgi_begin_request_rec; + +typedef struct _fcgi_end_request { + unsigned char appStatusB3; + unsigned char appStatusB2; + unsigned char appStatusB1; + unsigned char appStatusB0; + unsigned char protocolStatus; + unsigned char reserved[3]; +} fcgi_end_request; + +typedef struct _fcgi_end_request_rec { + fcgi_header hdr; + fcgi_end_request body; +} fcgi_end_request_rec; + +/* FastCGI client API */ + +typedef struct _fcgi_request { + int listen_socket; + int fd; + int id; + int keep; + + int in_len; + int in_pad; + + fcgi_header *out_hdr; + unsigned char *out_pos; + unsigned char out_buf[1024*8]; + unsigned char reserved[sizeof(fcgi_end_request_rec)]; + + char *env[128]; +} fcgi_request; + +int fcgi_init(void); +int fcgi_is_fastcgi(void); +int fcgi_listen(const char *path, int backlog); +void fcgi_init_request(fcgi_request *req, int listen_socket); +int fcgi_accept_request(fcgi_request *req); +int fcgi_finish_request(fcgi_request *req); + +char* fcgi_getenv(fcgi_request *req, const char* var, int var_len); +void fcgi_putenv(fcgi_request *req, char* var, int var_len); + +int fcgi_read(fcgi_request *req, char *str, int len); + +int fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int len); +int fcgi_flush(fcgi_request *req, int close); + +/* Some defines for limited libfcgi comatibility */ + +typedef struct _FCGX_Stream { + fcgi_request *req; + fcgi_request_type type; +} FCGX_Stream; + +typedef struct _FCGX_Request { + fcgi_request req; + FCGX_Stream in; + FCGX_Stream out; + FCGX_Stream err; + char **envp; +} FCGX_Request; + +#define FCGX_Init() +#define FCGX_IsCGI() (!fcgi_is_fastcgi()) +#define FCGX_OpenSocket(path, backlog) fcgi_listen(path, backlog) + +#define FCGX_InitRequest(r, sock, flags) \ + do { \ + fcgi_init_request(&(r)->req, sock); \ + (r)->in.req = &(r)->req; \ + (r)->out.req = &(r)->req; \ + (r)->err.req = &(r)->req; \ + (r)->in.type = FCGI_STDIN; \ + (r)->out.type = FCGI_STDOUT; \ + (r)->err.type = FCGI_STDERR; \ + (r)->envp = (r)->req.env; \ + } while (0); + + +#define FCGX_Accept_r(r) fcgi_accept_request(&(r)->req) +#define FCGX_Finish_r(r) fcgi_finish_request(&(r)->req) + +#define FCGX_PutStr(str, len, stream) fcgi_write((stream).req, (stream).type, str, len) +#define FCGX_PutS(str, len, stream) fcgi_write((stream).req, (stream).type, str, len) +#define FCGX_FFlush(stream) fcgi_flush((stream).req, 0) +#define FCGX_GetStr(str, len, stream) fcgi_read((stream).req, str, len) + +#define FCGX_GetParam(var, envp) fcgi_getenv_helper(envp, var, strlen(var)); + +#define FCGX_PutEnv(r, var) fcgi_putenv(&(r)->req, var, strlen(var)); + +int FCGX_FPrintF(FCGX_Stream stream, const char *format, ...); + +/* Internal helper functions. They shouldn't be used directly. */ + +char* fcgi_getenv_helper(char** env, const char *name, int len); + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ -- cgit v1.2.1