void Audio_Stream::seekToTime(unsigned newSeekTime) { unsigned duration = durationInSeconds(); if (!(duration > 0)) { return; } close(); setState(SEEKING); HTTP_Stream_Position position; double offset = (double)newSeekTime / (double)duration; position.start = m_dataOffset + offset * (contentLength() - m_dataOffset); position.end = contentLength(); m_seekTime = newSeekTime; if (m_httpStream->open(position)) { AS_TRACE("%s: HTTP stream opened, buffering...\n", __PRETTY_FUNCTION__); m_httpStreamRunning = true; } else { AS_TRACE("%s: failed to open the HTTP stream\n", __PRETTY_FUNCTION__); setState(FAILED); } }
void HexView::columnsChanged() { int remainder = contentLength() % bytesPerRow(); int rowCount = (remainder > 0) ? 1 : 0; setRowCount( rowCount + ( contentLength() / bytesPerRow() ) ); }
bool HttpClient::endOfBodyReached() { if (endOfHeadersReached() && (contentLength() != kNoContentLengthHeader)) { // We've got to the body and we know how long it will be return (iBodyLengthConsumed >= contentLength()); } return false; }
void Audio_Stream::seekToTime(unsigned newSeekTime) { unsigned duration = durationInSeconds(); if (!(duration > 0)) { return; } if (state() == SEEKING) { return; } else { setState(SEEKING); } m_seekTime = newSeekTime; double offset = (double)newSeekTime / (double)duration; UInt64 seekByteOffset = m_dataOffset + offset * (contentLength() - m_dataOffset); HTTP_Stream_Position position; position.start = seekByteOffset; position.end = contentLength(); double packetDuration = m_srcFormat.mFramesPerPacket / m_srcFormat.mSampleRate; if (packetDuration > 0 && bitrate() > 0) { UInt32 ioFlags = 0; SInt64 packetAlignedByteOffset; SInt64 seekPacket = floor((double)newSeekTime / packetDuration); OSStatus err = AudioFileStreamSeek(m_audioFileStream, seekPacket, &packetAlignedByteOffset, &ioFlags); if (!err) { position.start = packetAlignedByteOffset + m_dataOffset; } } close(); AS_TRACE("Seeking position %llu\n", position.start); if (m_httpStream->open(position)) { AS_TRACE("%s: HTTP stream opened, buffering...\n", __PRETTY_FUNCTION__); m_httpStreamRunning = true; } else { AS_TRACE("%s: failed to open the fHTTP stream\n", __PRETTY_FUNCTION__); setState(FAILED); } }
void HexView::paint(QPainter *painter) { int left = 0; int firstRow = getRowForY( viewport_.y() ) - 1; int lastRow = getRowForY( viewport_.y() + viewport_.height() ) + 1; if (firstRow < 0) firstRow = 0; if (lastRow > rowCount() ) lastRow = rowCount(); painter->setFont(QFont("Courier")); qDebug() << "contentlength=" << contentLength() << " firstrow=" << firstRow << " lastRow=" << lastRow << " viewport=" << viewport_; if (showGuidelines_) { QPen backpen(QColor(255,0,0)); painter->setPen(backpen); //painter->drawRect(viewport_); } if (showOffsets()) { paintOffsets(painter,left,firstRow,lastRow); } if (showHex()) { paintHex(painter,left,firstRow,lastRow); } if (showAscii()) { paintAscii(painter,left,firstRow,lastRow); } }
bool QHttpNetworkReplyPrivate::expectContent() { // check whether we can expect content after the headers (rfc 2616, sec4.4) if ((statusCode >= 100 && statusCode < 200) || statusCode == 204 || statusCode == 304) return false; if (request.operation() == QHttpNetworkRequest::Head) return !shouldEmitSignals(); if (contentLength() == 0) return false; return true; }
// discard remainder of POST data void HTTPHeader::discard(Socket *sock) { static char fred[4096]; off_t cl = contentLength() - postdatalen; int rc; while (cl > 0) { rc = sock->readFromSocket(fred, ((cl > 4096) ? 4096 : cl), 0, timeout, false); if (rc > 0) cl -= rc; else break; } }
unsigned Audio_Stream::durationInSeconds() { unsigned duration = 0; unsigned bitrate = m_audioQueue->bitrate(); if (bitrate == 0) { goto out; } duration = contentLength() / (bitrate * 0.125); out: return duration; }
bool QHttpNetworkReplyPrivate::expectContent() { // check whether we can expect content after the headers (rfc 2616, sec4.4) if ((statusCode >= 100 && statusCode < 200) || statusCode == 204 || statusCode == 304) return false; if (request.operation() == QHttpNetworkRequest::Head) return false; // no body expected for HEAD request qint64 expectedContentLength = contentLength(); if (expectedContentLength == 0) return false; if (expectedContentLength == -1 && bodyLength == 0) { // The content-length header was stripped, but its value was 0. // This would be the case for an explicitly zero-length compressed response. return false; } return true; }
String HttpClient::responseBody() { int bodyLength = contentLength(); String response; if (bodyLength > 0) { // try to reserve bodyLength bytes if (response.reserve(bodyLength) == 0) { // String reserve failed return String((const char*)NULL); } } // keep on timedRead'ing, until: // - we have a content length: body length equals consumed or no bytes // available // - no content length: no bytes are available while (iBodyLengthConsumed != bodyLength) { int c = timedRead(); if (c == -1) { // read timed out, done break; } if (!response.concat((char)c)) { // adding char failed return String((const char*)NULL); } } if (bodyLength > 0 && (unsigned int)bodyLength != response.length()) { // failure, we did not read in reponse content length bytes return String((const char*)NULL); } return response; }
unsigned Audio_Stream::durationInSeconds() { unsigned duration = 0; unsigned bitrate = this->bitrate(); if (bitrate == 0) { goto out; } double d; if (m_audioDataByteCount > 0) { d = m_audioDataByteCount; } else { d = contentLength(); } duration = d / (bitrate * 0.125); out: return duration; }
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 Reply::nextBuffers(std::vector<asio::const_buffer>& result) { bufs_.clear(); buf_.clear(); postBuf_.clear(); if (relay_.get()) return relay_->nextBuffers(result); else { if (!transmitting_) { transmitting_ = true; bool http10 = (request_.http_version_major == 1) && (request_.http_version_minor == 0); closeConnection_ = closeConnection_ || request_.closeConnection(); /* * Status line. */ buf_ << "HTTP/"; buf_ << request_.http_version_major; buf_ << '.'; buf_ << request_.http_version_minor; buf_ << ' '; status_strings::toText(buf_, status_); if (!http10 && status_ != switching_protocols) { /* * Date header (current time) */ buf_ << "Date: "; httpDateBuf(time(0), buf_); buf_ << "\r\n"; } /* * Content type or location */ std::string ct; if (status_ >= 300 && status_ < 400) { if (!location().empty()) { buf_ << "Location: " << location() << "\r\n"; } } else if (status_ != not_modified && status_ != switching_protocols) { ct = contentType(); buf_ << "Content-Type: " << ct << "\r\n"; } /* * Other provided headers */ bool haveContentEncoding = false; for (unsigned i = 0; i < headers_.size(); ++i) { if (headers_[i].first == "Content-Encoding") haveContentEncoding = true; buf_ << headers_[i].first << ": " << headers_[i].second << "\r\n"; } ::int64_t cl = -1; if (status_ != not_modified) cl = contentLength(); else cl = 0; /* * We would need to figure out the content length based on the * response data, but this doesn't work: WtReply reuses the * same buffers over and over, expecting them to be sent * inbetween each call to nextContentBuffer() */ if ((cl == -1) && http10) closeConnection_ = true; /* * Connection */ if (closeConnection_ && request_.type == Request::HTTP) { buf_ << "Connection: close\r\n"; } else { if (http10) { buf_ << "Connection: keep-alive\r\n"; } } if (status_ != not_modified) { #ifdef WTHTTP_WITH_ZLIB /* * Content-Encoding: gzip ? */ gzipEncoding_ = !haveContentEncoding && configuration_.compression() && request_.acceptGzipEncoding() && (cl == -1) && (ct.find("text/html") != std::string::npos || ct.find("text/plain") != std::string::npos || ct.find("text/javascript") != std::string::npos || ct.find("text/css") != std::string::npos || ct.find("application/xhtml+xml")!= std::string::npos || ct.find("image/svg+xml")!= std::string::npos || ct.find("application/octet")!= std::string::npos || ct.find("text/x-json") != std::string::npos); if (gzipEncoding_) { buf_ << "Content-Encoding: gzip\r\n"; initGzip(); } #endif /* * We do not need to determine the length of the response... * Transmit only header first. */ if (cl != -1) { buf_ << "Content-Length: " << (long long)cl << "\r\n"; chunkedEncoding_ = false; } else if (closeConnection_) chunkedEncoding_ = false; // should be false else if (!http10 && status_ != switching_protocols) chunkedEncoding_ = true; if (chunkedEncoding_) { buf_ << "Transfer-Encoding: chunked\r\n"; } buf_ << "\r\n"; return nextWrappedContentBuffers(result); } else { // status_ == not-modified buf_ << "\r\n"; buf_.asioBuffers(result); return true; } } else { // transmitting (data) return nextWrappedContentBuffers(result); } } assert(false); return true; }
// is this a POST request encapsulating a file upload? bool HTTPHeader::isPostUpload(Socket &peersock) { if (header.front().toCharArray()[0] != 'P') { return false; } /*bool answer = false; int postlen = postdata.buffer_length; int i; if (postlen < 14) { // min length for there to be a match return false; } char *postdatablock = new char[postlen + 64]; // extra 64 for search try { postdata.copyToMemory(postdatablock); for (i = 0; i < postlen; i++) { // make lowercase char by char if (isupper(postdatablock[i])) { postdatablock[i] = tolower(postdatablock[i]); } } RegExp mysearch; std::string dis("content-type: "); // signifies file upload char *p = new char[32]; try { for (i = 0; i < (signed) dis.length(); i++) { p[i] = dis[i]; // copy it to the block of memory } char *pend = p + dis.length(); // pointer for search char *postdatablockend = postdatablock + postlen; // search the post data for the content type header char *res = mysearch.search(postdatablock, postdatablockend, p, pend); // if we searched all the way to the end without finding it, // there is no post upload going on; otherwise, there is if (res != postdatablockend) { answer = true; } } catch(exception & e) { }; delete[]p; } catch(exception & e) { }; delete[]postdatablock; return answer;*/ off_t cl = contentLength(); if (((cl > 0) && (cl < 14)) || (getContentType() == "application/x-www-form-urlencoded")) { #ifdef DGDEBUG std::cout << "Based on content length/type, is not POST upload!" << std::endl; #endif ispostupload = false; return false; } if (getContentType().length() > 0) { #ifdef DGDEBUG std::cout << "Based on content length/type, is POST upload!" << std::endl; #endif ispostupload = true; return true; } #ifdef DGDEBUG std::cout << "Reading a line of POST data to determine content type: "; #endif postdatalen = peersock.getLine(postdata, 14, 60, &postdatachopped); #ifdef DGDEBUG std::cout << postdata << std::endl; #endif if (postdatalen != 14) { #ifdef DGDEBUG std::cout << "Is not POST upload!" << std::endl; #endif ispostupload = false; return false; } String conttype(postdata); if (conttype.startsWithLower("content-type: ")) { #ifdef DGDEBUG std::cout << "Is POST upload!" << std::endl; #endif ispostupload = true; return true; } else { #ifdef DGDEBUG std::cout << "Is not POST upload!" << std::endl; #endif ispostupload = false; return false; } }
// send headers out over the given socket // "reconnect" flag gives permission to reconnect to the socket on write error // - this allows us to re-open the proxy connection on pconns if squid's end has // timed out but the client's end hasn't. not much use with NTLM, since squid // will throw a 407 and restart negotiation, but works well with basic & others. void HTTPHeader::out(Socket * peersock, Socket * sock, int sendflag, bool reconnect) throw(std::exception) { String l; // for amalgamating to avoid conflict with the Nagel algorithm if (sendflag == __DGHEADER_SENDALL || sendflag == __DGHEADER_SENDFIRSTLINE) { if (header.size() > 0) { l = header.front() + "\n"; #ifdef DGDEBUG std::cout << "headertoclient:" << l << std::endl; #endif // first reconnect loop - send first line while (true) { if (!(*sock).writeToSocket(l.toCharArray(), l.length(), 0, timeout)) { // reconnect & try again if we've been told to if (reconnect) { // don't try more than once #ifdef DGDEBUG std::cout << "Proxy connection broken (1); trying to re-establish..." << std::endl; syslog(LOG_ERR,"Proxy connection broken (1); trying to re-establish..."); #endif reconnect = false; sock->reset(); int rc = sock->connect(o.proxy_ip, o.proxy_port); if (rc) throw std::exception(); continue; } throw std::exception(); } // if we got here, we succeeded, so break the reconnect loop break; } } if (sendflag == __DGHEADER_SENDFIRSTLINE) { return; } } l = ""; for (std::deque<String>::iterator i = header.begin() + 1; i != header.end(); i++) { l += (*i) + "\n"; } l += "\r\n"; #ifdef DGDEBUG std::cout << "headertoclient:" << l << std::endl; #endif // second reconnect loop while (true) { // send header to the output stream // need exception for bad write if (!(*sock).writeToSocket(l.toCharArray(), l.length(), 0, timeout)) { // reconnect & try again if we've been told to if (reconnect) { // don't try more than once #ifdef DGDEBUG std::cout << "Proxy connection broken (2); trying to re-establish..." << std::endl; syslog(LOG_ERR,"Proxy connection broken (2); trying to re-establish..."); #endif reconnect = false; sock->reset(); int rc = sock->connect(o.proxy_ip, o.proxy_port); if (rc) throw std::exception(); // include the first line on the retry l = header.front() + "\n" + l; continue; } throw std::exception(); } // if we got here, we succeeded, so break the reconnect loop break; } if ((!requestType().startsWith("HTTP")) && (pcontentlength != NULL)) { if (postdatalen > 0) { #ifdef DGDEBUG std::cout << "Sending initial POST data chunk" << std::endl; #endif // Re-add the chopped off \n, if necessary if (postdatachopped) { #ifdef DGDEBUG std::cout << "Re-adding newline to POST data (postdatalen " << postdatalen << ")" << std::endl; #endif postdata[postdatalen-1] = '\n'; postdata[postdatalen] = '\0'; } sock->writeToSockete(postdata, postdatalen, 0, timeout); } #ifdef DGDEBUG std::cout << "Opening tunnel for remainder of POST data" << std::endl; #endif FDTunnel fdt; off_t remaining = contentLength() - postdatalen; if (remaining < 0) throw std::runtime_error("No POST data left to send!?"); fdt.tunnel(*peersock, *sock, false, remaining, true); } }