/*!
    \internal
 */
void QWebSocketDataProcessor::process(QIODevice *pIoDevice)
{
    bool isDone = false;

    while (!isDone) {
        QWebSocketFrame frame = QWebSocketFrame::readFrame(pIoDevice);
        if (Q_LIKELY(frame.isValid())) {
            if (frame.isControlFrame()) {
                isDone = processControlFrame(frame);
            } else {
                //we have a dataframe; opcode can be OC_CONTINUE, OC_TEXT or OC_BINARY
                if (Q_UNLIKELY(!m_isFragmented && frame.isContinuationFrame())) {
                    clear();
                    Q_EMIT errorEncountered(QWebSocketProtocol::CloseCodeProtocolError,
                                            tr("Received Continuation frame, while there is " \
                                               "nothing to continue."));
                    return;
                }
                if (Q_UNLIKELY(m_isFragmented && frame.isDataFrame() &&
                               !frame.isContinuationFrame())) {
                    clear();
                    Q_EMIT errorEncountered(QWebSocketProtocol::CloseCodeProtocolError,
                                            tr("All data frames after the initial data frame " \
                                               "must have opcode 0 (continuation)."));
                    return;
                }
                if (!frame.isContinuationFrame()) {
                    m_opCode = frame.opCode();
                    m_isFragmented = !frame.isFinalFrame();
                }
                quint64 messageLength = (quint64)(m_opCode == QWebSocketProtocol::OpCodeText)
                        ? m_textMessage.length()
                        : m_binaryMessage.length();
                if (Q_UNLIKELY((messageLength + quint64(frame.payload().length())) >
                               MAX_MESSAGE_SIZE_IN_BYTES)) {
                    clear();
                    Q_EMIT errorEncountered(QWebSocketProtocol::CloseCodeTooMuchData,
                                            tr("Received message is too big."));
                    return;
                }

                if (m_opCode == QWebSocketProtocol::OpCodeText) {
                    QString frameTxt = m_pTextCodec->toUnicode(frame.payload().constData(),
                                                               frame.payload().size(),
                                                               m_pConverterState);
                    bool failed = (m_pConverterState->invalidChars != 0)
                            || (frame.isFinalFrame() && (m_pConverterState->remainingChars != 0));
                    if (Q_UNLIKELY(failed)) {
                        clear();
                        Q_EMIT errorEncountered(QWebSocketProtocol::CloseCodeWrongDatatype,
                                                tr("Invalid UTF-8 code encountered."));
                        return;
                    } else {
                        m_textMessage.append(frameTxt);
                        Q_EMIT textFrameReceived(frameTxt, frame.isFinalFrame());
                    }
                } else {
                    m_binaryMessage.append(frame.payload());
                    Q_EMIT binaryFrameReceived(frame.payload(), frame.isFinalFrame());
                }

                if (frame.isFinalFrame()) {
                    if (m_opCode == QWebSocketProtocol::OpCodeText)
                        Q_EMIT textMessageReceived(m_textMessage);
                    else
                        Q_EMIT binaryMessageReceived(m_binaryMessage);
                    clear();
                    isDone = true;
                }
            }
        } else {
            Q_EMIT errorEncountered(frame.closeCode(), frame.closeReason());
            clear();
            isDone = true;
        }
    }
}
/*!
    \internal
 */
bool QWebSocketDataProcessor::processControlFrame(const QWebSocketFrame &frame)
{
    bool mustStopProcessing = true; //control frames never expect additional frames to be processed
    switch (frame.opCode()) {
    case QWebSocketProtocol::OpCodePing:
        Q_EMIT pingReceived(frame.payload());
        break;

    case QWebSocketProtocol::OpCodePong:
        Q_EMIT pongReceived(frame.payload());
        break;

    case QWebSocketProtocol::OpCodeClose:
    {
        quint16 closeCode = QWebSocketProtocol::CloseCodeNormal;
        QString closeReason;
        QByteArray payload = frame.payload();
        if (Q_UNLIKELY(payload.size() == 1)) {
            //size is either 0 (no close code and no reason)
            //or >= 2 (at least a close code of 2 bytes)
            closeCode = QWebSocketProtocol::CloseCodeProtocolError;
            closeReason = tr("Payload of close frame is too small.");
        } else if (Q_LIKELY(payload.size() > 1)) {
            //close frame can have a close code and reason
            closeCode = qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(payload.constData()));
            if (Q_UNLIKELY(!QWebSocketProtocol::isCloseCodeValid(closeCode))) {
                closeCode = QWebSocketProtocol::CloseCodeProtocolError;
                closeReason = tr("Invalid close code %1 detected.").arg(closeCode);
            } else {
                if (payload.size() > 2) {
                    QTextCodec *tc = QTextCodec::codecForName(QByteArrayLiteral("UTF-8"));
                    QTextCodec::ConverterState state(QTextCodec::ConvertInvalidToNull);
                    closeReason = tc->toUnicode(payload.constData() + 2, payload.size() - 2, &state);
                    const bool failed = (state.invalidChars != 0) || (state.remainingChars != 0);
                    if (Q_UNLIKELY(failed)) {
                        closeCode = QWebSocketProtocol::CloseCodeWrongDatatype;
                        closeReason = tr("Invalid UTF-8 code encountered.");
                    }
                }
            }
        }
        Q_EMIT closeReceived(static_cast<QWebSocketProtocol::CloseCode>(closeCode), closeReason);
        break;
    }

    case QWebSocketProtocol::OpCodeContinue:
    case QWebSocketProtocol::OpCodeBinary:
    case QWebSocketProtocol::OpCodeText:
    case QWebSocketProtocol::OpCodeReserved3:
    case QWebSocketProtocol::OpCodeReserved4:
    case QWebSocketProtocol::OpCodeReserved5:
    case QWebSocketProtocol::OpCodeReserved6:
    case QWebSocketProtocol::OpCodeReserved7:
    case QWebSocketProtocol::OpCodeReservedC:
    case QWebSocketProtocol::OpCodeReservedB:
    case QWebSocketProtocol::OpCodeReservedD:
    case QWebSocketProtocol::OpCodeReservedE:
    case QWebSocketProtocol::OpCodeReservedF:
        //do nothing
        //case statements added to make C++ compiler happy
        break;

    default:
        Q_EMIT errorEncountered(QWebSocketProtocol::CloseCodeProtocolError,
                                tr("Invalid opcode detected: %1").arg(int(frame.opCode())));
        //do nothing
        break;
    }
    return mustStopProcessing;
}
Example #3
0
QVariant PlaylistModel::data(const QModelIndex &index, int role) const
{
    if ( Q_UNLIKELY(index.row() < 0 || index.row() > rowCount())) {
        return QVariant(QVariant::Invalid);
    }
    if(role==NameRole)
    {
        return mEntries->at(index.row())->getName();
    }
    else if(role==pathRole)
        return mEntries->at(index.row())->getFileUri();
    else if(role==filenameRole)
        return mEntries->at(index.row())->getFileName();
    else if(role==titleRole)
        return mEntries->at(index.row())->getTitle();
    else if(role==sectionRole) {
        MpdTrack  *tmpTrack = mEntries->at(index.row());
        QString album = tmpTrack->getAlbum();
        QString albumartist = tmpTrack->getAlbumArtist();
        QString artist = tmpTrack->getArtist();

        QString sectionString;
        if ( albumartist == "" ) {
            sectionString = artist + '|' + album;
        } else {
            sectionString = albumartist + '|' + album;
        }
        return sectionString;
    }
    else if(role==artistRole)
        return mEntries->at(index.row())->getArtist();
    else if(role==albumRole)
        return mEntries->at(index.row())->getAlbum();
    else if(role==lengthRole)
        return mEntries->at(index.row())->getLength();
    else if(role==lengthFormatedRole)
        return mEntries->at(index.row())->getLengthFormated();
    else if(role==tracknoRole)
        return mEntries->at(index.row())->getTrackNr();
    else if(role==yearRole)
        return mEntries->at(index.row())->getYear();
    else if(role==playingRole)
        return mEntries->at(index.row())->getPlaying();
    else if(role==trackmbidRole)
        return mEntries->at(index.row())->getTrackMBID();
    else if(role==albummbidRole)
        return mEntries->at(index.row())->getAlbumMBID();
    else if(role==artistmbidRole)
        return mEntries->at(index.row())->getArtistMBID();
    else if ( role== sectionImageURLRole ) {
        MpdTrack *track = mEntries->at(index.row());
        QString album = track->getAlbum();
        QString artist = track->getArtist();
        if ( artist != "" ) {
            int imageID = mDB->imageIDFromAlbumArtist(album,artist);
            // No image found return dummy url
            if ( imageID == -1 ) {
                // Start image retrieval
                qDebug() << "returning dummy image for album: " << album;
                //emit requestAlbumInformation(*album);
                // Return dummy for the time being
                return DUMMY_ALBUMIMAGE;
            } else if (imageID == -2 ) {
                // Try getting album art for album with out artist (think samplers)
                imageID = mDB->imageIDFromAlbum(album);
                if ( imageID >= 0 ) {
                    QString url = "image://imagedbprovider/albumid/" + QString::number(imageID);
                    return url;
                }
                qDebug() << "returning dummy image for blacklisted album: " << album;
                return DUMMY_ALBUMIMAGE;
            } else {
                qDebug() << "returning database image for album: " << album;
                QString url = "image://imagedbprovider/albumid/" + QString::number(imageID);
                return url;
            }
        }
        else {
            int imageID = mDB->imageIDFromAlbum(album);

            // No image found return dummy url
            if ( imageID == -1 ) {
                // Start image retrieval
                qDebug() << "returning dummy image for album: " << album;
                // Return dummy for the time being
                return DUMMY_ALBUMIMAGE;
            } else if (imageID == -2 ) {
                qDebug() << "returning dummy image for blacklisted album: " << album;
                return DUMMY_ALBUMIMAGE;
            }
            else {
                qDebug() << "returning database image for album: " << album;
                QString url = "image://imagedbprovider/albumid/" + QString::number(imageID);
                return url;
            }
        }
    }

    return QVariant(QVariant::Invalid);;
}
/*!
    \internal
 */
void QWebSocketServerPrivate::handshakeReceived()
{
    if (Q_UNLIKELY(!currentSender)) {
        qWarning() << QWebSocketServer::tr("Sender is NULL. This is a Qt bug.");
        return;
    }
    QTcpSocket *pTcpSocket = qobject_cast<QTcpSocket*>(currentSender->sender);
    if (Q_UNLIKELY(!pTcpSocket)) {
        qWarning() << QWebSocketServer::tr("Sender is not a QTcpSocket. This is a Qt bug!!!");
        return;
    }
    //When using Google Chrome the handshake in received in two parts.
    //Therefore, the readyRead signal is emitted twice.
    //This is a guard against the BEAST attack.
    //See: https://www.imperialviolet.org/2012/01/15/beastfollowup.html
    //For Safari, the handshake is delivered at once
    //FIXME: For FireFox, the readyRead signal is never emitted
    //This is a bug in FireFox (see https://bugzilla.mozilla.org/show_bug.cgi?id=594502)
    if (!pTcpSocket->canReadLine()) {
        return;
    }
    disconnect(pTcpSocket, &QTcpSocket::readyRead,
               this, &QWebSocketServerPrivate::handshakeReceived);
    Q_Q(QWebSocketServer);
    bool success = false;
    bool isSecure = false;

    if (m_pendingConnections.length() >= maxPendingConnections()) {
        pTcpSocket->close();
        pTcpSocket->deleteLater();
        qWarning() << QWebSocketServer::tr("Too many pending connections: " \
                                           "New WebSocket connection not accepted.");
        setError(QWebSocketProtocol::CloseCodeAbnormalDisconnection,
                 QWebSocketServer::tr("Too many pending connections."));
        return;
    }

    QWebSocketHandshakeRequest request(pTcpSocket->peerPort(), isSecure);
    QTextStream textStream(pTcpSocket);
    request.readHandshake(textStream);

    if (request.isValid()) {
        QWebSocketCorsAuthenticator corsAuthenticator(request.origin());
        Q_EMIT q->originAuthenticationRequired(&corsAuthenticator);

        QWebSocketHandshakeResponse response(request,
                                             m_serverName,
                                             corsAuthenticator.allowed(),
                                             supportedVersions(),
                                             supportedProtocols(),
                                             supportedExtensions());

        if (response.isValid()) {
            QTextStream httpStream(pTcpSocket);
            httpStream << response;
            httpStream.flush();

            if (response.canUpgrade()) {
                QWebSocket *pWebSocket = QWebSocketPrivate::upgradeFrom(pTcpSocket,
                                                                        request,
                                                                        response);
                if (pWebSocket) {
                    addPendingConnection(pWebSocket);
                    Q_EMIT q->newConnection();
                    success = true;
                } else {
                    setError(QWebSocketProtocol::CloseCodeAbnormalDisconnection,
                             QWebSocketServer::tr("Upgrade to WebSocket failed."));
                }
            }
            else {
                setError(response.error(), response.errorString());
            }
        } else {
            setError(QWebSocketProtocol::CloseCodeProtocolError,
                     QWebSocketServer::tr("Invalid response received."));
        }
    }
    if (!success) {
        qWarning() << QWebSocketServer::tr("Closing socket because of invalid or unsupported request.");
        pTcpSocket->close();
    }
}
void EMBLGenbankAbstractDocument::load(const U2DbiRef& dbiRef, IOAdapter* io, QList<GObject*>& objects, QVariantMap& fs, U2OpStatus& os, QString& writeLockReason) {
    DbiOperationsBlock opBlock(dbiRef, os);
    CHECK_OP(os, );
    Q_UNUSED(opBlock);
    writeLockReason.clear();

    //get settings
    int gapSize = qBound(-1, DocumentFormatUtils::getMergeGap(fs), 1000*1000);
    bool merge = gapSize!=-1;

    QScopedPointer<AnnotationTableObject> mergedAnnotations(NULL);
    QStringList contigs;
    QVector<U2Region> mergedMapping;

    // Sequence loading is 'lazy', so, if there is no sequence, it won't be created and there is no need to remove it.
    U2SequenceImporter seqImporter(fs, true);
    const QString folder = fs.value(DBI_FOLDER_HINT, U2ObjectDbi::ROOT_FOLDER).toString();

    QSet<QString> usedNames;

    GObjectReference sequenceRef(GObjectReference(io->getURL().getURLString(), "", GObjectTypes::SEQUENCE));

    QByteArray readBuffer(ParserState::LOCAL_READ_BUFFER_SIZE, '\0');
    ParserState st(isNcbiLikeFormat() ? 12 : 5, io, NULL, os);
    st.buff = readBuffer.data();

    TmpDbiObjects dbiObjects(dbiRef, os);
    int num_sequence = 0;

    qint64 sequenceStart = 0;
    int sequenceSize = 0;
    int fullSequenceSize = 0;
    const int objectsCountLimit = fs.contains(DocumentReadingMode_MaxObjectsInDoc) ? fs[DocumentReadingMode_MaxObjectsInDoc].toInt() : -1;

    for (int i=0; !os.isCoR(); i++, ++num_sequence) {
        if (objectsCountLimit > 0 && objects.size() >= objectsCountLimit) {
            os.setError(EMBLGenbankAbstractDocument::tr("File \"%1\" contains too many sequences to be displayed. "
                "However, you can process these data using instruments from the menu <i>Tools -> NGS data analysis</i> "
                "or pipelines built with Workflow Designer.")
                .arg(io->getURL().getURLString()));
            break;
        }

        //TODO: reference to a local variable??? Such a pointer will become invalid
        EMBLGenbankDataEntry data;
        st.entry = &data;

        if (num_sequence == 0 || merge == false){
            seqImporter.startSequence(dbiRef, folder, "default sequence name", false, os); //change name and circularity after finalize method
            CHECK_OP(os, );
        }

        sequenceSize = 0;
        os.setDescription(tr("Reading entry header"));
        int offset = 0;
        if (merge && num_sequence > 0) {
            offset = gapSize;
        }
        if (!readEntry(&st,seqImporter,sequenceSize,fullSequenceSize,merge,offset, os)) {
            break;
        }

        if (merge && sequenceSize > 0 && num_sequence > 0) {
                sequenceStart = fullSequenceSize - sequenceSize;
                sequenceStart += gapSize;
                fullSequenceSize += gapSize;
        }

        // tolerate blank lines between records
        char ch;
        bool b;
        while ((b = st.io->getChar(&ch)) && (ch == '\n' || ch == '\r')){}
        if (b) {
            st.io->skip(-1);
        }

        AnnotationTableObject *annotationsObject = NULL;

        if (data.hasAnnotationObjectFlag) {
            QString annotationName = genObjectName(usedNames, data.name, data.tags, i+1, GObjectTypes::ANNOTATION_TABLE);

            QVariantMap hints;
            hints.insert(DBI_FOLDER_HINT, fs.value(DBI_FOLDER_HINT, U2ObjectDbi::ROOT_FOLDER));
            if (Q_UNLIKELY(merge && NULL == mergedAnnotations)) {
                mergedAnnotations.reset(new AnnotationTableObject(annotationName, dbiRef, hints));
            }
            annotationsObject = merge ? mergedAnnotations.data() : new AnnotationTableObject(annotationName, dbiRef, hints);

            QStringList groupNames;
            QMap<QString, QList<SharedAnnotationData> > groupName2Annotations;
            for (int i = 0, n = data.features.size(); i < n; ++i) {
                SharedAnnotationData &d = data.features[i];
                if (!d->location->regions.isEmpty()) {
                    for (int i = 0, n = d->location->regions.size(); i < n; ++i) {
                        // for some reason larger numbers cannot be stored within rtree SQLite tables
                        if (d->location->regions[i].endPos() > 9223371036854775807LL) {
                            d->location->regions[i].length = 9223371036854775807LL - d->location->regions[i].startPos;
                        }
                    }
                }
                groupNames.clear();
                d->removeAllQualifiers(GBFeatureUtils::QUALIFIER_GROUP, groupNames);
                if (groupNames.isEmpty()) {
                    groupName2Annotations[""].append(d);
                } else {
                    foreach(const QString &gName, groupNames) {
                        groupName2Annotations[gName].append(d);
                    }
                }
                CHECK_OP(os, );
            }
Example #6
0
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;
}
Example #7
0
bool QDeviceDiscoveryStatic::checkDeviceType(const QString &device)
{
    int fd = QT_OPEN(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
    if (Q_UNLIKELY(fd == -1)) {
        qWarning() << "Device discovery cannot open device" << device;
        return false;
    }

    qCDebug(lcDD) << "doing static device discovery for " << device;

    if ((m_types & Device_DRM) && device.contains(QLatin1String(QT_DRM_DEVICE_PREFIX))) {
        QT_CLOSE(fd);
        return true;
    }

    long bitsAbs[LONG_FIELD_SIZE(ABS_CNT)];
    long bitsKey[LONG_FIELD_SIZE(KEY_CNT)];
    long bitsRel[LONG_FIELD_SIZE(REL_CNT)];
    memset(bitsAbs, 0, sizeof(bitsAbs));
    memset(bitsKey, 0, sizeof(bitsKey));
    memset(bitsRel, 0, sizeof(bitsRel));

    ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(bitsAbs)), bitsAbs);
    ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(bitsKey)), bitsKey);
    ioctl(fd, EVIOCGBIT(EV_REL, sizeof(bitsRel)), bitsRel);

    QT_CLOSE(fd);

    if ((m_types & Device_Keyboard)) {
        if (testBit(KEY_Q, bitsKey)) {
            qCDebug(lcDD) << "Found keyboard at" << device;
            return true;
        }
    }

    if ((m_types & Device_Mouse)) {
        if (testBit(REL_X, bitsRel) && testBit(REL_Y, bitsRel) && testBit(BTN_MOUSE, bitsKey)) {
            qCDebug(lcDD) << "Found mouse at" << device;
            return true;
        }
    }

    if ((m_types & (Device_Touchpad | Device_Touchscreen))) {
        if (testBit(ABS_X, bitsAbs) && testBit(ABS_Y, bitsAbs)) {
            if ((m_types & Device_Touchpad) && testBit(BTN_TOOL_FINGER, bitsKey)) {
                qCDebug(lcDD) << "Found touchpad at" << device;
                return true;
            } else if ((m_types & Device_Touchscreen) && testBit(BTN_TOUCH, bitsKey)) {
                qCDebug(lcDD) << "Found touchscreen at" << device;
                return true;
            } else if ((m_types & Device_Tablet) && (testBit(BTN_STYLUS, bitsKey) || testBit(BTN_TOOL_PEN, bitsKey))) {
                qCDebug(lcDD) << "Found tablet at" << device;
                return true;
            }
        } else if (testBit(ABS_MT_POSITION_X, bitsAbs) &&
                   testBit(ABS_MT_POSITION_Y, bitsAbs)) {
            qCDebug(lcDD) << "Found new-style touchscreen at" << device;
            return true;
        }
    }

    if ((m_types & Device_Joystick)) {
        if (testBit(BTN_A, bitsKey) || testBit(BTN_TRIGGER, bitsKey) || testBit(ABS_RX, bitsAbs)) {
            qCDebug(lcDD) << "Found joystick/gamepad at" << device;
            return true;
        }
    }

    return false;
}
int QEventDispatcherBlackberry::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
                                       timespec *timeout)
{
    Q_UNUSED(nfds);
    Q_D(QEventDispatcherBlackberry);
    const BBScopedLoopLevelCounter bbLoopCounter(d);

    BpsChannelScopeSwitcher channelSwitcher(d->bps_channel);

    // prepare file sets for bps callback
    d->ioData->count = 0;
    d->ioData->readfds = readfds;
    d->ioData->writefds = writefds;
    d->ioData->exceptfds = exceptfds;

    // reset all file sets
    if (readfds)
        FD_ZERO(readfds);

    if (writefds)
        FD_ZERO(writefds);

    if (exceptfds)
        FD_ZERO(exceptfds);

    bps_event_t *event = 0;
    unsigned int eventCount = 0;

    // If an event handler called through filterEvent() starts a nested event loop by creating a
    // new QEventLoop, we will recursively enter this function again.  However, each time
    // bps_get_event() is called, it destroys the last event it handed out before returning the
    // next event.  We don't want it to destroy the event that triggered the nested event loop,
    // since there may still be more handlers that need to get that event, once the nested event
    // loop is done and control returns to the outer event loop.
    //
    // So we move an event to a holding channel, which takes ownership of the event.  Putting
    // the event on our own channel allows us to manage when it is destroyed, keeping it alive
    // until we know we are done with it.  Each recursive call of this function needs to have
    // it's own holding channel, since a channel is a queue, not a stack.
    //
    // However, a recursive call into this function happens very rarely compared to the many
    // times this function is called.  We don't want to create a holding channel for each time
    // this function is called, only when it is called recursively.  Thus we have the instance
    // variable d->holding_channel to use in the common case.  We keep track of recursive calls
    // with d->loop_level.  If we are in a recursive call, then we create a new holding channel
    // for this run.
    int holding_channel = d->holding_channel;
    if ((d->loop_level > 1) &&
        Q_UNLIKELY(bps_channel_create(&holding_channel, 0) != BPS_SUCCESS)) {
        qWarning("QEventDispatcherBlackberry: bps_channel_create failed");
        holding_channel = -1;
    }

    // Convert timeout to milliseconds
    int timeoutTotal = -1;
    if (timeout)
        timeoutTotal = timespecToMillisecs(*timeout);
    int timeoutLeft = timeoutTotal;
    timespec startTime = qt_gettime();

    // This loop exists such that we can drain the bps event queue of all native events
    // more efficiently than if we were to return control to Qt after each event. This
    // is important for handling touch events which can come in rapidly.
    forever {
        // Only emit the awake() and aboutToBlock() signals in the second iteration. For the
        // first iteration, the UNIX event dispatcher will have taken care of that already.
        // Also native events are actually processed one loop iteration after they were
        // retrieved with bps_get_event().

        // Filtering the native event should happen between the awake() and aboutToBlock()
        // signal emissions. The calls awake() - filterNativeEvent() - aboutToBlock() -
        // bps_get_event() need not to be interrupted by a break or return statement.
        if (eventCount > 0) {
            if (event) {
                emit awake();
                filterNativeEvent(QByteArrayLiteral("bps_event_t"), static_cast<void*>(event), 0);
                emit aboutToBlock();

                if (Q_LIKELY(holding_channel != -1)) {
                    // We are now done with this BPS event.  Destroy it.
                    destroyHeldBpsEvent(holding_channel);
                }
            }

            // Update the timeout
            // Clock source is monotonic, so we can recalculate how much timeout is left
            if (timeoutTotal != -1) {
                timespec t2 = qt_gettime();
                timeoutLeft = timeoutTotal
                              - (timespecToMillisecs(t2) - timespecToMillisecs(startTime));
                if (timeoutLeft < 0)
                    timeoutLeft = 0;
            }

            timespec tnext;
            if (d->timerList.timerWait(tnext)) {
                int timeoutNext = timespecToMillisecs(tnext);
                if (timeoutNext < timeoutLeft || timeoutTotal == -1) {
                    timeoutTotal = timeoutLeft = timeoutNext;
                    startTime = qt_gettime();
                }
            }
        }

        event = 0;
        {   // We need to increase loop level in this scope,
            // because bps_get_event can also invoke callbacks
            QScopedLoopLevelCounter loopLevelCounter(d->threadData);

            // Wait for event or file to be ready
            const int result = bps_get_event(&event, timeoutLeft);
            if (Q_UNLIKELY(result != BPS_SUCCESS))
                qWarning("QEventDispatcherBlackberry: bps_get_event failed");
        }

        if (!event)    // In case of !event, we break out of the loop to let Qt process the timers
            break;     // (since timeout has expired) and socket notifiers that are now ready.

        if (bps_event_get_domain(event) == bpsUnblockDomain) {
            timeoutTotal = 0;   // in order to immediately drain the event queue of native events
            event = 0;          // (especially touch move events) we don't break out here
        } else {
            // Move the event to our holding channel so we can manage when it is destroyed.
            if (Q_LIKELY(holding_channel != 1) &&
                Q_UNLIKELY(bps_channel_push_event(holding_channel, event) != BPS_SUCCESS)) {
                qWarning("QEventDispatcherBlackberry: bps_channel_push_event failed");
            }
        }

        ++eventCount;

        // Make sure we are not trapped in this loop due to continuous native events
        // also we cannot recalculate the timeout without a monotonic clock as the time may have changed
        const unsigned int maximumEventCount = 12;
        if (Q_UNLIKELY((eventCount > maximumEventCount && timeoutLeft == 0)
                       || !QElapsedTimer::isMonotonic())) {
            if (event) {
                filterNativeEvent(QByteArrayLiteral("bps_event_t"), static_cast<void*>(event), 0);

                if (Q_LIKELY(holding_channel != -1)) {
                    // We are now done with this BPS event.  Destroy it.
                    destroyHeldBpsEvent(holding_channel);
                }
            }
            break;
        }
    }

    // If this was a recursive call into this function, a new holding channel was created for
    // this run, so destroy it now.
    if ((holding_channel != d->holding_channel) &&
        Q_LIKELY(holding_channel != -1) &&
        Q_UNLIKELY(bps_channel_destroy(holding_channel) != BPS_SUCCESS)) {
        qWarning("QEventDispatcherBlackberry: bps_channel_destroy failed");
    }

    // the number of bits set in the file sets
    return d->ioData->count;
}
bool OsmAnd::QFileDeviceInputStream::Next(const void** data, int* size)
{
    bool ok;

    // If memory was already mapped, unmap it
    if (Q_LIKELY(_mappedMemory != nullptr))
    {
        ok = _file->unmap(_mappedMemory);
        if (!ok)
        {
            LogPrintf(LogSeverityLevel::Warning,
                "Failed to unmap memory %p of '%s' (handle 0x%08x): (%d) %s",
                _mappedMemory,
                qPrintable(file->fileName()),
                file->handle(),
                static_cast<int>(file->error()),
                qPrintable(file->errorString()));
        }
        _mappedMemory = nullptr;
    }

    // Check if current position is in valid range
    if (Q_UNLIKELY(_currentPosition < 0 || _currentPosition >= _fileSize))
    {
        *data = nullptr;
        *size = 0;
        return false;
    }

    // If file is not opened, open it
    if (!_file->isOpen())
    {
        if (_wasInitiallyOpened)
            _file->open(_originalOpenMode);
        else
        {
            _file->open(QIODevice::ReadOnly);
            _closeOnDestruction = true;
        }
    }

    // Map new portion of data
    auto mappedSize = _memoryWindowSize;
    if (_currentPosition + mappedSize >= _fileSize)
        mappedSize = _fileSize - _currentPosition;
    _mappedMemory = _file->map(_currentPosition, mappedSize);

    // Check if memory was mapped successfully
    if (Q_UNLIKELY(!_mappedMemory))
    {
        LogPrintf(LogSeverityLevel::Warning,
            "Failed to map %" PRIu64 " bytes starting at %" PRIi64 " offset from '%s' (handle 0x%08x) into memory: (%d) %s",
            static_cast<uint64_t>(mappedSize),
            _currentPosition,
            qPrintable(file->fileName()),
            file->handle(),
            static_cast<int>(file->error()),
            qPrintable(file->errorString()));

        *data = nullptr;
        *size = 0;
        return false;
    }
    
    _currentPosition += mappedSize;

    *data = _mappedMemory;
    *size = mappedSize;
    return true;
}
void TWebSocketWorker::execute(int opcode, const QByteArray &payload)
{
    bool sendTask = false;
    QString es = TUrlRoute::splitPath(_requestPath).value(0).toLower() + "endpoint";
    TDispatcher<TWebSocketEndpoint> dispatcher(es);
    TWebSocketEndpoint *endpoint = dispatcher.object();

    if (!endpoint) {
        return;
    }

    try {
        tSystemDebug("Found endpoint: %s", qPrintable(es));
        tSystemDebug("TWebSocketWorker opcode: %d", opcode);

        endpoint->sessionStore = _socket->session(); // Sets websocket session
        endpoint->uuid = _socket->socketUuid();
        // Database Transaction
        setTransactionEnabled(endpoint->transactionEnabled());

        switch (_mode) {
        case Opening: {
            bool res = endpoint->onOpen(_httpSession);
            if (res) {
                // For switch response
                endpoint->taskList.prepend(qMakePair((int)TWebSocketEndpoint::OpenSuccess, QVariant()));

                if (endpoint->keepAliveInterval() > 0) {
                    endpoint->startKeepAlive(endpoint->keepAliveInterval());
                }
            } else {
                endpoint->taskList.prepend(qMakePair((int)TWebSocketEndpoint::OpenError, QVariant()));
            }
            break; }

        case Closing:
            if (!_socket->closing.exchange(true)) {
                endpoint->onClose(Tf::GoingAway);
                endpoint->unsubscribeFromAll();
            }
            break;

        case Receiving: {

            switch (opcode) {
            case TWebSocketFrame::TextFrame:
                endpoint->onTextReceived(QString::fromUtf8(payload));
                break;

            case TWebSocketFrame::BinaryFrame:
                endpoint->onBinaryReceived(payload);
                break;

            case TWebSocketFrame::Close: {
                quint16 closeCode = Tf::GoingAway;
                if (payload.length() >= 2) {
                    QDataStream ds(payload);
                    ds.setByteOrder(QDataStream::BigEndian);
                    ds >> closeCode;
                }

                if (!_socket->closing.exchange(true)) {
                    endpoint->onClose(closeCode);
                    endpoint->unsubscribeFromAll();
                }
                endpoint->close(closeCode);  // close response or disconnect
                break; }

            case TWebSocketFrame::Ping:
                endpoint->onPing(payload);
                break;

            case TWebSocketFrame::Pong:
                endpoint->onPong(payload);
                break;

            default:
                tSystemWarn("Invalid opcode: 0x%x  [%s:%d]", (int)opcode, __FILE__, __LINE__);
                break;
            }
            break; }

        default:
            break;
        }

        // Sets session to the websocket
        _socket->setSession(endpoint->session());

        for (auto &p : endpoint->taskList) {
            const QVariant &taskData = p.second;

            switch (p.first) {
            case TWebSocketEndpoint::OpenSuccess:
                _socket->sendHandshakeResponse();
                break;

            case TWebSocketEndpoint::OpenError:
                _socket->closing = true;
                _socket->closeSent = true;
                _socket->disconnect();
                goto open_error;
                break;

            case TWebSocketEndpoint::SendText:
                _socket->sendText(taskData.toString());
                sendTask = true;
                break;

            case TWebSocketEndpoint::SendBinary:
                _socket->sendBinary(taskData.toByteArray());
                sendTask = true;
                break;

            case TWebSocketEndpoint::SendClose:
                if (_socket->closing.load() && _socket->closeSent.load()) {
                    // close-frame sent and received
                    _socket->disconnect();
                } else {
                    uint closeCode = taskData.toUInt();
                    _socket->sendClose(closeCode);
                    sendTask = true;
                }
                break;

            case TWebSocketEndpoint::SendPing:
                _socket->sendPing(taskData.toByteArray());
                sendTask = true;
                break;

            case TWebSocketEndpoint::SendPong:
                _socket->sendPong(taskData.toByteArray());
                sendTask = true;
                break;

            case TWebSocketEndpoint::SendTextTo: {
                QVariantList lst = taskData.toList();
                TAbstractWebSocket *websocket = _socket->searchPeerSocket(lst[0].toByteArray());
                if (websocket) {
                    websocket->sendText(lst[1].toString());
                }
                break; }

            case TWebSocketEndpoint::SendBinaryTo: {
                QVariantList lst = taskData.toList();
                TAbstractWebSocket *websocket = _socket->searchPeerSocket(lst[0].toByteArray());
                if (websocket) {
                    websocket->sendBinary(lst[1].toByteArray());
                }
                break; }

            case TWebSocketEndpoint::SendCloseTo: {
                QVariantList lst = taskData.toList();
                TAbstractWebSocket *websocket = _socket->searchPeerSocket(lst[0].toByteArray());
                if (websocket) {
                    websocket->sendClose(lst[1].toInt());
                }
                break; }

            case TWebSocketEndpoint::Subscribe: {
                QVariantList lst = taskData.toList();
                TPublisher::instance()->subscribe(lst[0].toString(), lst[1].toBool(), _socket);
                break; }

            case TWebSocketEndpoint::Unsubscribe:
                TPublisher::instance()->unsubscribe(taskData.toString(), _socket);
                break;

            case TWebSocketEndpoint::UnsubscribeFromAll:
                TPublisher::instance()->unsubscribeFromAll(_socket);
                break;

            case TWebSocketEndpoint::PublishText: {
                QVariantList lst = taskData.toList();
                TPublisher::instance()->publish(lst[0].toString(), lst[1].toString(), _socket);
                break; }

            case TWebSocketEndpoint::PublishBinary: {
                QVariantList lst = taskData.toList();
                TPublisher::instance()->publish(lst[0].toString(), lst[1].toByteArray(), _socket);
                break; }

            case TWebSocketEndpoint::StartKeepAlive:
                _socket->startKeepAlive(taskData.toInt());
                break;

            case TWebSocketEndpoint::StopKeepAlive:
                _socket->stopKeepAlive();
                break;

            default:
                tSystemError("Invalid logic  [%s:%d]",  __FILE__, __LINE__);
                break;
            }
        }

        if (!sendTask) {
            // Receiving but not sending, so renew keep-alive
            _socket->renewKeepAlive();
        }

    open_error:
        // transaction
        if (Q_UNLIKELY(endpoint->rollbackRequested())) {
            rollbackTransactions();
        } else {
            // Commits a transaction to the database
            commitTransactions();
        }

    } catch (ClientErrorException &e) {
Example #11
0
void THttpSocket::readRequest()
{
    T_TRACEFUNC("");
    uint limitBodyBytes = Tf::appSettings()->value(Tf::LimitRequestBody, "0").toUInt();
    qint64 bytes = 0;
    QByteArray buf;

    while ((bytes = bytesAvailable()) > 0) {
        buf.resize(bytes);
        int rd = QTcpSocket::read(buf.data(), bytes);
        if (Q_UNLIKELY(rd != bytes)) {
            tSystemError("socket read error");
            buf.resize(0);
            break;
        }
        idleElapsed = std::time(nullptr);

        if (lengthToRead > 0) {
            // Writes to buffer
            if (fileBuffer.isOpen()) {
                if (fileBuffer.write(buf.data(), bytes) < 0) {
                    throw RuntimeException(QLatin1String("write error: ") + fileBuffer.fileName(), __FILE__, __LINE__);
                }
            } else {
                readBuffer.append(buf.data(), bytes);
            }
            lengthToRead = qMax(lengthToRead - bytes, 0LL);

        } else if (lengthToRead < 0) {
            readBuffer.append(buf);
            int idx = readBuffer.indexOf("\r\n\r\n");
            if (idx > 0) {
                THttpRequestHeader header(readBuffer);
                tSystemDebug("content-length: %d", header.contentLength());

                if (Q_UNLIKELY(limitBodyBytes > 0 && header.contentLength() > limitBodyBytes)) {
                    throw ClientErrorException(413);  // Request Entity Too Large
                }

                lengthToRead = qMax(idx + 4 + (qint64)header.contentLength() - readBuffer.length(), 0LL);

                if (header.contentType().trimmed().startsWith("multipart/form-data")
                        || header.contentLength() > READ_THRESHOLD_LENGTH) {
                    // Writes to file buffer
                    if (Q_UNLIKELY(!fileBuffer.open())) {
                        throw RuntimeException(QLatin1String("temporary file open error: ") + fileBuffer.fileTemplate(), __FILE__, __LINE__);
                    }
                    if (readBuffer.length() > idx + 4) {
                        tSystemDebug("fileBuffer name: %s", qPrintable(fileBuffer.fileName()));
                        if (fileBuffer.write(readBuffer.data() + idx + 4, readBuffer.length() - (idx + 4)) < 0) {
                            throw RuntimeException(QLatin1String("write error: ") + fileBuffer.fileName(), __FILE__, __LINE__);
                        }
                    }
                }
            }
        } else {
            // do nothing
            break;
        }

        if (lengthToRead == 0) {
            emit newRequest();
        }
    }
}
/*!
    \internal
 */
QString QWebSocketHandshakeResponse::getHandshakeResponse(
        const QWebSocketHandshakeRequest &request,
        const QString &serverName,
        bool isOriginAllowed,
        const QList<QWebSocketProtocol::Version> &supportedVersions,
        const QList<QString> &supportedProtocols,
        const QList<QString> &supportedExtensions)
{
    QStringList response;
    m_canUpgrade = false;

    if (!isOriginAllowed) {
        if (!m_canUpgrade) {
            m_error = QWebSocketProtocol::CloseCodePolicyViolated;
            m_errorString = tr("Access forbidden.");
            response << QStringLiteral("HTTP/1.1 403 Access Forbidden");
        }
    } else {
        if (request.isValid()) {
            const QString acceptKey = calculateAcceptKey(request.key());
            const QList<QString> matchingProtocols =
                    supportedProtocols.toSet().intersect(request.protocols().toSet()).toList();
            //TODO: extensions must be kept in the order in which they arrive
            //cannot use set.intersect() to get the supported extensions
            const QList<QString> matchingExtensions =
                    supportedExtensions.toSet().intersect(request.extensions().toSet()).toList();
            QList<QWebSocketProtocol::Version> matchingVersions =
                    request.versions().toSet().intersect(supportedVersions.toSet()).toList();
            std::sort(matchingVersions.begin(), matchingVersions.end(),
                      std::greater<QWebSocketProtocol::Version>());    //sort in descending order

            if (Q_UNLIKELY(matchingVersions.isEmpty())) {
                m_error = QWebSocketProtocol::CloseCodeProtocolError;
                m_errorString = tr("Unsupported version requested.");
                m_canUpgrade = false;
            } else {
                response << QStringLiteral("HTTP/1.1 101 Switching Protocols") <<
                            QStringLiteral("Upgrade: websocket") <<
                            QStringLiteral("Connection: Upgrade") <<
                            QStringLiteral("Sec-WebSocket-Accept: ") % acceptKey;
                if (!matchingProtocols.isEmpty()) {
                    m_acceptedProtocol = matchingProtocols.first();
                    response << QStringLiteral("Sec-WebSocket-Protocol: ") % m_acceptedProtocol;
                }
                if (!matchingExtensions.isEmpty()) {
                    m_acceptedExtension = matchingExtensions.first();
                    response << QStringLiteral("Sec-WebSocket-Extensions: ") % m_acceptedExtension;
                }
                QString origin = request.origin().trimmed();
                if (origin.contains(QStringLiteral("\r\n")) ||
                        serverName.contains(QStringLiteral("\r\n"))) {
                    m_error = QWebSocketProtocol::CloseCodeAbnormalDisconnection;
                    m_errorString = tr("One of the headers contains a newline. " \
                                       "Possible attack detected.");
                    m_canUpgrade = false;
                } else {
                    if (origin.isEmpty())
                        origin = QStringLiteral("*");
                    response << QStringLiteral("Server: ") % serverName                      <<
                                QStringLiteral("Access-Control-Allow-Credentials: false")    <<
                                QStringLiteral("Access-Control-Allow-Methods: GET")          <<
                                QStringLiteral("Access-Control-Allow-Headers: content-type") <<
                                QStringLiteral("Access-Control-Allow-Origin: ") % origin     <<
                                QStringLiteral("Date: ") %
                                    QDateTime::currentDateTimeUtc()
                                        .toString(QStringLiteral("ddd, dd MMM yyyy hh:mm:ss 'GMT'"));

                    m_acceptedVersion = QWebSocketProtocol::currentVersion();
                    m_canUpgrade = true;
                }
            }
        } else {
            m_error = QWebSocketProtocol::CloseCodeProtocolError;
            m_errorString = tr("Bad handshake request received.");
            m_canUpgrade = false;
        }
        if (Q_UNLIKELY(!m_canUpgrade)) {
            response << QStringLiteral("HTTP/1.1 400 Bad Request");
            QStringList versions;
            Q_FOREACH (const QWebSocketProtocol::Version &version, supportedVersions)
                versions << QString::number(static_cast<int>(version));
            response << QStringLiteral("Sec-WebSocket-Version: ")
                                % versions.join(QStringLiteral(", "));
        }
    }
Example #13
0
void BlinkParser::parseXml()
{
    while (!m_reader->atEnd()) {
        switch(m_reader->readNext()) {
        case QXmlStreamReader::StartElement:
            if (m_reader->name().endsWith(QStringLiteral("db_id"))) {
                state = State::ID;
            } else if (m_reader->name() == QStringLiteral("series_image")) {
                state = State::ImgLink;
            } else if (m_reader->name() == QStringLiteral("myinfo")) {
                m_atUserInfo = true;
            } else if (m_atUserInfo) {
                // here we rip off the total progress that we need
                if (m_reader->name() == QStringLiteral("user_watching")
                        || m_reader->name() == QStringLiteral("user_reading")
                        || m_reader->name() == QStringLiteral("user_completed")
                        || m_reader->name() == QStringLiteral("user_onhold")
                        || m_reader->name() == QStringLiteral("user_dropped")
                        || m_reader->name() == QStringLiteral("user_plantowatch")
                        || m_reader->name() == QStringLiteral("user_plantoread")) {
                    m_total += m_reader->readElementText().toInt();
                }
            } else if (m_reader->name() == "error") {
                emit writingError(m_reader->readElementText());
                return;
            }
            break;
        case QXmlStreamReader::Characters:
            if (state == State::ID) {
                m_currentId += m_reader->text();
            } else if (state == State::ImgLink) {
                m_currentImgLink += m_reader->text();
            }
        case QXmlStreamReader::EndElement:
            if (m_reader->name().endsWith(QStringLiteral("db_id"))
                || m_reader->name() == QStringLiteral("series_image")) {
                state = State::Nothing;
            }
            if (m_reader->name() == QStringLiteral("anime")
                || m_reader->name() == QStringLiteral("manga")) {
                emit write(m_currentId, m_currentImgLink);
                emit currentProgress(++m_current);
                m_currentId.clear();
                m_currentImgLink.clear();
            }
            if (m_reader->name() == QStringLiteral("myinfo")) {
                m_atUserInfo = false;
                emit totalCount(m_total);
            }
            break;
        case QXmlStreamReader::EndDocument:
            m_reply->deleteLater();
            m_reply = nullptr;
            emit writingFinished();
        default:
            break;
        }
    }
    if (Q_UNLIKELY(m_reader->hasError()
                   && m_reader->error()
                    != QXmlStreamReader::PrematureEndOfDocumentError)) {
        emit writingError(m_reader->errorString());
        m_reply->abort();
        m_reply->deleteLater();
        m_reply = nullptr;
    }
}
void EventDispatcherEPollPrivate::registerSocketNotifier(QSocketNotifier* notifier)
{
	Q_ASSERT(notifier != 0);
	Q_ASSUME(notifier != 0);

	int events = 0;
	QSocketNotifier** n = 0;
	int fd = static_cast<int>(notifier->socket());

	epoll_event e;
	e.data.fd = fd;

	HandleData* data;
	HandleHash::Iterator it = this->m_handles.find(fd);

	if (it == this->m_handles.end()) {
		data        = new HandleData;
		data->type  = htSocketNotifier;
		data->sni.r = 0;
		data->sni.w = 0;
		data->sni.x = 0;

		switch (notifier->type()) {
			case QSocketNotifier::Read:      events = EPOLLIN;  n = &data->sni.r; break;
			case QSocketNotifier::Write:     events = EPOLLOUT; n = &data->sni.w; break;
			case QSocketNotifier::Exception: events = EPOLLPRI; n = &data->sni.x; break;
			default:
				Q_UNREACHABLE();
		}

		data->sni.events = events;
		e.events         = events;
		*n               = notifier;

		int res = epoll_ctl(this->m_epoll_fd, EPOLL_CTL_ADD, fd, &e);
		if (Q_UNLIKELY(res != 0)) {
			qErrnoWarning("%s: epoll_ctl() failed", Q_FUNC_INFO);
			delete data;
			return;
		}

		this->m_handles.insert(fd, data);
	}
	else {
		data = it.value();

		Q_ASSERT(data->type == htSocketNotifier);
		if (data->type == htSocketNotifier) {
			switch (notifier->type()) {
				case QSocketNotifier::Read:      events = EPOLLIN;  n = &data->sni.r; break;
				case QSocketNotifier::Write:     events = EPOLLOUT; n = &data->sni.w; break;
				case QSocketNotifier::Exception: events = EPOLLPRI; n = &data->sni.x; break;
				default:
					Q_UNREACHABLE();
			}

			Q_ASSERT(n != 0);
			if (Q_UNLIKELY(*n != 0)) {
				qWarning("%s: cannot add two socket notifiers of the same type for the same descriptor", Q_FUNC_INFO);
				return;
			}

			Q_ASSERT((data->sni.events & events) == 0);

			data->sni.events |= events;
			e.events          = data->sni.events;
			*n                = notifier;

			int res = epoll_ctl(this->m_epoll_fd, EPOLL_CTL_MOD, fd, &e);
			if (Q_UNLIKELY(res != 0)) {
				qErrnoWarning("%s: epoll_ctl() failed", Q_FUNC_INFO);
				return;
			}
		}
		else {
			Q_UNREACHABLE();
		}
	}

	Q_ASSERT(!this->m_notifiers.contains(notifier));
	this->m_notifiers.insert(notifier, data);
}
/*!
    \internal
 */
void QWebSocketPrivate::open(const QUrl &url, bool mask)
{
    //just delete the old socket for the moment;
    //later, we can add more 'intelligent' handling by looking at the URL
    //m_pSocket.reset();
    Q_Q(QWebSocket);
    if (!url.isValid() || url.toString().contains(QStringLiteral("\r\n"))) {
        setErrorString(QWebSocket::tr("Invalid URL."));
        Q_EMIT q->error(QAbstractSocket::ConnectionRefusedError);
        return;
    }
    QTcpSocket *pTcpSocket = m_pSocket.take();
    if (pTcpSocket) {
        releaseConnections(pTcpSocket);
        pTcpSocket->deleteLater();
    }
    //if (m_url != url)
    if (Q_LIKELY(!m_pSocket)) {
        m_dataProcessor.clear();
        m_isClosingHandshakeReceived = false;
        m_isClosingHandshakeSent = false;

        setRequestUrl(url);
        QString resourceName = url.path(QUrl::FullyEncoded);
        // Check for encoded \r\n
        if (resourceName.contains(QStringLiteral("%0D%0A"))) {
            setRequestUrl(QUrl());  //clear requestUrl
            setErrorString(QWebSocket::tr("Invalid resource name."));
            Q_EMIT q->error(QAbstractSocket::ConnectionRefusedError);
            return;
        }
        if (!url.query().isEmpty()) {
            if (!resourceName.endsWith(QChar::fromLatin1('?'))) {
                resourceName.append(QChar::fromLatin1('?'));
            }
            resourceName.append(url.query(QUrl::FullyEncoded));
        }
        if (resourceName.isEmpty())
            resourceName = QStringLiteral("/");
        setResourceName(resourceName);
        enableMasking(mask);

    #ifndef QT_NO_SSL
        if (url.scheme() == QStringLiteral("wss")) {
            if (!QSslSocket::supportsSsl()) {
                const QString message =
                        QWebSocket::tr("SSL Sockets are not supported on this platform.");
                setErrorString(message);
                Q_EMIT q->error(QAbstractSocket::UnsupportedSocketOperationError);
            } else {
                QSslSocket *sslSocket = new QSslSocket;
                m_pSocket.reset(sslSocket);
                if (Q_LIKELY(m_pSocket)) {
                    m_pSocket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
                    m_pSocket->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
                    m_pSocket->setReadBufferSize(m_readBufferSize);
                    m_pSocket->setPauseMode(m_pauseMode);

                    makeConnections(m_pSocket.data());
                    setSocketState(QAbstractSocket::ConnectingState);

                    sslSocket->setSslConfiguration(m_configuration.m_sslConfiguration);
                    if (Q_UNLIKELY(m_configuration.m_ignoreSslErrors))
                        sslSocket->ignoreSslErrors();
                    else
                        sslSocket->ignoreSslErrors(m_configuration.m_ignoredSslErrors);
    #ifndef QT_NO_NETWORKPROXY
                    sslSocket->setProxy(m_configuration.m_proxy);
    #endif
                    sslSocket->connectToHostEncrypted(url.host(), url.port(443));
                } else {
                    const QString message = QWebSocket::tr("Out of memory.");
                    setErrorString(message);
                    Q_EMIT q->error(QAbstractSocket::SocketResourceError);
                }
            }
        } else
    #endif
        if (url.scheme() == QStringLiteral("ws")) {
            m_pSocket.reset(new QTcpSocket);
            if (Q_LIKELY(m_pSocket)) {
                m_pSocket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
                m_pSocket->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
                m_pSocket->setReadBufferSize(m_readBufferSize);
                m_pSocket->setPauseMode(m_pauseMode);

                makeConnections(m_pSocket.data());
                setSocketState(QAbstractSocket::ConnectingState);
    #ifndef QT_NO_NETWORKPROXY
                m_pSocket->setProxy(m_configuration.m_proxy);
    #endif
                m_pSocket->connectToHost(url.host(), url.port(80));
            } else {
                const QString message = QWebSocket::tr("Out of memory.");
                setErrorString(message);
                Q_EMIT q->error(QAbstractSocket::SocketResourceError);
            }
        } else {
            const QString message =
                    QWebSocket::tr("Unsupported WebSocket scheme: %1").arg(url.scheme());
            setErrorString(message);
            Q_EMIT q->error(QAbstractSocket::UnsupportedSocketOperationError);
        }
    }
}
Example #16
0
/*!
    \internal
 */
QWebSocketFrame QWebSocketFrame::readFrame(QIODevice *pIoDevice)
{
    bool isDone = false;
    qint64 bytesRead = 0;
    QWebSocketFrame frame;
    quint64 dataWaitSize = 0;
    Q_UNUSED(dataWaitSize); // value is used in MACRO, Q_UNUSED to avoid compiler warnings
    ProcessingState processingState = PS_READ_HEADER;
    ProcessingState returnState = PS_READ_HEADER;
    bool hasMask = false;
    quint64 payloadLength = 0;

    while (!isDone)
    {
        switch (processingState) {
        case PS_WAIT_FOR_MORE_DATA:
            //TODO: waitForReadyRead should really be changed
            //now, when a websocket is used in a GUI thread
            //the GUI will hang for at most 5 seconds
            //maybe, a QStateMachine should be used
            if (!pIoDevice->waitForReadyRead(5000)) {
                frame.setError(QWebSocketProtocol::CC_GOING_AWAY,
                               QString("Timeout when reading data from socket."));
                processingState = PS_DISPATCH_RESULT;
            } else {
                processingState = returnState;
            }
            break;

        case PS_READ_HEADER:
            if (Q_LIKELY(pIoDevice->bytesAvailable() >= 2)) {
                //FIN, RSV1-3, Opcode
                char header[2] = {0};
                bytesRead = pIoDevice->read(header, 2);
                frame.m_isFinalFrame = (header[0] & 0x80) != 0;
                frame.m_rsv1 = (header[0] & 0x40);
                frame.m_rsv2 = (header[0] & 0x20);
                frame.m_rsv3 = (header[0] & 0x10);
                frame.m_opCode = static_cast<QWebSocketProtocol::OpCode>(header[0] & 0x0F);

                //Mask, PayloadLength
                hasMask = (header[1] & 0x80) != 0;
                frame.m_length = (header[1] & 0x7F);

                switch (frame.m_length)
                {
                    case 126:
                    {
                        processingState = PS_READ_PAYLOAD_LENGTH;
                        break;
                    }
                    case 127:
                    {
                        processingState = PS_READ_BIG_PAYLOAD_LENGTH;
                        break;
                    }
                    default:
                    {
                        payloadLength = frame.m_length;
                        processingState = hasMask ? PS_READ_MASK : PS_READ_PAYLOAD;
                        break;
                    }
                }
                if (!frame.checkValidity())
                    processingState = PS_DISPATCH_RESULT;
            } else {
                WAIT_FOR_MORE_DATA(2);
            }
            break;

        case PS_READ_PAYLOAD_LENGTH:
            if (Q_LIKELY(pIoDevice->bytesAvailable() >= 2)) {
                uchar length[2] = {0};
                bytesRead = pIoDevice->read(reinterpret_cast<char *>(length), 2);
                if (Q_UNLIKELY(bytesRead == -1)) {
                    frame.setError(QWebSocketProtocol::CC_GOING_AWAY,
                                   QString("Error occurred while reading from the network: %1")
                                        .arg(pIoDevice->errorString()));
                    processingState = PS_DISPATCH_RESULT;
                } else {
                    payloadLength = qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(length));
                    if (Q_UNLIKELY(payloadLength < 126)) {
                        //see http://tools.ietf.org/html/rfc6455#page-28 paragraph 5.2
                        //"in all cases, the minimal number of bytes MUST be used to encode
                        //the length, for example, the length of a 124-byte-long string
                        //can't be encoded as the sequence 126, 0, 124"
                        frame.setError(QWebSocketProtocol::CC_PROTOCOL_ERROR,
                                       QString("Lengths smaller than 126 " \
                                                   "must be expressed as one byte."));
                        processingState = PS_DISPATCH_RESULT;
                    } else {
                        processingState = hasMask ? PS_READ_MASK : PS_READ_PAYLOAD;
                    }
                }
            } else {
                WAIT_FOR_MORE_DATA(2);
            }
            break;

        case PS_READ_BIG_PAYLOAD_LENGTH:
            if (Q_LIKELY(pIoDevice->bytesAvailable() >= 8)) {
                uchar length[8] = {0};
                bytesRead = pIoDevice->read(reinterpret_cast<char *>(length), 8);
                if (Q_UNLIKELY(bytesRead < 8)) {
                    frame.setError(QWebSocketProtocol::CC_ABNORMAL_DISCONNECTION,
                                   QString("Something went wrong during "\
                                               "reading from the network."));
                    processingState = PS_DISPATCH_RESULT;
                } else {
                    //Most significant bit must be set to 0 as
                    //per http://tools.ietf.org/html/rfc6455#section-5.2
                    payloadLength = qFromBigEndian<quint64>(length);
                    if (Q_UNLIKELY(payloadLength & (quint64(1) << 63))) {
                        frame.setError(QWebSocketProtocol::CC_PROTOCOL_ERROR,
                                       QString("Highest bit of payload length is not 0."));
                        processingState = PS_DISPATCH_RESULT;
                    } else if (Q_UNLIKELY(payloadLength <= 0xFFFFu)) {
                        //see http://tools.ietf.org/html/rfc6455#page-28 paragraph 5.2
                        //"in all cases, the minimal number of bytes MUST be used to encode
                        //the length, for example, the length of a 124-byte-long string
                        //can't be encoded as the sequence 126, 0, 124"
                        frame.setError(QWebSocketProtocol::CC_PROTOCOL_ERROR,
                                       QString("Lengths smaller than 65536 (2^16) " \
                                                   "must be expressed as 2 bytes."));
                        processingState = PS_DISPATCH_RESULT;
                    } else {
                        processingState = hasMask ? PS_READ_MASK : PS_READ_PAYLOAD;
                    }
                }
            } else {
                WAIT_FOR_MORE_DATA(8);
            }

            break;

        case PS_READ_MASK:
            if (Q_LIKELY(pIoDevice->bytesAvailable() >= 4)) {
                bytesRead = pIoDevice->read(reinterpret_cast<char *>(&frame.m_mask),
                                            sizeof(frame.m_mask));
                if (bytesRead == -1) {
                    frame.setError(QWebSocketProtocol::CC_GOING_AWAY,
                                   QString("Error while reading from the network: %1.")
                                        .arg(pIoDevice->errorString()));
                    processingState = PS_DISPATCH_RESULT;
                } else {
                    frame.m_mask = qFromBigEndian(frame.m_mask);
                    processingState = PS_READ_PAYLOAD;
                }
            } else {
                WAIT_FOR_MORE_DATA(4);
            }
            break;

        case PS_READ_PAYLOAD:
            if (!payloadLength) {
                processingState = PS_DISPATCH_RESULT;
            } else if (Q_UNLIKELY(payloadLength > MAX_FRAME_SIZE_IN_BYTES)) {
                frame.setError(QWebSocketProtocol::CC_TOO_MUCH_DATA,
                               QString("Maximum framesize exceeded."));
                processingState = PS_DISPATCH_RESULT;
            } else {
                quint64 bytesAvailable = quint64(pIoDevice->bytesAvailable());
                if (bytesAvailable >= payloadLength) {
                    frame.m_payload = pIoDevice->read(payloadLength);
                    //payloadLength can be safely cast to an integer,
                    //because MAX_FRAME_SIZE_IN_BYTES = MAX_INT
                    if (Q_UNLIKELY(frame.m_payload.length() != int(payloadLength))) {
                        //some error occurred; refer to the Qt documentation of QIODevice::read()
                        frame.setError(QWebSocketProtocol::CC_ABNORMAL_DISCONNECTION,
                                       QString("Some serious error occurred " \
                                                   "while reading from the network."));
                        processingState = PS_DISPATCH_RESULT;
                    } else {
                        if (hasMask)
                            QWebSocketProtocol::mask(&frame.m_payload, frame.m_mask);
                        processingState = PS_DISPATCH_RESULT;
                    }
                } else {
                    //if payload is too big, then this will timeout
                    WAIT_FOR_MORE_DATA(payloadLength);
                }
            }
            break;

        case PS_DISPATCH_RESULT:
            processingState = PS_READ_HEADER;
            isDone = true;
            break;

        default:
            //should not come here
            qWarning() << "DataProcessor::process: Found invalid state. This should not happen!";
            frame.clear();
            isDone = true;
            break;
        }	//end switch
    }

    return frame;
}
/*!
 * \internal
 */
qint64 QWebSocketPrivate::doWriteFrames(const QByteArray &data, bool isBinary)
{
    qint64 payloadWritten = 0;
    if (Q_UNLIKELY(!m_pSocket) || (state() != QAbstractSocket::ConnectedState))
        return payloadWritten;

    Q_Q(QWebSocket);
    const QWebSocketProtocol::OpCode firstOpCode = isBinary ?
                QWebSocketProtocol::OpCodeBinary : QWebSocketProtocol::OpCodeText;

    int numFrames = data.size() / FRAME_SIZE_IN_BYTES;
    QByteArray tmpData(data);
    tmpData.detach();
    char *payload = tmpData.data();
    quint64 sizeLeft = quint64(data.size()) % FRAME_SIZE_IN_BYTES;
    if (Q_LIKELY(sizeLeft))
        ++numFrames;

    //catch the case where the payload is zero bytes;
    //in this case, we still need to send a frame
    if (Q_UNLIKELY(numFrames == 0))
        numFrames = 1;
    quint64 currentPosition = 0;
    qint64 bytesWritten = 0;
    quint64 bytesLeft = data.size();

    for (int i = 0; i < numFrames; ++i) {
        quint32 maskingKey = 0;
        if (m_mustMask)
            maskingKey = generateMaskingKey();

        const bool isLastFrame = (i == (numFrames - 1));
        const bool isFirstFrame = (i == 0);

        const quint64 size = qMin(bytesLeft, FRAME_SIZE_IN_BYTES);
        const QWebSocketProtocol::OpCode opcode = isFirstFrame ? firstOpCode
                                                               : QWebSocketProtocol::OpCodeContinue;

        //write header
        bytesWritten += m_pSocket->write(getFrameHeader(opcode, size, maskingKey, isLastFrame));

        //write payload
        if (Q_LIKELY(size > 0)) {
            char *currentData = payload + currentPosition;
            if (m_mustMask)
                QWebSocketProtocol::mask(currentData, size, maskingKey);
            qint64 written = m_pSocket->write(currentData, static_cast<qint64>(size));
            if (Q_LIKELY(written > 0)) {
                bytesWritten += written;
                payloadWritten += written;
            } else {
                m_pSocket->flush();
                setErrorString(QWebSocket::tr("Error writing bytes to socket: %1.")
                               .arg(m_pSocket->errorString()));
                Q_EMIT q->error(QAbstractSocket::NetworkError);
                break;
            }
        }
        currentPosition += size;
        bytesLeft -= size;
    }
    if (Q_UNLIKELY(payloadWritten != data.size())) {
        setErrorString(QWebSocket::tr("Bytes written %1 != %2.")
                       .arg(payloadWritten).arg(data.size()));
        Q_EMIT q->error(QAbstractSocket::NetworkError);
    }
    return payloadWritten;
}
/*!
    \internal
 */
void QWebSocketHandshakeRequest::readHandshake(QTextStream &textStream)
{
    m_isValid = false;
    clear();
    if (Q_UNLIKELY(textStream.status() != QTextStream::Ok))
        return;
    const QString requestLine = textStream.readLine();
    const QStringList tokens = requestLine.split(' ', QString::SkipEmptyParts);
    if (Q_UNLIKELY(tokens.length() < 3)) {
        m_isValid = false;
        clear();
        return;
    }
    const QString verb(tokens.at(0));
    const QString resourceName(tokens.at(1));
    const QString httpProtocol(tokens.at(2));
    bool conversionOk = false;
    const float httpVersion = httpProtocol.midRef(5).toFloat(&conversionOk);

    if (Q_UNLIKELY(!conversionOk)) {
        clear();
        m_isValid = false;
        return;
    }
    QString headerLine = textStream.readLine();
    m_headers.clear();
    while (!headerLine.isEmpty()) {
        const QStringList headerField = headerLine.split(QStringLiteral(": "),
                                                         QString::SkipEmptyParts);
        if (Q_UNLIKELY(headerField.length() < 2)) {
            clear();
            return;
        }
        m_headers.insertMulti(headerField.at(0).toLower(), headerField.at(1));
        headerLine = textStream.readLine();
    }

    const QString host = m_headers.value(QStringLiteral("host"), QString());
    m_requestUrl = QUrl::fromEncoded(resourceName.toLatin1());
    if (m_requestUrl.isRelative())
        m_requestUrl.setHost(host);
    if (m_requestUrl.scheme().isEmpty()) {
        const QString scheme =  isSecure() ? QStringLiteral("wss") : QStringLiteral("ws");
        m_requestUrl.setScheme(scheme);
    }

    const QStringList versionLines = m_headers.values(QStringLiteral("sec-websocket-version"));
    for (QStringList::const_iterator v = versionLines.begin(); v != versionLines.end(); ++v) {
        const QStringList versions = (*v).split(QStringLiteral(","), QString::SkipEmptyParts);
        for (QStringList::const_iterator i = versions.begin(); i != versions.end(); ++i) {
            bool ok = false;
            (void)(*i).toUInt(&ok);
            if (!ok) {
                clear();
                return;
            }
            const QWebSocketProtocol::Version ver =
                    QWebSocketProtocol::versionFromString((*i).trimmed());
            m_versions << ver;
        }
    }
    //sort in descending order
    std::sort(m_versions.begin(), m_versions.end(), std::greater<QWebSocketProtocol::Version>());
    m_key = m_headers.value(QStringLiteral("sec-websocket-key"), QString());
    //must contain "Upgrade", case-insensitive
    const QString upgrade = m_headers.value(QStringLiteral("upgrade"), QString());
    //must be equal to "websocket", case-insensitive
    const QString connection = m_headers.value(QStringLiteral("connection"), QString());
    const QStringList connectionLine = connection.split(QStringLiteral(","),
                                                        QString::SkipEmptyParts);
    QStringList connectionValues;
    for (QStringList::const_iterator c = connectionLine.begin(); c != connectionLine.end(); ++c)
        connectionValues << (*c).trimmed();

    //optional headers
    m_origin = m_headers.value(QStringLiteral("sec-websocket-origin"), QString());
    const QStringList protocolLines = m_headers.values(QStringLiteral("sec-websocket-protocol"));
    for (QStringList::const_iterator pl = protocolLines.begin(); pl != protocolLines.end(); ++pl) {
        QStringList protocols = (*pl).split(QStringLiteral(","), QString::SkipEmptyParts);
        for (QStringList::const_iterator p = protocols.begin(); p != protocols.end(); ++p)
            m_protocols << (*p).trimmed();
    }
    const QStringList extensionLines = m_headers.values(QStringLiteral("sec-websocket-extensions"));
    for (QStringList::const_iterator el = extensionLines.begin();
         el != extensionLines.end(); ++el) {
        QStringList extensions = (*el).split(QStringLiteral(","), QString::SkipEmptyParts);
        for (QStringList::const_iterator e = extensions.begin(); e != extensions.end(); ++e)
            m_extensions << (*e).trimmed();
    }

    //TODO: authentication field

    m_isValid = !(host.isEmpty() ||
                  resourceName.isEmpty() ||
                  m_versions.isEmpty() ||
                  m_key.isEmpty() ||
                  (verb != QStringLiteral("GET")) ||
                  (!conversionOk || (httpVersion < 1.1f)) ||
                  (upgrade.toLower() != QStringLiteral("websocket")) ||
                  (!connectionValues.contains(QStringLiteral("upgrade"), Qt::CaseInsensitive)));
    if (Q_UNLIKELY(!m_isValid))
        clear();
}
/*!
    \internal
 */
void QWebSocketPrivate::processHandshake(QTcpSocket *pSocket)
{
    Q_Q(QWebSocket);
    if (Q_UNLIKELY(!pSocket))
        return;
    // Reset handshake on a new connection.
    if (m_handshakeState == AllDoneState)
        m_handshakeState = NothingDoneState;

    QString errorDescription;

    switch (m_handshakeState) {
    case NothingDoneState:
        m_headers.clear();
        m_handshakeState = ReadingStatusState;
        // no break
    case ReadingStatusState:
        if (!pSocket->canReadLine())
            return;
        m_statusLine = pSocket->readLine();
        if (Q_UNLIKELY(!parseStatusLine(m_statusLine, &m_httpMajorVersion, &m_httpMinorVersion, &m_httpStatusCode, &m_httpStatusMessage))) {
            errorDescription = QWebSocket::tr("Invalid statusline in response: %1.").arg(QString::fromLatin1(m_statusLine));
            break;
        }
        m_handshakeState = ReadingHeaderState;
        // no break
    case ReadingHeaderState:
        while (pSocket->canReadLine()) {
            QString headerLine = readLine(pSocket);
            const QStringList headerField = headerLine.split(QStringLiteral(": "),
                                                             QString::SkipEmptyParts);
            if (headerField.size() == 2) {
                m_headers.insertMulti(headerField[0].toLower(), headerField[1]);
            }
            if (headerField.isEmpty()) {
                m_handshakeState = ParsingHeaderState;
                break;
            }
        }

        if (m_handshakeState != ParsingHeaderState) {
            if (pSocket->atEnd()) {
                errorDescription = QWebSocket::tr("QWebSocketPrivate::processHandshake: Connection closed while reading header.");
                break;
            }
            return;
        }
        // no break
    case ParsingHeaderState: {
        const QString acceptKey = m_headers.value(QStringLiteral("sec-websocket-accept"), QString());
        const QString upgrade = m_headers.value(QStringLiteral("upgrade"), QString());
        const QString connection = m_headers.value(QStringLiteral("connection"), QString());
//        unused for the moment
//        const QString extensions = m_headers.value(QStringLiteral("sec-websocket-extensions"),
//                                                 QString());
//        const QString protocol = m_headers.value(QStringLiteral("sec-websocket-protocol"),
//                                               QString());
        const QString version = m_headers.value(QStringLiteral("sec-websocket-version"), QString());

        bool ok = false;
        if (Q_LIKELY(m_httpStatusCode == 101)) {
            //HTTP/x.y 101 Switching Protocols
            //TODO: do not check the httpStatusText right now
            ok = !(acceptKey.isEmpty() ||
                   (m_httpMajorVersion < 1 || m_httpMinorVersion < 1) ||
                   (upgrade.toLower() != QStringLiteral("websocket")) ||
                   (connection.toLower() != QStringLiteral("upgrade")));
            if (ok) {
                const QString accept = calculateAcceptKey(m_key);
                ok = (accept == acceptKey);
                if (!ok)
                    errorDescription =
                      QWebSocket::tr("Accept-Key received from server %1 does not match the client key %2.")
                            .arg(acceptKey).arg(accept);
            } else {
                errorDescription =
                    QWebSocket::tr("QWebSocketPrivate::processHandshake: Invalid statusline in response: %1.")
                        .arg(QString::fromLatin1(m_statusLine));
            }
        } else if (m_httpStatusCode == 400) {
            //HTTP/1.1 400 Bad Request
            if (!version.isEmpty()) {
                const QStringList versions = version.split(QStringLiteral(", "),
                                                           QString::SkipEmptyParts);
                if (!versions.contains(QString::number(QWebSocketProtocol::currentVersion()))) {
                    //if needed to switch protocol version, then we are finished here
                    //because we cannot handle other protocols than the RFC one (v13)
                    errorDescription =
                            QWebSocket::tr("Handshake: Server requests a version that we don't support: %1.")
                            .arg(versions.join(QStringLiteral(", ")));
                } else {
                    //we tried v13, but something different went wrong
                    errorDescription =
                        QWebSocket::tr("QWebSocketPrivate::processHandshake: Unknown error condition encountered. Aborting connection.");
                }
            } else {
                    errorDescription =
                        QWebSocket::tr("QWebSocketPrivate::processHandshake: Unknown error condition encountered. Aborting connection.");
            }
        } else {
            errorDescription =
                    QWebSocket::tr("QWebSocketPrivate::processHandshake: Unhandled http status code: %1 (%2).")
                        .arg(m_httpStatusCode).arg(m_httpStatusMessage);
        }
        if (ok)
            m_handshakeState = AllDoneState;
        break;
    }
    case AllDoneState:
        Q_UNREACHABLE();
        break;
    }

    if (m_handshakeState == AllDoneState) {
        // handshake succeeded
        setSocketState(QAbstractSocket::ConnectedState);
        Q_EMIT q->connected();
    } else {
        // handshake failed
        m_handshakeState = AllDoneState;
        setErrorString(errorDescription);
        Q_EMIT q->error(QAbstractSocket::ConnectionRefusedError);
    }
}
Example #20
0
void ApiYandexSearch::getSuggestionsFinished(QNetworkReply *reply)
{
    QByteArray content = reply->readAll();

    if (m_suggestionsParameters.v == "4") {
        QJsonParseError parseError;

        QVariant json = QJsonDocument::fromJson(content, &parseError).toVariant();
        if (Q_UNLIKELY(parseError.error)) {
            qWarning() << "ApiYandexSearch::getSuggestionsFinished():"
                       << tr("Can't parse JSON data:") << content
                       << tr(". Parser returned an error:") << parseError.errorString();
            qWarning() << "Request:" << m_currentSuggestionsRequest;
            m_currentSuggestionsRequest.clear();
            return;
        }
        QVariantList jsonList = json.toList();

        if (jsonList.size() == 0) {
                return;
        }

        QVariantList suggestions = jsonList.at(1).toList();

        QList<Consts::Shared::Suggestion> suggestionsToReturn;
        forc11 (QVariant var, suggestions) {
            Consts::Shared::Suggestion suggestion;

            // Query
            if (var.type() == QVariant::String) {
                suggestion.text = var.toString();
                suggestion.kind = Consts::Shared::Suggestion::Kind::Query;
            }
            else if (var.type() == QVariant::List) {
                QVariantList list = var.toList();

                QString kind = list.first().toString();

                // Fact
                if (kind == "fact") {
                    suggestion.text = list.at(1).toString();
                    suggestion.kind = Consts::Shared::Suggestion::Kind::Fact;
                    suggestion.others.fact = list.at(2).toString();
                }

                // Navigation
                else if (kind == "nav") {
                    suggestion.text = list.at(3).toString();
                    suggestion.kind = Consts::Shared::Suggestion::Kind::Navigation;
                    const QString nameOfGoToSite = QString::fromUtf8("перейти на сайт");
                    if (list.at(2).toString() != nameOfGoToSite)
                        suggestion.others.linkTitle = list.at(2).toString();
                }
                else {
                    continue;
                }
            }
            else {
                continue;
            }

            suggestionsToReturn.append(suggestion);
        }
// draw the chartchartheight
void
QTAChartCore::draw (void)
{
  QWidget *gqw;
  QTACObject *object, *delobject;
  
  if (Q_UNLIKELY (!tfinit))
  {
	QString title;  
	createTFButtons ();  
	HLOC = &TIMEFRAME[0].HLOC;
    HEIKINASHI = &TIMEFRAME[0].HEIKINASHI; 
    startbar = &TIMEFRAME[0].TFStartBar;
    excess_drag_width = &TIMEFRAME[0].TFExcess_Drag_Width;
    title = Symbol + " - " + TIMEFRAME[0].TFName;
    currenttf = TIMEFRAME[0].TFName;
    setTitle (title, QString::fromUtf8 (subtitletext));
    tfinit = true;
  }  
  
  // collect garbage objects
  do
  { 
	delobject = NULL;  
    foreach (object, Object)
      if (object->deleteit)
        delobject = object;
  
    if (delobject != NULL)
      deleteObject (delobject);
  }
  while (delobject != NULL);
  
  
  // collect garbase QWidgets
  if (garbageQWidget.size () > 0)
  {
	gqw = garbageQWidget[0];
	gqw->deleteLater ();
	garbageQWidget.remove (0); 
  }
  
  if (reloaded)
  {
    points = maxdecimals (HLOC);
    decimals = qCeil (qAbs (qLog10 (points)));
    OPEN.clear ();
    CLOSE.clear ();
    HIGH.clear ();
    LOW.clear ();
    VOLUME.clear ();
    foreach (const QTAChartFrame &frame, *HLOC)
    {
      OPEN += frame.Open;
      CLOSE += frame.Close;
      HIGH += frame.High;
      LOW += frame.Low;
      VOLUME += frame.Volume;
    }
    reloaded = false;
  }

  // geometry
  geom (this);
  
  // draw the objects
  foreach (object, Object)
    object->draw ();
  
  // draw the chart frame, grid, bottom text 
  ruller_cursor_x = chartrightmost + 2;
  ruller_cursor->setPos (ruller_cursor_x, ruller_cursor_y);
  bottom_text->setPos (chartleftmost, height - (bottomline_height + 5));

  topedge->setLine (chartleftmost, charttopmost, chartrightmost + 3, charttopmost);
  bottomedge->setLine (chartleftmost, chartbottomost + 5, width, chartbottomost + 5);
  rightedge->setLine (chartrightmost + 3, 0, chartrightmost + 3, height);
  leftedge->setLine (chartleftmost, 0, chartleftmost, height);
  
  if (show_grid)
    drawGRID ();
  else
    clearGRID ();
      
  if (linear)
    scaletitle->setPlainText ("Linear");
  else  
    scaletitle->setPlainText ("Logarithmic");
    
  if (chart_style == QTACHART_CANDLE)
  {
    typetitle->setPlainText ("Candle");
    drawCandleChart ();
  }  
  else  if (chart_style == QTACHART_HEIKINASHI)  
  {
    typetitle->setPlainText ("Heikin-Ashi");
    drawCandleChart ();
  }  
  else if (chart_style == QTACHART_BAR)
  {
    typetitle->setPlainText ("Bar");
    drawBarChart ();
  }  
  else if (chart_style == QTACHART_LINE)
  {
    typetitle->setPlainText ("Line");
    drawPriceLine (linecolor, linethickness);
  }  
  
  clearITEMS ();
  setRullerCursor (ruller_cursor_y);
}
/*!
    \internal
 */
QString QWebSocketHandshakeResponse::getHandshakeResponse(
        const QWebSocketHandshakeRequest &request,
        const QString &serverName,
        bool isOriginAllowed,
        const QList<QWebSocketProtocol::Version> &supportedVersions,
        const QList<QString> &supportedProtocols,
        const QList<QString> &supportedExtensions)
{
    QStringList response;
    m_canUpgrade = false;

    if (!isOriginAllowed) {
        if (!m_canUpgrade) {
            m_error = QWebSocketProtocol::CC_POLICY_VIOLATED;
            m_errorString = ("Access forbidden.");
            response << QStringLiteral("HTTP/1.1 403 Access Forbidden");
        }
    } else {
        if (request.isValid()) {
            const QString acceptKey = calculateAcceptKey(request.key());
            const QList<QString> matchingProtocols =
                    supportedProtocols.toSet().intersect(request.protocols().toSet()).toList();
            const QList<QString> matchingExtensions =
                    supportedExtensions.toSet().intersect(request.extensions().toSet()).toList();
            QList<QWebSocketProtocol::Version> matchingVersions =
                    request.versions().toSet().intersect(supportedVersions.toSet()).toList();
            std::sort(matchingVersions.begin(), matchingVersions.end(),
                      std::greater<QWebSocketProtocol::Version>());    //sort in descending order

            if (Q_UNLIKELY(matchingVersions.isEmpty())) {
                m_error = QWebSocketProtocol::CC_PROTOCOL_ERROR;
                m_errorString = ("Unsupported version requested.");
                m_canUpgrade = false;
            } else {
                response << QStringLiteral("HTTP/1.1 101 Switching Protocols") <<
                            QStringLiteral("Upgrade: websocket") <<
                            QStringLiteral("Connection: Upgrade") <<
                            QStringLiteral("Sec-WebSocket-Accept: ") % acceptKey;
                if (!matchingProtocols.isEmpty()) {
                    m_acceptedProtocol = matchingProtocols.first();
                    response << QStringLiteral("Sec-WebSocket-Protocol: ") % m_acceptedProtocol;
                }
                if (!matchingExtensions.isEmpty()) {
                    m_acceptedExtension = matchingExtensions.first();
                    response << QStringLiteral("Sec-WebSocket-Extensions: ") % m_acceptedExtension;
                }
                QString origin = request.origin().trimmed();
                if (origin.isEmpty())
                    origin = QStringLiteral("*");
                response << QStringLiteral("Server: ") % serverName                      <<
                            QStringLiteral("Access-Control-Allow-Credentials: false")    <<
                            QStringLiteral("Access-Control-Allow-Methods: GET")          <<
                            QStringLiteral("Access-Control-Allow-Headers: content-type") <<
                            QStringLiteral("Access-Control-Allow-Origin: ") % origin     <<
                            QStringLiteral("Date: ") %
                                QDateTime::currentDateTimeUtc()
                                    .toString(QStringLiteral("ddd, dd MMM yyyy hh:mm:ss 'GMT'"));

                m_acceptedVersion = QWebSocketProtocol::currentVersion();
                m_canUpgrade = true;
            }
        } else {
            m_error = QWebSocketProtocol::CC_PROTOCOL_ERROR;
            m_errorString = ("Bad handshake request received.");
            m_canUpgrade = false;
        }
        if (Q_UNLIKELY(!m_canUpgrade)) {
            response << QStringLiteral("HTTP/1.1 400 Bad Request");
            QStringList versions;
            Q_FOREACH (QWebSocketProtocol::Version version, supportedVersions)
                versions << QString::number(static_cast<int>(version));
            response << QStringLiteral("Sec-WebSocket-Version: ")
                                % versions.join(QStringLiteral(", "));
        }
    }
    response << QStringLiteral("\r\n");    //append empty line at end of header
    return response.join(QStringLiteral("\r\n"));
}
bool EventDispatcherEPollPrivate::processEvents(QEventLoop::ProcessEventsFlags flags)
{
    Q_Q(EventDispatcherEPoll);

    const bool exclude_notifiers = (flags & QEventLoop::ExcludeSocketNotifiers);
    const bool exclude_timers    = (flags & QEventLoop::X11ExcludeTimers);

    exclude_notifiers && disableSocketNotifiers(true);
    exclude_timers    && disableTimers(true);

    m_interrupt = false;
    Q_EMIT q->awake();

    bool result = q->hasPendingEvents();

    QCoreApplication::sendPostedEvents();

    bool can_wait =
            !m_interrupt
            && (flags & QEventLoop::WaitForMoreEvents)
            && !result
            ;

    int n_events = 0;

    if (!m_interrupt) {
        int timeout = 0;

        if (!exclude_timers && !m_zero_timers.isEmpty()) {
            QVector<ZeroTimer*> timers;
            auto it = m_zero_timers.constBegin();
            while (it != m_zero_timers.constEnd()) {
                ZeroTimer *data = it.value();
                data->ref();
                timers.push_back(data);
                ++it;
            }

            for (ZeroTimer *data : timers) {
                if (data->canProcess() && data->active) {
                    data->active = false;

                    QTimerEvent event(data->timerId);
                    QCoreApplication::sendEvent(data->object, &event);

                    result = true;
                    if (!data->active) {
                        data->active = true;
                    }
                }

                data->deref();
            }
        }

        if (can_wait && !result) {
            Q_EMIT q->aboutToBlock();
            timeout = -1;
        }

        struct epoll_event events[10024];
        do {
            n_events = epoll_wait(m_epoll_fd, events, 10024, timeout);
        } while (Q_UNLIKELY(-1 == n_events && errno == EINTR));

        for (int i = 0; i < n_events; ++i) {
            struct epoll_event &e = events[i];
            auto data = static_cast<EpollAbastractEvent*>(e.data.ptr);
            data->ref();
        }

        for (int i = 0; i < n_events; ++i) {
            struct epoll_event &e = events[i];
            auto data = static_cast<EpollAbastractEvent*>(e.data.ptr);
            if (data->canProcess()) {
                data->process(e.events);
            }

            data->deref();
        }
    }

    exclude_notifiers && disableSocketNotifiers(false);
    exclude_timers    && disableTimers(false);

    return result || n_events > 0;
}