VirtualBox

source: vbox/trunk/src/VBox/GuestHost/SharedClipboard/clipboard-common.cpp@ 79272

Last change on this file since 79272 was 79272, checked in by vboxsync, 5 years ago

Shared Clipboard/URI: SCM fix.

  • Property eol-style set to native
  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 13.2 KB
Line 
1/* $Id: clipboard-common.cpp 79272 2019-06-21 11:34:13Z vboxsync $ */
2/** @file
3 * Shared Clipboard: Some helper function for converting between the various eol.
4 */
5
6/*
7 * Includes contributions from François Revol
8 *
9 * Copyright (C) 2006-2019 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20#define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD
21
22#include <iprt/alloc.h>
23#include <iprt/assert.h>
24#include <iprt/path.h>
25
26#include <iprt/errcore.h>
27#include <VBox/log.h>
28#include <VBox/GuestHost/clipboard-helper.h>
29
30
31/** @todo use const where appropriate; delinuxify the code (*Lin* -> *Host*); use AssertLogRel*. */
32
33int vboxClipboardUtf16GetWinSize(PRTUTF16 pwszSrc, size_t cwSrc, size_t *pcwDest)
34{
35 size_t cwDest, i;
36
37 LogFlowFunc(("pwszSrc=%.*ls, cwSrc=%u\n", cwSrc, pwszSrc, cwSrc));
38 AssertLogRelMsgReturn(pwszSrc != NULL, ("vboxClipboardUtf16GetWinSize: received a null Utf16 string, returning VERR_INVALID_PARAMETER\n"), VERR_INVALID_PARAMETER);
39 if (cwSrc == 0)
40 {
41 *pcwDest = 0;
42 LogFlowFunc(("empty source string, returning\n"));
43 return VINF_SUCCESS;
44 }
45/** @todo convert the remainder of the Assert stuff to AssertLogRel. */
46 /* We only take little endian Utf16 */
47 if (pwszSrc[0] == UTF16BEMARKER)
48 {
49 LogRel(("vboxClipboardUtf16GetWinSize: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n"));
50 AssertReturn(pwszSrc[0] != UTF16BEMARKER, VERR_INVALID_PARAMETER);
51 }
52 cwDest = 0;
53 /* Calculate the size of the destination text string. */
54 /* Is this Utf16 or Utf16-LE? */
55 for (i = (pwszSrc[0] == UTF16LEMARKER ? 1 : 0); i < cwSrc; ++i, ++cwDest)
56 {
57 /* Check for a single line feed */
58 if (pwszSrc[i] == LINEFEED)
59 ++cwDest;
60#ifdef RT_OS_DARWIN
61 /* Check for a single carriage return (MacOS) */
62 if (pwszSrc[i] == CARRIAGERETURN)
63 ++cwDest;
64#endif
65 if (pwszSrc[i] == 0)
66 {
67 /* Don't count this, as we do so below. */
68 break;
69 }
70 }
71 /* Count the terminating null byte. */
72 ++cwDest;
73 LogFlowFunc(("returning VINF_SUCCESS, %d 16bit words\n", cwDest));
74 *pcwDest = cwDest;
75 return VINF_SUCCESS;
76}
77
78int vboxClipboardUtf16LinToWin(PRTUTF16 pwszSrc, size_t cwSrc, PRTUTF16 pu16Dest,
79 size_t cwDest)
80{
81 size_t i, j;
82 LogFlowFunc(("pwszSrc=%.*ls, cwSrc=%u\n", cwSrc, pwszSrc, cwSrc));
83 if (!VALID_PTR(pwszSrc) || !VALID_PTR(pu16Dest))
84 {
85 LogRel(("vboxClipboardUtf16LinToWin: received an invalid pointer, pwszSrc=%p, pu16Dest=%p, returning VERR_INVALID_PARAMETER\n", pwszSrc, pu16Dest));
86 AssertReturn(VALID_PTR(pwszSrc) && VALID_PTR(pu16Dest), VERR_INVALID_PARAMETER);
87 }
88 if (cwSrc == 0)
89 {
90 if (cwDest == 0)
91 {
92 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
93 return VERR_BUFFER_OVERFLOW;
94 }
95 pu16Dest[0] = 0;
96 LogFlowFunc(("empty source string, returning\n"));
97 return VINF_SUCCESS;
98 }
99 /* We only take little endian Utf16 */
100 if (pwszSrc[0] == UTF16BEMARKER)
101 {
102 LogRel(("vboxClipboardUtf16LinToWin: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n"));
103 AssertReturn(pwszSrc[0] != UTF16BEMARKER, VERR_INVALID_PARAMETER);
104 }
105 /* Don't copy the endian marker. */
106 for (i = (pwszSrc[0] == UTF16LEMARKER ? 1 : 0), j = 0; i < cwSrc; ++i, ++j)
107 {
108 /* Don't copy the null byte, as we add it below. */
109 if (pwszSrc[i] == 0)
110 break;
111 if (j == cwDest)
112 {
113 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
114 return VERR_BUFFER_OVERFLOW;
115 }
116 if (pwszSrc[i] == LINEFEED)
117 {
118 pu16Dest[j] = CARRIAGERETURN;
119 ++j;
120 if (j == cwDest)
121 {
122 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
123 return VERR_BUFFER_OVERFLOW;
124 }
125 }
126#ifdef RT_OS_DARWIN
127 /* Check for a single carriage return (MacOS) */
128 else if (pwszSrc[i] == CARRIAGERETURN)
129 {
130 /* set cr */
131 pu16Dest[j] = CARRIAGERETURN;
132 ++j;
133 if (j == cwDest)
134 {
135 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
136 return VERR_BUFFER_OVERFLOW;
137 }
138 /* add the lf */
139 pu16Dest[j] = LINEFEED;
140 continue;
141 }
142#endif
143 pu16Dest[j] = pwszSrc[i];
144 }
145 /* Add the trailing null. */
146 if (j == cwDest)
147 {
148 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
149 return VERR_BUFFER_OVERFLOW;
150 }
151 pu16Dest[j] = 0;
152 LogFlowFunc(("rc=VINF_SUCCESS, pu16Dest=%ls\n", pu16Dest));
153 return VINF_SUCCESS;
154}
155
156int vboxClipboardUtf16GetLinSize(PRTUTF16 pwszSrc, size_t cwSrc, size_t *pcwDest)
157{
158 size_t cwDest;
159
160 LogFlowFunc(("pwszSrc=%.*ls, cwSrc=%u\n", cwSrc, pwszSrc, cwSrc));
161 if (!VALID_PTR(pwszSrc))
162 {
163 LogRel(("vboxClipboardUtf16GetLinSize: received an invalid Utf16 string %p. Returning VERR_INVALID_PARAMETER.\n", pwszSrc));
164 AssertReturn(VALID_PTR(pwszSrc), VERR_INVALID_PARAMETER);
165 }
166 if (cwSrc == 0)
167 {
168 LogFlowFunc(("empty source string, returning VINF_SUCCESS\n"));
169 *pcwDest = 0;
170 return VINF_SUCCESS;
171 }
172 /* We only take little endian Utf16 */
173 if (pwszSrc[0] == UTF16BEMARKER)
174 {
175 LogRel(("vboxClipboardUtf16GetLinSize: received a big endian Utf16 string. Returning VERR_INVALID_PARAMETER.\n"));
176 AssertReturn(pwszSrc[0] != UTF16BEMARKER, VERR_INVALID_PARAMETER);
177 }
178 /* Calculate the size of the destination text string. */
179 /* Is this Utf16 or Utf16-LE? */
180 if (pwszSrc[0] == UTF16LEMARKER)
181 cwDest = 0;
182 else
183 cwDest = 1;
184 for (size_t i = 0; i < cwSrc; ++i, ++cwDest)
185 {
186 if ( (i + 1 < cwSrc)
187 && (pwszSrc[i] == CARRIAGERETURN)
188 && (pwszSrc[i + 1] == LINEFEED))
189 {
190 ++i;
191 }
192 if (pwszSrc[i] == 0)
193 {
194 break;
195 }
196 }
197 /* Terminating zero */
198 ++cwDest;
199 LogFlowFunc(("returning %d\n", cwDest));
200 *pcwDest = cwDest;
201 return VINF_SUCCESS;
202}
203
204int vboxClipboardUtf16WinToLin(PRTUTF16 pwszSrc, size_t cwSrc, PRTUTF16 pu16Dest,
205 size_t cwDest)
206{
207 size_t cwDestPos;
208
209 LogFlowFunc(("pwszSrc=%.*ls, cwSrc=%u, pu16Dest=%p, cwDest=%u\n",
210 cwSrc, pwszSrc, cwSrc, pu16Dest, cwDest));
211 /* A buffer of size 0 may not be an error, but it is not a good idea either. */
212 Assert(cwDest > 0);
213 if (!VALID_PTR(pwszSrc) || !VALID_PTR(pu16Dest))
214 {
215 LogRel(("vboxClipboardUtf16WinToLin: received an invalid ptr, pwszSrc=%p, pu16Dest=%p, returning VERR_INVALID_PARAMETER\n", pwszSrc, pu16Dest));
216 AssertReturn(VALID_PTR(pwszSrc) && VALID_PTR(pu16Dest), VERR_INVALID_PARAMETER);
217 }
218 /* We only take little endian Utf16 */
219 if (pwszSrc[0] == UTF16BEMARKER)
220 {
221 LogRel(("vboxClipboardUtf16WinToLin: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n"));
222 AssertMsgFailedReturn(("received a big endian string\n"), VERR_INVALID_PARAMETER);
223 }
224 if (cwDest == 0)
225 {
226 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
227 return VERR_BUFFER_OVERFLOW;
228 }
229 if (cwSrc == 0)
230 {
231 pu16Dest[0] = 0;
232 LogFlowFunc(("received empty string. Returning VINF_SUCCESS\n"));
233 return VINF_SUCCESS;
234 }
235 /* Prepend the Utf16 byte order marker if it is missing. */
236 if (pwszSrc[0] == UTF16LEMARKER)
237 {
238 cwDestPos = 0;
239 }
240 else
241 {
242 pu16Dest[0] = UTF16LEMARKER;
243 cwDestPos = 1;
244 }
245 for (size_t i = 0; i < cwSrc; ++i, ++cwDestPos)
246 {
247 if (pwszSrc[i] == 0)
248 {
249 break;
250 }
251 if (cwDestPos == cwDest)
252 {
253 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
254 return VERR_BUFFER_OVERFLOW;
255 }
256 if ( (i + 1 < cwSrc)
257 && (pwszSrc[i] == CARRIAGERETURN)
258 && (pwszSrc[i + 1] == LINEFEED))
259 {
260 ++i;
261 }
262 pu16Dest[cwDestPos] = pwszSrc[i];
263 }
264 /* Terminating zero */
265 if (cwDestPos == cwDest)
266 {
267 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
268 return VERR_BUFFER_OVERFLOW;
269 }
270 pu16Dest[cwDestPos] = 0;
271 LogFlowFunc(("set string %ls. Returning\n", pu16Dest + 1));
272 return VINF_SUCCESS;
273}
274
275int vboxClipboardDibToBmp(const void *pvSrc, size_t cbSrc, void **ppvDest, size_t *pcbDest)
276{
277 size_t cb = sizeof(BMFILEHEADER) + cbSrc;
278 PBMFILEHEADER pFileHeader = NULL;
279 void *pvDest = NULL;
280 size_t offPixel = 0;
281
282 AssertPtrReturn(pvSrc, VERR_INVALID_PARAMETER);
283 AssertPtrReturn(ppvDest, VERR_INVALID_PARAMETER);
284 AssertPtrReturn(pcbDest, VERR_INVALID_PARAMETER);
285
286 PBMINFOHEADER pBitmapInfoHeader = (PBMINFOHEADER)pvSrc;
287 /** @todo Support all the many versions of the DIB headers. */
288 if ( cbSrc < sizeof(BMINFOHEADER)
289 || RT_LE2H_U32(pBitmapInfoHeader->u32Size) < sizeof(BMINFOHEADER)
290 || RT_LE2H_U32(pBitmapInfoHeader->u32Size) != sizeof(BMINFOHEADER))
291 {
292 Log(("vboxClipboardDibToBmp: invalid or unsupported bitmap data.\n"));
293 return VERR_INVALID_PARAMETER;
294 }
295
296 offPixel = sizeof(BMFILEHEADER)
297 + RT_LE2H_U32(pBitmapInfoHeader->u32Size)
298 + RT_LE2H_U32(pBitmapInfoHeader->u32ClrUsed) * sizeof(uint32_t);
299 if (cbSrc < offPixel)
300 {
301 Log(("vboxClipboardDibToBmp: invalid bitmap data.\n"));
302 return VERR_INVALID_PARAMETER;
303 }
304
305 pvDest = RTMemAlloc(cb);
306 if (!pvDest)
307 {
308 Log(("writeToPasteboard: cannot allocate memory for bitmap.\n"));
309 return VERR_NO_MEMORY;
310 }
311
312 pFileHeader = (PBMFILEHEADER)pvDest;
313 pFileHeader->u16Type = BITMAPHEADERMAGIC;
314 pFileHeader->u32Size = (uint32_t)RT_H2LE_U32(cb);
315 pFileHeader->u16Reserved1 = pFileHeader->u16Reserved2 = 0;
316 pFileHeader->u32OffBits = (uint32_t)RT_H2LE_U32(offPixel);
317 memcpy((uint8_t *)pvDest + sizeof(BMFILEHEADER), pvSrc, cbSrc);
318 *ppvDest = pvDest;
319 *pcbDest = cb;
320 return VINF_SUCCESS;
321}
322
323int vboxClipboardBmpGetDib(const void *pvSrc, size_t cbSrc, const void **ppvDest, size_t *pcbDest)
324{
325 AssertPtrReturn(pvSrc, VERR_INVALID_PARAMETER);
326 AssertPtrReturn(ppvDest, VERR_INVALID_PARAMETER);
327 AssertPtrReturn(pcbDest, VERR_INVALID_PARAMETER);
328
329 PBMFILEHEADER pFileHeader = (PBMFILEHEADER)pvSrc;
330 if ( cbSrc < sizeof(BMFILEHEADER)
331 || pFileHeader->u16Type != BITMAPHEADERMAGIC
332 || RT_LE2H_U32(pFileHeader->u32Size) != cbSrc)
333 {
334 Log(("vboxClipboardBmpGetDib: invalid bitmap data.\n"));
335 return VERR_INVALID_PARAMETER;
336 }
337
338 *ppvDest = ((uint8_t *)pvSrc) + sizeof(BMFILEHEADER);
339 *pcbDest = cbSrc - sizeof(BMFILEHEADER);
340 return VINF_SUCCESS;
341}
342
343#ifdef LOG_ENABLED
344int VBoxClipboardDbgDumpHtml(const char *pszSrc, size_t cbSrc)
345{
346 size_t cchIgnored = 0;
347 int rc = RTStrNLenEx(pszSrc, cbSrc, &cchIgnored);
348 if (RT_SUCCESS(rc))
349 {
350 char *pszBuf = (char *)RTMemAllocZ(cbSrc + 1);
351 if (pszBuf)
352 {
353 rc = RTStrCopy(pszBuf, cbSrc + 1, (const char *)pszSrc);
354 if (RT_SUCCESS(rc))
355 {
356 for (size_t i = 0; i < cbSrc; ++i)
357 if (pszBuf[i] == '\n' || pszBuf[i] == '\r')
358 pszBuf[i] = ' ';
359 }
360 else
361 LogFunc(("Error in copying string\n"));
362 LogFunc(("Removed \\r\\n: %s\n", pszBuf));
363 RTMemFree(pszBuf);
364 }
365 else
366 rc = VERR_NO_MEMORY;
367 }
368
369 return rc;
370}
371
372void VBoxClipboardDbgDumpData(const void *pv, size_t cb, VBOXCLIPBOARDFORMAT u32Format)
373{
374 if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
375 {
376 LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT:\n"));
377 if (pv && cb)
378 LogFunc(("%ls\n", pv));
379 else
380 LogFunc(("%p %zu\n", pv, cb));
381 }
382 else if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
383 LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_BITMAP\n"));
384 else if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_HTML)
385 {
386 LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_HTML:\n"));
387 if (pv && cb)
388 {
389 LogFunc(("%s\n", pv));
390
391 //size_t cb = RTStrNLen(pv, );
392 char *pszBuf = (char *)RTMemAllocZ(cb + 1);
393 RTStrCopy(pszBuf, cb + 1, (const char *)pv);
394 for (size_t off = 0; off < cb; ++off)
395 {
396 if (pszBuf[off] == '\n' || pszBuf[off] == '\r')
397 pszBuf[off] = ' ';
398 }
399
400 LogFunc(("%s\n", pszBuf));
401 RTMemFree(pszBuf);
402 }
403 else
404 LogFunc(("%p %zu\n", pv, cb));
405 }
406 else
407 LogFunc(("Invalid format %02X\n", u32Format));
408}
409#endif /* LOG_ENABLED */
410
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette