1
/*********************************************************
2
* Copyright (C) 2007 VMware, Inc. All rights reserved.
4
* This program is free software; you can redistribute it and/or modify it
5
* under the terms of the GNU Lesser General Public License as published
6
* by the Free Software Foundation version 2.1 and no later version.
8
* This program is distributed in the hope that it will be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
11
* License for more details.
13
* You should have received a copy of the GNU Lesser General Public License
14
* along with this program; if not, write to the Free Software Foundation, Inc.,
15
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17
*********************************************************/
22
* Implementation of common layer CopyPaste object for guest.
25
#include "copyPaste.hh"
26
#include "copyPasteRpcV3.hh"
27
#include "dndFileList.hh"
34
#include "cpNameUtil.h"
36
#include "dndClipboard.h"
40
*---------------------------------------------------------------------
42
* CopyPaste::CopyPaste --
44
* Constructor for CopyPaste.
52
*---------------------------------------------------------------------
55
CopyPaste::CopyPaste(void) // IN
57
mVmxCopyPasteVersion(0)
59
mState = CPSTATE_INVALID;
64
*---------------------------------------------------------------------
66
* CopyPaste::~CopyPaste --
76
*---------------------------------------------------------------------
79
CopyPaste::~CopyPaste(void)
86
*-----------------------------------------------------------------------------
88
* CopyPaste::VmxCopyPasteVersionChanged --
90
* Vmx CopyPaste version changed so should create corresponding Rpc and
91
* register callbacks for signals if version changed.
99
*-----------------------------------------------------------------------------
103
CopyPaste::VmxCopyPasteVersionChanged(struct RpcIn *rpcIn, // IN
104
uint32 version) // IN
106
/* Do nothing if version is not changed. */
107
if (mVmxCopyPasteVersion == version) {
111
mVmxCopyPasteVersion = version;
112
Debug("%s: Version: %d", __FUNCTION__, version);
117
mState = CPSTATE_INVALID;
118
Hostinfo_GetTimeOfDay(&mStateChangeTime);
123
/* Here should create CopyPasteRpcV2 for version 1 & 2. */
126
mRpc = new CopyPasteRpcV3(rpcIn);
129
Debug("%s: got unsupported guest CopyPaste version %u.\n",
130
__FUNCTION__, version);
135
mRpc->ghGetClipboardChanged.connect(
136
sigc::mem_fun(this, &CopyPaste::OnGetLocalClipboard));
137
mRpc->hgSetClipboardChanged.connect(
138
sigc::mem_fun(this, &CopyPaste::OnGetRemoteClipboardDone));
139
mRpc->hgFileCopyDoneChanged.connect(
140
sigc::mem_fun(this, &CopyPaste::OnHGFileCopyDone));
141
mState = CPSTATE_READY;
147
*----------------------------------------------------------------------
149
* CopyPaste::OnGetRemoteClipboardDone --
151
* Got clipboard data from host. Put it into local buffer and
152
* inform UI to process the clipboard data.
160
*----------------------------------------------------------------------
164
CopyPaste::OnGetRemoteClipboardDone(const CPClipboard *clip) // IN: new clipboard
166
newClipboard.emit(clip);
167
mState = CPSTATE_READY;
168
Hostinfo_GetTimeOfDay(&mStateChangeTime);
173
*----------------------------------------------------------------------
175
* CopyPaste::OnGetLocalClipboard --
177
* Host is asking for guest clipboard data. Try to get it from local
178
* UI and send to host with GHGetClipboardDone.
186
*----------------------------------------------------------------------
190
CopyPaste::OnGetLocalClipboard(void)
195
CPClipboard_Init(&clip);
196
ready = localGetClipboard.emit(&clip);
198
* if caller decided to handle this asyncronously, it is responsible for
199
* calling SetRemoteClipboard() when it has completed. Otherwise, call it
203
SetRemoteClipboard(&clip);
205
CPClipboard_Destroy(&clip);
210
*----------------------------------------------------------------------
212
* CopyPaste::OnHGFileCopyDone --
214
* Host finished file copy. Inform UI to remove the block.
222
*----------------------------------------------------------------------
226
CopyPaste::OnHGFileCopyDone(bool success)
228
if (!success && !mStagingDir.empty()) {
229
/* Delete all files if host canceled the file transfer. */
230
DnD_DeleteStagingFiles(mStagingDir.c_str(), FALSE);
233
localGetFilesDoneChanged.emit(success);
238
*----------------------------------------------------------------------------
240
* CopyPaste::SetRemoteClipboard --
242
* Sets the internal clipboard. Also synchronizes remote clipboard with
243
* the guest clipboard.
246
* True if success, false otherwise.
251
*----------------------------------------------------------------------------
255
CopyPaste::SetRemoteClipboard(const CPClipboard* clip) // IN: new clipboard
258
Debug("%s: no valid rpc, guest version is %u.\n",
259
__FUNCTION__, mVmxCopyPasteVersion);
263
if (mState == CPSTATE_INVALID) {
264
Debug("%s: Invalid state.", __FUNCTION__);
268
if (!IsCopyPasteAllowed()) {
269
Debug("%s: CopyPasteAllowed() returned false.", __FUNCTION__);
273
/* Send clipboard data to remote side. */
274
mRpc->GHGetClipboardDone(clip);
281
*----------------------------------------------------------------------------
283
* CopyPaste::GetFiles --
285
* Gets the files that are referenced on the clipboard.
288
* The destination directory if we can start file copy, otherwise empty
294
*----------------------------------------------------------------------------
298
CopyPaste::GetFiles(std::string dir) // IN: suggested destination directory
302
char cpName[FILE_MAXPATH];
305
if (mState == CPSTATE_INVALID) {
306
Debug("%s: Invalid state.", __FUNCTION__);
310
/* Setup staging directory. */
311
destDir = SetupDestDir(dir);
312
if (destDir.empty()) {
316
/* XXX Here should first convert encoding to precomposed UTF8. */
318
/* Convert staging name to CP format. */
319
cpNameSize = CPNameUtil_ConvertToRoot(destDir.c_str(),
322
if (cpNameSize < 0) {
323
Debug("%s: Error, could not convert to CPName.\n", __FUNCTION__);
327
if (!mRpc->HGStartFileCopy(cpName, cpNameSize)) {
331
mStagingDir = destDir;
338
*----------------------------------------------------------------------------
340
* CopyPaste::SetupDestDir --
342
* Creates a directory for file transfer. If the destination
343
* dir is provided, we will attempt to copy files to the directory.
345
* Input directory will be in local format.
348
* The destination directory on success, an empty string on failure.
353
*----------------------------------------------------------------------------
357
CopyPaste::SetupDestDir(const std::string &destDir) // IN:
359
static const std::string failDir = "";
361
if (!destDir.empty() && File_Exists(destDir.c_str())) {
362
mStagingDir = destDir;
363
const char *lastSep = Str_Strrchr(mStagingDir.c_str(), DIRSEPC);
364
if (lastSep && lastSep[1] != '\0') {
365
mStagingDir += DIRSEPS;
372
newDir = DnD_CreateStagingDirectory();
373
if (newDir != NULL) {
374
mStagingDir = newDir;
376
char *lastSep = Str_Strrchr(newDir, DIRSEPC);
377
if (lastSep && lastSep[1] != '\0') {
378
mStagingDir += DIRSEPS;
381
Debug("%s: destdir: %s", __FUNCTION__, mStagingDir.c_str());
385
Debug("%s: destdir not created", __FUNCTION__);