/*
 * Copyright (C) 2018 Sony Interactive Entertainment Inc.
 *
 * 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. AND ITS CONTRIBUTORS ``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 ITS 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 "CookieUtil.h"

#if USE(CURL)

#include "Cookie.h"

#include <wtf/DateMath.h>
#include <wtf/Optional.h>
#include <wtf/text/WTFString.h>

/* This is the maximum line length we accept for a cookie line. RFC 2109
   section 6.3 says:

   "at least 4096 bytes per cookie (as measured by the size of the characters
   that comprise the cookie non-terminal in the syntax description of the
   Set-Cookie header)"
*/

#define MAX_COOKIE_LINE 5000
#define MAX_COOKIE_LINE_TXT "4999"

#define MAX_NAME 1024
#define MAX_NAME_TXT "1023"

namespace WebCore {

namespace CookieUtil {

bool isIPAddress(const String& hostname)
{
    return URL::hostIsIPAddress(hostname);
}

bool domainMatch(const String& cookieDomain, const String& host)
{
    size_t index = host.find(cookieDomain);

    bool tailMatch = (index != WTF::notFound && index + cookieDomain.length() == host.length());

    // Check if host equals cookie domain.
    if (tailMatch && !index)
        return true;

    // Check if host is a subdomain of the domain in the cookie.
    // Curl uses a '.' in front of domains to indicate it's valid on subdomains.
    if (tailMatch && index > 0 && host[index] == '.')
        return true;

    // Check the special case where host equals the cookie domain, except for a leading '.' in the cookie domain.
    // E.g. cookie domain is .apple.com and host is apple.com.
    if (cookieDomain[0] == '.' && cookieDomain.find(host) == 1)
        return true;

    return false;
}

static std::optional<double> parseExpires(const char* expires)
{
    double tmp = WTF::parseDateFromNullTerminatedCharacters(expires);
    if (isnan(tmp))
        return { };

    return std::optional<double> {tmp / WTF::msPerSecond};
}

static void parseCookieAttributes(const String& attribute, const String& domain, bool& hasMaxAge, Cookie& result)
{
    size_t assignmentPosition = attribute.find('=');

    String attributeName;
    String attributeValue;

    if (assignmentPosition != notFound) {
        attributeName = attribute.substring(0, assignmentPosition).stripWhiteSpace();
        attributeValue = attribute.substring(assignmentPosition + 1).stripWhiteSpace();
    } else
        attributeName = attribute.stripWhiteSpace();

    if (equalIgnoringASCIICase(attributeName, "httponly"))
        result.httpOnly = true;
    else if (equalIgnoringASCIICase(attributeName, "secure"))
        result.secure = true;
    else if (equalIgnoringASCIICase(attributeName, "domain")) {
        if (attributeValue.isEmpty())
            return;

        // Enforce a dot character prefix to hostnames which are not ip addresses and not single value hostnames such as localhost
        if (!isIPAddress(attributeValue) && !attributeValue.startsWith('.') && attributeValue.find('.') != notFound)
            attributeValue = "." + attributeValue;

        // Make sure the host can set a cookie for the domain
        // FIXME: firefox and chrome both ignore cookies with no valid domain set
        // we currently ignore the invalid domains and default to the hostname as the domain
        if (domainMatch(attributeValue, domain))
            result.domain = attributeValue;

    } else if (equalIgnoringASCIICase(attributeName, "max-age")) {
        bool ok;
        time_t expiryTime = time(0) + attributeValue.toInt64(&ok);
        if (ok) {
            result.expires = (double)expiryTime;
            result.session = false;

            // If there is a max-age attribute as well as an expires attribute
            // the rightmost max-age attribute takes precedence.
            hasMaxAge = true;
        }
    } else if (equalIgnoringASCIICase(attributeName, "expires") && !hasMaxAge) {
        if (auto expiryTime = parseExpires(attributeValue.utf8().data())) {
            result.expires = expiryTime.value();
            result.session = false;
        }
    } else if (equalIgnoringASCIICase(attributeName, "path")) {
        if (!attributeValue.isEmpty() && attributeValue.startsWith('/'))
            result.path = attributeValue;
    }
}

bool parseCookieHeader(const String& cookieLine, const String& domain, Cookie& result)
{
    if (cookieLine.length() >= MAX_COOKIE_LINE)
        return false;

    // This Algorithm is based on the algorithm defined in RFC 6265 5.2 https://tools.ietf.org/html/rfc6265#section-5.2/

    size_t separatorPosition = cookieLine.find(';');

    String cookiePair = separatorPosition == notFound ? cookieLine : cookieLine.substring(0, separatorPosition);

    String cookieName;
    String cookieValue;
    size_t assignmentPosition = cookieLine.find('=');

    // RFC6265 says to ignore cookies pairs with empty names or no assignment character
    // but browsers seem to treat this type of cookie string as the cookie value
    if (assignmentPosition == notFound)
        cookieValue = cookiePair;
    else {
        cookieName = cookiePair.substring(0, assignmentPosition);
        cookieValue = cookiePair.substring(assignmentPosition + 1);
    }

    result.name = cookieName.stripWhiteSpace();
    result.value = cookieValue.stripWhiteSpace();

    bool hasMaxAge = false;
    result.session = true;

    Vector<String> cookieAttributes;
    cookieLine.split(';', true, cookieAttributes);
    for (auto attribute : cookieAttributes)
        parseCookieAttributes(attribute, domain, hasMaxAge, result);

    return true;
}

} // namespace CookieUtil

} // namespace WebCore

#endif
