Home · All Classes · Main Classes · Grouped Classes · Modules · Functions

cookiejar.cpp Example File
demos/browser/cookiejar.cpp

 /****************************************************************************
 **
 ** Copyright (C) 2007-2008 Trolltech ASA. All rights reserved.
 **
 ** This file is part of the documentation of the Qt Toolkit.
 **
 ** This file may be used under the terms of the GNU General Public
** License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file.  Alternatively you may (at
** your option) use any later version of the GNU General Public
** License if such license has been publicly approved by Trolltech ASA
** (or its successors, if any) and the KDE Free Qt Foundation. In
** addition, as a special exception, Trolltech gives you certain
** additional rights. These rights are described in the Trolltech GPL
** Exception version 1.2, which can be found at
** http://www.trolltech.com/products/qt/gplexception/ and in the file
** GPL_EXCEPTION.txt in this package.
**
** Please review the following information to ensure GNU General
** Public Licensing requirements will be met:
** http://trolltech.com/products/qt/licenses/licensing/opensource/. If
** you are unsure which license is appropriate for your use, please
** review the following information:
** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
** or contact the sales department at sales@trolltech.com.
**
** In addition, as a special exception, Trolltech, as the sole
** copyright holder for Qt Designer, grants users of the Qt/Eclipse
** Integration plug-in the right for the Qt/Eclipse Integration to
** link to functionality provided by Qt Designer and its related
** libraries.
**
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE. Trolltech reserves all rights not expressly
** granted herein.
 **
 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 **
 ****************************************************************************/

 #include "cookiejar.h"
 #include "autosave.h"

 #include <QtCore/QSettings>
 #include <QtCore/QDateTime>
 #include <QtCore/QUrl>
 #include <QtCore/QMetaEnum>

 #include <QtGui/QFont>
 #include <QtGui/QHeaderView>
 #include <QtGui/QKeyEvent>
 #include <QtGui/QSortFilterProxyModel>
 #include <QtGui/QFontMetrics>
 #include <QtGui/QCompleter>
 #include <QtGui/QDesktopServices>
 #include <qdebug.h>

 static const unsigned int JAR_VERSION = 23;

 QT_BEGIN_NAMESPACE
 QDataStream &operator<<(QDataStream &s, const QList<QNetworkCookie> &l)
 {
     s << JAR_VERSION;
     s << quint32(l.size());
     for (int i = 0; i < l.size(); ++i)
         s << l.at(i).toRawForm();
     return s;
 }

 QDataStream &operator>>(QDataStream &s, QList<QNetworkCookie> &l)
 {
     l.clear();

     quint32 c;
     s >> c;

     if (c != JAR_VERSION)
         return s;

     s >> c;
     for(quint32 i = 0; i < c; ++i)
     {
         QByteArray value;
         s >> value;
         QList<QNetworkCookie> newCookies = QNetworkCookie::parseCookies(value);
         if (newCookies.count() == 0 && value.length() != 0) {
             qWarning() << "CookieJar: Unable to parse saved cookie:" << value;
         }
         for (int j = 0; j < newCookies.count(); ++j)
             l.append(newCookies.at(j));
         if (s.atEnd())
             break;
     }
     return s;
 }
 QT_END_NAMESPACE

 CookieJar::CookieJar(QObject *parent)
     : QNetworkCookieJar(parent)
     , m_loaded(false)
     , m_saveTimer(new AutoSave(this))
     , m_acceptCookies(AcceptOnlyFromSitesNavigatedTo)
 {
 }

 CookieJar::~CookieJar()
 {
     if (m_keepCookies == Exit)
         clear();
     m_saveTimer->saveNow();
 }

 void CookieJar::clear()
 {
     setAllCookies(QList<QNetworkCookie>());
     m_saveTimer->changed();
     emit cookiesChanged();
 }

 void CookieJar::load()
 {
     if (m_loaded)
         return;

     // load cookies and exceptions
     qRegisterMetaTypeStreamOperators<QList<QNetworkCookie> >("QList<QNetworkCookie>");
     QSettings cookieSettings(QDesktopServices::storageLocation(QDesktopServices::DataLocation) + QLatin1String("/cookies.ini"), QSettings::IniFormat);
     setAllCookies(qvariant_cast<QList<QNetworkCookie> >(cookieSettings.value(QLatin1String("cookies"))));
     cookieSettings.beginGroup(QLatin1String("Exceptions"));
     m_exceptions_block = cookieSettings.value(QLatin1String("block")).toStringList();
     m_exceptions_allow = cookieSettings.value(QLatin1String("allow")).toStringList();
     m_exceptions_allowForSession = cookieSettings.value(QLatin1String("allowForSession")).toStringList();
     qSort(m_exceptions_block.begin(), m_exceptions_block.end());
     qSort(m_exceptions_allow.begin(), m_exceptions_allow.end());
     qSort(m_exceptions_allowForSession.begin(), m_exceptions_allowForSession.end());

     // load cookie settings
     QSettings settings;
     settings.beginGroup("cookies");
     QByteArray value = settings.value(QLatin1String("acceptCookies"), "AcceptOnlyFromSitesNavigatedTo").toByteArray();
     QMetaEnum acceptPolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("AcceptPolicy"));
     m_acceptCookies = acceptPolicyEnum.keyToValue(value) == -1 ?
                         AcceptOnlyFromSitesNavigatedTo :
                         static_cast<AcceptPolicy>(acceptPolicyEnum.keyToValue(value));

     value = settings.value(QLatin1String("keepCookiesUntil"), "Expire").toByteArray();
     QMetaEnum keepPolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("KeepPolicy"));
     m_keepCookies = keepPolicyEnum.keyToValue(value) == -1 ?
                         Expire :
                         static_cast<KeepPolicy>(keepPolicyEnum.keyToValue(value));

     if (m_keepCookies == Exit)
         setAllCookies(QList<QNetworkCookie>());

     m_loaded = true;
     emit cookiesChanged();
 }

 void CookieJar::save()
 {
     if (!m_loaded)
         return;
     purgeOldCookies();
     QSettings cookieSettings(QDesktopServices::storageLocation(QDesktopServices::DataLocation) + QLatin1String("/cookies.ini"), QSettings::IniFormat);
     QList<QNetworkCookie> cookies = allCookies();
     for (int i = cookies.count() - 1; i >= 0; --i) {
         if (cookies.at(i).isSessionCookie())
             cookies.removeAt(i);
     }
     cookieSettings.setValue(QLatin1String("cookies"), qVariantFromValue<QList<QNetworkCookie> >(cookies));
     cookieSettings.beginGroup(QLatin1String("Exceptions"));
     cookieSettings.setValue(QLatin1String("block"), m_exceptions_block);
     cookieSettings.setValue(QLatin1String("allow"), m_exceptions_allow);
     cookieSettings.setValue(QLatin1String("allowForSession"), m_exceptions_allowForSession);

     // save cookie settings
     QSettings settings;
     settings.beginGroup("cookies");
     QMetaEnum acceptPolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("AcceptPolicy"));
     settings.setValue(QLatin1String("acceptCookies"), acceptPolicyEnum.valueToKey(m_acceptCookies));

     QMetaEnum keepPolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("KeepPolicy"));
     settings.setValue(QLatin1String("keepCookiesUntil"), keepPolicyEnum.valueToKey(m_keepCookies));
 }

 void CookieJar::purgeOldCookies()
 {
     QList<QNetworkCookie> cookies = allCookies();
     if (cookies.isEmpty())
         return;
     int oldCount = cookies.count();
     QDateTime now = QDateTime::currentDateTime();
     for (int i = cookies.count() - 1; i >= 0; --i) {
         if (!cookies.at(i).isSessionCookie() && cookies.at(i).expirationDate() < now)
             cookies.removeAt(i);
     }
     if (oldCount == cookies.count())
         return;
     setAllCookies(cookies);
     emit cookiesChanged();
 }

 QList<QNetworkCookie> CookieJar::cookiesForUrl(const QUrl &url) const
 {
     CookieJar *that = const_cast<CookieJar*>(this);
     if (!m_loaded)
         that->load();
     return QNetworkCookieJar::cookiesForUrl(url);
 }

 bool CookieJar::setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url)
 {
     if (!m_loaded)
         load();

     QString host = url.host();
     bool eBlock = qBinaryFind(m_exceptions_block.begin(), m_exceptions_block.end(), host) != m_exceptions_block.end();
     bool eAllow = qBinaryFind(m_exceptions_allow.begin(), m_exceptions_allow.end(), host) != m_exceptions_allow.end();
     bool eAllowSession = qBinaryFind(m_exceptions_allowForSession.begin(), m_exceptions_allowForSession.end(), host) != m_exceptions_allowForSession.end();

     bool addedCookies = false;
     // pass exceptions
     bool acceptInitially = (m_acceptCookies != AcceptNever);
     if ((acceptInitially && !eBlock)
         || (!acceptInitially && (eAllow || eAllowSession))) {
         // pass url domain == cookie domain
         QDateTime soon = QDateTime::currentDateTime();
         soon = soon.addDays(90);
         foreach(QNetworkCookie cookie, cookieList) {
             QList<QNetworkCookie> lst;
             if (m_keepCookies == TimeLimit
                 && !cookie.isSessionCookie()
                 && cookie.expirationDate() > soon) {
                     cookie.setExpirationDate(soon);
             }
             lst += cookie;
             if (QNetworkCookieJar::setCookiesFromUrl(lst, url)) {
                 addedCookies = true;
             } else {
                 // finally force it in if wanted
                 if (m_acceptCookies == AcceptAlways) {
                     QList<QNetworkCookie> cookies = allCookies();
                     cookies += cookie;
                     setAllCookies(cookies);
                     addedCookies = true;
                 }
 #if 0
                 else
                     qWarning() << "setCookiesFromUrl failed" << url << cookieList.value(0).toRawForm();
 #endif
             }
         }
     }

     if (addedCookies) {
         m_saveTimer->changed();
         emit cookiesChanged();
     }
     return addedCookies;
 }

 CookieJar::AcceptPolicy CookieJar::acceptPolicy() const
 {
     if (!m_loaded)
         (const_cast<CookieJar*>(this))->load();
     return m_acceptCookies;
 }

 void CookieJar::setAcceptPolicy(AcceptPolicy policy)
 {
     if (!m_loaded)
         load();
     m_acceptCookies = policy;
     m_saveTimer->changed();
 }

 CookieJar::KeepPolicy CookieJar::keepPolicy() const
 {
     if (!m_loaded)
         (const_cast<CookieJar*>(this))->load();
     return m_keepCookies;
 }

 void CookieJar::setKeepPolicy(KeepPolicy policy)
 {
     if (!m_loaded)
         load();
     m_keepCookies = policy;
     m_saveTimer->changed();
 }

 QStringList CookieJar::blockedCookies() const
 {
     if (!m_loaded)
         (const_cast<CookieJar*>(this))->load();
     return m_exceptions_block;
 }

 QStringList CookieJar::allowedCookies() const
 {
     if (!m_loaded)
         (const_cast<CookieJar*>(this))->load();
     return m_exceptions_allow;
 }

 QStringList CookieJar::allowForSessionCookies() const
 {
     if (!m_loaded)
         (const_cast<CookieJar*>(this))->load();
     return m_exceptions_allowForSession;
 }

 void CookieJar::setBlockedCookies(const QStringList &list)
 {
     if (!m_loaded)
         load();
     m_exceptions_block = list;
     qSort(m_exceptions_block.begin(), m_exceptions_block.end());
     m_saveTimer->changed();
 }

 void CookieJar::setAllowedCookies(const QStringList &list)
 {
     if (!m_loaded)
         load();
     m_exceptions_allow = list;
     qSort(m_exceptions_allow.begin(), m_exceptions_allow.end());
     m_saveTimer->changed();
 }

 void CookieJar::setAllowForSessionCookies(const QStringList &list)
 {
     if (!m_loaded)
         load();
     m_exceptions_allowForSession = list;
     qSort(m_exceptions_allowForSession.begin(), m_exceptions_allowForSession.end());
     m_saveTimer->changed();
 }

 CookieModel::CookieModel(CookieJar *jar, QObject *parent)
     : QAbstractTableModel(parent)
     , m_jar(jar)
 {
     connect(m_jar, SIGNAL(cookiesChanged()), this, SLOT(cookiesChanged()));
     m_jar->load();
 }

 QVariant CookieModel::headerData(int section, Qt::Orientation orientation, int role) const
 {
     if (role == Qt::SizeHintRole) {
         QFont font;
         font.setPointSize(10);
         QFontMetrics fm(font);
         int height = fm.height() + fm.height()/3;
         int width = fm.width(headerData(section, orientation, Qt::DisplayRole).toString());
         return QSize(width, height);
     }

     if (orientation == Qt::Horizontal) {
         if (role != Qt::DisplayRole)
             return QVariant();

         switch (section) {
             case 0:
                 return tr("Website");
             case 1:
                 return tr("Name");
             case 2:
                 return tr("Path");
             case 3:
                 return tr("Secure");
             case 4:
                 return tr("Expires");
             case 5:
                 return tr("Contents");
             default:
                 return QVariant();
         }
     }
     return QAbstractTableModel::headerData(section, orientation, role);
 }

 QVariant CookieModel::data(const QModelIndex &index, int role) const
 {
     QList<QNetworkCookie> lst;
     if (m_jar)
         lst = m_jar->allCookies();
     if (index.row() < 0 || index.row() >= lst.size())
         return QVariant();

     switch (role) {
     case Qt::DisplayRole:
     case Qt::EditRole: {
         QNetworkCookie cookie = lst.at(index.row());
         switch (index.column()) {
             case 0:
                 return cookie.domain();
             case 1:
                 return cookie.name();
             case 2:
                 return cookie.path();
             case 3:
                 return cookie.isSecure();
             case 4:
                 return cookie.expirationDate();
             case 5:
                 return cookie.value();
         }
         }
     case Qt::FontRole:{
         QFont font;
         font.setPointSize(10);
         return font;
         }
     }

     return QVariant();
 }

 int CookieModel::columnCount(const QModelIndex &parent) const
 {
     return (parent.isValid()) ? 0 : 6;
 }

 int CookieModel::rowCount(const QModelIndex &parent) const
 {
     return (parent.isValid() || !m_jar) ? 0 : m_jar->allCookies().count();
 }

 bool CookieModel::removeRows(int row, int count, const QModelIndex &parent)
 {
     if (parent.isValid() || !m_jar)
         return false;
     int lastRow = row + count - 1;
     beginRemoveRows(parent, row, lastRow);
     QList<QNetworkCookie> lst = m_jar->allCookies();
     for (int i = lastRow; i >= row; --i) {
         lst.removeAt(i);
     }
     m_jar->setAllCookies(lst);
     endRemoveRows();
     return true;
 }

 void CookieModel::cookiesChanged()
 {
     reset();
 }

 CookiesDialog::CookiesDialog(CookieJar *cookieJar, QWidget *parent) : QDialog(parent)
 {
     setupUi(this);
     CookieModel *model = new CookieModel(cookieJar, this);
     m_proxyModel = new QSortFilterProxyModel(this);
     connect(search, SIGNAL(textChanged(QString)), m_proxyModel, SLOT(setFilterFixedString(QString)));
     connect(removeButton, SIGNAL(clicked()), cookiesTable, SLOT(removeOne()));
     connect(removeAllButton, SIGNAL(clicked()), cookiesTable, SLOT(removeAll()));
     m_proxyModel->setSourceModel(model);
     cookiesTable->verticalHeader()->hide();
     cookiesTable->setSelectionBehavior(QAbstractItemView::SelectRows);
     cookiesTable->setModel(m_proxyModel);
     cookiesTable->setAlternatingRowColors(true);
     cookiesTable->setTextElideMode(Qt::ElideMiddle);
     cookiesTable->setShowGrid(false);
     cookiesTable->setSortingEnabled(true);
     QFont f = font();
     f.setPointSize(10);
     QFontMetrics fm(f);
     int height = fm.height() + fm.height()/3;
     cookiesTable->verticalHeader()->setDefaultSectionSize(height);
     cookiesTable->verticalHeader()->setMinimumSectionSize(-1);
     for (int i = 0; i < model->columnCount(); ++i){
         int header = cookiesTable->horizontalHeader()->sectionSizeHint(i);
         switch (i) {
         case 0:
             header = fm.width("averagehost.domain.com");
             break;
         case 1:
             header = fm.width("_session_id");
             break;
         case 4:
             header = fm.width(QDateTime::currentDateTime().toString(Qt::LocalDate));
             break;
         }
         int buffer = fm.width("xx");
         header += buffer;
         cookiesTable->horizontalHeader()->resizeSection(i, header);
     }
     cookiesTable->horizontalHeader()->setStretchLastSection(true);
 }

 CookieExceptionsModel::CookieExceptionsModel(CookieJar *cookiejar, QObject *parent)
     : QAbstractTableModel(parent)
     , m_jar(cookiejar)
 {
     m_allowedCookies = m_jar->allowedCookies();
     m_blockedCookies = m_jar->blockedCookies();
     m_sessionCookies = m_jar->allowForSessionCookies();
 }

 QVariant CookieExceptionsModel::headerData(int section, Qt::Orientation orientation, int role) const
 {
     if (role == Qt::SizeHintRole) {
         QFont font;
         font.setPointSize(10);
         QFontMetrics fm(font);
         int height = fm.height() + fm.height()/3;
         int width = fm.width(headerData(section, orientation, Qt::DisplayRole).toString());
         return QSize(width, height);
     }

     if (orientation == Qt::Horizontal
         && role == Qt::DisplayRole) {
         switch (section) {
             case 0:
                 return tr("Website");
             case 1:
                 return tr("Status");
         }
     }
     return QAbstractTableModel::headerData(section, orientation, role);
 }

 QVariant CookieExceptionsModel::data(const QModelIndex &index, int role) const
 {
     if (index.row() < 0 || index.row() >= rowCount())
         return QVariant();

     switch (role) {
     case Qt::DisplayRole:
     case Qt::EditRole: {
         int row = index.row();
         if (row < m_allowedCookies.count()) {
             switch (index.column()) {
                 case 0:
                     return m_allowedCookies.at(row);
                 case 1:
                     return tr("Allow");
             }
         }
         row = row - m_allowedCookies.count();
         if (row < m_blockedCookies.count()) {
             switch (index.column()) {
                 case 0:
                     return m_blockedCookies.at(row);
                 case 1:
                     return tr("Block");
             }
         }
         row = row - m_blockedCookies.count();
         if (row < m_sessionCookies.count()) {
             switch (index.column()) {
                 case 0:
                     return m_sessionCookies.at(row);
                 case 1:
                     return tr("Allow For Session");
             }
         }
         }
     case Qt::FontRole:{
         QFont font;
         font.setPointSize(10);
         return font;
         }
     }
     return QVariant();
 }

 int CookieExceptionsModel::columnCount(const QModelIndex &parent) const
 {
     return (parent.isValid()) ? 0 : 2;
 }

 int CookieExceptionsModel::rowCount(const QModelIndex &parent) const
 {
     return (parent.isValid() || !m_jar) ? 0 : m_allowedCookies.count() + m_blockedCookies.count() + m_sessionCookies.count();
 }

 bool CookieExceptionsModel::removeRows(int row, int count, const QModelIndex &parent)
 {
     if (parent.isValid() || !m_jar)
         return false;

     int lastRow = row + count - 1;
     beginRemoveRows(parent, row, lastRow);
     for (int i = lastRow; i >= row; --i) {
         if (i < m_allowedCookies.count()) {
             m_allowedCookies.removeAt(row);
             continue;
         }
         i = i - m_allowedCookies.count();
         if (i < m_blockedCookies.count()) {
             m_blockedCookies.removeAt(row);
             continue;
         }
         i = i - m_blockedCookies.count();
         if (i < m_sessionCookies.count()) {
             m_sessionCookies.removeAt(row);
             continue;
         }
     }
     m_jar->setAllowedCookies(m_allowedCookies);
     m_jar->setBlockedCookies(m_blockedCookies);
     m_jar->setAllowForSessionCookies(m_sessionCookies);
     endRemoveRows();
     return true;
 }

 CookiesExceptionsDialog::CookiesExceptionsDialog(CookieJar *cookieJar, QWidget *parent)
     : QDialog(parent)
     , m_jar(cookieJar)
 {
     setupUi(this);
     connect(removeButton, SIGNAL(clicked()), exceptionTable, SLOT(removeOne()));
     connect(removeAllButton, SIGNAL(clicked()), exceptionTable, SLOT(removeAll()));
     exceptionTable->verticalHeader()->hide();
     exceptionTable->setSelectionBehavior(QAbstractItemView::SelectRows);
     exceptionTable->setAlternatingRowColors(true);
     exceptionTable->setTextElideMode(Qt::ElideMiddle);
     exceptionTable->setShowGrid(false);
     exceptionTable->setSortingEnabled(true);
     m_model = new CookieExceptionsModel(cookieJar, this);
     m_proxyModel = new QSortFilterProxyModel(this);
     m_proxyModel->setSourceModel(m_model);
     connect(search, SIGNAL(textChanged(QString)), m_proxyModel, SLOT(setFilterFixedString(QString)));
     exceptionTable->setModel(m_proxyModel);

     CookieModel *cookieModel = new CookieModel(cookieJar, this);
     domainLineEdit->setCompleter(new QCompleter(cookieModel, domainLineEdit));

     connect(blockButton, SIGNAL(clicked()), this, SLOT(block()));
     connect(allowButton, SIGNAL(clicked()), this, SLOT(allow()));
     connect(allowForSessionButton, SIGNAL(clicked()), this, SLOT(allowForSession()));

     QFont f = font();
     f.setPointSize(10);
     QFontMetrics fm(f);
     int height = fm.height() + fm.height()/3;
     exceptionTable->verticalHeader()->setDefaultSectionSize(height);
     exceptionTable->verticalHeader()->setMinimumSectionSize(-1);
     for (int i = 0; i < m_model->columnCount(); ++i){
         int header = exceptionTable->horizontalHeader()->sectionSizeHint(i);
         switch (i) {
         case 0:
             header = fm.width("averagebiglonghost.domain.com");
             break;
         case 1:
             header = fm.width("Allow For Session");
             break;
         }
         int buffer = fm.width("xx");
         header += buffer;
         exceptionTable->horizontalHeader()->resizeSection(i, header);
     }
 }

 void CookiesExceptionsDialog::block()
 {
     m_model->m_blockedCookies.append(domainLineEdit->text());
     m_jar->setBlockedCookies(m_model->m_blockedCookies);
     m_model->reset();
 }

 void CookiesExceptionsDialog::allow()
 {
     m_model->m_allowedCookies.append(domainLineEdit->text());
     m_jar->setAllowedCookies(m_model->m_allowedCookies);
     m_model->reset();
 }

 void CookiesExceptionsDialog::allowForSession()
 {
     m_model->m_sessionCookies.append(domainLineEdit->text());
     m_jar->setAllowForSessionCookies(m_model->m_sessionCookies);
     m_model->reset();
 }


Copyright © 2008 Trolltech Trademarks
Qt 4.4.0-beta1