VirtualBox

Changeset 92845 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Dec 9, 2021 11:39:01 AM (3 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
148773
Message:

Additions: Shared Clipboard: fix HTML content conversion, bugref:10160.

This commit applies a fix for HTML content handling for the case when
data is being copied from X11 host and pasted into Windows guest. We
now make sure that clipboard data is NULL-terminated string. If HTML
data is not wrapped into CF_HTML format, we now do so.

Location:
trunk/src/VBox
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp

    r92735 r92845  
    438438                                    }
    439439                                }
     440                                else if (fFormat == VBOX_SHCL_FMT_HTML)
     441                                {
     442                                    /* Wrap content into CF_HTML clipboard format if needed. */
     443                                    if (!SharedClipboardWinIsCFHTML((const char *)pMem))
     444                                    {
     445                                        char *pszWrapped = NULL;
     446                                        uint32_t cbWrapped = 0;
     447                                        rc =  SharedClipboardWinConvertMIMEToCFHTML((const char *)pMem, cb, &pszWrapped, &cbWrapped);
     448                                        if (RT_SUCCESS(rc))
     449                                        {
     450                                            if (GlobalUnlock(hMem) == 0)
     451                                            {
     452                                                hMem = GlobalReAlloc(hMem, cbWrapped, 0);
     453                                                if (hMem)
     454                                                {
     455                                                    pMem = GlobalLock(hMem);
     456                                                    if (pMem)
     457                                                    {
     458                                                        /* Copy wrapped content back to memory passed to system clipboard. */
     459                                                        memcpy(pMem, pszWrapped, cbWrapped);
     460                                                        cb = cbWrapped;
     461                                                    }
     462                                                    else
     463                                                    {
     464                                                        LogRel(("Shared Clipboard: Cannot lock memory, "
     465                                                                "HTML clipboard data won't be converted into CF_HTML clipboard format\n"));
     466                                                        GlobalFree(hMem);
     467                                                        hMem = NULL;
     468                                                    }
     469                                                }
     470                                                else
     471                                                    LogRel(("Shared Clipboard: Cannot re-allocate memory, "
     472                                                            "HTML clipboard data won't be converted into CF_HTML clipboard format\n"));
     473                                            }
     474                                            else
     475                                                LogRel(("Shared Clipboard: Cannot unlock memory, "
     476                                                        "HTML clipboard data won't be converted into CF_HTML clipboard format\n"));
     477
     478                                            RTMemFree(pszWrapped);
     479                                        }
     480                                        else
     481                                            LogRel(("Shared Clipboard: Cannot convert HTML clipboard data into CF_HTML clipboard format, rc=%Rrc\n", rc));
     482                                    }
     483                                }
    440484                            }
    441485
  • trunk/src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp

    r92156 r92845  
    574574 *   EndFragment   = Header length + fragment length - 38(ending length)
    575575 *
     576 * @return  IPRT status code.
    576577 * @param   pszSource   Source buffer that contains utf-16 string in mime html format
    577578 * @param   cb          Size of source buffer in bytes
     
    585586int SharedClipboardWinConvertMIMEToCFHTML(const char *pszSource, size_t cb, char **ppszOutput, uint32_t *pcbOutput)
    586587{
     588    /**
     589     * CF_HTML format description (see also, https://docs.microsoft.com/en-us/previous-versions/
     590     * windows/internet-explorer/ie-developer/platform-apis/aa767917(v=vs.85)?redirectedfrom=MSDN):
     591     *
     592     *   @StartHtml - pos before <html>
     593     *   @EndHtml - whole size of text excluding ending zero char (pos after </html>)
     594     *   @StartFragment - pos after <!--StartFragment-->
     595     *   @EndFragment - pos before <!--EndFragment-->
     596     *   @note: all values includes CR\LF inserted into text
     597    */
     598
     599#define VBOX_CLIP_CF_HTML_HEADER \
     600    "Version:1.0\r\n" \
     601    "StartHTML:000000101\r\n" \
     602    "EndHTML:%0000009u\r\n" \
     603    "StartFragment:000000137\r\n" \
     604    "EndFragment:%0000009u\r\n" \
     605    "<html>\r\n" \
     606    "<body>\r\n" \
     607    "<!--StartFragment-->"
     608
     609#define VBOX_CLIP_CF_HTML_FOOTER \
     610    "<!--EndFragment-->\r\n" \
     611    "</body>\r\n" \
     612    "</html>\r\n"
     613
    587614    Assert(ppszOutput);
    588615    Assert(pcbOutput);
     
    590617    Assert(cb);
    591618
    592     /* construct CF_HTML formatted string */
    593     char *pszResult = NULL;
    594     size_t cchFragment;
    595     int rc = RTStrNLenEx(pszSource, cb, &cchFragment);
    596     if (!RT_SUCCESS(rc))
    597     {
    598         LogRelFlowFunc(("Error: invalid source fragment. rc = %Rrc\n"));
    599         return VERR_INVALID_PARAMETER;
    600     }
    601 
    602     /*
    603     @StartHtml - pos before <html>
    604     @EndHtml - whole size of text excluding ending zero char
    605     @StartFragment - pos after <!--StartFragment-->
    606     @EndFragment - pos before <!--EndFragment-->
    607     @note: all values includes CR\LF inserted into text
    608     Calculations:
    609     Header length = format Length + (3*6('digits')) - 2('%s') = format length + 16 (control value - 183)
    610     EndHtml  = Header length + fragment length
    611     StartHtml = 105(constant)
    612     StartFragment = 143(constant)
    613     EndFragment  = Header length + fragment length - 40(ending length)
    614     */
    615     static const char s_szFormatSample[] =
    616     /*   0:   */ "Version:1.0\r\n"
    617     /*  13:   */ "StartHTML:000000101\r\n"
    618     /*  34:   */ "EndHTML:%0000009u\r\n" // END HTML = Header length + fragment length
    619     /*  53:   */ "StartFragment:000000137\r\n"
    620     /*  78:   */ "EndFragment:%0000009u\r\n"
    621     /* 101:   */ "<html>\r\n"
    622     /* 109:   */ "<body>\r\n"
    623     /* 117:   */ "<!--StartFragment-->"
    624     /* 137:   */ "%s"
    625     /* 137+2: */ "<!--EndFragment-->\r\n"
    626     /* 157+2: */ "</body>\r\n"
    627     /* 166+2: */ "</html>\r\n";
    628     /* 175+2: */
    629     AssertCompile(sizeof(s_szFormatSample) == 175 + 2 + 1);
    630 
    631     /* calculate parameters of CF_HTML header */
    632     size_t cchHeader      = sizeof(s_szFormatSample) - 1;
    633     size_t offEndHtml     = cchHeader + cchFragment;
    634     size_t offEndFragment = cchHeader + cchFragment - 38; /* 175-137 = 38 */
    635     pszResult = (char *)RTMemAlloc(offEndHtml + 1);
     619    size_t  cchFragment;
     620    int     rc;
     621
     622    char    *szFormat       = VBOX_CLIP_CF_HTML_HEADER "%s" VBOX_CLIP_CF_HTML_FOOTER;
     623    size_t  offEndFragment  = sizeof(VBOX_CLIP_CF_HTML_HEADER) - 2 /* '%' chars */ + cb;
     624    size_t  offEndHTML      = offEndFragment + sizeof(VBOX_CLIP_CF_HTML_FOOTER);
     625    char    *pszResult      = NULL;
     626    size_t  cbResult        = sizeof(VBOX_CLIP_CF_HTML_HEADER) + cb + sizeof(VBOX_CLIP_CF_HTML_FOOTER);
     627
     628    /* Make sure input string is '\0' terminated. */
     629    rc = RTStrNLenEx(pszSource, cb, &cchFragment);
     630    if (RT_FAILURE(rc))
     631    {
     632        LogRelFlowFunc(("Error: invalid source fragment. rc = %Rrc\n", rc));
     633        return rc;
     634    }
     635
     636    pszResult = (char *)RTMemAllocZ(cbResult);
    636637    if (pszResult == NULL)
    637638    {
    638         LogRelFlowFunc(("Error: Cannot allocate memory for result buffer. rc = %Rrc\n"));
     639        LogRel(("Shared Clipboard: cannot allocate memory for HTML clipboard conversion, rc = %Rrc\n", rc));
    639640        return VERR_NO_MEMORY;
    640641    }
    641642
    642643    /* format result CF_HTML string */
    643     size_t cchFormatted = RTStrPrintf(pszResult, offEndHtml + 1,
    644                                       s_szFormatSample, offEndHtml, offEndFragment, pszSource);
    645     Assert(offEndHtml == cchFormatted); NOREF(cchFormatted);
    646 
    647 #ifdef VBOX_STRICT
    648     /* Control calculations. check consistency.*/
    649     static const char s_szStartFragment[] = "<!--StartFragment-->";
    650     static const char s_szEndFragment[] = "<!--EndFragment-->";
    651 
    652     /* check 'StartFragment:' value */
    653     const char *pszRealStartFragment = RTStrStr(pszResult, s_szStartFragment);
    654     Assert(&pszRealStartFragment[sizeof(s_szStartFragment) - 1] - pszResult == 137);
    655 
    656     /* check 'EndFragment:' value */
    657     const char *pszRealEndFragment = RTStrStr(pszResult, s_szEndFragment);
    658     Assert((size_t)(pszRealEndFragment - pszResult) == offEndFragment);
    659 #endif
    660 
    661     *ppszOutput = pszResult;
    662     *pcbOutput = (uint32_t)cchFormatted + 1;
    663     Assert(*pcbOutput == cchFormatted + 1);
    664 
    665     return VINF_SUCCESS;
     644    size_t cchFormatted = RTStrPrintf2(pszResult, cbResult, szFormat, offEndHTML, offEndFragment, pszSource);
     645    if (cchFormatted > 0)
     646    {
     647        *ppszOutput = pszResult;
     648        *pcbOutput = (uint32_t)cchFormatted + 1;
     649        return VINF_SUCCESS;
     650    }
     651    else
     652        LogRel(("Shared Clipboard: cannot format CF_HTML content\n"));
     653
     654    return VERR_INVALID_PARAMETER;
    666655}
    667656
  • trunk/src/VBox/GuestHost/SharedClipboard/clipboard-x11.cpp

    r92833 r92845  
    20372037                else /* Raw data. */
    20382038                {
    2039                    pvDst = RTMemAlloc(cbSrc);
    2040                    if(pvDst)
    2041                    {
    2042                         memcpy(pvDst, pvSrc, cbSrc);
    2043                         cbDst = cbSrc;
    2044                    }
    2045                    else
    2046                    {
    2047                         rc = VERR_NO_MEMORY;
    2048                         break;
    2049                    }
     2039                    pvDst = RTMemAllocZ(cbSrc + 1 /* '\0' */);
     2040                    if(pvDst)
     2041                    {
     2042                         memcpy(pvDst, pvSrc, cbSrc);
     2043                         cbDst = cbSrc + 1 /* '\0' */;
     2044                    }
     2045                    else
     2046                    {
     2047                         rc = VERR_NO_MEMORY;
     2048                         break;
     2049                    }
    20502050                }
    20512051
Note: See TracChangeset for help on using the changeset viewer.

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