00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include <jabberoo.hh>
00032 using namespace jabberoo;
00033
00034 Roster::Roster(Session& s)
00035 : _owner(s)
00036 {}
00037
00038 const Roster::Item& Roster::operator[](const string& jid) const
00039 {
00040 ItemMap::const_iterator it = _items.find(filterJID(jid));
00041 if (it == _items.end())
00042 throw XCP_InvalidJID();
00043 else
00044 return it->second;
00045 }
00046
00047 void Roster::reset()
00048 {
00049 _items.clear();
00050 }
00051
00052
00053
00054
00055 bool Roster::containsJID(const string& jid) const
00056 {
00057 return (_items.find(filterJID(jid)) != _items.end());
00058 }
00059
00060
00061
00062
00063 void Roster::update(const Element& t)
00064 {
00065 bool updateFlag = false;
00066
00067
00068
00069 Element::const_iterator it = t.begin();
00070 for (; it != t.end(); ++it )
00071 {
00072 if ((*it)->getType() != Node::ntElement)
00073 continue;
00074
00075 Element& item = *static_cast<Element*>(*it);
00076
00077
00078 string jid = filterJID(item.getAttrib("jid"));
00079
00080
00081 ItemMap::iterator rit = _items.find(jid);
00082
00083
00084 if (rit != _items.end())
00085 {
00086
00087
00088 updateFlag = true;
00089 if (item.cmpAttrib("subscription", "remove"))
00090 {
00091 removeItemFromAllGroups(rit->second);
00092 _items.erase(rit);
00093 }
00094
00095 else
00096 rit->second.update(*this, item);
00097
00098 }
00099
00100 else if (!item.cmpAttrib("subscription", "remove"))
00101 {
00102 _items.insert(make_pair(jid, Item(*this, item)));
00103 updateFlag = true;
00104 }
00105 }
00106
00107 if (updateFlag)
00108 evtRefresh();
00109
00110 }
00111
00112 void Roster::update(const Presence& p, Presence::Type prev_type)
00113 {
00114
00115 string jid = filterJID(p.getFrom());
00116 ItemMap::iterator it = _items.find(jid);
00117 if (it != _items.end())
00118 {
00119 it->second.update(*this, jid, p, prev_type);
00120 }
00121 }
00122
00123 void Roster::update(const Item& i)
00124 {
00125
00126 Element iq("iq");
00127 iq.putAttrib("type", "set");
00128 Element* query = iq.addElement("query");
00129 query->putAttrib("xmlns", "jabber:iq:roster");
00130 Element* item = query->addElement("item");
00131
00132
00133 item->putAttrib("jid", i.getJID());
00134 if (!i.getNickname().empty())
00135 item->putAttrib("name", i.getNickname());
00136
00137 for (Item::iterator it = i.begin(); it != i.end(); it++)
00138 item->addElement("group", *it);
00139
00140
00141 _owner << iq.toString().c_str();
00142 }
00143
00144
00145
00146
00147 void Roster::deleteUser(const string& jid)
00148 {
00149
00150
00151 Element iq("iq");
00152 iq.putAttrib("type", "set");
00153 Element* query = iq.addElement("query");
00154 query->putAttrib("xmlns", "jabber:iq:roster");
00155 Element* item = query->addElement("item");
00156 item->putAttrib("jid", jid);
00157 item->putAttrib("subscription", "remove");
00158
00159
00160 _owner << iq.toString().c_str() << Presence(jid, Presence::ptUnsubRequest);
00161
00162
00163 if ((jid.find("@") == string::npos) && (jid.find("/") != string::npos))
00164 _owner.queryNamespace("jabber:iq:register", slot(*this, &Roster::deleteAgent), jid);
00165 }
00166
00167 void Roster::deleteAgent(const Element& iq)
00168 {
00169 const Element* query = iq.findElement("query");
00170
00171 Element niq("iq");
00172 niq.putAttrib("type", "set");
00173 niq.putAttrib("to", iq.getAttrib("from"));
00174 Element* nquery = niq.addElement("query");
00175 nquery->putAttrib("xmlns", "jabber:iq:register");
00176 nquery->addElement("key", query->getChildCData("key"));
00177 nquery->addElement("remove");
00178
00179
00180 _owner << niq.toString().c_str();
00181 }
00182
00183 void Roster::fetch() const
00184 {
00185 Element iq("iq");
00186 iq.putAttrib("type", "get");
00187 Element* query = iq.addElement("query");
00188 query->putAttrib("xmlns", "jabber:iq:roster");
00189
00190 _owner << iq.toString().c_str();
00191 }
00192
00193
00194
00195
00196 string Roster::translateS10N(Subscription stype)
00197 {
00198 switch (stype)
00199 {
00200 case rsNone: return "none";
00201 case rsTo: return "to";
00202 case rsFrom: return "from";
00203 case rsBoth: return "both";
00204 case rsRemove: return "remove";
00205 }
00206 return "none";
00207 }
00208
00209 Roster::Subscription Roster::translateS10N(const string& stype)
00210 {
00211 if (stype == "to")
00212 return rsTo;
00213 else if (stype == "from")
00214 return rsFrom;
00215 else if (stype == "both")
00216 return rsBoth;
00217 else if (stype == "remove")
00218 return rsRemove;
00219 else
00220 return rsNone;
00221 }
00222
00223 string Roster::filterJID(const string& jid)
00224 {
00225
00226
00227 if (jid.find("@") == string::npos)
00228 return escape(jid);
00229
00230 else
00231 return JID::getUserHost(jid);
00232
00233 }
00234
00235 void Roster::removeItemFromGroup(const string& group, const string& jid)
00236 {
00237 typedef map<string, set<string> >::iterator GIT;
00238 GIT it = _groups.find(group);
00239
00240 if (it != _groups.end())
00241 {
00242
00243 set<string>::iterator member = it->second.find(jid);
00244 if (member != it->second.end())
00245 {
00246 it->second.erase(member);
00247 }
00248
00249 if (it->second.empty())
00250 _groups.erase(it);
00251 }
00252 }
00253
00254 void Roster::removeItemFromAllGroups(const Item& item)
00255 {
00256
00257 for (Item::iterator it = item.begin(); it != item.end(); it++)
00258 {
00259 removeItemFromGroup(*it, item.getJID());
00260 }
00261 }
00262
00263 void Roster::mergeItemGroups(const string& itemjid, const set<string>& oldgrp, const set<string>& newgrp)
00264 {
00265
00266
00267
00268 set<string>::const_iterator new_it = newgrp.begin();
00269 set<string>::const_iterator old_it = oldgrp.begin();
00270 while ((new_it != newgrp.end()) || (old_it != oldgrp.end()))
00271 {
00272 if ((old_it == oldgrp.end()) && (new_it != newgrp.end()))
00273 {
00274 _groups[*new_it].insert(itemjid);
00275 ++new_it;
00276 }
00277 else if ((old_it != oldgrp.end()) && (new_it == newgrp.end()))
00278 {
00279 removeItemFromGroup(*old_it, itemjid);
00280 ++old_it;
00281 }
00282 else if ((*old_it) == (*new_it))
00283 {
00284 ++old_it;
00285 ++new_it;
00286 }
00287 else
00288 {
00289 removeItemFromGroup(*old_it, itemjid);
00290 ++old_it;
00291 }
00292 }
00293
00294 }
00295
00296
00297
00298
00299
00300
00301 Roster::Item::Item(const Element& t)
00302 : _rescnt(0)
00303 {
00304 update(t);
00305 }
00306
00307 Roster::Item::Item(Roster& r, const Element& t)
00308 : _rescnt(0)
00309 {
00310 update(r, t);
00311 }
00312
00313 Roster::Item::Item(const string& jid, const string& nickname)
00314 : _jid(jid), _nickname(nickname)
00315 {}
00316
00317 Roster::Item::~Item()
00318 {}
00319
00320 void Roster::Item::addToGroup(const string& group)
00321 {
00322 _groups.insert(group);
00323 }
00324
00325 void Roster::Item::delFromGroup(const string& group)
00326 {
00327 _groups.erase(group);
00328 }
00329
00330 void Roster::Item::clearGroups()
00331 {
00332 _groups.clear();
00333 }
00334
00335 bool Roster::Item::update(const Element& t)
00336 {
00337 _jid = t.getAttrib("jid");
00338
00339
00340 _nickname = t.getAttrib("name");
00341 if (_nickname == "")
00342 _nickname = _jid;
00343
00344
00345 _type = Roster::translateS10N(t.getAttrib("subscription"));
00346
00347
00348 _pending = (t.getAttrib("ask") == "subscribe");
00349
00350 _groups.clear();
00351
00352
00353 Element::const_iterator it = t.begin();
00354 for (; it != t.end(); ++it)
00355 {
00356 if ((*it)->getType() != Node::ntElement)
00357 continue;
00358 string grp_name = static_cast<Element*>(*it)->getCDATA();
00359 if (!grp_name.empty())
00360 _groups.insert(grp_name);
00361 }
00362
00363
00364 if (_pending)
00365 {
00366 _groups.insert("Pending");
00367 }
00368
00369 else if (_groups.empty())
00370 {
00371
00372
00373 if ((_jid.find("@") == string::npos) && (_jid.find("/") != string::npos))
00374 _groups.insert("Agents");
00375
00376 else
00377 _groups.insert("Unfiled");
00378 }
00379
00380 return true;
00381 }
00382
00383 bool Roster::Item::update(Roster& r, const Element& t)
00384 {
00385
00386 set<string> oldGroups = _groups;
00387
00388 update(t);
00389
00390
00391
00392 r.mergeItemGroups(_jid, oldGroups, _groups);
00393
00394 return true;
00395 }
00396
00397 void Roster::Item::update(Roster& r, const string& jid, const Presence& p, Presence::Type prev_type)
00398 {
00399 bool available = r._owner.presenceDB().available(jid);
00400
00401 if ((available == true) && (_rescnt == 0))
00402 {
00403 ++_rescnt;
00404 }
00405 else if ((available == false) && (_rescnt == 1))
00406 {
00407 --_rescnt;
00408 }
00409 r.evtPresence(jid, (_rescnt != 0), prev_type);
00410 }
00411
00412 bool Roster::Item::isAvailable() const
00413 {
00414 return (_rescnt > 0);
00415 }
00416
00417 string Roster::Item::getNickname() const
00418 {
00419 return _nickname;
00420 }
00421
00422 void Roster::Item::setNickname(const string& nickname)
00423 {
00424 _nickname = nickname;
00425 }
00426
00427 string Roster::Item::getJID() const
00428 {
00429 return _jid;
00430 }
00431
00432 void Roster::Item::setJID(const string& jid)
00433 {
00434 _jid = jid;
00435 }
00436
00437 Roster::Subscription Roster::Item::getSubsType() const
00438 {
00439 return _type;
00440 }
00441
00442 bool Roster::Item::isPending() const
00443 {
00444 return _pending;
00445 }