- Timestamp:
- Jul 30, 2020 6:53:40 AM (4 years ago)
- Location:
- trunk/src/VBox/GuestHost/DragAndDrop
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/GuestHost/DragAndDrop/DnDTransferList.cpp
r85462 r85535 16 16 */ 17 17 18 /** 19 * This implementation is taylored to keeping track of a single DnD transfer by maintaining two separate entities, 20 * namely a list of root entries and a list of (recursive file system) transfer ojects to actually transfer. 21 * 22 * The list of root entries is sent to the target (guest/host) beforehand so that the OS has a data for the 23 * actual drag'n drop operation to work with. This also contains required header data like total number of 24 * objects or total bytes being received. 25 * 26 * The list of transfer objects only is needed in order to sending data from the source to the target. 27 * Currently there is no particular ordering implemented for the transfer object list; it depends on IPRT's RTDirRead(). 28 * 29 * The target must not know anything about the actual (absolute) path the root entries are coming from 30 * due to security reasons. Those root entries then can be re-based on the target to desired location there. 31 * 32 * All data handling internally is done in the so-called "transport" format, that is, non-URI (regular) paths 33 * with the "/" as path separator. From/to URI conversion is provided for convenience only. 34 */ 18 35 19 36 /********************************************************************************************************************************* … … 41 58 static int dndTransferListSetRootPath(PDNDTRANSFERLIST pList, const char *pcszRootPathAbs); 42 59 43 static int dndTransferListRoot Add(PDNDTRANSFERLIST pList, const char *pcszRoot);44 static void dndTransferListRoot Free(PDNDTRANSFERLIST pList, PDNDTRANSFERLISTROOT pRootObj);60 static int dndTransferListRootEntryAdd(PDNDTRANSFERLIST pList, const char *pcszRoot); 61 static void dndTransferListRootEntryFree(PDNDTRANSFERLIST pList, PDNDTRANSFERLISTROOT pRootObj); 45 62 46 63 static int dndTransferListObjAdd(PDNDTRANSFERLIST pList, const char *pcszSrcAbs, RTFMODE fMode, DNDTRANSFERLISTFLAGS fFlags); … … 87 104 * @returns VBox status code. 88 105 * @param pList Transfer list to initialize. 89 * @param pcszRootPathAbs Absolute root path to use for this list. Optional and can be NULL. 90 */ 91 int DnDTransferListInitEx(PDNDTRANSFERLIST pList, const char *pcszRootPathAbs) 92 { 93 return dndTransferListInitInternal(pList, pcszRootPathAbs); 106 * @param pcszRootPathAbs Absolute root path to use for this list. 107 * @param enmFmt Format of \a pcszRootPathAbs. 108 */ 109 int DnDTransferListInitEx(PDNDTRANSFERLIST pList, const char *pcszRootPathAbs, DNDTRANSFERLISTFMT enmFmt) 110 { 111 AssertPtrReturn(pList, VERR_INVALID_POINTER); 112 AssertPtrReturn(pcszRootPathAbs, VERR_INVALID_POINTER); 113 AssertReturn(*pcszRootPathAbs, VERR_INVALID_PARAMETER); 114 115 int rc; 116 117 if (enmFmt == DNDTRANSFERLISTFMT_URI) 118 { 119 char *pszPath; 120 rc = RTUriFilePathEx(pcszRootPathAbs, RTPATH_STR_F_STYLE_UNIX, &pszPath, 0 /*cbPath*/, NULL /*pcchPath*/); 121 if (RT_SUCCESS(rc)) 122 { 123 rc = dndTransferListInitInternal(pList, pszPath); 124 RTStrFree(pszPath); 125 } 126 } 127 else 128 rc = dndTransferListInitInternal(pList, pcszRootPathAbs); 129 130 return rc; 94 131 } 95 132 … … 122 159 123 160 /** 161 * Initializes a transfer list and sets the root path. 162 * 163 * Convenience function which calls dndTransferListInitInternal() if not initialized already. 164 * 165 * @returns VBox status code. 166 * @param pList List to determine root path for. 167 * @param pcszRootPathAbs Root path to use. 168 */ 169 static int dndTransferInitAndSetRoot(PDNDTRANSFERLIST pList, const char *pcszRootPathAbs) 170 { 171 int rc; 172 173 if (!pList->pszPathRootAbs) 174 { 175 rc = dndTransferListInitInternal(pList, pcszRootPathAbs); 176 AssertRCReturn(rc, rc); 177 178 LogRel2(("DnD: Determined root path is '%s'\n", pList->pszPathRootAbs)); 179 } 180 else 181 rc = VINF_SUCCESS; 182 183 return rc; 184 } 185 186 /** 124 187 * Resets a transfer list to its initial state. 125 188 * … … 138 201 PDNDTRANSFERLISTROOT pRootCur, pRootNext; 139 202 RTListForEachSafe(&pList->lstRoot, pRootCur, pRootNext, DNDTRANSFERLISTROOT, Node) 140 dndTransferListRoot Free(pList, pRootCur);203 dndTransferListRootEntryFree(pList, pRootCur); 141 204 Assert(RTListIsEmpty(&pList->lstRoot)); 142 205 … … 406 469 PRTFSOBJINFO pObjInfo, DNDTRANSFERLISTFLAGS fFlags) 407 470 { 408 RTDIR hDir; 409 int rc = RTDirOpen(&hDir, pszPathAbs); 410 AssertRCReturn(rc, rc); 471 const size_t cchPathRoot = RTStrNLen(pList->pszPathRootAbs, RTPATH_MAX); 472 AssertReturn(cchPathRoot, VERR_INVALID_PARAMETER); 411 473 412 474 const size_t cchPathAbs = RTPathEnsureTrailingSeparator(pszPathAbs, sizeof(cbPathAbs)); 413 475 AssertReturn(cchPathAbs, VERR_BUFFER_OVERFLOW); 414 415 rc = dndTransferListObjAdd(pList, pszPathAbs, pObjInfo->Attr.fMode, fFlags); 476 AssertReturn(cchPathAbs >= cchPathRoot, VERR_BUFFER_UNDERFLOW); 477 478 const bool fPathIsRoot = cchPathAbs == cchPathRoot; 479 480 int rc; 481 482 if (!fPathIsRoot) 483 { 484 rc = dndTransferListObjAdd(pList, pszPathAbs, pObjInfo->Attr.fMode, fFlags); 485 AssertRCReturn(rc, rc); 486 } 487 488 RTDIR hDir; 489 rc = RTDirOpen(&hDir, pszPathAbs); 416 490 AssertRCReturn(rc, rc); 417 491 … … 458 532 break; 459 533 } 534 535 if ( RT_SUCCESS(rc) 536 /* Make sure to add a root entry if we're processing the root path at the moment. */ 537 && fPathIsRoot) 538 { 539 rc = dndTransferListRootEntryAdd(pList, pszPathAbs); 540 } 460 541 } 461 542 else if (rc == VERR_NO_MORE_FILES) … … 518 599 } 519 600 520 rc = dndTransferListRootAdd(pList, szPathAbs); 601 const size_t cchPathRoot = RTStrNLen(pList->pszPathRootAbs, RTPATH_MAX); 602 AssertStmt(cchPathRoot, rc = VERR_INVALID_PARAMETER); 603 604 if ( RT_SUCCESS(rc) 605 && cchPathAbs > cchPathRoot) 606 rc = dndTransferListRootEntryAdd(pList, szPathAbs); 521 607 } 522 608 else … … 570 656 /* Query the path component of a file URI. If this hasn't a 571 657 * file scheme, NULL is returned. */ 572 char *psz FilePath;573 int rc = RTUriFilePathEx(pcszPath, RTPATH_STR_F_STYLE_UNIX, &psz FilePath, 0 /*cbPath*/, NULL /*pcchPath*/);658 char *pszPath; 659 int rc = RTUriFilePathEx(pcszPath, RTPATH_STR_F_STYLE_UNIX, &pszPath, 0 /*cbPath*/, NULL /*pcchPath*/); 574 660 if (RT_SUCCESS(rc)) 575 661 { 576 LogFlowFunc(("pcszPath=%s -> pszFilePath=%s\n", pcszPath, pszFilePath)); 577 rc = dndTransferListRootAdd(pList, pszFilePath); 578 RTStrFree(pszFilePath); 579 662 rc = dndTransferListAppendPathNative(pList, pszPath, fFlags); 663 RTStrFree(pszPath); 580 664 } 581 665 … … 717 801 if (pszRootPath) 718 802 { 719 LogRel2(("DnD: Determined root path is '%s'\n", pszRootPath)); 720 rc = dndTransferListInitInternal(pList, pszRootPath); 803 rc = dndTransferInitAndSetRoot(pList, pszRootPath); 721 804 RTStrFree(pszRootPath); 722 805 } … … 849 932 AssertRCBreak(rc); 850 933 851 rc = dndTransferListRoot Add(pList, szPath);934 rc = dndTransferListRootEntryAdd(pList, szPath); 852 935 if (RT_FAILURE(rc)) 853 936 { … … 1111 1194 RTPathEnsureTrailingSeparatorEx(szRootPath, sizeof(szRootPath), RTPATH_STR_F_STYLE_HOST); 1112 1195 1113 pList->pszPathRootAbs = RTStrDup(szRootPath); 1114 if (pList->pszPathRootAbs) 1115 { 1116 LogFlowFunc(("Root path is '%s'\n", pList->pszPathRootAbs)); 1117 } 1118 else 1119 rc = VERR_NO_MEMORY; 1196 /* Make sure the root path is a directory (and no symlink or stuff). */ 1197 RTFSOBJINFO objInfo; 1198 rc = RTPathQueryInfo(szRootPath, &objInfo, RTFSOBJATTRADD_NOTHING); 1199 if (RT_SUCCESS(rc)) 1200 { 1201 if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode & RTFS_TYPE_MASK)) 1202 { 1203 pList->pszPathRootAbs = RTStrDup(szRootPath); 1204 if (pList->pszPathRootAbs) 1205 { 1206 LogFlowFunc(("Root path is '%s'\n", pList->pszPathRootAbs)); 1207 } 1208 else 1209 rc = VERR_NO_MEMORY; 1210 } 1211 else 1212 rc = VERR_NOT_A_DIRECTORY; 1213 } 1120 1214 1121 1215 return rc; … … 1129 1223 * @param pcszRoot Root entry to add. 1130 1224 */ 1131 static int dndTransferListRoot Add(PDNDTRANSFERLIST pList, const char *pcszRoot)1225 static int dndTransferListRootEntryAdd(PDNDTRANSFERLIST pList, const char *pcszRoot) 1132 1226 { 1133 1227 AssertPtrReturn(pList->pszPathRootAbs, VERR_WRONG_ORDER); /* The list's root path must be set first. */ … … 1177 1271 * @param pRootObj Transfer list root to free. The pointer will be invalid after calling. 1178 1272 */ 1179 static void dndTransferListRoot Free(PDNDTRANSFERLIST pList, PDNDTRANSFERLISTROOT pRootObj)1273 static void dndTransferListRootEntryFree(PDNDTRANSFERLIST pList, PDNDTRANSFERLISTROOT pRootObj) 1180 1274 { 1181 1275 if (!pRootObj) -
trunk/src/VBox/GuestHost/DragAndDrop/testcase/tstDnDTransferList.cpp
r85428 r85535 40 40 RTStrCopy(szPathWellKnown, sizeof(szPathWellKnown), 41 41 #ifdef RT_OS_WINDOWS 42 "C:\\Windows\\ INF\\");42 "C:\\Windows\\System32\\Boot\\"); 43 43 #else 44 44 "/bin/"); 45 45 #endif 46 47 char szPathWellKnownURI[RTPATH_MAX]; 48 RTStrPrintf(szPathWellKnownURI, sizeof(szPathWellKnownURI), "file:///%s", szPathWellKnown); 46 49 47 50 DNDTRANSFERLIST list; … … 49 52 50 53 /* Invalid stuff. */ 51 RTTEST_CHECK_RC(hTest, DnDTransferListInitEx(&list, "" ), VERR_INVALID_PARAMETER);52 RTTEST_CHECK_RC(hTest, DnDTransferListInitEx(&list, szPathWellKnown ), VINF_SUCCESS);53 RTTEST_CHECK_RC(hTest, DnDTransferListInitEx(&list, szPathWellKnown ), VERR_WRONG_ORDER);54 RTTEST_CHECK_RC(hTest, DnDTransferListInitEx(&list, "", DNDTRANSFERLISTFMT_NATIVE), VERR_INVALID_PARAMETER); 55 RTTEST_CHECK_RC(hTest, DnDTransferListInitEx(&list, szPathWellKnown, DNDTRANSFERLISTFMT_NATIVE), VINF_SUCCESS); 56 RTTEST_CHECK_RC(hTest, DnDTransferListInitEx(&list, szPathWellKnown, DNDTRANSFERLISTFMT_NATIVE), VERR_WRONG_ORDER); 54 57 DnDTransferListDestroy(&list); 55 58 … … 59 62 60 63 /* Initial status. */ 61 RTTEST_CHECK_RC(hTest, DnDTransferListInitEx(&list, szPathWellKnown ), VINF_SUCCESS);64 RTTEST_CHECK_RC(hTest, DnDTransferListInitEx(&list, szPathWellKnown, DNDTRANSFERLISTFMT_NATIVE), VINF_SUCCESS); 62 65 RTTEST_CHECK(hTest, DnDTransferListGetRootCount(&list) == 0); 63 66 RTTEST_CHECK(hTest, DnDTransferListObjCount(&list) == 0); 64 67 RTTEST_CHECK(hTest, DnDTransferListObjTotalBytes(&list) == 0); 65 68 RTTEST_CHECK(hTest, DnDTransferListObjGetFirst(&list) == NULL); 69 DnDTransferListDestroy(&list); 66 70 67 71 char szPathTest[RTPATH_MAX]; 68 72 69 73 /* Root path handling. */ 74 RTTEST_CHECK_RC(hTest, DnDTransferListInitEx(&list, szPathWellKnown, DNDTRANSFERLISTFMT_NATIVE), VINF_SUCCESS); 70 75 RTTEST_CHECK_RC(hTest, DnDTransferListAppendPath(&list, DNDTRANSFERLISTFMT_NATIVE, "/wrong/root/path", DNDTRANSFERLIST_FLAGS_NONE), VERR_INVALID_PARAMETER); 71 76 rc = RTPathJoin(szPathTest, sizeof(szPathTest), szPathWellKnown, "/non/existing"); 72 77 AssertRCReturn(rc, RTEXITCODE_FAILURE); 73 78 RTTEST_CHECK_RC(hTest, DnDTransferListAppendPath(&list, DNDTRANSFERLISTFMT_NATIVE, szPathTest, DNDTRANSFERLIST_FLAGS_NONE), VERR_PATH_NOT_FOUND); 79 DnDTransferListDestroy(&list); 74 80 75 /* Adding stuff. */ 81 /* Adding native stuff. */ 82 /* No root path set yet and non-recursive -> will set root path to szPathWellKnown, but without any entries added. */ 83 RTTEST_CHECK_RC(hTest, DnDTransferListInitEx(&list, szPathWellKnown, DNDTRANSFERLISTFMT_NATIVE), VINF_SUCCESS); 84 RTTEST_CHECK_RC(hTest, DnDTransferListAppendPath(&list, DNDTRANSFERLISTFMT_NATIVE, szPathWellKnown, DNDTRANSFERLIST_FLAGS_NONE), VINF_SUCCESS); 85 RTTEST_CHECK(hTest, DnDTransferListGetRootCount(&list)); 86 RTTEST_CHECK(hTest, DnDTransferListObjCount(&list)); 87 88 /* Add szPathWellKnown again, this time recursively. */ 76 89 RTTEST_CHECK_RC(hTest, DnDTransferListAppendPath(&list, DNDTRANSFERLISTFMT_NATIVE, szPathWellKnown, DNDTRANSFERLIST_FLAGS_RECURSIVE), VINF_SUCCESS); 77 90 RTTEST_CHECK(hTest, DnDTransferListGetRootCount(&list)); … … 81 94 size_t cbString = 0; 82 95 RTTEST_CHECK_RC_OK(hTest, DnDTransferListGetRoots(&list, DNDTRANSFERLISTFMT_NATIVE, &pszString, &cbString)); 83 RTTestPrintf(hTest, RTTESTLVL_DEBUG, "Root : %s\n", pszString);96 RTTestPrintf(hTest, RTTESTLVL_DEBUG, "Roots:\n%s\n\n", pszString); 84 97 RTStrFree(pszString); 85 RTTestPrintf(hTest, RTTESTLVL_DEBUG, "\n");86 98 87 99 PDNDTRANSFEROBJECT pObj; … … 97 109 98 110 /* To URI data. */ 99 RTTEST_CHECK_RC(hTest, DnDTransferListInitEx(&list, szPathWellKnown), VINF_SUCCESS); 100 RTTEST_CHECK_RC(hTest, DnDTransferListAppendPath(&list, DNDTRANSFERLISTFMT_NATIVE, szPathWellKnown, DNDTRANSFERLIST_FLAGS_NONE), VINF_SUCCESS); 111 RTTEST_CHECK_RC(hTest, DnDTransferListInitEx(&list, szPathWellKnownURI, DNDTRANSFERLISTFMT_URI), VINF_SUCCESS); 112 RTStrPrintf(szPathTest, sizeof(szPathTest), "%s/foo", szPathWellKnownURI); 113 RTTEST_CHECK_RC(hTest, DnDTransferListAppendPath(&list, DNDTRANSFERLISTFMT_URI, szPathWellKnownURI, DNDTRANSFERLIST_FLAGS_NONE), VINF_SUCCESS); 114 RTTEST_CHECK_RC(hTest, DnDTransferListAppendPath(&list, DNDTRANSFERLISTFMT_URI, szPathTest, DNDTRANSFERLIST_FLAGS_NONE), VERR_FILE_NOT_FOUND); 101 115 RTTEST_CHECK_RC(hTest, DnDTransferListGetRootsEx(&list, DNDTRANSFERLISTFMT_NATIVE, "" /* pszBasePath */, "\n", &pszBuf, &cbBuf), VINF_SUCCESS); 102 116 RTTestPrintf(hTest, RTTESTLVL_DEBUG, "Roots (native):\n%s\n", pszBuf); … … 112 126 113 127 /* From URI data. */ 114 const char szURI[] = "file:///file1\r\n" 115 "file:///file2\r\n" 116 "file:///dir1\r\n" 117 "file:///dir%20with%20spaces\r\n"; 128 const char szURI[] = "file:///C:/Windows/System32/Boot/\r\n" 129 "file:///C:/Windows/System/\r\n"; 118 130 119 131 RTTEST_CHECK_RC(hTest, DnDTransferListAppendPathsFromBuffer(&list, DNDTRANSFERLISTFMT_URI, szURI, sizeof(szURI), "\r\n", 120 132 DNDTRANSFERLIST_FLAGS_NONE), VINF_SUCCESS); 121 RTTEST_CHECK(hTest, DnDTransferListGetRootCount(&list) == 4);122 RTTEST_CHECK(hTest, RT StrCmp(DnDTransferListGetRootPathAbs(&list), RTPATH_SLASH_STR) == 0);133 RTTEST_CHECK(hTest, DnDTransferListGetRootCount(&list) == 2); 134 RTTEST_CHECK(hTest, RTPathCompare(DnDTransferListGetRootPathAbs(&list), "C:/Windows/") == 0); 123 135 RTTEST_CHECK_RC(hTest, DnDTransferListGetRootsEx(&list, DNDTRANSFERLISTFMT_NATIVE, "/native/base/path", "\n", &pszBuf, &cbBuf), VINF_SUCCESS); 124 136 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Roots (URI, new base):\n%s\n", pszBuf); … … 129 141 RTStrFree(pszBuf); 130 142 143 DnDTransferListDestroy(&list); 144 DnDTransferListDestroy(&list); /* Doing this twice here is intentional. */ 145 131 146 return RTTestSummaryAndDestroy(hTest); 132 147 }
Note:
See TracChangeset
for help on using the changeset viewer.