From: Marcus Boerger Date: Sat, 3 Mar 2007 20:41:12 +0000 (+0000) Subject: - Add glob stream wrapper X-Git-Tag: RELEASE_1_0_1~119 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=01220f548f62f02bc319e3afdd8d3014b01b1f63;p=php - Add glob stream wrapper --- diff --git a/configure.in b/configure.in index ef91543db2..7450e236dc 100644 --- a/configure.in +++ b/configure.in @@ -1229,7 +1229,7 @@ PHP_ADD_SOURCES(main, main.c snprintf.c spprintf.c php_sprintf.c \ PHP_ADD_SOURCES(main/streams, streams.c cast.c memory.c filter.c \ plain_wrapper.c userspace.c transports.c xp_socket.c mmap.c \ - unicode_filter.c ) + unicode_filter.c glob_wrapper.c) PHP_ADD_SOURCES(/main, internal_functions.c,, sapi) diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index d60d8556a7..36b84f9d7e 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -4064,6 +4064,7 @@ PHP_MINIT_FUNCTION(basic) php_register_url_stream_wrapper("php", &php_stream_php_wrapper TSRMLS_CC); php_register_url_stream_wrapper("file", &php_plain_files_wrapper TSRMLS_CC); + php_register_url_stream_wrapper("glob", &php_glob_stream_wrapper TSRMLS_CC); php_register_url_stream_wrapper("data", &php_stream_rfc2397_wrapper TSRMLS_CC); #ifndef PHP_CURL_URL_WRAPPERS php_register_url_stream_wrapper("http", &php_stream_http_wrapper TSRMLS_CC); diff --git a/main/php_streams.h b/main/php_streams.h index 0d0cf1750b..0d3da88bd3 100755 --- a/main/php_streams.h +++ b/main/php_streams.h @@ -545,6 +545,7 @@ END_EXTERN_C() #include "streams/php_stream_transport.h" #include "streams/php_stream_plain_wrapper.h" +#include "streams/php_stream_glob_wrapper.h" #include "streams/php_stream_userspace.h" #include "streams/php_stream_mmap.h" @@ -614,6 +615,9 @@ END_EXTERN_C() /* get (or create) a persistent version of the stream */ #define STREAM_OPEN_PERSISTENT 2048 +/* use glob stream for directory open in plain files stream */ +#define STREAM_USE_GLOB_DIR_OPEN 4096 + /* Antique - no longer has meaning */ #define IGNORE_URL_WIN 0 diff --git a/main/streams/glob_wrapper.c b/main/streams/glob_wrapper.c new file mode 100755 index 0000000000..26353832ba --- /dev/null +++ b/main/streams/glob_wrapper.c @@ -0,0 +1,232 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2007 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: Marcus Boerger | + +----------------------------------------------------------------------+ + */ + +/* $Id$ */ + +#include "php.h" +#include "php_streams_int.h" + +#ifdef HAVE_GLOB +# ifndef PHP_WIN32 +# include +# else +# include "win32/glob.h" +# endif +#endif + +#ifndef GLOB_ONLYDIR +#define GLOB_ONLYDIR (1<<30) +#define GLOB_FLAGMASK (~GLOB_ONLYDIR) +#else +#define GLOB_FLAGMASK (~0) +#endif + +typedef struct { + glob_t glob; + size_t index; + int flags; + char *path; + size_t path_len; +} glob_s_t; + +PHPAPI char* _php_glob_stream_get_path(php_stream *stream, int copy, int *plen STREAMS_DC TSRMLS_DC) /* {{{ */ +{ + glob_s_t *pglob = (glob_s_t *)stream->abstract; + + if (pglob && pglob->path) { + if (plen) { + *plen = pglob->path_len; + } + if (copy) { + return estrndup(pglob->path, pglob->path_len); + } else { + return pglob->path; + } + } else { + if (plen) { + *plen = 0; + } + return NULL; + } +} +/* }}} */ + +static void php_glob_stream_path_split(glob_s_t *pglob, char *path, int get_path, char **p_file TSRMLS_DC) /* {{{ */ +{ + char *pos, *gpath = path; + + if ((pos = strrchr(path, '/')) != NULL) { + path = pos+1; + } +#if defined(PHP_WIN32) || defined(NETWARE) + if ((pos = strrchr(path, '\\')) != NULL) { + if (pos != NULL) { + path = pos+1; + } +#endif + + *p_file = path; + + if (get_path) { + if (pglob->path) { + efree(pglob->path); + } + pglob->path_len = path - gpath; + pglob->path = estrndup(gpath, pglob->path_len); + } +} +/* }}} */ + +static size_t php_glob_stream_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) /* {{{ */ +{ + glob_s_t *pglob = (glob_s_t *)stream->abstract; + php_stream_dirent *ent = (php_stream_dirent*)buf; + char *path; + + /* avoid problems if someone mis-uses the stream */ + if (count == sizeof(php_stream_dirent) && pglob) { + if (pglob->index < pglob->glob.gl_pathc) { + php_glob_stream_path_split(pglob, pglob->glob.gl_pathv[pglob->index++], pglob->flags & GLOB_APPEND, &path TSRMLS_CC); + PHP_STRLCPY(ent->d_name, path, sizeof(ent->d_name), strlen(path)); + return sizeof(php_stream_dirent); + } + pglob->index = pglob->glob.gl_pathc; + if (pglob->path) { + efree(pglob->path); + pglob->path = NULL; + } + } + + return 0; +} +/* }}} */ + +static int php_glob_stream_close(php_stream *stream, int close_handle TSRMLS_DC) /* {{{ */ +{ + glob_s_t *pglob = (glob_s_t *)stream->abstract; + + if (pglob) { + pglob->index = 0; + globfree(&pglob->glob); + if (pglob->path) { + efree(pglob->path); + } + } + efree(stream->abstract); + return 0; +} +/* {{{ */ + +static int php_glob_stream_rewind(php_stream *stream, off_t offset, int whence, off_t *newoffs TSRMLS_DC) /* {{{ */ +{ + glob_s_t *pglob = (glob_s_t *)stream->abstract; + + if (pglob) { + pglob->index = 0; + if (pglob->path) { + efree(pglob->path); + pglob->path = NULL; + } + } + return 0; +} +/* }}} */ + +static php_stream_ops php_glob_stream_ops = { + NULL, php_glob_stream_read, + php_glob_stream_close, NULL, + "glob", + php_glob_stream_rewind, + NULL, /* cast */ + NULL, /* stat */ + NULL /* set_option */ +}; + + /* {{{ php_glob_stream_opener */ +static php_stream *php_glob_stream_opener(php_stream_wrapper *wrapper, char *path, char *mode, + int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) +{ + glob_s_t *pglob; + int ret; + char *tmp; + + if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(path TSRMLS_CC)) { + return NULL; + } + + if (!strncmp(path, "glob://", sizeof("glob://")-1)) { + path += sizeof("glob://")-1; + if (opened_path) { + *opened_path = estrdup(path); + } + } + + pglob = ecalloc(sizeof(*pglob), 1); + + if (0 != (ret = glob(path, pglob->flags & GLOB_FLAGMASK, NULL, &pglob->glob))) { +#ifdef GLOB_NOMATCH + if (GLOB_NOMATCH != ret) +#endif + { + efree(pglob); + return NULL; + } + } + +#ifdef GLOB_APPEND + if ((pglob->flags & GLOB_APPEND) == 0) +#endif + { + if (pglob->glob.gl_pathc) { + php_glob_stream_path_split(pglob, pglob->glob.gl_pathv[0], 1, &tmp TSRMLS_CC); + } else { + php_glob_stream_path_split(pglob, path, 1, &tmp TSRMLS_CC); + } + } + + return php_stream_alloc(&php_glob_stream_ops, pglob, 0, mode); +} +/* }}} */ + +static php_stream_wrapper_ops php_glob_stream_wrapper_ops = { + NULL, + NULL, + NULL, + NULL, + php_glob_stream_opener, + "glob", + NULL, + NULL, + NULL, + NULL +}; + +php_stream_wrapper php_glob_stream_wrapper = { + &php_glob_stream_wrapper_ops, + NULL, + 0 +}; + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/main/streams/php_stream_glob_wrapper.h b/main/streams/php_stream_glob_wrapper.h new file mode 100755 index 0000000000..00bba9afe4 --- /dev/null +++ b/main/streams/php_stream_glob_wrapper.h @@ -0,0 +1,37 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2007 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. | + +----------------------------------------------------------------------+ + | Author: Marcus Boerger | + +----------------------------------------------------------------------+ + */ + +/* $Id$ */ + +PHPAPI extern php_stream_wrapper php_glob_stream_wrapper; + +BEGIN_EXTERN_C() + +PHPAPI char* _php_glob_stream_get_path(php_stream *stream, int copy, int *plen STREAMS_DC TSRMLS_DC); +#define php_glob_stream_get_path(stream, copy, plen) _php_glob_stream_get_path((stream), (copy), (plen) STREAMS_CC TSRMLS_CC) + +END_EXTERN_C() + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c index 2688838481..40fe2a9a77 100644 --- a/main/streams/plain_wrapper.c +++ b/main/streams/plain_wrapper.c @@ -836,6 +836,10 @@ static php_stream *php_plain_files_dir_opener(php_stream_wrapper *wrapper, char DIR *dir = NULL; php_stream *stream = NULL; + if (options & STREAM_USE_GLOB_DIR_OPEN) { + return php_glob_stream_wrapper.wops->dir_opener(&php_glob_stream_wrapper, path, mode, options, opened_path, context STREAMS_REL_CC TSRMLS_CC); + } + if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(path TSRMLS_CC)) { return NULL; }