VirtualBox

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

Last change on this file since 86728 was 85371, checked in by vboxsync, 4 years ago

DnD: Revamped code to simplify / untangle of internal data handling:

  • C-ifying and renaming classes DnDURIList / DnDURIObject -> DnDTransferList / DnDTransferObject
  • Added testcases for DnDTransferList / DnDTransferObject + DnDPath API
  • Reduced memory footprint
  • Greatly simplified / stripped down internal data flow of Main side
  • More (optional) release logging for further diagnosis

Work in progress.

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette