Advertisement
Guest User

Untitled

a guest
Aug 10th, 2017
470
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 68.89 KB | None | 0 0
  1. /* Main ChanServ module.
  2. *
  3. * IRC Services is copyright (c) 1996-2006 Andrew Church.
  4. * E-mail: <achurch@achurch.org>
  5. * Parts written by Andrew Kempe and others.
  6. * This program is free but copyrighted software; see the file COPYING for
  7. * details.
  8. */
  9.  
  10. /*************************************************************************/
  11.  
  12. #include "services.h"
  13. #include "modules.h"
  14. #include "conffile.h"
  15. #include "language.h"
  16. #include "commands.h"
  17. #include "encrypt.h"
  18. #include "modules/nickserv/nickserv.h"
  19. #include "modules/operserv/operserv.h"
  20.  
  21. #include "chanserv.h"
  22. #include "cs-local.h"
  23.  
  24. /*************************************************************************/
  25. /************************** Declaration section **************************/
  26. /*************************************************************************/
  27.  
  28. static Module *module;
  29. static Module *module_nickserv;
  30.  
  31. static int cb_clear = -1;
  32. static int cb_command = -1;
  33. static int cb_help = -1;
  34. static int cb_help_cmds = -1;
  35. static int cb_invite = -1;
  36. static int cb_unban = -1;
  37.  
  38. static int db_opened = 0;
  39.  
  40. char *s_ChanServ;
  41. static char *desc_ChanServ;
  42. static char *ChanDBName;
  43. EXPORT_VAR(char *,s_ChanServ)
  44.  
  45. static int CSEnableRegister;
  46. int CSRegisteredOnly;
  47. int32 CSMaxReg;
  48. int32 CSDefFlags;
  49. time_t CSExpire;
  50. int CSShowPassword;
  51. int32 CSAccessMax;
  52. int32 CSAutokickMax;
  53. char * CSAutokickReason;
  54. time_t CSInhabit;
  55. time_t CSRestrictDelay;
  56. int CSListOpersOnly;
  57. int32 CSListMax;
  58. time_t CSSuspendExpire;
  59. time_t CSSuspendGrace;
  60. int CSForbidShortChannel;
  61. EXPORT_VAR(int32,CSMaxReg)
  62.  
  63. /*************************************************************************/
  64.  
  65. /* Channel option list. */
  66.  
  67. #define CHANOPT(x) \
  68. { #x, CI_##x, CHAN_INFO_OPT_##x, \
  69. CHAN_SET_##x##_ON, CHAN_SET_##x##_OFF, CHAN_SET_##x##_SYNTAX }
  70. ChanOpt chanopts[] = {
  71. CHANOPT(KEEPTOPIC),
  72. CHANOPT(TOPICLOCK),
  73. CHANOPT(PRIVATE),
  74. CHANOPT(SECUREOPS),
  75. CHANOPT(LEAVEOPS),
  76. CHANOPT(RESTRICTED),
  77. CHANOPT(SECURE),
  78. CHANOPT(OPNOTICE),
  79. CHANOPT(ENFORCE),
  80. { "NOEXPIRE", CI_NOEXPIRE, -1, CHAN_SET_NOEXPIRE_ON,
  81. CHAN_SET_NOEXPIRE_OFF, CHAN_SET_NOEXPIRE_SYNTAX },
  82. { NULL }
  83. };
  84. #undef CHANOPT
  85.  
  86. /*************************************************************************/
  87.  
  88. /* Local functions. */
  89.  
  90. static void do_help(User *u);
  91. static void do_register(User *u);
  92. static void do_identify(User *u);
  93. static void do_drop(User *u);
  94. static void do_info(User *u);
  95. static void do_list(User *u);
  96. static void do_op(User *u);
  97. static void do_deop(User *u);
  98. static void do_voice(User *u);
  99. static void do_devoice(User *u);
  100. static void do_halfop(User *u);
  101. static void do_dehalfop(User *u);
  102. static void do_protect(User *u);
  103. static void do_deprotect(User *u);
  104. static void do_invite(User *u);
  105. static void do_unban(User *u);
  106. static void do_cskick(User *u);
  107. static void do_cstopic(User *u);
  108. static void do_clear(User *u);
  109. static void do_getpass(User *u);
  110. static void do_forbid(User *u);
  111. static void do_suspend(User *u);
  112. static void do_unsuspend(User *u);
  113. static void do_status(User *u);
  114.  
  115. /*************************************************************************/
  116.  
  117. /* Command list. */
  118.  
  119. static Command cmds[] = {
  120. { "HELP", do_help, NULL, -1, -1,-1 },
  121. { "REGISTER", do_register, NULL, CHAN_HELP_REGISTER, -1,-1 },
  122. { "IDENTIFY", do_identify, NULL, CHAN_HELP_IDENTIFY, -1,-1 },
  123. { "DROP", do_drop, NULL, -1,
  124. CHAN_HELP_DROP, CHAN_OPER_HELP_DROP },
  125. { "SET", do_set, NULL, CHAN_HELP_SET, -1, CHAN_OPER_HELP_SET },
  126. { "SET FOUNDER", NULL, NULL, CHAN_HELP_SET_FOUNDER, -1,-1 },
  127. { "SET SUCCESSOR", NULL, NULL, CHAN_HELP_SET_SUCCESSOR, -1,-1 },
  128. { "SET PASSWORD", NULL, NULL, CHAN_HELP_SET_PASSWORD, -1,-1 },
  129. { "SET DESC", NULL, NULL, CHAN_HELP_SET_DESC, -1,-1 },
  130. { "SET URL", NULL, NULL, CHAN_HELP_SET_URL, -1,-1 },
  131. { "SET EMAIL", NULL, NULL, CHAN_HELP_SET_EMAIL, -1,-1 },
  132. { "SET ENTRYMSG", NULL, NULL, CHAN_HELP_SET_ENTRYMSG, -1,-1 },
  133. { "SET KEEPTOPIC", NULL, NULL, CHAN_HELP_SET_KEEPTOPIC, -1,-1 },
  134. { "SET TOPICLOCK", NULL, NULL, CHAN_HELP_SET_TOPICLOCK, -1,-1 },
  135. { "SET MLOCK", NULL, NULL, CHAN_HELP_SET_MLOCK, -1,-1 },
  136. { "SET HIDE", NULL, NULL, CHAN_HELP_SET_HIDE, -1,-1 },
  137. { "SET PRIVATE", NULL, NULL, CHAN_HELP_SET_PRIVATE, -1,-1 },
  138. { "SET RESTRICTED", NULL, NULL, CHAN_HELP_SET_RESTRICTED, -1,-1 },
  139. { "SET SECURE", NULL, NULL, CHAN_HELP_SET_SECURE, -1,-1 },
  140. { "SET SECUREOPS", NULL, NULL, CHAN_HELP_SET_SECUREOPS, -1,-1 },
  141. { "SET LEAVEOPS", NULL, NULL, CHAN_HELP_SET_LEAVEOPS, -1,-1 },
  142. { "SET OPNOTICE", NULL, NULL, CHAN_HELP_SET_OPNOTICE, -1,-1 },
  143. { "SET ENFORCE", NULL, NULL, CHAN_HELP_SET_ENFORCE, -1,-1 },
  144. { "SET NOEXPIRE", NULL, NULL, -1, -1, CHAN_OPER_HELP_SET_NOEXPIRE },
  145. { "UNSET", do_unset, NULL, CHAN_HELP_UNSET,
  146. -1, CHAN_OPER_HELP_UNSET },
  147. { "INFO", do_info, NULL, CHAN_HELP_INFO,
  148. -1, CHAN_OPER_HELP_INFO },
  149. { "LIST", do_list, NULL, -1,
  150. CHAN_HELP_LIST, CHAN_OPER_HELP_LIST },
  151. { "AKICK", do_akick, NULL, CHAN_HELP_AKICK, -1,-1,
  152. (void *)ACCLEV_SOP },
  153. { "OP", do_op, NULL, CHAN_HELP_OP, -1,-1,
  154. (void *)ACCLEV_AOP },
  155. { "DEOP", do_deop, NULL, CHAN_HELP_DEOP, -1,-1,
  156. (void *)ACCLEV_AOP },
  157. { "VOICE", do_voice, NULL, CHAN_HELP_VOICE, -1,-1,
  158. (void *)ACCLEV_VOP },
  159. { "DEVOICE", do_devoice, NULL, CHAN_HELP_DEVOICE, -1,-1,
  160. (void *)ACCLEV_VOP },
  161. { "INVITE", do_invite, NULL, CHAN_HELP_INVITE, -1,-1,
  162. (void *)ACCLEV_AOP },
  163. { "UNBAN", do_unban, NULL, CHAN_HELP_UNBAN, -1,-1,
  164. (void *)ACCLEV_AOP },
  165. { "KICK", do_cskick, NULL, CHAN_HELP_KICK, -1,-1,
  166. (void *)ACCLEV_AOP },
  167. { "TOPIC", do_cstopic, NULL, CHAN_HELP_TOPIC, -1,-1,
  168. (void *)ACCLEV_AOP },
  169. { "CLEAR", do_clear, NULL, CHAN_HELP_CLEAR, -1,-1,
  170. (void *)ACCLEV_SOP },
  171. { "STATUS", do_status, NULL, CHAN_HELP_STATUS, -1,-1,
  172. (void *)ACCLEV_SOP },
  173. { "GETPASS", do_getpass, is_services_admin, -1,
  174. -1, CHAN_OPER_HELP_GETPASS },
  175. { "FORBID", do_forbid, is_services_admin, -1,
  176. -1, CHAN_OPER_HELP_FORBID },
  177. { "SUSPEND", do_suspend, is_services_admin, -1,
  178. -1, CHAN_OPER_HELP_SUSPEND },
  179. { "UNSUSPEND",do_unsuspend,is_services_admin, -1,
  180. -1, CHAN_OPER_HELP_UNSUSPEND },
  181. { NULL }
  182. };
  183.  
  184. static Command cmds_halfop[] = {
  185. { "HALFOP", do_halfop, NULL, CHAN_HELP_HALFOP, -1,-1,
  186. (void *)ACCLEV_AOP },
  187. { "DEHALFOP", do_dehalfop, NULL, CHAN_HELP_DEHALFOP, -1,-1,
  188. (void *)ACCLEV_AOP },
  189. { NULL }
  190. };
  191.  
  192. static Command cmds_chanprot[] = {
  193. { "PROTECT", do_protect, NULL, CHAN_HELP_PROTECT, -1,-1,
  194. (void *)ACCLEV_AOP },
  195. { "DEPROTECT",do_deprotect,NULL, CHAN_HELP_DEPROTECT, -1,-1,
  196. (void *)ACCLEV_AOP },
  197. { NULL }
  198. };
  199.  
  200. /*************************************************************************/
  201. /************************ Main ChanServ routines *************************/
  202. /*************************************************************************/
  203.  
  204. /* Introduce the ChanServ pseudoclient. */
  205.  
  206. static int introduce_chanserv(const char *nick)
  207. {
  208. if (!nick || irc_stricmp(nick, s_ChanServ) == 0) {
  209. char modebuf[BUFSIZE];
  210. snprintf(modebuf, sizeof(modebuf), "o%s", pseudoclient_modes);
  211. send_nick(s_ChanServ, ServiceUser, ServiceHost, ServerName,
  212. desc_ChanServ, modebuf);
  213. return nick ? 1 : 0;
  214. }
  215. return 0;
  216. }
  217.  
  218. /*************************************************************************/
  219.  
  220. /* Main ChanServ routine. */
  221.  
  222. static int chanserv(const char *source, const char *target, char *buf)
  223. {
  224. char *cmd;
  225. User *u = get_user(source);
  226.  
  227. if (irc_stricmp(target, s_ChanServ) != 0)
  228. return 0;
  229.  
  230. if (!u) {
  231. module_log("user record for %s not found", source);
  232. notice(s_ChanServ, source, getstring(NULL, INTERNAL_ERROR));
  233. return 1;
  234. }
  235.  
  236. cmd = strtok(buf, " ");
  237.  
  238. if (!cmd) {
  239. return 1;
  240. } else if (stricmp(cmd, "\1PING") == 0) {
  241. const char *s;
  242. if (!(s = strtok(NULL, "")))
  243. s = "\1";
  244. notice(s_ChanServ, source, "\1PING %s", s);
  245. } else {
  246. if (call_callback_2(module, cb_command, u, cmd) <= 0)
  247. run_cmd(s_ChanServ, u, module, cmd);
  248. }
  249. return 1;
  250. }
  251.  
  252. /*************************************************************************/
  253.  
  254. /* Return a /WHOIS response for ChanServ. */
  255.  
  256. static int chanserv_whois(const char *source, char *who, char *extra)
  257. {
  258. if (irc_stricmp(who, s_ChanServ) != 0)
  259. return 0;
  260. send_cmd(ServerName, "311 %s %s %s %s * :%s", source, who,
  261. ServiceUser, ServiceHost, desc_ChanServ);
  262. send_cmd(ServerName, "312 %s %s %s :%s", source, who,
  263. ServerName, ServerDesc);
  264. send_cmd(ServerName, "318 %s %s End of /WHOIS response.", source, who);
  265. return 1;
  266. }
  267. void ago_time(char *buf, time_t t, User *u) {
  268. int days, hours, minutes, seconds;
  269. days = t/(24*3600);
  270. t %= 24*3600;
  271. hours = t/3600;
  272. t %= 3600;
  273. minutes = t/60;
  274. t %= 60;
  275. seconds = t;
  276. sprintf(buf,"%d gün, %d saat, %d dakika ve %d saniye önce", days, hours, minutes, seconds);
  277. }
  278.  
  279. /*************************************************************************/
  280.  
  281. /* Save channel database. */
  282.  
  283. static int do_save_data()
  284. {
  285. sync_channel_db(ChanDBName);
  286. return 0;
  287. }
  288.  
  289. /*************************************************************************/
  290.  
  291. /* Callback for newly-created channels. */
  292.  
  293. static int do_channel_create(Channel *c, User *u, int32 modes)
  294. {
  295. /* Store ChannelInfo pointer in channel record */
  296. c->ci = get_channelinfo(c->name);
  297. if (c->ci) {
  298. /* Store return pointer in ChannelInfo record */
  299. c->ci->c = c;
  300. c->maxuser = c->ci->maxuser;
  301. c->maxuser_time = c->ci->maxuser_time;
  302. } else
  303. {
  304. c->maxuser = 1;
  305. c->maxuser_time = time(NULL);
  306. }
  307. /* Restore locked modes and saved topic */
  308. /* Note: these should be outside the c->ci test to ensure any spurious
  309. * +r modes are cleared */
  310. check_modes(c);
  311. restore_topic(c);
  312. return 0;
  313. }
  314.  
  315. /*************************************************************************/
  316.  
  317. /* Callback for users trying to join channels. */
  318.  
  319. static int do_channel_join_check(const char *channel, User *user)
  320. {
  321. return check_kick(user, channel);
  322. }
  323.  
  324. /*************************************************************************/
  325.  
  326. /* Callback for users joining channels. */
  327.  
  328. static int do_channel_join(Channel *c, struct c_userlist *u)
  329. {
  330. User *user = u->user;
  331. ChannelInfo *ci = c->ci;
  332.  
  333. check_chan_user_modes(NULL, u, c, -1);
  334. if (c->maxuser < ++(c->anuser)) {
  335. c->maxuser = c->anuser;
  336. c->maxuser_time = time(NULL);
  337. if(ci) {
  338. ci->maxuser = c->maxuser;
  339. ci->maxuser_time = c->maxuser_time;
  340. }
  341. }
  342. if (ci && ci->entry_message)
  343. notice(s_ChanServ, user->nick, "(%s) %s", ci->name, ci->entry_message);
  344. return 0;
  345. }
  346.  
  347. /*************************************************************************/
  348.  
  349. /* Callback for users leaving channels. Update the channel's last used
  350. * time if the user was an auto-op user.
  351. */
  352.  
  353. static int do_channel_part(Channel *c, User *u, const char *reason)
  354. {
  355. if (c->ci && check_access(u, c->ci, CA_AUTOOP)) {
  356. c->ci->last_used = time(NULL);
  357. put_channelinfo(c->ci);
  358. }
  359. return 0;
  360. }
  361.  
  362. /*************************************************************************/
  363.  
  364. /* Callback for channels being deleted. */
  365.  
  366. static int do_channel_delete(Channel *c)
  367. {
  368. if (c->ci)
  369. c->ci->c = NULL;
  370. return 0;
  371. }
  372.  
  373. /*************************************************************************/
  374.  
  375. /* Callback for channel mode changes. */
  376.  
  377. static int do_channel_mode_change(const char *source_unused, Channel *c)
  378. {
  379. check_modes(c);
  380. return 0;
  381. }
  382.  
  383. /*************************************************************************/
  384.  
  385. /* Callback for channel user mode changes. */
  386.  
  387. static int do_channel_umode_change(const char *source, Channel *c,
  388. struct c_userlist *u, int32 oldmodes)
  389. {
  390. if (!(u->mode & CUMODE_o))
  391. u->flags &= ~CUFLAG_DEOPPED;
  392. check_chan_user_modes(source, u, c, oldmodes);
  393. return 0;
  394. }
  395.  
  396. /*************************************************************************/
  397.  
  398. /* Callback for channel topic changes. */
  399.  
  400. static int do_channel_topic(Channel *c, const char *topic, const char *setter,
  401. time_t topic_time)
  402. {
  403. ChannelInfo *ci = c->ci;
  404.  
  405. if (check_topiclock(c, topic_time))
  406. return 1;
  407. record_topic(ci, topic, setter, topic_time);
  408. return 0;
  409. }
  410.  
  411. /*************************************************************************/
  412.  
  413. /* Callback for NickServ REGISTER/LINK check; we disallow
  414. * registration/linking of the ChanServ pseudoclient nickname.
  415. */
  416.  
  417. static int do_reglink_check(const User *u, const char *nick,
  418. const char *pass, const char *email)
  419. {
  420. return irc_stricmp(nick, s_ChanServ) == 0;
  421. }
  422.  
  423. /*************************************************************************/
  424.  
  425. /* Callback for users who have identified to their nicks: give them modes
  426. * as if they had just joined the channel.
  427. */
  428.  
  429. static int do_nick_identified(User *u, int old_authstat)
  430. {
  431. struct u_chanlist *uc; /* Node in list of channels the user is in */
  432. struct c_userlist *cu; /* Node in list of users in a channel */
  433.  
  434. LIST_FOREACH (uc, u->chans) {
  435. LIST_SEARCH_SCALAR(uc->chan->users, user, u, cu);
  436. if (!cu) {
  437. module_log("do_nick_identified(): BUG: user record not found in"
  438. " channel %s for user %s", uc->chan->name, u->nick);
  439. continue;
  440. }
  441. /* Use an empty source to force a mode recheck */
  442. check_chan_user_modes("", cu, uc->chan, -1);
  443. }
  444. return 0;
  445. }
  446.  
  447. /*************************************************************************/
  448.  
  449. /* Remove a (deleted or expired) nickname group from all channel lists. */
  450.  
  451. static int do_nickgroup_delete(const NickGroupInfo *ngi, const char *oldnick)
  452. {
  453. int i;
  454. int id = ngi->id;
  455. ChannelInfo *ci;
  456.  
  457. for (ci = first_channelinfo(); ci; ci = next_channelinfo()) {
  458. int modified = 0;
  459. if (ci->founder == id) {
  460. int was_suspended = (ci->suspendinfo != NULL);
  461. char name_save[CHANMAX];
  462. if (was_suspended)
  463. strscpy(name_save, ci->name, CHANMAX);
  464. if (ci->successor) {
  465. NickGroupInfo *ngi2 = get_ngi_id(ci->successor);
  466. if (!ngi2) {
  467. module_log("Unable to access successor group %u for"
  468. " deleted channel %s, deleting channel",
  469. ci->successor, ci->name);
  470. goto delete;
  471. } else if (check_channel_limit(ngi2, NULL) < 0) {
  472. module_log("Transferring foundership of %s from deleted"
  473. " nick %s to successor %s", ci->name,
  474. oldnick, ngi_mainnick(ngi2));
  475. uncount_chan(ci);
  476. ci->founder = ci->successor;
  477. ci->successor = 0;
  478. count_chan(ci);
  479. } else {
  480. module_log("Successor (%s) of %s owns too many channels,"
  481. " deleting channel", ngi_mainnick(ngi2),
  482. ci->name);
  483. goto delete;
  484. }
  485. } else {
  486. module_log("Deleting channel %s owned by deleted nick %s",
  487. ci->name, oldnick);
  488. delete:
  489. delchan(ci);
  490. if (was_suspended) {
  491. /* Channel was suspended, so make it forbidden */
  492. module_log("Channel %s was suspended, forbidding it",
  493. name_save);
  494. ci = makechan(name_save);
  495. ci->flags |= CI_VERBOTEN;
  496. }
  497. continue;
  498. }
  499. modified = 1;
  500. }
  501. if (ci->successor == id) {
  502. ci->successor = 0;
  503. modified = 1;
  504. }
  505. ARRAY_FOREACH (i, ci->access) {
  506. if (ci->access[i].nickgroup == id) {
  507. ci->access[i].nickgroup = 0;
  508. modified = 1;
  509. }
  510. }
  511. if (modified)
  512. put_channelinfo(ci);
  513. }
  514. return 0;
  515. }
  516.  
  517. /*************************************************************************/
  518. /*********************** ChanServ command routines ***********************/
  519. /*************************************************************************/
  520.  
  521. /* Short routine for do_help() to return the proper access level string for
  522. * a given level based on which access modules are loaded. Assumes numeric
  523. * levels if no access module is loaded.
  524. */
  525. static const char *getstring_cmdacc(NickGroupInfo *ngi, int16 level)
  526. {
  527. int str_levxop, str_lev, str_xop;
  528.  
  529. switch (level) {
  530. case ACCLEV_SOP:
  531. str_levxop = CHAN_HELP_REQSOP_LEVXOP;
  532. str_lev = CHAN_HELP_REQSOP_LEV;
  533. str_xop = CHAN_HELP_REQSOP_XOP;
  534. break;
  535. case ACCLEV_AOP:
  536. str_levxop = CHAN_HELP_REQAOP_LEVXOP;
  537. str_lev = CHAN_HELP_REQAOP_LEV;
  538. str_xop = CHAN_HELP_REQAOP_XOP;
  539. break;
  540. case ACCLEV_HOP:
  541. str_levxop = CHAN_HELP_REQHOP_LEVXOP;
  542. str_lev = CHAN_HELP_REQHOP_LEV;
  543. str_xop = CHAN_HELP_REQHOP_XOP;
  544. break;
  545. case ACCLEV_VOP:
  546. str_levxop = CHAN_HELP_REQVOP_LEVXOP;
  547. str_lev = CHAN_HELP_REQVOP_LEV;
  548. str_xop = CHAN_HELP_REQVOP_XOP;
  549. break;
  550. default:
  551. module_log("BUG: weird level (%d) in getstring_cmdacc()", level);
  552. return "???";
  553. }
  554. if (find_module("chanserv/access-xop")) {
  555. if (find_module("chanserv/access-levels"))
  556. return getstring(ngi, str_levxop);
  557. else
  558. return getstring(ngi, str_xop);
  559. } else {
  560. return getstring(ngi, str_lev);
  561. }
  562. }
  563.  
  564.  
  565. static void do_help(User *u)
  566. {
  567. char *cmd = strtok_remaining();
  568. Command *cmdrec;
  569.  
  570. if (!cmd) {
  571. notice_help(s_ChanServ, u, CHAN_HELP);
  572. if (CSExpire)
  573. notice_help(s_ChanServ, u, CHAN_HELP_EXPIRES,
  574. maketime(u->ngi,CSExpire,0));
  575. } else if (call_callback_2(module, cb_help, u, cmd) > 0) {
  576. return;
  577. } else if (stricmp(cmd, "COMMANDS") == 0) {
  578. notice_help(s_ChanServ, u, CHAN_HELP_COMMANDS);
  579. if (find_module("chanserv/sendpass"))
  580. notice_help(s_ChanServ, u, CHAN_HELP_COMMANDS_SENDPASS);
  581. notice_help(s_ChanServ, u, CHAN_HELP_COMMANDS_DROP);
  582. if (find_module("chanserv/access-levels"))
  583. notice_help(s_ChanServ, u, CHAN_HELP_COMMANDS_LEVELS);
  584. if (find_module("chanserv/access-xop")) {
  585. notice_help(s_ChanServ, u, CHAN_HELP_COMMANDS_XOP);
  586. if (protocol_features & PF_HALFOP)
  587. notice_help(s_ChanServ, u, CHAN_HELP_COMMANDS_HOP);
  588. }
  589. notice_help(s_ChanServ, u, CHAN_HELP_COMMANDS_OPVOICE);
  590. if (protocol_features & PF_HALFOP)
  591. notice_help(s_ChanServ, u, CHAN_HELP_COMMANDS_HALFOP);
  592. if (protocol_features & PF_CHANPROT)
  593. notice_help(s_ChanServ, u, CHAN_HELP_COMMANDS_PROTECT);
  594. notice_help(s_ChanServ, u, CHAN_HELP_COMMANDS_INVITE);
  595. if (!CSListOpersOnly)
  596. notice_help(s_ChanServ, u, CHAN_HELP_COMMANDS_LIST);
  597. notice_help(s_ChanServ, u, CHAN_HELP_COMMANDS_AKICK);
  598. call_callback_2(module, cb_help_cmds, u, 0);
  599. if (is_oper(u)) {
  600. notice_help(s_ChanServ, u, CHAN_OPER_HELP_COMMANDS);
  601. if (EnableGetpass)
  602. notice_help(s_ChanServ, u, CHAN_OPER_HELP_COMMANDS_GETPASS);
  603. notice_help(s_ChanServ, u, CHAN_OPER_HELP_COMMANDS_FORBID);
  604. if (CSListOpersOnly)
  605. notice_help(s_ChanServ, u, CHAN_HELP_COMMANDS_LIST);
  606. call_callback_2(module, cb_help_cmds, u, 1);
  607. notice_help(s_ChanServ, u, CHAN_OPER_HELP_COMMANDS_END);
  608. }
  609. } else if (!CSEnableRegister && is_oper(u) && stricmp(cmd,"REGISTER")==0) {
  610. notice_help(s_ChanServ, u, CHAN_HELP_REGISTER);
  611. notice_help(s_ChanServ, u, CHAN_HELP_REGISTER_ADMINONLY);
  612. } else if (stricmp(cmd, "LIST") == 0) {
  613. if (is_oper(u))
  614. notice_help(s_ChanServ, u, CHAN_OPER_HELP_LIST);
  615. else
  616. notice_help(s_ChanServ, u, CHAN_HELP_LIST);
  617. if (CSListOpersOnly)
  618. notice_help(s_ChanServ, u, CHAN_HELP_LIST_OPERSONLY);
  619. } else if (stricmp(cmd, "KICK") == 0) {
  620. cmdrec = lookup_cmd(module, cmd);
  621. notice_help(s_ChanServ, u, CHAN_HELP_KICK,
  622. getstring_cmdacc(u->ngi, cmdrec ? (int)(long)cmdrec->help_param1 : -1));
  623. if (protocol_features & PF_CHANPROT)
  624. notice_help(s_ChanServ, u, CHAN_HELP_KICK_PROTECTED);
  625. } else if (stricmp(cmd, "CLEAR") == 0) {
  626. notice_help(s_ChanServ, u, CHAN_HELP_CLEAR);
  627. if (protocol_features & PF_BANEXCEPT)
  628. notice_help(s_ChanServ, u, CHAN_HELP_CLEAR_EXCEPTIONS);
  629. if (protocol_features & PF_INVITEMASK)
  630. notice_help(s_ChanServ, u, CHAN_HELP_CLEAR_INVITES);
  631. notice_help(s_ChanServ, u, CHAN_HELP_CLEAR_MID);
  632. if (protocol_features & PF_HALFOP)
  633. notice_help(s_ChanServ, u, CHAN_HELP_CLEAR_HALFOPS);
  634. cmdrec = lookup_cmd(module, cmd);
  635. notice_help(s_ChanServ, u, CHAN_HELP_CLEAR_END,
  636. getstring_cmdacc(u->ngi, cmdrec ? (int)(long)cmdrec->help_param1 : -1));
  637. } else if ((stricmp(cmd, "AKICK") == 0
  638. || stricmp(cmd, "OP") == 0
  639. || stricmp(cmd, "DEOP") == 0
  640. || stricmp(cmd, "VOICE") == 0
  641. || stricmp(cmd, "DEVOICE") == 0
  642. || stricmp(cmd, "HALFOP") == 0
  643. || stricmp(cmd, "DEHALFOP") == 0
  644. || stricmp(cmd, "PROTECT") == 0
  645. || stricmp(cmd, "DEPROTECT") == 0
  646. || stricmp(cmd, "INVITE") == 0
  647. || stricmp(cmd, "UNBAN") == 0
  648. || stricmp(cmd, "KICK") == 0
  649. || stricmp(cmd, "TOPIC") == 0
  650. || stricmp(cmd, "CLEAR") == 0
  651. || stricmp(cmd, "STATUS") == 0)
  652. && (cmdrec = lookup_cmd(module, cmd)) != NULL
  653. ) {
  654. notice_help(s_ChanServ, u, cmdrec->helpmsg_all,
  655. getstring_cmdacc(u->ngi, (int)(long)cmdrec->help_param1));
  656. } else {
  657. help_cmd(s_ChanServ, u, module, cmd);
  658. }
  659. }
  660.  
  661. /*************************************************************************/
  662.  
  663. static void do_register(User *u)
  664. {
  665. char *chan = strtok(NULL, " ");
  666. char *pass = strtok(NULL, " ");
  667. char *desc = strtok_remaining();
  668. NickInfo *ni = u->ni;
  669. NickGroupInfo *ngi = u->ngi;
  670. Channel *c;
  671. ChannelInfo *ci;
  672. struct u_chaninfolist *uc;
  673. int max;
  674.  
  675. if (readonly) {
  676. notice_lang(s_ChanServ, u, CHAN_REGISTER_DISABLED);
  677. return;
  678. }
  679.  
  680. if (!desc) {
  681. syntax_error(s_ChanServ, u, "REGISTER", CHAN_REGISTER_SYNTAX);
  682. } else if (strcmp(chan, "#") == 0) {
  683. notice_lang(s_ChanServ, u, CHAN_REGISTER_SHORT_CHANNEL);
  684. } else if (*chan == '&') {
  685. notice_lang(s_ChanServ, u, CHAN_REGISTER_NOT_LOCAL);
  686. } else if (*chan != '#') {
  687. notice_lang(s_ChanServ, u, CHAN_REGISTER_INVALID_NAME);
  688. } else if (!ni) {
  689. notice_lang(s_ChanServ, u, CHAN_MUST_REGISTER_NICK, s_NickServ);
  690. } else if (!user_identified(u)) {
  691. notice_lang(s_ChanServ, u, CHAN_MUST_IDENTIFY_NICK,
  692. s_NickServ, s_NickServ);
  693.  
  694. } else if ((ci = get_channelinfo(chan)) != NULL) {
  695. if (ci->flags & CI_VERBOTEN) {
  696. module_log("Attempt to register forbidden channel %s by %s!%s@%s",
  697. ci->name, u->nick, u->username, u->host);
  698. notice_lang(s_ChanServ, u, CHAN_MAY_NOT_BE_REGISTERED, chan);
  699. } else if (ci->suspendinfo) {
  700. module_log("Attempt to register suspended channel %s by %s!%s@%s",
  701. ci->name, u->nick, u->username, u->host);
  702. notice_lang(s_ChanServ, u, CHAN_ALREADY_REGISTERED, chan);
  703. } else {
  704. notice_lang(s_ChanServ, u, CHAN_ALREADY_REGISTERED, chan);
  705. }
  706.  
  707. } else if (!is_chanop(u, chan)) {
  708. notice_lang(s_ChanServ, u, CHAN_MUST_BE_CHANOP);
  709.  
  710. } else if (!is_services_admin(u) && check_channel_limit(ngi, &max) >= 0) {
  711. notice_lang(s_ChanServ, u, ngi->channels_count > max
  712. ? CHAN_EXCEEDED_CHANNEL_LIMIT
  713. : CHAN_REACHED_CHANNEL_LIMIT, max);
  714.  
  715. } else if (!(c = get_channel(chan))) {
  716. /* Should not fail because we checked is_chanop() above, but just
  717. * in case... */
  718. module_log("Channel %s not found for REGISTER", chan);
  719. notice_lang(s_ChanServ, u, CHAN_REGISTRATION_FAILED);
  720.  
  721. } else if (!(ci = makechan(chan))) {
  722. module_log("makechan() failed for REGISTER %s", chan);
  723. notice_lang(s_ChanServ, u, CHAN_REGISTRATION_FAILED);
  724.  
  725. } else {
  726. int len = strlen(pass);
  727.  
  728. /* Password length check and truncation (like NickServ REGISTER) */
  729. max = encrypt_check_len(len, PASSMAX);
  730. if ((max == 0 && len > PASSMAX-1) || max > PASSMAX-1)
  731. max = PASSMAX-1;
  732. if (max > 0) {
  733. memset(pass+max, 0, len-max);
  734. len = max;
  735. notice_lang(s_ChanServ, u, PASSWORD_TRUNCATED, max);
  736. }
  737. if (encrypt(pass, len, ci->founderpass, PASSMAX) < 0) {
  738. module_log("Couldn't encrypt password for %s (REGISTER)", chan);
  739. notice_lang(s_ChanServ, u, CHAN_REGISTRATION_FAILED);
  740. delchan(ci);
  741. return;
  742. }
  743. c->ci = ci;
  744. ci->c = c;
  745. ci->flags = CSDefFlags;
  746. ci->mlock_on = CMODE_n | CMODE_t;
  747. ci->memos.memomax = MEMOMAX_DEFAULT;
  748. ci->last_used = ci->time_registered;
  749. ci->founder = u->ngi->id;
  750. ci->desc = sstrdup(desc);
  751. if (c->topic) {
  752. ci->last_topic = sstrdup(c->topic);
  753. strscpy(ci->last_topic_setter, c->topic_setter, NICKMAX);
  754. ci->last_topic_time = c->topic_time;
  755. }
  756. c->maxuser = c->anuser;
  757. c->maxuser_time = time(NULL);
  758. ci->maxuser = c->maxuser;
  759. ci->maxuser_time = c->maxuser_time;
  760. count_chan(ci);
  761. strscpy(last_register_chan, ci->name, CHANMAX);
  762. put_channelinfo(ci);
  763. module_log("Channel %s registered by %s!%s@%s",
  764. chan, u->nick, u->username, u->host);
  765. notice_lang(s_ChanServ, u, CHAN_REGISTERED, chan, u->nick);
  766. send_cmd(s_ChanServ, "PRIVMSG #Services \2%s\2 kanalı \2%s\2 (\2%s@%s\2) tarafından kayıt edildi. Kanal Açıklaması: %s", chan, u->nick, u->username, u->host, ci->desc);
  767. if (CSShowPassword)
  768. notice_lang(s_ChanServ, u, CHAN_PASSWORD_IS, pass);
  769. memset(pass, 0, len);
  770. uc = smalloc(sizeof(*uc));
  771. LIST_INSERT(uc, u->id_chans);
  772. strscpy(uc->chan, ci->name, CHANMAX);
  773. /* Implement new mode lock */
  774. check_modes(ci->c);
  775.  
  776. }
  777. }
  778.  
  779. /*************************************************************************/
  780.  
  781. static void do_identify(User *u)
  782. {
  783. char *chan = strtok(NULL, " ");
  784. char *pass = strtok_remaining();
  785. ChannelInfo *ci;
  786. struct u_chaninfolist *uc;
  787.  
  788. if (!pass) {
  789. syntax_error(s_ChanServ, u, "IDENTIFY", CHAN_IDENTIFY_SYNTAX);
  790. } else if (!(ci = get_channelinfo(chan))) {
  791. notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
  792. } else if (ci->flags & CI_VERBOTEN) {
  793. notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
  794. } else if (ci->suspendinfo) {
  795. notice_lang(s_ChanServ, u, CHAN_X_SUSPENDED, chan);
  796. } else {
  797. int res = check_password(pass, ci->founderpass);
  798. if (res == 1) {
  799. ci->bad_passwords = 0;
  800. ci->last_used = time(NULL);
  801. put_channelinfo(ci);
  802. if (!is_identified(u, ci)) {
  803. uc = smalloc(sizeof(*uc));
  804. LIST_INSERT(uc, u->id_chans);
  805. strscpy(uc->chan, ci->name, CHANMAX);
  806. module_log("%s!%s@%s identified for %s",
  807. u->nick, u->username, u->host, ci->name);
  808. }
  809. notice_lang(s_ChanServ, u, CHAN_IDENTIFY_SUCCEEDED, chan);
  810. } else if (res < 0) {
  811. module_log("check_password failed for %s", ci->name);
  812. notice_lang(s_ChanServ, u, CHAN_IDENTIFY_FAILED);
  813. } else {
  814. module_log("Failed IDENTIFY for %s by %s!%s@%s",
  815. ci->name, u->nick, u->username, u->host);
  816. chan_bad_password(u, ci);
  817. }
  818.  
  819. }
  820. }
  821.  
  822. /*************************************************************************/
  823.  
  824. static void do_drop(User *u)
  825. {
  826. char *chan = strtok(NULL, " ");
  827. ChannelInfo *ci;
  828. int is_servadmin = is_services_admin(u);
  829. Channel *c;
  830.  
  831. if (readonly && !is_servadmin) {
  832. notice_lang(s_ChanServ, u, CHAN_DROP_DISABLED);
  833. return;
  834. }
  835.  
  836. if (!chan) {
  837. syntax_error(s_ChanServ, u, "DROP", CHAN_DROP_SYNTAX);
  838. } else if (!(ci = get_channelinfo(chan))) {
  839. notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
  840. } else if (!is_servadmin && (ci->flags & CI_VERBOTEN)) {
  841. notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
  842. } else if (!is_servadmin && ci->suspendinfo) {
  843. notice_lang(s_ChanServ, u, CHAN_X_SUSPENDED, chan);
  844. } else if (!is_servadmin && !is_identified(u, ci)) {
  845. notice_lang(s_ChanServ, u, CHAN_IDENTIFY_REQUIRED, s_ChanServ, chan);
  846. } else {
  847. const char *founder;
  848. char tmpbuf[64];
  849.  
  850. if (readonly) /* in this case we know they're a Services admin */
  851. notice_lang(s_ChanServ, u, READ_ONLY_MODE);
  852. if (ci->founder) {
  853. NickGroupInfo *ngi = get_ngi_id(ci->founder);
  854. if (ngi) {
  855. founder = ngi_mainnick(ngi);
  856. } else {
  857. snprintf(tmpbuf, sizeof(tmpbuf), "<unknown: ID %u>",
  858. ci->founder);
  859. founder = tmpbuf;
  860. }
  861. } else {
  862. founder = "<none>";
  863. }
  864. module_log("Channel %s (founder %s) dropped by %s!%s@%s",
  865. ci->name, founder, u->nick, u->username, u->host);
  866. delchan(ci);
  867. if (chanmode_reg && (c = get_channel(chan))) {
  868. c->mode &= ~chanmode_reg;
  869. send_cmode_cmd(s_ChanServ, chan, "-%s",
  870. mode_flags_to_string(chanmode_reg, MODE_CHANNEL));
  871. }
  872. notice_lang(s_ChanServ, u, CHAN_DROPPED, chan);
  873. send_cmd(s_ChanServ, "PRIVMSG #Services CHAN-DROPPED: * \2%s\2 * kanalı droplandı, komutu uygulayan: * \2%s\2 *", chan, u->nick);
  874. }
  875. }
  876.  
  877. /*************************************************************************/
  878.  
  879. /* SADMINS, and users who have identified for a channel, can now cause its
  880. * entry message and successor to be displayed by supplying the ALL
  881. * parameter.
  882. * Syntax: INFO channel [ALL]
  883. * -TheShadow (29 Mar 1999)
  884. */
  885.  
  886. /* Check the status of show_all and make a note of having done so. See
  887. * comments at nickserv/main.c/do_info() for details. */
  888. #define CHECK_SHOW_ALL (used_all++, show_all)
  889.  
  890. static void do_info(User *u)
  891. {
  892. char *chan = strtok(NULL, " ");
  893. char *param = strtok(NULL, " ");
  894. ChannelInfo *ci;
  895. NickInfo *ni = u->ni;
  896. NickGroupInfo *ngi, *ngi2 = NULL;
  897. char buf[BUFSIZE], *end, *s;
  898. char emre[BUFSIZE];
  899. time_t now = time(NULL);
  900. int nick_online = 0;
  901. char buf2[BUFSIZE];
  902. time_t now=time(NULL);
  903. int is_servadmin = is_services_admin(u);
  904. int can_show_all = 0, show_all = 0, used_all = 0;
  905.  
  906. if (!chan) {
  907. syntax_error(s_ChanServ, u, "INFO", CHAN_INFO_SYNTAX);
  908. } else if (!(ci = get_channelinfo(chan))) {
  909. notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
  910. } else if (ci->flags & CI_VERBOTEN) {
  911. notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
  912. } else if (!ci->founder) {
  913. /* Paranoia... this shouldn't be able to happen */
  914. module_log("INFO: non-forbidden channel %s has no founder, deleting",
  915. ci->name);
  916. delchan(ci);
  917. notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
  918. } else if (!(ngi = get_ngi_id(ci->founder))
  919. || (ci->successor && !(ngi2 = get_ngi_id(ci->successor)))
  920. ) {
  921. notice_lang(s_ChanServ, u, INTERNAL_ERROR);
  922. } else {
  923.  
  924. /* Update last used time if the channel is currently in use. */
  925. if (ci->c) {
  926. struct c_userlist *cu;
  927. LIST_FOREACH (cu, ci->c->users) {
  928. if (check_access(cu->user, ci, CA_AUTOOP)) {
  929. if (debug >= 2)
  930. module_log("debug: updating last used time for %s"
  931. " (INFO)", ci->name);
  932. ci->last_used = time(NULL);
  933. put_channelinfo(ci);
  934. break;
  935. }
  936. }
  937. }
  938.  
  939. /* Only show all the channel's settings to sadmins and founders. */
  940. can_show_all = (is_founder(u, ci) || is_servadmin);
  941.  
  942. if ((param && stricmp(param, "ALL") == 0) && can_show_all)
  943. show_all = 1;
  944.  
  945. notice_lang(s_ChanServ, u, CHAN_INFO_HEADER, chan);
  946. ni = get_nickinfo(ngi_mainnick(ngi));
  947.  
  948. if (ni && ni->user && nick_id_or_rec(ni))
  949. nick_online = 1;
  950.  
  951. if (nick_online) {
  952. send_cmd(s_ChanServ, "NOTICE %s : Kanal Sahibi: %s [ONLINE]", u->nick, ngi_mainnick(ngi));
  953. } else {
  954. emre_time2(emre, now-ni->last_seen, u);
  955. send_cmd(s_ChanServ, "NOTICE %s : Kanal Sahibi: %s [OFFLINE] [%s]", u->nick, ngi_mainnick(ngi), emre);
  956. }
  957. if (ngi2 != NULL && CHECK_SHOW_ALL) {
  958. notice_lang(s_ChanServ, u, CHAN_INFO_SUCCESSOR,
  959. ngi_mainnick(ngi2));
  960. }
  961. notice_lang(s_ChanServ, u, CHAN_INFO_DESCRIPTION, ci->desc);
  962. strftime_lang(buf, sizeof(buf), u->ngi, STRFTIME_DATE_TIME_FORMAT,
  963. ci->time_registered);
  964. notice_lang(s_ChanServ, u, CHAN_INFO_TIME_REGGED, buf);
  965. strftime_lang(buf, sizeof(buf), u->ngi, STRFTIME_DATE_TIME_FORMAT,
  966. ci->last_used);
  967. notice_lang(s_ChanServ, u, CHAN_INFO_LAST_USED, buf);
  968.  
  969. /* Do not show last_topic if channel is mlock'ed +s or +p, or if the
  970. * channel's current modes include +s or +p. -TheShadow */
  971. /* But show it if we're showing all info. --AC */
  972. if (ci->last_topic) {
  973. int mlock_sp = (ci->mlock_on & (CMODE_s | CMODE_p));
  974. int mode_sp = (ci->c && (ci->c->mode & (CMODE_s | CMODE_p)));
  975. int hide = (ci->flags & CI_HIDE_TOPIC);
  976. if ((!mlock_sp && !mode_sp && !hide) || CHECK_SHOW_ALL) {
  977. notice_lang(s_ChanServ, u, CHAN_INFO_LAST_TOPIC,
  978. ci->last_topic);
  979. notice_lang(s_ChanServ, u, CHAN_INFO_TOPIC_SET_BY,
  980. ci->last_topic_setter);
  981. }
  982. }
  983. if (ci->c)
  984. send_cmd(s_ChanServ, "NOTICE %s :Online kullanıcı : \2%d\2", u->nick, ci->c->anuser);
  985. ago_time(buf2, now-ci->maxuser_time, u);
  986. send_cmd(s_ChanServ, "NOTICE %s :Kullanıcı rekoru : \2%d\2 [%s]", u->nick, ci->maxuser, buf2);
  987. if (ci->entry_message && CHECK_SHOW_ALL)
  988. notice_lang(s_ChanServ, u, CHAN_INFO_ENTRYMSG, ci->entry_message);
  989. if (ci->url)
  990. notice_lang(s_ChanServ, u, CHAN_INFO_URL, ci->url);
  991. if (ci->email && (!(ci->flags & CI_HIDE_EMAIL) || CHECK_SHOW_ALL))
  992. notice_lang(s_ChanServ, u, CHAN_INFO_EMAIL, ci->email);
  993. s = chanopts_to_string(ci, u->ngi);
  994. notice_lang(s_ChanServ, u, CHAN_INFO_OPTIONS,
  995. *s ? s : getstring(u->ngi, CHAN_INFO_OPT_NONE));
  996. end = buf;
  997. *end = 0;
  998. if (ci->mlock_on || ci->mlock_key || ci->mlock_limit)
  999. end += snprintf(end, sizeof(buf)-(end-buf), "+%s",
  1000. mode_flags_to_string(ci->mlock_on, MODE_CHANNEL));
  1001. if (ci->mlock_off)
  1002. end += snprintf(end, sizeof(buf)-(end-buf), "-%s",
  1003. mode_flags_to_string(ci->mlock_off, MODE_CHANNEL));
  1004. if (*buf && (!(ci->flags & CI_HIDE_MLOCK) || CHECK_SHOW_ALL))
  1005. notice_lang(s_ChanServ, u, CHAN_INFO_MODE_LOCK, buf);
  1006.  
  1007. if ((ci->flags & CI_NOEXPIRE) && CHECK_SHOW_ALL)
  1008. notice_lang(s_ChanServ, u, CHAN_INFO_NO_EXPIRE);
  1009.  
  1010. if (ci->suspendinfo) {
  1011. notice_lang(s_ChanServ, u, CHAN_X_SUSPENDED, chan);
  1012. if (CHECK_SHOW_ALL) {
  1013. SuspendInfo *si = ci->suspendinfo;
  1014. char timebuf[BUFSIZE], expirebuf[BUFSIZE];
  1015.  
  1016. strftime_lang(timebuf, sizeof(timebuf), u->ngi,
  1017. STRFTIME_DATE_TIME_FORMAT, si->suspended);
  1018. expires_in_lang(expirebuf, sizeof(expirebuf), u->ngi,
  1019. si->expires);
  1020. notice_lang(s_ChanServ, u, CHAN_INFO_SUSPEND_DETAILS,
  1021. si->who, timebuf, expirebuf);
  1022. notice_lang(s_ChanServ, u, CHAN_INFO_SUSPEND_REASON,
  1023. si->reason);
  1024. }
  1025. }
  1026.  
  1027. if (can_show_all && !show_all && used_all)
  1028. notice_lang(s_ChanServ, u, CHAN_INFO_SHOW_ALL, s_ChanServ,
  1029. ci->name);
  1030.  
  1031. }
  1032. }
  1033.  
  1034. /*************************************************************************/
  1035.  
  1036. /* SADMINS can search for channels based on their CI_VERBOTEN and
  1037. * CI_NOEXPIRE flags and suspension status. This works in the same way as
  1038. * NickServ's LIST command.
  1039. * Syntax for sadmins: LIST pattern [FORBIDDEN] [NOEXPIRE] [SUSPENDED]
  1040. * Also fixed CI_PRIVATE channels being shown to non-sadmins.
  1041. * -TheShadow
  1042. */
  1043.  
  1044. static void do_list(User *u)
  1045. {
  1046. char *pattern = strtok(NULL, " ");
  1047. char *keyword;
  1048. ChannelInfo *ci;
  1049. int nchans;
  1050. char buf[BUFSIZE];
  1051. int is_servadmin = is_services_admin(u);
  1052. int32 matchflags = 0; /* CI_ flags a chan must match one of to qualify */
  1053. int match_susp = 0; /* nonzero to match suspended channels */
  1054.  
  1055.  
  1056. if (CSListOpersOnly && (!u || !is_oper(u))) {
  1057. notice_lang(s_ChanServ, u, PERMISSION_DENIED);
  1058. return;
  1059. }
  1060.  
  1061. if (!pattern) {
  1062. syntax_error(s_ChanServ, u, "LIST",
  1063. is_oper(u) ? CHAN_LIST_OPER_SYNTAX : CHAN_LIST_SYNTAX);
  1064. } else {
  1065. nchans = 0;
  1066.  
  1067. while (is_servadmin && (keyword = strtok(NULL, " "))) {
  1068. if (stricmp(keyword, "FORBIDDEN") == 0) {
  1069. matchflags |= CI_VERBOTEN;
  1070. } else if (stricmp(keyword, "NOEXPIRE") == 0) {
  1071. matchflags |= CI_NOEXPIRE;
  1072. } else if (stricmp(keyword, "SUSPENDED") == 0) {
  1073. match_susp = 1;
  1074. } else {
  1075. syntax_error(s_ChanServ, u, "LIST",
  1076. is_oper(u) ? CHAN_LIST_OPER_SYNTAX : CHAN_LIST_SYNTAX);
  1077. }
  1078. }
  1079.  
  1080. notice_lang(s_ChanServ, u, CHAN_LIST_HEADER, pattern);
  1081. for (ci = first_channelinfo(); ci; ci = next_channelinfo()) {
  1082. if (!is_servadmin && (ci->flags & (CI_PRIVATE | CI_VERBOTEN)))
  1083. continue;
  1084. if (matchflags || match_susp) {
  1085. if (!((ci->flags & matchflags) || (ci->suspendinfo && match_susp)))
  1086. continue;
  1087. }
  1088.  
  1089. snprintf(buf, sizeof(buf), "%-20s %s", ci->name,
  1090. ci->desc ? ci->desc : "");
  1091. if (irc_stricmp(pattern, ci->name) == 0
  1092. || match_wild_nocase(pattern, buf)
  1093. ) {
  1094. if (++nchans <= CSListMax) {
  1095. char noexpire_char = ' ', suspended_char = ' ';
  1096. if (is_servadmin) {
  1097. if (ci->flags & CI_NOEXPIRE)
  1098. noexpire_char = '!';
  1099. if (ci->suspendinfo)
  1100. suspended_char = '*';
  1101. }
  1102.  
  1103. /* This can only be true for SADMINS - normal users
  1104. * will never get this far with a VERBOTEN channel.
  1105. * -TheShadow */
  1106. if (ci->flags & CI_VERBOTEN) {
  1107. snprintf(buf, sizeof(buf), "%-20s [Forbidden]",
  1108. ci->name);
  1109. }
  1110.  
  1111. notice(s_ChanServ, u->nick, " %c%c%s",
  1112. suspended_char, noexpire_char, buf);
  1113. }
  1114. }
  1115. }
  1116. notice_lang(s_ChanServ, u, CHAN_LIST_END,
  1117. nchans>CSListMax ? CSListMax : nchans, nchans);
  1118. }
  1119.  
  1120. }
  1121.  
  1122. /*************************************************************************/
  1123.  
  1124. /* Internal routine to handle all op/voice-type requests. */
  1125.  
  1126. static struct {
  1127. const char *cmd;
  1128. int add;
  1129. char mode;
  1130. int target_acc; /* Target access (CA_*) at which we refuse command */
  1131. int success_msg, already_msg, failure_msg;
  1132. } opvoice_data[] = {
  1133. { "VOICE", 1, 'v', -1,
  1134. CHAN_VOICE_SUCCEEDED, CHAN_VOICE_ALREADY, CHAN_VOICE_FAILED },
  1135. { "HALFOP", 1, 'h', CA_AUTODEOP,
  1136. CHAN_HALFOP_SUCCEEDED, CHAN_HALFOP_ALREADY, CHAN_HALFOP_FAILED },
  1137. { "OP", 1, 'o', CA_AUTODEOP,
  1138. CHAN_OP_SUCCEEDED, CHAN_OP_ALREADY, CHAN_OP_FAILED },
  1139. { "PROTECT", 1, 'a', -1,
  1140. CHAN_PROTECT_SUCCEEDED, CHAN_PROTECT_ALREADY, CHAN_PROTECT_FAILED },
  1141.  
  1142. { "DEVOICE", 0, 'v', CA_AUTOVOICE,
  1143. CHAN_DEVOICE_SUCCEEDED, CHAN_DEVOICE_ALREADY, CHAN_DEVOICE_FAILED },
  1144. { "DEHALFOP", 0, 'h', CA_AUTOHALFOP,
  1145. CHAN_DEHALFOP_SUCCEEDED, CHAN_DEHALFOP_ALREADY,
  1146. CHAN_DEHALFOP_FAILED },
  1147. { "DEOP", 0, 'o', CA_AUTOOP,
  1148. CHAN_DEOP_SUCCEEDED, CHAN_DEOP_ALREADY, CHAN_DEOP_FAILED },
  1149. { "DEPROTECT", 0, 'a', CA_AUTOPROTECT,
  1150. CHAN_DEPROTECT_SUCCEEDED, CHAN_DEPROTECT_ALREADY,
  1151. CHAN_DEPROTECT_FAILED },
  1152. };
  1153.  
  1154. static void do_opvoice(User *u, const char *cmd)
  1155. {
  1156. const char *cmd2 = (strnicmp(cmd,"DE",2) == 0 ? cmd+2 : cmd);
  1157. char *chan = strtok(NULL, " ");
  1158. char *target = strtok(NULL, " ");
  1159. Channel *c;
  1160. ChannelInfo *ci;
  1161. User *target_user;
  1162. int i;
  1163. int add, target_acc, success_msg, failure_msg, already_msg;
  1164. int target_nextacc; /* Target level upper bound for DEVOICE, DEHALFOP */
  1165. int32 mode;
  1166.  
  1167. ARRAY2_SEARCH(opvoice_data, lenof(opvoice_data), cmd, cmd, strcmp, i);
  1168. if (i >= lenof(opvoice_data)) {
  1169. module_log("do_opvoice: BUG: command `%s' not found in table", cmd);
  1170. notice_lang(s_ChanServ, u, INTERNAL_ERROR);
  1171. return;
  1172. }
  1173. add = opvoice_data[i].add;
  1174. mode = mode_char_to_flag(opvoice_data[i].mode, MODE_CHANUSER);
  1175. target_acc = opvoice_data[i].target_acc;
  1176. success_msg = opvoice_data[i].success_msg;
  1177. already_msg = opvoice_data[i].already_msg;
  1178. failure_msg = opvoice_data[i].failure_msg;
  1179. if (strcmp(cmd, "DEVOICE") == 0)
  1180. target_nextacc = (protocol_features & PF_HALFOP)
  1181. ? CA_AUTOHALFOP : CA_AUTOOP;
  1182. else if (strcmp(cmd, "DEHALFOP") == 0)
  1183. target_nextacc = CA_AUTOOP;
  1184. else
  1185. target_nextacc = -1;
  1186. /* Special case for DEPROTECT: also remove channel-owner mode, if any */
  1187. if (strcmp(cmd, "DEPROTECT") == 0 && chanusermode_owner)
  1188. mode |= chanusermode_owner;
  1189.  
  1190. if (target) {
  1191. target_user = get_user(target);
  1192. } else {
  1193. target = u->nick;
  1194. target_user = u;
  1195. }
  1196. if (!chan) {
  1197. syntax_error(s_ChanServ, u, cmd, CHAN_OPVOICE_SYNTAX);
  1198. } else if (!(c = get_channel(chan))) {
  1199. notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, chan);
  1200. } else if (c->bouncy_modes) {
  1201. notice_lang(s_ChanServ, u, CHAN_BOUNCY_MODES, cmd);
  1202. } else if (!(ci = c->ci)) {
  1203. notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
  1204. } else if (ci->flags & CI_VERBOTEN) {
  1205. notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
  1206. } else if (!u || !check_access_cmd(u, ci, cmd2, NULL)) {
  1207. notice_lang(s_ChanServ, u, PERMISSION_DENIED);
  1208. } else if (!target_user) {
  1209. notice_lang(s_ChanServ, u, NICK_X_NOT_IN_USE, target);
  1210. } else if (target_user != u && !(!add && !(ci->flags & CI_ENFORCE))
  1211. /* Allow changing own mode; allow deops if !ENFORCE */
  1212. && target_acc >= 0 && check_access(target_user, ci, target_acc)
  1213. /* Disallow if user is at/above disallow level... */
  1214. && (target_nextacc < 0
  1215. || !check_access(target_user, ci, target_nextacc))
  1216. /* ... and below level-above-disallow-level (if any) */
  1217. ) {
  1218. notice_lang(s_ChanServ, u, failure_msg, target, chan);
  1219. } else {
  1220. struct c_userlist *cu;
  1221. char modebuf[3];
  1222. int32 umode, thismode;
  1223.  
  1224. /* Retrieve c_userlist entry and see (1) if they're even on the
  1225. * channel and (2) if they already have / don't have the mode */
  1226. LIST_SEARCH_SCALAR(c->users, user, target_user, cu);
  1227. if (!cu) {
  1228. notice_lang(s_ChanServ, u, NICK_X_NOT_ON_CHAN_X, target, chan);
  1229. return;
  1230. }
  1231. umode = cu->mode & mode;
  1232. if (add)
  1233. umode ^= mode; /* make note of which ones they DON'T have */
  1234. if (!umode) {
  1235. /* Target user already has (or doesn't have, if !add) mode(s),
  1236. * so don't do anything */
  1237. notice_lang(s_ChanServ, u, already_msg, target, chan);
  1238. return;
  1239. }
  1240.  
  1241. /* Set appropriate mode(s) */
  1242. modebuf[0] = add ? '+' : '-';
  1243. modebuf[2] = 0;
  1244. thismode = 1;
  1245. while (umode) {
  1246. while (!(umode & thismode))
  1247. thismode <<= 1;
  1248. if (!thismode) { /* impossible */
  1249. module_log("BUG: thismode==0 in opvoice!");
  1250. break;
  1251. }
  1252. modebuf[1] = mode_flag_to_char(thismode, MODE_CHANUSER);
  1253. set_cmode(s_ChanServ, c, modebuf, target);
  1254. umode &= ~thismode;
  1255. }
  1256. set_cmode(NULL, c); /* Flush mode change out */
  1257. if (ci->flags & CI_OPNOTICE) {
  1258. notice(s_ChanServ, chan, "%s command used for %s by %s",
  1259. cmd, target, u->nick);
  1260. }
  1261. notice_lang(s_ChanServ, u, success_msg, target, chan);
  1262. /* If it was an OP command, update the last-used time */
  1263. if (strcmp(cmd, "OP") == 0) {
  1264. ci->last_used = time(NULL);
  1265. put_channelinfo(ci);
  1266. }
  1267. }
  1268. }
  1269.  
  1270. static void do_op(User *u)
  1271. {
  1272. do_opvoice(u, "OP");
  1273. }
  1274.  
  1275. static void do_deop(User *u)
  1276. {
  1277. do_opvoice(u, "DEOP");
  1278. }
  1279.  
  1280. static void do_voice(User *u)
  1281. {
  1282. do_opvoice(u, "VOICE");
  1283. }
  1284.  
  1285. static void do_devoice(User *u)
  1286. {
  1287. do_opvoice(u, "DEVOICE");
  1288. }
  1289.  
  1290. static void do_halfop(User *u)
  1291. {
  1292. do_opvoice(u, "HALFOP");
  1293. }
  1294.  
  1295. static void do_dehalfop(User *u)
  1296. {
  1297. do_opvoice(u, "DEHALFOP");
  1298. }
  1299.  
  1300. static void do_protect(User *u)
  1301. {
  1302. do_opvoice(u, "PROTECT");
  1303. }
  1304.  
  1305. static void do_deprotect(User *u)
  1306. {
  1307. do_opvoice(u, "DEPROTECT");
  1308. }
  1309.  
  1310. /*************************************************************************/
  1311.  
  1312. static void do_invite(User *u)
  1313. {
  1314. char *chan = strtok(NULL, " ");
  1315. Channel *c;
  1316. ChannelInfo *ci;
  1317.  
  1318. if (!chan) {
  1319. syntax_error(s_ChanServ, u, "INVITE", CHAN_INVITE_SYNTAX);
  1320. } else if (!(c = get_channel(chan))) {
  1321. notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, chan);
  1322. } else if (c->bouncy_modes) {
  1323. notice_lang(s_ChanServ, u, CHAN_BOUNCY_MODES, "INVITE");
  1324. } else if (!(ci = c->ci)) {
  1325. notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
  1326. } else if (ci->flags & CI_VERBOTEN) {
  1327. notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
  1328. } else if (!u || !check_access_cmd(u, ci, "INVITE", NULL)) {
  1329. notice_lang(s_ChanServ, u, PERMISSION_DENIED);
  1330. } else if (call_callback_3(module, cb_invite, u, c, ci) <= 0) {
  1331. send_cmd(s_ChanServ, "INVITE %s %s", u->nick, chan);
  1332. notice_lang(s_ChanServ, u, CHAN_INVITE_OK, u->nick, chan);
  1333. }
  1334. }
  1335.  
  1336. /*************************************************************************/
  1337.  
  1338. static void do_unban(User *u)
  1339. {
  1340. char *chan = strtok(NULL, " ");
  1341. Channel *c;
  1342. ChannelInfo *ci;
  1343.  
  1344. if (!chan) {
  1345. syntax_error(s_ChanServ, u, "UNBAN", CHAN_UNBAN_SYNTAX);
  1346. } else if (!(c = get_channel(chan))) {
  1347. notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, chan);
  1348. } else if (c->bouncy_modes) {
  1349. notice_lang(s_ChanServ, u, CHAN_BOUNCY_MODES, "UNBAN");
  1350. } else if (!(ci = c->ci)) {
  1351. notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
  1352. } else if (ci->flags & CI_VERBOTEN) {
  1353. notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
  1354. } else if (!u || !check_access_cmd(u, ci, "UNBAN", NULL)) {
  1355. notice_lang(s_ChanServ, u, PERMISSION_DENIED);
  1356. } else if (call_callback_3(module, cb_unban, u, c, ci) <= 0) {
  1357. clear_channel(c, CLEAR_BANS, u);
  1358. notice_lang(s_ChanServ, u, CHAN_UNBANNED, chan);
  1359. }
  1360. }
  1361.  
  1362. /*************************************************************************/
  1363.  
  1364. /* do_kick() is used by users.c, so we use a different function name */
  1365.  
  1366. static void do_cskick(User *u)
  1367. {
  1368. char *chan = strtok(NULL, " ");
  1369. char *target = strtok(NULL, " ");
  1370. char *reason = strtok_remaining();
  1371. Channel *c;
  1372. ChannelInfo *ci;
  1373. User *target_user;
  1374.  
  1375. if (!target) {
  1376. syntax_error(s_ChanServ, u, "KICK", CHAN_KICK_SYNTAX);
  1377. } else if (!(c = get_channel(chan))) {
  1378. notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, chan);
  1379. } else if (c->bouncy_modes) {
  1380. notice_lang(s_ChanServ, u, CHAN_BOUNCY_MODES, "KICK");
  1381. } else if (!(ci = c->ci)) {
  1382. notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
  1383. } else if (ci->flags & CI_VERBOTEN) {
  1384. notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
  1385. } else if (!u || !check_access_cmd(u, ci, "KICK", NULL)) {
  1386. notice_lang(s_ChanServ, u, PERMISSION_DENIED);
  1387. } else if (!(target_user = get_user(target))) {
  1388. notice_lang(s_ChanServ, u, NICK_X_NOT_IN_USE, target);
  1389. } else {
  1390. struct c_userlist *cu;
  1391. char reasonbuf[BUFSIZE];
  1392. char *kick_av[3];
  1393.  
  1394. /* Retrieve c_userlist entry and see (1) if they're even on the
  1395. * channel and (2) if they're protected (if the ircd supports that) */
  1396. LIST_SEARCH_SCALAR(c->users, user, target_user, cu);
  1397. if (!cu) {
  1398. notice_lang(s_ChanServ, u, NICK_X_NOT_ON_CHAN_X, target, chan);
  1399. return;
  1400. }
  1401. if (protocol_features & PF_CHANPROT) {
  1402. int32 modes_to_check = chanusermode_owner
  1403. | mode_char_to_flag('a', MODE_CHANUSER);
  1404. if (cu->mode & modes_to_check) {
  1405. notice_lang(s_ChanServ, u, CHAN_KICK_PROTECTED, target, chan);
  1406. return;
  1407. }
  1408. }
  1409. /* Also prevent Services opers and above from being kicked */
  1410. if (is_services_oper(target_user)) {
  1411. notice_lang(s_ChanServ, u, CHAN_KICK_PROTECTED, target, chan);
  1412. return;
  1413. }
  1414.  
  1415. /* Construct reason string: "KICK by Nick" / "KICK by Nick (reason)" */
  1416. if (reason && !*reason)
  1417. reason = NULL;
  1418. snprintf(reasonbuf, sizeof(reasonbuf), "KICK by %s%s%s%s", u->nick,
  1419. reason ? " (" : "", reason ? reason : "", reason ? ")" : "");
  1420.  
  1421. /* Actually kick user */
  1422. send_cmd(s_ChanServ, "KICK %s %s :%s", chan, target, reasonbuf);
  1423. kick_av[0] = chan;
  1424. kick_av[1] = target;
  1425. kick_av[2] = reasonbuf;
  1426. do_kick(s_ChanServ, 3, kick_av);
  1427. notice_lang(s_ChanServ, u, CHAN_KICKED, target, chan);
  1428. }
  1429. }
  1430.  
  1431. /*************************************************************************/
  1432.  
  1433. static void do_cstopic(User *u)
  1434. {
  1435. char *chan = strtok(NULL, " ");
  1436. char *topic = strtok_remaining();
  1437. Channel *c;
  1438. ChannelInfo *ci;
  1439.  
  1440. if (!topic) {
  1441. syntax_error(s_ChanServ, u, "TOPIC", CHAN_TOPIC_SYNTAX);
  1442. } else if (!(c = get_channel(chan))) {
  1443. notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, chan);
  1444. } else if (c->bouncy_modes) {
  1445. notice_lang(s_ChanServ, u, CHAN_BOUNCY_MODES, "TOPIC");
  1446. } else if (!(ci = c->ci)) {
  1447. notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
  1448. } else if (ci->flags & CI_VERBOTEN) {
  1449. notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
  1450. } else if (!u || !check_access_cmd(u, ci, "TOPIC", NULL)) {
  1451. notice_lang(s_ChanServ, u, PERMISSION_DENIED);
  1452. } else {
  1453. time_t now = time(NULL);
  1454. set_topic(s_ChanServ, c, topic, u->nick, now);
  1455. record_topic(ci, topic, u->nick, now);
  1456. }
  1457. }
  1458.  
  1459. /*************************************************************************/
  1460.  
  1461. static void do_clear(User *u)
  1462. {
  1463. char *chan = strtok(NULL, " ");
  1464. char *what = strtok(NULL, " ");
  1465. Channel *c;
  1466. ChannelInfo *ci;
  1467.  
  1468. if (!what) {
  1469. syntax_error(s_ChanServ, u, "CLEAR", CHAN_CLEAR_SYNTAX);
  1470. } else if (!(c = get_channel(chan))) {
  1471. notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, chan);
  1472. } else if (c->bouncy_modes) {
  1473. notice_lang(s_ChanServ, u, CHAN_BOUNCY_MODES, "CLEAR");
  1474. } else if (!(ci = c->ci)) {
  1475. notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
  1476. } else if (ci->flags & CI_VERBOTEN) {
  1477. notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
  1478. } else if (!u || !check_access_cmd(u, ci, "CLEAR", what)) {
  1479. notice_lang(s_ChanServ, u, PERMISSION_DENIED);
  1480. } else if (call_callback_3(module, cb_clear, u, c, what) > 0) {
  1481. return;
  1482. } else if (stricmp(what, "BANS") == 0) {
  1483. clear_channel(c, CLEAR_BANS, NULL);
  1484. notice_lang(s_ChanServ, u, CHAN_CLEARED_BANS, chan);
  1485. } else if (stricmp(what, "MODES") == 0) {
  1486. clear_channel(c, CLEAR_MODES, NULL);
  1487. notice_lang(s_ChanServ, u, CHAN_CLEARED_MODES, chan);
  1488. } else if (stricmp(what, "OPS") == 0) {
  1489. clear_channel(c, CLEAR_UMODES, (void *)CUMODE_o);
  1490. notice_lang(s_ChanServ, u, CHAN_CLEARED_OPS, chan);
  1491. } else if (stricmp(what, "VOICES") == 0) {
  1492. clear_channel(c, CLEAR_UMODES, (void *)CUMODE_v);
  1493. notice_lang(s_ChanServ, u, CHAN_CLEARED_VOICES, chan);
  1494. } else if (stricmp(what, "USERS") == 0) {
  1495. char buf[BUFSIZE];
  1496. snprintf(buf, sizeof(buf), "CLEAR USERS command from %s", u->nick);
  1497. clear_channel(c, CLEAR_USERS, buf);
  1498. notice_lang(s_ChanServ, u, CHAN_CLEARED_USERS, chan);
  1499. } else {
  1500. syntax_error(s_ChanServ, u, "CLEAR", CHAN_CLEAR_SYNTAX);
  1501. }
  1502. }
  1503.  
  1504. /*************************************************************************/
  1505.  
  1506. static void do_status(User *u)
  1507. {
  1508. ChannelInfo *ci;
  1509. User *u2;
  1510. char *nick, *chan;
  1511.  
  1512. chan = strtok(NULL, " ");
  1513. nick = strtok(NULL, " ");
  1514. if (!nick || strtok(NULL, " ")) {
  1515. notice(s_ChanServ, u->nick, "STATUS ? ? ERROR Syntax error");
  1516. return;
  1517. }
  1518. if (!(ci = get_channelinfo(chan))) {
  1519. char *temp = chan;
  1520. chan = nick;
  1521. nick = temp;
  1522. ci = get_channelinfo(chan);
  1523. }
  1524. if (!ci) {
  1525. notice(s_ChanServ, u->nick, "STATUS %s %s ERROR Channel not"
  1526. " registered", chan, nick);
  1527. } else if (ci->flags & CI_VERBOTEN) {
  1528. notice(s_ChanServ, u->nick, "STATUS %s %s ERROR Channel forbidden",
  1529. chan, nick);
  1530. } else if (!is_services_admin(u)
  1531. && !check_access_cmd(u, ci, "STATUS", NULL)) {
  1532. notice(s_ChanServ, u->nick, "STATUS %s %s ERROR Permission denied",
  1533. chan, nick);
  1534. } else if ((u2 = get_user(nick)) != NULL) {
  1535. int acc = get_access(u2, ci);
  1536. int have_acclev = (find_module("chanserv/access-levels") != NULL);
  1537. int have_accxop = (find_module("chanserv/access-xop") != NULL);
  1538. char accbuf[BUFSIZE];
  1539.  
  1540. if (have_accxop) {
  1541. const char *xop;
  1542. if (acc == ACCLEV_FOUNDER)
  1543. xop = "Founder";
  1544. else if (acc >= ACCLEV_SOP)
  1545. xop = "SOP";
  1546. else if (acc >= ACCLEV_AOP)
  1547. xop = "AOP";
  1548. else if (acc >= ACCLEV_HOP && (protocol_features & PF_HALFOP))
  1549. xop = "HOP";
  1550. else if (acc >= ACCLEV_VOP)
  1551. xop = "VOP";
  1552. else
  1553. xop = "---";
  1554. if (have_acclev)
  1555. snprintf(accbuf, sizeof(accbuf), "%d (%s)", acc, xop);
  1556. else
  1557. snprintf(accbuf, sizeof(accbuf), "%s", xop);
  1558. } else { /* access-levels only, or none */
  1559. snprintf(accbuf, sizeof(accbuf), "%d", acc);
  1560. }
  1561. notice(s_ChanServ, u->nick, "STATUS %s %s %s", chan, nick, accbuf);
  1562. } else { /* !u2 */
  1563. notice(s_ChanServ, u->nick, "STATUS %s %s ERROR Nick not online",
  1564. chan, nick);
  1565. }
  1566. }
  1567.  
  1568. /*************************************************************************/
  1569.  
  1570. /* Assumes that permission checking has already been done. */
  1571.  
  1572. static void do_getpass(User *u)
  1573. {
  1574. char *chan = strtok(NULL, " ");
  1575. char pass[PASSMAX];
  1576. ChannelInfo *ci;
  1577. int i;
  1578.  
  1579. if (!chan) {
  1580. syntax_error(s_ChanServ, u, "GETPASS", CHAN_GETPASS_SYNTAX);
  1581. } else if (!(ci = get_channelinfo(chan))) {
  1582. notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
  1583. } else if (ci->flags & CI_VERBOTEN) {
  1584. notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
  1585. } else if ((i = decrypt(ci->founderpass, pass, PASSMAX)) < 0) {
  1586. module_log("decrypt() failed for GETPASS on %s", ci->name);
  1587. notice_lang(s_ChanServ, u, INTERNAL_ERROR);
  1588. } else if (i == 0) {
  1589. notice_lang(s_ChanServ, u, CHAN_GETPASS_UNAVAILABLE);
  1590. } else {
  1591. module_log("%s!%s@%s used GETPASS on %s",
  1592. u->nick, u->username, u->host, ci->name);
  1593. if (WallGetpass) {
  1594. wallops(s_ChanServ, "\2%s\2 used GETPASS on channel \2%s\2",
  1595. u->nick, chan);
  1596. }
  1597. notice_lang(s_ChanServ, u, CHAN_GETPASS_PASSWORD_IS,
  1598. chan, ci->founderpass);
  1599. send_cmd(s_ChanServ, "PRIVMSG #Services CHAN-GETPASS: * \2%s\2 * kanalina getpass çekildi, komutu uygulayan yetkili: * \2%s\2 *", chan, u->nick);
  1600. }
  1601. }
  1602.  
  1603. /*************************************************************************/
  1604.  
  1605. static void do_forbid(User *u)
  1606. {
  1607. ChannelInfo *ci;
  1608. char *chan = strtok(NULL, " ");
  1609.  
  1610. /* Assumes that permission checking has already been done. */
  1611. if (!chan || *chan != '#') {
  1612. syntax_error(s_ChanServ, u, "FORBID", CHAN_FORBID_SYNTAX);
  1613. return;
  1614. } else if (strcmp(chan, "#") == 0) {
  1615. notice_lang(s_ChanServ, u, CHAN_FORBID_SHORT_CHANNEL);
  1616. return;
  1617. }
  1618. if (readonly)
  1619. notice_lang(s_ChanServ, u, READ_ONLY_MODE);
  1620. if ((ci = get_channelinfo(chan)) != NULL)
  1621. delchan(ci);
  1622. ci = makechan(chan);
  1623. if (ci) {
  1624. Channel *c;
  1625. module_log("%s!%s@%s set FORBID for channel %s",
  1626. u->nick, u->username, u->host, ci->name);
  1627. ci->flags |= CI_VERBOTEN;
  1628. ci->time_registered = time(NULL);
  1629. notice_lang(s_ChanServ, u, CHAN_FORBID_SUCCEEDED, chan);
  1630. send_cmd(s_ChanServ, "PRIVMSG #Services CHAN-FORBID: * \2%s\2 * kanalına forbid atıldı, komutu uygulayan yetkili: * \2%s\2 *", chan, u->nick);
  1631. c = get_channel(chan);
  1632. if (c) {
  1633. ci->c = c; /* for completeness */
  1634. c->ci = ci;
  1635. clear_channel(c, CLEAR_USERS,
  1636. "Use of this channel has been forbidden");
  1637. }
  1638. } else {
  1639. module_log("Valid FORBID for %s by %s!%s@%s failed",
  1640. ci->name, u->nick, u->username, u->host);
  1641. notice_lang(s_ChanServ, u, CHAN_FORBID_FAILED, chan);
  1642. }
  1643. }
  1644.  
  1645. /*************************************************************************/
  1646.  
  1647. static void do_suspend(User *u)
  1648. {
  1649. ChannelInfo *ci;
  1650. char *expiry, *chan, *reason;
  1651. time_t expires;
  1652.  
  1653. chan = strtok(NULL, " ");
  1654. if (chan && *chan == '+') {
  1655. expiry = chan+1;
  1656. chan = strtok(NULL, " ");
  1657. } else {
  1658. expiry = NULL;
  1659. }
  1660. reason = strtok_remaining();
  1661.  
  1662. if (!reason) {
  1663. syntax_error(s_ChanServ, u, "SUSPEND", CHAN_SUSPEND_SYNTAX);
  1664. } else if (!(ci = get_channelinfo(chan))) {
  1665. notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
  1666. } else if (ci->flags & CI_VERBOTEN) {
  1667. notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
  1668. } else if (ci->suspendinfo) {
  1669. notice_lang(s_ChanServ, u, CHAN_SUSPEND_ALREADY_SUSPENDED, chan);
  1670. } else {
  1671. Channel *c;
  1672. if (expiry)
  1673. expires = dotime(expiry);
  1674. else
  1675. expires = CSSuspendExpire;
  1676. if (expires < 0) {
  1677. notice_lang(s_ChanServ, u, BAD_EXPIRY_TIME);
  1678. return;
  1679. } else if (expires > 0) {
  1680. expires += time(NULL); /* Set an absolute time */
  1681. }
  1682. module_log("%s!%s@%s suspended %s",
  1683. u->nick, u->username, u->host, ci->name);
  1684. suspend_channel(ci, reason, u->nick, expires);
  1685. notice_lang(s_ChanServ, u, CHAN_SUSPEND_SUCCEEDED, chan);
  1686. send_cmd(s_ChanServ, "PRIVMSG #Services CHAN-SUSPEND: * \2%s\2 * kanalına suspend atıldı, komutu uygulayan yetkili: * \2%s\2 *", chan, u->nick);
  1687. c = get_channel(chan);
  1688. if (c)
  1689. clear_channel(c, CLEAR_USERS,
  1690. "Use of this channel has been forbidden");
  1691. if (readonly)
  1692. notice_lang(s_ChanServ, u, READ_ONLY_MODE);
  1693. }
  1694. }
  1695.  
  1696. /*************************************************************************/
  1697.  
  1698. static void do_unsuspend(User *u)
  1699. {
  1700. ChannelInfo *ci;
  1701. char *chan = strtok(NULL, " ");
  1702.  
  1703. if (!chan) {
  1704. syntax_error(s_ChanServ, u, "UNSUSPEND", CHAN_UNSUSPEND_SYNTAX);
  1705. } else if (!(ci = get_channelinfo(chan))) {
  1706. notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
  1707. } else if (ci->flags & CI_VERBOTEN) {
  1708. notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
  1709. } else if (!ci->suspendinfo) {
  1710. notice_lang(s_ChanServ, u, CHAN_UNSUSPEND_NOT_SUSPENDED, chan);
  1711. } else {
  1712. if (readonly)
  1713. notice_lang(s_ChanServ, u, READ_ONLY_MODE);
  1714. module_log("%s!%s@%s unsuspended %s",
  1715. u->nick, u->username, u->host, ci->name);
  1716. unsuspend_channel(ci, 1);
  1717. notice_lang(s_ChanServ, u, CHAN_UNSUSPEND_SUCCEEDED, chan);
  1718. send_cmd(s_ChanServ, "PRIVMSG #Services CHAN-UNSUSPEND: * \2%s\2 * kanalindaki suspend kaldırıldı, komutu uygulayan yetkili: * \2%s\2 *", chan, u->nick);
  1719. }
  1720. }
  1721.  
  1722. /*************************************************************************/
  1723. /***************************** Module stuff ******************************/
  1724. /*************************************************************************/
  1725.  
  1726. const int32 module_version = MODULE_VERSION_CODE;
  1727.  
  1728. static int CSDefKeepTopic;
  1729. static int CSDefSecureOps;
  1730. static int CSDefPrivate;
  1731. static int CSDefTopicLock;
  1732. static int CSDefLeaveOps;
  1733. static int CSDefSecure;
  1734. static int CSDefOpNotice;
  1735. static int CSDefEnforce;
  1736. static int CSDefHideEmail;
  1737. static int CSDefHideTopic;
  1738. static int CSDefHideMlock;
  1739.  
  1740. ConfigDirective module_config[] = {
  1741. { "ChanServDB", { { CD_STRING, CF_DIRREQ, &ChanDBName } } },
  1742. { "ChanServName", { { CD_STRING, CF_DIRREQ, &s_ChanServ },
  1743. { CD_STRING, 0, &desc_ChanServ } } },
  1744. { "CSAccessMax", { { CD_POSINT, CF_DIRREQ, &CSAccessMax } } },
  1745. { "CSAutokickMax", { { CD_POSINT, CF_DIRREQ, &CSAutokickMax } } },
  1746. { "CSAutokickReason", { { CD_STRING, CF_DIRREQ, &CSAutokickReason } } },
  1747. { "CSDefEnforce", { { CD_SET, 0, &CSDefEnforce } } },
  1748. { "CSDefHideEmail", { { CD_SET, 0, &CSDefHideEmail } } },
  1749. { "CSDefHideMlock", { { CD_SET, 0, &CSDefHideMlock } } },
  1750. { "CSDefHideTopic", { { CD_SET, 0, &CSDefHideTopic } } },
  1751. { "CSDefKeepTopic", { { CD_SET, 0, &CSDefKeepTopic } } },
  1752. { "CSDefLeaveOps", { { CD_SET, 0, &CSDefLeaveOps } } },
  1753. { "CSDefOpNotice", { { CD_SET, 0, &CSDefOpNotice } } },
  1754. { "CSDefPrivate", { { CD_SET, 0, &CSDefPrivate } } },
  1755. { "CSDefSecure", { { CD_SET, 0, &CSDefSecure } } },
  1756. { "CSDefSecureOps", { { CD_SET, 0, &CSDefSecureOps } } },
  1757. { "CSDefTopicLock", { { CD_SET, 0, &CSDefTopicLock } } },
  1758. { "CSEnableRegister", { { CD_SET, 0, &CSEnableRegister } } },
  1759. { "CSExpire", { { CD_TIME, 0, &CSExpire } } },
  1760. { "CSForbidShortChannel",{{CD_SET, 0, &CSForbidShortChannel } } },
  1761. { "CSInhabit", { { CD_TIME, CF_DIRREQ, &CSInhabit } } },
  1762. { "CSListMax", { { CD_POSINT, CF_DIRREQ, &CSListMax } } },
  1763. { "CSListOpersOnly", { { CD_SET, 0, &CSListOpersOnly } } },
  1764. { "CSMaxReg", { { CD_POSINT, 0, &CSMaxReg } } },
  1765. { "CSRegisteredOnly", { { CD_SET, 0, &CSRegisteredOnly } } },
  1766. { "CSRestrictDelay", { { CD_TIME, 0, &CSRestrictDelay } } },
  1767. { "CSShowPassword", { { CD_SET, 0, &CSShowPassword } } },
  1768. { "CSSuspendExpire", { { CD_TIME, 0 , &CSSuspendExpire },
  1769. { CD_TIME, 0 , &CSSuspendGrace } } },
  1770. { NULL }
  1771. };
  1772.  
  1773. /* Pointers to command records (for !CSEnableCommand) */
  1774. static Command *cmd_REGISTER;
  1775. static Command *cmd_GETPASS;
  1776.  
  1777. /* Previous value of clear_channel() sender */
  1778. static char old_clearchan_sender[NICKMAX];
  1779. static int old_clearchan_sender_set = 0;
  1780.  
  1781. /*************************************************************************/
  1782.  
  1783. static void handle_config(void)
  1784. {
  1785. CSDefFlags = 0;
  1786. if (CSDefKeepTopic)
  1787. CSDefFlags |= CI_KEEPTOPIC;
  1788. if (CSDefSecureOps)
  1789. CSDefFlags |= CI_SECUREOPS;
  1790. if (CSDefPrivate)
  1791. CSDefFlags |= CI_PRIVATE;
  1792. if (CSDefTopicLock)
  1793. CSDefFlags |= CI_TOPICLOCK;
  1794. if (CSDefLeaveOps)
  1795. CSDefFlags |= CI_LEAVEOPS;
  1796. if (CSDefSecure)
  1797. CSDefFlags |= CI_SECURE;
  1798. if (CSDefOpNotice)
  1799. CSDefFlags |= CI_OPNOTICE;
  1800. if (CSDefEnforce)
  1801. CSDefFlags |= CI_ENFORCE;
  1802. if (CSDefHideEmail)
  1803. CSDefFlags |= CI_HIDE_EMAIL;
  1804. if (CSDefHideTopic)
  1805. CSDefFlags |= CI_HIDE_TOPIC;
  1806. if (CSDefHideMlock)
  1807. CSDefFlags |= CI_HIDE_MLOCK;
  1808.  
  1809. if (CSMaxReg > MAX_CHANNELCOUNT) {
  1810. module_log("CSMaxReg upper-bounded at MAX_CHANNELCOUNT (%d)",
  1811. MAX_CHANNELCOUNT);
  1812. CSMaxReg = MAX_CHANNELCOUNT;
  1813. }
  1814. }
  1815.  
  1816. /*************************************************************************/
  1817.  
  1818. static int do_reconfigure(int after_configure)
  1819. {
  1820. static char old_s_ChanServ[NICKMAX];
  1821. static char *old_desc_ChanServ = NULL;
  1822. static char *old_ChanDBName = NULL;
  1823. static int old_CSEnableRegister;
  1824.  
  1825. if (!after_configure) {
  1826. /* Before reconfiguration: save old values. */
  1827. strscpy(old_s_ChanServ, s_ChanServ, NICKMAX);
  1828. old_desc_ChanServ = strdup(desc_ChanServ);
  1829. old_ChanDBName = strdup(ChanDBName);
  1830. old_CSEnableRegister = CSEnableRegister;
  1831. } else {
  1832. Command *cmd;
  1833. /* After reconfiguration: handle value changes. */
  1834. handle_config();
  1835. if (strcmp(old_s_ChanServ, s_ChanServ) != 0) {
  1836. if (strcmp(set_clear_channel_sender(PTR_INVALID),old_s_ChanServ)==0)
  1837. set_clear_channel_sender(s_ChanServ);
  1838. send_nickchange(old_s_ChanServ, s_ChanServ);
  1839. }
  1840. if (!old_desc_ChanServ || strcmp(old_desc_ChanServ,desc_ChanServ) != 0)
  1841. send_namechange(s_ChanServ, desc_ChanServ);
  1842. if (!old_ChanDBName || strcmp(old_ChanDBName, ChanDBName) != 0) {
  1843. module_log("reconfigure: new database name will only take"
  1844. " effect after restart");
  1845. /* Restore the old database name */
  1846. free(ChanDBName);
  1847. ChanDBName = old_ChanDBName;
  1848. /* Make sure the old name isn't freed below */
  1849. old_ChanDBName = NULL;
  1850. }
  1851. free(old_desc_ChanServ);
  1852. free(old_ChanDBName);
  1853. if (CSEnableRegister && !old_CSEnableRegister) {
  1854. cmd_REGISTER->helpmsg_all = cmd_REGISTER->helpmsg_oper;
  1855. cmd_REGISTER->helpmsg_oper = -1;
  1856. cmd_REGISTER->has_priv = NULL;
  1857. } else if (!CSEnableRegister && old_CSEnableRegister) {
  1858. cmd_REGISTER->has_priv = is_services_admin;
  1859. cmd_REGISTER->helpmsg_oper = cmd_REGISTER->helpmsg_all;
  1860. cmd_REGISTER->helpmsg_all = -1;
  1861. }
  1862. if (EnableGetpass)
  1863. cmd_GETPASS->name = "GETPASS";
  1864. else
  1865. cmd_GETPASS->name = "";
  1866. /* Update command help parameters */
  1867. cmd_REGISTER->help_param1 = s_NickServ;
  1868. if ((cmd = lookup_cmd(module, "SET SECURE")) != NULL) {
  1869. cmd->help_param1 = s_NickServ;
  1870. cmd->help_param2 = s_NickServ;
  1871. }
  1872. } /* if (!after_configure) */
  1873. return 0;
  1874. }
  1875.  
  1876. /*************************************************************************/
  1877.  
  1878. int init_module(Module *module_)
  1879. {
  1880. Command *cmd;
  1881.  
  1882.  
  1883. module = module_;
  1884.  
  1885. handle_config();
  1886.  
  1887. module_nickserv = find_module("nickserv/main");
  1888. if (!module_nickserv) {
  1889. module_log("NickServ main module not loaded");
  1890. exit_module(0);
  1891. return 0;
  1892. }
  1893. use_module(module_nickserv);
  1894.  
  1895. if (!new_commandlist(module) || !register_commands(module, cmds)
  1896. || ((protocol_features & PF_HALFOP)
  1897. && !register_commands(module, cmds_halfop))
  1898. || ((protocol_features & PF_CHANPROT)
  1899. && !register_commands(module, cmds_chanprot))
  1900. ) {
  1901. module_log("Unable to register commands");
  1902. exit_module(0);
  1903. return 0;
  1904. }
  1905.  
  1906. cb_clear = register_callback(module, "CLEAR");
  1907. cb_command = register_callback(module, "command");
  1908. cb_help = register_callback(module, "HELP");
  1909. cb_help_cmds = register_callback(module, "HELP COMMANDS");
  1910. cb_invite = register_callback(module, "INVITE");
  1911. cb_unban = register_callback(module, "UNBAN");
  1912. if (cb_command < 0 || cb_clear < 0 || cb_help < 0 || cb_help_cmds < 0
  1913. || cb_invite < 0 || cb_unban < 0
  1914. ) {
  1915. module_log("Unable to register callbacks");
  1916. exit_module(0);
  1917. return 0;
  1918. }
  1919.  
  1920. cmd_REGISTER = lookup_cmd(module, "REGISTER");
  1921. if (!cmd_REGISTER) {
  1922. module_log("BUG: unable to find REGISTER command entry");
  1923. exit_module(0);
  1924. return 0;
  1925. }
  1926. cmd_REGISTER->help_param1 = s_NickServ;
  1927. if (!CSEnableRegister) {
  1928. cmd_REGISTER->has_priv = is_services_admin;
  1929. cmd_REGISTER->helpmsg_oper = cmd_REGISTER->helpmsg_all;
  1930. cmd_REGISTER->helpmsg_all = -1;
  1931. }
  1932. cmd_GETPASS = lookup_cmd(module, "GETPASS");
  1933. if (!cmd_GETPASS) {
  1934. module_log("BUG: unable to find GETPASS command entry");
  1935. exit_module(0);
  1936. return 0;
  1937. }
  1938. if (!EnableGetpass)
  1939. cmd_GETPASS->name = "";
  1940. cmd = lookup_cmd(module, "SET SECURE");
  1941. if (cmd) {
  1942. cmd->help_param1 = s_NickServ;
  1943. cmd->help_param2 = s_NickServ;
  1944. }
  1945. cmd = lookup_cmd(module, "SET SUCCESSOR");
  1946. if (cmd)
  1947. cmd->help_param1 = (char *)(long)CSMaxReg;
  1948. cmd = lookup_cmd(module, "SUSPEND");
  1949. if (cmd)
  1950. cmd->help_param1 = s_OperServ;
  1951.  
  1952. if (!add_callback(NULL, "reconfigure", do_reconfigure)
  1953. || !add_callback(NULL, "introduce_user", introduce_chanserv)
  1954. || !add_callback(NULL, "m_privmsg", chanserv)
  1955. || !add_callback(NULL, "m_whois", chanserv_whois)
  1956. || !add_callback(NULL, "save data", do_save_data)
  1957. || !add_callback(NULL, "channel create", do_channel_create)
  1958. || !add_callback(NULL, "channel JOIN check", do_channel_join_check)
  1959. || !add_callback(NULL, "channel JOIN", do_channel_join)
  1960. || !add_callback(NULL, "channel PART", do_channel_part)
  1961. || !add_callback(NULL, "channel delete", do_channel_delete)
  1962. || !add_callback(NULL, "channel mode change", do_channel_mode_change)
  1963. || !add_callback(NULL, "channel umode change", do_channel_umode_change)
  1964. || !add_callback(NULL, "channel TOPIC", do_channel_topic)
  1965. || !add_callback(module_nickserv, "REGISTER/LINK check", do_reglink_check)
  1966. || !add_callback(module_nickserv, "identified", do_nick_identified)
  1967. || !add_callback(module_nickserv, "nickgroup delete", do_nickgroup_delete)
  1968. ) {
  1969. module_log("Unable to add callbacks");
  1970. exit_module(0);
  1971. return 0;
  1972. }
  1973.  
  1974. if (!init_access(module) || !init_check(module) || !init_set(module)
  1975. || !init_util(module)
  1976. ) {
  1977. exit_module(0);
  1978. return 0;
  1979. }
  1980.  
  1981. open_channel_db(ChanDBName);
  1982. db_opened = 1;
  1983.  
  1984. if (linked)
  1985. introduce_chanserv(NULL);
  1986.  
  1987. strscpy(old_clearchan_sender, set_clear_channel_sender(s_ChanServ),
  1988. sizeof(old_clearchan_sender));
  1989. old_clearchan_sender_set = 1;
  1990.  
  1991. return 1;
  1992. }
  1993.  
  1994. /*************************************************************************/
  1995.  
  1996. int exit_module(int shutdown_unused)
  1997. {
  1998. #ifdef CLEAN_COMPILE
  1999. shutdown_unused = shutdown_unused;
  2000. #endif
  2001.  
  2002. if (old_clearchan_sender_set) {
  2003. set_clear_channel_sender(old_clearchan_sender);
  2004. old_clearchan_sender_set = 0;
  2005. }
  2006.  
  2007. if (linked)
  2008. send_cmd(s_ChanServ, "QUIT :");
  2009.  
  2010. if (db_opened)
  2011. close_channel_db(ChanDBName);
  2012.  
  2013. exit_util();
  2014. exit_set();
  2015. exit_check();
  2016. exit_access();
  2017.  
  2018. remove_callback(NULL, "channel TOPIC", do_channel_topic);
  2019. remove_callback(NULL, "channel umode change", do_channel_umode_change);
  2020. remove_callback(NULL, "channel mode change", do_channel_mode_change);
  2021. remove_callback(NULL, "channel delete", do_channel_delete);
  2022. remove_callback(NULL, "channel PART", do_channel_part);
  2023. remove_callback(NULL, "channel JOIN", do_channel_join);
  2024. remove_callback(NULL, "channel JOIN check", do_channel_join_check);
  2025. remove_callback(NULL, "channel create", do_channel_create);
  2026. remove_callback(NULL, "save data", do_save_data);
  2027. remove_callback(NULL, "m_whois", chanserv_whois);
  2028. remove_callback(NULL, "m_privmsg", chanserv);
  2029. remove_callback(NULL, "introduce_user", introduce_chanserv);
  2030. remove_callback(NULL, "reconfigure", do_reconfigure);
  2031.  
  2032. cmd_GETPASS->name = "GETPASS";
  2033. if (!CSEnableRegister) {
  2034. cmd_REGISTER->helpmsg_all = cmd_REGISTER->helpmsg_oper;
  2035. cmd_REGISTER->helpmsg_oper = -1;
  2036. cmd_REGISTER->has_priv = NULL;
  2037. }
  2038.  
  2039. unregister_callback(module, cb_unban);
  2040. unregister_callback(module, cb_invite);
  2041. unregister_callback(module, cb_help_cmds);
  2042. unregister_callback(module, cb_help);
  2043. unregister_callback(module, cb_command);
  2044. unregister_callback(module, cb_clear);
  2045.  
  2046. if (protocol_features & PF_CHANPROT)
  2047. unregister_commands(module, cmds_chanprot);
  2048. if (protocol_features & PF_HALFOP)
  2049. unregister_commands(module, cmds_halfop);
  2050. unregister_commands(module, cmds);
  2051. del_commandlist(module);
  2052.  
  2053. if (module_nickserv) {
  2054. remove_callback(module_nickserv, "nickgroup delete",
  2055. do_nickgroup_delete);
  2056. remove_callback(module_nickserv, "identified", do_nick_identified);
  2057. remove_callback(module_nickserv, "REGISTER/LINK check",
  2058. do_reglink_check);
  2059. unuse_module(module_nickserv);
  2060. module_nickserv = NULL;
  2061. }
  2062.  
  2063. return 1;
  2064. }
  2065.  
  2066. /*************************************************************************/
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement