Merge branch 'PHP-5.5' of https://git.php.net/repository/php-src into PHP-5.5

* 'PHP-5.5' of https://git.php.net/repository/php-src:
  Improved fix for bug #44686 (SOAP-ERROR: Parsing WSDL)
  Fixed bug #65018 (SoapHeader problems with SoapServer)
  Added opcache.restrict_api configuration directive that may limit usage of OPcahce API functions only to patricular script(s)
  MFH: fixed #65045: mb_convert_encoding breaks well-formed character.
  Fixed php-5.2 support
  added test script for bug65045.
  MFH: fixed #65045: mb_convert_encoding breaks well-formed character.
  Added support for glob symbols in blacklist entries (?, *, **)
  Fixed bug #65336
This commit is contained in:
Christopher Jones 2013-07-31 09:01:56 -07:00
commit 0625d5ce67
16 changed files with 537 additions and 293 deletions

7
NEWS
View File

@ -11,6 +11,10 @@ PHP NEWS
limited case). (Arpad)
- OPcahce:
. Added opcache.restrict_api configuration directive that may limit
usage of OPcahce API functions only to patricular script(s). (Dmitry)
. Added support for glob symbols in blacklist entries (?, *, **).
(Terry Elison, Dmitry)
. Fixed bug #65338 (Enabling both php_opcache and php_wincache AVs on
shutdown). (Dmitry)
@ -21,6 +25,9 @@ PHP NEWS
. Fixed bug #65028 (Phar::buildFromDirectory creates corrupt archives for
some specific contents). (Stas)
- SOAP:
. Fixed bug #65018 (SoapHeader problems with SoapServer). (Dmitry)
- SPL:
. Fixed bug #65328 (Segfault when getting SplStack object Value). (Laruence)
. Added RecursiveTreeIterator setPostfix and getPostifx methods. (Joshua

View File

@ -79,7 +79,7 @@ const struct mbfl_convert_vtbl vtbl_utf8_wchar = {
mbfl_filt_conv_common_ctor,
mbfl_filt_conv_common_dtor,
mbfl_filt_conv_utf8_wchar,
mbfl_filt_conv_common_flush
mbfl_filt_conv_utf8_wchar_flush
};
const struct mbfl_convert_vtbl vtbl_wchar_utf8 = {
@ -93,6 +93,17 @@ const struct mbfl_convert_vtbl vtbl_wchar_utf8 = {
#define CK(statement) do { if ((statement) < 0) return (-1); } while (0)
int mbfl_filt_put_invalid_char(int c, mbfl_convert_filter *filter)
{
int w;
w = c & MBFL_WCSGROUP_MASK;
w |= MBFL_WCSGROUP_THROUGH;
filter->status = 0;
filter->cache = 0;
CK((*filter->output_function)(w, filter->data));
}
/*
* UTF-8 => wchar
*/
@ -100,111 +111,104 @@ int mbfl_filt_conv_utf8_wchar(int c, mbfl_convert_filter *filter)
{
int s, c1, w = 0, flag = 0;
if (c < 0x80) {
if (filter->status != 0) {
w = (filter->cache & MBFL_WCSGROUP_MASK) | MBFL_WCSGROUP_THROUGH;
CK((*filter->output_function)(w, filter->data));
filter->status = 0;
filter->cache = 0;
}
if (c >= 0) {
retry:
switch (filter->status & 0xff) {
case 0x00:
if (c < 0x80) {
CK((*filter->output_function)(c, filter->data));
}
} else if (c < 0xc0) {
int status = filter->status & 0xff;
switch (status) {
case 0x10: /* 2byte code 2nd char: 0x80-0xbf */
case 0x21: /* 3byte code 3rd char: 0x80-0xbf */
case 0x32: /* 4byte code 4th char: 0x80-0xbf */
filter->status = 0;
s = filter->cache | (c & 0x3f);
filter->cache = 0;
if ((status == 0x10 && s >= 0x80) ||
(status == 0x21 && s >= 0x800 && (s < 0xd800 || s > 0xdfff)) ||
(status == 0x32 && s >= 0x10000 && s < 0x110000)) {
CK((*filter->output_function)(s, filter->data));
} else {
w = s & MBFL_WCSGROUP_MASK;
flag = 1;
}
break;
case 0x20: /* 3byte code 2nd char: 0:0xa0-0xbf,D:0x80-9F,1-C,E-F:0x80-0x9f */
s = filter->cache | ((c & 0x3f) << 6);
c1 = (s >> 12) & 0xf;
if ((c1 == 0x0 && c >= 0xa0) ||
(c1 == 0xd && c < 0xa0) ||
(c1 > 0x0 && c1 != 0xd)) {
filter->cache = s;
filter->status++;
} else {
w = s & MBFL_WCSGROUP_MASK;
flag = 1;
}
break;
case 0x31: /* 4byte code 3rd char: 0x80-0xbf */
filter->cache |= ((c & 0x3f) << 6);
filter->status++;
break;
case 0x30: /* 4byte code 2nd char: 0:0x90-0xbf,1-3:0x80-0xbf,4:0x80-0x8f */
s = filter->cache | ((c & 0x3f) << 12);
c1 = (s >> 18) & 0x7;
if ((c1 == 0x0 && c >= 0x90) ||
(c1 > 0x0 && c1 < 0x4) ||
(c1 == 0x4 && c < 0x90)) {
filter->cache = s;
filter->status++;
} else {
w = s & MBFL_WCSGROUP_MASK;
flag = 1;
}
break;
default:
w = c & MBFL_WCSGROUP_MASK;
flag = 1;
break;
}
} else if (c < 0xc2) { /* invalid: 0xc0,0xc1 */
w = c & MBFL_WCSGROUP_MASK;
flag = 1;
} else if (c < 0xe0) { /* 2byte code first char: 0xc2-0xdf */
if (filter->status == 0x0) {
} else if (c >= 0xc2 && c <= 0xdf) { /* 2byte code first char: 0xc2-0xdf */
filter->status = 0x10;
filter->cache = (c & 0x1f) << 6;
} else {
w = c & MBFL_WCSGROUP_MASK;
flag = 1;
}
} else if (c < 0xf0) { /* 3byte code first char: 0xe0-0xef */
if (filter->status == 0x0) {
filter->cache = c & 0x1f;
} else if (c >= 0xe0 && c <= 0xef) { /* 3byte code first char: 0xe0-0xef */
filter->status = 0x20;
filter->cache = (c & 0xf) << 12;
} else {
w = c & MBFL_WCSGROUP_MASK;
flag = 1;
}
} else if (c < 0xf5) { /* 4byte code first char: 0xf0-0xf4 */
if (filter->status == 0x0) {
filter->cache = c & 0xf;
} else if (c >= 0xf0 && c <= 0xf4) { /* 3byte code first char: 0xf0-0xf4 */
filter->status = 0x30;
filter->cache = (c & 0x7) << 18;
filter->cache = c & 0x7;
} else {
w = c & MBFL_WCSGROUP_MASK;
flag = 1;
mbfl_filt_put_invalid_char(c, filter);
}
} else {
w = c & MBFL_WCSGROUP_MASK;
flag = 1;
}
if (flag) {
w |= MBFL_WCSGROUP_THROUGH;
CK((*filter->output_function)(w, filter->data));
break;
case 0x10: /* 2byte code 2nd char: 0x80-0xbf */
case 0x21: /* 3byte code 3rd char: 0x80-0xbf */
case 0x32: /* 4byte code 4th char: 0x80-0xbf */
filter->status = 0;
filter->cache = 0;
if (c >= 0x80 && c <= 0xbf) {
s = (filter->cache<<6) | (c & 0x3f);
filter->cache = 0;
CK((*filter->output_function)(s, filter->data));
} else {
mbfl_filt_put_invalid_char(filter->cache, filter);
goto retry;
}
break;
case 0x20: /* 3byte code 2nd char: 0:0xa0-0xbf,D:0x80-9F,1-C,E-F:0x80-0x9f */
s = (filter->cache<<6) | (c & 0x3f);
c1 = filter->cache & 0xf;
if ((c >= 0x80 && c <= 0xbf) &&
((c1 == 0x0 && c >= 0xa0) ||
(c1 == 0xd && c < 0xa0) ||
(c1 > 0x0 && c1 != 0xd))) {
filter->cache = s;
filter->status++;
} else {
mbfl_filt_put_invalid_char(filter->cache, filter);
goto retry;
}
break;
case 0x30: /* 4byte code 2nd char: 0:0x90-0xbf,1-3:0x80-0xbf,4:0x80-0x8f */
s = (filter->cache<<6) | (c & 0x3f);
c1 = filter->cache & 0x7;
if ((c >= 0x80 && c <= 0xbf) &&
((c1 == 0x0 && c >= 0x90) ||
(c1 == 0x4 && c < 0x90) ||
(c1 > 0x0 && c1 != 0x4))) {
filter->cache = s;
filter->status++;
} else {
mbfl_filt_put_invalid_char(filter->cache, filter);
goto retry;
}
break;
case 0x31: /* 4byte code 3rd char: 0x80-0xbf */
if (c >= 0x80 && c <= 0xbf) {
filter->cache = (filter->cache<<6) | (c & 0x3f);
filter->status++;
} else {
mbfl_filt_put_invalid_char(filter->cache, filter);
goto retry;
}
break;
default:
filter->status = 0;
break;
}
return c;
}
int mbfl_filt_conv_utf8_wchar_flush(mbfl_convert_filter *filter)
{
int status, cache;
status = filter->status;
cache = filter->cache;
filter->status = 0;
filter->cache = 0;
if (status != 0) {
mbfl_filt_put_invalid_char(cache, filter);
}
if (filter->flush_function != NULL) {
(*filter->flush_function)(filter->data);
}
return 0;
}
/*
* wchar => UTF-8
*/

View File

@ -37,5 +37,6 @@ extern const struct mbfl_convert_vtbl vtbl_wchar_utf8;
int mbfl_filt_conv_utf8_wchar(int c, mbfl_convert_filter *filter);
int mbfl_filt_conv_wchar_utf8(int c, mbfl_convert_filter *filter);
int mbfl_filt_conv_utf8_wchar_flush(mbfl_convert_filter *filter);
#endif /* MBFL_MBFILTER_UTF8_H */

View File

@ -37,6 +37,7 @@
#include "mbfilter_sjis_mobile.h"
extern int mbfl_filt_ident_utf8(int c, mbfl_identify_filter *filter);
extern int mbfl_filt_conv_utf8_wchar_flush(mbfl_convert_filter *filter);
extern const unsigned char mblen_table_utf8[];
@ -115,7 +116,7 @@ const struct mbfl_convert_vtbl vtbl_utf8_docomo_wchar = {
mbfl_filt_conv_common_ctor,
mbfl_filt_conv_common_dtor,
mbfl_filt_conv_utf8_mobile_wchar,
mbfl_filt_conv_common_flush
mbfl_filt_conv_utf8_wchar_flush
};
const struct mbfl_convert_vtbl vtbl_wchar_utf8_docomo = {
@ -133,7 +134,7 @@ const struct mbfl_convert_vtbl vtbl_utf8_kddi_a_wchar = {
mbfl_filt_conv_common_ctor,
mbfl_filt_conv_common_dtor,
mbfl_filt_conv_utf8_mobile_wchar,
mbfl_filt_conv_common_flush
mbfl_filt_conv_utf8_wchar_flush
};
const struct mbfl_convert_vtbl vtbl_wchar_utf8_kddi_a = {
@ -151,7 +152,7 @@ const struct mbfl_convert_vtbl vtbl_utf8_kddi_b_wchar = {
mbfl_filt_conv_common_ctor,
mbfl_filt_conv_common_dtor,
mbfl_filt_conv_utf8_mobile_wchar,
mbfl_filt_conv_common_flush
mbfl_filt_conv_utf8_wchar_flush
};
const struct mbfl_convert_vtbl vtbl_wchar_utf8_kddi_b = {
@ -169,7 +170,7 @@ const struct mbfl_convert_vtbl vtbl_utf8_sb_wchar = {
mbfl_filt_conv_common_ctor,
mbfl_filt_conv_common_dtor,
mbfl_filt_conv_utf8_mobile_wchar,
mbfl_filt_conv_common_flush
mbfl_filt_conv_utf8_wchar_flush
};
const struct mbfl_convert_vtbl vtbl_wchar_utf8_sb = {
@ -191,119 +192,97 @@ int mbfl_filt_conv_utf8_mobile_wchar(int c, mbfl_convert_filter *filter)
int s, w = 0, flag = 0;
int s1 = 0, c1 = 0, snd = 0;
if (c < 0x80) {
if (c >= 0) {
retry:
switch (filter->status & 0xff) {
case 0x00:
if (c < 0x80) {
CK((*filter->output_function)(c, filter->data));
}
filter->status = 0;
} else if (c < 0xc0) {
int status = filter->status & 0xff;
switch (status) {
case 0x10: /* 2byte code 2nd char: 0x80-0xbf */
case 0x21: /* 3byte code 3rd char: 0x80-0xbf */
case 0x32: /* 4byte code 4th char: 0x80-0xbf */
filter->status = 0;
s = filter->cache | (c & 0x3f);
filter->cache = 0;
if ((status == 0x10 && s >= 0x80) ||
(status == 0x21 && s >= 0x800 && (s < 0xd800 || s > 0xdfff)) ||
(status == 0x32 && s >= 0x10000 && s < 0x110000)) {
if (filter->from->no_encoding == mbfl_no_encoding_utf8_docomo &&
mbfilter_conv_r_map_tbl(s, &s1, mbfl_docomo2uni_pua, 4) > 0) {
s = mbfilter_sjis_emoji_docomo2unicode(s1, &snd);
} else if (filter->from->no_encoding == mbfl_no_encoding_utf8_kddi_a &&
mbfilter_conv_r_map_tbl(s, &s1, mbfl_kddi2uni_pua, 7) > 0) {
s = mbfilter_sjis_emoji_kddi2unicode(s1, &snd);
} else if (filter->from->no_encoding == mbfl_no_encoding_utf8_kddi_b &&
mbfilter_conv_r_map_tbl(s, &s1, mbfl_kddi2uni_pua_b, 8) > 0) {
s = mbfilter_sjis_emoji_kddi2unicode(s1, &snd);
} else if (filter->from->no_encoding == mbfl_no_encoding_utf8_sb &&
mbfilter_conv_r_map_tbl(s, &s1, mbfl_sb2uni_pua, 6) > 0) {
s = mbfilter_sjis_emoji_sb2unicode(s1, &snd);
}
if (snd > 0) {
CK((*filter->output_function)(snd, filter->data));
}
CK((*filter->output_function)(s, filter->data));
} else {
w = s & MBFL_WCSGROUP_MASK;
flag = 1;
}
break;
case 0x20: /* 3byte code 2nd char: 0:0xa0-0xbf,D:0x80-9F,1-C,E-F:0x80-0x9f */
s = filter->cache | ((c & 0x3f) << 6);
c1 = (s >> 12) & 0xf;
if ((c1 == 0x0 && c >= 0xa0) ||
(c1 == 0xd && c < 0xa0) ||
(c1 > 0x0 && c1 != 0xd)) {
filter->cache = s;
filter->status++;
} else {
w = s & MBFL_WCSGROUP_MASK;
flag = 1;
}
break;
case 0x31: /* 4byte code 3rd char: 0x80-0xbf */
filter->cache |= ((c & 0x3f) << 6);
filter->status++;
break;
case 0x30: /* 4byte code 2nd char: 0:0x90-0xbf,1-3:0x80-0xbf,4:0x80-0x8f */
s = filter->cache | ((c & 0x3f) << 12);
c1 = (s >> 18) & 0x7;
if ((c1 == 0x0 && c >= 0x90) ||
(c1 > 0x0 && c1 < 0x4) ||
(c1 == 0x4 && c < 0x90)) {
filter->cache = s;
filter->status++;
} else {
w = s & MBFL_WCSGROUP_MASK;
flag = 1;
}
break;
default:
w = c & MBFL_WCSGROUP_MASK;
flag = 1;
break;
}
} else if (c < 0xc2) { /* invalid: 0xc0,0xc1 */
w = c & MBFL_WCSGROUP_MASK;
flag = 1;
} else if (c < 0xe0) { /* 2byte code first char: 0xc2-0xdf */
if (filter->status == 0x0) {
} else if (c >= 0xc2 && c <= 0xdf) { /* 2byte code first char: 0xc2-0xdf */
filter->status = 0x10;
filter->cache = (c & 0x1f) << 6;
} else {
w = c & MBFL_WCSGROUP_MASK;
flag = 1;
}
} else if (c < 0xf0) { /* 3byte code first char: 0xe0-0xef */
if (filter->status == 0x0) {
filter->cache = c & 0x1f;
} else if (c >= 0xe0 && c <= 0xef) { /* 3byte code first char: 0xe0-0xef */
filter->status = 0x20;
filter->cache = (c & 0xf) << 12;
} else {
w = c & MBFL_WCSGROUP_MASK;
flag = 1;
}
} else if (c < 0xf5) { /* 4byte code first char: 0xf0-0xf4 */
if (filter->status == 0x0) {
filter->cache = c & 0xf;
} else if (c >= 0xf0 && c <= 0xf4) { /* 3byte code first char: 0xf0-0xf4 */
filter->status = 0x30;
filter->cache = (c & 0x7) << 18;
filter->cache = c & 0x7;
} else {
w = c & MBFL_WCSGROUP_MASK;
flag = 1;
mbfl_filt_put_invalid_char(c, filter);
}
} else {
w = c & MBFL_WCSGROUP_MASK;
flag = 1;
}
if (flag) {
w |= MBFL_WCSGROUP_THROUGH;
CK((*filter->output_function)(w, filter->data));
break;
case 0x10: /* 2byte code 2nd char: 0x80-0xbf */
case 0x21: /* 3byte code 3rd char: 0x80-0xbf */
case 0x32: /* 4byte code 4th char: 0x80-0xbf */
filter->status = 0;
filter->cache = 0;
if (c >= 0x80 && c <= 0xbf) {
s = (filter->cache<<6) | (c & 0x3f);
filter->cache = 0;
if (filter->from->no_encoding == mbfl_no_encoding_utf8_docomo &&
mbfilter_conv_r_map_tbl(s, &s1, mbfl_docomo2uni_pua, 4) > 0) {
s = mbfilter_sjis_emoji_docomo2unicode(s1, &snd);
} else if (filter->from->no_encoding == mbfl_no_encoding_utf8_kddi_a &&
mbfilter_conv_r_map_tbl(s, &s1, mbfl_kddi2uni_pua, 7) > 0) {
s = mbfilter_sjis_emoji_kddi2unicode(s1, &snd);
} else if (filter->from->no_encoding == mbfl_no_encoding_utf8_kddi_b &&
mbfilter_conv_r_map_tbl(s, &s1, mbfl_kddi2uni_pua_b, 8) > 0) {
s = mbfilter_sjis_emoji_kddi2unicode(s1, &snd);
} else if (filter->from->no_encoding == mbfl_no_encoding_utf8_sb &&
mbfilter_conv_r_map_tbl(s, &s1, mbfl_sb2uni_pua, 6) > 0) {
s = mbfilter_sjis_emoji_sb2unicode(s1, &snd);
}
if (snd > 0) {
CK((*filter->output_function)(snd, filter->data));
}
CK((*filter->output_function)(s, filter->data));
} else {
mbfl_filt_put_invalid_char(filter->cache, filter);
goto retry;
}
break;
case 0x20: /* 3byte code 2nd char: 0:0xa0-0xbf,D:0x80-9F,1-C,E-F:0x80-0x9f */
s = (filter->cache<<6) | (c & 0x3f);
c1 = filter->cache & 0xf;
if ((c >= 0x80 && c <= 0xbf) &&
((c1 == 0x0 && c >= 0xa0) ||
(c1 == 0xd && c < 0xa0) ||
(c1 > 0x0 && c1 != 0xd))) {
filter->cache = s;
filter->status++;
} else {
mbfl_filt_put_invalid_char(filter->cache, filter);
goto retry;
}
break;
case 0x30: /* 4byte code 2nd char: 0:0x90-0xbf,1-3:0x80-0xbf,4:0x80-0x8f */
s = (filter->cache<<6) | (c & 0x3f);
c1 = filter->cache & 0x7;
if ((c >= 0x80 && c <= 0xbf) &&
((c1 == 0x0 && c >= 0x90) ||
(c1 == 0x4 && c < 0x90) ||
(c1 > 0x0 && c1 != 0x4))) {
filter->cache = s;
filter->status++;
} else {
mbfl_filt_put_invalid_char(filter->cache, filter);
goto retry;
}
break;
case 0x31: /* 4byte code 3rd char: 0x80-0xbf */
if (c >= 0x80 && c <= 0xbf) {
filter->cache = (filter->cache<<6) | (c & 0x3f);
filter->status++;
} else {
mbfl_filt_put_invalid_char(filter->cache, filter);
goto retry;
}
break;
default:
filter->status = 0;
break;
}
return c;

View File

@ -0,0 +1,29 @@
--TEST--
Bug #65045: mb_convert_encoding breaks well-formed character
--SKIPIF--
<?php extension_loaded('mbstring') or die('skip mbstring not available'); ?>
--FILE--
<?php
//declare(encoding = 'UTF-8');
mb_internal_encoding('UTF-8');
$str = "\xF0\xA4\xAD". "\xF0\xA4\xAD\xA2"."\xF0\xA4\xAD\xA2";
$expected = "\xEF\xBF\xBD"."\xF0\xA4\xAD\xA2"."\xF0\xA4\xAD\xA2";
$str2 = "\xF0\xA4\xAD\xA2"."\xF0\xA4\xAD\xA2"."\xF0\xA4\xAD";
$expected2 = "\xF0\xA4\xAD\xA2"."\xF0\xA4\xAD\xA2"."\xEF\xBF\xBD";
mb_substitute_character(0xFFFD);
var_dump(
$expected === htmlspecialchars_decode(htmlspecialchars($str, ENT_SUBSTITUTE, 'UTF-8')),
$expected2 === htmlspecialchars_decode(htmlspecialchars($str2, ENT_SUBSTITUTE, 'UTF-8')),
$expected === mb_convert_encoding($str, 'UTF-8', 'UTF-8'),
$expected2 === mb_convert_encoding($str2, 'UTF-8', 'UTF-8')
);
--EXPECT--
bool(true)
bool(true)
bool(true)
bool(true)

View File

@ -25,28 +25,28 @@ var_dump(chk_enc("\x31\x32\x33", 0));
var_dump(chk_enc("\x41\x42\x43", 0));
var_dump(chk_enc("\xc0\xb1\xc0\xb2\xc0\xb3", 6));
var_dump(chk_enc("\xc1\x81\xc1\x82\xc1\x83", 6));
var_dump(chk_enc("\xe0\x80\xb1\xe0\x80\xb2\xe0\x80\xb3", 6));
var_dump(chk_enc("\xe0\x81\x81\xe0\x81\x82\xe0\x81\x83", 6));
var_dump(chk_enc("\xf0\x80\x80\xb1\xf0\x80\x80\xb2\xf0\x80\x80\xb3", 9));
var_dump(chk_enc("\xf0\x80\x81\x81\xf0\x80\x81\x82\xf0\x81\x83", 8));
var_dump(chk_enc("\xe0\x80\xb1\xe0\x80\xb2\xe0\x80\xb3", 9));
var_dump(chk_enc("\xe0\x81\x81\xe0\x81\x82\xe0\x81\x83", 9));
var_dump(chk_enc("\xf0\x80\x80\xb1\xf0\x80\x80\xb2\xf0\x80\x80\xb3", 12));
var_dump(chk_enc("\xf0\x80\x81\x81\xf0\x80\x81\x82\xf0\x81\x83", 11));
var_dump(chk_enc("\xf8\x80\x80\x80\xb1\xf8\x80\x80\x80\xb2\xf8\x80\x80\x80\xb3", 15));
var_dump(chk_enc("\xf8\x80\x80\x81\x81\xf8\x80\x80\x81\x82\xf8\x80\x80\x81\x83", 15));
var_dump(chk_enc("\xfc\x80\x80\x80\x80\xb1\xfc\x80\x80\x80\x80\xb2\xfc\x80\x80\x80\x80\xb3", 18));
var_dump(chk_enc("\xfc\x80\x80\x80\x81\x81\xfc\x80\x80\x80\x81\x82\xfc\x80\x80\x80\x81\x83", 18));
var_dump(chk_enc("\xc2\xa2\xc2\xa3\xc2\xa5", 0));
var_dump(chk_enc("\xe0\x82\xa2\xe0\x82\xa3\xe0\x82\xa5", 6));
var_dump(chk_enc("\xf0\x80\x82\xa2\xf0\x80\x82\xa3\xf0\x80\x82\xa5", 9));
var_dump(chk_enc("\xe0\x82\xa2\xe0\x82\xa3\xe0\x82\xa5", 9));
var_dump(chk_enc("\xf0\x80\x82\xa2\xf0\x80\x82\xa3\xf0\x80\x82\xa5", 12));
var_dump(chk_enc("\xf8\x80\x80\x82\xa2\xf8\x80\x80\x82\xa3\xf8\x80\x80\x82\xa5", 15));
var_dump(chk_enc("\xfc\x80\x80\x80\x82\xa2\xfc\x80\x80\x80\x82\xa3\xfc\x80\x80\x80\x82\xa5", 18));
var_dump(chk_enc("\xc1\xbf", 2));
var_dump(chk_enc("\xc2\x80", 0));
var_dump(chk_enc("\xdf\xbf", 0));
var_dump(chk_enc("\xe0\x9f\xff", 2));
var_dump(chk_enc("\xe0\x9f\xff", 3));
var_dump(chk_enc("\xe0\xa0\x80", 2));
var_dump(chk_enc("\xef\xbf\xbf", 0));
var_dump(chk_enc("\xf0\x8f\xbf\xbf", 3));
var_dump(chk_enc("\xf0\x8f\xbf\xbf", 4));
var_dump(chk_enc("\xf0\x90\x80\x80", 0));
var_dump(chk_enc("\xf7\xbf\xbf\xbf", 4));
var_dump(chk_enc("\xf8\x87\xbf\xbf\xbf", 5));
@ -61,7 +61,7 @@ echo "UTF-8 and surrogates area\n";
$out = '';
$cnt = 0;
for ($i = 0xd7ff; $i <= 0xe000; ++$i) {
$s = chk_enc(pack('C3', 0xe0 | ($i >> 12), 0x80 | ($i >> 6) & 0x3f, 0x80 | $i & 0x3f), 2);
$s = chk_enc(pack('C3', 0xe0 | ($i >> 12), 0x80 | ($i >> 6) & 0x3f, 0x80 | $i & 0x3f), 3);
if ($s === false) {
$cnt++;
} else {

View File

@ -199,6 +199,10 @@ opcache.protect_memory (default "0")
Protect the shared memory from unexpected writing during script execution.
Useful for internal debugging only.
opcache.restrict_api (default "")
Allows calling OPcache API functions only from PHP scripts which path is
started from specified string. The default "" means no restriction.
opcache.mmap_base
Mapping base of shared memory segments (for Windows only). All the PHP
processes have to map shared memory into the same address space. This

View File

@ -232,6 +232,7 @@ typedef struct _zend_accel_directives {
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
long interned_strings_buffer;
#endif
char *restrict_api;
} zend_accel_directives;
typedef struct _zend_accel_globals {

View File

@ -0,0 +1,3 @@
<?php
echo "ok\n";
?>

View File

@ -9,7 +9,13 @@ opcache.blacklist_filename={PWD}/opcache-*.blacklist
--FILE--
<?php
$conf = opcache_get_configuration();
print_r($conf['blacklist']);
$conf = $conf['blacklist'];
$conf[3] = preg_replace("!^\\Q".dirname(__FILE__)."\\E!", "__DIR__", $conf[3]);
$conf[4] = preg_replace("!^\\Q".dirname(__FILE__)."\\E!", "__DIR__", $conf[4]);
print_r($conf);
include("blacklist.inc");
$status = opcache_get_status();
print_r(count($status['scripts']));
?>
--EXPECT--
Array
@ -17,4 +23,10 @@ Array
[0] => /path/to/foo
[1] => /path/to/foo2
[2] => /path/to/bar
)
[3] => __DIR__/blacklist.inc
[4] => __DIR__/current.php
[5] => /tmp/path/?nocache.inc
[6] => /tmp/path/*/somedir
)
ok
1

View File

@ -1 +1,6 @@
/path/to/bar
; wildcard and relative entires
blacklist.inc
./current.php
/tmp/path/?nocache.inc
/tmp/path/*/somedir

View File

@ -30,6 +30,10 @@
# include "main/php_regex.h"
#endif
#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
# include "ext/standard/php_string.h"
#endif
#ifdef ZEND_WIN32
# define REGEX_MODE (REG_EXTENDED|REG_NOSUB|REG_ICASE)
#else
@ -86,9 +90,9 @@ static void blacklist_report_regexp_error(regex_t *comp_regex, int reg_err)
static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist)
{
char *regexp;
int i, j, clen, reg_err, end = 0, rlen = 6;
int i, reg_err;
zend_regexp_list **regexp_list_it, *it;
char regexp[12*1024], *p, *end, *c, *backtrack = NULL;
if (blacklist->pos == 0) {
/* we have no blacklist to talk about */
@ -96,36 +100,91 @@ static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist)
}
regexp_list_it = &(blacklist->regexp_list);
for (i = 0; i < blacklist->pos; i++) {
rlen += blacklist->entries[i].path_length * 2 + 2;
/* don't create a regexp buffer bigger than 12K)*/
if ((i + 1 == blacklist->pos) || ((rlen + blacklist->entries[i + 1].path_length * 2 + 2) > (12 * 1024))) {
regexp = (char *)malloc(rlen);
if (!regexp) {
zend_accel_error(ACCEL_LOG_ERROR, "malloc() failed\n");
return;
}
regexp[0] = '^';
regexp[1] = '(';
regexp[0] = '^';
regexp[1] = '(';
p = regexp + 2;
end = regexp + sizeof(regexp) - sizeof("[^\\\\]*)\0");
clen = 2;
for (j = end; j <= i; j++) {
int c;
if (j != end) {
regexp[clen++] = '|';
}
/* copy mangled filename */
for (c = 0; c < blacklist->entries[j].path_length; c++) {
if (strchr("^.[]$()|*+?{}\\", blacklist->entries[j].path[c])) {
regexp[clen++] = '\\';
}
regexp[clen++] = blacklist->entries[j].path[c];
for (i = 0; i < blacklist->pos; ) {
c = blacklist->entries[i].path;
if (p + blacklist->entries[i].path_length < end) {
while (*c && p < end) {
switch (*c) {
case '?':
c++;
#ifdef ZEND_WIN32
p[0] = '['; /* * => [^\\] on Win32 */
p[1] = '^';
p[2] = '\\';
p[3] = '\\';
p[4] = ']';
p += 5;
#else
p[0] = '['; /* * => [^/] on *nix */
p[1] = '^';
p[2] = '/';
p[3] = ']';
p += 4;
#endif
break;
case '*':
c++;
if (*c == '*') {
c++;
p[0] = '.'; /* ** => .* */
p[1] = '*';
p += 2;
} else {
#ifdef ZEND_WIN32
p[0] = '['; /* * => [^\\]* on Win32 */
p[1] = '^';
p[2] = '\\';
p[3] = '\\';
p[4] = ']';
p[5] = '*';
p += 6;
#else
p[0] = '['; /* * => [^/]* on *nix */
p[1] = '^';
p[2] = '/';
p[3] = ']';
p[4] = '*';
p += 5;
#endif
}
break;
case '^':
case '.':
case '[':
case ']':
case '$':
case '(':
case ')':
case '|':
case '+':
case '{':
case '}':
case '\\':
*p++ = '\\';
/* break missing intentionally */
default:
*p++ = *c++;
}
}
regexp[clen++] = ')';
regexp[clen] = '\0';
}
if (*c || i == blacklist->pos - 1) {
if (*c) {
if (!backtrack) {
zend_accel_error(ACCEL_LOG_ERROR, "Too long blacklist entry\n");
}
p = backtrack;
} else {
i++;
}
*p++ = ')';
*p++ = '\0';
it = (zend_regexp_list*)malloc(sizeof(zend_regexp_list));
if (!it) {
@ -138,11 +197,13 @@ static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist)
blacklist_report_regexp_error(&it->comp_regex, reg_err);
}
/* prepare for the next iteration */
free(regexp);
end = i + 1;
rlen = 6;
p = regexp + 2;
*regexp_list_it = it;
regexp_list_it = &it->next;
} else {
backtrack = p;
*p++ = '|';
i++;
}
}
}
@ -182,9 +243,9 @@ static void zend_accel_blacklist_loadone(zend_blacklist *blacklist, char *filena
void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename)
#endif
{
char buf[MAXPATHLEN + 1], real_path[MAXPATHLEN + 1];
char buf[MAXPATHLEN + 1], real_path[MAXPATHLEN + 1], *blacklist_path = NULL;
FILE *fp;
int path_length;
int path_length, blacklist_path_length;
TSRMLS_FETCH();
if ((fp = fopen(filename, "r")) == NULL) {
@ -194,6 +255,15 @@ void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename)
zend_accel_error(ACCEL_LOG_DEBUG,"Loading blacklist file: '%s'", filename);
if (VCWD_REALPATH(filename, buf)) {
#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
blacklist_path_length = php_dirname(buf, strlen(buf));
#else
blacklist_path_length = zend_dirname(buf, strlen(buf));
#endif
blacklist_path = zend_strndup(buf, blacklist_path_length);
}
memset(buf, 0, sizeof(buf));
memset(real_path, 0, sizeof(real_path));
@ -230,7 +300,11 @@ void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename)
}
path_dup = zend_strndup(pbuf, path_length);
expand_filepath(path_dup, real_path TSRMLS_CC);
if (blacklist_path) {
expand_filepath_ex(path_dup, real_path, blacklist_path, blacklist_path_length TSRMLS_CC);
} else {
expand_filepath(path_dup, real_path TSRMLS_CC);
}
path_length = strlen(real_path);
free(path_dup);
@ -247,6 +321,9 @@ void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename)
blacklist->pos++;
}
fclose(fp);
if (blacklist_path) {
free(blacklist_path);
}
zend_accel_blacklist_update_regexp(blacklist);
}
@ -254,7 +331,8 @@ void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename)
void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename)
{
glob_t globbuf;
int ret, i;
int ret;
unsigned int i;
memset(&globbuf, 0, sizeof(glob_t));

View File

@ -71,6 +71,21 @@ static zend_function_entry accel_functions[] = {
{ NULL, NULL, NULL, 0, 0 }
};
static int validate_api_restriction(TSRMLS_D)
{
if (ZCG(accel_directives).restrict_api && *ZCG(accel_directives).restrict_api) {
int len = strlen(ZCG(accel_directives).restrict_api);
if (!SG(request_info).path_translated ||
strlen(SG(request_info).path_translated) < len ||
memcmp(SG(request_info).path_translated, ZCG(accel_directives).restrict_api, len) != 0) {
zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " API is restricted by \"restrict_api\" configuration directive");
return 0;
}
}
return 1;
}
static ZEND_INI_MH(OnUpdateMemoryConsumption)
{
long *p;
@ -251,6 +266,7 @@ ZEND_INI_BEGIN()
STD_PHP_INI_BOOLEAN("opcache.enable_file_override" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.file_override_enabled, zend_accel_globals, accel_globals)
STD_PHP_INI_BOOLEAN("opcache.enable_cli" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.enable_cli, zend_accel_globals, accel_globals)
STD_PHP_INI_ENTRY("opcache.error_log" , "" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.error_log, zend_accel_globals, accel_globals)
STD_PHP_INI_ENTRY("opcache.restrict_api" , "" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.restrict_api, zend_accel_globals, accel_globals)
#ifdef ZEND_WIN32
STD_PHP_INI_ENTRY("opcache.mmap_base", NULL, PHP_INI_SYSTEM, OnUpdateString, accel_directives.mmap_base, zend_accel_globals, accel_globals)
@ -517,6 +533,10 @@ static ZEND_FUNCTION(opcache_get_status)
return;
}
if (!validate_api_restriction(TSRMLS_C)) {
RETURN_FALSE;
}
if (!accel_startup_ok) {
RETURN_FALSE;
}
@ -587,6 +607,10 @@ static ZEND_FUNCTION(opcache_get_configuration)
}
#endif
if (!validate_api_restriction(TSRMLS_C)) {
RETURN_FALSE;
}
array_init(return_value);
/* directives */
@ -651,6 +675,10 @@ static ZEND_FUNCTION(opcache_reset)
}
#endif
if (!validate_api_restriction(TSRMLS_C)) {
RETURN_FALSE;
}
if (!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled)) {
RETURN_FALSE;
}
@ -671,6 +699,10 @@ static ZEND_FUNCTION(opcache_invalidate)
return;
}
if (!validate_api_restriction(TSRMLS_C)) {
RETURN_FALSE;
}
if (zend_accel_invalidate(script_name, script_name_len, force TSRMLS_CC) == SUCCESS) {
RETURN_TRUE;
} else {

View File

@ -1081,6 +1081,14 @@ static int schema_group(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr groupType, sdlTyp
nsptr = xmlSearchNs(groupType->doc, groupType, BAD_CAST(ns));
if (nsptr != NULL) {
smart_str_appends(&key, (char*)nsptr->href);
} else {
xmlAttrPtr ns = get_attribute(groupType->properties, "targetNamespace");
if (ns == NULL) {
ns = tns;
}
if (ns) {
smart_str_appends(&key, (char*)ns->children->content);
}
}
smart_str_appendc(&key, ':');
smart_str_appends(&key, type);
@ -1509,6 +1517,14 @@ static int schema_element(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr element, sdlTyp
if (nsptr != NULL) {
smart_str_appends(&nscat, (char*)nsptr->href);
newType->namens = estrdup((char*)nsptr->href);
} else {
xmlAttrPtr ns = get_attribute(attrs, "targetNamespace");
if (ns == NULL) {
ns = tns;
}
if (ns) {
smart_str_appends(&nscat, (char*)ns->children->content);
}
}
smart_str_appendc(&nscat, ':');
smart_str_appends(&nscat, type);
@ -1735,6 +1751,14 @@ static int schema_attribute(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrType, sdl
if (nsptr != NULL) {
smart_str_appends(&key, (char*)nsptr->href);
newAttr->namens = estrdup((char*)nsptr->href);
} else {
xmlAttrPtr ns = get_attribute(attrType->properties, "targetNamespace");
if (ns == NULL) {
ns = tns;
}
if (ns) {
smart_str_appends(&key, (char*)ns->children->content);
}
}
smart_str_appendc(&key, ':');
smart_str_appends(&key, attr_name);
@ -2036,13 +2060,31 @@ static void copy_extra_attribute(void *attribute)
}
}
static void* schema_find_by_ref(HashTable *ht, char *ref)
{
void **tmp;
if (zend_hash_find(ht, ref, strlen(ref)+1, (void**)&tmp) == SUCCESS) {
return tmp;
} else {
ref = strrchr(ref, ':');
if (ref) {
if (zend_hash_find(ht, ref, strlen(ref)+1, (void**)&tmp) == SUCCESS) {
return tmp;
}
}
}
return NULL;
}
static void schema_attribute_fixup(sdlCtx *ctx, sdlAttributePtr attr)
{
sdlAttributePtr *tmp;
if (attr->ref != NULL) {
if (ctx->attributes != NULL) {
if (zend_hash_find(ctx->attributes, attr->ref, strlen(attr->ref)+1, (void**)&tmp) == SUCCESS) {
tmp = (sdlAttributePtr*)schema_find_by_ref(ctx->attributes, attr->ref);
if (tmp) {
schema_attribute_fixup(ctx, *tmp);
if ((*tmp)->name != NULL && attr->name == NULL) {
attr->name = estrdup((*tmp)->name);
@ -2092,7 +2134,8 @@ static void schema_attributegroup_fixup(sdlCtx *ctx, sdlAttributePtr attr, HashT
if (attr->ref != NULL) {
if (ctx->attributeGroups != NULL) {
if (zend_hash_find(ctx->attributeGroups, attr->ref, strlen(attr->ref)+1, (void**)&tmp) == SUCCESS) {
tmp = (sdlTypePtr*)schema_find_by_ref(ctx->attributeGroups, attr->ref);
if (tmp) {
if ((*tmp)->attributes) {
zend_hash_internal_pointer_reset((*tmp)->attributes);
while (zend_hash_get_current_data((*tmp)->attributes,(void**)&tmp_attr) == SUCCESS) {
@ -2149,7 +2192,7 @@ static void schema_content_model_fixup(sdlCtx *ctx, sdlContentModelPtr model)
model->kind = XSD_CONTENT_GROUP;
model->u.group = (*tmp);
} else {
soap_error0(E_ERROR, "Parsing Schema: unresolved group 'ref' attribute");
soap_error1(E_ERROR, "Parsing Schema: unresolved group 'ref' attribute '%s'", model->u.group_ref);
}
break;
}
@ -2193,7 +2236,8 @@ static void schema_type_fixup(sdlCtx *ctx, sdlTypePtr type)
if (type->ref != NULL) {
if (ctx->sdl->elements != NULL) {
if (zend_hash_find(ctx->sdl->elements, type->ref, strlen(type->ref)+1, (void**)&tmp) == SUCCESS) {
tmp = (sdlTypePtr*)schema_find_by_ref(ctx->sdl->elements, type->ref);
if (tmp) {
type->kind = (*tmp)->kind;
type->encode = (*tmp)->encode;
if ((*tmp)->nillable) {
@ -2209,7 +2253,7 @@ static void schema_type_fixup(sdlCtx *ctx, sdlTypePtr type)
} else if (strcmp(type->ref, SCHEMA_NAMESPACE ":schema") == 0) {
type->encode = get_conversion(XSD_ANYXML);
} else {
soap_error0(E_ERROR, "Parsing Schema: unresolved element 'ref' attribute");
soap_error1(E_ERROR, "Parsing Schema: unresolved element 'ref' attribute '%s'", type->ref);
}
}
efree(type->ref);

View File

@ -3669,7 +3669,44 @@ ignore_header:
return function;
}
static int serialize_response_call2(xmlNodePtr body, sdlFunctionPtr function, char *function_name, char *uri, zval *ret, int version, int main TSRMLS_DC)
static void set_soap_header_attributes(xmlNodePtr h, HashTable *ht, int version)
{
zval **tmp;
if (zend_hash_find(ht, "mustUnderstand", sizeof("mustUnderstand"), (void**)&tmp) == SUCCESS &&
Z_TYPE_PP(tmp) == IS_BOOL && Z_LVAL_PP(tmp)) {
if (version == SOAP_1_1) {
xmlSetProp(h, BAD_CAST(SOAP_1_1_ENV_NS_PREFIX":mustUnderstand"), BAD_CAST("1"));
} else {
xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":mustUnderstand"), BAD_CAST("true"));
}
}
if (zend_hash_find(ht, "actor", sizeof("actor"), (void**)&tmp) == SUCCESS) {
if (Z_TYPE_PP(tmp) == IS_STRING) {
if (version == SOAP_1_1) {
xmlSetProp(h, BAD_CAST(SOAP_1_1_ENV_NS_PREFIX":actor"), BAD_CAST(Z_STRVAL_PP(tmp)));
} else {
xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(Z_STRVAL_PP(tmp)));
}
} else if (Z_TYPE_PP(tmp) == IS_LONG) {
if (version == SOAP_1_1) {
if (Z_LVAL_PP(tmp) == SOAP_ACTOR_NEXT) {
xmlSetProp(h, BAD_CAST(SOAP_1_1_ENV_NS_PREFIX":actor"), BAD_CAST(SOAP_1_1_ACTOR_NEXT));
}
} else {
if (Z_LVAL_PP(tmp) == SOAP_ACTOR_NEXT) {
xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(SOAP_1_2_ACTOR_NEXT));
} else if (Z_LVAL_PP(tmp) == SOAP_ACTOR_NONE) {
xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(SOAP_1_2_ACTOR_NONE));
} else if (Z_LVAL_PP(tmp) == SOAP_ACTOR_UNLIMATERECEIVER) {
xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(SOAP_1_2_ACTOR_UNLIMATERECEIVER));
}
}
}
}
}
static int serialize_response_call2(xmlNodePtr body, sdlFunctionPtr function, char *function_name, char *uri, zval *ret, int version, int main, xmlNodePtr *node TSRMLS_DC)
{
xmlNodePtr method = NULL, param;
sdlParamPtr parameter = NULL;
@ -3769,6 +3806,9 @@ static int serialize_response_call2(xmlNodePtr body, sdlFunctionPtr function, ch
if (use == SOAP_ENCODED && version == SOAP_1_2 && method != NULL) {
xmlSetNsProp(method, body->ns, BAD_CAST("encodingStyle"), BAD_CAST(SOAP_1_2_ENC_NAMESPACE));
}
if (node) {
*node = method;
}
return use;
}
@ -3850,7 +3890,7 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
}
if (headers->function) {
if (serialize_response_call2(head, headers->function, Z_STRVAL(headers->function_name), uri, hdr_ret, version, 0 TSRMLS_CC) == SOAP_ENCODED) {
if (serialize_response_call2(head, headers->function, Z_STRVAL(headers->function_name), uri, hdr_ret, version, 0, NULL TSRMLS_CC) == SOAP_ENCODED) {
use = SOAP_ENCODED;
}
} else {
@ -4036,15 +4076,15 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
zval *hdr_ret = &h->retval;
char *hdr_ns = h->hdr?h->hdr->ns:NULL;
char *hdr_name = Z_STRVAL(h->function_name);
HashTable *ht = NULL;
if (Z_TYPE(h->retval) == IS_OBJECT &&
instanceof_function(Z_OBJCE(h->retval), soap_header_class_entry TSRMLS_CC)) {
HashTable* ht = Z_OBJPROP(h->retval);
zval **tmp;
sdlSoapBindingFunctionHeaderPtr *hdr;
smart_str key = {0};
ht = Z_OBJPROP(h->retval);
if (zend_hash_find(ht, "namespace", sizeof("namespace"), (void**)&tmp) == SUCCESS &&
Z_TYPE_PP(tmp) == IS_STRING) {
smart_str_appendl(&key, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
@ -4075,9 +4115,14 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
}
if (h->function) {
if (serialize_response_call2(head, h->function, Z_STRVAL(h->function_name), uri, hdr_ret, version, 0 TSRMLS_CC) == SOAP_ENCODED) {
xmlNodePtr xmlHdr = NULL;
if (serialize_response_call2(head, h->function, Z_STRVAL(h->function_name), uri, hdr_ret, version, 0, &xmlHdr TSRMLS_CC) == SOAP_ENCODED) {
use = SOAP_ENCODED;
}
if (ht) {
set_soap_header_attributes(xmlHdr, ht, version);
}
} else {
xmlNodePtr xmlHdr = master_to_xml(hdr_enc, hdr_ret, hdr_use, head TSRMLS_CC);
if (hdr_name) {
@ -4087,6 +4132,9 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
xmlNsPtr nsptr = encode_add_ns(xmlHdr,hdr_ns);
xmlSetNs(xmlHdr, nsptr);
}
if (ht) {
set_soap_header_attributes(xmlHdr, ht, version);
}
}
}
h = h->next;
@ -4100,7 +4148,7 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
body = xmlNewChild(envelope, ns, BAD_CAST("Body"), NULL);
if (serialize_response_call2(body, function, function_name, uri, ret, version, 1 TSRMLS_CC) == SOAP_ENCODED) {
if (serialize_response_call2(body, function, function_name, uri, ret, version, 1, NULL TSRMLS_CC) == SOAP_ENCODED) {
use = SOAP_ENCODED;
}
@ -4292,38 +4340,7 @@ static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function
}
nsptr = encode_add_ns(h, Z_STRVAL_PP(ns));
xmlSetNs(h, nsptr);
if (zend_hash_find(ht, "mustUnderstand", sizeof("mustUnderstand"), (void**)&tmp) == SUCCESS &&
Z_TYPE_PP(tmp) == IS_BOOL && Z_LVAL_PP(tmp)) {
if (version == SOAP_1_1) {
xmlSetProp(h, BAD_CAST(SOAP_1_1_ENV_NS_PREFIX":mustUnderstand"), BAD_CAST("1"));
} else {
xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":mustUnderstand"), BAD_CAST("true"));
}
}
if (zend_hash_find(ht, "actor", sizeof("actor"), (void**)&tmp) == SUCCESS) {
if (Z_TYPE_PP(tmp) == IS_STRING) {
if (version == SOAP_1_1) {
xmlSetProp(h, BAD_CAST(SOAP_1_1_ENV_NS_PREFIX":actor"), BAD_CAST(Z_STRVAL_PP(tmp)));
} else {
xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(Z_STRVAL_PP(tmp)));
}
} else if (Z_TYPE_PP(tmp) == IS_LONG) {
if (version == SOAP_1_1) {
if (Z_LVAL_PP(tmp) == SOAP_ACTOR_NEXT) {
xmlSetProp(h, BAD_CAST(SOAP_1_1_ENV_NS_PREFIX":actor"), BAD_CAST(SOAP_1_1_ACTOR_NEXT));
}
} else {
if (Z_LVAL_PP(tmp) == SOAP_ACTOR_NEXT) {
xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(SOAP_1_2_ACTOR_NEXT));
} else if (Z_LVAL_PP(tmp) == SOAP_ACTOR_NONE) {
xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(SOAP_1_2_ACTOR_NONE));
} else if (Z_LVAL_PP(tmp) == SOAP_ACTOR_UNLIMATERECEIVER) {
xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(SOAP_1_2_ACTOR_UNLIMATERECEIVER));
}
}
}
}
set_soap_header_attributes(h, ht, version);
}
zend_hash_move_forward(soap_headers);
}

View File

@ -0,0 +1,28 @@
--TEST--
Bug #65018 (SoapHeader problems with SoapServer)
--SKIPIF--
<?php require_once('skipif.inc'); ?>
--FILE--
<?php
class Tool{
public function TOKEN($id){
return new SoapHeader('namespace1', 'TOKEN', $id, true);
}
public function Method(){}
}
$input = $input =
'<?xml version="1.0"?>'.PHP_EOL.
'<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="namespace1"'.
' xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'.
' xmlns:xsd="http://www.w3.org/2001/XMLSchema">'.
'<SOAP-ENV:Header><ns1:TOKEN soapenv:mustUnderstand="1">abc</ns1:TOKEN></SOAP-ENV:Header>'.
'<SOAP-ENV:Body><ns1:Method /></SOAP-ENV:Body></SOAP-ENV:Envelope>';
$soap = new SoapServer(null, array('uri' => '127.0.0.1'));
$soap->setClass('Tool');
$soap->handle($input);
?>
--EXPECT--
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="namespace1" xmlns:ns2="127.0.0.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Header><ns1:TOKEN SOAP-ENV:mustUnderstand="1">abc</ns1:TOKEN></SOAP-ENV:Header><SOAP-ENV:Body><ns2:MethodResponse><return xsi:nil="true"/></ns2:MethodResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>