12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697 |
- /*
- +----------------------------------------------------------------------+
- | PHP Version 5 |
- +----------------------------------------------------------------------+
- | Copyright (c) 1997-2016 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | 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. |
- +----------------------------------------------------------------------+
- | Authors: Wez Furlong <wez@thebrainroom.com> |
- | Sara Golemon <pollita@php.net> |
- +----------------------------------------------------------------------+
- */
- /* $Id$ */
- #include "php.h"
- #include "php_globals.h"
- #include "ext/standard/file.h"
- #include "ext/standard/flock_compat.h"
- #ifdef HAVE_SYS_FILE_H
- #include <sys/file.h>
- #endif
- #include <stddef.h>
- #if HAVE_UTIME
- # ifdef PHP_WIN32
- # include <sys/utime.h>
- # else
- # include <utime.h>
- # endif
- #endif
- static int le_protocols;
- struct php_user_stream_wrapper {
- char * protoname;
- char * classname;
- zend_class_entry *ce;
- php_stream_wrapper wrapper;
- };
- static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, const char *filename, const char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC);
- static int user_wrapper_stat_url(php_stream_wrapper *wrapper, const char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC);
- static int user_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context TSRMLS_DC);
- static int user_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from, const char *url_to, int options, php_stream_context *context TSRMLS_DC);
- static int user_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url, int mode, int options, php_stream_context *context TSRMLS_DC);
- static int user_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context TSRMLS_DC);
- static int user_wrapper_metadata(php_stream_wrapper *wrapper, const char *url, int option, void *value, php_stream_context *context TSRMLS_DC);
- static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, const char *filename, const char *mode,
- int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC);
- static php_stream_wrapper_ops user_stream_wops = {
- user_wrapper_opener,
- NULL, /* close - the streams themselves know how */
- NULL, /* stat - the streams themselves know how */
- user_wrapper_stat_url,
- user_wrapper_opendir,
- "user-space",
- user_wrapper_unlink,
- user_wrapper_rename,
- user_wrapper_mkdir,
- user_wrapper_rmdir,
- user_wrapper_metadata
- };
- 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);
- }
- PHP_MINIT_FUNCTION(user_streams)
- {
- le_protocols = zend_register_list_destructors_ex(stream_wrapper_dtor, NULL, "stream factory", 0);
- 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_REPORT_ERRORS", REPORT_ERRORS, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("STREAM_MUST_SEEK", STREAM_MUST_SEEK, CONST_CS|CONST_PERSISTENT);
- 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);
- 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_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);
- REGISTER_LONG_CONSTANT("STREAM_META_TOUCH", PHP_STREAM_META_TOUCH, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("STREAM_META_OWNER", PHP_STREAM_META_OWNER, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("STREAM_META_OWNER_NAME", PHP_STREAM_META_OWNER_NAME, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("STREAM_META_GROUP", PHP_STREAM_META_GROUP, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("STREAM_META_GROUP_NAME", PHP_STREAM_META_GROUP_NAME, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("STREAM_META_ACCESS", PHP_STREAM_META_ACCESS, CONST_CS|CONST_PERSISTENT);
- return SUCCESS;
- }
- 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"
- #define USERSTREAM_STAT "stream_stat"
- #define USERSTREAM_STATURL "url_stat"
- #define USERSTREAM_UNLINK "unlink"
- #define USERSTREAM_RENAME "rename"
- #define USERSTREAM_MKDIR "mkdir"
- #define USERSTREAM_RMDIR "rmdir"
- #define USERSTREAM_DIR_OPEN "dir_opendir"
- #define USERSTREAM_DIR_READ "dir_readdir"
- #define USERSTREAM_DIR_REWIND "dir_rewinddir"
- #define USERSTREAM_DIR_CLOSE "dir_closedir"
- #define USERSTREAM_LOCK "stream_lock"
- #define USERSTREAM_CAST "stream_cast"
- #define USERSTREAM_SET_OPTION "stream_set_option"
- #define USERSTREAM_TRUNCATE "stream_truncate"
- #define USERSTREAM_METADATA "stream_metadata"
- /* {{{ class should have methods like these:
- 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;
- }
- function stream_stat()
- {
- return array( just like that returned by fstat() );
- }
- 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;
- }
- }
- function url_stat(string $url, int $flags)
- {
- return array( just like that returned by stat() );
- }
- function unlink(string $url)
- {
- return true / false;
- }
- function rename(string $from, string $to)
- {
- return true / false;
- }
- function mkdir($dir, $mode, $options)
- {
- return true / false;
- }
- function rmdir($dir, $options)
- {
- return true / false;
- }
- 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;
- }
- function stream_lock($operation)
- {
- return true / false;
- }
- function stream_truncate($new_size)
- {
- return true / false;
- }
- }}} **/
- static zval *user_stream_create_object(struct php_user_stream_wrapper *uwrap, php_stream_context *context TSRMLS_DC)
- {
- zval *object;
- /* create an instance of our class */
- ALLOC_ZVAL(object);
- object_init_ex(object, uwrap->ce);
- Z_SET_REFCOUNT_P(object, 1);
- Z_SET_ISREF_P(object);
- if (context) {
- add_property_resource(object, "context", context->rsrc_id);
- zend_list_addref(context->rsrc_id);
- } else {
- add_property_null(object, "context");
- }
- 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_ptr = 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);
- fcc.called_scope = Z_OBJCE_P(object);
- fcc.object_ptr = 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(object);
- FREE_ZVAL(object);
- return NULL;
- } else {
- if (retval_ptr) {
- zval_ptr_dtor(&retval_ptr);
- }
- }
- }
- return object;
- }
- static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, const char *filename, const 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;
- zval *zfilename, *zmode, *zopened, *zoptions, *zretval = NULL, *zfuncname;
- zval **args[4];
- int call_result;
- php_stream *stream = NULL;
- zend_bool old_in_user_include;
- /* 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;
- /* 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;
- }
- us = emalloc(sizeof(*us));
- us->wrapper = uwrap;
- us->object = user_stream_create_object(uwrap, context TSRMLS_CC);
- if(us->object == NULL) {
- FG(user_stream_current_filename) = NULL;
- PG(in_user_include) = old_in_user_include;
- efree(us);
- return NULL;
- }
- /* 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);
- Z_SET_REFCOUNT_P(zopened, 1);
- Z_SET_ISREF_P(zopened);
- ZVAL_NULL(zopened);
- args[3] = &zopened;
- MAKE_STD_ZVAL(zfuncname);
- ZVAL_STRING(zfuncname, USERSTREAM_OPEN, 1);
- zend_try {
- call_result = call_user_function_ex(NULL,
- &us->object,
- zfuncname,
- &zretval,
- 4, args,
- 0, NULL TSRMLS_CC);
- } zend_catch {
- FG(user_stream_current_filename) = NULL;
- zend_bailout();
- } zend_end_try();
- if (call_result == SUCCESS && zretval != NULL && zval_is_true(zretval)) {
- /* 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));
- }
- /* 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_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(&zopened);
- zval_ptr_dtor(&zoptions);
- zval_ptr_dtor(&zmode);
- zval_ptr_dtor(&zfilename);
- FG(user_stream_current_filename) = NULL;
- PG(in_user_include) = old_in_user_include;
- return stream;
- }
- static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, const char *filename, const 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;
- zval *zfilename, *zoptions, *zretval = NULL, *zfuncname;
- 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;
- us->object = user_stream_create_object(uwrap, context TSRMLS_CC);
- if(us->object == NULL) {
- FG(user_stream_current_filename) = NULL;
- efree(us);
- return NULL;
- }
- /* 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;
- }
- /* {{{ proto bool stream_wrapper_register(string protocol, string classname[, integer flags])
- Registers a custom URL protocol handler class */
- PHP_FUNCTION(stream_wrapper_register)
- {
- char *protocol, *classname;
- int protocol_len, classname_len;
- struct php_user_stream_wrapper * uwrap;
- int rsrc_id;
- long flags = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &protocol, &protocol_len, &classname, &classname_len, &flags) == FAILURE) {
- RETURN_FALSE;
- }
- uwrap = (struct php_user_stream_wrapper *)ecalloc(1, sizeof(*uwrap));
- uwrap->protoname = estrndup(protocol, protocol_len);
- uwrap->classname = estrndup(classname, classname_len);
- uwrap->wrapper.wops = &user_stream_wops;
- uwrap->wrapper.abstract = uwrap;
- uwrap->wrapper.is_url = ((flags & PHP_STREAM_IS_URL) != 0);
- rsrc_id = ZEND_REGISTER_RESOURCE(NULL, uwrap, le_protocols);
- if (zend_lookup_class(uwrap->classname, classname_len, (zend_class_entry***)&uwrap->ce TSRMLS_CC) == SUCCESS) {
- uwrap->ce = *(zend_class_entry**)uwrap->ce;
- if (php_register_url_stream_wrapper_volatile(protocol, &uwrap->wrapper TSRMLS_CC) == SUCCESS) {
- RETURN_TRUE;
- } else {
- /* We failed. But why? */
- if (zend_hash_exists(php_stream_get_url_stream_wrappers_hash(), protocol, protocol_len + 1)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Protocol %s:// is already defined.", protocol);
- } else {
- /* 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);
- }
- }
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "class '%s' is undefined", classname);
- }
- zend_list_delete(rsrc_id);
- RETURN_FALSE;
- }
- /* }}} */
- /* {{{ proto bool stream_wrapper_unregister(string protocol)
- 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;
- }
- /* }}} */
- /* {{{ proto bool stream_wrapper_restore(string protocol)
- Restore the original protocol handler, overriding if necessary */
- PHP_FUNCTION(stream_wrapper_restore)
- {
- char *protocol;
- int protocol_len;
- php_stream_wrapper **wrapperpp = NULL, *wrapper;
- 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;
- }
- if ((zend_hash_find(global_wrapper_hash, protocol, protocol_len + 1, (void**)&wrapperpp) == FAILURE) || !wrapperpp) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s:// never existed, nothing to restore", protocol);
- RETURN_FALSE;
- }
- /* next line might delete the pointer that wrapperpp points at, so deref it now */
- wrapper = *wrapperpp;
- /* 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;
- }
- /* }}} */
- 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];
- zval *zbufptr;
- size_t didwrite = 0;
- assert(us != NULL);
- ZVAL_STRINGL(&func_name, USERSTREAM_WRITE, sizeof(USERSTREAM_WRITE)-1, 0);
- MAKE_STD_ZVAL(zbufptr);
- ZVAL_STRINGL(zbufptr, (char*)buf, count, 1);;
- args[0] = &zbufptr;
- call_result = call_user_function_ex(NULL,
- &us->object,
- &func_name,
- &retval,
- 1, args,
- 0, NULL TSRMLS_CC);
- zval_ptr_dtor(&zbufptr);
- didwrite = 0;
- if (EG(exception)) {
- return 0;
- }
- if (call_result == SUCCESS && retval != NULL) {
- convert_to_long(retval);
- didwrite = Z_LVAL_P(retval);
- } else if (call_result == FAILURE) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_WRITE " is not implemented!",
- us->wrapper->classname);
- }
- /* don't allow strange buffer overruns due to bogus return */
- if (didwrite > count) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_WRITE " wrote %ld bytes more data than requested (%ld written, %ld max)",
- us->wrapper->classname,
- (long)(didwrite - count), (long)didwrite, (long)count);
- didwrite = count;
- }
- 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;
- zval *zcount;
- assert(us != NULL);
- ZVAL_STRINGL(&func_name, USERSTREAM_READ, sizeof(USERSTREAM_READ)-1, 0);
- MAKE_STD_ZVAL(zcount);
- ZVAL_LONG(zcount, count);
- args[0] = &zcount;
- call_result = call_user_function_ex(NULL,
- &us->object,
- &func_name,
- &retval,
- 1, args,
- 0, NULL TSRMLS_CC);
- zval_ptr_dtor(&zcount);
- if (EG(exception)) {
- return 0;
- }
- if (call_result == SUCCESS && retval != NULL) {
- convert_to_string(retval);
- didread = Z_STRLEN_P(retval);
- if (didread > count) {
- 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);
- didread = count;
- }
- 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);
- }
- if (retval) {
- zval_ptr_dtor(&retval);
- retval = NULL;
- }
- /* 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);
- 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);
- stream->eof = 1;
- }
- if (retval) {
- zval_ptr_dtor(&retval);
- retval = NULL;
- }
- 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);
- call_user_function_ex(NULL,
- &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;
- }
- static int php_userstreamop_seek(php_stream *stream, off_t offset, int whence, off_t *newoffs TSRMLS_DC)
- {
- zval func_name;
- zval *retval = NULL;
- int call_result, ret;
- php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract;
- zval **args[2];
- zval *zoffs, *zwhence;
- assert(us != NULL);
- ZVAL_STRINGL(&func_name, USERSTREAM_SEEK, sizeof(USERSTREAM_SEEK)-1, 0);
- 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,
- &us->object,
- &func_name,
- &retval,
- 2, args,
- 0, NULL TSRMLS_CC);
- zval_ptr_dtor(&zoffs);
- zval_ptr_dtor(&zwhence);
- 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 */
- if (retval)
- zval_ptr_dtor(&retval);
- return -1;
- } else if (call_result == SUCCESS && retval != NULL && zval_is_true(retval)) {
- ret = 0;
- } else {
- ret = -1;
- }
- if (retval) {
- zval_ptr_dtor(&retval);
- retval = NULL;
- }
- if (ret) {
- return ret;
- }
- /* now determine where we are */
- ZVAL_STRINGL(&func_name, USERSTREAM_TELL, sizeof(USERSTREAM_TELL)-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_LONG) {
- *newoffs = Z_LVAL_P(retval);
- 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;
- }
- if (retval) {
- zval_ptr_dtor(&retval);
- }
- return ret;
- }
- /* 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)
- {
- zval **elem;
- #define STAT_PROP_ENTRY_EX(name, name2) \
- if (SUCCESS == zend_hash_find(Z_ARRVAL_P(array), #name, sizeof(#name), (void**)&elem)) { \
- SEPARATE_ZVAL(elem); \
- convert_to_long(*elem); \
- ssb->sb.st_##name2 = Z_LVAL_PP(elem); \
- }
- #define STAT_PROP_ENTRY(name) STAT_PROP_ENTRY_EX(name,name)
- memset(ssb, 0, sizeof(php_stream_statbuf));
- 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);
- #ifdef NETWARE
- STAT_PROP_ENTRY_EX(atime, atime.tv_sec);
- STAT_PROP_ENTRY_EX(mtime, mtime.tv_sec);
- STAT_PROP_ENTRY_EX(ctime, ctime.tv_sec);
- #else
- STAT_PROP_ENTRY(atime);
- STAT_PROP_ENTRY(mtime);
- STAT_PROP_ENTRY(ctime);
- #endif
- #ifdef HAVE_ST_BLKSIZE
- STAT_PROP_ENTRY(blksize);
- #endif
- #ifdef HAVE_ST_BLOCKS
- STAT_PROP_ENTRY(blocks);
- #endif
- #undef STAT_PROP_ENTRY
- #undef STAT_PROP_ENTRY_EX
- 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);
- }
- }
- if (retval)
- zval_ptr_dtor(&retval);
- return ret;
- }
- 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 = PHP_STREAM_OPTION_RETURN_NOTIMPL;
- zval *zvalue = NULL;
- zval **args[3];
- switch (option) {
- 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) {
- ret = zval_is_true(retval) ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK;
- } 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;
- case PHP_STREAM_OPTION_LOCKING:
- MAKE_STD_ZVAL(zvalue);
- 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;
- }
- args[0] = &zvalue;
- /* TODO wouldblock */
- 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) {
- /* lock support test (TODO: more check) */
- ret = PHP_STREAM_OPTION_RETURN_OK;
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_LOCK " is not implemented!",
- us->wrapper->classname);
- ret = PHP_STREAM_OPTION_RETURN_ERR;
- }
- }
- break;
- case PHP_STREAM_OPTION_TRUNCATE_API:
- ZVAL_STRINGL(&func_name, USERSTREAM_TRUNCATE, sizeof(USERSTREAM_TRUNCATE)-1, 0);
- switch (value) {
- case PHP_STREAM_TRUNCATE_SUPPORTED:
- if (zend_is_callable_ex(&func_name, us->object, IS_CALLABLE_CHECK_SILENT,
- NULL, NULL, NULL, NULL TSRMLS_CC))
- ret = PHP_STREAM_OPTION_RETURN_OK;
- else
- ret = PHP_STREAM_OPTION_RETURN_ERR;
- break;
- case PHP_STREAM_TRUNCATE_SET_SIZE: {
- ptrdiff_t new_size = *(ptrdiff_t*) ptrparam;
- if (new_size >= 0 && new_size <= (ptrdiff_t)LONG_MAX) {
- MAKE_STD_ZVAL(zvalue);
- ZVAL_LONG(zvalue, (long)new_size);
- args[0] = &zvalue;
- call_result = call_user_function_ex(NULL,
- &us->object,
- &func_name,
- &retval,
- 1, args, 0, NULL TSRMLS_CC);
- if (call_result == SUCCESS && retval != NULL) {
- if (Z_TYPE_P(retval) == IS_BOOL) {
- ret = Z_LVAL_P(retval) ? PHP_STREAM_OPTION_RETURN_OK :
- PHP_STREAM_OPTION_RETURN_ERR;
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
- "%s::" USERSTREAM_TRUNCATE " did not return a boolean!",
- us->wrapper->classname);
- }
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
- "%s::" USERSTREAM_TRUNCATE " is not implemented!",
- us->wrapper->classname);
- }
- } else { /* bad new size */
- ret = PHP_STREAM_OPTION_RETURN_ERR;
- }
- break;
- }
- }
- break;
- 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);
- if (call_result == FAILURE) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_SET_OPTION " is not implemented!",
- us->wrapper->classname);
- ret = PHP_STREAM_OPTION_RETURN_ERR;
- } else if (retval && zend_is_true(retval)) {
- ret = PHP_STREAM_OPTION_RETURN_OK;
- } else {
- ret = PHP_STREAM_OPTION_RETURN_ERR;
- }
- if (zoption) {
- zval_ptr_dtor(&zoption);
- }
- if (zptrparam) {
- zval_ptr_dtor(&zptrparam);
- }
- break;
- }
- }
- /* clean up */
- if (retval) {
- zval_ptr_dtor(&retval);
- }
- if (zvalue) {
- zval_ptr_dtor(&zvalue);
- }
- return ret;
- }
- static int user_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context TSRMLS_DC)
- {
- struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract;
- zval *zfilename, *zfuncname, *zretval;
- zval **args[1];
- int call_result;
- zval *object;
- int ret = 0;
- /* create an instance of our class */
- object = user_stream_create_object(uwrap, context TSRMLS_CC);
- if(object == NULL) {
- return ret;
- }
- /* 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;
- }
- static int user_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from, const char *url_to,
- int options, php_stream_context *context TSRMLS_DC)
- {
- struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract;
- zval *zold_name, *znew_name, *zfuncname, *zretval;
- zval **args[2];
- int call_result;
- zval *object;
- int ret = 0;
- /* create an instance of our class */
- object = user_stream_create_object(uwrap, context TSRMLS_CC);
- if(object == NULL) {
- return ret;
- }
- /* 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;
- }
- static int user_wrapper_mkdir(php_stream_wrapper *wrapper, const 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;
- zval *zfilename, *zmode, *zoptions, *zfuncname, *zretval;
- zval **args[3];
- int call_result;
- zval *object;
- int ret = 0;
- /* create an instance of our class */
- object = user_stream_create_object(uwrap, context TSRMLS_CC);
- if(object == NULL) {
- return ret;
- }
- /* call the mkdir 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, const char *url,
- int options, php_stream_context *context TSRMLS_DC)
- {
- struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract;
- zval *zfilename, *zoptions, *zfuncname, *zretval;
- zval **args[3];
- int call_result;
- zval *object;
- int ret = 0;
- /* create an instance of our class */
- object = user_stream_create_object(uwrap, context TSRMLS_CC);
- if(object == NULL) {
- return ret;
- }
- /* call the rmdir 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;
- }
- static int user_wrapper_metadata(php_stream_wrapper *wrapper, const char *url, int option,
- void *value, php_stream_context *context TSRMLS_DC)
- {
- struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract;
- zval *zfilename, *zoption, *zvalue, *zfuncname, *zretval;
- zval **args[3];
- int call_result;
- zval *object;
- int ret = 0;
- MAKE_STD_ZVAL(zvalue);
- switch(option) {
- case PHP_STREAM_META_TOUCH:
- array_init(zvalue);
- if(value) {
- struct utimbuf *newtime = (struct utimbuf *)value;
- add_index_long(zvalue, 0, newtime->modtime);
- add_index_long(zvalue, 1, newtime->actime);
- }
- break;
- case PHP_STREAM_META_GROUP:
- case PHP_STREAM_META_OWNER:
- case PHP_STREAM_META_ACCESS:
- ZVAL_LONG(zvalue, *(long *)value);
- break;
- case PHP_STREAM_META_GROUP_NAME:
- case PHP_STREAM_META_OWNER_NAME:
- ZVAL_STRING(zvalue, value, 1);
- break;
- default:
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown option %d for " USERSTREAM_METADATA, option);
- zval_ptr_dtor(&zvalue);
- return ret;
- }
- /* create an instance of our class */
- object = user_stream_create_object(uwrap, context TSRMLS_CC);
- if(object == NULL) {
- zval_ptr_dtor(&zvalue);
- return ret;
- }
- /* call the mkdir method */
- MAKE_STD_ZVAL(zfilename);
- ZVAL_STRING(zfilename, url, 1);
- args[0] = &zfilename;
- MAKE_STD_ZVAL(zoption);
- ZVAL_LONG(zoption, option);
- args[1] = &zoption;
- args[2] = &zvalue;
- MAKE_STD_ZVAL(zfuncname);
- ZVAL_STRING(zfuncname, USERSTREAM_METADATA, 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_METADATA " 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(&zoption);
- zval_ptr_dtor(&zvalue);
- return ret;
- }
- static int user_wrapper_stat_url(php_stream_wrapper *wrapper, const char *url, int flags,
- php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC)
- {
- struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract;
- zval *zfilename, *zfuncname, *zretval, *zflags;
- zval **args[2];
- int call_result;
- zval *object;
- int ret = -1;
- /* create an instance of our class */
- object = user_stream_create_object(uwrap, context TSRMLS_CC);
- if(object == NULL) {
- return ret;
- }
- /* call it's stat_url method - set up params first */
- MAKE_STD_ZVAL(zfilename);
- ZVAL_STRING(zfilename, url, 1);
- args[0] = &zfilename;
- MAKE_STD_ZVAL(zflags);
- ZVAL_LONG(zflags, flags);
- args[1] = &zflags;
- MAKE_STD_ZVAL(zfuncname);
- ZVAL_STRING(zfuncname, USERSTREAM_STATURL, 1);
- call_result = call_user_function_ex(NULL,
- &object,
- zfuncname,
- &zretval,
- 2, args,
- 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);
- zval_ptr_dtor(&zflags);
- 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!",
- us->wrapper->classname);
- }
- 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);
- 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);
- if (retval)
- zval_ptr_dtor(&retval);
- zval_ptr_dtor(&us->object);
- efree(us);
- return 0;
- }
- 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;
- }
- 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;
- }
- php_stream_ops php_stream_userspace_ops = {
- php_userstreamop_write, php_userstreamop_read,
- php_userstreamop_close, php_userstreamop_flush,
- "user-space",
- php_userstreamop_seek,
- php_userstreamop_cast,
- php_userstreamop_stat,
- php_userstreamop_set_option,
- };
- 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 */
- NULL, /* stat */
- NULL /* set_option */
- };
|