From f215e02bf85f68d3a6106c2a1f4f7f063f819064 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:17:27 +0200 Subject: Adding upstream version 7.0.14-dfsg. Signed-off-by: Daniel Baumann --- src/VBox/GuestHost/DragAndDrop/DnDPath.cpp | 212 +++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 src/VBox/GuestHost/DragAndDrop/DnDPath.cpp (limited to 'src/VBox/GuestHost/DragAndDrop/DnDPath.cpp') diff --git a/src/VBox/GuestHost/DragAndDrop/DnDPath.cpp b/src/VBox/GuestHost/DragAndDrop/DnDPath.cpp new file mode 100644 index 00000000..e4ac219e --- /dev/null +++ b/src/VBox/GuestHost/DragAndDrop/DnDPath.cpp @@ -0,0 +1,212 @@ +/* $Id: DnDPath.cpp $ */ +/** @file + * DnD - Path handling. + */ + +/* + * Copyright (C) 2014-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define LOG_GROUP LOG_GROUP_GUEST_DND +#include + +#include +#include +#include +#include +#include +#include + + +/** + * Sanitizes the file name portion of a path so that unsupported characters will be replaced by an underscore ("_"). + * + * @return IPRT status code. + * @param pszFileName File name to sanitize. + * @param cbFileName Size (in bytes) of file name to sanitize. + */ +int DnDPathSanitizeFileName(char *pszFileName, size_t cbFileName) +{ + if (!pszFileName) /* No path given? Bail out early. */ + return VINF_SUCCESS; + + AssertReturn(cbFileName, VERR_INVALID_PARAMETER); + + int rc = VINF_SUCCESS; +#ifdef RT_OS_WINDOWS + RT_NOREF1(cbFileName); + /* Replace out characters not allowed on Windows platforms, put in by RTTimeSpecToString(). */ + /** @todo Use something like RTPathSanitize() if available later some time. */ + static const RTUNICP s_uszValidRangePairs[] = + { + ' ', ' ', + '(', ')', + '-', '.', + '0', '9', + 'A', 'Z', + 'a', 'z', + '_', '_', + 0xa0, 0xd7af, + '\0' + }; + + ssize_t cReplaced = RTStrPurgeComplementSet(pszFileName, s_uszValidRangePairs, '_' /* chReplacement */); + if (cReplaced < 0) + rc = VERR_INVALID_UTF8_ENCODING; +#else + RT_NOREF2(pszFileName, cbFileName); +#endif + return rc; +} + +/** + * Validates whether a given path matches our set of rules or not. + * + * Rules: + * - An empty path is allowed. + * - Dot components ("." or "..") are forbidden. + * - If \a fMustExist is \c true, the path either has to be a file or a directory and must exist. + * - Symbolic links are forbidden. + * + * @returns VBox status code. + * @param pcszPath Path to validate. + * @param fMustExist Whether the path to validate also must exist. + * @sa shClTransferValidatePath(). + */ +int DnDPathValidate(const char *pcszPath, bool fMustExist) +{ + if (!pcszPath) + return VERR_INVALID_POINTER; + + int rc = VINF_SUCCESS; + + if ( RT_SUCCESS(rc) + && !RTStrIsValidEncoding(pcszPath)) + { + rc = VERR_INVALID_UTF8_ENCODING; + } + + if ( RT_SUCCESS(rc) + && RTStrStr(pcszPath, "..")) + { + rc = VERR_INVALID_PARAMETER; + } + + if ( RT_SUCCESS(rc) + && fMustExist) + { + RTFSOBJINFO objInfo; + rc = RTPathQueryInfo(pcszPath, &objInfo, RTFSOBJATTRADD_NOTHING); + if (RT_SUCCESS(rc)) + { + if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode)) + { + if (!RTDirExists(pcszPath)) /* Path must exist. */ + rc = VERR_PATH_NOT_FOUND; + } + else if (RTFS_IS_FILE(objInfo.Attr.fMode)) + { + if (!RTFileExists(pcszPath)) /* File must exist. */ + rc = VERR_FILE_NOT_FOUND; + } + else /* Everything else (e.g. symbolic links) are not supported. */ + rc = VERR_NOT_SUPPORTED; + } + } + + return rc; +} + +/** + * Converts a DnD path. + * + * @returns VBox status code. + * @param pszPath Path to convert. + * @param cbPath Size (in bytes) of path to convert. + * @param fFlags Conversion flags of type DNDPATHCONVERT_FLAGS_. + */ +int DnDPathConvert(char *pszPath, size_t cbPath, DNDPATHCONVERTFLAGS fFlags) +{ + RT_NOREF(cbPath); + AssertReturn(!(fFlags & ~DNDPATHCONVERT_FLAGS_VALID_MASK), VERR_INVALID_FLAGS); + + if (fFlags & DNDPATHCONVERT_FLAGS_TO_DOS) + RTPathChangeToDosSlashes(pszPath, true /* fForce */); + else + RTPathChangeToUnixSlashes(pszPath, true /* fForce */); + + return VINF_SUCCESS; +} + +/** + * Rebases an absolute path from an old path base to a new path base. + * Note: Does *not* do any path conversion. + * + * @return IPRT status code. + * @param pcszPath Path to rebase. + * @param strBaseOld Old base path to rebase from. Optional and can be NULL. + * @param strBaseNew New base path to rebase to. + * @param ppszPath Where to store the allocated rebased path on success. Needs to be free'd with RTStrFree(). + */ +int DnDPathRebase(const char *pcszPath, const char *pcszBaseOld, const char *pcszBaseNew, + char **ppszPath) +{ + AssertPtrReturn(pcszPath, VERR_INVALID_POINTER); + AssertPtrReturn(pcszBaseOld, VERR_INVALID_POINTER); + AssertPtrReturn(pcszBaseNew, VERR_INVALID_POINTER); + AssertPtrReturn(ppszPath, VERR_INVALID_POINTER); + + char szPath[RTPATH_MAX]; + + /* Do we need to see if the given path is part of the old base? */ + size_t idxBase; + if ( pcszBaseOld + && RTPathStartsWith(pcszPath, pcszBaseOld)) + { + idxBase = strlen(pcszBaseOld); + } + else + idxBase = 0; + + int rc = RTStrCopy(szPath, sizeof(szPath), pcszBaseNew); + if (RT_SUCCESS(rc)) + { + rc = RTPathAppend(szPath, sizeof(szPath), &pcszPath[idxBase]); + if (RT_SUCCESS(rc)) + rc = DnDPathValidate(szPath, false /* fMustExist */); + } + + if (RT_SUCCESS(rc)) + { + char *pszPath = RTStrDup(szPath); + if (pszPath) + *ppszPath = pszPath; + else + rc = VERR_NO_MEMORY; + } + + return rc; +} + -- cgit v1.2.3