GUAC-584: Simplify copy logic. Store clipboard in static 256K buffer. Convert from UTF16 properly.
This commit is contained in:
parent
04ac42811f
commit
7cf5d02019
@ -26,7 +26,7 @@
|
|||||||
#include <guacamole/unicode.h>
|
#include <guacamole/unicode.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
void guac_iconv(guac_iconv_read* reader, char** input, int in_remaining,
|
int guac_iconv(guac_iconv_read* reader, char** input, int in_remaining,
|
||||||
guac_iconv_write* writer, char** output, int out_remaining) {
|
guac_iconv_write* writer, char** output, int out_remaining) {
|
||||||
|
|
||||||
while (in_remaining > 0 && out_remaining > 0) {
|
while (in_remaining > 0 && out_remaining > 0) {
|
||||||
@ -47,10 +47,13 @@ void guac_iconv(guac_iconv_read* reader, char** input, int in_remaining,
|
|||||||
|
|
||||||
/* Stop if null terminator reached */
|
/* Stop if null terminator reached */
|
||||||
if (value == 0)
|
if (value == 0)
|
||||||
break;
|
return 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Null terminator not reached */
|
||||||
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int GUAC_READ_UTF8(char** input, int remaining) {
|
int GUAC_READ_UTF8(char** input, int remaining) {
|
||||||
|
@ -53,8 +53,10 @@ typedef void guac_iconv_write(char** output, int remaining, int value);
|
|||||||
* @param output Pointer to the beginning of the output string.
|
* @param output Pointer to the beginning of the output string.
|
||||||
* @param out_remaining The number of bytes remaining after the pointer to the
|
* @param out_remaining The number of bytes remaining after the pointer to the
|
||||||
* output string.
|
* output string.
|
||||||
|
* @return Non-zero if the NULL terminator of the input string was read and
|
||||||
|
* copied into the destination string, zero otherwise.
|
||||||
*/
|
*/
|
||||||
void guac_iconv(guac_iconv_read* reader, char** input, int in_remaining,
|
int guac_iconv(guac_iconv_read* reader, char** input, int in_remaining,
|
||||||
guac_iconv_write* writer, char** output, int out_remaining);
|
guac_iconv_write* writer, char** output, int out_remaining);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -655,7 +655,6 @@ int guac_client_init(guac_client* client, int argc, char** argv) {
|
|||||||
guac_client_data->bounded = FALSE;
|
guac_client_data->bounded = FALSE;
|
||||||
guac_client_data->mouse_button_mask = 0;
|
guac_client_data->mouse_button_mask = 0;
|
||||||
guac_client_data->current_surface = GUAC_DEFAULT_LAYER;
|
guac_client_data->current_surface = GUAC_DEFAULT_LAYER;
|
||||||
guac_client_data->clipboard = NULL;
|
|
||||||
guac_client_data->requested_clipboard_format = CB_FORMAT_TEXT;
|
guac_client_data->requested_clipboard_format = CB_FORMAT_TEXT;
|
||||||
guac_client_data->audio = NULL;
|
guac_client_data->audio = NULL;
|
||||||
guac_client_data->filesystem = NULL;
|
guac_client_data->filesystem = NULL;
|
||||||
|
@ -70,6 +70,11 @@
|
|||||||
*/
|
*/
|
||||||
#define GUAC_RDP_REASONABLE_AREA (800*600)
|
#define GUAC_RDP_REASONABLE_AREA (800*600)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum number of bytes to allow within the clipboard.
|
||||||
|
*/
|
||||||
|
#define GUAC_RDP_CLIPBOARD_MAX_LENGTH 262144
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Client data that will remain accessible through the guac_client.
|
* Client data that will remain accessible through the guac_client.
|
||||||
* This should generally include data commonly used by Guacamole handlers.
|
* This should generally include data commonly used by Guacamole handlers.
|
||||||
@ -166,9 +171,9 @@ typedef struct rdp_guac_client_data {
|
|||||||
guac_rdp_keysym_state_map keysym_state;
|
guac_rdp_keysym_state_map keysym_state;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current text (NOT Unicode) clipboard contents.
|
* The current clipboard contents, in UTF-8.
|
||||||
*/
|
*/
|
||||||
char* clipboard;
|
char clipboard[GUAC_RDP_CLIPBOARD_MAX_LENGTH];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The format of the clipboard which was requested. Data received from
|
* The format of the clipboard which was requested. Data received from
|
||||||
|
@ -462,8 +462,8 @@ int rdp_guac_client_key_handler(guac_client* client, int keysym, int pressed) {
|
|||||||
|
|
||||||
int rdp_guac_client_clipboard_handler(guac_client* client, char* data) {
|
int rdp_guac_client_clipboard_handler(guac_client* client, char* data) {
|
||||||
|
|
||||||
rdpChannels* channels =
|
rdp_guac_client_data* client_data = (rdp_guac_client_data*) client->data;
|
||||||
((rdp_guac_client_data*) client->data)->rdp_inst->context->channels;
|
rdpChannels* channels = client_data->rdp_inst->context->channels;
|
||||||
|
|
||||||
RDP_CB_FORMAT_LIST_EVENT* format_list =
|
RDP_CB_FORMAT_LIST_EVENT* format_list =
|
||||||
(RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(
|
(RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(
|
||||||
@ -471,11 +471,8 @@ int rdp_guac_client_clipboard_handler(guac_client* client, char* data) {
|
|||||||
CliprdrChannel_FormatList,
|
CliprdrChannel_FormatList,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
|
|
||||||
/* Free existing data */
|
|
||||||
free(((rdp_guac_client_data*) client->data)->clipboard);
|
|
||||||
|
|
||||||
/* Store data in client */
|
/* Store data in client */
|
||||||
((rdp_guac_client_data*) client->data)->clipboard = strdup(data);
|
strncpy(client_data->clipboard, data, GUAC_RDP_CLIPBOARD_MAX_LENGTH);
|
||||||
|
|
||||||
/* Notify server that text data is now available */
|
/* Notify server that text data is now available */
|
||||||
format_list->formats = (UINT32*) malloc(sizeof(UINT32));
|
format_list->formats = (UINT32*) malloc(sizeof(UINT32));
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "rdp_cliprdr.h"
|
#include "rdp_cliprdr.h"
|
||||||
#include "unicode.h"
|
#include "guac_iconv.h"
|
||||||
|
|
||||||
#include <freerdp/channels/channels.h>
|
#include <freerdp/channels/channels.h>
|
||||||
#include <freerdp/freerdp.h>
|
#include <freerdp/freerdp.h>
|
||||||
@ -212,76 +212,26 @@ void guac_rdp_process_cb_data_request(guac_client* client,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __guac_rdp_clipboard_send_iso8859_1(guac_client* client,
|
|
||||||
RDP_CB_DATA_RESPONSE_EVENT* event) {
|
|
||||||
|
|
||||||
rdp_guac_client_data* client_data = (rdp_guac_client_data*) client->data;
|
|
||||||
|
|
||||||
/* Ensure data is large enough and has null terminator */
|
|
||||||
if (event->size < 1 || event->data[event->size - 1] != '\0') {
|
|
||||||
guac_client_log_error(client,
|
|
||||||
"Clipboard data missing null terminator");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free existing data */
|
|
||||||
free(client_data->clipboard);
|
|
||||||
|
|
||||||
/* Store clipboard data */
|
|
||||||
client_data->clipboard = strdup((char*) event->data);
|
|
||||||
|
|
||||||
/* Send clipboard data */
|
|
||||||
guac_protocol_send_clipboard(client->socket, client_data->clipboard);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __guac_rdp_clipboard_send_utf16(guac_client* client,
|
|
||||||
RDP_CB_DATA_RESPONSE_EVENT* event) {
|
|
||||||
|
|
||||||
rdp_guac_client_data* client_data = (rdp_guac_client_data*) client->data;
|
|
||||||
int output_length;
|
|
||||||
|
|
||||||
/* Ensure data is large enough and has null terminator */
|
|
||||||
if (event->size < 2
|
|
||||||
|| event->data[event->size - 2] != '\0'
|
|
||||||
|| event->data[event->size - 1] != '\0') {
|
|
||||||
guac_client_log_error(client,
|
|
||||||
"Clipboard data missing null terminator");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free existing data */
|
|
||||||
free(client_data->clipboard);
|
|
||||||
|
|
||||||
/* Store clipboard data */
|
|
||||||
output_length = event->size * 3;
|
|
||||||
client_data->clipboard = malloc(output_length);
|
|
||||||
guac_rdp_utf16_to_utf8(event->data, event->size/2,
|
|
||||||
client_data->clipboard, output_length);
|
|
||||||
|
|
||||||
/* Send clipboard data */
|
|
||||||
guac_protocol_send_clipboard(client->socket, client_data->clipboard);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void guac_rdp_process_cb_data_response(guac_client* client,
|
void guac_rdp_process_cb_data_response(guac_client* client,
|
||||||
RDP_CB_DATA_RESPONSE_EVENT* event) {
|
RDP_CB_DATA_RESPONSE_EVENT* event) {
|
||||||
|
|
||||||
rdp_guac_client_data* client_data = (rdp_guac_client_data*) client->data;
|
rdp_guac_client_data* client_data = (rdp_guac_client_data*) client->data;
|
||||||
|
|
||||||
/* Convert to UTF-8 based on format */
|
guac_iconv_read* reader;
|
||||||
|
char* input = (char*) event->data;
|
||||||
|
char* output = client_data->clipboard;
|
||||||
|
|
||||||
|
/* Find correct source encoding */
|
||||||
switch (client_data->requested_clipboard_format) {
|
switch (client_data->requested_clipboard_format) {
|
||||||
|
|
||||||
/* Non-Unicode */
|
/* Non-Unicode */
|
||||||
case CB_FORMAT_TEXT:
|
case CB_FORMAT_TEXT:
|
||||||
guac_client_log_info(client, "STUB: Copy non-unicode");
|
reader = GUAC_READ_UTF8;
|
||||||
__guac_rdp_clipboard_send_iso8859_1(client, event);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Unicode (UTF-16) */
|
/* Unicode (UTF-16) */
|
||||||
case CB_FORMAT_UNICODETEXT:
|
case CB_FORMAT_UNICODETEXT:
|
||||||
guac_client_log_info(client, "STUB: Copy unicode");
|
reader = GUAC_READ_UTF16;
|
||||||
__guac_rdp_clipboard_send_utf16(client, event);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -292,5 +242,10 @@ void guac_rdp_process_cb_data_response(guac_client* client,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Convert send clipboard data */
|
||||||
|
if (guac_iconv(reader, &input, event->size,
|
||||||
|
GUAC_WRITE_UTF8, &output, GUAC_RDP_CLIPBOARD_MAX_LENGTH))
|
||||||
|
guac_protocol_send_clipboard(client->socket, client_data->clipboard);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user