GUACAMOLE-478: Add optional clipboard line ending normalization for RDP.

This commit is contained in:
Michael Jumper 2021-12-25 00:31:17 -08:00
parent 7472310a03
commit 09bd4af77e
3 changed files with 65 additions and 10 deletions

View File

@ -352,10 +352,11 @@ static UINT guac_rdp_cliprdr_format_data_request(CliprdrClientContext* cliprdr,
guac_client* client = clipboard->client; guac_client* client = clipboard->client;
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
guac_rdp_settings* settings = rdp_client->settings;
guac_client_log(client, GUAC_LOG_TRACE, "CLIPRDR: Received format data request."); guac_client_log(client, GUAC_LOG_TRACE, "CLIPRDR: Received format data request.");
guac_iconv_write* writer; guac_iconv_write* remote_writer;
const char* input = clipboard->clipboard->buffer; const char* input = clipboard->clipboard->buffer;
char* output = malloc(GUAC_RDP_CLIPBOARD_MAX_LENGTH); char* output = malloc(GUAC_RDP_CLIPBOARD_MAX_LENGTH);
@ -363,11 +364,11 @@ static UINT guac_rdp_cliprdr_format_data_request(CliprdrClientContext* cliprdr,
switch (format_data_request->requestedFormatId) { switch (format_data_request->requestedFormatId) {
case CF_TEXT: case CF_TEXT:
writer = GUAC_WRITE_CP1252; remote_writer = settings->clipboard_crlf ? GUAC_WRITE_CP1252_CRLF : GUAC_WRITE_CP1252;
break; break;
case CF_UNICODETEXT: case CF_UNICODETEXT:
writer = GUAC_WRITE_UTF16; remote_writer = settings->clipboard_crlf ? GUAC_WRITE_UTF16_CRLF : GUAC_WRITE_UTF16;
break; break;
/* Warn if clipboard data cannot be sent as intended due to a violation /* Warn if clipboard data cannot be sent as intended due to a violation
@ -386,8 +387,9 @@ static UINT guac_rdp_cliprdr_format_data_request(CliprdrClientContext* cliprdr,
/* Send received clipboard data to the RDP server in the format /* Send received clipboard data to the RDP server in the format
* requested */ * requested */
BYTE* start = (BYTE*) output; BYTE* start = (BYTE*) output;
guac_iconv(GUAC_READ_UTF8, &input, clipboard->clipboard->length, guac_iconv_read* local_reader = settings->normalize_clipboard ? GUAC_READ_UTF8_NORMALIZED : GUAC_READ_UTF8;
writer, &output, GUAC_RDP_CLIPBOARD_MAX_LENGTH); guac_iconv(local_reader, &input, clipboard->clipboard->length,
remote_writer, &output, GUAC_RDP_CLIPBOARD_MAX_LENGTH);
CLIPRDR_FORMAT_DATA_RESPONSE data_response = { CLIPRDR_FORMAT_DATA_RESPONSE data_response = {
.requestedFormatData = (BYTE*) start, .requestedFormatData = (BYTE*) start,
@ -449,7 +451,7 @@ static UINT guac_rdp_cliprdr_format_data_response(CliprdrClientContext* cliprdr,
char received_data[GUAC_RDP_CLIPBOARD_MAX_LENGTH]; char received_data[GUAC_RDP_CLIPBOARD_MAX_LENGTH];
guac_iconv_read* reader; guac_iconv_read* remote_reader;
const char* input = (char*) format_data_response->requestedFormatData; const char* input = (char*) format_data_response->requestedFormatData;
char* output = received_data; char* output = received_data;
@ -458,12 +460,12 @@ static UINT guac_rdp_cliprdr_format_data_response(CliprdrClientContext* cliprdr,
/* Non-Unicode (Windows CP-1252) */ /* Non-Unicode (Windows CP-1252) */
case CF_TEXT: case CF_TEXT:
reader = GUAC_READ_CP1252; remote_reader = settings->normalize_clipboard ? GUAC_READ_CP1252_NORMALIZED : GUAC_READ_CP1252;
break; break;
/* Unicode (UTF-16) */ /* Unicode (UTF-16) */
case CF_UNICODETEXT: case CF_UNICODETEXT:
reader = GUAC_READ_UTF16; remote_reader = settings->normalize_clipboard ? GUAC_READ_UTF16_NORMALIZED : GUAC_READ_UTF16;
break; break;
/* If the format ID stored within the guac_rdp_clipboard structure is actually /* If the format ID stored within the guac_rdp_clipboard structure is actually
@ -481,7 +483,7 @@ static UINT guac_rdp_cliprdr_format_data_response(CliprdrClientContext* cliprdr,
/* Convert, store, and forward the clipboard data received from RDP /* Convert, store, and forward the clipboard data received from RDP
* server */ * server */
if (guac_iconv(reader, &input, format_data_response->dataLen, if (guac_iconv(remote_reader, &input, format_data_response->dataLen,
GUAC_WRITE_UTF8, &output, sizeof(received_data))) { GUAC_WRITE_UTF8, &output, sizeof(received_data))) {
int length = strnlen(received_data, sizeof(received_data)); int length = strnlen(received_data, sizeof(received_data));
guac_common_clipboard_reset(clipboard->clipboard, "text/plain"); guac_common_clipboard_reset(clipboard->clipboard, "text/plain");

View File

@ -130,6 +130,7 @@ const char* GUAC_RDP_CLIENT_ARGS[] = {
"wol-wait-time", "wol-wait-time",
"force-lossless", "force-lossless",
"normalize-clipboard",
NULL NULL
}; };
@ -647,6 +648,16 @@ enum RDP_ARGS_IDX {
*/ */
IDX_FORCE_LOSSLESS, IDX_FORCE_LOSSLESS,
/**
* Controls whether the text content of the clipboard should be
* automatically normalized to use a particular line ending format. Valid
* values are "preserve", to preserve line endings verbatim, "windows" to
* transform all line endings to Windows-style CRLF sequences, or "unix" to
* transform all line endings to Unix-style newline characters ('\n'). By
* default, line endings within the clipboard are preserved.
*/
IDX_NORMALIZE_CLIPBOARD,
RDP_ARGS_COUNT RDP_ARGS_COUNT
}; };
@ -1167,7 +1178,36 @@ guac_rdp_settings* guac_rdp_parse_args(guac_user* user,
settings->disable_paste = settings->disable_paste =
guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv,
IDX_DISABLE_PASTE, 0); IDX_DISABLE_PASTE, 0);
/* Normalize clipboard line endings to Unix format */
if (strcmp(argv[IDX_NORMALIZE_CLIPBOARD], "unix") == 0) {
guac_user_log(user, GUAC_LOG_INFO, "Clipboard line ending normalization: Unix (LF)");
settings->normalize_clipboard = 1;
settings->clipboard_crlf = 0;
}
/* Normalize clipboard line endings to Windows format */
else if (strcmp(argv[IDX_NORMALIZE_CLIPBOARD], "windows") == 0) {
guac_user_log(user, GUAC_LOG_INFO, "Clipboard line ending normalization: Windows (CRLF)");
settings->normalize_clipboard = 1;
settings->clipboard_crlf = 1;
}
/* Preserve clipboard line ending format */
else if (strcmp(argv[IDX_NORMALIZE_CLIPBOARD], "preserve") == 0) {
guac_user_log(user, GUAC_LOG_INFO, "Clipboard line ending normalization: Preserve (none)");
settings->normalize_clipboard = 0;
settings->clipboard_crlf = 0;
}
/* If nothing given, default to preserving line endings */
else {
guac_user_log(user, GUAC_LOG_INFO, "No clipboard line-ending normalization specified. Defaulting to preserving the format of all line endings.");
settings->normalize_clipboard = 0;
settings->clipboard_crlf = 0;
}
/* Parse Wake-on-LAN (WoL) settings */ /* Parse Wake-on-LAN (WoL) settings */
settings->wol_send_packet = settings->wol_send_packet =
guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv,

View File

@ -323,6 +323,19 @@ typedef struct guac_rdp_settings {
*/ */
int disable_paste; int disable_paste;
/**
* Whether line endings within the clipboard should be automatically
* normalized to Unix-style newline characters.
*/
int normalize_clipboard;
/**
* Whether Unix-style newline characters within the clipboard should be
* automatically translated to CRLF sequences before transmission to the
* RDP server.
*/
int clipboard_crlf;
/** /**
* Whether the desktop wallpaper should be visible. If unset, the desktop * Whether the desktop wallpaper should be visible. If unset, the desktop
* wallpaper will be hidden, reducing the amount of bandwidth required. * wallpaper will be hidden, reducing the amount of bandwidth required.