VirtualBox

source: vbox/trunk/src/VBox/GuestHost/DragAndDrop/DnDPath.cpp

Last change on this file was 98103, checked in by vboxsync, 17 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.4 KB
Line 
1/* $Id: DnDPath.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * DnD - Path handling.
4 */
5
6/*
7 * Copyright (C) 2014-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_GUEST_DND
33#include <VBox/GuestHost/DragAndDrop.h>
34
35#include <iprt/dir.h>
36#include <iprt/err.h>
37#include <iprt/file.h>
38#include <iprt/path.h>
39#include <iprt/string.h>
40#include <iprt/uri.h>
41
42
43/**
44 * Sanitizes the file name portion of a path so that unsupported characters will be replaced by an underscore ("_").
45 *
46 * @return IPRT status code.
47 * @param pszFileName File name to sanitize.
48 * @param cbFileName Size (in bytes) of file name to sanitize.
49 */
50int DnDPathSanitizeFileName(char *pszFileName, size_t cbFileName)
51{
52 if (!pszFileName) /* No path given? Bail out early. */
53 return VINF_SUCCESS;
54
55 AssertReturn(cbFileName, VERR_INVALID_PARAMETER);
56
57 int rc = VINF_SUCCESS;
58#ifdef RT_OS_WINDOWS
59 RT_NOREF1(cbFileName);
60 /* Replace out characters not allowed on Windows platforms, put in by RTTimeSpecToString(). */
61 /** @todo Use something like RTPathSanitize() if available later some time. */
62 static const RTUNICP s_uszValidRangePairs[] =
63 {
64 ' ', ' ',
65 '(', ')',
66 '-', '.',
67 '0', '9',
68 'A', 'Z',
69 'a', 'z',
70 '_', '_',
71 0xa0, 0xd7af,
72 '\0'
73 };
74
75 ssize_t cReplaced = RTStrPurgeComplementSet(pszFileName, s_uszValidRangePairs, '_' /* chReplacement */);
76 if (cReplaced < 0)
77 rc = VERR_INVALID_UTF8_ENCODING;
78#else
79 RT_NOREF2(pszFileName, cbFileName);
80#endif
81 return rc;
82}
83
84/**
85 * Validates whether a given path matches our set of rules or not.
86 *
87 * Rules:
88 * - An empty path is allowed.
89 * - Dot components ("." or "..") are forbidden.
90 * - If \a fMustExist is \c true, the path either has to be a file or a directory and must exist.
91 * - Symbolic links are forbidden.
92 *
93 * @returns VBox status code.
94 * @param pcszPath Path to validate.
95 * @param fMustExist Whether the path to validate also must exist.
96 * @sa shClTransferValidatePath().
97 */
98int DnDPathValidate(const char *pcszPath, bool fMustExist)
99{
100 if (!pcszPath)
101 return VERR_INVALID_POINTER;
102
103 int rc = VINF_SUCCESS;
104
105 if ( RT_SUCCESS(rc)
106 && !RTStrIsValidEncoding(pcszPath))
107 {
108 rc = VERR_INVALID_UTF8_ENCODING;
109 }
110
111 if ( RT_SUCCESS(rc)
112 && RTStrStr(pcszPath, ".."))
113 {
114 rc = VERR_INVALID_PARAMETER;
115 }
116
117 if ( RT_SUCCESS(rc)
118 && fMustExist)
119 {
120 RTFSOBJINFO objInfo;
121 rc = RTPathQueryInfo(pcszPath, &objInfo, RTFSOBJATTRADD_NOTHING);
122 if (RT_SUCCESS(rc))
123 {
124 if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode))
125 {
126 if (!RTDirExists(pcszPath)) /* Path must exist. */
127 rc = VERR_PATH_NOT_FOUND;
128 }
129 else if (RTFS_IS_FILE(objInfo.Attr.fMode))
130 {
131 if (!RTFileExists(pcszPath)) /* File must exist. */
132 rc = VERR_FILE_NOT_FOUND;
133 }
134 else /* Everything else (e.g. symbolic links) are not supported. */
135 rc = VERR_NOT_SUPPORTED;
136 }
137 }
138
139 return rc;
140}
141
142/**
143 * Converts a DnD path.
144 *
145 * @returns VBox status code.
146 * @param pszPath Path to convert.
147 * @param cbPath Size (in bytes) of path to convert.
148 * @param fFlags Conversion flags of type DNDPATHCONVERT_FLAGS_.
149 */
150int DnDPathConvert(char *pszPath, size_t cbPath, DNDPATHCONVERTFLAGS fFlags)
151{
152 RT_NOREF(cbPath);
153 AssertReturn(!(fFlags & ~DNDPATHCONVERT_FLAGS_VALID_MASK), VERR_INVALID_FLAGS);
154
155 if (fFlags & DNDPATHCONVERT_FLAGS_TO_DOS)
156 RTPathChangeToDosSlashes(pszPath, true /* fForce */);
157 else
158 RTPathChangeToUnixSlashes(pszPath, true /* fForce */);
159
160 return VINF_SUCCESS;
161}
162
163/**
164 * Rebases an absolute path from an old path base to a new path base.
165 * Note: Does *not* do any path conversion.
166 *
167 * @return IPRT status code.
168 * @param pcszPath Path to rebase.
169 * @param strBaseOld Old base path to rebase from. Optional and can be NULL.
170 * @param strBaseNew New base path to rebase to.
171 * @param ppszPath Where to store the allocated rebased path on success. Needs to be free'd with RTStrFree().
172 */
173int DnDPathRebase(const char *pcszPath, const char *pcszBaseOld, const char *pcszBaseNew,
174 char **ppszPath)
175{
176 AssertPtrReturn(pcszPath, VERR_INVALID_POINTER);
177 AssertPtrReturn(pcszBaseOld, VERR_INVALID_POINTER);
178 AssertPtrReturn(pcszBaseNew, VERR_INVALID_POINTER);
179 AssertPtrReturn(ppszPath, VERR_INVALID_POINTER);
180
181 char szPath[RTPATH_MAX];
182
183 /* Do we need to see if the given path is part of the old base? */
184 size_t idxBase;
185 if ( pcszBaseOld
186 && RTPathStartsWith(pcszPath, pcszBaseOld))
187 {
188 idxBase = strlen(pcszBaseOld);
189 }
190 else
191 idxBase = 0;
192
193 int rc = RTStrCopy(szPath, sizeof(szPath), pcszBaseNew);
194 if (RT_SUCCESS(rc))
195 {
196 rc = RTPathAppend(szPath, sizeof(szPath), &pcszPath[idxBase]);
197 if (RT_SUCCESS(rc))
198 rc = DnDPathValidate(szPath, false /* fMustExist */);
199 }
200
201 if (RT_SUCCESS(rc))
202 {
203 char *pszPath = RTStrDup(szPath);
204 if (pszPath)
205 *ppszPath = pszPath;
206 else
207 rc = VERR_NO_MEMORY;
208 }
209
210 return rc;
211}
212
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use