anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
nickcore.cpp (7420B)
1 /* 2 * 3 * (C) 2003-2022 Anope Team 4 * Contact us at team@anope.org 5 * 6 * Please read COPYING and README for further details. 7 * 8 * Based on the original code of Epona by Lara. 9 * Based on the original code of Services by Andy Church. 10 */ 11 12 #include "services.h" 13 #include "modules.h" 14 #include "account.h" 15 #include "config.h" 16 #include <climits> 17 18 Serialize::Checker<nickcore_map> NickCoreList("NickCore"); 19 nickcoreid_map NickCoreIdList; 20 21 NickCore::NickCore(const Anope::string &coredisplay, uint64_t coreid) : Serializable("NickCore"), chanaccess("ChannelInfo"), aliases("NickAlias") 22 { 23 if (coredisplay.empty()) 24 throw CoreException("Empty display passed to NickCore constructor"); 25 26 this->o = NULL; 27 this->channelcount = 0; 28 this->lastmail = 0; 29 30 this->display = coredisplay; 31 this->id = coreid; 32 33 size_t old = NickCoreList->size(); 34 (*NickCoreList)[this->display] = this; 35 if (old == NickCoreList->size()) 36 Log(LOG_DEBUG) << "Duplicate account " << coredisplay << " in nickcore table?"; 37 38 if (this->id) 39 NickCoreIdList[this->id] = this; 40 41 FOREACH_MOD(OnNickCoreCreate, (this)); 42 } 43 44 NickCore::~NickCore() 45 { 46 FOREACH_MOD(OnDelCore, (this)); 47 48 UnsetExtensibles(); 49 50 if (!this->chanaccess->empty()) 51 Log(LOG_DEBUG) << "Non-empty chanaccess list in destructor!"; 52 53 for (std::list<User *>::iterator it = this->users.begin(); it != this->users.end();) 54 { 55 User *user = *it++; 56 user->Logout(); 57 } 58 this->users.clear(); 59 60 NickCoreList->erase(this->display); 61 if (this->id) 62 NickCoreIdList.erase(this->id); 63 64 this->ClearAccess(); 65 66 if (!this->memos.memos->empty()) 67 { 68 for (unsigned i = 0, end = this->memos.memos->size(); i < end; ++i) 69 delete this->memos.GetMemo(i); 70 this->memos.memos->clear(); 71 } 72 } 73 74 void NickCore::Serialize(Serialize::Data &data) const 75 { 76 data["display"] << this->display; 77 data["uniqueid"] << this->id; 78 data["pass"] << this->pass; 79 data["email"] << this->email; 80 data["language"] << this->language; 81 for (unsigned i = 0; i < this->access.size(); ++i) 82 data["access"] << this->access[i] << " "; 83 data["memomax"] << this->memos.memomax; 84 for (unsigned i = 0; i < this->memos.ignores.size(); ++i) 85 data["memoignores"] << this->memos.ignores[i] << " "; 86 Extensible::ExtensibleSerialize(this, this, data); 87 } 88 89 Serializable* NickCore::Unserialize(Serializable *obj, Serialize::Data &data) 90 { 91 NickCore *nc; 92 93 Anope::string sdisplay; 94 data["display"] >> sdisplay; 95 96 uint64_t sid = 0; 97 data["uniqueid"] >> sid; 98 99 if (obj) 100 nc = anope_dynamic_static_cast<NickCore *>(obj); 101 else 102 nc = new NickCore(sdisplay, sid); 103 104 data["pass"] >> nc->pass; 105 data["email"] >> nc->email; 106 data["language"] >> nc->language; 107 { 108 Anope::string buf; 109 data["access"] >> buf; 110 spacesepstream sep(buf); 111 nc->access.clear(); 112 while (sep.GetToken(buf)) 113 nc->access.push_back(buf); 114 } 115 data["memomax"] >> nc->memos.memomax; 116 { 117 Anope::string buf; 118 data["memoignores"] >> buf; 119 spacesepstream sep(buf); 120 nc->memos.ignores.clear(); 121 while (sep.GetToken(buf)) 122 nc->memos.ignores.push_back(buf); 123 } 124 125 Extensible::ExtensibleUnserialize(nc, nc, data); 126 127 /* compat */ 128 bool b; 129 b = false; 130 data["extensible:SECURE"] >> b; 131 if (b) 132 nc->Extend<bool>("NS_SECURE"); 133 b = false; 134 data["extensible:PRIVATE"] >> b; 135 if (b) 136 nc->Extend<bool>("NS_PRIVATE"); 137 b = false; 138 data["extensible:AUTOOP"] >> b; 139 if (b) 140 nc->Extend<bool>("AUTOOP"); 141 b = false; 142 data["extensible:HIDE_EMAIL"] >> b; 143 if (b) 144 nc->Extend<bool>("HIDE_EMAIL"); 145 b = false; 146 data["extensible:HIDE_QUIT"] >> b; 147 if (b) 148 nc->Extend<bool>("HIDE_QUIT"); 149 b = false; 150 data["extensible:MEMO_RECEIVE"] >> b; 151 if (b) 152 nc->Extend<bool>("MEMO_RECEIVE"); 153 b = false; 154 data["extensible:MEMO_SIGNON"] >> b; 155 if (b) 156 nc->Extend<bool>("MEMO_SIGNON"); 157 b = false; 158 data["extensible:KILLPROTECT"] >> b; 159 if (b) 160 nc->Extend<bool>("KILLPROTECT"); 161 /* end compat */ 162 163 return nc; 164 } 165 166 void NickCore::SetDisplay(const NickAlias *na) 167 { 168 if (na->nc != this || na->nick == this->display) 169 return; 170 171 FOREACH_MOD(OnChangeCoreDisplay, (this, na->nick)); 172 173 /* this affects the serialized aliases */ 174 for (unsigned i = 0; i < aliases->size(); ++i) 175 aliases->at(i)->QueueUpdate(); 176 177 /* Remove the core from the list */ 178 NickCoreList->erase(this->display); 179 180 this->display = na->nick; 181 182 (*NickCoreList)[this->display] = this; 183 } 184 185 bool NickCore::IsServicesOper() const 186 { 187 return this->o != NULL; 188 } 189 190 void NickCore::AddAccess(const Anope::string &entry) 191 { 192 this->access.push_back(entry); 193 FOREACH_MOD(OnNickAddAccess, (this, entry)); 194 } 195 196 Anope::string NickCore::GetAccess(unsigned entry) const 197 { 198 if (this->access.empty() || entry >= this->access.size()) 199 return ""; 200 return this->access[entry]; 201 } 202 203 unsigned NickCore::GetAccessCount() const 204 { 205 return this->access.size(); 206 } 207 208 bool NickCore::FindAccess(const Anope::string &entry) 209 { 210 for (unsigned i = 0, end = this->access.size(); i < end; ++i) 211 if (this->access[i] == entry) 212 return true; 213 214 return false; 215 } 216 217 void NickCore::EraseAccess(const Anope::string &entry) 218 { 219 for (unsigned i = 0, end = this->access.size(); i < end; ++i) 220 if (this->access[i] == entry) 221 { 222 FOREACH_MOD(OnNickEraseAccess, (this, entry)); 223 this->access.erase(this->access.begin() + i); 224 break; 225 } 226 } 227 228 void NickCore::ClearAccess() 229 { 230 FOREACH_MOD(OnNickClearAccess, (this)); 231 this->access.clear(); 232 } 233 234 bool NickCore::IsOnAccess(const User *u) const 235 { 236 Anope::string buf = u->GetIdent() + "@" + u->host, buf2, buf3; 237 if (!u->vhost.empty()) 238 buf2 = u->GetIdent() + "@" + u->vhost; 239 if (!u->GetCloakedHost().empty()) 240 buf3 = u->GetIdent() + "@" + u->GetCloakedHost(); 241 242 for (unsigned i = 0, end = this->access.size(); i < end; ++i) 243 { 244 Anope::string a = this->GetAccess(i); 245 if (Anope::Match(buf, a) || (!buf2.empty() && Anope::Match(buf2, a)) || (!buf3.empty() && Anope::Match(buf3, a))) 246 return true; 247 } 248 return false; 249 } 250 251 void NickCore::AddChannelReference(ChannelInfo *ci) 252 { 253 ++(*this->chanaccess)[ci]; 254 } 255 256 void NickCore::RemoveChannelReference(ChannelInfo *ci) 257 { 258 int& i = (*this->chanaccess)[ci]; 259 if (--i <= 0) 260 this->chanaccess->erase(ci); 261 } 262 263 void NickCore::GetChannelReferences(std::deque<ChannelInfo *> &queue) 264 { 265 queue.clear(); 266 for (std::map<ChannelInfo *, int>::iterator it = this->chanaccess->begin(), it_end = this->chanaccess->end(); it != it_end; ++it) 267 queue.push_back(it->first); 268 } 269 270 NickCore* NickCore::Find(const Anope::string &nick) 271 { 272 nickcore_map::const_iterator it = NickCoreList->find(nick); 273 if (it != NickCoreList->end()) 274 { 275 it->second->QueueUpdate(); 276 return it->second; 277 } 278 279 return NULL; 280 } 281 282 uint64_t NickCore::GetId() 283 { 284 if (this->id) 285 return this->id; 286 287 NickAlias *na = NickAlias::Find(this->display); 288 if (!na) 289 { 290 Log(LOG_DEBUG) << "Unable to find the display NickAlias for NickCore: " << this->display; 291 return 0; 292 } 293 294 Anope::string secretid = this->display + "\0" + stringify(na->time_registered); 295 296 // Generate the account id. This should almost always only have one 297 // iteration but in the rare case that we generate a duplicate id we try 298 // again with a new key. 299 while (!this->id) 300 { 301 // Generate a random key for SipHash. 302 char key[16]; 303 for (size_t i = 0; i < sizeof(key); ++i) 304 key[i] = rand() % CHAR_MAX; 305 306 uint64_t newid = Anope::SipHash24(secretid.c_str(), secretid.length(), key); 307 nickcoreid_map::const_iterator it = NickCoreIdList.find(newid); 308 if (it == NickCoreIdList.end()) 309 { 310 this->id = newid; 311 NickCoreIdList[this->id] = this; 312 this->QueueUpdate(); 313 break; 314 } 315 } 316 317 return this->id; 318 }