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:
ilammy 2017-04-09 02:29:50 +03:00
parent b0bc59595d
commit 907f21e720
3 changed files with 124 additions and 0 deletions

View File

@ -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]);

View File

@ -60,6 +60,10 @@ struct _wClipboard
UINT32 formatId;
UINT32 sequenceNumber;
/* clipboard file handling */
wArrayList* localFiles;
CRITICAL_SECTION lock;
};

View File

@ -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;
}