示例#1
0
RTCString DnDURIList::RootToString(const RTCString &strBasePath /* = "" */,
                                   const RTCString &strSeparator /* = "\r\n" */)
{
    RTCString strRet;
    for (size_t i = 0; i < m_lstRoot.size(); i++)
    {
        const char *pszCurRoot = m_lstRoot.at(i).c_str();
#ifdef DEBUG_andy
        LogFlowFunc(("pszCurRoot=%s\n", pszCurRoot));
#endif
        if (strBasePath.isNotEmpty())
        {
            char *pszPath = RTPathJoinA(strBasePath.c_str(), pszCurRoot);
            if (pszPath)
            {
                char *pszPathURI = RTUriFileCreate(pszPath);
                if (pszPathURI)
                {
                    strRet += RTCString(pszPathURI) + strSeparator;
#ifdef DEBUG_andy
                    LogFlowFunc(("URI: %s\n", strRet.c_str()));
#endif
                    RTStrFree(pszPathURI);
                }
                else
                    break;
                RTStrFree(pszPath);
            }
            else
                break;
        }
        else
        {
            char *pszPathURI = RTUriFileCreate(pszCurRoot);
            if (pszPathURI)
            {
                strRet += RTCString(pszPathURI) + strSeparator;
#ifdef DEBUG_andy
                LogFlowFunc(("URI: %s\n", strRet.c_str()));
#endif
                RTStrFree(pszPathURI);
            }
            else
                break;
        }
    }

    return strRet;
}
static int vbglR3DnDHGProcessURIMessages(uint32_t   uClientId,
                                         uint32_t  *puScreenId,
                                         char      *pszFormat,
                                         uint32_t   cbFormat,
                                         uint32_t  *pcbFormatRecv,
                                         void     **ppvData,
                                         uint32_t   cbData,
                                         size_t    *pcbDataRecv)
{
    /* Make a string list out of the uri data. */
    RTCList<RTCString> uriList = RTCString(static_cast<char*>(*ppvData), *pcbDataRecv - 1).split("\r\n");
    if (uriList.isEmpty())
        return VINF_SUCCESS;

    uint32_t cbTmpData = _1M * 10;
    void *pvTmpData = RTMemAlloc(cbTmpData);
    if (!pvTmpData)
        return VERR_NO_MEMORY;

    /* Create and query the drop target directory. */
    char pszDropDir[RTPATH_MAX];
    int rc = vbglR3DnDCreateDropDir(pszDropDir, sizeof(pszDropDir));
    if (RT_FAILURE(rc))
    {
        RTMemFree(pvTmpData);
        return rc;
    }

    /* Patch the old drop data with the new drop directory, so the drop target
     * can find the files. */
    RTCList<RTCString> guestUriList;
    for (size_t i = 0; i < uriList.size(); ++i)
    {
        const RTCString &strUri = uriList.at(i);
        /* Query the path component of a file URI. If this hasn't a
         * file scheme, null is returned. */
        if (char *pszFilePath = RTUriFilePath(strUri.c_str(), URI_FILE_FORMAT_AUTO))
        {
            RTCString strFullPath = RTCString().printf("%s%c%s", pszDropDir, RTPATH_SLASH, pszFilePath);
            char *pszNewUri = RTUriFileCreate(strFullPath.c_str());
            if (pszNewUri)
            {
                guestUriList.append(pszNewUri);
                RTStrFree(pszNewUri);
            }
        }
        else
            guestUriList.append(strUri);
    }

    /* Cleanup the old data and write the new data back to the event. */
    RTMemFree(*ppvData);
    RTCString newData = RTCString::join(guestUriList, "\r\n") + "\r\n";
    *ppvData = RTStrDupN(newData.c_str(), newData.length());
    *pcbDataRecv = newData.length() + 1;

    /* Lists for holding created files & directories in the case of a
     * rollback. */
    RTCList<RTCString> guestDirList;
    RTCList<RTCString> guestFileList;
    char pszPathname[RTPATH_MAX];
    uint32_t cbPathname = 0;
    bool fLoop = true;
    do
    {
        uint32_t uNextMsg;
        uint32_t cNextParms;
        rc = vbglR3DnDQueryNextHostMessageType(uClientId, &uNextMsg, &cNextParms, false);
        DO(("%Rrc - %d\n", rc , uNextMsg));
        if (RT_SUCCESS(rc))
        {
            switch(uNextMsg)
            {
                case DragAndDropSvc::HOST_DND_HG_SND_DIR:
                {
                    uint32_t fMode = 0;
                    rc = vbglR3DnDHGProcessSendDirMessage(uClientId,
                                                          pszPathname,
                                                          sizeof(pszPathname),
                                                          &cbPathname,
                                                          &fMode);
                    if (RT_SUCCESS(rc))
                    {
                        DO(("Got drop dir: %s - %o - %Rrc\n", pszPathname, fMode, rc));
                        char *pszNewDir = RTPathJoinA(pszDropDir, pszPathname);
                        rc = RTDirCreate(pszNewDir, (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRWXU, 0);
                        if (!guestDirList.contains(pszNewDir))
                            guestDirList.append(pszNewDir);
                    }
                    break;
                }
                case DragAndDropSvc::HOST_DND_HG_SND_FILE:
                {
                    uint32_t cbDataRecv;
                    uint32_t fMode = 0;
                    rc = vbglR3DnDHGProcessSendFileMessage(uClientId,
                                                           pszPathname,
                                                           sizeof(pszPathname),
                                                           &cbPathname,
                                                           pvTmpData,
                                                           cbTmpData,
                                                           &cbDataRecv,
                                                           &fMode);
                    if (RT_SUCCESS(rc))
                    {
                        char *pszNewFile = RTPathJoinA(pszDropDir, pszPathname);
                        DO(("Got drop file: %s - %d - %o - %Rrc\n", pszPathname, cbDataRecv, fMode, rc));
                        RTFILE hFile;
                        rc = RTFileOpen(&hFile, pszNewFile, RTFILE_O_WRITE | RTFILE_O_APPEND | RTFILE_O_DENY_ALL | RTFILE_O_OPEN_CREATE);
                        if (RT_SUCCESS(rc))
                        {
                            rc = RTFileSeek(hFile, 0, RTFILE_SEEK_END, NULL);
                            if (RT_SUCCESS(rc))
                            {
                                rc = RTFileWrite(hFile, pvTmpData, cbDataRecv, 0);
                                /* Valid UNIX mode? */
                                if (   RT_SUCCESS(rc)
                                    && (fMode & RTFS_UNIX_MASK))
                                    rc = RTFileSetMode(hFile, (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR);
                            }
                            RTFileClose(hFile);
                            if (!guestFileList.contains(pszNewFile))
                                guestFileList.append(pszNewFile);
                        }
                    }
                    break;
                }
                case DragAndDropSvc::HOST_DND_HG_EVT_CANCEL:
                {
                    rc = vbglR3DnDHGProcessCancelMessage(uClientId);
                    if (RT_SUCCESS(rc))
                        rc = VERR_CANCELLED;
                    /* Break out of the loop. */
                }
                default: fLoop = false; break;
            }
        } else
        {
            if (rc == VERR_NO_DATA)
                rc = VINF_SUCCESS;
            break;
        }
    }while(fLoop);

    RTMemFree(pvTmpData);
    /* Cleanup on failure or if the user has canceled. */
    if (RT_FAILURE(rc))
    {
        /* Remove any stuff created. */
        for (size_t i = 0; i < guestFileList.size(); ++i)
            RTFileDelete(guestFileList.at(i).c_str());
        for (size_t i = 0; i < guestDirList.size(); ++i)
            RTDirRemove(guestDirList.at(i).c_str());
        RTDirRemove(pszDropDir);
    }

    return rc;
}
示例#3
0
/*
 * This class is a meta message class. It doesn't consist of any own message
 * data, but handle the meta info, the data itself as well any files or
 * directories which have to be transfered to the guest.
 */
DnDHGSendDataMessage::DnDHGSendDataMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[], PFNDNDPROGRESS pfnProgressCallback, void *pvProgressUser)
  : m_cbAll(0)
  , m_cbTransfered(0)
  , m_pfnProgressCallback(pfnProgressCallback)
  , m_pvProgressUser(pvProgressUser)
{
    RTCString strNewUris;
    /* Check the format for any uri type. */
    if (hasFileUrls(static_cast<const char*>(paParms[1].u.pointer.addr), paParms[1].u.pointer.size))
    {
        DO(("old data '%s'\n", (char*)paParms[3].u.pointer.addr));
        /* The list is separated by newline (Even if only one file is
         * listed). */
        RTCList<RTCString> oldUriList = RTCString(static_cast<const char*>(paParms[3].u.pointer.addr), paParms[3].u.pointer.size).split("\r\n");
        if (!oldUriList.isEmpty())
        {
            RTCList<RTCString> newUriList;
            for (size_t i = 0; i < oldUriList.size(); ++i)
            {
                const RTCString &strUri = oldUriList.at(i);
                /* Query the path component of a file URI. If this hasn't a
                 * file scheme null is returned. */
                if (char *pszFilePath = RTUriFilePath(strUri.c_str(), URI_FILE_FORMAT_AUTO))
                {
                    /* Add the path to our internal file list (recursive in
                     * the case of a directory). */
                    if (char *pszFilename = RTPathFilename(pszFilePath))
                    {
                        char *pszNewUri = RTUriFileCreate(pszFilename);
                        if (pszNewUri)
                        {
                            newUriList.append(pszNewUri);
                            RTStrFree(pszNewUri);
                            buildFileTree(pszFilePath, pszFilename - pszFilePath);
                        }
                    }
                    RTStrFree(pszFilePath);
                }
                else
                    newUriList.append(strUri);
            }
            /* We have to change the actual DnD data. Remove any host paths and
             * just decode the filename into the new data. The guest tools will
             * add the correct path again, before sending the DnD drop event to
             * some window. */
            strNewUris = RTCString::join(newUriList, "\r\n") + "\r\n";
            /* Remark: We don't delete the old pointer here, cause this is done
             * by the caller. We just use the RTString data, which has the
             * scope of this ctor. This is enough cause the data is copied in
             * the DnDHGSendDataMessagePrivate anyway. */
            paParms[3].u.pointer.addr = (void*)strNewUris.c_str();
            paParms[3].u.pointer.size = strNewUris.length() + 1;
            paParms[4].u.uint32       = strNewUris.length() + 1;
        }
    }
    /* Add the size of the data to the todo list. */
    m_cbAll += paParms[4].u.uint32;
    /* The first message is the meta info for the data and the data itself. */
    m_pNextPathMsg = new DnDHGSendDataMessagePrivate(uMsg, cParms, paParms, &DnDHGSendDataMessage::progressCallback, this);

    DO(("new data '%s'\n", (char*)paParms[3].u.pointer.addr));
    DO(("cbAll: %u\n", m_cbAll));
    DO(("cbData: %u\n", paParms[4].u.uint32));

    for (size_t i = 0; i < m_uriList.size(); ++i)
        DO(("file: %s : %s - %o - %ld\n", m_uriList.at(i).m_strHostPath.c_str(), m_uriList.at(i).m_strGuestPath.c_str(), m_uriList.at(i).m_fMode, m_uriList.at(i).m_cbSize));
}