VirtualBox

source: vbox/trunk/src/VBox/GuestHost/DragAndDrop/DnDURIList.cpp@ 57372

最後變更 在這個檔案從57372是 57372,由 vboxsync 提交於 10 年 前

scm: fixes in previous cleanup run.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 17.3 KB
 
1/* $Id: DnDURIList.cpp 57372 2015-08-14 22:01:25Z vboxsync $ */
2/** @file
3 * DnD: URI list class.
4 */
5
6/*
7 * Copyright (C) 2014-2015 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.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
23#include <iprt/dir.h>
24#include <iprt/file.h>
25#include <iprt/fs.h>
26#include <iprt/path.h>
27#include <iprt/symlink.h>
28#include <iprt/uri.h>
29
30#ifdef LOG_GROUP
31 #undef LOG_GROUP
32#endif
33#define LOG_GROUP LOG_GROUP_GUEST_DND
34#include <VBox/log.h>
35
36#include <VBox/GuestHost/DragAndDrop.h>
37
38DnDURIList::DnDURIList(void)
39 : m_cTotal(0)
40 , m_cbTotal(0)
41{
42}
43
44DnDURIList::~DnDURIList(void)
45{
46 Clear();
47}
48
49int DnDURIList::addEntry(const char *pcszSource, const char *pcszTarget, uint32_t fFlags)
50{
51 AssertPtrReturn(pcszSource, VERR_INVALID_POINTER);
52 AssertPtrReturn(pcszTarget, VERR_INVALID_POINTER);
53
54 LogFlowFunc(("pcszSource=%s, pcszTarget=%s, fFlags=0x%x\n", pcszSource, pcszTarget, fFlags));
55
56 RTFSOBJINFO objInfo;
57 int rc = RTPathQueryInfo(pcszSource, &objInfo, RTFSOBJATTRADD_NOTHING);
58 if (RT_SUCCESS(rc))
59 {
60 if (RTFS_IS_FILE(objInfo.Attr.fMode))
61 {
62 LogFlowFunc(("File '%s' -> '%s' (%RU64)\n", pcszSource, pcszTarget, (uint64_t)objInfo.cbObject));
63
64 DnDURIObject *pObjFile= new DnDURIObject(DnDURIObject::File, pcszSource, pcszTarget);
65 if (pObjFile)
66 {
67 if (fFlags & DNDURILIST_FLAGS_KEEP_OPEN) /* Shall we keep the file open while being added to this list? */
68 {
69 /** @todo Add a standard fOpen mode for this list. */
70 rc = pObjFile->Open(DnDURIObject::Source, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE, objInfo.Attr.fMode);
71 }
72
73 if (RT_SUCCESS(rc))
74 {
75 m_lstTree.append(pObjFile);
76
77 m_cTotal++;
78 m_cbTotal += pObjFile->GetSize();
79 }
80 }
81 else
82 rc = VERR_NO_MEMORY;
83 }
84 else if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode))
85 {
86 LogFlowFunc(("Directory '%s' -> '%s' \n", pcszSource, pcszTarget));
87
88 DnDURIObject *pObjDir= new DnDURIObject(DnDURIObject::Directory, pcszSource, pcszTarget,
89 objInfo.Attr.fMode, 0 /* Size */);
90 if (pObjDir)
91 {
92 m_lstTree.append(pObjDir);
93 }
94 else
95 rc = VERR_NO_MEMORY;
96
97 /** @todo Add DNDURILIST_FLAGS_KEEP_OPEN handling. */
98
99 m_cTotal++;
100 }
101 /* Note: Symlinks already should have been resolved at this point. */
102 else
103 rc = VERR_NOT_SUPPORTED;
104 }
105
106 LogFlowFuncLeaveRC(rc);
107 return rc;
108}
109
110int DnDURIList::appendPathRecursive(const char *pcszSrcPath,
111 const char *pcszDstPath, const char *pcszDstBase, size_t cchDstBase, uint32_t fFlags)
112{
113 AssertPtrReturn(pcszSrcPath, VERR_INVALID_POINTER);
114 AssertPtrReturn(pcszDstBase, VERR_INVALID_POINTER);
115 AssertPtrReturn(pcszDstPath, VERR_INVALID_POINTER);
116
117 LogFlowFunc(("pcszSrcPath=%s, pcszDstPath=%s, pcszDstBase=%s, cchDstBase=%zu\n",
118 pcszSrcPath, pcszDstPath, pcszDstBase, cchDstBase));
119
120 RTFSOBJINFO objInfo;
121 int rc = RTPathQueryInfo(pcszSrcPath, &objInfo, RTFSOBJATTRADD_NOTHING);
122 if (RT_SUCCESS(rc))
123 {
124 if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode))
125 {
126 rc = addEntry(pcszSrcPath, &pcszDstPath[cchDstBase], fFlags);
127
128 PRTDIR hDir;
129 if (RT_SUCCESS(rc))
130 rc = RTDirOpen(&hDir, pcszSrcPath);
131 if (RT_SUCCESS(rc))
132 {
133 do
134 {
135 RTDIRENTRY DirEntry;
136 rc = RTDirRead(hDir, &DirEntry, NULL);
137 if (RT_FAILURE(rc))
138 {
139 if (rc == VERR_NO_MORE_FILES)
140 rc = VINF_SUCCESS;
141 break;
142 }
143
144 switch (DirEntry.enmType)
145 {
146 case RTDIRENTRYTYPE_DIRECTORY:
147 {
148 /* Skip "." and ".." entries. */
149 if ( RTStrCmp(DirEntry.szName, ".") == 0
150 || RTStrCmp(DirEntry.szName, "..") == 0)
151 break;
152
153 char *pszSrc = RTPathJoinA(pcszSrcPath, DirEntry.szName);
154 if (pszSrc)
155 {
156 char *pszDst = RTPathJoinA(pcszDstPath, DirEntry.szName);
157 if (pszDst)
158 {
159 rc = appendPathRecursive(pszSrc, pszDst, pcszDstBase, cchDstBase, fFlags);
160 RTStrFree(pszDst);
161 }
162 else
163 rc = VERR_NO_MEMORY;
164
165 RTStrFree(pszSrc);
166 }
167 else
168 rc = VERR_NO_MEMORY;
169 break;
170 }
171
172 case RTDIRENTRYTYPE_FILE:
173 {
174 char *pszSrc = RTPathJoinA(pcszSrcPath, DirEntry.szName);
175 if (pszSrc)
176 {
177 char *pszDst = RTPathJoinA(pcszDstPath, DirEntry.szName);
178 if (pszDst)
179 {
180 rc = addEntry(pszSrc, &pszDst[cchDstBase], fFlags);
181 RTStrFree(pszDst);
182 }
183 else
184 rc = VERR_NO_MEMORY;
185 RTStrFree(pszSrc);
186 }
187 else
188 rc = VERR_NO_MEMORY;
189 break;
190 }
191 case RTDIRENTRYTYPE_SYMLINK:
192 {
193 if (fFlags & DNDURILIST_FLAGS_RESOLVE_SYMLINKS)
194 {
195 char *pszSrc = RTPathRealDup(pcszDstBase);
196 if (pszSrc)
197 {
198 rc = RTPathQueryInfo(pszSrc, &objInfo, RTFSOBJATTRADD_NOTHING);
199 if (RT_SUCCESS(rc))
200 {
201 if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode))
202 {
203 LogFlowFunc(("Directory entry is symlink to directory\n"));
204 rc = appendPathRecursive(pszSrc, pcszDstPath, pcszDstBase, cchDstBase, fFlags);
205 }
206 else if (RTFS_IS_FILE(objInfo.Attr.fMode))
207 {
208 LogFlowFunc(("Directory entry is symlink to file\n"));
209 rc = addEntry(pszSrc, &pcszDstPath[cchDstBase], fFlags);
210 }
211 else
212 rc = VERR_NOT_SUPPORTED;
213 }
214
215 RTStrFree(pszSrc);
216 }
217 else
218 rc = VERR_NO_MEMORY;
219 }
220 break;
221 }
222
223 default:
224 break;
225 }
226
227 } while (RT_SUCCESS(rc));
228
229 RTDirClose(hDir);
230 }
231 }
232 else if (RTFS_IS_FILE(objInfo.Attr.fMode))
233 {
234 rc = addEntry(pcszSrcPath, &pcszDstPath[cchDstBase], fFlags);
235 }
236 else if (RTFS_IS_SYMLINK(objInfo.Attr.fMode))
237 {
238 if (fFlags & DNDURILIST_FLAGS_RESOLVE_SYMLINKS)
239 {
240 char *pszSrc = RTPathRealDup(pcszSrcPath);
241 if (pszSrc)
242 {
243 rc = RTPathQueryInfo(pszSrc, &objInfo, RTFSOBJATTRADD_NOTHING);
244 if (RT_SUCCESS(rc))
245 {
246 if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode))
247 {
248 LogFlowFunc(("Symlink to directory\n"));
249 rc = appendPathRecursive(pszSrc, pcszDstPath, pcszDstBase, cchDstBase, fFlags);
250 }
251 else if (RTFS_IS_FILE(objInfo.Attr.fMode))
252 {
253 LogFlowFunc(("Symlink to file\n"));
254 rc = addEntry(pszSrc, &pcszDstPath[cchDstBase], fFlags);
255 }
256 else
257 rc = VERR_NOT_SUPPORTED;
258 }
259
260 RTStrFree(pszSrc);
261 }
262 else
263 rc = VERR_NO_MEMORY;
264 }
265 }
266 else
267 rc = VERR_NOT_SUPPORTED;
268 }
269
270 LogFlowFuncLeaveRC(rc);
271 return rc;
272}
273
274int DnDURIList::AppendNativePath(const char *pszPath, uint32_t fFlags)
275{
276 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
277
278 int rc;
279 char *pszPathNative = RTStrDup(pszPath);
280 if (pszPathNative)
281 {
282 RTPathChangeToUnixSlashes(pszPathNative, true /* fForce */);
283
284 char *pszPathURI = RTUriCreate("file" /* pszScheme */, "/" /* pszAuthority */,
285 pszPathNative, NULL /* pszQuery */, NULL /* pszFragment */);
286 if (pszPathURI)
287 {
288 rc = AppendURIPath(pszPathURI, fFlags);
289 RTStrFree(pszPathURI);
290 }
291 else
292 rc = VERR_INVALID_PARAMETER;
293
294 RTStrFree(pszPathNative);
295 }
296 else
297 rc = VERR_NO_MEMORY;
298
299 return rc;
300}
301
302int DnDURIList::AppendNativePathsFromList(const char *pszNativePaths, size_t cbNativePaths,
303 uint32_t fFlags)
304{
305 AssertPtrReturn(pszNativePaths, VERR_INVALID_POINTER);
306 AssertReturn(cbNativePaths, VERR_INVALID_PARAMETER);
307
308 RTCList<RTCString> lstPaths
309 = RTCString(pszNativePaths, cbNativePaths - 1).split("\r\n");
310 return AppendNativePathsFromList(lstPaths, fFlags);
311}
312
313int DnDURIList::AppendNativePathsFromList(const RTCList<RTCString> &lstNativePaths,
314 uint32_t fFlags)
315{
316 int rc = VINF_SUCCESS;
317
318 for (size_t i = 0; i < lstNativePaths.size(); i++)
319 {
320 const RTCString &strPath = lstNativePaths.at(i);
321 rc = AppendNativePath(strPath.c_str(), fFlags);
322 if (RT_FAILURE(rc))
323 break;
324 }
325
326 LogFlowFuncLeaveRC(rc);
327 return rc;
328}
329
330int DnDURIList::AppendURIPath(const char *pszURI, uint32_t fFlags)
331{
332 AssertPtrReturn(pszURI, VERR_INVALID_POINTER);
333
334 /** @todo Check for string termination? */
335#ifdef DEBUG_andy
336 LogFlowFunc(("pszPath=%s, fFlags=0x%x\n", pszURI, fFlags));
337#endif
338 int rc = VINF_SUCCESS;
339
340 /* Query the path component of a file URI. If this hasn't a
341 * file scheme NULL is returned. */
342 char *pszSrcPath = RTUriFilePath(pszURI, URI_FILE_FORMAT_AUTO);
343 if (pszSrcPath)
344 {
345 /* Add the path to our internal file list (recursive in
346 * the case of a directory). */
347 size_t cbPathLen = RTPathStripTrailingSlash(pszSrcPath);
348 if (cbPathLen)
349 {
350 char *pszFileName = RTPathFilename(pszSrcPath);
351 if (pszFileName)
352 {
353 Assert(pszFileName >= pszSrcPath);
354 size_t cchDstBase = (fFlags & DNDURILIST_FLAGS_ABSOLUTE_PATHS)
355 ? 0 /* Use start of path as root. */
356 : pszFileName - pszSrcPath;
357 char *pszDstPath = &pszSrcPath[cchDstBase];
358 m_lstRoot.append(pszDstPath);
359
360 LogFlowFunc(("pszFilePath=%s, pszFileName=%s, pszRoot=%s\n",
361 pszSrcPath, pszFileName, pszDstPath));
362
363 rc = appendPathRecursive(pszSrcPath, pszSrcPath, pszSrcPath, cchDstBase, fFlags);
364 }
365 else
366 rc = VERR_PATH_NOT_FOUND;
367 }
368 else
369 rc = VERR_INVALID_PARAMETER;
370
371 RTStrFree(pszSrcPath);
372 }
373 else
374 rc = VERR_INVALID_PARAMETER;
375
376 LogFlowFuncLeaveRC(rc);
377 return rc;
378}
379
380int DnDURIList::AppendURIPathsFromList(const char *pszURIPaths, size_t cbURIPaths,
381 uint32_t fFlags)
382{
383 AssertPtrReturn(pszURIPaths, VERR_INVALID_POINTER);
384 AssertReturn(cbURIPaths, VERR_INVALID_PARAMETER);
385
386 RTCList<RTCString> lstPaths
387 = RTCString(pszURIPaths, cbURIPaths - 1).split("\r\n");
388 return AppendURIPathsFromList(lstPaths, fFlags);
389}
390
391int DnDURIList::AppendURIPathsFromList(const RTCList<RTCString> &lstURI,
392 uint32_t fFlags)
393{
394 int rc = VINF_SUCCESS;
395
396 for (size_t i = 0; i < lstURI.size(); i++)
397 {
398 RTCString strURI = lstURI.at(i);
399 rc = AppendURIPath(strURI.c_str(), fFlags);
400
401 if (RT_FAILURE(rc))
402 break;
403 }
404
405 LogFlowFuncLeaveRC(rc);
406 return rc;
407}
408
409void DnDURIList::Clear(void)
410{
411 m_lstRoot.clear();
412
413 for (size_t i = 0; i < m_lstTree.size(); i++)
414 {
415 DnDURIObject *pCurObj = m_lstTree.at(i);
416 AssertPtr(pCurObj);
417 RTMemFree(pCurObj);
418 }
419 m_lstTree.clear();
420
421 m_cTotal = 0;
422 m_cbTotal = 0;
423}
424
425void DnDURIList::RemoveFirst(void)
426{
427 if (m_lstTree.isEmpty())
428 return;
429
430 DnDURIObject *pCurObj = m_lstTree.first();
431 AssertPtr(pCurObj);
432
433 uint64_t cbSize = pCurObj->GetSize();
434 Assert(m_cbTotal >= cbSize);
435 m_cbTotal -= cbSize; /* Adjust total size. */
436
437 pCurObj->Close();
438 RTMemFree(pCurObj);
439
440 m_lstTree.removeFirst();
441}
442
443int DnDURIList::RootFromURIData(const void *pvData, size_t cbData, uint32_t fFlags)
444{
445 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
446 AssertReturn(cbData, VERR_INVALID_PARAMETER);
447
448 RTCList<RTCString> lstURI =
449 RTCString(static_cast<const char*>(pvData), cbData - 1).split("\r\n");
450 if (lstURI.isEmpty())
451 return VINF_SUCCESS;
452
453 int rc = VINF_SUCCESS;
454
455 for (size_t i = 0; i < lstURI.size(); ++i)
456 {
457 /* Query the path component of a file URI. If this hasn't a
458 * file scheme, NULL is returned. */
459 const char *pszURI = lstURI.at(i).c_str();
460 char *pszFilePath = RTUriFilePath(pszURI,
461 URI_FILE_FORMAT_AUTO);
462#ifdef DEBUG_andy
463 LogFlowFunc(("pszURI=%s, pszFilePath=%s\n", pszURI, pszFilePath));
464#endif
465 if (pszFilePath)
466 {
467 rc = DnDPathSanitize(pszFilePath, strlen(pszFilePath));
468 if (RT_SUCCESS(rc))
469 {
470 m_lstRoot.append(pszFilePath);
471 m_cTotal++;
472 }
473
474 RTStrFree(pszFilePath);
475 }
476 else
477 rc = VERR_INVALID_PARAMETER;
478
479 if (RT_FAILURE(rc))
480 break;
481 }
482
483 return rc;
484}
485
486RTCString DnDURIList::RootToString(const RTCString &strPathBase /* = "" */,
487 const RTCString &strSeparator /* = "\r\n" */)
488{
489 RTCString strRet;
490 for (size_t i = 0; i < m_lstRoot.size(); i++)
491 {
492 const char *pszCurRoot = m_lstRoot.at(i).c_str();
493#ifdef DEBUG_andy
494 LogFlowFunc(("pszCurRoot=%s\n", pszCurRoot));
495#endif
496 if (strPathBase.isNotEmpty())
497 {
498 char *pszPath = RTPathJoinA(strPathBase.c_str(), pszCurRoot);
499 if (pszPath)
500 {
501 char *pszPathURI = RTUriFileCreate(pszPath);
502 if (pszPathURI)
503 {
504 strRet += RTCString(pszPathURI) + strSeparator;
505 LogFlowFunc(("URI: %s\n", strRet.c_str()));
506 RTStrFree(pszPathURI);
507 }
508
509 RTStrFree(pszPath);
510
511 if (!pszPathURI)
512 break;
513 }
514 else
515 break;
516 }
517 else
518 {
519 char *pszPathURI = RTUriFileCreate(pszCurRoot);
520 if (pszPathURI)
521 {
522 strRet += RTCString(pszPathURI) + strSeparator;
523 LogFlowFunc(("URI: %s\n", strRet.c_str()));
524 RTStrFree(pszPathURI);
525 }
526 else
527 break;
528 }
529 }
530
531 return strRet;
532}
533
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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