Diff
Modified: trunk/Source/WebCore/ChangeLog (227986 => 227987)
--- trunk/Source/WebCore/ChangeLog 2018-02-01 23:42:47 UTC (rev 227986)
+++ trunk/Source/WebCore/ChangeLog 2018-02-02 00:08:41 UTC (rev 227987)
@@ -1,3 +1,33 @@
+2018-02-01 Christopher Reid <[email protected]>
+
+ [Curl] Use SQLite database in cookie jar implementation for Curl port
+ https://bugs.webkit.org/show_bug.cgi?id=174942
+
+ Reviewed by Alex Christensen.
+
+ No new tests, Set-Cookie is already tested in Layout tests.
+
+ Adding an initial SQLite CookieJar implementation to the curl network layer.
+ WebCore will now parse and handle both HTTP and DOM cookies instead of using libcurl.
+ This currently supports cookie storage and retrieval.
+ Cookie deletion is not yet implemented.
+
+ * platform/Curl.cmake:
+ * platform/network/NetworkStorageSession.h: Added cookieDB storage in curl.
+ * platform/network/curl/CookieJarCurl.cpp: Removed the old curl cookie handling.
+ * platform/network/curl/CookieJarCurl.h:
+ * platform/network/curl/CookieJarCurlDatabase.cpp: Added.
+ * platform/network/curl/CookieJarCurlDatabase.h: Added.
+ * platform/network/curl/CookieJarDB.cpp: Added.
+ * platform/network/curl/CookieJarDB.h: Added.
+ * platform/network/curl/CookieUtil.cpp: Added.
+ * platform/network/curl/CookieUtil.h: Added.
+ * platform/network/curl/CurlContext.cpp: Removed the old curl cookie handling.
+ * platform/network/curl/CurlContext.h:
+ * platform/network/curl/CurlRequest.cpp: Added handlers for HTTP response cookies.
+ * platform/network/curl/NetworkStorageSessionCurl.cpp:
+ * platform/network/curl/ResourceHandleCurlDelegate.cpp:
+
2018-02-01 Chris Dumez <[email protected]>
Add missing RETURN_IF_EXCEPTION() after object->get() calls in convertDictionary<>()
Modified: trunk/Source/WebCore/platform/Curl.cmake (227986 => 227987)
--- trunk/Source/WebCore/platform/Curl.cmake 2018-02-01 23:42:47 UTC (rev 227986)
+++ trunk/Source/WebCore/platform/Curl.cmake 2018-02-02 00:08:41 UTC (rev 227987)
@@ -5,7 +5,10 @@
list(APPEND WebCore_SOURCES
platform/network/curl/AuthenticationChallengeCurl.cpp
platform/network/curl/CookieJarCurl.cpp
+ platform/network/curl/CookieJarCurlDatabase.cpp
+ platform/network/curl/CookieJarDB.cpp
platform/network/curl/CookieStorageCurl.cpp
+ platform/network/curl/CookieUtil.cpp
platform/network/curl/CredentialStorageCurl.cpp
platform/network/curl/CurlCacheEntry.cpp
platform/network/curl/CurlCacheManager.cpp
Modified: trunk/Source/WebCore/platform/network/NetworkStorageSession.h (227986 => 227987)
--- trunk/Source/WebCore/platform/network/NetworkStorageSession.h 2018-02-01 23:42:47 UTC (rev 227986)
+++ trunk/Source/WebCore/platform/network/NetworkStorageSession.h 2018-02-02 00:08:41 UTC (rev 227987)
@@ -43,6 +43,12 @@
typedef struct _SoupCookieJar SoupCookieJar;
#endif
+#if USE(CURL)
+#include "CookieJarCurl.h"
+#include "CookieJarDB.h"
+#include <wtf/UniqueRef.h>
+#endif
+
#ifdef __OBJC__
#include <objc/objc.h>
#endif
@@ -116,6 +122,14 @@
void setCookieObserverHandler(Function<void ()>&&);
void getCredentialFromPersistentStorage(const ProtectionSpace&, Function<void (Credential&&)> completionHandler);
void saveCredentialToPersistentStorage(const ProtectionSpace&, const Credential&);
+#elif USE(CURL)
+ NetworkStorageSession(PAL::SessionID, NetworkingContext*);
+ ~NetworkStorageSession();
+
+ const CookieJarCurl& cookieStorage() const { return m_cookieStorage; };
+ CookieJarDB& cookieDatabase() const { return m_cookieDatabase; };
+
+ NetworkingContext* context() const;
#else
NetworkStorageSession(PAL::SessionID, NetworkingContext*);
~NetworkStorageSession();
@@ -147,6 +161,11 @@
Function<void (Credential&&)> m_persisentStorageCompletionHandler;
GRefPtr<GCancellable> m_persisentStorageCancellable;
#endif
+#elif USE(CURL)
+ UniqueRef<CookieJarCurl> m_cookieStorage;
+ mutable CookieJarDB m_cookieDatabase;
+
+ RefPtr<NetworkingContext> m_context;
#else
RefPtr<NetworkingContext> m_context;
#endif
Modified: trunk/Source/WebCore/platform/network/curl/CookieJarCurl.cpp (227986 => 227987)
--- trunk/Source/WebCore/platform/network/curl/CookieJarCurl.cpp 2018-02-01 23:42:47 UTC (rev 227986)
+++ trunk/Source/WebCore/platform/network/curl/CookieJarCurl.cpp 2018-02-02 00:08:41 UTC (rev 227987)
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2018 Sony Interactive Entertainment Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -21,379 +22,61 @@
#if USE(CURL)
#include "Cookie.h"
-#include "CurlContext.h"
-#include "NotImplemented.h"
+#include "NetworkStorageSession.h"
#include "URL.h"
-#include <wtf/DateMath.h>
-#include <wtf/HashMap.h>
-#include <wtf/text/StringBuilder.h>
-#include <wtf/text/StringHash.h>
#include <wtf/text/WTFString.h>
namespace WebCore {
-static void readCurlCookieToken(const char*& cookie, String& token)
-{
- // Read the next token from a cookie with the Netscape cookie format.
- // Curl separates each token in line with tab character.
- const char* cookieStart = cookie;
- while (cookie && cookie[0] && cookie[0] != '\t')
- cookie++;
- token = String(cookieStart, cookie - cookieStart);
- if (cookie[0] == '\t')
- cookie++;
-}
-
-static 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 void addMatchingCurlCookie(const char* cookie, const String& domain, const String& path, StringBuilder& cookies, bool httponly)
-{
- // Check if the cookie matches domain and path, and is not expired.
- // If so, add it to the list of cookies.
- //
- // Description of the Netscape cookie file format which Curl uses:
- //
- // .netscape.com TRUE / FALSE 946684799 NETSCAPE_ID 100103
- //
- // Each line represents a single piece of stored information. A tab is inserted between each of the fields.
- //
- // From left-to-right, here is what each field represents:
- //
- // domain - The domain that created AND that can read the variable.
- // flag - A TRUE/FALSE value indicating if all machines within a given domain can access the variable. This value is set automatically by the browser, depending on the value you set for domain.
- // path - The path within the domain that the variable is valid for.
- // secure - A TRUE/FALSE value indicating if a secure connection with the domain is needed to access the variable.
- // expiration - The UNIX time that the variable will expire on. UNIX time is defined as the number of seconds since Jan 1, 1970 00:00:00 GMT.
- // name - The name of the variable.
- // value - The value of the variable.
-
- if (!cookie)
- return;
-
- String cookieDomain;
- readCurlCookieToken(cookie, cookieDomain);
-
- // HttpOnly cookie entries begin with "#HttpOnly_".
- if (cookieDomain.startsWith("#HttpOnly_")) {
- if (httponly)
- cookieDomain.remove(0, 10);
- else
- return;
- }
-
- if (!domainMatch(cookieDomain, domain))
- return;
-
- String strBoolean;
- readCurlCookieToken(cookie, strBoolean);
-
- String strPath;
- readCurlCookieToken(cookie, strPath);
-
- // Check if path matches
- int index = path.find(strPath);
- if (index)
- return;
-
- String strSecure;
- readCurlCookieToken(cookie, strSecure);
-
- String strExpires;
- readCurlCookieToken(cookie, strExpires);
-
- int expires = strExpires.toInt();
-
- time_t now = 0;
- time(&now);
-
- // Check if cookie has expired
- if (expires && now > expires)
- return;
-
- String strName;
- readCurlCookieToken(cookie, strName);
-
- String strValue;
- readCurlCookieToken(cookie, strValue);
-
- // The cookie matches, add it to the cookie list.
-
- if (cookies.length() > 0)
- cookies.append("; ");
-
- cookies.append(strName);
- cookies.append("=");
- cookies.append(strValue);
-
-}
-
-static String getNetscapeCookieFormat(const URL& url, const String& value)
-{
- // Constructs a cookie string in Netscape Cookie file format.
-
- if (value.isEmpty())
- return "";
-
- String valueStr;
- if (value.is8Bit())
- valueStr = value;
- else
- valueStr = String::make8BitFrom16BitSource(value.characters16(), value.length());
-
- Vector<String> attributes;
- valueStr.split(';', false, attributes);
-
- if (!attributes.size())
- return "";
-
- // First attribute should be <cookiename>=<cookievalue>
- String cookieName, cookieValue;
- Vector<String>::iterator attribute = attributes.begin();
- if (attribute->contains('=')) {
- Vector<String> nameValuePair;
- attribute->split('=', true, nameValuePair);
- cookieName = nameValuePair[0];
- cookieValue = nameValuePair[1];
- } else {
- // According to RFC6265 we should ignore the entire
- // set-cookie string now, but other browsers appear
- // to treat this as <cookiename>=<empty>
- cookieName = *attribute;
- }
-
- int expires = 0;
- String secure = "FALSE";
- String path = url.baseAsString().substring(url.pathStart());
- if (path.length() > 1 && path.endsWith('/'))
- path.remove(path.length() - 1);
- String domain = url.host();
-
- // Iterate through remaining attributes
- for (++attribute; attribute != attributes.end(); ++attribute) {
- if (attribute->contains('=')) {
- Vector<String> keyValuePair;
- attribute->split('=', true, keyValuePair);
- String key = keyValuePair[0].stripWhiteSpace();
- String val = keyValuePair[1].stripWhiteSpace();
- if (equalLettersIgnoringASCIICase(key, "expires")) {
- CString dateStr(reinterpret_cast<const char*>(val.characters8()), val.length());
- expires = WTF::parseDateFromNullTerminatedCharacters(dateStr.data()) / WTF::msPerSecond;
- } else if (equalLettersIgnoringASCIICase(key, "max-age"))
- expires = time(0) + val.toInt();
- else if (equalLettersIgnoringASCIICase(key, "domain"))
- domain = val;
- else if (equalLettersIgnoringASCIICase(key, "path"))
- path = val;
- } else {
- String key = attribute->stripWhiteSpace();
- if (equalLettersIgnoringASCIICase(key, "secure"))
- secure = "TRUE";
- }
- }
-
- String allowSubdomains = domain.startsWith('.') ? "TRUE" : "FALSE";
- String expiresStr = String::number(expires);
-
- int finalStringLength = domain.length() + path.length() + expiresStr.length() + cookieName.length();
- finalStringLength += cookieValue.length() + secure.length() + allowSubdomains.length();
- finalStringLength += 6; // Account for \t separators.
-
- StringBuilder cookieStr;
- cookieStr.reserveCapacity(finalStringLength);
- cookieStr.append(domain);
- cookieStr.append("\t");
- cookieStr.append(allowSubdomains);
- cookieStr.append("\t");
- cookieStr.append(path);
- cookieStr.append("\t");
- cookieStr.append(secure);
- cookieStr.append("\t");
- cookieStr.append(expiresStr);
- cookieStr.append("\t");
- cookieStr.append(cookieName);
- cookieStr.append("\t");
- cookieStr.append(cookieValue);
-
- return cookieStr.toString();
-}
-
-void CookieJarCurlFileSystem::setCookiesFromDOM(const NetworkStorageSession&, const URL& firstParty, const URL& url, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, const String& value)
-{
- UNUSED_PARAM(frameID);
- UNUSED_PARAM(pageID);
- CurlHandle curlHandle;
-
- curlHandle.enableShareHandle();
- curlHandle.enableCookieJarIfExists();
-
- // CURL accepts cookies in either Set-Cookie or Netscape file format.
- // However with Set-Cookie format, there is no way to specify that we
- // should not allow cookies to be read from subdomains, which is the
- // required behavior if the domain field is not explicity specified.
- String cookie = getNetscapeCookieFormat(url, value);
-
- if (!cookie.is8Bit())
- cookie = String::make8BitFrom16BitSource(cookie.characters16(), cookie.length());
-
- CString strCookie(reinterpret_cast<const char*>(cookie.characters8()), cookie.length());
-
- curlHandle.setCookieList(strCookie.data());
-}
-
-static String cookiesForSession(const NetworkStorageSession&, const URL&, const URL& url, bool httponly)
-{
- String cookies;
-
- CurlHandle curlHandle;
- curlHandle.enableShareHandle();
-
- CurlSList cookieList;
- curlHandle.fetchCookieList(cookieList);
- const struct curl_slist* list = cookieList.head();
- if (list) {
- String domain = url.host();
- String path = url.path();
- StringBuilder cookiesBuilder;
-
- while (list) {
- const char* cookie = list->data;
- addMatchingCurlCookie(cookie, domain, path, cookiesBuilder, httponly);
- list = list->next;
- }
-
- cookies = cookiesBuilder.toString();
- }
-
- return cookies;
-}
-
-std::pair<String, bool> CookieJarCurlFileSystem::cookiesForDOM(const NetworkStorageSession& session, const URL& firstParty, const URL& url, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, IncludeSecureCookies)
-{
- UNUSED_PARAM(frameID);
- UNUSED_PARAM(pageID);
- // FIXME: This should filter secure cookies out if the caller requests it.
- return { cookiesForSession(session, firstParty, url, false), false };
-}
-
-std::pair<String, bool> CookieJarCurlFileSystem::cookieRequestHeaderFieldValue(const NetworkStorageSession& session, const URL& firstParty, const URL& url, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, IncludeSecureCookies)
-{
- UNUSED_PARAM(frameID);
- UNUSED_PARAM(pageID);
- // FIXME: This should filter secure cookies out if the caller requests it.
- return { cookiesForSession(session, firstParty, url, true), false };
-}
-
-bool CookieJarCurlFileSystem::cookiesEnabled(const NetworkStorageSession&)
-{
- return true;
-}
-
-bool CookieJarCurlFileSystem::getRawCookies(const NetworkStorageSession&, const URL& firstParty, const URL&, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, Vector<Cookie>& rawCookies)
-{
- UNUSED_PARAM(frameID);
- UNUSED_PARAM(pageID);
- // FIXME: Not yet implemented
- rawCookies.clear();
- return false; // return true when implemented
-}
-
-void CookieJarCurlFileSystem::deleteCookie(const NetworkStorageSession&, const URL&, const String&)
-{
- // FIXME: Not yet implemented
-}
-
-void CookieJarCurlFileSystem::getHostnamesWithCookies(const NetworkStorageSession&, HashSet<String>& hostnames)
-{
- // FIXME: Not yet implemented
-}
-
-void CookieJarCurlFileSystem::deleteCookiesForHostnames(const NetworkStorageSession&, const Vector<String>& cookieHostNames)
-{
- // FIXME: Not yet implemented
-}
-
-void CookieJarCurlFileSystem::deleteAllCookies(const NetworkStorageSession&)
-{
- // FIXME: Not yet implemented
-}
-
-void CookieJarCurlFileSystem::deleteAllCookiesModifiedSince(const NetworkStorageSession&, WallTime)
-{
- // FIXME: Not yet implemented
-}
-
-// dispatcher functions
-
std::pair<String, bool> cookiesForDOM(const NetworkStorageSession& session, const URL& firstParty, const URL& url, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, IncludeSecureCookies includeSecureCookies)
{
- return CurlContext::singleton().cookieJar().cookiesForDOM(session, firstParty, url, frameID, pageID, includeSecureCookies);
+ return session.cookieStorage().cookiesForDOM(session, firstParty, url, frameID, pageID, includeSecureCookies);
}
void setCookiesFromDOM(const NetworkStorageSession& session, const URL& firstParty, const URL& url, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, const String& value)
{
- CurlContext::singleton().cookieJar().setCookiesFromDOM(session, firstParty, url, frameID, pageID, value);
+ session.cookieStorage().setCookiesFromDOM(session, firstParty, url, frameID, pageID, value);
}
std::pair<String, bool> cookieRequestHeaderFieldValue(const NetworkStorageSession& session, const URL& firstParty, const URL& url, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, IncludeSecureCookies includeSecureCookies)
{
- return CurlContext::singleton().cookieJar().cookieRequestHeaderFieldValue(session, firstParty, url, frameID, pageID, includeSecureCookies);
+ return session.cookieStorage().cookieRequestHeaderFieldValue(session, firstParty, url, frameID, pageID, includeSecureCookies);
}
bool cookiesEnabled(const NetworkStorageSession& session)
{
- return CurlContext::singleton().cookieJar().cookiesEnabled(session);
+ return session.cookieStorage().cookiesEnabled(session);
}
bool getRawCookies(const NetworkStorageSession& session, const URL& firstParty, const URL& url, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, Vector<Cookie>& rawCookies)
{
- return CurlContext::singleton().cookieJar().getRawCookies(session, firstParty, url, frameID, pageID, rawCookies);
+ return session.cookieStorage().getRawCookies(session, firstParty, url, frameID, pageID, rawCookies);
}
void deleteCookie(const NetworkStorageSession& session, const URL& url, const String& cookie)
{
- CurlContext::singleton().cookieJar().deleteCookie(session, url, cookie);
+ session.cookieStorage().deleteCookie(session, url, cookie);
}
void getHostnamesWithCookies(const NetworkStorageSession& session, HashSet<String>& hostnames)
{
- CurlContext::singleton().cookieJar().getHostnamesWithCookies(session, hostnames);
+ session.cookieStorage().getHostnamesWithCookies(session, hostnames);
}
void deleteCookiesForHostnames(const NetworkStorageSession& session, const Vector<String>& cookieHostNames)
{
- CurlContext::singleton().cookieJar().deleteCookiesForHostnames(session, cookieHostNames);
+ session.cookieStorage().deleteCookiesForHostnames(session, cookieHostNames);
}
void deleteAllCookies(const NetworkStorageSession& session)
{
- CurlContext::singleton().cookieJar().deleteAllCookies(session);
+ session.cookieStorage().deleteAllCookies(session);
}
void deleteAllCookiesModifiedSince(const NetworkStorageSession& session, WallTime since)
{
- CurlContext::singleton().cookieJar().deleteAllCookiesModifiedSince(session, since);
+ session.cookieStorage().deleteAllCookiesModifiedSince(session, since);
}
}
Modified: trunk/Source/WebCore/platform/network/curl/CookieJarCurl.h (227986 => 227987)
--- trunk/Source/WebCore/platform/network/curl/CookieJarCurl.h 2018-02-01 23:42:47 UTC (rev 227986)
+++ trunk/Source/WebCore/platform/network/curl/CookieJarCurl.h 2018-02-02 00:08:41 UTC (rev 227987)
@@ -28,29 +28,17 @@
class CookieJarCurl {
public:
- virtual std::pair<String, bool> cookiesForDOM(const NetworkStorageSession&, const URL& firstParty, const URL&, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, IncludeSecureCookies) = 0;
- virtual void setCookiesFromDOM(const NetworkStorageSession&, const URL& firstParty, const URL&, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, const String&) = 0;
- virtual bool cookiesEnabled(const NetworkStorageSession&) = 0;
- virtual std::pair<String, bool> cookieRequestHeaderFieldValue(const NetworkStorageSession&, const URL& firstParty, const URL&, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, IncludeSecureCookies) = 0;
- virtual bool getRawCookies(const NetworkStorageSession&, const URL& firstParty, const URL&, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, Vector<Cookie>&) = 0;
- virtual void deleteCookie(const NetworkStorageSession&, const URL&, const String&) = 0;
- virtual void getHostnamesWithCookies(const NetworkStorageSession&, HashSet<String>& hostnames) = 0;
- virtual void deleteCookiesForHostnames(const NetworkStorageSession&, const Vector<String>& cookieHostNames) = 0;
- virtual void deleteAllCookies(const NetworkStorageSession&) = 0;
- virtual void deleteAllCookiesModifiedSince(const NetworkStorageSession&, WallTime) = 0;
+ virtual std::pair<String, bool> cookiesForDOM(const NetworkStorageSession&, const URL& firstParty, const URL&, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, IncludeSecureCookies) const = 0;
+ virtual void setCookiesFromDOM(const NetworkStorageSession&, const URL& firstParty, const URL&, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, const String&) const = 0;
+ virtual void setCookiesFromHTTPResponse(const NetworkStorageSession&, const URL&, const String&) const = 0;
+ virtual bool cookiesEnabled(const NetworkStorageSession&) const = 0;
+ virtual std::pair<String, bool> cookieRequestHeaderFieldValue(const NetworkStorageSession&, const URL& firstParty, const URL&, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, IncludeSecureCookies) const = 0;
+ virtual bool getRawCookies(const NetworkStorageSession&, const URL& firstParty, const URL&, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, Vector<Cookie>&) const = 0;
+ virtual void deleteCookie(const NetworkStorageSession&, const URL&, const String&) const = 0;
+ virtual void getHostnamesWithCookies(const NetworkStorageSession&, HashSet<String>& hostnames) const = 0;
+ virtual void deleteCookiesForHostnames(const NetworkStorageSession&, const Vector<String>& cookieHostNames) const = 0;
+ virtual void deleteAllCookies(const NetworkStorageSession&) const = 0;
+ virtual void deleteAllCookiesModifiedSince(const NetworkStorageSession&, WallTime) const = 0;
};
-class CookieJarCurlFileSystem : public CookieJarCurl {
- std::pair<String, bool> cookiesForDOM(const NetworkStorageSession&, const URL& firstParty, const URL&, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, IncludeSecureCookies) override;
- void setCookiesFromDOM(const NetworkStorageSession&, const URL& firstParty, const URL&, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, const String&) override;
- bool cookiesEnabled(const NetworkStorageSession&) override;
- std::pair<String, bool> cookieRequestHeaderFieldValue(const NetworkStorageSession&, const URL& firstParty, const URL&, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, IncludeSecureCookies) override;
- bool getRawCookies(const NetworkStorageSession&, const URL& firstParty, const URL&, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, Vector<Cookie>&) override;
- void deleteCookie(const NetworkStorageSession&, const URL&, const String&) override;
- void getHostnamesWithCookies(const NetworkStorageSession&, HashSet<String>& hostnames) override;
- void deleteCookiesForHostnames(const NetworkStorageSession&, const Vector<String>& cookieHostNames) override;
- void deleteAllCookies(const NetworkStorageSession&) override;
- void deleteAllCookiesModifiedSince(const NetworkStorageSession&, WallTime) override;
-};
-
} // namespace WebCore
Added: trunk/Source/WebCore/platform/network/curl/CookieJarCurlDatabase.cpp (0 => 227987)
--- trunk/Source/WebCore/platform/network/curl/CookieJarCurlDatabase.cpp (rev 0)
+++ trunk/Source/WebCore/platform/network/curl/CookieJarCurlDatabase.cpp 2018-02-02 00:08:41 UTC (rev 227987)
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "config.h"
+#include "CookieJarCurlDatabase.h"
+
+#if USE(CURL)
+#include "Cookie.h"
+#include "CookieJarDB.h"
+#include "NetworkStorageSession.h"
+#include "NotImplemented.h"
+#include "URL.h"
+
+#include <wtf/Optional.h>
+#include <wtf/text/StringBuilder.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+static String cookiesForSession(const NetworkStorageSession& session, const URL&, const URL& url, bool httponly)
+{
+ StringBuilder cookies;
+
+ CookieJarDB& cookieJarDB = session.cookieDatabase();
+ auto isHttpOnly = (httponly ? std::nullopt : std::optional<bool> {false});
+ auto secure = url.protocolIs("https") ? std::nullopt : std::optional<bool> {false};
+
+ Vector<Cookie> results;
+ if (cookieJarDB.searchCookies(url.string(), isHttpOnly, secure, std::nullopt, results)) {
+ for (auto result : results) {
+ if (!cookies.isEmpty())
+ cookies.append("; ");
+ cookies.append(result.name);
+ cookies.append("=");
+ cookies.append(result.value);
+ }
+ }
+ return cookies.toString();
+}
+
+void CookieJarCurlDatabase::setCookiesFromDOM(const NetworkStorageSession& session, const URL& firstParty, const URL& url, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, const String& value) const
+{
+ UNUSED_PARAM(frameID);
+ UNUSED_PARAM(pageID);
+
+ CookieJarDB& cookieJarDB = session.cookieDatabase();
+ cookieJarDB.setCookie(url.string(), value, true);
+}
+
+void CookieJarCurlDatabase::setCookiesFromHTTPResponse(const NetworkStorageSession& session, const URL& url, const String& value) const
+{
+ CookieJarDB& cookieJarDB = session.cookieDatabase();
+ cookieJarDB.setCookie(url.string(), value, false);
+}
+
+std::pair<String, bool> CookieJarCurlDatabase::cookiesForDOM(const NetworkStorageSession& session, const URL& firstParty, const URL& url, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, IncludeSecureCookies) const
+{
+ UNUSED_PARAM(frameID);
+ UNUSED_PARAM(pageID);
+
+ // FIXME: This should filter secure cookies out if the caller requests it.
+ return { cookiesForSession(session, firstParty, url, false), false };
+}
+
+std::pair<String, bool> CookieJarCurlDatabase::cookieRequestHeaderFieldValue(const NetworkStorageSession& session, const URL& firstParty, const URL& url, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, IncludeSecureCookies) const
+{
+ UNUSED_PARAM(frameID);
+ UNUSED_PARAM(pageID);
+
+ // FIXME: This should filter secure cookies out if the caller requests it.
+ return { cookiesForSession(session, firstParty, url, true), false };
+}
+
+bool CookieJarCurlDatabase::cookiesEnabled(const NetworkStorageSession& session) const
+{
+ return true;
+}
+
+bool CookieJarCurlDatabase::getRawCookies(const NetworkStorageSession& session, const URL& firstParty, const URL&, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, Vector<Cookie>& rawCookies) const
+{
+ UNUSED_PARAM(frameID);
+ UNUSED_PARAM(pageID);
+
+ CookieJarDB& cookieJarDB = session.cookieDatabase();
+ return cookieJarDB.searchCookies(firstParty.string(), std::nullopt, std::nullopt, std::nullopt, rawCookies);
+}
+
+void CookieJarCurlDatabase::deleteCookie(const NetworkStorageSession&, const URL& url, const String& cookieName) const
+{
+ // FIXME: Not yet implemented
+}
+
+void CookieJarCurlDatabase::getHostnamesWithCookies(const NetworkStorageSession&, HashSet<String>& hostnames) const
+{
+ // FIXME: Not yet implemented
+}
+
+void CookieJarCurlDatabase::deleteCookiesForHostnames(const NetworkStorageSession&, const Vector<String>& cookieHostNames) const
+{
+ // FIXME: Not yet implemented
+}
+
+void CookieJarCurlDatabase::deleteAllCookies(const NetworkStorageSession&) const
+{
+ // FIXME: Not yet implemented
+}
+
+void CookieJarCurlDatabase::deleteAllCookiesModifiedSince(const NetworkStorageSession&, WallTime) const
+{
+ // FIXME: Not yet implemented
+}
+
+} // namespace WebCore
+
+#endif // USE(CURL)
Added: trunk/Source/WebCore/platform/network/curl/CookieJarCurlDatabase.h (0 => 227987)
--- trunk/Source/WebCore/platform/network/curl/CookieJarCurlDatabase.h (rev 0)
+++ trunk/Source/WebCore/platform/network/curl/CookieJarCurlDatabase.h 2018-02-02 00:08:41 UTC (rev 227987)
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "CookieJarCurl.h"
+
+namespace WebCore {
+
+class CookieJarCurlDatabase : public CookieJarCurl {
+ std::pair<String, bool> cookiesForDOM(const NetworkStorageSession&, const URL& firstParty, const URL&, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, IncludeSecureCookies) const override;
+ void setCookiesFromDOM(const NetworkStorageSession&, const URL& firstParty, const URL&, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, const String&) const override;
+ void setCookiesFromHTTPResponse(const NetworkStorageSession&, const URL&, const String&) const override;
+ bool cookiesEnabled(const NetworkStorageSession&) const override;
+ std::pair<String, bool> cookieRequestHeaderFieldValue(const NetworkStorageSession&, const URL& firstParty, const URL&, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, IncludeSecureCookies) const override;
+ bool getRawCookies(const NetworkStorageSession&, const URL& firstParty, const URL&, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, Vector<Cookie>&) const override;
+ void deleteCookie(const NetworkStorageSession&, const URL&, const String&) const override;
+ void getHostnamesWithCookies(const NetworkStorageSession&, HashSet<String>& hostnames) const override;
+ void deleteCookiesForHostnames(const NetworkStorageSession&, const Vector<String>& cookieHostNames) const override;
+ void deleteAllCookies(const NetworkStorageSession&) const override;
+ void deleteAllCookiesModifiedSince(const NetworkStorageSession&, WallTime) const override;
+};
+
+} // namespace WebCore
Added: trunk/Source/WebCore/platform/network/curl/CookieJarDB.cpp (0 => 227987)
--- trunk/Source/WebCore/platform/network/curl/CookieJarDB.cpp (rev 0)
+++ trunk/Source/WebCore/platform/network/curl/CookieJarDB.cpp 2018-02-02 00:08:41 UTC (rev 227987)
@@ -0,0 +1,492 @@
+/*
+ * 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 "CookieJarDB.h"
+
+#include "CookieUtil.h"
+#include "SQLiteFileSystem.h"
+#include "URL.h"
+
+namespace WebCore {
+
+#define CORRUPT_MARKER_SUFFIX "-corrupted"
+
+// At least 50 cookies per domain (RFC6265 6.1. Limits)
+#define MAX_COOKIE_PER_DOMAIN 80
+
+#define CREATE_COOKIE_TABLE_SQL \
+ "CREATE TABLE IF NOT EXISTS Cookie ("\
+ " name TEXT NOT NULL,"\
+ " value TEXT,"\
+ " domain TEXT NOT NULL,"\
+ " path TEXT NOT NULL,"\
+ " expires INTEGER NOT NULL,"\
+ " size INTEGER NOT NULL,"\
+ " session INTEGER NOT NULL,"\
+ " httponly INTEGER NOT NULL DEFAULT 0,"\
+ " secure INTEGER NOT NULL DEFAULT 0,"\
+ " lastupdated INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP, "\
+ " UNIQUE(name, domain, path));"
+#define CREATE_DOMAIN_INDEX_SQL \
+ "CREATE INDEX IF NOT EXISTS domain_index ON Cookie(domain);"
+#define CREATE_PATH_INDEX_SQL \
+ "CREATE INDEX IF NOT EXISTS path_index ON Cookie(path);"
+#define CHECK_EXISTS_HTTPONLY_COOKIE_SQL \
+ "SELECT name FROM Cookie WHERE (name = ?) AND (domain = ?) AND (path = ?) AND (httponly = 1);"
+#define SET_COOKIE_SQL \
+ "INSERT OR REPLACE INTO Cookie (name, value, domain, path, expires, size, session, httponly, secure) "\
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);"
+#define DELETE_COOKIE_BY_NAME_DOMAIN_PATH_SQL \
+ "DELETE FROM Cookie WHERE name = ? AND domain = ? AND path = ?;"
+#define DELETE_COOKIE_BY_NAME_DOMAIN_SQL \
+ "DELETE FROM Cookie WHERE name = ? AND domain = ?;"
+#define DELETE_ALL_SESSION_COOKIE_SQL \
+ "DELETE FROM Cookie WHERE session = 1;"
+#define DELETE_ALL_COOKIE_SQL \
+ "DELETE FROM Cookie;"
+
+void CookieJarDB::setEnabled(bool enable)
+{
+ CookieJarDB::m_cookieEnable = enable;
+}
+
+CookieJarDB::CookieJarDB(const String& databasePath)
+ : m_databasePath(databasePath)
+{
+ checkDatabaseCorruptionAndRemoveIfNeeded();
+
+ if (!openDatabase())
+ return;
+}
+
+CookieJarDB::~CookieJarDB()
+{
+ closeDatabase();
+}
+
+bool CookieJarDB::openDatabase()
+{
+ if (m_database.isOpen())
+ return true;
+
+ bool existsDatabaseFile = false;
+ if (!isOnMemory())
+ existsDatabaseFile = SQLiteFileSystem::ensureDatabaseFileExists(m_databasePath, false);
+
+ if (existsDatabaseFile) {
+ if (m_database.open(m_databasePath, false)) {
+ if (checkDatabaseValidity())
+ executeSimpleSql(DELETE_ALL_SESSION_COOKIE_SQL);
+ else {
+ // delete database and try to re-create again
+ m_database.close();
+ deleteAllDatabaseFiles();
+ existsDatabaseFile = false;
+ }
+ } else {
+ deleteAllDatabaseFiles();
+ existsDatabaseFile = false;
+ }
+ }
+
+ if (!existsDatabaseFile) {
+ if (m_database.open(m_databasePath, false)) {
+ bool databaseValidity = true;
+ databaseValidity &= (executeSimpleSql(CREATE_COOKIE_TABLE_SQL) == SQLITE_DONE);
+ databaseValidity &= (executeSimpleSql(CREATE_DOMAIN_INDEX_SQL) == SQLITE_DONE);
+ databaseValidity &= (executeSimpleSql(CREATE_PATH_INDEX_SQL) == SQLITE_DONE);
+ if (!databaseValidity) {
+ // give up create database at this time (all cookies on request/response are ignored)
+ m_database.close();
+ deleteAllDatabaseFiles();
+ }
+ }
+ }
+
+ if (!m_database.isOpen())
+ return false;
+
+ executeSimpleSql("PRAGMA temp_store = MEMORY;");
+ executeSimpleSql("PRAGMA synchronous = NORMAL;");
+ executeSimpleSql("PRAGMA journal_mode = WAL;");
+
+ // create prepared statements
+ createPrepareStatement(SET_COOKIE_SQL);
+ createPrepareStatement(CHECK_EXISTS_HTTPONLY_COOKIE_SQL);
+ createPrepareStatement(DELETE_COOKIE_BY_NAME_DOMAIN_PATH_SQL);
+ createPrepareStatement(DELETE_COOKIE_BY_NAME_DOMAIN_SQL);
+
+ return true;
+}
+
+void CookieJarDB::closeDatabase()
+{
+ if (m_database.isOpen()) {
+ for (const auto& statement : m_statements)
+ statement.value.get()->finalize();
+ m_statements.clear();
+ m_database.close();
+ }
+}
+
+String CookieJarDB::getCorruptionMarkerPath() const
+{
+ ASSERT(!isOnMemory());
+
+ return m_databasePath + CORRUPT_MARKER_SUFFIX;
+}
+
+void CookieJarDB::flagDatabaseCorruption()
+{
+ if (isOnMemory())
+ return;
+
+ FILE* f = fopen(getCorruptionMarkerPath().utf8().data(), "wb");
+ fclose(f);
+}
+
+bool CookieJarDB::checkDatabaseCorruptionAndRemoveIfNeeded()
+{
+ if (isOnMemory())
+ return false;
+
+ struct stat st = { 0 };
+ int ret = stat(getCorruptionMarkerPath().utf8().data(), &st);
+ if (!ret)
+ return false;
+
+ deleteAllDatabaseFiles();
+ return true;
+}
+
+bool CookieJarDB::checkSQLiteReturnCode(int actual, int expected)
+{
+ if (!m_detectedDatabaseCorruption) {
+ switch (actual) {
+ case SQLITE_CORRUPT:
+ case SQLITE_SCHEMA:
+ case SQLITE_FORMAT:
+ case SQLITE_NOTADB:
+ flagDatabaseCorruption();
+ m_detectedDatabaseCorruption = true;
+ }
+ }
+
+ return (actual == expected);
+}
+
+bool CookieJarDB::checkDatabaseValidity()
+{
+ ASSERT(m_database.isOpen());
+
+ return m_database.tableExists("Cookie");
+}
+
+void CookieJarDB::deleteAllDatabaseFiles()
+{
+ closeDatabase();
+ if (isOnMemory())
+ return;
+
+ int ret = 0;
+ String removePath;
+
+ // remove marker file (cookie.jar.db-corrupted)
+ ret = remove(removePath.utf8().data());
+
+ // remove shm file (cookie.jar.db-shm)
+ removePath = String(m_databasePath + "-shm");
+ ret = remove(removePath.utf8().data());
+
+ // remove wal file (cookie.jar.db-wal)
+ removePath = String(m_databasePath + "-wal");
+ ret = remove(removePath.utf8().data());
+}
+
+bool CookieJarDB::isEnabled()
+{
+ if (m_databasePath.isEmpty())
+ return false;
+
+ return m_cookieEnable;
+}
+
+bool CookieJarDB::searchCookies(const String& requestUrl, const std::optional<bool>& httpOnly, const std::optional<bool>& secure, const std::optional<bool>& session, Vector<Cookie>& results)
+{
+ if (!isEnabled() || !m_database.isOpen())
+ return false;
+
+ URL requestUrlObj(ParsedURLString, requestUrl);
+ String requestHost(requestUrlObj.host().convertToASCIILowercase());
+ String requestPath(requestUrlObj.path().convertToASCIILowercase());
+
+ if (requestHost.isEmpty())
+ return false;
+
+ if (requestPath.isEmpty())
+ requestPath = "/";
+
+ const String sql =
+ "SELECT name, value, domain, path, expires, httponly, secure, session FROM Cookie WHERE "\
+ "(NOT ((session = 0) AND (datetime(expires, 'unixepoch') < datetime('now')))) "\
+ "AND (httponly = COALESCE(NULLIF(?, -1), httponly)) "\
+ "AND (secure = COALESCE(NULLIF(?, -1), secure)) "\
+ "AND (session = COALESCE(NULLIF(?, -1), session)) "\
+ "AND ((domain = ?) OR (domain GLOB ?))";
+
+ std::unique_ptr<SQLiteStatement> pstmt = std::make_unique<SQLiteStatement>(m_database, sql);
+ pstmt->prepare();
+ pstmt->bindInt(1, httpOnly ? *httpOnly : -1);
+ pstmt->bindInt(2, secure ? *secure : -1);
+ pstmt->bindInt(3, session ? *session : -1);
+ pstmt->bindText(4, requestHost);
+
+ size_t topLevelSeparator = requestHost.reverseFind('.');
+ if (CookieUtil::isIPAddress(requestHost) || topLevelSeparator == notFound)
+ pstmt->bindNull(5);
+ else {
+ /* FIXME: currently we currently do not have a public suffic list in wincairo
+ so right now we glob using just the second level domain e.g. *.DOMAIN.com
+ This will return too many cookies under multilevel tlds such as *.co.uk
+ but we filter those out later
+ */
+
+ size_t secondLevelSeparator = requestHost.reverseFind('.', topLevelSeparator-1);
+ String localDomain = secondLevelSeparator == notFound ? requestHost : requestHost.substring(secondLevelSeparator+1);
+
+ ASSERT(!localDomain.isEmpty());
+ pstmt->bindText(5, String("*.") + localDomain);
+ }
+
+ if (!pstmt)
+ return false;
+
+ results.clear();
+
+ while (pstmt->step() == SQLITE_ROW) {
+
+ if (results.size() > MAX_COOKIE_PER_DOMAIN)
+ break;
+
+ String cookieName = pstmt->getColumnText(0);
+ String cookieValue = pstmt->getColumnText(1);
+ String cookieDomain = pstmt->getColumnText(2).convertToASCIILowercase();
+ String cookiePath = pstmt->getColumnText(3).convertToASCIILowercase();
+ double cookieExpires = (double)pstmt->getColumnInt64(4) * 1000;
+ bool cookieHttpOnly = (pstmt->getColumnInt(5) == 1);
+ bool cookieSecure = (pstmt->getColumnInt(6) == 1);
+ bool cookieSession = (pstmt->getColumnInt(7) == 1);
+
+ if (!CookieUtil::domainMatch(cookieDomain, requestHost))
+ continue;
+
+ // https://tools.ietf.org/html/rfc6265#section-5.1.4 "Paths and Path-Match"
+ bool isPathMatched = cookiePath == requestPath
+ || (requestPath.startsWith(cookiePath) && cookiePath.endsWith('/'))
+ || (requestPath.startsWith(cookiePath) && (requestPath.characterAt(cookiePath.length()) == '/'));
+
+ if (!isPathMatched)
+ continue;
+
+ Cookie result(cookieName,
+ cookieValue,
+ cookieDomain,
+ cookiePath,
+ 0,
+ cookieExpires,
+ cookieHttpOnly,
+ cookieSecure,
+ cookieSession,
+ String(),
+ URL(),
+ Vector<uint16_t>());
+
+ results.append(result);
+ }
+ pstmt->finalize();
+
+ return true;
+}
+
+bool CookieJarDB::hasHttpOnlyCookie(const String& name, const String& domain, const String& path)
+{
+ SQLiteStatement* statement = getPrepareStatement(CHECK_EXISTS_HTTPONLY_COOKIE_SQL);
+ ASSERT(statement);
+
+ statement->bindText(1, name);
+ statement->bindText(2, domain);
+ statement->bindText(3, path);
+
+ return statement->step() == SQLITE_ROW;
+}
+
+
+int CookieJarDB::setCookie(const Cookie& cookie)
+{
+ int ret = 0;
+ if (!cookie.session && (cookie.expires < ::time(0)))
+ ret = deleteCookieInternal(cookie.name, cookie.domain, cookie.path);
+ else {
+ SQLiteStatement* statement = getPrepareStatement(SET_COOKIE_SQL);
+ ASSERT(statement);
+
+ // FIXME: We should have some eviction policy when a domain goes over MAX_COOKIE_PER_DOMAIN
+
+ statement->bindText(1, cookie.name);
+ statement->bindText(2, cookie.value);
+ statement->bindText(3, cookie.domain);
+ statement->bindText(4, cookie.path);
+ statement->bindInt64(5, cookie.session ? 0 : (int64_t)cookie.expires);
+ statement->bindInt(6, cookie.value.length());
+ statement->bindInt(7, cookie.session ? 1 : 0);
+ statement->bindInt(8, cookie.httpOnly ? 1 : 0);
+ statement->bindInt(9, cookie.secure ? 1 : 0);
+
+ ret = statement->step();
+ }
+ ASSERT(checkSQLiteReturnCode(ret, SQLITE_DONE));
+
+ return ret;
+}
+
+int CookieJarDB::setCookie(const String& url, const String& cookie, bool fromJavaScript)
+{
+ if (!isEnabled() || !m_database.isOpen())
+ return -1;
+
+ if (url.isEmpty() || cookie.isEmpty())
+ return -1;
+
+ URL urlObj(ParsedURLString, url);
+ String host(urlObj.host());
+ String path(urlObj.path());
+
+ Cookie cookieObj;
+ if (!CookieUtil::parseCookieHeader(cookie, host, cookieObj))
+ return -1;
+
+ if (cookieObj.domain.isEmpty())
+ cookieObj.domain = String(host);
+
+ if (cookieObj.path.isEmpty())
+ cookieObj.path = String(path);
+
+ // FIXME: Need to check that a domain doesn't a set cookie for a tld when wincairo supports PSL
+
+ if (fromJavaScript && cookieObj.httpOnly)
+ return -1;
+
+ if (fromJavaScript && hasHttpOnlyCookie(cookieObj.name, cookieObj.domain, cookieObj.path))
+ return -1;
+
+ return setCookie(cookieObj);
+}
+
+int CookieJarDB::deleteCookie(const String& url, const String& name)
+{
+ if (!isEnabled() || !m_database.isOpen())
+ return -1;
+
+ String urlCopied = String(url);
+ if (urlCopied.startsWith('.'))
+ urlCopied.remove(0, 1);
+
+ URL urlObj(ParsedURLString, urlCopied);
+ if (urlObj.isValid()) {
+ String hostStr(urlObj.host());
+ String pathStr(urlObj.path());
+ int ret = deleteCookieInternal(name, hostStr, pathStr);
+ ASSERT(checkSQLiteReturnCode(ret, SQLITE_DONE));
+
+ return ret;
+ }
+
+ return -1;
+}
+
+int CookieJarDB::deleteCookieInternal(const String& name, const String& domain, const String& path)
+{
+ SQLiteStatement* statement;
+ if (!path.isEmpty()) {
+ statement = getPrepareStatement(DELETE_COOKIE_BY_NAME_DOMAIN_PATH_SQL);
+ ASSERT(statement);
+ statement->bindText(1, name);
+ statement->bindText(2, domain);
+ statement->bindText(3, path);
+ } else {
+ statement = getPrepareStatement(DELETE_COOKIE_BY_NAME_DOMAIN_SQL);
+ ASSERT(statement);
+ statement->bindText(1, name);
+ statement->bindText(2, domain);
+ }
+
+ return statement->step();
+}
+
+int CookieJarDB::deleteCookies(const String& url)
+{
+ // NOT IMPLEMENTED
+ // TODO: this function will be called if application calls WKCookieManagerDeleteCookiesForHostname() in WKCookieManager.h.
+ return 0;
+}
+
+int CookieJarDB::deleteAllCookies()
+{
+ if (!isEnabled() || !m_database.isOpen())
+ return -1;
+
+ return executeSimpleSql(DELETE_ALL_COOKIE_SQL);
+}
+
+void CookieJarDB::createPrepareStatement(const char* sql)
+{
+ auto statement = std::make_unique<SQLiteStatement>(m_database, sql);
+ int ret = statement->prepare();
+ ASSERT(ret == SQLITE_OK);
+ m_statements.add(String(sql), WTFMove(statement));
+}
+
+SQLiteStatement* CookieJarDB::getPrepareStatement(const char* sql)
+{
+ const auto& statement = m_statements.get(String(sql));
+ ASSERT(statement);
+ statement->reset();
+ return statement;
+}
+
+int CookieJarDB::executeSimpleSql(const char* sql, bool ignoreError)
+{
+ SQLiteStatement statement(m_database, sql);
+ int ret = statement.prepareAndStep();
+ statement.finalize();
+
+ ASSERT(checkSQLiteReturnCode(ret, SQLITE_OK)
+ || checkSQLiteReturnCode(ret, SQLITE_DONE)
+ || checkSQLiteReturnCode(ret, SQLITE_ROW)
+ || ignoreError);
+ return ret;
+}
+
+} // namespace WebCore
Added: trunk/Source/WebCore/platform/network/curl/CookieJarDB.h (0 => 227987)
--- trunk/Source/WebCore/platform/network/curl/CookieJarDB.h (rev 0)
+++ trunk/Source/WebCore/platform/network/curl/CookieJarDB.h 2018-02-02 00:08:41 UTC (rev 227987)
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "Cookie.h"
+#include "SQLiteDatabase.h"
+#include "SQLiteStatement.h"
+#include <wtf/HashMap.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/Optional.h>
+#include <wtf/Vector.h>
+#include <wtf/text/StringHash.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class CookieJarDB {
+ WTF_MAKE_NONCOPYABLE(CookieJarDB);
+
+public:
+ bool isEnabled();
+ void setEnabled(bool);
+
+ bool searchCookies(const String& requestUrl, const std::optional<bool>& httpOnly, const std::optional<bool>& secure, const std::optional<bool>& session, Vector<Cookie>& results);
+ int setCookie(const String& url, const String& cookie, bool fromJavaScript);
+ int setCookie(const Cookie&);
+
+ int deleteCookie(const String& url, const String& name);
+ int deleteCookies(const String& url);
+ int deleteAllCookies();
+
+ CookieJarDB(const String& databasePath);
+ ~CookieJarDB();
+
+private:
+
+ bool m_cookieEnable {true};
+ String m_databasePath;
+
+ bool m_detectedDatabaseCorruption {false};
+
+ bool isOnMemory() const { return (m_databasePath == ":onmemory:"); };
+
+ bool openDatabase();
+ void closeDatabase();
+
+ bool checkSQLiteReturnCode(int actual, int expected);
+ void flagDatabaseCorruption();
+ bool checkDatabaseCorruptionAndRemoveIfNeeded();
+ String getCorruptionMarkerPath() const;
+
+ bool checkDatabaseValidity();
+ void deleteAllDatabaseFiles();
+
+ void createPrepareStatement(const char* sql);
+ SQLiteStatement* getPrepareStatement(const char* sql);
+ int executeSimpleSql(const char* sql, bool ignoreError = false);
+
+ int deleteCookieInternal(const String& name, const String& domain, const String& path);
+ bool hasHttpOnlyCookie(const String& name, const String& domain, const String& path);
+
+ SQLiteDatabase m_database;
+ HashMap<String, std::unique_ptr<SQLiteStatement>> m_statements;
+};
+
+} // namespace WebCore
Added: trunk/Source/WebCore/platform/network/curl/CookieUtil.cpp (0 => 227987)
--- trunk/Source/WebCore/platform/network/curl/CookieUtil.cpp (rev 0)
+++ trunk/Source/WebCore/platform/network/curl/CookieUtil.cpp 2018-02-02 00:08:41 UTC (rev 227987)
@@ -0,0 +1,187 @@
+/*
+ * 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)
+{
+ // Assuming that hosts ending in a digit are IP Addresses
+ return !hostname.isEmpty() && isASCIIDigit(hostname[hostname.length() - 1]);
+}
+
+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
Added: trunk/Source/WebCore/platform/network/curl/CookieUtil.h (0 => 227987)
--- trunk/Source/WebCore/platform/network/curl/CookieUtil.h (rev 0)
+++ trunk/Source/WebCore/platform/network/curl/CookieUtil.h 2018-02-02 00:08:41 UTC (rev 227987)
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+struct Cookie;
+
+namespace CookieUtil {
+
+bool parseCookieHeader(const String& cookieLine, const String& domain, Cookie& result);
+
+bool isIPAddress(const String& hostname);
+
+bool domainMatch(const String& cookieDomain, const String& host);
+
+} // namespace CookieUtil
+
+} // namespace WebCore
Modified: trunk/Source/WebCore/platform/network/curl/CurlContext.cpp (227986 => 227987)
--- trunk/Source/WebCore/platform/network/curl/CurlContext.cpp 2018-02-01 23:42:47 UTC (rev 227986)
+++ trunk/Source/WebCore/platform/network/curl/CurlContext.cpp 2018-02-02 00:08:41 UTC (rev 227987)
@@ -42,38 +42,6 @@
namespace WebCore {
-static CString cookieJarPath()
-{
- char* cookieJarPath = getenv("CURL_COOKIE_JAR_PATH");
- if (cookieJarPath)
- return cookieJarPath;
-
-#if OS(WINDOWS)
- char executablePath[MAX_PATH];
- char appDataDirectory[MAX_PATH];
- char cookieJarFullPath[MAX_PATH];
- char cookieJarDirectory[MAX_PATH];
-
- if (FAILED(::SHGetFolderPathA(0, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, appDataDirectory))
- || FAILED(::GetModuleFileNameA(0, executablePath, MAX_PATH)))
- return "cookies.dat";
-
- ::PathRemoveExtensionA(executablePath);
- LPSTR executableName = ::PathFindFileNameA(executablePath);
- sprintf_s(cookieJarDirectory, MAX_PATH, "%s/%s", appDataDirectory, executableName);
- sprintf_s(cookieJarFullPath, MAX_PATH, "%s/cookies.dat", cookieJarDirectory);
-
- if (::SHCreateDirectoryExA(0, cookieJarDirectory, 0) != ERROR_SUCCESS
- && ::GetLastError() != ERROR_FILE_EXISTS
- && ::GetLastError() != ERROR_ALREADY_EXISTS)
- return "cookies.dat";
-
- return cookieJarFullPath;
-#else
- return "cookies.dat";
-#endif
-}
-
// CurlContext -------------------------------------------------------------------
CurlContext& CurlContext::singleton()
@@ -83,10 +51,8 @@
}
CurlContext::CurlContext()
-: m_cookieJarFileName { cookieJarPath() }
-, m_cookieJar { std::make_unique<CookieJarCurlFileSystem>() }
{
- initCookieSession();
+ initShareHandle();
#ifndef NDEBUG
m_verbose = getenv("DEBUG_CURL");
@@ -105,13 +71,8 @@
#endif
}
-// Cookie =======================
-
-void CurlContext::initCookieSession()
+void CurlContext::initShareHandle()
{
- // Curl saves both persistent cookies, and session cookies to the cookie file.
- // The session cookies should be deleted before starting a new session.
-
CURL* curl = curl_easy_init();
if (!curl)
@@ -119,13 +80,6 @@
curl_easy_setopt(curl, CURLOPT_SHARE, m_shareHandle.handle());
- if (!m_cookieJarFileName.isNull()) {
- curl_easy_setopt(curl, CURLOPT_COOKIEFILE, m_cookieJarFileName.data());
- curl_easy_setopt(curl, CURLOPT_COOKIEJAR, m_cookieJarFileName.data());
- }
-
- curl_easy_setopt(curl, CURLOPT_COOKIESESSION, 1);
-
curl_easy_cleanup(curl);
}
@@ -483,26 +437,6 @@
curl_easy_setopt(m_handle, CURLOPT_KEYPASSWD, password);
}
-void CurlHandle::enableCookieJarIfExists()
-{
- const char* cookieJar = CurlContext::singleton().getCookieJarFileName();
- if (cookieJar)
- curl_easy_setopt(m_handle, CURLOPT_COOKIEJAR, cookieJar);
-}
-
-void CurlHandle::setCookieList(const char* cookieList)
-{
- if (!cookieList)
- return;
-
- curl_easy_setopt(m_handle, CURLOPT_COOKIELIST, cookieList);
-}
-
-void CurlHandle::fetchCookieList(CurlSList &cookies) const
-{
- curl_easy_getinfo(m_handle, CURLINFO_COOKIELIST, static_cast<struct curl_slist**>(cookies));
-}
-
void CurlHandle::enableProxyIfExists()
{
auto& proxy = CurlContext::singleton().proxyInfo();
Modified: trunk/Source/WebCore/platform/network/curl/CurlContext.h (227986 => 227987)
--- trunk/Source/WebCore/platform/network/curl/CurlContext.h 2018-02-01 23:42:47 UTC (rev 227986)
+++ trunk/Source/WebCore/platform/network/curl/CurlContext.h 2018-02-02 00:08:41 UTC (rev 227987)
@@ -26,7 +26,6 @@
#pragma once
-#include "CookieJarCurl.h"
#include "CurlSSLHandle.h"
#include "URL.h"
@@ -110,11 +109,6 @@
const CurlShareHandle& shareHandle() { return m_shareHandle; }
- // Cookie
- const char* getCookieJarFileName() const { return m_cookieJarFileName.data(); }
- void setCookieJarFileName(const char* cookieJarFileName) { m_cookieJarFileName = CString(cookieJarFileName); }
- CookieJarCurl& cookieJar() { return *m_cookieJar; }
-
// Proxy
const ProxyInfo& proxyInfo() const { return m_proxy; }
void setProxyInfo(const ProxyInfo& info) { m_proxy = info; }
@@ -133,13 +127,11 @@
private:
ProxyInfo m_proxy;
- CString m_cookieJarFileName;
CurlShareHandle m_shareHandle;
- std::unique_ptr<CookieJarCurl> m_cookieJar;
CurlSSLHandle m_sslHandle;
CurlContext();
- void initCookieSession();
+ void initShareHandle();
#ifndef NDEBUG
FILE* m_logFile { nullptr };
@@ -256,10 +248,6 @@
void setSslCertType(const char*);
void setSslKeyPassword(const char*);
- void enableCookieJarIfExists();
- void setCookieList(const char*);
- void fetchCookieList(CurlSList &cookies) const;
-
void enableProxyIfExists();
void enableTimeout();
Modified: trunk/Source/WebCore/platform/network/curl/CurlRequest.cpp (227986 => 227987)
--- trunk/Source/WebCore/platform/network/curl/CurlRequest.cpp 2018-02-01 23:42:47 UTC (rev 227986)
+++ trunk/Source/WebCore/platform/network/curl/CurlRequest.cpp 2018-02-02 00:08:41 UTC (rev 227987)
@@ -200,7 +200,6 @@
m_curlHandle->setTimeout(timeoutMilliseconds);
m_curlHandle->enableProxyIfExists();
- m_curlHandle->enableCookieJarIfExists();
m_curlHandle->setSslVerifyPeer(CurlHandle::VerifyPeer::Enable);
m_curlHandle->setSslVerifyHost(CurlHandle::VerifyHost::StrictNameCheck);
Modified: trunk/Source/WebCore/platform/network/curl/NetworkStorageSessionCurl.cpp (227986 => 227987)
--- trunk/Source/WebCore/platform/network/curl/NetworkStorageSessionCurl.cpp 2018-02-01 23:42:47 UTC (rev 227986)
+++ trunk/Source/WebCore/platform/network/curl/NetworkStorageSessionCurl.cpp 2018-02-02 00:08:41 UTC (rev 227987)
@@ -29,6 +29,10 @@
#if USE(CURL)
#include "Cookie.h"
+#include "CookieJarCurlDatabase.h"
+#include "CookieJarDB.h"
+#include "CurlContext.h"
+#include "FileSystem.h"
#include "NetworkingContext.h"
#include "ResourceHandle.h"
@@ -37,9 +41,26 @@
namespace WebCore {
+static String defaultCookieJarPath()
+{
+ static const char* defaultFileName = "cookie.jar.db";
+ char* cookieJarPath = getenv("CURL_COOKIE_JAR_PATH");
+ if (cookieJarPath)
+ return cookieJarPath;
+
+ String cookieJarDirectory = FileSystem::localUserSpecificStorageDirectory();
+
+ if (!FileSystem::makeAllDirectories(cookieJarDirectory))
+ return defaultFileName;
+
+ return FileSystem::pathByAppendingComponent(cookieJarDirectory, defaultFileName);
+}
+
NetworkStorageSession::NetworkStorageSession(PAL::SessionID sessionID, NetworkingContext* context)
: m_sessionID(sessionID)
, m_context(context)
+ , m_cookieDatabase(defaultCookieJarPath())
+ , m_cookieStorage(makeUniqueRef<CookieJarCurlDatabase>())
{
}
Modified: trunk/Source/WebCore/platform/network/curl/ResourceHandleCurlDelegate.cpp (227986 => 227987)
--- trunk/Source/WebCore/platform/network/curl/ResourceHandleCurlDelegate.cpp 2018-02-01 23:42:47 UTC (rev 227986)
+++ trunk/Source/WebCore/platform/network/curl/ResourceHandleCurlDelegate.cpp 2018-02-02 00:08:41 UTC (rev 227987)
@@ -33,10 +33,12 @@
#if USE(CURL)
#include "AuthenticationChallenge.h"
+#include "CookieJarCurl.h"
#include "CredentialStorage.h"
#include "CurlCacheManager.h"
#include "CurlRequest.h"
#include "HTTPParsers.h"
+#include "NetworkStorageSession.h"
#include "ResourceHandleInternal.h"
#include "SharedBuffer.h"
#include "TextEncoding.h"
@@ -190,6 +192,20 @@
m_handle->client()->didSendData(m_handle, bytesSent, totalBytesToBeSent);
}
+static void handleCookieHeaders(const CurlResponse& response)
+{
+ static const auto setCookieHeader = "set-cookie: ";
+
+ auto& defaultStorageSession = NetworkStorageSession::defaultStorageSession();
+ const CookieJarCurl& cookieJar = defaultStorageSession.cookieStorage();
+ for (auto header : response.headers) {
+ if (header.startsWithIgnoringASCIICase(setCookieHeader)) {
+ String setCookieString = header.right(header.length() - strlen(setCookieHeader));
+ cookieJar.setCookiesFromHTTPResponse(defaultStorageSession, response.url, setCookieString);
+ }
+ }
+}
+
void ResourceHandleCurlDelegate::curlDidReceiveResponse(const CurlResponse& receivedResponse)
{
ASSERT(isMainThread());
@@ -203,6 +219,8 @@
if (m_curlRequest)
m_handle->getInternal()->m_response.setDeprecatedNetworkLoadMetrics(m_curlRequest->getNetworkLoadMetrics());
+ handleCookieHeaders(receivedResponse);
+
if (response().shouldRedirect()) {
willSendRequest();
return;