Qt 4.8
qnetworkaccesshttpbackend.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtNetwork module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 //#define QNETWORKACCESSHTTPBACKEND_DEBUG
43 
46 #include "qnetworkaccesscache_p.h"
47 #include "qabstractnetworkcache.h"
48 #include "qnetworkrequest.h"
49 #include "qnetworkreply.h"
50 #include "QtNetwork/private/qnetworksession_p.h"
51 #include "qnetworkrequest_p.h"
52 #include "qnetworkcookie_p.h"
53 #include "QtCore/qdatetime.h"
54 #include "QtCore/qelapsedtimer.h"
55 #include "QtNetwork/qsslconfiguration.h"
56 #include "qhttpthreaddelegate_p.h"
57 #include "qthread.h"
58 
59 #ifndef QT_NO_HTTP
60 
61 #include <string.h> // for strchr
62 
64 
66 
67 class QNetworkProxy;
68 
69 static inline bool isSeparator(register char c)
70 {
71  static const char separators[] = "()<>@,;:\\\"/[]?={}";
72  return isLWS(c) || strchr(separators, c) != 0;
73 }
74 
75 // ### merge with nextField in cookiejar.cpp
77 {
78  // The HTTP header is of the form:
79  // header = #1(directives)
80  // directives = token | value-directive
81  // value-directive = token "=" (token | quoted-string)
83 
84  int pos = 0;
85  while (true) {
86  // skip spaces
87  pos = nextNonWhitespace(header, pos);
88  if (pos == header.length())
89  return result; // end of parsing
90 
91  // pos points to a non-whitespace
92  int comma = header.indexOf(',', pos);
93  int equal = header.indexOf('=', pos);
94  if (comma == pos || equal == pos)
95  // huh? Broken header.
96  return result;
97 
98  // The key name is delimited by either a comma, an equal sign or the end
99  // of the header, whichever comes first
100  int end = comma;
101  if (end == -1)
102  end = header.length();
103  if (equal != -1 && end > equal)
104  end = equal; // equal sign comes before comma/end
105  QByteArray key = QByteArray(header.constData() + pos, end - pos).trimmed().toLower();
106  pos = end + 1;
107 
108  if (uint(equal) < uint(comma)) {
109  // case: token "=" (token | quoted-string)
110  // skip spaces
111  pos = nextNonWhitespace(header, pos);
112  if (pos == header.length())
113  // huh? Broken header
114  return result;
115 
116  QByteArray value;
117  value.reserve(header.length() - pos);
118  if (header.at(pos) == '"') {
119  // case: quoted-string
120  // quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
121  // qdtext = <any TEXT except <">>
122  // quoted-pair = "\" CHAR
123  ++pos;
124  while (pos < header.length()) {
125  register char c = header.at(pos);
126  if (c == '"') {
127  // end of quoted text
128  break;
129  } else if (c == '\\') {
130  ++pos;
131  if (pos >= header.length())
132  // broken header
133  return result;
134  c = header.at(pos);
135  }
136 
137  value += c;
138  ++pos;
139  }
140  } else {
141  // case: token
142  while (pos < header.length()) {
143  register char c = header.at(pos);
144  if (isSeparator(c))
145  break;
146  value += c;
147  ++pos;
148  }
149  }
150 
151  result.insert(key, value);
152 
153  // find the comma now:
154  comma = header.indexOf(',', pos);
155  if (comma == -1)
156  return result; // end of parsing
157  pos = comma + 1;
158  } else {
159  // case: token
160  // key is already set
161  result.insert(key, QByteArray());
162  }
163  }
164 }
165 
168  const QNetworkRequest &request) const
169 {
170  // check the operation
171  switch (op) {
178  break;
179 
180  default:
181  // no, we can't handle this request
182  return 0;
183  }
184 
185  QUrl url = request.url();
186  QString scheme = url.scheme().toLower();
187  if (scheme == QLatin1String("http") || scheme == QLatin1String("https"))
188  return new QNetworkAccessHttpBackend;
189 
190  return 0;
191 }
192 
195  , statusCode(0)
196  , pendingDownloadDataEmissions(new QAtomicInt())
197  , pendingDownloadProgressEmissions(new QAtomicInt())
198  , loadingFromCache(false)
199  , usingZerocopyDownloadBuffer(false)
200 #ifndef QT_NO_OPENSSL
201  , pendingSslConfiguration(0), pendingIgnoreAllSslErrors(false)
202 #endif
203  , resumeOffset(0)
204 {
205 }
206 
208 {
209  // This will do nothing if the request was already finished or aborted
211 
212 #ifndef QT_NO_OPENSSL
214 #endif
215 }
216 
217 /*
218  For a given httpRequest
219  1) If AlwaysNetwork, return
220  2) If we have a cache entry for this url populate headers so the server can return 304
221  3) Calculate if response_is_fresh and if so send the cache and set loadedFromCache to true
222  */
224 {
225  QNetworkRequest::CacheLoadControl CacheLoadControlAttribute =
227  if (CacheLoadControlAttribute == QNetworkRequest::AlwaysNetwork) {
228  // If the request does not already specify preferred cache-control
229  // force reload from the network and tell any caching proxy servers to reload too
230  if (!request().rawHeaderList().contains("Cache-Control")) {
231  httpRequest.setHeaderField("Cache-Control", "no-cache");
232  httpRequest.setHeaderField("Pragma", "no-cache");
233  }
234  return false;
235  }
236 
237  // The disk cache API does not currently support partial content retrieval.
238  // That is why we don't use the disk cache for any such requests.
239  if (request().hasRawHeader("Range"))
240  return false;
241 
243  if (!nc)
244  return false; // no local cache
245 
246  QNetworkCacheMetaData metaData = nc->metaData(url());
247  if (!metaData.isValid())
248  return false; // not in cache
249 
250  if (!metaData.saveToDisk())
251  return false;
252 
253  QNetworkHeadersPrivate cacheHeaders;
255  cacheHeaders.setAllRawHeaders(metaData.rawHeaders());
256 
257  it = cacheHeaders.findRawHeader("etag");
258  if (it != cacheHeaders.rawHeaders.constEnd())
259  httpRequest.setHeaderField("If-None-Match", it->second);
260 
261  QDateTime lastModified = metaData.lastModified();
262  if (lastModified.isValid())
263  httpRequest.setHeaderField("If-Modified-Since", QNetworkHeadersPrivate::toHttpDate(lastModified));
264 
265  it = cacheHeaders.findRawHeader("Cache-Control");
266  if (it != cacheHeaders.rawHeaders.constEnd()) {
267  QHash<QByteArray, QByteArray> cacheControl = parseHttpOptionHeader(it->second);
268  if (cacheControl.contains("must-revalidate"))
269  return false;
270  }
271 
272  QDateTime currentDateTime = QDateTime::currentDateTime();
273  QDateTime expirationDate = metaData.expirationDate();
274 
275 #if 0
276  /*
277  * age_value
278  * is the value of Age: header received by the cache with
279  * this response.
280  * date_value
281  * is the value of the origin server's Date: header
282  * request_time
283  * is the (local) time when the cache made the request
284  * that resulted in this cached response
285  * response_time
286  * is the (local) time when the cache received the
287  * response
288  * now
289  * is the current (local) time
290  */
291  int age_value = 0;
292  it = cacheHeaders.findRawHeader("age");
293  if (it != cacheHeaders.rawHeaders.constEnd())
294  age_value = it->second.toInt();
295 
296  QDateTime dateHeader;
297  int date_value = 0;
298  it = cacheHeaders.findRawHeader("date");
299  if (it != cacheHeaders.rawHeaders.constEnd()) {
300  dateHeader = QNetworkHeadersPrivate::fromHttpDate(it->second);
301  date_value = dateHeader.toTime_t();
302  }
303 
304  int now = currentDateTime.toUTC().toTime_t();
305  int request_time = now;
306  int response_time = now;
307 
308  // Algorithm from RFC 2616 section 13.2.3
309  int apparent_age = qMax(0, response_time - date_value);
310  int corrected_received_age = qMax(apparent_age, age_value);
311  int response_delay = response_time - request_time;
312  int corrected_initial_age = corrected_received_age + response_delay;
313  int resident_time = now - response_time;
314  int current_age = corrected_initial_age + resident_time;
315 
316  // RFC 2616 13.2.4 Expiration Calculations
317  if (!expirationDate.isValid()) {
318  if (lastModified.isValid()) {
319  int diff = currentDateTime.secsTo(lastModified);
320  expirationDate = lastModified;
321  expirationDate.addSecs(diff / 10);
322  if (httpRequest.headerField("Warning").isEmpty()) {
323  QDateTime dt;
324  dt.setTime_t(current_age);
325  if (dt.daysTo(currentDateTime) > 1)
326  httpRequest.setHeaderField("Warning", "113");
327  }
328  }
329  }
330 
331  // the cache-saving code below sets the expirationDate with date+max_age
332  // if "max-age" is present, or to Expires otherwise
333  int freshness_lifetime = dateHeader.secsTo(expirationDate);
334  bool response_is_fresh = (freshness_lifetime > current_age);
335 #else
336  bool response_is_fresh = currentDateTime.secsTo(expirationDate) >= 0;
337 #endif
338 
339  if (!response_is_fresh)
340  return false;
341 
342 #if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
343  qDebug() << "response_is_fresh" << CacheLoadControlAttribute;
344 #endif
345  return sendCacheContents(metaData);
346 }
347 
349 {
350  switch (prio) {
356  default:
358  }
359 }
360 
362 {
363  QThread *thread = 0;
364  if (isSynchronous()) {
365  // A synchronous HTTP request uses its own thread
366  thread = new QThread();
367  QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
368  thread->start();
369  } else if (!manager->httpThread) {
370  // We use the manager-global thread.
371  // At some point we could switch to having multiple threads if it makes sense.
372  manager->httpThread = new QThread();
375 #ifndef QT_NO_NETWORKPROXY
376  qRegisterMetaType<QNetworkProxy>("QNetworkProxy");
377 #endif
378 #ifndef QT_NO_OPENSSL
379  qRegisterMetaType<QList<QSslError> >("QList<QSslError>");
380  qRegisterMetaType<QSslConfiguration>("QSslConfiguration");
381 #endif
382  qRegisterMetaType<QList<QPair<QByteArray,QByteArray> > >("QList<QPair<QByteArray,QByteArray> >");
383  qRegisterMetaType<QHttpNetworkRequest>("QHttpNetworkRequest");
384  qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError");
385  qRegisterMetaType<QSharedPointer<char> >("QSharedPointer<char>");
386 
387  thread = manager->httpThread;
388  } else {
389  // Asynchronous request, thread already exists
390  thread = manager->httpThread;
391  }
392 
393  QUrl url = request().url();
394  httpRequest.setUrl(url);
395 
396  bool ssl = url.scheme().toLower() == QLatin1String("https");
398  httpRequest.setSsl(ssl);
399 
400 
401 #ifndef QT_NO_NETWORKPROXY
402  QNetworkProxy transparentProxy, cacheProxy;
403 
404  foreach (const QNetworkProxy &p, proxyList()) {
405  // use the first proxy that works
406  // for non-encrypted connections, any transparent or HTTP proxy
407  // for encrypted, only transparent proxies
408  if (!ssl
410  && (p.type() == QNetworkProxy::HttpProxy ||
412  cacheProxy = p;
413  transparentProxy = QNetworkProxy::NoProxy;
414  break;
415  }
416  if (p.isTransparentProxy()) {
417  transparentProxy = p;
418  cacheProxy = QNetworkProxy::NoProxy;
419  break;
420  }
421  }
422 
423  // check if at least one of the proxies
424  if (transparentProxy.type() == QNetworkProxy::DefaultProxy &&
425  cacheProxy.type() == QNetworkProxy::DefaultProxy) {
426  // unsuitable proxies
429  Q_ARG(QString, tr("No suitable proxy found")));
430  QMetaObject::invokeMethod(this, "finished", isSynchronous() ? Qt::DirectConnection : Qt::QueuedConnection);
431  return;
432  }
433 #endif
434 
435 
436  bool loadedFromCache = false;
437  httpRequest.setPriority(convert(request().priority()));
438 
439  switch (operation()) {
442  loadedFromCache = loadFromCacheIfAllowed(httpRequest);
443  break;
444 
447  loadedFromCache = loadFromCacheIfAllowed(httpRequest);
448  break;
449 
451  invalidateCache();
454  break;
455 
457  invalidateCache();
460  break;
461 
463  invalidateCache();
465  break;
466 
468  invalidateCache(); // for safety reasons, we don't know what the operation does
472  QNetworkRequest::CustomVerbAttribute).toByteArray());
473  break;
474 
475  default:
476  break; // can't happen
477  }
478 
479  if (loadedFromCache) {
480  // commented this out since it will be called later anyway
481  // by copyFinished()
482  //QNetworkAccessBackend::finished();
483  return; // no need to send the request! :)
484  }
485 
487  if (resumeOffset != 0) {
488  if (headers.contains("Range")) {
489  // Need to adjust resume offset for user specified range
490 
491  headers.removeOne("Range");
492 
493  // We've already verified that requestRange starts with "bytes=", see canResume.
494  QByteArray requestRange = request().rawHeader("Range").mid(6);
495 
496  int index = requestRange.indexOf('-');
497 
498  quint64 requestStartOffset = requestRange.left(index).toULongLong();
499  quint64 requestEndOffset = requestRange.mid(index + 1).toULongLong();
500 
501  requestRange = "bytes=" + QByteArray::number(resumeOffset + requestStartOffset) +
502  '-' + QByteArray::number(requestEndOffset);
503 
504  httpRequest.setHeaderField("Range", requestRange);
505  } else {
506  httpRequest.setHeaderField("Range", "bytes=" + QByteArray::number(resumeOffset) + '-');
507  }
508  }
509 
510  foreach (const QByteArray &header, headers)
511  httpRequest.setHeaderField(header, request().rawHeader(header));
512 
515 
516  if (static_cast<QNetworkRequest::LoadControl>
520 
521 
522  // Create the HTTP thread delegate
524 #ifndef QT_NO_BEARERMANAGEMENT
525  QVariant v(property("_q_networksession"));
526  if (v.isValid())
528 #endif
529 
530  // For the synchronous HTTP, this is the normal way the delegate gets deleted
531  // For the asynchronous HTTP this is a safety measure, the delegate deletes itself when HTTP is finished
532  connect(thread, SIGNAL(finished()), delegate, SLOT(deleteLater()));
533 
534  // Set the properties it needs
535  delegate->httpRequest = httpRequest;
536 #ifndef QT_NO_NETWORKPROXY
537  delegate->cacheProxy = cacheProxy;
538  delegate->transparentProxy = transparentProxy;
539 #endif
540  delegate->ssl = ssl;
541 #ifndef QT_NO_OPENSSL
542  if (ssl)
544 #endif
545 
546  // Do we use synchronous HTTP?
547  delegate->synchronous = isSynchronous();
548 
549  // The authentication manager is used to avoid the BlockingQueuedConnection communication
550  // from HTTP thread to user thread in some cases.
552 
553  if (!isSynchronous()) {
554  // Tell our zerocopy policy to the delegate
555  delegate->downloadBufferMaximumSize =
557 
558  // These atomic integers are used for signal compression
561 
562  // Connect the signals of the delegate to us
563  connect(delegate, SIGNAL(downloadData(QByteArray)),
566  connect(delegate, SIGNAL(downloadFinished()),
567  this, SLOT(replyFinished()),
569  connect(delegate, SIGNAL(downloadMetaData(QList<QPair<QByteArray,QByteArray> >,int,QString,bool,QSharedPointer<char>,qint64)),
572  connect(delegate, SIGNAL(downloadProgress(qint64,qint64)),
578 #ifndef QT_NO_OPENSSL
579  connect(delegate, SIGNAL(sslConfigurationChanged(QSslConfiguration)),
582 #endif
583  // Those need to report back, therefire BlockingQueuedConnection
587 #ifndef QT_NO_NETWORKPROXY
591 #endif
592 #ifndef QT_NO_OPENSSL
594  this, SLOT(replySslErrors(const QList<QSslError> &, bool *, QList<QSslError> *)),
596 #endif
597  // This signal we will use to start the request.
598  connect(this, SIGNAL(startHttpRequest()), delegate, SLOT(startRequest()));
599  connect(this, SIGNAL(abortHttpRequest()), delegate, SLOT(abortRequest()));
600 
601  // To throttle the connection.
604 
605  if (uploadByteDevice) {
606  QNonContiguousByteDeviceThreadForwardImpl *forwardUploadDevice =
609  forwardUploadDevice->disableReset();
610  forwardUploadDevice->setParent(delegate); // needed to make sure it is moved on moveToThread()
611  delegate->httpRequest.setUploadByteDevice(forwardUploadDevice);
612 
613  // From main thread to user thread:
615  forwardUploadDevice, SLOT(haveDataSlot(QByteArray, bool, qint64)), Qt::QueuedConnection);
617  forwardUploadDevice, SIGNAL(readyRead()),
619 
620  // From http thread to user thread:
621  QObject::connect(forwardUploadDevice, SIGNAL(wantData(qint64)),
622  this, SLOT(wantUploadDataSlot(qint64)));
623  QObject::connect(forwardUploadDevice, SIGNAL(processedData(qint64)),
624  this, SLOT(sentUploadDataSlot(qint64)));
625  connect(forwardUploadDevice, SIGNAL(resetData(bool*)),
626  this, SLOT(resetUploadDataSlot(bool*)),
627  Qt::BlockingQueuedConnection); // this is the only one with BlockingQueued!
628  }
629  } else if (isSynchronous()) {
630  connect(this, SIGNAL(startHttpRequestSynchronously()), delegate, SLOT(startRequestSynchronously()), Qt::BlockingQueuedConnection);
631 
632  if (uploadByteDevice) {
633  // For the synchronous HTTP use case the use thread (this one here) is blocked
634  // so we cannot use the asynchronous upload architecture.
635  // We therefore won't use the QNonContiguousByteDeviceThreadForwardImpl but directly
636  // use the uploadByteDevice provided to us by the QNetworkReplyImpl.
637  // The code that is in QNetworkReplyImplPrivate::setup() makes sure it is safe to use from a thread
638  // since it only wraps a QRingBuffer
640  }
641  }
642 
643 
644  // Move the delegate to the http thread
645  delegate->moveToThread(thread);
646  // This call automatically moves the uploadDevice too for the asynchronous case.
647 
648  // Send an signal to the delegate so it starts working in the other thread
649  if (isSynchronous()) {
650  emit startHttpRequestSynchronously(); // This one is BlockingQueuedConnection, so it will return when all work is done
651 
652  if (delegate->incomingErrorCode != QNetworkReply::NoError) {
654  (delegate->incomingHeaders,
655  delegate->incomingStatusCode,
656  delegate->incomingReasonPhrase,
657  delegate->isPipeliningUsed,
659  delegate->incomingContentLength);
661  httpError(delegate->incomingErrorCode, delegate->incomingErrorDetail);
662  } else {
664  (delegate->incomingHeaders,
665  delegate->incomingStatusCode,
666  delegate->incomingReasonPhrase,
667  delegate->isPipeliningUsed,
669  delegate->incomingContentLength);
671  }
672 
673  // End the thread. It will delete itself from the finished() signal
674  thread->quit();
675  thread->wait(5000);
676 
677  finished();
678  } else {
679  emit startHttpRequest(); // Signal to the HTTP thread and go back to user.
680  }
681 }
682 
684 {
686  if (nc)
687  nc->remove(url());
688 }
689 
691 {
692  postRequest();
693 }
694 
696 {
697  // FIXME Maybe we can get rid of this whole architecture part
698 }
699 
701 {
702  // FIXME Maybe we can get rid of this whole architecture part
703 }
704 
706 {
707  Q_UNUSED(b);
708  // We know that readBuffer maximum size limiting is broken since quite a while.
709  // The task to fix this is QTBUG-15065
710 }
711 
713 {
715 }
716 
718 {
719  emit readBufferFreed(size);
720 }
721 
723 {
724  int pendingSignals = (int)pendingDownloadDataEmissions->fetchAndAddAcquire(-1) - 1;
725 
726  if (pendingSignals > 0) {
727  // Some more signal emissions to this slot are pending.
728  // Instead of writing the downstream data, we wait
729  // and do it in the next call we get
730  // (signal comppression)
732  return;
733  }
734 
736  d.clear();
737  // We need to usa a copy for calling writeDownstreamData as we could
738  // possibly recurse into this this function when we call
739  // appendDownstreamDataSignalEmissions because the user might call
740  // processEvents() or spin an event loop when this occur.
741  QByteDataBuffer pendingDownloadDataCopy = pendingDownloadData;
743  writeDownstreamData(pendingDownloadDataCopy);
744 }
745 
747 {
748  // We are already loading from cache, we still however
749  // got this signal because it was posted already
750  if (loadingFromCache)
751  return;
752 
753  finished();
754 }
755 
757 {
758  switch (statusCode) {
759  case 301: // Moved Permanently
760  case 302: // Found
761  case 303: // See Other
762  case 307: // Temporary Redirect
763  // What do we do about the caching of the HTML note?
764  // The response to a 303 MUST NOT be cached, while the response to
765  // all of the others is cacheable if the headers indicate it to be
766  QByteArray header = rawHeader("location");
767  QUrl url = QUrl::fromEncoded(header);
768  if (!url.isValid())
769  url = QUrl(QLatin1String(header));
771  }
772 }
773 
776  int sc,QString rp,bool pu,
778  qint64 contentLength)
779 {
780  statusCode = sc;
781  reasonPhrase = rp;
782 
783  // Download buffer
784  if (!db.isNull()) {
785  reply->setDownloadBuffer(db, contentLength);
787  } else {
789  }
790 
792 
793  // reconstruct the HTTP header
794  QList<QPair<QByteArray, QByteArray> > headerMap = hm;
795  QList<QPair<QByteArray, QByteArray> >::ConstIterator it = headerMap.constBegin(),
796  end = headerMap.constEnd();
798 
799  for (; it != end; ++it) {
800  QByteArray value = rawHeader(it->first);
801  if (!value.isEmpty()) {
802  if (qstricmp(it->first.constData(), "set-cookie") == 0)
803  value += '\n';
804  else
805  value += ", ";
806  }
807  value += it->second;
808  setRawHeader(it->first, value);
809  }
810 
813 
814  // is it a redirection?
816 
817  if (statusCode >= 500 && statusCode < 600) {
819  if (nc) {
820  QNetworkCacheMetaData metaData = nc->metaData(url());
821  QNetworkHeadersPrivate cacheHeaders;
822  cacheHeaders.setAllRawHeaders(metaData.rawHeaders());
824  it = cacheHeaders.findRawHeader("Cache-Control");
825  bool mustReValidate = false;
826  if (it != cacheHeaders.rawHeaders.constEnd()) {
827  QHash<QByteArray, QByteArray> cacheControl = parseHttpOptionHeader(it->second);
828  if (cacheControl.contains("must-revalidate"))
829  mustReValidate = true;
830  }
831  if (!mustReValidate && sendCacheContents(metaData))
832  return;
833  }
834  }
835 
836  if (statusCode == 304) {
837 #if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
838  qDebug() << "Received a 304 from" << url();
839 #endif
841  if (nc) {
842  QNetworkCacheMetaData oldMetaData = nc->metaData(url());
843  QNetworkCacheMetaData metaData = fetchCacheMetaData(oldMetaData);
844  if (oldMetaData != metaData)
845  nc->updateMetaData(metaData);
846  if (sendCacheContents(metaData))
847  return;
848  }
849  }
850 
851 
852  if (statusCode != 304 && statusCode != 303) {
853  if (!isCachingEnabled())
854  setCachingEnabled(true);
855  }
856 
857  metaDataChanged();
858 }
859 
861 {
862  // we can be sure here that there is a download buffer
863 
864  int pendingSignals = (int)pendingDownloadProgressEmissions->fetchAndAddAcquire(-1) - 1;
865  if (pendingSignals > 0) {
866  // Let's ignore this signal and look at the next one coming in
867  // (signal comppression)
868  return;
869  }
870 
871  // Now do the actual notification of new bytes
872  writeDownstreamDataDownloadBuffer(received, total);
873 }
874 
876  QAuthenticator *auth)
877 {
879 }
880 
882  const QString &errorString)
883 {
884 #if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
885  qDebug() << "http error!" << errorCode << errorString;
886 #endif
887 
888  error(errorCode, errorString);
889 }
890 
891 #ifndef QT_NO_OPENSSL
893  const QList<QSslError> &list, bool *ignoreAll, QList<QSslError> *toBeIgnored)
894 {
895  // Go to generic backend
896  sslErrors(list);
897  // Check if the callback set any ignore and return this here to http thread
899  *ignoreAll = true;
901  *toBeIgnored = pendingIgnoreSslErrorsList;
902 }
903 
905 {
906  // Receiving the used SSL configuration from the HTTP thread
909  else if (!c.isNull())
911 }
912 #endif
913 
914 // Coming from QNonContiguousByteDeviceThreadForwardImpl in HTTP thread
916 {
917  *r = uploadByteDevice->reset();
918 }
919 
920 // Coming from QNonContiguousByteDeviceThreadForwardImpl in HTTP thread
922 {
924 }
925 
926 // Coming from QNonContiguousByteDeviceThreadForwardImpl in HTTP thread
928 {
929  // call readPointer
930  qint64 currentUploadDataLength = 0;
931  char *data = const_cast<char*>(uploadByteDevice->readPointer(maxSize, currentUploadDataLength));
932  // Let's make a copy of this data
933  QByteArray dataArray(data, currentUploadDataLength);
934 
935  // Communicate back to HTTP thread
937 }
938 
939 /*
940  A simple web page that can be used to test us: http://www.procata.com/cachetest/
941  */
943 {
944  setCachingEnabled(false);
945  if (!metaData.isValid())
946  return false;
947 
949  Q_ASSERT(nc);
950  QIODevice *contents = nc->data(url());
951  if (!contents) {
952 #if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
953  qDebug() << "Can not send cache, the contents are 0" << url();
954 #endif
955  return false;
956  }
957  contents->setParent(this);
958 
959  QNetworkCacheMetaData::AttributesMap attributes = metaData.attributes();
961  if (status < 100)
962  status = 200; // fake it
963 
967 
968  QNetworkCacheMetaData::RawHeaderList rawHeaders = metaData.rawHeaders();
970  end = rawHeaders.constEnd();
971  for ( ; it != end; ++it)
972  setRawHeader(it->first, it->second);
973 
974  checkForRedirect(status);
975 
976  // This needs to be emitted in the event loop because it can be reached at
977  // the direct code path of qnam.get(...) before the user has a chance
978  // to connect any signals.
980  qRegisterMetaType<QIODevice*>("QIODevice*");
981  QMetaObject::invokeMethod(this, "writeDownstreamData", isSynchronous() ? Qt::DirectConnection : Qt::QueuedConnection, Q_ARG(QIODevice*, contents));
982 
983 
984 #if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
985  qDebug() << "Successfully sent cache:" << url() << contents->size() << "bytes";
986 #endif
987 
988  // Set the following flag so we can ignore some signals from HTTP thread
989  // that would still come
990  loadingFromCache = true;
991  return true;
992 }
993 
995 {
996  delete dev;
997  finished();
998 }
999 
1000 #ifndef QT_NO_OPENSSL
1002 {
1004 }
1005 
1007 {
1008  // the pending list is set if QNetworkReply::ignoreSslErrors(const QList<QSslError> &errors)
1009  // is called before QNetworkAccessManager::get() (or post(), etc.)
1010  pendingIgnoreSslErrorsList = errors;
1011 }
1012 
1014 {
1016  config = *pendingSslConfiguration;
1017  else
1018  config = request().sslConfiguration();
1019 }
1020 
1022 {
1023  // Setting a SSL configuration on a reply is not supported. The user needs to set
1024  // her/his QSslConfiguration on the QNetworkRequest.
1025  Q_UNUSED(newconfig);
1026 }
1027 #endif
1028 
1030 {
1031  QNetworkCacheMetaData metaData = oldMetaData;
1032 
1033  QNetworkHeadersPrivate cacheHeaders;
1034  cacheHeaders.setAllRawHeaders(metaData.rawHeaders());
1036 
1037  QList<QByteArray> newHeaders = rawHeaderList();
1038  foreach (QByteArray header, newHeaders) {
1039  QByteArray originalHeader = header;
1040  header = header.toLower();
1041  bool hop_by_hop =
1042  (header == "connection"
1043  || header == "keep-alive"
1044  || header == "proxy-authenticate"
1045  || header == "proxy-authorization"
1046  || header == "te"
1047  || header == "trailers"
1048  || header == "transfer-encoding"
1049  || header == "upgrade");
1050  if (hop_by_hop)
1051  continue;
1052 
1053  // we are currently not using the date header to determine the expiration time of a page,
1054  // but only the "Expires", "max-age" and "s-maxage" headers, see
1055  // QNetworkAccessHttpBackend::validateCache() and below ("metaData.setExpirationDate()").
1056  if (header == "date")
1057  continue;
1058 
1059  // Don't store Warning 1xx headers
1060  if (header == "warning") {
1061  QByteArray v = rawHeader(header);
1062  if (v.length() == 3
1063  && v[0] == '1'
1064  && v[1] >= '0' && v[1] <= '9'
1065  && v[2] >= '0' && v[2] <= '9')
1066  continue;
1067  }
1068 
1069  it = cacheHeaders.findRawHeader(header);
1070  if (it != cacheHeaders.rawHeaders.constEnd()) {
1071  // Match the behavior of Firefox and assume Cache-Control: "no-transform"
1072  if (header == "content-encoding"
1073  || header == "content-range"
1074  || header == "content-type")
1075  continue;
1076 
1077  // For MS servers that send "Content-Length: 0" on 304 responses
1078  // ignore this too
1079  if (header == "content-length")
1080  continue;
1081  }
1082 
1083 #if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
1084  QByteArray n = rawHeader(header);
1085  QByteArray o;
1086  if (it != cacheHeaders.rawHeaders.constEnd())
1087  o = (*it).second;
1088  if (n != o && header != "date") {
1089  qDebug() << "replacing" << header;
1090  qDebug() << "new" << n;
1091  qDebug() << "old" << o;
1092  }
1093 #endif
1094  cacheHeaders.setRawHeader(originalHeader, rawHeader(header));
1095  }
1096  metaData.setRawHeaders(cacheHeaders.rawHeaders);
1097 
1098  bool checkExpired = true;
1099 
1100  QHash<QByteArray, QByteArray> cacheControl;
1101  it = cacheHeaders.findRawHeader("Cache-Control");
1102  if (it != cacheHeaders.rawHeaders.constEnd()) {
1103  cacheControl = parseHttpOptionHeader(it->second);
1104  QByteArray maxAge = cacheControl.value("max-age");
1105  if (!maxAge.isEmpty()) {
1106  checkExpired = false;
1108  dt = dt.addSecs(maxAge.toInt());
1109  metaData.setExpirationDate(dt);
1110  }
1111  }
1112  if (checkExpired) {
1113  it = cacheHeaders.findRawHeader("expires");
1114  if (it != cacheHeaders.rawHeaders.constEnd()) {
1115  QDateTime expiredDateTime = QNetworkHeadersPrivate::fromHttpDate(it->second);
1116  metaData.setExpirationDate(expiredDateTime);
1117  }
1118  }
1119 
1120  it = cacheHeaders.findRawHeader("last-modified");
1121  if (it != cacheHeaders.rawHeaders.constEnd())
1123 
1124  bool canDiskCache;
1125  // only cache GET replies by default, all other replies (POST, PUT, DELETE)
1126  // are not cacheable by default (according to RFC 2616 section 9)
1128 
1129  canDiskCache = true;
1130  // 14.32
1131  // HTTP/1.1 caches SHOULD treat "Pragma: no-cache" as if the client
1132  // had sent "Cache-Control: no-cache".
1133  it = cacheHeaders.findRawHeader("pragma");
1134  if (it != cacheHeaders.rawHeaders.constEnd()
1135  && it->second == "no-cache")
1136  canDiskCache = false;
1137 
1138  // HTTP/1.1. Check the Cache-Control header
1139  if (cacheControl.contains("no-cache"))
1140  canDiskCache = false;
1141  else if (cacheControl.contains("no-store"))
1142  canDiskCache = false;
1143 
1144  // responses to POST might be cacheable
1146 
1147  canDiskCache = false;
1148  // some pages contain "expires:" and "cache-control: no-cache" field,
1149  // so we only might cache POST requests if we get "cache-control: max-age ..."
1150  if (cacheControl.contains("max-age"))
1151  canDiskCache = true;
1152 
1153  // responses to PUT and DELETE are not cacheable
1154  } else {
1155  canDiskCache = false;
1156  }
1157 
1158  metaData.setSaveToDisk(canDiskCache);
1160  if (statusCode != 304) {
1161  // update the status code
1164  } else {
1165  // this is a redirection, keep the attributes intact
1166  attributes = oldMetaData.attributes();
1167  }
1168  metaData.setAttributes(attributes);
1169  return metaData;
1170 }
1171 
1173 {
1174  // Only GET operation supports resuming.
1176  return false;
1177 
1178  // Can only resume if server/resource supports Range header.
1179  QByteArray acceptRangesheaderName("Accept-Ranges");
1180  if (!hasRawHeader(acceptRangesheaderName) || rawHeader(acceptRangesheaderName) == "none")
1181  return false;
1182 
1183  // We only support resuming for byte ranges.
1184  if (request().hasRawHeader("Range")) {
1185  QByteArray range = request().rawHeader("Range");
1186  if (!range.startsWith("bytes="))
1187  return false;
1188  }
1189 
1190  // If we're using a download buffer then we don't support resuming/migration
1191  // right now. Too much trouble.
1193  return false;
1194 
1195  return true;
1196 }
1197 
1199 {
1200  resumeOffset = offset;
1201 }
1202 
1204 
1205 #endif // QT_NO_HTTP
QNetworkReply::NetworkError incomingErrorCode
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
QNetworkProxy::ProxyType type() const
Returns the proxy type for this instance.
QDateTime addSecs(int secs) const
Returns a QDateTime object containing a datetime s seconds later than the datetime of this object (or...
Definition: qdatetime.cpp:2869
double d
Definition: qnumeric_p.h:62
int daysTo(const QDateTime &) const
Returns the number of days from this datetime to the other datetime.
Definition: qdatetime.cpp:2894
static QHash< QByteArray, QByteArray > parseHttpOptionHeader(const QByteArray &header)
virtual bool reset()=0
Moves the internal read pointer back to the beginning.
void setSaveToDisk(bool allow)
Sets whether this network cache meta data and associated content should be allowed to be stored on di...
virtual qint64 size() const
For open random-access devices, this function returns the size of the device.
Definition: qiodevice.cpp:642
void setAllRawHeaders(const RawHeadersList &list)
Sets the internal raw headers list to match list.
bool isValid() const
Returns true if the URL is valid; otherwise returns false.
Definition: qurl.cpp:4303
virtual void updateMetaData(const QNetworkCacheMetaData &metaData)=0
Updates the cache meta date for the metaData&#39;s url to metaData.
unsigned char c[8]
Definition: qnumeric_p.h:62
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
virtual QNetworkAccessBackend * create(QNetworkAccessManager::Operation op, const QNetworkRequest &request) const
void setAttribute(QNetworkRequest::Attribute code, const QVariant &value)
QSslConfiguration sslConfiguration() const
Returns this network request&#39;s SSL configuration.
void setPriority(Priority priority)
The QAtomicInt class provides platform-independent atomic operations on integers. ...
Definition: qatomic.h:55
#define it(className, varName)
bool isValid() const
Returns true if this network cache meta data has attributes that have been set otherwise false...
QByteArray rawHeader(const QByteArray &headerName) const
Returns the raw form of header headerName.
QVariant header(QNetworkRequest::KnownHeaders header) const
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
void setRawHeader(const QByteArray &key, const QByteArray &value)
QVariant attribute(Attribute code, const QVariant &defaultValue=QVariant()) const
Returns the attribute associated with the code code.
#define SLOT(a)
Definition: qobjectdefs.h:226
QHttpNetworkRequest httpRequest
void setOperation(Operation operation)
QSslConfiguration incomingSslConfiguration
uint toTime_t() const
Returns the datetime as the number of seconds that have passed since 1970-01-01T00:00:00, Coordinated Universal Time (Qt::UTC).
Definition: qdatetime.cpp:2505
NetworkError
Indicates all possible error conditions found during the processing of the request.
Definition: qnetworkreply.h:70
const_iterator constBegin() const
Returns a const STL-style iterator pointing to the first item in the list.
Definition: qlist.h:269
void readBufferFreed(qint64 size)
Operation
Indicates the operation this reply is processing.
void setExpirationDate(const QDateTime &dateTime)
Sets the date and time when the meta data expires to dateTime.
Priority
This enum lists the possible network request priorities.
static LibLoadStatus status
Definition: qlocale_icu.cpp:69
#define Q_ARG(type, data)
Definition: qobjectdefs.h:246
QByteArray toLower() const
Returns a lowercase copy of the byte array.
bool isValid() const
Returns true if both the date and the time are valid; otherwise returns false.
Definition: qdatetime.cpp:2346
static QString tr(const char *sourceText, const char *comment=0, int n=-1)
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
void setAttributes(const AttributesMap &attributes)
Sets all attributes of this cache item to be the map attributes.
void append(QByteDataBuffer &other)
Definition: qbytedata_p.h:77
bool loadFromCacheIfAllowed(QHttpNetworkRequest &httpRequest)
virtual bool remove(const QUrl &url)=0
Removes the cache entry for url, returning true if success otherwise false.
void httpError(QNetworkReply::NetworkError error, const QString &errorString)
The QUrl class provides a convenient interface for working with URLs.
Definition: qurl.h:61
The QString class provides a Unicode character string.
Definition: qstring.h:83
void checkForRedirect(const int statusCode)
The QHash class is a template class that provides a hash-table-based dictionary.
Definition: qdatastream.h:66
void writeDownstreamDataDownloadBuffer(qint64, qint64)
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
bool startsWith(const QByteArray &a) const
Returns true if this byte array starts with byte array ba; otherwise returns false.
void setLastModified(const QDateTime &dateTime)
Sets the date and time when the meta data was last modified to dateTime.
QDateTime expirationDate() const
Returns the date and time when the meta data expires.
bool contains(const Key &key) const
Returns true if the hash contains an item with the key; otherwise returns false.
Definition: qhash.h:872
static int nextNonWhitespace(const QByteArray &text, int from)
void quit()
Tells the thread&#39;s event loop to exit with return code 0 (success).
Definition: qthread.cpp:614
const T value(const Key &key) const
Returns the value associated with the key.
Definition: qhash.h:606
void httpAuthenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *auth)
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
bool hasRawHeader(const QByteArray &headerName) const
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
QUrl url() const
Returns the URL this network request is referring to.
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition: qhash.h:753
void setParent(QObject *)
Makes the object a child of parent.
Definition: qobject.cpp:1950
virtual const char * readPointer(qint64 maximumLength, qint64 &len)=0
Return a byte pointer for at most maximumLength bytes of that device.
QSharedPointer< QAtomicInt > pendingDownloadDataEmissions
QNetworkAccessManagerPrivate * manager
virtual QIODevice * data(const QUrl &url)=0
Returns the data associated with url.
void haveUploadData(QByteArray dataArray, bool dataAtEnd, qint64 dataSize)
int toInt(bool *ok=0) const
Returns the variant as an int if the variant has type() Int , Bool , ByteArray , Char ...
Definition: qvariant.cpp:2625
Q_GUI_EXPORT QString errorString(EGLint code=eglGetError())
Definition: qegl.cpp:743
RawHeaderList rawHeaders() const
Returns a list of all raw headers that are set in this meta data.
virtual void copyFinished(QIODevice *)
Q_CORE_EXPORT void qDebug(const char *,...)
static bool toBool(Register *reg, int type, bool *ok=0)
bool removeOne(const T &t)
Removes the first occurrence of value in the list and returns true on success; otherwise returns fals...
Definition: qlist.h:796
#define SIGNAL(a)
Definition: qobjectdefs.h:227
void disableReset()
Disable the reset() call, e.
The QNetworkProxy class provides a network layer proxy.
QNonContiguousByteDevice * createUploadByteDevice()
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
qlonglong toLongLong(bool *ok=0) const
Returns the variant as a long long int if the variant has type() LongLong , Bool , ByteArray , Char , Double , Int , String , UInt , or ULongLong ; otherwise returns 0.
Definition: qvariant.cpp:2659
QByteArray headerField(const QByteArray &name, const QByteArray &defaultValue=QByteArray()) const
QNetworkReplyImplPrivate * reply
void setUrl(const QUrl &url)
QBool contains(const T &t) const
Returns true if the list contains an occurrence of value; otherwise returns false.
Definition: qlist.h:880
void setTime_t(uint secsSince1Jan1970UTC)
Sets the date and time given the number of seconds that have passed since 1970-01-01T00:00:00, Coordinated Universal Time (Qt::UTC).
Definition: qdatetime.cpp:2566
QNetworkCacheMetaData fetchCacheMetaData(const QNetworkCacheMetaData &metaData) const
unsigned __int64 quint64
Definition: qglobal.h:943
QDateTime lastModified() const
Returns the date and time when the meta data was last modified.
Capabilities capabilities() const
Returns the capabilities of this proxy server.
bool sendCacheContents(const QNetworkCacheMetaData &metaData)
static bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Creates a connection of the given type from the signal in the sender object to the method in the rece...
Definition: qobject.cpp:2580
#define emit
Definition: qobjectdefs.h:76
void setRawHeader(const QByteArray &headerName, const QByteArray &value)
QList< QNetworkProxy > proxyList() const
static QDateTime fromHttpDate(const QByteArray &value)
int secsTo(const QDateTime &) const
Returns the number of seconds from this datetime to the other datetime.
Definition: qdatetime.cpp:2914
static int toInt(const QByteArray &str)
Definition: generator.cpp:167
bool isNull() const
Returns true if this is a null QSslConfiguration object.
qulonglong toULongLong(bool *ok=0, int base=10) const
Returns the byte array converted to an {unsigned long long} using base base, which is 10 by default a...
static const char * data(const QByteArray &arr)
unsigned int uint
Definition: qglobal.h:996
static Bigint * diff(Bigint *a, Bigint *b)
AttributesMap attributes() const
Returns all the attributes stored with this cache item.
static QHttpNetworkRequest::Priority convert(const QNetworkRequest::Priority &prio)
void moveToThread(QThread *thread)
Changes the thread affinity for this object and its children.
Definition: qobject.cpp:1458
static bool isSeparator(register char c)
__int64 qint64
Definition: qglobal.h:942
QByteArray left(int len) const
Returns a byte array that contains the leftmost len bytes of this byte array.
QNetworkAccessManager::Operation operation() const
Operation operation() const
QByteArray mid(int index, int len=-1) const
Returns a byte array containing len bytes from this byte array, starting at position pos...
int indexOf(char c, int from=0) const
Returns the index position of the first occurrence of the character ch in the byte array...
void setDownloadBuffer(QSharedPointer< char > sp, qint64 size)
static bool isLWS(register char c)
QByteArray rawHeader(const QByteArray &headerName) const
#define Q_DECLARE_METATYPE(TYPE)
This macro makes the type Type known to QMetaType as long as it provides a public default constructor...
Definition: qmetatype.h:265
The QAuthenticator class provides an authentication object.
QSharedPointer< QNetworkAccessAuthenticationManager > authenticationManager
QAbstractNetworkCache * networkCache() const
int fetchAndAddAcquire(int valueToAdd)
Atomic fetch-and-add.
QDateTime toUTC() const
Returns a datetime containing the date and time information in this datetime, but specified using the...
Definition: qdatetime.h:251
void readBufferSizeChanged(qint64 size)
T * data() const
Returns the value of the pointer referenced by this object.
int length() const
Same as size().
Definition: qbytearray.h:356
T & first()
Returns a reference to the first item in the list.
Definition: qlist.h:282
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
QSharedPointer< QNonContiguousByteDevice > uploadByteDevice
virtual void setReadBufferSize(qint64 size)
void setRawHeaders(const RawHeaderList &headers)
Sets the raw headers to list.
QString scheme() const
Returns the scheme of the URL.
Definition: qurl.cpp:4550
void authenticationRequired(QAuthenticator *auth)
void error(QNetworkReply::NetworkError code, const QString &errorString)
void replySslConfigurationChanged(const QSslConfiguration &)
The QDateTime class provides date and time functions.
Definition: qdatetime.h:216
QString trimmed(QString source)
Definition: generator.cpp:233
QNetworkRequest request() const
virtual bool advanceReadPointer(qint64 amount)=0
The old readPointer is invalid after this call.
void start(Priority=InheritPriority)
Begins execution of the thread by calling run().
int toInt(bool *ok=0, int base=10) const
Returns the byte array converted to an int using base base, which is 10 by default and must be betwee...
bool wait(unsigned long time=ULONG_MAX)
Blocks the thread until either of these conditions is met:
QSharedPointer< QNetworkSession > networkSession
const_iterator ConstIterator
Qt-style synonym for QList::const_iterator.
Definition: qlist.h:279
int key
bool isTransparentProxy() const
Returns true if this proxy supports transparent tunneling of TCP connections.
QString toLower() const Q_REQUIRED_RESULT
Returns a lowercase copy of the string.
Definition: qstring.cpp:5389
RawHeadersList::ConstIterator findRawHeader(const QByteArray &key) const
if(void) toggleToolbarShown
static QDateTime currentDateTime()
Returns the current datetime, as reported by the system clock, in the local time zone.
Definition: qdatetime.cpp:3138
virtual QNetworkCacheMetaData metaData(const QUrl &url)=0
Returns the meta data for the url url.
void writeDownstreamData(QByteDataBuffer &list)
T qvariant_cast(const QVariant &)
Definition: qvariant.h:571
QVariant attribute(QNetworkRequest::Attribute code) const
The QNetworkRequest class holds a request to be sent with QNetworkAccessManager.
QSharedPointer< QAtomicInt > pendingDownloadProgress
void replyDownloadProgressSlot(qint64, qint64)
static QByteArray toHttpDate(const QDateTime &dt)
QSharedPointer< QNetworkAccessAuthenticationManager > authenticationManager
quint16 index
QVariant property(const char *name) const
Returns the value of the object&#39;s name property.
Definition: qobject.cpp:3807
QList< QPair< QByteArray, QByteArray > > incomingHeaders
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(0), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
Invokes the member (a signal or a slot name) on the object obj.
CacheLoadControl
Controls the caching mechanism of QNetworkAccessManager.
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
Definition: qbytearray.h:421
void setCachingEnabled(bool enable)
The QSslConfiguration class holds the configuration and state of an SSL connection.
void setHeaderField(const QByteArray &name, const QByteArray &data)
void replyDownloadMetaData(QList< QPair< QByteArray, QByteArray > >, int, QString, bool, QSharedPointer< char >, qint64)
QList< QByteArray > rawHeaderList() const
Returns a list of all raw headers that are set in this network request.
QThread * thread() const
Returns the thread in which the object lives.
Definition: qobject.cpp:1419
QSharedPointer< QAtomicInt > pendingDownloadProgressEmissions
virtual bool atEnd()=0
Returns true if everything has been read and the read pointer cannot be advanced anymore.
static QUrl fromEncoded(const QByteArray &url)
Parses input and returns the corresponding QUrl.
Definition: qurl.cpp:5964
Q_CORE_EXPORT int qstricmp(const char *, const char *)
virtual qint64 size()=0
Returns the size of the complete device or -1 if unknown.
void replySslErrors(const QList< QSslError > &, bool *, QList< QSslError > *)
char at(int i) const
Returns the character at index position i in the byte array.
Definition: qbytearray.h:413
bool isValid() const
Returns true if the storage type of this variant is not QVariant::Invalid; otherwise returns false...
Definition: qvariant.h:485
void reserve(int size)
Attempts to allocate memory for at least size bytes.
Definition: qbytearray.h:449
virtual void setSslConfiguration(const QSslConfiguration &configuration)
static const KeyPair *const end
The QIODevice class is the base interface class of all I/O devices in Qt.
Definition: qiodevice.h:66
void setCustomVerb(const QByteArray &customOperation)
bool saveToDisk() const
Returns is this cache should be allowed to be stored on disk.
The QThread class provides a platform-independent way to manage threads.
Definition: qthread.h:59
virtual void fetchSslConfiguration(QSslConfiguration &configuration) const
bool isNull() const
Returns true if this object is holding a reference to a null pointer.
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
static QByteArray number(int, int base=10)
Returns a byte array containing the string equivalent of the number n to base base (10 by default)...
void deleteLater()
Schedules this object for deletion.
Definition: qobject.cpp:2145
QList< QByteArray > rawHeaderList() const
void clear()
Clears the contents of the byte array and makes it empty.
The QNetworkCacheMetaData class provides cache information.
void redirectionRequested(const QUrl &destination)
static bool equal(const QChar *a, int l, const char *b)
Definition: qurl.cpp:3270
void sslErrors(const QList< QSslError > &errors)
QSharedPointer< QAtomicInt > pendingDownloadData
void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth)
The QAbstractNetworkCache class provides the interface for cache implementations. ...
const_iterator constEnd() const
Returns a const STL-style iterator pointing to the imaginary item after the last item in the list...
Definition: qlist.h:272
void setUploadByteDevice(QNonContiguousByteDevice *bd)
virtual void emitReadBufferFreed(qint64 size)