// 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)); }
/** * @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; }
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 {