217 |
217 |
218 QHttpNetworkReplyPrivate::~QHttpNetworkReplyPrivate() |
218 QHttpNetworkReplyPrivate::~QHttpNetworkReplyPrivate() |
219 { |
219 { |
220 } |
220 } |
221 |
221 |
222 void QHttpNetworkReplyPrivate::clear() |
222 void QHttpNetworkReplyPrivate::clearHttpLayerInformation() |
223 { |
223 { |
224 state = NothingDoneState; |
224 state = NothingDoneState; |
225 statusCode = 100; |
225 statusCode = 100; |
226 bodyLength = 0; |
226 bodyLength = 0; |
227 contentRead = 0; |
227 contentRead = 0; |
228 totalProgress = 0; |
228 totalProgress = 0; |
229 currentChunkSize = 0; |
229 currentChunkSize = 0; |
230 currentChunkRead = 0; |
230 currentChunkRead = 0; |
231 connectionCloseEnabled = true; |
231 connectionCloseEnabled = true; |
232 connection = 0; |
|
233 #ifndef QT_NO_COMPRESS |
232 #ifndef QT_NO_COMPRESS |
234 if (initInflate) |
233 if (initInflate) |
235 inflateEnd(&inflateStrm); |
234 inflateEnd(&inflateStrm); |
236 #endif |
235 #endif |
237 initInflate = false; |
236 initInflate = false; |
238 streamEnd = false; |
237 streamEnd = false; |
|
238 fields.clear(); |
|
239 } |
|
240 |
|
241 // TODO: Isn't everything HTTP layer related? We don't need to set connection and connectionChannel to 0 at all |
|
242 void QHttpNetworkReplyPrivate::clear() |
|
243 { |
|
244 connection = 0; |
|
245 connectionChannel = 0; |
239 autoDecompress = false; |
246 autoDecompress = false; |
240 fields.clear(); |
247 clearHttpLayerInformation(); |
241 } |
248 } |
242 |
249 |
243 // QHttpNetworkReplyPrivate |
250 // QHttpNetworkReplyPrivate |
244 qint64 QHttpNetworkReplyPrivate::bytesAvailable() const |
251 qint64 QHttpNetworkReplyPrivate::bytesAvailable() const |
245 { |
252 { |
421 } |
428 } |
422 #endif |
429 #endif |
423 |
430 |
424 qint64 QHttpNetworkReplyPrivate::readStatus(QAbstractSocket *socket) |
431 qint64 QHttpNetworkReplyPrivate::readStatus(QAbstractSocket *socket) |
425 { |
432 { |
|
433 if (fragment.isEmpty()) { |
|
434 // reserve bytes for the status line. This is better than always append() which reallocs the byte array |
|
435 fragment.reserve(32); |
|
436 } |
|
437 |
426 qint64 bytes = 0; |
438 qint64 bytes = 0; |
427 char c; |
439 char c; |
428 |
440 qint64 haveRead = 0; |
429 while (socket->bytesAvailable()) { |
441 |
|
442 do { |
|
443 haveRead = socket->read(&c, 1); |
|
444 if (haveRead == -1) |
|
445 return -1; // unexpected EOF |
|
446 else if (haveRead == 0) |
|
447 break; // read more later |
|
448 |
|
449 bytes++; |
|
450 |
430 // allow both CRLF & LF (only) line endings |
451 // allow both CRLF & LF (only) line endings |
431 if (socket->peek(&c, 1) == 1 && c == '\n') { |
452 if (c == '\n') { |
432 bytes += socket->read(&c, 1); // read the "n" |
|
433 // remove the CR at the end |
453 // remove the CR at the end |
434 if (fragment.endsWith('\r')) { |
454 if (fragment.endsWith('\r')) { |
435 fragment.truncate(fragment.length()-1); |
455 fragment.truncate(fragment.length()-1); |
436 } |
456 } |
437 bool ok = parseStatus(fragment); |
457 bool ok = parseStatus(fragment); |
498 return ok && uint(majorVersion) <= 9 && uint(minorVersion) <= 9; |
512 return ok && uint(majorVersion) <= 9 && uint(minorVersion) <= 9; |
499 } |
513 } |
500 |
514 |
501 qint64 QHttpNetworkReplyPrivate::readHeader(QAbstractSocket *socket) |
515 qint64 QHttpNetworkReplyPrivate::readHeader(QAbstractSocket *socket) |
502 { |
516 { |
|
517 if (fragment.isEmpty()) { |
|
518 // according to http://dev.opera.com/articles/view/mama-http-headers/ the average size of the header |
|
519 // block is 381 bytes. |
|
520 // reserve bytes. This is better than always append() which reallocs the byte array. |
|
521 fragment.reserve(512); |
|
522 } |
|
523 |
503 qint64 bytes = 0; |
524 qint64 bytes = 0; |
504 char c = 0; |
525 char c = 0; |
505 bool allHeaders = false; |
526 bool allHeaders = false; |
506 while (!allHeaders && socket->bytesAvailable()) { |
527 qint64 haveRead = 0; |
507 if (socket->peek(&c, 1) == 1 && c == '\n') { |
528 do { |
508 // check for possible header endings. As per HTTP rfc, |
529 haveRead = socket->read(&c, 1); |
509 // the header endings will be marked by CRLFCRLF. But |
530 if (haveRead == 0) { |
510 // we will allow CRLFLF, LFLF & CRLFCRLF |
531 // read more later |
511 if (fragment.endsWith("\n\r") || fragment.endsWith('\n')) |
532 break; |
512 allHeaders = true; |
533 } else if (haveRead == -1) { |
513 } |
534 // connection broke down |
514 bytes += socket->read(&c, 1); |
535 return -1; |
515 fragment.append(c); |
536 } else { |
516 } |
537 fragment.append(c); |
|
538 bytes++; |
|
539 |
|
540 if (c == '\n') { |
|
541 // check for possible header endings. As per HTTP rfc, |
|
542 // the header endings will be marked by CRLFCRLF. But |
|
543 // we will allow CRLFCRLF, CRLFLF, LFLF |
|
544 if (fragment.endsWith("\r\n\r\n") |
|
545 || fragment.endsWith("\r\n\n") |
|
546 || fragment.endsWith("\n\n")) |
|
547 allHeaders = true; |
|
548 |
|
549 // there is another case: We have no headers. Then the fragment equals just the line ending |
|
550 if ((fragment.length() == 2 && fragment.endsWith("\r\n")) |
|
551 || (fragment.length() == 1 && fragment.endsWith("\n"))) |
|
552 allHeaders = true; |
|
553 } |
|
554 } |
|
555 } while (!allHeaders && haveRead > 0); |
|
556 |
517 // we received all headers now parse them |
557 // we received all headers now parse them |
518 if (allHeaders) { |
558 if (allHeaders) { |
519 parseHeader(fragment); |
559 parseHeader(fragment); |
520 state = ReadingDataState; |
560 state = ReadingDataState; |
521 fragment.clear(); // next fragment |
561 fragment.clear(); // next fragment |
773 #ifndef QT_NO_OPENSSL |
813 #ifndef QT_NO_OPENSSL |
774 |
814 |
775 QSslConfiguration QHttpNetworkReply::sslConfiguration() const |
815 QSslConfiguration QHttpNetworkReply::sslConfiguration() const |
776 { |
816 { |
777 Q_D(const QHttpNetworkReply); |
817 Q_D(const QHttpNetworkReply); |
778 if (d->connection) |
818 |
779 return d->connection->d_func()->sslConfiguration(*this); |
819 if (!d->connectionChannel) |
780 return QSslConfiguration(); |
820 return QSslConfiguration(); |
|
821 |
|
822 QSslSocket *sslSocket = qobject_cast<QSslSocket*>(d->connectionChannel->socket); |
|
823 if (!sslSocket) |
|
824 return QSslConfiguration(); |
|
825 |
|
826 return sslSocket->sslConfiguration(); |
781 } |
827 } |
782 |
828 |
783 void QHttpNetworkReply::setSslConfiguration(const QSslConfiguration &config) |
829 void QHttpNetworkReply::setSslConfiguration(const QSslConfiguration &config) |
784 { |
830 { |
785 Q_D(QHttpNetworkReply); |
831 Q_D(QHttpNetworkReply); |