/*
* Copyright ( C ) 2010 - 2013 Groupement d ' Intérêt Public pour l ' Education Numérique en Afrique ( GIP ENA )
*
* This file is part of Open - Sankoré .
*
* Open - Sankoré is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , version 3 of the License ,
* with a specific linking exception for the OpenSSL project ' s
* " OpenSSL " library ( or with modified versions of it that use the
* same license as the " OpenSSL " library ) .
*
* Open - Sankoré is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with Open - Sankoré . If not , see < http : //www.gnu.org/licenses/>.
*/
/****************************************************************************
* *
* * Copyright ( C ) 2009 Nokia Corporation and / or its subsidiary ( - ies ) .
* * Contact : Qt Software Information ( qt - info @ nokia . com )
* *
* * This file is part of the demonstration applications of the Qt Toolkit .
* *
* * $ QT_BEGIN_LICENSE : LGPL $
* * Commercial Usage
* * Licensees holding valid Qt Commercial licenses may use this file in
* * accordance with the Qt Commercial License Agreement provided with the
* * Software or , alternatively , in accordance with the terms contained in
* * a written agreement between you and Nokia .
* *
* * GNU Lesser General Public License Usage
* * Alternatively , this file may be used under the terms of the GNU Lesser
* * General Public License version 2.1 as published by the Free Software
* * Foundation and appearing in the file LICENSE . LGPL included in the
* * packaging of this file . Please review the following information to
* * ensure the GNU Lesser General Public License version 2.1 requirements
* * will be met : http : //www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
* *
* * In addition , as a special exception , Nokia gives you certain
* * additional rights . These rights are described in the Nokia Qt LGPL
* * Exception version 1.0 , included in the file LGPL_EXCEPTION . txt in this
* * package .
* *
* * GNU General Public License Usage
* * Alternatively , this file may be used under the terms of the GNU
* * General Public License version 3.0 as published by the Free Software
* * Foundation and appearing in the file LICENSE . GPL included in the
* * packaging of this file . Please review the following information to
* * ensure the GNU General Public License version 3.0 requirements will be
* * met : http : //www.gnu.org/copyleft/gpl.html.
* *
* * If you are unsure which license is appropriate for your use , please
* * contact the sales department at qt - sales @ nokia . com .
* * $ QT_END_LICENSE $
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "UBCookieJar.h"
# include "UBAutoSaver.h"
# include "core/UBSettings.h"
# include <QtGui>
# include <QtWebKit>
# include "core/memcheck.h"
static const unsigned int JAR_VERSION = 23 ;
QT_BEGIN_NAMESPACE
QDataStream & operator < < ( QDataStream & stream , const QList < QNetworkCookie > & list )
{
stream < < JAR_VERSION ;
stream < < quint32 ( list . size ( ) ) ;
for ( int i = 0 ; i < list . size ( ) ; + + i )
stream < < list . at ( i ) . toRawForm ( ) ;
return stream ;
}
QDataStream & operator > > ( QDataStream & stream , QList < QNetworkCookie > & list )
{
list . clear ( ) ;
quint32 version ;
stream > > version ;
if ( version ! = JAR_VERSION )
return stream ;
quint32 count ;
stream > > count ;
for ( quint32 i = 0 ; i < count ; + + i )
{
QByteArray value ;
stream > > 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 )
list . append ( newCookies . at ( j ) ) ;
if ( stream . atEnd ( ) )
break ;
}
return stream ;
}
QT_END_NAMESPACE
UBCookieJar : : UBCookieJar ( QObject * parent )
: QNetworkCookieJar ( parent )
, mLoaded ( false )
, mSaveTimer ( new UBAutoSaver ( this ) )
, mAcceptCookies ( AcceptOnlyFromSitesNavigatedTo )
{
// NOOP
}
UBCookieJar : : ~ UBCookieJar ( )
{
if ( mKeepCookies = = KeepUntilExit )
clear ( ) ;
mSaveTimer - > saveIfNeccessary ( ) ;
}
void UBCookieJar : : clear ( )
{
setAllCookies ( QList < QNetworkCookie > ( ) ) ;
mSaveTimer - > changeOccurred ( ) ;
emit cookiesChanged ( ) ;
}
void UBCookieJar : : load ( )
{
if ( mLoaded )
return ;
// load cookies and exceptions
qRegisterMetaTypeStreamOperators < QList < QNetworkCookie > > ( " QList<QNetworkCookie> " ) ;
QSettings cookieSettings ( UBSettings : : userDataDirectory ( ) + QLatin1String ( " /cookies.ini " ) , QSettings : : IniFormat ) ;
QVariant vCookies = cookieSettings . value ( QLatin1String ( " cookies " ) ) ;
QList < QNetworkCookie > cookies = qvariant_cast < QList < QNetworkCookie > > ( vCookies ) ;
setAllCookies ( cookies ) ;
cookieSettings . beginGroup ( QLatin1String ( " Exceptions " ) ) ;
mExceptionsBlock = cookieSettings . value ( QLatin1String ( " block " ) ) . toStringList ( ) ;
mExceptionsAllow = cookieSettings . value ( QLatin1String ( " allow " ) ) . toStringList ( ) ;
mExceptionsAllowForSession = cookieSettings . value ( QLatin1String ( " allowForSession " ) ) . toStringList ( ) ;
qSort ( mExceptionsBlock . begin ( ) , mExceptionsBlock . end ( ) ) ;
qSort ( mExceptionsAllow . begin ( ) , mExceptionsAllow . end ( ) ) ;
qSort ( mExceptionsAllowForSession . begin ( ) , mExceptionsAllowForSession . end ( ) ) ;
loadSettings ( ) ;
}
void UBCookieJar : : loadSettings ( )
{
QSettings settings ;
settings . beginGroup ( QLatin1String ( " cookies " ) ) ;
QByteArray value = settings . value ( QLatin1String ( " acceptCookies " ) ,
QLatin1String ( " AcceptOnlyFromSitesNavigatedTo " ) ) . toByteArray ( ) ;
QMetaEnum acceptPolicyEnum = staticMetaObject . enumerator ( staticMetaObject . indexOfEnumerator ( " AcceptPolicy " ) ) ;
mAcceptCookies = acceptPolicyEnum . keyToValue ( value ) = = - 1 ?
AcceptOnlyFromSitesNavigatedTo :
static_cast < AcceptPolicy > ( acceptPolicyEnum . keyToValue ( value ) ) ;
value = settings . value ( QLatin1String ( " keepCookiesUntil " ) , QLatin1String ( " KeepUntilExpire " ) ) . toByteArray ( ) ;
QMetaEnum keepPolicyEnum = staticMetaObject . enumerator ( staticMetaObject . indexOfEnumerator ( " KeepPolicy " ) ) ;
mKeepCookies = keepPolicyEnum . keyToValue ( value ) = = - 1 ?
KeepUntilExpire :
static_cast < KeepPolicy > ( keepPolicyEnum . keyToValue ( value ) ) ;
if ( mKeepCookies = = KeepUntilExit )
setAllCookies ( QList < QNetworkCookie > ( ) ) ;
mLoaded = true ;
emit cookiesChanged ( ) ;
}
void UBCookieJar : : save ( )
{
if ( ! mLoaded )
return ;
purgeOldCookies ( ) ;
QString directory = UBSettings : : userDataDirectory ( ) ;
if ( directory . isEmpty ( ) )
directory = QDir : : homePath ( ) + QLatin1String ( " /. " ) + QCoreApplication : : applicationName ( ) ;
if ( ! QFile : : exists ( directory ) ) {
QDir dir ;
dir . mkpath ( directory ) ;
}
QSettings cookieSettings ( directory + 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 " ) , mExceptionsBlock ) ;
cookieSettings . setValue ( QLatin1String ( " allow " ) , mExceptionsAllow ) ;
cookieSettings . setValue ( QLatin1String ( " allowForSession " ) , mExceptionsAllowForSession ) ;
// save cookie settings
QSettings settings ;
settings . beginGroup ( QLatin1String ( " cookies " ) ) ;
QMetaEnum acceptPolicyEnum = staticMetaObject . enumerator ( staticMetaObject . indexOfEnumerator ( " AcceptPolicy " ) ) ;
settings . setValue ( QLatin1String ( " acceptCookies " ) , QLatin1String ( acceptPolicyEnum . valueToKey ( mAcceptCookies ) ) ) ;
QMetaEnum keepPolicyEnum = staticMetaObject . enumerator ( staticMetaObject . indexOfEnumerator ( " KeepPolicy " ) ) ;
settings . setValue ( QLatin1String ( " keepCookiesUntil " ) , QLatin1String ( keepPolicyEnum . valueToKey ( mKeepCookies ) ) ) ;
}
void UBCookieJar : : 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 > UBCookieJar : : cookiesForUrl ( const QUrl & url ) const
{
UBCookieJar * that = const_cast < UBCookieJar * > ( this ) ;
if ( ! mLoaded )
that - > load ( ) ;
QWebSettings * globalSettings = QWebSettings : : globalSettings ( ) ;
if ( globalSettings - > testAttribute ( QWebSettings : : PrivateBrowsingEnabled ) ) {
QList < QNetworkCookie > noCookies ;
return noCookies ;
}
return QNetworkCookieJar : : cookiesForUrl ( url ) ;
}
bool UBCookieJar : : setCookiesFromUrl ( const QList < QNetworkCookie > & cookieList , const QUrl & url )
{
if ( ! mLoaded )
load ( ) ;
QWebSettings * globalSettings = QWebSettings : : globalSettings ( ) ;
if ( globalSettings - > testAttribute ( QWebSettings : : PrivateBrowsingEnabled ) )
return false ;
QString host = url . host ( ) ;
bool eBlock = qBinaryFind ( mExceptionsBlock . begin ( ) , mExceptionsBlock . end ( ) , host ) ! = mExceptionsBlock . end ( ) ;
bool eAllow = qBinaryFind ( mExceptionsAllow . begin ( ) , mExceptionsAllow . end ( ) , host ) ! = mExceptionsAllow . end ( ) ;
bool eAllowSession = qBinaryFind ( mExceptionsAllowForSession . begin ( ) , mExceptionsAllowForSession . end ( ) , host ) ! = mExceptionsAllowForSession . end ( ) ;
bool addedCookies = false ;
// pass exceptions
bool acceptInitially = ( mAcceptCookies ! = 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 ( mKeepCookies = = KeepUntilTimeLimit
& & ! 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 ( mAcceptCookies = = 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 ) {
mSaveTimer - > changeOccurred ( ) ;
emit cookiesChanged ( ) ;
}
return addedCookies ;
}
UBCookieJar : : AcceptPolicy UBCookieJar : : acceptPolicy ( ) const
{
if ( ! mLoaded )
( const_cast < UBCookieJar * > ( this ) ) - > load ( ) ;
return mAcceptCookies ;
}
void UBCookieJar : : setAcceptPolicy ( AcceptPolicy policy )
{
if ( ! mLoaded )
load ( ) ;
if ( policy = = mAcceptCookies )
return ;
mAcceptCookies = policy ;
mSaveTimer - > changeOccurred ( ) ;
}
UBCookieJar : : KeepPolicy UBCookieJar : : keepPolicy ( ) const
{
if ( ! mLoaded )
( const_cast < UBCookieJar * > ( this ) ) - > load ( ) ;
return mKeepCookies ;
}
void UBCookieJar : : setKeepPolicy ( KeepPolicy policy )
{
if ( ! mLoaded )
load ( ) ;
if ( policy = = mKeepCookies )
return ;
mKeepCookies = policy ;
mSaveTimer - > changeOccurred ( ) ;
}
QStringList UBCookieJar : : blockedCookies ( ) const
{
if ( ! mLoaded )
( const_cast < UBCookieJar * > ( this ) ) - > load ( ) ;
return mExceptionsBlock ;
}
QStringList UBCookieJar : : allowedCookies ( ) const
{
if ( ! mLoaded )
( const_cast < UBCookieJar * > ( this ) ) - > load ( ) ;
return mExceptionsAllow ;
}
QStringList UBCookieJar : : allowForSessionCookies ( ) const
{
if ( ! mLoaded )
( const_cast < UBCookieJar * > ( this ) ) - > load ( ) ;
return mExceptionsAllowForSession ;
}
void UBCookieJar : : setBlockedCookies ( const QStringList & list )
{
if ( ! mLoaded )
load ( ) ;
mExceptionsBlock = list ;
qSort ( mExceptionsBlock . begin ( ) , mExceptionsBlock . end ( ) ) ;
mSaveTimer - > changeOccurred ( ) ;
}
void UBCookieJar : : setAllowedCookies ( const QStringList & list )
{
if ( ! mLoaded )
load ( ) ;
mExceptionsAllow = list ;
qSort ( mExceptionsAllow . begin ( ) , mExceptionsAllow . end ( ) ) ;
mSaveTimer - > changeOccurred ( ) ;
}
void UBCookieJar : : setAllowForSessionCookies ( const QStringList & list )
{
if ( ! mLoaded )
load ( ) ;
mExceptionsAllowForSession = list ;
qSort ( mExceptionsAllowForSession . begin ( ) , mExceptionsAllowForSession . end ( ) ) ;
mSaveTimer - > changeOccurred ( ) ;
}