msgcmds.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  1. /*
  2. * Copyright (C) 1997 Robey Pointer
  3. * Copyright (C) 1999 - 2002 Eggheads Development Team
  4. * Copyright (C) 2002 - 2008 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. * msgcmds.c -- part of irc.mod
  22. * all commands entered via /MSG
  23. *
  24. */
  25. #include "src/core_binds.h"
  26. static int msg_bewm(char *nick, char *host, struct userrec *u, char *par)
  27. {
  28. struct chanset_t *chan = NULL;
  29. if (!homechan[0] || !(chan = findchan_by_dname(homechan)))
  30. return BIND_RET_BREAK;
  31. if (!channel_active(chan))
  32. return BIND_RET_BREAK;
  33. if (match_my_nick(nick))
  34. return BIND_RET_BREAK;
  35. if (!u) {
  36. dprintf(DP_SERVER, STR("PRIVMSG %s :---- (%s!%s) attempted to gain secure invite, but is not a recognized user.\n"),
  37. chan->dname, nick, host);
  38. putlog(LOG_CMDS, "*", STR("(%s!%s) !*! BEWM"), nick, host);
  39. return BIND_RET_BREAK;
  40. }
  41. if (u->bot)
  42. return BIND_RET_BREAK;
  43. struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  44. get_user_flagrec(u, &fr, chan->dname, chan);
  45. if (!chk_op(fr, chan)) {
  46. putlog(LOG_CMDS, "*", STR("(%s!%s) !%s! !BEWM"), nick, host, u->handle);
  47. dprintf(DP_SERVER, STR("PRIVMSG %s :---- %s (%s!%s) attempted to gain secure invite, but is missing a flag.\n"),
  48. chan->dname, u->handle, nick, host);
  49. return BIND_RET_BREAK;
  50. }
  51. dprintf(DP_SERVER, "PRIVMSG %s :\001ACTION has invited \002%s\002 (%s!%s) to %s.\001\n"
  52. , chan->dname, u->handle, nick, host, chan->dname);
  53. cache_invite(chan, nick, host, u->handle, 0, 0);
  54. putlog(LOG_CMDS, "*", STR("(%s!%s) !%s! BEWM"), nick, host, u->handle);
  55. return BIND_RET_BREAK;
  56. }
  57. static int msg_pass(char *nick, char *host, struct userrec *u, char *par)
  58. {
  59. char *old = NULL, *mynew = NULL;
  60. if (match_my_nick(nick))
  61. return BIND_RET_BREAK;
  62. if (!u) {
  63. putlog(LOG_CMDS, "*", "(%s!%s) !*! PASS", nick, host);
  64. return BIND_RET_BREAK;
  65. }
  66. if (u->bot)
  67. return BIND_RET_BREAK;
  68. if (!par[0]) {
  69. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, u_pass_match(u, "-") ? "You don't have a password set." : "You have a password set.");
  70. putlog(LOG_CMDS, "*", "(%s!%s) !%s! PASS?", nick, host, u->handle);
  71. return BIND_RET_BREAK;
  72. }
  73. old = newsplit(&par);
  74. if (!u_pass_match(u, "-") && !par[0]) {
  75. putlog(LOG_CMDS, "*", "(%s!%s) !%s! $b!$bPASS...", nick, host, u->handle);
  76. dprintf(DP_HELP, "NOTICE %s :You already have a password set.\n", nick);
  77. return BIND_RET_BREAK;
  78. }
  79. if (par[0]) {
  80. if (!u_pass_match(u, old)) {
  81. putlog(LOG_CMDS, "*", "(%s!%s) !%s! $b!$bPASS...", nick, host, u->handle);
  82. dprintf(DP_HELP, "NOTICE %s :Incorrect password.\n", nick);
  83. return BIND_RET_BREAK;
  84. }
  85. mynew = newsplit(&par);
  86. } else {
  87. mynew = old;
  88. }
  89. if (strlen(mynew) > MAXPASSLEN)
  90. mynew[MAXPASSLEN] = 0;
  91. if (!goodpass(mynew, 0, nick)) {
  92. putlog(LOG_CMDS, "*", "(%s!%s) !%s! $b!$bPASS...", nick, host, u->handle);
  93. return BIND_RET_BREAK;
  94. }
  95. putlog(LOG_CMDS, "*", "(%s!%s) !%s! PASS", nick, host, u->handle);
  96. set_user(&USERENTRY_PASS, u, mynew);
  97. dprintf(DP_HELP, "NOTICE %s :%s '%s'.\n", nick,
  98. mynew == old ? "Password set to:" : "Password changed to:", mynew);
  99. return BIND_RET_BREAK;
  100. }
  101. static int msg_op(char *nick, char *host, struct userrec *u, char *par)
  102. {
  103. struct chanset_t *chan = NULL;
  104. char *pass = NULL;
  105. struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  106. if (match_my_nick(nick))
  107. return BIND_RET_BREAK;
  108. pass = newsplit(&par);
  109. if (homechan[0]) {
  110. struct chanset_t *hchan = NULL;
  111. hchan = findchan_by_dname(homechan);
  112. if (hchan && channel_active(hchan) && !ismember(hchan, nick)) {
  113. putlog(LOG_CMDS, "*", "(%s!%s) !*! failed OP %s (not in %s)", nick, host, par, homechan);
  114. if (par[0])
  115. dprintf(DP_SERVER, "PRIVMSG %s :---- (%s!%s) attempted to OP for %s but is not currently in %s.\n",
  116. homechan, nick, host, par, homechan);
  117. else
  118. dprintf(DP_SERVER, "PRIVMSG %s :---- (%s!%s) attempted to OP but is not currently in %s.\n",
  119. homechan, nick, host, homechan);
  120. return BIND_RET_BREAK;
  121. }
  122. }
  123. if (u_pass_match(u, pass)) {
  124. if (!u_pass_match(u, "-")) {
  125. if (par[0]) {
  126. chan = findchan_by_dname(par);
  127. if (chan && channel_active(chan)) {
  128. get_user_flagrec(u, &fr, par, chan);
  129. if (chk_op(fr, chan)) {
  130. if (do_op(nick, chan, 0, 1)) {
  131. stats_add(u, 0, 1);
  132. putlog(LOG_CMDS, "*", "(%s!%s) !%s! OP %s", nick, host, u->handle, par);
  133. if (manop_warn && chan->manop)
  134. dprintf(DP_HELP, "NOTICE %s :%s is currently set to punish for manual op.\n", nick, chan->dname);
  135. }
  136. }
  137. return BIND_RET_BREAK;
  138. }
  139. } else {
  140. int stats = 0;
  141. for (chan = chanset; chan; chan = chan->next) {
  142. get_user_flagrec(u, &fr, chan->dname, chan);
  143. if (chk_op(fr, chan)) {
  144. if (do_op(nick, chan, 0, 1)) {
  145. stats++;
  146. if (manop_warn && chan->manop)
  147. dprintf(DP_HELP, "NOTICE %s :%s is currently set to punish for manual op.\n", nick, chan->dname);
  148. }
  149. }
  150. }
  151. putlog(LOG_CMDS, "*", "(%s!%s) !%s! OP", nick, host, u->handle);
  152. if (stats)
  153. stats_add(u, 0, 1);
  154. return BIND_RET_BREAK;
  155. }
  156. }
  157. }
  158. putlog(LOG_CMDS, "*", "(%s!%s) !*! failed OP", nick, host);
  159. return BIND_RET_BREAK;
  160. }
  161. static int msg_ident(char *nick, char *host, struct userrec *u, char *par)
  162. {
  163. char s[UHOSTLEN] = "", s1[UHOSTLEN] = "", *pass = NULL, who[NICKLEN] = "";
  164. struct userrec *u2 = NULL;
  165. if (match_my_nick(nick) || (u && u->bot))
  166. return BIND_RET_BREAK;
  167. pass = newsplit(&par);
  168. if (!par[0])
  169. strlcpy(who, nick, sizeof(nick));
  170. else {
  171. strlcpy(who, par, sizeof(who));
  172. who[NICKMAX] = 0;
  173. }
  174. u2 = get_user_by_handle(userlist, who);
  175. if (u2 && rfc_casecmp(who, origbotname) && !u2->bot) {
  176. /* This could be used as detection... */
  177. if (u_pass_match(u2, "-")) {
  178. putlog(LOG_CMDS, "*", "(%s!%s) !*! IDENT %s", nick, host, who);
  179. } else if (!u_pass_match(u2, pass)) {
  180. putlog(LOG_CMDS, "*", "(%s!%s) !*! failed IDENT %s", nick, host, who);
  181. return BIND_RET_BREAK;
  182. } else if (u == u2) {
  183. dprintf(DP_HELP, "NOTICE %s :I recognize you there.\n", nick);
  184. return BIND_RET_BREAK;
  185. } else if (u) {
  186. dprintf(DP_HELP, "NOTICE %s :You're not %s, you're %s.\n", nick, who, u->handle);
  187. return BIND_RET_BREAK;
  188. } else {
  189. putlog(LOG_CMDS, "*", "(%s!%s) !*! IDENT %s", nick, host, who);
  190. simple_snprintf(s, sizeof s, "%s!%s", nick, host);
  191. maskaddr(s, s1, 0); /* *!user@host */
  192. dprintf(DP_HELP, "NOTICE %s :Added hostmask: %s\n", nick, s1);
  193. addhost_by_handle(who, s1);
  194. check_this_user(who, 0, NULL);
  195. return BIND_RET_BREAK;
  196. }
  197. }
  198. putlog(LOG_CMDS, "*", "(%s!%s) !*! failed IDENT %s", nick, host, who);
  199. return BIND_RET_BREAK;
  200. }
  201. static int msg_invite(char *nick, char *host, struct userrec *u, char *par)
  202. {
  203. char *pass = NULL;
  204. struct chanset_t *chan = NULL;
  205. struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  206. if (match_my_nick(nick))
  207. return BIND_RET_BREAK;
  208. pass = newsplit(&par);
  209. if (u_pass_match(u, pass) && !u_pass_match(u, "-")) {
  210. if (par[0] == '*') {
  211. for (chan = chanset; chan; chan = chan->next) {
  212. get_user_flagrec(u, &fr, chan->dname, chan);
  213. if (chk_op(fr, chan) && (chan->channel.mode & CHANINV)) {
  214. cache_invite(chan, nick, host, u->handle, 0, 0);
  215. }
  216. }
  217. putlog(LOG_CMDS, "*", "(%s!%s) !%s! INVITE ALL", nick, host, u->handle);
  218. return BIND_RET_BREAK;
  219. }
  220. if (!(chan = findchan_by_dname(par))) {
  221. dprintf(DP_HELP, "NOTICE %s :Usage: /MSG %s %s <pass> <channel>\n", nick, botname, msginvite);
  222. return BIND_RET_BREAK;
  223. }
  224. if (!channel_active(chan)) {
  225. dprintf(DP_HELP, "NOTICE %s :%s: Not on that channel right now.\n", nick, par);
  226. return BIND_RET_BREAK;
  227. }
  228. /* We need to check access here also (dw 991002) */
  229. get_user_flagrec(u, &fr, par, chan);
  230. if (chk_op(fr, chan)) {
  231. cache_invite(chan, nick, host, u->handle, 0, 0);
  232. putlog(LOG_CMDS, "*", "(%s!%s) !%s! INVITE %s", nick, host, u->handle, par);
  233. return BIND_RET_BREAK;
  234. }
  235. }
  236. putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed INVITE %s", nick, host, (u ? u->handle : "*"), par);
  237. return BIND_RET_BREAK;
  238. }
  239. static void reply(char *, struct chanset_t *, const char *, ...) __attribute__((format(printf, 3, 4)));
  240. static void reply(char *nick, struct chanset_t *chan, const char *format, ...)
  241. {
  242. va_list va;
  243. char buf[1024] = "";
  244. va_start(va, format);
  245. egg_vsnprintf(buf, sizeof buf, format, va);
  246. va_end(va);
  247. if (chan)
  248. dprintf(DP_HELP, "PRIVMSG %s :%s", chan->name, buf);
  249. else
  250. dprintf(DP_HELP, "NOTICE %s :%s", nick, buf);
  251. }
  252. static void logc(const char *cmd, Auth *a, char *chname, char *par)
  253. {
  254. if (chname && chname[0])
  255. putlog(LOG_CMDS, "*", "(%s!%s) !%s! %s %c%s %s", a->nick, a->host, a->handle, chname, auth_prefix[0], cmd, par ? par : "");
  256. else
  257. putlog(LOG_CMDS, "*", "(%s!%s) !%s! %c%s %s", a->nick, a->host, a->handle, auth_prefix[0], cmd, par ? par : "");
  258. }
  259. #define LOGC(cmd) logc(cmd, a, chname, par)
  260. static int msg_authstart(char *nick, char *host, struct userrec *u, char *par)
  261. {
  262. if (!u)
  263. return 0;
  264. if (match_my_nick(nick))
  265. return BIND_RET_BREAK;
  266. if (u && u->bot)
  267. return BIND_RET_BREAK;
  268. if (!ischanhub()) {
  269. putlog(LOG_WARN, "*", STR("(%s!%s) !%s! Attempted AUTH? (I'm not a chathub (+c))"), nick, host, u->handle);
  270. return BIND_RET_BREAK;
  271. }
  272. putlog(LOG_CMDS, "*", STR("(%s!%s) !%s! AUTH?"), nick, host, u->handle);
  273. Auth *auth = Auth::Find(host);
  274. if (auth) {
  275. if (auth->Authed()) {
  276. dprintf(DP_HELP, STR("NOTICE %s :You are already authed.\n"), nick);
  277. return 0;
  278. }
  279. } else
  280. auth = new Auth(nick, host, u);
  281. /* Send "auth." if they are recognized, otherwise "auth!" */
  282. auth->Status(AUTH_PASS);
  283. dprintf(DP_HELP, STR("PRIVMSG %s :auth%s %s\n"), nick, u ? "." : "!", conf.bot->nick);
  284. return BIND_RET_BREAK;
  285. }
  286. static void
  287. AuthFinish(Auth *auth)
  288. {
  289. putlog(LOG_CMDS, "*", STR("(%s!%s) !%s! +AUTH"), auth->nick, auth->host, auth->handle);
  290. auth->Done();
  291. dprintf(DP_HELP, STR("NOTICE %s :You are now authorized for cmds, see %chelp\n"), auth->nick, auth_prefix[0]);
  292. }
  293. static int msg_auth(char *nick, char *host, struct userrec *u, char *par)
  294. {
  295. char *pass = NULL;
  296. if (match_my_nick(nick))
  297. return BIND_RET_BREAK;
  298. if (u && u->bot)
  299. return BIND_RET_BREAK;
  300. Auth *auth = Auth::Find(host);
  301. if (!auth || auth->Status() != AUTH_PASS)
  302. return BIND_RET_BREAK;
  303. pass = newsplit(&par);
  304. if (u_pass_match(u, pass) && !u_pass_match(u, "-")) {
  305. auth->user = u;
  306. if (strlen(auth_key) && get_user(&USERENTRY_SECPASS, u)) {
  307. putlog(LOG_CMDS, "*", STR("(%s!%s) !%s! AUTH"), nick, host, u->handle);
  308. auth->Status(AUTH_HASH);
  309. auth->MakeHash();
  310. dprintf(DP_HELP, STR("PRIVMSG %s :-Auth %s %s\n"), nick, auth->rand, conf.bot->nick);
  311. } else {
  312. /* no auth_key and/or no SECPASS for the user, don't require a hash auth */
  313. AuthFinish(auth);
  314. }
  315. } else {
  316. putlog(LOG_CMDS, "*", STR("(%s!%s) !%s! failed AUTH"), nick, host, u->handle);
  317. delete auth;
  318. }
  319. return BIND_RET_BREAK;
  320. }
  321. static int msg_pls_auth(char *nick, char *host, struct userrec *u, char *par)
  322. {
  323. if (strlen(auth_key) && get_user(&USERENTRY_SECPASS, u)) {
  324. if (match_my_nick(nick))
  325. return BIND_RET_BREAK;
  326. if (u && u->bot)
  327. return BIND_RET_BREAK;
  328. Auth *auth = Auth::Find(host);
  329. if (!auth || auth->Status() != AUTH_HASH)
  330. return BIND_RET_BREAK;
  331. if (!strcmp(auth->hash, par)) { /* good hash! */
  332. AuthFinish(auth);
  333. } else { /* bad hash! */
  334. char s[300] = "";
  335. putlog(LOG_CMDS, "*", STR("(%s!%s) !%s! failed +AUTH"), nick, host, u->handle);
  336. dprintf(DP_HELP, STR("NOTICE %s :Invalid hash.\n"), nick);
  337. simple_snprintf(s, sizeof(s), "*!%s", host);
  338. addignore(s, origbotname, STR("Invalid auth hash."), now + (60 * ignore_time));
  339. delete auth;
  340. }
  341. return BIND_RET_BREAK;
  342. }
  343. return BIND_RET_LOG;
  344. }
  345. static int msg_unauth(char *nick, char *host, struct userrec *u, char *par)
  346. {
  347. if (match_my_nick(nick))
  348. return BIND_RET_BREAK;
  349. if (u && u->bot)
  350. return BIND_RET_BREAK;
  351. Auth *auth = Auth::Find(host);
  352. if (!auth)
  353. return BIND_RET_BREAK;
  354. delete auth;
  355. dprintf(DP_HELP, STR("NOTICE %s :You are now unauthorized.\n"), nick);
  356. putlog(LOG_CMDS, "*", STR("(%s!%s) !%s! UNAUTH"), nick, host, u->handle);
  357. return BIND_RET_BREAK;
  358. }
  359. /* MSG COMMANDS
  360. *
  361. * Function call should be:
  362. * int msg_cmd("handle","nick","user@host","params");
  363. *
  364. * The function is responsible for any logging. Return 1 if successful,
  365. * 0 if not.
  366. */
  367. static cmd_t C_msg[] =
  368. {
  369. {"auth?", "", (Function) msg_authstart, NULL, LEAF},
  370. {"auth", "", (Function) msg_auth, NULL, LEAF},
  371. {"+auth", "", (Function) msg_pls_auth, NULL, LEAF},
  372. {"unauth", "", (Function) msg_unauth, NULL, LEAF},
  373. {"ident", "", (Function) msg_ident, NULL, LEAF},
  374. {"invite", "", (Function) msg_invite, NULL, LEAF},
  375. {"op", "", (Function) msg_op, NULL, LEAF},
  376. {"pass", "", (Function) msg_pass, NULL, LEAF},
  377. {"bewm", "", (Function) msg_bewm, NULL, LEAF},
  378. {NULL, NULL, NULL, NULL, 0}
  379. };
  380. static int msgc_test(Auth *a, char *chname, char *par)
  381. {
  382. char *cmd = NULL;
  383. LOGC("TEST");
  384. cmd = newsplit(&par);
  385. if (a->GetIdx(chname)) {
  386. check_auth_dcc(a, cmd, par);
  387. }
  388. return BIND_RET_BREAK;
  389. }
  390. static int msgc_op(Auth *a, char *chname, char *par)
  391. {
  392. struct chanset_t *chan = NULL;
  393. struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  394. int force = 0;
  395. memberlist *m = NULL;
  396. if (chname && chname[0]) {
  397. chan = findchan_by_dname(chname);
  398. if (chan)
  399. m = ismember(chan, a->nick);
  400. }
  401. LOGC("OP");
  402. if (par[0] == '-') { /* we have an option! */
  403. char *tmp = NULL;
  404. par++;
  405. tmp = newsplit(&par);
  406. if (!strcasecmp(tmp, "force") || !strcasecmp(tmp, "f"))
  407. force = 1;
  408. else {
  409. dprintf(DP_HELP, "NOTICE %s :Invalid option: %s\n", a->nick, tmp);
  410. return 0;
  411. }
  412. }
  413. if (par[0] || chan) {
  414. if (!chan)
  415. chan = findchan_by_dname(par);
  416. if (chan && channel_active(chan)) {
  417. get_user_flagrec(a->user, &fr, chan->dname, chan);
  418. if (chk_op(fr, chan)) {
  419. if (do_op(a->nick, chan, 0, force))
  420. stats_add(a->user, 0, 1);
  421. }
  422. return BIND_RET_BREAK;
  423. }
  424. } else {
  425. for (chan = chanset; chan; chan = chan->next) {
  426. get_user_flagrec(a->user, &fr, chan->dname, chan);
  427. if (chk_op(fr, chan)) {
  428. if (do_op(a->nick, chan, 0, force))
  429. stats_add(a->user, 0, 1);
  430. }
  431. }
  432. }
  433. return BIND_RET_BREAK;
  434. }
  435. static int msgc_voice(Auth *a, char *chname, char *par)
  436. {
  437. struct chanset_t *chan = NULL;
  438. struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  439. int force = 0;
  440. memberlist *m = NULL;
  441. if (chname && chname[0]) {
  442. chan = findchan_by_dname(chname);
  443. if (chan)
  444. m = ismember(chan, a->nick);
  445. }
  446. LOGC("VOICE");
  447. if (par[0] == '-') { /* we have an option! */
  448. char *tmp = NULL;
  449. par++;
  450. tmp = newsplit(&par);
  451. if (!strcasecmp(tmp, "force") || !strcasecmp(tmp, "f"))
  452. force = 1;
  453. else {
  454. dprintf(DP_HELP, "NOTICE %s :Invalid option: %s\n", a->nick, tmp);
  455. return 0;
  456. }
  457. }
  458. if (par[0] || chan) {
  459. if (!chan)
  460. chan = findchan_by_dname(par);
  461. if (chan && channel_active(chan)) {
  462. get_user_flagrec(a->user, &fr, chan->dname, chan);
  463. if (!chk_devoice(fr)) { /* dont voice +q */
  464. add_mode(chan, '+', 'v', a->nick);
  465. }
  466. return BIND_RET_BREAK;
  467. }
  468. } else {
  469. for (chan = chanset; chan; chan = chan->next) {
  470. get_user_flagrec(a->user, &fr, chan->dname, chan);
  471. if (!chk_devoice(fr)) { /* dont voice +q */
  472. add_mode(chan, '+', 'v', a->nick);
  473. }
  474. }
  475. }
  476. return BIND_RET_BREAK;
  477. }
  478. static int msgc_channels(Auth *a, char *chname, char *par)
  479. {
  480. struct chanset_t *chan = NULL;
  481. struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  482. char list[1024] = "";
  483. LOGC("CHANNELS");
  484. for (chan = chanset; chan; chan = chan->next) {
  485. get_user_flagrec(a->user, &fr, chan->dname, chan);
  486. if (chk_op(fr, chan)) {
  487. if (me_op(chan))
  488. strlcat(list, "@", sizeof(list));
  489. strlcat(list, chan->dname, sizeof(list));
  490. strlcat(list, " ", sizeof(list));
  491. }
  492. }
  493. if (list[0])
  494. reply(a->nick, NULL, "You have access to: %s\n", list);
  495. else
  496. reply(a->nick, NULL, "You do not have access to any channels.\n");
  497. return BIND_RET_BREAK;
  498. }
  499. static int msgc_getkey(Auth *a, char *chname, char *par)
  500. {
  501. struct chanset_t *chan = NULL;
  502. struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  503. if (chname && chname[0])
  504. return 0;
  505. if (!par[0])
  506. return 0;
  507. LOGC("GETKEY");
  508. chan = findchan_by_dname(par);
  509. if (chan && channel_active(chan) && !channel_pending(chan)) {
  510. get_user_flagrec(a->user, &fr, chan->dname, chan);
  511. if (chk_op(fr, chan)) {
  512. if (chan->channel.key[0]) {
  513. reply(a->nick, NULL, "Key for %s is: %s\n", chan->name, chan->channel.key);
  514. } else {
  515. reply(a->nick, NULL, "%s has no key set.\n", chan->name);
  516. }
  517. }
  518. }
  519. return BIND_RET_BREAK;
  520. }
  521. static int msgc_help(Auth *a, char *chname, char *par)
  522. {
  523. LOGC("HELP");
  524. char outbuf[201] = "";
  525. struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  526. bind_entry_t *entry = NULL;
  527. bind_table_t *table = NULL;
  528. get_user_flagrec(a->user, &fr, chname ? chname : NULL);
  529. table = bind_table_lookup("msgc");
  530. for (entry = table->entries; entry && entry->next; entry = entry->next)
  531. if (((chname && chname[0] && entry->cflags & AUTH_CHAN) ||
  532. ((!chname || !chname[0]) && entry->cflags & AUTH_MSG)) && flagrec_ok(&entry->user_flags, &fr)) {
  533. if (outbuf[0])
  534. strlcat(outbuf, " ", sizeof(outbuf));
  535. strlcat(outbuf, entry->mask, sizeof(outbuf));
  536. }
  537. reply(a->nick, NULL, "%s\n", outbuf);
  538. return BIND_RET_BREAK;
  539. }
  540. static int msgc_md5(Auth *a, char *chname, char *par)
  541. {
  542. struct chanset_t *chan = NULL;
  543. LOGC("MD5");
  544. if (chname && chname[0])
  545. chan = findchan_by_dname(chname);
  546. reply(a->nick, chan, "MD5(%s) = %s\n", par, MD5(par));
  547. return BIND_RET_BREAK;
  548. }
  549. static int msgc_sha1(Auth *a, char *chname, char *par)
  550. {
  551. struct chanset_t *chan = NULL;
  552. LOGC("SHA1");
  553. if (chname && chname[0])
  554. chan = findchan_by_dname(chname);
  555. reply(a->nick, chan, "SHA1(%s) = %s\n", par, SHA1(par));
  556. return BIND_RET_BREAK;
  557. }
  558. static int msgc_invite(Auth *a, char *chname, char *par)
  559. {
  560. struct chanset_t *chan = NULL;
  561. struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  562. int force = 0;
  563. if (chname && chname[0])
  564. return 0;
  565. LOGC("INVITE");
  566. if (par[0] == '-') {
  567. char *tmp = NULL;
  568. par++;
  569. tmp = newsplit(&par);
  570. if (!strcasecmp(tmp, "force") || !strcasecmp(tmp, "f"))
  571. force = 1;
  572. else {
  573. dprintf(DP_HELP, "NOTICE %s :Invalid option: %s\n", a->nick, tmp);
  574. return 0;
  575. }
  576. }
  577. if (par[0] && (!chname || (chname && !chname[0]))) {
  578. chan = findchan_by_dname(par);
  579. if (chan && channel_active(chan) && !ismember(chan, a->nick)) {
  580. if ((!(chan->channel.mode & CHANINV) && force) || (chan->channel.mode & CHANINV)) {
  581. get_user_flagrec(a->user, &fr, chan->dname, chan);
  582. if (chk_op(fr, chan)) {
  583. cache_invite(chan, a->nick, a->host, a->handle, 0, 0);
  584. }
  585. return BIND_RET_BREAK;
  586. }
  587. }
  588. } else {
  589. for (chan = chanset; chan; chan = chan->next) {
  590. if (channel_active(chan) && !ismember(chan, a->nick)) {
  591. if ((!(chan->channel.mode & CHANINV) && force) || (chan->channel.mode & CHANINV)) {
  592. get_user_flagrec(a->user, &fr, chan->dname, chan);
  593. if (chk_op(fr, chan)) {
  594. cache_invite(chan, a->nick, a->host, a->handle, 0, 0);
  595. }
  596. }
  597. }
  598. }
  599. }
  600. return BIND_RET_BREAK;
  601. }
  602. static cmd_t C_msgc[] =
  603. {
  604. {"test", "a", (Function) msgc_test, NULL, LEAF|AUTH_CHAN|AUTH_MSG},
  605. {"channels", "", (Function) msgc_channels, NULL, LEAF|AUTH_CHAN|AUTH_MSG},
  606. {"getkey", "", (Function) msgc_getkey, NULL, LEAF|AUTH_MSG},
  607. {"help", "", (Function) msgc_help, NULL, LEAF|AUTH_CHAN|AUTH_MSG},
  608. {"invite", "", (Function) msgc_invite, NULL, LEAF|AUTH_MSG},
  609. {"md5", "", (Function) msgc_md5, NULL, LEAF|AUTH_MSG|AUTH_CHAN},
  610. {"op", "", (Function) msgc_op, NULL, LEAF|AUTH_CHAN|AUTH_MSG},
  611. {"sha1", "", (Function) msgc_sha1, NULL, LEAF|AUTH_CHAN|AUTH_MSG},
  612. {"voice", "", (Function) msgc_voice, NULL, LEAF|AUTH_CHAN|AUTH_MSG},
  613. {NULL, NULL, NULL, NULL, 0}
  614. };