@@ -59,39 +59,6 @@ static zend_function *dir_class_get_constructor(zend_object *object)
5959 return NULL ;
6060}
6161
62- #define FETCH_DIRP () \
63- myself = getThis(); \
64- if (!myself) { \
65- ZEND_PARSE_PARAMETERS_START(0, 1) \
66- Z_PARAM_OPTIONAL \
67- Z_PARAM_RESOURCE_OR_NULL(id) \
68- ZEND_PARSE_PARAMETERS_END(); \
69- if (id) { \
70- if ((dirp = (php_stream *)zend_fetch_resource(Z_RES_P(id), "Directory", php_file_le_stream())) == NULL) { \
71- RETURN_THROWS(); \
72- } \
73- } else { \
74- if (!DIRG(default_dir)) { \
75- zend_type_error("No resource supplied"); \
76- RETURN_THROWS(); \
77- } \
78- if ((dirp = (php_stream *)zend_fetch_resource(DIRG(default_dir), "Directory", php_file_le_stream())) == NULL) { \
79- RETURN_THROWS(); \
80- } \
81- } \
82- } else { \
83- ZEND_PARSE_PARAMETERS_NONE(); \
84- zval *handle_zv = Z_DIRECTORY_HANDLE_P(myself); \
85- if (Z_TYPE_P(handle_zv) != IS_RESOURCE) { \
86- zend_throw_error(NULL, "Unable to find my handle property"); \
87- RETURN_THROWS(); \
88- } \
89- if ((dirp = (php_stream *)zend_fetch_resource_ex(handle_zv, "Directory", php_file_le_stream())) == NULL) { \
90- RETURN_THROWS(); \
91- } \
92- }
93-
94-
9562static void php_set_default_dir (zend_resource * res )
9663{
9764 if (DIRG (default_dir )) {
@@ -189,29 +156,166 @@ PHP_FUNCTION(dir)
189156}
190157/* }}} */
191158
159+
160+ static php_stream * php_dir_get_directory_stream_from_user_arg (zval * arg )
161+ {
162+ zend_resource * res ;
163+ if (arg == NULL ) {
164+ if (UNEXPECTED (DIRG (default_dir ) == NULL )) {
165+ zend_type_error ("No resource supplied" );
166+ return NULL ;
167+ }
168+ res = DIRG (default_dir );
169+ } else {
170+ ZEND_ASSERT (Z_TYPE_P (arg ) == IS_RESOURCE );
171+ res = Z_RES_P (arg );
172+ }
173+
174+ if (UNEXPECTED (res -> type != php_file_le_stream ())) {
175+ zend_argument_type_error (1 , "must be a valid Directory resource" );
176+ return NULL ;
177+ }
178+ php_stream * dir_stream = (php_stream * ) res -> ptr ;
179+ if (UNEXPECTED ((dir_stream -> flags & PHP_STREAM_FLAG_IS_DIR )) == 0 ) {
180+ zend_argument_type_error (1 , "must be a valid Directory resource" );
181+ return NULL ;
182+ }
183+ return dir_stream ;
184+ }
185+
186+ static php_stream * php_dir_get_directory_stream_from_this (zval * this_z )
187+ {
188+ zval * handle_zv = Z_DIRECTORY_HANDLE_P (this_z );
189+ if (UNEXPECTED (Z_TYPE_P (handle_zv ) != IS_RESOURCE )) {
190+ zend_throw_error (NULL , "Internal directory stream has been altered" );
191+ return NULL ;
192+ }
193+ zend_resource * res = Z_RES_P (handle_zv );
194+ /* Assume the close() method was called
195+ * (instead of the hacky case where a different resource would have been set via the ArrayObject "hack") */
196+ if (UNEXPECTED (res -> type != php_file_le_stream ())) {
197+ /* TypeError is used for BC, TODO: Use base Error in PHP 9 */
198+ zend_type_error ("Directory::%s(): cannot use Directory resource after it has been closed" , get_active_function_name ());
199+ return NULL ;
200+ }
201+ php_stream * dir_stream = (php_stream * ) res -> ptr ;
202+ if (UNEXPECTED ((dir_stream -> flags & PHP_STREAM_FLAG_IS_DIR )) == 0 ) {
203+ zend_throw_error (NULL , "Internal directory stream has been altered" );
204+ return NULL ;
205+ }
206+ return dir_stream ;
207+ }
208+
192209/* {{{ Close directory connection identified by the dir_handle */
193210PHP_FUNCTION (closedir )
194211{
195- zval * id = NULL , * myself ;
196- php_stream * dirp ;
197- zend_resource * res ;
212+ zval * id = NULL ;
198213
199- FETCH_DIRP ();
214+ ZEND_PARSE_PARAMETERS_START (0 , 1 )
215+ Z_PARAM_OPTIONAL
216+ Z_PARAM_RESOURCE_OR_NULL (id )
217+ ZEND_PARSE_PARAMETERS_END ();
200218
201- if (!( dirp -> flags & PHP_STREAM_FLAG_IS_DIR )) {
202- zend_argument_type_error ( 1 , "must be a valid Directory resource" );
219+ php_stream * dirp = php_dir_get_directory_stream_from_user_arg ( id );
220+ if ( UNEXPECTED ( dirp == NULL )) {
203221 RETURN_THROWS ();
204222 }
223+ zend_resource * res = dirp -> res ;
224+ zend_list_close (res );
205225
206- res = dirp -> res ;
207- zend_list_close (dirp -> res );
226+ if (res == DIRG (default_dir )) {
227+ php_set_default_dir (NULL );
228+ }
229+ }
230+ /* }}} */
231+
232+ PHP_METHOD (Directory , close )
233+ {
234+ ZEND_PARSE_PARAMETERS_NONE ();
235+
236+ php_stream * dirp = php_dir_get_directory_stream_from_this (ZEND_THIS );
237+ if (UNEXPECTED (dirp == NULL )) {
238+ RETURN_THROWS ();
239+ }
240+
241+ zend_resource * res = dirp -> res ;
242+ zend_list_close (res );
208243
209244 if (res == DIRG (default_dir )) {
210245 php_set_default_dir (NULL );
211246 }
212247}
248+
249+ /* {{{ Rewind dir_handle back to the start */
250+ PHP_FUNCTION (rewinddir )
251+ {
252+ zval * id = NULL ;
253+
254+ ZEND_PARSE_PARAMETERS_START (0 , 1 )
255+ Z_PARAM_OPTIONAL
256+ Z_PARAM_RESOURCE_OR_NULL (id )
257+ ZEND_PARSE_PARAMETERS_END ();
258+
259+ php_stream * dirp = php_dir_get_directory_stream_from_user_arg (id );
260+ if (UNEXPECTED (dirp == NULL )) {
261+ RETURN_THROWS ();
262+ }
263+
264+ php_stream_rewinddir (dirp );
265+ }
213266/* }}} */
214267
268+ PHP_METHOD (Directory , rewind )
269+ {
270+ ZEND_PARSE_PARAMETERS_NONE ();
271+
272+ php_stream * dirp = php_dir_get_directory_stream_from_this (ZEND_THIS );
273+ if (UNEXPECTED (dirp == NULL )) {
274+ RETURN_THROWS ();
275+ }
276+
277+ php_stream_rewinddir (dirp );
278+ }
279+
280+ /* {{{ Read directory entry from dir_handle */
281+ PHP_FUNCTION (readdir )
282+ {
283+ zval * id = NULL ;
284+
285+ ZEND_PARSE_PARAMETERS_START (0 , 1 )
286+ Z_PARAM_OPTIONAL
287+ Z_PARAM_RESOURCE_OR_NULL (id )
288+ ZEND_PARSE_PARAMETERS_END ();
289+
290+ php_stream * dirp = php_dir_get_directory_stream_from_user_arg (id );
291+ if (UNEXPECTED (dirp == NULL )) {
292+ RETURN_THROWS ();
293+ }
294+
295+ php_stream_dirent entry ;
296+ if (php_stream_readdir (dirp , & entry )) {
297+ RETURN_STRING (entry .d_name );
298+ }
299+ RETURN_FALSE ;
300+ }
301+ /* }}} */
302+
303+ PHP_METHOD (Directory , read )
304+ {
305+ ZEND_PARSE_PARAMETERS_NONE ();
306+
307+ php_stream * dirp = php_dir_get_directory_stream_from_this (ZEND_THIS );
308+ if (UNEXPECTED (dirp == NULL )) {
309+ RETURN_THROWS ();
310+ }
311+
312+ php_stream_dirent entry ;
313+ if (php_stream_readdir (dirp , & entry )) {
314+ RETURN_STRING (entry .d_name );
315+ }
316+ RETURN_FALSE ;
317+ }
318+
215319#if defined(HAVE_CHROOT ) && !defined(ZTS ) && defined(ENABLE_CHROOT_FUNC )
216320/* {{{ Change root directory */
217321PHP_FUNCTION (chroot )
@@ -300,44 +404,6 @@ PHP_FUNCTION(getcwd)
300404}
301405/* }}} */
302406
303- /* {{{ Rewind dir_handle back to the start */
304- PHP_FUNCTION (rewinddir )
305- {
306- zval * id = NULL , * myself ;
307- php_stream * dirp ;
308-
309- FETCH_DIRP ();
310-
311- if (!(dirp -> flags & PHP_STREAM_FLAG_IS_DIR )) {
312- zend_argument_type_error (1 , "must be a valid Directory resource" );
313- RETURN_THROWS ();
314- }
315-
316- php_stream_rewinddir (dirp );
317- }
318- /* }}} */
319-
320- /* {{{ Read directory entry from dir_handle */
321- PHP_FUNCTION (readdir )
322- {
323- zval * id = NULL , * myself ;
324- php_stream * dirp ;
325- php_stream_dirent entry ;
326-
327- FETCH_DIRP ();
328-
329- if (!(dirp -> flags & PHP_STREAM_FLAG_IS_DIR )) {
330- zend_argument_type_error (1 , "must be a valid Directory resource" );
331- RETURN_THROWS ();
332- }
333-
334- if (php_stream_readdir (dirp , & entry )) {
335- RETURN_STRINGL (entry .d_name , strlen (entry .d_name ));
336- }
337- RETURN_FALSE ;
338- }
339- /* }}} */
340-
341407#ifdef HAVE_GLOB
342408/* {{{ Find pathnames matching a pattern */
343409PHP_FUNCTION (glob )
0 commit comments