VirtualBox

Changeset 85535 in vbox for trunk/src


Ignore:
Timestamp:
Jul 30, 2020 6:53:40 AM (4 years ago)
Author:
vboxsync
Message:

DnD/DnDTransferList: More fixes for newly added testcases.

Location:
trunk/src/VBox/GuestHost/DragAndDrop
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/GuestHost/DragAndDrop/DnDTransferList.cpp

    r85462 r85535  
    1616 */
    1717
     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 */
    1835
    1936/*********************************************************************************************************************************
     
    4158static int dndTransferListSetRootPath(PDNDTRANSFERLIST pList, const char *pcszRootPathAbs);
    4259
    43 static int dndTransferListRootAdd(PDNDTRANSFERLIST pList, const char *pcszRoot);
    44 static void dndTransferListRootFree(PDNDTRANSFERLIST pList, PDNDTRANSFERLISTROOT pRootObj);
     60static int dndTransferListRootEntryAdd(PDNDTRANSFERLIST pList, const char *pcszRoot);
     61static void dndTransferListRootEntryFree(PDNDTRANSFERLIST pList, PDNDTRANSFERLISTROOT pRootObj);
    4562
    4663static int dndTransferListObjAdd(PDNDTRANSFERLIST pList, const char *pcszSrcAbs, RTFMODE fMode, DNDTRANSFERLISTFLAGS fFlags);
     
    87104 * @returns VBox status code.
    88105 * @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 */
     109int 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;
    94131}
    95132
     
    122159
    123160/**
     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 */
     169static 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/**
    124187 * Resets a transfer list to its initial state.
    125188 *
     
    138201    PDNDTRANSFERLISTROOT pRootCur, pRootNext;
    139202    RTListForEachSafe(&pList->lstRoot, pRootCur, pRootNext, DNDTRANSFERLISTROOT, Node)
    140         dndTransferListRootFree(pList, pRootCur);
     203        dndTransferListRootEntryFree(pList, pRootCur);
    141204    Assert(RTListIsEmpty(&pList->lstRoot));
    142205
     
    406469                                          PRTFSOBJINFO pObjInfo, DNDTRANSFERLISTFLAGS fFlags)
    407470{
    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);
    411473
    412474    const size_t cchPathAbs = RTPathEnsureTrailingSeparator(pszPathAbs, sizeof(cbPathAbs));
    413475    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);
    416490    AssertRCReturn(rc, rc);
    417491
     
    458532                    break;
    459533            }
     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            }
    460541        }
    461542        else if (rc == VERR_NO_MORE_FILES)
     
    518599                    }
    519600
    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);
    521607                }
    522608                else
     
    570656    /* Query the path component of a file URI. If this hasn't a
    571657     * file scheme, NULL is returned. */
    572     char *pszFilePath;
    573     int rc = RTUriFilePathEx(pcszPath, RTPATH_STR_F_STYLE_UNIX, &pszFilePath, 0 /*cbPath*/, NULL /*pcchPath*/);
     658    char *pszPath;
     659    int rc = RTUriFilePathEx(pcszPath, RTPATH_STR_F_STYLE_UNIX, &pszPath, 0 /*cbPath*/, NULL /*pcchPath*/);
    574660    if (RT_SUCCESS(rc))
    575661    {
    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);
    580664    }
    581665
     
    717801            if (pszRootPath)
    718802            {
    719                 LogRel2(("DnD: Determined root path is '%s'\n", pszRootPath));
    720                 rc = dndTransferListInitInternal(pList, pszRootPath);
     803                rc = dndTransferInitAndSetRoot(pList, pszRootPath);
    721804                RTStrFree(pszRootPath);
    722805            }
     
    849932        AssertRCBreak(rc);
    850933
    851         rc = dndTransferListRootAdd(pList, szPath);
     934        rc = dndTransferListRootEntryAdd(pList, szPath);
    852935        if (RT_FAILURE(rc))
    853936        {
     
    11111194    RTPathEnsureTrailingSeparatorEx(szRootPath, sizeof(szRootPath), RTPATH_STR_F_STYLE_HOST);
    11121195
    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    }
    11201214
    11211215    return rc;
     
    11291223 * @param   pcszRoot            Root entry to add.
    11301224 */
    1131 static int dndTransferListRootAdd(PDNDTRANSFERLIST pList, const char *pcszRoot)
     1225static int dndTransferListRootEntryAdd(PDNDTRANSFERLIST pList, const char *pcszRoot)
    11321226{
    11331227    AssertPtrReturn(pList->pszPathRootAbs, VERR_WRONG_ORDER); /* The list's root path must be set first. */
     
    11771271 * @param   pRootObj            Transfer list root to free. The pointer will be invalid after calling.
    11781272 */
    1179 static void dndTransferListRootFree(PDNDTRANSFERLIST pList, PDNDTRANSFERLISTROOT pRootObj)
     1273static void dndTransferListRootEntryFree(PDNDTRANSFERLIST pList, PDNDTRANSFERLISTROOT pRootObj)
    11801274{
    11811275    if (!pRootObj)
  • trunk/src/VBox/GuestHost/DragAndDrop/testcase/tstDnDTransferList.cpp

    r85428 r85535  
    4040    RTStrCopy(szPathWellKnown, sizeof(szPathWellKnown),
    4141#ifdef RT_OS_WINDOWS
    42               "C:\\Windows\\INF\\");
     42              "C:\\Windows\\System32\\Boot\\");
    4343#else
    4444              "/bin/");
    4545#endif
     46
     47    char szPathWellKnownURI[RTPATH_MAX];
     48    RTStrPrintf(szPathWellKnownURI, sizeof(szPathWellKnownURI), "file:///%s", szPathWellKnown);
    4649
    4750    DNDTRANSFERLIST list;
     
    4952
    5053    /* 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);
    5457    DnDTransferListDestroy(&list);
    5558
     
    5962
    6063    /* Initial status. */
    61     RTTEST_CHECK_RC(hTest, DnDTransferListInitEx(&list, szPathWellKnown), VINF_SUCCESS);
     64    RTTEST_CHECK_RC(hTest, DnDTransferListInitEx(&list, szPathWellKnown, DNDTRANSFERLISTFMT_NATIVE), VINF_SUCCESS);
    6265    RTTEST_CHECK(hTest, DnDTransferListGetRootCount(&list) == 0);
    6366    RTTEST_CHECK(hTest, DnDTransferListObjCount(&list) == 0);
    6467    RTTEST_CHECK(hTest, DnDTransferListObjTotalBytes(&list) == 0);
    6568    RTTEST_CHECK(hTest, DnDTransferListObjGetFirst(&list) == NULL);
     69    DnDTransferListDestroy(&list);
    6670
    6771    char szPathTest[RTPATH_MAX];
    6872
    6973    /* Root path handling. */
     74    RTTEST_CHECK_RC(hTest, DnDTransferListInitEx(&list, szPathWellKnown, DNDTRANSFERLISTFMT_NATIVE), VINF_SUCCESS);
    7075    RTTEST_CHECK_RC(hTest, DnDTransferListAppendPath(&list, DNDTRANSFERLISTFMT_NATIVE, "/wrong/root/path", DNDTRANSFERLIST_FLAGS_NONE), VERR_INVALID_PARAMETER);
    7176    rc = RTPathJoin(szPathTest, sizeof(szPathTest), szPathWellKnown, "/non/existing");
    7277    AssertRCReturn(rc, RTEXITCODE_FAILURE);
    7378    RTTEST_CHECK_RC(hTest, DnDTransferListAppendPath(&list, DNDTRANSFERLISTFMT_NATIVE, szPathTest, DNDTRANSFERLIST_FLAGS_NONE), VERR_PATH_NOT_FOUND);
     79    DnDTransferListDestroy(&list);
    7480
    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. */
    7689    RTTEST_CHECK_RC(hTest, DnDTransferListAppendPath(&list, DNDTRANSFERLISTFMT_NATIVE, szPathWellKnown, DNDTRANSFERLIST_FLAGS_RECURSIVE), VINF_SUCCESS);
    7790    RTTEST_CHECK(hTest, DnDTransferListGetRootCount(&list));
     
    8194    size_t cbString = 0;
    8295    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);
    8497    RTStrFree(pszString);
    85     RTTestPrintf(hTest, RTTESTLVL_DEBUG, "\n");
    8698
    8799    PDNDTRANSFEROBJECT pObj;
     
    97109
    98110    /* 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);
    101115    RTTEST_CHECK_RC(hTest, DnDTransferListGetRootsEx(&list, DNDTRANSFERLISTFMT_NATIVE, "" /* pszBasePath */, "\n", &pszBuf, &cbBuf), VINF_SUCCESS);
    102116    RTTestPrintf(hTest, RTTESTLVL_DEBUG, "Roots (native):\n%s\n", pszBuf);
     
    112126
    113127    /* 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";
    118130
    119131    RTTEST_CHECK_RC(hTest, DnDTransferListAppendPathsFromBuffer(&list, DNDTRANSFERLISTFMT_URI, szURI, sizeof(szURI), "\r\n",
    120132                                                                DNDTRANSFERLIST_FLAGS_NONE), VINF_SUCCESS);
    121     RTTEST_CHECK(hTest, DnDTransferListGetRootCount(&list) == 4);
    122     RTTEST_CHECK(hTest, RTStrCmp(DnDTransferListGetRootPathAbs(&list), RTPATH_SLASH_STR) == 0);
     133    RTTEST_CHECK(hTest, DnDTransferListGetRootCount(&list) == 2);
     134    RTTEST_CHECK(hTest, RTPathCompare(DnDTransferListGetRootPathAbs(&list), "C:/Windows/") == 0);
    123135    RTTEST_CHECK_RC(hTest, DnDTransferListGetRootsEx(&list, DNDTRANSFERLISTFMT_NATIVE, "/native/base/path", "\n", &pszBuf, &cbBuf), VINF_SUCCESS);
    124136    RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Roots (URI, new base):\n%s\n", pszBuf);
     
    129141    RTStrFree(pszBuf);
    130142
     143    DnDTransferListDestroy(&list);
     144    DnDTransferListDestroy(&list); /* Doing this twice here is intentional. */
     145
    131146    return RTTestSummaryAndDestroy(hTest);
    132147}
Note: See TracChangeset for help on using the changeset viewer.

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