goldendict-ng/src/article_netmgr.hh
shenleban tongying 618310f772
Some checks are pending
SonarCloud / Build and analyze (push) Waiting to run
clean: just use #pragma once
2024-11-06 22:53:04 -05:00

244 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 */
#pragma once
#include <QtNetwork>
#include <QSet>
#include <QMap>
#include <QWebEngineUrlSchemeHandler>
#include <QWebEngineUrlRequestJob>
#include <QNetworkAccessManager>
#include <utility>
#include "dict/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;
}
void close() override
{
baseReply->close();
}
// QIODevice virtual functions
qint64 bytesAvailable() const override;
bool atEnd() const override
{
return baseReply->atEnd();
}
qint64 bytesToWrite() const override
{
return baseReply->bytesToWrite();
}
bool canReadLine() const override
{
return baseReply->canReadLine();
}
bool isSequential() const override
{
return baseReply->isSequential();
}
bool waitForReadyRead( int msecs ) override
{
return baseReply->waitForReadyRead( msecs );
}
bool waitForBytesWritten( int msecs ) override
{
return baseReply->waitForBytesWritten( msecs );
}
bool reset() override
{
return baseReply->reset();
}
public slots:
void applyError( QNetworkReply::NetworkError code );
// Redirect QNetworkReply slots
void abort() override
{
baseReply->abort();
}
void ignoreSslErrors() override
{
baseReply->ignoreSslErrors();
}
protected:
// QNetworkReply virtual functions
void ignoreSslErrorsImplementation( const QList< QSslError > & errors ) override
{
baseReply->ignoreSslErrors( errors );
}
void setSslConfigurationImplementation( const QSslConfiguration & configuration ) override
{
baseReply->setSslConfiguration( configuration );
}
void sslConfigurationImplementation( QSslConfiguration & configuration ) const override
{
configuration = baseReply->sslConfiguration();
}
// QIODevice virtual functions
qint64 readData( char * data, qint64 maxSize ) override;
qint64 readLineData( char * data, qint64 maxSize ) override
{
return baseReply->readLine( data, maxSize );
}
qint64 writeData( const char * data, qint64 maxSize ) override
{
return baseReply->write( data, maxSize );
}
};
enum class ResourceType {
UNTITLE,
WELCOME,
BLANK
};
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 );
string getHtml( ResourceType resourceType );
};
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 override;
bool atEnd() const override;
virtual void abort() override {}
virtual qint64 readData( char * data, qint64 maxSize ) override;
// 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;
};