[channels,cliprdr] implement client clipboard direction filter
* Filter remote -> local or local -> remote clipboard depending on setting. * Filter remote -> local or local -> remote file clipboard depending on setting.
This commit is contained in:
parent
7288680bdd
commit
98fb56b767
@ -26,6 +26,8 @@
|
||||
#include <winpr/print.h>
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/settings.h>
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/client/cliprdr.h>
|
||||
|
||||
@ -33,6 +35,70 @@
|
||||
#include "cliprdr_format.h"
|
||||
#include "../cliprdr_common.h"
|
||||
|
||||
static BOOL cliprdr_filter_server_format_list(CLIPRDR_FORMAT_LIST* list, const UINT32 mask)
|
||||
{
|
||||
const UINT32 all = CLIPRDR_FLAG_REMOTE_TO_LOCAL | CLIPRDR_FLAG_REMOTE_TO_LOCAL_FILES;
|
||||
WINPR_ASSERT(list);
|
||||
|
||||
if ((mask & all) == all)
|
||||
return TRUE;
|
||||
|
||||
if ((mask & CLIPRDR_FLAG_REMOTE_TO_LOCAL_FILES) != 0)
|
||||
{
|
||||
const CLIPRDR_FORMAT* files = NULL;
|
||||
for (size_t x = 0; x < list->numFormats; x++)
|
||||
{
|
||||
CLIPRDR_FORMAT* format = &list->formats[x];
|
||||
|
||||
if (!format->formatName)
|
||||
continue;
|
||||
if (strcmp(format->formatName, type_FileGroupDescriptorW) == 0)
|
||||
files = format;
|
||||
else
|
||||
{
|
||||
free(format->formatName);
|
||||
format->formatName = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!files)
|
||||
list->numFormats = 0;
|
||||
else
|
||||
{
|
||||
list->numFormats = 1;
|
||||
list->formats[0] = *files;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if ((mask & CLIPRDR_FLAG_REMOTE_TO_LOCAL) != 0)
|
||||
{
|
||||
BOOL move = FALSE;
|
||||
for (size_t x = 0; x < list->numFormats; x++)
|
||||
{
|
||||
CLIPRDR_FORMAT* format = &list->formats[x];
|
||||
|
||||
if (move)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (move)
|
||||
list->numFormats -= 1;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
@ -52,6 +118,11 @@ UINT cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 data
|
||||
if ((error = cliprdr_read_format_list(s, &formatList, cliprdr->useLongFormatNames)))
|
||||
goto error_out;
|
||||
|
||||
const UINT32 mask =
|
||||
freerdp_settings_get_uint32(context->rdpcontext->settings, FreeRDP_ClipboardFeatureMask);
|
||||
if (!cliprdr_filter_server_format_list(&formatList, mask))
|
||||
goto error_out;
|
||||
|
||||
WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatList: numFormats: %" PRIu32 "",
|
||||
formatList.numFormats);
|
||||
|
||||
@ -112,6 +183,13 @@ UINT cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, wStream* s, UIN
|
||||
if ((error = cliprdr_read_format_data_request(s, &formatDataRequest)))
|
||||
return error;
|
||||
|
||||
const UINT32 mask =
|
||||
freerdp_settings_get_uint32(context->rdpcontext->settings, FreeRDP_ClipboardFeatureMask);
|
||||
if ((mask & (CLIPRDR_FLAG_LOCAL_TO_REMOTE | CLIPRDR_FLAG_LOCAL_TO_REMOTE_FILES)) == 0)
|
||||
{
|
||||
return cliprdr_send_error_response(cliprdr, CB_FORMAT_DATA_RESPONSE);
|
||||
}
|
||||
|
||||
context->lastRequestedFormatId = formatDataRequest.requestedFormatId;
|
||||
IFCALLRET(context->ServerFormatDataRequest, error, context, &formatDataRequest);
|
||||
if (error)
|
||||
@ -141,6 +219,15 @@ UINT cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, wStream* s, UI
|
||||
if ((error = cliprdr_read_format_data_response(s, &formatDataResponse)))
|
||||
return error;
|
||||
|
||||
const UINT32 mask =
|
||||
freerdp_settings_get_uint32(context->rdpcontext->settings, FreeRDP_ClipboardFeatureMask);
|
||||
if ((mask & (CLIPRDR_FLAG_REMOTE_TO_LOCAL | CLIPRDR_FLAG_REMOTE_TO_LOCAL_FILES)) == 0)
|
||||
{
|
||||
WLog_WARN(TAG,
|
||||
"Received ServerFormatDataResponse but remote -> local clipboard is disabled");
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
IFCALLRET(context->ServerFormatDataResponse, error, context, &formatDataResponse);
|
||||
if (error)
|
||||
WLog_ERR(TAG, "ServerFormatDataResponse failed with error %" PRIu32 "!", error);
|
||||
|
@ -38,6 +38,8 @@
|
||||
#include "cliprdr_format.h"
|
||||
#include "../cliprdr_common.h"
|
||||
|
||||
const char* type_FileGroupDescriptorW = "FileGroupDescriptorW";
|
||||
|
||||
static const char* CB_MSG_TYPE_STRINGS(UINT32 type)
|
||||
{
|
||||
switch (type)
|
||||
@ -124,6 +126,18 @@ static UINT cliprdr_packet_send(cliprdrPlugin* cliprdr, wStream* s)
|
||||
return status;
|
||||
}
|
||||
|
||||
UINT cliprdr_send_error_response(cliprdrPlugin* cliprdr, UINT16 type)
|
||||
{
|
||||
wStream* s = cliprdr_packet_new(type, CB_RESPONSE_FAIL, 0);
|
||||
if (!s)
|
||||
{
|
||||
WLog_ERR(TAG, "cliprdr_packet_new failed!");
|
||||
return ERROR_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
return cliprdr_packet_send(cliprdr, s);
|
||||
}
|
||||
|
||||
static void cliprdr_print_general_capability_flags(UINT32 flags)
|
||||
{
|
||||
WLog_DBG(TAG, "generalFlags (0x%08" PRIX32 ") {", flags);
|
||||
@ -324,6 +338,13 @@ static UINT cliprdr_process_filecontents_request(cliprdrPlugin* cliprdr, wStream
|
||||
if ((error = cliprdr_read_file_contents_request(s, &request)))
|
||||
return error;
|
||||
|
||||
const UINT32 mask =
|
||||
freerdp_settings_get_uint32(context->rdpcontext->settings, FreeRDP_ClipboardFeatureMask);
|
||||
if ((mask & (CLIPRDR_FLAG_LOCAL_TO_REMOTE_FILES)) == 0)
|
||||
{
|
||||
WLog_WARN(TAG, "local -> remote file copy disabled, ignoring request");
|
||||
return cliprdr_send_error_response(cliprdr, CB_FILECONTENTS_RESPONSE);
|
||||
}
|
||||
IFCALLRET(context->ServerFileContentsRequest, error, context, &request);
|
||||
|
||||
if (error)
|
||||
@ -639,6 +660,66 @@ 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.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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
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
|
||||
*
|
||||
@ -655,7 +736,15 @@ static UINT cliprdr_client_format_list(CliprdrClientContext* context,
|
||||
cliprdr = (cliprdrPlugin*)context->handle;
|
||||
WINPR_ASSERT(cliprdr);
|
||||
|
||||
s = cliprdr_packet_format_list_new(formatList, cliprdr->useLongFormatNames);
|
||||
const UINT32 mask =
|
||||
freerdp_settings_get_uint32(context->rdpcontext->settings, FreeRDP_ClipboardFeatureMask);
|
||||
CLIPRDR_FORMAT_LIST filterList = cliprdr_filter_local_format_list(formatList, mask);
|
||||
if (filterList.numFormats == 0)
|
||||
return CHANNEL_RC_OK;
|
||||
|
||||
s = cliprdr_packet_format_list_new(&filterList, cliprdr->useLongFormatNames);
|
||||
cliprdr_free_format_list(&filterList);
|
||||
|
||||
if (!s)
|
||||
{
|
||||
WLog_ERR(TAG, "cliprdr_packet_format_list_new failed!");
|
||||
@ -775,6 +864,13 @@ static UINT cliprdr_client_format_data_request(CliprdrClientContext* context,
|
||||
cliprdr = (cliprdrPlugin*)context->handle;
|
||||
WINPR_ASSERT(cliprdr);
|
||||
|
||||
const UINT32 mask =
|
||||
freerdp_settings_get_uint32(context->rdpcontext->settings, FreeRDP_ClipboardFeatureMask);
|
||||
if ((mask & (CLIPRDR_FLAG_REMOTE_TO_LOCAL | CLIPRDR_FLAG_REMOTE_TO_LOCAL_FILES)) == 0)
|
||||
{
|
||||
WLog_WARN(TAG, "remote -> local copy disabled, ignoring request");
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
s = cliprdr_packet_new(CB_FORMAT_DATA_REQUEST, 0, 4);
|
||||
|
||||
if (!s)
|
||||
@ -806,6 +902,10 @@ cliprdr_client_format_data_response(CliprdrClientContext* context,
|
||||
cliprdr = (cliprdrPlugin*)context->handle;
|
||||
WINPR_ASSERT(cliprdr);
|
||||
|
||||
const UINT32 mask =
|
||||
freerdp_settings_get_uint32(context->rdpcontext->settings, FreeRDP_ClipboardFeatureMask);
|
||||
WINPR_ASSERT((mask & (CLIPRDR_FLAG_LOCAL_TO_REMOTE | CLIPRDR_FLAG_LOCAL_TO_REMOTE_FILES)) != 0);
|
||||
|
||||
s = cliprdr_packet_new(CB_FORMAT_DATA_RESPONSE, formatDataResponse->common.msgFlags,
|
||||
formatDataResponse->common.dataLen);
|
||||
|
||||
@ -835,6 +935,14 @@ cliprdr_client_file_contents_request(CliprdrClientContext* context,
|
||||
WINPR_ASSERT(context);
|
||||
WINPR_ASSERT(fileContentsRequest);
|
||||
|
||||
const UINT32 mask =
|
||||
freerdp_settings_get_uint32(context->rdpcontext->settings, FreeRDP_ClipboardFeatureMask);
|
||||
if ((mask & CLIPRDR_FLAG_REMOTE_TO_LOCAL_FILES) == 0)
|
||||
{
|
||||
WLog_WARN(TAG, "remote -> local file copy disabled, ignoring request");
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
cliprdr = (cliprdrPlugin*)context->handle;
|
||||
if (!cliprdr)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
@ -879,6 +987,11 @@ cliprdr_client_file_contents_response(CliprdrClientContext* context,
|
||||
cliprdr = (cliprdrPlugin*)context->handle;
|
||||
WINPR_ASSERT(cliprdr);
|
||||
|
||||
const UINT32 mask =
|
||||
freerdp_settings_get_uint32(context->rdpcontext->settings, FreeRDP_ClipboardFeatureMask);
|
||||
if ((mask & CLIPRDR_FLAG_LOCAL_TO_REMOTE_FILES) == 0)
|
||||
return cliprdr_send_error_response(cliprdr, CB_FILECONTENTS_RESPONSE);
|
||||
|
||||
s = cliprdr_packet_file_contents_response_new(fileContentsResponse);
|
||||
|
||||
if (!s)
|
||||
|
@ -52,5 +52,8 @@ typedef struct
|
||||
} cliprdrPlugin;
|
||||
|
||||
CliprdrClientContext* cliprdr_get_client_interface(cliprdrPlugin* cliprdr);
|
||||
UINT cliprdr_send_error_response(cliprdrPlugin* cliprdr, UINT16 type);
|
||||
|
||||
extern const char* type_FileGroupDescriptorW;
|
||||
|
||||
#endif /* FREERDP_CHANNEL_CLIPRDR_CLIENT_MAIN_H */
|
||||
|
@ -72,7 +72,7 @@ wStream* cliprdr_packet_new(UINT16 msgType, UINT16 msgFlags, UINT32 dataLen)
|
||||
Stream_Write_UINT16(s, msgType);
|
||||
Stream_Write_UINT16(s, msgFlags);
|
||||
/* Write actual length after the entire packet has been constructed. */
|
||||
Stream_Seek(s, 4);
|
||||
Stream_Write_UINT32(s, 0);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user