Commit message: Fix #78863: DirectoryIterator class silently truncates after a null byte

Since the constructor of DirectoryIterator and friends is supposed to
accepts paths (i.e. strings without NUL bytes), we must not accept
arbitrary strings.
CVE: CVE-2019-11045
CWE: CWE-74
Vulnerability description: In PHP versions 7.2.x below 7.2.26, 7.3.x below 7.3.13 and 7.4.0, PHP DirectoryIterator class accepts filenames with embedded \0 byte and treats them as terminating at that byte. This could lead to security vulnerabilities, e.g. in applications checking paths that the code is allowed to access.

Project: php-src
File: spl_directory.c

SPL_METHOD(RecursiveDirectoryIterator, __construct)
{
	spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIT_CTOR_FLAGS);
}

Project: php-src
File: spl_directory.c

static void spl_filesystem_tree_it_dtor(zend_object_iterator *iter)
{
	spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;

	if (!Z_ISUNDEF(iterator->intern.data)) {
		zval *object = &iterator->intern.data;
		zval_ptr_dtor(object);
	} else {
		if (!Z_ISUNDEF(iterator->current)) {
			zval_ptr_dtor(&iterator->current);
			ZVAL_UNDEF(&iterator->current);
		}
	}
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileInfo, _bad_state_ex)
{
	zend_throw_exception_ex(spl_ce_LogicException, 0,
		"The parent constructor was not called: the object is in an "
		"invalid state ");
}

Project: php-src
File: spl_directory.c

PHPAPI char* spl_filesystem_object_get_path(spl_filesystem_object *intern, size_t *len) /* {{{ */
{
#ifdef HAVE_GLOB
	if (intern->type == SPL_FS_DIR) {
		if (php_stream_is(intern->u.dir.dirp ,&php_glob_stream_ops)) {
			return php_glob_stream_get_path(intern->u.dir.dirp, 0, len);
		}
	}
#endif
	if (len) {
		*len = intern->_path_len;
	}
	return intern->_path;
} /* }}} */

Project: php-src
File: spl_directory.c

SPL_METHOD(RecursiveDirectoryIterator, getChildren)
{
	zval zpath, zflags;
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	spl_filesystem_object *subdir;
	char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH;

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	spl_filesystem_object_get_file_name(intern);

	ZVAL_LONG(&zflags, intern->flags);
	ZVAL_STRINGL(&zpath, intern->file_name, intern->file_name_len);
	spl_instantiate_arg_ex2(Z_OBJCE_P(getThis()), return_value, &zpath, &zflags);
	zval_ptr_dtor(&zpath);
	zval_ptr_dtor(&zflags);

	subdir = Z_SPLFILESYSTEM_P(return_value);
	if (subdir) {
		if (intern->u.dir.sub_path && intern->u.dir.sub_path[0]) {
			subdir->u.dir.sub_path_len = spprintf(&subdir->u.dir.sub_path, 0, "%s%c%s", intern->u.dir.sub_path, slash, intern->u.dir.entry.d_name);
		} else {
			subdir->u.dir.sub_path_len = strlen(intern->u.dir.entry.d_name);
			subdir->u.dir.sub_path = estrndup(intern->u.dir.entry.d_name, subdir->u.dir.sub_path_len);
		}
		subdir->info_class = intern->info_class;
		subdir->file_class = intern->file_class;
		subdir->oth = intern->oth;
	}
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileInfo, getLinkTarget)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	int ret;
	char buff[MAXPATHLEN];
	zend_error_handling error_handling;

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);

	if (intern->file_name == NULL) {
		spl_filesystem_object_get_file_name(intern);
	}
#if defined(PHP_WIN32) || HAVE_SYMLINK
	if (intern->file_name == NULL) {
		php_error_docref(NULL, E_WARNING, "Empty filename");
		RETURN_FALSE;
	} else if (!IS_ABSOLUTE_PATH(intern->file_name, intern->file_name_len)) {
		char expanded_path[MAXPATHLEN];
		if (!expand_filepath_with_mode(intern->file_name, expanded_path, NULL, 0, CWD_EXPAND )) {
			php_error_docref(NULL, E_WARNING, "No such file or directory");
			RETURN_FALSE;
		}
		ret = php_sys_readlink(expanded_path, buff, MAXPATHLEN - 1);
	} else {
		ret = php_sys_readlink(intern->file_name, buff,  MAXPATHLEN-1);
	}
#else
	ret = -1; /* always fail if not implemented */
#endif

	if (ret == -1) {
		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Unable to read link %s, error: %s", intern->file_name, strerror(errno));
		RETVAL_FALSE;
	} else {
		/* Append NULL to the end of the string */
		buff[ret] = '\0';

		RETVAL_STRINGL(buff, ret);
	}

	zend_restore_error_handling(&error_handling);
}

Project: php-src
File: spl_directory.c

static void spl_filesystem_tree_it_move_forward(zend_object_iterator *iter)
{
	spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;
	spl_filesystem_object   *object   = spl_filesystem_iterator_to_object(iterator);

	object->u.dir.index++;
	do {
		spl_filesystem_dir_read(object);
	} while (spl_filesystem_is_dot(object->u.dir.entry.d_name));
	if (object->file_name) {
		efree(object->file_name);
		object->file_name = NULL;
	}
	if (!Z_ISUNDEF(iterator->current)) {
		zval_ptr_dtor(&iterator->current);
		ZVAL_UNDEF(&iterator->current);
	}
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, getCsvControl)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	char delimiter[2], enclosure[2], escape[2];

	array_init(return_value);

	delimiter[0] = intern->u.file.delimiter;
	delimiter[1] = '\0';
	enclosure[0] = intern->u.file.enclosure;
	enclosure[1] = '\0';
	escape[0] = intern->u.file.escape;
	escape[1] = '\0';

	add_next_index_string(return_value, delimiter);
	add_next_index_string(return_value, enclosure);
	add_next_index_string(return_value, escape);
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileInfo, getRealPath)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	char buff[MAXPATHLEN];
	char *filename;
	zend_error_handling error_handling;

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);

	if (intern->type == SPL_FS_DIR && !intern->file_name && intern->u.dir.entry.d_name[0]) {
		spl_filesystem_object_get_file_name(intern);
	}

	if (intern->orig_path) {
		filename = intern->orig_path;
	} else {
		filename = intern->file_name;
	}


	if (filename && VCWD_REALPATH(filename, buff)) {
#ifdef ZTS
		if (VCWD_ACCESS(buff, F_OK)) {
			RETVAL_FALSE;
		} else
#endif
		RETVAL_STRING(buff);
	} else {
		RETVAL_FALSE;
	}

	zend_restore_error_handling(&error_handling);
}

Project: php-src
File: spl_directory.c

static void spl_filesystem_dir_it_move_forward(zend_object_iterator *iter)
{
	spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter);

	object->u.dir.index++;
	spl_filesystem_dir_read(object);
	if (object->file_name) {
		efree(object->file_name);
		object->file_name = NULL;
	}
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, seek)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	zend_long line_pos;

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &line_pos) == FAILURE) {
		return;
	}
	if(!intern->u.file.stream) {
		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
		return;
	}

	if (line_pos < 0) {
		zend_throw_exception_ex(spl_ce_LogicException, 0, "Can't seek file %s to negative line " ZEND_LONG_FMT, intern->file_name, line_pos);
		RETURN_FALSE;
	}

	spl_filesystem_file_rewind(getThis(), intern);

	while(intern->u.file.current_line_num < line_pos) {
		if (spl_filesystem_file_read_line(getThis(), intern, 1) == FAILURE) {
			break;
		}
	}
} /* }}} */

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileInfo, getBasename)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	char *fname, *suffix = 0;
	size_t flen;
	size_t slen = 0, path_len;

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &suffix, &slen) == FAILURE) {
		return;
	}

	spl_filesystem_object_get_path(intern, &path_len);

	if (path_len && path_len < intern->file_name_len) {
		fname = intern->file_name + path_len + 1;
		flen = intern->file_name_len - (path_len + 1);
	} else {
		fname = intern->file_name;
		flen = intern->file_name_len;
	}

	RETURN_STR(php_basename(fname, flen, suffix, slen));
}

Project: php-src
File: spl_directory.c

static int spl_filesystem_object_cast(zval *readobj, zval *writeobj, int type)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(readobj);

	if (type == IS_STRING) {
		if (Z_OBJCE_P(readobj)->__tostring) {
			return std_object_handlers.cast_object(readobj, writeobj, type);
		}

		switch (intern->type) {
		case SPL_FS_INFO:
		case SPL_FS_FILE:
			if (readobj == writeobj) {
				zval retval;
				zval *retval_ptr = &retval;

				ZVAL_STRINGL(retval_ptr, intern->file_name, intern->file_name_len);
				zval_ptr_dtor(readobj);
				ZVAL_NEW_STR(writeobj, Z_STR_P(retval_ptr));
			} else {
				ZVAL_STRINGL(writeobj, intern->file_name, intern->file_name_len);
			}
			return SUCCESS;
		case SPL_FS_DIR:
			if (readobj == writeobj) {
				zval retval;
				zval *retval_ptr = &retval;

				ZVAL_STRING(retval_ptr, intern->u.dir.entry.d_name);
				zval_ptr_dtor(readobj);
				ZVAL_NEW_STR(writeobj, Z_STR_P(retval_ptr));
			} else {
				ZVAL_STRING(writeobj, intern->u.dir.entry.d_name);
			}
			return SUCCESS;
		}
	} else if (type == _IS_BOOL) {
		ZVAL_TRUE(writeobj);
		return SUCCESS;
	}
	if (readobj == writeobj) {
		zval_ptr_dtor(readobj);
	}
	ZVAL_NULL(writeobj);
	return FAILURE;
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileInfo, setInfoClass)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	zend_class_entry *ce = spl_ce_SplFileInfo;
	zend_error_handling error_handling;

	zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling );

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C", &ce) == SUCCESS) {
		intern->info_class = ce;
	}

	zend_restore_error_handling(&error_handling);
}

Project: php-src
File: spl_directory.c

static zval *spl_filesystem_dir_it_current_data(zend_object_iterator *iter)
{
	spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;

	return &iterator->current;
}

Project: php-src
File: spl_directory.c

static int spl_filesystem_is_invalid_or_dot(const char * d_name) /* {{{ */
{
	return d_name[0] == '\0' || spl_filesystem_is_dot(d_name);
}

Project: php-src
File: spl_directory.c

static inline void spl_filesystem_object_get_file_name(spl_filesystem_object *intern) /* {{{ */
{
	char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH;

	switch (intern->type) {
		case SPL_FS_INFO:
		case SPL_FS_FILE:
			if (!intern->file_name) {
				php_error_docref(NULL, E_ERROR, "Object not initialized");
			}
			break;
		case SPL_FS_DIR:
			{
				size_t path_len = 0;
				char *path = spl_filesystem_object_get_path(intern, &path_len);
				if (intern->file_name) {
					efree(intern->file_name);
				}
				/* if there is parent path, ammend it, otherwise just use the given path as is */
				if (path_len == 0) {
					intern->file_name_len = spprintf(
						&intern->file_name, 0, "%s", intern->u.dir.entry.d_name);
				} else {
					intern->file_name_len = spprintf(
						&intern->file_name, 0, "%s%c%s", path, slash, intern->u.dir.entry.d_name);
				}
			}
			break;
	}
} /* }}} */

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileInfo, openFile)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());

	spl_filesystem_object_create_type(ZEND_NUM_ARGS(), intern, SPL_FS_FILE, NULL, return_value);
}

Project: php-src
File: spl_directory.c

static int spl_filesystem_file_read_line_ex(zval * this_ptr, spl_filesystem_object *intern, int silent) /* {{{ */
{
	zval retval;

	/* 1) use fgetcsv? 2) overloaded call the function, 3) do it directly */
	if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV) || intern->u.file.func_getCurr->common.scope != spl_ce_SplFileObject) {
		if (php_stream_eof(intern->u.file.stream)) {
			if (!silent) {
				zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot read from file %s", intern->file_name);
			}
			return FAILURE;
		}
		if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV)) {
			return spl_filesystem_file_read_csv(intern, intern->u.file.delimiter, intern->u.file.enclosure, intern->u.file.escape, NULL);
		} else {
			zend_execute_data *execute_data = EG(current_execute_data);
			zend_call_method_with_0_params(this_ptr, Z_OBJCE(EX(This)), &intern->u.file.func_getCurr, "getCurrentLine", &retval);
		}
		if (!Z_ISUNDEF(retval)) {
			if (intern->u.file.current_line || !Z_ISUNDEF(intern->u.file.current_zval)) {
				intern->u.file.current_line_num++;
			}
			spl_filesystem_file_free_line(intern);
			if (Z_TYPE(retval) == IS_STRING) {
				intern->u.file.current_line = estrndup(Z_STRVAL(retval), Z_STRLEN(retval));
				intern->u.file.current_line_len = Z_STRLEN(retval);
			} else {
				zval *value = &retval;

				ZVAL_DEREF(value);
				ZVAL_COPY(&intern->u.file.current_zval, value);
			}
			zval_ptr_dtor(&retval);
			return SUCCESS;
		} else {
			return FAILURE;
		}
	} else {
		return spl_filesystem_file_read(intern, silent);
	}
} /* }}} */

Project: php-src
File: spl_directory.c

static void spl_filesystem_dir_it_dtor(zend_object_iterator *iter)
{
	spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;

	if (!Z_ISUNDEF(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 IS_UNDEF.
	 * We don't even need to destroy iterator->current as we didn't add a
	 * reference to it in move_forward or get_iterator */
}

Project: php-src
File: spl_directory.c

static void spl_filesystem_dir_it_current_key(zend_object_iterator *iter, zval *key)
{
	spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter);

	ZVAL_LONG(key, object->u.dir.index);
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, fflush)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());

	if(!intern->u.file.stream) {
		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
		return;
	}

	RETURN_BOOL(!php_stream_flush(intern->u.file.stream));
} /* }}} */

Project: php-src
File: spl_directory.c

static int spl_filesystem_file_is_empty_line(spl_filesystem_object *intern) /* {{{ */
{
	if (intern->u.file.current_line) {
		return intern->u.file.current_line_len == 0;
	} else if (!Z_ISUNDEF(intern->u.file.current_zval)) {
		switch(Z_TYPE(intern->u.file.current_zval)) {
			case IS_STRING:
				return Z_STRLEN(intern->u.file.current_zval) == 0;
			case IS_ARRAY:
				if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV)
						&& zend_hash_num_elements(Z_ARRVAL(intern->u.file.current_zval)) == 1) {
					uint32_t idx = 0;
					zval *first;

					while (Z_ISUNDEF(Z_ARRVAL(intern->u.file.current_zval)->arData[idx].val)) {
						idx++;
					}
					first = &Z_ARRVAL(intern->u.file.current_zval)->arData[idx].val;
					return Z_TYPE_P(first) == IS_STRING && Z_STRLEN_P(first) == 0;
				}
				return zend_hash_num_elements(Z_ARRVAL(intern->u.file.current_zval)) == 0;
			case IS_NULL:
				return 1;
			default:
				return 0;
		}
	} else {
		return 1;
	}
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, current)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	if(!intern->u.file.stream) {
		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
		return;
	}

	if (!intern->u.file.current_line && Z_ISUNDEF(intern->u.file.current_zval)) {
		spl_filesystem_file_read_line(getThis(), intern, 1);
	}
	if (intern->u.file.current_line && (!SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV) || Z_ISUNDEF(intern->u.file.current_zval))) {
		RETURN_STRINGL(intern->u.file.current_line, intern->u.file.current_line_len);
	} else if (!Z_ISUNDEF(intern->u.file.current_zval)) {
		zval *value = &intern->u.file.current_zval;

		ZVAL_DEREF(value);
		ZVAL_COPY(return_value, value);
		return;
	}
	RETURN_FALSE;
} /* }}} */

Project: php-src
File: spl_directory.c

void spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAMETERS, zend_long ctor_flags) /* {{{ */
{
	spl_filesystem_object *intern;
	char *path;
	int parsed;
	size_t len;
	zend_long flags;
	zend_error_handling error_handling;

	zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling);

	if (SPL_HAS_FLAG(ctor_flags, DIT_CTOR_FLAGS)) {
		flags = SPL_FILE_DIR_KEY_AS_PATHNAME|SPL_FILE_DIR_CURRENT_AS_FILEINFO;
		parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "p|l", &path, &len, &flags);
	} else {
		flags = SPL_FILE_DIR_KEY_AS_PATHNAME|SPL_FILE_DIR_CURRENT_AS_SELF;
		parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "p", &path, &len);
	}
	if (SPL_HAS_FLAG(ctor_flags, SPL_FILE_DIR_SKIPDOTS)) {
		flags |= SPL_FILE_DIR_SKIPDOTS;
	}
	if (SPL_HAS_FLAG(ctor_flags, SPL_FILE_DIR_UNIXPATHS)) {
		flags |= SPL_FILE_DIR_UNIXPATHS;
	}
	if (parsed == FAILURE) {
		zend_restore_error_handling(&error_handling);
		return;
	}
	if (!len) {
		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Directory name must not be empty.");
		zend_restore_error_handling(&error_handling);
		return;
	}

	intern = Z_SPLFILESYSTEM_P(getThis());
	if (intern->_path) {
		/* object is alreay initialized */
		zend_restore_error_handling(&error_handling);
		php_error_docref(NULL, E_WARNING, "Directory object is already initialized");
		return;
	}
	intern->flags = flags;
#ifdef HAVE_GLOB
	if (SPL_HAS_FLAG(ctor_flags, DIT_CTOR_GLOB) && strstr(path, "glob://") != path) {
		spprintf(&path, 0, "glob://%s", path);
		spl_filesystem_dir_open(intern, path);
		efree(path);
	} else
#endif
	{
		spl_filesystem_dir_open(intern, path);

	}

	intern->u.dir.is_recursive = instanceof_function(intern->std.ce, spl_ce_RecursiveDirectoryIterator) ? 1 : 0;

	zend_restore_error_handling(&error_handling);
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, setFlags)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &intern->flags) == FAILURE) {
		return;
	}
} /* }}} */

Project: php-src
File: spl_directory.c

SPL_METHOD(SplTempFileObject, __construct)
{
	zend_long max_memory = PHP_STREAM_MAX_MEM;
	char tmp_fname[48];
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	zend_error_handling error_handling;

	if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "|l", &max_memory) == FAILURE) {
		return;
	}

	if (max_memory < 0) {
		intern->file_name = "php://memory";
		intern->file_name_len = 12;
	} else if (ZEND_NUM_ARGS()) {
		intern->file_name_len = slprintf(tmp_fname, sizeof(tmp_fname), "php://temp/maxmemory:" ZEND_LONG_FMT, max_memory);
		intern->file_name = tmp_fname;
	} else {
		intern->file_name = "php://temp";
		intern->file_name_len = 10;
	}
	intern->u.file.open_mode = "wb";
	intern->u.file.open_mode_len = 1;

	zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);
	if (spl_filesystem_file_open(intern, 0, 0) == SUCCESS) {
		intern->_path_len = 0;
		intern->_path = estrndup("", 0);
	}
	zend_restore_error_handling(&error_handling);
} /* }}} */

Project: php-src
File: spl_directory.c

SPL_METHOD(FilesystemIterator, getFlags)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	RETURN_LONG(intern->flags & (SPL_FILE_DIR_KEY_MODE_MASK | SPL_FILE_DIR_CURRENT_MODE_MASK | SPL_FILE_DIR_OTHERS_MASK));
} /* }}} */

Project: php-src
File: spl_directory.c

SPL_METHOD(RecursiveDirectoryIterator, getSubPath)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	if (intern->u.dir.sub_path) {
		RETURN_STRINGL(intern->u.dir.sub_path, intern->u.dir.sub_path_len);
	} else {
		RETURN_EMPTY_STRING();
	}
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, fputcsv)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	char delimiter = intern->u.file.delimiter, enclosure = intern->u.file.enclosure, escape = intern->u.file.escape;
	char *delim = NULL, *enclo = NULL, *esc = NULL;
	size_t d_len = 0, e_len = 0, esc_len = 0;
	zend_long ret;
	zval *fields = NULL;

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|sss", &fields, &delim, &d_len, &enclo, &e_len, &esc, &esc_len) == SUCCESS) {
		switch(ZEND_NUM_ARGS())
		{
		case 4:
			if (esc_len != 1) {
				php_error_docref(NULL, E_WARNING, "escape must be a character");
				RETURN_FALSE;
			}
			escape = esc[0];
			/* no break */
		case 3:
			if (e_len != 1) {
				php_error_docref(NULL, E_WARNING, "enclosure must be a character");
				RETURN_FALSE;
			}
			enclosure = enclo[0];
			/* no break */
		case 2:
			if (d_len != 1) {
				php_error_docref(NULL, 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);
		RETURN_LONG(ret);
	}
}

Project: php-src
File: spl_directory.c

static void spl_filesystem_file_free_line(spl_filesystem_object *intern) /* {{{ */
{
	if (intern->u.file.current_line) {
		efree(intern->u.file.current_line);
		intern->u.file.current_line = NULL;
	}
	if (!Z_ISUNDEF(intern->u.file.current_zval)) {
		zval_ptr_dtor(&intern->u.file.current_zval);
		ZVAL_UNDEF(&intern->u.file.current_zval);
	}
} /* }}} */

Project: php-src
File: spl_directory.c

static zend_object *spl_filesystem_object_new_ex(zend_class_entry *class_type)
{
	spl_filesystem_object *intern;

	intern = ecalloc(1, sizeof(spl_filesystem_object) + zend_object_properties_size(class_type));
	/* intern->type = SPL_FS_INFO; done by set 0 */
	intern->file_class = spl_ce_SplFileObject;
	intern->info_class = spl_ce_SplFileInfo;

	zend_object_std_init(&intern->std, class_type);
	object_properties_init(&intern->std, class_type);
	intern->std.handlers = &spl_filesystem_object_handlers;

	return &intern->std;
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, fgetcsv)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	char delimiter = intern->u.file.delimiter, enclosure = intern->u.file.enclosure, escape = intern->u.file.escape;
	char *delim = NULL, *enclo = NULL, *esc = NULL;
	size_t d_len = 0, e_len = 0, esc_len = 0;

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|sss", &delim, &d_len, &enclo, &e_len, &esc, &esc_len) == SUCCESS) {

		if(!intern->u.file.stream) {
			zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
			return;
		}

		switch(ZEND_NUM_ARGS())
		{
		case 3:
			if (esc_len != 1) {
				php_error_docref(NULL, E_WARNING, "escape must be a character");
				RETURN_FALSE;
			}
			escape = esc[0];
			/* no break */
		case 2:
			if (e_len != 1) {
				php_error_docref(NULL, E_WARNING, "enclosure must be a character");
				RETURN_FALSE;
			}
			enclosure = enclo[0];
			/* no break */
		case 1:
			if (d_len != 1) {
				php_error_docref(NULL, E_WARNING, "delimiter must be a character");
				RETURN_FALSE;
			}
			delimiter = delim[0];
			/* no break */
		case 0:
			break;
		}
		spl_filesystem_file_read_csv(intern, delimiter, enclosure, escape, return_value);
	}
}

Project: php-src
File: spl_directory.c

static void spl_filesystem_object_destroy_object(zend_object *object) /* {{{ */
{
	spl_filesystem_object *intern = spl_filesystem_from_obj(object);

	zend_objects_destroy_object(object);

	switch(intern->type) {
	case SPL_FS_DIR:
		if (intern->u.dir.dirp) {
			php_stream_close(intern->u.dir.dirp);
			intern->u.dir.dirp = NULL;
		}
		break;
	case SPL_FS_FILE:
		if (intern->u.file.stream) {
			/*
			if (intern->u.file.zcontext) {
			   zend_list_delref(Z_RESVAL_P(intern->zcontext));
			}
			*/
			if (!intern->u.file.stream->is_persistent) {
				php_stream_close(intern->u.file.stream);
			} else {
				php_stream_pclose(intern->u.file.stream);
			}
			intern->u.file.stream = NULL;
		}
		break;
	}
} /* }}} */

Project: php-src
File: spl_directory.c

SPL_METHOD(RecursiveDirectoryIterator, getSubPathname)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH;

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	if (intern->u.dir.sub_path) {
		RETURN_NEW_STR(strpprintf(0, "%s%c%s", intern->u.dir.sub_path, slash, intern->u.dir.entry.d_name));
	} else {
		RETURN_STRING(intern->u.dir.entry.d_name);
	}
}

Project: php-src
File: spl_directory.c

static void spl_filesystem_object_free_storage(zend_object *object) /* {{{ */
{
	spl_filesystem_object *intern = spl_filesystem_from_obj(object);

	if (intern->oth_handler && intern->oth_handler->dtor) {
		intern->oth_handler->dtor(intern);
	}

	zend_object_std_dtor(&intern->std);

	if (intern->_path) {
		efree(intern->_path);
	}
	if (intern->file_name) {
		efree(intern->file_name);
	}
	switch(intern->type) {
	case SPL_FS_INFO:
		break;
	case SPL_FS_DIR:
		if (intern->u.dir.sub_path) {
			efree(intern->u.dir.sub_path);
		}
		break;
	case SPL_FS_FILE:
		if (intern->u.file.open_mode) {
			efree(intern->u.file.open_mode);
		}
		if (intern->orig_path) {
			efree(intern->orig_path);
		}
		spl_filesystem_file_free_line(intern);
		break;
	}
} /* }}} */

Project: php-src
File: spl_directory.c

static inline int spl_filesystem_is_dot(const char * d_name) /* {{{ */
{
	return !strcmp(d_name, ".") || !strcmp(d_name, "..");
}

Project: php-src
File: spl_directory.c

SPL_METHOD(DirectoryIterator, rewind)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	intern->u.dir.index = 0;
	if (intern->u.dir.dirp) {
		php_stream_rewinddir(intern->u.dir.dirp);
	}
	spl_filesystem_dir_read(intern);
}

Project: php-src
File: spl_directory.c

static void spl_filesystem_tree_it_current_key(zend_object_iterator *iter, zval *key)
{
	spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter);

	if (SPL_FILE_DIR_KEY(object, SPL_FILE_DIR_KEY_AS_FILENAME)) {
		ZVAL_STRING(key, object->u.dir.entry.d_name);
	} else {
		spl_filesystem_object_get_file_name(object);
		ZVAL_STRINGL(key, object->file_name, object->file_name_len);
	}
}

Project: php-src
File: spl_directory.c

SPL_METHOD(GlobIterator, count)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	if (intern->u.dir.dirp && php_stream_is(intern->u.dir.dirp ,&php_glob_stream_ops)) {
		RETURN_LONG(php_glob_stream_get_count(intern->u.dir.dirp, NULL));
	} else {
		/* should not happen */
		php_error_docref(NULL, E_ERROR, "GlobIterator lost glob state");
	}
}

Project: php-src
File: spl_directory.c

SPL_METHOD(DirectoryIterator, __construct)
{
	spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
}

Project: php-src
File: spl_directory.c

zend_object_iterator *spl_filesystem_dir_get_iterator(zend_class_entry *ce, zval *object, int by_ref)
{
	spl_filesystem_iterator *iterator;
	spl_filesystem_object *dir_object;

	if (by_ref) {
		zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
	}
	dir_object = Z_SPLFILESYSTEM_P(object);
	iterator = spl_filesystem_object_to_iterator(dir_object);
	ZVAL_COPY(&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;

	return &iterator->intern;
}

Project: php-src
File: spl_directory.c

static int spl_filesystem_file_call(spl_filesystem_object *intern, zend_function *func_ptr, int pass_num_args, zval *return_value, zval *arg2) /* {{{ */
{
	zend_fcall_info fci;
	zend_fcall_info_cache fcic;
	zval *zresource_ptr = &intern->u.file.zresource, retval;
	int result;
	int num_args = pass_num_args + (arg2 ? 2 : 1);

	zval *params = (zval*)safe_emalloc(num_args, sizeof(zval), 0);

	params[0] = *zresource_ptr;

	if (arg2) {
		params[1] = *arg2;
	}

	if (zend_get_parameters_array_ex(pass_num_args, params + (arg2 ? 2 : 1)) != SUCCESS) {
		efree(params);
		WRONG_PARAM_COUNT_WITH_RETVAL(FAILURE);
	}

	ZVAL_UNDEF(&retval);

	fci.size = sizeof(fci);
	fci.object = NULL;
	fci.retval = &retval;
	fci.param_count = num_args;
	fci.params = params;
	fci.no_separation = 1;
	ZVAL_STR(&fci.function_name, func_ptr->common.function_name);

	fcic.initialized = 1;
	fcic.function_handler = func_ptr;
	fcic.calling_scope = NULL;
	fcic.called_scope = NULL;
	fcic.object = NULL;

	result = zend_call_function(&fci, &fcic);

	if (result == FAILURE || Z_ISUNDEF(retval)) {
		RETVAL_FALSE;
	} else {
		ZVAL_ZVAL(return_value, &retval, 0, 0);
	}

	efree(params);
	return result;
} /* }}} */

Project: php-src
File: spl_directory.c

SPL_METHOD(FilesystemIterator, __construct)
{
	spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIT_CTOR_FLAGS | SPL_FILE_DIR_SKIPDOTS);
}

Project: php-src
File: spl_directory.c

SPL_METHOD(FilesystemIterator, key)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	if (SPL_FILE_DIR_KEY(intern, SPL_FILE_DIR_KEY_AS_FILENAME)) {
		RETURN_STRING(intern->u.dir.entry.d_name);
	} else {
		spl_filesystem_object_get_file_name(intern);
		RETURN_STRINGL(intern->file_name, intern->file_name_len);
	}
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, eof)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	if(!intern->u.file.stream) {
		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
		return;
	}

	RETURN_BOOL(php_stream_eof(intern->u.file.stream));
} /* }}} */

Project: php-src
File: spl_directory.c

static char *spl_filesystem_object_get_pathname(spl_filesystem_object *intern, size_t *len) { /* {{{ */
	switch (intern->type) {
		case SPL_FS_INFO:
		case SPL_FS_FILE:
			*len = intern->file_name_len;
			return intern->file_name;
		case SPL_FS_DIR:
			if (intern->u.dir.entry.d_name[0]) {
				spl_filesystem_object_get_file_name(intern);
				*len = intern->file_name_len;
				return intern->file_name;
			}
	}
	*len = 0;
	return NULL;
}

Project: php-src
File: spl_directory.c

SPL_METHOD(DirectoryIterator, getBasename)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	char *suffix = 0;
	size_t slen = 0;
	zend_string *fname;

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &suffix, &slen) == FAILURE) {
		return;
	}

	fname = php_basename(intern->u.dir.entry.d_name, strlen(intern->u.dir.entry.d_name), suffix, slen);

	RETVAL_STR(fname);
}

Project: php-src
File: spl_directory.c

SPL_METHOD(DirectoryIterator, key)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	if (intern->u.dir.dirp) {
		RETURN_LONG(intern->u.dir.index);
	} else {
		RETURN_FALSE;
	}
}

Project: php-src
File: spl_directory.c

SPL_METHOD(RecursiveDirectoryIterator, hasChildren)
{
	zend_bool allow_links = 0;
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &allow_links) == FAILURE) {
		return;
	}
	if (spl_filesystem_is_invalid_or_dot(intern->u.dir.entry.d_name)) {
		RETURN_FALSE;
	} else {
		spl_filesystem_object_get_file_name(intern);
		if (!allow_links && !(intern->flags & SPL_FILE_DIR_FOLLOW_SYMLINKS)) {
			php_stat(intern->file_name, intern->file_name_len, FS_IS_LINK, return_value);
			if (zend_is_true(return_value)) {
				RETURN_FALSE;
			}
		}
		php_stat(intern->file_name, intern->file_name_len, FS_IS_DIR, return_value);
    }
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileInfo, getPath)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	char *path;
	size_t path_len;

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

  	path = spl_filesystem_object_get_path(intern, &path_len);
	RETURN_STRINGL(path, path_len);
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileInfo, __construct)
{
	spl_filesystem_object *intern;
	char *path;
	size_t len;

	if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "p", &path, &len) == FAILURE) {
		return;
	}

	intern = Z_SPLFILESYSTEM_P(getThis());

	spl_filesystem_info_set_filename(intern, path, len, 1);

	/* intern->type = SPL_FS_INFO; already set */
}

Project: php-src
File: spl_directory.c

SPL_METHOD(FilesystemIterator, setFlags)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	zend_long flags;

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &flags) == FAILURE) {
		return;
	}

	intern->flags &= ~(SPL_FILE_DIR_KEY_MODE_MASK|SPL_FILE_DIR_CURRENT_MODE_MASK|SPL_FILE_DIR_OTHERS_MASK);
	intern->flags |= ((SPL_FILE_DIR_KEY_MODE_MASK|SPL_FILE_DIR_CURRENT_MODE_MASK|SPL_FILE_DIR_OTHERS_MASK) & flags);
} /* }}} */

Project: php-src
File: spl_directory.c

static zend_object *spl_filesystem_object_new_check(zend_class_entry *class_type)
{
	spl_filesystem_object *ret = spl_filesystem_from_obj(spl_filesystem_object_new_ex(class_type));
	ret->std.handlers = &spl_filesystem_object_check_handlers;
	return &ret->std;
}

Project: php-src
File: spl_directory.c

SPL_METHOD(DirectoryIterator, next)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	int skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS);

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	intern->u.dir.index++;
	do {
		spl_filesystem_dir_read(intern);
	} while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name));
	if (intern->file_name) {
		efree(intern->file_name);
		intern->file_name = NULL;
	}
}

Project: php-src
File: spl_directory.c

static zend_object *spl_filesystem_object_clone(zval *zobject)
{
	zend_object *old_object;
	zend_object *new_object;
	spl_filesystem_object *intern;
	spl_filesystem_object *source;
	int index, skip_dots;

	old_object = Z_OBJ_P(zobject);
	source = spl_filesystem_from_obj(old_object);
	new_object = spl_filesystem_object_new_ex(old_object->ce);
	intern = spl_filesystem_from_obj(new_object);

	intern->flags = source->flags;

	switch (source->type) {
		case SPL_FS_INFO:
			intern->_path_len = source->_path_len;
			intern->_path = estrndup(source->_path, source->_path_len);
			intern->file_name_len = source->file_name_len;
			intern->file_name = estrndup(source->file_name, intern->file_name_len);
			break;
		case SPL_FS_DIR:
			spl_filesystem_dir_open(intern, source->_path);
			/* read until we hit the position in which we were before */
			skip_dots = SPL_HAS_FLAG(source->flags, SPL_FILE_DIR_SKIPDOTS);
			for(index = 0; index < source->u.dir.index; ++index) {
				do {
					spl_filesystem_dir_read(intern);
				} while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name));
			}
			intern->u.dir.index = index;
			break;
		case SPL_FS_FILE:
			ZEND_ASSERT(0);
	}

	intern->file_class = source->file_class;
	intern->info_class = source->info_class;
	intern->oth = source->oth;
	intern->oth_handler = source->oth_handler;

	zend_objects_clone_members(new_object, old_object);

	if (intern->oth_handler && intern->oth_handler->clone) {
		intern->oth_handler->clone(source, intern);
	}

	return new_object;
}

Project: php-src
File: spl_directory.c

static zend_object *spl_filesystem_object_new(zend_class_entry *class_type)
{
	return spl_filesystem_object_new_ex(class_type);
}

Project: php-src
File: spl_directory.c

PHP_MINIT_FUNCTION(spl_directory)
{
	REGISTER_SPL_STD_CLASS_EX(SplFileInfo, spl_filesystem_object_new, spl_SplFileInfo_functions);
	memcpy(&spl_filesystem_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
	spl_filesystem_object_handlers.offset = XtOffsetOf(spl_filesystem_object, std);
	spl_filesystem_object_handlers.clone_obj = spl_filesystem_object_clone;
	spl_filesystem_object_handlers.cast_object = spl_filesystem_object_cast;
	spl_filesystem_object_handlers.get_debug_info  = spl_filesystem_object_get_debug_info;
	spl_filesystem_object_handlers.dtor_obj = spl_filesystem_object_destroy_object;
	spl_filesystem_object_handlers.free_obj = spl_filesystem_object_free_storage;
	spl_ce_SplFileInfo->serialize = zend_class_serialize_deny;
	spl_ce_SplFileInfo->unserialize = zend_class_unserialize_deny;


	REGISTER_SPL_SUB_CLASS_EX(DirectoryIterator, SplFileInfo, spl_filesystem_object_new, spl_DirectoryIterator_functions);
	zend_class_implements(spl_ce_DirectoryIterator, 1, zend_ce_iterator);
	REGISTER_SPL_IMPLEMENTS(DirectoryIterator, SeekableIterator);

	spl_ce_DirectoryIterator->get_iterator = spl_filesystem_dir_get_iterator;

	REGISTER_SPL_SUB_CLASS_EX(FilesystemIterator, DirectoryIterator, spl_filesystem_object_new, spl_FilesystemIterator_functions);

	REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "CURRENT_MODE_MASK",   SPL_FILE_DIR_CURRENT_MODE_MASK);
	REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "CURRENT_AS_PATHNAME", SPL_FILE_DIR_CURRENT_AS_PATHNAME);
	REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "CURRENT_AS_FILEINFO", SPL_FILE_DIR_CURRENT_AS_FILEINFO);
	REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "CURRENT_AS_SELF",     SPL_FILE_DIR_CURRENT_AS_SELF);
	REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "KEY_MODE_MASK",       SPL_FILE_DIR_KEY_MODE_MASK);
	REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "KEY_AS_PATHNAME",     SPL_FILE_DIR_KEY_AS_PATHNAME);
	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);

	spl_ce_FilesystemIterator->get_iterator = spl_filesystem_tree_get_iterator;

	REGISTER_SPL_SUB_CLASS_EX(RecursiveDirectoryIterator, FilesystemIterator, spl_filesystem_object_new, spl_RecursiveDirectoryIterator_functions);
	REGISTER_SPL_IMPLEMENTS(RecursiveDirectoryIterator, RecursiveIterator);

	memcpy(&spl_filesystem_object_check_handlers, &spl_filesystem_object_handlers, sizeof(zend_object_handlers));
	spl_filesystem_object_check_handlers.clone_obj = NULL;
	spl_filesystem_object_check_handlers.get_method = spl_filesystem_object_get_method_check;

#ifdef HAVE_GLOB
	REGISTER_SPL_SUB_CLASS_EX(GlobIterator, FilesystemIterator, spl_filesystem_object_new_check, spl_GlobIterator_functions);
	REGISTER_SPL_IMPLEMENTS(GlobIterator, Countable);
#endif

	REGISTER_SPL_SUB_CLASS_EX(SplFileObject, SplFileInfo, spl_filesystem_object_new_check, spl_SplFileObject_functions);
	REGISTER_SPL_IMPLEMENTS(SplFileObject, RecursiveIterator);
	REGISTER_SPL_IMPLEMENTS(SplFileObject, SeekableIterator);

	REGISTER_SPL_CLASS_CONST_LONG(SplFileObject, "DROP_NEW_LINE", SPL_FILE_OBJECT_DROP_NEW_LINE);
	REGISTER_SPL_CLASS_CONST_LONG(SplFileObject, "READ_AHEAD",    SPL_FILE_OBJECT_READ_AHEAD);
	REGISTER_SPL_CLASS_CONST_LONG(SplFileObject, "SKIP_EMPTY",    SPL_FILE_OBJECT_SKIP_EMPTY);
	REGISTER_SPL_CLASS_CONST_LONG(SplFileObject, "READ_CSV",      SPL_FILE_OBJECT_READ_CSV);

	REGISTER_SPL_SUB_CLASS_EX(SplTempFileObject, SplFileObject, spl_filesystem_object_new_check, spl_SplTempFileObject_functions);
	return SUCCESS;
}

Project: php-src
File: spl_directory.c

SPL_METHOD(DirectoryIterator, current)
{
	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}
	ZVAL_OBJ(return_value, Z_OBJ_P(getThis()));
	Z_ADDREF_P(return_value);
}

Project: php-src
File: spl_directory.c

static int spl_filesystem_file_read_line(zval * this_ptr, spl_filesystem_object *intern, int silent) /* {{{ */
{
	int ret = spl_filesystem_file_read_line_ex(this_ptr, intern, silent);

	while (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_SKIP_EMPTY) && ret == SUCCESS && spl_filesystem_file_is_empty_line(intern)) {
		spl_filesystem_file_free_line(intern);
		ret = spl_filesystem_file_read_line_ex(this_ptr, intern, silent);
	}

	return ret;
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileInfo, getPathInfo)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	zend_class_entry *ce = intern->info_class;
	zend_error_handling error_handling;

	zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling);

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C", &ce) == SUCCESS) {
		size_t path_len;
		char *path = spl_filesystem_object_get_pathname(intern, &path_len);
		if (path) {
			char *dpath = estrndup(path, path_len);
			path_len = php_dirname(dpath, path_len);
			spl_filesystem_object_create_info(intern, dpath, path_len, 1, ce, return_value);
			efree(dpath);
		}
	}

	zend_restore_error_handling(&error_handling);
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, getChildren)
{
	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}
	/* return NULL */
} /* }}} */

Project: php-src
File: spl_directory.c

SPL_METHOD(DirectoryIterator, getFilename)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	RETURN_STRING(intern->u.dir.entry.d_name);
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, getFlags)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	RETURN_LONG(intern->flags & SPL_FILE_OBJECT_MASK);
} /* }}} */

Project: php-src
File: spl_directory.c

SPL_METHOD(DirectoryIterator, seek)
{
	spl_filesystem_object *intern    = Z_SPLFILESYSTEM_P(getThis());
	zval retval;
	zend_long pos;

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &pos) == FAILURE) {
		return;
	}

	if (intern->u.dir.index > pos) {
		/* we first rewind */
		zend_call_method_with_0_params(&EX(This), Z_OBJCE(EX(This)), &intern->u.dir.func_rewind, "rewind", NULL);
	}

	while (intern->u.dir.index < pos) {
		int valid = 0;
		zend_call_method_with_0_params(&EX(This), Z_OBJCE(EX(This)), &intern->u.dir.func_valid, "valid", &retval);
		if (!Z_ISUNDEF(retval)) {
			valid = zend_is_true(&retval);
			zval_ptr_dtor(&retval);
		}
		if (!valid) {
			zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0, "Seek position " ZEND_LONG_FMT " is out of range", pos);
			return;
		}
		zend_call_method_with_0_params(&EX(This), Z_OBJCE(EX(This)), &intern->u.dir.func_next, "next", NULL);
	}
} /* }}} */

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileInfo, setFileClass)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	zend_class_entry *ce = spl_ce_SplFileObject;
	zend_error_handling error_handling;

	zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling);

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C", &ce) == SUCCESS) {
		intern->file_class = ce;
	}

	zend_restore_error_handling(&error_handling);
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, fseek)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	zend_long pos, whence = SEEK_SET;

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &pos, &whence) == FAILURE) {
		return;
	}

	if(!intern->u.file.stream) {
		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
		return;
	}

	spl_filesystem_file_free_line(intern);
	RETURN_LONG(php_stream_seek(intern->u.file.stream, pos, (int)whence));
} /* }}} */

Project: php-src
File: spl_directory.c

static HashTable *spl_filesystem_object_get_debug_info(zval *object, int *is_temp) /* {{{ */
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(object);
	zval tmp;
	HashTable *rv;
	zend_string *pnstr;
	char *path;
	size_t  path_len;
	char stmp[2];

	*is_temp = 1;

	if (!intern->std.properties) {
		rebuild_object_properties(&intern->std);
	}

	rv = zend_array_dup(intern->std.properties);

	pnstr = spl_gen_private_prop_name(spl_ce_SplFileInfo, "pathName", sizeof("pathName")-1);
	path = spl_filesystem_object_get_pathname(intern, &path_len);
	ZVAL_STRINGL(&tmp, path, path_len);
	zend_symtable_update(rv, pnstr, &tmp);
	zend_string_release(pnstr);

	if (intern->file_name) {
		pnstr = spl_gen_private_prop_name(spl_ce_SplFileInfo, "fileName", sizeof("fileName")-1);
		spl_filesystem_object_get_path(intern, &path_len);

		if (path_len && path_len < intern->file_name_len) {
			ZVAL_STRINGL(&tmp, intern->file_name + path_len + 1, intern->file_name_len - (path_len + 1));
		} else {
			ZVAL_STRINGL(&tmp, intern->file_name, intern->file_name_len);
		}
		zend_symtable_update(rv, pnstr, &tmp);
		zend_string_release(pnstr);
	}
	if (intern->type == SPL_FS_DIR) {
#ifdef HAVE_GLOB
		pnstr = spl_gen_private_prop_name(spl_ce_DirectoryIterator, "glob", sizeof("glob")-1);
		if (php_stream_is(intern->u.dir.dirp ,&php_glob_stream_ops)) {
			ZVAL_STRINGL(&tmp, intern->_path, intern->_path_len);
		} else {
			ZVAL_FALSE(&tmp);
		}
		zend_symtable_update(rv, pnstr, &tmp);
		zend_string_release(pnstr);
#endif
		pnstr = spl_gen_private_prop_name(spl_ce_RecursiveDirectoryIterator, "subPathName", sizeof("subPathName")-1);
		if (intern->u.dir.sub_path) {
			ZVAL_STRINGL(&tmp, intern->u.dir.sub_path, intern->u.dir.sub_path_len);
		} else {
			ZVAL_EMPTY_STRING(&tmp);
		}
		zend_symtable_update(rv, pnstr, &tmp);
		zend_string_release(pnstr);
	}
	if (intern->type == SPL_FS_FILE) {
		pnstr = spl_gen_private_prop_name(spl_ce_SplFileObject, "openMode", sizeof("openMode")-1);
		ZVAL_STRINGL(&tmp, intern->u.file.open_mode, intern->u.file.open_mode_len);
		zend_symtable_update(rv, pnstr, &tmp);
		zend_string_release(pnstr);
		stmp[1] = '\0';
		stmp[0] = intern->u.file.delimiter;
		pnstr = spl_gen_private_prop_name(spl_ce_SplFileObject, "delimiter", sizeof("delimiter")-1);
		ZVAL_STRINGL(&tmp, stmp, 1);
		zend_symtable_update(rv, pnstr, &tmp);
		zend_string_release(pnstr);
		stmp[0] = intern->u.file.enclosure;
		pnstr = spl_gen_private_prop_name(spl_ce_SplFileObject, "enclosure", sizeof("enclosure")-1);
		ZVAL_STRINGL(&tmp, stmp, 1);
		zend_symtable_update(rv, pnstr, &tmp);
		zend_string_release(pnstr);
	}

	return rv;
}

Project: php-src
File: spl_directory.c

static void spl_filesystem_dir_it_rewind(zend_object_iterator *iter)
{
	spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter);

	object->u.dir.index = 0;
	if (object->u.dir.dirp) {
		php_stream_rewinddir(object->u.dir.dirp);
	}
	spl_filesystem_dir_read(object);
}

Project: php-src
File: spl_directory.c

static zval *spl_filesystem_tree_it_current_data(zend_object_iterator *iter)
{
	spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;
	spl_filesystem_object   *object   = spl_filesystem_iterator_to_object(iterator);

	if (SPL_FILE_DIR_CURRENT(object, SPL_FILE_DIR_CURRENT_AS_PATHNAME)) {
		if (Z_ISUNDEF(iterator->current)) {
			spl_filesystem_object_get_file_name(object);
			ZVAL_STRINGL(&iterator->current, object->file_name, object->file_name_len);
		}
		return &iterator->current;
	} else if (SPL_FILE_DIR_CURRENT(object, SPL_FILE_DIR_CURRENT_AS_FILEINFO)) {
		if (Z_ISUNDEF(iterator->current)) {
			spl_filesystem_object_get_file_name(object);
			spl_filesystem_object_create_type(0, object, SPL_FS_INFO, NULL, &iterator->current);
		}
		return &iterator->current;
	} else {
		return &iterator->intern.data;
	}
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, fgetc)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	char buf[2];
	int result;

	if(!intern->u.file.stream) {
		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
		return;
	}

	spl_filesystem_file_free_line(intern);

	result = php_stream_getc(intern->u.file.stream);

	if (result == EOF) {
		RETVAL_FALSE;
	} else {
		if (result == '\n') {
			intern->u.file.current_line_num++;
		}
		buf[0] = result;
		buf[1] = '\0';

		RETURN_STRINGL(buf, 1);
	}
} /* }}} */

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, ftell)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	zend_long ret;

	if(!intern->u.file.stream) {
		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
		return;
	}

	ret = php_stream_tell(intern->u.file.stream);

	if (ret == -1) {
		RETURN_FALSE;
	} else {
		RETURN_LONG(ret);
	}
} /* }}} */

Project: php-src
File: spl_directory.c

static int spl_filesystem_dir_read(spl_filesystem_object *intern) /* {{{ */
{
	if (!intern->u.dir.dirp || !php_stream_readdir(intern->u.dir.dirp, &intern->u.dir.entry)) {
		intern->u.dir.entry.d_name[0] = '\0';
		return 0;
	} else {
		return 1;
	}
}

Project: php-src
File: spl_directory.c

static void spl_filesystem_file_rewind(zval * this_ptr, spl_filesystem_object *intern) /* {{{ */
{
	if(!intern->u.file.stream) {
		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
		return;
	}
	if (-1 == php_stream_rewind(intern->u.file.stream)) {
		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot rewind file %s", intern->file_name);
	} else {
		spl_filesystem_file_free_line(intern);
		intern->u.file.current_line_num = 0;
	}
	if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_AHEAD)) {
		spl_filesystem_file_read_line(this_ptr, intern, 1);
	}
} /* }}} */

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, key)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

/*	Do not read the next line to support correct counting with fgetc()
	if (!intern->current_line) {
		spl_filesystem_file_read_line(getThis(), intern, 1);
	} */
	RETURN_LONG(intern->u.file.current_line_num);
} /* }}} */

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, fgetss)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	zval arg2;

	if(!intern->u.file.stream) {
		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
		return;
	}

	if (intern->u.file.max_line_len > 0) {
		ZVAL_LONG(&arg2, intern->u.file.max_line_len);
	} else {
		ZVAL_LONG(&arg2, 1024);
	}

	spl_filesystem_file_free_line(intern);
	intern->u.file.current_line_num++;

	FileFunctionCall(fgetss, ZEND_NUM_ARGS(), &arg2);
} /* }}} */

Project: php-src
File: spl_directory.c

static int spl_filesystem_file_read(spl_filesystem_object *intern, int silent) /* {{{ */
{
	char *buf;
	size_t line_len = 0;
	zend_long line_add = (intern->u.file.current_line || !Z_ISUNDEF(intern->u.file.current_zval)) ? 1 : 0;

	spl_filesystem_file_free_line(intern);

	if (php_stream_eof(intern->u.file.stream)) {
		if (!silent) {
			zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot read from file %s", intern->file_name);
		}
		return FAILURE;
	}

	if (intern->u.file.max_line_len > 0) {
		buf = safe_emalloc((intern->u.file.max_line_len + 1), sizeof(char), 0);
		if (php_stream_get_line(intern->u.file.stream, buf, intern->u.file.max_line_len + 1, &line_len) == NULL) {
			efree(buf);
			buf = NULL;
		} else {
			buf[line_len] = '\0';
		}
	} else {
		buf = php_stream_get_line(intern->u.file.stream, NULL, 0, &line_len);
	}

	if (!buf) {
		intern->u.file.current_line = estrdup("");
		intern->u.file.current_line_len = 0;
	} else {
		if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_DROP_NEW_LINE)) {
			line_len = strcspn(buf, "\r\n");
			buf[line_len] = '\0';
		}

		intern->u.file.current_line = buf;
		intern->u.file.current_line_len = line_len;
	}
	intern->u.file.current_line_num += line_add;

	return SUCCESS;
} /* }}} */

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileInfo, getFilename)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	size_t path_len;

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	spl_filesystem_object_get_path(intern, &path_len);

	if (path_len && path_len < intern->file_name_len) {
		RETURN_STRINGL(intern->file_name + path_len + 1, intern->file_name_len - (path_len + 1));
	} else {
		RETURN_STRINGL(intern->file_name, intern->file_name_len);
	}
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, hasChildren)
{
	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	RETURN_FALSE;
} /* }}} */

Project: php-src
File: spl_directory.c

static spl_filesystem_object *spl_filesystem_object_create_type(int ht, spl_filesystem_object *source, int type, zend_class_entry *ce, zval *return_value) /* {{{ */
{
	spl_filesystem_object *intern;
	zend_bool use_include_path = 0;
	zval arg1, arg2;
	zend_error_handling error_handling;

	zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);

	switch (source->type) {
		case SPL_FS_INFO:
		case SPL_FS_FILE:
			break;
		case SPL_FS_DIR:
			if (!source->u.dir.entry.d_name[0]) {
				zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Could not open file");
				zend_restore_error_handling(&error_handling);
				return NULL;
			}
	}

	switch (type) {
		case SPL_FS_INFO:
			ce = ce ? ce : source->info_class;

			if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
				break;
			}

			intern = spl_filesystem_from_obj(spl_filesystem_object_new_ex(ce));
			ZVAL_OBJ(return_value, &intern->std);

			spl_filesystem_object_get_file_name(source);
			if (ce->constructor->common.scope != spl_ce_SplFileInfo) {
				ZVAL_STRINGL(&arg1, source->file_name, source->file_name_len);
				zend_call_method_with_1_params(return_value, ce, &ce->constructor, "__construct", NULL, &arg1);
				zval_ptr_dtor(&arg1);
			} else {
				intern->file_name = estrndup(source->file_name, source->file_name_len);
				intern->file_name_len = source->file_name_len;
				intern->_path = spl_filesystem_object_get_path(source, &intern->_path_len);
				intern->_path = estrndup(intern->_path, intern->_path_len);
			}
			break;
		case SPL_FS_FILE:
			ce = ce ? ce : source->file_class;

			if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
				break;
			}

			intern = spl_filesystem_from_obj(spl_filesystem_object_new_ex(ce));

			ZVAL_OBJ(return_value, &intern->std);

			spl_filesystem_object_get_file_name(source);

			if (ce->constructor->common.scope != spl_ce_SplFileObject) {
				ZVAL_STRINGL(&arg1, source->file_name, source->file_name_len);
				ZVAL_STRINGL(&arg2, "r", 1);
				zend_call_method_with_2_params(return_value, ce, &ce->constructor, "__construct", NULL, &arg1, &arg2);
				zval_ptr_dtor(&arg1);
				zval_ptr_dtor(&arg2);
			} else {
				intern->file_name = source->file_name;
				intern->file_name_len = source->file_name_len;
				intern->_path = spl_filesystem_object_get_path(source, &intern->_path_len);
				intern->_path = estrndup(intern->_path, intern->_path_len);

				intern->u.file.open_mode = "r";
				intern->u.file.open_mode_len = 1;

				if (ht && zend_parse_parameters(ht, "|sbr",
							&intern->u.file.open_mode, &intern->u.file.open_mode_len,
							&use_include_path, &intern->u.file.zcontext) == FAILURE) {
					zend_restore_error_handling(&error_handling);
					intern->u.file.open_mode = NULL;
					intern->file_name = NULL;
					zval_ptr_dtor(return_value);
					ZVAL_NULL(return_value);
					return NULL;
				}

				if (spl_filesystem_file_open(intern, use_include_path, 0) == FAILURE) {
					zend_restore_error_handling(&error_handling);
					zval_ptr_dtor(return_value);
					ZVAL_NULL(return_value);
					return NULL;
				}
			}
			break;
		case SPL_FS_DIR:
			zend_restore_error_handling(&error_handling);
			zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Operation not supported");
			return NULL;
	}
	zend_restore_error_handling(&error_handling);
	return NULL;
} /* }}} */

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, rewind)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	spl_filesystem_file_rewind(getThis(), intern);
} /* }}} */

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, fwrite)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	char *str;
	size_t str_len;
	zend_long length = 0;

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &str, &str_len, &length) == FAILURE) {
		return;
	}

	if(!intern->u.file.stream) {
		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
		return;
	}

	if (ZEND_NUM_ARGS() > 1) {
		if (length >= 0) {
			str_len = MIN((size_t)length, str_len);
		} else {
			/* Negative length given, nothing to write */
			str_len = 0;
		}
	}
	if (!str_len) {
		RETURN_LONG(0);
	}

	RETURN_LONG(php_stream_write(intern->u.file.stream, str, str_len));
} /* }}} */

Project: php-src
File: spl_directory.c

SPL_METHOD(GlobIterator, __construct)
{
	spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIT_CTOR_FLAGS|DIT_CTOR_GLOB);
}

Project: php-src
File: spl_directory.c

static spl_filesystem_object *spl_filesystem_object_create_info(spl_filesystem_object *source, char *file_path, size_t file_path_len, int use_copy, zend_class_entry *ce, zval *return_value) /* {{{ */
{
	spl_filesystem_object *intern;
	zval arg1;
	zend_error_handling error_handling;

	if (!file_path || !file_path_len) {
#if defined(PHP_WIN32)
		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot create SplFileInfo for empty path");
		if (file_path && !use_copy) {
			efree(file_path);
		}
#else
		if (file_path && !use_copy) {
			efree(file_path);
		}
		file_path_len = 1;
		file_path = "/";
#endif
		return NULL;
	}

	zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);

	ce = ce ? ce : source->info_class;

	zend_update_class_constants(ce);

	intern = spl_filesystem_from_obj(spl_filesystem_object_new_ex(ce));
	ZVAL_OBJ(return_value, &intern->std);

	if (ce->constructor->common.scope != spl_ce_SplFileInfo) {
		ZVAL_STRINGL(&arg1, file_path, file_path_len);
		zend_call_method_with_1_params(return_value, ce, &ce->constructor, "__construct", NULL, &arg1);
		zval_ptr_dtor(&arg1);
	} else {
		spl_filesystem_info_set_filename(intern, file_path, file_path_len, use_copy);
	}

	zend_restore_error_handling(&error_handling);
	return intern;
} /* }}} */

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, getMaxLineLen)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	RETURN_LONG((zend_long)intern->u.file.max_line_len);
} /* }}} */

Project: php-src
File: spl_directory.c

static int spl_filesystem_file_open(spl_filesystem_object *intern, int use_include_path, int silent) /* {{{ */
{
	zval tmp;

	intern->type = SPL_FS_FILE;

	php_stat(intern->file_name, intern->file_name_len, FS_IS_DIR, &tmp);
	if (Z_TYPE(tmp) == IS_TRUE) {
		intern->u.file.open_mode = NULL;
		intern->file_name = NULL;
		zend_throw_exception_ex(spl_ce_LogicException, 0, "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) | REPORT_ERRORS, NULL, intern->u.file.context);

	if (!intern->file_name_len || !intern->u.file.stream) {
		if (!EG(exception)) {
			zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot open file '%s'", intern->file_name_len ? intern->file_name : "");
		}
		intern->file_name = NULL; /* until here it is not a copy */
		intern->u.file.open_mode = NULL;
		return FAILURE;
	}

	/*
	if (intern->u.file.zcontext) {
		//zend_list_addref(Z_RES_VAL(intern->u.file.zcontext));
		Z_ADDREF_P(intern->u.file.zcontext);
	}
	*/

	if (intern->file_name_len > 1 && IS_SLASH_AT(intern->file_name, intern->file_name_len-1)) {
		intern->file_name_len--;
	}

	intern->orig_path = estrndup(intern->u.file.stream->orig_path, strlen(intern->u.file.stream->orig_path));

	intern->file_name = estrndup(intern->file_name, intern->file_name_len);
	intern->u.file.open_mode = estrndup(intern->u.file.open_mode, intern->u.file.open_mode_len);

	/* avoid reference counting in debug mode, thus do it manually */
	ZVAL_RES(&intern->u.file.zresource, intern->u.file.stream->res);
	/*!!! TODO: maybe bug?
	Z_SET_REFCOUNT(intern->u.file.zresource, 1);
	*/

	intern->u.file.delimiter = ',';
	intern->u.file.enclosure = '"';
	intern->u.file.escape = '\\';

	intern->u.file.func_getCurr = zend_hash_str_find_ptr(&intern->std.ce->function_table, "getcurrentline", sizeof("getcurrentline") - 1);

	return SUCCESS;
} /* }}} */

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, fgets)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	if(!intern->u.file.stream) {
		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
		return;
	}

	if (spl_filesystem_file_read(intern, 0) == FAILURE) {
		RETURN_FALSE;
	}
	RETURN_STRINGL(intern->u.file.current_line, intern->u.file.current_line_len);
} /* }}} */

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, fpassthru)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());

	if(!intern->u.file.stream) {
		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
		return;
	}

	RETURN_LONG(php_stream_passthru(intern->u.file.stream));
} /* }}} */

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, fread)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	zend_long length = 0;

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &length) == FAILURE) {
		return;
	}

	if(!intern->u.file.stream) {
		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
		return;
	}

	if (length <= 0) {
		php_error_docref(NULL, E_WARNING, "Length parameter must be greater than 0");
		RETURN_FALSE;
	}

	ZVAL_NEW_STR(return_value, zend_string_alloc(length, 0));
	Z_STRLEN_P(return_value) = php_stream_read(intern->u.file.stream, Z_STRVAL_P(return_value), length);

	/* needed because recv/read/gzread doesnt put a null at the end*/
	Z_STRVAL_P(return_value)[Z_STRLEN_P(return_value)] = 0;
}

Project: php-src
File: spl_directory.c

static void spl_filesystem_dir_open(spl_filesystem_object* intern, char *path)
{
	int skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS);

	intern->type = SPL_FS_DIR;
	intern->_path_len = strlen(path);
	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);
	} else {
		intern->_path = estrndup(path, intern->_path_len);
	}
	intern->u.dir.index = 0;

	if (EG(exception) || intern->u.dir.dirp == NULL) {
		intern->u.dir.entry.d_name[0] = '\0';
		if (!EG(exception)) {
			/* open failed w/out notice (turned to exception due to EH_THROW) */
			zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
				"Failed to open directory \"%s\"", path);
		}
	} else {
		do {
			spl_filesystem_dir_read(intern);
		} while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name));
	}
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, setCsvControl)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	char delimiter = ',', enclosure = '"', escape='\\';
	char *delim = NULL, *enclo = NULL, *esc = NULL;
	size_t d_len = 0, e_len = 0, esc_len = 0;

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|sss", &delim, &d_len, &enclo, &e_len, &esc, &esc_len) == SUCCESS) {
		switch(ZEND_NUM_ARGS())
		{
		case 3:
			if (esc_len != 1) {
				php_error_docref(NULL, E_WARNING, "escape must be a character");
				RETURN_FALSE;
			}
			escape = esc[0];
			/* no break */
		case 2:
			if (e_len != 1) {
				php_error_docref(NULL, E_WARNING, "enclosure must be a character");
				RETURN_FALSE;
			}
			enclosure = enclo[0];
			/* no break */
		case 1:
			if (d_len != 1) {
				php_error_docref(NULL, E_WARNING, "delimiter must be a character");
				RETURN_FALSE;
			}
			delimiter = delim[0];
			/* no break */
		case 0:
			break;
		}
		intern->u.file.delimiter = delimiter;
		intern->u.file.enclosure = enclosure;
		intern->u.file.escape    = escape;
	}
}

Project: php-src
File: spl_directory.c

SPL_METHOD(DirectoryIterator, getExtension)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	const char *p;
	size_t idx;
	zend_string *fname;

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	fname = php_basename(intern->u.dir.entry.d_name, strlen(intern->u.dir.entry.d_name), NULL, 0);

	p = zend_memrchr(ZSTR_VAL(fname), '.', ZSTR_LEN(fname));
	if (p) {
		idx = p - ZSTR_VAL(fname);
		RETVAL_STRINGL(ZSTR_VAL(fname) + idx + 1, ZSTR_LEN(fname) - idx - 1);
		zend_string_release(fname);
	} else {
		zend_string_release(fname);
		RETURN_EMPTY_STRING();
	}
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileInfo, getPathname)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	char *path;
	size_t path_len;

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}
	path = spl_filesystem_object_get_pathname(intern, &path_len);
	if (path != NULL) {
		RETURN_STRINGL(path, path_len);
	} else {
		RETURN_FALSE;
	}
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, __construct)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	zend_bool use_include_path = 0;
	char *p1, *p2;
	char *tmp_path;
	size_t   tmp_path_len;
	zend_error_handling error_handling;

	intern->u.file.open_mode = NULL;
	intern->u.file.open_mode_len = 0;

	if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "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) {
		intern->u.file.open_mode = NULL;
		intern->file_name = NULL;
		return;
	}

	if (intern->u.file.open_mode == NULL) {
		intern->u.file.open_mode = "r";
		intern->u.file.open_mode_len = 1;
	}

	zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);

	if (spl_filesystem_file_open(intern, use_include_path, 0) == SUCCESS) {
		tmp_path_len = strlen(intern->u.file.stream->orig_path);

		if (tmp_path_len > 1 && IS_SLASH_AT(intern->u.file.stream->orig_path, tmp_path_len-1)) {
			tmp_path_len--;
		}

		tmp_path = estrndup(intern->u.file.stream->orig_path, tmp_path_len);

		p1 = strrchr(tmp_path, '/');
#if defined(PHP_WIN32)
		p2 = strrchr(tmp_path, '\\');
#else
		p2 = 0;
#endif
		if (p1 || p2) {
			intern->_path_len = ((p1 > p2 ? p1 : p2) - tmp_path);
		} else {
			intern->_path_len = 0;
		}

		efree(tmp_path);

		intern->_path = estrndup(intern->u.file.stream->orig_path, intern->_path_len);
	}

	zend_restore_error_handling(&error_handling);

} /* }}} */

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileInfo, getFileInfo)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	zend_class_entry *ce = intern->info_class;
	zend_error_handling error_handling;

	zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling);

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C", &ce) == SUCCESS) {
		spl_filesystem_object_create_type(ZEND_NUM_ARGS(), intern, SPL_FS_INFO, ce, return_value);
	}

	zend_restore_error_handling(&error_handling);
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, valid)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_AHEAD)) {
		RETURN_BOOL(intern->u.file.current_line || !Z_ISUNDEF(intern->u.file.current_zval));
	} else {
		if(!intern->u.file.stream) {
			RETURN_FALSE;
		}
		RETVAL_BOOL(!php_stream_eof(intern->u.file.stream));
	}
} /* }}} */

Project: php-src
File: spl_directory.c

void spl_filesystem_info_set_filename(spl_filesystem_object *intern, char *path, size_t len, size_t use_copy) /* {{{ */
{
	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;

	while (intern->file_name_len > 1 && IS_SLASH_AT(intern->file_name, intern->file_name_len-1)) {
		intern->file_name[intern->file_name_len-1] = 0;
		intern->file_name_len--;
	}

	p1 = strrchr(intern->file_name, '/');
#if defined(PHP_WIN32)
	p2 = strrchr(intern->file_name, '\\');
#else
	p2 = 0;
#endif
	if (p1 || p2) {
		intern->_path_len = ((p1 > p2 ? p1 : p2) - intern->file_name);
	} else {
		intern->_path_len = 0;
	}

	if (intern->_path) {
		efree(intern->_path);
	}
	intern->_path = estrndup(path, intern->_path_len);
} /* }}} */

Project: php-src
File: spl_directory.c

static int spl_filesystem_file_read_csv(spl_filesystem_object *intern, char delimiter, char enclosure, char escape, zval *return_value) /* {{{ */
{
	int ret = SUCCESS;
	zval *value;

	do {
		ret = spl_filesystem_file_read(intern, 1);
	} while (ret == SUCCESS && !intern->u.file.current_line_len && SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_SKIP_EMPTY));

	if (ret == SUCCESS) {
		size_t buf_len = intern->u.file.current_line_len;
		char *buf = estrndup(intern->u.file.current_line, buf_len);

		if (!Z_ISUNDEF(intern->u.file.current_zval)) {
			zval_ptr_dtor(&intern->u.file.current_zval);
			ZVAL_UNDEF(&intern->u.file.current_zval);
		}

		php_fgetcsv(intern->u.file.stream, delimiter, enclosure, escape, buf_len, buf, &intern->u.file.current_zval);
		if (return_value) {
			zval_ptr_dtor(return_value);
			value = &intern->u.file.current_zval;
			ZVAL_DEREF(value);
			ZVAL_COPY(return_value, value);
		}
	}
	return ret;
}

Project: php-src
File: spl_directory.c

SPL_METHOD(DirectoryIterator, valid)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	RETURN_BOOL(intern->u.dir.entry.d_name[0] != '\0');
}

Project: php-src
File: spl_directory.c

static int spl_filesystem_dir_it_valid(zend_object_iterator *iter)
{
	spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter);

	return object->u.dir.entry.d_name[0] != '\0' ? SUCCESS : FAILURE;
}

Project: php-src
File: spl_directory.c

zend_object_iterator *spl_filesystem_tree_get_iterator(zend_class_entry *ce, zval *object, int by_ref)
{
	spl_filesystem_iterator *iterator;
	spl_filesystem_object *dir_object;

	if (by_ref) {
		zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
	}
	dir_object = Z_SPLFILESYSTEM_P(object);
	iterator = spl_filesystem_object_to_iterator(dir_object);

	ZVAL_COPY(&iterator->intern.data, object);
	iterator->intern.funcs = &spl_filesystem_tree_it_funcs;

	return &iterator->intern;
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileInfo, getExtension)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	char *fname = NULL;
	const char *p;
	size_t flen;
	size_t path_len;
	size_t idx;
	zend_string *ret;

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	spl_filesystem_object_get_path(intern, &path_len);

	if (path_len && path_len < intern->file_name_len) {
		fname = intern->file_name + path_len + 1;
		flen = intern->file_name_len - (path_len + 1);
	} else {
		fname = intern->file_name;
		flen = intern->file_name_len;
	}

	ret = php_basename(fname, flen, NULL, 0);

	p = zend_memrchr(ZSTR_VAL(ret), '.', ZSTR_LEN(ret));
	if (p) {
		idx = p - ZSTR_VAL(ret);
		RETVAL_STRINGL(ZSTR_VAL(ret) + idx + 1, ZSTR_LEN(ret) - idx - 1);
		zend_string_release(ret);
		return;
	} else {
		zend_string_release(ret);
		RETURN_EMPTY_STRING();
	}
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, next)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	spl_filesystem_file_free_line(intern);
	if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_AHEAD)) {
		spl_filesystem_file_read_line(getThis(), intern, 1);
	}
	intern->u.file.current_line_num++;
} /* }}} */

Project: php-src
File: spl_directory.c

SPL_METHOD(DirectoryIterator, isDot)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	RETURN_BOOL(spl_filesystem_is_dot(intern->u.dir.entry.d_name));
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, setMaxLineLen)
{
	zend_long max_len;

	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &max_len) == FAILURE) {
		return;
	}

	if (max_len < 0) {
		zend_throw_exception_ex(spl_ce_DomainException, 0, "Maximum line length must be greater than or equal zero");
		return;
	}

	intern->u.file.max_line_len = max_len;
} /* }}} */

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, ftruncate)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	zend_long size;

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &size) == FAILURE) {
		return;
	}

	if(!intern->u.file.stream) {
		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
		return;
	}

	if (!php_stream_truncate_supported(intern->u.file.stream)) {
		zend_throw_exception_ex(spl_ce_LogicException, 0, "Can't truncate file %s", intern->file_name);
		RETURN_FALSE;
	}

	RETURN_BOOL(0 == php_stream_truncate_set_size(intern->u.file.stream, size));
} /* }}} */

Project: php-src
File: spl_directory.c

static void spl_filesystem_tree_it_rewind(zend_object_iterator *iter)
{
	spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;
	spl_filesystem_object   *object   = spl_filesystem_iterator_to_object(iterator);

	object->u.dir.index = 0;
	if (object->u.dir.dirp) {
		php_stream_rewinddir(object->u.dir.dirp);
	}
	do {
		spl_filesystem_dir_read(object);
	} while (spl_filesystem_is_dot(object->u.dir.entry.d_name));
	if (!Z_ISUNDEF(iterator->current)) {
		zval_ptr_dtor(&iterator->current);
		ZVAL_UNDEF(&iterator->current);
	}
}

Project: php-src
File: spl_directory.c

zend_function *spl_filesystem_object_get_method_check(zend_object **object, zend_string *method, const zval *key) /* {{{ */
{
	spl_filesystem_object *fsobj = spl_filesystem_from_obj(*object);

	if (fsobj->u.dir.dirp == NULL && fsobj->orig_path == NULL) {
		zend_function *func;
		zend_string *tmp = zend_string_init("_bad_state_ex", sizeof("_bad_state_ex") - 1, 0);
		func = zend_get_std_object_handlers()->get_method(object, tmp, NULL);
		zend_string_release(tmp);
		return func;
	}

	return zend_get_std_object_handlers()->get_method(object, method, key);
}

Project: php-src
File: spl_directory.c

SPL_METHOD(FilesystemIterator, rewind)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
	int skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS);

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	intern->u.dir.index = 0;
	if (intern->u.dir.dirp) {
		php_stream_rewinddir(intern->u.dir.dirp);
	}
	do {
		spl_filesystem_dir_read(intern);
	} while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name));
}

Project: php-src
File: spl_directory.c

SPL_METHOD(SplFileObject, fscanf)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());

	if(!intern->u.file.stream) {
		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
		return;
	}

	spl_filesystem_file_free_line(intern);
	intern->u.file.current_line_num++;

	FileFunctionCall(fscanf, ZEND_NUM_ARGS(), NULL);
}

Project: php-src
File: spl_directory.c

SPL_METHOD(FilesystemIterator, current)
{
	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());

	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}

	if (SPL_FILE_DIR_CURRENT(intern, SPL_FILE_DIR_CURRENT_AS_PATHNAME)) {
		spl_filesystem_object_get_file_name(intern);
		RETURN_STRINGL(intern->file_name, intern->file_name_len);
	} else if (SPL_FILE_DIR_CURRENT(intern, SPL_FILE_DIR_CURRENT_AS_FILEINFO)) {
		spl_filesystem_object_get_file_name(intern);
		spl_filesystem_object_create_type(0, intern, SPL_FS_INFO, NULL, return_value);
	} else {
		ZVAL_OBJ(return_value, Z_OBJ_P(getThis()));
		Z_ADDREF_P(return_value);
		/*RETURN_STRING(intern->u.dir.entry.d_name, 1);*/
	}
}