/*
 * Copyright (C) 2006-2007, 2016 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 "ResourceResponse.h"

#if USE(CFURLCONNECTION)

#include <pal/spi/cf/CFNetworkSPI.h>

#include "HTTPParsers.h"
#include "MIMETypeRegistry.h"
#include <wtf/RetainPtr.h>

namespace WebCore {

static CFStringRef const commonHeaderFields[] = {
    CFSTR("Age"), CFSTR("Cache-Control"), CFSTR("Content-Type"), CFSTR("Date"), CFSTR("Etag"), CFSTR("Expires"), CFSTR("Last-Modified"), CFSTR("Pragma")
};

CFURLResponseRef ResourceResponse::cfURLResponse() const
{
    if (!m_cfResponse && !m_isNull) {
        RetainPtr<CFURLRef> url = m_url.createCFURL();
        // FIXME: This creates a very incomplete CFURLResponse, which does not even have a status code.
        m_cfResponse = adoptCF(CFURLResponseCreate(0, url.get(), m_mimeType.string().createCFString().get(), m_expectedContentLength, m_textEncodingName.string().createCFString().get(), kCFURLCacheStorageAllowed));
    }

    return m_cfResponse.get();
}

static void addToHTTPHeaderMap(const void* key, const void* value, void* context)
{
    HTTPHeaderMap* httpHeaderMap = (HTTPHeaderMap*)context;
    httpHeaderMap->set((CFStringRef)key, (CFStringRef)value);
}

void ResourceResponse::platformLazyInit(InitLevel initLevel)
{
    if (m_initLevel > initLevel)
        return;

    if (m_isNull || !m_cfResponse.get())
        return;

    if (m_initLevel < CommonFieldsOnly && initLevel >= CommonFieldsOnly) {
        m_url = CFURLResponseGetURL(m_cfResponse.get());
        m_mimeType = CFURLResponseGetMIMEType(m_cfResponse.get());
        m_expectedContentLength = CFURLResponseGetExpectedContentLength(m_cfResponse.get());
        m_textEncodingName = CFURLResponseGetTextEncodingName(m_cfResponse.get());

        // Workaround for <rdar://problem/8757088>, can be removed once that is fixed.
        unsigned textEncodingNameLength = m_textEncodingName.length();
        if (textEncodingNameLength >= 2 && m_textEncodingName[0U] == '"' && m_textEncodingName[textEncodingNameLength - 1] == '"')
            m_textEncodingName = m_textEncodingName.string().substring(1, textEncodingNameLength - 2);

        CFHTTPMessageRef httpResponse = CFURLResponseGetHTTPResponse(m_cfResponse.get());
        if (httpResponse) {
            m_httpStatusCode = CFHTTPMessageGetResponseStatusCode(httpResponse);
            
            if (initLevel < AllFields) {
                RetainPtr<CFDictionaryRef> headers = adoptCF(CFHTTPMessageCopyAllHeaderFields(httpResponse));
                for (auto& commonHeader : commonHeaderFields) {
                    CFStringRef value;
                    if (CFDictionaryGetValueIfPresent(headers.get(), commonHeader, (const void **)&value))
                        m_httpHeaderFields.set(commonHeader, value);
                }
            }
        } else
            m_httpStatusCode = 0;
    }

    if (m_initLevel < AllFields && initLevel == AllFields) {
        CFHTTPMessageRef httpResponse = CFURLResponseGetHTTPResponse(m_cfResponse.get());
        if (httpResponse) {
            m_httpVersion = String(adoptCF(CFHTTPMessageCopyVersion(httpResponse)).get()).convertToASCIIUppercase();

            RetainPtr<CFStringRef> statusLine = adoptCF(CFHTTPMessageCopyResponseStatusLine(httpResponse));
            m_httpStatusText = extractReasonPhraseFromHTTPStatusLine(statusLine.get());

            RetainPtr<CFDictionaryRef> headers = adoptCF(CFHTTPMessageCopyAllHeaderFields(httpResponse));
            CFDictionaryApplyFunction(headers.get(), addToHTTPHeaderMap, &m_httpHeaderFields);
        }
    }

    m_initLevel = initLevel;
}

CertificateInfo ResourceResponse::platformCertificateInfo() const
{
    return { };
}

String ResourceResponse::platformSuggestedFilename() const
{
    if (!cfURLResponse())
        return String();
    RetainPtr<CFStringRef> suggestedFilename = adoptCF(CFURLResponseCopySuggestedFilename(cfURLResponse()));
    return suggestedFilename.get();
}

bool ResourceResponse::platformCompare(const ResourceResponse& a, const ResourceResponse& b)
{
    // CFEqual crashes if you pass it 0 so do an early check before calling it.
    if (!a.cfURLResponse() || !b.cfURLResponse())
        return a.cfURLResponse() == b.cfURLResponse();
    return CFEqual(a.cfURLResponse(), b.cfURLResponse());
}


} // namespace WebCore

#endif // USE(CFURLCONNECTION)
