/*
 * Copyright (C) 2010 Google 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
 * OWNER 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.
 */

// Ideally, we would rely on platform support for parsing a cookie, since
// this would save us from any potential inconsistency. However, exposing
// platform cookie parsing logic would require quite a bit of additional
// plumbing, and at least some platforms lack support for parsing Cookie,
// which is in a format slightly different from Set-Cookie and is normally
// only required on the server side.

/**
 * @constructor
 */
WebInspector.CookieParser = function()
{
}

/**
 * @constructor
 * @param {string} key
 * @param {string|undefined} value
 * @param {number} position
 */
WebInspector.CookieParser.KeyValue = function(key, value, position)
{
    this.key = key;
    this.value = value;
    this.position = position;
}

WebInspector.CookieParser.prototype = {
    /**
     * @return {Array.<WebInspector.Cookie>}
     */
    cookies: function()
    {
        return this._cookies;
    },

    /**
     * @param {string|undefined} cookieHeader
     * @return {?Array.<WebInspector.Cookie>}
     */
    parseCookie: function(cookieHeader)
    {
        if (!this._initialize(cookieHeader))
            return null;

        for (var kv = this._extractKeyValue(); kv; kv = this._extractKeyValue()) {
            if (kv.key.charAt(0) === "$" && this._lastCookie)
                this._lastCookie.addAttribute(kv.key.slice(1), kv.value);
            else if (kv.key.toLowerCase() !== "$version" && typeof kv.value === "string")
                this._addCookie(kv, WebInspector.Cookie.Type.Request);
            this._advanceAndCheckCookieDelimiter();
        }
        this._flushCookie();
        return this._cookies;
    },

    /**
     * @param {string|undefined} setCookieHeader
     * @return {?Array.<WebInspector.Cookie>}
     */
    parseSetCookie: function(setCookieHeader)
    {
        if (!this._initialize(setCookieHeader))
            return null;
        for (var kv = this._extractKeyValue(); kv; kv = this._extractKeyValue()) {
            if (this._lastCookie)
                this._lastCookie.addAttribute(kv.key, kv.value);
            else
                this._addCookie(kv, WebInspector.Cookie.Type.Response);
            if (this._advanceAndCheckCookieDelimiter())
                this._flushCookie();
        }
        this._flushCookie();
        return this._cookies;
    },

    /**
     * @param {string|undefined} headerValue
     * @return {boolean}
     */
    _initialize: function(headerValue)
    {
        this._input = headerValue;
        if (typeof headerValue !== "string")
            return false;
        this._cookies = [];
        this._lastCookie = null;
        this._originalInputLength = this._input.length;
        return true;
    },

    _flushCookie: function()
    {
        if (this._lastCookie)
            this._lastCookie.setSize(this._originalInputLength - this._input.length - this._lastCookiePosition);
        this._lastCookie = null;
    },

    /**
     * @return {WebInspector.CookieParser.KeyValue}
     */
    _extractKeyValue: function()
    {
        if (!this._input || !this._input.length)
            return null;
        // Note: RFCs offer an option for quoted values that may contain commas and semicolons.
        // Many browsers/platforms do not support this, however (see http://webkit.org/b/16699
        // and http://crbug.com/12361). The logic below matches latest versions of IE, Firefox,
        // Chrome and Safari on some old platforms. The latest version of Safari supports quoted
        // cookie values, though.
        var keyValueMatch = /^[ \t]*([^\s=;]+)[ \t]*(?:=[ \t]*([^;\n]*))?/.exec(this._input);
        if (!keyValueMatch) {
            console.log("Failed parsing cookie header before: " + this._input);
            return null;
        }

        var result = new WebInspector.CookieParser.KeyValue(keyValueMatch[1], keyValueMatch[2] && keyValueMatch[2].trim(), this._originalInputLength - this._input.length);
        this._input = this._input.slice(keyValueMatch[0].length);
        return result;
    },

    /**
     * @return {boolean}
     */
    _advanceAndCheckCookieDelimiter: function()
    {
        var match = /^\s*[\n;]\s*/.exec(this._input);
        if (!match)
            return false;
        this._input = this._input.slice(match[0].length);
        return match[0].match("\n") !== null;
    },

    /**
     * @param {!WebInspector.CookieParser.KeyValue} keyValue
     * @param {!WebInspector.Cookie.Type} type
     */
    _addCookie: function(keyValue, type)
    {
        if (this._lastCookie)
            this._lastCookie.setSize(keyValue.position - this._lastCookiePosition);
        // Mozilla bug 169091: Mozilla, IE and Chrome treat single token (w/o "=") as
        // specifying a value for a cookie with empty name.
        this._lastCookie = typeof keyValue.value === "string" ? new WebInspector.Cookie(keyValue.key, keyValue.value, type) :
            new WebInspector.Cookie("", keyValue.key, type);
        this._lastCookiePosition = keyValue.position;
        this._cookies.push(this._lastCookie);
    }
};

/**
 * @param {string|undefined} header
 * @return {?Array.<WebInspector.Cookie>}
 */
WebInspector.CookieParser.parseCookie = function(header)
{
    return (new WebInspector.CookieParser()).parseCookie(header);
}

/**
 * @param {string|undefined} header
 * @return {?Array.<WebInspector.Cookie>}
 */
WebInspector.CookieParser.parseSetCookie = function(header)
{
    return (new WebInspector.CookieParser()).parseSetCookie(header);
}

/**
 * @constructor
 * @param {string} name
 * @param {string} value
 * @param {?WebInspector.Cookie.Type} type
 */
WebInspector.Cookie = function(name, value, type)
{
    this._name = name;
    this._value = value;
    this._type = type;
    this._attributes = {};
}

WebInspector.Cookie.prototype = {
    /**
     * @return {string}
     */
    name: function()
    {
        return this._name;
    },

    /**
     * @return {string}
     */
    value: function()
    {
        return this._value;
    },

    /**
     * @return {?WebInspector.Cookie.Type}
     */
    type: function()
    {
        return this._type;
    },

    /**
     * @return {boolean}
     */
    httpOnly: function()
    {
        return "httponly" in this._attributes;
    },

    /**
     * @return {boolean}
     */
    secure: function()
    {
        return "secure" in this._attributes;
    },

    /**
     * @return {boolean}
     */
    session: function()
    {
        // RFC 2965 suggests using Discard attribute to mark session cookies, but this does not seem to be widely used.
        // Check for absence of explicitly max-age or expiry date instead.
        return !("expires" in this._attributes || "max-age" in this._attributes);
    },

    /**
     * @return {string}
     */
    path: function()
    {
        return this._attributes["path"];
    },

    /**
     * @return {string}
     */
    port: function()
    {
        return this._attributes["port"];
    },

    /**
     * @return {string}
     */
    domain: function()
    {
        return this._attributes["domain"];
    },

    /**
     * @return {string}
     */
    expires: function()
    {
        return this._attributes["expires"];
    },

    /**
     * @return {string}
     */
    maxAge: function()
    {
        return this._attributes["max-age"];
    },

    /**
     * @return {number}
     */
    size: function()
    {
        return this._size;
    },

    /**
     * @param {number} size
     */
    setSize: function(size)
    {
        this._size = size;
    },

    /**
     * @return {Date}
     */
    expiresDate: function(requestDate)
    {
        // RFC 6265 indicates that the max-age attribute takes precedence over the expires attribute
        if (this.maxAge()) {
            var targetDate = requestDate === null ? new Date() : requestDate;
            return new Date(targetDate.getTime() + 1000 * this.maxAge());
        }

        if (this.expires())
            return new Date(this.expires());

        return null;
    },

    /**
     * @return {Object}
     */
    attributes: function()
    {
        return this._attributes;
    },

    /**
     * @param {string} key 
     * @param {string=} value 
     */
    addAttribute: function(key, value)
    {
        this._attributes[key.toLowerCase()] = value;
    },

    /**
     * @param {function(?Protocol.Error)=} callback
     */
    remove: function(callback)
    {
        PageAgent.deleteCookie(this.name(), (this.secure() ? "https://" : "http://") + this.domain() + this.path(), callback);
    }
}

/**
 * @enum {number}
 */
WebInspector.Cookie.Type = {
    Request: 0,
    Response: 1
};

WebInspector.Cookies = {}

/**
 * @param {function(!Array.<!WebInspector.Cookie>)} callback
 */
WebInspector.Cookies.getCookiesAsync = function(callback)
{
    /**
     * @param {?Protocol.Error} error 
     * @param {Array.<PageAgent.Cookie>} cookies
     * @param {string} cookiesString
     */
    function mycallback(error, cookies, cookiesString)
    {
        if (error)
            return;
        callback(cookies.map(WebInspector.Cookies.buildCookieProtocolObject));
    }

    PageAgent.getCookies(mycallback);
}

/**
 * @param {!PageAgent.Cookie} protocolCookie
 * @return {!WebInspector.Cookie}
 */
WebInspector.Cookies.buildCookieProtocolObject = function(protocolCookie)
{
    var cookie = new WebInspector.Cookie(protocolCookie.name, protocolCookie.value, null);
    cookie.addAttribute("domain", protocolCookie["domain"]);
    cookie.addAttribute("path", protocolCookie["path"]);
    cookie.addAttribute("port", protocolCookie["port"]);
    if (protocolCookie["expires"])
        cookie.addAttribute("expires", protocolCookie["expires"]);
    if (protocolCookie["httpOnly"])
        cookie.addAttribute("httpOnly");
    if (protocolCookie["secure"])
        cookie.addAttribute("secure");
    cookie.setSize(protocolCookie["size"]);
    return cookie;
}

/**
 * @param {WebInspector.Cookie} cookie 
 * @param {string} resourceURL
 */
WebInspector.Cookies.cookieMatchesResourceURL = function(cookie, resourceURL)
{
    var url = resourceURL.asParsedURL();
    if (!url || !WebInspector.Cookies.cookieDomainMatchesResourceDomain(cookie.domain(), url.host))
        return false;
    return (url.path.startsWith(cookie.path())
        && (!cookie.port() || url.port == cookie.port())
        && (!cookie.secure() || url.scheme === "https"));
}

/**
 * @param {string} cookieDomain 
 * @param {string} resourceDomain
 */
WebInspector.Cookies.cookieDomainMatchesResourceDomain = function(cookieDomain, resourceDomain)
{
    if (cookieDomain.charAt(0) !== '.')
        return resourceDomain === cookieDomain;
    return !!resourceDomain.match(new RegExp("^([^\\.]+\\.)*" + cookieDomain.substring(1).escapeForRegExp() + "$", "i"));
}
