Пример #1
0
ProcessResult ProcessMuc::blockArrived(JabberDataBlockRef block, const ResourceContextRef rc){

    JabberDataBlockRef xmuc=block->findChildNamespace("x", "http://jabber.org/protocol/muc#user");
    if (!xmuc) return BLOCK_REJECTED;

    const std::string &from=block->getAttribute("from");
    const std::string &type=block->getAttribute("type");

    Jid roomNode;
    roomNode.setJid(from);

    std::string message;

    //1. group
    MucGroup::ref roomGrp;
    roomGrp=boost::dynamic_pointer_cast<MucGroup> (rc->roster->findGroup(roomNode.getBareJid()));

    if (!roomGrp) return BLOCK_PROCESSED; //dropped presence

    MucContact::ref c=getMucContactEntry(from, rc);

    MPA action=NONE;

    if (type=="error") {
        JabberDataBlockRef error=block->getChildByName("error");
        int errCode=atoi(error->getAttribute("code").c_str());

        //todo: if (status>=Presence.PRESENCE_OFFLINE) testMeOffline();
        action=LEAVE;
        
        //todo: if (errCode!=409 || status>=Presence.PRESENCE_OFFLINE)  setStatus(presenceType);

        std::string errText=error->getChildText("text");
        if (errText.length()>0) message=errText; // if error description is provided by server
        else // legacy codes
            switch (errCode) {
                case 401: message="Password required";
                case 403: message="You are banned in this room";
                case 404: message="Room does not exists";
                case 405: message="You can't create room on this server";
                case 406: message="Reserved roomnick must be used";
                case 407: message="This room is members-only";
                case 409: message="Nickname is already in use by another occupant";
                case 503: message="Maximum number of users has been reached in this room";
                default: message=*(error->toXML());
            }
    } else {
        JabberDataBlockRef item=xmuc->getChildByName("item");   

        MucContact::Role role = 
            getRoleIndex(item->getAttribute("role"));
        c->sortKey=MucContact::MODERATOR-role;
        
        MucContact::Affiliation affiliation = 
            getAffiliationIndex(item->getAttribute("affiliation"));

        boolean roleChanged= c->role != role;
        boolean affiliationChanged= c->affiliation !=affiliation;
    
        c->role=role;
        c->affiliation=affiliation;

        

        //setSortKey(nick);

        switch (role) {
        case MucContact::MODERATOR:
            c->transpIndex=icons::ICON_MODERATOR_INDEX;
            break;
        case MucContact::VISITOR:
            {
                Skin * il= dynamic_cast<Skin *>(skin.get());
                c->transpIndex=(il)? il->getBaseIndex("visitors") : 0;
                break;
            }
        default:
            c->transpIndex=0;
        }

        JabberDataBlockRef statusBlock=xmuc->getChildByName("status");
        int statusCode=(statusBlock)? atoi(statusBlock->getAttribute("code").c_str()) : 0; 

        message=c->jid.getResource(); // nick

        if (type=="unavailable") {
            action=LEAVE;
            std::string reason=item->getChildText("reason");

            switch (statusCode) {
            case 303:
                message+=" is now known as ";
                message+=item->getAttribute("nick");
                c->jid.setResource(item->getAttribute("nick"));
                c->rosterJid=c->jid.getJid(); //for vCard
                c->update();
                action=NONE;
                break;

            case 307: //kick
            case 301: //ban
                message+=(statusCode==307)?" was kicked " : " was banned ";
                message+="(";
                message+=reason;
                message+=")";

                if (c->realJid.length()>0){
                    message+=" - ";
                    message+=c->realJid;
                }
                break;

            case 321:
                message+=" has been unaffiliated and kicked from members-only room";
                break;

            case 322:
                message+=" has been kicked because room became members-only";
                break;

            default:
                {
                    message+=" has left the channel";
                    const std::string & status=block->getChildText("status");
                    if (status.length()) {
                        message+=" (";
                        message+=status;
                        message+=")";
                    }
                }
            }
        } else { //onlines
            action=ENTER;
            if (c->status>=presence::OFFLINE) {
                // first online
                std::string realJid=item->getAttribute("jid");
                if (realJid.length()) {
                    c->realJid=realJid;
                    message+=" (";
                    message+=realJid;  //for moderating purposes
                    message+=")";
                }
                message+=" has joined the channel as ";
                message+=roleName[role];

                if (affiliation!=MucContact::NONE) {
                    message+=" and ";
                    message+=affiliationName[affiliation-MucContact::OUTCAST];

                    const std::string & status=block->getChildText("status");
                    if (status.length()) {
                        message+=" (";
                        message+=status;
                        message+=")";
                    }
                }
            } else {
                //change status
                message+=" is now ";

                if ( roleChanged ) message+=roleName[role];
                if (affiliationChanged) {
                    if (roleChanged) message+=" and ";
                    message+=(affiliation==MucContact::NONE)? 
                        "unaffiliated" : affiliationName[affiliation-MucContact::OUTCAST];
                }
                if (!roleChanged && !affiliationChanged) {
                    const std::string &show=block->getChildText("show");
                    if (show.length()==0) message+="online";
                    else message+=show;

                    const std::string & status=block->getChildText("status");
                    if (status.length()) {
                        message+=" (";
                        message+=status;
                        message+=")";
                    }

                }
            }
        }
    }

    if (c.get()==roomGrp->selfContact.get()) {
        switch (action) {
            case ENTER:
                // room contact is online
                roomGrp->room->status=presence::ONLINE;
                break;
            case LEAVE:
                // room contact is offline
                roomGrp->room->status=presence::OFFLINE;
                // make all occupants offline
                rc->roster->setStatusByFilter(roomNode.getBareJid(), presence::OFFLINE);
                break;
        }
    }

    {
        ChatView *cv = dynamic_cast<ChatView *>(tabs->getWindowByODR(c).get());

        bool ascroll=(cv==NULL)? false: cv->autoScroll();

        c->processPresence(block);

        if (ascroll) {
            cv->moveEnd();
        }
        if (cv) if (IsWindowVisible(cv->getHWnd())) cv->redraw();
    }
    rc->roster->makeViewList();


    {
        Message::ref msg=Message::ref(new Message(message, from, false, Message::PRESENCE, Message::extractXDelay(block) ));

        Contact::ref room=roomGrp->room;

        ChatView *cv = dynamic_cast<ChatView *>(tabs->getWindowByODR(room).get());

        bool ascroll=(cv==NULL)? false: cv->autoScroll();
        room->messageList->push_back(msg);

        if (ascroll) {
            cv->moveEnd();
        }
        if (cv) if (IsWindowVisible(cv->getHWnd())) cv->redraw();
    }

    return BLOCK_PROCESSED;
}
Пример #2
0
void Contact::processPresence( JabberDataBlockRef block ) {

    std::string type=block->getAttribute("type");
    std::string priority=block->getChildText("priority");
    std::string status=block->getChildText("status");

    presence::PresenceIndex typeIndex=presence::OFFLINE;
    presence::PresenceIndex type2=presence::NOCHANGE; //no change
    Message::MsgType msgType=Message::PRESENCE;

    if (type=="unavailable") { 
        typeIndex=presence::OFFLINE;
        type="offline";
    } else if (type=="subscribe") { 
        msgType=Message::PRESENCE_ASK_SUBSCR;
        //TODO:
    } else if (type=="subscribed") {
        msgType=Message::PRESENCE_SUBSCRIBED;
        //TODO:
    } else if (type=="unsubscribe") {
        //TODO:
    } else if (type=="unsubscribed") {
        msgType=Message::PRESENCE_UNSUBSCRIBED;
        //TODO:
    } else if (type=="error") {
        typeIndex=presence::OFFLINE;
        type2=presence::PRESENCE_ERROR;
        //todo: extract error text here
    } else {
        type=block->getChildText("show");
        if (type=="chat") typeIndex=presence::CHAT; else
            if (type=="away") typeIndex=presence::AWAY; else
                if (type=="xa") typeIndex=presence::XA; else
                    if (type=="dnd") typeIndex=presence::DND; else {
                        typeIndex=presence::ONLINE;
                        type="online";
                    }
    }
/*
<presence id="36">
<priority>30</priority>
<show>xa</show>
<x xmlns="vcard-temp:x:update" />
<c xmlns="http://jabber.org/protocol/caps" node="http://gajim.org" ver="2sSROk7c/BXz4QRPKkeriaW4V6M=" hash="sha-1" />icons::ICON_BOMBUS_NG
<status>ага</status>
</presence>
*/
typevs=type;

    this->status=typeIndex;
    if (type2!=presence::NOCHANGE) this->offlineIcon=type2;

    if (nickname.empty() && this->status<=presence::DND) {
        JabberDataBlockRef nick=block->findChildNamespace("nick","http://jabber.org/protocol/nick");
        if (nick) {
            nickname=nick->getText();
            std::trim(nickname);
		}
    }
	
	JabberDataBlockRef nodeBlock=block->findChildNamespace("c","http://jabber.org/protocol/caps");
	   if(nodeBlock){
          nodeInfo = nodeBlock->getAttribute("node");
		  //Log::getInstance()->msg("[***]Get node CLIENT: " + block->getAttribute("from") + " " + nodeInfo 
		  //	  + " VERSION: " + nodeBlock->getAttribute("ver"));
	   }else{nodeInfo = "";}
	
    update();

    std::string body=type;
    if (status.length()) {
        body+=" (";
        body+=status;
		statusMessage = status;
        body+=')';
    }
statusMessage2=statusMessage;
    if (priority.length()) {
        body+=" [";
        //std::strAppendInt(body, priority);
        body+=priority;
        body+=']';
    }

    Message::ref msg=Message::ref(new Message(body, block->getAttribute("from"), false, msgType, Message::extractXDelay(block) ));

    if (messageList->size()==1) {
        //verify if it is presence;
        Message::ref mfirst=boost::dynamic_pointer_cast<Message>(messageList->front());
        if (mfirst) if (mfirst->type==Message::PRESENCE)
            this->messageList->erase( this->messageList->begin());
    }
	if (Config::getInstance()->showStatusInSimpleChat==false){
        //Отображение статусной информации у simple контакта
	    if(msgType!=Message::PRESENCE){
          this->messageList->push_back(msg); //исключаем презенсы
	    } 
	}else{
      this->messageList->push_back(msg);
	}

}