[nycphp-talk] How to invoke stream_cast method?
Gary A. Mort
garyamort at gmail.com
Mon Dec 30 17:00:41 EST 2013
Short question:
The stream_cast method has thrown me for a loop. The method does not
take any parameters and is invoked by stream_select which has lots of
arguements - so I don't know what I'm supposed to return for it and
where to get the options.... I figured I'd ask here if anyone else
knows what they are.
-----Long explanation------
I've been hacking about with Google's App Engine and Joomla. One
limitation I ran into is that App Engine does not allow for the PHP
application running on the website to change/modify/add files to a
running application. In essence, from within a PHP application running
on App Engine[or any other language for that matter] we only have "read"
access to the file system.
Benefits of this are of course, security[no exploits can be used to
modify php scripts on the website] - performance[static resources such
as javascript, images, css, etc can be optimized for delivery] and
caching[since the files are only modified when new code is 'deployed'
APC does not need to check the file change dates when caching PHP code -
the deployment process can force a flush of the cache when needed].
App Engine does allow for accessing files from Google Cloud Storage
buckets - and they even provide a stream wrapper so any gs://bucketname
paths can be treated like files. You can even allow for execution of
PHP code from Cloud Storage....but then your no longer secure from
exploits which try to modify PHP files on the server!]
For my own custom code, it's easy enough to build paths using different
paths. IE when checking to include php scripts with file_exists I can
use the local file: path - and when saving or retrieiving image file
uploads I can use the gs: file path. But to get someone else's code
working that way is a non-trivial chunk of work - and it struck me that
instead I can let PHP do things "magically". So I created my own stream
wrapper:https://github.com/garyamort/Stream-Morpher
<https://github.com/garyamort/Stream-Morpher>
It can use a set of string manipulation rules to convert one path to
another, ie
ggsm://websitepath/media/image.png would become
gs://gmimagebucket/images/image.png and a default rule at the end can
swap ggsm://websitepath/anythingelse to file:///appinstancepath/anythingelse
For the most part, it's been fairly obvious how to map to method calls.
Most file modifications will only be made after a call to fopen, so
stream_open is the primary method:
$this->streamHandle = false;
if ($this->processPathname($pathname, $mode))
{
if ($this->checkRecursiveRules($this->path,
STREAM_URL_STAT_QUIET))
{
// Path translated to itself recursively, abort, abort
$this->path = null;
return false;
}
$use_include_path = $options & STREAM_USE_PATH;
$handle = fopen($this->path->truePath, $mode,
$use_include_path);
if (is_resource($handle))
{
$this->streamHandle = $handle;
return true;
}
}
return false;
That code converts the pathname to the "true" pathname, makes sure that
whatever stream it morphed into is not assigned to the stream morpher
itself[otherwise you get ugly recursion calls as it tries to keep
morphing it over and over], and finally simply calls fopen again to
pass the file open on to the real processor.
One oddity I found is that the return from stream_open is irrelevant, I
originally tried returning the handle opened however future calls to
read and write would use my morpher object, not the handle - so I had to
save the "true" handle in the morpher object and create a proxy call for
every method. Some of them, such as write, are simple:
function stream_write($data)
{
return fwrite($this->streamHandle, $data);
}
Some them are ugly due to having to check lots of flags, such as set_option:
public function stream_set_option ( $option , $arg1 , $arg2 )
{
if ($option & STREAM_OPTION_BLOCKING)
{
return stream_set_blocking($arg1, $arg2);
}
if ($option & STREAM_OPTION_READ_TIMEOUT)
{
return stream_set_timeout($arg1, $arg2);
}
if ($option & STREAM_OPTION_WRITE_BUFFER)
{
return stream_set_write_buffer($arg1, $arg2);
}
return false;
}
But stream_cast has thrown me for a loop. The method does not take any
parameters and is invoked by stream_select which has lots of arguements
- so I don't know what I'm supposed to return for it and where to get
the options.... I figured I'd ask here if anyone else knows what they are.
I'm still hacking around a bit on the driver to use it for other
things. For example, since the mode a file is opened with is known, it
would be possible to use the regular file stream wrapper for files
opened in read mode, but use an ftp wrapper for files opened in write mode.
Or for things like logfile writing, since their usually a sequence of
lines appended to a file, modify log file paths so writes get sent to
syslog of phperror instead.
--Gary
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.nyphp.org/pipermail/talk/attachments/20131230/dc71b2d2/attachment.html>
More information about the talk
mailing list