qint64 QHttpNetworkHeaderPrivate::contentLength() const { bool ok = false; QByteArray value = headerField("content-length"); qint64 length = value.toULongLong(&ok); if (ok) return length; return -1; // the header field is not set }
void CWspDefaultHdrReader::DecodeHeaderL(RHeaderField& aHeader) { // Get and store the header field name TPtrC8 headerField(aHeader.Name().DesC()); // Decode the header as a text-string TPtrC8 rawHeaderData; aHeader.RawDataL(rawHeaderData); TInt startPos = 0; TInt separatorPos = 0; TInt ii = 0; // Loop through all the parts separated by the header field name do { TPtrC8 rawData(rawHeaderData.Mid(startPos)); separatorPos = rawData.FindF(headerField); if(separatorPos!=KErrNotFound) rawData.Set(rawHeaderData.Mid(startPos, separatorPos)); // Check that the length of the data is at least 1 if( rawData.Length() < 1 ) User::Leave(KErrCorrupt); // Check if the data is an empty string which should only have a NULL terminator // otherwise extract the text-string from the primitive decoder TUint8 firstByte = rawData[0]; TWspPrimitiveDecoder wspDecoder(rawData); TPtrC8 buffer; if( firstByte == 0 ) buffer.Set(KNullDesC8()); else User::LeaveIfError(wspDecoder.String(buffer)); // Create a header part from the decoded buffer and add the part to the header field RStringF partStr = iStrPool.OpenFStringL(buffer); CleanupClosePushL(partStr); THTTPHdrVal partVal(partStr); CHeaderFieldPart* part = CHeaderFieldPart::NewL(partVal); CleanupStack::PushL(part); aHeader.SetPartL(part, ii); CleanupStack::Pop(part); CleanupStack::PopAndDestroy(&partStr); ++ii; startPos += (separatorPos + headerField.Length() + 1); } while( separatorPos != KErrNotFound ); }
qint64 QHttpNetworkReplyPrivate::readHeader(QAbstractSocket *socket) { if (fragment.isEmpty()) { // according to http://dev.opera.com/articles/view/mama-http-headers/ the average size of the header // block is 381 bytes. // reserve bytes. This is better than always append() which reallocs the byte array. fragment.reserve(512); } qint64 bytes = 0; char c = 0; bool allHeaders = false; qint64 haveRead = 0; do { haveRead = socket->read(&c, 1); if (haveRead == 0) { // read more later break; } else if (haveRead == -1) { // connection broke down return -1; } else { fragment.append(c); bytes++; if (c == '\n') { // check for possible header endings. As per HTTP rfc, // the header endings will be marked by CRLFCRLF. But // we will allow CRLFCRLF, CRLFLF, LFLF if (fragment.endsWith("\r\n\r\n") || fragment.endsWith("\r\n\n") || fragment.endsWith("\n\n")) allHeaders = true; // there is another case: We have no headers. Then the fragment equals just the line ending if ((fragment.length() == 2 && fragment.endsWith("\r\n")) || (fragment.length() == 1 && fragment.endsWith("\n"))) allHeaders = true; } } } while (!allHeaders && haveRead > 0); // we received all headers now parse them if (allHeaders) { parseHeader(fragment); state = ReadingDataState; fragment.clear(); // next fragment bodyLength = contentLength(); // cache the length // cache isChunked() since it is called often chunkedTransferEncoding = headerField("transfer-encoding").toLower().contains("chunked"); // cache isConnectionCloseEnabled since it is called often QByteArray connectionHeaderField = headerField("connection"); // check for explicit indication of close or the implicit connection close of HTTP/1.0 connectionCloseEnabled = (connectionHeaderField.toLower().contains("close") || headerField("proxy-connection").toLower().contains("close")) || (majorVersion == 1 && minorVersion == 0 && (connectionHeaderField.isEmpty() && !headerField("proxy-connection").toLower().contains("keep-alive"))); } return bytes; }
bool QHttpNetworkReplyPrivate::isGzipped() { QByteArray encoding = headerField("content-encoding"); return qstricmp(encoding.constData(), "gzip") == 0; }