VirtualBox

Changeset 100676 in vbox for trunk


Ignore:
Timestamp:
Jul 21, 2023 11:26:04 AM (21 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
158516
Message:

Shared Clipboard: HTTP transfers with multiple files are also working now. bugref:9437

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/GuestHost/SharedClipboard-transfers.h

    r100660 r100676  
    11881188int ShClTransferSetProvider(PSHCLTRANSFER pTransfer, PSHCLTXPROVIDER pProvider);
    11891189
     1190int ShClTransferRootsInitFromStringListEx(PSHCLTRANSFER pTransfer, const char *pszRoots, size_t cbRoots, const char *pszSep);
    11901191int ShClTransferRootsInitFromStringList(PSHCLTRANSFER pTransfer, const char *pszRoots, size_t cbRoots);
    11911192int ShClTransferRootsInitFromStringListUnicode(PSHCLTRANSFER pTransfer, PRTUTF16 pwszRoots, size_t cbRoots);
     
    12431244uint32_t ShClTransferHttpServerGetTransferCount(PSHCLHTTPSERVER pSrv);
    12441245char *ShClTransferHttpServerGetAddressA(PSHCLHTTPSERVER pSrv);
    1245 char *ShClTransferHttpServerGetUrlA(PSHCLHTTPSERVER pSrv, SHCLTRANSFERID idTransfer);
     1246char *ShClTransferHttpServerGetUrlA(PSHCLHTTPSERVER pSrv, SHCLTRANSFERID idTransfer, uint64_t idxEntry);
    12461247bool ShClTransferHttpServerIsInitialized(PSHCLHTTPSERVER pSrv);
    12471248bool ShClTransferHttpServerIsRunning(PSHCLHTTPSERVER pSrv);
  • trunk/src/VBox/Additions/x11/VBoxClient/clipboard-x11.cpp

    r100367 r100676  
    9595                            PSHCLX11RESPONSE pResp = (PSHCLX11RESPONSE)pPayload->pvData;
    9696
    97                             rc = ShClTransferRootsInitFromStringList(pTransfer, (const char *)pResp->Read.pvData, pResp->Read.cbData);
     97                            rc = ShClTransferRootsInitFromStringListEx(pTransfer, (const char *)pResp->Read.pvData, pResp->Read.cbData,
     98                                                                       "\n" /* X11-based Desktop environments separate entries with "\n" */);
    9899
    99100                            RTMemFree(pResp->Read.pvData);
     
    329330                        if (RT_SUCCESS(rc))
    330331                        {
    331                             char *pszURL = ShClTransferHttpServerGetUrlA(pSrv, pTransfer->State.uID);
    332                             if (pszURL)
     332                            char *pszURL = NULL;
     333
     334                            uint64_t const cRoots = ShClTransferRootsCount(pTransfer);
     335                            for (uint32_t i = 0; i < cRoots; i++)
     336                            {
     337                                char *pszEntry = ShClTransferHttpServerGetUrlA(pSrv, ShClTransferGetID(pTransfer), i /* Entry index */);
     338                                AssertPtrBreakStmt(pszEntry, rc = VERR_NO_MEMORY);
     339
     340                                if (i > 0)
     341                                {
     342                                    rc = RTStrAAppend(&pszURL, "\n"); /* Separate entries with a newline. */
     343                                    AssertRCBreak(rc);
     344                                }
     345
     346                                rc = RTStrAAppend(&pszURL, pszEntry);
     347                                AssertRCBreak(rc);
     348
     349                                RTStrFree(pszEntry);
     350                            }
     351
     352                            if (RT_SUCCESS(rc))
    333353                            {
    334354                                *ppv = pszURL;
     
    339359                                /* ppv has ownership of pszURL. */
    340360                            }
    341                             else
    342                                 rc = VERR_NO_MEMORY;
    343361                        }
    344362                    }
  • trunk/src/VBox/GuestHost/SharedClipboard/clipboard-transfers-http.cpp

    r100675 r100676  
    6969*********************************************************************************************************************************/
    7070
    71 #ifdef DEBUG_andy
     71#ifdef DEBUG_andy_0
    7272/** When enabled, this lets the HTTP server run at a predictable URL and port for debugging:
    7373 *  URL: http://localhost:49200/transfer<ID> */
     
    401401    RT_NOREF(ppszMIMEHint);
    402402
     403    AssertReturn(RTStrIsValidEncoding(pReq->pszUrl), VERR_INVALID_PARAMETER);
     404
     405    size_t const cchUrl  = strlen(pReq->pszUrl);
     406    AssertReturn(cchUrl, VERR_INVALID_PARAMETER);
     407
    403408    int rc;
    404409
     410    /* For now we only know the transfer -- now we need to figure out the entry we want to serve. */
    405411    PSHCLHTTPSERVERTRANSFER pSrvTx = (PSHCLHTTPSERVERTRANSFER)pReq->pvUser;
    406412    if (pSrvTx)
    407413    {
     414        size_t const cchBase = strlen(pSrvTx->szPathVirtual) + 1 /* Skip slash separating the base from the rest */;
     415        AssertReturn(cchUrl >= cchBase, VERR_INVALID_PARAMETER);
     416
    408417        SHCLOBJOPENCREATEPARMS openParms;
    409418        rc = ShClTransferObjOpenParmsInit(&openParms);
     
    416425            AssertPtr(pTx);
    417426
    418             /** @todo For now we only serve single files, hence index 0 below. */
    419             PCSHCLLISTENTRY pEntry = ShClTransferRootsEntryGet(pTx, 0 /* First file */);
    420             if (pEntry)
     427            rc = VERR_NOT_FOUND; /* Must find the matching root entry first. */
     428
     429            uint64_t const cRoots = ShClTransferRootsCount(pTx);
     430            for (uint32_t i = 0; i < cRoots; i++)
    421431            {
     432                PCSHCLLISTENTRY pEntry = ShClTransferRootsEntryGet(pTx, i);
     433                AssertPtrBreakStmt(pEntry, rc = VERR_NOT_FOUND);
     434
     435                const char *pszName = pReq->pszUrl + cchBase;
     436
     437                Log3Func(("pReqUrl=%s -> pszName=%s vs. pEntry=%s\n", pReq->pszUrl, pszName, pEntry->pszName));
     438
     439                if (RTStrCmp(pEntry->pszName, pszName)) /* Case-sensitive! */
     440                    continue;
     441
    422442                LogRel2(("Shared Clipboard: Querying HTTP transfer information for '%s' ...\n", pEntry->pszName));
    423443
     
    449469                    }
    450470                }
     471
     472                break;
    451473            }
    452             else
    453                 rc = VERR_NOT_FOUND;
    454474
    455475            ShClTransferObjOpenParmsDestroy(&openParms);
     
    856876    uint64_t const cRoots = ShClTransferRootsCount(pTransfer);
    857877    AssertMsgReturn(cRoots  > 0, ("Transfer has no root entries\n"), VERR_INVALID_PARAMETER);
    858     AssertMsgReturn(cRoots == 1, ("Only single files are supported for now\n"), VERR_NOT_SUPPORTED);
    859878    /** @todo Check for directories? */
    860879
     
    875894            AssertRCReturn(rc, rc);
    876895
    877             PCSHCLLISTENTRY pEntry = ShClTransferRootsEntryGet(pTransfer, 0 /* First file */);
    878             if (pEntry)
    879             {
    880                 /* Create the virtual HTTP path for the transfer.
    881                  * Every transfer has a dedicated HTTP path (but live in the same URL namespace). */
    882                 char *pszPath;
     896            /* Create the virtual HTTP path for the transfer.
     897             * Every transfer has a dedicated HTTP path (but live in the same URL namespace). */
     898            char *pszPath;
    883899#ifdef VBOX_SHCL_DEBUG_HTTPSERVER
    884900# ifdef DEBUG_andy /** Too lazy to specify a different transfer ID for debugging. */
    885                 ssize_t cch = RTStrAPrintf(&pszPath, "//transfer");
     901            ssize_t cch = RTStrAPrintf(&pszPath, "//transfer");
    886902# else
    887                 ssize_t cch = RTStrAPrintf(&pszPath, "//transfer%RU16", pTransfer->State.uID);
     903            ssize_t cch = RTStrAPrintf(&pszPath, "//transfer%RU16", pTransfer->State.uID);
    888904# endif
    889905#else /* Release mode */
    890                 ssize_t cch = RTStrAPrintf(&pszPath, "//%s/%s/%s", SHCL_HTTPT_URL_NAMESPACE, szUuid, pEntry->pszName);
     906            ssize_t cch = RTStrAPrintf(&pszPath, "//%s/%s", SHCL_HTTPT_URL_NAMESPACE, szUuid);
    891907#endif
    892                 AssertReturn(cch, VERR_NO_MEMORY);
    893 
    894                 const char   szScheme[] = "http"; /** @todo For now we only support HTTP. */
    895                 const size_t cchScheme  = strlen(szScheme) + 3 /* "://" */;
    896 
    897                 char *pszURI = RTUriCreate(szScheme, NULL /* pszAuthority */, pszPath, NULL /* pszQuery */, NULL /* pszFragment */);
    898                 if (pszURI)
     908            AssertReturn(cch, VERR_NO_MEMORY);
     909
     910            const char   szScheme[] = "http"; /** @todo For now we only support HTTP. */
     911            const size_t cchScheme  = strlen(szScheme) + 3 /* "://" */;
     912
     913            char *pszURI = RTUriCreate(szScheme, NULL /* pszAuthority */, pszPath, NULL /* pszQuery */, NULL /* pszFragment */);
     914            if (pszURI)
     915            {
     916                if (strlen(pszURI) >= cchScheme)
    899917                {
    900                     if (strlen(pszURI) >= cchScheme)
    901                     {
    902                         /* For the virtual path we only keep everything after the full scheme (e.g. "http://").
    903                          * The virtual path always has to start with a "/". */
    904                         if (RTStrPrintf2(pSrvTx->szPathVirtual, sizeof(pSrvTx->szPathVirtual), "/%s", pszURI + cchScheme) <= 0)
    905                             rc = VERR_BUFFER_OVERFLOW;
    906                     }
    907                     else
    908                         rc = VERR_INVALID_PARAMETER;
    909 
    910                     RTStrFree(pszURI);
    911                     pszURI = NULL;
     918                    /* For the virtual path we only keep everything after the full scheme (e.g. "http://").
     919                     * The virtual path always has to start with a "/". */
     920                    if (RTStrPrintf2(pSrvTx->szPathVirtual, sizeof(pSrvTx->szPathVirtual), "/%s", pszURI + cchScheme) <= 0)
     921                        rc = VERR_BUFFER_OVERFLOW;
    912922                }
    913923                else
    914                     rc = VERR_NO_MEMORY;
    915 
    916                 RTStrFree(pszPath);
    917                 pszPath = NULL;
    918 
    919                 AssertRCReturn(rc, rc);
    920 
    921                 pSrvTx->pTransfer = pTransfer;
    922                 pSrvTx->hObj      = NIL_SHCLOBJHANDLE;
    923 
    924                 RTListAppend(&pSrv->lstTransfers, &pSrvTx->Node);
    925                 pSrv->cTransfers++;
    926 
    927                 shclTransferHttpServerSetStatusLocked(pSrv, SHCLHTTPSERVERSTATUS_TRANSFER_REGISTERED);
    928 
    929                 LogFunc(("pTransfer=%p, idTransfer=%RU16, szPath=%s -> %RU32 transfers\n",
    930                          pSrvTx->pTransfer, pSrvTx->pTransfer->State.uID, pSrvTx->szPathVirtual, pSrv->cTransfers));
    931 
    932                 LogRel2(("Shared Clipboard: Registered HTTP transfer %RU16, now %RU32 HTTP transfers total\n",
    933                          pTransfer->State.uID, pSrv->cTransfers));
     924                    rc = VERR_INVALID_PARAMETER;
     925
     926                RTStrFree(pszURI);
     927                pszURI = NULL;
    934928            }
     929            else
     930                rc = VERR_NO_MEMORY;
     931
     932            RTStrFree(pszPath);
     933            pszPath = NULL;
     934
     935            AssertRCReturn(rc, rc);
     936
     937            pSrvTx->pTransfer = pTransfer;
     938            pSrvTx->hObj      = NIL_SHCLOBJHANDLE;
     939
     940            RTListAppend(&pSrv->lstTransfers, &pSrvTx->Node);
     941            pSrv->cTransfers++;
     942
     943            shclTransferHttpServerSetStatusLocked(pSrv, SHCLHTTPSERVERSTATUS_TRANSFER_REGISTERED);
     944
     945            LogFunc(("pTransfer=%p, idTransfer=%RU16, szPath=%s -> %RU32 transfers\n",
     946                     pSrvTx->pTransfer, pSrvTx->pTransfer->State.uID, pSrvTx->szPathVirtual, pSrv->cTransfers));
     947
     948            LogRel2(("Shared Clipboard: Registered HTTP transfer %RU16, now %RU32 HTTP transfers total\n",
     949                     pTransfer->State.uID, pSrv->cTransfers));
    935950        }
     951
    936952    }
    937953
     
    11261142 * @param   pSrv                HTTP server instance to return URL for.
    11271143 * @param   idTransfer          Transfer ID to return the URL for.
    1128  */
    1129 char *ShClTransferHttpServerGetUrlA(PSHCLHTTPSERVER pSrv, SHCLTRANSFERID idTransfer)
     1144 * @param   idxEntry            Index of transfer entry to return URL for.
     1145 */
     1146char *ShClTransferHttpServerGetUrlA(PSHCLHTTPSERVER pSrv, SHCLTRANSFERID idTransfer, uint64_t idxEntry)
    11301147{
    11311148    AssertPtrReturn(pSrv, NULL);
     
    11421159    }
    11431160
    1144     AssertReturn(RTStrNLen(pSrvTx->szPathVirtual, RTPATH_MAX), NULL);
    1145     char *pszUrl = RTStrAPrintf2("%s:%RU16%s", shClTransferHttpServerGetHost(pSrv), pSrv->uPort, pSrvTx->szPathVirtual);
    1146     AssertPtr(pszUrl);
    1147 
    1148     shClTransferHttpServerUnlock(pSrv);
     1161    PSHCLTRANSFER pTx = pSrvTx->pTransfer;
     1162    AssertPtr(pTx);
     1163
     1164    char *pszUrl = NULL;
     1165
     1166    /* For now this only supports root entries. */
     1167    PCSHCLLISTENTRY pEntry = ShClTransferRootsEntryGet(pTx, idxEntry);
     1168    if (pEntry)
     1169    {
     1170        AssertReturn(RTStrNLen(pSrvTx->szPathVirtual, RTPATH_MAX), NULL);
     1171        pszUrl = RTStrAPrintf2("%s:%RU16%s/%s", shClTransferHttpServerGetHost(pSrv), pSrv->uPort, pSrvTx->szPathVirtual, pEntry->pszName);
     1172        AssertPtr(pszUrl);
     1173
     1174        shClTransferHttpServerUnlock(pSrv);
     1175    }
    11491176
    11501177    return pszUrl;
  • trunk/src/VBox/GuestHost/SharedClipboard/clipboard-transfers.cpp

    r100660 r100676  
    18111811
    18121812/**
    1813  * Initializes the root list entries for a given clipboard transfer.
     1813 * Initializes the root list entries for a given clipboard transfer, extended version.
    18141814 *
    18151815 * @returns VBox status code.
    18161816 * @param   pTransfer           Transfer to set transfer list entries for.
    1817  * @param   pszRoots            String list (separated by CRLF) of root entries to set.
     1817 * @param   pszRoots            String list (separated by \a pszSep) of root entries to set.
    18181818 *                              All entries must have the same root path.
    18191819 * @param   cbRoots             Size (in bytes) of string list. Includes zero terminator.
     1820 * @param   pszSep              String separator to use for splitting up the root entries.
    18201821 *
    18211822 * @note    Accepts local paths or URI string lists (absolute only).
    18221823 */
    1823 int ShClTransferRootsInitFromStringList(PSHCLTRANSFER pTransfer, const char *pszRoots, size_t cbRoots)
     1824int ShClTransferRootsInitFromStringListEx(PSHCLTRANSFER pTransfer, const char *pszRoots, size_t cbRoots, const char *pszSep)
    18241825{
    18251826    AssertPtrReturn(pTransfer,      VERR_INVALID_POINTER);
    18261827    AssertPtrReturn(pszRoots,       VERR_INVALID_POINTER);
    18271828    AssertReturn(cbRoots,           VERR_INVALID_PARAMETER);
     1829    AssertPtrReturn(pszSep,         VERR_INVALID_POINTER);
    18281830
    18291831#ifdef DEBUG_andy
     
    18431845    char     *pszPathRootAbs = NULL;
    18441846
    1845     RTCList<RTCString> lstRootEntries = RTCString(pszRoots, cbRoots).split(SHCL_TRANSFER_URI_LIST_SEP_STR);
     1847    RTCList<RTCString> lstRootEntries = RTCString(pszRoots, cbRoots).split(pszSep);
    18461848    if (!lstRootEntries.size())
    18471849    {
     
    19711973    LogFlowFuncLeaveRC(rc);
    19721974    return rc;
     1975}
     1976
     1977/**
     1978 * Initializes the root list entries for a given clipboard transfer.
     1979 *
     1980 * @returns VBox status code.
     1981 * @param   pTransfer           Transfer to set transfer list entries for.
     1982 * @param   pszRoots            String list (separated by SHCL_TRANSFER_URI_LIST_SEP_STR) of root entries to set.
     1983 *                              All entries must have the same root path.
     1984 * @param   cbRoots             Size (in bytes) of string list. Includes zero terminator.
     1985 *
     1986 * @note    Accepts local paths or URI string lists (absolute only).
     1987 */
     1988int ShClTransferRootsInitFromStringList(PSHCLTRANSFER pTransfer, const char *pszRoots, size_t cbRoots)
     1989{
     1990    return ShClTransferRootsInitFromStringListEx(pTransfer, pszRoots, cbRoots, SHCL_TRANSFER_URI_LIST_SEP_STR);
    19731991}
    19741992
  • trunk/src/VBox/GuestHost/SharedClipboard/testcase/tstClipboardHttpServer.cpp

    r100668 r100676  
    251251
    252252                uint16_t const uID    = ShClTransferGetID(pTx);
    253                 char          *pszURL = ShClTransferHttpServerGetUrlA(&HttpSrv, uID);
     253                char          *pszURL = ShClTransferHttpServerGetUrlA(&HttpSrv, uID, 0 /* Entry index */);
    254254                RTTEST_CHECK(hTest, pszURL != NULL);
    255255                RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "URL #%02RU32: %s\n", i, pszURL);
     
    275275
    276276                        uint16_t const uID    = ShClTransferGetID(pTx);
    277                         char          *pszURL = ShClTransferHttpServerGetUrlA(&HttpSrv, uID);
     277                        char          *pszURL = ShClTransferHttpServerGetUrlA(&HttpSrv, uID, 0 /* Entry index */);
    278278                        RTTEST_CHECK(hTest, pszURL != NULL);
    279279                        RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Downloading: %s -> %s\n", pszURL, szFileTemp);
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-x11.cpp

    r100656 r100676  
    615615                    if (RT_SUCCESS(rc))
    616616                    {
    617                         char *pszURL = ShClTransferHttpServerGetUrlA(pHttpSrv, pTransfer->State.uID);
    618                         if (pszURL)
     617                        char *pszURL = NULL;
     618
     619                        uint64_t const cRoots = ShClTransferRootsCount(pTransfer);
     620                        for (uint32_t i = 0; i < cRoots; i++)
     621                        {
     622                            char *pszEntry = ShClTransferHttpServerGetUrlA(pHttpSrv, ShClTransferGetID(pTransfer), i /* Entry index */);
     623                            AssertPtrBreakStmt(pszEntry, rc = VERR_NO_MEMORY);
     624
     625                            if (i > 0)
     626                            {
     627                                rc = RTStrAAppend(&pszURL, "\n"); /* Separate entries with a newline. */
     628                                AssertRCBreak(rc);
     629                            }
     630
     631                            rc = RTStrAAppend(&pszURL, pszEntry);
     632                            AssertRCBreak(rc);
     633
     634                            RTStrFree(pszEntry);
     635                        }
     636
     637                        if (RT_SUCCESS(rc))
    619638                        {
    620639                            *ppv = pszURL;
     
    624643
    625644                            /* ppv has ownership of pszURL. */
    626 
    627                             rc = VINF_SUCCESS;
    628645                        }
    629                         else
    630                             rc = VERR_NO_MEMORY;
    631646                    }
    632647# else
Note: See TracChangeset for help on using the changeset viewer.

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