Warning, file /frameworks/kio/src/kioworkers/http/http.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2000, 2001 Dawit Alemayehu <adawit@kde.org> 0003 SPDX-FileCopyrightText: 2000, 2001 Waldo Bastian <bastian@kde.org> 0004 SPDX-FileCopyrightText: 2000, 2001 George Staikos <staikos@kde.org> 0005 SPDX-FileCopyrightText: 2001, 2002 Hamish Rodda <rodda@kde.org> 0006 SPDX-FileCopyrightText: 2007 Daniel Nicoletti <mirttex@users.sourceforge.net> 0007 SPDX-FileCopyrightText: 2008, 2009 Andreas Hartmetz <ahartmetz@gmail.com> 0008 SPDX-FileCopyrightText: 2022 Harald Sitter <sitter@kde.org> 0009 0010 SPDX-License-Identifier: LGPL-2.0-or-later 0011 */ 0012 0013 #ifndef HTTP_H 0014 #define HTTP_H 0015 0016 #include <QDateTime> 0017 #include <QList> 0018 #include <QLocalSocket> 0019 #include <QStringList> 0020 #include <QUrl> 0021 0022 #include "httpmethod_p.h" 0023 #include "kio/tcpworkerbase.h" 0024 0025 class QDomNodeList; 0026 class QFile; 0027 class QIODevice; 0028 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0029 class QNetworkConfigurationManager; 0030 #endif 0031 0032 namespace KIO 0033 { 0034 class AuthInfo; 0035 } 0036 0037 class HeaderTokenizer; 0038 class KAbstractHttpAuthentication; 0039 0040 class HTTPProtocol : public QObject, public KIO::TCPWorkerBase 0041 { 0042 Q_OBJECT 0043 public: 0044 HTTPProtocol(const QByteArray &protocol, const QByteArray &pool, const QByteArray &app); 0045 ~HTTPProtocol() override; 0046 0047 /** HTTP version **/ 0048 enum HTTP_REV { HTTP_None, HTTP_Unknown, HTTP_10, HTTP_11, SHOUTCAST }; 0049 0050 /** Authorization method used **/ 0051 enum AUTH_SCHEME { AUTH_None, AUTH_Basic, AUTH_NTLM, AUTH_Digest, AUTH_Negotiate }; 0052 0053 /** DAV-specific request elements for the current connection **/ 0054 struct DAVRequest { 0055 DAVRequest() 0056 { 0057 overwrite = false; 0058 depth = 0; 0059 } 0060 0061 QString desturl; 0062 bool overwrite; 0063 int depth; 0064 }; 0065 0066 enum CacheIOMode { 0067 NoCache = 0, 0068 ReadFromCache = 1, 0069 WriteToCache = 2, 0070 }; 0071 0072 struct CacheTag { 0073 CacheTag() 0074 { 0075 useCache = false; 0076 ioMode = NoCache; 0077 bytesCached = 0; 0078 file = nullptr; 0079 } 0080 0081 enum CachePlan { 0082 UseCached = 0, 0083 ValidateCached, 0084 IgnoreCached, 0085 }; 0086 // int maxCacheAge refers to seconds 0087 CachePlan plan(int maxCacheAge) const; 0088 0089 QByteArray serialize() const; 0090 bool deserialize(const QByteArray &); 0091 0092 KIO::CacheControl policy; // ### initialize in the constructor? 0093 bool useCache; // Whether the cache should be used 0094 enum CacheIOMode ioMode; // Write to cache file, read from it, or don't use it. 0095 quint32 fileUseCount; 0096 quint32 bytesCached; 0097 QString etag; // entity tag header as described in the HTTP standard. 0098 QFile *file; // file on disk - either a QTemporaryFile (write) or QFile (read) 0099 QDateTime servedDate; // Date when the resource was served by the origin server 0100 QDateTime lastModifiedDate; // Last modified. 0101 QDateTime expireDate; // Date when the cache entry will expire 0102 QString charset; 0103 }; 0104 0105 /** The request for the current connection **/ 0106 struct HTTPRequest { 0107 HTTPRequest() 0108 { 0109 method = KIO::HTTP_UNKNOWN; 0110 offset = 0; 0111 endoffset = 0; 0112 allowTransferCompression = false; 0113 disablePassDialog = false; 0114 doNotWWWAuthenticate = false; 0115 doNotProxyAuthenticate = false; 0116 preferErrorPage = false; 0117 useCookieJar = false; 0118 } 0119 0120 QByteArray methodString() const; 0121 0122 QUrl url; 0123 QString encoded_hostname; // ### can be calculated on-the-fly 0124 // Persistent connections 0125 bool isKeepAlive; 0126 int keepAliveTimeout; // Timeout in seconds. 0127 0128 KIO::HTTP_METHOD method; 0129 QString methodStringOverride; // Overrides method if non-empty. 0130 QByteArray sentMethodString; // Stores http method actually sent 0131 KIO::filesize_t offset; 0132 KIO::filesize_t endoffset; 0133 QString windowId; // Window Id this request is related to. 0134 // Header fields 0135 QString referrer; 0136 QString charsets; 0137 QString languages; 0138 QString userAgent; 0139 // Previous and current response codes 0140 unsigned int responseCode; 0141 unsigned int prevResponseCode; 0142 // Miscellaneous 0143 QString id; 0144 DAVRequest davData; 0145 QUrl redirectUrl; 0146 QUrl proxyUrl; 0147 QStringList proxyUrls; 0148 0149 bool isPersistentProxyConnection; 0150 bool allowTransferCompression; 0151 bool disablePassDialog; 0152 bool doNotWWWAuthenticate; 0153 bool doNotProxyAuthenticate; 0154 // Indicates whether an error page or error message is preferred. 0155 bool preferErrorPage; 0156 0157 // Use the cookie jar (or pass cookies to the application as metadata instead) 0158 bool useCookieJar; 0159 // Cookie flags 0160 enum { CookiesAuto, CookiesManual, CookiesNone } cookieMode; 0161 0162 CacheTag cacheTag; 0163 }; 0164 0165 /** State of the current connection to the server **/ 0166 struct HTTPServerState { 0167 HTTPServerState() 0168 { 0169 isKeepAlive = false; 0170 isPersistentProxyConnection = false; 0171 } 0172 0173 void initFrom(const HTTPRequest &request) 0174 { 0175 url = request.url; 0176 encoded_hostname = request.encoded_hostname; 0177 isKeepAlive = request.isKeepAlive; 0178 proxyUrl = request.proxyUrl; 0179 isPersistentProxyConnection = request.isPersistentProxyConnection; 0180 } 0181 0182 void updateCredentials(const HTTPRequest &request) 0183 { 0184 if (url.host() == request.url.host() && url.port() == request.url.port()) { 0185 url.setUserName(request.url.userName()); 0186 url.setPassword(request.url.password()); 0187 } 0188 if (proxyUrl.host() == request.proxyUrl.host() && proxyUrl.port() == request.proxyUrl.port()) { 0189 proxyUrl.setUserName(request.proxyUrl.userName()); 0190 proxyUrl.setPassword(request.proxyUrl.password()); 0191 } 0192 } 0193 0194 void clear() 0195 { 0196 url.clear(); 0197 encoded_hostname.clear(); 0198 proxyUrl.clear(); 0199 isKeepAlive = false; 0200 isPersistentProxyConnection = false; 0201 } 0202 0203 QUrl url; 0204 QString encoded_hostname; 0205 QUrl proxyUrl; 0206 bool isKeepAlive; 0207 bool isPersistentProxyConnection; 0208 }; 0209 0210 //---------------------- Re-implemented methods ---------------- 0211 virtual void setHost(const QString &host, quint16 port, const QString &user, const QString &pass) override; 0212 0213 void worker_status() override; 0214 0215 KIO::WorkerResult get(const QUrl &url) override; 0216 KIO::WorkerResult put(const QUrl &url, int _mode, KIO::JobFlags flags) override; 0217 0218 //----------------- Re-implemented methods for WebDAV ----------- 0219 KIO::WorkerResult listDir(const QUrl &url) override; 0220 KIO::WorkerResult mkdir(const QUrl &url, int _permissions) override; 0221 0222 KIO::WorkerResult rename(const QUrl &src, const QUrl &dest, KIO::JobFlags flags) override; 0223 KIO::WorkerResult copy(const QUrl &src, const QUrl &dest, int _permissions, KIO::JobFlags flags) override; 0224 KIO::WorkerResult del(const QUrl &url, bool _isfile) override; 0225 0226 // ask the host whether it supports WebDAV & cache this info 0227 Q_REQUIRED_RESULT KIO::WorkerResult davHostOk(); 0228 0229 // send generic DAV request 0230 Q_REQUIRED_RESULT KIO::WorkerResult davGeneric(const QUrl &url, KIO::HTTP_METHOD method, qint64 size = -1); 0231 0232 // Send requests to lock and unlock resources 0233 Q_REQUIRED_RESULT KIO::WorkerResult davLock(const QUrl &url, const QString &scope, const QString &type, const QString &owner); 0234 Q_REQUIRED_RESULT KIO::WorkerResult davUnlock(const QUrl &url); 0235 0236 // Calls httpClose() and finished() 0237 Q_REQUIRED_RESULT KIO::WorkerResult davFinished(); 0238 0239 // Handle error conditions 0240 Q_REQUIRED_RESULT KIO::WorkerResult davError(int code = -1, const QString &url = QString()); 0241 Q_REQUIRED_RESULT KIO::WorkerResult davError(QString &errorMsg, int code = -1, const QString &url = QString()); 0242 //---------------------------- End WebDAV ----------------------- 0243 0244 /** 0245 * Special commands supported by this worker : 0246 * 1 - HTTP POST 0247 * 2 - Cache has been updated 0248 * 3 - SSL Certificate Cache has been updated 0249 * 4 - HTTP multi get 0250 * 5 - DAV LOCK (see 0251 * 6 - DAV UNLOCK README.webdav) 0252 */ 0253 KIO::WorkerResult special(const QByteArray &data) override; 0254 0255 KIO::WorkerResult mimetype(const QUrl &url) override; 0256 0257 KIO::WorkerResult stat(const QUrl &url) override; 0258 0259 void reparseConfiguration() override; 0260 0261 /** 0262 * Forced close of connection 0263 */ 0264 void closeConnection() override; 0265 0266 Q_REQUIRED_RESULT KIO::WorkerResult post(const QUrl &url, qint64 size = -1); 0267 KIO::WorkerResult multiGet(const QByteArray &data) override; 0268 Q_REQUIRED_RESULT KIO::WorkerResult maybeSetRequestUrl(const QUrl &); 0269 0270 /** 0271 * Generate and send error message based on response code. 0272 */ 0273 Q_REQUIRED_RESULT KIO::WorkerResult sendHttpError(); 0274 0275 /** 0276 * Call WorkerBase::errorPage() and remember that we've called it 0277 */ 0278 bool sendErrorPageNotification(); 0279 0280 /** 0281 * Check network status 0282 */ 0283 bool isOffline(); 0284 0285 protected Q_SLOTS: 0286 void slotData(const QByteArray &); 0287 Q_REQUIRED_RESULT KIO::WorkerResult slotFilterError(const QString &text); 0288 Q_REQUIRED_RESULT KIO::WorkerResult error(int errid, const QString &text); 0289 Q_REQUIRED_RESULT KIO::WorkerResult proxyAuthenticationForSocket(const QNetworkProxy &, QAuthenticator *); 0290 void saveProxyAuthenticationForSocket(); 0291 0292 protected: 0293 int readChunked(); ///< Read a chunk 0294 int readLimited(); ///< Read maximum m_iSize bytes. 0295 int readUnlimited(); ///< Read as much as possible. 0296 0297 /** 0298 * A thin wrapper around TCPWorkerBase::write() that will retry writing as 0299 * long as no error occurs. 0300 */ 0301 ssize_t write(const void *buf, size_t nbytes); 0302 using WorkerBase::write; 0303 0304 /** 0305 * Add an encoding on to the appropriate stack this 0306 * is necessary because transfer encodings and 0307 * content encodings must be handled separately. 0308 */ 0309 void addEncoding(const QString &, QStringList &); 0310 0311 quint16 defaultPort() const; 0312 0313 // The methods between here and sendQuery() are helpers for sendQuery(). 0314 0315 /** 0316 * Return true if the request is already "done", false otherwise. 0317 * 0318 * @p cacheHasPage will be set to true if the page was found, false otherwise. 0319 */ 0320 Q_REQUIRED_RESULT bool satisfyRequestFromCache(bool *cacheHasPage, KIO::WorkerResult &result); 0321 QString formatRequestUri() const; 0322 /** 0323 * create HTTP authentications response(s), if any 0324 */ 0325 QString authenticationHeader(); 0326 Q_REQUIRED_RESULT KIO::WorkerResult sendQuery(); 0327 0328 /** 0329 * Close transfer 0330 */ 0331 void httpClose(bool keepAlive); 0332 /** 0333 * Open connection 0334 */ 0335 Q_REQUIRED_RESULT KIO::WorkerResult httpOpenConnection(); 0336 /** 0337 * Close connection 0338 */ 0339 void httpCloseConnection(); 0340 /** 0341 * Check whether to keep or close the connection. 0342 */ 0343 bool httpShouldCloseConnection(); 0344 0345 void forwardHttpResponseHeader(bool forwardImmediately = true); 0346 0347 /** 0348 * fix common MIME type errors by webservers. 0349 * 0350 * Helper for readResponseHeader(). 0351 */ 0352 void fixupResponseMimetype(); 0353 /** 0354 * fix common content-encoding errors by webservers. 0355 * 0356 * Helper for readResponseHeader(). 0357 */ 0358 void fixupResponseContentEncoding(); 0359 0360 Q_REQUIRED_RESULT KIO::WorkerResult readResponseHeader(); 0361 bool parseHeaderFromCache(); 0362 void parseContentDisposition(const QString &disposition); 0363 0364 Q_REQUIRED_RESULT KIO::WorkerResult sendBody(); 0365 Q_REQUIRED_RESULT KIO::WorkerResult sendCachedBody(); 0366 0367 // where dataInternal == true, the content is to be made available 0368 // to an internal function. 0369 Q_REQUIRED_RESULT KIO::WorkerResult readBody(bool dataInternal = false); 0370 0371 /** 0372 * Performs a WebDAV stat or list 0373 */ 0374 void davSetRequest(const QByteArray &requestXML); 0375 Q_REQUIRED_RESULT KIO::WorkerResult davStatList(const QUrl &url, bool stat = true); 0376 void davParsePropstats(const QDomNodeList &propstats, KIO::UDSEntry &entry); 0377 void davParseActiveLocks(const QDomNodeList &activeLocks, uint &lockCount); 0378 0379 /** 0380 * Parses a date & time string 0381 */ 0382 QDateTime parseDateTime(const QString &input, const QString &type); 0383 0384 /** 0385 * Returns the error code from a "HTTP/1.1 code Code Name" string 0386 */ 0387 int codeFromResponse(const QString &response); 0388 0389 /** 0390 * Extracts locks from metadata 0391 * Returns the appropriate If: header 0392 */ 0393 QString davProcessLocks(); 0394 0395 /** 0396 * Send a cookie to the cookiejar 0397 */ 0398 void addCookies(const QString &url, const QByteArray &cookieHeader); 0399 0400 /** 0401 * Look for cookies in the cookiejar 0402 */ 0403 QString findCookies(const QString &url); 0404 0405 void cacheParseResponseHeader(const HeaderTokenizer &tokenizer); 0406 0407 QString cacheFilePathFromUrl(const QUrl &url) const; 0408 bool cacheFileOpenRead(); 0409 bool cacheFileOpenWrite(); 0410 void cacheFileClose(); 0411 void sendCacheCleanerCommand(const QByteArray &command); 0412 0413 QByteArray cacheFileReadPayload(int maxLength); 0414 void cacheFileWritePayload(const QByteArray &d); 0415 void cacheFileWriteTextHeader(); 0416 /** 0417 * check URL to guard against hash collisions, and load the etag for validation 0418 */ 0419 bool cacheFileReadTextHeader1(const QUrl &desiredUrl); 0420 /** 0421 * load the rest of the text fields 0422 */ 0423 bool cacheFileReadTextHeader2(); 0424 void setCacheabilityMetadata(bool cachingAllowed); 0425 0426 /** 0427 * Do everything proceedUntilResponseHeader does, and also get the response body. 0428 * This is being used as a replacement for proceedUntilResponseHeader() in 0429 * situations where we actually expect the response to have a body / payload data. 0430 * 0431 * where dataInternal == true, the content is to be made available 0432 * to an internal function. 0433 */ 0434 Q_REQUIRED_RESULT KIO::WorkerResult proceedUntilResponseContent(bool dataInternal = false); 0435 0436 /** 0437 * Ensure we are connected, send our query, and get the response header. 0438 */ 0439 Q_REQUIRED_RESULT KIO::WorkerResult proceedUntilResponseHeader(); 0440 0441 /** 0442 * Resets any per session settings. 0443 */ 0444 void resetSessionSettings(); 0445 0446 /** 0447 * Resets variables related to parsing a response. 0448 */ 0449 void resetResponseParsing(); 0450 0451 /** 0452 * Resets any per connection settings. These are different from 0453 * per-session settings in that they must be invalidated every time 0454 * a request is made, e.g. a retry to re-send the header to the 0455 * server, as compared to only when a new request arrives. 0456 */ 0457 void resetConnectionSettings(); 0458 0459 /** 0460 * Caches the POST data in a temporary buffer. 0461 * 0462 * Depending on size of content, the temporary buffer might be 0463 * created either in memory or on disk as (a temporary file). 0464 */ 0465 void cachePostData(const QByteArray &); 0466 0467 /** 0468 * Clears the POST data buffer. 0469 * 0470 * Note that calling this function results in the POST data buffer 0471 * getting completely deleted. 0472 */ 0473 void clearPostDataBuffer(); 0474 0475 /** 0476 * Returns true on successful retrieval of all content data. 0477 */ 0478 Q_REQUIRED_RESULT KIO::WorkerResult retrieveAllData(); 0479 0480 /** 0481 * Saves HTTP authentication data. 0482 */ 0483 void saveAuthenticationData(); 0484 0485 /** 0486 * Handles HTTP authentication. 0487 */ 0488 bool handleAuthenticationHeader(const HeaderTokenizer *tokenizer); 0489 0490 /** 0491 * Handles file -> webdav put requests. 0492 */ 0493 Q_REQUIRED_RESULT KIO::WorkerResult copyPut(const QUrl &src, const QUrl &dest, KIO::JobFlags flags); 0494 0495 /** 0496 * Stats a remote DAV file and returns true if it already exists. 0497 */ 0498 bool davDestinationExists(); 0499 0500 KIO::WorkerResult fileSystemFreeSpace(const QUrl &url) override; 0501 0502 protected: 0503 /* This stores information about the credentials already tried 0504 * during the authentication stage (in case the auth method uses 0505 * a username and password). Initially the job-provided credentials 0506 * are used (if any). In case of failure the credential cache is 0507 * queried and if this fails the user is asked to provide credentials 0508 * interactively (unless forbidden by metadata) */ 0509 enum TriedCredentials { 0510 NoCredentials = 0, 0511 JobCredentials, 0512 CachedCredentials, 0513 UserInputCredentials, 0514 }; 0515 0516 HTTPServerState m_server; 0517 HTTPRequest m_request; 0518 QList<HTTPRequest> m_requestQueue; 0519 0520 // Processing related 0521 KIO::filesize_t m_iSize; ///< Expected size of message 0522 KIO::filesize_t m_iPostDataSize; 0523 KIO::filesize_t m_iBytesLeft; ///< # of bytes left to receive in this message. 0524 KIO::filesize_t m_iContentLeft; ///< # of content bytes left 0525 QByteArray m_receiveBuf; ///< Receive buffer 0526 bool m_dataInternal; ///< Data is for internal consumption 0527 bool m_isChunked; ///< Chunked transfer encoding 0528 0529 bool m_isBusy; ///< Busy handling request queue. 0530 bool m_isEOF; 0531 bool m_isEOD; 0532 0533 //--- Settings related to a single response only 0534 bool m_isRedirection; ///< Indicates current request is a redirection 0535 QStringList m_responseHeaders; ///< All headers 0536 0537 // Language/Encoding related 0538 QStringList m_transferEncodings; 0539 QStringList m_contentEncodings; 0540 QString m_contentMD5; 0541 QString m_mimeType; // TODO QByteArray? 0542 0543 //--- WebDAV 0544 // Data structure to hold data which will be passed to an internal func. 0545 QByteArray m_webDavDataBuf; 0546 QStringList m_davCapabilities; 0547 0548 bool m_davHostOk; 0549 bool m_davHostUnsupported; 0550 //---------- 0551 0552 // Mimetype determination 0553 bool m_cpMimeBuffer; 0554 QByteArray m_mimeTypeBuffer; 0555 0556 // Holds the POST data so it won't get lost on if we 0557 // happened to get a 401/407 response when submitting 0558 // a form. 0559 QIODevice *m_POSTbuf; 0560 0561 // Cache related 0562 int m_maxCacheAge; ///< Maximum age of a cache entry in seconds. 0563 long m_maxCacheSize; ///< Maximum cache size in Kb. 0564 QString m_strCacheDir; ///< Location of the cache. 0565 QLocalSocket m_cacheCleanerConnection; ///< Connection to the cache cleaner process 0566 0567 // Operation mode 0568 QByteArray m_protocol; 0569 0570 KAbstractHttpAuthentication *m_wwwAuth; 0571 QList<QByteArray> m_blacklistedWwwAuthMethods; 0572 TriedCredentials m_triedWwwCredentials; 0573 KAbstractHttpAuthentication *m_proxyAuth; 0574 QList<QByteArray> m_blacklistedProxyAuthMethods; 0575 TriedCredentials m_triedProxyCredentials; 0576 // For proxy auth when it's handled by the Qt/KDE socket classes 0577 QAuthenticator *m_socketProxyAuth; 0578 0579 // To know if we are online or not 0580 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0581 QNetworkConfigurationManager *m_networkConfig = nullptr; 0582 #endif 0583 0584 // The current KIO error on this request / response pair - zero / KJob::NoError if no error 0585 int m_kioError; 0586 QString m_kioErrorString; 0587 // Whether we are loading an error page (body of a reply with error response code) 0588 bool m_isLoadingErrorPage; 0589 0590 // Values that determine the remote connection timeouts. 0591 int m_remoteRespTimeout; 0592 0593 // EOF Retry count 0594 quint8 m_iEOFRetryCount; 0595 0596 QByteArray m_unreadBuf; 0597 void clearUnreadBuffer(); 0598 void unread(char *buf, size_t size); 0599 size_t readBuffered(char *buf, size_t size, bool unlimited = true); 0600 bool readDelimitedText(char *buf, int *idx, int end, int numNewlines); 0601 }; 0602 #endif