--- embedaddon/php/ext/spl/spl_directory.c 2012/02/21 23:48:01 1.1.1.1 +++ embedaddon/php/ext/spl/spl_directory.c 2012/05/29 12:34:42 1.1.1.2 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: spl_directory.c,v 1.1.1.1 2012/02/21 23:48:01 misho Exp $ */ +/* $Id: spl_directory.c,v 1.1.1.2 2012/05/29 12:34:42 misho Exp $ */ #ifdef HAVE_CONFIG_H # include "config.h" @@ -120,6 +120,16 @@ static void spl_filesystem_object_free_storage(void *o spl_filesystem_file_free_line(intern TSRMLS_CC); break; } + + { + zend_object_iterator *iterator; + iterator = (zend_object_iterator*) + spl_filesystem_object_to_iterator(intern); + if (iterator->data != NULL) { + iterator->data = NULL; + iterator->funcs->dtor(iterator TSRMLS_CC); + } + } efree(object); } /* }}} */ @@ -138,7 +148,6 @@ static zend_object_value spl_filesystem_object_new_ex( { zend_object_value retval; spl_filesystem_object *intern; - zval *tmp; intern = emalloc(sizeof(spl_filesystem_object)); memset(intern, 0, sizeof(spl_filesystem_object)); @@ -148,7 +157,7 @@ static zend_object_value spl_filesystem_object_new_ex( if (obj) *obj = intern; zend_object_std_init(&intern->std, class_type TSRMLS_CC); - zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); + object_properties_init(&intern->std, class_type); retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) spl_filesystem_object_free_storage, NULL TSRMLS_CC); retval.handlers = &spl_filesystem_object_handlers; @@ -235,7 +244,7 @@ static void spl_filesystem_dir_open(spl_filesystem_obj intern->type = SPL_FS_DIR; intern->_path_len = strlen(path); - intern->u.dir.dirp = php_stream_opendir(path, ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL); + intern->u.dir.dirp = php_stream_opendir(path, REPORT_ERRORS, FG(default_context)); if (intern->_path_len > 1 && IS_SLASH_AT(path, intern->_path_len-1)) { intern->_path = estrndup(path, --intern->_path_len); @@ -261,9 +270,20 @@ static void spl_filesystem_dir_open(spl_filesystem_obj static int spl_filesystem_file_open(spl_filesystem_object *intern, int use_include_path, int silent TSRMLS_DC) /* {{{ */ { + zval tmp; + intern->type = SPL_FS_FILE; + + php_stat(intern->file_name, intern->file_name_len, FS_IS_DIR, &tmp TSRMLS_CC); + if (Z_LVAL(tmp)) { + intern->u.file.open_mode = NULL; + intern->file_name = NULL; + zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "Cannot use SplFileObject with directories"); + return FAILURE; + } + intern->u.file.context = php_stream_context_from_zval(intern->u.file.zcontext, 0); - intern->u.file.stream = php_stream_open_wrapper_ex(intern->file_name, intern->u.file.open_mode, (use_include_path ? USE_PATH : 0) | ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, intern->u.file.context); + intern->u.file.stream = php_stream_open_wrapper_ex(intern->file_name, intern->u.file.open_mode, (use_include_path ? USE_PATH : 0) | REPORT_ERRORS, NULL, intern->u.file.context); if (!intern->file_name_len || !intern->u.file.stream) { if (!EG(exception)) { @@ -366,6 +386,10 @@ static zend_object_value spl_filesystem_object_clone(z void spl_filesystem_info_set_filename(spl_filesystem_object *intern, char *path, int len, int use_copy TSRMLS_DC) /* {{{ */ { char *p1, *p2; + + if (intern->file_name) { + efree(intern->file_name); + } intern->file_name = use_copy ? estrndup(path, len) : path; intern->file_name_len = len; @@ -386,7 +410,10 @@ void spl_filesystem_info_set_filename(spl_filesystem_o } else { intern->_path_len = 0; } - + + if (intern->_path) { + efree(intern->_path); + } intern->_path = estrndup(path, intern->_path_len); } /* }}} */ @@ -568,6 +595,10 @@ static HashTable* spl_filesystem_object_get_debug_info *is_temp = 1; + if (!intern->std.properties) { + rebuild_object_properties(&intern->std); + } + ALLOC_HASHTABLE(rv); ZEND_INIT_SYMTABLE_EX(rv, zend_hash_num_elements(intern->std.properties) + 3, 0); @@ -629,16 +660,17 @@ static HashTable* spl_filesystem_object_get_debug_info } /* }}} */ -zend_function *spl_filesystem_object_get_method_check(zval **object_ptr, char *method, int method_len TSRMLS_DC) /* {{{ */ +zend_function *spl_filesystem_object_get_method_check(zval **object_ptr, char *method, int method_len, const struct _zend_literal *key TSRMLS_DC) /* {{{ */ { spl_filesystem_object *fsobj = zend_object_store_get_object(*object_ptr TSRMLS_CC); if (fsobj->u.dir.entry.d_name[0] == '\0' && fsobj->orig_path == NULL) { method = "_bad_state_ex"; method_len = sizeof("_bad_state_ex") - 1; + key = NULL; } - return zend_get_std_object_handlers()->get_method(object_ptr, method, method_len TSRMLS_CC); + return zend_get_std_object_handlers()->get_method(object_ptr, method, method_len, key TSRMLS_CC); } /* }}} */ @@ -1220,11 +1252,7 @@ SPL_METHOD(SplFileInfo, getLinkTarget) RETURN_FALSE; } else if (!IS_ABSOLUTE_PATH(intern->file_name, intern->file_name_len)) { char expanded_path[MAXPATHLEN]; - - /* TODO: Fix expand_filepath to do not resolve links but only expand the path - avoiding double two resolution attempts - (Pierre) */ - if (!expand_filepath(intern->file_name, expanded_path TSRMLS_CC)) { + if (!expand_filepath_with_mode(intern->file_name, expanded_path, NULL, 0, CWD_EXPAND TSRMLS_CC)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such file or directory"); RETURN_FALSE; } @@ -1620,10 +1648,15 @@ zend_object_iterator *spl_filesystem_dir_get_iterator( dir_object = (spl_filesystem_object*)zend_object_store_get_object(object TSRMLS_CC); iterator = spl_filesystem_object_to_iterator(dir_object); - Z_SET_REFCOUNT_P(object, Z_REFCOUNT_P(object) + 2); - iterator->intern.data = (void*)object; - iterator->intern.funcs = &spl_filesystem_dir_it_funcs; - iterator->current = object; + /* initialize iterator if it wasn't gotten before */ + if (iterator->intern.data == NULL) { + iterator->intern.data = object; + iterator->intern.funcs = &spl_filesystem_dir_it_funcs; + /* ->current must be initialized; rewind doesn't set it and valid + * doesn't check whether it's set */ + iterator->current = object; + } + zval_add_ref(&object); return (zend_object_iterator*)iterator; } @@ -1633,13 +1666,16 @@ zend_object_iterator *spl_filesystem_dir_get_iterator( static void spl_filesystem_dir_it_dtor(zend_object_iterator *iter TSRMLS_DC) { spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter; - zval *zfree = (zval*)iterator->intern.data; - iterator->intern.data = NULL; /* mark as unused */ - zval_ptr_dtor(&iterator->current); - if (zfree) { - zval_ptr_dtor(&zfree); + if (iterator->intern.data) { + zval *object = iterator->intern.data; + zval_ptr_dtor(&object); } + /* Otherwise we were called from the owning object free storage handler as + * it sets + * iterator->intern.data to NULL. + * We don't even need to destroy iterator->current as we didn't add a + * reference to it in move_forward or get_iterator */ } /* }}} */ @@ -1702,15 +1738,15 @@ static void spl_filesystem_dir_it_rewind(zend_object_i static void spl_filesystem_tree_it_dtor(zend_object_iterator *iter TSRMLS_DC) { spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter; - zval *zfree = (zval*)iterator->intern.data; - if (iterator->current) { - zval_ptr_dtor(&iterator->current); + if (iterator->intern.data) { + zval *object = iterator->intern.data; + zval_ptr_dtor(&object); + } else { + if (iterator->current) { + zval_ptr_dtor(&iterator->current); + } } - iterator->intern.data = NULL; /* mark as unused */ - /* free twice as we add ref twice */ - zval_ptr_dtor(&zfree); - zval_ptr_dtor(&zfree); } /* }}} */ @@ -1821,10 +1857,12 @@ zend_object_iterator *spl_filesystem_tree_get_iterator dir_object = (spl_filesystem_object*)zend_object_store_get_object(object TSRMLS_CC); iterator = spl_filesystem_object_to_iterator(dir_object); - Z_SET_REFCOUNT_P(object, Z_REFCOUNT_P(object) + 2); - iterator->intern.data = (void*)object; - iterator->intern.funcs = &spl_filesystem_tree_it_funcs; - iterator->current = NULL; + /* initialize iterator if wasn't gotten before */ + if (iterator->intern.data == NULL) { + iterator->intern.data = object; + iterator->intern.funcs = &spl_filesystem_tree_it_funcs; + } + zval_add_ref(&object); return (zend_object_iterator*)iterator; } @@ -2005,7 +2043,6 @@ static int spl_filesystem_file_read(spl_filesystem_obj { char *buf; size_t line_len = 0; - int len; long line_add = (intern->u.file.current_line || intern->u.file.current_zval) ? 1 : 0; spl_filesystem_file_free_line(intern TSRMLS_CC); @@ -2038,11 +2075,6 @@ static int spl_filesystem_file_read(spl_filesystem_obj buf[line_len] = '\0'; } - if (PG(magic_quotes_runtime)) { - buf = php_addslashes(buf, line_len, &len, 1 TSRMLS_CC); - line_len = len; - } - intern->u.file.current_line = buf; intern->u.file.current_line_len = line_len; } @@ -2250,7 +2282,7 @@ SPL_METHOD(SplFileObject, __construct) intern->u.file.open_mode = NULL; intern->u.file.open_mode_len = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|sbr", + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|sbr", &intern->file_name, &intern->file_name_len, &intern->u.file.open_mode, &intern->u.file.open_mode_len, &use_include_path, &intern->u.file.zcontext) == FAILURE) { @@ -2264,7 +2296,7 @@ SPL_METHOD(SplFileObject, __construct) intern->u.file.open_mode = "r"; intern->u.file.open_mode_len = 1; } - + if (spl_filesystem_file_open(intern, use_include_path, 0 TSRMLS_CC) == SUCCESS) { tmp_path_len = strlen(intern->u.file.stream->orig_path); @@ -2452,7 +2484,9 @@ SPL_METHOD(SplFileObject, setFlags) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &intern->flags); + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &intern->flags) == FAILURE) { + return; + } } /* }}} */ /* {{{ proto int SplFileObject::getFlags() @@ -2572,6 +2606,43 @@ SPL_METHOD(SplFileObject, fgetcsv) } /* }}} */ +/* {{{ proto int SplFileObject::fputcsv(array fields, [string delimiter [, string enclosure]]) + Output a field array as a CSV line */ +SPL_METHOD(SplFileObject, fputcsv) +{ + spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + char delimiter = intern->u.file.delimiter, enclosure = intern->u.file.enclosure, escape = intern->u.file.escape; + char *delim = NULL, *enclo = NULL; + int d_len = 0, e_len = 0, ret; + zval *fields = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|ss", &fields, &delim, &d_len, &enclo, &e_len) == SUCCESS) { + switch(ZEND_NUM_ARGS()) + { + case 3: + if (e_len != 1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "enclosure must be a character"); + RETURN_FALSE; + } + enclosure = enclo[0]; + /* no break */ + case 2: + if (d_len != 1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "delimiter must be a character"); + RETURN_FALSE; + } + delimiter = delim[0]; + /* no break */ + case 1: + case 0: + break; + } + ret = php_fputcsv(intern->u.file.stream, fields, delimiter, enclosure, escape TSRMLS_CC); + RETURN_LONG(ret); + } +} +/* }}} */ + /* {{{ proto void SplFileObject::setCsvControl([string delimiter = ',' [, string enclosure = '"' [, string escape = '\\']]]) Set the delimiter and enclosure character used in fgetcsv */ SPL_METHOD(SplFileObject, setCsvControl) @@ -2753,7 +2824,6 @@ SPL_METHOD(SplFileObject, fwrite) spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); char *str; int str_len; - int ret; long length = 0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &str, &str_len, &length) == FAILURE) { @@ -2767,14 +2837,6 @@ SPL_METHOD(SplFileObject, fwrite) RETURN_LONG(0); } - if (PG(magic_quotes_runtime)) { - str = estrndup(str, str_len); - php_stripslashes(str, &str_len TSRMLS_CC); - ret = php_stream_write(intern->u.file.stream, str, str_len); - efree(str); - RETURN_LONG(ret); - } - RETURN_LONG(php_stream_write(intern->u.file.stream, str, str_len)); } /* }}} */ @@ -2845,8 +2907,15 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fgetcsv, 0, 0, 0) ZEND_ARG_INFO(0, delimiter) ZEND_ARG_INFO(0, enclosure) + ZEND_ARG_INFO(0, escape) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fputcsv, 0, 0, 1) + ZEND_ARG_INFO(0, fields) + ZEND_ARG_INFO(0, delimiter) + ZEND_ARG_INFO(0, enclosure) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_flock, 0, 0, 1) ZEND_ARG_INFO(0, operation) ZEND_ARG_INFO(1, wouldblock) @@ -2861,7 +2930,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fgetss, 0, ZEND_ARG_INFO(0, allowable_tags) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fscanf, 1, 0, 1) +ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fscanf, 1, 0, 1) ZEND_ARG_INFO(0, format) ZEND_END_ARG_INFO() @@ -2885,6 +2954,7 @@ static const zend_function_entry spl_SplFileObject_fun SPL_ME(SplFileObject, valid, arginfo_splfileinfo_void, ZEND_ACC_PUBLIC) SPL_ME(SplFileObject, fgets, arginfo_splfileinfo_void, ZEND_ACC_PUBLIC) SPL_ME(SplFileObject, fgetcsv, arginfo_file_object_fgetcsv, ZEND_ACC_PUBLIC) + SPL_ME(SplFileObject, fputcsv, arginfo_file_object_fputcsv, ZEND_ACC_PUBLIC) SPL_ME(SplFileObject, setCsvControl, arginfo_file_object_fgetcsv, ZEND_ACC_PUBLIC) SPL_ME(SplFileObject, getCsvControl, arginfo_splfileinfo_void, ZEND_ACC_PUBLIC) SPL_ME(SplFileObject, flock, arginfo_file_object_flock, ZEND_ACC_PUBLIC) @@ -2953,6 +3023,7 @@ PHP_MINIT_FUNCTION(spl_directory) REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "FOLLOW_SYMLINKS", SPL_FILE_DIR_FOLLOW_SYMLINKS); REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "KEY_AS_FILENAME", SPL_FILE_DIR_KEY_AS_FILENAME); REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "NEW_CURRENT_AND_KEY", SPL_FILE_DIR_KEY_AS_FILENAME|SPL_FILE_DIR_CURRENT_AS_FILEINFO); + REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "OTHER_MODE_MASK", SPL_FILE_DIR_OTHERS_MASK); REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "SKIP_DOTS", SPL_FILE_DIR_SKIPDOTS); REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "UNIX_PATHS", SPL_FILE_DIR_UNIXPATHS);