1/* 2 * Copyright (C) 2008 Xan Lopez <xan@gnome.org> 3 * Copyright (C) 2009 Igalia S.L. 4 * Copyright (C) 2008 Apple Inc. All rights reserved. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21#include "config.h" 22 23#if USE(SOUP) 24 25#include "CookieJarSoup.h" 26 27#include "Cookie.h" 28#include "GUniquePtrSoup.h" 29#include "URL.h" 30#include "NetworkingContext.h" 31#include "PlatformCookieJar.h" 32#include "SoupNetworkSession.h" 33#include <wtf/gobject/GRefPtr.h> 34#include <wtf/text/CString.h> 35 36namespace WebCore { 37 38static SoupCookieJar* cookieJarForSession(const NetworkStorageSession& session) 39{ 40 return session.soupNetworkSession().cookieJar(); 41} 42 43static GRefPtr<SoupCookieJar>& defaultCookieJar() 44{ 45 DEPRECATED_DEFINE_STATIC_LOCAL(GRefPtr<SoupCookieJar>, cookieJar, ()); 46 return cookieJar; 47} 48 49SoupCookieJar* soupCookieJar() 50{ 51 if (GRefPtr<SoupCookieJar>& jar = defaultCookieJar()) 52 return jar.get(); 53 54 SoupCookieJar* jar = soup_cookie_jar_new(); 55 soup_cookie_jar_set_accept_policy(jar, SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY); 56 setSoupCookieJar(jar); 57 return jar; 58} 59 60SoupCookieJar* createPrivateBrowsingCookieJar() 61{ 62 SoupCookieJar* jar = soup_cookie_jar_new(); 63 64 soup_cookie_jar_set_accept_policy(jar, SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY); 65 66 return jar; 67} 68 69void setSoupCookieJar(SoupCookieJar* jar) 70{ 71 defaultCookieJar() = jar; 72} 73 74static inline bool httpOnlyCookieExists(const GSList* cookies, const gchar* name, const gchar* path) 75{ 76 for (const GSList* iter = cookies; iter; iter = g_slist_next(iter)) { 77 SoupCookie* cookie = static_cast<SoupCookie*>(iter->data); 78 if (!strcmp(soup_cookie_get_name(cookie), name) 79 && !g_strcmp0(soup_cookie_get_path(cookie), path)) { 80 if (soup_cookie_get_http_only(cookie)) 81 return true; 82 break; 83 } 84 } 85 return false; 86} 87 88void setCookiesFromDOM(const NetworkStorageSession& session, const URL& firstParty, const URL& url, const String& value) 89{ 90 SoupCookieJar* jar = cookieJarForSession(session); 91 if (!jar) 92 return; 93 94 GUniquePtr<SoupURI> origin = url.createSoupURI(); 95 GUniquePtr<SoupURI> firstPartyURI = firstParty.createSoupURI(); 96 97 // Get existing cookies for this origin. 98 GSList* existingCookies = soup_cookie_jar_get_cookie_list(jar, origin.get(), TRUE); 99 100 Vector<String> cookies; 101 value.split('\n', cookies); 102 const size_t cookiesCount = cookies.size(); 103 for (size_t i = 0; i < cookiesCount; ++i) { 104 GUniquePtr<SoupCookie> cookie(soup_cookie_parse(cookies[i].utf8().data(), origin.get())); 105 if (!cookie) 106 continue; 107 108 // Make sure the cookie is not httpOnly since such cookies should not be set from JavaScript. 109 if (soup_cookie_get_http_only(cookie.get())) 110 continue; 111 112 // Make sure we do not overwrite httpOnly cookies from JavaScript. 113 if (httpOnlyCookieExists(existingCookies, soup_cookie_get_name(cookie.get()), soup_cookie_get_path(cookie.get()))) 114 continue; 115 116 soup_cookie_jar_add_cookie_with_first_party(jar, firstPartyURI.get(), cookie.release()); 117 } 118 119 soup_cookies_free(existingCookies); 120} 121 122static String cookiesForSession(const NetworkStorageSession& session, const URL& url, bool forHTTPHeader) 123{ 124 SoupCookieJar* jar = cookieJarForSession(session); 125 if (!jar) 126 return String(); 127 128 GUniquePtr<SoupURI> uri = url.createSoupURI(); 129 GUniquePtr<char> cookies(soup_cookie_jar_get_cookies(jar, uri.get(), forHTTPHeader)); 130 return String::fromUTF8(cookies.get()); 131} 132 133String cookiesForDOM(const NetworkStorageSession& session, const URL&, const URL& url) 134{ 135 return cookiesForSession(session, url, false); 136} 137 138String cookieRequestHeaderFieldValue(const NetworkStorageSession& session, const URL& /*firstParty*/, const URL& url) 139{ 140 return cookiesForSession(session, url, true); 141} 142 143bool cookiesEnabled(const NetworkStorageSession& session, const URL& /*firstParty*/, const URL& /*url*/) 144{ 145 return !!cookieJarForSession(session); 146} 147 148bool getRawCookies(const NetworkStorageSession& session, const URL& /*firstParty*/, const URL& url, Vector<Cookie>& rawCookies) 149{ 150 rawCookies.clear(); 151 SoupCookieJar* jar = cookieJarForSession(session); 152 if (!jar) 153 return false; 154 155 GUniquePtr<SoupURI> uri = url.createSoupURI(); 156 GUniquePtr<GSList> cookies(soup_cookie_jar_get_cookie_list(jar, uri.get(), TRUE)); 157 if (!cookies) 158 return false; 159 160 for (GSList* iter = cookies.get(); iter; iter = g_slist_next(iter)) { 161 SoupCookie* cookie = static_cast<SoupCookie*>(iter->data); 162 rawCookies.append(Cookie(String::fromUTF8(cookie->name), String::fromUTF8(cookie->value), String::fromUTF8(cookie->domain), 163 String::fromUTF8(cookie->path), cookie->expires ? static_cast<double>(soup_date_to_time_t(cookie->expires)) * 1000 : 0, 164 cookie->http_only, cookie->secure, !cookie->expires)); 165 soup_cookie_free(cookie); 166 } 167 168 return true; 169} 170 171void deleteCookie(const NetworkStorageSession& session, const URL& url, const String& name) 172{ 173 SoupCookieJar* jar = cookieJarForSession(session); 174 if (!jar) 175 return; 176 177 GUniquePtr<SoupURI> uri = url.createSoupURI(); 178 GUniquePtr<GSList> cookies(soup_cookie_jar_get_cookie_list(jar, uri.get(), TRUE)); 179 if (!cookies) 180 return; 181 182 CString cookieName = name.utf8(); 183 bool wasDeleted = false; 184 for (GSList* iter = cookies.get(); iter; iter = g_slist_next(iter)) { 185 SoupCookie* cookie = static_cast<SoupCookie*>(iter->data); 186 if (!wasDeleted && cookieName == cookie->name) { 187 soup_cookie_jar_delete_cookie(jar, cookie); 188 wasDeleted = true; 189 } 190 soup_cookie_free(cookie); 191 } 192} 193 194void getHostnamesWithCookies(const NetworkStorageSession& session, HashSet<String>& hostnames) 195{ 196 SoupCookieJar* cookieJar = cookieJarForSession(session); 197 GUniquePtr<GSList> cookies(soup_cookie_jar_all_cookies(cookieJar)); 198 for (GSList* item = cookies.get(); item; item = g_slist_next(item)) { 199 SoupCookie* cookie = static_cast<SoupCookie*>(item->data); 200 if (cookie->domain) 201 hostnames.add(String::fromUTF8(cookie->domain)); 202 soup_cookie_free(cookie); 203 } 204} 205 206void deleteCookiesForHostname(const NetworkStorageSession& session, const String& hostname) 207{ 208 CString hostNameString = hostname.utf8(); 209 SoupCookieJar* cookieJar = cookieJarForSession(session); 210 GUniquePtr<GSList> cookies(soup_cookie_jar_all_cookies(cookieJar)); 211 for (GSList* item = cookies.get(); item; item = g_slist_next(item)) { 212 SoupCookie* cookie = static_cast<SoupCookie*>(item->data); 213 if (soup_cookie_domain_matches(cookie, hostNameString.data())) 214 soup_cookie_jar_delete_cookie(cookieJar, cookie); 215 soup_cookie_free(cookie); 216 } 217} 218 219void deleteAllCookies(const NetworkStorageSession& session) 220{ 221 SoupCookieJar* cookieJar = cookieJarForSession(session); 222 GUniquePtr<GSList> cookies(soup_cookie_jar_all_cookies(cookieJar)); 223 for (GSList* item = cookies.get(); item; item = g_slist_next(item)) { 224 SoupCookie* cookie = static_cast<SoupCookie*>(item->data); 225 soup_cookie_jar_delete_cookie(cookieJar, cookie); 226 soup_cookie_free(cookie); 227 } 228} 229 230void deleteAllCookiesModifiedAfterDate(const NetworkStorageSession&, double) 231{ 232} 233 234} 235 236#endif 237