Skip to content

Remove requirement for authority portion of user stream wrapper URIs #2331

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions ext/standard/tests/file/userwrapper_001.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
--TEST--
Userstream with STREAM_IS_URI flag unlink, rename, mkdir, rmdir, and url_stat.
--FILE--
<?php # vim:ft=php:
class test {
function unlink($file) {
print "Unlinking file: $file\n";
}

function rename($from, $to) {
print "Renaming $from to $to\n";
}

function mkdir($directory, $mode, $options) {
printf("Making directory: %s as %o%s\n", $directory, $mode, $options & STREAM_MKDIR_RECURSIVE ? " recursively" : "");
}

function rmdir($directory, $options) {
print "Removing directory: $directory\n";
}

function url_stat($path, $options) {
/* By printing out a notice that we are actively stating the file
then subsequently performing multiple stat operations on it
we effectively test the stat cache mechanism */
print "Stating file: $path\n";
return array('dev'=>1, 'ino'=>2, 'mode'=>0644, 'nlink'=>3,
'uid'=>100, 'gid'=>1000, 'rdev'=>-1, 'size'=>31337,
'atime'=>1234567890, 'mtime'=>1231231231, 'ctime'=>1234564564,
'blksize'=>-1, 'blocks'=>-1);
}
}

stream_wrapper_register('test', 'test', STREAM_IS_URI);

unlink('test:example.com/path/to/file');
rename('test:example.com/path/to/from', 'test:example.com/path/to/to');
/* We *want* this to fail and thus not output the watch statement */
@rename('test:example.com/path/to/from', 'http://example.com/path/to/to');
mkdir('test:example.com/path/to/directory', 0755);
rmdir('test:example.com/path/to/directory');
print_r(stat('test:example.com/path/to/file'));
echo "Filesize = " . filesize('test:example.com/path/to/file') . "\n";
echo "filemtime = " . filemtime('test:example.com/path/to/file') . "\n";
?>
--EXPECT--
Unlinking file: test:example.com/path/to/file
Renaming test:example.com/path/to/from to test:example.com/path/to/to
Making directory: test:example.com/path/to/directory as 755
Removing directory: test:example.com/path/to/directory
Stating file: test:example.com/path/to/file
Array
(
[0] => 1
[1] => 2
[2] => 420
[3] => 3
[4] => 100
[5] => 1000
[6] => -1
[7] => 31337
[8] => 1234567890
[9] => 1231231231
[10] => 1234564564
[11] => -1
[12] => -1
[dev] => 1
[ino] => 2
[mode] => 420
[nlink] => 3
[uid] => 100
[gid] => 1000
[rdev] => -1
[size] => 31337
[atime] => 1234567890
[mtime] => 1231231231
[ctime] => 1234564564
[blksize] => -1
[blocks] => -1
)
Filesize = 31337
filemtime = 1231231231

2 changes: 2 additions & 0 deletions main/php_streams.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ struct _php_stream_wrapper {
php_stream_wrapper_ops *wops; /* operations the wrapper can perform */
void *abstract; /* context for the wrapper */
int is_url; /* so that PG(allow_url_fopen) can be respected */
int is_uri; /* so that scheme complies with RFC 2396 and opaque_part (without leading "//"" after ":") can be respected */
};

#define PHP_STREAM_FLAG_NO_SEEK 0x1
Expand Down Expand Up @@ -599,6 +600,7 @@ END_EXTERN_C()

/* Definitions for user streams */
#define PHP_STREAM_IS_URL 1
#define PHP_STREAM_IS_URI 2

/* Stream metadata definitions */
/* Create if referred resource does not exist */
Expand Down
1 change: 1 addition & 0 deletions main/streams/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,7 @@ PHPAPI php_stream_wrapper php_stream_rfc2397_wrapper = {
&php_stream_rfc2397_wops,
NULL,
1, /* is_url */
1, /* is_uri */
};

/*
Expand Down
19 changes: 14 additions & 5 deletions main/streams/streams.c
Original file line number Diff line number Diff line change
Expand Up @@ -1753,7 +1753,7 @@ PHPAPI php_stream_wrapper *php_stream_locate_url_wrapper(const char *path, const
HashTable *wrapper_hash = (FG(stream_wrappers) ? FG(stream_wrappers) : &url_stream_wrappers_hash);
php_stream_wrapper *wrapper = NULL;
const char *p, *protocol = NULL;
size_t n = 0;
size_t n = 0, slashes = 0;

if (path_for_open) {
*path_for_open = (char*)path;
Expand All @@ -1767,8 +1767,9 @@ PHPAPI php_stream_wrapper *php_stream_locate_url_wrapper(const char *path, const
n++;
}

if ((*p == ':') && (n > 1) && (!strncmp("//", p+1, 2) || (n == 4 && !memcmp("data:", path, 5)))) {
if ((*p == ':') && (n > 1)) {
protocol = path;
slashes = !strncmp("//", p+1, 2);
}

if (protocol) {
Expand All @@ -1781,16 +1782,24 @@ PHPAPI php_stream_wrapper *php_stream_locate_url_wrapper(const char *path, const
if (n >= sizeof(wrapper_name)) {
n = sizeof(wrapper_name) - 1;
}
PHP_STRLCPY(wrapper_name, protocol, sizeof(wrapper_name), n);

php_error_docref(NULL, E_WARNING, "Unable to find the wrapper \"%s\" - did you forget to enable it when you configured PHP?", wrapper_name);
/* Raising for <protocol>:// so <protocol>:<path> can be handled with php_plain_files_wrapper if no <protocol> wrapper registered */
if (slashes == 1) {
PHP_STRLCPY(wrapper_name, protocol, sizeof(wrapper_name), n);

php_error_docref(NULL, E_WARNING, "Unable to find the wrapper \"%s\" - did you forget to enable it when you configured PHP?", wrapper_name);
}
wrapper = NULL;
protocol = NULL;
}
}
efree(tmp);
}

if (wrapper && wrapper->is_uri == 0 && slashes == 0) {
wrapper = NULL;
protocol = NULL;
}

/* TODO: curl based streams probably support file:// properly */
if (!protocol || !strncasecmp(protocol, "file", n)) {
/* fall back on regular file access */
Expand Down
2 changes: 2 additions & 0 deletions main/streams/userspace.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ PHP_MINIT_FUNCTION(user_streams)
REGISTER_LONG_CONSTANT("STREAM_MKDIR_RECURSIVE", PHP_STREAM_MKDIR_RECURSIVE, CONST_CS|CONST_PERSISTENT);

REGISTER_LONG_CONSTANT("STREAM_IS_URL", PHP_STREAM_IS_URL, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("STREAM_IS_URI", PHP_STREAM_IS_URI, CONST_CS|CONST_PERSISTENT);

REGISTER_LONG_CONSTANT("STREAM_OPTION_BLOCKING", PHP_STREAM_OPTION_BLOCKING, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("STREAM_OPTION_READ_TIMEOUT", PHP_STREAM_OPTION_READ_TIMEOUT, CONST_CS|CONST_PERSISTENT);
Expand Down Expand Up @@ -505,6 +506,7 @@ PHP_FUNCTION(stream_wrapper_register)
uwrap->wrapper.wops = &user_stream_wops;
uwrap->wrapper.abstract = uwrap;
uwrap->wrapper.is_url = ((flags & PHP_STREAM_IS_URL) != 0);
uwrap->wrapper.is_uri = ((flags & PHP_STREAM_IS_URI) != 0);

rsrc = zend_register_resource(uwrap, le_protocols);

Expand Down