1 /* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org> 2 * Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */ 3 4 #ifndef __ARTICLE_NETMGR_HH_INCLUDED__ 5 #define __ARTICLE_NETMGR_HH_INCLUDED__ 6 7 #include <QtNetwork> 8 9 #if QT_VERSION >= 0x050300 // Qt 5.3+ 10 #include <QWebSecurityOrigin> 11 #include <QSet> 12 #include <QMap> 13 #include <QPair> 14 #endif 15 16 #include "dictionary.hh" 17 #include "article_maker.hh" 18 19 using std::vector; 20 21 /// A custom QNetworkAccessManager version which fetches images from the 22 /// dictionaries when requested. 23 24 #if QT_VERSION >= 0x050300 // Qt 5.3+ 25 26 // White lists for QWebSecurityOrigin 27 struct SecurityWhiteList 28 { 29 QWebSecurityOrigin * origin; 30 QString originUri; 31 QSet< QPair< QString, QString > > hostsToAccess; 32 SecurityWhiteListSecurityWhiteList33 SecurityWhiteList() : 34 origin( 0 ) 35 {} 36 ~SecurityWhiteListSecurityWhiteList37 ~SecurityWhiteList() 38 { swlDelete(); } 39 SecurityWhiteListSecurityWhiteList40 SecurityWhiteList( SecurityWhiteList const & swl ) : 41 origin( 0 ) 42 { swlCopy( swl ); } 43 44 SecurityWhiteList & operator=( SecurityWhiteList const & swl ); 45 QWebSecurityOrigin * setOrigin( QUrl const & url ); 46 47 private: 48 void swlCopy( SecurityWhiteList const & swl ); 49 void swlDelete(); 50 }; 51 52 typedef QMap< QString, SecurityWhiteList > Origins; 53 54 // Proxy class for QNetworkReply to remove X-Frame-Options header 55 // It allow to show websites in <iframe> tag like Qt 4.x 56 57 class AllowFrameReply : public QNetworkReply 58 { 59 Q_OBJECT 60 private: 61 QNetworkReply * baseReply; 62 QByteArray buffer; 63 64 AllowFrameReply(); 65 AllowFrameReply( AllowFrameReply const & ); 66 67 public: 68 explicit AllowFrameReply( QNetworkReply * _reply ); ~AllowFrameReply()69 ~AllowFrameReply() 70 { delete baseReply; } 71 72 // QNetworkReply virtual functions 73 void setReadBufferSize( qint64 size ); close()74 void close() 75 { baseReply->close(); } 76 77 // QIODevice virtual functions 78 qint64 bytesAvailable() const; atEnd() const79 bool atEnd() const 80 { return baseReply->atEnd(); } bytesToWrite() const81 qint64 bytesToWrite() const 82 { return baseReply->bytesToWrite(); } canReadLine() const83 bool canReadLine() const 84 { return baseReply->canReadLine(); } isSequential() const85 bool isSequential() const 86 { return baseReply->isSequential(); } waitForReadyRead(int msecs)87 bool waitForReadyRead( int msecs ) 88 { return baseReply->waitForReadyRead( msecs ); } waitForBytesWritten(int msecs)89 bool waitForBytesWritten( int msecs ) 90 { return baseReply->waitForBytesWritten( msecs ); } reset()91 bool reset() 92 { return baseReply->reset(); } 93 94 public slots: 95 96 // Own AllowFrameReply slots 97 void applyMetaData(); 98 void applyError( QNetworkReply::NetworkError code ); 99 void readDataFromBase(); 100 101 // Redirect QNetworkReply slots abort()102 virtual void abort() 103 { baseReply->abort(); } ignoreSslErrors()104 virtual void ignoreSslErrors() 105 { baseReply->ignoreSslErrors(); } 106 107 protected: 108 // QNetworkReply virtual functions ignoreSslErrorsImplementation(const QList<QSslError> & errors)109 void ignoreSslErrorsImplementation( const QList< QSslError > & errors ) 110 { baseReply->ignoreSslErrors( errors ); } setSslConfigurationImplementation(const QSslConfiguration & configuration)111 void setSslConfigurationImplementation( const QSslConfiguration & configuration ) 112 { baseReply->setSslConfiguration( configuration ); } sslConfigurationImplementation(QSslConfiguration & configuration) const113 void sslConfigurationImplementation( QSslConfiguration & configuration ) const 114 { configuration = baseReply->sslConfiguration(); } 115 116 // QIODevice virtual functions 117 qint64 readData( char * data, qint64 maxSize ); readLineData(char * data,qint64 maxSize)118 qint64 readLineData( char * data, qint64 maxSize ) 119 { return baseReply->readLine( data, maxSize ); } writeData(const char * data,qint64 maxSize)120 qint64 writeData( const char * data, qint64 maxSize ) 121 { return baseReply->write( data, maxSize ); } 122 }; 123 #endif 124 125 class ArticleNetworkAccessManager: public QNetworkAccessManager 126 { 127 vector< sptr< Dictionary::Class > > const & dictionaries; 128 ArticleMaker const & articleMaker; 129 bool const & disallowContentFromOtherSites; 130 bool const & hideGoldenDictHeader; 131 #if QT_VERSION >= 0x050300 // Qt 5.3+ 132 Origins allOrigins; 133 #endif 134 public: 135 ArticleNetworkAccessManager(QObject * parent,vector<sptr<Dictionary::Class>> const & dictionaries_,ArticleMaker const & articleMaker_,bool const & disallowContentFromOtherSites_,bool const & hideGoldenDictHeader_)136 ArticleNetworkAccessManager( QObject * parent, 137 vector< sptr< Dictionary::Class > > const & 138 dictionaries_, 139 ArticleMaker const & articleMaker_, 140 bool const & disallowContentFromOtherSites_, 141 bool const & hideGoldenDictHeader_ ): 142 QNetworkAccessManager( parent ), dictionaries( dictionaries_ ), 143 articleMaker( articleMaker_ ), 144 disallowContentFromOtherSites( disallowContentFromOtherSites_ ), 145 hideGoldenDictHeader( hideGoldenDictHeader_ ) 146 {} 147 148 /// Tries handling any kind of internal resources referenced by dictionaries. 149 /// If it succeeds, the result is a dictionary request object. Otherwise, an 150 /// empty pointer is returned. 151 /// The function can optionally set the Content-Type header correspondingly. 152 sptr< Dictionary::DataRequest > getResource( QUrl const & url, 153 QString & contentType ); 154 155 protected: 156 157 virtual QNetworkReply * createRequest( Operation op, 158 QNetworkRequest const & req, 159 QIODevice * outgoingData ); 160 }; 161 162 class ArticleResourceReply: public QNetworkReply 163 { 164 Q_OBJECT 165 166 sptr< Dictionary::DataRequest > req; 167 qint64 alreadyRead; 168 169 public: 170 171 ArticleResourceReply( QObject * parent, 172 QNetworkRequest const &, 173 sptr< Dictionary::DataRequest > const &, 174 QString const & contentType ); 175 176 ~ArticleResourceReply(); 177 178 protected: 179 180 virtual qint64 bytesAvailable() const; 181 abort()182 virtual void abort() 183 {} 184 virtual qint64 readData( char * data, qint64 maxSize ); 185 186 // We use the hackery below to work around the fact that we need to emit 187 // ready/finish signals after we've been constructed. 188 signals: 189 190 void readyReadSignal(); 191 void finishedSignal(); 192 193 private slots: 194 195 void reqUpdated(); 196 void reqFinished(); 197 198 void readyReadSlot(); 199 void finishedSlot(); 200 }; 201 202 class BlockedNetworkReply: public QNetworkReply 203 { 204 Q_OBJECT 205 206 public: 207 208 BlockedNetworkReply( QObject * parent ); 209 readData(char *,qint64)210 virtual qint64 readData( char *, qint64 ) 211 { 212 return -1; 213 } 214 abort()215 virtual void abort() 216 {} 217 218 protected: 219 220 // We use the hackery below to work around the fact that we need to emit 221 // ready/finish signals after we've been constructed. 222 223 signals: 224 225 void finishedSignal(); 226 227 private slots: 228 229 void finishedSlot(); 230 }; 231 232 #endif 233