From b5b25b1f32ff0b3d9833420b68facc38844b72b0 Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 23 Jan 2016 09:44:41 +0100 Subject: [PATCH] Changed: Add a parameter to CPath::makePathAbsolute to simplify the path (remove all . and ..) --- code/nel/include/nel/misc/path.h | 3 +- code/nel/src/misc/path.cpp | 123 ++++++++++++++++++++++--------- 2 files changed, 92 insertions(+), 34 deletions(-) diff --git a/code/nel/include/nel/misc/path.h b/code/nel/include/nel/misc/path.h index 20ea9b2a9..9c3e2e21b 100644 --- a/code/nel/include/nel/misc/path.h +++ b/code/nel/include/nel/misc/path.h @@ -510,9 +510,10 @@ public: /** Make path absolute * \param relativePath - The relative path * \param directory - the directory to which the path is relative to + * \param simplify - if we should simplify or not the path (convert . and .. in path) * returns the absolute path, or empty if something went wrong. */ - static std::string makePathAbsolute (const std::string &relativePath, const std::string &directory ); + static std::string makePathAbsolute (const std::string &relativePath, const std::string &directory, bool simplify = false ); /** Return if a path is absolute or not. * \param path - The path diff --git a/code/nel/src/misc/path.cpp b/code/nel/src/misc/path.cpp index 7ec61fdd7..4fcaa0459 100644 --- a/code/nel/src/misc/path.cpp +++ b/code/nel/src/misc/path.cpp @@ -2546,55 +2546,112 @@ bool CPath::makePathRelative (const char *basePath, std::string &relativePath) return false; } -std::string CPath::makePathAbsolute( const std::string &relativePath, const std::string &directory ) +std::string CPath::makePathAbsolute( const std::string &relativePath, const std::string &directory, bool simplify ) { if( relativePath.empty() ) return ""; if( directory.empty() ) return ""; + std::string absolutePath; + #ifdef NL_OS_WINDOWS // Windows network address. Eg.: \\someshare\path - if( ( relativePath[ 0 ] == '\\' ) && ( relativePath[ 1 ] == '\\' ) ) - return relativePath; + if ((relativePath[0] == '\\') && (relativePath[1] == '\\')) + { + absolutePath = relativePath; + } // Normal Windows absolute path. Eg.: C:\something // - if( isalpha( relativePath[ 0 ] ) && ( relativePath[ 1 ] == ':' ) && ( ( relativePath[ 2 ] == '\\' ) || ( relativePath[ 2 ] == '/' ) ) ) - return relativePath; + else if (isalpha(relativePath[0]) && (relativePath[1] == ':') && ((relativePath[2] == '\\') || (relativePath[2] == '/'))) + { + absolutePath = relativePath; + } #else // Unix filesystem absolute path - if( relativePath[ 0 ] == '/' ) - return relativePath; - + if (relativePath[0] == '/') + { + absolutePath = relativePath; + } #endif - - // Add a slash to the directory if necessary. - // If the relative path starts with dots we need a slash. - // If the relative path starts with a slash we don't. - // If it starts with neither, we need a slash. - bool needSlash = true; - char c = relativePath[ 0 ]; - if( ( c == '\\' ) || ( c == '/' ) ) - needSlash = false; - - bool hasSlash = false; - std::string npath = directory; - c = npath[ npath.size() - 1 ]; - if( ( c == '\\' ) || ( c == '/' ) ) - hasSlash = true; - - if( needSlash && !hasSlash ) - npath += '/'; else - if( hasSlash && !needSlash ) - npath.resize( npath.size() - 1 ); - - // Now build the new absolute path - npath += relativePath; - npath = standardizePath( npath, false ); + { + // Add a slash to the directory if necessary. + // If the relative path starts with dots we need a slash. + // If the relative path starts with a slash we don't. + // If it starts with neither, we need a slash. + bool needSlash = true; + char c = relativePath[0]; + if ((c == '\\') || (c == '/')) + needSlash = false; - return npath; + bool hasSlash = false; + absolutePath = directory; + c = absolutePath[absolutePath.size() - 1]; + if ((c == '\\') || (c == '/')) + hasSlash = true; + + if (needSlash && !hasSlash) + absolutePath += '/'; + else + if (hasSlash && !needSlash) + absolutePath.resize(absolutePath.size() - 1); + + // Now build the new absolute path + absolutePath += relativePath; + absolutePath = standardizePath(absolutePath, true); + } + + if (simplify) + { + // split all components path to manage parent directories + std::vector tokens; + explode(absolutePath, std::string("/"), tokens, true); + + std::vector directoryParts; + + // process all components + for(uint i = 0, len = tokens.size(); i < len; ++i) + { + std::string token = tokens[i]; + + // current directory + if (token != ".") + { + // parent directory + if (token == "..") + { + // remove last directory + directoryParts.pop_back(); + } + else + { + // append directory + directoryParts.push_back(token); + } + } + } + + if (!directoryParts.empty()) + { + absolutePath = directoryParts[0]; + + // rebuild the whole absolute path + for(uint i = 1, len = directoryParts.size(); i < len; ++i) + absolutePath += "/" + directoryParts[i]; + + // add trailing slash + absolutePath += "/"; + } + else + { + // invalid path + absolutePath.clear(); + } + } + + return absolutePath; } bool CPath::isAbsolutePath(const std::string &path)