bool QNetworkAccessFileBackend::readMoreFromFile() { qint64 wantToRead; while ((wantToRead = nextDownstreamBlockSize()) > 0) { // ### FIXME!! // Obtain a pointer from the ringbuffer! // Avoid extra copy QByteArray data; data.reserve(wantToRead); qint64 actuallyRead = file.read(data.data(), wantToRead); if (actuallyRead <= 0) { // EOF or error if (file.error() != QFile::NoError) { QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Read error reading from %1: %2") .arg(url().toString(), file.errorString()); error(QNetworkReply::ProtocolFailure, msg); finished(); return false; } finished(); return true; } data.resize(actuallyRead); totalBytes += actuallyRead; QByteDataBuffer list; list.append(data); data.clear(); // important because of implicit sharing! writeDownstreamData(list); } return true; }
void QNetworkAccessDebugPipeBackend::pushFromSocketToDownstream() { QByteArray buffer; if (socket.state() == QAbstractSocket::ConnectingState) { return; } forever { if (hasDownloadFinished) return; buffer.resize(ReadBufferSize); qint64 haveRead = socket.read(buffer.data(), ReadBufferSize); if (haveRead == -1) { hasDownloadFinished = true; // this ensures a good last downloadProgress is emitted setHeader(QNetworkRequest::ContentLengthHeader, QVariant()); possiblyFinish(); break; } else if (haveRead == 0) { break; } else { // have read something buffer.resize(haveRead); bytesDownloaded += haveRead; QByteDataBuffer list; list.append(buffer); buffer.clear(); // important because of implicit sharing! writeDownstreamData(list); } } }
void QNetworkAccessHttpBackend::readFromHttp() { // We implement the download rate control // Don't read from QHttpNetworkAccess more than QNetworkAccessBackend wants // One of the two functions above will be called when we can read again qint64 bytesToRead = qBound<qint64>(0, httpReply->bytesAvailable(), nextDownstreamBlockSize()); if (!bytesToRead) return; QByteArray data = httpReply->read(bytesToRead); writeDownstreamData(data); }
bool QNetworkAccessCacheBackend::sendCacheContents() { setCachingEnabled(false); QAbstractNetworkCache *nc = networkCache(); if (!nc) return false; QNetworkCacheMetaData item = nc->metaData(url()); if (!item.isValid()) return false; QNetworkCacheMetaData::AttributesMap attributes = item.attributes(); setAttribute(QNetworkRequest::HttpStatusCodeAttribute, attributes.value(QNetworkRequest::HttpStatusCodeAttribute)); setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, attributes.value(QNetworkRequest::HttpReasonPhraseAttribute)); // set the raw headers QNetworkCacheMetaData::RawHeaderList rawHeaders = item.rawHeaders(); QNetworkCacheMetaData::RawHeaderList::ConstIterator it = rawHeaders.constBegin(), end = rawHeaders.constEnd(); for ( ; it != end; ++it) { if (it->first.toLower() == "cache-control" && it->second.toLower().contains("must-revalidate")) { return false; } setRawHeader(it->first, it->second); } // handle a possible redirect QVariant redirectionTarget = attributes.value(QNetworkRequest::RedirectionTargetAttribute); if (redirectionTarget.isValid()) { setAttribute(QNetworkRequest::RedirectionTargetAttribute, redirectionTarget); redirectionRequested(redirectionTarget.toUrl()); } // signal we're open metaDataChanged(); if (operation() == QNetworkAccessManager::GetOperation) { QIODevice *contents = nc->data(url()); if (!contents) return false; contents->setParent(this); writeDownstreamData(contents); } #if defined(QNETWORKACCESSCACHEBACKEND_DEBUG) qDebug() << "Successfully sent cache:" << url(); #endif return true; }
void QNetworkAccessHttpBackend::readFromHttp() { if (!httpReply) return; // We read possibly more than nextDownstreamBlockSize(), but // this is not a critical thing since it is already in the // memory anyway QByteDataBuffer list; while (httpReply->bytesAvailable() != 0 && nextDownstreamBlockSize() != 0 && nextDownstreamBlockSize() > list.byteAmount()) { list.append(httpReply->readAny()); } if (!list.isEmpty()) writeDownstreamData(list); }
/* A simple web page that can be used to test us: http://www.procata.com/cachetest/ */ bool QNetworkAccessHttpBackend::sendCacheContents(const QNetworkCacheMetaData &metaData) { setCachingEnabled(false); if (!metaData.isValid()) return false; QAbstractNetworkCache *nc = networkCache(); Q_ASSERT(nc); QIODevice *contents = nc->data(url()); if (!contents) { #if defined(QNETWORKACCESSHTTPBACKEND_DEBUG) qDebug() << "Can not send cache, the contents are 0" << url(); #endif return false; } contents->setParent(this); QNetworkCacheMetaData::AttributesMap attributes = metaData.attributes(); int status = attributes.value(QNetworkRequest::HttpStatusCodeAttribute).toInt(); if (status < 100) status = 200; // fake it setAttribute(QNetworkRequest::HttpStatusCodeAttribute, status); setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, attributes.value(QNetworkRequest::HttpReasonPhraseAttribute)); setAttribute(QNetworkRequest::SourceIsFromCacheAttribute, true); QNetworkCacheMetaData::RawHeaderList rawHeaders = metaData.rawHeaders(); QNetworkCacheMetaData::RawHeaderList::ConstIterator it = rawHeaders.constBegin(), end = rawHeaders.constEnd(); for ( ; it != end; ++it) setRawHeader(it->first, it->second); checkForRedirect(status); writeDownstreamData(contents); #if defined(QNETWORKACCESSHTTPBACKEND_DEBUG) qDebug() << "Successfully sent cache:" << url() << contents->size() << "bytes"; #endif if (httpReply) disconnect(httpReply, SIGNAL(finished()), this, SLOT(replyFinished())); return true; }
void QNetworkAccessDataBackend::open() { QUrl uri = request().url(); if (operation() != QNetworkAccessManager::GetOperation && operation() != QNetworkAccessManager::HeadOperation) { // data: doesn't support anything but GET const QString msg = QCoreApplication::translate("QNetworkAccessDataBackend", "Operation not supported on %1") .arg(uri.toString()); error(QNetworkReply::ContentOperationNotPermittedError, msg); finished(); return; } QPair<QString, QByteArray> decoded = qDecodeDataUrl(uri); if (! decoded.first.isNull()) { setHeader(QNetworkRequest::ContentTypeHeader, decoded.first); setHeader(QNetworkRequest::ContentLengthHeader, decoded.second.size()); emit metaDataChanged(); QByteDataBuffer list; list.append(decoded.second); decoded.second.clear(); // important because of implicit sharing! writeDownstreamData(list); finished(); return; } // something wrong with this URI const QString msg = QCoreApplication::translate("QNetworkAccessDataBackend", "Invalid URI: %1").arg(uri.toString()); error(QNetworkReply::ProtocolFailure, msg); finished(); }
void QNetworkAccessDataBackend::open() { QUrl uri = request().url(); if (operation() != QNetworkAccessManager::GetOperation && operation() != QNetworkAccessManager::HeadOperation) { // data: doesn't support anything but GET QString msg = QObject::tr("Operation not supported on %1") .arg(uri.toString()); error(QNetworkReply::ContentOperationNotPermittedError, msg); finished(); return; } if (uri.host().isEmpty()) { setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String("text/plain;charset=US-ASCII")); // the following would have been the correct thing, but // reality often differs from the specification. People have // data: URIs with ? and # //QByteArray data = QByteArray::fromPercentEncoding(uri.encodedPath()); QByteArray data = QByteArray::fromPercentEncoding(uri.toEncoded()); // remove the data: scheme data.remove(0, 5); // parse it: int pos = data.indexOf(','); if (pos != -1) { QByteArray payload = data.mid(pos + 1); data.truncate(pos); data = data.trimmed(); // find out if the payload is encoded in Base64 if (data.endsWith(";base64")) { payload = QByteArray::fromBase64(payload); data.chop(7); } if (data.toLower().startsWith("charset")) { int i = 7; // strlen("charset") while (data.at(i) == ' ') ++i; if (data.at(i) == '=') data.prepend("text/plain;"); } if (!data.isEmpty()) setHeader(QNetworkRequest::ContentTypeHeader, data.trimmed()); setHeader(QNetworkRequest::ContentLengthHeader, payload.size()); emit metaDataChanged(); writeDownstreamData(payload); finished(); return; } } // something wrong with this URI QString msg = QObject::tr("Invalid URI: %1").arg(uri.toString()); error(QNetworkReply::ProtocolFailure, msg); finished(); }