mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-15 00:44:19 +09:00
Merge pull request #5266 from akallabeth/file_list_synth
Added a proper synthesizer for FileGroupDescriptorW to text/uri-list
This commit is contained in:
@@ -854,6 +854,8 @@ wfClipboard* wlf_clipboard_new(wlfContext* wfc)
|
||||
clipboard->system = ClipboardCreate();
|
||||
clipboard->delegate = ClipboardGetDelegate(clipboard->system);
|
||||
clipboard->delegate->custom = clipboard;
|
||||
/* TODO: set up a filesystem base path for local URI */
|
||||
/* clipboard->delegate->basePath = "file:///tmp/foo/bar/gaga"; */
|
||||
clipboard->delegate->ClipboardFileSizeSuccess = wlf_cliprdr_clipboard_file_size_success;
|
||||
clipboard->delegate->ClipboardFileSizeFailure = wlf_cliprdr_clipboard_file_size_failure;
|
||||
clipboard->delegate->ClipboardFileRangeSuccess = wlf_cliprdr_clipboard_file_range_success;
|
||||
|
||||
@@ -1387,6 +1387,13 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext*
|
||||
dstFormatId = ClipboardGetFormatId(clipboard->system, "text/html");
|
||||
nullTerminated = TRUE;
|
||||
}
|
||||
|
||||
if (strcmp(clipboard->data_format_name, "FileGroupDescriptorW") == 0)
|
||||
{
|
||||
srcFormatId = ClipboardGetFormatId(clipboard->system, "FileGroupDescriptorW");
|
||||
dstFormatId = ClipboardGetFormatId(clipboard->system, "text/uri-list");
|
||||
nullTerminated = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1436,10 +1443,10 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext*
|
||||
|
||||
if (!pDstData)
|
||||
{
|
||||
WLog_ERR(TAG, "failed to get clipboard data in format %s [source format %s]",
|
||||
ClipboardGetFormatName(clipboard->system, dstFormatId),
|
||||
ClipboardGetFormatName(clipboard->system, srcFormatId));
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
WLog_WARN(TAG, "failed to get clipboard data in format %s [source format %s]",
|
||||
ClipboardGetFormatName(clipboard->system, dstFormatId),
|
||||
ClipboardGetFormatName(clipboard->system, srcFormatId));
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
if (nullTerminated)
|
||||
@@ -1716,6 +1723,8 @@ xfClipboard* xf_clipboard_new(xfContext* xfc)
|
||||
clipboard->incr_atom = XInternAtom(xfc->display, "INCR", FALSE);
|
||||
clipboard->delegate = ClipboardGetDelegate(clipboard->system);
|
||||
clipboard->delegate->custom = clipboard;
|
||||
/* TODO: set up a filesystem base path for local URI */
|
||||
/* clipboard->delegate->basePath = "file:///tmp/foo/bar/gaga"; */
|
||||
clipboard->delegate->ClipboardFileSizeSuccess = xf_cliprdr_clipboard_file_size_success;
|
||||
clipboard->delegate->ClipboardFileSizeFailure = xf_cliprdr_clipboard_file_size_failure;
|
||||
clipboard->delegate->ClipboardFileRangeSuccess = xf_cliprdr_clipboard_file_range_success;
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
|
||||
typedef struct _wClipboard wClipboard;
|
||||
|
||||
typedef void* (*CLIPBOARD_SYNTHESIZE_FN)(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32* pSize);
|
||||
typedef void* (*CLIPBOARD_SYNTHESIZE_FN)(wClipboard* clipboard, UINT32 formatId, const void* data,
|
||||
UINT32* pSize);
|
||||
|
||||
struct _wClipboardFileSizeRequest
|
||||
{
|
||||
@@ -50,18 +51,19 @@ struct _wClipboardDelegate
|
||||
{
|
||||
wClipboard* clipboard;
|
||||
void* custom;
|
||||
char* basePath;
|
||||
|
||||
UINT (*ClientRequestFileSize)(wClipboardDelegate*, const wClipboardFileSizeRequest*);
|
||||
UINT (*ClipboardFileSizeSuccess)(wClipboardDelegate*, const wClipboardFileSizeRequest*,
|
||||
UINT64 fileSize);
|
||||
UINT (*ClipboardFileSizeFailure)(wClipboardDelegate*, const wClipboardFileSizeRequest*,
|
||||
UINT errorCode);
|
||||
UINT(*ClientRequestFileSize)(wClipboardDelegate*, const wClipboardFileSizeRequest*);
|
||||
UINT(*ClipboardFileSizeSuccess)(wClipboardDelegate*, const wClipboardFileSizeRequest*,
|
||||
UINT64 fileSize);
|
||||
UINT(*ClipboardFileSizeFailure)(wClipboardDelegate*, const wClipboardFileSizeRequest*,
|
||||
UINT errorCode);
|
||||
|
||||
UINT (*ClientRequestFileRange)(wClipboardDelegate*, const wClipboardFileRangeRequest*);
|
||||
UINT (*ClipboardFileRangeSuccess)(wClipboardDelegate*, const wClipboardFileRangeRequest*,
|
||||
const BYTE* data, UINT32 size);
|
||||
UINT (*ClipboardFileRangeFailure)(wClipboardDelegate*, const wClipboardFileRangeRequest*,
|
||||
UINT errorCode);
|
||||
UINT(*ClientRequestFileRange)(wClipboardDelegate*, const wClipboardFileRangeRequest*);
|
||||
UINT(*ClipboardFileRangeSuccess)(wClipboardDelegate*, const wClipboardFileRangeRequest*,
|
||||
const BYTE* data, UINT32 size);
|
||||
UINT(*ClipboardFileRangeFailure)(wClipboardDelegate*, const wClipboardFileRangeRequest*,
|
||||
UINT errorCode);
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -80,19 +82,20 @@ WINPR_API UINT32 ClipboardGetRegisteredFormatIds(wClipboard* clipboard, UINT32**
|
||||
WINPR_API UINT32 ClipboardRegisterFormat(wClipboard* clipboard, const char* name);
|
||||
|
||||
WINPR_API BOOL ClipboardRegisterSynthesizer(wClipboard* clipboard, UINT32 formatId,
|
||||
UINT32 syntheticId, CLIPBOARD_SYNTHESIZE_FN pfnSynthesize);
|
||||
UINT32 syntheticId, CLIPBOARD_SYNTHESIZE_FN pfnSynthesize);
|
||||
|
||||
WINPR_API UINT32 ClipboardGetFormatId(wClipboard* clipboard, const char* name);
|
||||
WINPR_API const char* ClipboardGetFormatName(wClipboard* clipboard, UINT32 formatId);
|
||||
WINPR_API void* ClipboardGetData(wClipboard* clipboard, UINT32 formatId, UINT32* pSize);
|
||||
WINPR_API BOOL ClipboardSetData(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32 size);
|
||||
WINPR_API BOOL ClipboardSetData(wClipboard* clipboard, UINT32 formatId, const void* data,
|
||||
UINT32 size);
|
||||
|
||||
WINPR_API UINT64 ClipboardGetOwner(wClipboard* clipboard);
|
||||
WINPR_API void ClipboardSetOwner(wClipboard* clipboard, UINT64 ownerId);
|
||||
|
||||
WINPR_API wClipboardDelegate* ClipboardGetDelegate(wClipboard* clipboard);
|
||||
|
||||
WINPR_API wClipboard* ClipboardCreate();
|
||||
WINPR_API wClipboard* ClipboardCreate(void);
|
||||
WINPR_API void ClipboardDestroy(wClipboard* clipboard);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -373,6 +373,7 @@ BOOL ClipboardInitFormats(wClipboard* clipboard)
|
||||
ZeroMemory(format, sizeof(wClipboardFormat));
|
||||
format->formatId = formatId;
|
||||
format->formatName = _strdup(CF_STANDARD_STRINGS[formatId]);
|
||||
|
||||
if (!format->formatName)
|
||||
goto error;
|
||||
}
|
||||
@@ -381,13 +382,14 @@ BOOL ClipboardInitFormats(wClipboard* clipboard)
|
||||
goto error;
|
||||
|
||||
return TRUE;
|
||||
|
||||
error:
|
||||
|
||||
for (formatId = 0; formatId < clipboard->numFormats; formatId++)
|
||||
{
|
||||
free(clipboard->formats[formatId].formatName);
|
||||
free(clipboard->formats[formatId].synthesizers);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -522,13 +524,12 @@ wClipboardDelegate* ClipboardGetDelegate(wClipboard* clipboard)
|
||||
return &clipboard->delegate;
|
||||
}
|
||||
|
||||
void ClipboardInitLocalFileSubsystem(wClipboard* clipboard)
|
||||
static void ClipboardInitLocalFileSubsystem(wClipboard* clipboard)
|
||||
{
|
||||
/*
|
||||
* There can be only one local file subsystem active.
|
||||
* Return as soon as initialization succeeds.
|
||||
*/
|
||||
|
||||
#ifdef WITH_WCLIPBOARD_POSIX
|
||||
if (ClipboardInitPosixFileSubsystem(clipboard))
|
||||
{
|
||||
@@ -539,16 +540,16 @@ void ClipboardInitLocalFileSubsystem(wClipboard* clipboard)
|
||||
{
|
||||
WLog_WARN(TAG, "failed to initialize POSIX local file subsystem");
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
WLog_INFO(TAG, "failed to initialize local file subsystem, file transfer not available");
|
||||
}
|
||||
|
||||
wClipboard* ClipboardCreate()
|
||||
wClipboard* ClipboardCreate(void)
|
||||
{
|
||||
wClipboard* clipboard;
|
||||
|
||||
clipboard = (wClipboard*) calloc(1, sizeof(wClipboard));
|
||||
|
||||
if (!clipboard)
|
||||
return NULL;
|
||||
|
||||
@@ -560,9 +561,9 @@ wClipboard* ClipboardCreate()
|
||||
|
||||
clipboard->numFormats = 0;
|
||||
clipboard->maxFormats = 64;
|
||||
|
||||
clipboard->formats = (wClipboardFormat*)
|
||||
calloc(clipboard->maxFormats, sizeof(wClipboardFormat));
|
||||
calloc(clipboard->maxFormats, sizeof(wClipboardFormat));
|
||||
|
||||
if (!clipboard->formats)
|
||||
goto error_free_lock;
|
||||
|
||||
@@ -570,11 +571,8 @@ wClipboard* ClipboardCreate()
|
||||
goto error_free_formats;
|
||||
|
||||
clipboard->delegate.clipboard = clipboard;
|
||||
|
||||
ClipboardInitLocalFileSubsystem(clipboard);
|
||||
|
||||
return clipboard;
|
||||
|
||||
error_free_formats:
|
||||
free(clipboard->formats);
|
||||
error_free_lock:
|
||||
|
||||
@@ -575,6 +575,88 @@ static void* convert_uri_list_to_filedescriptors(wClipboard* clipboard, UINT32 f
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
static void* convert_filedescriptors_to_uri_list(wClipboard* clipboard, UINT32 formatId,
|
||||
const void* data, UINT32* pSize)
|
||||
{
|
||||
const FILEDESCRIPTOR* descriptors;
|
||||
UINT32 nrDescriptors = 0;
|
||||
size_t count, x, alloc, pos, baseLength = 0;
|
||||
const char* src = (const char*) data;
|
||||
char* dst;
|
||||
|
||||
if (!clipboard || !data || !pSize)
|
||||
return NULL;
|
||||
|
||||
if (*pSize < sizeof(UINT32))
|
||||
return NULL;
|
||||
|
||||
if (clipboard->delegate.basePath)
|
||||
baseLength = strnlen(clipboard->delegate.basePath, MAX_PATH);
|
||||
|
||||
if (baseLength < 1)
|
||||
return NULL;
|
||||
|
||||
if (clipboard->delegate.ClientRequestFileSize)
|
||||
nrDescriptors = (UINT32)(src[3] << 24) | (UINT32)(src[2] << 16) | (UINT32)(src[1] << 8) |
|
||||
(src[0] & 0xFF);
|
||||
|
||||
count = (*pSize - 4) / sizeof(FILEDESCRIPTOR);
|
||||
|
||||
if ((count < 1) || (count != nrDescriptors))
|
||||
return NULL;
|
||||
|
||||
descriptors = (const FILEDESCRIPTOR*)&src[4];
|
||||
|
||||
if (formatId != ClipboardGetFormatId(clipboard, "FileGroupDescriptorW"))
|
||||
return NULL;
|
||||
|
||||
alloc = 0;
|
||||
|
||||
/* Get total size of file names */
|
||||
for (x = 0; x < count; x++)
|
||||
alloc += _wcsnlen(descriptors[x].cFileName, ARRAYSIZE(descriptors[x].cFileName));
|
||||
|
||||
/* Append a prefix file:// and postfix \r\n for each file */
|
||||
alloc += (sizeof("/\r\n") + baseLength) * count;
|
||||
dst = calloc(alloc, sizeof(char));
|
||||
|
||||
if (!dst)
|
||||
return NULL;
|
||||
|
||||
pos = 0;
|
||||
|
||||
for (x = 0; x < count; x++)
|
||||
{
|
||||
int rc;
|
||||
const FILEDESCRIPTOR* cur = &descriptors[x];
|
||||
size_t curLen = _wcsnlen(cur->cFileName, ARRAYSIZE(cur->cFileName));
|
||||
char* curName = NULL;
|
||||
rc = ConvertFromUnicode(CP_UTF8, 0, cur->cFileName, (int)curLen, &curName, 0, NULL, NULL);
|
||||
|
||||
if (rc != (int)curLen)
|
||||
{
|
||||
free(curName);
|
||||
free(dst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = _snprintf(&dst[pos], alloc - pos, "%s/%s\r\n", clipboard->delegate.basePath, curName);
|
||||
free(curName);
|
||||
|
||||
if (rc < 0)
|
||||
{
|
||||
free(dst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pos += (size_t)rc;
|
||||
}
|
||||
|
||||
*pSize = (UINT32)alloc;
|
||||
clipboard->fileListSequenceNumber = clipboard->sequenceNumber;
|
||||
return dst;
|
||||
}
|
||||
|
||||
static BOOL register_file_formats_and_synthesizers(wClipboard* clipboard)
|
||||
{
|
||||
UINT32 file_group_format_id;
|
||||
@@ -597,6 +679,11 @@ static BOOL register_file_formats_and_synthesizers(wClipboard* clipboard)
|
||||
convert_uri_list_to_filedescriptors))
|
||||
goto error_free_local_files;
|
||||
|
||||
if (!ClipboardRegisterSynthesizer(clipboard,
|
||||
file_group_format_id, local_file_format_id,
|
||||
convert_filedescriptors_to_uri_list))
|
||||
goto error_free_local_files;
|
||||
|
||||
return TRUE;
|
||||
error_free_local_files:
|
||||
ArrayList_Free(clipboard->localFiles);
|
||||
|
||||
Reference in New Issue
Block a user