goldendict-ng/article_netmgr.hh
xiaoyifang 8349295b00 fix: rewrite atEnd function
take the code from vedgy's webengine port
2023-03-30 14:41:39 +08:00

215 lines
5.7 KiB
C++

/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#ifndef __ARTICLE_NETMGR_HH_INCLUDED__
#define __ARTICLE_NETMGR_HH_INCLUDED__
#include <QtNetwork>
#include <QSet>
#include <QMap>
#include <QPair>
#include <QWebEngineUrlSchemeHandler>
#include <QWebEngineUrlRequestJob>
#include <QNetworkAccessManager>
#include "dictionary.hh"
#include "article_maker.hh"
using std::vector;
/// A custom QNetworkAccessManager version which fetches images from the
/// dictionaries when requested.
// 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;
QByteArray buffer;
AllowFrameReply();
AllowFrameReply( AllowFrameReply const & );
public:
explicit AllowFrameReply( QNetworkReply * _reply );
~AllowFrameReply()
{ delete baseReply; }
// QNetworkReply virtual functions
void setReadBufferSize( qint64 size );
void close()
{ baseReply->close(); }
// QIODevice virtual functions
qint64 bytesAvailable() const;
bool atEnd() const
{ return baseReply->atEnd(); }
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 );
// void readDataFromBase();
// Redirect QNetworkReply slots
virtual void abort()
{ baseReply->abort(); }
virtual void ignoreSslErrors()
{ baseReply->ignoreSslErrors(); }
void finishedSlot();
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 );
qint64 readLineData( char * data, qint64 maxSize )
{ return baseReply->readLine( data, maxSize ); }
qint64 writeData( const char * data, qint64 maxSize )
{ return baseReply->write( data, maxSize ); }
};
class ArticleNetworkAccessManager: public QNetworkAccessManager
{
Q_OBJECT
vector< sptr< Dictionary::Class > > const & dictionaries;
ArticleMaker const & articleMaker;
bool const & disallowContentFromOtherSites;
bool const & hideGoldenDictHeader;
QMimeDatabase db;
public:
ArticleNetworkAccessManager( QObject * parent,
vector< sptr< Dictionary::Class > > const &
dictionaries_,
ArticleMaker const & articleMaker_,
bool const & disallowContentFromOtherSites_,
bool const & hideGoldenDictHeader_ ):
QNetworkAccessManager( parent ), dictionaries( dictionaries_ ),
articleMaker( articleMaker_ ),
disallowContentFromOtherSites( disallowContentFromOtherSites_ ),
hideGoldenDictHeader( hideGoldenDictHeader_ )
{}
/// Tries handling any kind of internal resources referenced by dictionaries.
/// If it succeeds, the result is a dictionary request object. Otherwise, an
/// empty pointer is returned.
/// The function can optionally set the Content-Type header correspondingly.
sptr< Dictionary::DataRequest > getResource( QUrl const & url,
QString & contentType );
virtual QNetworkReply * getArticleReply( QNetworkRequest const & req );
};
class ArticleResourceReply: public QNetworkReply
{
Q_OBJECT
sptr< Dictionary::DataRequest > req;
qint64 alreadyRead;
QAtomicInt finishSignalSent;
public:
ArticleResourceReply( QObject * parent,
QNetworkRequest const &,
sptr< Dictionary::DataRequest > const &,
QString const & contentType );
~ArticleResourceReply();
protected:
virtual qint64 bytesAvailable() const;
bool atEnd() const override;
virtual void abort()
{}
virtual qint64 readData( char * data, qint64 maxSize );
// We use the hackery below to work around the fact that we need to emit
// ready/finish signals after we've been constructed.
signals:
void readyReadSignal();
void finishedSignal();
private slots:
void reqUpdated();
void reqFinished();
void readyReadSlot();
void finishedSlot();
};
class BlockedNetworkReply: public QNetworkReply
{
Q_OBJECT
public:
BlockedNetworkReply( QObject * parent );
virtual qint64 readData( char *, qint64 )
{
return -1;
}
virtual void abort()
{}
protected:
// We use the hackery below to work around the fact that we need to emit
// ready/finish signals after we've been constructed.
signals:
void finishedSignal();
private slots:
void finishedSlot();
};
class LocalSchemeHandler : public QWebEngineUrlSchemeHandler
{
Q_OBJECT
public:
LocalSchemeHandler( ArticleNetworkAccessManager & articleNetMgr, QObject *parent = nullptr);
void requestStarted( QWebEngineUrlRequestJob * requestJob );
protected:
private:
ArticleNetworkAccessManager & mManager;
QNetworkAccessManager mgr;
};
#endif