GUACAMOLE-249: Restore support for CLIPRDR channel.
This commit is contained in:
parent
831606a4e9
commit
b64b8f375a
@ -36,6 +36,7 @@ libguac_client_rdp_la_SOURCES = \
|
||||
audio_input.c \
|
||||
channels.c \
|
||||
client.c \
|
||||
clipboard.c \
|
||||
decompose.c \
|
||||
dvc.c \
|
||||
error.c \
|
||||
@ -44,7 +45,6 @@ libguac_client_rdp_la_SOURCES = \
|
||||
ptr_string.c \
|
||||
rdp.c \
|
||||
rdp_bitmap.c \
|
||||
rdp_cliprdr.c \
|
||||
rdp_color.c \
|
||||
rdp_disp.c \
|
||||
rdp_fs.c \
|
||||
@ -104,6 +104,7 @@ noinst_HEADERS = \
|
||||
guac_svc/svc_service.h \
|
||||
audio_input.h \
|
||||
client.h \
|
||||
clipboard.h \
|
||||
channels.h \
|
||||
decompose.h \
|
||||
dvc.h \
|
||||
@ -113,7 +114,6 @@ noinst_HEADERS = \
|
||||
ptr_string.h \
|
||||
rdp.h \
|
||||
rdp_bitmap.h \
|
||||
rdp_cliprdr.h \
|
||||
rdp_color.h \
|
||||
rdp_disp.h \
|
||||
rdp_fs.h \
|
||||
|
@ -56,7 +56,7 @@ int guac_client_init(guac_client* client, int argc, char** argv) {
|
||||
client->data = rdp_client;
|
||||
|
||||
/* Init clipboard */
|
||||
rdp_client->clipboard = guac_common_clipboard_alloc(GUAC_RDP_CLIPBOARD_MAX_LENGTH);
|
||||
rdp_client->clipboard = guac_rdp_clipboard_alloc(client);
|
||||
|
||||
/* Init display update module */
|
||||
rdp_client->disp = guac_rdp_disp_alloc();
|
||||
@ -92,6 +92,9 @@ int guac_rdp_client_free_handler(guac_client* client) {
|
||||
if (rdp_client->settings != NULL)
|
||||
guac_rdp_settings_free(rdp_client->settings);
|
||||
|
||||
/* Clean up clipboard */
|
||||
guac_rdp_clipboard_free(rdp_client->clipboard);
|
||||
|
||||
/* Free display update module */
|
||||
guac_rdp_disp_free(rdp_client->disp);
|
||||
|
||||
@ -128,7 +131,6 @@ int guac_rdp_client_free_handler(guac_client* client) {
|
||||
guac_rdp_audio_buffer_free(rdp_client->audio_input);
|
||||
|
||||
/* Free client data */
|
||||
guac_common_clipboard_free(rdp_client->clipboard);
|
||||
free(rdp_client);
|
||||
|
||||
return 0;
|
||||
|
527
src/protocols/rdp/clipboard.c
Normal file
527
src/protocols/rdp/clipboard.c
Normal file
@ -0,0 +1,527 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "channels.h"
|
||||
#include "client.h"
|
||||
#include "clipboard.h"
|
||||
#include "common/clipboard.h"
|
||||
#include "common/iconv.h"
|
||||
#include "rdp.h"
|
||||
|
||||
#include <freerdp/channels/channels.h>
|
||||
#include <freerdp/client/cliprdr.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <guacamole/client.h>
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* Sends a Format List PDU to the RDP server containing the formats of
|
||||
* clipboard data supported. This PDU is used both to indicate the general
|
||||
* clipboard formats supported at the begining of an RDP session and to inform
|
||||
* the RDP server that new clipboard data is available within the listed
|
||||
* formats.
|
||||
*
|
||||
* @param cliprdr
|
||||
* The CliprdrClientContext structure used by FreeRDP to handle the
|
||||
* CLIPRDR channel for the current RDP session.
|
||||
*
|
||||
* @return
|
||||
* CHANNEL_RC_OK (zero) if the Format List PDU was sent successfully, an
|
||||
* error code (non-zero) otherwise.
|
||||
*/
|
||||
static UINT guac_rdp_cliprdr_send_format_list(CliprdrClientContext* cliprdr) {
|
||||
|
||||
/* We support CP-1252 and UTF-16 text */
|
||||
CLIPRDR_FORMAT_LIST format_list = {
|
||||
.formats = (CLIPRDR_FORMAT[]) {
|
||||
{ .formatId = CF_TEXT },
|
||||
{ .formatId = CF_UNICODETEXT }
|
||||
},
|
||||
.numFormats = 2,
|
||||
.msgFlags = CB_RESPONSE_OK
|
||||
};
|
||||
|
||||
return cliprdr->ClientFormatList(cliprdr, &format_list);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback invoked by the FreeRDP CLIPRDR plugin for received Monitor Ready
|
||||
* PDUs. The Monitor Ready PDU is sent by the RDP server only during
|
||||
* initialization of the CLIPRDR channel. It is part of the CLIPRDR channel
|
||||
* handshake and indicates that the RDP server's handling of clipboard
|
||||
* redirection is ready to proceed.
|
||||
*
|
||||
* @param cliprdr
|
||||
* The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
|
||||
* channel for the current RDP session.
|
||||
*
|
||||
* @param monitor_ready
|
||||
* The CLIPRDR_MONITOR_READY structure representing the Monitor Ready PDU
|
||||
* that was received.
|
||||
*
|
||||
* @return
|
||||
* CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
|
||||
* (non-zero) otherwise.
|
||||
*/
|
||||
static UINT guac_rdp_cliprdr_monitor_ready(CliprdrClientContext* cliprdr,
|
||||
const CLIPRDR_MONITOR_READY* monitor_ready) {
|
||||
|
||||
/* Respond with supported format list */
|
||||
return guac_rdp_cliprdr_send_format_list(cliprdr);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a Format Data Request PDU to the RDP server, requesting that available
|
||||
* clipboard data be sent to the client in the specified format. This PDU is
|
||||
* sent when the server indicating that clipboard data is available via a
|
||||
* Format List PDU.
|
||||
*
|
||||
* @param client
|
||||
* The guac_client associated with the current RDP session.
|
||||
*
|
||||
* @param format
|
||||
* The clipboard format to request. This format must be one of the
|
||||
* documented values used by the CLIPRDR channel for clipboard format IDs.
|
||||
*
|
||||
* @return
|
||||
* CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
|
||||
* (non-zero) otherwise.
|
||||
*/
|
||||
static UINT guac_rdp_cliprdr_send_format_data_request(
|
||||
CliprdrClientContext* cliprdr, UINT32 format) {
|
||||
|
||||
/* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
|
||||
* callable, until after the relevant guac_rdp_clipboard structure is
|
||||
* allocated and associated with the CliprdrClientContext */
|
||||
guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
|
||||
assert(clipboard != NULL);
|
||||
|
||||
/* Create new data request */
|
||||
CLIPRDR_FORMAT_DATA_REQUEST data_request = {
|
||||
.requestedFormatId = format
|
||||
};
|
||||
|
||||
/* Note the format we've requested for reference later when the requested
|
||||
* data is received via a Format Data Response PDU */
|
||||
clipboard->requested_format = format;
|
||||
|
||||
/* Send request */
|
||||
return cliprdr->ClientFormatDataRequest(cliprdr, &data_request);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given Format List PDU indicates support for the given
|
||||
* clipboard format.
|
||||
*
|
||||
* @param format_list
|
||||
* The CLIPRDR_FORMAT_LIST structure representing the Format List PDU
|
||||
* being tested.
|
||||
*
|
||||
* @param format_id
|
||||
* The ID of the clipboard format to test, such as CF_TEXT or
|
||||
* CF_UNICODETEXT.
|
||||
*
|
||||
* @return
|
||||
* Non-zero if the given Format List PDU indicates support for the given
|
||||
* clipboard format, zero otherwise.
|
||||
*/
|
||||
static int guac_rdp_cliprdr_format_supported(const CLIPRDR_FORMAT_LIST* format_list,
|
||||
UINT format_id) {
|
||||
|
||||
/* Search format list for matching ID */
|
||||
for (int i = 0; i < format_list->numFormats; i++) {
|
||||
if (format_list->formats[i].formatId == format_id)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* If no matching ID, format is not supported */
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback invoked by the FreeRDP CLIPRDR plugin for received Format List
|
||||
* PDUs. The Format List PDU is sent by the RDP server to indicate that new
|
||||
* clipboard data has been copied and is available for retrieval in the formats
|
||||
* listed. A client wishing to retrieve that data responds with a Format Data
|
||||
* Request PDU.
|
||||
*
|
||||
* @param cliprdr
|
||||
* The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
|
||||
* channel for the current RDP session.
|
||||
*
|
||||
* @param format_list
|
||||
* The CLIPRDR_FORMAT_LIST structure representing the Format List PDU that
|
||||
* was received.
|
||||
*
|
||||
* @return
|
||||
* CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
|
||||
* (non-zero) otherwise.
|
||||
*/
|
||||
static UINT guac_rdp_cliprdr_format_list(CliprdrClientContext* cliprdr,
|
||||
const CLIPRDR_FORMAT_LIST* format_list) {
|
||||
|
||||
/* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
|
||||
* callable, until after the relevant guac_rdp_clipboard structure is
|
||||
* allocated and associated with the CliprdrClientContext */
|
||||
guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
|
||||
assert(clipboard != NULL);
|
||||
|
||||
/* Prefer Unicode (in this case, UTF-16) */
|
||||
if (guac_rdp_cliprdr_format_supported(format_list, CF_UNICODETEXT))
|
||||
return guac_rdp_cliprdr_send_format_data_request(cliprdr, CF_UNICODETEXT);
|
||||
|
||||
/* Use Windows' CP-1252 if Unicode unavailable */
|
||||
if (guac_rdp_cliprdr_format_supported(format_list, CF_TEXT))
|
||||
return guac_rdp_cliprdr_send_format_data_request(cliprdr, CF_TEXT);
|
||||
|
||||
/* Ignore any unsupported data */
|
||||
guac_client_log(clipboard->client, GUAC_LOG_DEBUG, "Ignoring unsupported "
|
||||
"clipboard data. Only Unicode and text clipboard formats are "
|
||||
"currently supported.");
|
||||
return CHANNEL_RC_OK;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback invoked by the FreeRDP CLIPRDR plugin for received Format Data
|
||||
* Request PDUs. The Format Data Request PDU is sent by the RDP server when
|
||||
* requesting that clipboard data be sent, in response to a received Format
|
||||
* List PDU. The client is required to respond with a Format Data Response PDU
|
||||
* containing the requested data.
|
||||
*
|
||||
* @param cliprdr
|
||||
* The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
|
||||
* channel for the current RDP session.
|
||||
*
|
||||
* @param format_data_request
|
||||
* The CLIPRDR_FORMAT_DATA_REQUEST structure representing the Format Data
|
||||
* Request PDU that was received.
|
||||
*
|
||||
* @return
|
||||
* CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
|
||||
* (non-zero) otherwise.
|
||||
*/
|
||||
static UINT guac_rdp_cliprdr_format_data_request(CliprdrClientContext* cliprdr,
|
||||
const CLIPRDR_FORMAT_DATA_REQUEST* format_data_request) {
|
||||
|
||||
/* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
|
||||
* callable, until after the relevant guac_rdp_clipboard structure is
|
||||
* allocated and associated with the CliprdrClientContext */
|
||||
guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
|
||||
assert(clipboard != NULL);
|
||||
|
||||
guac_iconv_write* writer;
|
||||
const char* input = clipboard->clipboard->buffer;
|
||||
char* output = malloc(GUAC_RDP_CLIPBOARD_MAX_LENGTH);
|
||||
|
||||
/* Map requested clipboard format to a guac_iconv writer */
|
||||
switch (format_data_request->requestedFormatId) {
|
||||
|
||||
case CF_TEXT:
|
||||
writer = GUAC_WRITE_CP1252;
|
||||
break;
|
||||
|
||||
case CF_UNICODETEXT:
|
||||
writer = GUAC_WRITE_UTF16;
|
||||
break;
|
||||
|
||||
/* Warn if clipboard data cannot be sent as intended due to a violation
|
||||
* of the CLIPRDR spec */
|
||||
default:
|
||||
guac_client_log(clipboard->client, GUAC_LOG_WARNING, "Received "
|
||||
"clipboard data cannot be sent to the RDP server because "
|
||||
"the RDP server has requested a clipboard format which "
|
||||
"was not declared as available. This violates the "
|
||||
"specification for the CLIPRDR channel.");
|
||||
free(output);
|
||||
return CHANNEL_RC_OK;
|
||||
|
||||
}
|
||||
|
||||
/* Send received clipboard data to the RDP server in the format
|
||||
* requested */
|
||||
BYTE* start = (BYTE*) output;
|
||||
guac_iconv(GUAC_READ_UTF8, &input, clipboard->clipboard->length,
|
||||
writer, &output, GUAC_RDP_CLIPBOARD_MAX_LENGTH);
|
||||
|
||||
CLIPRDR_FORMAT_DATA_RESPONSE data_response = {
|
||||
.requestedFormatData = (BYTE*) output,
|
||||
.dataLen = ((BYTE*) output) - start
|
||||
};
|
||||
|
||||
return cliprdr->ClientFormatDataResponse(cliprdr, &data_response);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback invoked by the FreeRDP CLIPRDR plugin for received Format Data
|
||||
* Response PDUs. The Format Data Response PDU is sent by the RDP server when
|
||||
* fullfilling a request for clipboard data received via a Format Data Request
|
||||
* PDU.
|
||||
*
|
||||
* @param cliprdr
|
||||
* The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
|
||||
* channel for the current RDP session.
|
||||
*
|
||||
* @param format_data_response
|
||||
* The CLIPRDR_FORMAT_DATA_RESPONSE structure representing the Format Data
|
||||
* Response PDU that was received.
|
||||
*
|
||||
* @return
|
||||
* CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
|
||||
* (non-zero) otherwise.
|
||||
*/
|
||||
static UINT guac_rdp_cliprdr_format_data_response(CliprdrClientContext* cliprdr,
|
||||
const CLIPRDR_FORMAT_DATA_RESPONSE* format_data_response) {
|
||||
|
||||
/* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
|
||||
* callable, until after the relevant guac_rdp_clipboard structure is
|
||||
* allocated and associated with the CliprdrClientContext */
|
||||
guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
|
||||
assert(clipboard != NULL);
|
||||
|
||||
char received_data[GUAC_RDP_CLIPBOARD_MAX_LENGTH];
|
||||
|
||||
guac_iconv_read* reader;
|
||||
const char* input = (char*) format_data_response->requestedFormatData;
|
||||
char* output = received_data;
|
||||
|
||||
/* Find correct source encoding */
|
||||
switch (clipboard->requested_format) {
|
||||
|
||||
/* Non-Unicode (Windows CP-1252) */
|
||||
case CF_TEXT:
|
||||
reader = GUAC_READ_CP1252;
|
||||
break;
|
||||
|
||||
/* Unicode (UTF-16) */
|
||||
case CF_UNICODETEXT:
|
||||
reader = GUAC_READ_UTF16;
|
||||
break;
|
||||
|
||||
/* If the format ID stored within the guac_rdp_clipboard structure is actually
|
||||
* not supported here, then something has been implemented incorrectly.
|
||||
* Either incorrect values are (somehow) being stored, or support for
|
||||
* the format indicated by that value is incomplete and must be added
|
||||
* here. The values which may be stored within requested_format are
|
||||
* completely within our control. */
|
||||
default:
|
||||
guac_client_log(clipboard->client, GUAC_LOG_DEBUG, "Requested "
|
||||
"clipboard data in unsupported format (0x%X).",
|
||||
clipboard->requested_format);
|
||||
return CHANNEL_RC_OK;
|
||||
|
||||
}
|
||||
|
||||
/* Convert, store, and forward the clipboard data received from RDP
|
||||
* server */
|
||||
if (guac_iconv(reader, &input, format_data_response->dataLen,
|
||||
GUAC_WRITE_UTF8, &output, sizeof(received_data))) {
|
||||
int length = strnlen(received_data, sizeof(received_data));
|
||||
guac_common_clipboard_reset(clipboard->clipboard, "text/plain");
|
||||
guac_common_clipboard_append(clipboard->clipboard, received_data, length);
|
||||
guac_common_clipboard_send(clipboard->clipboard, clipboard->client);
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback which associates handlers specific to Guacamole with the
|
||||
* CliprdrClientContext instance allocated by FreeRDP to deal with received
|
||||
* CLIPRDR (clipboard redirection) messages.
|
||||
*
|
||||
* This function is called whenever a channel connects via the PubSub event
|
||||
* system within FreeRDP, but only has any effect if the connected channel is
|
||||
* the CLIPRDR channel. This specific callback is registered with the PubSub
|
||||
* system of the relevant rdpContext when guac_rdp_clipboard_load_plugin() is
|
||||
* called.
|
||||
*
|
||||
* @param context
|
||||
* The rdpContext associated with the active RDP session.
|
||||
*
|
||||
* @param e
|
||||
* Event-specific arguments, mainly the name of the channel, and a
|
||||
* reference to the associated plugin loaded for that channel by FreeRDP.
|
||||
*/
|
||||
static void guac_rdp_cliprdr_channel_connected(rdpContext* context,
|
||||
ChannelConnectedEventArgs* e) {
|
||||
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||
guac_rdp_clipboard* clipboard = rdp_client->clipboard;
|
||||
|
||||
/* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
|
||||
* callable, until after the relevant guac_rdp_clipboard structure is
|
||||
* allocated and associated with the guac_rdp_client */
|
||||
assert(clipboard != NULL);
|
||||
|
||||
/* Ignore connection event if it's not for the CLIPRDR channel */
|
||||
if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) != 0)
|
||||
return;
|
||||
|
||||
/* The structure pointed to by pInterface is guaranteed to be a
|
||||
* CliprdrClientContext if the channel is CLIPRDR */
|
||||
CliprdrClientContext* cliprdr = (CliprdrClientContext*) e->pInterface;
|
||||
|
||||
/* Associate FreeRDP CLIPRDR context and its Guacamole counterpart with
|
||||
* eachother */
|
||||
cliprdr->custom = clipboard;
|
||||
clipboard->cliprdr = cliprdr;
|
||||
|
||||
cliprdr->MonitorReady = guac_rdp_cliprdr_monitor_ready;
|
||||
cliprdr->ServerFormatList = guac_rdp_cliprdr_format_list;
|
||||
cliprdr->ServerFormatDataRequest = guac_rdp_cliprdr_format_data_request;
|
||||
cliprdr->ServerFormatDataResponse = guac_rdp_cliprdr_format_data_response;
|
||||
|
||||
guac_client_log(client, GUAC_LOG_DEBUG, "CLIPRDR (clipboard redirection) "
|
||||
"channel connected.");
|
||||
|
||||
}
|
||||
|
||||
guac_rdp_clipboard* guac_rdp_clipboard_alloc(guac_client* client) {
|
||||
|
||||
/* Allocate clipboard and underlying storage */
|
||||
guac_rdp_clipboard* clipboard = calloc(1, sizeof(guac_rdp_clipboard));
|
||||
clipboard->client = client;
|
||||
clipboard->clipboard = guac_common_clipboard_alloc(GUAC_RDP_CLIPBOARD_MAX_LENGTH);
|
||||
clipboard->requested_format = CF_TEXT;
|
||||
|
||||
return clipboard;
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_clipboard_load_plugin(guac_rdp_clipboard* clipboard,
|
||||
rdpContext* context) {
|
||||
|
||||
/* Attempt to load FreeRDP support for the CLIPRDR channel */
|
||||
if (guac_freerdp_channels_load_plugin(context->channels, context->settings, "cliprdr", NULL)) {
|
||||
guac_client_log(clipboard->client, GUAC_LOG_WARNING,
|
||||
"Support for the CLIPRDR channel (clipboard redirection) "
|
||||
"could not be loaded. This support normally takes the form of "
|
||||
"a plugin which is built into FreeRDP. Lacking this support, "
|
||||
"clipboard will not work.");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Complete RDP side of initialization when channel is connected */
|
||||
PubSub_SubscribeChannelConnected(context->pubSub,
|
||||
(pChannelConnectedEventHandler) guac_rdp_cliprdr_channel_connected);
|
||||
|
||||
guac_client_log(clipboard->client, GUAC_LOG_DEBUG, "Support for CLIPRDR "
|
||||
"(clipboard redirection) registered. Awaiting channel "
|
||||
"connection.");
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_clipboard_free(guac_rdp_clipboard* clipboard) {
|
||||
|
||||
/* Do nothing if the clipboard is not actually allocated */
|
||||
if (clipboard == NULL)
|
||||
return;
|
||||
|
||||
/* Free clipboard and underlying storage */
|
||||
guac_common_clipboard_free(clipboard->clipboard);
|
||||
free(clipboard);
|
||||
|
||||
}
|
||||
|
||||
int guac_rdp_clipboard_handler(guac_user* user, guac_stream* stream,
|
||||
char* mimetype) {
|
||||
|
||||
guac_client* client = user->client;
|
||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||
|
||||
/* Ignore stream creation if no clipboard structure is available to handle
|
||||
* received data */
|
||||
guac_rdp_clipboard* clipboard = rdp_client->clipboard;
|
||||
if (clipboard == NULL)
|
||||
return 0;
|
||||
|
||||
/* Handle any future "blob" and "end" instructions for this stream with
|
||||
* handlers that are aware of the RDP clipboard state */
|
||||
stream->blob_handler = guac_rdp_clipboard_blob_handler;
|
||||
stream->end_handler = guac_rdp_clipboard_end_handler;
|
||||
|
||||
/* Clear any current contents, assigning the mimetype the data which will
|
||||
* be received */
|
||||
guac_common_clipboard_reset(clipboard->clipboard, mimetype);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int guac_rdp_clipboard_blob_handler(guac_user* user, guac_stream* stream,
|
||||
void* data, int length) {
|
||||
|
||||
guac_client* client = user->client;
|
||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||
|
||||
/* Ignore received data if no clipboard structure is available to handle
|
||||
* that data */
|
||||
guac_rdp_clipboard* clipboard = rdp_client->clipboard;
|
||||
if (clipboard == NULL)
|
||||
return 0;
|
||||
|
||||
/* Append received data to current clipboard contents */
|
||||
guac_common_clipboard_append(clipboard->clipboard, (char*) data, length);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int guac_rdp_clipboard_end_handler(guac_user* user, guac_stream* stream) {
|
||||
|
||||
guac_client* client = user->client;
|
||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||
|
||||
/* Ignore end of stream if no clipboard structure is available to handle
|
||||
* the data that was received */
|
||||
guac_rdp_clipboard* clipboard = rdp_client->clipboard;
|
||||
if (clipboard == NULL)
|
||||
return 0;
|
||||
|
||||
/* Terminate clipboard data with NULL */
|
||||
guac_common_clipboard_append(clipboard->clipboard, "", 1);
|
||||
|
||||
/* Notify RDP server of new data, if connected */
|
||||
if (clipboard->cliprdr != NULL) {
|
||||
guac_client_log(client, GUAC_LOG_DEBUG, "Clipboard data received. "
|
||||
"Reporting availability of clipboard data to RDP server.");
|
||||
guac_rdp_cliprdr_send_format_list(clipboard->cliprdr);
|
||||
}
|
||||
else
|
||||
guac_client_log(client, GUAC_LOG_DEBUG, "Clipboard data has been "
|
||||
"received, but cannot be sent to the RDP server because the "
|
||||
"CLIPRDR channel is not yet connected.");
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
144
src/protocols/rdp/clipboard.h
Normal file
144
src/protocols/rdp/clipboard.h
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef GUAC_RDP_CLIPBOARD_H
|
||||
#define GUAC_RDP_CLIPBOARD_H
|
||||
|
||||
#include "config.h"
|
||||
#include "common/clipboard.h"
|
||||
|
||||
#include <guacamole/client.h>
|
||||
#include <freerdp/client/cliprdr.h>
|
||||
#include <winpr/stream.h>
|
||||
|
||||
/**
|
||||
* RDP clipboard, leveraging the "CLIPRDR" channel.
|
||||
*/
|
||||
typedef struct guac_rdp_clipboard {
|
||||
|
||||
/**
|
||||
* The guac_client associated with the RDP connection. The broadcast
|
||||
* socket of this client will receive any clipboard data received from the
|
||||
* RDP server.
|
||||
*/
|
||||
guac_client* client;
|
||||
|
||||
/**
|
||||
* CLIPRDR control interface.
|
||||
*/
|
||||
CliprdrClientContext* cliprdr;
|
||||
|
||||
/**
|
||||
* The current clipboard contents.
|
||||
*/
|
||||
guac_common_clipboard* clipboard;
|
||||
|
||||
/**
|
||||
* The format of the clipboard which was requested. Data received from
|
||||
* the RDP server should conform to this format. This will be one of
|
||||
* several legal clipboard format values defined within FreeRDP's WinPR
|
||||
* library, such as CF_TEXT.
|
||||
*/
|
||||
UINT requested_format;
|
||||
|
||||
} guac_rdp_clipboard;
|
||||
|
||||
/**
|
||||
* Allocates a new guac_rdp_clipboard which has been initialized for processing
|
||||
* of Guacamole clipboard data. Support for the RDP side of the clipboard (the
|
||||
* CLIPRDR channel) must be loaded separately during FreeRDP's PreConnect event
|
||||
* using guac_rdp_clipboard_load_plugin().
|
||||
*
|
||||
* @param client
|
||||
* The guac_client associated with the Guacamole side of the RDP
|
||||
* connection.
|
||||
*
|
||||
* @return
|
||||
* A newly-allocated instance of guac_rdp_clipboard which has been
|
||||
* initialized for processing Guacamole clipboard data.
|
||||
*/
|
||||
guac_rdp_clipboard* guac_rdp_clipboard_alloc(guac_client* client);
|
||||
|
||||
/**
|
||||
* Initializes clipboard support for RDP and handling of the CLIPRDR channel.
|
||||
* If failures occur, messages noting the specifics of those failures will be
|
||||
* logged, and the RDP side of clipboard support will not be functional.
|
||||
*
|
||||
* This MUST be called within the PreConnect callback of the freerdp instance
|
||||
* for CLIPRDR support to be loaded.
|
||||
*
|
||||
* @param clipboard
|
||||
* The guac_rdp_clipboard instance which has been allocated for the current
|
||||
* RDP connection.
|
||||
*
|
||||
* @param rdpContext
|
||||
* The rdpContext associated with the FreeRDP side of the RDP connection.
|
||||
*/
|
||||
void guac_rdp_clipboard_load_plugin(guac_rdp_clipboard* clipboard,
|
||||
rdpContext* context);
|
||||
|
||||
/**
|
||||
* Frees the resources associated with clipboard support for RDP and handling
|
||||
* of the CLIPRDR channel. Only resources specific to Guacamole are freed.
|
||||
* Resources specific to FreeRDP's handling of the CLIPRDR channel will be
|
||||
* freed by FreeRDP. If the provided guac_rdp_clipboard is NULL, this function
|
||||
* has no effect.
|
||||
*
|
||||
* @param clipboard
|
||||
* The guac_rdp_clipboard instance which was been allocated for the current
|
||||
* RDP connection.
|
||||
*/
|
||||
void guac_rdp_clipboard_free(guac_rdp_clipboard* clipboard);
|
||||
|
||||
/**
|
||||
* Handler for inbound clipboard data, received via the stream created by an
|
||||
* inbound "clipboard" instruction. This handler will assign the
|
||||
* stream-specific handlers for processing "blob" and "end" instructions which
|
||||
* will eventually be received as clipboard data is sent. This specific handler
|
||||
* is expected to be assigned to the guac_user object of any user that may send
|
||||
* clipboard data. The guac_rdp_clipboard instance which will receive this data
|
||||
* MUST already be stored on the guac_rdp_client structure associated with the
|
||||
* current RDP connection.
|
||||
*/
|
||||
guac_user_clipboard_handler guac_rdp_clipboard_handler;
|
||||
|
||||
/**
|
||||
* Handler for stream data related to clipboard, received via "blob"
|
||||
* instructions for a stream which has already been created with an inbound
|
||||
* "clipboard" instruction. This specific handler is assigned to the
|
||||
* guac_stream structure associated with that clipboard stream by
|
||||
* guac_rdp_clipboard_handler(). The guac_rdp_clipboard instance which will
|
||||
* receive this data MUST already be stored on the guac_rdp_client structure
|
||||
* associated with the current RDP connection.
|
||||
*/
|
||||
guac_user_blob_handler guac_rdp_clipboard_blob_handler;
|
||||
|
||||
/**
|
||||
* Handler for end-of-stream related to clipboard, indicated via an "end"
|
||||
* instruction for a stream which has already been created with an inbound
|
||||
* "clipboard" instruction. This specific handler is assigned to the
|
||||
* guac_stream structure associated with that clipboard stream by
|
||||
* guac_rdp_clipboard_handler(). The guac_rdp_clipboard instance which will
|
||||
* receive this data MUST already be stored on the guac_rdp_client structure
|
||||
* associated with the current RDP connection.
|
||||
*/
|
||||
guac_user_end_handler guac_rdp_clipboard_end_handler;
|
||||
|
||||
#endif
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "audio_input.h"
|
||||
#include "channels.h"
|
||||
#include "client.h"
|
||||
#include "clipboard.h"
|
||||
#include "common/cursor.h"
|
||||
#include "common/display.h"
|
||||
#include "common/recording.h"
|
||||
@ -30,7 +31,6 @@
|
||||
#include "keyboard.h"
|
||||
#include "rdp.h"
|
||||
#include "rdp_bitmap.h"
|
||||
#include "rdp_cliprdr.h"
|
||||
#include "rdp_disp.h"
|
||||
#include "rdp_fs.h"
|
||||
#include "rdp_print_job.h"
|
||||
@ -109,11 +109,8 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) {
|
||||
guac_rdp_audio_load_plugin(instance->context, dvc_list);
|
||||
}
|
||||
|
||||
/* Load clipboard plugin */
|
||||
if (guac_freerdp_channels_load_plugin(channels, instance->settings,
|
||||
"cliprdr", NULL))
|
||||
guac_client_log(client, GUAC_LOG_WARNING,
|
||||
"Failed to load cliprdr plugin. Clipboard will not work.");
|
||||
/* Load "cliprdr" plugin for clipboard support */
|
||||
guac_rdp_clipboard_load_plugin(rdp_client->clipboard, context);
|
||||
|
||||
/* If RDPSND/RDPDR required, load them */
|
||||
if (settings->printing_enabled
|
||||
@ -414,7 +411,6 @@ static int guac_rdp_handle_connection(guac_client* client) {
|
||||
|
||||
rdp_client->current_surface = rdp_client->display->default_surface;
|
||||
|
||||
rdp_client->requested_clipboard_format = CF_TEXT;
|
||||
rdp_client->available_svc = guac_common_list_alloc();
|
||||
|
||||
/* Init client */
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "audio_input.h"
|
||||
#include "clipboard.h"
|
||||
#include "common/clipboard.h"
|
||||
#include "common/display.h"
|
||||
#include "common/list.h"
|
||||
@ -95,17 +96,9 @@ typedef struct guac_rdp_client {
|
||||
guac_rdp_keyboard* keyboard;
|
||||
|
||||
/**
|
||||
* The current clipboard contents.
|
||||
* The current state of the clipboard and the CLIPRDR channel.
|
||||
*/
|
||||
guac_common_clipboard* clipboard;
|
||||
|
||||
/**
|
||||
* The format of the clipboard which was requested. Data received from
|
||||
* the RDP server should conform to this format. This will be one of
|
||||
* several legal clipboard format values defined within FreeRDP, such as
|
||||
* CB_FORMAT_TEXT.
|
||||
*/
|
||||
int requested_clipboard_format;
|
||||
guac_rdp_clipboard* clipboard;
|
||||
|
||||
/**
|
||||
* Audio output, if any.
|
||||
|
@ -1,249 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "client.h"
|
||||
#include "common/clipboard.h"
|
||||
#include "common/iconv.h"
|
||||
#include "rdp.h"
|
||||
#include "rdp_cliprdr.h"
|
||||
|
||||
#include <freerdp/channels/channels.h>
|
||||
#include <freerdp/client/cliprdr.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <guacamole/client.h>
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void guac_rdp_process_cliprdr_event(guac_client* client, wMessage* event) {
|
||||
#if 0
|
||||
switch (event->event_type) {
|
||||
|
||||
case CliprdrChannel_MonitorReady:
|
||||
guac_rdp_process_cb_monitor_ready(client, event);
|
||||
break;
|
||||
|
||||
case CliprdrChannel_FormatList:
|
||||
guac_rdp_process_cb_format_list(client,
|
||||
(RDP_CB_FORMAT_LIST_EVENT*) event);
|
||||
break;
|
||||
|
||||
case CliprdrChannel_DataRequest:
|
||||
guac_rdp_process_cb_data_request(client,
|
||||
(RDP_CB_DATA_REQUEST_EVENT*) event);
|
||||
break;
|
||||
|
||||
case CliprdrChannel_DataResponse:
|
||||
guac_rdp_process_cb_data_response(client,
|
||||
(RDP_CB_DATA_RESPONSE_EVENT*) event);
|
||||
break;
|
||||
|
||||
default:
|
||||
guac_client_log(client, GUAC_LOG_INFO,
|
||||
"Unknown cliprdr event type: 0x%x",
|
||||
GetMessageType(event->id));
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void guac_rdp_process_cb_monitor_ready(guac_client* client, wMessage* event) {
|
||||
#if 0
|
||||
rdpChannels* channels =
|
||||
((guac_rdp_client*) client->data)->rdp_inst->context->channels;
|
||||
|
||||
RDP_CB_FORMAT_LIST_EVENT* format_list =
|
||||
(RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(
|
||||
CliprdrChannel_Class,
|
||||
CliprdrChannel_FormatList,
|
||||
NULL, NULL);
|
||||
|
||||
/* Received notification of clipboard support. */
|
||||
|
||||
/* Respond with supported format list */
|
||||
format_list->formats = (UINT32*) malloc(sizeof(UINT32)*2);
|
||||
format_list->formats[0] = CF_TEXT;
|
||||
format_list->formats[1] = CF_UNICODETEXT;
|
||||
format_list->num_formats = 2;
|
||||
|
||||
freerdp_channels_send_event(channels, (wMessage*) format_list);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a clipboard data request for the given format.
|
||||
*
|
||||
* @param client
|
||||
* The guac_client associated with the current RDP session.
|
||||
*
|
||||
* @param format
|
||||
* The clipboard format to request. This format must be one of the
|
||||
* documented values used by the CLIPRDR channel for clipboard format IDs.
|
||||
*/
|
||||
static void __guac_rdp_cb_request_format(guac_client* client, int format) {
|
||||
#if 0
|
||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||
rdpChannels* channels = rdp_client->rdp_inst->context->channels;
|
||||
|
||||
/* Create new data request */
|
||||
RDP_CB_DATA_REQUEST_EVENT* data_request =
|
||||
(RDP_CB_DATA_REQUEST_EVENT*) freerdp_event_new(
|
||||
CliprdrChannel_Class,
|
||||
CliprdrChannel_DataRequest,
|
||||
NULL, NULL);
|
||||
|
||||
/* Set to requested format */
|
||||
rdp_client->requested_clipboard_format = format;
|
||||
data_request->format = format;
|
||||
|
||||
/* Send request */
|
||||
freerdp_channels_send_event(channels, (wMessage*) data_request);
|
||||
#endif
|
||||
}
|
||||
|
||||
void guac_rdp_process_cb_format_list(guac_client* client,
|
||||
RDP_CB_FORMAT_LIST_EVENT* event) {
|
||||
|
||||
int formats = 0;
|
||||
|
||||
/* Received notification of available data */
|
||||
|
||||
int i;
|
||||
for (i=0; i<event->num_formats; i++) {
|
||||
|
||||
/* If plain text available, request it */
|
||||
if (event->formats[i] == CF_TEXT)
|
||||
formats |= GUAC_RDP_CLIPBOARD_FORMAT_CP1252;
|
||||
else if (event->formats[i] == CF_UNICODETEXT)
|
||||
formats |= GUAC_RDP_CLIPBOARD_FORMAT_UTF16;
|
||||
|
||||
}
|
||||
|
||||
/* Prefer Unicode to plain text */
|
||||
if (formats & GUAC_RDP_CLIPBOARD_FORMAT_UTF16) {
|
||||
__guac_rdp_cb_request_format(client, CF_UNICODETEXT);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Use plain text if Unicode unavailable */
|
||||
if (formats & GUAC_RDP_CLIPBOARD_FORMAT_CP1252) {
|
||||
__guac_rdp_cb_request_format(client, CF_TEXT);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ignore if no supported format available */
|
||||
guac_client_log(client, GUAC_LOG_INFO, "Ignoring unsupported clipboard data");
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_process_cb_data_request(guac_client* client,
|
||||
RDP_CB_DATA_REQUEST_EVENT* event) {
|
||||
#if 0
|
||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||
rdpChannels* channels = rdp_client->rdp_inst->context->channels;
|
||||
|
||||
guac_iconv_write* writer;
|
||||
const char* input = rdp_client->clipboard->buffer;
|
||||
char* output = malloc(GUAC_RDP_CLIPBOARD_MAX_LENGTH);
|
||||
|
||||
RDP_CB_DATA_RESPONSE_EVENT* data_response;
|
||||
|
||||
/* Determine output encoding */
|
||||
switch (event->format) {
|
||||
|
||||
case CF_TEXT:
|
||||
writer = GUAC_WRITE_CP1252;
|
||||
break;
|
||||
|
||||
case CF_UNICODETEXT:
|
||||
writer = GUAC_WRITE_UTF16;
|
||||
break;
|
||||
|
||||
default:
|
||||
guac_client_log(client, GUAC_LOG_ERROR,
|
||||
"Server requested unsupported clipboard data type");
|
||||
free(output);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/* Create new data response */
|
||||
data_response = (RDP_CB_DATA_RESPONSE_EVENT*) freerdp_event_new(
|
||||
CliprdrChannel_Class,
|
||||
CliprdrChannel_DataResponse,
|
||||
NULL, NULL);
|
||||
|
||||
/* Set data and size */
|
||||
data_response->data = (BYTE*) output;
|
||||
guac_iconv(GUAC_READ_UTF8, &input, rdp_client->clipboard->length,
|
||||
writer, &output, GUAC_RDP_CLIPBOARD_MAX_LENGTH);
|
||||
data_response->size = ((BYTE*) output) - data_response->data;
|
||||
|
||||
/* Send response */
|
||||
freerdp_channels_send_event(channels, (wMessage*) data_response);
|
||||
#endif
|
||||
}
|
||||
|
||||
void guac_rdp_process_cb_data_response(guac_client* client,
|
||||
RDP_CB_DATA_RESPONSE_EVENT* event) {
|
||||
|
||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||
char received_data[GUAC_RDP_CLIPBOARD_MAX_LENGTH];
|
||||
|
||||
guac_iconv_read* reader;
|
||||
const char* input = (char*) event->data;
|
||||
char* output = received_data;
|
||||
|
||||
/* Find correct source encoding */
|
||||
switch (rdp_client->requested_clipboard_format) {
|
||||
|
||||
/* Non-Unicode */
|
||||
case CF_TEXT:
|
||||
reader = GUAC_READ_CP1252;
|
||||
break;
|
||||
|
||||
/* Unicode (UTF-16) */
|
||||
case CF_UNICODETEXT:
|
||||
reader = GUAC_READ_UTF16;
|
||||
break;
|
||||
|
||||
default:
|
||||
guac_client_log(client, GUAC_LOG_ERROR, "Requested clipboard data in "
|
||||
"unsupported format %i",
|
||||
rdp_client->requested_clipboard_format);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/* Convert send clipboard data */
|
||||
if (guac_iconv(reader, &input, event->size,
|
||||
GUAC_WRITE_UTF8, &output, sizeof(received_data))) {
|
||||
|
||||
int length = strnlen(received_data, sizeof(received_data));
|
||||
guac_common_clipboard_reset(rdp_client->clipboard, "text/plain");
|
||||
guac_common_clipboard_append(rdp_client->clipboard, received_data, length);
|
||||
guac_common_clipboard_send(rdp_client->clipboard, client);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,110 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __GUAC_RDP_RDP_CLIPRDR_H
|
||||
#define __GUAC_RDP_RDP_CLIPRDR_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <guacamole/client.h>
|
||||
#include <freerdp/client/cliprdr.h>
|
||||
#include <winpr/stream.h>
|
||||
|
||||
/**
|
||||
* Clipboard format for text encoded in Windows CP1252.
|
||||
*/
|
||||
#define GUAC_RDP_CLIPBOARD_FORMAT_CP1252 1
|
||||
|
||||
/**
|
||||
* Clipboard format for text encoded in UTF-16.
|
||||
*/
|
||||
#define GUAC_RDP_CLIPBOARD_FORMAT_UTF16 2
|
||||
|
||||
/**
|
||||
* Called within the main RDP connection thread whenever a CLIPRDR message is
|
||||
* received. This function will dispatch that message to an appropriate
|
||||
* function, specific to that message type.
|
||||
*
|
||||
* @param client
|
||||
* The guac_client associated with the current RDP session.
|
||||
*
|
||||
* @param event
|
||||
* The received CLIPRDR message.
|
||||
*/
|
||||
void guac_rdp_process_cliprdr_event(guac_client* client, wMessage* event);
|
||||
|
||||
/**
|
||||
* Handles the given CLIPRDR event, which MUST be a Monitor Ready event. It
|
||||
* is the responsibility of this function to respond to the Monitor Ready
|
||||
* event with a list of supported clipboard formats.
|
||||
*
|
||||
* @param client
|
||||
* The guac_client associated with the current RDP session.
|
||||
*
|
||||
* @param event
|
||||
* The received CLIPRDR message, which must be a Monitor Ready event.
|
||||
*/
|
||||
void guac_rdp_process_cb_monitor_ready(guac_client* client, wMessage* event);
|
||||
|
||||
/**
|
||||
* Handles the given CLIPRDR event, which MUST be a Format List event. It
|
||||
* is the responsibility of this function to respond to the Format List
|
||||
* event with a request for clipboard data in one of the enumerated formats.
|
||||
* This event is fired whenever remote clipboard data is available.
|
||||
*
|
||||
* @param client
|
||||
* The guac_client associated with the current RDP session.
|
||||
*
|
||||
* @param event
|
||||
* The received CLIPRDR message, which must be a Format List event.
|
||||
*/
|
||||
void guac_rdp_process_cb_format_list(guac_client* client,
|
||||
RDP_CB_FORMAT_LIST_EVENT* event);
|
||||
|
||||
/**
|
||||
* Handles the given CLIPRDR event, which MUST be a Data Request event. It
|
||||
* is the responsibility of this function to respond to the Data Request
|
||||
* event with a data response containing the current clipoard contents.
|
||||
*
|
||||
* @param client
|
||||
* The guac_client associated with the current RDP session.
|
||||
*
|
||||
* @param event
|
||||
* The received CLIPRDR message, which must be a Data Request event.
|
||||
*/
|
||||
void guac_rdp_process_cb_data_request(guac_client* client,
|
||||
RDP_CB_DATA_REQUEST_EVENT* event);
|
||||
|
||||
/**
|
||||
* Handles the given CLIPRDR event, which MUST be a Data Response event. It
|
||||
* is the responsibility of this function to read and forward the received
|
||||
* clipboard data to connected clients.
|
||||
*
|
||||
* @param client
|
||||
* The guac_client associated with the current RDP session.
|
||||
*
|
||||
* @param event
|
||||
* The received CLIPRDR message, which must be a Data Response event.
|
||||
*/
|
||||
void guac_rdp_process_cb_data_response(guac_client* client,
|
||||
RDP_CB_DATA_RESPONSE_EVENT* event);
|
||||
|
||||
#endif
|
||||
|
@ -20,7 +20,6 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "client.h"
|
||||
#include "common/clipboard.h"
|
||||
#include "rdp.h"
|
||||
#include "rdp_fs.h"
|
||||
#if 0
|
||||
@ -153,24 +152,6 @@ int guac_rdp_svc_pipe_handler(guac_user* user, guac_stream* stream,
|
||||
|
||||
}
|
||||
|
||||
int guac_rdp_clipboard_handler(guac_user* user, guac_stream* stream,
|
||||
char* mimetype) {
|
||||
|
||||
guac_client* client = user->client;
|
||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||
guac_rdp_stream* rdp_stream;
|
||||
|
||||
/* Init stream data */
|
||||
stream->data = rdp_stream = malloc(sizeof(guac_rdp_stream));
|
||||
stream->blob_handler = guac_rdp_clipboard_blob_handler;
|
||||
stream->end_handler = guac_rdp_clipboard_end_handler;
|
||||
rdp_stream->type = GUAC_RDP_INBOUND_CLIPBOARD_STREAM;
|
||||
|
||||
guac_common_clipboard_reset(rdp_client->clipboard, mimetype);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int guac_rdp_upload_blob_handler(guac_user* user, guac_stream* stream,
|
||||
void* data, int length) {
|
||||
|
||||
@ -237,16 +218,6 @@ int guac_rdp_svc_blob_handler(guac_user* user, guac_stream* stream,
|
||||
|
||||
}
|
||||
|
||||
int guac_rdp_clipboard_blob_handler(guac_user* user, guac_stream* stream,
|
||||
void* data, int length) {
|
||||
|
||||
guac_client* client = user->client;
|
||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||
guac_common_clipboard_append(rdp_client->clipboard, (char*) data, length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int guac_rdp_upload_end_handler(guac_user* user, guac_stream* stream) {
|
||||
|
||||
guac_client* client = user->client;
|
||||
@ -275,41 +246,6 @@ int guac_rdp_upload_end_handler(guac_user* user, guac_stream* stream) {
|
||||
|
||||
}
|
||||
|
||||
int guac_rdp_clipboard_end_handler(guac_user* user, guac_stream* stream) {
|
||||
|
||||
guac_client* client = user->client;
|
||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||
|
||||
/* Terminate clipboard data with NULL */
|
||||
guac_common_clipboard_append(rdp_client->clipboard, "", 1);
|
||||
|
||||
/* Notify RDP server of new data, if connected */
|
||||
#if 0
|
||||
freerdp* rdp_inst = rdp_client->rdp_inst;
|
||||
if (rdp_inst != NULL) {
|
||||
|
||||
rdpChannels* channels = rdp_inst->context->channels;
|
||||
|
||||
RDP_CB_FORMAT_LIST_EVENT* format_list =
|
||||
(RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(
|
||||
CliprdrChannel_Class,
|
||||
CliprdrChannel_FormatList,
|
||||
NULL, NULL);
|
||||
|
||||
/* Notify server that text data is now available */
|
||||
format_list->formats = (UINT32*) malloc(sizeof(UINT32) * 2);
|
||||
format_list->formats[0] = CF_TEXT;
|
||||
format_list->formats[1] = CF_UNICODETEXT;
|
||||
format_list->num_formats = 2;
|
||||
|
||||
freerdp_channels_send_event(channels, (wMessage*) format_list);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int guac_rdp_download_ack_handler(guac_user* user, guac_stream* stream,
|
||||
char* message, guac_protocol_status status) {
|
||||
|
||||
|
@ -118,12 +118,7 @@ typedef enum guac_rdp_stream_type {
|
||||
/**
|
||||
* The inbound half of a static virtual channel.
|
||||
*/
|
||||
GUAC_RDP_INBOUND_SVC_STREAM,
|
||||
|
||||
/**
|
||||
* An inbound stream of clipboard data.
|
||||
*/
|
||||
GUAC_RDP_INBOUND_CLIPBOARD_STREAM
|
||||
GUAC_RDP_INBOUND_SVC_STREAM
|
||||
|
||||
} guac_rdp_stream_type;
|
||||
|
||||
@ -171,11 +166,6 @@ guac_user_file_handler guac_rdp_upload_file_handler;
|
||||
*/
|
||||
guac_user_pipe_handler guac_rdp_svc_pipe_handler;
|
||||
|
||||
/**
|
||||
* Handler for inbound clipboard data.
|
||||
*/
|
||||
guac_user_clipboard_handler guac_rdp_clipboard_handler;
|
||||
|
||||
/**
|
||||
* Handler for stream data related to file uploads.
|
||||
*/
|
||||
@ -186,21 +176,11 @@ guac_user_blob_handler guac_rdp_upload_blob_handler;
|
||||
*/
|
||||
guac_user_blob_handler guac_rdp_svc_blob_handler;
|
||||
|
||||
/**
|
||||
* Handler for stream data related to clipboard.
|
||||
*/
|
||||
guac_user_blob_handler guac_rdp_clipboard_blob_handler;
|
||||
|
||||
/**
|
||||
* Handler for end-of-stream related to file uploads.
|
||||
*/
|
||||
guac_user_end_handler guac_rdp_upload_end_handler;
|
||||
|
||||
/**
|
||||
* Handler for end-of-stream related to clipboard.
|
||||
*/
|
||||
guac_user_end_handler guac_rdp_clipboard_end_handler;
|
||||
|
||||
/**
|
||||
* Handler for acknowledgements of receipt of data related to file downloads.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user