20 #include <winpr/config.h>
23 #include <winpr/crt.h>
24 #include <winpr/user.h>
25 #include <winpr/image.h>
27 #include "../utils/image.h"
28 #include "clipboard.h"
30 static const char* mime_bitmap[] = {
"image/bmp",
"image/x-bmp",
"image/x-MS-bmp",
31 "image/x-win-bitmap" };
33 #if defined(WINPR_UTILS_IMAGE_WEBP)
34 static const char mime_webp[] =
"image/webp";
36 #if defined(WINPR_UTILS_IMAGE_PNG)
37 static const char mime_png[] =
"image/png";
39 #if defined(WINPR_UTILS_IMAGE_JPEG)
40 static const char mime_jpeg[] =
"image/jpeg";
53 static void* clipboard_synthesize_cf_text(wClipboard* clipboard, UINT32 formatId,
const void* data,
57 char* pDstData = NULL;
59 if (formatId == CF_UNICODETEXT)
61 char* str = ConvertWCharNToUtf8Alloc(data, *pSize /
sizeof(WCHAR), &size);
63 if (!str || (size > UINT32_MAX))
69 pDstData = ConvertLineEndingToCRLF(str, &size);
71 *pSize = (UINT32)size;
74 else if ((formatId == CF_TEXT) || (formatId == CF_OEMTEXT) ||
75 (formatId == ClipboardGetFormatId(clipboard, mime_text_plain)))
78 pDstData = ConvertLineEndingToCRLF(data, &size);
80 if (!pDstData || (size > *pSize))
83 *pSize = (UINT32)size;
96 static void* clipboard_synthesize_cf_oemtext(wClipboard* clipboard, UINT32 formatId,
97 const void* data, UINT32* pSize)
99 return clipboard_synthesize_cf_text(clipboard, formatId, data, pSize);
108 static void* clipboard_synthesize_cf_locale(wClipboard* clipboard, UINT32 formatId,
109 const void* data, UINT32* pSize)
111 UINT32* pDstData = NULL;
112 pDstData = (UINT32*)malloc(
sizeof(UINT32));
118 return (
void*)pDstData;
127 static void* clipboard_synthesize_cf_unicodetext(wClipboard* clipboard, UINT32 formatId,
128 const void* data, UINT32* pSize)
131 char* crlfStr = NULL;
132 WCHAR* pDstData = NULL;
134 if ((formatId == CF_TEXT) || (formatId == CF_OEMTEXT) ||
135 (formatId == ClipboardGetFormatId(clipboard, mime_text_plain)))
138 if (!pSize || (*pSize > INT32_MAX))
142 crlfStr = ConvertLineEndingToCRLF((
const char*)data, &size);
147 pDstData = ConvertUtf8NToWCharAlloc(crlfStr, size, &len);
150 if ((len < 1) || ((len + 1) > UINT32_MAX /
sizeof(WCHAR)))
156 const size_t slen = (len + 1) *
sizeof(WCHAR);
157 *pSize = (UINT32)slen;
160 return (
void*)pDstData;
169 static void* clipboard_synthesize_utf8_string(wClipboard* clipboard, UINT32 formatId,
170 const void* data, UINT32* pSize)
172 if (formatId == CF_UNICODETEXT)
175 char* pDstData = ConvertWCharNToUtf8Alloc(data, *pSize /
sizeof(WCHAR), &size);
180 const size_t rc = ConvertLineEndingToLF(pDstData, size);
181 WINPR_ASSERT(rc <= UINT32_MAX);
185 else if ((formatId == CF_TEXT) || (formatId == CF_OEMTEXT) ||
186 (formatId == ClipboardGetFormatId(clipboard, mime_text_plain)))
188 const size_t size = *pSize;
189 char* pDstData = calloc(size + 1,
sizeof(
char));
194 CopyMemory(pDstData, data, size);
195 const size_t rc = ConvertLineEndingToLF(pDstData, size);
196 WINPR_ASSERT(rc <= UINT32_MAX);
204 static BOOL is_format_bitmap(wClipboard* clipboard, UINT32 formatId)
206 for (
size_t x = 0; x < ARRAYSIZE(mime_bitmap); x++)
208 const char* mime = mime_bitmap[x];
209 const UINT32 altFormatId = ClipboardGetFormatId(clipboard, mime);
210 if (altFormatId == formatId)
223 static void* clipboard_synthesize_cf_dib(wClipboard* clipboard, UINT32 formatId,
const void* data,
228 BYTE* pDstData = NULL;
231 if (formatId == CF_DIBV5)
234 else if (is_format_bitmap(clipboard, formatId))
238 wStream* s = Stream_StaticConstInit(&sbuffer, data, SrcSize);
239 if (!readBitmapFileHeader(s, &pFileHeader))
243 pDstData = (BYTE*)malloc(DstSize);
249 CopyMemory(pDstData, data, DstSize);
263 static void* clipboard_synthesize_cf_dibv5(wClipboard* clipboard, UINT32 formatId,
const void* data,
266 if (formatId == CF_DIB)
269 else if (is_format_bitmap(clipboard, formatId))
277 const void* data,
size_t size, UINT32* pSize)
279 WINPR_ASSERT(pInfoHeader);
283 if ((pInfoHeader->biBitCount < 1) || (pInfoHeader->biBitCount > 32))
287 if (DstSize > UINT32_MAX)
290 wStream* s = Stream_New(NULL, DstSize);
295 fileHeader.bfType[0] =
'B';
296 fileHeader.bfType[1] =
'M';
297 fileHeader.bfSize = (UINT32)DstSize;
299 if (!writeBitmapFileHeader(s, &fileHeader))
302 if (!Stream_EnsureRemainingCapacity(s, size))
304 Stream_Write(s, data, size);
305 const size_t len = Stream_GetPosition(s);
308 *pSize = (UINT32)DstSize;
310 BYTE* dst = Stream_Buffer(s);
311 Stream_Free(s, FALSE);
315 Stream_Free(s, TRUE);
325 static void* clipboard_synthesize_image_bmp(wClipboard* clipboard, UINT32 formatId,
326 const void* data, UINT32* pSize)
328 UINT32 SrcSize = *pSize;
330 if (formatId == CF_DIB)
338 wStream* s = Stream_StaticConstInit(&sbuffer, data, SrcSize);
339 if (!readBitmapInfoHeader(s, &header, &offset))
342 return clipboard_prepend_bmp_header(&header, data, SrcSize, pSize);
344 else if (formatId == CF_DIBV5)
351 #if defined(WINPR_UTILS_IMAGE_PNG) || defined(WINPR_UTILS_IMAGE_WEBP) || \
352 defined(WINPR_UTILS_IMAGE_JPEG)
353 static void* clipboard_synthesize_image_bmp_to_format(wClipboard* clipboard, UINT32 formatId,
354 UINT32 bmpFormat,
const void* data,
357 WINPR_ASSERT(clipboard);
364 wImage* img = winpr_image_new();
365 void* bmp = clipboard_synthesize_image_bmp(clipboard, formatId, data, pSize);
366 const UINT32 SrcSize = *pSize;
372 if (winpr_image_read_buffer(img, bmp, SrcSize) <= 0)
375 result = winpr_image_write_buffer(img, bmpFormat, &dsize);
378 if (dsize <= UINT32_MAX)
379 *pSize = (UINT32)dsize;
389 winpr_image_free(img, TRUE);
394 #if defined(WINPR_UTILS_IMAGE_PNG)
395 static void* clipboard_synthesize_image_bmp_to_png(wClipboard* clipboard, UINT32 formatId,
396 const void* data, UINT32* pSize)
398 return clipboard_synthesize_image_bmp_to_format(clipboard, formatId, WINPR_IMAGE_PNG, data,
402 static void* clipboard_synthesize_image_format_to_bmp(wClipboard* clipboard, UINT32 srcFormatId,
403 const void* data, UINT32* pSize)
405 WINPR_ASSERT(clipboard);
410 const UINT32 SrcSize = *pSize;
412 wImage* image = winpr_image_new();
416 const int res = winpr_image_read_buffer(image, data, SrcSize);
420 dst = winpr_image_write_buffer(image, WINPR_IMAGE_BITMAP, &size);
427 *pSize = (UINT32)size;
430 winpr_image_free(image, TRUE);
438 static void* clipboard_synthesize_image_png_to_bmp(wClipboard* clipboard, UINT32 formatId,
439 const void* data, UINT32* pSize)
441 return clipboard_synthesize_image_format_to_bmp(clipboard, formatId, data, pSize);
445 #if defined(WINPR_UTILS_IMAGE_WEBP)
446 static void* clipboard_synthesize_image_bmp_to_webp(wClipboard* clipboard, UINT32 formatId,
447 const void* data, UINT32* pSize)
449 return clipboard_synthesize_image_bmp_to_format(clipboard, formatId, WINPR_IMAGE_WEBP, data,
453 static void* clipboard_synthesize_image_webp_to_bmp(wClipboard* clipboard, UINT32 formatId,
454 const void* data, UINT32* pSize)
456 return clipboard_synthesize_image_format_to_bmp(clipboard, formatId, data, pSize);
460 #if defined(WINPR_UTILS_IMAGE_JPEG)
461 static void* clipboard_synthesize_image_bmp_to_jpeg(wClipboard* clipboard, UINT32 formatId,
462 const void* data, UINT32* pSize)
464 return clipboard_synthesize_image_bmp_to_format(clipboard, formatId, WINPR_IMAGE_JPEG, data,
468 static void* clipboard_synthesize_image_jpeg_to_bmp(wClipboard* clipboard, UINT32 formatId,
469 const void* data, UINT32* pSize)
471 return clipboard_synthesize_image_format_to_bmp(clipboard, formatId, data, pSize);
481 static void* clipboard_synthesize_html_format(wClipboard* clipboard, UINT32 formatId,
482 const void* pData, UINT32* pSize)
491 char* pDstData = NULL;
495 WINPR_ASSERT(clipboard);
498 if (formatId == ClipboardGetFormatId(clipboard,
"text/html"))
500 const INT64 SrcSize = (INT64)*pSize;
501 const size_t DstSize = SrcSize + 200;
503 char num[20] = { 0 };
506 pSrcData.pv = calloc(1, SrcSize + 1);
509 memcpy(pSrcData.pv, pData, SrcSize);
513 if (SrcSize > INT_MAX)
517 if ((pSrcData.cpb[0] == 0xFE) && (pSrcData.cpb[1] == 0xFF))
518 ByteSwapUnicode(pSrcData.pv, (SrcSize / 2));
521 if ((pSrcData.cpb[0] == 0xFF) && (pSrcData.cpb[1] == 0xFE))
524 ConvertWCharNToUtf8Alloc(&pSrcData.pv[1], SrcSize /
sizeof(WCHAR), NULL);
526 pSrcData.cpc = utfString;
532 pDstData = (
char*)calloc(1, DstSize);
537 (void)sprintf_s(pDstData, DstSize,
539 "StartHTML:0000000000\r\n"
540 "EndHTML:0000000000\r\n"
541 "StartFragment:0000000000\r\n"
542 "EndFragment:0000000000\r\n");
543 body = strstr(pSrcData.cpc,
"<body");
546 body = strstr(pSrcData.cpc,
"<BODY");
549 (void)sprintf_s(num,
sizeof(num),
"%010" PRIuz
"", strnlen(pDstData, DstSize));
550 CopyMemory(&pDstData[23], num, 10);
554 if (!winpr_str_append(
"<HTML><BODY>", pDstData, DstSize, NULL))
558 if (!winpr_str_append(
"<!--StartFragment-->", pDstData, DstSize, NULL))
562 (void)sprintf_s(num,
sizeof(num),
"%010" PRIuz
"", strnlen(pDstData, SrcSize + 200));
563 CopyMemory(&pDstData[69], num, 10);
565 if (!winpr_str_append(pSrcData.cpc, pDstData, DstSize, NULL))
569 (void)sprintf_s(num,
sizeof(num),
"%010" PRIuz
"", strnlen(pDstData, SrcSize + 200));
570 CopyMemory(&pDstData[93], num, 10);
572 if (!winpr_str_append(
"<!--EndFragment-->", pDstData, DstSize, NULL))
577 if (!winpr_str_append(
"</BODY></HTML>", pDstData, DstSize, NULL))
582 (void)sprintf_s(num,
sizeof(num),
"%010" PRIuz
"", strnlen(pDstData, DstSize));
583 CopyMemory(&pDstData[43], num, 10);
584 *pSize = (UINT32)strnlen(pDstData, DstSize) + 1;
597 static void* clipboard_synthesize_text_html(wClipboard* clipboard, UINT32 formatId,
598 const void* data, UINT32* pSize)
600 char* pDstData = NULL;
602 if (formatId == ClipboardGetFormatId(clipboard,
"HTML Format"))
604 const char* str = (
const char*)data;
605 const size_t SrcSize = (INT64)*pSize;
606 const char* begStr = strstr(str,
"StartHTML:");
607 const char* endStr = strstr(str,
"EndHTML:");
609 if (!begStr || !endStr)
613 const long beg = strtol(&begStr[10], NULL, 10);
618 const long end = strtol(&endStr[8], NULL, 10);
620 if ((beg < 0) || (end < 0) || ((
size_t)beg > SrcSize) || ((
size_t)end > SrcSize) ||
621 (beg >= end) || (errno != 0))
624 const size_t DstSize = (size_t)(end - beg);
625 pDstData = calloc(DstSize + 1,
sizeof(
char));
630 CopyMemory(pDstData, &str[beg], DstSize);
631 const size_t rc = ConvertLineEndingToLF(pDstData, DstSize);
632 WINPR_ASSERT(rc <= UINT32_MAX);
639 BOOL ClipboardInitSynthesizers(wClipboard* clipboard)
645 ClipboardRegisterSynthesizer(clipboard, CF_TEXT, CF_OEMTEXT,
646 clipboard_synthesize_cf_oemtext);
647 ClipboardRegisterSynthesizer(clipboard, CF_TEXT, CF_UNICODETEXT,
648 clipboard_synthesize_cf_unicodetext);
649 ClipboardRegisterSynthesizer(clipboard, CF_TEXT, CF_LOCALE, clipboard_synthesize_cf_locale);
651 UINT32 altFormatId = ClipboardRegisterFormat(clipboard, mime_text_plain);
652 ClipboardRegisterSynthesizer(clipboard, CF_TEXT, altFormatId,
653 clipboard_synthesize_utf8_string);
659 ClipboardRegisterSynthesizer(clipboard, CF_OEMTEXT, CF_TEXT, clipboard_synthesize_cf_text);
660 ClipboardRegisterSynthesizer(clipboard, CF_OEMTEXT, CF_UNICODETEXT,
661 clipboard_synthesize_cf_unicodetext);
662 ClipboardRegisterSynthesizer(clipboard, CF_OEMTEXT, CF_LOCALE,
663 clipboard_synthesize_cf_locale);
664 UINT32 altFormatId = ClipboardRegisterFormat(clipboard, mime_text_plain);
665 ClipboardRegisterSynthesizer(clipboard, CF_OEMTEXT, altFormatId,
666 clipboard_synthesize_utf8_string);
672 ClipboardRegisterSynthesizer(clipboard, CF_UNICODETEXT, CF_TEXT,
673 clipboard_synthesize_cf_text);
674 ClipboardRegisterSynthesizer(clipboard, CF_UNICODETEXT, CF_OEMTEXT,
675 clipboard_synthesize_cf_oemtext);
676 ClipboardRegisterSynthesizer(clipboard, CF_UNICODETEXT, CF_LOCALE,
677 clipboard_synthesize_cf_locale);
678 UINT32 altFormatId = ClipboardRegisterFormat(clipboard, mime_text_plain);
679 ClipboardRegisterSynthesizer(clipboard, CF_UNICODETEXT, altFormatId,
680 clipboard_synthesize_utf8_string);
686 UINT32 formatId = ClipboardRegisterFormat(clipboard, mime_text_plain);
690 ClipboardRegisterSynthesizer(clipboard, formatId, CF_TEXT,
691 clipboard_synthesize_cf_text);
692 ClipboardRegisterSynthesizer(clipboard, formatId, CF_OEMTEXT,
693 clipboard_synthesize_cf_oemtext);
694 ClipboardRegisterSynthesizer(clipboard, formatId, CF_UNICODETEXT,
695 clipboard_synthesize_cf_unicodetext);
696 ClipboardRegisterSynthesizer(clipboard, formatId, CF_LOCALE,
697 clipboard_synthesize_cf_locale);
704 UINT32 formatId = ClipboardRegisterFormat(clipboard, mime_text_plain);
708 ClipboardRegisterSynthesizer(clipboard, formatId, CF_TEXT,
709 clipboard_synthesize_cf_text);
710 ClipboardRegisterSynthesizer(clipboard, formatId, CF_OEMTEXT,
711 clipboard_synthesize_cf_oemtext);
712 ClipboardRegisterSynthesizer(clipboard, formatId, CF_UNICODETEXT,
713 clipboard_synthesize_cf_unicodetext);
714 ClipboardRegisterSynthesizer(clipboard, formatId, CF_LOCALE,
715 clipboard_synthesize_cf_locale);
722 ClipboardRegisterSynthesizer(clipboard, CF_DIB, CF_DIBV5, clipboard_synthesize_cf_dibv5);
723 for (
size_t x = 0; x < ARRAYSIZE(mime_bitmap); x++)
725 const char* mime = mime_bitmap[x];
726 const UINT32 altFormatId = ClipboardRegisterFormat(clipboard, mime);
727 if (altFormatId == 0)
729 ClipboardRegisterSynthesizer(clipboard, CF_DIB, altFormatId,
730 clipboard_synthesize_image_bmp);
740 ClipboardRegisterSynthesizer(clipboard, CF_DIBV5, CF_DIB, clipboard_synthesize_cf_dib);
742 for (
size_t x = 0; x < ARRAYSIZE(mime_bitmap); x++)
744 const char* mime = mime_bitmap[x];
745 const UINT32 altFormatId = ClipboardRegisterFormat(clipboard, mime);
746 if (altFormatId == 0)
748 ClipboardRegisterSynthesizer(clipboard, CF_DIBV5, altFormatId,
749 clipboard_synthesize_image_bmp);
756 for (
size_t x = 0; x < ARRAYSIZE(mime_bitmap); x++)
758 const char* mime = mime_bitmap[x];
759 const UINT32 altFormatId = ClipboardRegisterFormat(clipboard, mime);
760 if (altFormatId == 0)
762 ClipboardRegisterSynthesizer(clipboard, altFormatId, CF_DIB, clipboard_synthesize_cf_dib);
763 ClipboardRegisterSynthesizer(clipboard, altFormatId, CF_DIBV5,
764 clipboard_synthesize_cf_dibv5);
770 #if defined(WINPR_UTILS_IMAGE_PNG)
772 const UINT32 altFormatId = ClipboardRegisterFormat(clipboard, mime_png);
773 ClipboardRegisterSynthesizer(clipboard, CF_DIB, altFormatId,
774 clipboard_synthesize_image_bmp_to_png);
775 ClipboardRegisterSynthesizer(clipboard, CF_DIBV5, altFormatId,
776 clipboard_synthesize_image_bmp_to_png);
777 ClipboardRegisterSynthesizer(clipboard, altFormatId, CF_DIB,
778 clipboard_synthesize_image_png_to_bmp);
779 ClipboardRegisterSynthesizer(clipboard, altFormatId, CF_DIBV5,
780 clipboard_synthesize_image_png_to_bmp);
787 #if defined(WINPR_UTILS_IMAGE_WEBP)
789 const UINT32 altFormatId = ClipboardRegisterFormat(clipboard, mime_webp);
790 ClipboardRegisterSynthesizer(clipboard, CF_DIB, altFormatId,
791 clipboard_synthesize_image_bmp_to_webp);
792 ClipboardRegisterSynthesizer(clipboard, CF_DIBV5, altFormatId,
793 clipboard_synthesize_image_webp_to_bmp);
794 ClipboardRegisterSynthesizer(clipboard, altFormatId, CF_DIB,
795 clipboard_synthesize_image_bmp_to_webp);
796 ClipboardRegisterSynthesizer(clipboard, altFormatId, CF_DIBV5,
797 clipboard_synthesize_image_webp_to_bmp);
804 #if defined(WINPR_UTILS_IMAGE_JPEG)
806 const UINT32 altFormatId = ClipboardRegisterFormat(clipboard, mime_jpeg);
807 ClipboardRegisterSynthesizer(clipboard, CF_DIB, altFormatId,
808 clipboard_synthesize_image_bmp_to_jpeg);
809 ClipboardRegisterSynthesizer(clipboard, CF_DIBV5, altFormatId,
810 clipboard_synthesize_image_jpeg_to_bmp);
811 ClipboardRegisterSynthesizer(clipboard, altFormatId, CF_DIB,
812 clipboard_synthesize_image_bmp_to_jpeg);
813 ClipboardRegisterSynthesizer(clipboard, altFormatId, CF_DIBV5,
814 clipboard_synthesize_image_jpeg_to_bmp);
822 UINT32 formatId = ClipboardRegisterFormat(clipboard,
"HTML Format");
826 const UINT32 altFormatId = ClipboardRegisterFormat(clipboard,
"text/html");
827 ClipboardRegisterSynthesizer(clipboard, formatId, altFormatId,
828 clipboard_synthesize_text_html);
836 UINT32 formatId = ClipboardRegisterFormat(clipboard,
"text/html");
840 const UINT32 altFormatId = ClipboardRegisterFormat(clipboard,
"HTML Format");
841 ClipboardRegisterSynthesizer(clipboard, formatId, altFormatId,
842 clipboard_synthesize_html_format);