KIOSlave
http.h
Go to the documentation of this file.
00001 /* 00002 Copyright (C) 2000,2001 Dawit Alemayehu <adawit@kde.org> 00003 Copyright (C) 2000,2001 Waldo Bastian <bastian@kde.org> 00004 Copyright (C) 2000,2001 George Staikos <staikos@kde.org> 00005 Copyright (C) 2001,2002 Hamish Rodda <rodda@kde.org> 00006 Copyright (C) 2007 Daniel Nicoletti <mirttex@users.sourceforge.net> 00007 Copyright (C) 2008,2009 Andreas Hartmetz <ahartmetz@gmail.com> 00008 00009 This library is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU Library General Public 00011 License as published by the Free Software Foundation; either 00012 version 2 of the License, or (at your option) any later version. 00013 00014 This library is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 Library General Public License for more details. 00018 00019 You should have received a copy of the GNU Library General Public License 00020 along with this library; see the file COPYING.LIB. If not, write to 00021 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00022 Boston, MA 02110-1301, USA. 00023 */ 00024 00025 #ifndef HTTP_H_ 00026 #define HTTP_H_ 00027 00028 00029 #include <sys/types.h> 00030 #include <netinet/in.h> 00031 #include <arpa/inet.h> 00032 #include <string.h> 00033 #include <stdio.h> 00034 #include <time.h> 00035 00036 #include <QtCore/QList> 00037 #include <QtCore/QStringList> 00038 #include <QtNetwork/QLocalSocket> 00039 00040 #include <kurl.h> 00041 #include "kio/tcpslavebase.h" 00042 #include "kio/http.h" 00043 00044 00045 class QDomNodeList; 00046 class QFile; 00047 class QIODevice; 00048 00049 namespace KIO { 00050 class AuthInfo; 00051 } 00052 00053 class HeaderTokenizer; 00054 class KAbstractHttpAuthentication; 00055 00056 class HTTPProtocol : public QObject, public KIO::TCPSlaveBase 00057 { 00058 Q_OBJECT 00059 public: 00060 HTTPProtocol( const QByteArray &protocol, const QByteArray &pool, 00061 const QByteArray &app ); 00062 virtual ~HTTPProtocol(); 00063 00065 enum HTTP_REV {HTTP_None, HTTP_Unknown, HTTP_10, HTTP_11, SHOUTCAST}; 00066 00068 enum AUTH_SCHEME {AUTH_None, AUTH_Basic, AUTH_NTLM, AUTH_Digest, AUTH_Negotiate}; 00069 00071 struct DAVRequest 00072 { 00073 DAVRequest () 00074 { 00075 overwrite = false; 00076 depth = 0; 00077 } 00078 00079 QString desturl; 00080 bool overwrite; 00081 int depth; 00082 }; 00083 00084 enum CacheIOMode { 00085 NoCache = 0, 00086 ReadFromCache = 1, 00087 WriteToCache = 2 00088 }; 00089 00090 struct CacheTag 00091 { 00092 CacheTag() 00093 { 00094 useCache = false; 00095 ioMode = NoCache; 00096 bytesCached = 0; 00097 file = 0; 00098 expireDate = 0; 00099 servedDate = 0; 00100 } 00101 00102 enum CachePlan { 00103 UseCached = 0, 00104 ValidateCached, 00105 IgnoreCached 00106 }; 00107 CachePlan plan(time_t maxCacheAge) const; 00108 00109 QByteArray serialize() const; 00110 bool deserialize(const QByteArray &); 00111 00112 KIO::CacheControl policy; // ### initialize in the constructor? 00113 bool useCache; // Whether the cache should be used 00114 enum CacheIOMode ioMode; // Write to cache file, read from it, or don't use it. 00115 quint32 fileUseCount; 00116 quint32 bytesCached; 00117 QString etag; // entity tag header as described in the HTTP standard. 00118 QFile *file; // file on disk - either a QTemporaryFile (write) or QFile (read) 00119 time_t servedDate; // Date when the resource was served by the origin server 00120 time_t lastModifiedDate; // Last modified. 00121 time_t expireDate; // Date when the cache entry will expire 00122 QString charset; 00123 }; 00124 00126 struct HTTPRequest 00127 { 00128 HTTPRequest () 00129 { 00130 method = KIO::HTTP_UNKNOWN; 00131 offset = 0; 00132 endoffset = 0; 00133 allowTransferCompression = false; 00134 disablePassDialog = false; 00135 doNotAuthenticate = false; 00136 preferErrorPage = false; 00137 useCookieJar = false; 00138 } 00139 00140 QByteArray methodString() const; 00141 00142 KUrl url; 00143 QString encoded_hostname; //### can be calculated on-the-fly 00144 // Persistent connections 00145 bool isKeepAlive; 00146 int keepAliveTimeout; // Timeout in seconds. 00147 00148 KIO::HTTP_METHOD method; 00149 QString methodStringOverride; // Overrides method if non-empty. 00150 KIO::filesize_t offset; 00151 KIO::filesize_t endoffset; 00152 QString windowId; // Window Id this request is related to. 00153 // Header fields 00154 QString referrer; 00155 QString charsets; 00156 QString languages; 00157 QString userAgent; 00158 // Previous and current response codes 00159 unsigned int responseCode; 00160 unsigned int prevResponseCode; 00161 // Miscellaneous 00162 QString id; 00163 DAVRequest davData; 00164 KUrl redirectUrl; 00165 KUrl proxyUrl; 00166 QStringList proxyUrls; 00167 00168 bool isPersistentProxyConnection; 00169 bool allowTransferCompression; 00170 bool disablePassDialog; 00171 bool doNotAuthenticate; 00172 // Indicates whether an error page or error message is preferred. 00173 bool preferErrorPage; 00174 00175 // Use the cookie jar (or pass cookies to the application as metadata instead) 00176 bool useCookieJar; 00177 // Cookie flags 00178 enum { CookiesAuto, CookiesManual, CookiesNone } cookieMode; 00179 00180 CacheTag cacheTag; 00181 }; 00182 00184 struct HTTPServerState 00185 { 00186 HTTPServerState() 00187 { 00188 isKeepAlive = false; 00189 isPersistentProxyConnection = false; 00190 } 00191 00192 void initFrom(const HTTPRequest &request) 00193 { 00194 url = request.url; 00195 encoded_hostname = request.encoded_hostname; 00196 isKeepAlive = request.isKeepAlive; 00197 proxyUrl = request.proxyUrl; 00198 isPersistentProxyConnection = request.isPersistentProxyConnection; 00199 } 00200 00201 void updateCredentials(const HTTPRequest &request) 00202 { 00203 if (url.host() == request.url.host() && url.port() == request.url.port()) { 00204 url.setUserName(request.url.userName()); 00205 url.setPassword(request.url.password()); 00206 } 00207 if (proxyUrl.host() == request.proxyUrl.host() && 00208 proxyUrl.port() == request.proxyUrl.port()) { 00209 proxyUrl.setUserName(request.proxyUrl.userName()); 00210 proxyUrl.setPassword(request.proxyUrl.password()); 00211 } 00212 } 00213 00214 void clear() 00215 { 00216 url.clear(); 00217 encoded_hostname.clear(); 00218 proxyUrl.clear(); 00219 isKeepAlive = false; 00220 isPersistentProxyConnection = false; 00221 } 00222 00223 KUrl url; 00224 QString encoded_hostname; 00225 KUrl proxyUrl; 00226 bool isKeepAlive; 00227 bool isPersistentProxyConnection; 00228 }; 00229 00230 //---------------------- Re-implemented methods ---------------- 00231 virtual void setHost(const QString& host, quint16 port, const QString& user, 00232 const QString& pass); 00233 00234 virtual void slave_status(); 00235 00236 virtual void get( const KUrl& url ); 00237 virtual void put( const KUrl& url, int _mode, KIO::JobFlags flags ); 00238 00239 //----------------- Re-implemented methods for WebDAV ----------- 00240 virtual void listDir( const KUrl& url ); 00241 virtual void mkdir( const KUrl& url, int _permissions ); 00242 00243 virtual void rename( const KUrl& src, const KUrl& dest, KIO::JobFlags flags ); 00244 virtual void copy( const KUrl& src, const KUrl& dest, int _permissions, KIO::JobFlags flags ); 00245 virtual void del( const KUrl& url, bool _isfile ); 00246 00247 // ask the host whether it supports WebDAV & cache this info 00248 bool davHostOk(); 00249 00250 // send generic DAV request 00251 void davGeneric( const KUrl& url, KIO::HTTP_METHOD method, qint64 size = -1 ); 00252 00253 // Send requests to lock and unlock resources 00254 void davLock( const KUrl& url, const QString& scope, 00255 const QString& type, const QString& owner ); 00256 void davUnlock( const KUrl& url ); 00257 00258 // Calls httpClose() and finished() 00259 void davFinished(); 00260 00261 // Handle error conditions 00262 QString davError( int code = -1, const QString &url = QString() ); 00263 //---------------------------- End WebDAV ----------------------- 00264 00274 virtual void special( const QByteArray &data ); 00275 00276 virtual void mimetype( const KUrl& url); 00277 00278 virtual void stat( const KUrl& url ); 00279 00280 virtual void reparseConfiguration(); 00281 00285 virtual void closeConnection(); 00286 00287 void post( const KUrl& url, qint64 size = -1 ); 00288 void multiGet(const QByteArray &data); 00289 bool maybeSetRequestUrl(const KUrl &); 00290 00294 void httpPutError(); 00298 bool sendErrorPageNotification(); 00299 00303 bool isOffline(); 00304 00305 protected Q_SLOTS: 00306 void slotData(const QByteArray &); 00307 void slotFilterError(const QString &text); 00308 void error(int errid, const QString &text); 00309 void proxyAuthenticationForSocket(const QNetworkProxy &, QAuthenticator *); 00310 void saveProxyAuthenticationForSocket(); 00311 00312 protected: 00313 int readChunked(); 00314 int readLimited(); 00315 int readUnlimited(); 00316 00321 ssize_t write(const void *buf, size_t nbytes); 00322 using SlaveBase::write; 00323 00329 void addEncoding(const QString &, QStringList &); 00330 00331 quint16 defaultPort() const; 00332 00333 // The methods between here and sendQuery() are helpers for sendQuery(). 00334 00340 bool satisfyRequestFromCache(bool *cacheHasPage); 00341 QString formatRequestUri() const; 00345 QString authenticationHeader(); 00346 bool sendQuery(); 00347 00351 void httpClose(bool keepAlive); 00355 bool httpOpenConnection(); 00359 void httpCloseConnection(); 00363 bool httpShouldCloseConnection(); 00364 00365 void forwardHttpResponseHeader(bool forwardImmediately = true); 00366 00372 void fixupResponseMimetype(); 00378 void fixupResponseContentEncoding(); 00379 00380 bool readResponseHeader(); 00381 bool parseHeaderFromCache(); 00382 void parseContentDisposition(const QString &disposition); 00383 00384 bool sendBody(); 00385 bool sendCachedBody(); 00386 00387 // where dataInternal == true, the content is to be made available 00388 // to an internal function. 00389 bool readBody( bool dataInternal = false ); 00390 00394 void davSetRequest( const QByteArray& requestXML ); 00395 void davStatList( const KUrl& url, bool stat = true ); 00396 void davParsePropstats( const QDomNodeList& propstats, KIO::UDSEntry& entry ); 00397 void davParseActiveLocks( const QDomNodeList& activeLocks, 00398 uint& lockCount ); 00399 00403 long parseDateTime( const QString& input, const QString& type ); 00404 00408 int codeFromResponse( const QString& response ); 00409 00414 QString davProcessLocks(); 00415 00419 void addCookies( const QString &url, const QByteArray &cookieHeader); 00420 00424 QString findCookies( const QString &url); 00425 00426 void cacheParseResponseHeader(const HeaderTokenizer &tokenizer); 00427 00428 QString cacheFilePathFromUrl(const KUrl &url) const; 00429 bool cacheFileOpenRead(); 00430 bool cacheFileOpenWrite(); 00431 void cacheFileClose(); 00432 void sendCacheCleanerCommand(const QByteArray &command); 00433 00434 QByteArray cacheFileReadPayload(int maxLength); 00435 void cacheFileWritePayload(const QByteArray &d); 00436 void cacheFileWriteTextHeader(); 00440 bool cacheFileReadTextHeader1(const KUrl &desiredUrl); 00444 bool cacheFileReadTextHeader2(); 00445 void setCacheabilityMetadata(bool cachingAllowed); 00446 00455 void proceedUntilResponseContent( bool dataInternal = false ); 00456 00460 bool proceedUntilResponseHeader(); 00461 00465 void resetSessionSettings(); 00466 00470 void resetResponseParsing(); 00471 00478 void resetConnectionSettings(); 00479 00486 void cachePostData(const QByteArray&); 00487 00494 void clearPostDataBuffer(); 00495 00499 bool retrieveAllData(); 00500 00501 protected: 00502 HTTPServerState m_server; 00503 HTTPRequest m_request; 00504 QList<HTTPRequest> m_requestQueue; 00505 00506 // Processing related 00507 KIO::filesize_t m_iSize; 00508 KIO::filesize_t m_iPostDataSize; 00509 KIO::filesize_t m_iBytesLeft; 00510 KIO::filesize_t m_iContentLeft; 00511 QByteArray m_receiveBuf; 00512 bool m_dataInternal; 00513 bool m_isChunked; 00514 00515 bool m_isBusy; 00516 bool m_isEOF; 00517 bool m_isEOD; 00518 00519 //--- Settings related to a single response only 00520 bool m_isRedirection; 00521 QStringList m_responseHeaders; 00522 00523 00524 // Language/Encoding related 00525 QStringList m_transferEncodings; 00526 QStringList m_contentEncodings; 00527 QString m_contentMD5; 00528 QString m_mimeType; // TODO QByteArray? 00529 00530 00531 //--- WebDAV 00532 // Data structure to hold data which will be passed to an internal func. 00533 QByteArray m_webDavDataBuf; 00534 QStringList m_davCapabilities; 00535 00536 bool m_davHostOk; 00537 bool m_davHostUnsupported; 00538 //---------- 00539 00540 // Mimetype determination 00541 bool m_cpMimeBuffer; 00542 QByteArray m_mimeTypeBuffer; 00543 00544 00545 // Holds the POST data so it won't get lost on if we 00546 // happend to get a 401/407 response when submitting 00547 // a form. 00548 QIODevice* m_POSTbuf; 00549 00550 // Cache related 00551 int m_maxCacheAge; 00552 long m_maxCacheSize; 00553 QString m_strCacheDir; 00554 QLocalSocket m_cacheCleanerConnection; 00555 00556 // Operation mode 00557 QByteArray m_protocol; 00558 00559 KAbstractHttpAuthentication *m_wwwAuth; 00560 KAbstractHttpAuthentication *m_proxyAuth; 00561 // For proxy auth when it's handled by the Qt/KDE socket classes 00562 QAuthenticator *m_socketProxyAuth; 00563 00564 // Indicates whether there was some connection error. 00565 bool m_isError; 00566 // Whether we are loading an error page (we should close the connection afterwards) 00567 bool m_isLoadingErrorPage; 00568 00569 // Values that determine the remote connection timeouts. 00570 int m_remoteRespTimeout; 00571 00572 QByteArray m_unreadBuf; 00573 void clearUnreadBuffer(); 00574 void unread(char *buf, size_t size); 00575 size_t readBuffered(char *buf, size_t size, bool unlimited = true); 00576 bool readDelimitedText(char *buf, int *idx, int end, int numNewlines); 00577 }; 00578 #endif
KDE 4.7 API Reference