userrec.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047
  1. /*
  2. * userrec.c -- handles:
  3. * add_q() del_q() str2flags() flags2str() str2chflags() chflags2str()
  4. * a bunch of functions to find and change user records
  5. * change and check user (and channel-specific) flags
  6. *
  7. */
  8. #include <sys/stat.h>
  9. #include "main.h"
  10. #include "users.h"
  11. #include "chan.h"
  12. #include "modules.h"
  13. #include "tandem.h"
  14. extern struct dcc_t *dcc;
  15. extern struct chanset_t *chanset;
  16. extern int default_flags, default_uflags, quiet_save,
  17. dcc_total, share_greet;
  18. extern char userfile[], ver[], botnetnick[];
  19. extern time_t now;
  20. int noshare = 1; /* don't send out to sharebots */
  21. int sort_users = 1; /* sort the userlist when saving */
  22. struct userrec *userlist = NULL; /* user records are stored here */
  23. struct userrec *lastuser = NULL; /* last accessed user record */
  24. maskrec *global_bans = NULL,
  25. *global_exempts = NULL,
  26. *global_invites = NULL;
  27. struct igrec *global_ign = NULL;
  28. int cache_hit = 0,
  29. cache_miss = 0; /* temporary cache accounting */
  30. int strict_host = 0;
  31. int userfile_perm = 0600; /* Userfile permissions,
  32. default rw------- */
  33. #ifdef S_DCCPASS
  34. extern struct cmd_pass *cmdpass;
  35. #endif
  36. void *_user_malloc(int size, const char *file, int line)
  37. {
  38. #ifdef DEBUG_MEM
  39. char x[1024];
  40. const char *p;
  41. p = strrchr(file, '/');
  42. simple_sprintf(x, "userrec.c:%s", p ? p + 1 : file);
  43. return n_malloc(size, x, line);
  44. #else
  45. return nmalloc(size);
  46. #endif
  47. }
  48. void *_user_realloc(void *ptr, int size, const char *file, int line)
  49. {
  50. #ifdef DEBUG_MEM
  51. char x[1024];
  52. const char *p;
  53. p = strrchr(file, '/');
  54. simple_sprintf(x, "userrec.c:%s", p ? p + 1 : file);
  55. return n_realloc(ptr, size, x, line);
  56. #else
  57. return nrealloc(ptr, size);
  58. #endif
  59. }
  60. inline int expmem_mask(struct maskrec *m)
  61. {
  62. int result = 0;
  63. while (m) {
  64. result += sizeof(struct maskrec);
  65. result += strlen(m->mask) + 1;
  66. if (m->user)
  67. result += strlen(m->user) + 1;
  68. if (m->desc)
  69. result += strlen(m->desc) + 1;
  70. m = m->next;
  71. }
  72. return result;
  73. }
  74. /* Memory we should be using
  75. */
  76. int expmem_users()
  77. {
  78. int tot;
  79. struct userrec *u;
  80. struct chanuserrec *ch;
  81. struct chanset_t *chan;
  82. struct user_entry *ue;
  83. struct igrec *i;
  84. Context;
  85. tot = 0;
  86. u = userlist;
  87. while (u != NULL) {
  88. ch = u->chanrec;
  89. Context;
  90. while (ch) {
  91. tot += sizeof(struct chanuserrec);
  92. if (ch->info != NULL)
  93. tot += strlen(ch->info) + 1;
  94. ch = ch->next;
  95. }
  96. tot += sizeof(struct userrec);
  97. Context;
  98. for (ue = u->entries; ue; ue = ue->next) {
  99. tot += sizeof(struct user_entry);
  100. Context;
  101. if (ue->name) {
  102. Context;
  103. tot += strlen(ue->name) + 1;
  104. tot += list_type_expmem(ue->u.list);
  105. } else {
  106. Context;
  107. tot += ue->type->expmem(ue);
  108. }
  109. }
  110. u = u->next;
  111. }
  112. /* account for each channel's masks */
  113. Context;
  114. for (chan = chanset; chan; chan = chan->next) {
  115. Context;
  116. /* account for each channel's ban-list user */
  117. tot += expmem_mask(chan->bans);
  118. /* account for each channel's exempt-list user */
  119. tot += expmem_mask(chan->exempts);
  120. /* account for each channel's invite-list user */
  121. tot += expmem_mask(chan->invites);
  122. }
  123. tot += expmem_mask(global_bans);
  124. tot += expmem_mask(global_exempts);
  125. tot += expmem_mask(global_invites);
  126. Context;
  127. for (i = global_ign; i; i = i->next) {
  128. tot += sizeof(struct igrec);
  129. tot += strlen(i->igmask) + 1;
  130. if (i->user)
  131. tot += strlen(i->user) + 1;
  132. if (i->msg)
  133. tot += strlen(i->msg) + 1;
  134. }
  135. Context;
  136. return tot;
  137. }
  138. int count_users(struct userrec *bu)
  139. {
  140. int tot = 0;
  141. struct userrec *u ;
  142. for (u = bu; u; u = u->next)
  143. tot++;
  144. return tot;
  145. }
  146. /* Convert "nick!~user@host", "nick!+user@host" and "nick!-user@host"
  147. * to "nick!user@host" if necessary. (drummer)
  148. */
  149. char *fixfrom(char *s)
  150. {
  151. char *p;
  152. static char buf[512];
  153. if (s == NULL)
  154. return NULL;
  155. strncpyz(buf, s, sizeof buf);
  156. if (strict_host)
  157. return buf;
  158. if ((p = strchr(buf, '!')))
  159. p++;
  160. else
  161. p = s; /* Sometimes we get passed just a
  162. * user@host here... */
  163. /* These are ludicrous. */
  164. if (strchr("~+-^=", *p) && (p[1] != '@')) /* added check for @ - drummer */
  165. strcpy(p, p + 1);
  166. /* Bug was: n!~@host -> n!@host now: n!~@host */
  167. return buf;
  168. }
  169. struct userrec *check_dcclist_hand(char *handle)
  170. {
  171. int i;
  172. for (i = 0; i < dcc_total; i++)
  173. if (!egg_strcasecmp(dcc[i].nick, handle))
  174. return dcc[i].user;
  175. return NULL;
  176. }
  177. struct userrec *get_user_by_handle(struct userrec *bu, char *handle)
  178. {
  179. struct userrec *u, *ret;
  180. if (!handle)
  181. return NULL;
  182. /* FIXME: This should be done outside of this function. */
  183. rmspace(handle);
  184. if (!handle[0] || (handle[0] == '*'))
  185. return NULL;
  186. if (bu == userlist) {
  187. if (lastuser && !egg_strcasecmp(lastuser->handle, handle)) {
  188. cache_hit++;
  189. return lastuser;
  190. }
  191. ret = check_dcclist_hand(handle);
  192. if (ret) {
  193. cache_hit++;
  194. return ret;
  195. }
  196. ret = check_chanlist_hand(handle);
  197. if (ret) {
  198. cache_hit++;
  199. return ret;
  200. }
  201. cache_miss++;
  202. }
  203. for (u = bu; u; u = u->next)
  204. if (!egg_strcasecmp(u->handle, handle)) {
  205. if (bu == userlist)
  206. lastuser = u;
  207. return u;
  208. }
  209. return NULL;
  210. }
  211. /* Fix capitalization, etc
  212. */
  213. void correct_handle(char *handle)
  214. {
  215. struct userrec *u;
  216. u = get_user_by_handle(userlist, handle);
  217. if (u == NULL)
  218. return;
  219. strcpy(handle, u->handle);
  220. }
  221. /* This will be usefull in a lot of places, much more code re-use so we
  222. * endup with a smaller executable bot. <cybah>
  223. */
  224. void clear_masks(maskrec *m)
  225. {
  226. maskrec *temp = NULL;
  227. for (; m; m = temp) {
  228. temp = m->next;
  229. if (m->mask)
  230. nfree(m->mask);
  231. if (m->user)
  232. nfree(m->user);
  233. if (m->desc)
  234. nfree(m->desc);
  235. nfree(m);
  236. }
  237. }
  238. void clear_userlist(struct userrec *bu)
  239. {
  240. struct userrec *u, *v;
  241. int i;
  242. for (u = bu; u; u = v) {
  243. v = u->next;
  244. freeuser(u);
  245. }
  246. if (userlist == bu) {
  247. struct chanset_t *cst;
  248. for (i = 0; i < dcc_total; i++)
  249. dcc[i].user = NULL;
  250. clear_chanlist();
  251. lastuser = NULL;
  252. while (global_ign)
  253. delignore(global_ign->igmask);
  254. clear_masks(global_bans);
  255. clear_masks(global_exempts);
  256. clear_masks(global_invites);
  257. global_exempts = global_invites = global_bans = NULL;
  258. for (cst = chanset; cst; cst = cst->next) {
  259. clear_masks(cst->bans);
  260. clear_masks(cst->exempts);
  261. clear_masks(cst->invites);
  262. cst->bans = cst->exempts = cst->invites = NULL;
  263. }
  264. }
  265. /* Remember to set your userlist to NULL after calling this */
  266. }
  267. /* Find CLOSEST host match
  268. * (if "*!*@*" and "*!*@*clemson.edu" both match, use the latter!)
  269. *
  270. * Checks the chanlist first, to possibly avoid needless search.
  271. */
  272. struct userrec *get_user_by_host(char *host)
  273. {
  274. struct userrec *u, *ret;
  275. struct list_type *q;
  276. int cnt, i;
  277. char host2[UHOSTLEN];
  278. if (host == NULL)
  279. return NULL;
  280. rmspace(host);
  281. if (!host[0])
  282. return NULL;
  283. ret = check_chanlist(host);
  284. cnt = 0;
  285. if (ret != NULL) {
  286. cache_hit++;
  287. return ret;
  288. }
  289. cache_miss++;
  290. strncpyz(host2, host, sizeof host2);
  291. host = fixfrom(host);
  292. for (u = userlist; u; u = u->next) {
  293. q = get_user(&USERENTRY_HOSTS, u);
  294. for (; q; q = q->next) {
  295. i = wild_match(q->extra, host);
  296. if (i > cnt) {
  297. ret = u;
  298. cnt = i;
  299. }
  300. }
  301. }
  302. if (ret != NULL) {
  303. lastuser = ret;
  304. set_chanlist(host2, ret);
  305. }
  306. return ret;
  307. }
  308. /* use fixfrom() or dont? (drummer)
  309. */
  310. struct userrec *get_user_by_equal_host(char *host)
  311. {
  312. struct userrec *u;
  313. struct list_type *q;
  314. for (u = userlist; u; u = u->next)
  315. for (q = get_user(&USERENTRY_HOSTS, u); q; q = q->next)
  316. if (!rfc_casecmp(q->extra, host))
  317. return u;
  318. return NULL;
  319. }
  320. /* Try: pass_match_by_host("-",host)
  321. * will return 1 if no password is set for that host
  322. */
  323. int u_pass_match(struct userrec *u, char *pass)
  324. {
  325. char *cmp, new[32];
  326. if (!u)
  327. return 0;
  328. cmp = get_user(&USERENTRY_PASS, u);
  329. if (!cmp && (!pass[0] || (pass[0] == '-')))
  330. return 1;
  331. if (!cmp || !pass || !pass[0] || (pass[0] == '-'))
  332. return 0;
  333. if (u->flags & USER_BOT) {
  334. if (!strcmp(cmp, pass))
  335. return 1;
  336. } else {
  337. if (strlen(pass) > 15)
  338. pass[15] = 0;
  339. encrypt_pass(pass, new);
  340. if (!strcmp(cmp, new))
  341. return 1;
  342. }
  343. return 0;
  344. }
  345. int write_user(struct userrec *u, FILE * f, int idx)
  346. {
  347. char s[181];
  348. struct chanuserrec *ch;
  349. struct chanset_t *cst;
  350. struct user_entry *ue;
  351. struct flag_record fr = {FR_GLOBAL, 0, 0, 0, 0, 0};
  352. fr.global = u->flags;
  353. fr.udef_global = u->flags_udef;
  354. build_flags(s, &fr, NULL);
  355. if (lfprintf(f, "%-10s - %-24s\n", u->handle, s) == EOF)
  356. return 0;
  357. for (ch = u->chanrec; ch; ch = ch->next) {
  358. cst = findchan_by_dname(ch->channel);
  359. if (cst && ((idx < 0) || channel_shared(cst))) {
  360. if (idx >= 0) {
  361. fr.match = (FR_CHAN | FR_BOT);
  362. get_user_flagrec(dcc[idx].user, &fr, ch->channel);
  363. } else
  364. fr.chan = BOT_SHARE;
  365. if ((fr.chan & BOT_SHARE) || (1)) {
  366. fr.match = FR_CHAN;
  367. fr.chan = ch->flags;
  368. fr.udef_chan = ch->flags_udef;
  369. build_flags(s, &fr, NULL);
  370. if (lfprintf(f, "! %-20s %lu %-10s %s\n", ch->channel, ch->laston, s,
  371. (((idx < 0) || share_greet) && ch->info) ? ch->info
  372. : "") == EOF)
  373. return 0;
  374. }
  375. }
  376. }
  377. for (ue = u->entries; ue; ue = ue->next) {
  378. if (ue->name) {
  379. struct list_type *lt;
  380. for (lt = ue->u.list; lt; lt = lt->next)
  381. if (lfprintf(f, "--%s %s\n", ue->name, lt->extra) == EOF)
  382. return 0;
  383. } else {
  384. if (!ue->type->write_userfile(f, u, ue))
  385. return 0;
  386. }
  387. }
  388. return 1;
  389. }
  390. int sort_compare(struct userrec *a, struct userrec *b)
  391. {
  392. /* Order by flags, then alphabetically
  393. * first bots: +h / +a / +l / other bots
  394. * then users: +n / +m / +o / other users
  395. * return true if (a > b)
  396. */
  397. if (a->flags & b->flags & USER_BOT) {
  398. if (~bot_flags(a) & bot_flags(b) & BOT_HUB)
  399. return 1;
  400. if (bot_flags(a) & ~bot_flags(b) & BOT_HUB)
  401. return 0;
  402. /* if (~bot_flags(a) & bot_flags(b) & BOT_ALT)
  403. return 1;
  404. if (bot_flags(a) & ~bot_flags(b) & BOT_ALT)
  405. return 0;*/
  406. if (~bot_flags(a) & bot_flags(b) & BOT_LEAF)
  407. return 1;
  408. if (bot_flags(a) & ~bot_flags(b) & BOT_LEAF)
  409. return 0;
  410. } else {
  411. if (~a->flags & b->flags & USER_BOT)
  412. return 1;
  413. if (a->flags & ~b->flags & USER_BOT)
  414. return 0;
  415. if (~a->flags & b->flags & USER_OWNER)
  416. return 1;
  417. if (a->flags & ~b->flags & USER_OWNER)
  418. return 0;
  419. if (~a->flags & b->flags & USER_MASTER)
  420. return 1;
  421. if (a->flags & ~b->flags & USER_MASTER)
  422. return 0;
  423. if (~a->flags & b->flags & USER_OP)
  424. return 1;
  425. if (a->flags & ~b->flags & USER_OP)
  426. return 0;
  427. }
  428. return (egg_strcasecmp(a->handle, b->handle) > 0);
  429. }
  430. void sort_userlist()
  431. {
  432. int again;
  433. struct userrec *last, *p, *c, *n;
  434. again = 1;
  435. last = NULL;
  436. while ((userlist != last) && (again)) {
  437. p = NULL;
  438. c = userlist;
  439. n = c->next;
  440. again = 0;
  441. while (n != last) {
  442. if (sort_compare(c, n)) {
  443. again = 1;
  444. c->next = n->next;
  445. n->next = c;
  446. if (p == NULL)
  447. userlist = n;
  448. else
  449. p->next = n;
  450. }
  451. p = c;
  452. c = n;
  453. n = n->next;
  454. }
  455. last = c;
  456. }
  457. }
  458. /* Rewrite the entire user file. Call USERFILE hook as well, probably
  459. * causing the channel file to be rewritten as well.
  460. */
  461. void write_userfile(int idx)
  462. {
  463. FILE *f;
  464. char *new_userfile;
  465. char s1[81];
  466. time_t tt;
  467. struct userrec *u;
  468. int ok;
  469. if (userlist == NULL)
  470. return; /* No point in saving userfile */
  471. new_userfile = nmalloc(strlen(userfile) + 5);
  472. sprintf(new_userfile, "%s~new", userfile);
  473. f = fopen(new_userfile, "w");
  474. chmod(new_userfile, 0600);
  475. if (f == NULL) {
  476. putlog(LOG_MISC, "*", USERF_ERRWRITE);
  477. nfree(new_userfile);
  478. return;
  479. }
  480. if (!quiet_save)
  481. putlog(LOG_MISC, "*", USERF_WRITING);
  482. if (sort_users)
  483. sort_userlist();
  484. tt = now;
  485. strcpy(s1, ctime(&tt));
  486. lfprintf(f, "#4v: %s -- %s -- written %s", ver, botnetnick, s1);
  487. ok = 1;
  488. fclose(f);
  489. call_hook(HOOK_USERFILE);
  490. f = fopen(new_userfile, "a");
  491. putlog(LOG_DEBUG, "@", "Writing user entries.");
  492. for (u = userlist; u && ok; u = u->next)
  493. ok = write_user(u, f, idx);
  494. if (!ok || fflush(f)) {
  495. putlog(LOG_MISC, "*", "%s (%s)", USERF_ERRWRITE, strerror(ferror(f)));
  496. fclose(f);
  497. nfree(new_userfile);
  498. return;
  499. }
  500. lfprintf(f, "#DONT DELETE THIS LINE.");
  501. fclose(f);
  502. putlog(LOG_DEBUG, "@", "Done writing userfile.");
  503. movefile(new_userfile, userfile);
  504. nfree(new_userfile);
  505. }
  506. int change_handle(struct userrec *u, char *newh)
  507. {
  508. int i;
  509. char s[HANDLEN + 1];
  510. if (!u)
  511. return 0;
  512. /* Nothing that will confuse the userfile */
  513. if (!newh[1] && strchr(BADHANDCHARS, newh[0]))
  514. return 0;
  515. check_tcl_nkch(u->handle, newh);
  516. /* Yes, even send bot nick changes now: */
  517. if (!noshare && !(u->flags & USER_UNSHARED))
  518. shareout(NULL, "h %s %s\n", u->handle, newh);
  519. strncpyz(s, u->handle, sizeof s);
  520. strncpyz(u->handle, newh, sizeof u->handle);
  521. for (i = 0; i < dcc_total; i++)
  522. if (dcc[i].type != &DCC_BOT && !egg_strcasecmp(dcc[i].nick, s)) {
  523. strncpyz(dcc[i].nick, newh, sizeof dcc[i].nick);
  524. if (dcc[i].type == &DCC_CHAT && dcc[i].u.chat->channel >= 0) {
  525. chanout_but(-1, dcc[i].u.chat->channel,
  526. "*** Handle change: %s -> %s\n", s, newh);
  527. if (dcc[i].u.chat->channel < GLOBAL_CHANS)
  528. botnet_send_nkch(i, s);
  529. }
  530. }
  531. return 1;
  532. }
  533. struct userrec *adduser(struct userrec *bu, char *handle, char *host,
  534. char *pass, int flags)
  535. {
  536. struct userrec *u, *x;
  537. // struct xtra_key *xk;
  538. int oldshare = noshare;
  539. noshare = 1;
  540. u = (struct userrec *) nmalloc(sizeof(struct userrec));
  541. /* u->next=bu; bu=u; */
  542. strncpyz(u->handle, handle, sizeof u->handle);
  543. u->next = NULL;
  544. u->chanrec = NULL;
  545. u->entries = NULL;
  546. if (flags != USER_DEFAULT) { /* drummer */
  547. u->flags = flags;
  548. u->flags_udef = 0;
  549. } else {
  550. u->flags = default_flags;
  551. u->flags_udef = default_uflags;
  552. }
  553. set_user(&USERENTRY_PASS, u, pass);
  554. /* Strip out commas -- they're illegal */
  555. if (host && host[0]) {
  556. char *p;
  557. /* About this fixfrom():
  558. * We should use this fixfrom before every call of adduser()
  559. * but its much easier to use here... (drummer)
  560. * Only use it if we have a host :) (dw)
  561. */
  562. host = fixfrom(host);
  563. p = strchr(host, ',');
  564. while (p != NULL) {
  565. *p = '?';
  566. p = strchr(host, ',');
  567. }
  568. set_user(&USERENTRY_HOSTS, u, host);
  569. } else
  570. set_user(&USERENTRY_HOSTS, u, "none");
  571. if (bu == userlist)
  572. clear_chanlist();
  573. noshare = oldshare;
  574. if ((!noshare) && (handle[0] != '*') && (!(flags & USER_UNSHARED)) &&
  575. (bu == userlist)) {
  576. struct flag_record fr = {FR_GLOBAL, 0, 0, 0, 0, 0};
  577. char x[100];
  578. fr.global = u->flags;
  579. fr.udef_global = u->flags_udef;
  580. build_flags(x, &fr, 0);
  581. shareout(NULL, "n %s %s %s %s\n", handle, host && host[0] ? host : "none",
  582. pass, x);
  583. }
  584. if (bu == NULL)
  585. bu = u;
  586. else {
  587. if ((bu == userlist) && (lastuser != NULL))
  588. x = lastuser;
  589. else
  590. x = bu;
  591. while (x->next != NULL)
  592. x = x->next;
  593. x->next = u;
  594. if (bu == userlist)
  595. lastuser = u;
  596. }
  597. return bu;
  598. }
  599. void freeuser(struct userrec *u)
  600. {
  601. struct user_entry *ue, *ut;
  602. struct chanuserrec *ch, *z;
  603. Context;
  604. if (u == NULL)
  605. return;
  606. ch = u->chanrec;
  607. while (ch) {
  608. z = ch;
  609. ch = ch->next;
  610. if (z->info != NULL)
  611. nfree(z->info);
  612. nfree(z);
  613. }
  614. u->chanrec = NULL;
  615. for (ue = u->entries; ue; ue = ut) {
  616. ut = ue->next;
  617. if (ue->name) {
  618. struct list_type *lt, *ltt;
  619. for (lt = ue->u.list; lt; lt = ltt) {
  620. ltt = lt->next;
  621. nfree(lt->extra);
  622. nfree(lt);
  623. }
  624. nfree(ue->name);
  625. nfree(ue);
  626. } else {
  627. Context;
  628. ue->type->kill(ue);
  629. Context;
  630. }
  631. }
  632. nfree(u);
  633. }
  634. int deluser(char *handle)
  635. {
  636. struct userrec *u = userlist, *prev = NULL;
  637. int fnd = 0;
  638. while ((u != NULL) && (!fnd)) {
  639. if (!egg_strcasecmp(u->handle, handle))
  640. fnd = 1;
  641. else {
  642. prev = u;
  643. u = u->next;
  644. }
  645. }
  646. if (!fnd)
  647. return 0;
  648. if (prev == NULL)
  649. userlist = u->next;
  650. else
  651. prev->next = u->next;
  652. if (!noshare && (handle[0] != '*') && !(u->flags & USER_UNSHARED))
  653. shareout(NULL, "k %s\n", handle);
  654. for (fnd = 0; fnd < dcc_total; fnd++)
  655. if (dcc[fnd].user == u)
  656. dcc[fnd].user = 0; /* Clear any dcc users for this entry,
  657. * null is safe-ish */
  658. clear_chanlist();
  659. freeuser(u);
  660. lastuser = NULL;
  661. return 1;
  662. }
  663. int delhost_by_handle(char *handle, char *host)
  664. {
  665. struct userrec *u;
  666. struct list_type *q, *qnext, *qprev;
  667. struct user_entry *e = NULL;
  668. int i = 0;
  669. u = get_user_by_handle(userlist, handle);
  670. if (!u)
  671. return 0;
  672. q = get_user(&USERENTRY_HOSTS, u);
  673. qprev = q;
  674. if (q) {
  675. if (!rfc_casecmp(q->extra, host)) {
  676. e = find_user_entry(&USERENTRY_HOSTS, u);
  677. e->u.extra = q->next;
  678. nfree(q->extra);
  679. nfree(q);
  680. i++;
  681. qprev = NULL;
  682. q = e->u.extra;
  683. } else
  684. q = q->next;
  685. while (q) {
  686. qnext = q->next;
  687. if (!rfc_casecmp(q->extra, host)) {
  688. if (qprev)
  689. qprev->next = q->next;
  690. else if (e) {
  691. e->u.extra = q->next;
  692. qprev = NULL;
  693. }
  694. nfree(q->extra);
  695. nfree(q);
  696. i++;
  697. } else
  698. qprev = q;
  699. q = qnext;
  700. }
  701. }
  702. if (!qprev)
  703. set_user(&USERENTRY_HOSTS, u, "none");
  704. if (!noshare && i && !(u->flags & USER_UNSHARED))
  705. shareout(NULL, "-h %s %s\n", handle, host);
  706. clear_chanlist();
  707. return i;
  708. }
  709. void addhost_by_handle(char *handle, char *host)
  710. {
  711. struct userrec *u = get_user_by_handle(userlist, handle);
  712. set_user(&USERENTRY_HOSTS, u, host);
  713. /* u will be cached, so really no overhead, even tho this looks dumb: */
  714. if ((!noshare) && !(u->flags & USER_UNSHARED)) {
  715. if (u->flags & USER_BOT)
  716. shareout(NULL, "+bh %s %s\n", handle, host);
  717. else
  718. shareout(NULL, "+h %s %s\n", handle, host);
  719. }
  720. clear_chanlist();
  721. }
  722. void touch_laston(struct userrec *u, char *where, time_t timeval)
  723. {
  724. if (!u)
  725. return;
  726. if (timeval > 1) {
  727. struct laston_info *li =
  728. (struct laston_info *) get_user(&USERENTRY_LASTON, u);
  729. if (!li)
  730. li = nmalloc(sizeof(struct laston_info));
  731. else if (li->lastonplace)
  732. nfree(li->lastonplace);
  733. li->laston = timeval;
  734. if (where) {
  735. li->lastonplace = nmalloc(strlen(where) + 1);
  736. strcpy(li->lastonplace, where);
  737. } else
  738. li->lastonplace = NULL;
  739. set_user(&USERENTRY_LASTON, u, li);
  740. // if(li->lastonplace)
  741. // nfree(li->lastonplace);
  742. } else if (timeval == 1) {
  743. set_user(&USERENTRY_LASTON, u, 0);
  744. }
  745. }
  746. /* Go through all channel records and try to find a matching
  747. * nick. Will return the user's user record if that is known
  748. * to the bot. (Fabian)
  749. *
  750. * Warning: This is unreliable by concept!
  751. */
  752. struct userrec *get_user_by_nick(char *nick)
  753. {
  754. struct chanset_t *chan;
  755. memberlist *m;
  756. for (chan = chanset; chan; chan = chan->next) {
  757. for (m = chan->channel.member; m && m->nick[0] ;m = m->next) {
  758. if (!rfc_casecmp(nick, m->nick)) {
  759. char word[512];
  760. egg_snprintf(word, sizeof word, "%s!%s", m->nick, m->userhost);
  761. /* No need to check the return value ourself */
  762. return get_user_by_host(word);;
  763. }
  764. }
  765. }
  766. /* Sorry, no matches */
  767. return NULL;
  768. }
  769. void user_del_chan(char *dname)
  770. {
  771. struct chanuserrec *ch, *och;
  772. struct userrec *u;
  773. for (u = userlist; u; u = u->next) {
  774. ch = u->chanrec;
  775. och = NULL;
  776. while (ch) {
  777. if (!rfc_casecmp(dname, ch->channel)) {
  778. if (och)
  779. och->next = ch->next;
  780. else
  781. u->chanrec = ch->next;
  782. if (ch->info)
  783. nfree(ch->info);
  784. nfree(ch);
  785. break;
  786. }
  787. och = ch;
  788. ch = ch->next;
  789. }
  790. }
  791. }
  792. struct cfg_entry
  793. CFG_BADCOOKIE,
  794. CFG_MANUALOP,
  795. #ifdef G_MEAN
  796. CFG_MEANDEOP,
  797. CFG_MEANKICK,
  798. CFG_MEANBAN,
  799. #endif
  800. CFG_MDOP;
  801. int deflag_dontshare=0;
  802. char deflag_tmp[20];
  803. #define DEFL_IGNORE 0
  804. #define DEFL_DEOP 1
  805. #define DEFL_KICK 2
  806. #define DEFL_DELETE 3
  807. void deflag_describe(struct cfg_entry *cfgent, int idx)
  808. {
  809. if (cfgent == &CFG_BADCOOKIE)
  810. dprintf(idx, STR("bad-cookie decides what happens to a bot if it does an illegal op (no/incorrect op cookie)\n"));
  811. else if (cfgent==&CFG_MANUALOP)
  812. dprintf(idx, STR("manop decides what happens to a user doing a manual op in a -manop channel\n"));
  813. #ifdef G_MEAN
  814. else if (cfgent==&CFG_MEANDEOP)
  815. dprintf(idx, STR("mean-deop decides what happens to a user deopping a bot in a +mean channel\n"));
  816. else if (cfgent==&CFG_MEANKICK)
  817. dprintf(idx, STR("mean-kick decides what happens to a user kicking a bot in a +mean channel\n"));
  818. else if (cfgent==&CFG_MEANBAN)
  819. dprintf(idx, STR("mean-ban decides what happens to a user banning a bot in a +mean channel\n"));
  820. #endif
  821. else if (cfgent==&CFG_MDOP)
  822. dprintf(idx, STR("mdop decides what happens to a user doing a mass deop\n"));
  823. dprintf(idx, STR("Valid settings are: ignore (No flag changes), deop (give -fmnop+d), kick (give -fmnop+dk) or delete (remove from userlist)\n"));
  824. }
  825. void deflag_changed(struct cfg_entry * entry, char * oldval, int * valid) {
  826. char * p = (char *) entry->gdata;
  827. if (!p)
  828. return;
  829. if (strcmp(p, STR("ignore")) && strcmp(p, STR("deop")) && strcmp(p, STR("kick")) && strcmp(p, STR("delete")))
  830. *valid=0;
  831. }
  832. struct cfg_entry CFG_BADCOOKIE = {
  833. "bad-cookie", CFGF_GLOBAL, NULL, NULL,
  834. deflag_changed,
  835. NULL,
  836. deflag_describe
  837. };
  838. struct cfg_entry CFG_MANUALOP = {
  839. "manop", CFGF_GLOBAL, NULL, NULL,
  840. deflag_changed,
  841. NULL,
  842. deflag_describe
  843. };
  844. #ifdef G_MEAN
  845. struct cfg_entry CFG_MEANDEOP = {
  846. "mean-deop", CFGF_GLOBAL, NULL, NULL,
  847. deflag_changed,
  848. NULL,
  849. deflag_describe
  850. };
  851. struct cfg_entry CFG_MEANKICK = {
  852. "mean-kick", CFGF_GLOBAL, NULL, NULL,
  853. deflag_changed,
  854. NULL,
  855. deflag_describe
  856. };
  857. struct cfg_entry CFG_MEANBAN = {
  858. "mean-ban", CFGF_GLOBAL, NULL, NULL,
  859. deflag_changed,
  860. NULL,
  861. deflag_describe
  862. };
  863. #endif
  864. struct cfg_entry CFG_MDOP = {
  865. "mdop", CFGF_GLOBAL, NULL, NULL,
  866. deflag_changed,
  867. NULL,
  868. deflag_describe
  869. };
  870. void deflag_user(struct userrec *u, int why, char *msg, struct chanset_t *chan)
  871. {
  872. char tmp[256], tmp2[1024];
  873. struct cfg_entry * ent = NULL;
  874. struct flag_record fr = {FR_GLOBAL, FR_CHAN, 0, 0, 0};
  875. if (!u)
  876. return;
  877. switch (why) {
  878. case DEFLAG_BADCOOKIE:
  879. strcpy(tmp, STR("Bad op cookie"));
  880. ent=&CFG_BADCOOKIE;
  881. break;
  882. case DEFLAG_MANUALOP:
  883. strcpy(tmp, STR("Manual op in -manop channel"));
  884. ent=&CFG_MANUALOP;
  885. break;
  886. #ifdef G_MEAN
  887. case DEFLAG_MEAN_DEOP:
  888. strcpy(tmp, STR("Deopped bot in +mean channel"));
  889. ent=&CFG_MEANDEOP;
  890. break;
  891. case DEFLAG_MEAN_KICK:
  892. strcpy(tmp, STR("Kicked bot in +mean channel"));
  893. ent=&CFG_MEANDEOP;
  894. break;
  895. case DEFLAG_MEAN_BAN:
  896. strcpy(tmp, STR("Banned bot in +mean channel"));
  897. ent=&CFG_MEANDEOP;
  898. break;
  899. #endif
  900. case DEFLAG_MDOP:
  901. strcpy(tmp, STR("Mass deop"));
  902. ent=&CFG_MDOP;
  903. break;
  904. default:
  905. ent=NULL;
  906. sprintf(tmp, STR("Reason #%i"), why);
  907. }
  908. if (ent && ent->gdata && !strcmp(ent->gdata, STR("deop"))) {
  909. putlog(LOG_WARN, "*", STR("Setting %s +d (%s): %s\n"), u->handle, tmp, msg);
  910. sprintf(tmp2, STR("+d: %s (%s)"), tmp, msg);
  911. set_user(&USERENTRY_COMMENT, u, tmp2);
  912. get_user_flagrec(u, &fr, chan->dname);
  913. fr.global = USER_DEOP;
  914. fr.chan = USER_DEOP;
  915. set_user_flagrec(u, &fr, chan->dname);
  916. } else if (ent && ent->gdata && !strcmp(ent->gdata, STR("kick"))) {
  917. putlog(LOG_WARN, "*", STR("Setting %s +dk (%s): %s\n"), u->handle, tmp, msg);
  918. sprintf(tmp2, STR("+dk: %s (%s)"), tmp, msg);
  919. set_user(&USERENTRY_COMMENT, u, tmp2);
  920. get_user_flagrec(u, &fr, chan->dname);
  921. fr.global = USER_DEOP | USER_KICK;
  922. fr.chan = USER_DEOP | USER_KICK;
  923. set_user_flagrec(u, &fr, chan->dname);
  924. } else if (ent && ent->gdata && !strcmp(ent->gdata, STR("delete"))) {
  925. putlog(LOG_WARN, "*", STR("Deleting %s (%s): %s\n"), u->handle, tmp, msg);
  926. deluser(u->handle);
  927. } else {
  928. putlog(LOG_WARN, "*", STR("No user flag effects for %s (%s): %s\n"), u->handle, tmp, msg);
  929. sprintf(tmp2, STR("Warning: %s (%s)"), tmp, msg);
  930. set_user(&USERENTRY_COMMENT, u, tmp2);
  931. }
  932. }
  933. void init_userrec() {
  934. add_cfg(&CFG_BADCOOKIE);
  935. add_cfg(&CFG_MANUALOP);
  936. #ifdef G_MEAN
  937. add_cfg(&CFG_MEANDEOP);
  938. add_cfg(&CFG_MEANKICK);
  939. add_cfg(&CFG_MEANBAN);
  940. #endif
  941. add_cfg(&CFG_MDOP);
  942. }