コード例 #1
0
ファイル: xf_cliprdr.c プロジェクト: Nigel62/FreeRDP
static void xf_cliprdr_process_html(clipboardContext* cb, BYTE* data, int size)
{
	char* start_str;
	char* end_str;
	int start;
	int end;

	start_str = strstr((char*) data, "StartHTML:");
	end_str = strstr((char*) data, "EndHTML:");
	if (start_str == NULL || end_str == NULL)
	{
		DEBUG_X11_CLIPRDR("invalid HTML clipboard format");
		return;
	}
	start = atoi(start_str + 10);
	end = atoi(end_str + 8);
	if (start > size || end > size || start >= end)
	{
		DEBUG_X11_CLIPRDR("invalid HTML offset");
		return;
	}

	cb->data = (BYTE*) malloc(size - start + 1);
	CopyMemory(cb->data, data + start, end - start);
	cb->data_length = end - start;
	crlf2lf(cb->data, &cb->data_length);
}
コード例 #2
0
ファイル: xf_cliprdr.c プロジェクト: Nigel62/FreeRDP
BOOL xf_cliprdr_process_property_notify(xfInfo* xfi, XEvent* xevent)
{
	clipboardContext* cb = (clipboardContext*) xfi->clipboard_context;

	if (!cb)
		return TRUE;

	if (xevent->xproperty.atom != cb->property_atom)
		return FALSE; /* Not cliprdr-related */

	if (xevent->xproperty.window == cb->root_window)
	{
		DEBUG_X11_CLIPRDR("root window PropertyNotify");
		xf_cliprdr_send_format_list(xfi);
	}
	else if (xevent->xproperty.window == xfi->drawable &&
		xevent->xproperty.state == PropertyNewValue &&
		cb->incr_starts && cb->request_index >= 0)
	{
		DEBUG_X11_CLIPRDR("cliprdr window PropertyNotify");
		xf_cliprdr_get_requested_data(xfi,
			cb->format_mappings[cb->request_index].target_format);
	}

	return TRUE;
}
コード例 #3
0
ファイル: xf_cliprdr.c プロジェクト: Nigel62/FreeRDP
static void xf_cliprdr_send_raw_format_list(xfInfo* xfi)
{
	Atom type;
	BYTE* format_data;
	int format, result;
	unsigned long length, bytes_left;
	RDP_CB_FORMAT_LIST_EVENT* event;
	clipboardContext* cb = (clipboardContext*) xfi->clipboard_context;

	result = XGetWindowProperty(xfi->display, cb->root_window,
		cb->property_atom, 0, 3600, 0, XA_STRING,
		&type, &format, &length, &bytes_left, (BYTE**) &format_data);

	if (result != Success)
	{
		DEBUG_WARN("XGetWindowProperty failed");
		return;
	}
	DEBUG_X11_CLIPRDR("format=%d len=%d bytes_left=%d", format, (int) length, (int) bytes_left);

	event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(CliprdrChannel_Class,
			CliprdrChannel_FormatList, NULL, NULL);

	event->raw_format_data = (BYTE*) malloc(length);
	CopyMemory(event->raw_format_data, format_data, length);
	event->raw_format_data_size = length;
	XFree(format_data);

	freerdp_channels_send_event(cb->channels, (wMessage*) event);
}
コード例 #4
0
ファイル: xf_cliprdr.c プロジェクト: Nigel62/FreeRDP
void xf_process_cliprdr_event(xfInfo* xfi, wMessage* event)
{
	switch (GetMessageType(event->id))
	{
		case CliprdrChannel_MonitorReady:
			xf_cliprdr_process_cb_monitor_ready_event(xfi);
			break;

		case CliprdrChannel_FormatList:
			xf_cliprdr_process_cb_format_list_event(xfi, (RDP_CB_FORMAT_LIST_EVENT*) event);
			break;

		case CliprdrChannel_DataRequest:
			xf_cliprdr_process_cb_data_request_event(xfi, (RDP_CB_DATA_REQUEST_EVENT*) event);
			break;

		case CliprdrChannel_DataResponse:
			xf_cliprdr_process_cb_data_response_event(xfi, (RDP_CB_DATA_RESPONSE_EVENT*) event);
			break;

		default:
			DEBUG_X11_CLIPRDR("unknown event type %d", GetMessageType(event->id));
			break;
	}
}
コード例 #5
0
ファイル: xf_cliprdr.c プロジェクト: johnsonyes/FreeRDP
void xf_process_cliprdr_event(xfInfo* xfi, RDP_EVENT* event)
{
	switch (event->event_type)
	{
		case RDP_EVENT_TYPE_CB_MONITOR_READY:
			xf_cliprdr_process_cb_monitor_ready_event(xfi);
			break;

		case RDP_EVENT_TYPE_CB_FORMAT_LIST:
			xf_cliprdr_process_cb_format_list_event(xfi, (RDP_CB_FORMAT_LIST_EVENT*) event);
			break;

		case RDP_EVENT_TYPE_CB_DATA_REQUEST:
			xf_cliprdr_process_cb_data_request_event(xfi, (RDP_CB_DATA_REQUEST_EVENT*) event);
			break;

		case RDP_EVENT_TYPE_CB_DATA_RESPONSE:
			xf_cliprdr_process_cb_data_response_event(xfi, (RDP_CB_DATA_RESPONSE_EVENT*) event);
			break;

		default:
			DEBUG_X11_CLIPRDR("unknown event type %d", event->event_type);
			break;
	}
}
コード例 #6
0
ファイル: xf_cliprdr.c プロジェクト: Nigel62/FreeRDP
static void xf_cliprdr_get_requested_targets(xfInfo* xfi)
{
	int num;
	int i, j;
	Atom atom;
	int format;
	BYTE* data = NULL;
	unsigned long length, bytes_left;
	RDP_CB_FORMAT_LIST_EVENT* event;
	clipboardContext* cb = (clipboardContext*) xfi->clipboard_context;

	XGetWindowProperty(xfi->display, xfi->drawable, cb->property_atom,
		0, 200, 0, XA_ATOM, &atom, &format, &length, &bytes_left, &data);

	DEBUG_X11_CLIPRDR("type=%d format=%d length=%d bytes_left=%d",
		(int) atom, format, (int) length, (int) bytes_left);

	if (length > 0)
	{
		event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(CliprdrChannel_Class,
				CliprdrChannel_FormatList, NULL, NULL);

		event->formats = (UINT32*) malloc(sizeof(UINT32) * cb->num_format_mappings);
		num = 0;

		for (i = 0; i < length; i++)
		{
			atom = ((Atom*) data)[i];
			DEBUG_X11("atom %d", (int) atom);

			for (j = 0; j < cb->num_format_mappings; j++)
			{
				if (cb->format_mappings[j].target_format == atom)
				{
					DEBUG_X11("found format %d for atom %d",
						cb->format_mappings[j].format_id, (int)atom);
					event->formats[num++] = cb->format_mappings[j].format_id;
					break;
				}
			}
		}

		event->num_formats = num;
		XFree(data);

		freerdp_channels_send_event(cb->channels, (wMessage*) event);
	}
	else
	{
		if (data)
			XFree(data);

		xf_cliprdr_send_null_format_list(xfi);
	}
}
コード例 #7
0
ファイル: xf_cliprdr.c プロジェクト: johnsonyes/FreeRDP
static void xf_cliprdr_process_dib(clipboardContext* cb, uint8* data, int size)
{
	STREAM* s;
	uint16 bpp;
	uint32 offset;
	uint32 ncolors;

	/* size should be at least sizeof(BITMAPINFOHEADER) */
	if (size < 40)
	{
		DEBUG_X11_CLIPRDR("dib size %d too short", size);
		return;
	}

	s = stream_new(0);
	stream_attach(s, data, size);
	stream_seek(s, 14);
	stream_read_uint16(s, bpp);
	stream_read_uint32(s, ncolors);
	offset = 14 + 40 + (bpp <= 8 ? (ncolors == 0 ? (1 << bpp) : ncolors) * 4 : 0);
	stream_detach(s);
	stream_free(s);

	DEBUG_X11_CLIPRDR("offset=%d bpp=%d ncolors=%d", offset, bpp, ncolors);

	s = stream_new(14 + size);
	stream_write_uint8(s, 'B');
	stream_write_uint8(s, 'M');
	stream_write_uint32(s, 14 + size);
	stream_write_uint32(s, 0);
	stream_write_uint32(s, offset);
	stream_write(s, data, size);

	cb->data = stream_get_head(s);
	cb->data_length = stream_get_length(s);
	stream_detach(s);
	stream_free(s);
}
コード例 #8
0
ファイル: xf_cliprdr.c プロジェクト: Nigel62/FreeRDP
static void xf_cliprdr_process_cb_data_request_event(xfInfo* xfi, RDP_CB_DATA_REQUEST_EVENT* event)
{
	int i;
	clipboardContext* cb = (clipboardContext*) xfi->clipboard_context;

	DEBUG_X11_CLIPRDR("format %d", event->format);

	if (xf_cliprdr_is_self_owned(xfi))
	{
		/* CB_FORMAT_RAW */
		i = 0;
		XChangeProperty(xfi->display, xfi->drawable, cb->property_atom,
			XA_INTEGER, 32, PropModeReplace, (BYTE*) &event->format, 1);
	}
	else
	{
		i = xf_cliprdr_select_format_by_id(cb, event->format);
	}

	if (i < 0)
	{
		DEBUG_X11_CLIPRDR("unsupported format requested");
		xf_cliprdr_send_null_data_response(xfi);
	}
	else
	{
		cb->request_index = i;

		DEBUG_X11_CLIPRDR("target=%d", (int) cb->format_mappings[i].target_format);

		XConvertSelection(xfi->display, cb->clipboard_atom,
			cb->format_mappings[i].target_format, cb->property_atom,
			xfi->drawable, CurrentTime);
		XFlush(xfi->display);
		/* After this point, we expect a SelectionNotify event from the clipboard owner. */
	}
}
コード例 #9
0
ファイル: xf_cliprdr.c プロジェクト: Nigel62/FreeRDP
static void xf_cliprdr_process_dib(clipboardContext* cb, BYTE* data, int size)
{
	wStream* s;
	UINT16 bpp;
	UINT32 offset;
	UINT32 ncolors;

	/* size should be at least sizeof(BITMAPINFOHEADER) */

	if (size < 40)
	{
		DEBUG_X11_CLIPRDR("dib size %d too short", size);
		return;
	}

	s = Stream_New(data, size);
	Stream_Seek(s, 14);
	Stream_Read_UINT16(s, bpp);
	Stream_Read_UINT32(s, ncolors);
	offset = 14 + 40 + (bpp <= 8 ? (ncolors == 0 ? (1 << bpp) : ncolors) * 4 : 0);
	Stream_Free(s, FALSE);

	DEBUG_X11_CLIPRDR("offset=%d bpp=%d ncolors=%d", offset, bpp, ncolors);

	s = Stream_New(NULL, 14 + size);
	Stream_Write_UINT8(s, 'B');
	Stream_Write_UINT8(s, 'M');
	Stream_Write_UINT32(s, 14 + size);
	Stream_Write_UINT32(s, 0);
	Stream_Write_UINT32(s, offset);
	Stream_Write(s, data, size);

	cb->data = Stream_Buffer(s);
	cb->data_length = Stream_GetPosition(s);
	Stream_Free(s, FALSE);
}
コード例 #10
0
ファイル: xf_cliprdr.c プロジェクト: johnsonyes/FreeRDP
static uint8* xf_cliprdr_process_requested_dib(uint8* data, int* size)
{
	uint8* outbuf;

	/* length should be at least BMP header (14) + sizeof(BITMAPINFOHEADER) */
	if (*size < 54)
	{
		DEBUG_X11_CLIPRDR("bmp length %d too short", *size);
		return NULL;
	}

	*size -= 14;
	outbuf = (uint8*) xzalloc(*size);
	memcpy(outbuf, data + 14, *size);

	return outbuf;
}
コード例 #11
0
ファイル: xf_cliprdr.c プロジェクト: gotomypc/FreeRDP
static BYTE* xf_cliprdr_process_requested_dib(BYTE* data, int* size)
{
	BYTE* outbuf;

	/* length should be at least BMP header (14) + sizeof(BITMAPINFOHEADER) */
	if (*size < 54)
	{
		DEBUG_X11_CLIPRDR("bmp length %d too short", *capacity);
		return NULL;
	}

	*size -= 14;
	outbuf = (BYTE*) malloc(*size);
	ZeroMemory(outbuf, *size);

	memcpy(outbuf, data + 14, *size);

	return outbuf;
}
コード例 #12
0
ファイル: xf_cliprdr.c プロジェクト: Nigel62/FreeRDP
BOOL xf_cliprdr_process_selection_notify(xfInfo* xfi, XEvent* xevent)
{
	clipboardContext* cb = (clipboardContext*) xfi->clipboard_context;

	if (xevent->xselection.target == cb->targets[1])
	{
		if (xevent->xselection.property == None)
		{
			DEBUG_X11_CLIPRDR("owner not support TARGETS. sending all format.");
			xf_cliprdr_send_supported_format_list(xfi);
		}
		else
		{
			xf_cliprdr_get_requested_targets(xfi);
		}

		return TRUE;
	}
	else
	{
		return xf_cliprdr_get_requested_data(xfi, xevent->xselection.target);
	}
}
コード例 #13
0
ファイル: xf_cliprdr.c プロジェクト: Nigel62/FreeRDP
static void xf_cliprdr_process_cb_data_response_event(xfInfo* xfi, RDP_CB_DATA_RESPONSE_EVENT* event)
{
	clipboardContext* cb = (clipboardContext*) xfi->clipboard_context;

	DEBUG_X11_CLIPRDR("size=%d", event->size);

	if (!cb->respond)
	{
		DEBUG_X11_CLIPRDR("unexpected data");
		return;
	}

	if (event->size == 0)
	{
		cb->respond->xselection.property = None;
	}
	else
	{
		if (cb->data)
		{
			free(cb->data);
			cb->data = NULL;
		}

		switch (cb->data_format)
		{
			case CB_FORMAT_RAW:
			case CB_FORMAT_PNG:
			case CB_FORMAT_JPEG:
			case CB_FORMAT_GIF:
				cb->data = event->data;
				cb->data_length = event->size;
				event->data = NULL;
				event->size = 0;
				break;

			case CB_FORMAT_TEXT:
				xf_cliprdr_process_text(cb, event->data, event->size);
				break;

			case CB_FORMAT_UNICODETEXT:
				xf_cliprdr_process_unicodetext(cb, event->data, event->size);
				break;

			case CB_FORMAT_DIB:
				xf_cliprdr_process_dib(cb, event->data, event->size);
				break;

			case CB_FORMAT_HTML:
				xf_cliprdr_process_html(cb, event->data, event->size);
				break;

			default:
				cb->respond->xselection.property = None;
				break;
		}
		xf_cliprdr_provide_data(xfi, cb->respond);
	}

	XSendEvent(xfi->display, cb->respond->xselection.requestor, 0, 0, cb->respond);
	XFlush(xfi->display);
	free(cb->respond);
	cb->respond = NULL;
}
コード例 #14
0
ファイル: xf_cliprdr.c プロジェクト: Nigel62/FreeRDP
static BOOL xf_cliprdr_get_requested_data(xfInfo* xfi, Atom target)
{
	Atom type;
	int format;
	BYTE* data = NULL;
	BOOL has_data = FALSE;
	unsigned long length, bytes_left, dummy;
	clipboardContext* cb = (clipboardContext*) xfi->clipboard_context;

	if ((cb->request_index < 0) || (cb->format_mappings[cb->request_index].target_format != target))
	{
		DEBUG_X11_CLIPRDR("invalid target");
		xf_cliprdr_send_null_data_response(xfi);
		return FALSE;
	}

	XGetWindowProperty(xfi->display, xfi->drawable,
		cb->property_atom, 0, 0, 0, target,
		&type, &format, &length, &bytes_left, &data);

	DEBUG_X11_CLIPRDR("type=%d format=%d bytes=%d request_index=%d",
		(int) type, format, (int) bytes_left, cb->request_index);

	if (data)
	{
		XFree(data);
		data = NULL;
	}
	if (bytes_left <= 0 && !cb->incr_starts)
	{
		DEBUG_X11("no data");
	}
	else if (type == cb->incr_atom)
	{
		DEBUG_X11("INCR started");
		cb->incr_starts = TRUE;
		if (cb->incr_data)
		{
			free(cb->incr_data);
			cb->incr_data = NULL;
		}
		cb->incr_data_length = 0;
		/* Data will be followed in PropertyNotify event */
		has_data = TRUE;
	}
	else
	{
		if (bytes_left <= 0)
		{
			/* INCR finish */
			data = cb->incr_data;
			cb->incr_data = NULL;
			bytes_left = cb->incr_data_length;
			cb->incr_data_length = 0;
			cb->incr_starts = 0;
			DEBUG_X11("INCR finished");
			has_data = TRUE;
		}
		else if (XGetWindowProperty(xfi->display, xfi->drawable,
			cb->property_atom, 0, bytes_left, 0, target,
			&type, &format, &length, &dummy, &data) == Success)
		{
			if (cb->incr_starts)
			{
				bytes_left = length * format / 8;
				DEBUG_X11("%d bytes", (int)bytes_left);
				cb->incr_data = (BYTE*) realloc(cb->incr_data, cb->incr_data_length + bytes_left);
				CopyMemory(cb->incr_data + cb->incr_data_length, data, bytes_left);
				cb->incr_data_length += bytes_left;
				XFree(data);
				data = NULL;
			}
			has_data = TRUE;
		}
		else
		{
			DEBUG_X11_CLIPRDR("XGetWindowProperty failed");
		}
	}
	XDeleteProperty(xfi->display, xfi->drawable, cb->property_atom);

	xf_cliprdr_process_requested_data(xfi, has_data, data, (int) bytes_left);

	if (data)
		XFree(data);

	return TRUE;
}
コード例 #15
0
ファイル: xf_cliprdr.c プロジェクト: Nigel62/FreeRDP
BOOL xf_cliprdr_process_selection_request(xfInfo* xfi, XEvent* xevent)
{
	int i;
	int fmt;
	Atom type;
	UINT32 format;
	XEvent* respond;
	UINT32 alt_format;
	BYTE* data = NULL;
	BOOL delay_respond;
	unsigned long length, bytes_left;
	clipboardContext* cb = (clipboardContext*) xfi->clipboard_context;

	DEBUG_X11_CLIPRDR("target=%d", (int) xevent->xselectionrequest.target);

	if (xevent->xselectionrequest.owner != xfi->drawable)
	{
		DEBUG_X11_CLIPRDR("not owner");
		return FALSE;
	}

	delay_respond = FALSE;

	respond = (XEvent*) malloc(sizeof(XEvent));
	ZeroMemory(respond, sizeof(XEvent));

	respond->xselection.property = None;
	respond->xselection.type = SelectionNotify;
	respond->xselection.display = xevent->xselectionrequest.display;
	respond->xselection.requestor = xevent->xselectionrequest.requestor;
	respond->xselection.selection = xevent->xselectionrequest.selection;
	respond->xselection.target = xevent->xselectionrequest.target;
	respond->xselection.time = xevent->xselectionrequest.time;

	if (xevent->xselectionrequest.target == cb->targets[0]) /* TIMESTAMP */
	{
		/* TODO */
		DEBUG_X11_CLIPRDR("target: TIMESTAMP (unimplemented)");
	}
	else if (xevent->xselectionrequest.target == cb->targets[1]) /* TARGETS */
	{
		/* Someone else requests our available formats */
		DEBUG_X11_CLIPRDR("target: TARGETS");
		respond->xselection.property = xevent->xselectionrequest.property;
		xf_cliprdr_provide_targets(xfi, respond);
	}
	else
	{
		DEBUG_X11_CLIPRDR("target: other");

		i = xf_cliprdr_select_format_by_atom(cb, xevent->xselectionrequest.target);

		if (i >= 0 && xevent->xselectionrequest.requestor != xfi->drawable)
		{
			format = cb->format_mappings[i].format_id;
			alt_format = format;

			if (format == CB_FORMAT_RAW)
			{
				if (XGetWindowProperty(xfi->display, xevent->xselectionrequest.requestor,
					cb->property_atom, 0, 4, 0, XA_INTEGER,
					&type, &fmt, &length, &bytes_left, &data) != Success)
				{
					DEBUG_X11_CLIPRDR("XGetWindowProperty failed");
				}
				if (data)
				{
					CopyMemory(&alt_format, data, 4);
					XFree(data);
				}
			}

			DEBUG_X11_CLIPRDR("provide format 0x%04x alt_format 0x%04x", format, alt_format);

			if ((cb->data != 0) && (format == cb->data_format) && (alt_format == cb->data_alt_format))
			{
				/* Cached clipboard data available. Send it now */
				respond->xselection.property = xevent->xselectionrequest.property;
				xf_cliprdr_provide_data(xfi, respond);
			}
			else if (cb->respond)
			{
				DEBUG_X11_CLIPRDR("duplicated request");
			}
			else
			{
				/**
				 * Send clipboard data request to the server.
				 * Response will be postponed after receiving the data
				 */
				if (cb->data)
				{
					free(cb->data);
					cb->data = NULL;
				}

				respond->xselection.property = xevent->xselectionrequest.property;
				cb->respond = respond;
				cb->data_format = format;
				cb->data_alt_format = alt_format;
				delay_respond = TRUE;

				xf_cliprdr_send_data_request(xfi, alt_format);
			}
		}
	}

	if (delay_respond == FALSE)
	{
		XSendEvent(xfi->display, xevent->xselectionrequest.requestor, 0, 0, respond);
		XFlush(xfi->display);
		free(respond);
	}

	return TRUE;
}