mirror of
https://github.com/xiaoyifang/goldendict-ng.git
synced 2024-11-27 23:34:06 +00:00
Websites(Qt 5.2+): Ignore X-Frame-Options header like in Qt 4.x
This commit is contained in:
parent
792b9a4f2f
commit
747185c490
|
@ -16,6 +16,165 @@
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
|
#if QT_VERSION >= 0x050200 // Qt 5.2+
|
||||||
|
|
||||||
|
// SecurityWhiteList
|
||||||
|
|
||||||
|
SecurityWhiteList & SecurityWhiteList::operator=( SecurityWhiteList const & swl )
|
||||||
|
{
|
||||||
|
swlDelete();
|
||||||
|
swlCopy( swl );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWebSecurityOrigin * SecurityWhiteList::setOrigin( QUrl const & url )
|
||||||
|
{
|
||||||
|
swlDelete();
|
||||||
|
originUri = url.toString( QUrl::FullyDecoded );
|
||||||
|
origin = new QWebSecurityOrigin( url );
|
||||||
|
return origin;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SecurityWhiteList::swlCopy( SecurityWhiteList const & swl )
|
||||||
|
{
|
||||||
|
if( swl.origin )
|
||||||
|
{
|
||||||
|
hostsToAccess = swl.hostsToAccess;
|
||||||
|
originUri = swl.originUri;
|
||||||
|
origin = new QWebSecurityOrigin( QUrl( originUri ) );
|
||||||
|
|
||||||
|
for( QSet< QPair< QString, QString > >::iterator it = hostsToAccess.begin();
|
||||||
|
it != hostsToAccess.end(); ++it )
|
||||||
|
origin->addAccessWhitelistEntry( it->first, it->second, QWebSecurityOrigin::AllowSubdomains );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SecurityWhiteList::swlDelete()
|
||||||
|
{
|
||||||
|
if( origin )
|
||||||
|
{
|
||||||
|
for( QSet< QPair< QString, QString > >::iterator it = hostsToAccess.begin();
|
||||||
|
it != hostsToAccess.end(); ++it )
|
||||||
|
origin->removeAccessWhitelistEntry( it->first, it->second, QWebSecurityOrigin::AllowSubdomains );
|
||||||
|
|
||||||
|
delete origin;
|
||||||
|
origin = 0;
|
||||||
|
}
|
||||||
|
hostsToAccess.clear();
|
||||||
|
originUri.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllowFrameReply
|
||||||
|
|
||||||
|
AllowFrameReply::AllowFrameReply( QNetworkReply * _reply ) :
|
||||||
|
baseReply( _reply )
|
||||||
|
{
|
||||||
|
// Set base data
|
||||||
|
|
||||||
|
setOperation( baseReply->operation() );
|
||||||
|
setRequest( baseReply->request() );
|
||||||
|
setUrl( baseReply->url() );
|
||||||
|
|
||||||
|
// Signals to own slots
|
||||||
|
|
||||||
|
connect( baseReply, SIGNAL( metaDataChanged() ), this, SLOT( applyMetaData() ) );
|
||||||
|
|
||||||
|
connect( baseReply, SIGNAL( error( QNetworkReply::NetworkError) ),
|
||||||
|
this, SLOT( applyError( QNetworkReply::NetworkError ) ) );
|
||||||
|
|
||||||
|
// Redirect QNetworkReply signals
|
||||||
|
|
||||||
|
connect( baseReply, SIGNAL( downloadProgress( qint64, qint64 ) ),
|
||||||
|
this, SIGNAL( downloadProgress( qint64, qint64 ) ) );
|
||||||
|
|
||||||
|
connect( baseReply, SIGNAL( encrypted() ), this, SIGNAL( encrypted() ) );
|
||||||
|
|
||||||
|
connect( baseReply, SIGNAL( finished() ), this, SIGNAL( finished() ) );
|
||||||
|
|
||||||
|
connect( baseReply, SIGNAL( preSharedKeyAuthenticationRequired( QSslPreSharedKeyAuthenticator * ) ),
|
||||||
|
this, SIGNAL( preSharedKeyAuthenticationRequired( QSslPreSharedKeyAuthenticator * ) ) );
|
||||||
|
|
||||||
|
connect( baseReply, SIGNAL( redirected( const QUrl & ) ), this, SIGNAL( redirected( const QUrl & ) ) );
|
||||||
|
|
||||||
|
connect( baseReply, SIGNAL( sslErrors( const QList< QSslError > & ) ),
|
||||||
|
this, SIGNAL( sslErrors( const QList< QSslError > & ) ) );
|
||||||
|
|
||||||
|
connect( baseReply, SIGNAL( uploadProgress( qint64, qint64 ) ),
|
||||||
|
this, SIGNAL( uploadProgress( qint64, qint64 ) ) );
|
||||||
|
|
||||||
|
// Redirect QIODevice signals
|
||||||
|
|
||||||
|
connect( baseReply, SIGNAL( aboutToClose() ), this, SIGNAL( aboutToClose() ) );
|
||||||
|
|
||||||
|
connect( baseReply, SIGNAL( bytesWritten( qint64 ) ), this, SIGNAL( bytesWritten( qint64 ) ) );
|
||||||
|
|
||||||
|
connect( baseReply, SIGNAL( readChannelFinished() ), this, SIGNAL( readChannelFinished() ) );
|
||||||
|
|
||||||
|
connect( baseReply, SIGNAL( readyRead() ), this, SIGNAL( readyRead() ) );
|
||||||
|
|
||||||
|
|
||||||
|
setOpenMode( QIODevice::ReadOnly );
|
||||||
|
}
|
||||||
|
|
||||||
|
void AllowFrameReply::applyMetaData()
|
||||||
|
{
|
||||||
|
// Set raw headers except X-Frame-Options
|
||||||
|
QList< QByteArray > rawHeaders = baseReply->rawHeaderList();
|
||||||
|
for( QList< QByteArray >::iterator it = rawHeaders.begin(); it != rawHeaders.end(); ++it )
|
||||||
|
{
|
||||||
|
if( it->toLower() != "x-frame-options" )
|
||||||
|
setRawHeader( *it, baseReply->rawHeader( *it ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set known headers
|
||||||
|
setHeader( QNetworkRequest::ContentDispositionHeader,
|
||||||
|
baseReply->header( QNetworkRequest::ContentDispositionHeader ) );
|
||||||
|
setHeader( QNetworkRequest::ContentTypeHeader,
|
||||||
|
baseReply->header( QNetworkRequest::ContentTypeHeader ) );
|
||||||
|
setHeader( QNetworkRequest::ContentLengthHeader,
|
||||||
|
baseReply->header( QNetworkRequest::ContentLengthHeader ) );
|
||||||
|
setHeader( QNetworkRequest::LocationHeader,
|
||||||
|
baseReply->header( QNetworkRequest::LocationHeader ) );
|
||||||
|
setHeader( QNetworkRequest::LastModifiedHeader,
|
||||||
|
baseReply->header( QNetworkRequest::LastModifiedHeader ) );
|
||||||
|
setHeader( QNetworkRequest::CookieHeader,
|
||||||
|
baseReply->header( QNetworkRequest::CookieHeader ) );
|
||||||
|
setHeader( QNetworkRequest::SetCookieHeader,
|
||||||
|
baseReply->header( QNetworkRequest::SetCookieHeader ) );
|
||||||
|
setHeader( QNetworkRequest::UserAgentHeader,
|
||||||
|
baseReply->header( QNetworkRequest::UserAgentHeader ) );
|
||||||
|
setHeader( QNetworkRequest::ServerHeader,
|
||||||
|
baseReply->header( QNetworkRequest::ServerHeader ) );
|
||||||
|
|
||||||
|
// Set attributes
|
||||||
|
setAttribute( QNetworkRequest::HttpStatusCodeAttribute,
|
||||||
|
baseReply->attribute( QNetworkRequest::HttpStatusCodeAttribute ) );
|
||||||
|
setAttribute( QNetworkRequest::HttpReasonPhraseAttribute,
|
||||||
|
baseReply->attribute( QNetworkRequest::HttpReasonPhraseAttribute ) );
|
||||||
|
setAttribute( QNetworkRequest::RedirectionTargetAttribute,
|
||||||
|
baseReply->attribute( QNetworkRequest::RedirectionTargetAttribute ) );
|
||||||
|
setAttribute( QNetworkRequest::ConnectionEncryptedAttribute,
|
||||||
|
baseReply->attribute( QNetworkRequest::ConnectionEncryptedAttribute ) );
|
||||||
|
setAttribute( QNetworkRequest::SourceIsFromCacheAttribute,
|
||||||
|
baseReply->attribute( QNetworkRequest::SourceIsFromCacheAttribute ) );
|
||||||
|
setAttribute( QNetworkRequest::HttpPipeliningWasUsedAttribute,
|
||||||
|
baseReply->attribute( QNetworkRequest::HttpPipeliningWasUsedAttribute ) );
|
||||||
|
setAttribute( QNetworkRequest::BackgroundRequestAttribute,
|
||||||
|
baseReply->attribute( QNetworkRequest::BackgroundRequestAttribute ) );
|
||||||
|
setAttribute( QNetworkRequest::SpdyWasUsedAttribute,
|
||||||
|
baseReply->attribute( QNetworkRequest::SpdyWasUsedAttribute ) );
|
||||||
|
|
||||||
|
emit metaDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AllowFrameReply::applyError( QNetworkReply::NetworkError code )
|
||||||
|
{
|
||||||
|
setError( code, baseReply->errorString() );
|
||||||
|
emit error( code );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
/// Uses some heuristics to chop off the first domain name from the host name,
|
/// Uses some heuristics to chop off the first domain name from the host name,
|
||||||
|
@ -69,7 +228,7 @@ QNetworkReply * ArticleNetworkAccessManager::createRequest( Operation op,
|
||||||
return QNetworkAccessManager::createRequest( op, newReq, outgoingData );
|
return QNetworkAccessManager::createRequest( op, newReq, outgoingData );
|
||||||
}
|
}
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5,2,0)
|
#if QT_VERSION >= 0x050200 // Qt 5.2+
|
||||||
// Workaround of same-origin policy
|
// Workaround of same-origin policy
|
||||||
if( ( req.url().scheme().startsWith( "http" ) || req.url().scheme() == "ftp" )
|
if( ( req.url().scheme().startsWith( "http" ) || req.url().scheme() == "ftp" )
|
||||||
&& req.hasRawHeader( "Referer" ) )
|
&& req.hasRawHeader( "Referer" ) )
|
||||||
|
@ -171,7 +330,11 @@ QNetworkReply * ArticleNetworkAccessManager::createRequest( Operation op,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if QT_VERSION >= 0x050200 // Qt 5.2+
|
||||||
|
return new AllowFrameReply( reply );
|
||||||
|
#else
|
||||||
return reply;
|
return reply;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
sptr< Dictionary::DataRequest > ArticleNetworkAccessManager::getResource(
|
sptr< Dictionary::DataRequest > ArticleNetworkAccessManager::getResource(
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#include <QtNetwork>
|
#include <QtNetwork>
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5,2,0)
|
#if QT_VERSION >= 0x050200 // Qt 5.2+
|
||||||
#include <QWebSecurityOrigin>
|
#include <QWebSecurityOrigin>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
|
@ -21,7 +21,7 @@ using std::vector;
|
||||||
/// A custom QNetworkAccessManager version which fetches images from the
|
/// A custom QNetworkAccessManager version which fetches images from the
|
||||||
/// dictionaries when requested.
|
/// dictionaries when requested.
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5,2,0)
|
#if QT_VERSION >= 0x050200 // Qt 5.2+
|
||||||
|
|
||||||
// White lists for QWebSecurityOrigin
|
// White lists for QWebSecurityOrigin
|
||||||
struct SecurityWhiteList
|
struct SecurityWhiteList
|
||||||
|
@ -35,64 +35,92 @@ struct SecurityWhiteList
|
||||||
{}
|
{}
|
||||||
|
|
||||||
~SecurityWhiteList()
|
~SecurityWhiteList()
|
||||||
{
|
{ swlDelete(); }
|
||||||
swlDelete();
|
|
||||||
}
|
|
||||||
SecurityWhiteList( SecurityWhiteList const & swl ) :
|
SecurityWhiteList( SecurityWhiteList const & swl ) :
|
||||||
origin( 0 )
|
origin( 0 )
|
||||||
{
|
{ swlCopy( swl ); }
|
||||||
swlCopy( swl );
|
|
||||||
}
|
|
||||||
|
|
||||||
SecurityWhiteList & operator=( SecurityWhiteList const & swl )
|
SecurityWhiteList & operator=( SecurityWhiteList const & swl );
|
||||||
{
|
QWebSecurityOrigin * setOrigin( QUrl const & url );
|
||||||
swlDelete();
|
|
||||||
swlCopy( swl );
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
QWebSecurityOrigin * setOrigin( QUrl const & url )
|
|
||||||
{
|
|
||||||
swlDelete();
|
|
||||||
originUri = url.toString( QUrl::FullyDecoded );
|
|
||||||
origin = new QWebSecurityOrigin( url );
|
|
||||||
return origin;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void swlCopy( SecurityWhiteList const & swl );
|
||||||
void swlCopy( SecurityWhiteList const & swl )
|
void swlDelete();
|
||||||
{
|
|
||||||
if( swl.origin )
|
|
||||||
{
|
|
||||||
hostsToAccess = swl.hostsToAccess;
|
|
||||||
originUri = swl.originUri;
|
|
||||||
origin = new QWebSecurityOrigin( QUrl( originUri ) );
|
|
||||||
|
|
||||||
for( QSet< QPair< QString, QString > >::iterator it = hostsToAccess.begin();
|
|
||||||
it != hostsToAccess.end(); ++it )
|
|
||||||
origin->addAccessWhitelistEntry( it->first, it->second, QWebSecurityOrigin::AllowSubdomains );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void swlDelete()
|
|
||||||
{
|
|
||||||
if( origin )
|
|
||||||
{
|
|
||||||
for( QSet< QPair< QString, QString > >::iterator it = hostsToAccess.begin();
|
|
||||||
it != hostsToAccess.end(); ++it )
|
|
||||||
origin->removeAccessWhitelistEntry( it->first, it->second, QWebSecurityOrigin::AllowSubdomains );
|
|
||||||
|
|
||||||
delete origin;
|
|
||||||
origin = 0;
|
|
||||||
}
|
|
||||||
hostsToAccess.clear();
|
|
||||||
originUri.clear();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef QMap< QString, SecurityWhiteList > Origins;
|
typedef QMap< QString, SecurityWhiteList > Origins;
|
||||||
|
|
||||||
|
// Proxy class for QNetworkReply to remove X-Frame-Options header
|
||||||
|
// It allow to show websites in <iframe> tag like Qt 4.x
|
||||||
|
|
||||||
|
class AllowFrameReply : public QNetworkReply
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
private:
|
||||||
|
QNetworkReply * baseReply;
|
||||||
|
|
||||||
|
AllowFrameReply();
|
||||||
|
AllowFrameReply( AllowFrameReply const & );
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit AllowFrameReply( QNetworkReply * _reply );
|
||||||
|
~AllowFrameReply()
|
||||||
|
{ delete baseReply; }
|
||||||
|
|
||||||
|
// QNetworkReply virtual functions
|
||||||
|
void setReadBufferSize( qint64 size )
|
||||||
|
{ baseReply->setReadBufferSize( size ); }
|
||||||
|
void close()
|
||||||
|
{ baseReply->close(); }
|
||||||
|
|
||||||
|
// QIODevice virtual functions
|
||||||
|
bool atEnd() const
|
||||||
|
{ return baseReply->atEnd(); }
|
||||||
|
qint64 bytesAvailable() const
|
||||||
|
{ return baseReply->bytesAvailable(); }
|
||||||
|
qint64 bytesToWrite() const
|
||||||
|
{ return baseReply->bytesToWrite(); }
|
||||||
|
bool canReadLine() const
|
||||||
|
{ return baseReply->canReadLine(); }
|
||||||
|
bool isSequential() const
|
||||||
|
{ return baseReply->isSequential(); }
|
||||||
|
bool waitForReadyRead( int msecs )
|
||||||
|
{ return baseReply->waitForReadyRead( msecs ); }
|
||||||
|
bool waitForBytesWritten( int msecs )
|
||||||
|
{ return baseReply->waitForBytesWritten( msecs ); }
|
||||||
|
bool reset()
|
||||||
|
{ return baseReply->reset(); }
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
// Own AllowFrameReply slots
|
||||||
|
void applyMetaData();
|
||||||
|
void applyError( QNetworkReply::NetworkError code );
|
||||||
|
|
||||||
|
// Redirect QNetworkReply slots
|
||||||
|
virtual void abort()
|
||||||
|
{ baseReply->abort(); }
|
||||||
|
virtual void ignoreSslErrors()
|
||||||
|
{ baseReply->ignoreSslErrors(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// QNetworkReply virtual functions
|
||||||
|
void ignoreSslErrorsImplementation( const QList< QSslError > & errors )
|
||||||
|
{ baseReply->ignoreSslErrors( errors ); }
|
||||||
|
void setSslConfigurationImplementation( const QSslConfiguration & configuration )
|
||||||
|
{ baseReply->setSslConfiguration( configuration ); }
|
||||||
|
void sslConfigurationImplementation( QSslConfiguration & configuration ) const
|
||||||
|
{ configuration = baseReply->sslConfiguration(); }
|
||||||
|
|
||||||
|
// QIODevice virtual functions
|
||||||
|
qint64 readData( char * data, qint64 maxSize )
|
||||||
|
{ return baseReply->read( data, maxSize ); }
|
||||||
|
qint64 readLineData( char * data, qint64 maxSize )
|
||||||
|
{ return baseReply->readLine( data, maxSize ); }
|
||||||
|
qint64 writeData( const char * data, qint64 maxSize )
|
||||||
|
{ return baseReply->write( data, maxSize ); }
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class ArticleNetworkAccessManager: public QNetworkAccessManager
|
class ArticleNetworkAccessManager: public QNetworkAccessManager
|
||||||
|
@ -101,7 +129,7 @@ class ArticleNetworkAccessManager: public QNetworkAccessManager
|
||||||
ArticleMaker const & articleMaker;
|
ArticleMaker const & articleMaker;
|
||||||
bool const & disallowContentFromOtherSites;
|
bool const & disallowContentFromOtherSites;
|
||||||
bool const & hideGoldenDictHeader;
|
bool const & hideGoldenDictHeader;
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5,2,0)
|
#if QT_VERSION >= 0x050200 // Qt 5.2+
|
||||||
Origins allOrigins;
|
Origins allOrigins;
|
||||||
#endif
|
#endif
|
||||||
public:
|
public:
|
||||||
|
|
Loading…
Reference in a new issue