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))
86 *pSize = (UINT32)size;
99 static void* clipboard_synthesize_cf_oemtext(wClipboard* clipboard, UINT32 formatId,
100 const void* data, UINT32* pSize)
102 return clipboard_synthesize_cf_text(clipboard, formatId, data, pSize);
111 static void* clipboard_synthesize_cf_locale(wClipboard* clipboard, UINT32 formatId,
112 const void* data, UINT32* pSize)
114 UINT32* pDstData = NULL;
115 pDstData = (UINT32*)malloc(
sizeof(UINT32));
121 return (
void*)pDstData;
130 static void* clipboard_synthesize_cf_unicodetext(wClipboard* clipboard, UINT32 formatId,
131 const void* data, UINT32* pSize)
134 char* crlfStr = NULL;
135 WCHAR* pDstData = NULL;
137 if ((formatId == CF_TEXT) || (formatId == CF_OEMTEXT) ||
138 (formatId == ClipboardGetFormatId(clipboard, mime_text_plain)))
141 if (!pSize || (*pSize > INT32_MAX))
145 crlfStr = ConvertLineEndingToCRLF((
const char*)data, &size);
150 pDstData = ConvertUtf8NToWCharAlloc(crlfStr, size, &len);
153 if ((len < 1) || ((len + 1) > UINT32_MAX /
sizeof(WCHAR)))
159 const size_t slen = (len + 1) *
sizeof(WCHAR);
160 *pSize = (UINT32)slen;
163 return (
void*)pDstData;
172 static void* clipboard_synthesize_utf8_string(wClipboard* clipboard, UINT32 formatId,
173 const void* data, UINT32* pSize)
175 if (formatId == CF_UNICODETEXT)
178 char* pDstData = ConvertWCharNToUtf8Alloc(data, *pSize /
sizeof(WCHAR), &size);
183 const size_t rc = ConvertLineEndingToLF(pDstData, size);
184 WINPR_ASSERT(rc <= UINT32_MAX);
188 else if ((formatId == CF_TEXT) || (formatId == CF_OEMTEXT) ||
189 (formatId == ClipboardGetFormatId(clipboard, mime_text_plain)))
191 const size_t size = *pSize;
192 char* pDstData = calloc(size + 1,
sizeof(
char));
197 CopyMemory(pDstData, data, size);
198 const size_t rc = ConvertLineEndingToLF(pDstData, size);
199 WINPR_ASSERT(rc <= UINT32_MAX);
207 static BOOL is_format_bitmap(wClipboard* clipboard, UINT32 formatId)
209 for (
size_t x = 0; x < ARRAYSIZE(mime_bitmap); x++)
211 const char* mime = mime_bitmap[x];
212 const UINT32 altFormatId = ClipboardGetFormatId(clipboard, mime);
213 if (altFormatId == formatId)
226 static void* clipboard_synthesize_cf_dib(wClipboard* clipboard, UINT32 formatId,
const void* data,
231 BYTE* pDstData = NULL;
234 if (formatId == CF_DIBV5)
237 else if (is_format_bitmap(clipboard, formatId))
241 wStream* s = Stream_StaticConstInit(&sbuffer, data, SrcSize);
242 if (!readBitmapFileHeader(s, &pFileHeader))
246 pDstData = (BYTE*)malloc(DstSize);
252 CopyMemory(pDstData, data, DstSize);
266 static void* clipboard_synthesize_cf_dibv5(wClipboard* clipboard, UINT32 formatId,
const void* data,
269 if (formatId == CF_DIB)
272 else if (is_format_bitmap(clipboard, formatId))
280 const void* data,
size_t size, UINT32* pSize)
282 WINPR_ASSERT(pInfoHeader);
286 if ((pInfoHeader->biBitCount < 1) || (pInfoHeader->biBitCount > 32))
290 if (DstSize > UINT32_MAX)
293 wStream* s = Stream_New(NULL, DstSize);
298 fileHeader.bfType[0] =
'B';
299 fileHeader.bfType[1] =
'M';
300 fileHeader.bfSize = (UINT32)DstSize;
302 if (!writeBitmapFileHeader(s, &fileHeader))
305 if (!Stream_EnsureRemainingCapacity(s, size))
307 Stream_Write(s, data, size);
308 const size_t len = Stream_GetPosition(s);
311 *pSize = (UINT32)DstSize;
313 BYTE* dst = Stream_Buffer(s);
314 Stream_Free(s, FALSE);
318 Stream_Free(s, TRUE);
328 static void* clipboard_synthesize_image_bmp(wClipboard* clipboard, UINT32 formatId,
329 const void* data, UINT32* pSize)
331 UINT32 SrcSize = *pSize;
333 if (formatId == CF_DIB)
341 wStream* s = Stream_StaticConstInit(&sbuffer, data, SrcSize);
342 if (!readBitmapInfoHeader(s, &header, &offset))
345 return clipboard_prepend_bmp_header(&header, data, SrcSize, pSize);
347 else if (formatId == CF_DIBV5)
354 #if defined(WINPR_UTILS_IMAGE_PNG) || defined(WINPR_UTILS_IMAGE_WEBP) || \
355 defined(WINPR_UTILS_IMAGE_JPEG)
356 static void* clipboard_synthesize_image_bmp_to_format(wClipboard* clipboard, UINT32 formatId,
357 UINT32 bmpFormat,
const void* data,
360 WINPR_ASSERT(clipboard);
367 wImage* img = winpr_image_new();
368 void* bmp = clipboard_synthesize_image_bmp(clipboard, formatId, data, pSize);
369 const UINT32 SrcSize = *pSize;
375 if (winpr_image_read_buffer(img, bmp, SrcSize) <= 0)
378 result = winpr_image_write_buffer(img, bmpFormat, &dsize);
381 if (dsize <= UINT32_MAX)
382 *pSize = (UINT32)dsize;
392 winpr_image_free(img, TRUE);
397 #if defined(WINPR_UTILS_IMAGE_PNG)
398 static void* clipboard_synthesize_image_bmp_to_png(wClipboard* clipboard, UINT32 formatId,
399 const void* data, UINT32* pSize)
401 return clipboard_synthesize_image_bmp_to_format(clipboard, formatId, WINPR_IMAGE_PNG, data,
405 static void* clipboard_synthesize_image_format_to_bmp(wClipboard* clipboard, UINT32 srcFormatId,
406 const void* data, UINT32* pSize)
408 WINPR_ASSERT(clipboard);
413 const UINT32 SrcSize = *pSize;
415 wImage* image = winpr_image_new();
419 const int res = winpr_image_read_buffer(image, data, SrcSize);
423 dst = winpr_image_write_buffer(image, WINPR_IMAGE_BITMAP, &size);
430 *pSize = (UINT32)size;
433 winpr_image_free(image, TRUE);
441 static void* clipboard_synthesize_image_png_to_bmp(wClipboard* clipboard, UINT32 formatId,
442 const void* data, UINT32* pSize)
444 return clipboard_synthesize_image_format_to_bmp(clipboard, formatId, data, pSize);
448 #if defined(WINPR_UTILS_IMAGE_WEBP)
449 static void* clipboard_synthesize_image_bmp_to_webp(wClipboard* clipboard, UINT32 formatId,
450 const void* data, UINT32* pSize)
452 return clipboard_synthesize_image_bmp_to_format(clipboard, formatId, WINPR_IMAGE_WEBP, data,
456 static void* clipboard_synthesize_image_webp_to_bmp(wClipboard* clipboard, UINT32 formatId,
457 const void* data, UINT32* pSize)
459 return clipboard_synthesize_image_format_to_bmp(clipboard, formatId, data, pSize);
463 #if defined(WINPR_UTILS_IMAGE_JPEG)
464 static void* clipboard_synthesize_image_bmp_to_jpeg(wClipboard* clipboard, UINT32 formatId,
465 const void* data, UINT32* pSize)
467 return clipboard_synthesize_image_bmp_to_format(clipboard, formatId, WINPR_IMAGE_JPEG, data,
471 static void* clipboard_synthesize_image_jpeg_to_bmp(wClipboard* clipboard, UINT32 formatId,
472 const void* data, UINT32* pSize)
474 return clipboard_synthesize_image_format_to_bmp(clipboard, formatId, data, pSize);
484 static void* clipboard_synthesize_html_format(wClipboard* clipboard, UINT32 formatId,
485 const void* pData, UINT32* pSize)
494 char* pDstData = NULL;
498 WINPR_ASSERT(clipboard);
501 if (formatId == ClipboardGetFormatId(clipboard,
"text/html"))
503 const size_t SrcSize = (size_t)*pSize;
504 const size_t DstSize = SrcSize + 200;
506 char num[20] = { 0 };
509 pSrcData.pv = calloc(1, SrcSize + 1);
512 memcpy(pSrcData.pv, pData, SrcSize);
516 if (SrcSize > INT_MAX)
520 if ((pSrcData.cpb[0] == 0xFE) && (pSrcData.cpb[1] == 0xFF))
521 ByteSwapUnicode(pSrcData.pv, (SrcSize / 2));
524 if ((pSrcData.cpb[0] == 0xFF) && (pSrcData.cpb[1] == 0xFE))
527 ConvertWCharNToUtf8Alloc(&pSrcData.pv[1], SrcSize /
sizeof(WCHAR), NULL);
529 pSrcData.cpc = utfString;
535 pDstData = (
char*)calloc(1, DstSize);
540 (void)sprintf_s(pDstData, DstSize,
542 "StartHTML:0000000000\r\n"
543 "EndHTML:0000000000\r\n"
544 "StartFragment:0000000000\r\n"
545 "EndFragment:0000000000\r\n");
546 body = strstr(pSrcData.cpc,
"<body");
549 body = strstr(pSrcData.cpc,
"<BODY");
552 (void)sprintf_s(num,
sizeof(num),
"%010" PRIuz
"", strnlen(pDstData, DstSize));
553 CopyMemory(&pDstData[23], num, 10);
557 if (!winpr_str_append(
"<HTML><BODY>", pDstData, DstSize, NULL))
561 if (!winpr_str_append(
"<!--StartFragment-->", pDstData, DstSize, NULL))
565 (void)sprintf_s(num,
sizeof(num),
"%010" PRIuz
"", strnlen(pDstData, SrcSize + 200));
566 CopyMemory(&pDstData[69], num, 10);
568 if (!winpr_str_append(pSrcData.cpc, pDstData, DstSize, NULL))
572 (void)sprintf_s(num,
sizeof(num),
"%010" PRIuz
"", strnlen(pDstData, SrcSize + 200));
573 CopyMemory(&pDstData[93], num, 10);
575 if (!winpr_str_append(
"<!--EndFragment-->", pDstData, DstSize, NULL))
580 if (!winpr_str_append(
"</BODY></HTML>", pDstData, DstSize, NULL))
585 (void)sprintf_s(num,
sizeof(num),
"%010" PRIuz
"", strnlen(pDstData, DstSize));
586 CopyMemory(&pDstData[43], num, 10);
587 *pSize = (UINT32)strnlen(pDstData, DstSize) + 1;
600 static void* clipboard_synthesize_text_html(wClipboard* clipboard, UINT32 formatId,
601 const void* data, UINT32* pSize)
603 char* pDstData = NULL;
605 if (formatId == ClipboardGetFormatId(clipboard,
"HTML Format"))
607 const char* str = (
const char*)data;
608 const size_t SrcSize = *pSize;
609 const char* begStr = strstr(str,
"StartHTML:");
610 const char* endStr = strstr(str,
"EndHTML:");
612 if (!begStr || !endStr)
616 const long beg = strtol(&begStr[10], NULL, 10);
621 const long end = strtol(&endStr[8], NULL, 10);
623 if ((beg < 0) || (end < 0) || ((
size_t)beg > SrcSize) || ((
size_t)end > SrcSize) ||
624 (beg >= end) || (errno != 0))
627 const size_t DstSize = (size_t)(end - beg);
628 pDstData = calloc(DstSize + 1,
sizeof(
char));
633 CopyMemory(pDstData, &str[beg], DstSize);
634 const size_t rc = ConvertLineEndingToLF(pDstData, DstSize);
635 WINPR_ASSERT(rc <= UINT32_MAX);
642 BOOL ClipboardInitSynthesizers(wClipboard* clipboard)
648 ClipboardRegisterSynthesizer(clipboard, CF_TEXT, CF_OEMTEXT,
649 clipboard_synthesize_cf_oemtext);
650 ClipboardRegisterSynthesizer(clipboard, CF_TEXT, CF_UNICODETEXT,
651 clipboard_synthesize_cf_unicodetext);
652 ClipboardRegisterSynthesizer(clipboard, CF_TEXT, CF_LOCALE, clipboard_synthesize_cf_locale);
654 UINT32 altFormatId = ClipboardRegisterFormat(clipboard, mime_text_plain);
655 ClipboardRegisterSynthesizer(clipboard, CF_TEXT, altFormatId,
656 clipboard_synthesize_utf8_string);
662 ClipboardRegisterSynthesizer(clipboard, CF_OEMTEXT, CF_TEXT, clipboard_synthesize_cf_text);
663 ClipboardRegisterSynthesizer(clipboard, CF_OEMTEXT, CF_UNICODETEXT,
664 clipboard_synthesize_cf_unicodetext);
665 ClipboardRegisterSynthesizer(clipboard, CF_OEMTEXT, CF_LOCALE,
666 clipboard_synthesize_cf_locale);
667 UINT32 altFormatId = ClipboardRegisterFormat(clipboard, mime_text_plain);
668 ClipboardRegisterSynthesizer(clipboard, CF_OEMTEXT, altFormatId,
669 clipboard_synthesize_utf8_string);
675 ClipboardRegisterSynthesizer(clipboard, CF_UNICODETEXT, CF_TEXT,
676 clipboard_synthesize_cf_text);
677 ClipboardRegisterSynthesizer(clipboard, CF_UNICODETEXT, CF_OEMTEXT,
678 clipboard_synthesize_cf_oemtext);
679 ClipboardRegisterSynthesizer(clipboard, CF_UNICODETEXT, CF_LOCALE,
680 clipboard_synthesize_cf_locale);
681 UINT32 altFormatId = ClipboardRegisterFormat(clipboard, mime_text_plain);
682 ClipboardRegisterSynthesizer(clipboard, CF_UNICODETEXT, altFormatId,
683 clipboard_synthesize_utf8_string);
689 UINT32 formatId = ClipboardRegisterFormat(clipboard, mime_text_plain);
693 ClipboardRegisterSynthesizer(clipboard, formatId, CF_TEXT,
694 clipboard_synthesize_cf_text);
695 ClipboardRegisterSynthesizer(clipboard, formatId, CF_OEMTEXT,
696 clipboard_synthesize_cf_oemtext);
697 ClipboardRegisterSynthesizer(clipboard, formatId, CF_UNICODETEXT,
698 clipboard_synthesize_cf_unicodetext);
699 ClipboardRegisterSynthesizer(clipboard, formatId, CF_LOCALE,
700 clipboard_synthesize_cf_locale);
707 UINT32 formatId = ClipboardRegisterFormat(clipboard, mime_text_plain);
711 ClipboardRegisterSynthesizer(clipboard, formatId, CF_TEXT,
712 clipboard_synthesize_cf_text);
713 ClipboardRegisterSynthesizer(clipboard, formatId, CF_OEMTEXT,
714 clipboard_synthesize_cf_oemtext);
715 ClipboardRegisterSynthesizer(clipboard, formatId, CF_UNICODETEXT,
716 clipboard_synthesize_cf_unicodetext);
717 ClipboardRegisterSynthesizer(clipboard, formatId, CF_LOCALE,
718 clipboard_synthesize_cf_locale);
725 ClipboardRegisterSynthesizer(clipboard, CF_DIB, CF_DIBV5, clipboard_synthesize_cf_dibv5);
726 for (
size_t x = 0; x < ARRAYSIZE(mime_bitmap); x++)
728 const char* mime = mime_bitmap[x];
729 const UINT32 altFormatId = ClipboardRegisterFormat(clipboard, mime);
730 if (altFormatId == 0)
732 ClipboardRegisterSynthesizer(clipboard, CF_DIB, altFormatId,
733 clipboard_synthesize_image_bmp);
743 ClipboardRegisterSynthesizer(clipboard, CF_DIBV5, CF_DIB, clipboard_synthesize_cf_dib);
745 for (
size_t x = 0; x < ARRAYSIZE(mime_bitmap); x++)
747 const char* mime = mime_bitmap[x];
748 const UINT32 altFormatId = ClipboardRegisterFormat(clipboard, mime);
749 if (altFormatId == 0)
751 ClipboardRegisterSynthesizer(clipboard, CF_DIBV5, altFormatId,
752 clipboard_synthesize_image_bmp);
759 for (
size_t x = 0; x < ARRAYSIZE(mime_bitmap); x++)
761 const char* mime = mime_bitmap[x];
762 const UINT32 altFormatId = ClipboardRegisterFormat(clipboard, mime);
763 if (altFormatId == 0)
765 ClipboardRegisterSynthesizer(clipboard, altFormatId, CF_DIB, clipboard_synthesize_cf_dib);
766 ClipboardRegisterSynthesizer(clipboard, altFormatId, CF_DIBV5,
767 clipboard_synthesize_cf_dibv5);
773 #if defined(WINPR_UTILS_IMAGE_PNG)
775 const UINT32 altFormatId = ClipboardRegisterFormat(clipboard, mime_png);
776 ClipboardRegisterSynthesizer(clipboard, CF_DIB, altFormatId,
777 clipboard_synthesize_image_bmp_to_png);
778 ClipboardRegisterSynthesizer(clipboard, CF_DIBV5, altFormatId,
779 clipboard_synthesize_image_bmp_to_png);
780 ClipboardRegisterSynthesizer(clipboard, altFormatId, CF_DIB,
781 clipboard_synthesize_image_png_to_bmp);
782 ClipboardRegisterSynthesizer(clipboard, altFormatId, CF_DIBV5,
783 clipboard_synthesize_image_png_to_bmp);
790 #if defined(WINPR_UTILS_IMAGE_WEBP)
792 const UINT32 altFormatId = ClipboardRegisterFormat(clipboard, mime_webp);
793 ClipboardRegisterSynthesizer(clipboard, CF_DIB, altFormatId,
794 clipboard_synthesize_image_bmp_to_webp);
795 ClipboardRegisterSynthesizer(clipboard, CF_DIBV5, altFormatId,
796 clipboard_synthesize_image_webp_to_bmp);
797 ClipboardRegisterSynthesizer(clipboard, altFormatId, CF_DIB,
798 clipboard_synthesize_image_bmp_to_webp);
799 ClipboardRegisterSynthesizer(clipboard, altFormatId, CF_DIBV5,
800 clipboard_synthesize_image_webp_to_bmp);
807 #if defined(WINPR_UTILS_IMAGE_JPEG)
809 const UINT32 altFormatId = ClipboardRegisterFormat(clipboard, mime_jpeg);
810 ClipboardRegisterSynthesizer(clipboard, CF_DIB, altFormatId,
811 clipboard_synthesize_image_bmp_to_jpeg);
812 ClipboardRegisterSynthesizer(clipboard, CF_DIBV5, altFormatId,
813 clipboard_synthesize_image_jpeg_to_bmp);
814 ClipboardRegisterSynthesizer(clipboard, altFormatId, CF_DIB,
815 clipboard_synthesize_image_bmp_to_jpeg);
816 ClipboardRegisterSynthesizer(clipboard, altFormatId, CF_DIBV5,
817 clipboard_synthesize_image_jpeg_to_bmp);
825 UINT32 formatId = ClipboardRegisterFormat(clipboard,
"HTML Format");
829 const UINT32 altFormatId = ClipboardRegisterFormat(clipboard,
"text/html");
830 ClipboardRegisterSynthesizer(clipboard, formatId, altFormatId,
831 clipboard_synthesize_text_html);
839 UINT32 formatId = ClipboardRegisterFormat(clipboard,
"text/html");
843 const UINT32 altFormatId = ClipboardRegisterFormat(clipboard,
"HTML Format");
844 ClipboardRegisterSynthesizer(clipboard, formatId, altFormatId,
845 clipboard_synthesize_html_format);