wClipboard/posix: basic file list handling
Here you can see an outline of our approach to handling file lists put on the clipboard. Typical usage of wClipboard by the clients sums up to doing a ClipboardSetData() call followed by a ClipboardGetData() call with appropriate format ID passed to them. Thus for files we would expect the clients to first set the local format (like "text/uri-list") and then to get the remote format (the "FileGroupDescriptorW"). MS-RDPECLIP has a concept of locally-stored list of files on the clipboard. This is modeled by clipboard->localFiles ArrayList. We need to populate this list before we serialize it into CLIPRDR_FILELIST and send it to the server. The easiest way to achieve this is a bit hacky, but it works: we populate the file list from inside the synthesizer callback registered for text/uri-list -> FileGroupDescriptorW conversion. So the client would first set the data it received from local clipboard as "text/uri-list" format, then it gets a "FileGroupDescriptorW" format, during that conversion we will prepare to serve file content requests, and in the end we provide a FILEDESCRIPTOR array to the client as the conversion result. The client will then serialize the array into CLIPRDR_FILELIST and sent it to the server. (We cannot do serialization in WinPR as WinPR should not know about cliprdr and its data formats.) The subsystems are expected to store their private structures in the clipboard->localFiles array. POSIX subsystem uses struct posix_file which currently has bare minimum of fields: the local file name (for open() and the like) and the remote file name (the one to put into FILEDESCRIPTOR).
This commit is contained in:
parent
b0bc59595d
commit
907f21e720
@ -581,6 +581,9 @@ void ClipboardDestroy(wClipboard* clipboard)
|
||||
if (!clipboard)
|
||||
return;
|
||||
|
||||
ArrayList_Free(clipboard->localFiles);
|
||||
clipboard->localFiles = NULL;
|
||||
|
||||
for (index = 0; index < clipboard->numFormats; index++)
|
||||
{
|
||||
format = &(clipboard->formats[index]);
|
||||
|
@ -60,6 +60,10 @@ struct _wClipboard
|
||||
UINT32 formatId;
|
||||
UINT32 sequenceNumber;
|
||||
|
||||
/* clipboard file handling */
|
||||
|
||||
wArrayList* localFiles;
|
||||
|
||||
CRITICAL_SECTION lock;
|
||||
};
|
||||
|
||||
|
@ -21,7 +21,13 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <winpr/clipboard.h>
|
||||
#include <winpr/collections.h>
|
||||
#include <winpr/shell.h>
|
||||
#include <winpr/string.h>
|
||||
#include <winpr/wlog.h>
|
||||
|
||||
#include "clipboard.h"
|
||||
@ -30,10 +36,121 @@
|
||||
#include "../log.h"
|
||||
#define TAG WINPR_TAG("clipboard.posix")
|
||||
|
||||
struct posix_file
|
||||
{
|
||||
char* local_name;
|
||||
WCHAR* remote_name;
|
||||
};
|
||||
|
||||
static struct posix_file* make_posix_file(const char* local_name, const WCHAR* remote_name)
|
||||
{
|
||||
struct posix_file* file = NULL;
|
||||
|
||||
file = calloc(1, sizeof(*file));
|
||||
if (!file)
|
||||
return NULL;
|
||||
|
||||
file->local_name = _strdup(local_name);
|
||||
file->remote_name = _wcsdup(remote_name);
|
||||
|
||||
if (!file->local_name || !file->remote_name)
|
||||
goto error;
|
||||
|
||||
return file;
|
||||
|
||||
error:
|
||||
free(file->local_name);
|
||||
free(file->remote_name);
|
||||
free(file);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void free_posix_file(void* the_file)
|
||||
{
|
||||
struct posix_file* file = the_file;
|
||||
|
||||
if (!file)
|
||||
return;
|
||||
|
||||
free(file->local_name);
|
||||
free(file->remote_name);
|
||||
free(file);
|
||||
}
|
||||
|
||||
static BOOL process_uri_list(const char* data, size_t length, wArrayList* files)
|
||||
{
|
||||
ArrayList_Clear(files);
|
||||
/* TBD: parse text/uri-list `data` and store it into `files` */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static FILEDESCRIPTOR* convert_local_file_list_to_filedescriptors(wArrayList* files)
|
||||
{
|
||||
/* TBD: convert `files` into a FILEDESCRIPTOR array */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void* convert_uri_list_to_filedescriptors(wClipboard* clipboard, UINT32 formatId,
|
||||
const void* data, UINT32* pSize)
|
||||
{
|
||||
FILEDESCRIPTOR* descriptors = NULL;
|
||||
|
||||
if (!clipboard || !data || !pSize)
|
||||
return NULL;
|
||||
|
||||
if (formatId != ClipboardGetFormatId(clipboard, "text/uri-list"))
|
||||
return NULL;
|
||||
|
||||
if (!process_uri_list((const char*) data, *pSize, clipboard->localFiles))
|
||||
return NULL;
|
||||
|
||||
descriptors = convert_local_file_list_to_filedescriptors(clipboard->localFiles);
|
||||
if (!descriptors)
|
||||
return NULL;
|
||||
|
||||
*pSize = ArrayList_Count(clipboard->localFiles) * sizeof(FILEDESCRIPTOR);
|
||||
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
static BOOL register_file_formats_and_synthesizers(wClipboard* clipboard)
|
||||
{
|
||||
UINT32 file_group_format_id;
|
||||
UINT32 local_file_format_id;
|
||||
|
||||
file_group_format_id = ClipboardRegisterFormat(clipboard, "FileGroupDescriptorW");
|
||||
local_file_format_id = ClipboardRegisterFormat(clipboard, "text/uri-list");
|
||||
if (!file_group_format_id || !local_file_format_id)
|
||||
goto error;
|
||||
|
||||
clipboard->localFiles = ArrayList_New(FALSE);
|
||||
if (!clipboard->localFiles)
|
||||
goto error;
|
||||
|
||||
ArrayList_Object(clipboard->localFiles)->fnObjectFree = free_posix_file;
|
||||
|
||||
if (!ClipboardRegisterSynthesizer(clipboard,
|
||||
local_file_format_id, file_group_format_id,
|
||||
convert_uri_list_to_filedescriptors))
|
||||
goto error_free_local_files;
|
||||
|
||||
return TRUE;
|
||||
|
||||
error_free_local_files:
|
||||
ArrayList_Free(clipboard->localFiles);
|
||||
clipboard->localFiles = NULL;
|
||||
error:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL ClipboardInitPosixFileSubsystem(wClipboard* clipboard)
|
||||
{
|
||||
if (!clipboard)
|
||||
return FALSE;
|
||||
|
||||
if (!register_file_formats_and_synthesizers(clipboard))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user