ProcessResult EntityCaps::blockArrived(JabberDataBlockRef block, const ResourceContextRef rc) { JabberDataBlockRef query=block->getChildByName("query"); if (!query) return BLOCK_REJECTED; std::string xmlns=query->getAttribute("xmlns"); if (xmlns!="http://jabber.org/protocol/disco#info") return BLOCK_REJECTED; std::string node=query->getAttribute("node"); if (node.length()>0) if (node.find("http://bombus-im.org/ng")<0) return BLOCK_REJECTED; JabberDataBlock result ("iq"); result.setAttribute("to", block->getAttribute("from")); result.setAttribute("type", "result"); result.setAttribute("id", block->getAttribute("id")); result.addChild(query); JabberDataBlockRef identity=query->addChild("identity",NULL); identity->setAttribute("category", rc->myCaps->identityCategory.c_str()); identity->setAttribute("type", rc->myCaps->identityType.c_str()); identity->setAttribute("name", rc->myCaps->identityName.c_str()); rc->myCaps->appendFeatures(query); rc->jabberStream->sendStanza(result); return BLOCK_PROCESSED; }
ProcessResult GetInfo::blockArrived(JabberDataBlockRef block, const ResourceContextRef rc){ ClientInfoForm::ref vfRef=vf.lock(); if (!vfRef) return CANCEL; if (block->getTagName()!="iq") return BLOCK_REJECTED; //if (block->getAttribute("from")!=jid) return BLOCK_REJECTED; TODO: stringprep const std::string &type=block->getAttribute("type"); int nType=-1; if (type=="result") nType=1; if (type=="error") nType=0; if (nType<0) return BLOCK_REJECTED; const std::string &id=block->getAttribute("id"); bool idMatch=(id==idVer || id==idLast || id==idTime); if (!idMatch) return BLOCK_REJECTED; JabberDataBlockRef qry=block->findChildNamespace("query","jabber:iq:version"); if (qry) { if (nType) { vfRef->clientName=qry->getChildText("name"); vfRef->clientVersion=qry->getChildText("version"); vfRef->clientOS=qry->getChildText("os"); } /*else { vfRef->clientVersion="unavailable"; }*/ } qry=block->findChildNamespace("query","jabber:iq:last"); if (qry) { if (nType) { const std::string &seconds=qry->getAttribute("seconds"); vfRef->lastActivityMessage=qry->getText(); vfRef->lastActivityTime=seconds; //todo: convert to absolute time } /*else { vfRef->lastActivityTime="unavailable"; }*/ } qry=block->findChildNamespace("query","jabber:iq:time"); if (qry) { if (nType) { const std::string &display=qry->getChildText("display"); vfRef->clientTime=display; } } vfRef->infoArrivedNotify(); resultCount--; return (resultCount==0)? LAST_BLOCK_PROCESSED : BLOCK_PROCESSED; }
ProcessResult LastActivity::blockArrived(JabberDataBlockRef block, const ResourceContextRef rc){ JabberDataBlockRef query=block->findChildNamespace("query","jabber:iq:last"); if (!query) return BLOCK_REJECTED; //Log::getInstance()->msg("Last Activity query: ", block->getAttribute("from").c_str()); JabberDataBlock result("iq"); result.setAttribute("to", block->getAttribute("from")); result.setAttribute("type", "result"); result.setAttribute("id", block->getAttribute("id")); result.addChild(query); query->setAttribute("seconds",delay()); //query->setText("This is stub time"); rc->jabberStream->sendStanza(result); return BLOCK_PROCESSED; }
ProcessResult CaptchaListener::blockArrived(JabberDataBlockRef block, const ResourceContextRef rc){ JabberDataBlockRef challenge=block->findChildNamespace("challenge", "urn:xmpp:tmp:challenge"); if (!challenge) return BLOCK_REJECTED; JabberDataBlockRef xdata=challenge->findChildNamespace("x", "jabber:x:data"); const std::string &jid=block->getAttribute("from"); const std::string &id=block->getAttribute("id"); CaptchaForm::ref rform=CaptchaForm::createCaptchaForm(tabs->getHWnd(), jid, id, rc); tabs->addWindow(rform); tabs->switchByWndRef(rform); rform->bindXData(xdata); return BLOCK_PROCESSED; }
ProcessResult GetDisco::blockArrived(JabberDataBlockRef block, const ResourceContextRef rc){ ServiceDiscovery::ref sd=vf.lock(); if (!sd) return CANCEL; if (block->getAttribute("id")==idinfo) { if (block->getAttribute("type")=="result") { sd->infoReply=block->findChildNamespace("query", "http://jabber.org/protocol/disco#info"); } else { if (block->getAttribute("type")=="error") { sd->infoReply=block->getChildByName("error"); } } SendMessage(sd->getHWnd(), WM_NOTIFY_BLOCKARRIVED, 0,0); return BLOCK_PROCESSED; } if (block->getAttribute("id")==iditems) { if (block->getAttribute("type")=="result") { sd->itemReply=block->findChildNamespace("query", "http://jabber.org/protocol/disco#items"); } else { if (block->getAttribute("type")=="error") { sd->itemReply=block->getChildByName("error"); } } SendMessage(sd->getHWnd(), WM_NOTIFY_BLOCKARRIVED, 0,0); return LAST_BLOCK_PROCESSED; } return BLOCK_REJECTED; }
ProcessResult GetVcardNick::blockArrived(JabberDataBlockRef block, const ResourceContextRef rc){ std::string &type=block->getAttribute("type"); std::string nick; if (type=="result") { JabberDataBlockRef vcard=block->getChildByName("vCard"); if (vcard) { nick=vcard->getChildText("NICKNAME"); if (nick.length()==0) nick=vcard->getChildText("FN"); } SetDlgItemText(targetDlg, targetCtrl, nick); } return LAST_BLOCK_PROCESSED; }
void MucConfigForm::MucConfigResultNotify(JabberDataBlockRef block) { if (block->getAttribute("type")=="error") { XmppError::ref xe= XmppError::findInStanza(block); //todo: error handling MessageBox(getHWnd(), utf8::utf8_wchar(xe->toString()).c_str() , L"MucConfig", MB_OK | MB_ICONEXCLAMATION ); return; } JabberDataBlockRef query=block->findChildNamespace("query","http://jabber.org/protocol/muc#owner"); this->xdata=query->findChildNamespace("x","jabber:x:data"); //non-descriptive result if (!xdata && plainText.empty()) plainText="done"; //todo: make more informative and localizabe PostMessage(getHWnd(), WM_HTML_UPDATE, 0, (LPARAM)""); return; }
ProcessResult MucBookmarks::blockArrived( JabberDataBlockRef block, const ResourceContextRef rc ) { std::string &type=block->getAttribute("type"); if (type=="error") { return LAST_BLOCK_PROCESSED; } bookmarksAvailable=true; if (type=="result") { JabberDataBlockRef pvt=block->findChildNamespace("query","jabber:iq:private"); if (!pvt) return LAST_BLOCK_PROCESSED; JabberDataBlockRef storage=pvt->findChildNamespace("storage","storage:bookmarks"); JabberDataBlockRefList::iterator i=storage->getChilds()->begin(); while (i!=storage->getChilds()->end()) { JabberDataBlockRef item=*(i++); const std::string &tagName=item->getTagName(); MucBookmarkItem::ref b=addNewBookmark(); b->name=item->getAttribute("name"); if (tagName=="url") { b->url=item->getAttribute("url"); if (b->name.empty()) b->name=b->url; } if (tagName=="conference") { b->jid=item->getAttribute("jid"); b->nick=item->getChildText("nick"); b->password=item->getChildText("password"); const std::string &autoJoin=item->getAttribute("autojoin"); b->autoJoin=(autoJoin=="1" || autoJoin=="true"); } } std::stable_sort(bookmarks.begin(), bookmarks.end(), MucBookmarkItem::compare); } Log::getInstance()->msg("Bookmarks received successfully", Log::info); return LAST_BLOCK_PROCESSED; }
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; }
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); } }