From 42742bacede7ecfbf8e87651bdbf9dee14ec6a87 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Wed, 19 Aug 2015 07:54:06 +0200 Subject: [PATCH] Fix: Utility::Glob on Windows doesn't support wildcards in all but the last path component fixes #9962 --- lib/base/utility.cpp | 79 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 63 insertions(+), 16 deletions(-) diff --git a/lib/base/utility.cpp b/lib/base/utility.cpp index 6287920aa..478b40555 100644 --- a/lib/base/utility.cpp +++ b/lib/base/utility.cpp @@ -387,18 +387,9 @@ String Utility::NewUniqueID(void) return id; } -/** - * Calls the specified callback for each file matching the path specification. - * - * @param pathSpec The path specification. - * @param callback The callback which is invoked for each matching file. - * @param type The file type (a combination of GlobFile and GlobDirectory) - */ -bool Utility::Glob(const String& pathSpec, const boost::function& callback, int type) -{ - std::vector files, dirs; - #ifdef _WIN32 +static bool GlobHelper(const String& pathSpec, int type, std::vector& files, std::vector& dirs) +{ HANDLE handle; WIN32_FIND_DATA wfd; @@ -411,16 +402,16 @@ bool Utility::Glob(const String& pathSpec, const boost::function& callback, int type) +{ + std::vector files, dirs; + +#ifdef _WIN32 + std::vector tokens; + boost::algorithm::split(tokens, pathSpec, boost::is_any_of("\\/")); + + String part1; + + for (std::vector::size_type i = 0; i < tokens.size() - 1; i++) { + const String& token = tokens[i]; + + if (!part1.IsEmpty()) + part1 += "/"; + + part1 += token; + + if (token.FindFirstOf("?*") != String::NPos) { + String part2; + + for (std::vector::size_type k = i + 1; k < tokens.size(); k++) { + if (!part2.IsEmpty()) + part2 += "/"; + + part2 += tokens[k]; + } + + std::vector files2, dirs2; + + if (!GlobHelper(part1, GlobDirectory, files2, dirs2)) + return false; + + BOOST_FOREACH(const String& dir, dirs2) { + if (!Utility::Glob(dir + "/" + part2, callback, type)) + return false; + } + + return true; + } + } + + if (!GlobHelper(part1 + "/" + tokens[tokens.size() - 1], type, files, dirs)) + return false; #else /* _WIN32 */ glob_t gr;