cliprdr: Fix an issue with file format filtering on Windows
This PR fixes an issue caused by clipboard format filtering which discarded all formats but `FileGroupDescriptorW` to enable clipboard file transfer. However at least on windows we also need `FileContents` to be placed in the clipboard to make file transfer work correctly. The PR also unifies list filtering into a single functions instead of having two different functions.
This commit is contained in:
parent
3fd78adaed
commit
3b9a19e993
@ -35,68 +35,71 @@
|
||||
#include "cliprdr_format.h"
|
||||
#include "../cliprdr_common.h"
|
||||
|
||||
static BOOL cliprdr_filter_server_format_list(CLIPRDR_FORMAT_LIST* list, const UINT32 mask)
|
||||
CLIPRDR_FORMAT_LIST cliprdr_filter_format_list(const CLIPRDR_FORMAT_LIST* list, const UINT32 mask,
|
||||
const UINT32 checkMask)
|
||||
{
|
||||
const UINT32 all = CLIPRDR_FLAG_REMOTE_TO_LOCAL | CLIPRDR_FLAG_REMOTE_TO_LOCAL_FILES;
|
||||
const UINT32 maskData =
|
||||
checkMask & (CLIPRDR_FLAG_LOCAL_TO_REMOTE | CLIPRDR_FLAG_REMOTE_TO_LOCAL);
|
||||
const UINT32 maskFiles =
|
||||
checkMask & (CLIPRDR_FLAG_LOCAL_TO_REMOTE_FILES | CLIPRDR_FLAG_REMOTE_TO_LOCAL_FILES);
|
||||
WINPR_ASSERT(list);
|
||||
|
||||
if ((mask & all) == all)
|
||||
return TRUE;
|
||||
CLIPRDR_FORMAT_LIST filtered = { 0 };
|
||||
filtered.common.msgType = CB_FORMAT_LIST;
|
||||
filtered.numFormats = list->numFormats;
|
||||
filtered.formats = calloc(filtered.numFormats, sizeof(CLIPRDR_FORMAT_LIST));
|
||||
|
||||
if ((mask & CLIPRDR_FLAG_REMOTE_TO_LOCAL_FILES) != 0)
|
||||
size_t wpos = 0;
|
||||
if ((mask & checkMask) == checkMask)
|
||||
{
|
||||
const CLIPRDR_FORMAT* files = NULL;
|
||||
for (size_t x = 0; x < list->numFormats; x++)
|
||||
{
|
||||
CLIPRDR_FORMAT* format = &list->formats[x];
|
||||
const CLIPRDR_FORMAT* format = &list->formats[x];
|
||||
CLIPRDR_FORMAT* cur = &filtered.formats[x];
|
||||
cur->formatId = format->formatId;
|
||||
if (format->formatName)
|
||||
cur->formatName = _strdup(format->formatName);
|
||||
wpos++;
|
||||
}
|
||||
}
|
||||
else if ((mask & maskFiles) != 0)
|
||||
{
|
||||
for (size_t x = 0; x < list->numFormats; x++)
|
||||
{
|
||||
const CLIPRDR_FORMAT* format = &list->formats[x];
|
||||
CLIPRDR_FORMAT* cur = &filtered.formats[wpos];
|
||||
|
||||
if (!format->formatName)
|
||||
continue;
|
||||
if (strcmp(format->formatName, type_FileGroupDescriptorW) == 0)
|
||||
files = format;
|
||||
else
|
||||
if (strcmp(format->formatName, type_FileGroupDescriptorW) == 0 ||
|
||||
strcmp(format->formatName, type_FileContents) == 0)
|
||||
{
|
||||
free(format->formatName);
|
||||
format->formatName = NULL;
|
||||
cur->formatId = format->formatId;
|
||||
cur->formatName = _strdup(format->formatName);
|
||||
wpos++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!files)
|
||||
list->numFormats = 0;
|
||||
else
|
||||
{
|
||||
list->numFormats = 1;
|
||||
list->formats[0] = *files;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if ((mask & CLIPRDR_FLAG_REMOTE_TO_LOCAL) != 0)
|
||||
else if ((mask & maskData) != 0)
|
||||
{
|
||||
BOOL move = FALSE;
|
||||
for (size_t x = 0; x < list->numFormats; x++)
|
||||
{
|
||||
CLIPRDR_FORMAT* format = &list->formats[x];
|
||||
const CLIPRDR_FORMAT* format = &list->formats[x];
|
||||
CLIPRDR_FORMAT* cur = &filtered.formats[wpos];
|
||||
|
||||
if (move)
|
||||
if (!format->formatName ||
|
||||
(strcmp(format->formatName, type_FileGroupDescriptorW) != 0 &&
|
||||
strcmp(format->formatName, type_FileContents) != 0))
|
||||
{
|
||||
CLIPRDR_FORMAT* last = &list->formats[x - 1];
|
||||
*last = *format;
|
||||
}
|
||||
else if (!format->formatName)
|
||||
continue;
|
||||
else if (strcmp(format->formatName, type_FileGroupDescriptorW) == 0)
|
||||
{
|
||||
move = TRUE;
|
||||
free(format->formatName);
|
||||
format->formatName = NULL;
|
||||
cur->formatId = format->formatId;
|
||||
if (format->formatName)
|
||||
cur->formatName = _strdup(format->formatName);
|
||||
wpos++;
|
||||
}
|
||||
}
|
||||
if (move)
|
||||
list->numFormats -= 1;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
filtered.numFormats = wpos;
|
||||
return filtered;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -108,6 +111,7 @@ UINT cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 data
|
||||
UINT16 msgFlags)
|
||||
{
|
||||
CLIPRDR_FORMAT_LIST formatList = { 0 };
|
||||
CLIPRDR_FORMAT_LIST filteredFormatList = { 0 };
|
||||
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
|
||||
@ -120,19 +124,22 @@ UINT cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 data
|
||||
|
||||
const UINT32 mask =
|
||||
freerdp_settings_get_uint32(context->rdpcontext->settings, FreeRDP_ClipboardFeatureMask);
|
||||
if (!cliprdr_filter_server_format_list(&formatList, mask))
|
||||
filteredFormatList = cliprdr_filter_format_list(
|
||||
&formatList, mask, CLIPRDR_FLAG_REMOTE_TO_LOCAL | CLIPRDR_FLAG_REMOTE_TO_LOCAL_FILES);
|
||||
if (filteredFormatList.numFormats == 0)
|
||||
goto error_out;
|
||||
|
||||
WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatList: numFormats: %" PRIu32 "",
|
||||
formatList.numFormats);
|
||||
filteredFormatList.numFormats);
|
||||
|
||||
if (context->ServerFormatList)
|
||||
{
|
||||
if ((error = context->ServerFormatList(context, &formatList)))
|
||||
if ((error = context->ServerFormatList(context, &filteredFormatList)))
|
||||
WLog_ERR(TAG, "ServerFormatList failed with error %" PRIu32 "", error);
|
||||
}
|
||||
|
||||
error_out:
|
||||
cliprdr_free_format_list(&filteredFormatList);
|
||||
cliprdr_free_format_list(&formatList);
|
||||
return error;
|
||||
}
|
||||
|
@ -31,5 +31,7 @@ UINT cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, wStream* s, UIN
|
||||
UINT16 msgFlags);
|
||||
UINT cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen,
|
||||
UINT16 msgFlags);
|
||||
CLIPRDR_FORMAT_LIST cliprdr_filter_format_list(const CLIPRDR_FORMAT_LIST* list, const UINT32 mask,
|
||||
const UINT32 checkMask);
|
||||
|
||||
#endif /* FREERDP_CHANNEL_CLIPRDR_CLIENT_FORMAT_H */
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "../cliprdr_common.h"
|
||||
|
||||
const char* type_FileGroupDescriptorW = "FileGroupDescriptorW";
|
||||
const char* type_FileContents = "FileContents";
|
||||
|
||||
static const char* CB_MSG_TYPE_STRINGS(UINT32 type)
|
||||
{
|
||||
@ -660,68 +661,6 @@ static UINT cliprdr_temp_directory(CliprdrClientContext* context,
|
||||
return cliprdr_packet_send(cliprdr, s);
|
||||
}
|
||||
|
||||
static CLIPRDR_FORMAT_LIST cliprdr_filter_local_format_list(const CLIPRDR_FORMAT_LIST* list,
|
||||
const UINT32 mask)
|
||||
{
|
||||
const UINT32 all = CLIPRDR_FLAG_LOCAL_TO_REMOTE | CLIPRDR_FLAG_LOCAL_TO_REMOTE_FILES;
|
||||
WINPR_ASSERT(list);
|
||||
|
||||
CLIPRDR_FORMAT_LIST filtered = { 0 };
|
||||
filtered.common.msgType = CB_FORMAT_LIST;
|
||||
filtered.numFormats = list->numFormats;
|
||||
filtered.formats = calloc(filtered.numFormats, sizeof(CLIPRDR_FORMAT_LIST));
|
||||
|
||||
size_t wpos = 0;
|
||||
if ((mask & all) == all)
|
||||
{
|
||||
for (size_t x = 0; x < list->numFormats; x++)
|
||||
{
|
||||
const CLIPRDR_FORMAT* format = &list->formats[x];
|
||||
CLIPRDR_FORMAT* cur = &filtered.formats[x];
|
||||
cur->formatId = format->formatId;
|
||||
if (format->formatName)
|
||||
cur->formatName = _strdup(format->formatName);
|
||||
wpos++;
|
||||
}
|
||||
}
|
||||
else if ((mask & CLIPRDR_FLAG_LOCAL_TO_REMOTE_FILES) != 0)
|
||||
{
|
||||
for (size_t x = 0; x < list->numFormats; x++)
|
||||
{
|
||||
const CLIPRDR_FORMAT* format = &list->formats[x];
|
||||
CLIPRDR_FORMAT* cur = &filtered.formats[wpos];
|
||||
|
||||
if (!format->formatName)
|
||||
continue;
|
||||
if (strcmp(format->formatName, type_FileGroupDescriptorW) == 0)
|
||||
{
|
||||
cur->formatId = format->formatId;
|
||||
cur->formatName = _strdup(format->formatName);
|
||||
wpos++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((mask & CLIPRDR_FLAG_LOCAL_TO_REMOTE) != 0)
|
||||
{
|
||||
for (size_t x = 0; x < list->numFormats; x++)
|
||||
{
|
||||
const CLIPRDR_FORMAT* format = &list->formats[x];
|
||||
CLIPRDR_FORMAT* cur = &filtered.formats[wpos];
|
||||
|
||||
if (!format->formatName || (strcmp(format->formatName, type_FileGroupDescriptorW) != 0))
|
||||
{
|
||||
cur->formatId = format->formatId;
|
||||
if (format->formatName)
|
||||
cur->formatName = _strdup(format->formatName);
|
||||
wpos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
filtered.numFormats = wpos;
|
||||
return filtered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
@ -741,7 +680,8 @@ static UINT cliprdr_client_format_list(CliprdrClientContext* context,
|
||||
|
||||
const UINT32 mask =
|
||||
freerdp_settings_get_uint32(context->rdpcontext->settings, FreeRDP_ClipboardFeatureMask);
|
||||
CLIPRDR_FORMAT_LIST filterList = cliprdr_filter_local_format_list(formatList, mask);
|
||||
CLIPRDR_FORMAT_LIST filterList = cliprdr_filter_format_list(
|
||||
formatList, mask, CLIPRDR_FLAG_LOCAL_TO_REMOTE | CLIPRDR_FLAG_LOCAL_TO_REMOTE_FILES);
|
||||
|
||||
/* Allow initial format list from monitor ready, but ignore later attempts */
|
||||
if ((filterList.numFormats == 0) && cliprdr->initialFormatListSent)
|
||||
|
@ -56,5 +56,6 @@ CliprdrClientContext* cliprdr_get_client_interface(cliprdrPlugin* cliprdr);
|
||||
UINT cliprdr_send_error_response(cliprdrPlugin* cliprdr, UINT16 type);
|
||||
|
||||
extern const char* type_FileGroupDescriptorW;
|
||||
extern const char* type_FileContents;
|
||||
|
||||
#endif /* FREERDP_CHANNEL_CLIPRDR_CLIENT_MAIN_H */
|
||||
|
Loading…
Reference in New Issue
Block a user