--- /dev/null
+--TEST--
+Stream: RFC2397 getting meta data
+--FILE--
+<?php
+
+$streams = array(
+ 'data://,',
+ 'data://',
+ 'data://;base64,',
+ 'data://;base64',
+ 'data://foo,',
+ 'data://foo=bar,',
+ 'data://text/plain,',
+ 'data://text/plain;foo,',
+ 'data://text/plain;foo=bar,',
+ 'data://text/plain;foo=bar;bla,',
+ 'data://text/plain;foo=bar;base64,',
+ 'data://text/plain;foo=bar;bar=baz',
+ 'data://text/plain;foo=bar;bar=baz,',
+ );
+
+foreach($streams as $stream)
+{
+ $stream = fopen($stream, 'r');
+ $meta = @stream_get_meta_data($stream);
+ var_dump($meta);
+ var_dump(isset($meta['foo']) ? $meta['foo'] : null);
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+array(7) {
+ ["wrapper_type"]=>
+ string(7) "RFC2397"
+ ["stream_type"]=>
+ string(7) "RFC2397"
+ ["mode"]=>
+ string(1) "r"
+ ["unread_bytes"]=>
+ int(0)
+ ["seekable"]=>
+ bool(true)
+ ["uri"]=>
+ string(8) "data://,"
+ ["base64"]=>
+ bool(false)
+}
+NULL
+
+Warning: fopen(data://): failed to open stream: rfc2397: no comma in url in %sstream_rfc2397_002.php on line %d
+bool(false)
+NULL
+array(7) {
+ ["wrapper_type"]=>
+ string(7) "RFC2397"
+ ["stream_type"]=>
+ string(7) "RFC2397"
+ ["mode"]=>
+ string(1) "r"
+ ["unread_bytes"]=>
+ int(0)
+ ["seekable"]=>
+ bool(true)
+ ["uri"]=>
+ string(15) "data://;base64,"
+ ["base64"]=>
+ bool(true)
+}
+NULL
+
+Warning: fopen(data://;base64): failed to open stream: rfc2397: no comma in url in %sstream_rfc2397_002.php on line %d
+bool(false)
+NULL
+
+Warning: fopen(data://foo,): failed to open stream: rfc2397: illegal media type in %sstream_rfc2397_002.php on line %d
+bool(false)
+NULL
+
+Warning: fopen(data://foo=bar,): failed to open stream: rfc2397: illegal media type in %sstream_rfc2397_002.php on line %d
+bool(false)
+NULL
+array(8) {
+ ["wrapper_type"]=>
+ string(7) "RFC2397"
+ ["stream_type"]=>
+ string(7) "RFC2397"
+ ["mode"]=>
+ string(1) "r"
+ ["unread_bytes"]=>
+ int(0)
+ ["seekable"]=>
+ bool(true)
+ ["uri"]=>
+ string(18) "data://text/plain,"
+ ["mediatype"]=>
+ string(10) "text/plain"
+ ["base64"]=>
+ bool(false)
+}
+NULL
+
+Warning: fopen(data://text/plain;foo,): failed to open stream: rfc2397: illegal parameter in %sstream_rfc2397_002.php on line %d
+bool(false)
+NULL
+array(9) {
+ ["wrapper_type"]=>
+ string(7) "RFC2397"
+ ["stream_type"]=>
+ string(7) "RFC2397"
+ ["mode"]=>
+ string(1) "r"
+ ["unread_bytes"]=>
+ int(0)
+ ["seekable"]=>
+ bool(true)
+ ["uri"]=>
+ string(26) "data://text/plain;foo=bar,"
+ ["mediatype"]=>
+ string(10) "text/plain"
+ ["foo"]=>
+ string(3) "bar"
+ ["base64"]=>
+ bool(false)
+}
+string(3) "bar"
+
+Warning: fopen(data://text/plain;foo=bar;bla,): failed to open stream: rfc2397: illegal parameter in %sstream_rfc2397_002.php on line %d
+bool(false)
+NULL
+array(9) {
+ ["wrapper_type"]=>
+ string(7) "RFC2397"
+ ["stream_type"]=>
+ string(7) "RFC2397"
+ ["mode"]=>
+ string(1) "r"
+ ["unread_bytes"]=>
+ int(0)
+ ["seekable"]=>
+ bool(true)
+ ["uri"]=>
+ string(33) "data://text/plain;foo=bar;base64,"
+ ["mediatype"]=>
+ string(10) "text/plain"
+ ["foo"]=>
+ string(3) "bar"
+ ["base64"]=>
+ bool(true)
+}
+string(3) "bar"
+
+Warning: fopen(data://text/plain;foo=bar;bar=baz): failed to open stream: rfc2397: no comma in url in %sstream_rfc2397_002.php on line %d
+bool(false)
+NULL
+array(10) {
+ ["wrapper_type"]=>
+ string(7) "RFC2397"
+ ["stream_type"]=>
+ string(7) "RFC2397"
+ ["mode"]=>
+ string(1) "r"
+ ["unread_bytes"]=>
+ int(0)
+ ["seekable"]=>
+ bool(true)
+ ["uri"]=>
+ string(34) "data://text/plain;foo=bar;bar=baz,"
+ ["mediatype"]=>
+ string(10) "text/plain"
+ ["foo"]=>
+ string(3) "bar"
+ ["bar"]=>
+ string(3) "baz"
+ ["base64"]=>
+ bool(false)
+}
+string(3) "bar"
+===DONE===
\ No newline at end of file
{
php_stream *stream;
php_stream_temp_data *ts;
- char *comma, *semi;
- size_t mlen, dlen;
+ char *comma, *semi, *sep, *key;
+ size_t mlen, dlen, plen, vlen;
off_t newoffs;
+ zval *meta = NULL;
+ int base64 = 0;
if (memcmp(path, "data:", 5)) {
return NULL;
return NULL;
}
- if ((stream = php_stream_temp_create_rel(0, ~0u)) != NULL) {
- if (comma != path) {
- /* meta info */
- mlen = comma - path;
- dlen -= mlen;
+ if (comma != path) {
+ /* meta info */
+ mlen = comma - path;
+ dlen -= mlen;
+ semi = memchr(path, ';', mlen);
+ sep = memchr(path, '/', mlen);
+
+ if (!semi && !sep) {
+ php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "rfc2397: illegal media type");
+ return NULL;
+ }
+
+ MAKE_STD_ZVAL(meta);
+ array_init(meta);
+ if (!semi) { /* there is only a mime type */
+ add_assoc_stringl(meta, "mediatype", path, mlen, 1);
+ mlen = 0;
+ } else if (sep && sep < semi) { /* there is a mime type */
+ plen = semi - path;
+ add_assoc_stringl(meta, "mediatype", path, plen, 1);
+ mlen -= plen;
+ path += plen;
+ } else if (semi != path || mlen != sizeof(";base64")-1 || memcmp(path, ";base64", sizeof(";base64")-1)) { /* must be error since parameters are only allowed after mediatype */
+ zval_ptr_dtor(&meta);
+ php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "rfc2397: illegal media type");
+ return NULL;
+ }
+ /* get parameters and potentially ';base64' */
+ while(semi && (semi == path)) {
+ path++;
+ mlen--;
+ sep = memchr(path, '=', mlen);
semi = memchr(path, ';', mlen);
+ if (!sep || (semi && semi < sep)) { /* must be ';base64' or failure */
+ if (mlen != sizeof("base64")-1 || memcmp(path, "base64", sizeof("base64")-1)) {
+ /* must be error since parameters are only allowed after mediatype and we have no '=' sign */
+ zval_ptr_dtor(&meta);
+ php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "rfc2397: illegal parameter");
+ return NULL;
+ }
+ base64 = 1;
+ mlen -= sizeof("base64") - 1;
+ path += sizeof("base64") - 1;
+ break;
+ }
+ /* found parameter ... the heart of cs ppl lies in +1/-1 or was it +2 this time? */
+ plen = sep - path;
+ vlen = (semi ? semi - sep : mlen - plen) - 1 /* '=' */;
+ key = estrndup(path, plen);
+ add_assoc_stringl_ex(meta, key, plen + 1, sep + 1, vlen, 1);
+ efree(key);
+ plen += vlen + 1;
+ mlen -= plen;
+ path += plen;
}
+ if (mlen) {
+ zval_ptr_dtor(&meta);
+ php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "rfc2397: illegal url");
+ return NULL;
+ }
+ } else {
+ MAKE_STD_ZVAL(meta);
+ array_init(meta);
+ }
+ add_assoc_bool(meta, "base64", base64);
+
+ if ((stream = php_stream_temp_create_rel(0, ~0u)) != NULL) {
/* skip ',' */
comma++;
dlen--;
/* store data */
php_stream_temp_write(stream, comma, dlen TSRMLS_CC);
php_stream_temp_seek(stream, 0, SEEK_SET, &newoffs TSRMLS_CC);
+ /* set special stream stuff (enforce exact mode) */
+ vlen = strlen(mode);
+ if (vlen >= sizeof(stream->mode)) {
+ vlen = sizeof(stream->mode) - 1;
+ }
+ memcpy(stream->mode, mode, vlen);
+ stream->mode[vlen] = '\0';
+ stream->ops = &php_stream_rfc2397_ops;
ts = (php_stream_temp_data*)stream->abstract;
assert(ts != NULL);
ts->mode = mode && mode[0] == 'r' ? TEMP_STREAM_READONLY : 0;
+ ts->meta = meta;
}
return stream;