Changeset 61589 in vbox for trunk/src/VBox
- Timestamp:
- Jun 8, 2016 4:05:44 PM (9 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/GuestHost/SharedClipboard/x11-clipboard.cpp
r57413 r61589 54 54 #include <VBox/HostServices/VBoxClipboardSvc.h> 55 55 56 class formats; 56 57 static Atom clipGetAtom(CLIPBACKEND *pCtx, const char *pszName); 57 58 … … 63 64 TEXT, /* Treat this as Utf8, but it may really be ascii */ 64 65 UTF8, 65 BMP 66 BMP, 67 HTML 66 68 }; 67 69 … … 88 90 { "TEXT", TEXT, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT }, 89 91 { "text/plain", TEXT, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT }, 92 { "text/html", HTML, VBOX_SHARED_CLIPBOARD_FMT_HTML }, 93 { "text/html;charset=utf-8", HTML, 94 VBOX_SHARED_CLIPBOARD_FMT_HTML }, 90 95 { "image/bmp", BMP, VBOX_SHARED_CLIPBOARD_FMT_BITMAP }, 91 96 { "image/x-bmp", BMP, VBOX_SHARED_CLIPBOARD_FMT_BITMAP }, 92 { "image/x-MS-bmp", BMP, VBOX_SHARED_CLIPBOARD_FMT_BITMAP }, 97 { "image/x-MS-bmp", BMP, VBOX_SHARED_CLIPBOARD_FMT_BITMAP } 98 99 93 100 /* TODO: Inkscape exports image/png but not bmp... */ 94 101 }; … … 187 194 * table */ 188 195 CLIPX11FORMAT X11BitmapFormat; 196 /** The best HTML format X11 has to offer, as an index into the formats 197 * table */ 198 CLIPX11FORMAT X11HTMLFormat; 189 199 /** What formats does VBox have on offer? */ 190 200 uint32_t vboxFormats; … … 327 337 uint32_t u32VBoxFormats = clipVBoxFormatForX11Format(pCtx->X11TextFormat); 328 338 u32VBoxFormats |= clipVBoxFormatForX11Format(pCtx->X11BitmapFormat); 339 u32VBoxFormats |= clipVBoxFormatForX11Format(pCtx->X11HTMLFormat); 340 LogRelFlowFunc(("clipReportFormatsToVBox format: %d\n", u32VBoxFormats)); 341 LogRelFlowFunc(("clipReportFormatsToVBox txt: %d, bitm: %d, html:%d, u32VBoxFormats: %d\n", 342 pCtx->X11TextFormat, pCtx->X11BitmapFormat, pCtx->X11HTMLFormat, 343 u32VBoxFormats )); 329 344 ClipReportX11Formats(pCtx->pFrontend, u32VBoxFormats); 330 345 } … … 337 352 pCtx->X11TextFormat = INVALID; 338 353 pCtx->X11BitmapFormat = INVALID; 354 pCtx->X11HTMLFormat = INVALID; 339 355 } 340 356 … … 433 449 434 450 /** 451 * Go through an array of X11 clipboard targets to see if they contain a HTML 452 * format we can support, and if so choose the ones we prefer 453 * @param pCtx the clipboard backend context structure 454 * @param pTargets the list of targets 455 * @param cTargets the size of the list in @a pTargets 456 */ 457 static CLIPX11FORMAT clipGetHtmlFormatFromTargets(CLIPBACKEND *pCtx, 458 CLIPX11FORMAT *pTargets, 459 size_t cTargets) 460 { 461 CLIPX11FORMAT bestHTMLFormat = NIL_CLIPX11FORMAT; 462 CLIPFORMAT enmBestHtmlTarget = INVALID; 463 AssertPtrReturn(pCtx, NIL_CLIPX11FORMAT); 464 AssertReturn(VALID_PTR(pTargets) || cTargets == 0, NIL_CLIPX11FORMAT); 465 for (unsigned i = 0; i < cTargets; ++i) 466 { 467 CLIPX11FORMAT format = pTargets[i]; 468 if (format != NIL_CLIPX11FORMAT) 469 { 470 if ( (clipVBoxFormatForX11Format(format) == VBOX_SHARED_CLIPBOARD_FMT_HTML) 471 && enmBestHtmlTarget < clipRealFormatForX11Format(format)) 472 { 473 enmBestHtmlTarget = clipRealFormatForX11Format(format); 474 bestHTMLFormat = format; 475 } 476 } 477 } 478 return bestHTMLFormat; 479 } 480 481 482 /** 435 483 * Go through an array of X11 clipboard targets to see if we can support any 436 484 * of them and if relevant to choose the ones we prefer (e.g. we like Utf8 … … 447 495 CLIPX11FORMAT bestTextFormat; 448 496 CLIPX11FORMAT bestBitmapFormat; 497 CLIPX11FORMAT bestHtmlFormat; 449 498 bestTextFormat = clipGetTextFormatFromTargets(pCtx, pTargets, cTargets); 450 499 if (pCtx->X11TextFormat != bestTextFormat) … … 457 506 { 458 507 pCtx->X11BitmapFormat = bestBitmapFormat; 508 } 509 bestHtmlFormat = clipGetHtmlFormatFromTargets(pCtx, pTargets, cTargets); 510 if(pCtx->X11HTMLFormat != bestHtmlFormat) 511 { 512 pCtx->X11HTMLFormat = bestHtmlFormat; 459 513 } 460 514 } … … 1120 1174 1121 1175 /** 1176 * Satisfy a request from X11 to convert the clipboard HTML fragment to Utf-8. We 1177 * return null-terminated text, but can cope with non-null-terminated input. 1178 * 1179 * @returns iprt status code 1180 * @param pDisplay an X11 display structure, needed for conversions 1181 * performed by Xlib 1182 * @param pv the text to be converted (UTF8 with Windows EOLs) 1183 * @param cb the length of the text in @cb in bytes 1184 * @param atomTypeReturn where to store the atom for the type of the data 1185 * we are returning 1186 * @param pValReturn where to store the pointer to the data we are 1187 * returning. This should be to memory allocated by 1188 * XtMalloc, which will be freed by the Xt toolkit 1189 * later. 1190 * @param pcLenReturn where to store the length of the data we are 1191 * returning 1192 * @param piFormatReturn where to store the bit width (8, 16, 32) of the 1193 * data we are returning 1194 */ 1195 static int clipWinHTMLToUtf8ForX11CB(Display *pDisplay, const char* pszSrc, 1196 size_t cbSrc, Atom *atomTarget, 1197 Atom *atomTypeReturn, 1198 XtPointer *pValReturn, 1199 unsigned long *pcLenReturn, 1200 int *piFormatReturn) 1201 { 1202 /* This may slightly overestimate the space needed. */ 1203 LogRelFlowFunc(("source: %s", pszSrc)); 1204 1205 char *pszDest = (char *)XtMalloc(cbSrc); 1206 if(pszDest == NULL) 1207 return VERR_NO_MEMORY; 1208 1209 memcpy(pszDest, pszSrc, cbSrc); 1210 1211 *atomTypeReturn = *atomTarget; 1212 *pValReturn = (XtPointer)pszDest; 1213 *pcLenReturn = cbSrc; 1214 *piFormatReturn = 8; 1215 1216 return VINF_SUCCESS; 1217 } 1218 1219 1220 /** 1122 1221 * Does this atom correspond to one of the two selection types we support? 1123 1222 * @param widget a valid Xt widget … … 1142 1241 AssertPtrReturnVoid(pText); 1143 1242 AssertPtrReturnVoid(pcText); 1144 AssertReturnVoid((format == UTF8) || (format == TEXT) );1243 AssertReturnVoid((format == UTF8) || (format == TEXT) || (format == HTML)); 1145 1244 if (((char *)pText)[*pcText - 1] == '\0') 1146 1245 --(*pcText); … … 1200 1299 } 1201 1300 RTMemFree(pv); 1301 } 1302 else if ( (format == HTML) 1303 && (pCtx->vboxFormats & VBOX_SHARED_CLIPBOARD_FMT_HTML)) 1304 { 1305 void *pv = NULL; 1306 uint32_t cb = 0; 1307 rc = clipReadVBoxClipboard(pCtx, 1308 VBOX_SHARED_CLIPBOARD_FMT_HTML, 1309 &pv, &cb); 1310 if (RT_SUCCESS(rc) && (cb == 0)) 1311 rc = VERR_NO_DATA; 1312 if (RT_SUCCESS(rc)) 1313 { 1314 /* 1315 * The common VBox HTML encoding will be - Utf8 1316 * becuase it more general for HTML formats then UTF16 1317 * X11 clipboard returns UTF16, so before sending it we should 1318 * convert it to UTF8 1319 * It's very strange but here we get utf16 from x11 clipboard 1320 * in same time we send utf8 to x11 clipboard and it's work 1321 */ 1322 rc = clipWinHTMLToUtf8ForX11CB(XtDisplay(pCtx->widget), 1323 (const char*)pv, cb, atomTarget, 1324 atomTypeReturn, pValReturn, 1325 pcLenReturn, piFormatReturn); 1326 1327 1328 if (RT_SUCCESS(rc)) 1329 clipTrimTrailingNul(*(XtPointer *)pValReturn, pcLenReturn, format); 1330 RTMemFree(pv); 1331 } 1202 1332 } 1203 1333 else … … 1467 1597 } 1468 1598 1599 1600 /** 1601 * Convert Utf16 text into UTF8 as Windows expects 1602 * it and return the result in a RTMemAlloc allocated buffer. 1603 * @returns IPRT status code 1604 * @param pcSrc The source text 1605 * @param cbSrc The size of the source in bytes, not counting the 1606 * terminating zero 1607 * @param ppwszDest Where to store the buffer address 1608 * @param pcbDest On success, where to store the number of bytes written. 1609 * Undefined otherwise. Optional 1610 */ 1611 int clipUTF16ToWinHTML(RTUTF16* buffer, size_t cb, char **output, uint32_t *outsz) 1612 { 1613 Assert(buffer); 1614 Assert(cb); 1615 Assert(output); 1616 Assert(outsz); 1617 1618 size_t i = 0; 1619 RTUTF16* p = buffer; 1620 char* result = NULL; 1621 size_t resultLen = 0; 1622 LogRelFlowFunc(("clipUTF16ToWinHTML src= %ls cb=%d i=%i, %x %x\n", buffer, cb, i, output, outsz)); 1623 while (i != cb / 2) 1624 { 1625 /* find zero symbol (end of string) */ 1626 for (; i < cb / 2 && buffer[i] != 0; i++); 1627 LogRelFlowFunc(("skipped nulls i=%d cb/2=%d\n", i, cb / 2)); 1628 1629 /* convert found string */ 1630 char* cTmp = NULL; 1631 size_t sz = 0; 1632 int rc = RTUtf16ToUtf8Ex(p, cb / 2, &cTmp, p - buffer, &sz); 1633 LogRelFlowFunc(("utf16toutf8 src= %ls res=%s i=%i\n", p, cTmp, i)); 1634 if (!RT_SUCCESS(rc)) 1635 return rc; 1636 1637 /* append new substring */ 1638 result = (char*)RTMemRealloc(result, resultLen + sz + 1); 1639 if (result == NULL) 1640 { 1641 RTStrFree(cTmp); 1642 cTmp = NULL; 1643 return VERR_NO_MEMORY; 1644 } 1645 memcpy(result + resultLen, cTmp, sz + 1); 1646 LogRelFlowFunc(("Temp result res=%s\n", result + resultLen)); 1647 1648 /* remove temporary buffer */ 1649 RTStrFree(cTmp); 1650 resultLen += sz + 1; 1651 /* skip zero symbols */ 1652 for (; i < cb / 2 && buffer[i] == 0; i++); 1653 /* remember start of string */ 1654 p += i; 1655 } 1656 *output = result; 1657 *outsz = resultLen; 1658 1659 return VINF_SUCCESS; 1660 } 1661 1662 1663 1469 1664 /** A structure containing information about where to store a request 1470 1665 * for the X11 clipboard contents. */ … … 1477 1672 /** The bitmap format we requested from X11 if we requested bitmap */ 1478 1673 CLIPX11FORMAT mBitmapFormat; 1674 /** The HTML format we requested from X11 if we requested HTML */ 1675 CLIPX11FORMAT mHtmlFormat; 1479 1676 /** The clipboard context this request is associated with */ 1480 1677 CLIPBACKEND *mCtx; … … 1497 1694 CLIPREADX11CBREQ *pReq = (CLIPREADX11CBREQ *) pClientData; 1498 1695 LogRelFlowFunc(("pReq->mFormat=%02X, pReq->mTextFormat=%u, " 1499 "pReq->mBitmapFormat=%u, pReq->m Ctx=%p\n",1696 "pReq->mBitmapFormat=%u, pReq->mHtmlFormat=%u, pReq->mCtx=%p\n", 1500 1697 pReq->mFormat, pReq->mTextFormat, pReq->mBitmapFormat, 1501 pReq->m Ctx));1698 pReq->mHtmlFormat, pReq->mCtx)); 1502 1699 AssertPtr(pReq->mCtx); 1503 1700 Assert(pReq->mFormat != 0); /* sanity */ … … 1564 1761 } 1565 1762 } 1763 else if(pReq->mFormat == VBOX_SHARED_CLIPBOARD_FMT_HTML) 1764 { 1765 /* In which format is the clipboard data? */ 1766 switch (clipRealFormatForX11Format(pReq->mHtmlFormat)) 1767 { 1768 case HTML: 1769 { 1770 /* The common VBox HTML encoding will be - Utf8 1771 * becuase it more general for HTML formats then UTF16 1772 * X11 clipboard returns UTF16, so before sending it we should 1773 * convert it to UTF8 1774 */ 1775 pvDest = NULL; 1776 cbDest = 0; 1777 rc = clipUTF16ToWinHTML((RTUTF16*)pvSrc, cbSrc, 1778 (char**)&pvDest, &cbDest); 1779 LogRelFlowFunc(("Source unicode %ls, cbSrc = %d\n", pvSrc, cbSrc)); 1780 LogRelFlowFunc(("converted to win unicode %s, cbDest = %d, rc = %Rrc\n", pvDest, cbDest, rc)); 1781 rc = VINF_SUCCESS; 1782 break; 1783 } 1784 default: 1785 { 1786 rc = VERR_INVALID_PARAMETER; 1787 } 1788 } 1789 } 1566 1790 else 1567 1791 rc = VERR_NOT_IMPLEMENTED; … … 1653 1877 getSelectionValue(pCtx, pCtx->X11BitmapFormat, pReq); 1654 1878 } 1655 else 1879 else if(pReq->mFormat == VBOX_SHARED_CLIPBOARD_FMT_HTML) 1880 { 1881 /* Send out a request for the data to the current clipboard 1882 * owner */ 1883 pReq->mHtmlFormat = pCtx->X11HTMLFormat; 1884 if(pReq->mHtmlFormat == INVALID) 1885 /* VBox thinks we have data and we don't */ 1886 rc = VERR_NO_DATA; 1887 else 1888 /* Send out a request for the data to the current clipboard 1889 * owner */ 1890 getSelectionValue(pCtx, pCtx->X11HTMLFormat, pReq); 1891 } 1892 else 1656 1893 rc = VERR_NOT_IMPLEMENTED; 1657 1894 if (RT_FAILURE(rc)) … … 2545 2782 2546 2783 #endif /* SMOKETEST defined */ 2784 2785 -
trunk/src/VBox/HostServices/SharedClipboard/VBoxClipboard-win.cpp
r60784 r61589 42 42 typedef FNREMOVECLIPBOARDFORMATLISTENER *PFNREMOVECLIPBOARDFORMATLISTENER; 43 43 44 /*Forward declarations*/ 45 int ConvertMimeToCFHTML(const char *source, size_t cb, char **output, size_t *pcch); 46 int ConvertCFHtmlToMime(const char *source, const uint32_t cch, char **output, size_t *pcch); 47 bool IsWindowsHTML(const char *source); 48 49 44 50 #ifndef WM_CLIPBOARDUPDATE 45 51 #define WM_CLIPBOARDUPDATE 0x031D … … 96 102 { 97 103 Log(("%s\n", pv)); 104 105 //size_t cb = RTStrNLen(pv, ); 106 char* buf = (char*)RTMemAlloc(cb + 1); 107 RT_BZERO(buf, cb); 108 RTStrCopy(buf, cb, (const char*)pv); 109 for (int i = 0; i < cb; ++i) 110 { 111 if (buf[i] == '\n' || buf[i] == '\r') 112 buf[i] = ' '; 113 } 114 115 Log(("%s\n", buf)); 116 RTMemFree(buf); 98 117 } 99 118 else … … 202 221 } 203 222 204 memcpy (pvDst, pvSrc, cbSrc); 223 if (u32Format == VBOX_SHARED_CLIPBOARD_FMT_HTML && 224 IsWindowsHTML((const char*)pvSrc)) 225 { 226 char* buffer = NULL; 227 size_t cbuf = 0; 228 ConvertCFHtmlToMime((const char*)pvSrc, cbSrc, (char**)&buffer, &cbuf); 229 if (cbuf > cbDst) 230 { 231 /* Do not copy data. The dst buffer is not enough. */ 232 return; 233 } 234 memcpy(pvDst, buffer, cbuf); 235 *pcbActualDst = cbuf; 236 RTMemFree(buffer); 237 } 238 else 239 { 240 memcpy(pvDst, pvSrc, cbSrc); 241 } 205 242 206 243 vboxClipboardDump(pvDst, cbSrc, u32Format); … … 794 831 } 795 832 833 int DumpHtml(char* src, size_t cb) 834 { 835 size_t lenght = 0; 836 int rc = RTStrNLenEx(src, cb, &lenght); 837 if (RT_SUCCESS(rc)) 838 { 839 char* buf = (char*)RTMemAlloc(cb + 1); 840 if (buf != NULL) 841 { 842 RT_BZERO(buf, cb + 1); 843 rc = RTStrCopy(buf, cb, (const char*)src); 844 if (RT_SUCCESS(rc)) 845 { 846 for (int i = 0; i < cb; ++i) 847 { 848 if (buf[i] == '\n' || buf[i] == '\r') 849 buf[i] = ' '; 850 } 851 } 852 else 853 { 854 Log(("Error in copying string.\n")); 855 } 856 Log(("Removed \\r\\n: %s\n", buf)); 857 RTMemFree(buf); 858 } 859 else 860 { 861 rc = VERR_NO_MEMORY; 862 Log(("Not enough memory to allocate buffer.\n")); 863 } 864 } 865 return rc; 866 } 867 796 868 int vboxClipboardReadData (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Format, void *pv, uint32_t cb, uint32_t *pcbActual) 797 869 { … … 872 944 vboxClipboardGetData (VBOX_SHARED_CLIPBOARD_FMT_HTML, lp, GlobalSize (hClip), 873 945 pv, cb, pcbActual); 874 946 LogRelFlowFunc(("Raw HTML clipboard data from host :")); 947 DumpHtml((char*)pv, cb); 875 948 GlobalUnlock(hClip); 876 949 } … … 913 986 if (cb > 0) 914 987 { 915 pClient->data.pv = RTMemAlloc (cb); 916 917 if (pClient->data.pv) 918 { 919 memcpy (pClient->data.pv, pv, cb); 920 pClient->data.cb = cb; 921 pClient->data.u32Format = u32Format; 988 char* result = NULL; 989 size_t cch; 990 991 if(u32Format == VBOX_SHARED_CLIPBOARD_FMT_HTML && 992 !IsWindowsHTML((const char*)pv)) 993 { 994 /* check that this is not already CF_HTML */ 995 int rc = ConvertMimeToCFHTML((const char*)pv, cb, &result, &cch); 996 if (RT_SUCCESS(rc)) 997 { 998 if (result != NULL && cch != 0) 999 { 1000 pClient->data.pv = result; 1001 pClient->data.cb = cch; 1002 pClient->data.u32Format = u32Format; 1003 } 1004 } 1005 } 1006 else 1007 { 1008 pClient->data.pv = RTMemAlloc (cb); 1009 if (pClient->data.pv) 1010 { 1011 memcpy (pClient->data.pv, pv, cb); 1012 pClient->data.cb = cb; 1013 pClient->data.u32Format = u32Format; 1014 } 922 1015 } 923 1016 } … … 925 1018 SetEvent(pClient->pCtx->hRenderEvent); 926 1019 } 1020 1021 /* 1022 @StartHtml - pos before <html> 1023 @EndHtml - whole size of text excluding ending zero char 1024 @StartFragment - pos after <!--StartFragment--> 1025 @EndFragment - pos before <!--EndFragment--> 1026 @note: all values includes CR\LF inserted into text 1027 Calculations: 1028 Header length = format Length + (3*6('digits')) - 2('%s') = format length + 16 (control value - 183) 1029 EndHtml = Header length + fragment length 1030 StartHtml = 105(constant) 1031 StartFragment = 143(constant) 1032 EndFragment = Header length + fragment length - 40(ending length) 1033 */ 1034 char strFormatSample[] = 1035 "Version:1.0\r\n" 1036 "StartHTML:000000101\r\n" 1037 "EndHTML:%09d\r\n" // END HTML = Header length + fragment lengh 1038 "StartFragment:000000137\r\n" 1039 "EndFragment:%09d\r\n" 1040 "<html>\r\n" 1041 "<body>\r\n" 1042 "<!--StartFragment-->%s<!--EndFragment-->\r\n" 1043 "</body>\r\n" 1044 "</html>\r\n"; 1045 1046 /* 1047 * Extracts field value from CF_HTML struct 1048 * @src - source in CF_HTML format 1049 * @option - name of CF_HTML field 1050 * @value - extracted value of CF_HTML field 1051 * returns RC result code 1052 */ 1053 int GetHeaderValue(const char *src, const char *option, size_t *value) 1054 { 1055 size_t optionLenght; 1056 int rc = VERR_INVALID_PARAMETER; 1057 1058 Assert(src); 1059 Assert(option); 1060 1061 char* optionValue = RTStrStr(src, option); 1062 if (optionValue) 1063 { 1064 rc = RTStrNLenEx(option, RTSTR_MAX, &optionLenght); 1065 Assert(optionLenght); 1066 if (RT_SUCCESS(rc)) 1067 { 1068 int32_t tmpValue; 1069 rc = RTStrToInt32Ex(optionValue + optionLenght, NULL, 10, &tmpValue); 1070 if (RT_SUCCESS(rc)) 1071 { 1072 *value = tmpValue; 1073 rc = VINF_SUCCESS; 1074 } 1075 } 1076 } 1077 return rc; 1078 } 1079 1080 /* 1081 * Check that the source string contains CF_HTML struct 1082 * returns true if the @source string is in CF_HTML format 1083 */ 1084 bool IsWindowsHTML(const char *source) 1085 { 1086 return RTStrStr(source, "Version:") != NULL 1087 && RTStrStr(source, "StartHTML:") != NULL; 1088 } 1089 1090 1091 /* 1092 * Converts clipboard data from CF_HTML format to mimie clipboard format 1093 * Returns allocated buffer that contains html converted to text/html mime type 1094 * return result code 1095 * parameters - output buffer and size of output buffer 1096 * It allocates the buffer needed for storing converted fragment 1097 * Allocated buffer should be destroyed by RTMemFree after usage 1098 */ 1099 int ConvertCFHtmlToMime(const char *source, const uint32_t cch, char **output, size_t *pcch) 1100 { 1101 char* result = NULL; 1102 1103 Assert(source); 1104 Assert(cch); 1105 Assert(output); 1106 Assert(pcch); 1107 1108 size_t startOffset, endOffset; 1109 int rc = GetHeaderValue(source, "StartFragment:", &startOffset); 1110 if (!RT_SUCCESS(rc)) 1111 { 1112 LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected StartFragment. rc = %Rrc.\n", rc)); 1113 return VERR_INVALID_PARAMETER; 1114 } 1115 rc = GetHeaderValue(source, "EndFragment:", &endOffset); 1116 if (!RT_SUCCESS(rc)) 1117 { 1118 LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment. rc = %Rrc.\n", rc)); 1119 return VERR_INVALID_PARAMETER; 1120 } 1121 if (startOffset > 0 && endOffset > 0 && endOffset > startOffset) 1122 { 1123 size_t substrlen = endOffset - startOffset; 1124 result = (char*)RTMemAlloc(substrlen + 1); 1125 if (result) 1126 { 1127 RT_BZERO(result, substrlen + 1); 1128 rc = RTStrCopyEx(result, substrlen + 1, source + startOffset, substrlen); 1129 if (RT_SUCCESS(rc)) 1130 { 1131 *output = result; 1132 *pcch = substrlen + 1; 1133 } 1134 else 1135 { 1136 LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment. rc = %Rrc\n", rc)); 1137 return rc; 1138 } 1139 } 1140 else 1141 { 1142 LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment.\n")); 1143 return VERR_NO_MEMORY; 1144 } 1145 } 1146 1147 return VINF_SUCCESS; 1148 } 1149 1150 1151 1152 /* 1153 * Converts source Utf16 mime html clipboard data to Utf8 CF_HTML format 1154 * It allocates 1155 * Calculations: 1156 * Header length = format Length + (2*(10 - 5('%010d'))('digits')) - 2('%s') = format length + 8 1157 * EndHtml = Header length + fragment length 1158 * StartHtml = 105(constant) 1159 * StartFragment = 141(constant) may vary if the header html content will be extended 1160 * EndFragment = Header length + fragment length - 38(ending length) 1161 * @source: source buffer that contains utf-16 string in mime html format 1162 * @cb: size of source buffer in bytes 1163 * @output: allocated output buffer to put converted Utf8 CF_HTML clipboard data. This function allocates memory for this. 1164 * @pcch: size of allocated result buffer in bytes 1165 * @note: output buffer should be free using RTMemFree() 1166 * @note: Everything inside of fragment can be UTF8. Windows allows it. Everything in header should be Latin1. 1167 */ 1168 int ConvertMimeToCFHTML(const char *source, size_t cb, char **output, size_t *pcch) 1169 { 1170 Assert(output); 1171 Assert(pcch); 1172 Assert(source); 1173 Assert(cb); 1174 1175 size_t fragmentLength = 0; 1176 1177 char* buf = (char*)source; 1178 1179 /* construct CF_HTML formatted string */ 1180 char* result = NULL; 1181 int rc = RTStrNLenEx(buf, RTSTR_MAX, &fragmentLength); 1182 if (!RT_SUCCESS(rc)) 1183 { 1184 LogRelFlowFunc(("Error: invalid source fragment. rc = %Rrc.\n")); 1185 return VERR_INVALID_PARAMETER; 1186 } 1187 1188 /* caluclate parameters of CF_HTML header */ 1189 size_t headerLength = (sizeof(strFormatSample) - 1) + 8; 1190 size_t endHtml = headerLength + fragmentLength; 1191 size_t endFragment = headerLength + fragmentLength - 38; 1192 result = (char*)RTMemAlloc(endHtml + 1); 1193 if (result == NULL) 1194 { 1195 LogRelFlowFunc(("Error: Cannot allocate memory for result buffer. rc = %Rrc.\n")); 1196 return VERR_NO_MEMORY; 1197 } 1198 1199 /* format result CF_HTML string */ 1200 rc = RTStrPrintf(result, endHtml + 1, strFormatSample, endHtml, endFragment, buf); 1201 if (rc == -1) 1202 { 1203 LogRelFlowFunc(("Error: cannot construct CF_HTML. rc = %Rrc.\n")); 1204 return VERR_CANT_CREATE; 1205 } 1206 Assert(endHtml == rc); 1207 1208 #ifdef DEBUG 1209 { 1210 /*Control calculations. check consistency.*/ 1211 const char strStartFragment[] = "<!--StartFragment-->"; 1212 const char strEndFragment[] = "<!--EndFragment-->"; 1213 1214 /* check 'StartFragment:' value */ 1215 const char* realStartFragment = RTStrStr(result, strStartFragment); 1216 Assert((realStartFragment + sizeof(strStartFragment) - 1) - result == 137);//141); 1217 1218 /* check 'EndFragment:' value */ 1219 const char* realEndFragment = RTStrStr(result, strEndFragment); 1220 Assert((realEndFragment - result) == endFragment); 1221 } 1222 #endif 1223 1224 *output = result; 1225 *pcch = rc+1; 1226 1227 return VINF_SUCCESS; 1228 }
Note:
See TracChangeset
for help on using the changeset viewer.