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 // HeaderTokenizer declarations 00045 #include "parsinghelpers.h" 00046 // KHttpAuthentication & KHttpAuthenticationOutcome declarations 00047 #include "httpauthentication.h" 00048 00049 class QDomNodeList; 00050 class QFile; 00051 00052 namespace KIO { 00053 class AuthInfo; 00054 } 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 proxyUrl; 00165 KUrl redirectUrl; 00166 bool isPersistentProxyConnection; 00167 bool allowTransferCompression; 00168 bool disablePassDialog; 00169 bool doNotAuthenticate; 00170 // Indicates whether an error page or error message is preferred. 00171 bool preferErrorPage; 00172 00173 // Use the cookie jar (or pass cookies to the application as metadata instead) 00174 bool useCookieJar; 00175 // Cookie flags 00176 enum { CookiesAuto, CookiesManual, CookiesNone } cookieMode; 00177 00178 CacheTag cacheTag; 00179 }; 00180 00182 struct HTTPServerState 00183 { 00184 HTTPServerState() 00185 { 00186 isKeepAlive = false; 00187 isPersistentProxyConnection = false; 00188 } 00189 00190 void initFrom(const HTTPRequest &request) 00191 { 00192 url = request.url; 00193 encoded_hostname = request.encoded_hostname; 00194 isKeepAlive = request.isKeepAlive; 00195 proxyUrl = request.proxyUrl; 00196 isPersistentProxyConnection = request.isPersistentProxyConnection; 00197 } 00198 00199 void updateCredentials(const HTTPRequest &request) 00200 { 00201 if (url.host() == request.url.host() && url.port() == request.url.port()) { 00202 url.setUserName(request.url.userName()); 00203 url.setPassword(request.url.password()); 00204 } 00205 if (proxyUrl.host() == request.proxyUrl.host() && 00206 proxyUrl.port() == request.proxyUrl.port()) { 00207 proxyUrl.setUserName(request.proxyUrl.userName()); 00208 proxyUrl.setPassword(request.proxyUrl.password()); 00209 } 00210 } 00211 00212 void clear() 00213 { 00214 url.clear(); 00215 encoded_hostname.clear(); 00216 proxyUrl.clear(); 00217 isKeepAlive = false; 00218 isPersistentProxyConnection = false; 00219 } 00220 00221 KUrl url; 00222 QString encoded_hostname; 00223 KUrl proxyUrl; 00224 bool isKeepAlive; 00225 bool isPersistentProxyConnection; 00226 }; 00227 00228 //---------------------- Re-implemented methods ---------------- 00229 virtual void setHost(const QString& host, quint16 port, const QString& user, 00230 const QString& pass); 00231 00232 virtual void slave_status(); 00233 00234 virtual void get( const KUrl& url ); 00235 virtual void put( const KUrl& url, int _mode, KIO::JobFlags flags ); 00236 00237 //----------------- Re-implemented methods for WebDAV ----------- 00238 virtual void listDir( const KUrl& url ); 00239 virtual void mkdir( const KUrl& url, int _permissions ); 00240 00241 virtual void rename( const KUrl& src, const KUrl& dest, KIO::JobFlags flags ); 00242 virtual void copy( const KUrl& src, const KUrl& dest, int _permissions, KIO::JobFlags flags ); 00243 virtual void del( const KUrl& url, bool _isfile ); 00244 00245 // ask the host whether it supports WebDAV & cache this info 00246 bool davHostOk(); 00247 00248 // send generic DAV request 00249 void davGeneric( const KUrl& url, KIO::HTTP_METHOD method ); 00250 00251 // Send requests to lock and unlock resources 00252 void davLock( const KUrl& url, const QString& scope, 00253 const QString& type, const QString& owner ); 00254 void davUnlock( const KUrl& url ); 00255 00256 // Calls httpClose() and finished() 00257 void davFinished(); 00258 00259 // Handle error conditions 00260 QString davError( int code = -1, const QString &url = QString() ); 00261 //---------------------------- End WebDAV ----------------------- 00262 00272 virtual void special( const QByteArray &data ); 00273 00274 virtual void mimetype( const KUrl& url); 00275 00276 virtual void stat( const KUrl& url ); 00277 00278 virtual void reparseConfiguration(); 00279 00280 virtual void closeConnection(); // Forced close of connection 00281 00282 void post( const KUrl& url ); 00283 void multiGet(const QByteArray &data); 00284 bool maybeSetRequestUrl(const KUrl &); 00285 00286 void httpPutError(); // Generate error message based on response code 00287 bool sendErrorPageNotification(); // Call SlaveBase::errorPage() and remember that we've called it 00288 00289 bool isOffline(); // Check network status 00290 00291 protected Q_SLOTS: 00292 void slotData(const QByteArray &); 00293 void slotFilterError(const QString &text); 00294 void error(int errid, const QString &text); 00295 void proxyAuthenticationForSocket(const QNetworkProxy &, QAuthenticator *); 00296 void saveProxyAuthenticationForSocket(); 00297 00298 protected: 00299 int readChunked(); // Read a chunk 00300 int readLimited(); // Read maximum m_iSize bytes. 00301 int readUnlimited(); // Read as much as possible. 00302 00307 ssize_t write(const void *buf, size_t nbytes); 00308 using SlaveBase::write; 00309 00315 void addEncoding(const QString &, QStringList &); 00316 00317 quint16 defaultPort() const; 00318 00319 // The methods between here and sendQuery() are helpers for sendQuery(). 00320 00321 // Return true if the request is already "done", false otherwise. 00322 // *sucesss will be set to true if the page was found, false otherwise. 00323 bool satisfyRequestFromCache(bool *cacheHasPage); 00324 QString formatRequestUri() const; 00325 // create HTTP authentications response(s), if any 00326 QString authenticationHeader(); 00327 bool sendQuery(); 00328 00329 void httpClose(bool keepAlive); // Close transfer 00330 bool httpOpenConnection(); // Open connection 00331 void httpCloseConnection(); // Close connection 00332 bool httpShouldCloseConnection(); // Check whether to keep or close the connection. 00333 00334 void forwardHttpResponseHeader(bool forwardImmediately = true); 00335 00336 // Helpers for readResponseHeader - fix common mimetype/content-encoding errors by webservers. 00337 void fixupResponseMimetype(); 00338 void fixupResponseContentEncoding(); 00339 00340 bool readResponseHeader(); 00341 bool parseHeaderFromCache(); 00342 void parseContentDisposition(const QString &disposition); 00343 00344 bool sendBody(); 00345 00346 // where dataInternal == true, the content is to be made available 00347 // to an internal function. 00348 bool readBody( bool dataInternal = false ); 00349 00353 void davSetRequest( const QByteArray& requestXML ); 00354 void davStatList( const KUrl& url, bool stat = true ); 00355 void davParsePropstats( const QDomNodeList& propstats, KIO::UDSEntry& entry ); 00356 void davParseActiveLocks( const QDomNodeList& activeLocks, 00357 uint& lockCount ); 00358 00362 long parseDateTime( const QString& input, const QString& type ); 00363 00367 int codeFromResponse( const QString& response ); 00368 00373 QString davProcessLocks(); 00374 00378 void addCookies( const QString &url, const QByteArray &cookieHeader); 00379 00383 QString findCookies( const QString &url); 00384 00385 void cacheParseResponseHeader(const HeaderTokenizer &tokenizer); 00386 00387 QString cacheFilePathFromUrl(const KUrl &url) const; 00388 bool cacheFileOpenRead(); 00389 bool cacheFileOpenWrite(); 00390 void cacheFileClose(); 00391 void sendCacheCleanerCommand(const QByteArray &command); 00392 00393 QByteArray cacheFileReadPayload(int maxLength); 00394 void cacheFileWritePayload(const QByteArray &d); 00395 void cacheFileWriteTextHeader(); 00396 // check URL to guard against hash collisions, and load the etag for validation 00397 bool cacheFileReadTextHeader1(const KUrl &desiredUrl); 00398 // load the rest of the text fields 00399 bool cacheFileReadTextHeader2(); 00400 void setCacheabilityMetadata(bool cachingAllowed); 00401 00407 // where dataInternal == true, the content is to be made available 00408 // to an internal function. 00409 void proceedUntilResponseContent( bool dataInternal = false ); 00410 00414 bool proceedUntilResponseHeader(); 00415 00419 void resetSessionSettings(); 00420 00424 void resetResponseParsing(); 00425 00432 void resetConnectionSettings(); 00433 00434 protected: 00435 HTTPServerState m_server; 00436 HTTPRequest m_request; 00437 QList<HTTPRequest> m_requestQueue; 00438 00439 // Processing related 00440 KIO::filesize_t m_iSize; // Expected size of message 00441 KIO::filesize_t m_iBytesLeft; // # of bytes left to receive in this message. 00442 KIO::filesize_t m_iContentLeft; // # of content bytes left 00443 QByteArray m_receiveBuf; // Receive buffer 00444 bool m_dataInternal; // Data is for internal consumption 00445 bool m_isChunked; // Chunked transfer encoding 00446 00447 bool m_isBusy; // Busy handling request queue. 00448 bool m_isEOF; 00449 bool m_isEOD; 00450 00451 //--- Settings related to a single response only 00452 bool m_isRedirection; // Indicates current request is a redirection 00453 QStringList m_responseHeaders; // All headers 00454 00455 00456 // Language/Encoding related 00457 QStringList m_transferEncodings; 00458 QStringList m_contentEncodings; 00459 QString m_contentMD5; 00460 QString m_mimeType; // TODO QByteArray? 00461 00462 00463 //--- WebDAV 00464 // Data structure to hold data which will be passed to an internal func. 00465 QByteArray m_webDavDataBuf; 00466 QStringList m_davCapabilities; 00467 00468 bool m_davHostOk; 00469 bool m_davHostUnsupported; 00470 //---------- 00471 00472 // Mimetype determination 00473 bool m_cpMimeBuffer; 00474 QByteArray m_mimeTypeBuffer; 00475 00476 00477 // Holds the POST data so it won't get lost on if we 00478 // happend to get a 401/407 response when submitting 00479 // a form. 00480 QByteArray m_POSTbuf; 00481 00482 // Cache related 00483 int m_maxCacheAge; // Maximum age of a cache entry. 00484 long m_maxCacheSize; // Maximum cache size in Kb. 00485 QString m_strCacheDir; // Location of the cache. 00486 QLocalSocket m_cacheCleanerConnection; // Connection to the cache cleaner process 00487 00488 // Operation mode 00489 QByteArray m_protocol; 00490 00491 KAbstractHttpAuthentication *m_wwwAuth; 00492 KAbstractHttpAuthentication *m_proxyAuth; 00493 // For proxy auth when it's handled by the Qt/KDE socket classes 00494 QAuthenticator *m_socketProxyAuth; 00495 00496 // Indicates whether there was some connection error. 00497 bool m_isError; 00498 // Whether we are loading an error page (we should close the connection afterwards) 00499 bool m_isLoadingErrorPage; 00500 00501 // Values that determine the remote connection timeouts. 00502 int m_remoteRespTimeout; 00503 00504 QByteArray m_unreadBuf; 00505 void clearUnreadBuffer(); 00506 void unread(char *buf, size_t size); 00507 size_t readBuffered(char *buf, size_t size, bool unlimited = true); 00508 bool readDelimitedText(char *buf, int *idx, int end, int numNewlines); 00509 }; 00510 #endif
KDE 4.6 API Reference