mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
[RFC] Add stream open functions to XML{Reader,Writer}
RFC: https://wiki.php.net/rfc/xmlreader_writer_streams
This commit is contained in:
@@ -167,8 +167,7 @@ static zend_function *xmlreader_get_method(zend_object **obj, zend_string *name,
|
||||
/* There are only two static internal methods and they both have overrides. */
|
||||
if (ZSTR_LEN(name) == sizeof("xml") - 1) {
|
||||
return (zend_function *) &xmlreader_xml_fn;
|
||||
} else {
|
||||
ZEND_ASSERT(ZSTR_LEN(name) == sizeof("open") - 1);
|
||||
} else if (ZSTR_LEN(name) == sizeof("open") - 1) {
|
||||
return (zend_function *) &xmlreader_open_fn;
|
||||
}
|
||||
}
|
||||
@@ -799,6 +798,22 @@ PHP_METHOD(XMLReader, next)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static bool xmlreader_valid_encoding(const char *encoding)
|
||||
{
|
||||
if (!encoding) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Normally we could use xmlTextReaderConstEncoding() afterwards but libxml2 < 2.12.0 has a bug of course
|
||||
* where it returns NULL for some valid encodings instead. */
|
||||
xmlCharEncodingHandlerPtr handler = xmlFindCharEncodingHandler(encoding);
|
||||
if (!handler) {
|
||||
return false;
|
||||
}
|
||||
xmlCharEncCloseFunc(handler);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* {{{ Sets the URI that the XMLReader will parse. */
|
||||
PHP_METHOD(XMLReader, open)
|
||||
{
|
||||
@@ -811,7 +826,7 @@ PHP_METHOD(XMLReader, open)
|
||||
char resolved_path[MAXPATHLEN + 1];
|
||||
xmlTextReaderPtr reader = NULL;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|s!l", &source, &source_len, &encoding, &encoding_len, &options) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|p!l", &source, &source_len, &encoding, &encoding_len, &options) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
@@ -827,9 +842,9 @@ PHP_METHOD(XMLReader, open)
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
if (encoding && CHECK_NULL_PATH(encoding, encoding_len)) {
|
||||
php_error_docref(NULL, E_WARNING, "Encoding must not contain NUL bytes");
|
||||
RETURN_FALSE;
|
||||
if (!xmlreader_valid_encoding(encoding)) {
|
||||
zend_argument_value_error(2, "must be a valid character encoding");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
valid_file = _xmlreader_get_valid_file_path(source, resolved_path, MAXPATHLEN );
|
||||
@@ -859,6 +874,76 @@ PHP_METHOD(XMLReader, open)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int xml_reader_stream_read(void *context, char *buffer, int len)
|
||||
{
|
||||
zend_resource *resource = context;
|
||||
if (EXPECTED(resource->ptr)) {
|
||||
php_stream *stream = resource->ptr;
|
||||
return php_stream_read(stream, buffer, len);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int xml_reader_stream_close(void *context)
|
||||
{
|
||||
zend_resource *resource = context;
|
||||
/* Don't close it as others may still use it! We don't own the resource!
|
||||
* Just delete our reference (and clean up if we're the last one). */
|
||||
zend_list_delete(resource);
|
||||
return 0;
|
||||
}
|
||||
|
||||
PHP_METHOD(XMLReader, fromStream)
|
||||
{
|
||||
zval *stream_zv;
|
||||
php_stream *stream;
|
||||
char *document_uri = NULL;
|
||||
char *encoding_name = NULL;
|
||||
size_t document_uri_len, encoding_name_len;
|
||||
zend_long flags = 0;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(1, 4)
|
||||
Z_PARAM_RESOURCE(stream_zv);
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_PATH_OR_NULL(encoding_name, encoding_name_len)
|
||||
Z_PARAM_LONG(flags)
|
||||
Z_PARAM_PATH_OR_NULL(document_uri, document_uri_len)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
php_stream_from_res(stream, Z_RES_P(stream_zv));
|
||||
|
||||
if (!xmlreader_valid_encoding(encoding_name)) {
|
||||
zend_argument_value_error(2, "must be a valid character encoding");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
PHP_LIBXML_SANITIZE_GLOBALS(reader_for_stream);
|
||||
xmlTextReaderPtr reader = xmlReaderForIO(
|
||||
xml_reader_stream_read,
|
||||
xml_reader_stream_close,
|
||||
stream->res,
|
||||
document_uri,
|
||||
encoding_name,
|
||||
flags
|
||||
);
|
||||
PHP_LIBXML_RESTORE_GLOBALS(reader_for_stream);
|
||||
|
||||
if (UNEXPECTED(reader == NULL)) {
|
||||
zend_throw_error(NULL, "Could not construct libxml reader");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
/* When the reader is closed (even in error paths) the reference is destroyed. */
|
||||
Z_ADDREF_P(stream_zv);
|
||||
|
||||
if (object_init_with_constructor(return_value, Z_CE_P(ZEND_THIS), 0, NULL, NULL) == SUCCESS) {
|
||||
xmlreader_object *intern = Z_XMLREADER_P(return_value);
|
||||
intern->ptr = reader;
|
||||
} else {
|
||||
xmlFreeTextReader(reader);
|
||||
}
|
||||
}
|
||||
|
||||
/* Not Yet Implemented in libxml - functions exist just not coded
|
||||
PHP_METHOD(XMLReader, resetState)
|
||||
{
|
||||
@@ -995,7 +1080,7 @@ PHP_METHOD(XMLReader, XML)
|
||||
xmlParserInputBufferPtr inputbfr;
|
||||
xmlTextReaderPtr reader;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s!l", &source, &source_len, &encoding, &encoding_len, &options) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|p!l", &source, &source_len, &encoding, &encoding_len, &options) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
@@ -1011,9 +1096,9 @@ PHP_METHOD(XMLReader, XML)
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
if (encoding && CHECK_NULL_PATH(encoding, encoding_len)) {
|
||||
php_error_docref(NULL, E_WARNING, "Encoding must not contain NUL bytes");
|
||||
RETURN_FALSE;
|
||||
if (!xmlreader_valid_encoding(encoding)) {
|
||||
zend_argument_value_error(2, "must be a valid character encoding");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
inputbfr = xmlParserInputBufferCreateMem(source, source_len, XML_CHAR_ENCODING_NONE);
|
||||
|
||||
Reference in New Issue
Block a user