Compare commits

...
1 Commits
98 changed files with 6181 additions and 0 deletions

No files matched your search

+30
View File
@@ -0,0 +1,30 @@
--TEST--
Bug #36006 (Problem with $this in __destruct())
--FILE--
<?php
class Person {
public $dad;
public function __destruct() {
$this->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
+14
View File
@@ -0,0 +1,14 @@
--TEST--
Bug #36037 (heredoc adds extra line number)
--FILE--
<?php
echo __LINE__, "\n";
$x=<<<XXX
123
YYY;
XXX;
echo __LINE__, "\n";
?>
--EXPECT--
2
7
+13
View File
@@ -0,0 +1,13 @@
--TEST--
Bug #36071 (Engine Crash related with 'clone')
--INI--
error_reporting=4095
--FILE--
<?php
$a = clone 0;
$a[0]->b = 0;
echo "ok\n";
?>
--EXPECTF--
Warning: __clone method called on non-object in %sbug36071.php on line 2
ok
+14
View File
@@ -0,0 +1,14 @@
--TEST--
Bug #36268 (Object destructors called even after fatal errors)
--FILE--
<?php
class Foo {
function __destruct() {
echo "Ha!\n";
}
}
$x = new Foo();
bar();
?>
--EXPECTF--
Fatal error: Call to undefined function bar() in %sbug36268.php on line 8
+12
View File
@@ -0,0 +1,12 @@
--TEST--
Bug #36303 (foreach on error_zval produces segfault)
--FILE--
<?php
$x="test";
foreach($x->a->b as &$v) {
}
echo "ok\n";
?>
--EXPECTF--
Warning: Invalid argument supplied for foreach() in %sbug36303.php on line 3
ok
+22
View File
@@ -0,0 +1,22 @@
--TEST--
Bug #36513 (comment will be outputed in last line)
--FILE--
<?php
function test($s) {
echo "'".trim(str_replace("&nbsp;", " ", htmlspecialchars_decode(strip_tags(highlight_string($s,1)))))."'\n";
}
eval('echo "1";//2');
eval('echo 3; //{ 4?>5');
echo "\n";
//test('<?php echo "1";//');
test('<?php echo "1";//2');
test('<?php echo "1";//22');
test('<?php echo 3; // 4 ?>5');
?>
--EXPECT--
135
'<?php echo "1";//2'
'<?php echo "1";//22'
'<?php echo 3; // 4 ?>5'
+15
View File
@@ -0,0 +1,15 @@
--TEST--
Bug #36568 (memory_limit has no effect)
--SKIPIF--
<?php
if (!function_exists('memory_get_usage')) die('skip PHP is configured without memory_limit');
?>
--INI--
memory_limit=16M
--FILE--
<?php
ini_set("memory_limit", "32M");
echo ini_get("memory_limit");
?>
--EXPECT--
32M
+23
View File
@@ -0,0 +1,23 @@
--TEST--
Bug #37046 (foreach breaks static scope)
--FILE--
<?php
function s() {
static $storage = array(array('x', 'y'));
return $storage[0];
}
foreach (s() as $k => $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
+21
View File
@@ -0,0 +1,21 @@
--TEST--
Bug #37138 (__autoload tries to load callback'ed self and parent)
--FILE--
<?php
function __autoload ($CN) {var_dump ($CN);}
class st {
public static function e () {echo ("EHLO\n");}
public static function e2 () {call_user_func (array ('self', 'e'));}
}
class stch extends st {
public static function g () {call_user_func (array ('parent', 'e'));}
}
st::e ();
st::e2 ();
stch::g ();
?>
--EXPECT--
EHLO
EHLO
EHLO
+19
View File
@@ -0,0 +1,19 @@
--TEST--
zend_strtod() leaks on big doubles
--INI--
precision=14
--FILE--
<?php
var_dump("1139932690.21688500" - "1139932790.21688500");
var_dump("1139932690000.21688500" - "331139932790.21688500");
var_dump("339932690.21688500" - "4564645646456463461139932790.21688500");
var_dump("123123139932690.21688500" - "11399327900000000.21688500");
echo "Done\n";
?>
--EXPECTF--
float(-100)
float(808792757210)
float(-4.5646456464565E+27)
float(-11276204760067000)
Done
+22
View File
@@ -0,0 +1,22 @@
--TEST--
Bug #34272 (empty array onto COM object blows up)
--SKIPIF--
<?php
if (!extension_loaded("com_dotnet")) print "skip COM/.Net support not present"; ?>
--FILE--
<?php
error_reporting(E_ALL);
try {
$dict = new COM("Scripting.Dictionary");
$dict->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
+13
View File
@@ -0,0 +1,13 @@
--TEST--
Bug #36224 (date(DATE_ATOM) gives wrong resulsts)
--FILE--
<?php
date_default_timezone_set("Europe/Oslo");
echo date(DATE_ATOM, strtotime('2006-01-31T19:23:56Z')) . "\n";
echo date(DATE_ATOM, strtotime('2006-01-31T19:23:56')) . "\n";
?>
--EXPECT--
2006-01-31T20:23:56+01:00
2006-01-31T19:23:56+01:00
+14
View File
@@ -0,0 +1,14 @@
--TEST--
Bug #36510 (strtotime() fails to parse date strings with tabs)
--FILE--
<?php
date_default_timezone_set("UTC");
$t = 1140973388;
var_dump(strtotime("-2 hours", $t));
var_dump(strtotime("-2\thours", $t));
?>
--EXPECT--
int(1140966188)
int(1140966188)
+12
View File
@@ -0,0 +1,12 @@
--TEST--
Bug #36599 (DATE_W3C format constant incorrect).
--FILE--
<?php
date_default_timezone_set("UTC");
echo date( DATE_ATOM, strtotime( "2006-03-03 08:47:55" ) ), "\n";
echo date( DATE_W3C, strtotime( "2006-03-03 08:47:55" ) ), "\n";
?>
--EXPECT--
2006-03-03T08:47:55+00:00
2006-03-03T08:47:55+00:00
+12
View File
@@ -0,0 +1,12 @@
--TEST--
Bug #36988 (mktime freezes on long numbers)
--INI--
date.timezone=GMT
--FILE--
<?php
$start = microtime(true);
$a = mktime(1, 1, 1, 1, 1, 11111111111);
echo (microtime(true) - $start) < 1 ? "smaller than one second" : "more than a second";
?>
--EXPECT--
smaller than one second
+16
View File
@@ -0,0 +1,16 @@
--TEST--
Bug #37017 (strtotime fails before 13:00:00 with some time zones identifiers).
--INI--
date.timezone=GMT
--FILE--
<?php
echo strtotime("2006-05-12 13:00:01 America/New_York"), "\n";
echo strtotime("2006-05-12 13:00:00 America/New_York"), "\n";
echo strtotime("2006-05-12 12:59:59 America/New_York"), "\n";
echo strtotime("2006-05-12 12:59:59 GMT"), "\n";
?>
--EXPECT--
1147453201
1147453200
1147453199
1147438799
+34
View File
@@ -0,0 +1,34 @@
--TEST--
Bug #36436 DBA problem with Berkeley DB4
--SKIPIF--
<?php
$handler = 'db4';
require_once('skipif.inc');
?>
--FILE--
<?php
$handler = 'db4';
require_once('test.inc');
$db = dba_popen($db_filename, 'c', 'db4');
dba_insert('X', 'XYZ', $db);
dba_insert('Y', '123', $db);
var_dump($db, dba_fetch('X', $db));
var_dump(dba_firstkey($db));
var_dump(dba_nextkey($db));
dba_close($db);
unlink($db_filename);
?>
===DONE===
--EXPECTF--
resource(%d) of type (dba persistent)
string(3) "XYZ"
string(1) "X"
string(1) "Y"
===DONE===
+35
View File
@@ -0,0 +1,35 @@
--TEST--
Bug #36756: (DOMDocument::removeChild corrupts node)
--SKIPIF--
<?php require_once('skipif.inc'); ?>
--FILE--
<?php
/* Node is preserved from removeChild */
$dom = new DOMDocument();
$dom->loadXML('<root><child/></root>');
$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('<root><child/></root>');
$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:
+99
View File
@@ -0,0 +1,99 @@
--TEST--
Test 7: DTD tests
--SKIPIF--
<?php
require_once('skipif.inc');
?>
--FILE--
<?php
$xml = <<< EOXML
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE courses [
<!ELEMENT courses (course+)>
<!ELEMENT course (title, description, temp*)>
<!ATTLIST course cid ID #REQUIRED>
<!ELEMENT title (#PCDATA)>
<!ELEMENT description (#PCDATA)>
<!ELEMENT temp (#PCDATA)>
<!ATTLIST temp vid ID #REQUIRED>
<!ENTITY test 'http://www.hpl.hp.com/semweb/2003/query_tester#'>
<!ENTITY rdf 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'>
<!NOTATION GIF PUBLIC "-" "image/gif">
<!ENTITY myimage PUBLIC "-" "mypicture.gif" NDATA GIF>
]>
<courses>
<course cid="c1">
<title>Basic Languages</title>
<description>Introduction to Languages</description>
</course>
<course cid="c6">
<title>French I</title>
<description>Introduction to French</description>
<temp vid="c7">
</temp>
</course>
</courses>
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
+31
View File
@@ -0,0 +1,31 @@
--TEST--
Bug #36697 (TrueColor transparency with GIF palette output).
--SKIPIF--
<?php
if (!extension_loaded('gd')) {
die("skip gd extension not available\n");
}
if (!GD_BUNDLED) {
die('skip external GD libraries may fail');
}
?>
--FILE--
<?php
$dest = dirname(__FILE__) . "/36697.gif";
$im = imagecreatetruecolor(192, 36);
$trans_color = imagecolorallocate($im, 255, 0, 0);
$color = imagecolorallocate($im, 255, 255, 255);
imagecolortransparent($im, $trans_color);
imagefilledrectangle($im, 0,0, 192,36, $trans_color);
$c = imagecolorat($im, 191,35);
imagegif($im, $dest);
imagedestroy($im);
$im = imagecreatefromgif($dest);
$c = imagecolorat($im, 191, 35);
$colors = imagecolorsforindex($im, $c);
echo $colors['red'] . ' ' . $colors['green'] . ' ' . $colors['blue'];
@unlink($dest);
?>
--EXPECT--
255 0 0
+25
View File
@@ -0,0 +1,25 @@
--TEST--
bug #36420 (segfault when access result->num_rows after calling result->close())
--SKIPIF--
<?php require_once('skipif.inc'); ?>
--FILE--
<?php
include "connect.inc";
$mysqli = mysqli_connect($host, $user, $passwd);
$result = $mysqli->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
+23
View File
@@ -0,0 +1,23 @@
--TEST--
bug #36745 : LOAD DATA LOCAL INFILE doesn't return correct error message
--SKIPIF--
<?php require_once('skipif.inc'); ?>
--FILE--
<?php
include ("connect.inc");
/*** test mysqli_connect 127.0.0.1 ***/
$mysql = mysqli_connect($host, $user, $passwd, "test");
$mysql->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
+42
View File
@@ -0,0 +1,42 @@
--TEST--
bug #36802 : crashes with mysql_init
--SKIPIF--
<?php require_once('skipif.inc'); ?>
--FILE--
<?php
class my_mysqli extends mysqli {
function __construct()
{
}
}
include "connect.inc";
$mysql = mysqli_init();
/* following operations should not work */
$x[0] = @$mysql->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)
}
+38
View File
@@ -0,0 +1,38 @@
--TEST--
bind LONG field
--SKIPIF--
<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
--FILE--
<?php
require dirname(__FILE__)."/connect.inc";
$stmt = oci_parse($c, "create table phptestlng( id number(10), fileimage long)");
oci_execute($stmt);
$stmt = oci_parse ($c, "insert into phptestlng (id, fileimage) values (:id, :fileimage)");
$i=1;
$fileimage = file_get_contents( dirname(__FILE__)."/test.gif");
oci_bind_by_name( $stmt, ":id", $i, -1);
oci_bind_by_name( $stmt, ":fileimage", $fileimage, -1, SQLT_LNG);
oci_execute($stmt, OCI_DEFAULT);
oci_commit($c);
$stmt = oci_parse($c, "SELECT fileimage FROM phptestlng");
oci_execute($stmt);
$row = oci_fetch_row($stmt);
var_dump(md5($row[0]));
var_dump(strlen($row[0]));
$stmt = oci_parse($c, "drop table phptestlng");
oci_execute($stmt);
echo "Done\n";
?>
--EXPECT--
string(32) "d04e7036e2f4221abc88fd14e960a45b"
int(2523)
Done
+38
View File
@@ -0,0 +1,38 @@
--TEST--
bind LONG RAW field
--SKIPIF--
<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
--FILE--
<?php
require dirname(__FILE__)."/connect.inc";
$stmt = oci_parse($c, "create table phptestlngraw( id number(10), fileimage long raw)");
oci_execute($stmt);
$stmt = oci_parse ($c, "insert into phptestlngraw (id, fileimage) values (:id, :fileimage)");
$i=1;
$fileimage = file_get_contents( dirname(__FILE__)."/test.gif");
oci_bind_by_name( $stmt, ":id", $i, -1);
oci_bind_by_name( $stmt, ":fileimage", $fileimage, -1, SQLT_LBI);
oci_execute($stmt, OCI_DEFAULT);
oci_commit($c);
$stmt = oci_parse($c, "SELECT fileimage FROM phptestlngraw");
oci_execute($stmt);
$row = oci_fetch_row($stmt);
var_dump(md5($row[0]));
var_dump(strlen($row[0]));
$stmt = oci_parse($c, "drop table phptestlngraw");
oci_execute($stmt);
echo "Done\n";
?>
--EXPECT--
string(32) "614fcbba1effb7caa27ef0ef25c27fcf"
int(2523)
Done
+39
View File
@@ -0,0 +1,39 @@
--TEST--
bind RAW field
--SKIPIF--
<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
--FILE--
<?php
require dirname(__FILE__)."/connect.inc";
$stmt = oci_parse($c, "create table phptestrawtable( id number(10), fileimage raw(1000))");
oci_execute($stmt);
$stmt = oci_parse ($c, "insert into phptestrawtable (id, fileimage) values (:id, :fileimage)");
$i=1;
$fileimage = file_get_contents( dirname(__FILE__)."/test.gif");
$fileimage = substr($fileimage, 0, 300);
oci_bind_by_name( $stmt, ":id", $i, -1);
oci_bind_by_name( $stmt, ":fileimage", $fileimage, -1, SQLT_BIN);
oci_execute($stmt, OCI_DEFAULT);
oci_commit($c);
$stmt = oci_parse($c, "SELECT fileimage FROM phptestrawtable");
oci_execute($stmt);
$row = oci_fetch_row($stmt);
var_dump(md5($row[0]));
var_dump(strlen($row[0]));
$stmt = oci_parse($c, "drop table phptestrawtable");
oci_execute($stmt);
echo "Done\n";
?>
--EXPECT--
string(32) "88b274d7a257ac6f70435b83abd4e26e"
int(300)
Done
+26
View File
@@ -0,0 +1,26 @@
--TEST--
bug #36010 (Crash when executing SQL statment with lob parameter twice)
--SKIPIF--
<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
--FILE--
<?php
require dirname(__FILE__).'/connect.inc';
function f($conn)
{
$sql = "begin :p_clob := 'lob string'; end;";
$stid = oci_parse($conn, $sql);
$clob = oci_new_descriptor($conn, OCI_D_LOB);
oci_bind_by_name($stid, ":p_clob", $clob, -1, OCI_B_CLOB);
$r = oci_execute($stid, OCI_DEFAULT);
}
f($c);
f($c);
echo "Done\n";
?>
--EXPECT--
Done
+28
View File
@@ -0,0 +1,28 @@
--TEST--
Bug #36096 (oci_result() returns garbage after oci_fetch() failed)
--SKIPIF--
<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
--FILE--
<?php
require dirname(__FILE__)."/connect.inc";
$sql = "SELECT 'ABC' FROM DUAL WHERE 1<>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
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

+466
View File
@@ -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 */
+175
View File
@@ -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 */
+171
View File
@@ -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 <stdlib.h> // for NULL
#include <string>
namespace pcrecpp {
class StringPiece;
// Hex/Octal/Binary?
// Special class for parsing into objects that define a ParseFrom() method
template <class T>
class _RE_MatchObject {
public:
static inline bool Parse(const char* str, int n, void* dest) {
T* object = reinterpret_cast<T*>(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 <class T> Arg(T*, Parser parser);
// Generic constructor template
template <class T> Arg(T* p)
: arg_(p), parser_(_RE_MatchObject<T>::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 */
+45
View File
@@ -0,0 +1,45 @@
--TEST--
PDO Common: PHP Bug #35671: binding by name breakage
--SKIPIF--
<?php # vim:ft=php
if (!extension_loaded('pdo')) die('skip');
$dir = getenv('REDIR_TEST_DIR');
if (false == $dir) die('skip no driver');
require_once $dir . 'pdo_test.inc';
PDOTest::skip();
?>
--FILE--
<?php
if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.dirname(__FILE__) . '/../../pdo/tests/');
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();
$db->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"
}
}
+23
View File
@@ -0,0 +1,23 @@
--TEST--
Bug #36727 (segfault in bindValue() when no parameters are defined)
--SKIPIF--
<?php
if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
require dirname(__FILE__) . '/config.inc';
PDOTest::skip();
?>
--FILE--
<?php
require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
require dirname(__FILE__) . '/config.inc';
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
$stmt = $db->prepare('SELECT * FROM child');
var_dump($stmt->bindValue(':test', 1, PDO::PARAM_INT));
echo "Done\n";
?>
--EXPECT--
bool(false)
Done
+49
View File
@@ -0,0 +1,49 @@
--TEST--
Bug #36625 (pg_trace() does not work)
--SKIPIF--
<?php
require_once('skipif.inc');
?>
--FILE--
<?php
require_once('config.inc');
$dbh = @pg_connect($conn_str);
if (!$dbh) {
die ('Could not connect to the server');
}
$tracefile = dirname(__FILE__) . '/trace.tmp';
@unlink($tracefile);
var_dump(file_exists($tracefile));
pg_trace($tracefile, 'w', $dbh);
$res = pg_query($dbh, 'select 1');
var_dump($res);
pg_close($dbh);
$found = 0;
function search_trace_file($line)
{
if (strpos($line, '"select 1"') !== false || strpos($line, "'select 1'") !== false) {
$GLOBALS['found']++;
}
}
$trace = file($tracefile);
array_walk($trace, 'search_trace_file');
var_dump($found > 0);
var_dump(file_exists($tracefile));
?>
===DONE===
--CLEAN--
<?php unlink($tracefile); ?>
--EXPECTF--
bool(false)
resource(%d) of type (pgsql result)
bool(true)
bool(true)
===DONE===
+162
View File
@@ -0,0 +1,162 @@
--TEST--
ReflectionClass::newInstance[Args]
--SKIPIF--
<?php extension_loaded('reflection') or die('skip'); ?>
--FILE--
<?php
function test($class)
{
echo "====>$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===
<?php exit(0); ?>
--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===
+41
View File
@@ -0,0 +1,41 @@
--TEST--
Reflection Bug #29986 (Class constants won't work with predefined constants when using ReflectionClass)
--SKIPIF--
<?php extension_loaded('reflection') or die('skip'); ?>
--FILE--
<?php
class just_constants
{
const BOOLEAN_CONSTANT = true;
const NULL_CONSTANT = null;
const STRING_CONSTANT = 'This is a string';
const INTEGER_CONSTANT = 1000;
const FLOAT_CONSTANT = 3.14159265;
}
Reflection::export(new ReflectionClass('just_constants'));
?>
--EXPECTF--
Class [ <user> 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] {
}
}
+22
View File
@@ -0,0 +1,22 @@
--TEST--
Reflection Bug #36308 (ReflectionProperty::getDocComment() does not reflect extended class commentary)
--SKIPIF--
<?php extension_loaded('reflection') or die('skip'); ?>
--FILE--
<?php
class Base {
/** Base comment block */
public $foo = 'bar';
}
class Extended extends Base {
/** Extended commentary */
public $foo = 'zim';
}
$reflect = new ReflectionClass('Extended');
$props = $reflect->getProperties();
echo $props[0]->getDocComment();
?>
--EXPECT--
/** Extended commentary */
+30
View File
@@ -0,0 +1,30 @@
--TEST--
Reflection Bug #36337 (ReflectionProperty fails to return correct visibility)
--SKIPIF--
<?php extension_loaded('reflection') or die('skip'); ?>
--FILE--
<?php
abstract class enum {
protected $_values;
public function __construct() {
$property = new ReflectionProperty(get_class($this),'_values');
var_dump($property->isProtected());
}
}
final class myEnum extends enum {
public $_values = array(
0 => 'No value',
);
}
$x = new myEnum();
echo "Done\n";
?>
--EXPECT--
bool(false)
Done
+33
View File
@@ -0,0 +1,33 @@
--TEST--
Reflection Bug #36434 (Properties from parent class fail to indetify their true origin)
--SKIPIF--
<?php extension_loaded('reflection') or die('skip'); ?>
--FILE--
<?php
class ancester
{
public $ancester = 0;
function ancester()
{
return $this->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
+209
View File
@@ -0,0 +1,209 @@
--TEST--
ReflectionParameter::getClass(), getDeclaringClass(), getDeclaringFunction()
--SKIPIF--
<?php extension_loaded('reflection') or die('skip'); ?>
--FILE--
<?php
function test($nix, Array $ar, &$ref, stdClass $std, NonExistingClass $na, stdClass &$opt = NULL, $def = "FooBar")
{
}
class test
{
function test($nix, Array $ar, &$ref, stdClass $std, NonExistingClass $na, stdClass $opt = NULL, $def = "FooBar")
{
}
}
function check_params_decl_func($r, $f)
{
$c = $r->$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===
<?php exit(0); ?>
--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===
+41
View File
@@ -0,0 +1,41 @@
--TEST--
bug #31454 (Incorrect adding PHPSESSID to links, which contains \r\n)
--SKIPIF--
<?php include('skipif.inc'); ?>
--FILE--
<?php
error_reporting(E_ALL);
ini_set('session.use_trans_sid', 1);
ini_set('session.use_cookies', 0);
ini_set('session.name', 'sid');
session_start();
# Do not remove \r from this tests, they are essential!
?>
<html>
<head>
<title>Bug #36459 Incorrect adding PHPSESSID to links, which contains \r\n</title>
</head>
<body>
<p>See source html code</p>
<a href="/b2w/www/ru/adm/pages/?action=prev&rec_id=8&pid=2"
style="font: normal 11pt Times New Roman">incorrect link</a><br />
<br />
<a href="/b2w/www/ru/adm/pages/?action=prev&rec_id=8&pid=2" style="font: normal 11pt Times New Roman">correct link</a>
</body>
</html>
--EXPECTF--
<html>
<head>
<title>Bug #36459 Incorrect adding PHPSESSID to links, which contains \r\n</title>
</head>
<body>
<p>See source html code</p>
<a href="/b2w/www/ru/adm/pages/?action=prev&rec_id=8&pid=2&sid=%s"
style="font: normal 11pt Times New Roman">incorrect link</a><br />
<br />
<a href="/b2w/www/ru/adm/pages/?action=prev&rec_id=8&pid=2&sid=%s" style="font: normal 11pt Times New Roman">correct link</a>
</body>
</html>
+35
View File
@@ -0,0 +1,35 @@
--TEST--
SimpleXML: foreach
--SKIPIF--
<?php if (!extension_loaded("simplexml")) print "skip"; ?>
--FILE--
<?php
$sxe = simplexml_load_string(<<<EOF
<?xml version='1.0'?>
<!DOCTYPE sxe SYSTEM "notfound.dtd">
<sxe id="elem1">
Plain text.
<elem1 attr1='first'>Bla bla 1.<!-- comment --><elem2>
Here we have some text data.
</elem2></elem1>
<elem11 attr2='second'>Bla bla 2.</elem11>
</sxe>
EOF
);
var_dump($sxe->children());
?>
===DONE===
<?php exit(0); ?>
--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===
+40
View File
@@ -0,0 +1,40 @@
--TEST--
SimpleXML: getName()
--SKIPIF--
<?php if (!extension_loaded("simplexml")) print "skip"; ?>
--FILE--
<?php
$xml =<<<EOF
<people>
<person>Jane</person>
</people>
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."</$name>\n";
}
$people = simplexml_load_string($xml);
traverse_xml($people);
?>
===DONE===
--EXPECTF--
<people>
<person>Jane
</person>
</people>
===DONE===
+74
View File
@@ -0,0 +1,74 @@
--TEST--
SimpleXML: Adding an elements
--SKIPIF--
<?php if (!extension_loaded("simplexml")) print "skip"; ?>
--FILE--
<?php
$xml =<<<EOF
<people></people>
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."</$name>\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--
<people>
</people>
<people>
<person gender="male">Joe
</person>
</people>
<people>
<person gender="male">Jane
</person>
</people>
<people>
<person gender="female">Jane
</person>
<person gender="male">Joe
</person>
</people>
Warning: main(): Cannot add element person number 3 when only 2 such elements exist in %s027.php on line %d
<people>
<person gender="female">Jane
</person>
<person gender="male">Joe
</person>
<person gender="male">Minni-me
</person>
</people>
Fatal error: Objects used as arrays in post/pre increment/decrement must return values by reference in %s027.php on line %d
+42
View File
@@ -0,0 +1,42 @@
--TEST--
SimpleXML: Adding an elements without text
--SKIPIF--
<?php if (!extension_loaded("simplexml")) print "skip"; ?>
--FILE--
<?php
$xml =<<<EOF
<people></people>
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."</$name>\n";
}
$people = simplexml_load_string($xml);
traverse_xml($people);
$people->person['name'] = 'John';
traverse_xml($people);
?>
===DONE===
--EXPECTF--
<people>
</people>
<people>
<person name="John">
</person>
</people>
===DONE===
+40
View File
@@ -0,0 +1,40 @@
--TEST--
SimpleXML: foreach and count
--SKIPIF--
<?php if (!extension_loaded("simplexml")) print "skip"; ?>
--FILE--
<?php
$xml =<<<EOF
<people>
<person name="Joe"/>
<person name="John">
<children>
<person name="Joe"/>
</children>
</person>
<person name="Jane"/>
</people>
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===
+44
View File
@@ -0,0 +1,44 @@
--TEST--
SimpleXML: isset and unset by offset
--SKIPIF--
<?php if (!extension_loaded("simplexml")) print "skip"; ?>
--FILE--
<?php
$xml =<<<EOF
<root s:att1="b" att1="a"
xmlns:s="urn::test" xmlns:t="urn::test-t">
<child1>test</child1>
<child1>test 2</child1>
<s:child3 />
</root>
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===
+57
View File
@@ -0,0 +1,57 @@
--TEST--
SimpleXML: addChild and addAttribute
--SKIPIF--
<?php if (!extension_loaded("simplexml")) print "skip"; ?>
--FILE--
<?php
$xml =<<<EOF
<root s:att1="b" att1="a"
xmlns:s="urn::test" xmlns:t="urn::test-t">
<child1>test</child1>
<child1>test 2</child1>
<s:child3 />
</root>
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
<?xml version="1.0"?>
<root xmlns:s="urn::test" xmlns:t="urn::test-t" xmlns:v="urn::test-v" s:att1="b" att1="a" v:att11="xxx" att2="no-ns">
<child1>test</child1>
<child1>test 2</child1>
<s:child3/>
<s:test1>myval</s:test1><m:test2 xmlns:m="urn::testnew">myval</m:test2><test3 xmlns="urn::testnew">myval</test3><test4>myval</test4><test5>myval</test5></root>
===DONE===
+45
View File
@@ -0,0 +1,45 @@
--TEST--
SimpleXML: comparing instances
--SKIPIF--
<?php if (!extension_loaded("simplexml")) print "skip"; ?>
--FILE--
<?php
$xml =<<<EOF
<people>
<person name="Joe"/>
<person name="John">
<children>
<person name="Joe"/>
</children>
</person>
<person name="Jane"/>
</people>
EOF;
$xml1 =<<<EOF
<people>
<person name="John">
<children>
<person name="Joe"/>
</children>
</person>
<person name="Jane"/>
</people>
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===
+137
View File
@@ -0,0 +1,137 @@
--TEST--
SimpleXML: casting instances
--SKIPIF--
<?php if (!extension_loaded("simplexml")) print "skip"; ?>
--FILE--
<?php
$xml =<<<EOF
<people>
test
<person name="Joe"/>
<person name="John">
<children>
<person name="Joe"/>
</children>
</person>
<person name="Jane"/>
</people>
EOF;
$foo = simplexml_load_string( "<foo />" );
$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===
+28
View File
@@ -0,0 +1,28 @@
--TEST--
Bug #36611 (assignment to SimpleXML object attribute changes argument type to string)
--FILE--
<?php
$xml_str = <<<EOD
<?xml version="1.0" encoding="ISO-8859-1" ?>
<c_fpobel >
<pos >
<pos/>
</pos>
</c_fpobel>
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
+139
View File
@@ -0,0 +1,139 @@
--TEST--
Bug #36226 SOAP Inconsistent handling when passing potential arrays.
--SKIPIF--
<?php require_once('skipif.inc'); ?>
--INI--
soap.wsdl_cache_enabled=0
--FILE--
<?php
ini_set("soap.wsdl_cache_enabled",0);
$timestamp = "2005-11-08T11:22:07+03:00";
$wsdl = dirname(__FILE__)."/bug35142.wsdl";
function PostEvents($x) {
var_dump($x);
exit();
return $x;
}
class TestSoapClient extends SoapClient {
function __construct($wsdl, $options) {
parent::__construct($wsdl, $options);
$this->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--
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://testurl/Message"><SOAP-ENV:Body><ns1:ivrEvents version="1.0" activityId="101" messageId="12345" source="IVR"><ns1:logOffEvent audienceMemberId="34567" timestamp="2005-11-08T11:22:07+03:00" smokeStatus="Smoked" callInitiator="IVR"/><ns1:logOffEvent audienceMemberId="34568" timestamp="2005-11-08T11:22:07+03:00" smokeStatus="SmokeFree" callInitiator="IVR"/><ns1:logOnEvent audienceMemberId="34567" timestamp="2005-11-08T11:22:07+03:00"/></ns1:ivrEvents></SOAP-ENV:Body></SOAP-ENV:Envelope>
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"
}
}
}
+52
View File
@@ -0,0 +1,52 @@
--TEST--
Bug #36575 (Incorrect complex type instantiation with hierarchies)
--SKIPIF--
<?php require_once('skipif.inc'); ?>
--INI--
soap.wsdl_cache_enabled=0
--FILE--
<?php
abstract class CT_A1 {
public $var1;
}
class CT_A2 extends CT_A1 {
public $var2;
}
class CT_A3 extends CT_A2 {
public $var3;
}
// returns A2 in WSDL
function test( $a1 ) {
$a3 = new CT_A3();
$a3->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--
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:test.soap#" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns2="urn:test.soap.types#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:test><a1 xsi:type="ns2:A2"><var1 xsi:type="xsd:string">one</var1><var2 xsi:type="xsd:string">two</var2></a1></ns1:test></SOAP-ENV:Body></SOAP-ENV:Envelope>
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:test.soap#" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns2="urn:test.soap.types#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:testResponse><result xsi:type="ns2:A3"><var1 xsi:type="xsd:string">one</var1><var2 xsi:type="xsd:string">var two</var2><var3 xsi:type="xsd:string">var three</var3></result></ns1:testResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
ok
+87
View File
@@ -0,0 +1,87 @@
<?xml version="1.0" encoding="utf-8"?>
<definitions name="shoppingcart"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="urn:test.soap#" targetNamespace="urn:test.soap#"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:types="urn:test.soap.types#">
<!-- all datatypes will be imported to namespace types: -->
<types>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:soap = "http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="urn:test.soap.types#"
targetNamespace="urn:test.soap.types#">
<xs:complexType name="A1">
<xs:all>
<xs:element name="var1" type="xs:string" nillable="true"/>
</xs:all>
</xs:complexType>
<xs:complexType name="A2">
<xs:complexContent>
<xs:extension base="tns:A1">
<xs:all>
<xs:element name="var2" type="xs:string" nillable="true"/>
</xs:all>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="A3">
<xs:complexContent>
<xs:extension base="tns:A2">
<xs:all>
<xs:element name="var3" type="xs:string" nillable="true"/>
</xs:all>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
</types>
<message name="test-request">
<part name="a1" type="types:A1"/>
</message>
<message name="test-response">
<part name="result" type="types:A2"/>
</message>
<portType name="catalog-porttype">
<operation name="test" parameterOrder="a1">
<input name="test-request" message="tns:test-request"/>
<output name="test-response" message="tns:test-response"/>
</operation>
</portType>
<!-- @type doesn't like tns: -->
<binding name="catalog-binding" type="tns:catalog-porttype">
<soap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="test">
<soap:operation soapAction="urn:test.soap#test"/>
<input>
<soap:body use="encoded" namespace="urn:test.soap#"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output>
<soap:body use="encoded" namespace="urn:test.soap#"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>
</binding>
<service name="catalog">
<!-- @binding doesn't like to be tns: -->
<port name="catalog-port" binding="tns:catalog-binding">
<soap:address location="xxxxxxxx"/>
</port>
</service>
</definitions>
+13
View File
@@ -0,0 +1,13 @@
--TEST--
Bug #36614 (Segfault when using Soap)
--SKIPIF--
<?php require_once('skipif.inc'); ?>
--INI--
soap.wsdl_cache_enabled=0
--FILE--
<?php
$lo_soap = new SoapClient(dirname(__FILE__)."/bug36614.wsdl");
echo "ok\n";
?>
--EXPECT--
ok
+204
View File
@@ -0,0 +1,204 @@
<?xml version="1.0" encoding="UTF-8" ?>
<definitions name="SonicMobile Web-Services"
targetNamespace="http://soap.sonicmobile.com/sonicmobile.wsdl"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:sonic="http://soap.sonicmobile.com/sonicmobile.wsdl"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<types>
<xsd:schema xmlns="http://www.w3.org/2000/10/XMLSchema">
<import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
<complexType name="TransportCount">
<all>
<element name="transport" type="string" />
<element name="count" type="integer" />
<element name="rate" type="integer" />
<element name="last_message" type="integer" />
</all>
</complexType>
<complexType name="ArrayOfTransportCount">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" arrayType="TransportCount[]" />
</restriction>
</complexContent>
</complexType>
</xsd:schema>
</types>
<message name="userSendMessageRequest">
<part name="sourceUser" type="xsd:int"/>
<part name="password" type="xsd:string"/>
<part name="destinationUser" type="xsd:int"/>
<part name="content" type="xsd:string"/>
<part name="sendRepliesTo" type="xsd:string"/>
<part name="reference" type="xsd:string"/>
</message>
<message name="sendMessageRequest">
<part name="application" type="xsd:string"/>
<part name="password" type="xsd:string"/>
<part name="destination" type="xsd:string"/>
<part name="content" type="xsd:string"/>
<part name="reference" type="xsd:string"/>
<part name="requestSource" type="xsd:string"/>
<part name="customer" type="xsd:string"/>
<part name="class" type="xsd:string"/>
</message>
<message name="MessageResponse">
<part name="messageid" type="xsd:int"/>
<part name="response" type="xsd:string"/>
</message>
<message name="messageCountRequest">
<part name="password" type="xsd:string"/>
</message>
<message name="messageCountResponse">
<part name="transports" type="tns:ArrayOfTransportCount"/>
</message>
<message name="serverStatusRequest">
<part name="password" type="xsd:string"/>
</message>
<message name="serverStatusResponse">
<part name="status_string" type="xsd:string"/>
</message>
<message name="flushGatewayRequest">
<part name="password" type="xsd:string"/>
</message>
<message name="flushGatewayResponse">
<part name="status_string" type="xsd:string"/>
</message>
<portType name="SonicMobilePortType">
<operation name="userSendMessage">
<input message="sonic:userSendMessageRequest"/>
<output message="sonic:MessageResponse"/>
</operation>
<operation name="sendMessage">
<input message="sonic:sendMessageRequest"/>
<output message="sonic:MessageResponse"/>
</operation>
<operation name="messageCount">
<input message="sonic:messageCountRequest"/>
<output message="sonic:messageCountResponse"/>
</operation>
<operation name="serverStatus">
<input message="sonic:serverStatusRequest"/>
<output message="sonic:serverStatusResponse"/>
</operation>
<operation name="flushGateway">
<input message="sonic:flushGatewayRequest"/>
<output message="sonic:flushGatewayResponse"/>
</operation>
</portType>
<binding name="SonicMobileBinding" type="sonic:SonicMobilePortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
<operation name="userSendMessage">
<soap:operation soapAction="http://soap.sonicmobile.com/SonicMobile/SOAP#userSendMessage"/>
<input>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://soap.sonicmobile.com/SonicMobile/SOAP"
use="encoded" />
</input>
<output>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://soap.sonicmobile.com/SonicMobile/SOAP"
use="encoded" />
</output>
</operation>
<operation name="sendMessage">
<soap:operation soapAction="http://soap.sonicmobile.com/SonicMobile/SOAP#sendMessage"/>
<input>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://soap.sonicmobile.com/SonicMobile/SOAP"
use="encoded" />
</input>
<output>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://soap.sonicmobile.com/SonicMobile/SOAP"
use="encoded" />
</output>
</operation>
<operation name="messageCount">
<soap:operation soapAction="http://soap.sonicmobile.com/SonicMobile/SOAP#messageCount"/>
<input>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://soap.sonicmobile.com/SonicMobile/SOAP"
use="encoded" />
</input>
<output>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://soap.sonicmobile.com/SonicMobile/SOAP"
use="encoded" />
</output>
</operation>
<operation name="serverStatus">
<soap:operation soapAction="http://soap.sonicmobile.com/SonicMobile/SOAP#serverStatus"/>
<input>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://soap.sonicmobile.com/SonicMobile/SOAP"
use="encoded" />
</input>
<output>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://soap.sonicmobile.com/SonicMobile/SOAP"
use="encoded" />
</output>
</operation>
<operation name="flushGateway">
<soap:operation soapAction="http://soap.sonicmobile.com/SonicMobile/SOAP#flushGateway"/>
<input>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://soap.sonicmobile.com/SonicMobile/SOAP"
use="encoded" />
</input>
<output>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://soap.sonicmobile.com/SonicMobile/SOAP"
use="encoded" />
</output>
</operation>
</binding>
<service name="SonicMobile">
<port name="SonicMobilePort" binding="sonic:SonicMobileBinding">
<soap:address location="http://soap.sonicmobile.com/"/>
</port>
</service>
</definitions>
+53
View File
@@ -0,0 +1,53 @@
--TEST--
Bug #36629 (SoapServer::handle() exits on SOAP faults)
--SKIPIF--
<?php require_once('skipif.inc'); ?>
--FILE--
<?php
function test1() {
throw new SoapFault("Server", "test1");
}
function test2() {
return new SoapFault("Server", "test2");
}
$server = new soapserver(null,array('uri'=>"http://testuri.org"));
$server->addfunction(array("test1","test2"));
$HTTP_RAW_POST_DATA = <<<EOF
<?xml version="1.0" encoding="ISO-8859-1"?>
<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:si="http://soapinterop.org/xsd">
<SOAP-ENV:Body>
<ns1:test1 xmlns:ns1="http://testuri.org" />
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
EOF;
$server->handle();
$HTTP_RAW_POST_DATA = <<<EOF
<?xml version="1.0" encoding="ISO-8859-1"?>
<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:si="http://soapinterop.org/xsd">
<SOAP-ENV:Body>
<ns1:test2 xmlns:ns1="http://testuri.org" />
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
EOF;
$server->handle();
echo "ok\n";
?>
--EXPECT--
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>SOAP-ENV:Server</faultcode><faultstring>test1</faultstring></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>SOAP-ENV:Server</faultcode><faultstring>test2</faultstring></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>
ok
+54
View File
@@ -0,0 +1,54 @@
--TEST--
SOAP Classmap 3: encoding of inherited objects
--SKIPIF--
<?php require_once('skipif.inc'); ?>
--FILE--
<?php
ini_set("soap.wsdl_cache_enabled",0);
class A {
public $x;
function __construct($a){
$this->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
)
+51
View File
@@ -0,0 +1,51 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- WSDL file generated by Zend Studio. -->
<definitions name="ab" targetNamespace="urn:ab" xmlns:typens="urn:ab" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<xsd:schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:ab">
<xsd:complexType name="A">
<xsd:sequence>
<xsd:element name="x" type="xsd:anyType"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="B">
<xsd:complexContent>
<xsd:extension base="typens:A">
<xsd:sequence>
<xsd:element name="y" type="xsd:anyType"/>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:schema>
</types>
<message name="f"/>
<message name="fResponse">
<part name="fReturn" type="typens:A"/>
</message>
<portType name="abServerPortType">
<operation name="f">
<input message="typens:f"/>
<output message="typens:fResponse"/>
</operation>
</portType>
<binding name="abServerBinding" type="typens:abServerPortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="f">
<soap:operation soapAction="urn:abServerAction"/>
<input>
<soap:body namespace="urn:ab" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output>
<soap:body namespace="urn:ab" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>
</binding>
<service name="abService">
<port name="abServerPort" binding="typens:abServerBinding">
<soap:address location="http://localhost/abServer.php"/>
</port>
</service>
</definitions>
+37
View File
@@ -0,0 +1,37 @@
--TEST--
SOAP Server 23: Send SOAP headers those were not received
--SKIPIF--
<?php require_once('skipif.inc'); ?>
--FILE--
<?php
function test() {
global $server;
$server->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
<?xml version="1.0" encoding="ISO-8859-1"?>
<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:si="http://soapinterop.org/xsd">
<SOAP-ENV:Body>
<ns1:test xmlns:ns1="http://testuri.org"/>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
EOF;
$server->handle();
echo "ok\n";
?>
--EXPECT--
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://testuri.org" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Header><ns1:Test1>Hello Header!</ns1:Test1><ns1:Test2>Hello Header!</ns1:Test2></SOAP-ENV:Header><SOAP-ENV:Body><ns1:testResponse><return xsi:type="xsd:string">Hello Body!</return></ns1:testResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
ok
+49
View File
@@ -0,0 +1,49 @@
--TEST--
SOAP Server 24: Send SOAP headers those were not received
--SKIPIF--
<?php require_once('skipif.inc'); ?>
--FILE--
<?php
class TestHeader1 extends SoapHeader {
function __construct($data) {
parent::__construct("http://testuri.org", "Test1", $data);
}
}
class TestHeader2 extends SoapHeader {
function __construct($data) {
parent::__construct("http://testuri.org", "Test2", $data);
}
}
function test() {
global $server;
$server->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
<?xml version="1.0" encoding="ISO-8859-1"?>
<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:si="http://soapinterop.org/xsd">
<SOAP-ENV:Body>
<ns1:test xmlns:ns1="http://testuri.org"/>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
EOF;
$server->handle();
echo "ok\n";
?>
--EXPECT--
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://testuri.org" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Header><ns1:Test1>Hello Header!</ns1:Test1><ns1:Test2>Hello Header!</ns1:Test2></SOAP-ENV:Header><SOAP-ENV:Body><ns1:testResponse><return xsi:type="xsd:string">Hello Body!</return></ns1:testResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
ok
+46
View File
@@ -0,0 +1,46 @@
--TEST--
SOAP Server 25: One-way SOAP headers encoding using WSDL
--SKIPIF--
<?php require_once('skipif.inc'); ?>
--FILE--
<?php
class TestHeader1 extends SoapHeader {
function __construct($data) {
parent::__construct("http://testuri.org", "Test1", $data);
}
}
class TestHeader2 extends SoapHeader {
function __construct($data) {
parent::__construct("http://testuri.org", "Test2", $data);
}
}
function test() {
global $server;
$server->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
<?xml version="1.0" encoding="ISO-8859-1"?>
<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<ns1:test xmlns:ns1="http://testuri.org"/>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
EOF;
$server->handle();
echo "ok\n";
?>
--EXPECT--
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns1="http://testuri.org"><SOAP-ENV:Header><ns1:Test1 xsi:type="xsd:string">Hello Header!</ns1:Test1><ns1:Test2 xsi:type="xsd:string">Hello Header!</ns1:Test2></SOAP-ENV:Header><SOAP-ENV:Body><ns1:testResponse><result>Hello Body!</result></ns1:testResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
ok
+55
View File
@@ -0,0 +1,55 @@
<?xml version="1.0" ?>
<definitions
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:si="http://soapinterop.org/xsd"
xmlns:tns="http://linuxsrv.home/~dmitry/soap/test.wsdl"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="http://testuri.org">
<message name="TestHeader1">
<part name="Test1" type="xsd:string" />
</message>
<message name="TestHeader2">
<part name="Test2" type="xsd:string" />
</message>
<message name="TestRequest">
</message>
<message name="TestResponse">
<part name="result" type="xsd:string" />
</message>
<portType name="TestServicePortType">
<operation name="test">
<input message="tns:TestRequest" />
<output message="tns:TestResponse" />
</operation>
</portType>
<binding name="TestServiceBinding" type="tns:TestServicePortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
<operation name="test">
<soap:operation soapAction="Test" style="rpc" />
<input>
<soap:body namespace="http://testuri.org" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
</input>
<output>
<soap:body namespace="http://testuri.org" use="literal" />
<soap:header namespace="http://testuri.org" message="tns:TestHeader1" part="Test1" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
<soap:header namespace="http://testuri.org" message="tns:TestHeader2" part="Test2" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
</output>
</operation>
</binding>
<service name="TestService">
<port name="TestServicePort" binding="tns:TestServiceBinding">
<soap:address location="http://linuxsrv.home/~dmitry/soap/soap_server.php" />
</port>
</service>
</definitions>
+32
View File
@@ -0,0 +1,32 @@
--TEST--
SPL: ArrayIterator and foreach by reference
--SKIPIF--
<?php if (!extension_loaded("spl")) print "skip"; ?>
--FILE--
<?php
$ar = new ArrayObject(array(1)); foreach($ar as &$v) var_dump($v);
$ar = new ArrayIterator(array(2)); foreach($ar as &$v) var_dump($v);
$ar = new RecursiveArrayIterator(array(3)); foreach($ar as &$v) var_dump($v);
class ArrayIteratorEx extends ArrayIterator
{
function current()
{
return ArrayIterator::current();
}
}
$ar = new ArrayIteratorEx(array(4)); foreach($ar as $v) var_dump($v);
$ar = new ArrayIteratorEx(array(5)); foreach($ar as &$v) var_dump($v);
?>
===DONE===
<?php exit(0); ?>
--EXPECTF--
int(1)
int(2)
int(3)
int(4)
int(5)
===DONE===
+66
View File
@@ -0,0 +1,66 @@
--TEST--
SPL: ArrayIterator overloading
--SKIPIF--
<?php if (!extension_loaded("spl")) print "skip"; ?>
--FILE--
<?php
class ArrayIteratorEx extends ArrayIterator
{
function rewind()
{
echo __METHOD__ . "\n";
ArrayIterator::rewind();
}
function valid()
{
echo __METHOD__ . "\n";
return ArrayIterator::valid();
}
function key()
{
echo __METHOD__ . "\n";
return ArrayIterator::key();
}
function current()
{
echo __METHOD__ . "\n";
return ArrayIterator::current();
}
function next()
{
echo __METHOD__ . "\n";
return ArrayIterator::next();
}
}
$ar = new ArrayIteratorEx(array(1,2));
foreach($ar as $k => $v)
{
var_dump($k);
var_dump($v);
}
?>
===DONE===
<?php exit(0); ?>
--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===
+31
View File
@@ -0,0 +1,31 @@
--TEST--
SPL: ArrayObject::seek() and exceptions
--FILE--
<?php
class foo extends ArrayObject
{
public function seek($key)
{
echo __METHOD__ . "($key)\n";
throw new Exception("hi");
}
}
$test = new foo(array(1,2,3));
try
{
$test->seek('bar');
}
catch (Exception $e)
{
echo "got exception\n";
}
?>
===DONE===
--EXPECT--
foo::seek(bar)
got exception
===DONE===
+94
View File
@@ -0,0 +1,94 @@
--TEST--
SPL: ArrayObject/Iterator and reference to self
--FILE--
==ArrayObject===
<?php
class MyArrayObject extends ArrayObject
{
public function __construct()
{
parent::__construct($this);
$this['bar'] = 'baz';
}
}
$a = new MyArrayObject;
$b = clone $a;
$b['baz'] = 'Foo';
var_dump($a);
var_dump($b);
?>
==ArrayIterator===
<?php
class MyArrayIterator extends ArrayIterator
{
public function __construct()
{
parent::__construct($this);
$this['bar'] = 'baz';
}
}
$a = new MyArrayIterator;
$b = clone $a;
$b['baz'] = 'Foo';
var_dump($a);
var_dump($b);
?>
===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===
+21
View File
@@ -0,0 +1,21 @@
--TEST--
Bug #36258 (SplFileObject::getPath() may lead to segfault)
--SKIPIF--
<?php if (!extension_loaded("spl")) print "skip"; ?>
--FILE--
<?php
$diriter = new RecursiveIteratorIterator( new RecursiveDirectoryIterator('.') );
foreach ($diriter as $key => $file) {
var_dump($file->getFilename());
var_dump($file->getPath());
break;
}
echo "Done\n";
?>
--EXPECTF--
string(%d) "%s"
string(%d) "%s"
Done
+40
View File
@@ -0,0 +1,40 @@
--TEST--
Bug #36287
--SKIPIF--
<?php if (!extension_loaded("spl")) print "skip"; ?>
--FILE--
<?php
$it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator("."), true);
$idx = 0;
foreach($it as $file)
{
echo "First\n";
if("." != $file && ".." != $file)
{
var_Dump($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===
+33
View File
@@ -0,0 +1,33 @@
--TEST--
Bug #36825 (Exceptions thrown in ArrayObject::offsetGet cause segfault)
--SKIPIF--
<?php if (!extension_loaded("spl")) print "skip"; ?>
--FILE--
<?php
class foo extends ArrayObject
{
public function offsetGet($key)
{
echo __METHOD__ . "($key)\n";
throw new Exception("hi");
}
}
$test = new foo();
try
{
var_dump($test['bar']);
}
catch (Exception $e)
{
echo "got exception\n";
}
?>
===DONE===
--EXPECT--
foo::offsetGet(bar)
got exception
===DONE===
+46
View File
@@ -0,0 +1,46 @@
--TEST--
Bug #36941 (ArrayIterator does not clone itself)
--FILE--
===ArrayObject===
<?php
$a = new ArrayObject();
$a[] = 1;
$b = clone $a;
var_dump($a[0], $b[0]);
$b[0] = $b[0] + 1;
var_dump($a[0], $b[0]);
$b[0] = 3;
var_dump($a[0], $b[0]);
?>
===ArrayIterator===
<?php
$a = new ArrayIterator();
$a[] = 1;
$b = clone $a;
var_dump($a[0], $b[0]);
$b[0] = $b[0] + 1;
var_dump($a[0], $b[0]);
$b[0] = 3;
var_dump($a[0], $b[0]);
?>
===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===
+46
View File
@@ -0,0 +1,46 @@
--TEST--
SPL: EmptyIterator access
--SKIPIF--
<?php if (!extension_loaded("spl")) print "skip"; ?>
--FILE--
<?php
$it = new EmptyIterator;
var_dump($it->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===
<?php exit(0); ?>
--EXPECT--
bool(false)
bool(false)
bool(false)
Accessing the key of an EmptyIterator
Accessing the value of an EmptyIterator
bool(false)
===DONE===
+118
View File
@@ -0,0 +1,118 @@
--TEST--
SPL: AppendIterator::append() rewinds when neccessary
--SKIPIF--
<?php if (!extension_loaded("spl")) print "skip"; ?>
--FILE--
<?php
class MyArrayIterator extends ArrayIterator
{
function rewind()
{
echo __METHOD__ . "\n";
parent::rewind();
}
}
$it = new MyArrayIterator(array(1,2));
foreach($it as $k=>$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===
<?php exit(0); ?>
--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===
+52
View File
@@ -0,0 +1,52 @@
--TEST--
SPL: LimitIterator::getPosition()
--SKIPIF--
<?php if (!extension_loaded("spl")) print "skip"; ?>
--FILE--
<?php
$it = new LimitIterator(new ArrayIterator(array(1,2,3,4)), 1, 2);
foreach($it as $k=>$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===
<?php exit(0); ?>
--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===
+46
View File
@@ -0,0 +1,46 @@
--TEST--
SPL: ParentIterator
--SKIPIF--
<?php if (!extension_loaded("spl")) print "skip"; ?>
--FILE--
<?php
$it = new ParentIterator(new RecursiveArrayIterator(array(1,array(21,22, array(231)),3)));
foreach(new RecursiveIteratorIterator($it) as $k=>$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===
<?php exit(0); ?>
--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===
+190
View File
@@ -0,0 +1,190 @@
--TEST--
SPL: RecursiveIteratorIterator and break deep
--SKIPIF--
<?php if (!extension_loaded("spl")) print "skip"; ?>
--FILE--
<?php
class MyRecursiveArrayIterator extends RecursiveArrayIterator
{
function valid()
{
if (!parent::valid())
{
echo __METHOD__ . "() = false\n";
return false;
}
else
{
return true;
}
}
function getChildren()
{
echo __METHOD__ . "()\n";
return parent::getChildren();
}
function rewind()
{
echo __METHOD__ . "()\n";
parent::rewind();
}
}
class RecursiveArrayIteratorIterator extends RecursiveIteratorIterator
{
private $max_depth;
private $over = 0;
function __construct($it, $max_depth)
{
$this->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===
<?php exit(0); ?>
--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===
+17
View File
@@ -0,0 +1,17 @@
--TEST--
SPL: ArrayIterator and values assigned by reference
--SKIPIF--
<?php if (!extension_loaded("spl")) print "skip"; ?>
--FILE--
<?php
$tmp = 1;
$a = new ArrayIterator();
$a[] = $tmp;
$a[] = &$tmp;
echo "Done\n";
?>
--EXPECTF--
Fatal error: Objects used as arrays in post/pre increment/decrement must return values by reference in %s on line %d
+131
View File
@@ -0,0 +1,131 @@
--TEST--
SPL: spl_autoload() with exceptions
--SKIPIF--
<?php if (!extension_loaded("spl")) print "skip"; ?>
--INI--
include_path=.
--FILE--
<?php
function MyAutoLoad($className)
{
echo __METHOD__ . "($className)\n";
throw new Exception('Bla');
}
class MyAutoLoader
{
static function autoLoad($className)
{
echo __METHOD__ . "($className)\n";
throw new Exception('Bla');
}
function dynaLoad($className)
{
echo __METHOD__ . "($className)\n";
throw new Exception('Bla');
}
}
$obj = new MyAutoLoader;
$funcs = array(
'MyAutoLoad',
'MyAutoLoader::autoLoad',
'MyAutoLoader::dynaLoad',
array('MyAutoLoader', 'autoLoad'),
array('MyAutoLoader', 'dynaLoad'),
array($obj, 'autoLoad'),
array($obj, 'dynaLoad'),
);
foreach($funcs as $idx => $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===
<?php exit(0); ?>
--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===
+46
View File
@@ -0,0 +1,46 @@
--TEST--
SPL: SimpleXMLIterator and getChildren()
--SKIPIF--
<?php
if (!extension_loaded("spl")) print "skip";
if (!extension_loaded('simplexml')) print 'skip';
if (!extension_loaded("libxml")) print "skip LibXML not present";
if (!class_exists('RecursiveIteratorIterator')) print 'skip RecursiveIteratorIterator not available';
?>
--FILE--
<?php
$xml =<<<EOF
<?xml version='1.0'?>
<sxe>
<elem1/>
<elem2/>
<elem2/>
</sxe>
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===
+39
View File
@@ -0,0 +1,39 @@
--TEST--
Bug #37158 (if userspace stream is present, fread() reads in 8192 max, otherwise it works)
--FILE--
<?php
class VariableStream {
function stream_open($path, $mode, $options, &$opened_path)
{
return true;
}
}
stream_wrapper_register("var", "VariableStream");
error_reporting(E_ALL | E_STRICT);
$file = dirname(__FILE__) . '/footest.txt';
$x = str_repeat(1, 8192);
$fp = fopen($file, 'w');
for ($i = 0; $i < 5; $i++) {
fwrite($fp, $x);
}
fclose($fp);
$fp = fopen($file, 'r');
$outsidecontents = fread($fp, 20000);
fclose($fp);
var_dump('size of contents 1 = ' . strlen($outsidecontents));
$outsidecontents = file_get_contents($file);
var_dump('size of contents 2 = ' . strlen($outsidecontents));
unlink($file);
echo "Done\n";
?>
--EXPECT--
string(26) "size of contents 1 = 20000"
string(26) "size of contents 2 = 40960"
Done
+72
View File
@@ -0,0 +1,72 @@
--TEST--
stream filter - reading
--FILE--
<?php
echo "-TEST\n";
class filter extends php_user_filter {
function filter($in, $out, &$consumed, $closing)
{
$output = 0;
while ($bucket = stream_bucket_make_writeable($in)) {
$bucket->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
<?PHP
ECHO "-TEST\N";
CLASS FILTER EXTENDS PHP_USER_FILTER {
FUNCTION FILTER($IN, $OUT, &$CONSUMED, $CLOSING)
{
$OUTPUT = 0;
WHILE ($BUCKET = STREAM_BUCKET_MAKE_WRITEABLE($IN)) {
$BUCKET->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
+46
View File
@@ -0,0 +1,46 @@
--TEST--
Bug #36011 (Strict errormsg wrong for call_user_func() and the likes)
--FILE--
<?php
class TestClass
{
static function test()
{
echo __METHOD__ . "()\n";
}
function whee()
{
array_map(array('TestClass', 'test'), array('array_value'));
}
function whee4()
{
call_user_func(array('TestClass', 'test'));
}
static function whee5()
{
call_user_func(array('TestClass', 'test'));
}
}
TestClass::test();
$a = new TestClass();
$a->whee();
$a->whee4();
$a->whee5();
TestClass::whee5();
?>
===DONE===
--EXPECTF--
TestClass::test()
TestClass::test()
TestClass::test()
TestClass::test()
TestClass::test()
===DONE===
+11
View File
@@ -0,0 +1,11 @@
--TEST--
Bug #33605 (substr_compare crashes)
--FILE--
<?php
$res = substr_compare("aa", "a", -99999999, 0, 0);
var_dump($res);
?>
--EXPECTF--
Warning: substr_compare(): The length must be greater than zero in %s on line %d
bool(false)
+29
View File
@@ -0,0 +1,29 @@
--TEST--
Bug #36148 (unpack("H*hex", $data) is adding an extra character to the end of the string)
--FILE--
<?php
$values = array("a", "aa", "aaa", "aaaa");
foreach ($values as $value) {
$a = pack("H*", $value);
$b = unpack("H*", $a);
echo $value.": ";
var_dump($b);
}
?>
--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"
}
+15
View File
@@ -0,0 +1,15 @@
--TEST--
Bug #36306 crc32() 64bit
--FILE--
<?php
/* as an example how to write crc32 tests
PHP does not have uint values, you cannot
display crc32 like a signed integer.
Have to find some small strings to truely reproduce
the problem, this example being not a problem
*/
echo dechex(crc32("platform independant")) . "\n";
?>
--EXPECT--
ccd9fe66
+26
View File
@@ -0,0 +1,26 @@
--TEST--
Bug #36944 (strncmp & strncasecmp do not return false on negative string length)
--FILE--
<?php
var_dump(strncmp("test ", "e", -1));
var_dump(strncmp("test ", "e", 10));
var_dump(strncmp("test ", "e", 0));
var_dump(strncasecmp("test ", "E", -1));
var_dump(strncasecmp("test ", "E", 10));
var_dump(strncasecmp("test ", "E", 0));
echo "Done\n";
?>
--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
@@ -0,0 +1,39 @@
--TEST--
substr_compare()
--FILE--
<?php
var_dump(substr_compare("abcde", "bc", 1, 2));
var_dump(substr_compare("abcde", "bcg", 1, 2));
var_dump(substr_compare("abcde", "BC", 1, 2, true));
var_dump(substr_compare("abcde", "bc", 1, 3));
var_dump(substr_compare("abcde", "cd", 1, 2));
var_dump(substr_compare("abcde", "abc", 5, 1));
var_dump(substr_compare("abcde", -1, 0, NULL, new stdClass));
echo "Test\n";
var_dump(substr_compare("abcde", "abc", -1, NULL, -5));
var_dump(substr_compare("abcde", -1, 0, "str", new stdClass));
echo "Done\n";
?>
--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
+34
View File
@@ -0,0 +1,34 @@
--TEST--
XMLReader: libxml2 XML Reader, string data
--SKIPIF--
<?php if (!extension_loaded("xmlreader")) print "skip";
$reader = new XMLReader();
if (!method_exists($reader, 'readInnerXml')) print "skip";
?>
--FILE--
<?php
/* $Id$ */
$xmlstring = '<?xml version="1.0" encoding="UTF-8"?>
<books><book>test</book></books>';
$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--
<book>test</book>
<books><book>test</book></books>
===DONE===
+2
View File
@@ -0,0 +1,2 @@
<!ELEMENT foo EMPTY>
<!ATTLIST foo bar CDATA '' baz CDATA ''>
+69
View File
@@ -0,0 +1,69 @@
--TEST--
XMLReader: accessing empty and non existing attributes
--SKIPIF--
<?php if (!extension_loaded("xmlreader")) print "skip"; ?>
--FILE--
<?php
/* $Id$ */
$xmlstring =<<<EOF
<?xml version="1.0" encoding="UTF-8"?>
<foo bar=""/>
EOF;
$reader = new XMLReader();
$reader->XML($xmlstring);
$reader->read();
var_dump($reader->getAttribute('bar'));
var_dump($reader->getAttribute('baz'));
$reader->close();
$xmlstring =<<<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo SYSTEM "012.dtd">
<foo bar=""/>
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===
<?php
$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();
$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===
+3
View File
@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo SYSTEM "012.dtd">
<foo bar=""/>
+25
View File
@@ -0,0 +1,25 @@
--TEST--
Bug #36743 (In a class extending XMLReader array properties are not writable)
--FILE--
<?php
class Test extends XMLReader
{
private $testArr = array();
public function __construct()
{
$this->testArr[] = 1;
var_dump($this->testArr);
}
}
$t = new test;
echo "Done\n";
?>
--EXPECT--
array(1) {
[0]=>
int(1)
}
Done
+62
View File
@@ -0,0 +1,62 @@
--TEST--
Bug #37057 (xmlrpc_decode() may produce arrays with numeric string keys which are unaccessible)
--FILE--
<?php
$response='<?xml version="1.0"?>
<methodResponse>
<params>
<param>
<value>
<struct>
<member>
<name>50</name>
<value><string>0.29</string></value>
</member>
</struct>
</value>
</param>
</params>
</methodResponse>';
$retval=xmlrpc_decode($response);
var_dump($retval);
var_dump($retval["50"]);
var_dump($retval[50]);
$response='<?xml version="1.0"?>
<methodResponse>
<params>
<param>
<value>
<struct>
<member>
<name>0</name>
<value><string>0.29</string></value>
</member>
</struct>
</value>
</param>
</params>
</methodResponse>';
$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
+938
View File
@@ -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 <dmitry@zend.com> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#include "fastcgi.h"
#include "php.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <errno.h>
#ifdef _WIN32
#include <windows.h>
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 <sys/types.h>
# include <sys/stat.h>
# include <unistd.h>
# include <fcntl.h>
# include <sys/socket.h>
# include <sys/un.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <netdb.h>
# include <sys/signal.h>
#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 <port>) */
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
*/
+183
View File
@@ -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 <dmitry@zend.com> |
+----------------------------------------------------------------------+
*/
/* $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
*/