Qt 4.8
qhttp.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 QHTTP_DEBUG
43 
44 #include <qplatformdefs.h>
45 #include "qhttp.h"
46 
47 #ifndef QT_NO_HTTP
48 # include "private/qobject_p.h"
49 # include "qtcpsocket.h"
50 # include "qsslsocket.h"
51 # include "qtextstream.h"
52 # include "qmap.h"
53 # include "qlist.h"
54 # include "qstring.h"
55 # include "qstringlist.h"
56 # include "qbuffer.h"
57 # include "private/qringbuffer_p.h"
58 # include "qcoreevent.h"
59 # include "qurl.h"
60 # include "qnetworkproxy.h"
61 # include "qauthenticator.h"
62 # include "qauthenticator_p.h"
63 # include "qdebug.h"
64 # include "qtimer.h"
65 #endif
66 
67 #ifndef QT_NO_HTTP
68 
70 
71 class QHttpNormalRequest;
73 {
74 public:
76  { id = idCounter.fetchAndAddRelaxed(1); }
77  virtual ~QHttpRequest()
78  { }
79 
80  virtual void start(QHttp *) = 0;
81  virtual bool hasRequestHeader();
83 
84  virtual QIODevice *sourceDevice() = 0;
85  virtual QIODevice *destinationDevice() = 0;
86 
87  int id;
88  bool finished;
89 
90 private:
92 };
93 
95 {
96 public:
98 
99  inline QHttpPrivate()
100  : socket(0), reconnectAttempts(2),
101  deleteSocket(0), state(QHttp::Unconnected),
102  error(QHttp::NoError), port(0), mode(QHttp::ConnectionModeHttp),
103  toDevice(0), postDevice(0), bytesDone(0), chunkedSize(-1),
104  repost(false), pendingPost(false)
105  {
106  }
107 
108  inline ~QHttpPrivate()
109  {
110  while (!pending.isEmpty())
111  delete pending.takeFirst();
112 
113  if (deleteSocket)
114  delete socket;
115  }
116 
117  // private slots
118  void _q_startNextRequest();
119  void _q_slotReadyRead();
120  void _q_slotConnected();
121  void _q_slotError(QAbstractSocket::SocketError);
122  void _q_slotClosed();
123  void _q_slotBytesWritten(qint64 numBytes);
124 #ifndef QT_NO_OPENSSL
125  void _q_slotEncryptedBytesWritten(qint64 numBytes);
126 #endif
127  void _q_slotDoFinished();
128  void _q_slotSendRequest();
129  void _q_continuePost();
130 
131  int addRequest(QHttpNormalRequest *);
132  int addRequest(QHttpRequest *);
133  void finishedWithSuccess();
134  void finishedWithError(const QString &detail, int errorCode);
135 
136  void init();
137  void setState(int);
138  void closeConn();
139  void setSock(QTcpSocket *sock);
140 
141  void postMoreData();
142 
147 
151 
155 
159 
163 
165 
169 
171 
172 #ifndef QT_NO_NETWORKPROXY
175 #endif
177  bool repost;
181 };
182 
184 
186 {
187  return false;
188 }
189 
191 {
192  return QHttpRequestHeader();
193 }
194 
195 /****************************************************
196  *
197  * QHttpNormalRequest
198  *
199  ****************************************************/
200 
202 {
203 public:
205  header(h), to(t)
206  {
207  is_ba = false;
208  data.dev = d;
209  }
210 
212  header(h), to(t)
213  {
214  is_ba = true;
215  data.ba = d;
216  }
217 
219  {
220  if (is_ba)
221  delete data.ba;
222  }
223 
224  void start(QHttp *);
225  bool hasRequestHeader();
227  inline void setRequestHeader(const QHttpRequestHeader &h) { header = h; }
228 
231 
232 protected:
234 
235 private:
236  union {
239  } data;
240  bool is_ba;
242 };
243 
245 {
246  if (!http->d_func()->socket)
247  http->d_func()->setSock(0);
248  http->d_func()->header = header;
249 
250  if (is_ba) {
251  http->d_func()->buffer = *data.ba;
252  if (http->d_func()->buffer.size() >= 0)
253  http->d_func()->header.setContentLength(http->d_func()->buffer.size());
254 
255  http->d_func()->postDevice = 0;
256  } else {
257  http->d_func()->buffer = QByteArray();
258 
259  if (data.dev && (data.dev->isOpen() || data.dev->open(QIODevice::ReadOnly))) {
260  http->d_func()->postDevice = data.dev;
261  if (http->d_func()->postDevice->size() >= 0)
262  http->d_func()->header.setContentLength(http->d_func()->postDevice->size());
263  } else {
264  http->d_func()->postDevice = 0;
265  }
266  }
267 
268  if (to && (to->isOpen() || to->open(QIODevice::WriteOnly)))
269  http->d_func()->toDevice = to;
270  else
271  http->d_func()->toDevice = 0;
272 
273  http->d_func()->reconnectAttempts = 2;
274  http->d_func()->_q_slotSendRequest();
275 }
276 
278 {
279  return true;
280 }
281 
283 {
284  return header;
285 }
286 
288 {
289  if (is_ba)
290  return 0;
291  return data.dev;
292 }
293 
295 {
296  return to;
297 }
298 
299 /****************************************************
300  *
301  * QHttpPGHRequest
302  * (like a QHttpNormalRequest, but for the convenience
303  * functions put(), get() and head() -- i.e. set the
304  * host header field correctly before sending the
305  * request)
306  *
307  ****************************************************/
308 
310 {
311 public:
313  QHttpNormalRequest(h, d, t)
314  { }
315 
317  QHttpNormalRequest(h, d, t)
318  { }
319 
321  { }
322 
323  void start(QHttp *);
324 };
325 
327 {
328  if (http->d_func()->port && http->d_func()->port != 80)
329  header.setValue(QLatin1String("Host"), http->d_func()->hostName + QLatin1Char(':') + QString::number(http->d_func()->port));
330  else
331  header.setValue(QLatin1String("Host"), http->d_func()->hostName);
333 }
334 
335 /****************************************************
336  *
337  * QHttpSetHostRequest
338  *
339  ****************************************************/
340 
342 {
343 public:
345  : hostName(h), port(p), mode(m)
346  { }
347 
348  void start(QHttp *);
349 
351  { return 0; }
353  { return 0; }
354 
355 private:
359 };
360 
362 {
363  http->d_func()->hostName = hostName;
364  http->d_func()->port = port;
365  http->d_func()->mode = mode;
366 
367 #ifdef QT_NO_OPENSSL
368  if (mode == QHttp::ConnectionModeHttps) {
369  // SSL requested but no SSL support compiled in
370  http->d_func()->finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "HTTPS connection requested but SSL support not compiled in")),
372  return;
373  }
374 #endif
375 
376  http->d_func()->finishedWithSuccess();
377 }
378 
379 /****************************************************
380  *
381  * QHttpSetUserRequest
382  *
383  ****************************************************/
384 
386 {
387 public:
388  QHttpSetUserRequest(const QString &userName, const QString &password) :
389  user(userName), pass(password)
390  { }
391 
392  void start(QHttp *);
393 
395  { return 0; }
397  { return 0; }
398 
399 private:
402 };
403 
405 {
406  http->d_func()->authenticator.setUser(user);
407  http->d_func()->authenticator.setPassword(pass);
408  http->d_func()->finishedWithSuccess();
409 }
410 
411 #ifndef QT_NO_NETWORKPROXY
412 
413 /****************************************************
414  *
415  * QHttpSetProxyRequest
416  *
417  ****************************************************/
418 
420 {
421 public:
422  inline QHttpSetProxyRequest(const QNetworkProxy &proxy)
423  {
424  this->proxy = proxy;
425  }
426 
427  inline void start(QHttp *http)
428  {
429  http->d_func()->proxy = proxy;
430  QString user = proxy.user();
431  if (!user.isEmpty())
432  http->d_func()->proxyAuthenticator.setUser(user);
433  QString password = proxy.password();
434  if (!password.isEmpty())
435  http->d_func()->proxyAuthenticator.setPassword(password);
436  http->d_func()->finishedWithSuccess();
437  }
438 
440  { return 0; }
442  { return 0; }
443 private:
445 };
446 
447 #endif // QT_NO_NETWORKPROXY
448 
449 /****************************************************
450  *
451  * QHttpSetSocketRequest
452  *
453  ****************************************************/
454 
456 {
457 public:
459  { }
460 
461  void start(QHttp *);
462 
464  { return 0; }
466  { return 0; }
467 
468 private:
470 };
471 
473 {
474  http->d_func()->setSock(socket);
475  http->d_func()->finishedWithSuccess();
476 }
477 
478 /****************************************************
479  *
480  * QHttpCloseRequest
481  *
482  ****************************************************/
483 
485 {
486 public:
488  { }
489  void start(QHttp *);
490 
492  { return 0; }
494  { return 0; }
495 };
496 
498 {
499  http->d_func()->closeConn();
500 }
501 
503 {
505 public:
506  inline virtual ~QHttpHeaderPrivate() {}
507 
509  bool valid;
511 };
512 
513 /****************************************************
514  *
515  * QHttpHeader
516  *
517  ****************************************************/
518 
579  : d_ptr(new QHttpHeaderPrivate)
580 {
581  Q_D(QHttpHeader);
582  d->q_ptr = this;
583  d->valid = true;
584 }
585 
591 {
592  Q_D(QHttpHeader);
593  d->q_ptr = this;
594  d->valid = header.d_func()->valid;
595  d->values = header.d_func()->values;
596 }
597 
608 {
609  Q_D(QHttpHeader);
610  d->q_ptr = this;
611  d->valid = true;
612  parse(str);
613 }
614 
618  : d_ptr(&dd)
619 {
620  Q_D(QHttpHeader);
621  d->q_ptr = this;
622  d->valid = true;
623  if (!str.isEmpty())
624  parse(str);
625 }
626 
630  : d_ptr(&dd)
631 {
632  Q_D(QHttpHeader);
633  d->q_ptr = this;
634  d->valid = header.d_func()->valid;
635  d->values = header.d_func()->values;
636 }
641 {
642 }
643 
648 {
649  Q_D(QHttpHeader);
650  d->values = h.d_func()->values;
651  d->valid = h.d_func()->valid;
652  return *this;
653 }
654 
661 {
662  Q_D(const QHttpHeader);
663  return d->valid;
664 }
665 
678 bool QHttpHeader::parse(const QString &str)
679 {
680  Q_D(QHttpHeader);
681  QStringList lst;
682  int pos = str.indexOf(QLatin1Char('\n'));
683  if (pos > 0 && str.at(pos - 1) == QLatin1Char('\r'))
684  lst = str.trimmed().split(QLatin1String("\r\n"));
685  else
686  lst = str.trimmed().split(QLatin1String("\n"));
687  lst.removeAll(QString()); // No empties
688 
689  if (lst.isEmpty())
690  return true;
691 
692  QStringList lines;
694  for (; it != lst.end(); ++it) {
695  if (!(*it).isEmpty()) {
696  if ((*it)[0].isSpace()) {
697  if (!lines.isEmpty()) {
698  lines.last() += QLatin1Char(' ');
699  lines.last() += (*it).trimmed();
700  }
701  } else {
702  lines.append((*it));
703  }
704  }
705  }
706 
707  int number = 0;
708  it = lines.begin();
709  for (; it != lines.end(); ++it) {
710  if (!parseLine(*it, number++)) {
711  d->valid = false;
712  return false;
713  }
714  }
715  return true;
716 }
717 
721 {
722  Q_D(QHttpHeader);
723  d->valid = v;
724 }
725 
733 {
734  Q_D(const QHttpHeader);
735  QString lowercaseKey = key.toLower();
736  QList<QPair<QString, QString> >::ConstIterator it = d->values.constBegin();
737  while (it != d->values.constEnd()) {
738  if ((*it).first.toLower() == lowercaseKey)
739  return (*it).second;
740  ++it;
741  }
742  return QString();
743 }
744 
750 {
751  Q_D(const QHttpHeader);
752  QString lowercaseKey = key.toLower();
753  QStringList valueList;
754  QList<QPair<QString, QString> >::ConstIterator it = d->values.constBegin();
755  while (it != d->values.constEnd()) {
756  if ((*it).first.toLower() == lowercaseKey)
757  valueList.append((*it).second);
758  ++it;
759  }
760  return valueList;
761 }
762 
769 {
770  Q_D(const QHttpHeader);
771  QStringList keyList;
772  QSet<QString> seenKeys;
773  QList<QPair<QString, QString> >::ConstIterator it = d->values.constBegin();
774  while (it != d->values.constEnd()) {
775  const QString &key = (*it).first;
776  QString lowercaseKey = key.toLower();
777  if (!seenKeys.contains(lowercaseKey)) {
778  keyList.append(key);
779  seenKeys.insert(lowercaseKey);
780  }
781  ++it;
782  }
783  return keyList;
784 }
785 
792 bool QHttpHeader::hasKey(const QString &key) const
793 {
794  Q_D(const QHttpHeader);
795  QString lowercaseKey = key.toLower();
796  QList<QPair<QString, QString> >::ConstIterator it = d->values.constBegin();
797  while (it != d->values.constEnd()) {
798  if ((*it).first.toLower() == lowercaseKey)
799  return true;
800  ++it;
801  }
802  return false;
803 }
804 
816 {
817  Q_D(QHttpHeader);
818  QString lowercaseKey = key.toLower();
819  QList<QPair<QString, QString> >::Iterator it = d->values.begin();
820  while (it != d->values.end()) {
821  if ((*it).first.toLower() == lowercaseKey) {
822  (*it).second = value;
823  return;
824  }
825  ++it;
826  }
827  // not found so add
828  addValue(key, value);
829 }
830 
835 {
836  Q_D(QHttpHeader);
837  d->values = values;
838 }
839 
844 {
845  Q_D(QHttpHeader);
846  d->values.append(qMakePair(key, value));
847 }
848 
853 {
854  Q_D(const QHttpHeader);
855  return d->values;
856 }
857 
864 {
865  Q_D(QHttpHeader);
866  QString lowercaseKey = key.toLower();
867  QList<QPair<QString, QString> >::Iterator it = d->values.begin();
868  while (it != d->values.end()) {
869  if ((*it).first.toLower() == lowercaseKey) {
870  d->values.erase(it);
871  return;
872  }
873  ++it;
874  }
875 }
876 
881 {
882  Q_D(QHttpHeader);
883  QString lowercaseKey = key.toLower();
884  QList<QPair<QString, QString> >::Iterator it = d->values.begin();
885  while (it != d->values.end()) {
886  if ((*it).first.toLower() == lowercaseKey) {
887  it = d->values.erase(it);
888  continue;
889  }
890  ++it;
891  }
892 }
893 
905 bool QHttpHeader::parseLine(const QString &line, int)
906 {
907  int i = line.indexOf(QLatin1Char(':'));
908  if (i == -1)
909  return false;
910 
911  addValue(line.left(i).trimmed(), line.mid(i + 1).trimmed());
912 
913  return true;
914 }
915 
924 {
925  Q_D(const QHttpHeader);
926  if (!isValid())
927  return QLatin1String("");
928 
929  QString ret = QLatin1String("");
930 
931  QList<QPair<QString, QString> >::ConstIterator it = d->values.constBegin();
932  while (it != d->values.constEnd()) {
933  ret += (*it).first + QLatin1String(": ") + (*it).second + QLatin1String("\r\n");
934  ++it;
935  }
936  return ret;
937 }
938 
946 {
947  return hasKey(QLatin1String("content-length"));
948 }
949 
957 {
958  return value(QLatin1String("content-length")).toUInt();
959 }
960 
968 {
969  setValue(QLatin1String("content-length"), QString::number(len));
970 }
971 
979 {
980  return hasKey(QLatin1String("content-type"));
981 }
982 
989 {
990  QString type = value(QLatin1String("content-type"));
991  if (type.isEmpty())
992  return QString();
993 
994  int pos = type.indexOf(QLatin1Char(';'));
995  if (pos == -1)
996  return type;
997 
998  return type.left(pos).trimmed();
999 }
1000 
1008 {
1009  setValue(QLatin1String("content-type"), type);
1010 }
1011 
1013 {
1015 public:
1018  int majVer;
1019  int minVer;
1020 };
1021 
1022 /****************************************************
1023  *
1024  * QHttpResponseHeader
1025  *
1026  ****************************************************/
1027 
1057 {
1058  setValid(false);
1059 }
1060 
1065  : QHttpHeader(*new QHttpResponseHeaderPrivate, header)
1066 {
1068  d->statCode = header.d_func()->statCode;
1069  d->reasonPhr = header.d_func()->reasonPhr;
1070  d->majVer = header.d_func()->majVer;
1071  d->minVer = header.d_func()->minVer;
1072 }
1073 
1078 {
1080  QHttpHeader::operator=(header);
1081  d->statCode = header.d_func()->statCode;
1082  d->reasonPhr = header.d_func()->reasonPhr;
1083  d->majVer = header.d_func()->majVer;
1084  d->minVer = header.d_func()->minVer;
1085  return *this;
1086 }
1087 
1098 {
1099  parse(str);
1100 }
1101 
1114 QHttpResponseHeader::QHttpResponseHeader(int code, const QString &text, int majorVer, int minorVer)
1116 {
1117  setStatusLine(code, text, majorVer, minorVer);
1118 }
1119 
1131 void QHttpResponseHeader::setStatusLine(int code, const QString &text, int majorVer, int minorVer)
1132 {
1134  setValid(true);
1135  d->statCode = code;
1136  d->reasonPhr = text;
1137  d->majVer = majorVer;
1138  d->minVer = minorVer;
1139 }
1140 
1147 {
1148  Q_D(const QHttpResponseHeader);
1149  return d->statCode;
1150 }
1151 
1158 {
1159  Q_D(const QHttpResponseHeader);
1160  return d->reasonPhr;
1161 }
1162 
1169 {
1170  Q_D(const QHttpResponseHeader);
1171  return d->majVer;
1172 }
1173 
1180 {
1181  Q_D(const QHttpResponseHeader);
1182  return d->minVer;
1183 }
1184 
1187 bool QHttpResponseHeader::parseLine(const QString &line, int number)
1188 {
1190  if (number != 0)
1191  return QHttpHeader::parseLine(line, number);
1192 
1193  QString l = line.simplified();
1194  if (l.length() < 10)
1195  return false;
1196 
1197  if (l.left(5) == QLatin1String("HTTP/") && l[5].isDigit() && l[6] == QLatin1Char('.') &&
1198  l[7].isDigit() && l[8] == QLatin1Char(' ') && l[9].isDigit()) {
1199  d->majVer = l[5].toLatin1() - '0';
1200  d->minVer = l[7].toLatin1() - '0';
1201 
1202  int pos = l.indexOf(QLatin1Char(' '), 9);
1203  if (pos != -1) {
1204  d->reasonPhr = l.mid(pos + 1);
1205  d->statCode = l.mid(9, pos - 9).toInt();
1206  } else {
1207  d->statCode = l.mid(9).toInt();
1208  d->reasonPhr.clear();
1209  }
1210  } else {
1211  return false;
1212  }
1213 
1214  return true;
1215 }
1216 
1220 {
1221  Q_D(const QHttpResponseHeader);
1222  QString ret(QLatin1String("HTTP/%1.%2 %3 %4\r\n%5\r\n"));
1223  return ret.arg(d->majVer).arg(d->minVer).arg(d->statCode).arg(d->reasonPhr).arg(QHttpHeader::toString());
1224 }
1225 
1227 {
1229 public:
1232  int majVer;
1233  int minVer;
1234 };
1235 
1236 /****************************************************
1237  *
1238  * QHttpRequestHeader
1239  *
1240  ****************************************************/
1241 
1281 {
1282  setValid(false);
1283 }
1284 
1291 QHttpRequestHeader::QHttpRequestHeader(const QString &method, const QString &path, int majorVer, int minorVer)
1293 {
1295  d->m = method;
1296  d->p = path;
1297  d->majVer = majorVer;
1298  d->minVer = minorVer;
1299 }
1300 
1305  : QHttpHeader(*new QHttpRequestHeaderPrivate, header)
1306 {
1308  d->m = header.d_func()->m;
1309  d->p = header.d_func()->p;
1310  d->majVer = header.d_func()->majVer;
1311  d->minVer = header.d_func()->minVer;
1312 }
1313 
1318 {
1320  QHttpHeader::operator=(header);
1321  d->m = header.d_func()->m;
1322  d->p = header.d_func()->p;
1323  d->majVer = header.d_func()->majVer;
1324  d->minVer = header.d_func()->minVer;
1325  return *this;
1326 }
1327 
1337 {
1338  parse(str);
1339 }
1340 
1349 void QHttpRequestHeader::setRequest(const QString &method, const QString &path, int majorVer, int minorVer)
1350 {
1352  setValid(true);
1353  d->m = method;
1354  d->p = path;
1355  d->majVer = majorVer;
1356  d->minVer = minorVer;
1357 }
1358 
1365 {
1366  Q_D(const QHttpRequestHeader);
1367  return d->m;
1368 }
1369 
1376 {
1377  Q_D(const QHttpRequestHeader);
1378  return d->p;
1379 }
1380 
1387 {
1388  Q_D(const QHttpRequestHeader);
1389  return d->majVer;
1390 }
1391 
1398 {
1399  Q_D(const QHttpRequestHeader);
1400  return d->minVer;
1401 }
1402 
1405 bool QHttpRequestHeader::parseLine(const QString &line, int number)
1406 {
1408  if (number != 0)
1409  return QHttpHeader::parseLine(line, number);
1410 
1411  QStringList lst = line.simplified().split(QLatin1String(" "));
1412  if (lst.count() > 0) {
1413  d->m = lst[0];
1414  if (lst.count() > 1) {
1415  d->p = lst[1];
1416  if (lst.count() > 2) {
1417  QString v = lst[2];
1418  if (v.length() >= 8 && v.left(5) == QLatin1String("HTTP/") &&
1419  v[5].isDigit() && v[6] == QLatin1Char('.') && v[7].isDigit()) {
1420  d->majVer = v[5].toLatin1() - '0';
1421  d->minVer = v[7].toLatin1() - '0';
1422  return true;
1423  }
1424  }
1425  }
1426  }
1427 
1428  return false;
1429 }
1430 
1434 {
1435  Q_D(const QHttpRequestHeader);
1436  QString first(QLatin1String("%1 %2"));
1437  QString last(QLatin1String(" HTTP/%3.%4\r\n%5\r\n"));
1438  return first.arg(d->m).arg(d->p) +
1439  last.arg(d->majVer).arg(d->minVer).arg(QHttpHeader::toString());
1440 }
1441 
1442 
1443 /****************************************************
1444  *
1445  * QHttp
1446  *
1447  ****************************************************/
1560  : QObject(*new QHttpPrivate, parent)
1561 {
1562  Q_D(QHttp);
1563  d->init();
1564 }
1565 
1574 QHttp::QHttp(const QString &hostName, quint16 port, QObject *parent)
1575  : QObject(*new QHttpPrivate, parent)
1576 {
1577  Q_D(QHttp);
1578  d->init();
1579 
1580  d->hostName = hostName;
1581  d->port = port;
1582 }
1583 
1597  : QObject(*new QHttpPrivate, parent)
1598 {
1599  Q_D(QHttp);
1600  d->init();
1601 
1602  d->hostName = hostName;
1603  if (port == 0)
1604  port = (mode == ConnectionModeHttp) ? 80 : 443;
1605  d->port = port;
1606  d->mode = mode;
1607 }
1608 
1610 {
1611  Q_Q(QHttp);
1612  errorString = QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Unknown error"));
1613  QMetaObject::invokeMethod(q, "_q_slotDoFinished", Qt::QueuedConnection);
1614  post100ContinueTimer.setSingleShot(true);
1615  QObject::connect(&post100ContinueTimer, SIGNAL(timeout()), q, SLOT(_q_continuePost()));
1616 }
1617 
1623 {
1624  abort();
1625 }
1626 
1829 #ifndef QT_NO_NETWORKPROXY
1830 
1847 #endif
1848 
1895 {
1896  Q_D(QHttp);
1897  if (d->pending.isEmpty())
1898  return;
1899 
1900  d->finishedWithError(tr("Request aborted"), Aborted);
1902  if (d->socket)
1903  d->socket->abort();
1904  d->closeConn();
1905 }
1906 
1914 {
1915  Q_D(const QHttp);
1916 #if defined(QHTTP_DEBUG)
1917  qDebug("QHttp::bytesAvailable(): %d bytes", (int)d->rba.size());
1918 #endif
1919  return qint64(d->rba.size());
1920 }
1921 
1934 {
1935  Q_D(QHttp);
1936  if (data == 0 && maxlen != 0) {
1937  qWarning("QHttp::read: Null pointer error");
1938  return -1;
1939  }
1940  if (maxlen >= d->rba.size())
1941  maxlen = d->rba.size();
1942  int readSoFar = 0;
1943  while (!d->rba.isEmpty() && readSoFar < maxlen) {
1944  int nextBlockSize = d->rba.nextDataBlockSize();
1945  int bytesToRead = qMin<qint64>(maxlen - readSoFar, nextBlockSize);
1946  memcpy(data + readSoFar, d->rba.readPointer(), bytesToRead);
1947  d->rba.free(bytesToRead);
1948  readSoFar += bytesToRead;
1949  }
1950 
1951  d->bytesDone += maxlen;
1952 #if defined(QHTTP_DEBUG)
1953  qDebug("QHttp::read(): read %lld bytes (%lld bytes done)", maxlen, d->bytesDone);
1954 #endif
1955  return maxlen;
1956 }
1957 
1964 {
1965  qint64 avail = bytesAvailable();
1966  QByteArray tmp;
1967  tmp.resize(int(avail));
1968  qint64 got = read(tmp.data(), int(avail));
1969  tmp.resize(got);
1970  return tmp;
1971 }
1972 
1979 int QHttp::currentId() const
1980 {
1981  Q_D(const QHttp);
1982  if (d->pending.isEmpty())
1983  return 0;
1984  return d->pending.first()->id;
1985 }
1986 
1996 {
1997  Q_D(const QHttp);
1998  if (!d->pending.isEmpty()) {
1999  QHttpRequest *r = d->pending.first();
2000  if (r->hasRequestHeader())
2001  return r->requestHeader();
2002  }
2003  return QHttpRequestHeader();
2004 }
2005 
2014 {
2015  Q_D(const QHttp);
2016  return d->response;
2017 }
2018 
2030 {
2031  Q_D(const QHttp);
2032  if (d->pending.isEmpty())
2033  return 0;
2034  return d->pending.first()->sourceDevice();
2035 }
2036 
2048 {
2049  Q_D(const QHttp);
2050  if (d->pending.isEmpty())
2051  return 0;
2052  return d->pending.first()->destinationDevice();
2053 }
2054 
2065 {
2066  Q_D(const QHttp);
2067  return d->pending.count() > 1;
2068 }
2069 
2078 {
2079  Q_D(QHttp);
2080  // delete all entires except the first one
2081  while (d->pending.count() > 1)
2082  delete d->pending.takeLast();
2083 }
2084 
2100 int QHttp::setHost(const QString &hostName, quint16 port)
2101 {
2102  Q_D(QHttp);
2103  return d->addRequest(new QHttpSetHostRequest(hostName, port, ConnectionModeHttp));
2104 }
2105 
2124 int QHttp::setHost(const QString &hostName, ConnectionMode mode, quint16 port)
2125 {
2126 #ifdef QT_NO_OPENSSL
2127  if (mode == ConnectionModeHttps)
2128  qWarning("QHttp::setHost: HTTPS connection requested but SSL support not compiled in");
2129 #endif
2130  Q_D(QHttp);
2131  if (port == 0)
2132  port = (mode == ConnectionModeHttp) ? 80 : 443;
2133  return d->addRequest(new QHttpSetHostRequest(hostName, port, mode));
2134 }
2135 
2158 {
2159  Q_D(QHttp);
2160  return d->addRequest(new QHttpSetSocketRequest(socket));
2161 }
2162 
2176 int QHttp::setUser(const QString &userName, const QString &password)
2177 {
2178  Q_D(QHttp);
2179  return d->addRequest(new QHttpSetUserRequest(userName, password));
2180 }
2181 
2182 #ifndef QT_NO_NETWORKPROXY
2183 
2203 int QHttp::setProxy(const QString &host, int port,
2204  const QString &username, const QString &password)
2205 {
2206  Q_D(QHttp);
2207  QNetworkProxy proxy(QNetworkProxy::HttpProxy, host, port, username, password);
2208  return d->addRequest(new QHttpSetProxyRequest(proxy));
2209 }
2210 
2229 {
2230  Q_D(QHttp);
2231  return d->addRequest(new QHttpSetProxyRequest(proxy));
2232 }
2233 
2234 #endif
2235 
2267 int QHttp::get(const QString &path, QIODevice *to)
2268 {
2269  Q_D(QHttp);
2270  QHttpRequestHeader header(QLatin1String("GET"), path);
2271  header.setValue(QLatin1String("Connection"), QLatin1String("Keep-Alive"));
2272  return d->addRequest(new QHttpPGHRequest(header, (QIODevice *) 0, to));
2273 }
2274 
2305 int QHttp::post(const QString &path, QIODevice *data, QIODevice *to )
2306 {
2307  Q_D(QHttp);
2308  QHttpRequestHeader header(QLatin1String("POST"), path);
2309  header.setValue(QLatin1String("Connection"), QLatin1String("Keep-Alive"));
2310  return d->addRequest(new QHttpPGHRequest(header, data, to));
2311 }
2312 
2318 int QHttp::post(const QString &path, const QByteArray &data, QIODevice *to)
2319 {
2320  Q_D(QHttp);
2321  QHttpRequestHeader header(QLatin1String("POST"), path);
2322  header.setValue(QLatin1String("Connection"), QLatin1String("Keep-Alive"));
2323  return d->addRequest(new QHttpPGHRequest(header, new QByteArray(data), to));
2324 }
2325 
2344 int QHttp::head(const QString &path)
2345 {
2346  Q_D(QHttp);
2347  QHttpRequestHeader header(QLatin1String("HEAD"), path);
2348  header.setValue(QLatin1String("Connection"), QLatin1String("Keep-Alive"));
2349  return d->addRequest(new QHttpPGHRequest(header, (QIODevice*)0, 0));
2350 }
2351 
2380 {
2381  Q_D(QHttp);
2382  return d->addRequest(new QHttpNormalRequest(header, data, to));
2383 }
2384 
2391 {
2392  Q_D(QHttp);
2393  return d->addRequest(new QHttpNormalRequest(header, new QByteArray(data), to));
2394 }
2395 
2421 {
2422  Q_D(QHttp);
2423  return d->addRequest(new QHttpCloseRequest());
2424 }
2425 
2435 {
2436  Q_D(QHttp);
2437  return d->addRequest(new QHttpCloseRequest());
2438 }
2439 
2441 {
2442  QHttpRequestHeader h = req->requestHeader();
2443  if (h.path().isEmpty()) {
2444  // note: the following qWarning is autotested. If you change it, change the test too.
2445  qWarning("QHttp: empty path requested is invalid -- using '/'");
2446  h.setRequest(h.method(), QLatin1String("/"), h.majorVersion(), h.minorVersion());
2447  req->setRequestHeader(h);
2448  }
2449 
2450  // contine below
2451  return addRequest(static_cast<QHttpRequest *>(req));
2452 }
2453 
2455 {
2456  Q_Q(QHttp);
2457  pending.append(req);
2458 
2459  if (pending.count() == 1) {
2460  // don't emit the requestStarted() signal before the id is returned
2461  QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
2462  }
2463  return req->id;
2464 }
2465 
2467 {
2468  Q_Q(QHttp);
2469  if (pending.isEmpty())
2470  return;
2471  QHttpRequest *r = pending.first();
2472 
2474  errorString = QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Unknown error"));
2475 
2476  if (q->bytesAvailable() != 0)
2477  q->readAll(); // clear the data
2478  emit q->requestStarted(r->id);
2479  r->start(q);
2480 }
2481 
2483 {
2484  if (hostName.isNull()) {
2485  finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "No server set to connect to")),
2487  return;
2488  }
2489 
2490  QString connectionHost = hostName;
2491  int connectionPort = port;
2492  bool sslInUse = false;
2493 
2494 #ifndef QT_NO_OPENSSL
2495  QSslSocket *sslSocket = qobject_cast<QSslSocket *>(socket);
2496  if (mode == QHttp::ConnectionModeHttps || (sslSocket && sslSocket->isEncrypted()))
2497  sslInUse = true;
2498 #endif
2499 
2500 #ifndef QT_NO_NETWORKPROXY
2501  bool cachingProxyInUse = false;
2502  bool transparentProxyInUse = false;
2503  if (proxy.type() == QNetworkProxy::DefaultProxy)
2505 
2506  if (proxy.type() == QNetworkProxy::HttpCachingProxy) {
2507  if (proxy.hostName().isEmpty())
2509  else
2510  cachingProxyInUse = true;
2511  } else if (proxy.type() == QNetworkProxy::HttpProxy) {
2512  // Compatibility behaviour: HttpProxy can be used to mean both
2513  // transparent and caching proxy
2514  if (proxy.hostName().isEmpty()) {
2516  } else if (sslInUse) {
2517  // Disallow use of caching proxy with HTTPS; instead fall back to
2518  // transparent HTTP CONNECT proxying.
2519  transparentProxyInUse = true;
2520  } else {
2522  cachingProxyInUse = true;
2523  }
2524  }
2525 
2526  // Proxy support. Insert the Proxy-Authorization item into the
2527  // header before it's sent off to the proxy.
2528  if (cachingProxyInUse) {
2529  QUrl proxyUrl;
2530  proxyUrl.setScheme(QLatin1String("http"));
2531  proxyUrl.setHost(hostName);
2532  if (port && port != 80)
2533  proxyUrl.setPort(port);
2535 
2536  header.setRequest(header.method(), request, header.majorVersion(), header.minorVersion());
2537  header.setValue(QLatin1String("Proxy-Connection"), QLatin1String("keep-alive"));
2538 
2539  QAuthenticatorPrivate *auth = QAuthenticatorPrivate::getPrivate(proxyAuthenticator);
2540  if (auth && auth->method != QAuthenticatorPrivate::None) {
2541  QByteArray response = auth->calculateResponse(header.method().toLatin1(), header.path().toLatin1());
2542  header.setValue(QLatin1String("Proxy-Authorization"), QString::fromLatin1(response));
2543  }
2544 
2545  connectionHost = proxy.hostName();
2546  connectionPort = proxy.port();
2547  }
2548 
2549  if (transparentProxyInUse || sslInUse) {
2550  socket->setProxy(proxy);
2551  }
2552 #endif
2553 
2554  // Username support. Insert the user and password into the query
2555  // string.
2557  if (auth && auth->method != QAuthenticatorPrivate::None) {
2558  QByteArray response = auth->calculateResponse(header.method().toLatin1(), header.path().toLatin1());
2559  header.setValue(QLatin1String("Authorization"), QString::fromLatin1(response));
2560  }
2561 
2562  // Do we need to setup a new connection or can we reuse an
2563  // existing one?
2564  if (socket->peerName() != connectionHost || socket->peerPort() != connectionPort
2565  || socket->state() != QTcpSocket::ConnectedState
2566 #ifndef QT_NO_OPENSSL
2567  || (sslSocket && sslSocket->isEncrypted() != (mode == QHttp::ConnectionModeHttps))
2568 #endif
2569  ) {
2570  socket->blockSignals(true);
2571  socket->abort();
2572  socket->blockSignals(false);
2573 
2574  setState(QHttp::Connecting);
2575 #ifndef QT_NO_OPENSSL
2576  if (sslSocket && mode == QHttp::ConnectionModeHttps) {
2577  sslSocket->connectToHostEncrypted(hostName, port);
2578  } else
2579 #endif
2580  {
2581  socket->connectToHost(connectionHost, connectionPort);
2582  }
2583  } else {
2584  _q_slotConnected();
2585  }
2586 
2587 }
2588 
2590 {
2591  Q_Q(QHttp);
2592  if (pending.isEmpty())
2593  return;
2594  QHttpRequest *r = pending.first();
2595 
2596  // did we recurse?
2597  if (r->finished)
2598  return;
2599  r->finished = true;
2600  hasFinishedWithError = false;
2601 
2602  emit q->requestFinished(r->id, false);
2603  if (hasFinishedWithError) {
2604  // we recursed and changed into an error. The finishedWithError function
2605  // below has emitted the done(bool) signal and cleared the queue by now.
2606  return;
2607  }
2608 
2609  pending.removeFirst();
2610  delete r;
2611 
2612  if (pending.isEmpty()) {
2613  emit q->done(false);
2614  } else {
2615  _q_startNextRequest();
2616  }
2617 }
2618 
2619 void QHttpPrivate::finishedWithError(const QString &detail, int errorCode)
2620 {
2621  Q_Q(QHttp);
2622  if (pending.isEmpty())
2623  return;
2624  QHttpRequest *r = pending.first();
2625  hasFinishedWithError = true;
2626 
2627  error = QHttp::Error(errorCode);
2628  errorString = detail;
2629 
2630  // did we recurse?
2631  if (!r->finished) {
2632  r->finished = true;
2633  emit q->requestFinished(r->id, true);
2634  }
2635 
2636  while (!pending.isEmpty())
2637  delete pending.takeFirst();
2638  emit q->done(hasFinishedWithError);
2639 }
2640 
2642 {
2643  Q_Q(QHttp);
2644 
2645  if (state == QHttp::Reading) {
2646  if (response.hasKey(QLatin1String("content-length"))) {
2647  // We got Content-Length, so did we get all bytes?
2648  if (bytesDone + q->bytesAvailable() != response.contentLength()) {
2649  finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Wrong content length")), QHttp::WrongContentLength);
2650  }
2651  }
2652  } else if (state == QHttp::Connecting || state == QHttp::Sending) {
2653  finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Server closed connection unexpectedly")), QHttp::UnexpectedClose);
2654  }
2655 
2656  postDevice = 0;
2657  if (state != QHttp::Closing)
2658  setState(QHttp::Closing);
2659  QMetaObject::invokeMethod(q, "_q_slotDoFinished", Qt::QueuedConnection);
2660 }
2661 
2663 {
2664  if (pendingPost) {
2665  pendingPost = false;
2666  setState(QHttp::Sending);
2667  _q_slotBytesWritten(0);
2668  }
2669 }
2670 
2672 {
2673  if (state != QHttp::Sending) {
2674  bytesDone = 0;
2675  setState(QHttp::Sending);
2676  }
2677 
2678  QString str = header.toString();
2679  bytesTotal = str.length();
2680  socket->write(str.toLatin1(), bytesTotal);
2681 #if defined(QHTTP_DEBUG)
2682  qDebug("QHttp: write request header %p:\n---{\n%s}---", &header, str.toLatin1().constData());
2683 #endif
2684 
2685  if (postDevice) {
2686  postDevice->seek(0); // reposition the device
2687  bytesTotal += postDevice->size();
2688  //check for 100-continue
2689  if (header.value(QLatin1String("expect")).contains(QLatin1String("100-continue"), Qt::CaseInsensitive)) {
2690  //create a time out for 2 secs.
2691  pendingPost = true;
2692  post100ContinueTimer.start(2000);
2693  }
2694  } else {
2695  bytesTotal += buffer.size();
2696  socket->write(buffer, buffer.size());
2697  }
2698 }
2699 
2701 {
2702  Q_Q(QHttp);
2703  postDevice = 0;
2704 
2706  switch (err) {
2708  finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Connection refused (or timed out)")), QHttp::ConnectionRefused);
2709  break;
2711  finishedWithError(QString::fromLatin1(QT_TRANSLATE_NOOP("QHttp", "Host %1 not found"))
2712  .arg(socket->peerName()), QHttp::HostNotFound);
2713  break;
2715  if (state == QHttp::Sending && reconnectAttempts--) {
2716  setState(QHttp::Closing);
2717  setState(QHttp::Unconnected);
2718  socket->blockSignals(true);
2719  socket->abort();
2720  socket->blockSignals(false);
2721  QMetaObject::invokeMethod(q, "_q_slotSendRequest", Qt::QueuedConnection);
2722  return;
2723  }
2724  break;
2725 #ifndef QT_NO_NETWORKPROXY
2727  finishedWithError(socket->errorString(), QHttp::ProxyAuthenticationRequiredError);
2728  break;
2729 #endif
2730  default:
2731  finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "HTTP request failed")), QHttp::UnknownError);
2732  break;
2733  }
2734  }
2735 
2736  closeConn();
2737 }
2738 
2739 #ifndef QT_NO_OPENSSL
2741 {
2742  Q_UNUSED(written);
2743  postMoreData();
2744 }
2745 #endif
2746 
2748 {
2749  Q_Q(QHttp);
2750  bytesDone += written;
2751  emit q->dataSendProgress(bytesDone, bytesTotal);
2752  postMoreData();
2753 }
2754 
2755 // Send the POST data
2757 {
2758  if (pendingPost)
2759  return;
2760 
2761  if (!postDevice)
2762  return;
2763 
2764  // the following is backported code from Qt 4.6 QNetworkAccessManager.
2765  // We also have to check the encryptedBytesToWrite() if it is an SSL socket.
2766 #ifndef QT_NO_OPENSSL
2767  QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket);
2768  // if it is really an ssl socket, check more than just bytesToWrite()
2769  if ((socket->bytesToWrite() + (sslSocket ? sslSocket->encryptedBytesToWrite() : 0)) == 0) {
2770 #else
2771  if (socket->bytesToWrite() == 0) {
2772 #endif
2773  int max = qMin<qint64>(4096, postDevice->size() - postDevice->pos());
2774  QByteArray arr;
2775  arr.resize(max);
2776 
2777  int n = postDevice->read(arr.data(), max);
2778  if (n < 0) {
2779  qWarning("Could not read enough bytes from the device");
2780  closeConn();
2781  return;
2782  }
2783  if (postDevice->atEnd()) {
2784  postDevice = 0;
2785  }
2786 
2787  socket->write(arr, n);
2788  }
2789 }
2790 
2792 {
2793  Q_Q(QHttp);
2794  QHttp::State oldState = state;
2795  if (state != QHttp::Reading) {
2796  setState(QHttp::Reading);
2797  readHeader = true;
2798  headerStr = QLatin1String("");
2799  bytesDone = 0;
2800  chunkedSize = -1;
2801  repost = false;
2802  }
2803 
2804  while (readHeader) {
2805  bool end = false;
2806  QString tmp;
2807  while (!end && socket->canReadLine()) {
2808  tmp = QString::fromAscii(socket->readLine());
2809  if (tmp == QLatin1String("\r\n") || tmp == QLatin1String("\n") || tmp.isEmpty())
2810  end = true;
2811  else
2812  headerStr += tmp;
2813  }
2814 
2815  if (!end)
2816  return;
2817 
2818  response = QHttpResponseHeader(headerStr);
2819  headerStr = QLatin1String("");
2820 #if defined(QHTTP_DEBUG)
2821  qDebug("QHttp: read response header:\n---{\n%s}---", response.toString().toLatin1().constData());
2822 #endif
2823  // Check header
2824  if (!response.isValid()) {
2825  finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Invalid HTTP response header")),
2827  closeConn();
2828  return;
2829  }
2830 
2831  int statusCode = response.statusCode();
2832  if (statusCode == 401 || statusCode == 407) { // (Proxy) Authentication required
2833  QAuthenticator *auth =
2834 #ifndef QT_NO_NETWORKPROXY
2835  statusCode == 407
2836  ? &proxyAuthenticator :
2837 #endif
2838  &authenticator;
2839  if (auth->isNull())
2840  auth->detach();
2842  priv->parseHttpResponse(response, (statusCode == 407));
2843  if (priv->phase == QAuthenticatorPrivate::Done) {
2844  socket->blockSignals(true);
2845 #ifndef QT_NO_NETWORKPROXY
2846  if (statusCode == 407)
2847  emit q->proxyAuthenticationRequired(proxy, auth);
2848  else
2849 #endif
2850  emit q->authenticationRequired(hostName, port, auth);
2851  socket->blockSignals(false);
2852  } else if (priv->phase == QAuthenticatorPrivate::Invalid) {
2853  finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Unknown authentication method")),
2855  closeConn();
2856  return;
2857  }
2858 
2859  // priv->phase will get reset to QAuthenticatorPrivate::Start if the authenticator got modified in the signal above.
2860  if (priv->phase == QAuthenticatorPrivate::Done) {
2861 #ifndef QT_NO_NETWORKPROXY
2862  if (statusCode == 407)
2863  finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Proxy authentication required")),
2865  else
2866 #endif
2867  finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Authentication required")),
2869  closeConn();
2870  return;
2871  } else {
2872  // close the connection if it isn't already and reconnect using the chosen authentication method
2873  bool willClose = (response.value(QLatin1String("proxy-connection")).toLower() == QLatin1String("close"))
2874  || (response.value(QLatin1String("connection")).toLower() == QLatin1String("close"));
2875  if (willClose) {
2876  if (socket) {
2877  setState(QHttp::Closing);
2878  socket->blockSignals(true);
2879  socket->close();
2880  socket->blockSignals(false);
2881  socket->readAll();
2882  }
2883  _q_slotSendRequest();
2884  return;
2885  } else {
2886  repost = true;
2887  }
2888  }
2889  } else {
2890  buffer.clear();
2891  }
2892 
2893  if (response.statusCode() == 100 && pendingPost) {
2894  // if we have pending POST, start sending data otherwise ignore
2895  post100ContinueTimer.stop();
2896  QMetaObject::invokeMethod(q, "_q_continuePost", Qt::QueuedConnection);
2897  return;
2898  }
2899 
2900  // The 100-continue header is ignored (in case of no 'expect:100-continue' header),
2901  // because when using the POST method, we send both the request header and data in
2902  // one chunk.
2903  if (response.statusCode() != 100) {
2904  post100ContinueTimer.stop();
2905  pendingPost = false;
2906  readHeader = false;
2907  if (response.hasKey(QLatin1String("transfer-encoding")) &&
2908  response.value(QLatin1String("transfer-encoding")).toLower().contains(QLatin1String("chunked")))
2909  chunkedSize = 0;
2910 
2911  if (!repost)
2912  emit q->responseHeaderReceived(response);
2914  return;
2915  } else {
2916  // Restore the state, the next incoming data will be treated as if
2917  // we never say the 100 response.
2918  state = oldState;
2919  }
2920  }
2921 
2922  bool everythingRead = false;
2923 
2924  if (q->currentRequest().method() == QLatin1String("HEAD") ||
2925  response.statusCode() == 304 || response.statusCode() == 204 ||
2926  response.statusCode() == 205) {
2927  // HEAD requests have only headers as replies
2928  // These status codes never have a body:
2929  // 304 Not Modified
2930  // 204 No Content
2931  // 205 Reset Content
2932  everythingRead = true;
2933  } else {
2934  qint64 n = socket->bytesAvailable();
2935  QByteArray *arr = 0;
2936  if (chunkedSize != -1) {
2937  // transfer-encoding is chunked
2938  for (;;) {
2939  // get chunk size
2940  if (chunkedSize == 0) {
2941  if (!socket->canReadLine())
2942  break;
2943  QString sizeString = QString::fromAscii(socket->readLine());
2944  int tPos = sizeString.indexOf(QLatin1Char(';'));
2945  if (tPos != -1)
2946  sizeString.truncate(tPos);
2947  bool ok;
2948  chunkedSize = sizeString.toInt(&ok, 16);
2949  if (!ok) {
2950  finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Invalid HTTP chunked body")),
2952  closeConn();
2953  delete arr;
2954  return;
2955  }
2956  if (chunkedSize == 0) // last-chunk
2957  chunkedSize = -2;
2958  }
2959 
2960  // read trailer
2961  while (chunkedSize == -2 && socket->canReadLine()) {
2962  QString read = QString::fromAscii(socket->readLine());
2963  if (read == QLatin1String("\r\n") || read == QLatin1String("\n"))
2964  chunkedSize = -1;
2965  }
2966  if (chunkedSize == -1) {
2967  everythingRead = true;
2968  break;
2969  }
2970 
2971  // make sure that you can read the terminating CRLF,
2972  // otherwise wait until next time...
2973  n = socket->bytesAvailable();
2974  if (n == 0)
2975  break;
2976  if (n == chunkedSize || n == chunkedSize+1) {
2977  n = chunkedSize - 1;
2978  if (n == 0)
2979  break;
2980  }
2981 
2982  // read data
2983  qint64 toRead = chunkedSize < 0 ? n : qMin(n, chunkedSize);
2984  if (!arr)
2985  arr = new QByteArray;
2986  uint oldArrSize = arr->size();
2987  arr->resize(oldArrSize + toRead);
2988  qint64 read = socket->read(arr->data()+oldArrSize, toRead);
2989  arr->resize(oldArrSize + read);
2990 
2991  chunkedSize -= read;
2992 
2993  if (chunkedSize == 0 && n - read >= 2) {
2994  // read terminating CRLF
2995  char tmp[2];
2996  socket->read(tmp, 2);
2997  if (tmp[0] != '\r' || tmp[1] != '\n') {
2998  finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Invalid HTTP chunked body")),
3000  closeConn();
3001  delete arr;
3002  return;
3003  }
3004  }
3005  }
3006  } else if (response.hasContentLength()) {
3007  if (repost && (n < response.contentLength())) {
3008  // wait for the content to be available fully
3009  // if repost is required, the content is ignored
3010  return;
3011  }
3012  n = qMin(qint64(response.contentLength() - bytesDone), n);
3013  if (n > 0) {
3014  arr = new QByteArray;
3015  arr->resize(n);
3016  qint64 read = socket->read(arr->data(), n);
3017  arr->resize(read);
3018  }
3019  if (bytesDone + q->bytesAvailable() + n == response.contentLength())
3020  everythingRead = true;
3021  } else if (n > 0) {
3022  // workaround for VC++ bug
3023  QByteArray temp = socket->readAll();
3024  arr = new QByteArray(temp);
3025  }
3026 
3027  if (arr && !repost) {
3028  n = arr->size();
3029  if (toDevice) {
3030  qint64 bytesWritten;
3031  bytesWritten = toDevice->write(*arr, n);
3032  delete arr;
3033  arr = 0;
3034  // if writing to the device does not succeed, quit with error
3035  if (bytesWritten == -1 || bytesWritten < n) {
3036  finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Error writing response to device")), QHttp::UnknownError);
3037  } else {
3038  bytesDone += bytesWritten;
3039 #if defined(QHTTP_DEBUG)
3040  qDebug("QHttp::_q_slotReadyRead(): read %lld bytes (%lld bytes done)", n, bytesDone);
3041 #endif
3042  }
3043  if (response.hasContentLength())
3044  emit q->dataReadProgress(bytesDone, response.contentLength());
3045  else
3046  emit q->dataReadProgress(bytesDone, 0);
3047  } else {
3048  char *ptr = rba.reserve(arr->size());
3049  memcpy(ptr, arr->data(), arr->size());
3050  delete arr;
3051  arr = 0;
3052 #if defined(QHTTP_DEBUG)
3053  qDebug("QHttp::_q_slotReadyRead(): read %lld bytes (%lld bytes done)", n, bytesDone + q->bytesAvailable());
3054 #endif
3055  if (response.hasContentLength())
3056  emit q->dataReadProgress(bytesDone + q->bytesAvailable(), response.contentLength());
3057  else
3058  emit q->dataReadProgress(bytesDone + q->bytesAvailable(), 0);
3059  emit q->readyRead(response);
3060  }
3061  }
3062 
3063  delete arr;
3064  }
3065 
3066  if (everythingRead) {
3067  if (repost) {
3068  _q_slotSendRequest();
3069  return;
3070  }
3071  // Handle "Connection: close"
3072  if (response.value(QLatin1String("connection")).toLower() == QLatin1String("close")) {
3073  closeConn();
3074  } else {
3075  setState(QHttp::Connected);
3076  // Start a timer, so that we emit the keep alive signal
3077  // "after" this method returned.
3078  QMetaObject::invokeMethod(q, "_q_slotDoFinished", Qt::QueuedConnection);
3079  }
3080  }
3081 }
3082 
3084 {
3085  if (state == QHttp::Connected) {
3086  finishedWithSuccess();
3087  } else if (state != QHttp::Unconnected) {
3088  setState(QHttp::Unconnected);
3089  finishedWithSuccess();
3090  }
3091 }
3092 
3093 
3101 {
3102  Q_D(const QHttp);
3103  return d->state;
3104 }
3105 
3114 {
3115  Q_D(const QHttp);
3116  return d->error;
3117 }
3118 
3126 {
3127  Q_D(const QHttp);
3128  return d->errorString;
3129 }
3130 
3132 {
3133  Q_Q(QHttp);
3134 #if defined(QHTTP_DEBUG)
3135  qDebug("QHttp state changed %d -> %d", state, s);
3136 #endif
3137  state = QHttp::State(s);
3138  emit q->stateChanged(s);
3139 }
3140 
3142 {
3143  Q_Q(QHttp);
3144  // If no connection is open -> ignore
3146  return;
3147 
3148  postDevice = 0;
3149  setState(QHttp::Closing);
3150 
3151  // Already closed ?
3152  if (!socket || !socket->isOpen()) {
3153  QMetaObject::invokeMethod(q, "_q_slotDoFinished", Qt::QueuedConnection);
3154  } else {
3155  // Close now.
3156  socket->close();
3157  }
3158 }
3159 
3161 {
3162  Q_Q(const QHttp);
3163 
3164  // disconnect all existing signals
3165  if (socket)
3166  socket->disconnect();
3167  if (deleteSocket)
3168  delete socket;
3169 
3170  // use the new QTcpSocket socket, or create one if socket is 0.
3171  deleteSocket = (sock == 0);
3172  socket = sock;
3173  if (!socket) {
3174 #ifndef QT_NO_OPENSSL
3176  socket = new QSslSocket();
3177  else
3178 #endif
3179  socket = new QTcpSocket();
3180  }
3181 
3182  // connect all signals
3183  QObject::connect(socket, SIGNAL(connected()), q, SLOT(_q_slotConnected()));
3184  QObject::connect(socket, SIGNAL(disconnected()), q, SLOT(_q_slotClosed()));
3185  QObject::connect(socket, SIGNAL(readyRead()), q, SLOT(_q_slotReadyRead()));
3187  QObject::connect(socket, SIGNAL(bytesWritten(qint64)),
3188  q, SLOT(_q_slotBytesWritten(qint64)));
3189 #ifndef QT_NO_NETWORKPROXY
3192 #endif
3193 
3194 #ifndef QT_NO_OPENSSL
3195  if (qobject_cast<QSslSocket *>(socket)) {
3198  QObject::connect(socket, SIGNAL(encryptedBytesWritten(qint64)),
3199  q, SLOT(_q_slotEncryptedBytesWritten(qint64)));
3200  }
3201 #endif
3202 }
3203 
3213 #ifndef QT_NO_OPENSSL
3215 {
3216  Q_D(QHttp);
3217  QSslSocket *sslSocket = qobject_cast<QSslSocket *>(d->socket);
3218  if (sslSocket)
3219  sslSocket->ignoreSslErrors();
3220 }
3221 #endif
3222 
3224 
3225 #include "moc_qhttp.cpp"
3226 
3227 #endif
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: qstring.cpp:6448
QNetworkProxy::ProxyType type() const
Returns the proxy type for this instance.
QBool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.h:904
QString toString() const
Reimplemented Function
Definition: qhttp.cpp:1433
double d
Definition: qnumeric_p.h:62
QAuthenticator authenticator
Definition: qhttp.cpp:176
QHttpPGHRequest(const QHttpRequestHeader &h, QByteArray *d, QIODevice *t)
Definition: qhttp.cpp:316
void setSingleShot(bool singleShot)
Definition: qtimer.h:108
int currentId() const
Returns the identifier of the HTTP request being executed or 0 if there is no request being executed ...
Definition: qhttp.cpp:1979
void _q_slotError(QAbstractSocket::SocketError)
Definition: qhttp.cpp:2700
QString value(const QString &key) const
Returns the first value for the entry with the given key.
Definition: qhttp.cpp:732
QHttpSetSocketRequest(QTcpSocket *s)
Definition: qhttp.cpp:458
void sslErrors(const QList< QSslError > &errors)
Forwards the sslErrors signal from the QSslSocket used in QHttp.
bool hasContentLength() const
Returns true if the header has an entry for the special HTTP header field content-length; otherwise r...
Definition: qhttp.cpp:945
bool repost
Definition: qhttp.cpp:177
bool blockSignals(bool b)
If block is true, signals emitted by this object are blocked (i.e., emitting a signal will not invoke...
Definition: qobject.cpp:1406
virtual qint64 size() const
For open random-access devices, this function returns the size of the device.
Definition: qiodevice.cpp:642
QString peerName() const
Returns the name of the peer as specified by connectToHost(), or an empty QString if connectToHost() ...
State
This enum is used to specify the state the client is in:
Definition: qhttp.h:188
QHttpNormalRequest(const QHttpRequestHeader &h, QByteArray *d, QIODevice *t)
Definition: qhttp.cpp:211
int type
Definition: qmetatype.cpp:239
QIODevice * sourceDevice()
Definition: qhttp.cpp:463
friend class QHttpSetUserRequest
Definition: qhttp.h:303
QHttpResponseHeader response
Definition: qhttp.cpp:168
virtual bool parseLine(const QString &line, int number)
Parses the single HTTP header line line which has the format key, colon, space, value, and adds key/value to the headers.
Definition: qhttp.cpp:905
ConnectionMode
This enum is used to specify the mode of connection to use:
Definition: qhttp.h:178
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
static QString fromAscii(const char *, int size=-1)
Returns a QString initialized with the first size characters from the string str. ...
Definition: qstring.cpp:4276
QHttpRequestHeader requestHeader()
Definition: qhttp.cpp:282
void start(QHttp *)
Definition: qhttp.cpp:244
char * data()
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:429
bool parseLine(const QString &line, int number)
Definition: qhttp.cpp:1187
const QChar at(int i) const
Returns the character at the given index position in the string.
Definition: qstring.h:698
QHttpSetUserRequest(const QString &userName, const QString &password)
Definition: qhttp.cpp:388
qint64 bytesAvailable() const
Returns the number of incoming bytes that are waiting to be read.
qint64 bytesAvailable() const
Returns the number of bytes that can be read from the response content at the moment.
Definition: qhttp.cpp:1913
int toInt(bool *ok=0, int base=10) const
Returns the string converted to an int using base base, which is 10 by default and must be between 2 ...
Definition: qstring.cpp:6090
void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *)
#define it(className, varName)
QIODevice * destinationDevice()
Definition: qhttp.cpp:294
void start(QHttp *)
Definition: qhttp.cpp:472
virtual QHttpRequestHeader requestHeader()
Definition: qhttp.cpp:190
qint64 encryptedBytesToWrite() const
Returns the number of encrypted bytes that are waiting to be written to the network.
Definition: qsslsocket.cpp:783
~QHttpPrivate()
Definition: qhttp.cpp:108
#define error(msg)
void connectToHost(const QString &hostName, quint16 port, OpenMode mode=ReadWrite)
Attempts to make a connection to hostName on the given port.
void parseHttpResponse(const QHttpResponseHeader &, bool isProxy)
bool parseLine(const QString &line, int number)
Definition: qhttp.cpp:1405
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
bool hasFinishedWithError
Definition: qhttp.cpp:178
QHttpSetHostRequest(const QString &h, quint16 p, QHttp::ConnectionMode m)
Definition: qhttp.cpp:344
QHttpRequestHeader()
Constructs an empty HTTP request header.
Definition: qhttp.cpp:1279
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
virtual QIODevice * destinationDevice()=0
void start(QHttp *http)
Definition: qhttp.cpp:427
void readyRead(const QHttpResponseHeader &resp)
This signal is emitted when there is new response data to read.
#define SLOT(a)
Definition: qobjectdefs.h:226
bool finished
Definition: qhttp.cpp:88
QString errorString() const
Returns a human-readable description of the last device error that occurred.
Definition: qiodevice.cpp:1671
virtual qint64 pos() const
For random-access devices, this function returns the position that data is written to or read from...
Definition: qiodevice.cpp:624
QHttpRequest()
Definition: qhttp.cpp:75
The QSslSocket class provides an SSL encrypted socket for both clients and servers.
Definition: qsslsocket.h:67
QIODevice * sourceDevice()
Definition: qhttp.cpp:394
QHttpHeader * q_ptr
Definition: qhttp.cpp:510
iterator begin()
Returns an STL-style iterator pointing to the first item in the list.
Definition: qlist.h:267
void _q_slotBytesWritten(qint64 numBytes)
Definition: qhttp.cpp:2747
quint16 peerPort() const
Returns the port of the connected peer if the socket is in ConnectedState; otherwise returns 0...
QHttp::ConnectionMode mode
Definition: qhttp.cpp:358
QHttp::State state
Definition: qhttp.cpp:148
void init()
Definition: qhttp.cpp:1609
QString toString() const
Reimplemented Function
Definition: qhttp.cpp:1219
QStringList allValues(const QString &key) const
Returns all the entries with the given key.
Definition: qhttp.cpp:749
#define QT_TRANSLATE_NOOP(scope, x)
Marks the string literal sourceText for dynamic translation in the given context; i...
Definition: qglobal.h:2487
static QString tr(const char *sourceText, const char *comment=0, int n=-1)
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
virtual ~QHttpHeader()
Destructor.
Definition: qhttp.cpp:640
QScopedPointer< QHttpHeaderPrivate > d_ptr
Definition: qhttp.h:112
friend class QHttpSetSocketRequest
Definition: qhttp.h:302
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
QList< QHttpRequest * > pending
Definition: qhttp.cpp:146
virtual QIODevice * sourceDevice()=0
void setValid(bool)
Definition: qhttp.cpp:720
void ignoreSslErrors(const QList< QSslError > &errors)
This method tells QSslSocket to ignore only the errors given in errors.
The QUrl class provides a convenient interface for working with URLs.
Definition: qurl.h:61
void abort()
Aborts the current connection and resets the socket.
The QString class provides a Unicode character string.
Definition: qstring.h:83
T * qobject_cast(QObject *object)
Definition: qobject.h:375
friend class QHttpNormalRequest
Definition: qhttp.h:300
virtual ~QHttpRequest()
Definition: qhttp.cpp:77
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
#define Q_BASIC_ATOMIC_INITIALIZER(a)
Definition: qbasicatomic.h:218
void setContentLength(int len)
Sets the value of the special HTTP header field content-length to len.
Definition: qhttp.cpp:967
void setHost(const QString &host)
Sets the host of the URL to host.
Definition: qurl.cpp:4821
QHttp::Error error
Definition: qhttp.cpp:149
#define Q_D(Class)
Definition: qglobal.h:2482
QIODevice * destinationDevice()
Definition: qhttp.cpp:441
QString headerStr
Definition: qhttp.cpp:167
virtual bool atEnd() const
Returns true if the current read and write position is at the end of the device (i.e.
Definition: qiodevice.cpp:711
QNetworkProxy proxy
Definition: qhttp.cpp:173
void setState(int)
Definition: qhttp.cpp:3131
int reconnectAttempts
Definition: qhttp.cpp:144
static bool supportsSsl()
Returns true if this platform supports SSL; otherwise, returns false.
iterator Iterator
Qt-style synonym for QList::iterator.
Definition: qlist.h:278
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
QTcpSocket * socket
Definition: qhttp.cpp:469
void _q_slotClosed()
Definition: qhttp.cpp:2641
static QAuthenticatorPrivate * getPrivate(QAuthenticator &auth)
#define Q_Q(Class)
Definition: qglobal.h:2483
QIODevice * currentSourceDevice() const
Returns the QIODevice pointer that is used as the data source of the HTTP request being executed...
Definition: qhttp.cpp:2029
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read...
Definition: qiodevice.cpp:791
QTcpSocket * socket
Definition: qhttp.cpp:143
Q_CORE_EXPORT void qDebug(const char *,...)
QIODevice * currentDestinationDevice() const
Returns the QIODevice pointer that is used as to store the data of the HTTP request being executed...
Definition: qhttp.cpp:2047
#define SIGNAL(a)
Definition: qobjectdefs.h:227
bool parse(const QString &str)
Parses the HTTP header string str for header fields and adds the keys/values it finds.
Definition: qhttp.cpp:678
static QNetworkProxy applicationProxy()
Returns the application level network proxying.
void _q_slotSendRequest()
Definition: qhttp.cpp:2482
int setProxy(const QString &host, int port, const QString &username=QString(), const QString &password=QString())
Enables HTTP proxy support, using the proxy server host on port port.
Definition: qhttp.cpp:2203
void _q_slotConnected()
Definition: qhttp.cpp:2671
The QNetworkProxy class provides a network layer proxy.
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
QRingBuffer rba
Definition: qhttp.cpp:170
char * reserve(int bytes)
void start(QHttp *)
Definition: qhttp.cpp:361
QList< QPair< QString, QString > > values() const
Returns all the entries in the header.
Definition: qhttp.cpp:852
QHttp(QObject *parent=0)
Constructs a QHttp object.
Definition: qhttp.cpp:1559
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
static QIntfbScreen * connected
void setStatusLine(int code, const QString &text=QString(), int majorVer=1, int minorVer=1)
Sets the status code to code, the reason phrase to text and the protocol-version to majorVer and mino...
Definition: qhttp.cpp:1131
bool isOpen() const
Returns true if the device is open; otherwise returns false.
Definition: qiodevice.cpp:530
quint16 port
Definition: qhttp.cpp:153
void truncate(int pos)
Truncates the string at the given position index.
Definition: qstring.cpp:4603
QIODevice * to
Definition: qhttp.cpp:241
friend class QHttpCloseRequest
Definition: qhttp.h:305
QString left(int n) const Q_REQUIRED_RESULT
Returns a substring that contains the n leftmost characters of the string.
Definition: qstring.cpp:3664
void setValue(const QString &key, const QString &value)
Sets the value of the entry with the key to value.
Definition: qhttp.cpp:815
bool contains(const T &value) const
Definition: qset.h:91
QString trimmed() const Q_REQUIRED_RESULT
Returns a string that has whitespace removed from the start and the end.
Definition: qstring.cpp:4506
T takeFirst()
Removes the first item in the list and returns it.
Definition: qlist.h:489
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
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
QHttp::ConnectionMode mode
Definition: qhttp.cpp:154
QIODevice * destinationDevice()
Definition: qhttp.cpp:352
static bool init
virtual QString toString() const
Returns a string representation of the HTTP header.
Definition: qhttp.cpp:923
iterator end()
Returns an STL-style iterator pointing to the imaginary item after the last item in the list...
Definition: qlist.h:270
QHttpSetProxyRequest(const QNetworkProxy &proxy)
Definition: qhttp.cpp:422
QByteArray buffer
Definition: qhttp.cpp:156
QHttpRequestHeader currentRequest() const
Returns the request header of the HTTP request being executed.
Definition: qhttp.cpp:1995
QString path() const
Returns the request-URI of the HTTP request header.
Definition: qhttp.cpp:1375
#define emit
Definition: qobjectdefs.h:76
QHttpResponseHeader lastResponse() const
Returns the received response header of the most recently finished HTTP request.
Definition: qhttp.cpp:2013
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
SocketError
This enum describes the socket errors that can occur.
void connectToHostEncrypted(const QString &hostName, quint16 port, OpenMode mode=ReadWrite)
Starts an encrypted connection to the device hostName on port, using mode as the OpenMode ...
Definition: qsslsocket.cpp:414
void setContentType(const QString &type)
Sets the value of the special HTTP header field content-type to type.
Definition: qhttp.cpp:1007
void closeConn()
Definition: qhttp.cpp:3141
QHttpRequestHeader header
Definition: qhttp.cpp:233
void setSock(QTcpSocket *sock)
Definition: qhttp.cpp:3160
void setRequestHeader(const QHttpRequestHeader &h)
Definition: qhttp.cpp:227
unsigned short quint16
Definition: qglobal.h:936
Q_CORE_EXPORT void qWarning(const char *,...)
void finishedWithSuccess()
Definition: qhttp.cpp:2589
const_iterator insert(const T &value)
Definition: qset.h:179
int minorVersion() const
Returns the minor protocol-version of the HTTP response header.
Definition: qhttp.cpp:1179
static const char * data(const QByteArray &arr)
unsigned int uint
Definition: qglobal.h:996
int setSocket(QTcpSocket *socket)
Replaces the internal QTcpSocket that QHttp uses with socket.
Definition: qhttp.cpp:2157
int indexOf(QChar c, int from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:2838
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
void removeFirst()
Removes the first item in the list.
Definition: qlist.h:286
int get(const QString &path, QIODevice *to=0)
Sends a get request for path to the server set by setHost() or as specified in the constructor...
Definition: qhttp.cpp:2267
static QBasicAtomicInt idCounter
Definition: qhttp.cpp:91
The QTcpSocket class provides a TCP socket.
Definition: qtcpsocket.h:56
void _q_slotReadyRead()
Definition: qhttp.cpp:2791
qint64 bytesDone
Definition: qhttp.cpp:160
QString errorString
Definition: qhttp.cpp:150
void start(QHttp *)
Definition: qhttp.cpp:404
const T * ptr(const T &t)
void setValues(const QList< QPair< QString, QString > > &values)
Sets the header entries to be the list of key value pairs in values.
Definition: qhttp.cpp:834
bool hasKey(const QString &key) const
Returns true if the HTTP header has an entry with the given key; otherwise returns false...
Definition: qhttp.cpp:792
virtual ~QHttp()
Destroys the QHttp object.
Definition: qhttp.cpp:1622
QByteArray toLatin1() const Q_REQUIRED_RESULT
Returns a Latin-1 representation of the string as a QByteArray.
Definition: qstring.cpp:3993
__int64 qint64
Definition: qglobal.h:942
Error error() const
Returns the last error that occurred.
Definition: qhttp.cpp:3113
friend class QHttpSetHostRequest
Definition: qhttp.h:301
QString contentType() const
Returns the value of the special HTTP header field content-type.
Definition: qhttp.cpp:988
bool isEncrypted() const
Returns true if the socket is encrypted; otherwise, false is returned.
Definition: qsslsocket.cpp:563
void close()
Closes the I/O device for the socket, disconnects the socket&#39;s connection with the host...
QIODevice * sourceDevice()
Definition: qhttp.cpp:491
bool deleteSocket
Definition: qhttp.cpp:145
void addValue(const QString &key, const QString &value)
Adds a new entry with the key and value.
Definition: qhttp.cpp:843
int setHost(const QString &hostname, quint16 port=80)
Sets the HTTP server that is used for requests to hostName on port port.
Definition: qhttp.cpp:2100
virtual ~QHttpHeaderPrivate()
Definition: qhttp.cpp:506
The QAuthenticator class provides an authentication object.
bool isValid() const
Returns true if the HTTP header is valid; otherwise returns false.
Definition: qhttp.cpp:660
QIODevice * destinationDevice()
Definition: qhttp.cpp:396
QIODevice * destinationDevice()
Definition: qhttp.cpp:493
int setUser(const QString &username, const QString &password=QString())
This function sets the user name userName and password password for web pages that require authentica...
Definition: qhttp.cpp:2176
bool hasContentType() const
Returns true if the header has an entry for the special HTTP header field content-type; otherwise ret...
Definition: qhttp.cpp:978
QByteArray toEncoded(FormattingOptions options=None) const
Returns the encoded representation of the URL if it&#39;s valid; otherwise an empty QByteArray is returne...
Definition: qurl.cpp:5949
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
bool isNull() const
Returns true if this string is null; otherwise returns false.
Definition: qstring.h:505
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
Disconnects signal in object sender from method in object receiver.
Definition: qobject.cpp:2895
virtual void start(QHttp *)=0
QString mid(int position, int n=-1) const Q_REQUIRED_RESULT
Returns a string that contains n characters of this string, starting at the specified position index...
Definition: qstring.cpp:3706
QHttpResponseHeader & operator=(const QHttpResponseHeader &header)
Copies the contents of header into this QHttpResponseHeader.
Definition: qhttp.cpp:1077
void setProxy(const QNetworkProxy &networkProxy)
Sets the explicit network proxy for this socket to networkProxy.
QString arg(qlonglong a, int fieldwidth=0, int base=10, const QChar &fillChar=QLatin1Char(' ')) const Q_REQUIRED_RESULT
Definition: qstring.cpp:7186
uint contentLength() const
Returns the value of the special HTTP header field content-length.
Definition: qhttp.cpp:956
QHttpRequestHeader & operator=(const QHttpRequestHeader &header)
Copies the content of header into this QHttpRequestHeader.
Definition: qhttp.cpp:1317
QHttpHeader & operator=(const QHttpHeader &h)
Assigns h and returns a reference to this http header.
Definition: qhttp.cpp:647
int head(const QString &path)
Sends a header request for path to the server set by setHost() or as specified in the constructor...
Definition: qhttp.cpp:2344
void finishedWithError(const QString &detail, int errorCode)
Definition: qhttp.cpp:2619
#define Q_DECLARE_PUBLIC(Class)
Definition: qglobal.h:2477
void start(QHttp *)
Definition: qhttp.cpp:497
bool pendingPost
Definition: qhttp.cpp:179
bool readHeader
Definition: qhttp.cpp:166
void setPort(int port)
Sets the port of the URL to port.
Definition: qurl.cpp:4897
The QHttp class provides an implementation of the HTTP protocol.
Definition: qhttp.h:173
QString method() const
Returns the method of the HTTP request header.
Definition: qhttp.cpp:1364
QString hostName
Definition: qhttp.cpp:356
qint64 readLine(char *data, qint64 maxlen)
This function reads a line of ASCII characters from the device, up to a maximum of maxSize - 1 bytes...
Definition: qiodevice.cpp:1110
QString simplified() const Q_REQUIRED_RESULT
Returns a string that has whitespace removed from the start and the end, and that has each sequence o...
Definition: qstring.cpp:4415
QIODevice * postDevice
Definition: qhttp.cpp:158
qint64 bytesTotal
Definition: qhttp.cpp:161
Error
This enum identifies the error that occurred.
Definition: qhttp.h:197
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
Definition: qstring.cpp:4188
bool isNull() const
Returns true if the authenticator is null.
int addRequest(QHttpNormalRequest *)
Definition: qhttp.cpp:2440
QObject * parent() const
Returns a pointer to the parent object.
Definition: qobject.h:273
QIODevice * sourceDevice()
Definition: qhttp.cpp:287
friend class QHttpSetProxyRequest
Definition: qhttp.h:304
QIODevice * sourceDevice()
Definition: qhttp.cpp:439
friend class QHttpPGHRequest
Definition: qhttp.h:306
Q_OUTOFLINE_TEMPLATE QPair< T1, T2 > qMakePair(const T1 &x, const T2 &y)
Definition: qpair.h:102
int key
QString toLower() const Q_REQUIRED_RESULT
Returns a lowercase copy of the string.
Definition: qstring.cpp:5389
T & last()
Returns a reference to the last item in the list.
Definition: qlist.h:284
void resize(int size)
Sets the size of the byte array to size bytes.
quint16 port() const
Returns the port of the proxy host.
QIODevice * toDevice
Definition: qhttp.cpp:157
static const QMetaObjectPrivate * priv(const uint *data)
void setRequest(const QString &method, const QString &path, int majorVer=1, int minorVer=1)
This function sets the request method to method, the request-URI to path and the protocol-version to ...
Definition: qhttp.cpp:1349
void ignoreSslErrors()
Tells the QSslSocket used for the Http connection to ignore the errors reported in the sslErrors() si...
Definition: qhttp.cpp:3214
QByteArray * ba
Definition: qhttp.cpp:237
uint toUInt(bool *ok=0, int base=10) const
Returns the string converted to an unsigned int using base base, which is 10 by default and must be b...
Definition: qstring.cpp:6120
int fetchAndAddRelaxed(int valueToAdd)
QString hostName
Definition: qhttp.cpp:152
QFactoryLoader * l
bool hasRequestHeader()
Definition: qhttp.cpp:277
void setType(QNetworkProxy::ProxyType type)
Sets the proxy type for this instance to be type.
qint64 bytesToWrite() const
Returns the number of bytes that are waiting to be written.
QByteArray readAll()
Reads all available data from the device, and returns it as a QByteArray.
Definition: qiodevice.cpp:1025
QByteArray calculateResponse(const QByteArray &method, const QByteArray &path)
void _q_slotEncryptedBytesWritten(qint64 numBytes)
Definition: qhttp.cpp:2740
int post(const QString &path, QIODevice *data, QIODevice *to=0)
Sends a post request for path to the server set by setHost() or as specified in the constructor...
Definition: qhttp.cpp:2305
int size() const
Returns the number of bytes in this byte array.
Definition: qbytearray.h:402
The QHttpRequestHeader class contains request header information for HTTP.
Definition: qhttp.h:147
QHttpPGHRequest(const QHttpRequestHeader &h, QIODevice *d, QIODevice *t)
Definition: qhttp.cpp:312
QTimer post100ContinueTimer
Definition: qhttp.cpp:180
QString reasonPhrase() const
Returns the reason phrase of the HTTP response header.
Definition: qhttp.cpp:1157
void setScheme(const QString &scheme)
Sets the scheme of the URL to scheme.
Definition: qurl.cpp:4533
int request(const QHttpRequestHeader &header, QIODevice *device=0, QIODevice *to=0)
Sends a request to the server set by setHost() or as specified in the constructor.
Definition: qhttp.cpp:2379
QIODevice * sourceDevice()
Definition: qhttp.cpp:350
QStringList keys() const
Returns a list of the keys in the HTTP header.
Definition: qhttp.cpp:768
QHttpHeader()
Constructs an empty HTTP header.
Definition: qhttp.cpp:578
void removeAllValues(const QString &key)
Removes all the entries with the key key from the HTTP header.
Definition: qhttp.cpp:880
QList< QPair< QString, QString > > values
Definition: qhttp.cpp:508
QString password() const
Returns the password used for authentication.
The QHttpHeader class contains header information for HTTP.
Definition: qhttp.h:69
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.
int close()
Closes the connection; this is useful if you have a keep-alive connection and want to close it...
Definition: qhttp.cpp:2420
State state() const
Returns the current state of the object.
Definition: qhttp.cpp:3100
void _q_slotDoFinished()
Definition: qhttp.cpp:3083
void postMoreData()
Definition: qhttp.cpp:2756
QStringList split(const QString &sep, SplitBehavior behavior=KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const Q_REQUIRED_RESULT
Splits the string into substrings wherever sep occurs, and returns the list of those strings...
Definition: qstring.cpp:6526
QHttpRequestHeader header
Definition: qhttp.cpp:164
int minorVersion() const
Returns the minor protocol-version of the HTTP request header.
Definition: qhttp.cpp:1397
void start(QHttp *)
Definition: qhttp.cpp:326
int statusCode() const
Returns the status code of the HTTP response header.
Definition: qhttp.cpp:1146
The QTimer class provides repetitive and single-shot timers.
Definition: qtimer.h:56
virtual bool hasRequestHeader()
Definition: qhttp.cpp:185
int majorVersion() const
Returns the major protocol-version of the HTTP request header.
Definition: qhttp.cpp:1386
static QUrl fromEncoded(const QByteArray &url)
Parses input and returns the corresponding QUrl.
Definition: qurl.cpp:5964
bool hasPendingRequests() const
Returns true if there are any requests scheduled that have not yet been executed; otherwise returns f...
Definition: qhttp.cpp:2064
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
Definition: qiodevice.cpp:1342
void _q_continuePost()
Definition: qhttp.cpp:2662
QString user() const
Returns the user name used for authentication.
QAuthenticator proxyAuthenticator
Definition: qhttp.cpp:174
QString errorString() const
Returns a human-readable description of the last error that occurred.
Definition: qhttp.cpp:3125
QUrl resolved(const QUrl &relative) const
Returns the result of the merge of this URL with relative.
Definition: qurl.cpp:5819
QIODevice * destinationDevice()
Definition: qhttp.cpp:465
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 stop()
Stops the timer.
Definition: qtimer.cpp:284
void start(int msec)
Starts or restarts the timer with a timeout interval of msec milliseconds.
Definition: qtimer.cpp:249
bool canReadLine() const
Returns true if a line of data can be read from the socket; otherwise returns false.
The QHttpResponseHeader class contains response header information for HTTP.
Definition: qhttp.h:119
#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
virtual bool seek(qint64 pos)
For random-access devices, this function sets the current position to pos, returning true on success...
Definition: qiodevice.cpp:659
int majorVersion() const
Returns the major protocol-version of the HTTP response header.
Definition: qhttp.cpp:1168
int closeConnection()
Behaves the same as close().
Definition: qhttp.cpp:2434
void clearPendingRequests()
Deletes all pending requests from the list of scheduled requests.
Definition: qhttp.cpp:2077
void abort()
Aborts the current request and deletes all scheduled requests.
Definition: qhttp.cpp:1894
void _q_startNextRequest()
Definition: qhttp.cpp:2466
QIODevice * dev
Definition: qhttp.cpp:238
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
QHttpResponseHeader()
Constructs an empty HTTP response header.
Definition: qhttp.cpp:1055
QByteArray readAll()
Reads all the bytes from the response content and returns them.
Definition: qhttp.cpp:1963
void clear()
Clears the contents of the byte array and makes it empty.
SocketState state() const
Returns the state of the socket.
#define text
Definition: qobjectdefs.h:80
QNetworkProxy proxy
Definition: qhttp.cpp:444
qint64 chunkedSize
Definition: qhttp.cpp:162
QHttpNormalRequest(const QHttpRequestHeader &h, QIODevice *d, QIODevice *t)
Definition: qhttp.cpp:204
void removeValue(const QString &key)
Removes the entry with the key key from the HTTP header.
Definition: qhttp.cpp:863
The QList class is a template class that provides lists.
Definition: qdatastream.h:62
qint64 read(char *data, qint64 maxlen)
Reads maxlen bytes from the response content into data and returns the number of bytes read...
Definition: qhttp.cpp:1933
int removeAll(const T &t)
Removes all occurrences of value in the list and returns the number of entries removed.
Definition: qlist.h:770
QString hostName() const
Returns the host name of the proxy host.