Changeset 85408 in vbox
- Timestamp:
- Jul 22, 2020 8:49:55 AM (5 years ago)
- svn:sync-xref-src-repo-rev:
- 139447
- Location:
- trunk/src/VBox/GuestHost/DragAndDrop
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/GuestHost/DragAndDrop/DnDTransferList.cpp
r85382 r85408 53 53 54 54 /** 55 * Initializes a transfer list .55 * Initializes a transfer list, internal version. 56 56 * 57 57 * @returns VBox status code. … … 59 59 * @param pcszRootPathAbs Absolute root path to use for this list. Optional and can be NULL. 60 60 */ 61 int DnDTransferListInit(PDNDTRANSFERLIST pList, const char *pcszRootPathAbs)61 static int dndTransferListInitInternal(PDNDTRANSFERLIST pList, const char *pcszRootPathAbs) 62 62 { 63 63 AssertPtrReturn(pList, VERR_INVALID_POINTER); … … 83 83 84 84 return VINF_SUCCESS; 85 } 86 87 /** 88 * Initializes a transfer list. 89 * 90 * @returns VBox status code. 91 * @param pList Transfer list to initialize. 92 * @param pcszRootPathAbs Absolute root path to use for this list. Optional and can be NULL. 93 */ 94 int DnDTransferListInit(PDNDTRANSFERLIST pList, const char *pcszRootPathAbs) 95 { 96 return dndTransferListInitInternal(pList, pcszRootPathAbs); 85 97 } 86 98 … … 369 381 } 370 382 383 /** 384 * Helper function for appending a local directory to a DnD transfer list. 385 * 386 * @returns VBox status code. 387 * @param pList Transfer list to return total number of root entries for. 388 * @param pszPathAbs Absolute path of directory to append. 389 * @param cbPathAbs Size (in bytes) of absolute path of directory to append. 390 * @param fFlags Transfer list flags to use for appending. 391 */ 392 static int dndTransferListAppenDirectory(PDNDTRANSFERLIST pList, char* pszPathAbs, size_t cbPathAbs, 393 DNDTRANSFERLISTFLAGS fFlags) 394 { 395 RTDIR hDir; 396 int rc = RTDirOpen(&hDir, pszPathAbs); 397 if (RT_FAILURE(rc)) 398 return rc; 399 400 const size_t cchPathAbs = RTStrNLen(pszPathAbs, cbPathAbs); 401 402 for (;;) 403 { 404 /* Get the next directory. */ 405 RTDIRENTRYEX dirEntry; 406 rc = RTDirReadEx(hDir, &dirEntry, NULL, RTFSOBJATTRADD_UNIX, 407 RTPATH_F_ON_LINK /** @todo No symlinks yet. */); 408 if (RT_SUCCESS(rc)) 409 { 410 if (RTDirEntryExIsStdDotLink(&dirEntry)) 411 continue; 412 413 /* Check length. */ 414 if (dirEntry.cbName + cchPathAbs + 3 >= cbPathAbs) 415 { 416 rc = VERR_BUFFER_OVERFLOW; 417 break; 418 } 419 420 /* Append the directory entry to our absolute path. */ 421 memcpy(&pszPathAbs[cchPathAbs], dirEntry.szName, dirEntry.cbName + 1); 422 423 LogFlowFunc(("szName=%s, pszPathAbs=%s\n", dirEntry.szName, pszPathAbs)); 424 425 switch (dirEntry.Info.Attr.fMode & RTFS_TYPE_MASK) 426 { 427 case RTFS_TYPE_DIRECTORY: 428 { 429 rc = dndTransferListAppendPathNativeRecursive(pList, pszPathAbs, fFlags); 430 break; 431 } 432 433 case RTFS_TYPE_FILE: 434 { 435 rc = dndTransferListObjAdd(pList, pszPathAbs, dirEntry.Info.Attr.fMode, fFlags); 436 break; 437 } 438 439 default: 440 /* Silently skip everything else. */ 441 break; 442 } 443 } 444 else if (rc == VERR_NO_MORE_FILES) 445 { 446 rc = VINF_SUCCESS; 447 break; 448 } 449 else 450 break; 451 } 452 453 return rc; 454 } 455 456 /** 457 * Appends a native path to a DnD transfer list. 458 * 459 * @returns VBox status code. 460 * @param pList Transfer list to append native path to. 461 * @param pcszPath Path (native) to append. 462 * @param fFlags Transfer list flags to use for appending. 463 */ 371 464 static int dndTransferListAppendPathNative(PDNDTRANSFERLIST pList, const char *pcszPath, DNDTRANSFERLISTFLAGS fFlags) 372 465 { … … 394 487 if (RTPathStartsWith(szPathAbs, pList->pszPathRootAbs)) 395 488 { 396 RT DIR hDir;397 rc = RT DirOpen(&hDir, szPathAbs);489 RTFSOBJINFO objInfo; 490 rc = RTPathQueryInfo(szPathAbs, &objInfo, RTFSOBJATTRADD_NOTHING); 398 491 if (RT_SUCCESS(rc)) 399 492 { 400 for (;;)493 switch (objInfo.Attr.fMode & RTFS_TYPE_MASK) 401 494 { 402 /* Get the next directory. */ 403 RTDIRENTRYEX dirEntry; 404 rc = RTDirReadEx(hDir, &dirEntry, NULL, RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK /** @todo No symlinks yet. */); 405 if (RT_SUCCESS(rc)) 406 { 407 if (RTDirEntryExIsStdDotLink(&dirEntry)) 408 continue; 409 410 /* Check length. */ 411 if (dirEntry.cbName + cchPathAbs + 3 >= sizeof(szPathAbs)) 412 { 413 rc = VERR_BUFFER_OVERFLOW; 414 break; 415 } 416 417 /* Append the directory entry to our absolute path. */ 418 memcpy(&szPathAbs[cchPathAbs], dirEntry.szName, dirEntry.cbName + 1); 419 420 LogFlowFunc(("szName=%s, szPathAbs=%s\n", dirEntry.szName, szPathAbs)); 421 422 switch (dirEntry.Info.Attr.fMode & RTFS_TYPE_MASK) 423 { 424 case RTFS_TYPE_DIRECTORY: 425 { 426 rc = dndTransferListAppendPathNativeRecursive(pList, szPathAbs, fFlags); 427 break; 428 } 429 430 case RTFS_TYPE_FILE: 431 { 432 rc = dndTransferListObjAdd(pList, szPathAbs, dirEntry.Info.Attr.fMode, fFlags); 433 break; 434 } 435 436 default: 437 rc = VERR_NOT_SUPPORTED; 438 break; 439 } 440 441 if (RT_SUCCESS(rc)) 442 rc = dndTransferListRootAdd(pList, dirEntry.szName); 443 } 444 else if (rc == VERR_NO_MORE_FILES) 445 { 446 rc = VINF_SUCCESS; 495 case RTFS_TYPE_DIRECTORY: 496 if (fFlags & DNDTRANSFERLIST_FLAGS_RECURSIVE) 497 rc = dndTransferListAppenDirectory(pList, szPathAbs, sizeof(szPathAbs), fFlags); 447 498 break; 448 } 449 else 499 500 case RTFS_TYPE_FILE: 501 rc = dndTransferListObjAdd(pList, szPathAbs, objInfo.Attr.fMode, fFlags); 450 502 break; 451 503 452 if (RT_FAILURE(rc)) 504 default: 505 /* Silently skip everything else. */ 453 506 break; 454 507 } 508 509 if (RT_SUCCESS(rc)) 510 rc = dndTransferListRootAdd(pList, szPathAbs); 455 511 } 456 512 } … … 465 521 } 466 522 523 /** 524 * Appends an URI path to a DnD transfer list. 525 * 526 * @returns VBox status code. 527 * @param pList Transfer list to append native path to. 528 * @param pcszPath URI path to append. 529 * @param fFlags Transfer list flags to use for appending. 530 */ 467 531 static int dndTransferListAppendPathURI(PDNDTRANSFERLIST pList, const char *pcszPath, DNDTRANSFERLISTFLAGS fFlags) 468 532 { … … 579 643 return VINF_SUCCESS; 580 644 645 char **papszPathsTmp = NULL; 646 647 /* If URI data is being handed in, extract the paths first. */ 648 if (enmFmt == DNDTRANSFERLISTFMT_URI) 649 { 650 papszPathsTmp = (char **)RTMemAlloc(sizeof(char *) * cPaths); 651 if (papszPathsTmp) 652 { 653 for (size_t i = 0; i < cPaths; i++) 654 papszPathsTmp[i] = RTUriFilePath(papcszPaths[i]); 655 } 656 else 657 rc = VERR_NO_MEMORY; 658 } 659 660 if (RT_FAILURE(rc)) 661 return rc; 662 581 663 /* If we don't have a root path set, try to find the common path of all handed-in paths. */ 582 664 if (!pList->pszPathRootAbs) 583 665 { 584 size_t cchRootPath = RTPathFindCommon(cPaths, papcszPaths); 666 /* Can we work on the unmodified, handed-in data or do we need to use our temporary paths? */ 667 const char * const *papszPathTmp = enmFmt == DNDTRANSFERLISTFMT_NATIVE 668 ? papcszPaths : papszPathsTmp; 669 670 size_t cchRootPath = 0; /* Length of root path in chars. */ 671 if (cPaths > 1) 672 { 673 cchRootPath = RTPathFindCommon(cPaths, papszPathTmp); 674 } 675 else 676 cchRootPath = RTPathParentLength(papszPathTmp[0]); 677 585 678 if (cchRootPath) 586 679 { 587 680 /* Just use the first path in the array as the reference. */ 588 char *pszRootPath = RTStrDupN(pap cszPaths[0], cchRootPath);681 char *pszRootPath = RTStrDupN(papszPathTmp[0], cchRootPath); 589 682 if (pszRootPath) 590 683 { 591 684 LogRel2(("DnD: Determined root path is '%s'\n", pszRootPath)); 592 rc = dndTransferList SetRootPath(pList, pszRootPath);685 rc = dndTransferListInitInternal(pList, pszRootPath); 593 686 RTStrFree(pszRootPath); 594 687 } … … 596 689 rc = VERR_NO_MEMORY; 597 690 } 598 } 599 600 /* 601 * Go through the created list and make sure all entries have the same root path. 602 */ 603 for (size_t i = 0; i < cPaths; i++) 604 { 605 rc = DnDTransferListAppendPath(pList, enmFmt, papcszPaths[i], fFlags); 606 if (RT_FAILURE(rc)) 607 break; 691 else 692 rc = VERR_INVALID_PARAMETER; 693 } 694 695 if (RT_SUCCESS(rc)) 696 { 697 /* 698 * Add all paths to the list. 699 */ 700 for (size_t i = 0; i < cPaths; i++) 701 { 702 const char *pcszPath = enmFmt == DNDTRANSFERLISTFMT_NATIVE 703 ? papcszPaths[i] : papszPathsTmp[i]; 704 rc = DnDTransferListAppendPath(pList, DNDTRANSFERLISTFMT_NATIVE, pcszPath, fFlags); 705 if (RT_FAILURE(rc)) 706 { 707 LogRel(("DnD: Adding path '%s' (format %#x, root '%s') to transfer list failed with %Rrc\n", 708 pcszPath, enmFmt, pList->pszPathRootAbs ? pList->pszPathRootAbs : "<None>", rc)); 709 break; 710 } 711 } 712 } 713 714 if (papszPathsTmp) 715 { 716 for (size_t i = 0; i < cPaths; i++) 717 RTStrFree(papszPathsTmp[i]); 718 RTMemFree(papszPathsTmp); 608 719 } 609 720 … … 667 778 AssertPtrReturn(pcbBuffer, VERR_INVALID_POINTER); 668 779 669 char *pszString = NULL; 780 char *pszString = NULL; 781 size_t cchString = 0; 782 783 const size_t cchSep = RTStrNLen(pcszSeparator, RTPATH_MAX); 670 784 671 785 /* Find out which root path to use. */ 672 786 const char *pcszPathRootTmp = pcszPathBase ? pcszPathBase : pList->pszPathRootAbs; 673 /* pcszPathRootTmp can be NULL */787 /* pcszPathRootTmp can be NULL */ 674 788 675 789 LogFlowFunc(("Using root path '%s'\n", pcszPathRootTmp ? pcszPathRootTmp : "<None>")); … … 688 802 rc = RTStrCopy(szPath, sizeof(szPath), pcszPathRootTmp); 689 803 AssertRCBreak(rc); 804 cchString += RTStrNLen(pcszPathRootTmp, RTPATH_MAX); 690 805 } 691 806 … … 697 812 char *pszPathURI = RTUriFileCreate(szPath); 698 813 AssertPtrBreakStmt(pszPathURI, rc = VERR_NO_MEMORY); 699 700 814 rc = RTStrAAppend(&pszString, pszPathURI); 815 cchString += RTStrNLen(pszPathURI, RTPATH_MAX); 701 816 RTStrFree(pszPathURI); 702 817 AssertRCBreak(rc); 703 818 } 704 else 705 { 706 rc = RTStrAAppend(&pszString, szPath); 707 AssertRCBreak(rc); 819 else /* Native */ 820 { 821 #if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) 822 /* Convert paths to native path style. */ 823 rc = DnDPathConvert(szPath, sizeof(szPath), DNDPATHCONVERT_FLAGS_TO_DOS); 824 #endif 825 if (RT_SUCCESS(rc)) 826 { 827 rc = RTStrAAppend(&pszString, szPath); 828 AssertRCBreak(rc); 829 830 cchString += RTStrNLen(szPath, RTPATH_MAX); 831 } 708 832 } 709 833 710 834 rc = RTStrAAppend(&pszString, pcszSeparator); 711 835 AssertRCBreak(rc); 836 837 cchString += cchSep; 712 838 } 713 839 … … 715 841 { 716 842 *ppszBuffer = pszString; 717 *pcbBuffer = pszString ? strlen(pszString)+ 1 /* Include termination */ : 0;843 *pcbBuffer = pszString ? cchString + 1 /* Include termination */ : 0; 718 844 } 719 845 else … … 722 848 } 723 849 850 /** 851 * Returns all root entries for a DnD transfer list. 852 * 853 * Note: Convenience function which uses the default DnD path separator. 854 * 855 * @returns VBox status code. 856 * @param pList Transfer list to return root entries for. 857 * @param enmFmt Which format to use for returning the entries. 858 * @param ppszBuffer Where to return the allocated string on success. Needs to be free'd with RTStrFree(). 859 * @param pcbBuffer Where to return the size (in bytes) of the allocated string on success, including terminator. 860 */ 724 861 int DnDTransferListGetRoots(PDNDTRANSFERLIST pList, 725 862 DNDTRANSFERLISTFMT enmFmt, char **ppszBuffer, size_t *pcbBuffer) … … 812 949 } 813 950 951 /** 952 * Adds a root entry to a DnD transfer list. 953 * 954 * @returns VBox status code. 955 * @param pList Transfer list to add root entry to. 956 * @param pcszRoot Root entry to add. 957 */ 814 958 static int dndTransferListRootAdd(PDNDTRANSFERLIST pList, const char *pcszRoot) 815 959 { 816 960 int rc; 961 962 /** @todo Handle / reject double entries. */ 963 964 /* Calculate the path to add as the destination path to our URI object. */ 965 const size_t idxPathToAdd = strlen(pList->pszPathRootAbs); 966 AssertReturn(strlen(pcszRoot) > idxPathToAdd, VERR_INVALID_PARAMETER); /* Should never happen (tm). */ 817 967 818 968 PDNDTRANSFERLISTROOT pRoot = (PDNDTRANSFERLISTROOT)RTMemAllocZ(sizeof(DNDTRANSFERLISTROOT)); 819 969 if (pRoot) 820 970 { 821 pRoot->pszPathRoot = RTStrDup(pcszRoot); 971 const char *pcszRootIdx = &pcszRoot[idxPathToAdd]; 972 973 LogFlowFunc(("pcszRoot=%s\n", pcszRootIdx)); 974 975 pRoot->pszPathRoot = RTStrDup(pcszRootIdx); 822 976 if (pRoot->pszPathRoot) 823 977 { … … 843 997 844 998 /** 845 * Frees an internal DnD transfer root.999 * Removes (and destroys) a DnD transfer root entry. 846 1000 * 847 1001 * @param pList Transfer list to free root for. … … 862 1016 } 863 1017 864 865 #if 0866 /**867 * Appends a single URI path to a transfer list.868 *869 * @returns VBox status code.870 * @param pList Transfer list to append URI path to.871 * @param pszURIPath URI path to append.872 * @param fFlags Transfer list flags to use for appending.873 */874 int DnDTransferListURIAppendPath(PDNDTRANSFERLIST pList, const char *pszURIPath, DNDTRANSFERLISTFLAGS fFlags)875 {876 AssertPtrReturn(pList, VERR_INVALID_POINTER);877 AssertPtrReturn(pszURIPath, VERR_INVALID_POINTER);878 AssertReturn(!(fFlags & ~DNDTRANSFERLIST_FLAGS_VALID_MASK), VERR_INVALID_FLAGS);879 880 in rc;881 882 /* Query the path component of a file URI. If this hasn't a883 * file scheme, NULL is returned. */884 char *pszFilePath = RTUriFilePathEx(pszURIPath, RTPATH_STR_F_STYLE_UNIX, &pszFilePath, 0 /*cbPath*/, NULL /*pcchPath*/);885 LogFlowFunc(("pszPath=%s, pszFilePath=%s\n", pszFilePath));886 if (pszFilePath)887 {888 rc = DnDPathValidate(pszFilePath, false /* fMustExist */);889 if (RT_SUCCESS(rc))890 {891 uint32_t fPathConvert = DNDPATHCONVERT_FLAGS_TRANSPORT;892 #ifdef RT_OS_WINDOWS893 fPathConvert |= DNDPATHCONVERT_FLAGS_TO_DOS;894 #endif895 rc = DnDPathConvert(pszFilePath, strlen(pszFilePath) + 1, fPathConvert);896 if (RT_SUCCESS(rc))897 {898 LogRel2(("DnD: Got URI data item '%s'\n", pszFilePath));899 900 PDNDTRANSFERLISTROOT pRoot = (PDNDTRANSFERLISTROOT)RTMemAlloc(sizeof(DNDTRANSFERLISTROOT));901 if (pRoot)902 {903 pRoot->pszPathRoot = pszFilePath;904 905 RTListAppend(&pList->lstRoot, &pRoot->Node);906 pList->cRoots++;907 908 }909 else910 rc = VERR_NO_MEMORY;911 }912 else913 LogRel(("DnD: Path conversion of URI data item '%s' failed with %Rrc\n", pszFilePath, rc));914 }915 else916 LogRel(("DnD: Path validation for URI data item '%s' failed with %Rrc\n", pszFilePath, rc));917 918 if (RT_FAILURE(rc))919 RTStrFree(pszFilePath);920 }921 922 LogFlowFuncLeaveRC(rc);923 return rc;924 }925 926 /**927 * Appends transfer list items from an URI string buffer.928 *929 * @returns VBox status code.930 * @param pList Transfer list to append list data to.931 * @param pszURIPaths String list to append.932 * @param cbURIPaths Size (in bytes) of string list to append.933 * @param pcszSeparator Separator string to use for separating strings of \a pszURIPathsAbs.934 * @param fFlags Transfer list flags to use for appending.935 */936 int DnDTransferListURIAppendFromBuffer(PDNDTRANSFERLIST pList,937 const char *pszURIPaths, size_t cbURIPaths,938 const char *pcszSeparator, DNDTRANSFERLISTFLAGS fFlags)939 {940 AssertPtrReturn(pList, VERR_INVALID_POINTER);941 AssertPtrReturn(pszURIPaths, VERR_INVALID_POINTER);942 AssertReturn(cbURIPaths, VERR_INVALID_PARAMETER);943 AssertReturn(!(fFlags & ~DNDTRANSFERLIST_FLAGS_VALID_MASK), VERR_INVALID_FLAGS);944 945 char **papszPaths = NULL;946 size_t cPaths = 0;947 int rc = RTStrSplit(pszURIPaths, cbURIPaths, pcszSeparator, &papszPaths, &cPaths);948 if (RT_SUCCESS(rc))949 {950 for (size_t i = 0; i < cPaths; i++)951 {952 rc = DnDTransferListURIAppendPath(pList, papszPaths[i], fFlags);953 if (RT_FAILURE(rc))954 break;955 }956 957 for (size_t i = 0; i < cPaths; ++i)958 RTStrFree(papszPaths[i]);959 RTMemFree(papszPaths);960 }961 962 LogFlowFuncLeaveRC(rc);963 return rc;964 }965 #endif -
trunk/src/VBox/GuestHost/DragAndDrop/testcase/tstDnDTransferList.cpp
r85381 r85408 71 71 72 72 /* Adding stuff. */ 73 RTTEST_CHECK_RC(hTest, DnDTransferListAppendPath(&list, DNDTRANSFERLISTFMT_NATIVE, szPathWellKnown, DNDTRANSFERLIST_FLAGS_ NONE), VINF_SUCCESS);73 RTTEST_CHECK_RC(hTest, DnDTransferListAppendPath(&list, DNDTRANSFERLISTFMT_NATIVE, szPathWellKnown, DNDTRANSFERLIST_FLAGS_RECURSIVE), VINF_SUCCESS); 74 74 RTTEST_CHECK(hTest, DnDTransferListGetRootCount(&list)); 75 75 RTTEST_CHECK(hTest, DnDTransferListObjCount(&list)); … … 113 113 "file:///dir1\r\n" 114 114 "file:///dir%20with%20spaces\r\n"; 115 115 116 RTTEST_CHECK_RC(hTest, DnDTransferListAppendPathsFromBuffer(&list, DNDTRANSFERLISTFMT_URI, szURI, sizeof(szURI), "\r\n", 116 117 DNDTRANSFERLIST_FLAGS_NONE), VINF_SUCCESS); 117 118 RTTEST_CHECK(hTest, DnDTransferListGetRootCount(&list) == 4); 119 RTTEST_CHECK(hTest, RTStrCmp(DnDTransferListGetRootPathAbs(&list), RTPATH_SLASH_STR) == 0); 118 120 RTTEST_CHECK_RC(hTest, DnDTransferListGetRootsEx(&list, DNDTRANSFERLISTFMT_NATIVE, "/native/base/path", "\n", &pszBuf, &cbBuf), VINF_SUCCESS); 121 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Roots (URI, new base):\n%s\n", pszBuf); 122 RTTEST_CHECK_RC(hTest, DnDTransferListGetRootsEx(&list, DNDTRANSFERLISTFMT_NATIVE, "\\windows\\path", "\n", &pszBuf, &cbBuf), VINF_SUCCESS); 123 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Roots (URI, new base):\n%s\n", pszBuf); 124 RTTEST_CHECK_RC(hTest, DnDTransferListGetRootsEx(&list, DNDTRANSFERLISTFMT_NATIVE, "\\\\windows\\\\path", "\n", &pszBuf, &cbBuf), VINF_SUCCESS); 119 125 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Roots (URI, new base):\n%s\n", pszBuf); 120 126 RTStrFree(pszBuf);
Note:
See TracChangeset
for help on using the changeset viewer.