2002-03-19 11:51:01 +08:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2004-01-08 16:18:22 +08:00
| PHP Version 5 |
2002-03-19 11:51:01 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2007-12-31 15:17:19 +08:00
| Copyright ( c ) 1997 - 2008 The PHP Group |
2002-03-19 11:51:01 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2006-01-01 20:51:34 +08:00
| This source file is subject to version 3.01 of the PHP license , |
2002-03-19 11:51:01 +08:00
| that is bundled with this package in the file LICENSE , and is |
2003-06-11 04:04:29 +08:00
| available through the world - wide - web at the following url : |
2006-01-01 20:51:34 +08:00
| http : //www.php.net/license/3_01.txt |
2002-03-19 11:51:01 +08:00
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world - wide - web , please send a note to |
| license @ php . net so we can mail you a copy immediately . |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2003-02-19 16:40:19 +08:00
| Authors : Wez Furlong < wez @ thebrainroom . com > |
2003-12-13 12:07:18 +08:00
| Sara Golemon < pollita @ php . net > |
2002-03-19 11:51:01 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2002-05-05 01:41:03 +08:00
*/
2002-03-19 11:51:01 +08:00
2002-05-05 01:42:58 +08:00
/* $Id$ */
2002-05-05 01:39:05 +08:00
2002-03-19 11:51:01 +08:00
# include "php.h"
# include "php_globals.h"
2002-09-26 20:12:27 +08:00
# include "ext/standard/file.h"
2008-11-26 12:19:20 +08:00
# include "ext/standard/flock_compat.h"
# ifdef HAVE_SYS_FILE_H
# include <sys/file.h>
# endif
2002-03-19 11:51:01 +08:00
static int le_protocols ;
struct php_user_stream_wrapper {
char * protoname ;
char * classname ;
zend_class_entry * ce ;
php_stream_wrapper wrapper ;
} ;
2002-04-11 20:13:17 +08:00
static php_stream * user_wrapper_opener ( php_stream_wrapper * wrapper , char * filename , char * mode , int options , char * * opened_path , php_stream_context * context STREAMS_DC TSRMLS_DC ) ;
2003-12-03 02:52:58 +08:00
static int user_wrapper_stat_url ( php_stream_wrapper * wrapper , char * url , int flags , php_stream_statbuf * ssb , php_stream_context * context TSRMLS_DC ) ;
2003-05-15 02:30:49 +08:00
static int user_wrapper_unlink ( php_stream_wrapper * wrapper , char * url , int options , php_stream_context * context TSRMLS_DC ) ;
2003-12-13 07:06:42 +08:00
static int user_wrapper_rename ( php_stream_wrapper * wrapper , char * url_from , char * url_to , int options , php_stream_context * context TSRMLS_DC ) ;
2003-12-13 12:07:18 +08:00
static int user_wrapper_mkdir ( php_stream_wrapper * wrapper , char * url , int mode , int options , php_stream_context * context TSRMLS_DC ) ;
static int user_wrapper_rmdir ( php_stream_wrapper * wrapper , char * url , int options , php_stream_context * context TSRMLS_DC ) ;
2002-09-28 21:05:47 +08:00
static php_stream * user_wrapper_opendir ( php_stream_wrapper * wrapper , char * filename , char * mode ,
int options , char * * opened_path , php_stream_context * context STREAMS_DC TSRMLS_DC ) ;
2002-03-25 02:05:49 +08:00
static php_stream_wrapper_ops user_stream_wops = {
user_wrapper_opener ,
2002-09-28 21:05:47 +08:00
NULL , /* close - the streams themselves know how */
NULL , /* stat - the streams themselves know how */
user_wrapper_stat_url ,
user_wrapper_opendir ,
2003-05-14 14:10:04 +08:00
" user-space " ,
2003-12-13 07:06:42 +08:00
user_wrapper_unlink ,
2003-12-13 12:07:18 +08:00
user_wrapper_rename ,
user_wrapper_mkdir ,
user_wrapper_rmdir
2002-03-25 02:05:49 +08:00
} ;
2002-03-19 11:51:01 +08:00
static void stream_wrapper_dtor ( zend_rsrc_list_entry * rsrc TSRMLS_DC )
{
struct php_user_stream_wrapper * uwrap = ( struct php_user_stream_wrapper * ) rsrc - > ptr ;
efree ( uwrap - > protoname ) ;
efree ( uwrap - > classname ) ;
efree ( uwrap ) ;
}
2002-03-19 22:35:55 +08:00
PHP_MINIT_FUNCTION ( user_streams )
2002-03-19 11:51:01 +08:00
{
le_protocols = zend_register_list_destructors_ex ( stream_wrapper_dtor , NULL , " stream factory " , 0 ) ;
2002-03-19 22:35:55 +08:00
if ( le_protocols = = FAILURE )
return FAILURE ;
REGISTER_LONG_CONSTANT ( " STREAM_USE_PATH " , USE_PATH , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " STREAM_IGNORE_URL " , IGNORE_URL , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " STREAM_ENFORCE_SAFE_MODE " , ENFORCE_SAFE_MODE , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " STREAM_REPORT_ERRORS " , REPORT_ERRORS , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " STREAM_MUST_SEEK " , STREAM_MUST_SEEK , CONST_CS | CONST_PERSISTENT ) ;
2003-12-03 04:06:40 +08:00
REGISTER_LONG_CONSTANT ( " STREAM_URL_STAT_LINK " , PHP_STREAM_URL_STAT_LINK , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " STREAM_URL_STAT_QUIET " , PHP_STREAM_URL_STAT_QUIET , CONST_CS | CONST_PERSISTENT ) ;
2003-12-14 07:13:51 +08:00
REGISTER_LONG_CONSTANT ( " STREAM_MKDIR_RECURSIVE " , PHP_STREAM_MKDIR_RECURSIVE , CONST_CS | CONST_PERSISTENT ) ;
2003-12-03 04:06:40 +08:00
2007-07-10 01:27:24 +08:00
REGISTER_LONG_CONSTANT ( " STREAM_IS_URL " , PHP_STREAM_IS_URL , CONST_CS | CONST_PERSISTENT ) ;
2008-11-15 20:52:13 +08:00
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 ) ;
REGISTER_LONG_CONSTANT ( " STREAM_OPTION_READ_BUFFER " , PHP_STREAM_OPTION_READ_BUFFER , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " STREAM_OPTION_WRITE_BUFFER " , PHP_STREAM_OPTION_WRITE_BUFFER , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " STREAM_BUFFER_NONE " , PHP_STREAM_BUFFER_NONE , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " STREAM_BUFFER_LINE " , PHP_STREAM_BUFFER_LINE , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " STREAM_BUFFER_FULL " , PHP_STREAM_BUFFER_FULL , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " STREAM_CAST_AS_STREAM " , PHP_STREAM_AS_STDIO , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " STREAM_CAST_FOR_SELECT " , PHP_STREAM_AS_FD_FOR_SELECT , CONST_CS | CONST_PERSISTENT ) ;
2002-03-19 22:35:55 +08:00
return SUCCESS ;
2002-03-19 11:51:01 +08:00
}
struct _php_userstream_data {
struct php_user_stream_wrapper * wrapper ;
zval * object ;
} ;
typedef struct _php_userstream_data php_userstream_data_t ;
/* names of methods */
# define USERSTREAM_OPEN "stream_open"
# define USERSTREAM_CLOSE "stream_close"
# define USERSTREAM_READ "stream_read"
# define USERSTREAM_WRITE "stream_write"
# define USERSTREAM_FLUSH "stream_flush"
# define USERSTREAM_SEEK "stream_seek"
# define USERSTREAM_TELL "stream_tell"
# define USERSTREAM_EOF "stream_eof"
2002-09-28 21:05:47 +08:00
# define USERSTREAM_STAT "stream_stat"
# define USERSTREAM_STATURL "url_stat"
2003-05-15 02:30:49 +08:00
# define USERSTREAM_UNLINK "unlink"
2003-12-13 07:06:42 +08:00
# define USERSTREAM_RENAME "rename"
2003-12-13 12:07:18 +08:00
# define USERSTREAM_MKDIR "mkdir"
# define USERSTREAM_RMDIR "rmdir"
2002-09-28 21:05:47 +08:00
# define USERSTREAM_DIR_OPEN "dir_opendir"
# define USERSTREAM_DIR_READ "dir_readdir"
# define USERSTREAM_DIR_REWIND "dir_rewinddir"
# define USERSTREAM_DIR_CLOSE "dir_closedir"
2004-01-21 18:17:12 +08:00
# define USERSTREAM_LOCK "stream_lock"
2008-11-15 20:52:13 +08:00
# define USERSTREAM_CAST "stream_cast"
# define USERSTREAM_SET_OPTION "stream_set_option"
2002-09-28 21:05:47 +08:00
/* {{{ class should have methods like these:
2002-03-19 11:51:01 +08:00
2002-09-23 21:22:10 +08:00
function stream_open ( $ path , $ mode , $ options , & $ opened_path )
{
return true / false ;
}
function stream_read ( $ count )
{
return false on error ;
else return string ;
}
function stream_write ( $ data )
{
return false on error ;
else return count written ;
}
function stream_close ( )
{
}
function stream_flush ( )
{
return true / false ;
}
function stream_seek ( $ offset , $ whence )
{
return true / false ;
}
function stream_tell ( )
{
return ( int ) $ position ;
}
function stream_eof ( )
{
return true / false ;
}
2002-09-28 21:05:47 +08:00
function stream_stat ( )
{
return array ( just like that returned by fstat ( ) ) ;
}
2008-11-15 20:52:13 +08:00
function stream_cast ( $ castas )
{
if ( $ castas = = STREAM_CAST_FOR_SELECT ) {
return $ this - > underlying_stream ;
}
return false ;
}
function stream_set_option ( $ option , $ arg1 , $ arg2 )
{
switch ( $ option ) {
case STREAM_OPTION_BLOCKING :
$ blocking = $ arg1 ;
. . .
case STREAM_OPTION_READ_TIMEOUT :
$ sec = $ arg1 ;
$ usec = $ arg2 ;
. . .
case STREAM_OPTION_WRITE_BUFFER :
$ mode = $ arg1 ;
$ size = $ arg2 ;
. . .
default :
return false ;
}
}
2003-12-03 02:52:58 +08:00
function url_stat ( string $ url , int $ flags )
2002-09-28 21:05:47 +08:00
{
return array ( just like that returned by stat ( ) ) ;
}
2003-05-15 02:30:49 +08:00
function unlink ( string $ url )
{
return true / false ;
}
2003-12-13 07:06:42 +08:00
function rename ( string $ from , string $ to )
{
return true / false ;
}
2003-12-13 12:07:18 +08:00
function mkdir ( $ dir , $ mode , $ options )
{
return true / false ;
}
function rmdir ( $ dir , $ options )
{
return true / false ;
}
2002-09-28 21:05:47 +08:00
function dir_opendir ( string $ url , int $ options )
{
return true / false ;
}
function dir_readdir ( )
{
return string next filename in dir ;
}
function dir_closedir ( )
{
release dir related resources ;
}
function dir_rewinddir ( )
{
reset to start of dir list ;
}
2002-09-23 09:47:04 +08:00
2002-09-28 21:05:47 +08:00
} } } * */
2002-03-19 11:51:01 +08:00
2002-04-11 20:13:17 +08:00
static php_stream * user_wrapper_opener ( php_stream_wrapper * wrapper , char * filename , char * mode , int options , char * * opened_path , php_stream_context * context STREAMS_DC TSRMLS_DC )
2002-03-19 11:51:01 +08:00
{
2002-03-25 02:05:49 +08:00
struct php_user_stream_wrapper * uwrap = ( struct php_user_stream_wrapper * ) wrapper - > abstract ;
2002-03-19 11:51:01 +08:00
php_userstream_data_t * us ;
zval * zfilename , * zmode , * zopened , * zoptions , * zretval = NULL , * zfuncname ;
zval * * args [ 4 ] ;
int call_result ;
php_stream * stream = NULL ;
2007-07-10 01:27:24 +08:00
zend_bool old_in_user_include ;
2002-03-20 22:21:30 +08:00
2002-09-28 21:05:47 +08:00
/* Try to catch bad usage without preventing flexibility */
2002-09-26 20:12:27 +08:00
if ( FG ( user_stream_current_filename ) ! = NULL & & strcmp ( filename , FG ( user_stream_current_filename ) ) = = 0 ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " infinite recursion prevented " ) ;
return NULL ;
}
FG ( user_stream_current_filename ) = filename ;
2007-07-10 01:27:24 +08:00
/* if the user stream was registered as local and we are in include context,
we add allow_url_include restrictions to allow_url_fopen ones */
/* we need only is_url == 0 here since if is_url == 1 and remote wrappers
were restricted we wouldn ' t get here */
old_in_user_include = PG ( in_user_include ) ;
if ( uwrap - > wrapper . is_url = = 0 & &
( options & STREAM_OPEN_FOR_INCLUDE ) & &
! PG ( allow_url_include ) ) {
PG ( in_user_include ) = 1 ;
}
2002-03-19 11:51:01 +08:00
us = emalloc ( sizeof ( * us ) ) ;
us - > wrapper = uwrap ;
/* create an instance of our class */
ALLOC_ZVAL ( us - > object ) ;
object_init_ex ( us - > object , uwrap - > ce ) ;
2007-10-07 13:22:07 +08:00
Z_SET_REFCOUNT_P ( us - > object , 1 ) ;
Z_SET_ISREF_P ( us - > object ) ;
2006-08-14 23:01:29 +08:00
if ( uwrap - > ce - > constructor ) {
zend_fcall_info fci ;
zend_fcall_info_cache fcc ;
zval * retval_ptr ;
fci . size = sizeof ( fci ) ;
fci . function_table = & uwrap - > ce - > function_table ;
fci . function_name = NULL ;
fci . symbol_table = NULL ;
fci . object_pp = & us - > object ;
fci . retval_ptr_ptr = & retval_ptr ;
fci . param_count = 0 ;
fci . params = NULL ;
fci . no_separation = 1 ;
fcc . initialized = 1 ;
fcc . function_handler = uwrap - > ce - > constructor ;
fcc . calling_scope = EG ( scope ) ;
2008-07-25 16:23:07 +08:00
fcc . called_scope = Z_OBJCE_P ( us - > object ) ;
2006-08-14 23:01:29 +08:00
fcc . object_pp = & us - > object ;
if ( zend_call_function ( & fci , & fcc TSRMLS_CC ) = = FAILURE ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Could not execute %s::%s() " , uwrap - > ce - > name , uwrap - > ce - > constructor - > common . function_name ) ;
zval_dtor ( us - > object ) ;
FREE_ZVAL ( us - > object ) ;
efree ( us ) ;
FG ( user_stream_current_filename ) = NULL ;
2007-07-10 01:27:24 +08:00
PG ( in_user_include ) = old_in_user_include ;
2006-08-14 23:01:29 +08:00
return NULL ;
} else {
if ( retval_ptr ) {
zval_ptr_dtor ( & retval_ptr ) ;
}
}
}
2003-06-17 03:13:39 +08:00
if ( context ) {
2008-07-11 18:25:15 +08:00
add_property_resource ( us - > object , " context " , context - > rsrc_id ) ;
zend_list_addref ( context - > rsrc_id ) ;
2003-06-17 03:13:39 +08:00
} else {
add_property_null ( us - > object , " context " ) ;
}
2002-03-19 11:51:01 +08:00
/* call it's stream_open method - set up params first */
MAKE_STD_ZVAL ( zfilename ) ;
ZVAL_STRING ( zfilename , filename , 1 ) ;
args [ 0 ] = & zfilename ;
MAKE_STD_ZVAL ( zmode ) ;
ZVAL_STRING ( zmode , mode , 1 ) ;
args [ 1 ] = & zmode ;
MAKE_STD_ZVAL ( zoptions ) ;
ZVAL_LONG ( zoptions , options ) ;
args [ 2 ] = & zoptions ;
MAKE_STD_ZVAL ( zopened ) ;
2007-10-07 13:22:07 +08:00
Z_SET_REFCOUNT_P ( zopened , 1 ) ;
Z_SET_ISREF_P ( zopened ) ;
2002-03-19 11:51:01 +08:00
ZVAL_NULL ( zopened ) ;
args [ 3 ] = & zopened ;
MAKE_STD_ZVAL ( zfuncname ) ;
ZVAL_STRING ( zfuncname , USERSTREAM_OPEN , 1 ) ;
call_result = call_user_function_ex ( NULL ,
& us - > object ,
zfuncname ,
& zretval ,
4 , args ,
0 , NULL TSRMLS_CC ) ;
2002-09-18 18:15:40 +08:00
if ( call_result = = SUCCESS & & zretval ! = NULL & & zval_is_true ( zretval ) ) {
2002-03-19 11:51:01 +08:00
/* the stream is now open! */
stream = php_stream_alloc_rel ( & php_stream_userspace_ops , us , 0 , mode ) ;
/* if the opened path is set, copy it out */
if ( Z_TYPE_P ( zopened ) = = IS_STRING & & opened_path ) {
* opened_path = estrndup ( Z_STRVAL_P ( zopened ) , Z_STRLEN_P ( zopened ) ) ;
}
2002-03-19 21:42:25 +08:00
/* set wrapper data to be a reference to our object */
stream - > wrapperdata = us - > object ;
zval_add_ref ( & stream - > wrapperdata ) ;
2002-03-19 11:51:01 +08:00
} else {
2002-09-18 18:15:40 +08:00
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " \" %s:: " USERSTREAM_OPEN " \" call failed " ,
us - > wrapper - > classname ) ;
2002-03-19 11:51:01 +08:00
}
/* destroy everything else */
2002-09-18 18:15:40 +08:00
if ( stream = = NULL ) {
zval_ptr_dtor ( & us - > object ) ;
efree ( us ) ;
}
2002-03-19 11:51:01 +08:00
if ( zretval )
zval_ptr_dtor ( & zretval ) ;
zval_ptr_dtor ( & zfuncname ) ;
zval_ptr_dtor ( & zopened ) ;
zval_ptr_dtor ( & zoptions ) ;
zval_ptr_dtor ( & zmode ) ;
zval_ptr_dtor ( & zfilename ) ;
2002-09-26 20:12:27 +08:00
FG ( user_stream_current_filename ) = NULL ;
2007-07-10 01:27:24 +08:00
PG ( in_user_include ) = old_in_user_include ;
2002-03-19 11:51:01 +08:00
return stream ;
}
2002-09-28 21:05:47 +08:00
static php_stream * user_wrapper_opendir ( php_stream_wrapper * wrapper , char * filename , char * mode ,
int options , char * * opened_path , php_stream_context * context STREAMS_DC TSRMLS_DC )
{
struct php_user_stream_wrapper * uwrap = ( struct php_user_stream_wrapper * ) wrapper - > abstract ;
php_userstream_data_t * us ;
2008-07-11 18:25:15 +08:00
zval * zfilename , * zoptions , * zretval = NULL , * zfuncname ;
2002-09-28 21:05:47 +08:00
zval * * args [ 2 ] ;
int call_result ;
php_stream * stream = NULL ;
/* Try to catch bad usage without preventing flexibility */
if ( FG ( user_stream_current_filename ) ! = NULL & & strcmp ( filename , FG ( user_stream_current_filename ) ) = = 0 ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " infinite recursion prevented " ) ;
return NULL ;
}
FG ( user_stream_current_filename ) = filename ;
us = emalloc ( sizeof ( * us ) ) ;
us - > wrapper = uwrap ;
/* create an instance of our class */
ALLOC_ZVAL ( us - > object ) ;
object_init_ex ( us - > object , uwrap - > ce ) ;
2007-10-07 13:22:07 +08:00
Z_SET_REFCOUNT_P ( us - > object , 1 ) ;
Z_SET_ISREF_P ( us - > object ) ;
2003-12-03 03:14:31 +08:00
if ( context ) {
2008-07-11 18:25:15 +08:00
add_property_resource ( us - > object , " context " , context - > rsrc_id ) ;
zend_list_addref ( context - > rsrc_id ) ;
2003-12-03 03:14:31 +08:00
} else {
add_property_null ( us - > object , " context " ) ;
}
2002-09-28 21:05:47 +08:00
/* call it's dir_open method - set up params first */
MAKE_STD_ZVAL ( zfilename ) ;
ZVAL_STRING ( zfilename , filename , 1 ) ;
args [ 0 ] = & zfilename ;
MAKE_STD_ZVAL ( zoptions ) ;
ZVAL_LONG ( zoptions , options ) ;
args [ 1 ] = & zoptions ;
MAKE_STD_ZVAL ( zfuncname ) ;
ZVAL_STRING ( zfuncname , USERSTREAM_DIR_OPEN , 1 ) ;
call_result = call_user_function_ex ( NULL ,
& us - > object ,
zfuncname ,
& zretval ,
2 , args ,
0 , NULL TSRMLS_CC ) ;
if ( call_result = = SUCCESS & & zretval ! = NULL & & zval_is_true ( zretval ) ) {
/* the stream is now open! */
stream = php_stream_alloc_rel ( & php_stream_userspace_dir_ops , us , 0 , mode ) ;
/* set wrapper data to be a reference to our object */
stream - > wrapperdata = us - > object ;
zval_add_ref ( & stream - > wrapperdata ) ;
} else {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " \" %s:: " USERSTREAM_DIR_OPEN " \" call failed " ,
us - > wrapper - > classname ) ;
}
/* destroy everything else */
if ( stream = = NULL ) {
zval_ptr_dtor ( & us - > object ) ;
efree ( us ) ;
}
if ( zretval )
zval_ptr_dtor ( & zretval ) ;
zval_ptr_dtor ( & zfuncname ) ;
zval_ptr_dtor ( & zoptions ) ;
zval_ptr_dtor ( & zfilename ) ;
FG ( user_stream_current_filename ) = NULL ;
return stream ;
}
2007-08-17 07:54:24 +08:00
/* {{{ proto bool stream_wrapper_register(string protocol, string classname[, integer flags])
2002-03-19 11:51:01 +08:00
Registers a custom URL protocol handler class */
2003-05-19 23:35:06 +08:00
PHP_FUNCTION ( stream_wrapper_register )
2002-03-19 11:51:01 +08:00
{
char * protocol , * classname ;
int protocol_len , classname_len ;
struct php_user_stream_wrapper * uwrap ;
int rsrc_id ;
2007-07-10 01:27:24 +08:00
long flags = 0 ;
2002-03-19 11:51:01 +08:00
2007-07-10 01:27:24 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " ss|l " , & protocol , & protocol_len , & classname , & classname_len , & flags ) = = FAILURE ) {
2002-03-19 11:51:01 +08:00
RETURN_FALSE ;
}
uwrap = ( struct php_user_stream_wrapper * ) ecalloc ( 1 , sizeof ( * uwrap ) ) ;
uwrap - > protoname = estrndup ( protocol , protocol_len ) ;
uwrap - > classname = estrndup ( classname , classname_len ) ;
2002-03-25 02:05:49 +08:00
uwrap - > wrapper . wops = & user_stream_wops ;
uwrap - > wrapper . abstract = uwrap ;
2007-07-10 01:27:24 +08:00
uwrap - > wrapper . is_url = ( ( flags & PHP_STREAM_IS_URL ) ! = 0 ) ;
2002-03-19 11:51:01 +08:00
rsrc_id = ZEND_REGISTER_RESOURCE ( NULL , uwrap , le_protocols ) ;
2004-06-22 02:58:55 +08:00
2004-05-06 02:18:57 +08:00
if ( zend_lookup_class ( uwrap - > classname , classname_len , ( zend_class_entry * * * ) & uwrap - > ce TSRMLS_CC ) = = SUCCESS ) {
2002-03-19 11:51:01 +08:00
uwrap - > ce = * ( zend_class_entry * * ) uwrap - > ce ;
2004-06-22 02:58:55 +08:00
if ( php_register_url_stream_wrapper_volatile ( protocol , & uwrap - > wrapper TSRMLS_CC ) = = SUCCESS ) {
2002-03-19 11:51:01 +08:00
RETURN_TRUE ;
2004-03-17 08:08:22 +08:00
} else {
/* We failed. But why? */
2007-01-16 01:07:08 +08:00
if ( zend_hash_exists ( php_stream_get_url_stream_wrappers_hash ( ) , protocol , protocol_len + 1 ) ) {
2004-03-17 08:08:22 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Protocol %s:// is already defined. " , protocol ) ;
} else {
2007-05-15 21:04:43 +08:00
/* Hash doesn't exist so it must have been an invalid protocol scheme */
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Invalid protocol scheme specified. Unable to register wrapper class %s to %s:// " , classname , protocol ) ;
2004-03-17 08:08:22 +08:00
}
2002-03-19 11:51:01 +08:00
}
} else {
2004-03-17 08:08:22 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " class '%s' is undefined " , classname ) ;
2002-03-19 11:51:01 +08:00
}
zend_list_delete ( rsrc_id ) ;
RETURN_FALSE ;
}
/* }}} */
2005-12-18 23:38:08 +08:00
/* {{{ proto bool stream_wrapper_unregister(string protocol)
2004-09-11 04:45:35 +08:00
Unregister a wrapper for the life of the current request . */
PHP_FUNCTION ( stream_wrapper_unregister )
{
char * protocol ;
int protocol_len ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " s " , & protocol , & protocol_len ) = = FAILURE ) {
RETURN_FALSE ;
}
if ( php_unregister_url_stream_wrapper_volatile ( protocol TSRMLS_CC ) = = FAILURE ) {
/* We failed */
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Unable to unregister protocol %s:// " , protocol ) ;
RETURN_FALSE ;
}
RETURN_TRUE ;
}
/* }}} */
2005-12-18 23:38:08 +08:00
/* {{{ proto bool stream_wrapper_restore(string protocol)
2004-09-11 04:45:35 +08:00
Restore the original protocol handler , overriding if necessary */
PHP_FUNCTION ( stream_wrapper_restore )
{
char * protocol ;
int protocol_len ;
2006-04-23 01:17:40 +08:00
php_stream_wrapper * * wrapperpp = NULL , * wrapper ;
2004-09-11 04:45:35 +08:00
HashTable * global_wrapper_hash ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " s " , & protocol , & protocol_len ) = = FAILURE ) {
RETURN_FALSE ;
}
global_wrapper_hash = php_stream_get_url_stream_wrappers_hash_global ( ) ;
if ( php_stream_get_url_stream_wrappers_hash ( ) = = global_wrapper_hash ) {
php_error_docref ( NULL TSRMLS_CC , E_NOTICE , " %s:// was never changed, nothing to restore " , protocol ) ;
RETURN_TRUE ;
}
2007-01-16 01:07:08 +08:00
if ( ( zend_hash_find ( global_wrapper_hash , protocol , protocol_len + 1 , ( void * * ) & wrapperpp ) = = FAILURE ) | | ! wrapperpp ) {
2004-09-11 04:45:35 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %s:// never existed, nothing to restore " , protocol ) ;
RETURN_FALSE ;
}
2006-04-23 01:17:40 +08:00
/* next line might delete the pointer that wrapperpp points at, so deref it now */
wrapper = * wrapperpp ;
2004-09-11 04:45:35 +08:00
/* A failure here could be okay given that the protocol might have been merely unregistered */
php_unregister_url_stream_wrapper_volatile ( protocol TSRMLS_CC ) ;
if ( php_register_url_stream_wrapper_volatile ( protocol , wrapper TSRMLS_CC ) = = FAILURE ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Unable to restore original %s:// wrapper " , protocol ) ;
RETURN_FALSE ;
}
RETURN_TRUE ;
}
/* }}} */
2002-03-19 11:51:01 +08:00
static size_t php_userstreamop_write ( php_stream * stream , const char * buf , size_t count TSRMLS_DC )
{
zval func_name ;
zval * retval = NULL ;
int call_result ;
php_userstream_data_t * us = ( php_userstream_data_t * ) stream - > abstract ;
zval * * args [ 1 ] ;
2004-10-08 22:40:11 +08:00
zval * zbufptr ;
2002-03-19 11:51:01 +08:00
size_t didwrite = 0 ;
assert ( us ! = NULL ) ;
ZVAL_STRINGL ( & func_name , USERSTREAM_WRITE , sizeof ( USERSTREAM_WRITE ) - 1 , 0 ) ;
2004-10-08 22:40:11 +08:00
MAKE_STD_ZVAL ( zbufptr ) ;
ZVAL_STRINGL ( zbufptr , ( char * ) buf , count , 1 ) ; ;
2002-03-19 11:51:01 +08:00
args [ 0 ] = & zbufptr ;
call_result = call_user_function_ex ( NULL ,
& us - > object ,
& func_name ,
& retval ,
1 , args ,
0 , NULL TSRMLS_CC ) ;
2004-10-08 22:40:11 +08:00
zval_ptr_dtor ( & zbufptr ) ;
2002-03-19 11:51:01 +08:00
2002-09-18 18:15:40 +08:00
didwrite = 0 ;
if ( call_result = = SUCCESS & & retval ! = NULL ) {
2002-09-28 21:05:47 +08:00
convert_to_long ( retval ) ;
2002-03-19 11:51:01 +08:00
didwrite = Z_LVAL_P ( retval ) ;
2002-09-23 21:22:10 +08:00
} else if ( call_result = = FAILURE ) {
2002-09-28 21:05:47 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %s:: " USERSTREAM_WRITE " is not implemented! " ,
2002-09-23 21:22:10 +08:00
us - > wrapper - > classname ) ;
2002-09-18 18:15:40 +08:00
}
2002-03-19 21:44:38 +08:00
/* don't allow strange buffer overruns due to bogus return */
if ( didwrite > count ) {
2004-03-09 07:11:45 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %s:: " USERSTREAM_WRITE " wrote %ld bytes more data than requested (%ld written, %ld max) " ,
2002-03-20 00:56:53 +08:00
us - > wrapper - > classname ,
2004-03-09 07:11:45 +08:00
( long ) ( didwrite - count ) , ( long ) didwrite , ( long ) count ) ;
2002-03-19 21:44:38 +08:00
didwrite = count ;
}
2002-03-19 11:51:01 +08:00
if ( retval )
zval_ptr_dtor ( & retval ) ;
return didwrite ;
}
static size_t php_userstreamop_read ( php_stream * stream , char * buf , size_t count TSRMLS_DC )
{
zval func_name ;
zval * retval = NULL ;
zval * * args [ 1 ] ;
int call_result ;
size_t didread = 0 ;
php_userstream_data_t * us = ( php_userstream_data_t * ) stream - > abstract ;
2002-10-05 18:35:13 +08:00
zval * zcount ;
2002-03-19 11:51:01 +08:00
assert ( us ! = NULL ) ;
2002-10-05 18:35:13 +08:00
ZVAL_STRINGL ( & func_name , USERSTREAM_READ , sizeof ( USERSTREAM_READ ) - 1 , 0 ) ;
2002-03-19 11:51:01 +08:00
2002-10-05 18:35:13 +08:00
MAKE_STD_ZVAL ( zcount ) ;
ZVAL_LONG ( zcount , count ) ;
args [ 0 ] = & zcount ;
call_result = call_user_function_ex ( NULL ,
2002-03-19 11:51:01 +08:00
& us - > object ,
& func_name ,
& retval ,
2002-10-05 18:35:13 +08:00
1 , args ,
0 , NULL TSRMLS_CC ) ;
2002-09-23 21:22:10 +08:00
2002-10-05 18:35:13 +08:00
if ( call_result = = SUCCESS & & retval ! = NULL ) {
convert_to_string ( retval ) ;
didread = Z_STRLEN_P ( retval ) ;
if ( didread > count ) {
2004-03-09 07:11:45 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %s:: " USERSTREAM_READ " - read %ld bytes more data than requested (%ld read, %ld max) - excess data will be lost " ,
us - > wrapper - > classname , ( long ) ( didread - count ) , ( long ) didread , ( long ) count ) ;
2002-10-05 18:35:13 +08:00
didread = count ;
2002-09-23 21:22:10 +08:00
}
2002-10-05 18:35:13 +08:00
if ( didread > 0 )
memcpy ( buf , Z_STRVAL_P ( retval ) , didread ) ;
} else if ( call_result = = FAILURE ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %s:: " USERSTREAM_READ " is not implemented! " ,
us - > wrapper - > classname ) ;
}
zval_ptr_dtor ( & zcount ) ;
2002-03-19 11:51:01 +08:00
2002-10-15 09:57:19 +08:00
if ( retval ) {
2002-10-05 18:35:13 +08:00
zval_ptr_dtor ( & retval ) ;
2002-10-15 09:57:19 +08:00
retval = NULL ;
}
2002-10-05 18:35:13 +08:00
/* since the user stream has no way of setting the eof flag directly, we need to ask it if we hit eof */
ZVAL_STRINGL ( & func_name , USERSTREAM_EOF , sizeof ( USERSTREAM_EOF ) - 1 , 0 ) ;
call_result = call_user_function_ex ( NULL ,
& us - > object ,
& func_name ,
& retval ,
0 , NULL , 0 , NULL TSRMLS_CC ) ;
2002-10-14 08:16:02 +08:00
if ( call_result = = SUCCESS & & retval ! = NULL & & zval_is_true ( retval ) ) {
stream - > eof = 1 ;
} else if ( call_result = = FAILURE ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING ,
" %s:: " USERSTREAM_EOF " is not implemented! Assuming EOF " ,
us - > wrapper - > classname ) ;
2002-10-05 18:35:13 +08:00
stream - > eof = 1 ;
2002-03-19 11:51:01 +08:00
}
2002-10-05 18:35:13 +08:00
2002-10-15 09:57:19 +08:00
if ( retval ) {
zval_ptr_dtor ( & retval ) ;
retval = NULL ;
}
2002-03-19 11:51:01 +08:00
return didread ;
}
static int php_userstreamop_close ( php_stream * stream , int close_handle TSRMLS_DC )
{
zval func_name ;
zval * retval = NULL ;
php_userstream_data_t * us = ( php_userstream_data_t * ) stream - > abstract ;
assert ( us ! = NULL ) ;
ZVAL_STRINGL ( & func_name , USERSTREAM_CLOSE , sizeof ( USERSTREAM_CLOSE ) - 1 , 0 ) ;
2002-05-05 01:32:01 +08:00
call_user_function_ex ( NULL ,
2002-03-19 11:51:01 +08:00
& us - > object ,
& func_name ,
& retval ,
0 , NULL , 0 , NULL TSRMLS_CC ) ;
if ( retval )
zval_ptr_dtor ( & retval ) ;
zval_ptr_dtor ( & us - > object ) ;
efree ( us ) ;
return 0 ;
}
static int php_userstreamop_flush ( php_stream * stream TSRMLS_DC )
{
zval func_name ;
zval * retval = NULL ;
int call_result ;
php_userstream_data_t * us = ( php_userstream_data_t * ) stream - > abstract ;
assert ( us ! = NULL ) ;
ZVAL_STRINGL ( & func_name , USERSTREAM_FLUSH , sizeof ( USERSTREAM_FLUSH ) - 1 , 0 ) ;
call_result = call_user_function_ex ( NULL ,
& us - > object ,
& func_name ,
& retval ,
0 , NULL , 0 , NULL TSRMLS_CC ) ;
if ( call_result = = SUCCESS & & retval ! = NULL & & zval_is_true ( retval ) )
call_result = 0 ;
else
call_result = - 1 ;
if ( retval )
zval_ptr_dtor ( & retval ) ;
return call_result ;
}
2002-09-23 09:47:04 +08:00
static int php_userstreamop_seek ( php_stream * stream , off_t offset , int whence , off_t * newoffs TSRMLS_DC )
2002-03-19 11:51:01 +08:00
{
zval func_name ;
zval * retval = NULL ;
2002-09-23 09:47:04 +08:00
int call_result , ret ;
2002-03-19 11:51:01 +08:00
php_userstream_data_t * us = ( php_userstream_data_t * ) stream - > abstract ;
2002-09-23 09:47:04 +08:00
zval * * args [ 2 ] ;
zval * zoffs , * zwhence ;
2002-03-19 11:51:01 +08:00
assert ( us ! = NULL ) ;
2002-09-23 09:47:04 +08:00
ZVAL_STRINGL ( & func_name , USERSTREAM_SEEK , sizeof ( USERSTREAM_SEEK ) - 1 , 0 ) ;
2002-03-19 11:51:01 +08:00
2002-09-23 09:47:04 +08:00
MAKE_STD_ZVAL ( zoffs ) ;
ZVAL_LONG ( zoffs , offset ) ;
args [ 0 ] = & zoffs ;
MAKE_STD_ZVAL ( zwhence ) ;
ZVAL_LONG ( zwhence , whence ) ;
args [ 1 ] = & zwhence ;
call_result = call_user_function_ex ( NULL ,
2002-03-19 11:51:01 +08:00
& us - > object ,
& func_name ,
& retval ,
2002-09-23 09:47:04 +08:00
2 , args ,
0 , NULL TSRMLS_CC ) ;
2002-03-19 11:51:01 +08:00
2002-09-23 09:47:04 +08:00
zval_ptr_dtor ( & zoffs ) ;
zval_ptr_dtor ( & zwhence ) ;
2002-03-19 11:51:01 +08:00
2002-09-23 21:22:10 +08:00
if ( call_result = = FAILURE ) {
/* stream_seek is not implemented, so disable seeks for this stream */
stream - > flags | = PHP_STREAM_FLAG_NO_SEEK ;
/* there should be no retval to clean up */
2002-10-15 10:05:27 +08:00
if ( retval )
zval_ptr_dtor ( & retval ) ;
2002-09-23 21:22:10 +08:00
return - 1 ;
} else if ( call_result = = SUCCESS & & retval ! = NULL & & zval_is_true ( retval ) ) {
ret = 0 ;
} else {
2002-09-23 09:47:04 +08:00
ret = - 1 ;
2002-09-23 21:22:10 +08:00
}
2002-10-15 09:57:19 +08:00
if ( retval ) {
2002-09-23 21:22:10 +08:00
zval_ptr_dtor ( & retval ) ;
2002-10-15 09:57:19 +08:00
retval = NULL ;
}
2002-03-19 11:51:01 +08:00
2007-02-14 03:50:59 +08:00
if ( ret ) {
return ret ;
}
2002-09-23 09:47:04 +08:00
/* now determine where we are */
ZVAL_STRINGL ( & func_name , USERSTREAM_TELL , sizeof ( USERSTREAM_TELL ) - 1 , 0 ) ;
2002-03-19 11:51:01 +08:00
2002-09-18 18:15:40 +08:00
call_result = call_user_function_ex ( NULL ,
2002-09-23 09:47:04 +08:00
& us - > object ,
& func_name ,
& retval ,
0 , NULL , 0 , NULL TSRMLS_CC ) ;
2002-03-19 11:51:01 +08:00
2007-02-14 03:50:59 +08:00
if ( call_result = = SUCCESS & & retval ! = NULL & & Z_TYPE_P ( retval ) = = IS_LONG ) {
2002-09-23 09:47:04 +08:00
* newoffs = Z_LVAL_P ( retval ) ;
2007-02-14 03:50:59 +08:00
ret = 0 ;
} else if ( call_result = = FAILURE ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %s:: " USERSTREAM_TELL " is not implemented! " , us - > wrapper - > classname ) ;
ret = - 1 ;
} else {
ret = - 1 ;
}
2002-10-15 09:57:19 +08:00
2007-02-14 03:50:59 +08:00
if ( retval ) {
2002-09-28 21:05:47 +08:00
zval_ptr_dtor ( & retval ) ;
2007-02-14 03:50:59 +08:00
}
return ret ;
2002-09-28 21:05:47 +08:00
}
/* parse the return value from one of the stat functions and store the
* relevant fields into the statbuf provided */
static int statbuf_from_array ( zval * array , php_stream_statbuf * ssb TSRMLS_DC )
{
2003-05-30 04:19:03 +08:00
zval * * elem ;
2002-09-28 21:05:47 +08:00
2003-05-20 21:09:11 +08:00
# define STAT_PROP_ENTRY_EX(name, name2) \
2002-09-28 21:05:47 +08:00
if ( SUCCESS = = zend_hash_find ( Z_ARRVAL_P ( array ) , # name , sizeof ( # name ) , ( void * * ) & elem ) ) { \
2003-05-30 04:19:03 +08:00
convert_to_long ( * elem ) ; \
ssb - > sb . st_ # # name2 = Z_LVAL_PP ( elem ) ; \
2002-09-28 21:05:47 +08:00
}
2003-05-20 21:09:11 +08:00
# define STAT_PROP_ENTRY(name) STAT_PROP_ENTRY_EX(name,name)
2002-09-28 21:05:47 +08:00
STAT_PROP_ENTRY ( dev ) ;
STAT_PROP_ENTRY ( ino ) ;
STAT_PROP_ENTRY ( mode ) ;
STAT_PROP_ENTRY ( nlink ) ;
STAT_PROP_ENTRY ( uid ) ;
STAT_PROP_ENTRY ( gid ) ;
# if HAVE_ST_RDEV
STAT_PROP_ENTRY ( rdev ) ;
# endif
STAT_PROP_ENTRY ( size ) ;
2004-09-23 21:07:43 +08:00
# ifdef NETWARE
2003-05-20 21:09:11 +08:00
STAT_PROP_ENTRY_EX ( atime , atime . tv_sec ) ;
STAT_PROP_ENTRY_EX ( mtime , mtime . tv_sec ) ;
STAT_PROP_ENTRY_EX ( ctime , ctime . tv_sec ) ;
2003-01-03 20:48:14 +08:00
# else
2002-09-28 21:05:47 +08:00
STAT_PROP_ENTRY ( atime ) ;
STAT_PROP_ENTRY ( mtime ) ;
STAT_PROP_ENTRY ( ctime ) ;
2003-01-03 20:48:14 +08:00
# endif
2002-09-28 21:05:47 +08:00
# ifdef HAVE_ST_BLKSIZE
STAT_PROP_ENTRY ( blksize ) ;
# endif
# ifdef HAVE_ST_BLOCKS
STAT_PROP_ENTRY ( blocks ) ;
# endif
# undef STAT_PROP_ENTRY
2003-05-20 21:09:11 +08:00
# undef STAT_PROP_ENTRY_EX
2002-09-28 21:05:47 +08:00
return SUCCESS ;
}
static int php_userstreamop_stat ( php_stream * stream , php_stream_statbuf * ssb TSRMLS_DC )
{
zval func_name ;
zval * retval = NULL ;
int call_result ;
php_userstream_data_t * us = ( php_userstream_data_t * ) stream - > abstract ;
int ret = - 1 ;
ZVAL_STRINGL ( & func_name , USERSTREAM_STAT , sizeof ( USERSTREAM_STAT ) - 1 , 0 ) ;
call_result = call_user_function_ex ( NULL ,
& us - > object ,
& func_name ,
& retval ,
0 , NULL , 0 , NULL TSRMLS_CC ) ;
if ( call_result = = SUCCESS & & retval ! = NULL & & Z_TYPE_P ( retval ) = = IS_ARRAY ) {
if ( SUCCESS = = statbuf_from_array ( retval , ssb TSRMLS_CC ) )
ret = 0 ;
} else {
if ( call_result = = FAILURE ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %s:: " USERSTREAM_STAT " is not implemented! " ,
us - > wrapper - > classname ) ;
}
}
2003-05-30 04:19:03 +08:00
2002-10-15 10:05:27 +08:00
if ( retval )
zval_ptr_dtor ( & retval ) ;
2002-09-28 21:05:47 +08:00
return ret ;
}
2004-01-21 18:17:12 +08:00
static int php_userstreamop_set_option ( php_stream * stream , int option , int value , void * ptrparam TSRMLS_DC ) {
zval func_name ;
zval * retval = NULL ;
int call_result ;
php_userstream_data_t * us = ( php_userstream_data_t * ) stream - > abstract ;
int ret = - 1 ;
2004-03-08 06:05:21 +08:00
zval * zvalue = NULL ;
2008-11-15 20:52:13 +08:00
zval * * args [ 3 ] ;
2004-01-21 18:17:12 +08:00
switch ( option ) {
2004-03-08 06:05:21 +08:00
case PHP_STREAM_OPTION_CHECK_LIVENESS :
ZVAL_STRINGL ( & func_name , USERSTREAM_EOF , sizeof ( USERSTREAM_EOF ) - 1 , 0 ) ;
call_result = call_user_function_ex ( NULL , & us - > object , & func_name , & retval , 0 , NULL , 0 , NULL TSRMLS_CC ) ;
if ( call_result = = SUCCESS & & retval ! = NULL & & Z_TYPE_P ( retval ) = = IS_BOOL ) {
2005-05-11 10:02:27 +08:00
ret = zval_is_true ( retval ) ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK ;
2004-03-08 06:05:21 +08:00
} else {
ret = PHP_STREAM_OPTION_RETURN_ERR ;
php_error_docref ( NULL TSRMLS_CC , E_WARNING ,
" %s:: " USERSTREAM_EOF " is not implemented! Assuming EOF " ,
us - > wrapper - > classname ) ;
}
break ;
2004-01-21 18:17:12 +08:00
case PHP_STREAM_OPTION_LOCKING :
2004-03-08 06:05:21 +08:00
MAKE_STD_ZVAL ( zvalue ) ;
2008-11-26 12:19:20 +08:00
ZVAL_LONG ( zvalue , 0 ) ;
if ( value & LOCK_NB ) {
Z_LVAL_P ( zvalue ) | = PHP_LOCK_NB ;
}
switch ( value & ~ LOCK_NB ) {
case LOCK_SH :
Z_LVAL_P ( zvalue ) | = PHP_LOCK_SH ;
break ;
case LOCK_EX :
Z_LVAL_P ( zvalue ) | = PHP_LOCK_EX ;
break ;
case LOCK_UN :
Z_LVAL_P ( zvalue ) | = PHP_LOCK_UN ;
break ;
}
2004-03-08 06:05:21 +08:00
args [ 0 ] = & zvalue ;
/* TODO wouldblock */
2004-01-21 18:17:12 +08:00
ZVAL_STRINGL ( & func_name , USERSTREAM_LOCK , sizeof ( USERSTREAM_LOCK ) - 1 , 0 ) ;
call_result = call_user_function_ex ( NULL ,
& us - > object ,
& func_name ,
& retval ,
1 , args , 0 , NULL TSRMLS_CC ) ;
if ( call_result = = SUCCESS & & retval ! = NULL & & Z_TYPE_P ( retval ) = = IS_BOOL ) {
ret = ! Z_LVAL_P ( retval ) ;
} else if ( call_result = = FAILURE ) {
if ( value = = 0 ) {
2004-03-08 06:05:21 +08:00
/* lock support test (TODO: more check) */
ret = 0 ;
2004-01-21 18:17:12 +08:00
} else {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %s:: " USERSTREAM_LOCK " is not implemented! " ,
us - > wrapper - > classname ) ;
}
}
break ;
2008-11-15 20:52:13 +08:00
case PHP_STREAM_OPTION_READ_BUFFER :
case PHP_STREAM_OPTION_WRITE_BUFFER :
case PHP_STREAM_OPTION_READ_TIMEOUT :
case PHP_STREAM_OPTION_BLOCKING : {
zval * zoption = NULL ;
zval * zptrparam = NULL ;
ZVAL_STRINGL ( & func_name , USERSTREAM_SET_OPTION , sizeof ( USERSTREAM_SET_OPTION ) - 1 , 0 ) ;
ALLOC_INIT_ZVAL ( zoption ) ;
ZVAL_LONG ( zoption , option ) ;
ALLOC_INIT_ZVAL ( zvalue ) ;
ALLOC_INIT_ZVAL ( zptrparam ) ;
args [ 0 ] = & zoption ;
args [ 1 ] = & zvalue ;
args [ 2 ] = & zptrparam ;
switch ( option ) {
case PHP_STREAM_OPTION_READ_BUFFER :
case PHP_STREAM_OPTION_WRITE_BUFFER :
ZVAL_LONG ( zvalue , value ) ;
if ( ptrparam ) {
ZVAL_LONG ( zptrparam , * ( long * ) ptrparam ) ;
} else {
ZVAL_LONG ( zptrparam , BUFSIZ ) ;
}
break ;
case PHP_STREAM_OPTION_READ_TIMEOUT : {
struct timeval tv = * ( struct timeval * ) ptrparam ;
ZVAL_LONG ( zvalue , tv . tv_sec ) ;
ZVAL_LONG ( zptrparam , tv . tv_usec ) ;
break ;
}
case PHP_STREAM_OPTION_BLOCKING :
ZVAL_LONG ( zvalue , value ) ;
break ;
default :
break ;
}
call_result = call_user_function_ex ( NULL ,
& us - > object ,
& func_name ,
& retval ,
3 , args , 0 , NULL TSRMLS_CC ) ;
do {
if ( call_result = = FAILURE ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %s:: " USERSTREAM_SET_OPTION " is not implemented! " ,
us - > wrapper - > classname ) ;
break ;
}
if ( retval & & zend_is_true ( retval ) ) {
ret = PHP_STREAM_OPTION_RETURN_OK ;
}
} while ( 0 ) ;
if ( zoption ) {
zval_ptr_dtor ( & zoption ) ;
}
if ( zptrparam ) {
zval_ptr_dtor ( & zptrparam ) ;
}
break ;
}
2004-01-21 18:17:12 +08:00
}
/* clean up */
2004-03-08 06:05:21 +08:00
if ( retval ) {
zval_ptr_dtor ( & retval ) ;
}
if ( zvalue ) {
zval_ptr_dtor ( & zvalue ) ;
}
2004-01-21 18:17:12 +08:00
return ret ;
}
2003-05-15 02:30:49 +08:00
static int user_wrapper_unlink ( php_stream_wrapper * wrapper , char * url , int options , php_stream_context * context TSRMLS_DC )
{
struct php_user_stream_wrapper * uwrap = ( struct php_user_stream_wrapper * ) wrapper - > abstract ;
2008-07-11 18:25:15 +08:00
zval * zfilename , * zfuncname , * zretval ;
2003-05-15 02:30:49 +08:00
zval * * args [ 1 ] ;
int call_result ;
zval * object ;
int ret = 0 ;
/* create an instance of our class */
ALLOC_ZVAL ( object ) ;
object_init_ex ( object , uwrap - > ce ) ;
2007-10-07 13:22:07 +08:00
Z_SET_REFCOUNT_P ( object , 1 ) ;
Z_SET_ISREF_P ( object ) ;
2003-05-15 02:30:49 +08:00
2003-12-03 03:14:31 +08:00
if ( context ) {
2008-07-11 18:25:15 +08:00
add_property_resource ( object , " context " , context - > rsrc_id ) ;
zend_list_addref ( context - > rsrc_id ) ;
2003-12-03 03:14:31 +08:00
} else {
add_property_null ( object , " context " ) ;
}
2003-05-15 02:30:49 +08:00
/* call the unlink method */
MAKE_STD_ZVAL ( zfilename ) ;
ZVAL_STRING ( zfilename , url , 1 ) ;
args [ 0 ] = & zfilename ;
MAKE_STD_ZVAL ( zfuncname ) ;
ZVAL_STRING ( zfuncname , USERSTREAM_UNLINK , 1 ) ;
call_result = call_user_function_ex ( NULL ,
& object ,
zfuncname ,
& zretval ,
1 , args ,
0 , NULL TSRMLS_CC ) ;
if ( call_result = = SUCCESS & & zretval & & Z_TYPE_P ( zretval ) = = IS_BOOL ) {
ret = Z_LVAL_P ( zretval ) ;
} else if ( call_result = = FAILURE ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %s:: " USERSTREAM_UNLINK " is not implemented! " , uwrap - > classname ) ;
}
/* clean up */
zval_ptr_dtor ( & object ) ;
if ( zretval )
zval_ptr_dtor ( & zretval ) ;
zval_ptr_dtor ( & zfuncname ) ;
zval_ptr_dtor ( & zfilename ) ;
return ret ;
}
2003-12-13 07:06:42 +08:00
static int user_wrapper_rename ( php_stream_wrapper * wrapper , char * url_from , char * url_to , int options , php_stream_context * context TSRMLS_DC )
{
struct php_user_stream_wrapper * uwrap = ( struct php_user_stream_wrapper * ) wrapper - > abstract ;
2008-07-11 18:25:15 +08:00
zval * zold_name , * znew_name , * zfuncname , * zretval ;
2003-12-13 07:06:42 +08:00
zval * * args [ 2 ] ;
int call_result ;
zval * object ;
int ret = 0 ;
/* create an instance of our class */
ALLOC_ZVAL ( object ) ;
object_init_ex ( object , uwrap - > ce ) ;
2007-10-07 13:22:07 +08:00
Z_SET_REFCOUNT_P ( object , 1 ) ;
Z_SET_ISREF_P ( object ) ;
2003-12-13 07:06:42 +08:00
if ( context ) {
2008-07-11 18:25:15 +08:00
add_property_resource ( object , " context " , context - > rsrc_id ) ;
zend_list_addref ( context - > rsrc_id ) ;
2003-12-13 07:06:42 +08:00
} else {
add_property_null ( object , " context " ) ;
}
/* call the rename method */
MAKE_STD_ZVAL ( zold_name ) ;
ZVAL_STRING ( zold_name , url_from , 1 ) ;
args [ 0 ] = & zold_name ;
MAKE_STD_ZVAL ( znew_name ) ;
ZVAL_STRING ( znew_name , url_to , 1 ) ;
args [ 1 ] = & znew_name ;
MAKE_STD_ZVAL ( zfuncname ) ;
ZVAL_STRING ( zfuncname , USERSTREAM_RENAME , 1 ) ;
call_result = call_user_function_ex ( NULL ,
& object ,
zfuncname ,
& zretval ,
2 , args ,
0 , NULL TSRMLS_CC ) ;
if ( call_result = = SUCCESS & & zretval & & Z_TYPE_P ( zretval ) = = IS_BOOL ) {
ret = Z_LVAL_P ( zretval ) ;
} else if ( call_result = = FAILURE ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %s:: " USERSTREAM_RENAME " is not implemented! " , uwrap - > classname ) ;
}
/* clean up */
zval_ptr_dtor ( & object ) ;
if ( zretval )
zval_ptr_dtor ( & zretval ) ;
zval_ptr_dtor ( & zfuncname ) ;
zval_ptr_dtor ( & zold_name ) ;
zval_ptr_dtor ( & znew_name ) ;
return ret ;
}
2003-12-13 12:07:18 +08:00
static int user_wrapper_mkdir ( php_stream_wrapper * wrapper , char * url , int mode , int options , php_stream_context * context TSRMLS_DC )
{
struct php_user_stream_wrapper * uwrap = ( struct php_user_stream_wrapper * ) wrapper - > abstract ;
2008-07-11 18:25:15 +08:00
zval * zfilename , * zmode , * zoptions , * zfuncname , * zretval ;
2003-12-13 12:07:18 +08:00
zval * * args [ 3 ] ;
int call_result ;
zval * object ;
int ret = 0 ;
/* create an instance of our class */
ALLOC_ZVAL ( object ) ;
object_init_ex ( object , uwrap - > ce ) ;
2007-10-07 13:22:07 +08:00
Z_SET_REFCOUNT_P ( object , 1 ) ;
Z_SET_ISREF_P ( object ) ;
2003-12-13 12:07:18 +08:00
if ( context ) {
2008-07-11 18:25:15 +08:00
add_property_resource ( object , " context " , context - > rsrc_id ) ;
zend_list_addref ( context - > rsrc_id ) ;
2003-12-13 12:07:18 +08:00
} else {
add_property_null ( object , " context " ) ;
}
/* call the unlink method */
MAKE_STD_ZVAL ( zfilename ) ;
ZVAL_STRING ( zfilename , url , 1 ) ;
args [ 0 ] = & zfilename ;
MAKE_STD_ZVAL ( zmode ) ;
ZVAL_LONG ( zmode , mode ) ;
args [ 1 ] = & zmode ;
MAKE_STD_ZVAL ( zoptions ) ;
ZVAL_LONG ( zoptions , options ) ;
args [ 2 ] = & zoptions ;
MAKE_STD_ZVAL ( zfuncname ) ;
ZVAL_STRING ( zfuncname , USERSTREAM_MKDIR , 1 ) ;
call_result = call_user_function_ex ( NULL ,
& object ,
zfuncname ,
& zretval ,
3 , args ,
0 , NULL TSRMLS_CC ) ;
if ( call_result = = SUCCESS & & zretval & & Z_TYPE_P ( zretval ) = = IS_BOOL ) {
ret = Z_LVAL_P ( zretval ) ;
} else if ( call_result = = FAILURE ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %s:: " USERSTREAM_MKDIR " is not implemented! " , uwrap - > classname ) ;
}
/* clean up */
zval_ptr_dtor ( & object ) ;
if ( zretval ) {
zval_ptr_dtor ( & zretval ) ;
}
zval_ptr_dtor ( & zfuncname ) ;
zval_ptr_dtor ( & zfilename ) ;
zval_ptr_dtor ( & zmode ) ;
zval_ptr_dtor ( & zoptions ) ;
return ret ;
}
static int user_wrapper_rmdir ( php_stream_wrapper * wrapper , char * url , int options , php_stream_context * context TSRMLS_DC )
{
struct php_user_stream_wrapper * uwrap = ( struct php_user_stream_wrapper * ) wrapper - > abstract ;
2008-07-11 18:25:15 +08:00
zval * zfilename , * zoptions , * zfuncname , * zretval ;
2003-12-13 12:07:18 +08:00
zval * * args [ 3 ] ;
int call_result ;
zval * object ;
int ret = 0 ;
/* create an instance of our class */
ALLOC_ZVAL ( object ) ;
object_init_ex ( object , uwrap - > ce ) ;
2007-10-07 13:22:07 +08:00
Z_SET_REFCOUNT_P ( object , 1 ) ;
Z_SET_ISREF_P ( object ) ;
2003-12-13 12:07:18 +08:00
if ( context ) {
2008-07-11 18:25:15 +08:00
add_property_resource ( object , " context " , context - > rsrc_id ) ;
zend_list_addref ( context - > rsrc_id ) ;
2003-12-13 12:07:18 +08:00
} else {
add_property_null ( object , " context " ) ;
}
/* call the unlink method */
MAKE_STD_ZVAL ( zfilename ) ;
ZVAL_STRING ( zfilename , url , 1 ) ;
args [ 0 ] = & zfilename ;
MAKE_STD_ZVAL ( zoptions ) ;
ZVAL_LONG ( zoptions , options ) ;
args [ 1 ] = & zoptions ;
MAKE_STD_ZVAL ( zfuncname ) ;
ZVAL_STRING ( zfuncname , USERSTREAM_RMDIR , 1 ) ;
call_result = call_user_function_ex ( NULL ,
& object ,
zfuncname ,
& zretval ,
2 , args ,
0 , NULL TSRMLS_CC ) ;
if ( call_result = = SUCCESS & & zretval & & Z_TYPE_P ( zretval ) = = IS_BOOL ) {
ret = Z_LVAL_P ( zretval ) ;
} else if ( call_result = = FAILURE ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %s:: " USERSTREAM_RMDIR " is not implemented! " , uwrap - > classname ) ;
}
/* clean up */
zval_ptr_dtor ( & object ) ;
if ( zretval ) {
zval_ptr_dtor ( & zretval ) ;
}
zval_ptr_dtor ( & zfuncname ) ;
zval_ptr_dtor ( & zfilename ) ;
zval_ptr_dtor ( & zoptions ) ;
return ret ;
}
2003-12-03 02:52:58 +08:00
static int user_wrapper_stat_url ( php_stream_wrapper * wrapper , char * url , int flags , php_stream_statbuf * ssb , php_stream_context * context TSRMLS_DC )
2002-09-28 21:05:47 +08:00
{
struct php_user_stream_wrapper * uwrap = ( struct php_user_stream_wrapper * ) wrapper - > abstract ;
2008-07-11 18:25:15 +08:00
zval * zfilename , * zfuncname , * zretval , * zflags ;
2003-12-03 02:52:58 +08:00
zval * * args [ 2 ] ;
2002-09-28 21:05:47 +08:00
int call_result ;
zval * object ;
int ret = - 1 ;
/* create an instance of our class */
ALLOC_ZVAL ( object ) ;
object_init_ex ( object , uwrap - > ce ) ;
2007-10-07 13:22:07 +08:00
Z_SET_REFCOUNT_P ( object , 1 ) ;
Z_SET_ISREF_P ( object ) ;
2002-09-28 21:05:47 +08:00
2003-12-03 03:14:31 +08:00
if ( context ) {
2008-07-11 18:25:15 +08:00
add_property_resource ( object , " context " , context - > rsrc_id ) ;
zend_list_addref ( context - > rsrc_id ) ;
2003-12-03 03:14:31 +08:00
} else {
add_property_null ( object , " context " ) ;
}
2002-09-28 21:05:47 +08:00
/* call the stat_url method */
/* call it's stream_open method - set up params first */
MAKE_STD_ZVAL ( zfilename ) ;
ZVAL_STRING ( zfilename , url , 1 ) ;
args [ 0 ] = & zfilename ;
2003-12-03 02:52:58 +08:00
MAKE_STD_ZVAL ( zflags ) ;
ZVAL_LONG ( zflags , flags ) ;
args [ 1 ] = & zflags ;
2002-09-28 21:05:47 +08:00
MAKE_STD_ZVAL ( zfuncname ) ;
ZVAL_STRING ( zfuncname , USERSTREAM_STATURL , 1 ) ;
call_result = call_user_function_ex ( NULL ,
& object ,
zfuncname ,
& zretval ,
2003-12-03 02:52:58 +08:00
2 , args ,
2002-09-28 21:05:47 +08:00
0 , NULL TSRMLS_CC ) ;
if ( call_result = = SUCCESS & & zretval ! = NULL & & Z_TYPE_P ( zretval ) = = IS_ARRAY ) {
/* We got the info we needed */
if ( SUCCESS = = statbuf_from_array ( zretval , ssb TSRMLS_CC ) )
ret = 0 ;
} else {
if ( call_result = = FAILURE ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %s:: " USERSTREAM_STATURL " is not implemented! " ,
uwrap - > classname ) ;
}
}
/* clean up */
zval_ptr_dtor ( & object ) ;
if ( zretval )
zval_ptr_dtor ( & zretval ) ;
zval_ptr_dtor ( & zfuncname ) ;
zval_ptr_dtor ( & zfilename ) ;
2003-12-03 02:52:58 +08:00
zval_ptr_dtor ( & zflags ) ;
2002-09-28 21:05:47 +08:00
return ret ;
}
static size_t php_userstreamop_readdir ( php_stream * stream , char * buf , size_t count TSRMLS_DC )
{
zval func_name ;
zval * retval = NULL ;
int call_result ;
size_t didread = 0 ;
php_userstream_data_t * us = ( php_userstream_data_t * ) stream - > abstract ;
php_stream_dirent * ent = ( php_stream_dirent * ) buf ;
/* avoid problems if someone mis-uses the stream */
if ( count ! = sizeof ( php_stream_dirent ) )
return 0 ;
ZVAL_STRINGL ( & func_name , USERSTREAM_DIR_READ , sizeof ( USERSTREAM_DIR_READ ) - 1 , 0 ) ;
call_result = call_user_function_ex ( NULL ,
& us - > object ,
& func_name ,
& retval ,
0 , NULL ,
0 , NULL TSRMLS_CC ) ;
if ( call_result = = SUCCESS & & retval ! = NULL & & Z_TYPE_P ( retval ) ! = IS_BOOL ) {
convert_to_string ( retval ) ;
PHP_STRLCPY ( ent - > d_name , Z_STRVAL_P ( retval ) , sizeof ( ent - > d_name ) , Z_STRLEN_P ( retval ) ) ;
didread = sizeof ( php_stream_dirent ) ;
} else if ( call_result = = FAILURE ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %s:: " USERSTREAM_DIR_READ " is not implemented! " ,
2002-09-23 21:22:10 +08:00
us - > wrapper - > classname ) ;
2002-09-28 21:05:47 +08:00
}
if ( retval )
zval_ptr_dtor ( & retval ) ;
return didread ;
}
static int php_userstreamop_closedir ( php_stream * stream , int close_handle TSRMLS_DC )
{
zval func_name ;
zval * retval = NULL ;
php_userstream_data_t * us = ( php_userstream_data_t * ) stream - > abstract ;
assert ( us ! = NULL ) ;
2002-09-23 09:47:04 +08:00
2002-09-28 21:05:47 +08:00
ZVAL_STRINGL ( & func_name , USERSTREAM_DIR_CLOSE , sizeof ( USERSTREAM_DIR_CLOSE ) - 1 , 0 ) ;
call_user_function_ex ( NULL ,
& us - > object ,
& func_name ,
& retval ,
0 , NULL , 0 , NULL TSRMLS_CC ) ;
2002-03-19 11:51:01 +08:00
if ( retval )
2002-09-23 09:47:04 +08:00
zval_ptr_dtor ( & retval ) ;
2002-09-28 21:05:47 +08:00
zval_ptr_dtor ( & us - > object ) ;
2002-03-19 11:51:01 +08:00
2002-09-28 21:05:47 +08:00
efree ( us ) ;
2002-03-19 11:51:01 +08:00
return 0 ;
}
2002-09-28 21:05:47 +08:00
static int php_userstreamop_rewinddir ( php_stream * stream , off_t offset , int whence , off_t * newoffs TSRMLS_DC )
{
zval func_name ;
zval * retval = NULL ;
php_userstream_data_t * us = ( php_userstream_data_t * ) stream - > abstract ;
ZVAL_STRINGL ( & func_name , USERSTREAM_DIR_REWIND , sizeof ( USERSTREAM_DIR_REWIND ) - 1 , 0 ) ;
call_user_function_ex ( NULL ,
& us - > object ,
& func_name ,
& retval ,
0 , NULL , 0 , NULL TSRMLS_CC ) ;
if ( retval )
zval_ptr_dtor ( & retval ) ;
return 0 ;
}
2008-11-15 20:52:13 +08:00
static int php_userstreamop_cast ( php_stream * stream , int castas , void * * retptr TSRMLS_DC )
{
php_userstream_data_t * us = ( php_userstream_data_t * ) stream - > abstract ;
zval func_name ;
zval * retval = NULL ;
zval * zcastas = NULL ;
zval * * args [ 1 ] ;
php_stream * intstream = NULL ;
int call_result ;
int ret = FAILURE ;
ZVAL_STRINGL ( & func_name , USERSTREAM_CAST , sizeof ( USERSTREAM_CAST ) - 1 , 0 ) ;
ALLOC_INIT_ZVAL ( zcastas ) ;
switch ( castas ) {
case PHP_STREAM_AS_FD_FOR_SELECT :
ZVAL_LONG ( zcastas , PHP_STREAM_AS_FD_FOR_SELECT ) ;
break ;
default :
ZVAL_LONG ( zcastas , PHP_STREAM_AS_STDIO ) ;
break ;
}
args [ 0 ] = & zcastas ;
call_result = call_user_function_ex ( NULL ,
& us - > object ,
& func_name ,
& retval ,
1 , args , 0 , NULL TSRMLS_CC ) ;
do {
if ( call_result = = FAILURE ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %s:: " USERSTREAM_CAST " is not implemented! " ,
us - > wrapper - > classname ) ;
break ;
}
if ( retval = = NULL | | ! zend_is_true ( retval ) ) {
break ;
}
php_stream_from_zval_no_verify ( intstream , & retval ) ;
if ( ! intstream ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %s:: " USERSTREAM_CAST " must return a stream resource " ,
us - > wrapper - > classname ) ;
break ;
}
if ( intstream = = stream ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %s:: " USERSTREAM_CAST " must not return itself " ,
us - > wrapper - > classname ) ;
intstream = NULL ;
break ;
}
ret = php_stream_cast ( intstream , castas , retptr , 1 ) ;
} while ( 0 ) ;
if ( retval ) {
zval_ptr_dtor ( & retval ) ;
}
if ( zcastas ) {
zval_ptr_dtor ( & zcastas ) ;
}
return ret ;
}
2002-03-19 11:51:01 +08:00
php_stream_ops php_stream_userspace_ops = {
php_userstreamop_write , php_userstreamop_read ,
php_userstreamop_close , php_userstreamop_flush ,
2002-03-28 08:49:00 +08:00
" user-space " ,
2002-09-23 09:47:04 +08:00
php_userstreamop_seek ,
2008-11-15 20:52:13 +08:00
php_userstreamop_cast ,
2004-01-21 18:17:12 +08:00
php_userstreamop_stat ,
php_userstreamop_set_option ,
2002-09-28 21:05:47 +08:00
} ;
php_stream_ops php_stream_userspace_dir_ops = {
NULL , /* write */
php_userstreamop_readdir ,
php_userstreamop_closedir ,
NULL , /* flush */
" user-space-dir " ,
php_userstreamop_rewinddir ,
NULL , /* cast */
2002-09-23 09:47:04 +08:00
NULL , /* stat */
NULL /* set_option */
2002-03-19 11:51:01 +08:00
} ;