~ubuntu-branches/ubuntu/oneiric/arora/oneiric

« back to all changes in this revision

Viewing changes to src/network/cookiejar/cookiejar.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Roderick B. Greening
  • Date: 2009-09-10 15:24:04 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090910152404-668k22ux3mfap6g0
Tags: 0.9.0-0ubuntu1
* New upstream release
* Update patches:
  - kubuntu_02_default_bookmarks.diff
* Remove patches:
  - kubuntu_04_startpage_spacing.diff (fixed upstream)
  - kubuntu_05_manpages.diff (fixed upstream)
  - kubuntu_07_adblock.diff (unstable/unsuitable)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2008-2009 Benjamin C. Meyer <ben@meyerhome.net>
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by
 
6
 * the Free Software Foundation; either version 2 of the License, or
 
7
 * (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
17
 * Boston, MA  02110-1301  USA
 
18
 */
 
19
 
 
20
/****************************************************************************
 
21
**
 
22
** Copyright (C) 2007-2008 Trolltech ASA. All rights reserved.
 
23
**
 
24
** This file is part of the demonstration applications of the Qt Toolkit.
 
25
**
 
26
** This file may be used under the terms of the GNU General Public
 
27
** License versions 2.0 or 3.0 as published by the Free Software
 
28
** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
 
29
** included in the packaging of this file.  Alternatively you may (at
 
30
** your option) use any later version of the GNU General Public
 
31
** License if such license has been publicly approved by Trolltech ASA
 
32
** (or its successors, if any) and the KDE Free Qt Foundation. In
 
33
** addition, as a special exception, Trolltech gives you certain
 
34
** additional rights. These rights are described in the Trolltech GPL
 
35
** Exception version 1.2, which can be found at
 
36
** http://www.trolltech.com/products/qt/gplexception/ and in the file
 
37
** GPL_EXCEPTION.txt in this package.
 
38
**
 
39
** Please review the following information to ensure GNU General
 
40
** Public Licensing requirements will be met:
 
41
** http://trolltech.com/products/qt/licenses/licensing/opensource/. If
 
42
** you are unsure which license is appropriate for your use, please
 
43
** review the following information:
 
44
** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
 
45
** or contact the sales department at sales@trolltech.com.
 
46
**
 
47
** In addition, as a special exception, Trolltech, as the sole
 
48
** copyright holder for Qt Designer, grants users of the Qt/Eclipse
 
49
** Integration plug-in the right for the Qt/Eclipse Integration to
 
50
** link to functionality provided by Qt Designer and its related
 
51
** libraries.
 
52
**
 
53
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
 
54
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
 
55
** A PARTICULAR PURPOSE. Trolltech reserves all rights not expressly
 
56
** granted herein.
 
57
**
 
58
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 
59
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
60
**
 
61
****************************************************************************/
 
62
 
 
63
#include "cookiejar.h"
 
64
 
 
65
#include "autosaver.h"
 
66
 
 
67
#include <qapplication.h>
 
68
#include <qdesktopservices.h>
 
69
#include <qdir.h>
 
70
#include <qmetaobject.h>
 
71
#include <qsettings.h>
 
72
#include <qurl.h>
 
73
 
 
74
#include <qdebug.h>
 
75
 
 
76
static const unsigned int JAR_VERSION = 23;
 
77
 
 
78
QT_BEGIN_NAMESPACE
 
79
QDataStream &operator<<(QDataStream &stream, const QList<QNetworkCookie> &list)
 
80
{
 
81
    stream << JAR_VERSION;
 
82
    stream << quint32(list.size());
 
83
    for (int i = 0; i < list.size(); ++i)
 
84
        stream << list.at(i).toRawForm();
 
85
    return stream;
 
86
}
 
87
 
 
88
QDataStream &operator>>(QDataStream &stream, QList<QNetworkCookie> &list)
 
89
{
 
90
    list.clear();
 
91
 
 
92
    quint32 version;
 
93
    stream >> version;
 
94
 
 
95
    if (version != JAR_VERSION)
 
96
        return stream;
 
97
 
 
98
    quint32 count;
 
99
    stream >> count;
 
100
    for (quint32 i = 0; i < count; ++i) {
 
101
        QByteArray value;
 
102
        stream >> value;
 
103
        QList<QNetworkCookie> newCookies = QNetworkCookie::parseCookies(value);
 
104
        if (newCookies.count() == 0 && value.length() != 0) {
 
105
            qWarning() << "CookieJar: Unable to parse saved cookie:" << value;
 
106
        }
 
107
        for (int j = 0; j < newCookies.count(); ++j)
 
108
            list.append(newCookies.at(j));
 
109
        if (stream.atEnd())
 
110
            break;
 
111
    }
 
112
    return stream;
 
113
}
 
114
QT_END_NAMESPACE
 
115
 
 
116
CookieJar::CookieJar(QObject *parent)
 
117
    : NetworkCookieJar(parent)
 
118
    , m_loaded(false)
 
119
    , m_saveTimer(new AutoSaver(this))
 
120
    , m_filterTrackingCookies(false)
 
121
    , m_acceptCookies(AcceptOnlyFromSitesNavigatedTo)
 
122
    , m_isPrivate(false)
 
123
{
 
124
}
 
125
 
 
126
CookieJar::~CookieJar()
 
127
{
 
128
    if (m_loaded && m_keepCookies == KeepUntilExit)
 
129
        clear();
 
130
    m_saveTimer->saveIfNeccessary();
 
131
}
 
132
 
 
133
void CookieJar::setPrivate(bool isPrivate)
 
134
{
 
135
    m_isPrivate = isPrivate;
 
136
}
 
137
 
 
138
void CookieJar::clear()
 
139
{
 
140
    if (!m_loaded)
 
141
        load();
 
142
    setAllCookies(QList<QNetworkCookie>());
 
143
    m_saveTimer->changeOccurred();
 
144
    emit cookiesChanged();
 
145
}
 
146
 
 
147
void CookieJar::load()
 
148
{
 
149
    if (m_loaded)
 
150
        return;
 
151
    // load cookies and exceptions
 
152
    qRegisterMetaTypeStreamOperators<QList<QNetworkCookie> >("QList<QNetworkCookie>");
 
153
    QSettings cookieSettings(QDesktopServices::storageLocation(QDesktopServices::DataLocation) + QLatin1String("/cookies.ini"), QSettings::IniFormat);
 
154
    if (!m_isPrivate) {
 
155
        setAllCookies(qvariant_cast<QList<QNetworkCookie> >(cookieSettings.value(QLatin1String("cookies"))));
 
156
    }
 
157
    cookieSettings.beginGroup(QLatin1String("Exceptions"));
 
158
    m_exceptions_block = cookieSettings.value(QLatin1String("block")).toStringList();
 
159
    m_exceptions_allow = cookieSettings.value(QLatin1String("allow")).toStringList();
 
160
    m_exceptions_allowForSession = cookieSettings.value(QLatin1String("allowForSession")).toStringList();
 
161
    qSort(m_exceptions_block.begin(), m_exceptions_block.end());
 
162
    qSort(m_exceptions_allow.begin(), m_exceptions_allow.end());
 
163
    qSort(m_exceptions_allowForSession.begin(), m_exceptions_allowForSession.end());
 
164
 
 
165
    loadSettings();
 
166
}
 
167
 
 
168
void CookieJar::loadSettings()
 
169
{
 
170
    QSettings settings;
 
171
    settings.beginGroup(QLatin1String("cookies"));
 
172
    QByteArray value = settings.value(QLatin1String("acceptCookies"),
 
173
                                      QLatin1String("AcceptOnlyFromSitesNavigatedTo")).toByteArray();
 
174
    QMetaEnum acceptPolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("AcceptPolicy"));
 
175
    m_acceptCookies = acceptPolicyEnum.keyToValue(value) == -1 ?
 
176
                      AcceptOnlyFromSitesNavigatedTo :
 
177
                      static_cast<AcceptPolicy>(acceptPolicyEnum.keyToValue(value));
 
178
 
 
179
    value = settings.value(QLatin1String("keepCookiesUntil"), QLatin1String("KeepUntilExpire")).toByteArray();
 
180
    QMetaEnum keepPolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("KeepPolicy"));
 
181
    m_keepCookies = keepPolicyEnum.keyToValue(value) == -1 ?
 
182
                    KeepUntilExpire :
 
183
                    static_cast<KeepPolicy>(keepPolicyEnum.keyToValue(value));
 
184
 
 
185
    if (m_keepCookies == KeepUntilExit)
 
186
        setAllCookies(QList<QNetworkCookie>());
 
187
 
 
188
    m_loaded = true;
 
189
    m_filterTrackingCookies = settings.value(QLatin1String("filterTrackingCookies"), m_filterTrackingCookies).toBool();
 
190
    emit cookiesChanged();
 
191
}
 
192
 
 
193
void CookieJar::save()
 
194
{
 
195
    if (!m_loaded || m_isPrivate)
 
196
        return;
 
197
    purgeOldCookies();
 
198
    QString directory = QDesktopServices::storageLocation(QDesktopServices::DataLocation);
 
199
    if (directory.isEmpty())
 
200
        directory = QDir::homePath() + QLatin1String("/.") + QCoreApplication::applicationName();
 
201
    if (!QFile::exists(directory)) {
 
202
        QDir dir;
 
203
        dir.mkpath(directory);
 
204
    }
 
205
    QSettings cookieSettings(directory + QLatin1String("/cookies.ini"), QSettings::IniFormat);
 
206
    QList<QNetworkCookie> cookies = allCookies();
 
207
    for (int i = cookies.count() - 1; i >= 0; --i) {
 
208
        if (cookies.at(i).isSessionCookie())
 
209
            cookies.removeAt(i);
 
210
    }
 
211
    cookieSettings.setValue(QLatin1String("cookies"), qVariantFromValue<QList<QNetworkCookie> >(cookies));
 
212
    cookieSettings.beginGroup(QLatin1String("Exceptions"));
 
213
    cookieSettings.setValue(QLatin1String("block"), m_exceptions_block);
 
214
    cookieSettings.setValue(QLatin1String("allow"), m_exceptions_allow);
 
215
    cookieSettings.setValue(QLatin1String("allowForSession"), m_exceptions_allowForSession);
 
216
 
 
217
    // save cookie settings
 
218
    QSettings settings;
 
219
    settings.beginGroup(QLatin1String("cookies"));
 
220
    QMetaEnum acceptPolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("AcceptPolicy"));
 
221
    settings.setValue(QLatin1String("acceptCookies"), QLatin1String(acceptPolicyEnum.valueToKey(m_acceptCookies)));
 
222
 
 
223
    QMetaEnum keepPolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("KeepPolicy"));
 
224
    settings.setValue(QLatin1String("keepCookiesUntil"), QLatin1String(keepPolicyEnum.valueToKey(m_keepCookies)));
 
225
 
 
226
    settings.setValue(QLatin1String("filterTrackingCookies"), m_filterTrackingCookies);
 
227
}
 
228
 
 
229
void CookieJar::purgeOldCookies()
 
230
{
 
231
    QList<QNetworkCookie> cookies = allCookies();
 
232
    if (cookies.isEmpty())
 
233
        return;
 
234
    int oldCount = cookies.count();
 
235
    QDateTime now = QDateTime::currentDateTime();
 
236
    for (int i = cookies.count() - 1; i >= 0; --i) {
 
237
        if (!cookies.at(i).isSessionCookie() && cookies.at(i).expirationDate() < now)
 
238
            cookies.removeAt(i);
 
239
    }
 
240
    if (oldCount == cookies.count())
 
241
        return;
 
242
    setAllCookies(cookies);
 
243
    emit cookiesChanged();
 
244
}
 
245
 
 
246
QList<QNetworkCookie> CookieJar::cookiesForUrl(const QUrl &url) const
 
247
{
 
248
    CookieJar *that = const_cast<CookieJar*>(this);
 
249
    if (!m_loaded)
 
250
        that->load();
 
251
 
 
252
    return NetworkCookieJar::cookiesForUrl(url);
 
253
}
 
254
 
 
255
bool CookieJar::setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url)
 
256
{
 
257
    if (!m_loaded)
 
258
        load();
 
259
 
 
260
    QString host = url.host();
 
261
    bool eBlock = isOnDomainList(m_exceptions_block, host);
 
262
    bool eAllow = !eBlock && isOnDomainList(m_exceptions_allow, host);
 
263
    bool eAllowSession = !eBlock && !eAllow && isOnDomainList(m_exceptions_allowForSession, host);
 
264
 
 
265
    bool addedCookies = false;
 
266
    // pass exceptions
 
267
    bool acceptInitially = (m_acceptCookies != AcceptNever);
 
268
    if ((acceptInitially && !eBlock)
 
269
        || (!acceptInitially && (eAllow || eAllowSession))) {
 
270
        // pass url domain == cookie domain
 
271
        QDateTime soon = QDateTime::currentDateTime();
 
272
        soon = soon.addDays(90);
 
273
        foreach (QNetworkCookie cookie, cookieList) {
 
274
            QList<QNetworkCookie> lst;
 
275
            if (!(m_filterTrackingCookies && cookie.name().startsWith("__utm"))) {
 
276
 
 
277
 
 
278
                if (eAllowSession) {
 
279
                    cookie.setExpirationDate(QDateTime());
 
280
                }
 
281
                if (m_keepCookies == KeepUntilTimeLimit
 
282
                    && !cookie.isSessionCookie()
 
283
                    && cookie.expirationDate() > soon) {
 
284
                    cookie.setExpirationDate(soon);
 
285
                }
 
286
                lst += cookie;
 
287
                if (NetworkCookieJar::setCookiesFromUrl(lst, url)) {
 
288
                    addedCookies = true;
 
289
                } else {
 
290
                    // finally force it in if wanted
 
291
                    if (m_acceptCookies == AcceptAlways) {
 
292
                        QList<QNetworkCookie> cookies = allCookies();
 
293
                        QList<QNetworkCookie>::Iterator it = cookies.begin(),
 
294
                                   end = cookies.end();
 
295
                        for ( ; it != end; ++it) {
 
296
                            // does this cookie already exist?
 
297
                            if (cookie.name() == it->name() &&
 
298
                                cookie.domain() == it->domain() &&
 
299
                                cookie.path() == it->path()) {
 
300
                                // found a match
 
301
                                cookies.erase(it);
 
302
                                break;
 
303
                            }
 
304
                        }
 
305
 
 
306
                        cookies += cookie;
 
307
                        setAllCookies(cookies);
 
308
                        addedCookies = true;
 
309
                    }
 
310
    #if 0
 
311
                    else
 
312
                        qWarning() << "setCookiesFromUrl failed" << url << cookieList.value(0).toRawForm();
 
313
    #endif
 
314
                }
 
315
#if 0
 
316
            } else {
 
317
                qWarning() << "cookie treated as tracking cookie" << cookie;
 
318
#endif
 
319
            }
 
320
        }
 
321
    }
 
322
 
 
323
    if (addedCookies) {
 
324
        m_saveTimer->changeOccurred();
 
325
        emit cookiesChanged();
 
326
    }
 
327
    return addedCookies;
 
328
}
 
329
 
 
330
bool CookieJar::isOnDomainList(const QStringList &rules, const QString &domain)
 
331
{
 
332
    // Either the rule matches the domain exactly
 
333
    // or the domain ends with ".rule"
 
334
    foreach (const QString &rule, rules) {
 
335
        if (rule.startsWith(QLatin1String("."))) {
 
336
            if (domain.endsWith(rule))
 
337
                return true;
 
338
 
 
339
            QStringRef withoutDot = rule.rightRef(rule.size() - 1);
 
340
            if (domain == withoutDot)
 
341
                return true;
 
342
        } else {
 
343
            QStringRef domainEnding = domain.rightRef(rule.size() + 1);
 
344
            if (!domainEnding.isEmpty()
 
345
                && domainEnding.at(0) == QLatin1Char('.')
 
346
                && domain.endsWith(rule)) {
 
347
                return true;
 
348
            }
 
349
 
 
350
            if (rule == domain)
 
351
                return true;
 
352
        }
 
353
    }
 
354
    return false;
 
355
}
 
356
 
 
357
CookieJar::AcceptPolicy CookieJar::acceptPolicy() const
 
358
{
 
359
    if (!m_loaded)
 
360
        (const_cast<CookieJar*>(this))->load();
 
361
    return m_acceptCookies;
 
362
}
 
363
 
 
364
void CookieJar::setAcceptPolicy(AcceptPolicy policy)
 
365
{
 
366
    if (!m_loaded)
 
367
        load();
 
368
    if (policy == m_acceptCookies)
 
369
        return;
 
370
    m_acceptCookies = policy;
 
371
    m_saveTimer->changeOccurred();
 
372
}
 
373
 
 
374
CookieJar::KeepPolicy CookieJar::keepPolicy() const
 
375
{
 
376
    if (!m_loaded)
 
377
        (const_cast<CookieJar*>(this))->load();
 
378
    return m_keepCookies;
 
379
}
 
380
 
 
381
void CookieJar::setKeepPolicy(KeepPolicy policy)
 
382
{
 
383
    if (!m_loaded)
 
384
        load();
 
385
    if (policy == m_keepCookies)
 
386
        return;
 
387
    m_keepCookies = policy;
 
388
    m_saveTimer->changeOccurred();
 
389
}
 
390
 
 
391
QStringList CookieJar::blockedCookies() const
 
392
{
 
393
    if (!m_loaded)
 
394
        (const_cast<CookieJar*>(this))->load();
 
395
    return m_exceptions_block;
 
396
}
 
397
 
 
398
QStringList CookieJar::allowedCookies() const
 
399
{
 
400
    if (!m_loaded)
 
401
        (const_cast<CookieJar*>(this))->load();
 
402
    return m_exceptions_allow;
 
403
}
 
404
 
 
405
QStringList CookieJar::allowForSessionCookies() const
 
406
{
 
407
    if (!m_loaded)
 
408
        (const_cast<CookieJar*>(this))->load();
 
409
    return m_exceptions_allowForSession;
 
410
}
 
411
 
 
412
void CookieJar::setBlockedCookies(const QStringList &list)
 
413
{
 
414
    if (!m_loaded)
 
415
        load();
 
416
    m_exceptions_block = list;
 
417
    qSort(m_exceptions_block.begin(), m_exceptions_block.end());
 
418
    applyRules();
 
419
    m_saveTimer->changeOccurred();
 
420
}
 
421
 
 
422
void CookieJar::setAllowedCookies(const QStringList &list)
 
423
{
 
424
    if (!m_loaded)
 
425
        load();
 
426
    m_exceptions_allow = list;
 
427
    qSort(m_exceptions_allow.begin(), m_exceptions_allow.end());
 
428
    applyRules();
 
429
    m_saveTimer->changeOccurred();
 
430
}
 
431
 
 
432
void CookieJar::setAllowForSessionCookies(const QStringList &list)
 
433
{
 
434
    if (!m_loaded)
 
435
        load();
 
436
    m_exceptions_allowForSession = list;
 
437
    qSort(m_exceptions_allowForSession.begin(), m_exceptions_allowForSession.end());
 
438
    applyRules();
 
439
    m_saveTimer->changeOccurred();
 
440
}
 
441
 
 
442
void CookieJar::applyRules()
 
443
{
 
444
    QList<QNetworkCookie> cookies = allCookies();
 
445
    bool changed = false;
 
446
    for (int i = cookies.count() - 1; i >= 0; --i) {
 
447
        const QNetworkCookie &cookie = cookies.at(i);
 
448
        if (isOnDomainList(m_exceptions_block, cookie.domain())) {
 
449
            cookies.removeAt(i);
 
450
            changed = true;
 
451
        } else if (isOnDomainList(m_exceptions_allowForSession, cookie.domain())) {
 
452
            const_cast<QNetworkCookie&>(cookie).setExpirationDate(QDateTime());
 
453
            changed = true;
 
454
        }
 
455
    }
 
456
    if (changed) {
 
457
        setAllCookies(cookies);
 
458
        m_saveTimer->changeOccurred();
 
459
        emit cookiesChanged();
 
460
    }
 
461
}
 
462
 
 
463
bool CookieJar::filterTrackingCookies() const
 
464
{
 
465
    return this->m_filterTrackingCookies;
 
466
}
 
467
 
 
468
void CookieJar::setFilterTrackingCookies(bool filterTrackingCookies)
 
469
{
 
470
    this->m_filterTrackingCookies = filterTrackingCookies;
 
471
}
 
472