anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
db_old.cpp (31723B)
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 "module.h" 13 #include "modules/os_session.h" 14 #include "modules/bs_kick.h" 15 #include "modules/cs_mode.h" 16 #include "modules/bs_badwords.h" 17 #include "modules/os_news.h" 18 #include "modules/suspend.h" 19 #include "modules/os_forbid.h" 20 #include "modules/cs_entrymsg.h" 21 22 #define READ(x) \ 23 if (true) \ 24 { \ 25 if ((x) < 0) \ 26 printf("Error, the database is broken, line %d, trying to continue... no guarantee.\n", __LINE__); \ 27 } \ 28 else \ 29 static_cast<void>(0) 30 31 #define getc_db(f) (fgetc((f)->fp)) 32 #define read_db(f, buf, len) (fread((buf), 1, (len), (f)->fp)) 33 #define read_buffer(buf, f) ((read_db((f), (buf), sizeof(buf)) == sizeof(buf)) ? 0 : -1) 34 35 #define OLD_BI_PRIVATE 0x0001 36 37 #define OLD_NI_KILLPROTECT 0x00000001 /* Kill others who take this nick */ 38 #define OLD_NI_SECURE 0x00000002 /* Don't recognize unless IDENTIFY'd */ 39 #define OLD_NI_MSG 0x00000004 /* Use PRIVMSGs instead of NOTICEs */ 40 #define OLD_NI_MEMO_HARDMAX 0x00000008 /* Don't allow user to change memo limit */ 41 #define OLD_NI_MEMO_SIGNON 0x00000010 /* Notify of memos at signon and un-away */ 42 #define OLD_NI_MEMO_RECEIVE 0x00000020 /* Notify of new memos when sent */ 43 #define OLD_NI_PRIVATE 0x00000040 /* Don't show in LIST to non-servadmins */ 44 #define OLD_NI_HIDE_EMAIL 0x00000080 /* Don't show E-mail in INFO */ 45 #define OLD_NI_HIDE_MASK 0x00000100 /* Don't show last seen address in INFO */ 46 #define OLD_NI_HIDE_QUIT 0x00000200 /* Don't show last quit message in INFO */ 47 #define OLD_NI_KILL_QUICK 0x00000400 /* Kill in 20 seconds instead of 60 */ 48 #define OLD_NI_KILL_IMMED 0x00000800 /* Kill immediately instead of in 60 sec */ 49 #define OLD_NI_MEMO_MAIL 0x00010000 /* User gets email on memo */ 50 #define OLD_NI_HIDE_STATUS 0x00020000 /* Don't show services access status */ 51 #define OLD_NI_SUSPENDED 0x00040000 /* Nickname is suspended */ 52 #define OLD_NI_AUTOOP 0x00080000 /* Autoop nickname in channels */ 53 54 #define OLD_NS_NO_EXPIRE 0x0004 /* nick won't expire */ 55 #define OLD_NS_VERBOTEN 0x0002 56 57 #define OLD_CI_KEEPTOPIC 0x00000001 58 #define OLD_CI_SECUREOPS 0x00000002 59 #define OLD_CI_PRIVATE 0x00000004 60 #define OLD_CI_TOPICLOCK 0x00000008 61 #define OLD_CI_RESTRICTED 0x00000010 62 #define OLD_CI_PEACE 0x00000020 63 #define OLD_CI_SECURE 0x00000040 64 #define OLD_CI_VERBOTEN 0x00000080 65 #define OLD_CI_ENCRYPTEDPW 0x00000100 66 #define OLD_CI_NO_EXPIRE 0x00000200 67 #define OLD_CI_MEMO_HARDMAX 0x00000400 68 #define OLD_CI_OPNOTICE 0x00000800 69 #define OLD_CI_SECUREFOUNDER 0x00001000 70 #define OLD_CI_SIGNKICK 0x00002000 71 #define OLD_CI_SIGNKICK_LEVEL 0x00004000 72 #define OLD_CI_XOP 0x00008000 73 #define OLD_CI_SUSPENDED 0x00010000 74 75 /* BotServ SET flags */ 76 #define OLD_BS_DONTKICKOPS 0x00000001 77 #define OLD_BS_DONTKICKVOICES 0x00000002 78 #define OLD_BS_FANTASY 0x00000004 79 #define OLD_BS_SYMBIOSIS 0x00000008 80 #define OLD_BS_GREET 0x00000010 81 #define OLD_BS_NOBOT 0x00000020 82 83 /* BotServ Kickers flags */ 84 #define OLD_BS_KICK_BOLDS 0x80000000 85 #define OLD_BS_KICK_COLORS 0x40000000 86 #define OLD_BS_KICK_REVERSES 0x20000000 87 #define OLD_BS_KICK_UNDERLINES 0x10000000 88 #define OLD_BS_KICK_BADWORDS 0x08000000 89 #define OLD_BS_KICK_CAPS 0x04000000 90 #define OLD_BS_KICK_FLOOD 0x02000000 91 #define OLD_BS_KICK_REPEAT 0x01000000 92 93 #define OLD_NEWS_LOGON 0 94 #define OLD_NEWS_OPER 1 95 #define OLD_NEWS_RANDOM 2 96 97 static struct mlock_info 98 { 99 char c; 100 uint32_t m; 101 } mlock_infos[] = { 102 {'i', 0x00000001}, 103 {'m', 0x00000002}, 104 {'n', 0x00000004}, 105 {'p', 0x00000008}, 106 {'s', 0x00000010}, 107 {'t', 0x00000020}, 108 {'R', 0x00000100}, 109 {'r', 0x00000200}, 110 {'c', 0x00000400}, 111 {'A', 0x00000800}, 112 {'K', 0x00002000}, 113 {'O', 0x00008000}, 114 {'Q', 0x00010000}, 115 {'S', 0x00020000}, 116 {'G', 0x00100000}, 117 {'C', 0x00200000}, 118 {'u', 0x00400000}, 119 {'z', 0x00800000}, 120 {'N', 0x01000000}, 121 {'M', 0x04000000} 122 }; 123 124 static Anope::string hashm; 125 126 enum 127 { 128 LANG_EN_US, /* United States English */ 129 LANG_JA_JIS, /* Japanese (JIS encoding) */ 130 LANG_JA_EUC, /* Japanese (EUC encoding) */ 131 LANG_JA_SJIS, /* Japanese (SJIS encoding) */ 132 LANG_ES, /* Spanish */ 133 LANG_PT, /* Portugese */ 134 LANG_FR, /* French */ 135 LANG_TR, /* Turkish */ 136 LANG_IT, /* Italian */ 137 LANG_DE, /* German */ 138 LANG_CAT, /* Catalan */ 139 LANG_GR, /* Greek */ 140 LANG_NL, /* Dutch */ 141 LANG_RU, /* Russian */ 142 LANG_HUN, /* Hungarian */ 143 LANG_PL /* Polish */ 144 }; 145 146 static void process_mlock(ChannelInfo *ci, uint32_t lock, bool status, uint32_t *limit, Anope::string *key) 147 { 148 ModeLocks *ml = ci->Require<ModeLocks>("modelocks"); 149 for (unsigned i = 0; i < (sizeof(mlock_infos) / sizeof(mlock_info)); ++i) 150 if (lock & mlock_infos[i].m) 151 { 152 ChannelMode *cm = ModeManager::FindChannelModeByChar(mlock_infos[i].c); 153 if (cm && ml) 154 { 155 if (limit && mlock_infos[i].c == 'l') 156 ml->SetMLock(cm, status, stringify(*limit)); 157 else if (key && mlock_infos[i].c == 'k') 158 ml->SetMLock(cm, status, *key); 159 else 160 ml->SetMLock(cm, status); 161 } 162 } 163 } 164 165 static const char Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 166 static const char Pad64 = '='; 167 168 static void my_b64_encode(const Anope::string &src, Anope::string &target) 169 { 170 size_t src_pos = 0, src_len = src.length(); 171 unsigned char input[3]; 172 173 target.clear(); 174 175 while (src_len - src_pos > 2) 176 { 177 input[0] = src[src_pos++]; 178 input[1] = src[src_pos++]; 179 input[2] = src[src_pos++]; 180 181 target += Base64[input[0] >> 2]; 182 target += Base64[((input[0] & 0x03) << 4) + (input[1] >> 4)]; 183 target += Base64[((input[1] & 0x0f) << 2) + (input[2] >> 6)]; 184 target += Base64[input[2] & 0x3f]; 185 } 186 187 /* Now we worry about padding */ 188 if (src_pos != src_len) 189 { 190 input[0] = input[1] = input[2] = 0; 191 for (size_t i = 0; i < src_len - src_pos; ++i) 192 input[i] = src[src_pos + i]; 193 194 target += Base64[input[0] >> 2]; 195 target += Base64[((input[0] & 0x03) << 4) + (input[1] >> 4)]; 196 if (src_pos == src_len - 1) 197 target += Pad64; 198 else 199 target += Base64[((input[1] & 0x0f) << 2) + (input[2] >> 6)]; 200 target += Pad64; 201 } 202 } 203 204 static Anope::string Hex(const char *data, size_t l) 205 { 206 const char hextable[] = "0123456789abcdef"; 207 208 std::string rv; 209 for (size_t i = 0; i < l; ++i) 210 { 211 unsigned char c = data[i]; 212 rv += hextable[c >> 4]; 213 rv += hextable[c & 0xF]; 214 } 215 return rv; 216 } 217 218 static Anope::string GetLevelName(int level) 219 { 220 switch (level) 221 { 222 case 0: 223 return "INVITE"; 224 case 1: 225 return "AKICK"; 226 case 2: 227 return "SET"; 228 case 3: 229 return "UNBAN"; 230 case 4: 231 return "AUTOOP"; 232 case 5: 233 return "AUTODEOP"; 234 case 6: 235 return "AUTOVOICE"; 236 case 7: 237 return "OP"; 238 case 8: 239 return "ACCESS_LIST"; 240 case 9: 241 return "CLEAR"; 242 case 10: 243 return "NOJOIN"; 244 case 11: 245 return "ACCESS_CHANGE"; 246 case 12: 247 return "MEMO"; 248 case 13: 249 return "ASSIGN"; 250 case 14: 251 return "BADWORDS"; 252 case 15: 253 return "NOKICK"; 254 case 16: 255 return "FANTASIA"; 256 case 17: 257 return "SAY"; 258 case 18: 259 return "GREET"; 260 case 19: 261 return "VOICEME"; 262 case 20: 263 return "VOICE"; 264 case 21: 265 return "GETKEY"; 266 case 22: 267 return "AUTOHALFOP"; 268 case 23: 269 return "AUTOPROTECT"; 270 case 24: 271 return "OPME"; 272 case 25: 273 return "HALFOPME"; 274 case 26: 275 return "HALFOP"; 276 case 27: 277 return "PROTECTME"; 278 case 28: 279 return "PROTECT"; 280 case 29: 281 return "KICKME"; 282 case 30: 283 return "KICK"; 284 case 31: 285 return "SIGNKICK"; 286 case 32: 287 return "BANME"; 288 case 33: 289 return "BAN"; 290 case 34: 291 return "TOPIC"; 292 case 35: 293 return "INFO"; 294 default: 295 return "INVALID"; 296 } 297 } 298 299 static char *strscpy(char *d, const char *s, size_t len) 300 { 301 char *d_orig = d; 302 303 if (!len) 304 return d; 305 while (--len && (*d++ = *s++)); 306 *d = '\0'; 307 return d_orig; 308 } 309 310 struct dbFILE 311 { 312 int mode; /* 'r' for reading, 'w' for writing */ 313 FILE *fp; /* The normal file descriptor */ 314 char filename[1024]; /* Name of the database file */ 315 }; 316 317 static dbFILE *open_db_read(const char *service, const char *filename, int version) 318 { 319 dbFILE *f; 320 FILE *fp; 321 int myversion; 322 323 f = new dbFILE; 324 strscpy(f->filename, (Anope::DataDir + "/" + filename).c_str(), sizeof(f->filename)); 325 f->mode = 'r'; 326 fp = fopen(f->filename, "rb"); 327 if (!fp) 328 { 329 Log() << "Can't read " << service << " database " << f->filename; 330 delete f; 331 return NULL; 332 } 333 f->fp = fp; 334 myversion = fgetc(fp) << 24 | fgetc(fp) << 16 | fgetc(fp) << 8 | fgetc(fp); 335 if (feof(fp)) 336 { 337 Log() << "Error reading version number on " << f->filename << ": End of file detected."; 338 delete f; 339 return NULL; 340 } 341 else if (myversion < version) 342 { 343 Log() << "Unsupported database version (" << myversion << ") on " << f->filename << "."; 344 delete f; 345 return NULL; 346 } 347 return f; 348 } 349 350 void close_db(dbFILE *f) 351 { 352 fclose(f->fp); 353 delete f; 354 } 355 356 static int read_int16(int16_t *ret, dbFILE *f) 357 { 358 int c1, c2; 359 360 *ret = 0; 361 362 c1 = fgetc(f->fp); 363 c2 = fgetc(f->fp); 364 if (c1 == EOF || c2 == EOF) 365 return -1; 366 *ret = c1 << 8 | c2; 367 return 0; 368 } 369 370 static int read_uint16(uint16_t *ret, dbFILE *f) 371 { 372 int c1, c2; 373 374 *ret = 0; 375 376 c1 = fgetc(f->fp); 377 c2 = fgetc(f->fp); 378 if (c1 == EOF || c2 == EOF) 379 return -1; 380 *ret = c1 << 8 | c2; 381 return 0; 382 } 383 384 static int read_string(Anope::string &str, dbFILE *f) 385 { 386 str.clear(); 387 uint16_t len; 388 389 if (read_uint16(&len, f) < 0) 390 return -1; 391 if (len == 0) 392 return 0; 393 char *s = new char[len]; 394 if (len != fread(s, 1, len, f->fp)) 395 { 396 delete [] s; 397 return -1; 398 } 399 str = s; 400 delete [] s; 401 return 0; 402 } 403 404 static int read_uint32(uint32_t *ret, dbFILE *f) 405 { 406 int c1, c2, c3, c4; 407 408 *ret = 0; 409 410 c1 = fgetc(f->fp); 411 c2 = fgetc(f->fp); 412 c3 = fgetc(f->fp); 413 c4 = fgetc(f->fp); 414 if (c1 == EOF || c2 == EOF || c3 == EOF || c4 == EOF) 415 return -1; 416 *ret = c1 << 24 | c2 << 16 | c3 << 8 | c4; 417 return 0; 418 } 419 420 int read_int32(int32_t *ret, dbFILE *f) 421 { 422 int c1, c2, c3, c4; 423 424 *ret = 0; 425 426 c1 = fgetc(f->fp); 427 c2 = fgetc(f->fp); 428 c3 = fgetc(f->fp); 429 c4 = fgetc(f->fp); 430 if (c1 == EOF || c2 == EOF || c3 == EOF || c4 == EOF) 431 return -1; 432 *ret = c1 << 24 | c2 << 16 | c3 << 8 | c4; 433 return 0; 434 } 435 436 static void LoadNicks() 437 { 438 ServiceReference<ForbidService> forbid("ForbidService", "forbid"); 439 dbFILE *f = open_db_read("NickServ", "nick.db", 14); 440 if (f == NULL) 441 return; 442 for (int i = 0; i < 1024; ++i) 443 for (int c; (c = getc_db(f)) == 1;) 444 { 445 Anope::string buffer; 446 447 READ(read_string(buffer, f)); 448 NickCore *nc = new NickCore(buffer); 449 450 const Anope::string settings[] = { "killprotect", "kill_quick", "ns_secure", "ns_private", "hide_email", 451 "hide_mask", "hide_quit", "memo_signon", "memo_receive", "autoop", "msg", "ns_keepmodes" }; 452 for (unsigned j = 0; j < sizeof(settings) / sizeof(Anope::string); ++j) 453 nc->Shrink<bool>(settings[j].upper()); 454 455 char pwbuf[32]; 456 READ(read_buffer(pwbuf, f)); 457 if (hashm == "plain") 458 my_b64_encode(pwbuf, nc->pass); 459 else if (hashm == "md5" || hashm == "oldmd5") 460 nc->pass = Hex(pwbuf, 16); 461 else if (hashm == "sha1") 462 nc->pass = Hex(pwbuf, 20); 463 else 464 nc->pass = Hex(pwbuf, strlen(pwbuf)); 465 nc->pass = hashm + ":" + nc->pass; 466 467 READ(read_string(buffer, f)); 468 nc->email = buffer; 469 470 READ(read_string(buffer, f)); 471 if (!buffer.empty()) 472 nc->Extend<Anope::string>("greet", buffer); 473 474 uint32_t u32; 475 READ(read_uint32(&u32, f)); 476 //nc->icq = u32; 477 478 READ(read_string(buffer, f)); 479 //nc->url = buffer; 480 481 READ(read_uint32(&u32, f)); 482 if (u32 & OLD_NI_KILLPROTECT) 483 nc->Extend<bool>("KILLPROTECT"); 484 if (u32 & OLD_NI_SECURE) 485 nc->Extend<bool>("NS_SECURE"); 486 if (u32 & OLD_NI_MSG) 487 nc->Extend<bool>("MSG"); 488 if (u32 & OLD_NI_MEMO_HARDMAX) 489 nc->Extend<bool>("MEMO_HARDMAX"); 490 if (u32 & OLD_NI_MEMO_SIGNON) 491 nc->Extend<bool>("MEMO_SIGNON"); 492 if (u32 & OLD_NI_MEMO_RECEIVE) 493 nc->Extend<bool>("MEMO_RECEIVE"); 494 if (u32 & OLD_NI_PRIVATE) 495 nc->Extend<bool>("NS_PRIVATE"); 496 if (u32 & OLD_NI_HIDE_EMAIL) 497 nc->Extend<bool>("HIDE_EMAIL"); 498 if (u32 & OLD_NI_HIDE_MASK) 499 nc->Extend<bool>("HIDE_MASK"); 500 if (u32 & OLD_NI_HIDE_QUIT) 501 nc->Extend<bool>("HIDE_QUIT"); 502 if (u32 & OLD_NI_KILL_QUICK) 503 nc->Extend<bool>("KILL_QUICK"); 504 if (u32 & OLD_NI_KILL_IMMED) 505 nc->Extend<bool>("KILL_IMMED"); 506 if (u32 & OLD_NI_MEMO_MAIL) 507 nc->Extend<bool>("MEMO_MAIL"); 508 if (u32 & OLD_NI_HIDE_STATUS) 509 nc->Extend<bool>("HIDE_STATUS"); 510 if (u32 & OLD_NI_SUSPENDED) 511 { 512 SuspendInfo si; 513 si.what = nc->display; 514 si.when = si.expires = 0; 515 nc->Extend("NS_SUSPENDED", si); 516 } 517 if (!(u32 & OLD_NI_AUTOOP)) 518 nc->Extend<bool>("AUTOOP"); 519 520 uint16_t u16; 521 READ(read_uint16(&u16, f)); 522 switch (u16) 523 { 524 case LANG_ES: 525 nc->language = "es_ES.UTF-8"; 526 break; 527 case LANG_PT: 528 nc->language = "pt_PT.UTF-8"; 529 break; 530 case LANG_FR: 531 nc->language = "fr_FR.UTF-8"; 532 break; 533 case LANG_TR: 534 nc->language = "tr_TR.UTF-8"; 535 break; 536 case LANG_IT: 537 nc->language = "it_IT.UTF-8"; 538 break; 539 case LANG_DE: 540 nc->language = "de_DE.UTF-8"; 541 break; 542 case LANG_CAT: 543 nc->language = "ca_ES.UTF-8"; // yes, iso639 defines catalan as CA 544 break; 545 case LANG_GR: 546 nc->language = "el_GR.UTF-8"; 547 break; 548 case LANG_NL: 549 nc->language = "nl_NL.UTF-8"; 550 break; 551 case LANG_RU: 552 nc->language = "ru_RU.UTF-8"; 553 break; 554 case LANG_HUN: 555 nc->language = "hu_HU.UTF-8"; 556 break; 557 case LANG_PL: 558 nc->language = "pl_PL.UTF-8"; 559 break; 560 case LANG_EN_US: 561 case LANG_JA_JIS: 562 case LANG_JA_EUC: 563 case LANG_JA_SJIS: // these seem to be unused 564 default: 565 nc->language = "en"; 566 } 567 568 READ(read_uint16(&u16, f)); 569 for (uint16_t j = 0; j < u16; ++j) 570 { 571 READ(read_string(buffer, f)); 572 nc->access.push_back(buffer); 573 } 574 575 int16_t i16; 576 READ(read_int16(&i16, f)); 577 READ(read_int16(&nc->memos.memomax, f)); 578 for (int16_t j = 0; j < i16; ++j) 579 { 580 Memo *m = new Memo; 581 READ(read_uint32(&u32, f)); 582 uint16_t flags; 583 READ(read_uint16(&flags, f)); 584 int32_t tmp32; 585 READ(read_int32(&tmp32, f)); 586 m->time = tmp32; 587 char sbuf[32]; 588 READ(read_buffer(sbuf, f)); 589 m->sender = sbuf; 590 READ(read_string(m->text, f)); 591 m->owner = nc->display; 592 nc->memos.memos->push_back(m); 593 m->mi = &nc->memos; 594 } 595 READ(read_uint16(&u16, f)); 596 READ(read_int16(&i16, f)); 597 598 Log(LOG_DEBUG) << "Loaded NickCore " << nc->display; 599 } 600 601 for (int i = 0; i < 1024; ++i) 602 for (int c; (c = getc_db(f)) == 1;) 603 { 604 Anope::string nick, last_usermask, last_realname, last_quit; 605 time_t time_registered, last_seen; 606 607 READ(read_string(nick, f)); 608 READ(read_string(last_usermask, f)); 609 READ(read_string(last_realname, f)); 610 READ(read_string(last_quit, f)); 611 612 int32_t tmp32; 613 READ(read_int32(&tmp32, f)); 614 time_registered = tmp32; 615 READ(read_int32(&tmp32, f)); 616 last_seen = tmp32; 617 618 uint16_t tmpu16; 619 READ(read_uint16(&tmpu16, f)); 620 621 Anope::string core; 622 READ(read_string(core, f)); 623 NickCore *nc = NickCore::Find(core); 624 if (nc == NULL) 625 { 626 Log() << "Skipping coreless nick " << nick << " with core " << core; 627 continue; 628 } 629 630 if (tmpu16 & OLD_NS_VERBOTEN) 631 { 632 if (!forbid) 633 { 634 delete nc; 635 continue; 636 } 637 638 if (nc->display.find_first_of("?*") != Anope::string::npos) 639 { 640 delete nc; 641 continue; 642 } 643 644 ForbidData *d = forbid->CreateForbid(); 645 d->mask = nc->display; 646 d->creator = last_usermask; 647 d->reason = last_realname; 648 d->expires = 0; 649 d->created = 0; 650 d->type = FT_NICK; 651 delete nc; 652 forbid->AddForbid(d); 653 continue; 654 } 655 656 NickAlias *na = new NickAlias(nick, nc); 657 na->last_usermask = last_usermask; 658 na->last_realname = last_realname; 659 na->last_quit = last_quit; 660 na->time_registered = time_registered; 661 na->last_seen = last_seen; 662 663 if (tmpu16 & OLD_NS_NO_EXPIRE) 664 na->Extend<bool>("NS_NO_EXPIRE"); 665 666 Log(LOG_DEBUG) << "Loaded NickAlias " << na->nick; 667 } 668 669 close_db(f); /* End of section Ia */ 670 } 671 672 static void LoadVHosts() 673 { 674 dbFILE *f = open_db_read("HostServ", "hosts.db", 3); 675 if (f == NULL) 676 return; 677 678 for (int c; (c = getc_db(f)) == 1;) 679 { 680 Anope::string nick, ident, host, creator; 681 int32_t vtime; 682 683 READ(read_string(nick, f)); 684 READ(read_string(ident, f)); 685 READ(read_string(host, f)); 686 READ(read_string(creator, f)); 687 READ(read_int32(&vtime, f)); 688 689 NickAlias *na = NickAlias::Find(nick); 690 if (na == NULL) 691 { 692 Log() << "Removing vhost for nonexistent nick " << nick; 693 continue; 694 } 695 696 na->SetVhost(ident, host, creator, vtime); 697 698 Log() << "Loaded vhost for " << na->nick; 699 } 700 701 close_db(f); 702 } 703 704 static void LoadBots() 705 { 706 dbFILE *f = open_db_read("Botserv", "bot.db", 10); 707 if (f == NULL) 708 return; 709 710 for (int c; (c = getc_db(f)) == 1;) 711 { 712 Anope::string nick, user, host, real; 713 int16_t flags, chancount; 714 int32_t created; 715 716 READ(read_string(nick, f)); 717 READ(read_string(user, f)); 718 READ(read_string(host, f)); 719 READ(read_string(real, f)); 720 READ(read_int16(&flags, f)); 721 READ(read_int32(&created, f)); 722 READ(read_int16(&chancount, f)); 723 724 BotInfo *bi = BotInfo::Find(nick, true); 725 if (!bi) 726 bi = new BotInfo(nick, user, host, real); 727 bi->created = created; 728 729 if (flags & OLD_BI_PRIVATE) 730 bi->oper_only = true; 731 732 Log(LOG_DEBUG) << "Loaded bot " << bi->nick; 733 } 734 735 close_db(f); 736 } 737 738 static void LoadChannels() 739 { 740 ServiceReference<ForbidService> forbid("ForbidService", "forbid"); 741 dbFILE *f = open_db_read("ChanServ", "chan.db", 16); 742 if (f == NULL) 743 return; 744 745 for (int i = 0; i < 256; ++i) 746 for (int c; (c = getc_db(f)) == 1;) 747 { 748 Anope::string buffer; 749 char namebuf[64]; 750 READ(read_buffer(namebuf, f)); 751 ChannelInfo *ci = new ChannelInfo(namebuf); 752 753 const Anope::string settings[] = { "keeptopic", "peace", "cs_private", "restricted", "cs_secure", "secureops", "securefounder", 754 "signkick", "signkick_level", "topiclock", "persist", "noautoop", "cs_keepmodes" }; 755 for (unsigned j = 0; j < sizeof(settings) / sizeof(Anope::string); ++j) 756 ci->Shrink<bool>(settings[j].upper()); 757 758 READ(read_string(buffer, f)); 759 ci->SetFounder(NickCore::Find(buffer)); 760 761 READ(read_string(buffer, f)); 762 ci->SetSuccessor(NickCore::Find(buffer)); 763 764 char pwbuf[32]; 765 READ(read_buffer(pwbuf, f)); 766 767 READ(read_string(ci->desc, f)); 768 READ(read_string(buffer, f)); 769 READ(read_string(buffer, f)); 770 771 int32_t tmp32; 772 READ(read_int32(&tmp32, f)); 773 ci->time_registered = tmp32; 774 775 READ(read_int32(&tmp32, f)); 776 ci->last_used = tmp32; 777 778 READ(read_string(ci->last_topic, f)); 779 780 READ(read_buffer(pwbuf, f)); 781 ci->last_topic_setter = pwbuf; 782 783 READ(read_int32(&tmp32, f)); 784 ci->last_topic_time = tmp32; 785 786 uint32_t tmpu32; 787 READ(read_uint32(&tmpu32, f)); 788 // Temporary flags cleanup 789 tmpu32 &= ~0x80000000; 790 if (tmpu32 & OLD_CI_KEEPTOPIC) 791 ci->Extend<bool>("KEEPTOPIC"); 792 if (tmpu32 & OLD_CI_SECUREOPS) 793 ci->Extend<bool>("SECUREOPS"); 794 if (tmpu32 & OLD_CI_PRIVATE) 795 ci->Extend<bool>("CS_PRIVATE"); 796 if (tmpu32 & OLD_CI_TOPICLOCK) 797 ci->Extend<bool>("TOPICLOCK"); 798 if (tmpu32 & OLD_CI_RESTRICTED) 799 ci->Extend<bool>("RESTRICTED"); 800 if (tmpu32 & OLD_CI_PEACE) 801 ci->Extend<bool>("PEACE"); 802 if (tmpu32 & OLD_CI_SECURE) 803 ci->Extend<bool>("CS_SECURE"); 804 if (tmpu32 & OLD_CI_NO_EXPIRE) 805 ci->Extend<bool>("CS_NO_EXPIRE"); 806 if (tmpu32 & OLD_CI_MEMO_HARDMAX) 807 ci->Extend<bool>("MEMO_HARDMAX"); 808 if (tmpu32 & OLD_CI_SECUREFOUNDER) 809 ci->Extend<bool>("SECUREFOUNDER"); 810 if (tmpu32 & OLD_CI_SIGNKICK) 811 ci->Extend<bool>("SIGNKICK"); 812 if (tmpu32 & OLD_CI_SIGNKICK_LEVEL) 813 ci->Extend<bool>("SIGNKICK_LEVEL"); 814 815 Anope::string forbidby, forbidreason; 816 READ(read_string(forbidby, f)); 817 READ(read_string(forbidreason, f)); 818 if (tmpu32 & OLD_CI_SUSPENDED) 819 { 820 SuspendInfo si; 821 si.what = ci->name; 822 si.by = forbidby; 823 si.reason = forbidreason; 824 si.when = si.expires = 0; 825 ci->Extend("CS_SUSPENDED", si); 826 } 827 bool forbid_chan = tmpu32 & OLD_CI_VERBOTEN; 828 829 int16_t tmp16; 830 READ(read_int16(&tmp16, f)); 831 ci->bantype = tmp16; 832 833 READ(read_int16(&tmp16, f)); 834 if (tmp16 > 36) 835 tmp16 = 36; 836 for (int16_t j = 0; j < tmp16; ++j) 837 { 838 int16_t level; 839 READ(read_int16(&level, f)); 840 841 if (level == ACCESS_INVALID) 842 level = ACCESS_FOUNDER; 843 844 if (j == 10 && level < 0) // NOJOIN 845 ci->Shrink<bool>("RESTRICTED"); // If CSDefRestricted was enabled this can happen 846 847 ci->SetLevel(GetLevelName(j), level); 848 } 849 850 bool xop = tmpu32 & OLD_CI_XOP; 851 ServiceReference<AccessProvider> provider_access("AccessProvider", "access/access"), provider_xop("AccessProvider", "access/xop"); 852 uint16_t tmpu16; 853 READ(read_uint16(&tmpu16, f)); 854 for (uint16_t j = 0; j < tmpu16; ++j) 855 { 856 uint16_t in_use; 857 READ(read_uint16(&in_use, f)); 858 if (in_use) 859 { 860 ChanAccess *access = NULL; 861 862 if (xop) 863 { 864 if (provider_xop) 865 access = provider_xop->Create(); 866 } 867 else 868 if (provider_access) 869 access = provider_access->Create(); 870 871 if (access) 872 access->ci = ci; 873 874 int16_t level; 875 READ(read_int16(&level, f)); 876 if (access) 877 { 878 if (xop) 879 { 880 switch (level) 881 { 882 case 3: 883 access->AccessUnserialize("VOP"); 884 break; 885 case 4: 886 access->AccessUnserialize("HOP"); 887 break; 888 case 5: 889 access->AccessUnserialize("AOP"); 890 break; 891 case 10: 892 access->AccessUnserialize("SOP"); 893 break; 894 } 895 } 896 else 897 access->AccessUnserialize(stringify(level)); 898 } 899 900 Anope::string mask; 901 READ(read_string(mask, f)); 902 if (access) 903 access->SetMask(mask, ci); 904 905 READ(read_int32(&tmp32, f)); 906 if (access) 907 { 908 access->last_seen = tmp32; 909 access->creator = "Unknown"; 910 access->created = Anope::CurTime; 911 912 ci->AddAccess(access); 913 } 914 } 915 } 916 917 READ(read_uint16(&tmpu16, f)); 918 for (uint16_t j = 0; j < tmpu16; ++j) 919 { 920 uint16_t flags; 921 READ(read_uint16(&flags, f)); 922 if (flags & 0x0001) 923 { 924 Anope::string mask, reason, creator; 925 READ(read_string(mask, f)); 926 READ(read_string(reason, f)); 927 READ(read_string(creator, f)); 928 READ(read_int32(&tmp32, f)); 929 930 ci->AddAkick(creator, mask, reason, tmp32); 931 } 932 } 933 934 READ(read_uint32(&tmpu32, f)); // mlock on 935 ci->Extend<uint32_t>("mlock_on", tmpu32); 936 READ(read_uint32(&tmpu32, f)); // mlock off 937 ci->Extend<uint32_t>("mlock_off", tmpu32); 938 READ(read_uint32(&tmpu32, f)); // mlock limit 939 ci->Extend<uint32_t>("mlock_limit", tmpu32); 940 READ(read_string(buffer, f)); // key 941 ci->Extend<Anope::string>("mlock_key", buffer); 942 READ(read_string(buffer, f)); // +f 943 READ(read_string(buffer, f)); // +L 944 945 READ(read_int16(&tmp16, f)); 946 READ(read_int16(&ci->memos.memomax, f)); 947 for (int16_t j = 0; j < tmp16; ++j) 948 { 949 READ(read_uint32(&tmpu32, f)); 950 READ(read_uint16(&tmpu16, f)); 951 Memo *m = new Memo; 952 READ(read_int32(&tmp32, f)); 953 m->time = tmp32; 954 char sbuf[32]; 955 READ(read_buffer(sbuf, f)); 956 m->sender = sbuf; 957 READ(read_string(m->text, f)); 958 m->owner = ci->name; 959 ci->memos.memos->push_back(m); 960 m->mi = &ci->memos; 961 } 962 963 READ(read_string(buffer, f)); 964 if (!buffer.empty()) 965 { 966 EntryMessageList *eml = ci->Require<EntryMessageList>("entrymsg"); 967 if (eml) 968 { 969 EntryMsg *e = eml->Create(); 970 971 e->chan = ci->name; 972 e->creator = "Unknown"; 973 e->message = buffer; 974 e->when = Anope::CurTime; 975 976 (*eml)->push_back(e); 977 } 978 } 979 980 READ(read_string(buffer, f)); 981 ci->bi = BotInfo::Find(buffer, true); 982 983 READ(read_int32(&tmp32, f)); 984 if (tmp32 & OLD_BS_DONTKICKOPS) 985 ci->Extend<bool>("BS_DONTKICKOPS"); 986 if (tmp32 & OLD_BS_DONTKICKVOICES) 987 ci->Extend<bool>("BS_DONTKICKVOICES"); 988 if (tmp32 & OLD_BS_FANTASY) 989 ci->Extend<bool>("BS_FANTASY"); 990 if (tmp32 & OLD_BS_GREET) 991 ci->Extend<bool>("BS_GREET"); 992 if (tmp32 & OLD_BS_NOBOT) 993 ci->Extend<bool>("BS_NOBOT"); 994 995 KickerData *kd = ci->Require<KickerData>("kickerdata"); 996 if (kd) 997 { 998 if (tmp32 & OLD_BS_KICK_BOLDS) 999 kd->bolds = true; 1000 if (tmp32 & OLD_BS_KICK_COLORS) 1001 kd->colors = true; 1002 if (tmp32 & OLD_BS_KICK_REVERSES) 1003 kd->reverses = true; 1004 if (tmp32 & OLD_BS_KICK_UNDERLINES) 1005 kd->underlines = true; 1006 if (tmp32 & OLD_BS_KICK_BADWORDS) 1007 kd->badwords = true; 1008 if (tmp32 & OLD_BS_KICK_CAPS) 1009 kd->caps = true; 1010 if (tmp32 & OLD_BS_KICK_FLOOD) 1011 kd->flood = true; 1012 if (tmp32 & OLD_BS_KICK_REPEAT) 1013 kd->repeat = true; 1014 } 1015 1016 READ(read_int16(&tmp16, f)); 1017 for (int16_t j = 0; j < tmp16; ++j) 1018 { 1019 int16_t ttb; 1020 READ(read_int16(&ttb, f)); 1021 if (j < TTB_SIZE && kd) 1022 kd->ttb[j] = ttb; 1023 } 1024 1025 READ(read_int16(&tmp16, f)); 1026 if (kd) 1027 kd->capsmin = tmp16; 1028 READ(read_int16(&tmp16, f)); 1029 if (kd) 1030 kd->capspercent = tmp16; 1031 READ(read_int16(&tmp16, f)); 1032 if (kd) 1033 kd->floodlines = tmp16; 1034 READ(read_int16(&tmp16, f)); 1035 if (kd) 1036 kd->floodsecs = tmp16; 1037 READ(read_int16(&tmp16, f)); 1038 if (kd) 1039 kd->repeattimes = tmp16; 1040 1041 BadWords *bw = ci->Require<BadWords>("badwords"); 1042 READ(read_uint16(&tmpu16, f)); 1043 for (uint16_t j = 0; j < tmpu16; ++j) 1044 { 1045 uint16_t in_use; 1046 READ(read_uint16(&in_use, f)); 1047 if (in_use) 1048 { 1049 READ(read_string(buffer, f)); 1050 uint16_t type; 1051 READ(read_uint16(&type, f)); 1052 1053 BadWordType bwtype = BW_ANY; 1054 if (type == 1) 1055 bwtype = BW_SINGLE; 1056 else if (type == 2) 1057 bwtype = BW_START; 1058 else if (type == 3) 1059 bwtype = BW_END; 1060 1061 if (bw) 1062 bw->AddBadWord(buffer, bwtype); 1063 } 1064 } 1065 1066 if (forbid_chan) 1067 { 1068 if (!forbid) 1069 { 1070 delete ci; 1071 continue; 1072 } 1073 1074 if (ci->name.find_first_of("?*") != Anope::string::npos) 1075 { 1076 delete ci; 1077 continue; 1078 } 1079 1080 ForbidData *d = forbid->CreateForbid(); 1081 d->mask = ci->name; 1082 d->creator = forbidby; 1083 d->reason = forbidreason; 1084 d->expires = 0; 1085 d->created = 0; 1086 d->type = FT_CHAN; 1087 delete ci; 1088 forbid->AddForbid(d); 1089 continue; 1090 } 1091 1092 Log(LOG_DEBUG) << "Loaded channel " << ci->name; 1093 } 1094 1095 close_db(f); 1096 } 1097 1098 static void LoadOper() 1099 { 1100 dbFILE *f = open_db_read("OperServ", "oper.db", 13); 1101 if (f == NULL) 1102 return; 1103 1104 XLineManager *akill, *sqline, *snline, *szline; 1105 akill = sqline = snline = szline = NULL; 1106 1107 for (std::list<XLineManager *>::iterator it = XLineManager::XLineManagers.begin(), it_end = XLineManager::XLineManagers.end(); it != it_end; ++it) 1108 { 1109 XLineManager *xl = *it; 1110 if (xl->Type() == 'G') 1111 akill = xl; 1112 else if (xl->Type() == 'Q') 1113 sqline = xl; 1114 else if (xl->Type() == 'N') 1115 snline = xl; 1116 else if (xl->Type() == 'Z') 1117 szline = xl; 1118 } 1119 1120 int32_t tmp32; 1121 READ(read_int32(&tmp32, f)); 1122 READ(read_int32(&tmp32, f)); 1123 1124 int16_t capacity; 1125 read_int16(&capacity, f); // AKill count 1126 for (int16_t i = 0; i < capacity; ++i) 1127 { 1128 Anope::string user, host, by, reason; 1129 int32_t seton, expires; 1130 1131 READ(read_string(user, f)); 1132 READ(read_string(host, f)); 1133 READ(read_string(by, f)); 1134 READ(read_string(reason, f)); 1135 READ(read_int32(&seton, f)); 1136 READ(read_int32(&expires, f)); 1137 1138 if (!akill) 1139 continue; 1140 1141 XLine *x = new XLine(user + "@" + host, by, expires, reason, XLineManager::GenerateUID()); 1142 x->created = seton; 1143 akill->AddXLine(x); 1144 } 1145 1146 read_int16(&capacity, f); // SNLines 1147 for (int16_t i = 0; i < capacity; ++i) 1148 { 1149 Anope::string mask, by, reason; 1150 int32_t seton, expires; 1151 1152 READ(read_string(mask, f)); 1153 READ(read_string(by, f)); 1154 READ(read_string(reason, f)); 1155 READ(read_int32(&seton, f)); 1156 READ(read_int32(&expires, f)); 1157 1158 if (!snline) 1159 continue; 1160 1161 XLine *x = new XLine(mask, by, expires, reason, XLineManager::GenerateUID()); 1162 x->created = seton; 1163 snline->AddXLine(x); 1164 } 1165 1166 read_int16(&capacity, f); // SQLines 1167 for (int16_t i = 0; i < capacity; ++i) 1168 { 1169 Anope::string mask, by, reason; 1170 int32_t seton, expires; 1171 1172 READ(read_string(mask, f)); 1173 READ(read_string(by, f)); 1174 READ(read_string(reason, f)); 1175 READ(read_int32(&seton, f)); 1176 READ(read_int32(&expires, f)); 1177 1178 if (!sqline) 1179 continue; 1180 1181 XLine *x = new XLine(mask, by, expires, reason, XLineManager::GenerateUID()); 1182 x->created = seton; 1183 sqline->AddXLine(x); 1184 } 1185 1186 read_int16(&capacity, f); // SZLines 1187 for (int16_t i = 0; i < capacity; ++i) 1188 { 1189 Anope::string mask, by, reason; 1190 int32_t seton, expires; 1191 1192 READ(read_string(mask, f)); 1193 READ(read_string(by, f)); 1194 READ(read_string(reason, f)); 1195 READ(read_int32(&seton, f)); 1196 READ(read_int32(&expires, f)); 1197 1198 if (!szline) 1199 continue; 1200 1201 XLine *x = new XLine(mask, by, expires, reason, XLineManager::GenerateUID()); 1202 x->created = seton; 1203 szline->AddXLine(x); 1204 } 1205 1206 close_db(f); 1207 } 1208 1209 static void LoadExceptions() 1210 { 1211 if (!session_service) 1212 return; 1213 1214 dbFILE *f = open_db_read("OperServ", "exception.db", 9); 1215 if (f == NULL) 1216 return; 1217 1218 int16_t num; 1219 READ(read_int16(&num, f)); 1220 for (int i = 0; i < num; ++i) 1221 { 1222 Anope::string mask, reason; 1223 int16_t limit; 1224 char who[32]; 1225 int32_t time, expires; 1226 1227 READ(read_string(mask, f)); 1228 READ(read_int16(&limit, f)); 1229 READ(read_buffer(who, f)); 1230 READ(read_string(reason, f)); 1231 READ(read_int32(&time, f)); 1232 READ(read_int32(&expires, f)); 1233 1234 Exception *exception = session_service->CreateException(); 1235 exception->mask = mask; 1236 exception->limit = limit; 1237 exception->who = who; 1238 exception->time = time; 1239 exception->expires = expires; 1240 exception->reason = reason; 1241 session_service->AddException(exception); 1242 } 1243 1244 close_db(f); 1245 } 1246 1247 static void LoadNews() 1248 { 1249 if (!news_service) 1250 return; 1251 1252 dbFILE *f = open_db_read("OperServ", "news.db", 9); 1253 1254 if (f == NULL) 1255 return; 1256 1257 int16_t n; 1258 READ(read_int16(&n, f)); 1259 1260 for (int16_t i = 0; i < n; i++) 1261 { 1262 int16_t type; 1263 NewsItem *ni = news_service->CreateNewsItem(); 1264 1265 READ(read_int16(&type, f)); 1266 1267 switch (type) 1268 { 1269 case OLD_NEWS_LOGON: 1270 ni->type = NEWS_LOGON; 1271 break; 1272 case OLD_NEWS_OPER: 1273 ni->type = NEWS_OPER; 1274 break; 1275 case OLD_NEWS_RANDOM: 1276 ni->type = NEWS_RANDOM; 1277 break; 1278 } 1279 1280 int32_t unused; 1281 READ(read_int32(&unused, f)); 1282 1283 READ(read_string(ni->text, f)); 1284 1285 char who[32]; 1286 READ(read_buffer(who, f)); 1287 ni->who = who; 1288 1289 int32_t tmp; 1290 READ(read_int32(&tmp, f)); 1291 ni->time = tmp; 1292 1293 news_service->AddNewsItem(ni); 1294 } 1295 1296 close_db(f); 1297 } 1298 1299 class DBOld : public Module 1300 { 1301 PrimitiveExtensibleItem<uint32_t> mlock_on, mlock_off, mlock_limit; 1302 PrimitiveExtensibleItem<Anope::string> mlock_key; 1303 1304 public: 1305 DBOld(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE | VENDOR), 1306 mlock_on(this, "mlock_on"), mlock_off(this, "mlock_off"), mlock_limit(this, "mlock_limit"), mlock_key(this, "mlock_key") 1307 { 1308 1309 1310 hashm = Config->GetModule(this)->Get<const Anope::string>("hash"); 1311 1312 if (hashm != "md5" && hashm != "oldmd5" && hashm != "sha1" && hashm != "plain" && hashm != "sha256") 1313 throw ModuleException("Invalid hash method"); 1314 } 1315 1316 EventReturn OnLoadDatabase() anope_override 1317 { 1318 LoadNicks(); 1319 LoadVHosts(); 1320 LoadBots(); 1321 LoadChannels(); 1322 LoadOper(); 1323 LoadExceptions(); 1324 LoadNews(); 1325 1326 return EVENT_STOP; 1327 } 1328 1329 void OnUplinkSync(Server *s) anope_override 1330 { 1331 for (registered_channel_map::iterator it = RegisteredChannelList->begin(), it_end = RegisteredChannelList->end(); it != it_end; ++it) 1332 { 1333 ChannelInfo *ci = it->second; 1334 uint32_t *limit = mlock_limit.Get(ci); 1335 Anope::string *key = mlock_key.Get(ci); 1336 1337 uint32_t *u = mlock_on.Get(ci); 1338 if (u) 1339 { 1340 process_mlock(ci, *u, true, limit, key); 1341 mlock_on.Unset(ci); 1342 } 1343 1344 u = mlock_off.Get(ci); 1345 if (u) 1346 { 1347 process_mlock(ci, *u, false, limit, key); 1348 mlock_off.Unset(ci); 1349 } 1350 1351 mlock_limit.Unset(ci); 1352 mlock_key.Unset(ci); 1353 1354 if (ci->c) 1355 ci->c->CheckModes(); 1356 } 1357 } 1358 }; 1359 1360 MODULE_INIT(DBOld)