[PATCH] adding stream wrappers to include_path
| From: | Gregory Beaver | Date: | Fri, 07 Mar 2008 05:06:23 +0000 |
| Subject: | [PATCH] adding stream wrappers to include_path | ||
| Groups: | php.internals | ||
| Request: | Send a blank email to internals+get-36031@lists.php.net to get a copy of this message | ||
Hi,
I found some time to whip up a quick patch against 5.3.
This patch allows adding stream wrappers to include_path on both windows
and unix. This means one can set an include_path to
".:/usr/local/lib/php:phar:///path/to/ZF.phar/lib" or the windows
equivalent ".;C:\php5;phar://C:/php5/ZF.phar/lib" Any stream wrapper,
userspace or built-in, will work as long as it satisfies security
constraints and implements url_stat(), stream_open(), stat(), and read()
or the C equivalents.
In other words, this test I already had created for pecl/phar works:
<?php
$fname = dirname(__FILE__) . '/tempmanifest1.phar.php';
$a = new Phar($fname);
$a['file1.php'] = 'file1.php
';
$a['test/file1.php'] = 'test/file1.php
';
unset($a);
set_include_path('.' . PATH_SEPARATOR . 'phar://' . $fname);
include 'file1.php';
set_include_path('.' . PATH_SEPARATOR . 'phar://' . $fname . '/test');
include 'file1.php';
include 'file2.php';
?>
===DONE===
with output:
--EXPECTF--
file1.php
test/file1.php
Warning: include(file2.php): failed to open stream: No such file or
directory in %sinclude_path.php on line %d
Warning: include(): Failed opening 'file2.php' for inclusion
(include_path='.:phar:///home/cellog/workspace/php5/ext/phar/tests/tempmanifest1.phar.php/test')
in %sinclude_path.php on line %d
===DONE===
The internals of the patch borrows logic from
php_stream_locate_url_wrapper to quickly detect a stream wrapper. It
excludes the data stream wrapper out of hand as this has no business in
include_path for obvious reasons. It also fully supports disabled
allow_url_fopen/allow_url_include by passing STREAM_OPEN_FOR_INCLUDE to
the eventual php_stream_locate_url_wrapper call. The most important
part of the patch is the way it finds a stream wrapper on unix. Because
PATH_SEPARATOR is ":" on unix, the include_path scanner will stop after
"phar" in the sample include_paths above. The new scanner checks for a
valid stream wrapper (a sequence of alpha-numeric, +, -, or . characters
followed by ://) and seeks to the next : if found.
My primary concern with the patch is performance. I'm certain it can be
tweaked. I extracted the call to url_stat from php_stream_stat(), which
removes the possibility of hitting stat cache but eliminates the
redundant call to php_stream_locate_url_wrapper. If it is indeed faster
to use php_stream_stat(), that's one easy optimization.
In any case, it adds an additional scan of each include_path component
to detect stream wrappers, which is called on each include. This may be
the biggest candidate for optimization, as a simple cache of paths with
stream wrapper/not could be created whenever include_path is set and
used instead of scanning the string every time.
By the way, there may be some unsafe scans in
php_stream_locate_url_wrapper, specifically line 1531 in PHP_5_3:
if ((*p == ':') && (n > 1) && (!strncmp("//", p+1, 2) ||
!memcmp("data", path, 4))) {
It doesn't seem to verify that path is at least 4 or there is at least 2
extra characters after p before checking for "//" or "data"
Thanks,
Greg