blob: c449fc68140536643d52ddd5bd5536e0b189ac23 [file] [log] [blame]
/*
* Copyright (C) 2008, 2009 Julien Chaffraix <julien.chaffraix@gmail.com>
* Copyright (C) 2011, 2012 Research In Motion Limited. 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 COMPUTER, 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 "ParsedCookie.h"
#include "CookieManager.h"
#include <wtf/CurrentTime.h>
#include "KURL.h"
#include "Logging.h"
#include <curl/curl.h>
#include <wtf/text/CString.h>
#include <wtf/text/StringBuilder.h>
namespace WebCore {
ParsedCookie::ParsedCookie(double currentTime)
: m_expiry(-1)
, m_creationTime(currentTime)
, m_lastAccessed(currentTime)
, m_isSecure(false)
, m_isHttpOnly(false)
, m_isSession(true)
, m_isForceExpired(false)
, m_domainIsIPAddress(false)
{
}
ParsedCookie::ParsedCookie(const String& name, const String& value, const String& domain, const String& protocol, const String& path, double expiry, double lastAccessed, double creationTime, bool isSecure, bool isHttpOnly)
: m_name(name)
, m_value(value)
, m_domain(domain)
, m_protocol(protocol)
, m_path(path)
, m_expiry(expiry)
, m_creationTime(creationTime)
, m_lastAccessed(lastAccessed)
, m_isSecure(isSecure)
, m_isHttpOnly(isHttpOnly)
, m_isSession(false)
, m_isForceExpired(false)
, m_domainIsIPAddress(false)
{
}
ParsedCookie::ParsedCookie(const ParsedCookie* cookie)
: m_name(String(cookie->m_name))
, m_value(String(cookie->m_value))
, m_domain(String(cookie->m_domain))
, m_protocol(String(cookie->m_protocol))
, m_path(String(cookie->m_path))
, m_expiry(cookie->m_expiry)
, m_creationTime(cookie->m_creationTime)
, m_lastAccessed(cookie->m_lastAccessed)
, m_isSecure(cookie->m_isSecure)
, m_isHttpOnly(cookie->m_isHttpOnly)
, m_isSession(cookie->m_isSession)
, m_isForceExpired(cookie->m_isForceExpired)
, m_domainIsIPAddress(cookie->m_domainIsIPAddress)
{
}
ParsedCookie::~ParsedCookie()
{
}
void ParsedCookie::setExpiry(const String& expiry)
{
// If a cookie has both the Max-Age and the Expires attribute,
// the Max-Age attribute has precedence and controls the expiration date of the cookie.
if (m_expiry != -1 || expiry.isEmpty())
return;
m_isSession = false;
m_expiry = static_cast<double>(curl_getdate(expiry.utf8().data(), 0));
if (m_expiry == -1) {
LOG_ERROR("Could not parse date");
// In this case, consider that the cookie is session only
m_isSession = true;
}
}
void ParsedCookie::setMaxAge(const String& maxAge)
{
// According to the HTTP Cookie specification (RFC6265, http://tools.ietf.org/html/rfc6265),
// the first character can be a DIGIT or a "-", and the reminder
// of the value can only contain DIGIT characters.
if (maxAge.isEmpty() || (maxAge[0] != '-' && !isASCIIDigit(maxAge[0]))) {
LOG_ERROR("Could not parse Max-Age : %s, first character can only be '-' or ascii digit.", maxAge.ascii().data());
return;
}
bool ok;
int value = maxAge.toIntStrict(&ok);
if (!ok) {
LOG_ERROR("Could not parse Max-Age : %s", maxAge.ascii().data());
return;
}
m_expiry = value;
m_isSession = false;
// If maxAge value is not positive, let expiry-time be the earliest representable time.
if (m_expiry > 0)
m_expiry += currentTime();
else
m_expiry = 0;
}
bool ParsedCookie::hasExpired() const
{
// Session cookies do not expire, they will just not be saved to the backing store.
return !m_isSession && (m_isForceExpired || m_expiry < currentTime());
}
bool ParsedCookie::isUnderSizeLimit() const
{
return m_value.length() <= CookieManager::maxCookieLength() && m_name.length() <= CookieManager::maxCookieLength();
}
String ParsedCookie::toString() const
{
StringBuilder builder;
builder.append(name());
builder.append(" = ");
builder.append(value());
builder.append("; Domain = ");
builder.append(domain());
builder.append("; Path = ");
builder.append(path());
builder.append("; Protocol = ");
builder.append(protocol());
return builder.toString();
}
String ParsedCookie::toNameValuePair() const
{
static const String equal("=");
size_t cookieLength = m_name.length() + m_value.length() + 2;
Vector<UChar> result;
result.reserveInitialCapacity(cookieLength);
append(result, m_name);
append(result, equal);
append(result, m_value);
return String::adopt(result);
}
void ParsedCookie::appendWebCoreCookie(Vector<Cookie>& cookieVector) const
{
cookieVector.append(Cookie(String(m_name), String(m_value), String(m_domain),
// We multiply m_expiry by 1000 to convert from seconds to milliseconds.
// This value is passed to Web Inspector and used in the JavaScript Date constructor.
String(m_path), (m_expiry * 1000), m_isHttpOnly, m_isSecure, m_isSession));
}
} // namespace WebCore