Beispiel #1
0
// streaming callbacks
static int ReadFunc(void *opaque, uint8_t *buf, int buf_size)
{
    QIODevice *io = (QIODevice*)opaque;

    buf_size = min(buf_size, (int) io->bytesAvailable());
    return io->read((char*)buf, buf_size);
}
qint64 QIODeviceProto::bytesAvailable() const
{
  QIODevice *item = qscriptvalue_cast<QIODevice*>(thisObject());
  if (item)
    return item->bytesAvailable();
  return 0;
}
bool SdtpCatalogDataProvider::parseSearchData( QIODevice &stream, XFileList& list )
{
    while ( stream.bytesAvailable() > 0 ) {
        quint32 id, pid, date;
        QString name, thumbLink;

        try {
            id = SDTP::unpackUInt32(stream);
            pid = SDTP::unpackUInt32(stream);
            name = SDTP::unpackString(stream);
            thumbLink = SDTP::unpackString(stream);
            date = SDTP::unpackUInt32(stream);
        } catch( std::exception *e ) {
            qDebug("Failed to parse 'search' packet");
            delete e;
            for ( XFileList::iterator it = list.begin(); it != list.end(); ++it )
                delete *it;
            return false;
        }

        XFile *file = new XFile(id, NULL, name);
        file->setThumbLink(thumbLink);
        file->setDate(date);
        file->setPid(pid);

        list.append(file);
    }

    return true;
}
/** Check if a full message is available in the buffer
 *
 * @param ioDevice
 *
 * @return
 *
 * History:
 * - 2010/08/03: STEELJ  - Initial Version.
  */
bool CAdChannel::fullMessageAvailable(QIODevice& ioDevice) const
{
  if (ioDevice.bytesAvailable() < 4)
    return false;
  QByteArray startData = ioDevice.peek(4);
  if (startData.size() < 4)
    return false;
  QDataStream stream(startData);
  quint16 messageId, messageSize;
  stream >> messageId;
  stream >> messageSize;
  return(m_socket->bytesAvailable() >= (messageSize + 8));
}
Beispiel #5
0
/**
  * @exception notEnoughDataException
  */
MessageHeader MessageHeader::readHeader(QIODevice& device, bool skipReadData)
{
   if (device.bytesAvailable() < HEADER_SIZE)
      throw notEnoughDataException();

   char data[HEADER_SIZE];

   if (skipReadData)
      device.read(data, HEADER_SIZE);
   else
      device.peek(data, HEADER_SIZE);

   return MessageHeader::readHeader(data);
}
bool SdtpCatalogDataProvider::parseFoldersRecursiveData( XFolder* parent, QIODevice& stream,
        XFolderDict& folderDict, XFolderList& list )
{
    folderDict[parent->id()] = parent;

    while ( stream.bytesAvailable() > 0 ) {
        quint32 id, pid, children;
        QString name;

        try{
            id = SDTP::unpackUInt32(stream);
            pid = SDTP::unpackUInt32(stream);
            children = SDTP::unpackUInt32(stream);
            name = SDTP::unpackString(stream);
        } catch( std::exception *e ) {
            qDebug("Failed to parse 'allfolder' packet");
            for ( XFolderList::iterator it = list.begin(); it != list.end(); ++it )
                delete *it;
            folderDict.clear();
            delete e;
            return false;
        }

        parent = folderDict[pid];
        if ( NULL == parent ) {
            qDebug("Folder id=%u with pid=%u hasn't parent in dictionary: skipping", id, pid);
            continue;
        }

        XFolder* folder = new XFolder(id, name, children, parent);
        folder->setFoldersFetchStatus(Done);
        parent->addFolder(folder);

        if( 0 == pid ) // add to root list
            list.append(folder);
        folderDict[id] = folder;
    }

    return true;
}
bool SdtpCatalogDataProvider::parseFoldersData( XFolder* parent, QIODevice &stream, XFolderList& list )
{
    while ( stream.bytesAvailable() > 0 ) {
        quint32 id, children;
        QString name;

        try {
            id = SDTP::unpackUInt32(stream);
            children = SDTP::unpackUInt32(stream);
            name = SDTP::unpackString(stream);
        } catch ( std::exception *e ) {
            qDebug("Failed to parse 'folder' packet");
            delete e;
            for ( XFolderList::iterator it = list.begin(); it != list.end(); ++it )
                delete *it;
            return false;
        }

        XFolder* folder = new XFolder(id, name, children, parent);
        list.append(folder);
    }

    return true;
}
bool LimitedSocket::readCycle()
{
	QByteArray buffer;
	bool bProblem = false;
	
	QIODevice* pRemote = getRemote();

	if(m_timer.isNull())
	{
		m_prevBytes = 0;
		m_timer.start();
	}
	
	int limit = m_nSpeedLimit;

	do
	{
		QByteArray buf;
		qint64 available;
		
		available = pRemote->bytesAvailable();
		if(!available && !pRemote->waitForReadyRead(10000))
		{
			bProblem = true;
			break;
		}
		
		qint64 toread = (limit) ? limit/2 : available;
		
		if(m_nToTransfer && m_nToTransfer-m_nTransfered < toread)
			toread = m_nToTransfer-m_nTransfered;
		
		buf = pRemote->read(toread);
		buffer += buf;
		m_nTransfered += buf.size();
		
		if(m_nTransfered >= m_nToTransfer && m_nToTransfer)
			break;
	}
	while(buffer.size() < 1024);

	m_file.write(buffer);

	if(bProblem)
	{
		/*if(m_pSocket->state() == QAbstractSocket::ConnectedState) // timeout
			m_strError = tr ( "Timeout" );
		else if(m_pSocket->error() == QAbstractSocket::RemoteHostClosedError)
		{
			if(m_nToTransfer > m_nTransfered && m_nToTransfer)
			{
				qDebug() << "Remote host closed the connection";
				m_strError = tr ( "Connection lost" );
			}
		}
		else
		{
			m_strError = m_pSocket->errorString();
			if ( m_strError.isEmpty() )
			{
				qDebug() << "Connection lost!";
				m_strError = tr ( "Connection lost" );
			}
		}*/
	}
	else if(!m_bAbort)
	{
//		QTime now = QTime::currentTime();
		qulonglong bnow = m_nTransfered;

		int msecs;
		qulonglong bytes = bnow - m_prevBytes;

		if((msecs = m_timer.elapsed()) > 1000)
		{
			m_statsLock.lockForWrite();
			m_stats << QPair<int,qulonglong> ( m_timer.restart(), bytes );
			if(m_stats.size() > SPEED_SAMPLES)
				m_stats.removeFirst();
			m_statsLock.unlock();

			m_prevBytes = bnow;
		}

		if(limit > 0 && bytes)
		{
			int sleeptime = bytes/ ( limit/1000 ) - msecs;
			if(sleeptime > 0)
				msleep(sleeptime*2);
		}
	}

	return !bProblem;
}
qint64 FlushedProcess::bytesAvailable() const {
    QIODevice * dev = readingIODevice();
    return (dev == NULL)?0:dev->bytesAvailable();
}
int TAbstractWebSocket::parse(QByteArray &recvData)
{
    tSystemDebug("parse enter  data len:%d  sid:%d", recvData.length(), socketId());
    if (websocketFrames().isEmpty()) {
        websocketFrames().append(TWebSocketFrame());
    } else {
        const TWebSocketFrame &f = websocketFrames().last();
        if (f.state() == TWebSocketFrame::Completed) {
            websocketFrames().append(TWebSocketFrame());
        }
    }

    TWebSocketFrame *pfrm = &websocketFrames().last();
    quint8  b;
    quint16 w;
    quint32 n;
    quint64 d;

    QDataStream ds(recvData);
    ds.setByteOrder(QDataStream::BigEndian);
    QIODevice *dev = ds.device();
    QByteArray hdr;

    while (!ds.atEnd()) {
        switch (pfrm->state()) {
        case TWebSocketFrame::Empty: {
            hdr = dev->peek(14);
            QDataStream dshdr(hdr);
            dshdr.setByteOrder(QDataStream::BigEndian);
            QIODevice *devhdr = dshdr.device();

            if (Q_UNLIKELY(devhdr->bytesAvailable() < 2)) {
                goto parse_end;
            }

            dshdr >> b;
            pfrm->setFirstByte(b);
            dshdr >> b;
            bool maskFlag = b & 0x80;
            quint8 len = b & 0x7f;

            // payload length
            switch (len) {
            case 126:
                if (Q_UNLIKELY(devhdr->bytesAvailable() < (int)sizeof(w))) {
                    goto parse_end;
                }
                dshdr >> w;
                if (Q_UNLIKELY(w < 126)) {
                    tSystemError("WebSocket protocol error  [%s:%d]", __FILE__, __LINE__);
                    return -1;
                }
                pfrm->setPayloadLength( w );
                break;

            case 127:
                if (Q_UNLIKELY(devhdr->bytesAvailable() < (int)sizeof(d))) {
                    goto parse_end;
                }
                dshdr >> d;
                if (Q_UNLIKELY(d <= 0xFFFF)) {
                    tSystemError("WebSocket protocol error  [%s:%d]", __FILE__, __LINE__);
                    return -1;
                }
                pfrm->setPayloadLength( d );
                break;

            default:
                pfrm->setPayloadLength( len );
                break;
            }

            // Mask key
            if (maskFlag) {
                if (Q_UNLIKELY(devhdr->bytesAvailable() < (int)sizeof(n))) {
                    goto parse_end;
                }
                dshdr >> n;
                pfrm->setMaskKey( n );
            }

            if (pfrm->payloadLength() == 0) {
                pfrm->setState(TWebSocketFrame::Completed);
            } else {
                pfrm->setState(TWebSocketFrame::HeaderParsed);
                if (pfrm->payloadLength() >= 2 * 1024 * 1024 * 1024ULL) {
                    tSystemError("Too big frame  [%s:%d]", __FILE__, __LINE__);
                    pfrm->clear();
                } else {
                    pfrm->payload().reserve(pfrm->payloadLength());
                }
            }

            tSystemDebug("WebSocket parse header pos: %lld", devhdr->pos());
            tSystemDebug("WebSocket payload length:%lld", pfrm->payloadLength());

            int hdrlen = hdr.length() - devhdr->bytesAvailable();
            ds.skipRawData(hdrlen);  // Forwards the pos
            break; }

        case TWebSocketFrame::HeaderParsed:  // fall through
        case TWebSocketFrame::MoreData: {
            tSystemDebug("WebSocket reading payload:  available length:%lld", dev->bytesAvailable());
            tSystemDebug("WebSocket parsing  length to read:%llu  current buf len:%d", pfrm->payloadLength(), pfrm->payload().size());
            quint64 size = qMin((pfrm->payloadLength() - pfrm->payload().size()), (quint64)dev->bytesAvailable());
            if (Q_UNLIKELY(size == 0)) {
                Q_ASSERT(0);
                break;
            }

            char *p = pfrm->payload().data() + pfrm->payload().size();
            size = ds.readRawData(p, size);

            if (pfrm->maskKey()) {
                // Unmask
                const quint8 mask[4] = { quint8((pfrm->maskKey() & 0xFF000000) >> 24),
                                         quint8((pfrm->maskKey() & 0x00FF0000) >> 16),
                                         quint8((pfrm->maskKey() & 0x0000FF00) >> 8),
                                         quint8((pfrm->maskKey() & 0x000000FF)) };

                int i = pfrm->payload().size();
                const char *end = p + size;
                while (p < end) {
                    *p++ ^= mask[i++ % 4];
                }
            }
            pfrm->payload().resize( pfrm->payload().size() + size );
            tSystemDebug("WebSocket payload curent buf len: %d", pfrm->payload().length());

            if ((quint64)pfrm->payload().size() == pfrm->payloadLength()) {
                pfrm->setState(TWebSocketFrame::Completed);
                tSystemDebug("Parse Completed   payload len: %d", pfrm->payload().size());
            } else {
                pfrm->setState(TWebSocketFrame::MoreData);
                tSystemDebug("Parse MoreData   payload len: %d", pfrm->payload().size());
            }
            break; }

        case TWebSocketFrame::Completed:  // fall through
        default:
            Q_ASSERT(0);
            break;
        }

        if (pfrm->state() == TWebSocketFrame::Completed) {
            if (Q_UNLIKELY(!pfrm->validate())) {
                pfrm->clear();
                continue;
            }

            // Fragmented message validation
            if (pfrm->opCode() == TWebSocketFrame::Continuation) {
                if (websocketFrames().count() >= 2) {
                    const TWebSocketFrame &before = websocketFrames()[websocketFrames().count() - 2];
                    if (before.isFinalFrame() || before.isControlFrame()) {
                        pfrm->clear();
                        tSystemWarn("Invalid continuation frame detected  [%s:%d]", __FILE__, __LINE__);
                        continue;
                    }
                }
            }

            // In case of control frame, moves forward after previous control frames
            if (pfrm->isControlFrame()) {
                if (websocketFrames().count() >= 2) {
                    TWebSocketFrame frm = websocketFrames().takeLast();
                    QMutableListIterator<TWebSocketFrame> it(websocketFrames());
                    while (it.hasNext()) {
                        TWebSocketFrame &f = it.next();
                        if (!f.isControlFrame()) {
                            break;
                        }
                    }

                    it.insert(frm);
                }
            }

            if (!ds.atEnd()) {
                // Prepare next frame
                websocketFrames().append(TWebSocketFrame());
                pfrm = &websocketFrames().last();
            } else {
                break;
            }
        }
    }

parse_end:
    int parsedlen = recvData.size() - dev->bytesAvailable();
    recvData.remove(0, parsedlen);
    return parsedlen;
}
Beispiel #11
0
image::Image image::readTGA(QIODevice& content) {
    enum class TGAImageType : uint8_t {
        NoImageData = 0,
        UncompressedColorMapped = 1,
        UncompressedTrueColor = 2,
        UncompressedBlackWhite = 3,
        RunLengthEncodedColorMapped = 9,
        RunLengthEncodedTrueColor = 10,
        RunLengthEncodedBlackWhite = 11,
    };

    struct TGAHeader {
        uint8_t idLength;
        uint8_t colorMapType;
        TGAImageType imageType;
        struct {
            uint64_t firstEntryIndex : 16;
            uint64_t length : 16;
            uint64_t entrySize : 8;
        } colorMap;
        uint16_t xOrigin;
        uint16_t yOrigin;
        uint16_t width;
        uint16_t height;
        uint8_t pixelDepth;
        struct {
            uint8_t attributeBitsPerPixel : 4;
            uint8_t reserved : 1;
            uint8_t orientation : 1;
            uint8_t padding : 2;
        } imageDescriptor;
    };

    constexpr bool WANT_DEBUG { false };
    constexpr qint64 TGA_HEADER_SIZE_BYTES { 18 };

    // BottomLeft: 0, TopLeft: 1
    constexpr uint8_t ORIENTATION_BOTTOM_LEFT { 0 };

    TGAHeader header;

    if (content.isSequential()) {
        qWarning(imagelogging) << "TGA - Sequential devices are not supported for reading";
        return QImage();
    }

    if (content.bytesAvailable() < TGA_HEADER_SIZE_BYTES) {
        qWarning(imagelogging) << "TGA - Unexpectedly reached end of file";
        return QImage();
    }

    content.read((char*)&header.idLength, 1);
    content.read((char*)&header.colorMapType, 1);
    content.read((char*)&header.imageType, 1);
    content.read((char*)&header.colorMap, 5);
    content.read((char*)&header.xOrigin, 2);
    content.read((char*)&header.yOrigin, 2);
    content.read((char*)&header.width, 2);
    content.read((char*)&header.height, 2);
    content.read((char*)&header.pixelDepth, 1);
    content.read((char*)&header.imageDescriptor, 1);

    if (WANT_DEBUG) {
        qDebug(imagelogging) << "Id Length: " << (int)header.idLength;
        qDebug(imagelogging) << "Color map: " << (int)header.colorMap.firstEntryIndex << header.colorMap.length << header.colorMap.entrySize;
        qDebug(imagelogging) << "Color map type: " << (int)header.colorMapType;
        qDebug(imagelogging) << "Image type: " << (int)header.imageType;
        qDebug(imagelogging) << "Origin: " << header.xOrigin << header.yOrigin;
        qDebug(imagelogging) << "Size: " << header.width << header.height;
        qDebug(imagelogging) << "Depth: " << header.pixelDepth;
        qDebug(imagelogging) << "Image desc: " << header.imageDescriptor.attributeBitsPerPixel << (int)header.imageDescriptor.orientation;
    }

    if (header.xOrigin != 0 || header.yOrigin != 0) {
        qWarning(imagelogging) << "TGA - origin not supporter";
        return QImage();
    }

    if (!(header.pixelDepth == 24 && header.imageDescriptor.attributeBitsPerPixel == 0) && header.pixelDepth != 32) {
        qWarning(imagelogging) << "TGA - Only pixel depths of 24 (with no alpha) and 32 bits are supported";
        return QImage();
    }

    if (header.imageDescriptor.attributeBitsPerPixel != 0 && header.imageDescriptor.attributeBitsPerPixel != 8) {
        qWarning(imagelogging) << "TGA - Only 0 or 8 bits for the alpha channel is supported";
        return QImage();
    }

    char alphaMask = header.imageDescriptor.attributeBitsPerPixel == 8 ? 0x00 : 0xFF;
    int bytesPerPixel = header.pixelDepth / 8;

    content.skip(header.idLength);
    if (header.imageType == TGAImageType::UncompressedTrueColor) {
        qint64 minimumSize = header.width * header.height * bytesPerPixel;
        if (content.bytesAvailable() < minimumSize) {
            qWarning(imagelogging) << "TGA - Unexpectedly reached end of file";
            return QImage();
        }

        QImage image{ header.width, header.height, QImage::Format_ARGB32 };
        char* line;
        for (int y = 0; y < header.height; ++y) {
            if (header.imageDescriptor.orientation == ORIENTATION_BOTTOM_LEFT) {
                line = (char*)image.scanLine(header.height - y - 1);
            } else {
                line = (char*)image.scanLine(y);
            }
            for (int x = 0; x < header.width; ++x) {
                content.read(line, bytesPerPixel);
                *(line + 3) |= alphaMask;

                line += 4;
            }
        }
        return image;
    } else if (header.imageType == TGAImageType::RunLengthEncodedTrueColor) {
        QImage image{ header.width, header.height, QImage::Format_ARGB32 };

        for (int y = 0; y < header.height; ++y) {
            char* line;
            if (header.imageDescriptor.orientation == ORIENTATION_BOTTOM_LEFT) {
                line = (char*)image.scanLine(header.height - y - 1);
            } else {
                line = (char*)image.scanLine(y);
            }
            int col = 0;
            while (col < header.width) {
                constexpr char IS_REPETITION_MASK{ (char)0x80 };
                constexpr char LENGTH_MASK{ (char)0x7f };
                char repetition;
                if (content.read(&repetition, 1) != 1) {
                    qWarning(imagelogging) << "TGA - Unexpectedly reached end of file";
                    return QImage();
                }
                bool isRepetition = repetition & IS_REPETITION_MASK;

                // The length in `repetition` is always 1 less than the number of following pixels,
                // so we need to increment it by 1. Because of this, the length is never 0.
                int length = (repetition & LENGTH_MASK) + 1;

                if (isRepetition) {
                    // Read into temporary buffer
                    char color[4];
                    if (content.read(color, bytesPerPixel) != bytesPerPixel) {
                        qWarning(imagelogging) << "TGA - Unexpectedly reached end of file";
                        return QImage();
                    }
                    color[3] |= alphaMask;

                    // Copy `length` number of times
                    col += length;
                    while (length-- > 0) {
                        *line = color[0];
                        *(line + 1) = color[1];
                        *(line + 2) = color[2];
                        *(line + 3) = color[3];

                        line += 4;
                    }
                } else {
                    qint64 minimumSize = length * bytesPerPixel;
                    if (content.bytesAvailable() < minimumSize) {
                        qWarning(imagelogging) << "TGA - Unexpectedly reached end of file";
                        return QImage();
                    }

                    // Read in `length` number of pixels
                    col += length;
                    while (length-- > 0) {
                        content.read(line, bytesPerPixel);
                        *(line + 3) |= alphaMask;

                        line += 4;
                    }
                }
            }
        }
        return image;
    } else {
        qWarning(imagelogging) << "TGA - Unsupported image type: " << (int)header.imageType;
    }

    return QImage();
}
/*!
 * \reimp
 */
void QxtHttpSessionManager::processEvents()
{
    if (QThread::currentThreadId() != qxt_d().mainThread)
    {
        QMetaObject::invokeMethod(this, "processEvents", Qt::QueuedConnection);
        return;
    }
    QxtHttpSessionManagerPrivate& d = qxt_d();
    QMutexLocker locker(&d.eventLock);
    if (!d.eventQueue.count()) return;

    int ct = d.eventQueue.count(), sessionID = 0, requestID = 0, pagePos = -1;
    QxtWebRedirectEvent* re = 0;
    QxtWebPageEvent* pe = 0;
    for (int i = 0; i < ct; i++)
    {
        if (d.eventQueue[i]->type() != QxtWebEvent::Page && d.eventQueue[i]->type() != QxtWebEvent::Redirect) continue;
        pagePos = i;
        sessionID = d.eventQueue[i]->sessionID;
        if (d.eventQueue[pagePos]->type() == QxtWebEvent::Redirect)
        {
            re = static_cast<QxtWebRedirectEvent*>(d.eventQueue[pagePos]);
        }
        pe = static_cast<QxtWebPageEvent*>(d.eventQueue[pagePos]);
        requestID = pe->requestID;
        break;
    }
    if (pagePos == -1) return; // no pages to send yet

    QHttpResponseHeader header;
    QList<int> removeIDs;
    QxtWebEvent* e = 0;
    for (int i = 0; i < pagePos; i++)
    {
        if (d.eventQueue[i]->sessionID != sessionID) continue;
        e = d.eventQueue[i];
        if (e->type() == QxtWebEvent::StoreCookie)
        {
            QxtWebStoreCookieEvent* ce = static_cast<QxtWebStoreCookieEvent*>(e);
            QString cookie = ce->name + '=' + ce->data;
            if (!ce->path.isEmpty())
                cookie += "; path=" + ce->path;
            if (ce->expiration.isValid())
            {
                cookie += "; max-age=" + QString::number(QDateTime::currentDateTime().secsTo(ce->expiration))
                          + "; expires=" + ce->expiration.toUTC().toString("ddd, dd-MMM-YYYY hh:mm:ss GMT");
            }
            header.addValue("set-cookie", cookie);
            removeIDs.push_front(i);
        }
        else if (e->type() == QxtWebEvent::RemoveCookie)
        {
            QxtWebRemoveCookieEvent* ce = static_cast<QxtWebRemoveCookieEvent*>(e);
            QString path;
            if(!ce->path.isEmpty()) path = "path=" + ce->path + "; ";
            header.addValue("set-cookie", ce->name + "=; "+path+"max-age=0; expires=" + QDateTime(QDate(1970, 1, 1)).toString("ddd, dd-MMM-YYYY hh:mm:ss GMT"));
            removeIDs.push_front(i);
        }
    }
    removeIDs.push_front(pagePos);

    QIODevice* device = connector()->getRequestConnection(requestID);
    QxtWebContent* content = qobject_cast<QxtWebContent*>(device);
    // TODO: This should only be invoked when pipelining occurs
    // In theory it shouldn't cause any problems as POST is specced to not be pipelined
    if (content) content->ignoreRemainingContent();
    QHash<QPair<int,int>,QxtWebRequestEvent*>::iterator iPending =
	qxt_d().pendingRequests.find(QPair<int,int>(sessionID, requestID));
    if(iPending != qxt_d().pendingRequests.end()){
	delete *iPending;
	qxt_d().pendingRequests.erase(iPending);
    }

    QxtHttpSessionManagerPrivate::ConnectionState& state = qxt_d().connectionState[connector()->getRequestConnection(requestID)];
    QIODevice* source;
    header.setStatusLine(pe->status, pe->statusMessage, state.httpMajorVersion, state.httpMinorVersion);

    if (re)
    {
        header.setValue("location", re->destination);
    }

    // Set custom header values
    for (QMultiHash<QString, QString>::iterator it = pe->headers.begin(); it != pe->headers.end(); ++it)
    {
        header.setValue(it.key(), it.value());
    }

    header.setContentType(pe->contentType);
    if (state.httpMajorVersion == 0 || (state.httpMajorVersion == 1 && state.httpMinorVersion == 0))
        pe->chunked = false;

    source = pe->dataSource;
    state.finishedTransfer = false;
    bool emptyContent = !source->bytesAvailable() && !pe->streaming;
    state.readyRead = source->bytesAvailable();
    state.streaming = pe->streaming;

    if (emptyContent)
    {
        header.setValue("connection", "close");
        connector()->writeHeaders(device, header);
        closeConnection(requestID);
    }
    else
    {
        pe->dataSource = 0;     // so that it isn't destroyed when the event is deleted
        state.clearHandlers();  // disconnect old handlers

        if (!pe->chunked)
        {
            state.keepAlive = false;
            state.onBytesWritten = QxtMetaObject::bind(this, SLOT(sendNextBlock(int, QObject*)), Q_ARG(int, requestID), Q_ARG(QObject*, source));
            state.onReadyRead = QxtMetaObject::bind(this, SLOT(blockReadyRead(int, QObject*)), Q_ARG(int, requestID), Q_ARG(QObject*, source));
            state.onAboutToClose = QxtMetaObject::bind(this, SLOT(closeConnection(int)), Q_ARG(int, requestID));
        }
        else
        {