mirror of
https://github.com/php/php-src.git
synced 2024-11-24 02:15:04 +08:00
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:
commit
0625d5ce67
7
NEWS
7
NEWS
@ -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
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
29
ext/mbstring/tests/bug65045.phpt
Normal file
29
ext/mbstring/tests/bug65045.phpt
Normal 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)
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
3
ext/opcache/tests/blacklist.inc
Normal file
3
ext/opcache/tests/blacklist.inc
Normal file
@ -0,0 +1,3 @@
|
||||
<?php
|
||||
echo "ok\n";
|
||||
?>
|
@ -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
|
||||
|
@ -1 +1,6 @@
|
||||
/path/to/bar
|
||||
; wildcard and relative entires
|
||||
blacklist.inc
|
||||
./current.php
|
||||
/tmp/path/?nocache.inc
|
||||
/tmp/path/*/somedir
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
28
ext/soap/tests/bugs/bug65018.phpt
Normal file
28
ext/soap/tests/bugs/bug65018.phpt
Normal 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>
|
Loading…
Reference in New Issue
Block a user