/*
 * Copyright (C) 2012 Igalia S.L.
 *
 * 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 IGALIA S.L. ``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"

#if USE(SOUP)

#include "AuthenticationChallenge.h"

#include "ResourceError.h"
#include "URLSoup.h"
#include <libsoup/soup.h>

namespace WebCore {

static ProtectionSpaceServerType protectionSpaceServerTypeFromURL(const URL& url, bool isForProxy)
{
    if (url.protocolIs("https"))
        return isForProxy ? ProtectionSpaceProxyHTTPS : ProtectionSpaceServerHTTPS;
    if (url.protocolIs("http"))
        return isForProxy ? ProtectionSpaceProxyHTTP : ProtectionSpaceServerHTTP;
    if (url.protocolIs("ftp"))
        return isForProxy ? ProtectionSpaceProxyFTP : ProtectionSpaceServerFTP;
    return isForProxy ? ProtectionSpaceProxyHTTP : ProtectionSpaceServerHTTP;
}

static ProtectionSpace protectionSpaceFromSoupAuthAndURL(SoupAuth* soupAuth, const URL& url)
{
    const char* schemeName = soup_auth_get_scheme_name(soupAuth);
    ProtectionSpaceAuthenticationScheme scheme;
    if (!g_ascii_strcasecmp(schemeName, "basic"))
        scheme = ProtectionSpaceAuthenticationSchemeHTTPBasic;
    else if (!g_ascii_strcasecmp(schemeName, "digest"))
        scheme = ProtectionSpaceAuthenticationSchemeHTTPDigest;
    else if (!g_ascii_strcasecmp(schemeName, "ntlm"))
        scheme = ProtectionSpaceAuthenticationSchemeNTLM;
    else if (!g_ascii_strcasecmp(schemeName, "negotiate"))
        scheme = ProtectionSpaceAuthenticationSchemeNegotiate;
    else
        scheme = ProtectionSpaceAuthenticationSchemeUnknown;

#if USE(SOUP2)
    auto host = url.host();
    auto port = url.port();
    if (!port)
        port = defaultPortForProtocol(url.protocol());
#else
    URL authURL({ }, makeString("http://", soup_auth_get_authority(soupAuth)));
    auto host = authURL.host();
    auto port = authURL.port();
#endif

    return ProtectionSpace(host.toString(), static_cast<int>(port.value_or(0)),
        protectionSpaceServerTypeFromURL(url, soup_auth_is_for_proxy(soupAuth)),
        String::fromUTF8(soup_auth_get_realm(soupAuth)), scheme);
}

AuthenticationChallenge::AuthenticationChallenge(SoupMessage* soupMessage, SoupAuth* soupAuth, bool retrying)
    : AuthenticationChallengeBase(protectionSpaceFromSoupAuthAndURL(soupAuth, soupURIToURL(soup_message_get_uri(soupMessage)))
        , Credential() // proposedCredentials
        , retrying ? 1 : 0 // previousFailureCount
        , soupMessage // failureResponse
        , ResourceError::authenticationError(soupMessage))
#if USE(SOUP2)
    , m_soupMessage(soupMessage)
#endif
    , m_soupAuth(soupAuth)
{
}

static ProtectionSpace protectionSpaceForClientCertificate(const URL& url)
{
    auto port = url.port();
    if (!port)
        port = defaultPortForProtocol(url.protocol());
    return ProtectionSpace(url.host().toString(), static_cast<int>(port.value_or(0)), protectionSpaceServerTypeFromURL(url, false), { },
        ProtectionSpaceAuthenticationSchemeClientCertificateRequested);
}

AuthenticationChallenge::AuthenticationChallenge(SoupMessage* soupMessage, GTlsClientConnection*)
    : AuthenticationChallengeBase(protectionSpaceForClientCertificate(soupURIToURL(soup_message_get_uri(soupMessage)))
        , Credential() // proposedCredentials
        , 0 // previousFailureCount
        , soupMessage // failureResponse
        , ResourceError::authenticationError(soupMessage))
{
}

static ProtectionSpace protectionSpaceForClientCertificatePassword(GTlsPassword* tlsPassword, const URL& url)
{
    auto port = url.port();
    if (!port)
        port = defaultPortForProtocol(url.protocol());
    return ProtectionSpace(url.host().toString(), static_cast<int>(port.value_or(0)), protectionSpaceServerTypeFromURL(url, false),
        String::fromUTF8(g_tls_password_get_description(tlsPassword)), ProtectionSpaceAuthenticationSchemeClientCertificatePINRequested);
}

AuthenticationChallenge::AuthenticationChallenge(SoupMessage* soupMessage, GTlsPassword* tlsPassword)
    : AuthenticationChallengeBase(protectionSpaceForClientCertificatePassword(tlsPassword, soupURIToURL(soup_message_get_uri(soupMessage)))
        , Credential() // proposedCredentials
        , g_tls_password_get_flags(tlsPassword) & G_TLS_PASSWORD_RETRY ? 1 : 0 // previousFailureCount
        , soupMessage // failureResponse
        , ResourceError::authenticationError(soupMessage))
    , m_tlsPassword(tlsPassword)
    , m_tlsPasswordFlags(tlsPassword ? g_tls_password_get_flags(tlsPassword) : G_TLS_PASSWORD_NONE)
{
}

bool AuthenticationChallenge::platformCompare(const AuthenticationChallenge& a, const AuthenticationChallenge& b)
{
    if (a.soupAuth() != b.soupAuth())
        return false;

    if (a.tlsPassword() != b.tlsPassword())
        return false;

    if (a.tlsPasswordFlags() != b.tlsPasswordFlags())
        return false;

#if USE(SOUP2)
    return a.soupMessage() == b.soupMessage();
#endif

    return true;
}

} // namespace WebCore

#endif
