1/* 2 * Copyright (C) 2006 George Staikos <staikos@kde.org> 3 * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies) 4 * 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include "config.h" 30#include "CookieJarQt.h" 31 32#include "Cookie.h" 33#include "KURL.h" 34#include "NetworkingContext.h" 35#include "PlatformCookieJar.h" 36#include "ThirdPartyCookiesQt.h" 37#include <QDateTime> 38#include <QNetworkAccessManager> 39#include <QNetworkCookie> 40#include <QSqlQuery> 41#include <QStringList> 42#include <QVariant> 43#include <wtf/text/WTFString.h> 44 45namespace WebCore { 46 47static SharedCookieJarQt* s_sharedCookieJarQt = 0; 48 49void setCookiesFromDOM(const NetworkStorageSession& session, const KURL& firstParty, const KURL& url, const String& value) 50{ 51 QNetworkCookieJar* jar = session.context() ? session.context()->networkAccessManager()->cookieJar() : SharedCookieJarQt::shared(); 52 if (!jar) 53 return; 54 55 QUrl urlForCookies(url); 56 QUrl firstPartyUrl(firstParty); 57 if (!thirdPartyCookiePolicyPermits(session.context(), urlForCookies, firstPartyUrl)) 58 return; 59 60 QList<QNetworkCookie> cookies = QNetworkCookie::parseCookies(QString(value).toLatin1()); 61 QList<QNetworkCookie>::Iterator it = cookies.begin(); 62 while (it != cookies.end()) { 63 if (it->isHttpOnly()) 64 it = cookies.erase(it); 65 else 66 ++it; 67 } 68 69 jar->setCookiesFromUrl(cookies, urlForCookies); 70} 71 72String cookiesForDOM(const NetworkStorageSession& session, const KURL& firstParty, const KURL& url) 73{ 74 QNetworkCookieJar* jar = session.context() ? session.context()->networkAccessManager()->cookieJar() : SharedCookieJarQt::shared(); 75 if (!jar) 76 return String(); 77 78 QUrl urlForCookies(url); 79 QUrl firstPartyUrl(firstParty); 80 if (!thirdPartyCookiePolicyPermits(session.context(), urlForCookies, firstPartyUrl)) 81 return String(); 82 83 QList<QNetworkCookie> cookies = jar->cookiesForUrl(urlForCookies); 84 if (cookies.isEmpty()) 85 return String(); 86 87 QStringList resultCookies; 88 foreach (const QNetworkCookie& networkCookie, cookies) { 89 if (networkCookie.isHttpOnly()) 90 continue; 91 resultCookies.append(QString::fromLatin1(networkCookie.toRawForm(QNetworkCookie::NameAndValueOnly).constData())); 92 } 93 94 return resultCookies.join(QLatin1String("; ")); 95} 96 97String cookieRequestHeaderFieldValue(const NetworkStorageSession& session, const KURL& /*firstParty*/, const KURL& url) 98{ 99 QNetworkCookieJar* jar = session.context() ? session.context()->networkAccessManager()->cookieJar() : SharedCookieJarQt::shared(); 100 if (!jar) 101 return String(); 102 103 QList<QNetworkCookie> cookies = jar->cookiesForUrl(QUrl(url)); 104 if (cookies.isEmpty()) 105 return String(); 106 107 QStringList resultCookies; 108 foreach (QNetworkCookie networkCookie, cookies) 109 resultCookies.append(QString::fromLatin1(networkCookie.toRawForm(QNetworkCookie::NameAndValueOnly).constData())); 110 111 return resultCookies.join(QLatin1String("; ")); 112} 113 114bool cookiesEnabled(const NetworkStorageSession& session, const KURL& /*firstParty*/, const KURL& /*url*/) 115{ 116 QNetworkCookieJar* jar = session.context() ? session.context()->networkAccessManager()->cookieJar() : SharedCookieJarQt::shared(); 117 return !!jar; 118} 119 120bool getRawCookies(const NetworkStorageSession& session, const KURL& /*firstParty*/, const KURL& /*url*/, Vector<Cookie>& rawCookies) 121{ 122 // FIXME: Not yet implemented 123 rawCookies.clear(); 124 return false; // return true when implemented 125} 126 127void deleteCookie(const NetworkStorageSession&, const KURL&, const String&) 128{ 129 // FIXME: Not yet implemented 130} 131 132void getHostnamesWithCookies(const NetworkStorageSession& session, HashSet<String>& hostnames) 133{ 134 ASSERT_UNUSED(session, !session.context()); // Not yet implemented for cookie jars other than the shared one. 135 SharedCookieJarQt* jar = SharedCookieJarQt::shared(); 136 if (jar) 137 jar->getHostnamesWithCookies(hostnames); 138} 139 140void deleteCookiesForHostname(const NetworkStorageSession& session, const String& hostname) 141{ 142 ASSERT_UNUSED(session, !session.context()); // Not yet implemented for cookie jars other than the shared one. 143 SharedCookieJarQt* jar = SharedCookieJarQt::shared(); 144 if (jar) 145 jar->deleteCookiesForHostname(hostname); 146} 147 148void deleteAllCookies(const NetworkStorageSession& session) 149{ 150 ASSERT_UNUSED(session, !session.context()); // Not yet implemented for cookie jars other than the shared one. 151 SharedCookieJarQt* jar = SharedCookieJarQt::shared(); 152 if (jar) 153 jar->deleteAllCookies(); 154} 155 156SharedCookieJarQt* SharedCookieJarQt::shared() 157{ 158 return s_sharedCookieJarQt; 159} 160 161SharedCookieJarQt* SharedCookieJarQt::create(const String& cookieStorageDirectory) 162{ 163 if (!s_sharedCookieJarQt) 164 s_sharedCookieJarQt = new SharedCookieJarQt(cookieStorageDirectory); 165 166 return s_sharedCookieJarQt; 167} 168 169void SharedCookieJarQt::destroy() 170{ 171 delete s_sharedCookieJarQt; 172 s_sharedCookieJarQt = 0; 173} 174 175void SharedCookieJarQt::getHostnamesWithCookies(HashSet<String>& hostnames) 176{ 177 QList<QNetworkCookie> cookies = allCookies(); 178 foreach (const QNetworkCookie& networkCookie, cookies) 179 hostnames.add(networkCookie.domain()); 180} 181 182bool SharedCookieJarQt::deleteCookie(const QNetworkCookie& cookie) 183{ 184 if (!QNetworkCookieJar::deleteCookie(cookie)) 185 return false; 186 187 if (!m_database.isOpen()) 188 return false; 189 190 QSqlQuery sqlQuery(m_database); 191 sqlQuery.prepare(QLatin1String("DELETE FROM cookies WHERE cookieId=:cookieIdvalue")); 192 sqlQuery.bindValue(QLatin1String(":cookieIdvalue"), cookie.domain().append(QLatin1String(cookie.name()))); 193 sqlQuery.exec(); 194 195 return true; 196} 197 198void SharedCookieJarQt::deleteCookiesForHostname(const String& hostname) 199{ 200 if (!m_database.isOpen()) 201 return; 202 203 QList<QNetworkCookie> cookies = allCookies(); 204 QList<QNetworkCookie>::Iterator it = cookies.begin(); 205 QList<QNetworkCookie>::Iterator end = cookies.end(); 206 QSqlQuery sqlQuery(m_database); 207 sqlQuery.prepare(QLatin1String("DELETE FROM cookies WHERE cookieId=:cookieIdvalue")); 208 while (it != end) { 209 if (it->domain() == QString(hostname)) { 210 sqlQuery.bindValue(QLatin1String(":cookieIdvalue"), it->domain().append(QLatin1String(it->name()))); 211 sqlQuery.exec(); 212 it = cookies.erase(it); 213 } else 214 it++; 215 } 216 setAllCookies(cookies); 217} 218 219void SharedCookieJarQt::deleteAllCookies() 220{ 221 if (!m_database.isOpen()) 222 return; 223 224 QSqlQuery sqlQuery(m_database); 225 sqlQuery.prepare(QLatin1String("DELETE FROM cookies")); 226 sqlQuery.exec(); 227 setAllCookies(QList<QNetworkCookie>()); 228} 229 230SharedCookieJarQt::SharedCookieJarQt(const String& cookieStorageDirectory) 231{ 232 m_database = QSqlDatabase::addDatabase(QLatin1String("QSQLITE")); 233 const QString cookieStoragePath = cookieStorageDirectory; 234 const QString dataBaseName = cookieStoragePath + QLatin1String("/cookies.db"); 235 m_database.setDatabaseName(dataBaseName); 236 ensureDatabaseTable(); 237 loadCookies(); 238} 239 240SharedCookieJarQt::~SharedCookieJarQt() 241{ 242 m_database.close(); 243} 244 245bool SharedCookieJarQt::setCookiesFromUrl(const QList<QNetworkCookie>& cookieList, const QUrl& url) 246{ 247 if (!QNetworkCookieJar::setCookiesFromUrl(cookieList, url)) 248 return false; 249 250 if (!m_database.isOpen()) 251 return false; 252 253 QSqlQuery sqlQuery(m_database); 254 sqlQuery.prepare(QLatin1String("INSERT OR REPLACE INTO cookies (cookieId, cookie) VALUES (:cookieIdvalue, :cookievalue)")); 255 QVariantList cookiesIds; 256 QVariantList cookiesValues; 257 foreach (const QNetworkCookie &cookie, cookiesForUrl(url)) { 258 if (cookie.isSessionCookie()) 259 continue; 260 cookiesIds.append(cookie.domain().append(QLatin1String(cookie.name()))); 261 cookiesValues.append(cookie.toRawForm()); 262 } 263 sqlQuery.bindValue(QLatin1String(":cookieIdvalue"), cookiesIds); 264 sqlQuery.bindValue(QLatin1String(":cookievalue"), cookiesValues); 265 sqlQuery.execBatch(); 266 return true; 267} 268 269void SharedCookieJarQt::ensureDatabaseTable() 270{ 271 if (!m_database.open()) { 272 qWarning("Can't open cookie database"); 273 return; 274 } 275 m_database.exec(QLatin1String("PRAGMA synchronous=OFF")); 276 277 QSqlQuery sqlQuery(m_database); 278 sqlQuery.prepare(QLatin1String("CREATE TABLE IF NOT EXISTS cookies (cookieId VARCHAR PRIMARY KEY, cookie BLOB);")); 279 sqlQuery.exec(); 280} 281 282void SharedCookieJarQt::loadCookies() 283{ 284 if (!m_database.isOpen()) 285 return; 286 287 QList<QNetworkCookie> cookies; 288 QSqlQuery sqlQuery(m_database); 289 sqlQuery.prepare(QLatin1String("SELECT cookie FROM cookies")); 290 sqlQuery.exec(); 291 while (sqlQuery.next()) 292 cookies.append(QNetworkCookie::parseCookies(sqlQuery.value(0).toByteArray())); 293 setAllCookies(cookies); 294} 295 296#include "moc_CookieJarQt.cpp" 297 298} 299 300// vim: ts=4 sw=4 et 301