diff --git a/client/X11/xf_cliprdr.c b/client/X11/xf_cliprdr.c index 7cca2c4b7..539795cf3 100644 --- a/client/X11/xf_cliprdr.c +++ b/client/X11/xf_cliprdr.c @@ -93,7 +93,7 @@ struct xf_clipboard int xf_cliprdr_send_client_format_list(xfClipboard* clipboard); -static BYTE* lf2crlf(BYTE* data, int* size) +static BYTE* ConvertLineEndingToCRLF(BYTE* str, int* size) { BYTE c; BYTE* outbuf; @@ -104,15 +104,15 @@ static BYTE* lf2crlf(BYTE* data, int* size) out_size = (*size) * 2 + 1; outbuf = (BYTE*) malloc(out_size); - ZeroMemory(outbuf, out_size); out = outbuf; - in = data; - in_end = data + (*size); + in = str; + in_end = str + (*size); while (in < in_end) { c = *in++; + if (c == '\n') { *out++ = '\r'; @@ -130,16 +130,17 @@ static BYTE* lf2crlf(BYTE* data, int* size) return outbuf; } -static void crlf2lf(BYTE* data, int* size) +static int ConvertLineEndingToLF(BYTE* str, int length) { BYTE c; BYTE* out; BYTE* in; BYTE* in_end; + int status = -1; - out = data; - in = data; - in_end = data + (*size); + out = str; + in = str; + in_end = &str[length]; while (in < in_end) { @@ -149,21 +150,19 @@ static void crlf2lf(BYTE* data, int* size) *out++ = c; } - *size = out - data; + status = out - str; + + return status; } -static void be2le(BYTE* data, int size) +static void ByteSwapUnicode(WCHAR* wstr, int length) { - BYTE c; + WCHAR* end = &wstr[length]; - while (size >= 2) + while (wstr < end) { - c = data[0]; - data[0] = data[1]; - data[1] = c; - - data += 2; - size -= 2; + *wstr = _byteswap_ushort(*wstr); + wstr++; } } @@ -242,31 +241,6 @@ static xfCliprdrFormat* xf_cliprdr_get_format_by_atom(xfClipboard* clipboard, At return NULL; } -static void xf_cliprdr_send_supported_format_list(xfClipboard* clipboard) -{ - int i; - - CLIPRDR_FORMAT* formats; - CLIPRDR_FORMAT_LIST formatList; - - ZeroMemory(&formatList, sizeof(CLIPRDR_FORMAT_LIST)); - - formatList.msgFlags = CB_RESPONSE_OK; - formatList.cFormats = clipboard->numClientFormats; - formats = (CLIPRDR_FORMAT*) calloc(formatList.cFormats, sizeof(CLIPRDR_FORMAT)); - formatList.formats = formats; - - for (i = 0; i < clipboard->numClientFormats; i++) - { - formats->formatId = clipboard->clientFormats[i].formatId; - formats->formatName = clipboard->clientFormats[i].formatName; - } - - clipboard->context->ClientFormatList(clipboard->context, &formatList); - - free(formats); -} - static void xf_cliprdr_send_data_request(xfClipboard* clipboard, UINT32 formatId) { CLIPRDR_FORMAT_DATA_REQUEST request; @@ -305,6 +279,9 @@ static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard) CLIPRDR_FORMAT* formats = NULL; xfContext* xfc = clipboard->xfc; + if (!clipboard->numServerFormats) + return; /* server format list was not yet received */ + XGetWindowProperty(xfc->display, xfc->drawable, clipboard->property_atom, 0, 200, 0, XA_ATOM, &atom, &format_property, &length, &bytes_left, &data); @@ -350,7 +327,7 @@ static BYTE* xf_cliprdr_process_requested_unicodetext(BYTE* data, int* size) WCHAR* outbuf = NULL; int out_size; - inbuf = (char*) lf2crlf(data, size); + inbuf = (char*) ConvertLineEndingToCRLF(data, size); out_size = ConvertToUnicode(CP_UTF8, 0, inbuf, -1, &outbuf, 0); free(inbuf); @@ -363,7 +340,7 @@ static BYTE* xf_cliprdr_process_requested_text(BYTE* data, int* size) { BYTE* outbuf; - outbuf = lf2crlf(data, size); + outbuf = ConvertLineEndingToCRLF(data, size); return outbuf; } @@ -395,19 +372,23 @@ static BYTE* xf_cliprdr_process_requested_html(BYTE* data, int* size) if (*size > 2) { - if ((BYTE) data[0] == 0xFE && (BYTE) data[1] == 0xFF) + BYTE bom[2]; + + CopyMemory(bom, data, 2); + + if ((bom[0] == 0xFE) && (bom[1] == 0xFF)) { - be2le(data, *size); + ByteSwapUnicode((WCHAR*) data, *size / 2); } - if ((BYTE) data[0] == 0xFF && (BYTE) data[1] == 0xFE) + if ((bom[0] == 0xFF) && (bom[1] == 0xFE)) { ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) (data + 2), (*size - 2) / 2, &inbuf, 0, NULL, NULL); } } - if (inbuf == NULL) + if (!inbuf) { inbuf = calloc(1, *size + 1); CopyMemory(inbuf, data, *size); @@ -424,17 +405,16 @@ static BYTE* xf_cliprdr_process_requested_html(BYTE* data, int* size) in = (BYTE*) strstr((char*) inbuf, ""); - } + strcat((char*) outbuf, ""); /* StartFragment */ snprintf(num, sizeof(num), "%010lu", (unsigned long) strlen((char*) outbuf)); @@ -444,10 +424,10 @@ static BYTE* xf_cliprdr_process_requested_html(BYTE* data, int* size) snprintf(num, sizeof(num), "%010lu", (unsigned long) strlen((char*) outbuf)); CopyMemory(outbuf + 93, num, 10); strcat((char*) outbuf, ""); - if (in == NULL) - { + + if (!in) strcat((char*) outbuf, ""); - } + /* EndHTML */ snprintf(num, sizeof(num), "%010lu", (unsigned long) strlen((char*) outbuf)); CopyMemory(outbuf + 43, num, 10); @@ -645,81 +625,109 @@ static void xf_cliprdr_provide_data(xfClipboard* clipboard, XEvent* respond) } } -static void xf_cliprdr_process_text(xfClipboard* clipboard, BYTE* data, int size) +static int xf_cliprdr_process_text(BYTE* pSrcData, int SrcSize, BYTE** ppDstData) { - clipboard->data = (BYTE*) malloc(size); - CopyMemory(clipboard->data, data, size); - clipboard->data_length = size; - crlf2lf(clipboard->data, &clipboard->data_length); + int DstSize = -1; + BYTE* pDstData = NULL; + + pDstData = (BYTE*) malloc(SrcSize); + CopyMemory(pDstData, pSrcData, SrcSize); + + DstSize = SrcSize; + DstSize = ConvertLineEndingToLF(pDstData, DstSize); + + *ppDstData = pDstData; + + return DstSize; } -static void xf_cliprdr_process_unicodetext(xfClipboard* clipboard, BYTE* data, int size) +static int xf_cliprdr_process_unicodetext(BYTE* pSrcData, int SrcSize, BYTE** ppDstData) { - clipboard->data_length = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) data, size / 2, (CHAR**) &(clipboard->data), 0, NULL, NULL); - crlf2lf(clipboard->data, &clipboard->data_length); + int DstSize = -1; + BYTE* pDstData = NULL; + + DstSize = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) pSrcData, + SrcSize / 2, (CHAR**) &pDstData, 0, NULL, NULL); + + DstSize = ConvertLineEndingToLF(pDstData, DstSize); + + *ppDstData = pDstData; + + return DstSize; } -static BOOL xf_cliprdr_process_dib(xfClipboard* clipboard, BYTE* data, int size) +static int xf_cliprdr_process_dib(BYTE* pSrcData, int SrcSize, BYTE** ppDstData) { wStream* s; UINT16 bpp; UINT32 offset; UINT32 ncolors; + int DstSize = -1; + BYTE* pDstData = NULL; /* size should be at least sizeof(BITMAPINFOHEADER) */ - if (size < 40) - return FALSE; + if (SrcSize < 40) + return -1; - s = Stream_New(data, size); + s = Stream_New(pSrcData, SrcSize); Stream_Seek(s, 14); Stream_Read_UINT16(s, bpp); if ((bpp < 1) || (bpp > 32)) - return FALSE; + return -1; Stream_Read_UINT32(s, ncolors); offset = 14 + 40 + (bpp <= 8 ? (ncolors == 0 ? (1 << bpp) : ncolors) * 4 : 0); Stream_Free(s, FALSE); - s = Stream_New(NULL, 14 + size); + s = Stream_New(NULL, 14 + SrcSize); Stream_Write_UINT8(s, 'B'); Stream_Write_UINT8(s, 'M'); - Stream_Write_UINT32(s, 14 + size); + Stream_Write_UINT32(s, 14 + SrcSize); Stream_Write_UINT32(s, 0); Stream_Write_UINT32(s, offset); - Stream_Write(s, data, size); + Stream_Write(s, pSrcData, SrcSize); - clipboard->data = Stream_Buffer(s); - clipboard->data_length = Stream_GetPosition(s); + pDstData = Stream_Buffer(s); + DstSize = Stream_GetPosition(s); Stream_Free(s, FALSE); - return TRUE; + *ppDstData = pDstData; + + return DstSize; } -static void xf_cliprdr_process_html(xfClipboard* clipboard, BYTE* data, int size) +static int xf_cliprdr_process_html(BYTE* pSrcData, int SrcSize, BYTE** ppDstData) { int start; int end; char* start_str; char* end_str; + int DstSize = -1; + BYTE* pDstData = NULL; - start_str = strstr((char*) data, "StartHTML:"); - end_str = strstr((char*) data, "EndHTML:"); + start_str = strstr((char*) pSrcData, "StartHTML:"); + end_str = strstr((char*) pSrcData, "EndHTML:"); if (!start_str || !end_str) - return; + return -1; start = atoi(start_str + 10); end = atoi(end_str + 8); - if ((start > size) || (end > size) || (start >= end)) - return; + if ((start > SrcSize) || (end > SrcSize) || (start >= end)) + return -1; - clipboard->data = (BYTE*) malloc(size - start + 1); - CopyMemory(clipboard->data, data + start, end - start); - clipboard->data_length = end - start; - crlf2lf(clipboard->data, &clipboard->data_length); + DstSize = end - start; + + pDstData = (BYTE*) malloc(SrcSize - start + 1); + CopyMemory(pDstData, pSrcData + start, DstSize); + DstSize = ConvertLineEndingToLF(pDstData, DstSize); + + *ppDstData = pDstData; + + return DstSize; } static BOOL xf_cliprdr_process_selection_notify(xfClipboard* clipboard, XEvent* xevent) @@ -728,7 +736,7 @@ static BOOL xf_cliprdr_process_selection_notify(xfClipboard* clipboard, XEvent* { if (xevent->xselection.property == None) { - xf_cliprdr_send_supported_format_list(clipboard); + xf_cliprdr_send_client_format_list(clipboard); } else { @@ -987,59 +995,31 @@ int xf_cliprdr_send_client_capabilities(xfClipboard* clipboard) int xf_cliprdr_send_client_format_list(xfClipboard* clipboard) { + UINT32 i, numFormats; + CLIPRDR_FORMAT* formats; CLIPRDR_FORMAT_LIST formatList; xfContext* xfc = clipboard->xfc; ZeroMemory(&formatList, sizeof(CLIPRDR_FORMAT_LIST)); - if (!clipboard->sync) + numFormats = clipboard->numClientFormats; + formats = (CLIPRDR_FORMAT*) calloc(numFormats, sizeof(CLIPRDR_FORMAT)); + + for (i = 0; i < numFormats; i++) { - UINT32 i, numFormats; - CLIPRDR_FORMAT* formats; - - numFormats = clipboard->numClientFormats; - formats = (CLIPRDR_FORMAT*) calloc(numFormats, sizeof(CLIPRDR_FORMAT)); - - for (i = 0; i < numFormats; i++) - { - formats[i].formatId = clipboard->clientFormats[i].formatId; - formats[i].formatName = clipboard->clientFormats[i].formatName; - } - - formatList.msgFlags = CB_RESPONSE_OK; - formatList.cFormats = numFormats; - formatList.formats = formats; - - clipboard->context->ClientFormatList(clipboard->context, &formatList); - - free(formats); - - return 1; + formats[i].formatId = clipboard->clientFormats[i].formatId; + formats[i].formatName = clipboard->clientFormats[i].formatName; } - if (xf_cliprdr_is_self_owned(clipboard)) - { - /** - * TODO: handle (raw?) format data - * The original code appears to be sending back the original, - * unmodified server format list here. - */ + formatList.msgFlags = CB_RESPONSE_OK; + formatList.cFormats = numFormats; + formatList.formats = formats; - formatList.msgFlags = CB_RESPONSE_OK; - formatList.cFormats = clipboard->numServerFormats; - formatList.formats = clipboard->serverFormats; + clipboard->context->ClientFormatList(clipboard->context, &formatList); - clipboard->context->ClientFormatList(clipboard->context, &formatList); - } - else if (clipboard->owner == None) - { - formatList.msgFlags = CB_RESPONSE_OK; - formatList.cFormats = 0; - formatList.formats = NULL; + free(formats); - clipboard->context->ClientFormatList(clipboard->context, &formatList); - } - else if (clipboard->owner != xfc->drawable) + if (clipboard->owner != xfc->drawable) { /* Request the owner for TARGETS, and wait for SelectionNotify event */ XConvertSelection(xfc->display, clipboard->clipboard_atom, @@ -1115,6 +1095,8 @@ static int xf_cliprdr_server_format_list(CliprdrClientContext* context, CLIPRDR_ free(clipboard->serverFormats); clipboard->serverFormats = NULL; + + clipboard->numServerFormats = 0; } clipboard->numServerFormats = formatList->cFormats; @@ -1200,6 +1182,8 @@ static int xf_cliprdr_server_format_data_request(CliprdrClientContext* context, static int xf_cliprdr_server_format_data_response(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse) { + int status; + BYTE* pDstData; UINT32 size = formatDataResponse->dataLen; BYTE* data = formatDataResponse->requestedFormatData; xfClipboard* clipboard = (xfClipboard*) context->custom; @@ -1220,12 +1204,16 @@ static int xf_cliprdr_server_format_data_response(CliprdrClientContext* context, clipboard->data = NULL; } + status = -1; + pDstData = NULL; + switch (clipboard->data_format) { case CLIPRDR_FORMAT_RAW: case CB_FORMAT_PNG: case CB_FORMAT_JPEG: case CB_FORMAT_GIF: + status = size; clipboard->data = data; clipboard->data_length = size; data = NULL; @@ -1233,19 +1221,19 @@ static int xf_cliprdr_server_format_data_response(CliprdrClientContext* context, break; case CLIPRDR_FORMAT_TEXT: - xf_cliprdr_process_text(clipboard, data, size); + status = xf_cliprdr_process_text(data, size, &pDstData); break; case CLIPRDR_FORMAT_UNICODETEXT: - xf_cliprdr_process_unicodetext(clipboard, data, size); + status = xf_cliprdr_process_unicodetext(data, size, &pDstData); break; case CLIPRDR_FORMAT_DIB: - xf_cliprdr_process_dib(clipboard, data, size); + status = xf_cliprdr_process_dib(data, size, &pDstData); break; case CB_FORMAT_HTML: - xf_cliprdr_process_html(clipboard, data, size); + status = xf_cliprdr_process_html(data, size, &pDstData); break; default: @@ -1253,6 +1241,17 @@ static int xf_cliprdr_server_format_data_response(CliprdrClientContext* context, break; } + if (status < 1) + { + clipboard->data = NULL; + clipboard->data_length = 0; + } + else + { + clipboard->data = pDstData; + clipboard->data_length = status; + } + xf_cliprdr_provide_data(clipboard, clipboard->respond); }