void Imap4Analyser::analyse(const char* content, size_t length, const SessionId& sessionId)
    {
        LOG4CPLUS_TRACE(LOGGER, "********************analyse enter, content=" << content << ", length=" << length << ", sessionId=" << sessionId);

        // 长度至少要为最小可分析长度
        if (0 == content || MIN_LENGTH > length) {
            LOG4CPLUS_WARN(LOGGER, "invalid packet, content error or length error");
            LOG4CPLUS_TRACE(LOGGER, "analyse leave");
            return;
        }

        string str(content);

        // 查找第一个空格,将之前的内容视为标签
        size_t tagEndPos = str.find_first_of(' ');

        // 未找到空格,视为无效数据
        if (string::npos == tagEndPos) {
            LOG4CPLUS_WARN(LOGGER, "invalid packet, can't find blank character");
            LOG4CPLUS_TRACE(LOGGER, "analyse leave");
            return;
        }

        // 标签长度为零
        if (0 == tagEndPos) {
            LOG4CPLUS_WARN(LOGGER, "invalid packet, tag length is zero");
            LOG4CPLUS_TRACE(LOGGER, "analyse leave");
            return;
        }

        // 得到标签
        string tag = str.substr(0, tagEndPos);
        LOG4CPLUS_TRACE(LOGGER, "get tag, tag=" << tag);

        // 测试长度是否足够继续分析
        if (tagEndPos + 1 >= length) {
            LOG4CPLUS_WARN(LOGGER, "invalid packet, content deficient");
            LOG4CPLUS_TRACE(LOGGER, "analyse leave");
            return;
        }

        // 查找LOGIN命令
        size_t cmdOrResponseBeginPos = str.find(COMMAND_LOGIN, tagEndPos + 1);

        // 找到LOGIN命令
        if (string::npos != cmdOrResponseBeginPos && tagEndPos + 1 == cmdOrResponseBeginPos) {
            LOG4CPLUS_TRACE(LOGGER, "get LOGIN cmd");

            // 测试长度是否足够继续分析
            size_t cmdEndPos = cmdOrResponseBeginPos + COMMAND_LOGIN.size();
            if (cmdOrResponseBeginPos + 2 >= length) {
                LOG4CPLUS_WARN(LOGGER, "invalid packet, content deficient");
                LOG4CPLUS_TRACE(LOGGER, "analyse leave");
                return;
            }

            // 查找登录用户名
            size_t userNameEndPos = str.find_first_of(' ', cmdEndPos + 2);
            if (string::npos == userNameEndPos) {
                LOG4CPLUS_WARN(LOGGER, "invalid login cmd, can't find user name");
                LOG4CPLUS_TRACE(LOGGER, "analyse leave");
                return;
            }

            // 获取登录用户名
            string userName = str.substr(cmdEndPos, userNameEndPos - cmdEndPos);
            LOG4CPLUS_TRACE(LOGGER, "get LOGIN user name, userName="******"removed existing sessionInfo");
            }

            // 创建新的会话信息
            SessionInfo * const sessionInfoP = new SessionInfo();
            putSessionInfo(sessionId, *sessionInfoP);

            // 放入登录信息
            CmdInfo* cmdInfoP = new CmdInfo();
            cmdInfoP->setCmdId(ID_COMMAND_LOGIN);
            const time_t now = time(0);
            cmdInfoP->setStartMillis(now * 1000);

            // 放入命令标签
            int key = PROPS_KEY_TAG;
            pair<int, void*> propTag(key, new string(tag));
            cmdInfoP->addProperty(propTag);

            // 放入用户名
            key = PROPS_KEY_USER_NAME;
            pair<int, void*> propUserName(key, new string(userName));
            cmdInfoP->addProperty(propUserName);
            sessionInfoP->addCmd(cmdInfoP);

            // 设置服务端和客户端IP
            sessionInfoP->setServerIp(sessionId.getDestIp());
            sessionInfoP->setServerPort(sessionId.getDestPort());
            sessionInfoP->setClientIp(sessionId.getSourceIp());
            sessionInfoP->setClientPort(sessionId.getSourcePort());

            // 计算包数量和大小
            sessionInfoP->setPacketsCount(1);
            sessionInfoP->setBytesCount(54 + length);
            LOG4CPLUS_TRACE(LOGGER, "analyse leave");
            return;
        }

        LOG4CPLUS_TRACE(LOGGER, "can't find LOGIN cmd");

        // 查看是否已经有相关信息,是否已经LOGIN
        bool contained = containsSessionInfo(sessionId);

        // 当前包是否为响应命令
        bool isResponse = !contained;
        const SessionId* reverseIdP = 0;

        // 测试是否为响应包
        if (!contained) {
            reverseIdP = new SessionId(sessionId.getDestIp(), sessionId.getDestPort(), sessionId.getSourceIp(), sessionId.getSourcePort(), sessionId.getProtocolId());
            contained = containsSessionInfo(*reverseIdP);
            isResponse = contained;
        }

        // 非已知的会话包,丢弃
        if (!contained) {
            LOG4CPLUS_WARN(LOGGER, "ignored packed, can't find sessionInfo");
            LOG4CPLUS_TRACE(LOGGER, "analyse leave");
            return;
        }

        // 是已知的会话包,计算大小及包数
        SessionInfo * const sessionInfoP = getSessionInfo(isResponse ? *reverseIdP : sessionId);

        sessionInfoP->setPacketsCount((sessionInfoP->getPacketsCount() + 1));
        sessionInfoP->setBytesCount(sessionInfoP->getBytesCount() + 54 + length);

        // 非响应包,由客户端发向服务器
        if (!isResponse) {

            // 查找LOGINOUT命令
            cmdOrResponseBeginPos = str.find(COMMAND_LOGOUT, tagEndPos + 1);

            // 找到登出命令
            if (string::npos != cmdOrResponseBeginPos && tagEndPos + 1 == cmdOrResponseBeginPos) {
                LOG4CPLUS_TRACE(LOGGER, "get LOGOUT cmd");

                // 放入登出信息
                CmdInfo* cmdInfoP = new CmdInfo();
                cmdInfoP->setCmdId(ID_COMMAND_LOGOUT);
                const time_t now = time(0);
                cmdInfoP->setStartMillis(now * 1000);

                // 放入命令标签
                int key = PROPS_KEY_TAG;
                pair<int, void*> propTag(key, new string(tag));
                cmdInfoP->addProperty(propTag);

                sessionInfoP->addCmd(cmdInfoP);
            }
            LOG4CPLUS_TRACE(LOGGER, "analyse leave");
        }

            // 响应包,由服务器发向客户端
        else {
            // 先查找LOGIN的返回状态,先查看标签是否一致
            vector<CmdInfo*> cmds = (*(sessionInfoP->getCmds()));
            string* tagP = static_cast<string*> (cmds[0]->getProperty(PROPS_KEY_TAG));
            bool isSameTag = *tagP == tag;

            // 标签一致,是期待的LOGIN的响应
            if (isSameTag) {

                // 查找登录的命令响应
                const size_t responseBeginPos = tagEndPos + 1;
                int statusId = ID_RESPONSE_LOGIN_UNKNOW;

                // 尝试OK响应
                cmdOrResponseBeginPos = str.find(RESPONSE_LOGIN_OK, responseBeginPos);
                if (string::npos != cmdOrResponseBeginPos && cmdOrResponseBeginPos == responseBeginPos) {
                    statusId = ID_RESPONSE_LOGIN_OK;
                }
                else {
                    // 尝试NO响应
                    cmdOrResponseBeginPos = str.find(RESPONSE_LOGIN_NO, responseBeginPos);
                    if (string::npos != cmdOrResponseBeginPos && cmdOrResponseBeginPos == responseBeginPos) {
                        statusId = ID_RESPONSE_LOGIN_NO;
                    }
                    else {
                        // 尝试BAD响应
                        cmdOrResponseBeginPos = str.find(RESPONSE_LOGIN_BAD, responseBeginPos);
                        if (string::npos != cmdOrResponseBeginPos && cmdOrResponseBeginPos == responseBeginPos) {
                            statusId = ID_RESPONSE_LOGIN_BAD;
                        }
                    }
                }
                const time_t now = time(0);
                cmds[0]->setResponseMillis(now * 1000);
                cmds[0]->setStatusId(statusId);
                LOG4CPLUS_TRACE(LOGGER, "got LOGIN cmd response, statusId=" << statusId);
            }
                // 查找 LOGOUT 命令的响应
            else {

                // 是否已经收到LOGOUT命令
                if (2 == cmds.size()) {
                    tagP = static_cast<string*> (cmds[1]->getProperty(PROPS_KEY_TAG));

                    // 查看标签是否一致
                    isSameTag = *tagP == tag;

                    size_t responseBeginPos = tagEndPos + 1;

                    if (!isSameTag && GENERAL_TAG == tag && responseBeginPos < length) {
                        string newTag("\r\n");
                        newTag.append(*tagP);
                        newTag.append(" ");
                        newTag.append(RESPONSE_LOGOUT_OK);
                        size_t tmp = str.find(newTag, responseBeginPos);
                        isSameTag = string::npos != tmp;
                        if (isSameTag) {
                            responseBeginPos = tmp + 3 + tagP->size();
                        }
                        // 再尝试BAD
                        if (!isSameTag) {
                            string newTag("\r\n");
                            newTag.append(*tagP);
                            newTag.append(" ");
                            newTag.append(RESPONSE_LOGOUT_BAD);
                            size_t tmp = str.find(newTag, responseBeginPos);
                            isSameTag = string::npos != tmp;
                            if (isSameTag) {
                                responseBeginPos = tmp + 3 + tagP->size();
                            }
                        }
                    }

                    // 标签一致,是期待的LOGOUT的响应
                    if (isSameTag) {

                        // 查找的登出命令响应
                        int statusId = ID_RESPONSE_LOGOUT_BAD;

                        // 尝试OK响应
                        cmdOrResponseBeginPos = str.find(RESPONSE_LOGOUT_OK, responseBeginPos);
                        if (string::npos != cmdOrResponseBeginPos && responseBeginPos == cmdOrResponseBeginPos) {
                            statusId = ID_RESPONSE_LOGOUT_OK;
                        }
                        const time_t now = time(0);
                        cmds[1]->setResponseMillis(now * 1000);
                        cmds[1]->setStatusId(statusId);
                        LOG4CPLUS_TRACE(LOGGER, "got LOGOUT cmd response, statusId=" << statusId);
                        log(sessionInfoP);
                        removeSessionInfo(*reverseIdP);
                    }
                }
            }
            delete reverseIdP;
            LOG4CPLUS_TRACE(LOGGER, "analyse leave");
        }
    }
Esempio n. 2
0
// ============================================================================
// CWidgetEntry::InternalizeXmlL()
// read from persistent storage(file)
//
// @since 5.0
// ============================================================================
//
void CWidgetEntry::InternalizeXmlL( RFs& aFileSession,
                                    xmlDocPtr aDoc,
                                    xmlNode* n,
                                    CWidgetRegistryXml* aXmlProcessor )
{
    // <prop>name<val>value<type>typename</type></val></prop>
    //
    // prop subtree traversal assumes strict adherence to the
    // prototype structure, otherwise code leaves with corrupt code
    for ( ;
            n;
        )
    {
        // permit some non element stuff (comment, whitespace...) before <prop>
        while ( n && ( n->type != XML_ELEMENT_NODE ) )
        {
            n = n->next;
        }
        if ( NULL == n )
        {
            for (TInt i = iPropertyValues.Count(); i < EWidgetPropertyIdCount; i++)
            {
                CWidgetPropertyValue* val = CWidgetPropertyValue::NewL();
                CleanupStack::PushL(val);
                iPropertyValues.AppendL( val );
                CleanupStack::Pop(); // val
            }
            return;
        }
        TPtrC8 propTag( n->name );
        if ( 0 != propTag.Compare( KXmlPropTag() ) )
        {
            // TODO unrecognized subtree?
            return;
        }
        // TODO validate n->children != NULL and type XML_TEXT_NODE
        HBufC* name;
        aXmlProcessor->GetContentL( aFileSession, aDoc, n->children, &name );

        // get value array index (TWidgetPropertyId) for name
        TPtr namePtr( name->Des() );
        TInt propId =
            aXmlProcessor->GetPropertyId( namePtr );
        delete name;
        name = NULL;
        if ( EWidgetPropertyIdInvalid == propId )
        {
            User::Leave( KErrNoMemory );
        }

        for (TInt i = iPropertyValues.Count(); i <= propId; i++)
        {
            CWidgetPropertyValue* val = CWidgetPropertyValue::NewL();
            CleanupStack::PushL(val);
            iPropertyValues.AppendL( val );
            CleanupStack::Pop(); // val
        }

        n = n->children->next; // down to val
        if ( NULL == n )
        {
            User::Leave( KErrCorrupt );
        }
        TPtrC8 valTag( n->name );
        if ( 0 != valTag.Compare( KXmlValTag() ) )
        {
            User::Leave( KErrCorrupt );
        }
        if (propId >= EWidgetPropertyIdCount) // unsupported property
        {
            HBufC* value = NULL;
            if (n->children)
            {
                aXmlProcessor->GetTextContentAsStringL( aFileSession, aDoc, n->children, &value );
            }
            else
            {
                value = KNullDesC().AllocL();
            }
            (*this)[propId].iValue.s = value;
            (*this)[propId].iType = EWidgetPropTypeBlob;
            n = (n->parent)->next; // up two and next sibling
            continue;
        }
        // TODO validate n->children != NULL and type XML_TEXT_NODE
        HBufC* value;
        aXmlProcessor->GetContentL( aFileSession, aDoc, n->children, &value );
        CleanupStack::PushL( value );

        n = n->children->next; // down to type
        if ( NULL == n )
        {
            User::Leave( KErrCorrupt );
        }
        TPtrC8 typeTag( n->name );
        if ( 0 != typeTag.Compare( KXmlTypeTag() ) )
        {
            User::Leave( KErrCorrupt );
        }
        // TODO validate n->children != NULL and type XML_TEXT_NODE
        HBufC* type;
        aXmlProcessor->GetContentL( aFileSession, aDoc, n->children, &type );
        CleanupStack::PushL( type );

        // now have: name, value, type
        // convert type string to TWidgetPropertyType
        //
        // assume void/unknown is not put in XML format so anything
        // not recognized should be handled like other unrecognized
        // subtree
        TWidgetPropertyType typeEnum = EWidgetPropTypeUnknown;
        if ( 0 == type->Des().Compare( KXmlDataTypeBool() ) )
        {
            typeEnum = EWidgetPropTypeBool;
        }
        else if ( 0 == type->Des().Compare( KXmlDataTypeInt() ) )
        {
            typeEnum = EWidgetPropTypeInt;
        }
        else if ( 0 == type->Des().Compare( KXmlDataTypeString() ) )
        {
            typeEnum = EWidgetPropTypeString;
        }
        else if ( 0 == type->Des().Compare( KXmlDataTypeUid() ) )
        {
            typeEnum = EWidgetPropTypeUid;
        }
        CleanupStack::PopAndDestroy( type );

        // TODO handle unknown type due to future extensions: add prop
        // subtree to list of unrecognized subtrees

        // set prop according to type
        switch ( typeEnum )
        {
        case EWidgetPropTypeBool:
            if ( 0 == value->Des().Compare( _L("0") ) )
            {
                (*this)[propId].iValue.i = 0;
            }
            else
            {
                (*this)[propId].iValue.i = 1;
            }
            break;
        case EWidgetPropTypeInt:
        {
            TLex toInt( value->Des() );
            TInt k;
            if ( KErrNone != toInt.Val( k ) )
            {
                User::Leave( KErrCorrupt );
            }
            (*this)[propId].iValue.i = k;
        }
        break;
        case EWidgetPropTypeString:
            (*this)[propId].iValue.s = value;
            break;
        case EWidgetPropTypeUid:
        {
            TLex toUid( value->Des() );
            TInt u;
            if ( KErrNone != toUid.Val( u ) )
            {
                User::Leave( KErrCorrupt );
            }
            (*this)[propId].iValue.uid = TUid::Uid( u );
        }
        break;
        };

        (*this)[propId].iType = typeEnum;

        CleanupStack::Pop( value );
        if ( EWidgetPropTypeString != typeEnum )
        {
            delete value;
        }

        n = ((n->parent)->parent)->next; // up two and next sibling
    }
}