1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 5 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2014 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Marcus Boerger <helly@php.net> |
16 +----------------------------------------------------------------------+
17 */
18
19 /* $Id$ */
20
21 #include "php.h"
22 #include "php_streams_int.h"
23
24 #ifdef HAVE_GLOB
25 # ifndef PHP_WIN32
26 # include <glob.h>
27 # else
28 # include "win32/glob.h"
29 # endif
30 #endif
31
32 #ifdef HAVE_GLOB
33 #ifndef GLOB_ONLYDIR
34 #define GLOB_ONLYDIR (1<<30)
35 #define GLOB_FLAGMASK (~GLOB_ONLYDIR)
36 #else
37 #define GLOB_FLAGMASK (~0)
38 #endif
39
40 typedef struct {
41 glob_t glob;
42 size_t index;
43 int flags;
44 char *path;
45 size_t path_len;
46 char *pattern;
47 size_t pattern_len;
48 } glob_s_t;
49
_php_glob_stream_get_path(php_stream * stream,int copy,int * plen STREAMS_DC TSRMLS_DC)50 PHPAPI char* _php_glob_stream_get_path(php_stream *stream, int copy, int *plen STREAMS_DC TSRMLS_DC) /* {{{ */
51 {
52 glob_s_t *pglob = (glob_s_t *)stream->abstract;
53
54 if (pglob && pglob->path) {
55 if (plen) {
56 *plen = pglob->path_len;
57 }
58 if (copy) {
59 return estrndup(pglob->path, pglob->path_len);
60 } else {
61 return pglob->path;
62 }
63 } else {
64 if (plen) {
65 *plen = 0;
66 }
67 return NULL;
68 }
69 }
70 /* }}} */
71
_php_glob_stream_get_pattern(php_stream * stream,int copy,int * plen STREAMS_DC TSRMLS_DC)72 PHPAPI char* _php_glob_stream_get_pattern(php_stream *stream, int copy, int *plen STREAMS_DC TSRMLS_DC) /* {{{ */
73 {
74 glob_s_t *pglob = (glob_s_t *)stream->abstract;
75
76 if (pglob && pglob->pattern) {
77 if (plen) {
78 *plen = pglob->pattern_len;
79 }
80 if (copy) {
81 return estrndup(pglob->pattern, pglob->pattern_len);
82 } else {
83 return pglob->pattern;
84 }
85 } else {
86 if (plen) {
87 *plen = 0;
88 }
89 return NULL;
90 }
91 }
92 /* }}} */
93
_php_glob_stream_get_count(php_stream * stream,int * pflags STREAMS_DC TSRMLS_DC)94 PHPAPI int _php_glob_stream_get_count(php_stream *stream, int *pflags STREAMS_DC TSRMLS_DC) /* {{{ */
95 {
96 glob_s_t *pglob = (glob_s_t *)stream->abstract;
97
98 if (pglob) {
99 if (pflags) {
100 *pflags = pglob->flags;
101 }
102 return pglob->glob.gl_pathc;
103 } else {
104 if (pflags) {
105 *pflags = 0;
106 }
107 return 0;
108 }
109 }
110 /* }}} */
111
php_glob_stream_path_split(glob_s_t * pglob,char * path,int get_path,char ** p_file TSRMLS_DC)112 static void php_glob_stream_path_split(glob_s_t *pglob, char *path, int get_path, char **p_file TSRMLS_DC) /* {{{ */
113 {
114 char *pos, *gpath = path;
115
116 if ((pos = strrchr(path, '/')) != NULL) {
117 path = pos+1;
118 }
119 #if defined(PHP_WIN32) || defined(NETWARE)
120 if ((pos = strrchr(path, '\\')) != NULL) {
121 path = pos+1;
122 }
123 #endif
124
125 *p_file = path;
126
127 if (get_path) {
128 if (pglob->path) {
129 efree(pglob->path);
130 }
131 if (path != gpath) {
132 path--;
133 }
134 pglob->path_len = path - gpath;
135 pglob->path = estrndup(gpath, pglob->path_len);
136 }
137 }
138 /* }}} */
139
php_glob_stream_read(php_stream * stream,char * buf,size_t count TSRMLS_DC)140 static size_t php_glob_stream_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) /* {{{ */
141 {
142 glob_s_t *pglob = (glob_s_t *)stream->abstract;
143 php_stream_dirent *ent = (php_stream_dirent*)buf;
144 char *path;
145
146 /* avoid problems if someone mis-uses the stream */
147 if (count == sizeof(php_stream_dirent) && pglob) {
148 if (pglob->index < (size_t)pglob->glob.gl_pathc) {
149 php_glob_stream_path_split(pglob, pglob->glob.gl_pathv[pglob->index++], pglob->flags & GLOB_APPEND, &path TSRMLS_CC);
150 PHP_STRLCPY(ent->d_name, path, sizeof(ent->d_name), strlen(path));
151 return sizeof(php_stream_dirent);
152 }
153 pglob->index = pglob->glob.gl_pathc;
154 if (pglob->path) {
155 efree(pglob->path);
156 pglob->path = NULL;
157 }
158 }
159
160 return 0;
161 }
162 /* }}} */
163
php_glob_stream_close(php_stream * stream,int close_handle TSRMLS_DC)164 static int php_glob_stream_close(php_stream *stream, int close_handle TSRMLS_DC) /* {{{ */
165 {
166 glob_s_t *pglob = (glob_s_t *)stream->abstract;
167
168 if (pglob) {
169 pglob->index = 0;
170 globfree(&pglob->glob);
171 if (pglob->path) {
172 efree(pglob->path);
173 }
174 if (pglob->pattern) {
175 efree(pglob->pattern);
176 }
177 }
178 efree(stream->abstract);
179 return 0;
180 }
181 /* {{{ */
182
php_glob_stream_rewind(php_stream * stream,off_t offset,int whence,off_t * newoffs TSRMLS_DC)183 static int php_glob_stream_rewind(php_stream *stream, off_t offset, int whence, off_t *newoffs TSRMLS_DC) /* {{{ */
184 {
185 glob_s_t *pglob = (glob_s_t *)stream->abstract;
186
187 if (pglob) {
188 pglob->index = 0;
189 if (pglob->path) {
190 efree(pglob->path);
191 pglob->path = NULL;
192 }
193 }
194 return 0;
195 }
196 /* }}} */
197
198 php_stream_ops php_glob_stream_ops = {
199 NULL, php_glob_stream_read,
200 php_glob_stream_close, NULL,
201 "glob",
202 php_glob_stream_rewind,
203 NULL, /* cast */
204 NULL, /* stat */
205 NULL /* set_option */
206 };
207
208 /* {{{ php_glob_stream_opener */
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)209 static php_stream *php_glob_stream_opener(php_stream_wrapper *wrapper, char *path, char *mode,
210 int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
211 {
212 glob_s_t *pglob;
213 int ret;
214 char *tmp, *pos;
215
216 if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(path TSRMLS_CC)) {
217 return NULL;
218 }
219
220 if (!strncmp(path, "glob://", sizeof("glob://")-1)) {
221 path += sizeof("glob://")-1;
222 if (opened_path) {
223 *opened_path = estrdup(path);
224 }
225 }
226
227 pglob = ecalloc(sizeof(*pglob), 1);
228
229 if (0 != (ret = glob(path, pglob->flags & GLOB_FLAGMASK, NULL, &pglob->glob))) {
230 #ifdef GLOB_NOMATCH
231 if (GLOB_NOMATCH != ret)
232 #endif
233 {
234 efree(pglob);
235 return NULL;
236 }
237 }
238
239 pos = path;
240 if ((tmp = strrchr(pos, '/')) != NULL) {
241 pos = tmp+1;
242 }
243 #if defined(PHP_WIN32) || defined(NETWARE)
244 if ((tmp = strrchr(pos, '\\')) != NULL) {
245 pos = tmp+1;
246 }
247 #endif
248
249 pglob->pattern_len = strlen(pos);
250 pglob->pattern = estrndup(pos, pglob->pattern_len);
251
252 pglob->flags |= GLOB_APPEND;
253
254 if (pglob->glob.gl_pathc) {
255 php_glob_stream_path_split(pglob, pglob->glob.gl_pathv[0], 1, &tmp TSRMLS_CC);
256 } else {
257 php_glob_stream_path_split(pglob, path, 1, &tmp TSRMLS_CC);
258 }
259
260 return php_stream_alloc(&php_glob_stream_ops, pglob, 0, mode);
261 }
262 /* }}} */
263
264 static php_stream_wrapper_ops php_glob_stream_wrapper_ops = {
265 NULL,
266 NULL,
267 NULL,
268 NULL,
269 php_glob_stream_opener,
270 "glob",
271 NULL,
272 NULL,
273 NULL,
274 NULL
275 };
276
277 php_stream_wrapper php_glob_stream_wrapper = {
278 &php_glob_stream_wrapper_ops,
279 NULL,
280 0
281 };
282 #endif /* HAVE_GLOB */
283
284 /*
285 * Local variables:
286 * tab-width: 4
287 * c-basic-offset: 4
288 * End:
289 * vim600: noet sw=4 ts=4 fdm=marker
290 * vim<600: noet sw=4 ts=4
291 */
292