flags.cc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  1. /*
  2. * Copyright (C) 1997 Robey Pointer
  3. * Copyright (C) 1999 - 2002 Eggheads Development Team
  4. * Copyright (C) 2002 - 2014 Bryan Drewery
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19. */
  20. /*
  21. * flags.c -- handles:
  22. * all the flag matching/conversion functions in one neat package :)
  23. *
  24. */
  25. #include "common.h"
  26. #include "crypt.h"
  27. #include "src/mod/share.mod/share.h"
  28. #include "rfc1459.h"
  29. #include "userrec.h"
  30. #include "misc.h"
  31. #include "dccutil.h"
  32. #include "userent.h"
  33. #include "users.h"
  34. #include "chanprog.h"
  35. flag_t FLAG[128];
  36. struct rolecount role_counts[] = {
  37. {"voice", ROLE_VOICE, 1},
  38. {"flood", ROLE_FLOOD, 3},
  39. {"op", ROLE_OP, 1},
  40. {"deop", ROLE_DEOP, 1},
  41. {"kick", ROLE_KICK, 2},
  42. {"ban", ROLE_BAN, 2},
  43. {"topic", ROLE_TOPIC, 1},
  44. {"limit", ROLE_LIMIT, 1},
  45. {"resolv", ROLE_RESOLV, 2},
  46. {"revenge", ROLE_REVENGE, 3},
  47. {"chanmode", ROLE_CHANMODE, 1},
  48. {"protect", ROLE_PROTECT, 2},
  49. {"invite", ROLE_INVITE, 1},
  50. {NULL, 0, 0},
  51. };
  52. void
  53. init_flags()
  54. {
  55. unsigned char i;
  56. for (i = 0; i < 'A'; i++)
  57. FLAG[(int) i] = 0;
  58. for (; i <= 'Z'; i++)
  59. FLAG[(int) i] = (flag_t) 1 << (26 + (i - 'A'));
  60. for (; i < 'a'; i++)
  61. FLAG[(int) i] = 0;
  62. for (; i <= 'z'; i++)
  63. FLAG[(int) i] = (flag_t) 1 << (i - 'a');
  64. for (; i < 128; i++)
  65. FLAG[(int) i] = 0;
  66. }
  67. /* Some flags are mutually exclusive -- this roots them out
  68. */
  69. flag_t
  70. sanity_check(flag_t atr, int bot)
  71. {
  72. if (bot && (atr & (USER_PARTY | USER_MASTER | USER_OWNER | USER_ADMIN | USER_HUBA | USER_CHUBA)))
  73. atr &= ~(USER_PARTY | USER_MASTER | USER_OWNER | USER_ADMIN | USER_HUBA | USER_CHUBA);
  74. /* only bots should be there: */
  75. if (!bot && (atr & (BOT_DOLIMIT | BOT_DOVOICE | BOT_UPDATEHUB | BOT_CHANHUB | BOT_FLOODBOT )))
  76. atr &= ~(BOT_DOLIMIT | BOT_DOVOICE | BOT_UPDATEHUB | BOT_CHANHUB | BOT_FLOODBOT );
  77. if (atr & USER_AUTOOP)
  78. atr |= USER_OP;
  79. if ((atr & USER_OP) && (atr & USER_DEOP))
  80. atr &= ~(USER_OP | USER_DEOP);
  81. if ((atr & USER_AUTOOP) && (atr & USER_DEOP))
  82. atr &= ~(USER_AUTOOP | USER_DEOP);
  83. if ((atr & USER_VOICE) && (atr & USER_QUIET))
  84. atr &= ~(USER_VOICE | USER_QUIET);
  85. /* Can't be admin without also being owner and having hub access */
  86. if (atr & USER_ADMIN)
  87. atr |= USER_OWNER | USER_HUBA | USER_PARTY;
  88. /* Hub access gets chanhub access */
  89. if (atr & USER_HUBA)
  90. atr |= USER_CHUBA;
  91. if (atr & USER_OWNER) {
  92. atr |= USER_MASTER;
  93. }
  94. /* Master implies botmaster, op */
  95. if (atr & USER_MASTER)
  96. atr |= USER_OP;
  97. /* Can't be botnet master without party-line access */
  98. /* if (atr & USER_BOTMAST)
  99. atr |= USER_PARTY;
  100. */
  101. return atr;
  102. }
  103. /* Sanity check on channel attributes
  104. */
  105. flag_t
  106. chan_sanity_check(flag_t chatr, int bot)
  107. {
  108. /* these should only be global */
  109. if (chatr & (USER_PARTY | USER_ADMIN | USER_HUBA | USER_CHUBA | BOT_UPDATEHUB))
  110. chatr &= ~(USER_PARTY | USER_ADMIN | USER_HUBA | USER_CHUBA | BOT_UPDATEHUB);
  111. /* these should only be set on bots */
  112. if (!bot && (chatr & (BOT_DOLIMIT | BOT_DOVOICE | BOT_CHANHUB | BOT_FLOODBOT )))
  113. chatr &= ~(BOT_DOLIMIT | BOT_DOVOICE | BOT_CHANHUB | BOT_FLOODBOT );
  114. if ((chatr & USER_OP) && (chatr & USER_DEOP))
  115. chatr &= ~(USER_OP | USER_DEOP);
  116. if ((chatr & USER_AUTOOP) && (chatr & USER_DEOP))
  117. chatr &= ~(USER_AUTOOP | USER_DEOP);
  118. if ((chatr & USER_VOICE) && (chatr & USER_QUIET))
  119. chatr &= ~(USER_VOICE | USER_QUIET);
  120. /* Can't be channel owner without also being channel master */
  121. if (chatr & USER_OWNER)
  122. chatr |= USER_MASTER;
  123. /* Master implies op */
  124. if (chatr & USER_MASTER)
  125. chatr |= USER_OP;
  126. return chatr;
  127. }
  128. /* Get icon symbol for a user (depending on access level)
  129. *
  130. * (*) owner on any channel
  131. * (+) master on any channel
  132. * (%) botnet master
  133. * (@) op on any channel
  134. * (-) other
  135. */
  136. char
  137. geticon(int idx)
  138. {
  139. if (!dcc[idx].user)
  140. return '-';
  141. struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0 };
  142. get_user_flagrec(dcc[idx].user, &fr, NULL);
  143. if (glob_admin(fr))
  144. return '^';
  145. if (chan_owner(fr))
  146. return '*';
  147. if (chan_master(fr))
  148. return '+';
  149. if (chan_op(fr))
  150. return '@';
  151. return '-';
  152. }
  153. void
  154. break_down_flags(const char *string, struct flag_record *plus, struct flag_record *minus)
  155. {
  156. struct flag_record *which = plus;
  157. int chan = 0; /* 0 = glob, 1 = chan */
  158. int flags = plus->match;
  159. if (!(flags & FR_GLOBAL)) {
  160. if (flags & FR_CHAN)
  161. chan = 1;
  162. else
  163. return; /* We dont actually want any..huh? */
  164. }
  165. bzero(plus, sizeof(struct flag_record));
  166. if (minus)
  167. bzero(minus, sizeof(struct flag_record));
  168. plus->match = FR_OR; /* Default binding type OR */
  169. while (*string) {
  170. switch (*string) {
  171. case '+':
  172. which = plus;
  173. break;
  174. case '-':
  175. which = minus ? minus : plus;
  176. break;
  177. case '|':
  178. case '&':
  179. if (!chan) {
  180. if (*string == '|')
  181. plus->match = FR_OR;
  182. else
  183. plus->match = FR_AND;
  184. }
  185. which = plus;
  186. chan++;
  187. if (chan == 2)
  188. string = "";
  189. else if (chan == 3)
  190. chan = 1;
  191. break; /* switch() */
  192. default:
  193. {
  194. flag_t flagbit = FLAG[(int) *string];
  195. if (flagbit) {
  196. switch (chan) {
  197. case 0:
  198. /* which->global |= (flag_t) 1 << (*string - 'a'); */
  199. which->global |=flagbit;
  200. break;
  201. case 1:
  202. /* which->chan |= (flag_t) 1 << (*string - 'a'); */
  203. which->chan |= flagbit;
  204. break;
  205. }
  206. }
  207. }
  208. }
  209. string++;
  210. }
  211. for (which = plus; which; which = (which == plus ? minus : 0)) {
  212. if (flags & FR_BOT) {
  213. which->global &= BOT_VALID;
  214. which->chan &= BOT_CHAN_VALID;
  215. } else {
  216. which->global &= USER_VALID;
  217. which->chan &= USER_CHAN_VALID;
  218. }
  219. }
  220. plus->match |= flags;
  221. if (minus) {
  222. minus->match |= flags;
  223. if (!(plus->match & (FR_AND | FR_OR)))
  224. plus->match |= FR_OR;
  225. }
  226. }
  227. static int
  228. flag2str(char *string, flag_t flag)
  229. {
  230. unsigned char c;
  231. char *old = string;
  232. for (c = 0; c < 128; c++)
  233. if (flag & FLAG[(int) c])
  234. *string++ = c;
  235. if (string == old)
  236. *string++ = '-';
  237. return string - old;
  238. }
  239. int
  240. build_flags(char *string, struct flag_record *plus, struct flag_record *minus)
  241. {
  242. char *old = string;
  243. if (plus->match & FR_GLOBAL) {
  244. if (minus && plus->global)
  245. *string++ = '+';
  246. string += flag2str(string, plus->global);
  247. if (minus && minus->global) {
  248. *string++ = '-';
  249. string += flag2str(string, minus->global);
  250. }
  251. }
  252. if (plus->match & FR_CHAN) {
  253. if (plus->match & FR_GLOBAL)
  254. *string++ = (plus->match & FR_AND) ? '&' : '|';
  255. if (minus && plus->chan)
  256. *string++ = '+';
  257. string += flag2str(string, plus->chan);
  258. if (minus && minus->chan) {
  259. *string++ = '-';
  260. string += flag2str(string, minus->global);
  261. }
  262. }
  263. if (string == old) {
  264. *string++ = '-';
  265. *string = 0;
  266. return 0;
  267. }
  268. *string = 0;
  269. return string - old;
  270. }
  271. /* Returns 1 if flags match, 0 if they don't. */
  272. int
  273. flagrec_ok(const struct flag_record *req, const struct flag_record *have)
  274. {
  275. if (req->match & FR_AND) {
  276. return flagrec_eq(req, have);
  277. } else if (req->match & FR_OR) {
  278. int hav = have->global;
  279. /* no flags, is a match */
  280. if (!req->chan && !req->global)
  281. return 1;
  282. if (hav & req->global)
  283. return 1;
  284. if (have->chan & req->chan)
  285. return 1;
  286. return 0;
  287. }
  288. return 0;
  289. }
  290. /* Returns 1 if flags match, 0 if they don't. */
  291. int
  292. flagrec_eq(const struct flag_record *req, const struct flag_record *have)
  293. {
  294. if (req->match & FR_AND) {
  295. if (req->match & FR_GLOBAL) {
  296. if ((req->global &have->global) !=req->global)
  297. return 0;
  298. }
  299. if (req->match & FR_CHAN) {
  300. if ((req->chan & have->chan) != req->chan)
  301. return 0;
  302. }
  303. return 1;
  304. } else if (req->match & FR_OR) {
  305. if (!req->chan && !req->global)
  306. return 1;
  307. if (req->match & FR_GLOBAL) {
  308. if (have->global &req->global)
  309. return 1;
  310. }
  311. if (req->match & FR_CHAN) {
  312. if (have->chan & req->chan)
  313. return 1;
  314. }
  315. return 0;
  316. }
  317. return 0; /* fr0k3 binding, dont pass it */
  318. }
  319. void
  320. set_user_flagrec(struct userrec *u, struct flag_record *fr, const char *chname)
  321. {
  322. if (!u)
  323. return;
  324. struct chanuserrec *cr = NULL;
  325. flag_t oldflags = fr->match;
  326. char buffer[100] = "";
  327. struct chanset_t *ch;
  328. if (oldflags & FR_GLOBAL) {
  329. u->flags = fr->global;
  330. if (!noshare) {
  331. fr->match = FR_GLOBAL;
  332. build_flags(buffer, fr, NULL);
  333. shareout("a %s %s\n", u->handle, buffer);
  334. }
  335. }
  336. if ((oldflags & FR_CHAN) && chname) {
  337. for (cr = u->chanrec; cr; cr = cr->next)
  338. if (!rfc_casecmp(chname, cr->channel))
  339. break;
  340. ch = findchan_by_dname(chname);
  341. if (!cr && ch) {
  342. cr = (struct chanuserrec *) calloc(1, sizeof(struct chanuserrec));
  343. cr->next = u->chanrec;
  344. u->chanrec = cr;
  345. strlcpy(cr->channel, chname, sizeof cr->channel);
  346. }
  347. if (cr && ch) {
  348. cr->flags = fr->chan;
  349. if (!noshare) {
  350. fr->match = FR_CHAN;
  351. build_flags(buffer, fr, NULL);
  352. shareout("a %s %s %s\n", u->handle, buffer, chname);
  353. }
  354. }
  355. }
  356. fr->match = oldflags;
  357. }
  358. /* Always pass the dname (display name) to this function for chname <cybah>
  359. */
  360. void
  361. get_user_flagrec(const struct userrec *u, struct flag_record *fr, const char *chname, const struct chanset_t* chan)
  362. {
  363. fr->bot = 0;
  364. if (!u) {
  365. fr->global = fr->chan = 0;
  366. return;
  367. }
  368. if (u->bot)
  369. fr->bot = 1;
  370. fr->global = (fr->match & FR_GLOBAL) ? u->flags : 0;
  371. if (fr->match & FR_CHAN) {
  372. struct chanuserrec *cr = NULL;
  373. if ((fr->match & FR_ANYWH) || (fr->match & FR_ANYCH)) {
  374. if (fr->match & FR_ANYWH)
  375. fr->chan = u->flags;
  376. for (cr = u->chanrec; cr; cr = cr->next) {
  377. if (chan || findchan_by_dname(cr->channel)) {
  378. fr->chan |= cr->flags;
  379. }
  380. }
  381. } else {
  382. if (chname) {
  383. for (cr = u->chanrec; cr; cr = cr->next) {
  384. if (!rfc_casecmp(chname, cr->channel))
  385. break;
  386. }
  387. }
  388. if (cr) {
  389. fr->chan = cr->flags;
  390. } else {
  391. fr->chan = 0;
  392. }
  393. }
  394. }
  395. }
  396. /* private returns 0 if user has access, and 1 if they dont because of +private
  397. * This function does not check if the user has "op" access, it only checks if the user is
  398. * restricted by +private for the channel
  399. */
  400. int
  401. privchan(const struct flag_record fr, const struct chanset_t *chan, int type)
  402. {
  403. if (!chan || !channel_privchan(chan) || glob_bot(fr) || glob_owner(fr))
  404. return 0; /* user is implicitly not restricted by +private, they may however be lacking other flags */
  405. if (type == PRIV_OP) {
  406. /* |o implies all flags above. n| has access to all +private. Bots are exempt. */
  407. if (chan_op(fr))
  408. return 0;
  409. } else if (type == PRIV_VOICE) {
  410. if (chan_voice(fr) || chan_op(fr))
  411. return 0;
  412. }
  413. return 1; /* user is restricted by +private */
  414. }
  415. int
  416. real_chk_op(const struct flag_record fr, const struct chanset_t *chan, bool botbitch)
  417. {
  418. if (!chan && glob_op(fr))
  419. return 1;
  420. else if (!chan)
  421. return 0;
  422. if (!privchan(fr, chan, PRIV_OP) && !real_chk_deop(fr, chan, botbitch)) {
  423. if (chan_op(fr) || (glob_op(fr) && !chan_deop(fr)))
  424. return 1;
  425. }
  426. return 0;
  427. }
  428. static int
  429. chk_homechan_user_op(const memberlist *m, const struct chanset_t *chan)
  430. {
  431. struct chanset_t *homechan_chan = NULL;
  432. memberlist *homechan_m = NULL;
  433. if (!homechan[0] || channel_take(chan))
  434. return 0;
  435. if (!(homechan_chan = findchan_by_dname(homechan)))
  436. return 0;
  437. if (homechan_chan == chan)
  438. return 0;
  439. if (!(homechan_m = ismember(homechan_chan, *m->rfc_nick)))
  440. return 0;
  441. if (chan_hasop(homechan_m))
  442. return 1;
  443. return 0;
  444. }
  445. int
  446. chk_autoop(const memberlist *m, const struct flag_record fr, const struct chanset_t *chan)
  447. {
  448. if (glob_bot(fr) || !chan || (m->user && u_pass_match(m->user, "-")) ||
  449. channel_take(chan) || privchan(fr, chan, PRIV_OP) || chk_deop(fr, chan))
  450. return 0;
  451. if (chk_op(fr, chan) || (chan->homechan_user == HOMECHAN_USER_OP &&
  452. chk_homechan_user_op(m, chan))) {
  453. if (channel_autoop(chan) || chan_autoop(fr) || glob_autoop(fr))
  454. return 1;
  455. }
  456. return 0;
  457. }
  458. int
  459. chk_voice(const memberlist *m, const struct flag_record fr, const struct chanset_t *chan)
  460. {
  461. if (!chan || privchan(fr, chan, PRIV_VOICE) || chk_devoice(fr))
  462. return 0;
  463. if (chan_voice(fr) || (glob_voice(fr) && !chan_quiet(fr)) ||
  464. (chan->homechan_user == HOMECHAN_USER_VOICE &&
  465. chk_homechan_user_op(m, chan)))
  466. return 1;
  467. return 0;
  468. }
  469. int
  470. real_chk_deop(const struct flag_record fr, const struct chanset_t *chan, bool botbitch)
  471. {
  472. if (chan && botbitch && channel_botbitch(chan) && !glob_bot(fr))
  473. return 1;
  474. if (chan_deop(fr) || (glob_deop(fr) && !chan_op(fr)))
  475. return 1;
  476. else
  477. return 0;
  478. }
  479. int
  480. doresolv(const struct chanset_t *chan)
  481. {
  482. if (!chan)
  483. return 0;
  484. if (chan->role & ROLE_RESOLV)
  485. return 1;
  486. struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_BOT, 0, 0, 0 };
  487. get_user_flagrec(conf.bot->u, &fr, chan->dname);
  488. if (glob_doresolv(fr) || chan_doresolv(fr))
  489. return 1;
  490. return 0;
  491. }
  492. int
  493. dovoice(const struct chanset_t *chan)
  494. {
  495. if (!chan)
  496. return 0;
  497. if (chan->role & ROLE_VOICE)
  498. return 1;
  499. struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_BOT, 0, 0, 0 };
  500. get_user_flagrec(conf.bot->u, &fr, chan->dname);
  501. if (glob_dovoice(fr) || chan_dovoice(fr))
  502. return 1;
  503. return 0;
  504. }
  505. int
  506. doflood(const struct chanset_t *chan)
  507. {
  508. if (!chan)
  509. return 0;
  510. if (chan->role & ROLE_FLOOD)
  511. return 1;
  512. struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_BOT, 0, 0, 0 };
  513. if (!chan)
  514. fr.match |= FR_ANYWH;
  515. get_user_flagrec(conf.bot->u, &fr, chan ? chan->dname : NULL);
  516. if (glob_doflood(fr) || chan_doflood(fr))
  517. return 1;
  518. return 0;
  519. }
  520. int
  521. dolimit(const struct chanset_t *chan)
  522. {
  523. if (!chan)
  524. return 0;
  525. if (chan->role & ROLE_LIMIT)
  526. return 1;
  527. struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_BOT, 0, 0, 0 };
  528. get_user_flagrec(conf.bot->u, &fr, chan->dname);
  529. if (glob_dolimit(fr) || chan_dolimit(fr))
  530. return 1;
  531. return 0;
  532. }
  533. int
  534. whois_access(struct userrec *user, struct userrec *whois_user)
  535. {
  536. if (user == whois_user)
  537. return 1;
  538. struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0 }, whois = {
  539. FR_GLOBAL | FR_CHAN, 0, 0, 0};
  540. get_user_flagrec(user, &fr, NULL);
  541. get_user_flagrec(whois_user, &whois, NULL);
  542. /* Don't show hub bots from leaf bots. */
  543. if (!conf.bot->hub && whois_user->bot && bot_hublevel(whois_user) < 999)
  544. return 0;
  545. if (
  546. (isowner(whois_user->handle) && !isowner(user->handle)) ||
  547. (glob_admin(whois) && !glob_admin(fr)) ||
  548. (glob_owner(whois) && !glob_owner(fr)) ||
  549. (glob_master(whois) && !glob_master(fr)) ||
  550. (glob_bot(whois) && !glob_master(fr))
  551. )
  552. return 0;
  553. return 1;
  554. }
  555. homechan_user_t homechan_user_translate(const char *buf)
  556. {
  557. if (str_isdigit(buf))
  558. return (static_cast<homechan_user_t>(atoi(buf)));
  559. if (!strcasecmp(buf, "none"))
  560. return HOMECHAN_USER_NONE;
  561. else if (!strcasecmp(buf, "voice"))
  562. return HOMECHAN_USER_VOICE;
  563. else if (!strcasecmp(buf, "op"))
  564. return HOMECHAN_USER_OP;
  565. return HOMECHAN_USER_NONE;
  566. }
  567. deflag_t deflag_translate(const char *buf)
  568. {
  569. if (str_isdigit(buf))
  570. return (static_cast<deflag_t>(atoi(buf)));
  571. if (!strcasecmp(buf, "ignore"))
  572. return DEFLAG_IGNORE;
  573. else if (!strcasecmp(buf, "deop"))
  574. return DEFLAG_DEOP;
  575. else if (!strcasecmp(buf, "kick"))
  576. return DEFLAG_KICK;
  577. else if (!strcasecmp(buf, "delete") || !strcasecmp(buf, "remove"))
  578. return DEFLAG_DELETE;
  579. else if (!strcasecmp(buf, "react"))
  580. return DEFLAG_REACT;
  581. return DEFLAG_IGNORE;
  582. }
  583. void deflag_user(struct userrec *u, deflag_event_t why, const char *msg, const struct chanset_t *chan)
  584. {
  585. char tmp[50] = "", tmp2[1024] = "";
  586. struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  587. int which = 0;
  588. switch (why) {
  589. case DEFLAG_EVENT_BADCOOKIE:
  590. strlcpy(tmp, "Bad op cookie", sizeof(tmp));
  591. which = chan->bad_cookie;
  592. break;
  593. case DEFLAG_EVENT_MANUALOP:
  594. strlcpy(tmp, STR("Manual op in -manop channel"), sizeof(tmp));
  595. which = chan->manop;
  596. break;
  597. case DEFLAG_EVENT_REVENGE_DEOP:
  598. strlcpy(tmp, STR("Deopped bot in +revenge channel"), sizeof(tmp));
  599. which = chan->revenge;
  600. break;
  601. case DEFLAG_EVENT_REVENGE_KICK:
  602. strlcpy(tmp, STR("Kicked bot in +revenge channel"), sizeof(tmp));
  603. which = chan->revenge;
  604. break;
  605. case DEFLAG_EVENT_REVENGE_BAN:
  606. strlcpy(tmp, STR("Banned bot in +revenge channel"), sizeof(tmp));
  607. which = chan->revenge;
  608. break;
  609. case DEFLAG_EVENT_MDOP:
  610. strlcpy(tmp, "Mass deop", sizeof(tmp));
  611. which = chan->mdop;
  612. break;
  613. case DEFLAG_EVENT_MOP:
  614. strlcpy(tmp, "Mass op", sizeof(tmp));
  615. which = chan->mop;
  616. break;
  617. default:
  618. simple_snprintf(tmp, sizeof(tmp), "Reason #%i", why);
  619. }
  620. if (which == DEFLAG_DEOP) {
  621. putlog(LOG_WARN, "*", "Setting %s +d (%s): %s", u->handle, tmp, msg);
  622. simple_snprintf(tmp2, sizeof(tmp2), "+d: %s (%s)", tmp, msg);
  623. set_user(&USERENTRY_COMMENT, u, tmp2);
  624. get_user_flagrec(u, &fr, chan->dname);
  625. if (fr.global == USER_DEOP)
  626. fr.match &= ~FR_GLOBAL;
  627. else
  628. fr.global = USER_DEOP;
  629. if (fr.chan == USER_DEOP)
  630. fr.match &= ~FR_CHAN;
  631. else
  632. fr.chan = USER_DEOP;
  633. /* did anything change? */
  634. if (fr.match)
  635. set_user_flagrec(u, &fr, chan->dname);
  636. } else if (which == DEFLAG_KICK) {
  637. putlog(LOG_WARN, "*", "Setting %s +dk (%s): %s", u->handle, tmp, msg);
  638. simple_snprintf(tmp2, sizeof(tmp2), "+dk: %s (%s)", tmp, msg);
  639. set_user(&USERENTRY_COMMENT, u, tmp2);
  640. get_user_flagrec(u, &fr, chan->dname);
  641. if (fr.global == (USER_DEOP|USER_KICK))
  642. fr.match &= ~FR_GLOBAL;
  643. else
  644. fr.global = USER_DEOP | USER_KICK;
  645. if (fr.chan == (USER_DEOP|USER_KICK))
  646. fr.match &= ~FR_CHAN;
  647. else
  648. fr.chan = USER_DEOP | USER_KICK;
  649. /* did anything change */
  650. if (fr.match)
  651. set_user_flagrec(u, &fr, chan->dname);
  652. } else if (which == DEFLAG_DELETE) {
  653. putlog(LOG_WARN, "*", "Deleting %s (%s): %s", u->handle, tmp, msg);
  654. deluser(u->handle);
  655. } else {
  656. putlog(LOG_WARN, "*", "No user flag effects for %s (%s): %s", u->handle, tmp, msg);
  657. simple_snprintf(tmp2, sizeof(tmp2), "Warning: %s (%s)", tmp, msg);
  658. set_user(&USERENTRY_COMMENT, u, tmp2);
  659. }
  660. }
  661. /* vim: set sts=2 sw=2 ts=8 et: */