From 0d02c8607bf239067b14c9bf103fb6457f113149 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Thu, 7 Nov 2024 12:21:18 +0100 Subject: [PATCH] [winpr,path] implement normalize and IsRootOf functions --- winpr/include/winpr/path.h | 42 ++++++++++++++++++++++ winpr/libwinpr/path/path.c | 70 +++++++++++++++++++++++++++++++++++++ winpr/libwinpr/path/shell.c | 61 +++++++++----------------------- 3 files changed, 128 insertions(+), 45 deletions(-) diff --git a/winpr/include/winpr/path.h b/winpr/include/winpr/path.h index 8b8aa90e4..c62264921 100644 --- a/winpr/include/winpr/path.h +++ b/winpr/include/winpr/path.h @@ -342,6 +342,48 @@ extern "C" WINPR_ATTR_MALLOC(free, 1) WINPR_API char* GetCombinedPath(const char* basePath, const char* subPath); + /** @brief creates a normalized version of \b path + * Duplicate path delimiters and '.' in path are removed, '..' is resolved. The normalized + * path does not contain any of these. + * + * @param path The path to normalize + * @return A normalized version of \b path or \b NULL in case of an error + * @since version 3.10.0 + */ + WINPR_ATTR_MALLOC(free, 1) + WINPR_API WCHAR* winpr_NormalizePathW(const WCHAR* path); + + /** @brief creates a normalized version of \b path + * Duplicate path delimiters and '.' in path are removed, '..' is resolved. The normalized + * path does not contain any of these. + * + * @param path The path to normalize + * @return A normalized version of \b path or \b NULL in case of an error + * @since version 3.10.0 + */ + WINPR_ATTR_MALLOC(free, 1) + WINPR_API char* winpr_NormalizePathA(const char* path); + + /** @brief Checks if path \b root is the root of \b path + * Both paths are normalized first and then checked if \b root is a prefix of \b path. + * + * @param root The root path, must be an absolute path. + * @param path The path to check + * @return \b TRUE if \b path has \b root as parent + * @since version 3.10.0 + */ + WINPR_API BOOL winpr_PathIsRootOfA(const char* root, const char* path); + + /** @brief Checks if path \b root is the root of \b path + * Both paths are normalized first and then checked if \b root is a prefix of \b path + * + * @param root The root path, must be an absolute path. + * @param path The path to check + * @return \b TRUE if \b path has \b root as parent + * @since version 3.10.0 + */ + WINPR_API BOOL winpr_PathIsRootOfW(const WCHAR* root, const WCHAR* path); + WINPR_API BOOL PathMakePathA(LPCSTR path, LPSECURITY_ATTRIBUTES lpAttributes); WINPR_API BOOL PathMakePathW(LPCWSTR path, LPSECURITY_ATTRIBUTES lpAttributes); diff --git a/winpr/libwinpr/path/path.c b/winpr/libwinpr/path/path.c index c6929697a..e5500178b 100644 --- a/winpr/libwinpr/path/path.c +++ b/winpr/libwinpr/path/path.c @@ -21,12 +21,15 @@ #include #include +#include #include #include #include #include +#include + #define STR(x) #x #define PATH_SLASH_CHR '/' @@ -1214,3 +1217,70 @@ char* winpr_GetConfigFilePath(BOOL system, const char* filename) return path; } + +char* winpr_NormalizePathA(const char* path) +{ + const size_t rc = cwk_path_normalize(path, NULL, 0); + if (rc == 0) + return NULL; + char* npath = calloc(rc + 2, sizeof(char)); + if (!npath) + return NULL; + const size_t chk = cwk_path_normalize(path, npath, rc + 1); + WINPR_ASSERT(chk == rc); + if (chk != rc) + { + free(npath); + return NULL; + } + return npath; +} + +WCHAR* winpr_NormalizePathW(const WCHAR* path) +{ + char* utf = ConvertWCharToUtf8Alloc(path, NULL); + if (!utf) + return NULL; + char* nutf = winpr_NormalizePathA(utf); + free(utf); + if (!nutf) + return NULL; + WCHAR* wstr = ConvertUtf8ToWCharAlloc(nutf, NULL); + free(nutf); + return wstr; +} + +BOOL winpr_PathIsRootOfA(const char* root, const char* path) +{ + BOOL rc = FALSE; + if (!cwk_path_is_absolute(root)) + return FALSE; + + char* nroot = winpr_NormalizePathA(root); + char* npath = winpr_NormalizePathA(path); + if (npath && nroot) + { + const size_t len = strlen(root); + const size_t ilen = cwk_path_get_intersection(nroot, npath); + rc = len == ilen; + } + free(npath); + free(nroot); + + return rc; +} + +BOOL winpr_PathIsRootOfW(const WCHAR* root, const WCHAR* path) +{ + if (!root || !path) + return FALSE; + + char* utfroot = ConvertWCharToUtf8Alloc(root, NULL); + char* utfpath = ConvertWCharToUtf8Alloc(path, NULL); + BOOL rc = FALSE; + if (utfroot && utfpath) + rc = winpr_PathIsRootOfA(utfroot, utfpath); + free(utfroot); + free(utfpath); + return rc; +} diff --git a/winpr/libwinpr/path/shell.c b/winpr/libwinpr/path/shell.c index 59d93a583..c3b75cb76 100644 --- a/winpr/libwinpr/path/shell.c +++ b/winpr/libwinpr/path/shell.c @@ -19,6 +19,7 @@ */ #include +#include #include #include @@ -26,6 +27,8 @@ #include #include +#include + #include #include #include @@ -447,53 +450,22 @@ char* GetEnvironmentSubPath(char* name, const char* path) char* GetCombinedPath(const char* basePath, const char* subPath) { - size_t length = 0; - HRESULT status = 0; - char* path = NULL; - char* subPathCpy = NULL; - size_t basePathLength = 0; - size_t subPathLength = 0; - - if (basePath) - basePathLength = strlen(basePath); - - if (subPath) - subPathLength = strlen(subPath); - - length = basePathLength + subPathLength + 1; - path = (char*)calloc(1, length + 1); + const size_t len = cwk_path_join(basePath, subPath, NULL, 0); + if (len == 0) + return NULL; + char* path = calloc(len + 2, sizeof(char)); if (!path) - goto fail; + return NULL; - if (basePath) - CopyMemory(path, basePath, basePathLength); - - if (FAILED(PathCchConvertStyleA(path, basePathLength, PATH_STYLE_NATIVE))) - goto fail; - - if (!subPath) - return path; - - subPathCpy = _strdup(subPath); - - if (!subPathCpy) - goto fail; - - if (FAILED(PathCchConvertStyleA(subPathCpy, subPathLength, PATH_STYLE_NATIVE))) - goto fail; - - status = NativePathCchAppendA(path, length + 1, subPathCpy); - if (FAILED(status)) - goto fail; - - free(subPathCpy); + const size_t chk = cwk_path_join(basePath, subPath, path, len + 1); + WINPR_ASSERT(len == chk); + if (len != chk) + { + free(path); + return NULL; + } return path; - -fail: - free(path); - free(subPathCpy); - return NULL; } BOOL PathMakePathA(LPCSTR path, LPSECURITY_ATTRIBUTES lpAttributes) @@ -610,8 +582,7 @@ BOOL PathIsRelativeA(LPCSTR pszPath) { if (!pszPath) return FALSE; - - return pszPath[0] != '/'; + return cwk_path_is_relative(pszPath); } BOOL PathIsRelativeW(LPCWSTR pszPath)