/*
 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#include "config.h"
#include "ClipboardUtilitiesWin.h"

#include "DocumentFragment.h"
#include "TextEncoding.h"
#include "markup.h"
#include <shlobj.h>
#include <shlwapi.h>
#include <wininet.h> // for INTERNET_MAX_URL_LENGTH
#include <wtf/StringExtras.h>
#include <wtf/URL.h>
#include <wtf/Vector.h>
#include <wtf/text/CString.h>
#include <wtf/text/StringBuilder.h>
#include <wtf/text/win/WCharStringExtras.h>

#if USE(CF)
#include <CoreFoundation/CoreFoundation.h>
#include <wtf/RetainPtr.h>
#endif

namespace WebCore {

#if USE(CF)
FORMATETC* cfHDropFormat()
{
    static FORMATETC urlFormat = {CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
    return &urlFormat;
}

static bool urlFromPath(CFStringRef path, String& url)
{
    if (!path)
        return false;

    RetainPtr<CFURLRef> cfURL = adoptCF(CFURLCreateWithFileSystemPath(0, path, kCFURLWindowsPathStyle, false));
    if (!cfURL)
        return false;

    url = CFURLGetString(cfURL.get());

    // Work around <rdar://problem/6708300>, where CFURLCreateWithFileSystemPath makes URLs with "localhost".
    if (url.startsWith("file://localhost/"))
        url.remove(7, 9);

    return true;
}
#endif

static bool getDataMapItem(const DragDataMap* dataObject, FORMATETC* format, String& item)
{
    DragDataMap::const_iterator found = dataObject->find(format->cfFormat);
    if (found == dataObject->end())
        return false;
    item = found->value[0];
    return true;
}

static bool getWebLocData(IDataObject* dataObject, String& url, String* title) 
{
    bool succeeded = false;
#if USE(CF)
    WCHAR filename[MAX_PATH];
    WCHAR urlBuffer[INTERNET_MAX_URL_LENGTH];

    STGMEDIUM medium;
    if (FAILED(dataObject->GetData(cfHDropFormat(), &medium)))
        return false;

    HDROP hdrop = static_cast<HDROP>(GlobalLock(medium.hGlobal));

    if (!hdrop)
        return false;

    if (!DragQueryFileW(hdrop, 0, filename, WTF_ARRAY_LENGTH(filename)))
        goto exit;

    if (_wcsicmp(PathFindExtensionW(filename), L".url"))
        goto exit;    
    
    if (!GetPrivateProfileStringW(L"InternetShortcut", L"url", 0, urlBuffer, WTF_ARRAY_LENGTH(urlBuffer), filename))
        goto exit;
    
    if (title) {
        PathRemoveExtension(filename);
        *title = String((UChar*)filename);
    }
    
    url = String((UChar*)urlBuffer);
    succeeded = true;

exit:
    // Free up memory.
    DragFinish(hdrop);
    GlobalUnlock(medium.hGlobal);
#endif
    return succeeded;
}

static bool getWebLocData(const DragDataMap* dataObject, String& url, String* title) 
{
#if USE(CF)
    WCHAR filename[MAX_PATH];
    WCHAR urlBuffer[INTERNET_MAX_URL_LENGTH];

    if (!dataObject->contains(cfHDropFormat()->cfFormat))
        return false;

    wcscpy(filename, dataObject->get(cfHDropFormat()->cfFormat)[0].wideCharacters().data());
    if (_wcsicmp(PathFindExtensionW(filename), L".url"))
        return false;    

    if (!GetPrivateProfileStringW(L"InternetShortcut", L"url", 0, urlBuffer, WTF_ARRAY_LENGTH(urlBuffer), filename))
        return false;

    if (title) {
        PathRemoveExtension(filename);
        *title = String(filename);
    }
    
    url = String(urlBuffer);
    return true;
#else
    return false;
#endif
}

static String extractURL(const String &inURL, String* title)
{
    String url = inURL;
    int splitLoc = url.find('\n');
    if (splitLoc > 0) {
        if (title)
            *title = url.substring(splitLoc+1);
        url.truncate(splitLoc);
    } else if (title)
        *title = url;
    return url;
}

static CLIPFORMAT registerClipboardFormat(LPCWSTR format)
{
    return static_cast<CLIPFORMAT>(RegisterClipboardFormat(format));
}

// Firefox text/html
static FORMATETC* texthtmlFormat() 
{
    static CLIPFORMAT cf = registerClipboardFormat(L"text/html");
    static FORMATETC texthtmlFormat = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
    return &texthtmlFormat;
}

HGLOBAL createGlobalData(const URL& url, const String& title)
{
    String mutableURL(url.string());
    String mutableTitle(title);
    SIZE_T size = mutableURL.length() + mutableTitle.length() + 2; // +1 for "\n" and +1 for null terminator
    HGLOBAL cbData = ::GlobalAlloc(GPTR, size * sizeof(UChar));

    if (cbData) {
        PWSTR buffer = static_cast<PWSTR>(GlobalLock(cbData));
        _snwprintf(buffer, size, L"%s\n%s", mutableURL.wideCharacters().data(), mutableTitle.wideCharacters().data());
        GlobalUnlock(cbData);
    }
    return cbData;
}

HGLOBAL createGlobalData(const String& str)
{
    HGLOBAL vm = ::GlobalAlloc(GPTR, (str.length() + 1) * sizeof(UChar));
    if (!vm)
        return 0;
    UChar* buffer = static_cast<UChar*>(GlobalLock(vm));
    StringView(str).getCharactersWithUpconvert(buffer);
    buffer[str.length()] = 0;
    GlobalUnlock(vm);
    return vm;
}

HGLOBAL createGlobalData(const Vector<char>& vector)
{
    HGLOBAL vm = ::GlobalAlloc(GPTR, vector.size() + 1);
    if (!vm)
        return 0;
    char* buffer = static_cast<char*>(GlobalLock(vm));
    memcpy(buffer, vector.data(), vector.size());
    buffer[vector.size()] = 0;
    GlobalUnlock(vm);
    return vm;
}

static String getFullCFHTML(IDataObject* data)
{
    STGMEDIUM store;
    if (SUCCEEDED(data->GetData(htmlFormat(), &store))) {
        // MS HTML Format parsing
        char* data = static_cast<char*>(GlobalLock(store.hGlobal));
        SIZE_T dataSize = ::GlobalSize(store.hGlobal);
        String cfhtml(UTF8Encoding().decode(data, dataSize));
        GlobalUnlock(store.hGlobal);
        ReleaseStgMedium(&store);
        return cfhtml;
    }
    return String();
}

static void append(Vector<char>& vector, const char* string)
{
    vector.append(string, strlen(string));
}

static void append(Vector<char>& vector, const CString& string)
{
    vector.append(string.data(), string.length());
}

// Find the markup between "<!--StartFragment -->" and "<!--EndFragment -->", accounting for browser quirks.
static String extractMarkupFromCFHTML(const String& cfhtml)
{
    unsigned markupStart = cfhtml.findIgnoringASCIICase("<html");
    unsigned tagStart = cfhtml.findIgnoringASCIICase("startfragment", markupStart);
    unsigned fragmentStart = cfhtml.find('>', tagStart) + 1;
    unsigned tagEnd = cfhtml.findIgnoringASCIICase("endfragment", fragmentStart);
    unsigned fragmentEnd = cfhtml.reverseFind('<', tagEnd);
    return cfhtml.substring(fragmentStart, fragmentEnd - fragmentStart).stripWhiteSpace();
}

// Documentation for the CF_HTML format is available at http://msdn.microsoft.com/workshop/networking/clipboard/htmlclipboard.asp
void markupToCFHTML(const String& markup, const String& srcURL, Vector<char>& result)
{
    if (markup.isEmpty())
        return;

    #define MAX_DIGITS 10
    #define MAKE_NUMBER_FORMAT_1(digits) MAKE_NUMBER_FORMAT_2(digits)
    #define MAKE_NUMBER_FORMAT_2(digits) "%0" #digits "u"
    #define NUMBER_FORMAT MAKE_NUMBER_FORMAT_1(MAX_DIGITS)

    const char* header = "Version:0.9\n"
        "StartHTML:" NUMBER_FORMAT "\n"
        "EndHTML:" NUMBER_FORMAT "\n"
        "StartFragment:" NUMBER_FORMAT "\n"
        "EndFragment:" NUMBER_FORMAT "\n";
    const char* sourceURLPrefix = "SourceURL:";

    const char* startMarkup = "<HTML>\n<BODY>\n<!--StartFragment-->\n";
    const char* endMarkup = "\n<!--EndFragment-->\n</BODY>\n</HTML>";

    CString sourceURLUTF8 = srcURL == WTF::blankURL() ? "" : srcURL.utf8();
    CString markupUTF8 = markup.utf8();

    // calculate offsets
    unsigned startHTMLOffset = strlen(header) - strlen(NUMBER_FORMAT) * 4 + MAX_DIGITS * 4;
    if (sourceURLUTF8.length())
        startHTMLOffset += strlen(sourceURLPrefix) + sourceURLUTF8.length() + 1;
    unsigned startFragmentOffset = startHTMLOffset + strlen(startMarkup);
    unsigned endFragmentOffset = startFragmentOffset + markupUTF8.length();
    unsigned endHTMLOffset = endFragmentOffset + strlen(endMarkup);

    {
        unsigned headerBufferLength = startHTMLOffset + 1; // + 1 for '\0' terminator.
        static const constexpr unsigned InitialBufferSize { 2048 };
        Vector<char, InitialBufferSize> headerBuffer(headerBufferLength);
        snprintf(headerBuffer.data(), headerBufferLength, header, startHTMLOffset, endHTMLOffset, startFragmentOffset, endFragmentOffset);
        append(result, CString(headerBuffer.data()));
    }
    if (sourceURLUTF8.length()) {
        append(result, sourceURLPrefix);
        append(result, sourceURLUTF8);
        result.append('\n');
    }
    append(result, startMarkup);
    append(result, markupUTF8);
    append(result, endMarkup);

    #undef MAX_DIGITS
    #undef MAKE_NUMBER_FORMAT_1
    #undef MAKE_NUMBER_FORMAT_2
    #undef NUMBER_FORMAT
}

void replaceNewlinesWithWindowsStyleNewlines(String& str)
{
    StringBuilder result;
    for (unsigned index = 0; index < str.length(); ++index) {
        if (str[index] != '\n' || (index > 0 && str[index - 1] == '\r'))
            result.append(str[index]);
        else
            result.appendLiteral("\r\n");
    }
    str = result.toString();
}

void replaceNBSPWithSpace(String& str)
{
    static const UChar NonBreakingSpaceCharacter = 0xA0;
    static const UChar SpaceCharacter = ' ';
    str.replace(NonBreakingSpaceCharacter, SpaceCharacter);
}

FORMATETC* urlWFormat()
{
    static CLIPFORMAT cf = registerClipboardFormat(L"UniformResourceLocatorW");
    static FORMATETC urlFormat = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
    return &urlFormat;
}

FORMATETC* urlFormat()
{
    static CLIPFORMAT cf = registerClipboardFormat(L"UniformResourceLocator");
    static FORMATETC urlFormat = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
    return &urlFormat;
}

FORMATETC* plainTextFormat()
{
    static FORMATETC textFormat = {CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
    return &textFormat;
}

FORMATETC* plainTextWFormat()
{
    static FORMATETC textFormat = {CF_UNICODETEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
    return &textFormat;
}

FORMATETC* filenameWFormat()
{
    static CLIPFORMAT cf = registerClipboardFormat(L"FileNameW");
    static FORMATETC urlFormat = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
    return &urlFormat;
}

FORMATETC* filenameFormat()
{
    static CLIPFORMAT cf = registerClipboardFormat(L"FileName");
    static FORMATETC urlFormat = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
    return &urlFormat;
}

// MSIE HTML Format
FORMATETC* htmlFormat() 
{
    static CLIPFORMAT cf = registerClipboardFormat(L"HTML Format");
    static FORMATETC htmlFormat = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
    return &htmlFormat;
}

FORMATETC* smartPasteFormat()
{
    static CLIPFORMAT cf = registerClipboardFormat(L"WebKit Smart Paste Format");
    static FORMATETC htmlFormat = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
    return &htmlFormat;
}

FORMATETC* fileDescriptorFormat()
{
    static CLIPFORMAT cf = registerClipboardFormat(CFSTR_FILEDESCRIPTOR);
    static FORMATETC fileDescriptorFormat = { cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
    return &fileDescriptorFormat;
}

FORMATETC* fileContentFormatZero()
{
    static CLIPFORMAT cf = registerClipboardFormat(CFSTR_FILECONTENTS);
    static FORMATETC fileContentFormat = { cf, 0, DVASPECT_CONTENT, 0, TYMED_HGLOBAL };
    return &fileContentFormat;
}

void getFileDescriptorData(IDataObject* dataObject, int& size, String& pathname)
{
    STGMEDIUM store;
    size = 0;
    if (FAILED(dataObject->GetData(fileDescriptorFormat(), &store)))
        return;

    FILEGROUPDESCRIPTOR* fgd = static_cast<FILEGROUPDESCRIPTOR*>(GlobalLock(store.hGlobal));
    size = fgd->fgd[0].nFileSizeLow;
    pathname = String(fgd->fgd[0].cFileName);

    GlobalUnlock(store.hGlobal);
    ::ReleaseStgMedium(&store);
}

void getFileContentData(IDataObject* dataObject, int size, void* dataBlob)
{
    STGMEDIUM store;
    if (FAILED(dataObject->GetData(fileContentFormatZero(), &store)))
        return;
    void* data = GlobalLock(store.hGlobal);
    ::CopyMemory(dataBlob, data, size);

    GlobalUnlock(store.hGlobal);
    ::ReleaseStgMedium(&store);
}

void setFileDescriptorData(IDataObject* dataObject, int size, const String& passedPathname)
{
    String pathname = passedPathname;

    STGMEDIUM medium { };
    medium.tymed = TYMED_HGLOBAL;

    medium.hGlobal = ::GlobalAlloc(GPTR, sizeof(FILEGROUPDESCRIPTOR));
    if (!medium.hGlobal)
        return;

    FILEGROUPDESCRIPTOR* fgd = static_cast<FILEGROUPDESCRIPTOR*>(GlobalLock(medium.hGlobal));
    ::ZeroMemory(fgd, sizeof(FILEGROUPDESCRIPTOR));
    fgd->cItems = 1;
    fgd->fgd[0].dwFlags = FD_FILESIZE;
    fgd->fgd[0].nFileSizeLow = size;

    int maxSize = std::min<int>(pathname.length(), WTF_ARRAY_LENGTH(fgd->fgd[0].cFileName));
    CopyMemory(fgd->fgd[0].cFileName, pathname.charactersWithNullTermination().data(), maxSize * sizeof(UChar));
    GlobalUnlock(medium.hGlobal);

    dataObject->SetData(fileDescriptorFormat(), &medium, TRUE);
}

void setFileContentData(IDataObject* dataObject, int size, void* dataBlob)
{
    STGMEDIUM medium { };
    medium.tymed = TYMED_HGLOBAL;

    medium.hGlobal = ::GlobalAlloc(GPTR, size);
    if (!medium.hGlobal)
        return;
    void* fileContents = GlobalLock(medium.hGlobal);
    ::CopyMemory(fileContents, dataBlob, size);
    GlobalUnlock(medium.hGlobal);

    dataObject->SetData(fileContentFormatZero(), &medium, TRUE);
}

String getURL(IDataObject* dataObject, DragData::FilenameConversionPolicy filenamePolicy, String* title)
{
    STGMEDIUM store;
    String url;
    if (getWebLocData(dataObject, url, title))
        return url;

    if (SUCCEEDED(dataObject->GetData(urlWFormat(), &store))) {
        // URL using Unicode
        UChar* data = static_cast<UChar*>(GlobalLock(store.hGlobal));
        url = extractURL(String(data), title);
        GlobalUnlock(store.hGlobal);
        ReleaseStgMedium(&store);
    } else if (SUCCEEDED(dataObject->GetData(urlFormat(), &store))) {
        // URL using ASCII
        char* data = static_cast<char*>(GlobalLock(store.hGlobal));
        url = extractURL(String(data), title);
        GlobalUnlock(store.hGlobal);
        ReleaseStgMedium(&store);
    }
#if USE(CF)
    else if (filenamePolicy == DragData::ConvertFilenames) {
        if (SUCCEEDED(dataObject->GetData(filenameWFormat(), &store))) {
            // file using unicode
            wchar_t* data = static_cast<wchar_t*>(GlobalLock(store.hGlobal));
            if (data && data[0] && (PathFileExists(data) || PathIsUNC(data))) {
                RetainPtr<CFStringRef> pathAsCFString = adoptCF(CFStringCreateWithCharacters(kCFAllocatorDefault, (const UniChar*)data, wcslen(data)));
                if (urlFromPath(pathAsCFString.get(), url) && title)
                    *title = url;
            }
            GlobalUnlock(store.hGlobal);
            ReleaseStgMedium(&store);
        } else if (SUCCEEDED(dataObject->GetData(filenameFormat(), &store))) {
            // filename using ascii
            char* data = static_cast<char*>(GlobalLock(store.hGlobal));
            if (data && data[0] && (PathFileExistsA(data) || PathIsUNCA(data))) {
                RetainPtr<CFStringRef> pathAsCFString = adoptCF(CFStringCreateWithCString(kCFAllocatorDefault, data, kCFStringEncodingASCII));
                if (urlFromPath(pathAsCFString.get(), url) && title)
                    *title = url;
            }
            GlobalUnlock(store.hGlobal);
            ReleaseStgMedium(&store);
        }
    }
#endif
    return url;
}

String getURL(const DragDataMap* data, DragData::FilenameConversionPolicy filenamePolicy, String* title)
{
    String url;

    if (getWebLocData(data, url, title))
        return url;
    if (getDataMapItem(data, urlWFormat(), url))
        return extractURL(url, title);
    if (getDataMapItem(data, urlFormat(), url))
        return extractURL(url, title);
#if USE(CF)
    if (filenamePolicy != DragData::ConvertFilenames)
        return url;

    String stringData;
    if (!getDataMapItem(data, filenameWFormat(), stringData))
        getDataMapItem(data, filenameFormat(), stringData);

    auto wcharData = stringData.wideCharacters().data();
    if (stringData.isEmpty() || (!PathFileExists(wcharData) && !PathIsUNC(wcharData)))
        return url;
    RetainPtr<CFStringRef> pathAsCFString = adoptCF(CFStringCreateWithCharacters(kCFAllocatorDefault, (const UniChar *)wcharData, wcslen(wcharData)));
    if (urlFromPath(pathAsCFString.get(), url) && title)
        *title = url;
#endif
    return url;
}

String getPlainText(IDataObject* dataObject)
{
    STGMEDIUM store;
    String text;
    if (SUCCEEDED(dataObject->GetData(plainTextWFormat(), &store))) {
        // Unicode text
        UChar* data = static_cast<UChar*>(GlobalLock(store.hGlobal));
        text = String(data);
        GlobalUnlock(store.hGlobal);
        ReleaseStgMedium(&store);
    } else if (SUCCEEDED(dataObject->GetData(plainTextFormat(), &store))) {
        // ASCII text
        char* data = static_cast<char*>(GlobalLock(store.hGlobal));
        text = String(data);
        GlobalUnlock(store.hGlobal);
        ReleaseStgMedium(&store);
    } else {
        // FIXME: Originally, we called getURL() here because dragging and dropping files doesn't
        // populate the drag with text data. Per https://bugs.webkit.org/show_bug.cgi?id=38826, this
        // is undesirable, so maybe this line can be removed.
        text = getURL(dataObject, DragData::DoNotConvertFilenames);
    }
    return text;
}

String getPlainText(const DragDataMap* data)
{
    String text;
    
    if (getDataMapItem(data, plainTextWFormat(), text))
        return text;
    if (getDataMapItem(data, plainTextFormat(), text))
        return text;
    return getURL(data, DragData::DoNotConvertFilenames);
}

String getTextHTML(IDataObject* data)
{
    STGMEDIUM store;
    String html;
    if (SUCCEEDED(data->GetData(texthtmlFormat(), &store))) {
        UChar* data = static_cast<UChar*>(GlobalLock(store.hGlobal));
        html = String(data);
        GlobalUnlock(store.hGlobal);
        ReleaseStgMedium(&store);
    }
    return html;
}

String getTextHTML(const DragDataMap* data)
{
    String text;
    getDataMapItem(data, texthtmlFormat(), text);
    return text;
}

String getCFHTML(IDataObject* data)
{
    String cfhtml = getFullCFHTML(data);
    if (!cfhtml.isEmpty())
        return extractMarkupFromCFHTML(cfhtml);
    return String();
}

String getCFHTML(const DragDataMap* dataMap)
{
    String cfhtml;
    getDataMapItem(dataMap, htmlFormat(), cfhtml);
    return extractMarkupFromCFHTML(cfhtml);
}

RefPtr<DocumentFragment> fragmentFromFilenames(Document*, const IDataObject*)
{
    // FIXME: We should be able to create fragments from files
    return nullptr;
}

RefPtr<DocumentFragment> fragmentFromFilenames(Document*, const DragDataMap*)
{
    // FIXME: We should be able to create fragments from files
    return nullptr;
}

bool containsFilenames(const IDataObject*)
{
    // FIXME: We'll want to update this once we can produce fragments from files
    return false;
}

bool containsFilenames(const DragDataMap*)
{
    // FIXME: We'll want to update this once we can produce fragments from files
    return false;
}

// Convert a String containing CF_HTML formatted text to a DocumentFragment
Ref<DocumentFragment> fragmentFromCFHTML(Document* doc, const String& cfhtml)
{
    // obtain baseURL if present
    String srcURLStr("sourceURL:");
    String srcURL;
    unsigned lineStart = cfhtml.findIgnoringASCIICase(srcURLStr);
    if (lineStart != -1) {
        unsigned srcEnd = cfhtml.find('\n', lineStart);
        unsigned srcStart = lineStart+srcURLStr.length();
        String rawSrcURL = cfhtml.substring(srcStart, srcEnd-srcStart);
        replaceNBSPWithSpace(rawSrcURL);
        srcURL = rawSrcURL.stripWhiteSpace();
    }

    String markup = extractMarkupFromCFHTML(cfhtml);
    return createFragmentFromMarkup(*doc, markup, srcURL, DisallowScriptingAndPluginContent);
}

RefPtr<DocumentFragment> fragmentFromHTML(Document* doc, IDataObject* data)
{
    if (!doc || !data)
        return nullptr;

    String cfhtml = getFullCFHTML(data);
    if (!cfhtml.isEmpty())
        return fragmentFromCFHTML(doc, cfhtml);

    String html = getTextHTML(data);
    String srcURL;
    if (!html.isEmpty())
        return createFragmentFromMarkup(*doc, html, srcURL, DisallowScriptingAndPluginContent);

    return nullptr;
}

RefPtr<DocumentFragment> fragmentFromHTML(Document* document, const DragDataMap* data)
{
    if (!document || !data || data->isEmpty())
        return nullptr;

    String stringData;
    if (getDataMapItem(data, htmlFormat(), stringData))
        return fragmentFromCFHTML(document, stringData);

    String srcURL;
    if (getDataMapItem(data, texthtmlFormat(), stringData))
        return createFragmentFromMarkup(*document, stringData, srcURL, DisallowScriptingAndPluginContent);

    return nullptr;
}

bool containsHTML(IDataObject* data)
{
    return SUCCEEDED(data->QueryGetData(texthtmlFormat())) || SUCCEEDED(data->QueryGetData(htmlFormat()));
}

bool containsHTML(const DragDataMap* data)
{
    return data->contains(texthtmlFormat()->cfFormat) || data->contains(htmlFormat()->cfFormat);
}

typedef void (*GetStringFunction)(IDataObject*, FORMATETC*, Vector<String>&);
typedef void (*SetStringFunction)(IDataObject*, FORMATETC*, const Vector<String>&);

struct ClipboardDataItem {
    FORMATETC* format;
    GetStringFunction getString;
    SetStringFunction setString;

    ClipboardDataItem(FORMATETC* format, GetStringFunction getString, SetStringFunction setString): format(format), getString(getString), setString(setString) { }
};

typedef HashMap<UINT, ClipboardDataItem*> ClipboardFormatMap;

// Getter functions.

template<typename T> void getStringData(IDataObject* data, FORMATETC* format, Vector<String>& dataStrings)
{
    STGMEDIUM store;
    if (FAILED(data->GetData(format, &store)))
        return;
    dataStrings.append(String(static_cast<T*>(GlobalLock(store.hGlobal)), ::GlobalSize(store.hGlobal) / sizeof(T)));
    GlobalUnlock(store.hGlobal);
    ReleaseStgMedium(&store);
}

void getUtf8Data(IDataObject* data, FORMATETC* format, Vector<String>& dataStrings)
{
    STGMEDIUM store;
    if (FAILED(data->GetData(format, &store)))
        return;
    dataStrings.append(String(UTF8Encoding().decode(static_cast<char*>(GlobalLock(store.hGlobal)), GlobalSize(store.hGlobal))));
    GlobalUnlock(store.hGlobal);
    ReleaseStgMedium(&store);
}

#if USE(CF)
void getCFData(IDataObject* data, FORMATETC* format, Vector<String>& dataStrings)
{
    STGMEDIUM store;
    if (FAILED(data->GetData(format, &store)))
        return;

    HDROP hdrop = reinterpret_cast<HDROP>(GlobalLock(store.hGlobal));
    if (!hdrop)
        return;

    WCHAR filename[MAX_PATH];
    UINT fileCount = DragQueryFileW(hdrop, 0xFFFFFFFF, 0, 0);
    for (UINT i = 0; i < fileCount; i++) {
        if (!DragQueryFileW(hdrop, i, filename, WTF_ARRAY_LENGTH(filename)))
            continue;
        dataStrings.append(filename);
    }

    GlobalUnlock(store.hGlobal);
    ReleaseStgMedium(&store);
}
#endif

// Setter functions.

void setUCharData(IDataObject* data, FORMATETC* format, const Vector<String>& dataStrings)
{
    STGMEDIUM medium { };
    medium.tymed = TYMED_HGLOBAL;

    medium.hGlobal = createGlobalData(dataStrings.first());
    if (!medium.hGlobal)
        return;
    data->SetData(format, &medium, FALSE);
    ::GlobalFree(medium.hGlobal);
}

void setUtf8Data(IDataObject* data, FORMATETC* format, const Vector<String>& dataStrings)
{
    STGMEDIUM medium { };
    medium.tymed = TYMED_HGLOBAL;

    CString charString = dataStrings.first().utf8();
    size_t stringLength = charString.length();
    medium.hGlobal = ::GlobalAlloc(GPTR, stringLength + 1);
    if (!medium.hGlobal)
        return;
    char* buffer = static_cast<char*>(GlobalLock(medium.hGlobal));
    memcpy(buffer, charString.data(), stringLength);
    buffer[stringLength] = 0;
    GlobalUnlock(medium.hGlobal);
    data->SetData(format, &medium, FALSE);
    ::GlobalFree(medium.hGlobal);
}

#if USE(CF)
void setCFData(IDataObject* data, FORMATETC* format, const Vector<String>& dataStrings)
{
    STGMEDIUM medium { };
    medium.tymed = TYMED_HGLOBAL;

    SIZE_T dropFilesSize = sizeof(DROPFILES) + (sizeof(WCHAR) * (dataStrings.first().length() + 2));
    medium.hGlobal = ::GlobalAlloc(GHND | GMEM_SHARE, dropFilesSize);
    if (!medium.hGlobal) 
        return;

    DROPFILES* dropFiles = reinterpret_cast<DROPFILES *>(GlobalLock(medium.hGlobal));
    dropFiles->pFiles = sizeof(DROPFILES);
    dropFiles->fWide = TRUE;
    String filename = dataStrings.first();
    wcscpy(reinterpret_cast<LPWSTR>(dropFiles + 1), filename.wideCharacters().data());
    GlobalUnlock(medium.hGlobal);
    data->SetData(format, &medium, FALSE);
    ::GlobalFree(medium.hGlobal);
}
#endif

static const ClipboardFormatMap& getClipboardMap()
{
    static ClipboardFormatMap formatMap;
    if (formatMap.isEmpty()) {
        formatMap.add(htmlFormat()->cfFormat, new ClipboardDataItem(htmlFormat(), getUtf8Data, setUtf8Data));
        formatMap.add(texthtmlFormat()->cfFormat, new ClipboardDataItem(texthtmlFormat(), getStringData<UChar>, setUCharData));
        formatMap.add(plainTextFormat()->cfFormat,  new ClipboardDataItem(plainTextFormat(), getStringData<char>, setUtf8Data));
        formatMap.add(plainTextWFormat()->cfFormat,  new ClipboardDataItem(plainTextWFormat(), getStringData<UChar>, setUCharData));
#if USE(CF)
        formatMap.add(cfHDropFormat()->cfFormat,  new ClipboardDataItem(cfHDropFormat(), getCFData, setCFData));
#endif
        formatMap.add(filenameFormat()->cfFormat,  new ClipboardDataItem(filenameFormat(), getStringData<char>, setUtf8Data));
        formatMap.add(filenameWFormat()->cfFormat,  new ClipboardDataItem(filenameWFormat(), getStringData<UChar>, setUCharData));
        formatMap.add(urlFormat()->cfFormat,  new ClipboardDataItem(urlFormat(), getStringData<char>, setUtf8Data));
        formatMap.add(urlWFormat()->cfFormat,  new ClipboardDataItem(urlWFormat(), getStringData<UChar>, setUCharData));
    }
    return formatMap;
}

void getClipboardData(IDataObject* dataObject, FORMATETC* format, Vector<String>& dataStrings)
{
    const ClipboardFormatMap& formatMap = getClipboardMap();
    ClipboardFormatMap::const_iterator found = formatMap.find(format->cfFormat);
    if (found == formatMap.end())
        return;
    found->value->getString(dataObject, found->value->format, dataStrings);
}

void setClipboardData(IDataObject* dataObject, UINT format, const Vector<String>& dataStrings)
{
    const ClipboardFormatMap& formatMap = getClipboardMap();
    ClipboardFormatMap::const_iterator found = formatMap.find(format);
    if (found == formatMap.end())
        return;
    found->value->setString(dataObject, found->value->format, dataStrings);
}

} // namespace WebCore
