toXic , Falan Göremedim ßen Arıyorum 2 Saattir. Ne Yaptımsa. Hata Veriyor ; S
Kod: Kodu kopyalamak için üzerine çift tıklayın!
/* Main ChanServ module.
*
* IRC Services is copyright (c) 1996-2006 Andrew Church.
* E-mail: <
Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.
>
* Parts written by Andrew Kempe and others.
* This program is free but copyrighted software; see the file COPYING for
* details.
*/
/*************************************************************************/
#include "services.h"
#include "modules.h"
#include "conffile.h"
#include "language.h"
#include "commands.h"
#include "encrypt.h"
#include "modules/nickserv/nickserv.h"
#include "modules/operserv/operserv.h"
#include "chanserv.h"
#include "cs-local.h"
/*************************************************************************/
/************************** Declaration section **************************/
/*************************************************************************/
static Module *module;
static Module *module_nickserv;
static int cb_clear = -1;
static int cb_command = -1;
static int cb_help = -1;
static int cb_help_cmds = -1;
static int cb_invite = -1;
static int cb_unban = -1;
static int db_opened = 0;
char *s_ChanServ;
static char *desc_ChanServ;
static char *ChanDBName;
EXPORT_VAR(char *,s_ChanServ)
static int CSEnableRegister;
int CSRegisteredOnly;
int32 CSMaxReg;
int32 CSDefFlags;
time_t C***pire;
int CSShowPassword;
int32 CSAccessMax;
int32 CSAutokickMax;
char * CSAutokickReason;
time_t CSInhabit;
time_t CSRestrictDelay;
int CSListOpersOnly;
int32 CSListMax;
time_t CSSuspendExpire;
time_t CSSuspendGrace;
int CSForbidShortChannel;
EXPORT_VAR(int32,CSMaxReg)
/*************************************************************************/
/* Channel option list. */
#define CHANOPT(x) \
{ #x, CI_##x, CHAN_INFO_OPT_##x, \
CHAN_SET_##x##_ON, CHAN_SET_##x##_OFF, CHAN_SET_##x##_SYNTAX }
ChanOpt chanopts[] = {
CHANOPT(KEEPTOPIC),
CHANOPT(TOPICLOCK),
CHANOPT(PRIVATE),
CHANOPT(SECUREOPS),
CHANOPT(LEAVEOPS),
CHANOPT(RESTRICTED),
CHANOPT(SECURE),
CHANOPT(OPNOTICE),
CHANOPT(ENFORCE),
{ "NOEXPIRE", CI_NOEXPIRE, -1, CHAN_SET_NOEXPIRE_ON,
CHAN_SET_NOEXPIRE_OFF, CHAN_SET_NOEXPIRE_SYNTAX },
{ NULL }
};
#undef CHANOPT
/*************************************************************************/
/* Local functions. */
static void do_help(User *u);
static void do_register(User *u);
static void do_identify(User *u);
static void do_drop(User *u);
static void do_info(User *u);
static void do_list(User *u);
static void do_op(User *u);
static void do_deop(User *u);
static void do_voice(User *u);
static void do_devoice(User *u);
static void do_halfop(User *u);
static void do_dehalfop(User *u);
static void do_protect(User *u);
static void do_deprotect(User *u);
static void do_invite(User *u);
static void do_unban(User *u);
static void do_cskick(User *u);
static void do_cstopic(User *u);
static void do_clear(User *u);
static void do_getpass(User *u);
static void do_forbid(User *u);
static void do_suspend(User *u);
static void do_unsuspend(User *u);
static void do_status(User *u);
/*************************************************************************/
/* Command list. */
static Command cmds[] = {
{ "HELP", do_help, NULL, -1, -1,-1 },
{ "REGISTER", do_register, NULL, CHAN_HELP_REGISTER, -1,-1 },
{ "IDENTIFY", do_identify, NULL, CHAN_HELP_IDENTIFY, -1,-1 },
{ "DROP", do_drop, NULL, -1,
CHAN_HELP_DROP, CHAN_OPER_HELP_DROP },
{ "SET", do_set, NULL, CHAN_HELP_SET, -1, CHAN_OPER_HELP_SET },
{ "SET FOUNDER", NULL, NULL, CHAN_HELP_SET_FOUNDER, -1,-1 },
{ "SET SUCCESSOR", NULL, NULL, CHAN_HELP_SET_SUCCESSOR, -1,-1 },
{ "SET PASSWORD", NULL, NULL, CHAN_HELP_SET_PASSWORD, -1,-1 },
{ "SET DESC", NULL, NULL, CHAN_HELP_SET_DESC, -1,-1 },
{ "SET URL", NULL, NULL, CHAN_HELP_SET_URL, -1,-1 },
{ "SET EMAIL", NULL, NULL, CHAN_HELP_SET_EMAIL, -1,-1 },
{ "SET ENTRYMSG", NULL, NULL, CHAN_HELP_SET_ENTRYMSG, -1,-1 },
{ "SET KEEPTOPIC", NULL, NULL, CHAN_HELP_SET_KEEPTOPIC, -1,-1 },
{ "SET TOPICLOCK", NULL, NULL, CHAN_HELP_SET_TOPICLOCK, -1,-1 },
{ "SET MLOCK", NULL, NULL, CHAN_HELP_SET_MLOCK, -1,-1 },
{ "SET HIDE", NULL, NULL, CHAN_HELP_SET_HIDE, -1,-1 },
{ "SET PRIVATE", NULL, NULL, CHAN_HELP_SET_PRIVATE, -1,-1 },
{ "SET RESTRICTED", NULL, NULL, CHAN_HELP_SET_RESTRICTED, -1,-1 },
{ "SET SECURE", NULL, NULL, CHAN_HELP_SET_SECURE, -1,-1 },
{ "SET SECUREOPS", NULL, NULL, CHAN_HELP_SET_SECUREOPS, -1,-1 },
{ "SET LEAVEOPS", NULL, NULL, CHAN_HELP_SET_LEAVEOPS, -1,-1 },
{ "SET OPNOTICE", NULL, NULL, CHAN_HELP_SET_OPNOTICE, -1,-1 },
{ "SET ENFORCE", NULL, NULL, CHAN_HELP_SET_ENFORCE, -1,-1 },
{ "SET NOEXPIRE", NULL, NULL, -1, -1, CHAN_OPER_HELP_SET_NOEXPIRE },
{ "UNSET", do_unset, NULL, CHAN_HELP_UNSET,
-1, CHAN_OPER_HELP_UNSET },
{ "INFO", do_info, NULL, CHAN_HELP_INFO,
-1, CHAN_OPER_HELP_INFO },
{ "LIST", do_list, NULL, -1,
CHAN_HELP_LIST, CHAN_OPER_HELP_LIST },
{ "AKICK", do_akick, NULL, CHAN_HELP_AKICK, -1,-1,
(void *)ACCLEV_SOP },
{ "OP", do_op, NULL, CHAN_HELP_OP, -1,-1,
(void *)ACCLEV_AOP },
{ "DEOP", do_deop, NULL, CHAN_HELP_DEOP, -1,-1,
(void *)ACCLEV_AOP },
{ "VOICE", do_voice, NULL, CHAN_HELP_VOICE, -1,-1,
(void *)ACCLEV_VOP },
{ "DEVOICE", do_devoice, NULL, CHAN_HELP_DEVOICE, -1,-1,
(void *)ACCLEV_VOP },
{ "INVITE", do_invite, NULL, CHAN_HELP_INVITE, -1,-1,
(void *)ACCLEV_AOP },
{ "UNBAN", do_unban, NULL, CHAN_HELP_UNBAN, -1,-1,
(void *)ACCLEV_AOP },
{ "KICK", do_cskick, NULL, CHAN_HELP_KICK, -1,-1,
(void *)ACCLEV_AOP },
{ "TOPIC", do_cstopic, NULL, CHAN_HELP_TOPIC, -1,-1,
(void *)ACCLEV_AOP },
{ "CLEAR", do_clear, NULL, CHAN_HELP_CLEAR, -1,-1,
(void *)ACCLEV_SOP },
{ "STATUS", do_status, NULL, CHAN_HELP_STATUS, -1,-1,
(void *)ACCLEV_SOP },
{ "GETPASS", do_getpass, is_services_admin, -1,
-1, CHAN_OPER_HELP_GETPASS },
{ "FORBID", do_forbid, is_services_admin, -1,
-1, CHAN_OPER_HELP_FORBID },
{ "SUSPEND", do_suspend, is_services_admin, -1,
-1, CHAN_OPER_HELP_SUSPEND },
{ "UNSUSPEND",do_unsuspend,is_services_admin, -1,
-1, CHAN_OPER_HELP_UNSUSPEND },
{ NULL }
};
static Command cmds_halfop[] = {
{ "HALFOP", do_halfop, NULL, CHAN_HELP_HALFOP, -1,-1,
(void *)ACCLEV_AOP },
{ "DEHALFOP", do_dehalfop, NULL, CHAN_HELP_DEHALFOP, -1,-1,
(void *)ACCLEV_AOP },
{ NULL }
};
static Command cmds_chanprot[] = {
{ "PROTECT", do_protect, NULL, CHAN_HELP_PROTECT, -1,-1,
(void *)ACCLEV_AOP },
{ "DEPROTECT",do_deprotect,NULL, CHAN_HELP_DEPROTECT, -1,-1,
(void *)ACCLEV_AOP },
{ NULL }
};
/*************************************************************************/
/************************ Main ChanServ routines *************************/
/*************************************************************************/
/* Introduce the ChanServ pseudoclient. */
static int introduce_chanserv(const char *nick)
{
if (!nick || irc_stricmp(nick, s_ChanServ) == 0) {
char modebuf[BUFSIZE];
snprintf(modebuf, sizeof(modebuf), "o%s", pseudoclient_modes);
send_nick(s_ChanServ, ServiceUser, ServiceHost, ServerName,
desc_ChanServ, modebuf);
return nick ? 1 : 0;
}
return 0;
}
/*************************************************************************/
/* Main ChanServ routine. */
static int chanserv(const char *source, const char *target, char *buf)
{
char *cmd;
User *u = get_user(source);
if (irc_stricmp(target, s_ChanServ) != 0)
return 0;
if (!u) {
module_log("user record for %s not found", source);
notice(s_ChanServ, source, getstring(NULL, INTERNAL_ERROR));
return 1;
}
cmd = strtok(buf, " ");
if (!cmd) {
return 1;
} else if (stricmp(cmd, "\1PING") == 0) {
const char *s;
if (!(s = strtok(NULL, "")))
s = "\1";
notice(s_ChanServ, source, "\1PING %s", s);
} else {
if (call_callback_2(module, cb_command, u, cmd) <= 0)
run_cmd(s_ChanServ, u, module, cmd);
}
return 1;
}
/*************************************************************************/
/* Return a /WHOIS response for ChanServ. */
static int chanserv_whois(const char *source, char *who, char *extra)
{
if (irc_stricmp(who, s_ChanServ) != 0)
return 0;
send_cmd(ServerName, "311 %s %s %s %s * :%s", source, who,
ServiceUser, ServiceHost, desc_ChanServ);
send_cmd(ServerName, "312 %s %s %s :%s", source, who,
ServerName, ServerDesc);
send_cmd(ServerName, "318 %s %s End of /WHOIS response.", source, who);
return 1;
}
void ago_time(char *buf, time_t t, User *u)
{
int days, hours, minutes, seconds;
days = t/(24*3600);
t %= 24*3600;
hours = t/3600;
t %= 3600;
minutes = t/60;
t %= 60;
seconds = t;
sprintf(buf,"%d gün, %d saat, %d dakika ve %d saniye önce", days, hours, minutes, seconds);
}
/*************************************************************************/
/* Save channel database. */
static int do_save_data()
{
sync_channel_db(ChanDBName);
return 0;
}
/*************************************************************************/
/* Callback for newly-created channels. */
static int do_channel_create(Channel *c, User *u, int32 modes)
{
/* Store ChannelInfo pointer in channel record */
c->ci = get_channelinfo(c->name);
if (c->ci) {
/* Store return pointer in ChannelInfo record */
c->ci->c = c;
c->maxuser = c->ci->maxuser;
c->maxuser_time = c->ci->maxuser_time;
} else
{
c->maxuser = 1;
c->maxuser_time = time(NULL);
}
/* Restore locked modes and saved topic */
/* Note: these should be outside the c->ci test to ensure any spurious
* +r modes are cleared */
check_modes(c);
restore_topic(c);
return 0;
}
/*************************************************************************/
/* Callback for users trying to join channels. */
static int do_channel_join_check(const char *channel, User *user)
{
return check_kick(user, channel);
}
/*************************************************************************/
/* Callback for users joining channels. */
static int do_channel_join(Channel *c, struct c_userlist *u)
{
User *user = u->user;
ChannelInfo *ci = c->ci;
check_chan_user_modes(NULL, u, c, -1);
if (c->maxuser < ++(c->anuser)) {
c->maxuser = c->anuser;
c->maxuser_time = time(NULL);
if(ci) {
ci->maxuser = c->maxuser;
ci->maxuser_time = c->maxuser_time;
}
}
if (ci && ci->entry_message)
notice(s_ChanServ, user->nick, "(%s) %s", ci->name, ci->entry_message);
return 0;
}
/*************************************************************************/
/* Callback for users leaving channels. Update the channel's last used
* time if the user was an auto-op user.
*/
static int do_channel_part(Channel *c, User *u, const char *reason)
{
if (c->ci && check_access(u, c->ci, CA_AUTOOP)) {
c->ci->last_used = time(NULL);
put_channelinfo(c->ci);
}
return 0;
}
/*************************************************************************/
/* Callback for channels being deleted. */
static int do_channel_delete(Channel *c)
{
if (c->ci)
c->ci->c = NULL;
return 0;
}
/*************************************************************************/
/* Callback for channel mode changes. */
static int do_channel_mode_change(const char *source_unused, Channel *c)
{
check_modes(c);
return 0;
}
/*************************************************************************/
/* Callback for channel user mode changes. */
static int do_channel_umode_change(const char *source, Channel *c,
struct c_userlist *u, int32 oldmodes)
{
if (!(u->mode & CUMODE_o))
u->flags &= ~CUFLAG_DEOPPED;
check_chan_user_modes(source, u, c, oldmodes);
return 0;
}
/*************************************************************************/
/* Callback for channel topic changes. */
static int do_channel_topic(Channel *c, const char *topic, const char *setter,
time_t topic_time)
{
ChannelInfo *ci = c->ci;
if (check_topiclock(c, topic_time))
return 1;
record_topic(ci, topic, setter, topic_time);
return 0;
}
/*************************************************************************/
/* Callback for NickServ REGISTER/LINK check; we disallow
* registration/linking of the ChanServ pseudoclient nickname.
*/
static int do_reglink_check(const User *u, const char *nick,
const char *pass, const char *email)
{
return irc_stricmp(nick, s_ChanServ) == 0;
}
/*************************************************************************/
/* Callback for users who have identified to their nicks: give them modes
* as if they had just joined the channel.
*/
static int do_nick_identified(User *u, int old_authstat)
{
struct u_chanlist *uc; /* Node in list of channels the user is in */
struct c_userlist *cu; /* Node in list of users in a channel */
LIST_FOREACH (uc, u->chans) {
LIST_SEARCH_SCALAR(uc->chan->users, user, u, cu);
if (!cu) {
module_log("do_nick_identified(): BUG: user record not found in"
" channel %s for user %s", uc->chan->name, u->nick);
continue;
}
/* Use an empty source to force a mode recheck */
check_chan_user_modes("", cu, uc->chan, -1);
}
return 0;
}
/*************************************************************************/
/* Remove a (deleted or expired) nickname group from all channel lists. */
static int do_nickgroup_delete(const NickGroupInfo *ngi, const char *oldnick)
{
int i;
int id = ngi->id;
ChannelInfo *ci;
for (ci = first_channelinfo(); ci; ci = next_channelinfo()) {
int modified = 0;
if (ci->founder == id) {
int was_suspended = (ci->suspendinfo != NULL);
char name_save[CHANMAX];
if (was_suspended)
strscpy(name_save, ci->name, CHANMAX);
if (ci->successor) {
NickGroupInfo *ngi2 = get_ngi_id(ci->successor);
if (!ngi2) {
module_log("Unable to access successor group %u for"
" deleted channel %s, deleting channel",
ci->successor, ci->name);
goto delete;
} else if (check_channel_limit(ngi2, NULL) < 0) {
module_log("Transferring foundership of %s from deleted"
" nick %s to successor %s", ci->name,
oldnick, ngi_mainnick(ngi2));
uncount_chan(ci);
ci->founder = ci->successor;
ci->successor = 0;
count_chan(ci);
} else {
module_log("Successor (%s) of %s owns too many channels,"
" deleting channel", ngi_mainnick(ngi2),
ci->name);
goto delete;
}
} else {
module_log("Deleting channel %s owned by deleted nick %s",
ci->name, oldnick);
delete:
delchan(ci);
if (was_suspended) {
/* Channel was suspended, so make it forbidden */
module_log("Channel %s was suspended, forbidding it",
name_save);
ci = makechan(name_save);
ci->flags |= CI_VERBOTEN;
}
continue;
}
modified = 1;
}
if (ci->successor == id) {
ci->successor = 0;
modified = 1;
}
ARRAY_FOREACH (i, ci->access) {
if (ci->access[i].nickgroup == id) {
ci->access[i].nickgroup = 0;
modified = 1;
}
}
if (modified)
put_channelinfo(ci);
}
return 0;
}
/*************************************************************************/
/*********************** ChanServ command routines ***********************/
/*************************************************************************/
/* Short routine for do_help() to return the proper access level string for
* a given level based on which access modules are loaded. Assumes numeric
* levels if no access module is loaded.
*/
static const char *getstring_cmdacc(NickGroupInfo *ngi, int16 level)
{
int str_levxop, str_lev, str_xop;
switch (level) {
case ACCLEV_SOP:
str_levxop = CHAN_HELP_REQSOP_LEVXOP;
str_lev = CHAN_HELP_REQSOP_LEV;
str_xop = CHAN_HELP_REQSOP_XOP;
break;
case ACCLEV_AOP:
str_levxop = CHAN_HELP_REQAOP_LEVXOP;
str_lev = CHAN_HELP_REQAOP_LEV;
str_xop = CHAN_HELP_REQAOP_XOP;
break;
case ACCLEV_HOP:
str_levxop = CHAN_HELP_REQHOP_LEVXOP;
str_lev = CHAN_HELP_REQHOP_LEV;
str_xop = CHAN_HELP_REQHOP_XOP;
break;
case ACCLEV_VOP:
str_levxop = CHAN_HELP_REQVOP_LEVXOP;
str_lev = CHAN_HELP_REQVOP_LEV;
str_xop = CHAN_HELP_REQVOP_XOP;
break;
default:
module_log("BUG: weird level (%d) in getstring_cmdacc()", level);
return "???";
}
if (find_module("chanserv/access-xop")) {
if (find_module("chanserv/access-levels"))
return getstring(ngi, str_levxop);
else
return getstring(ngi, str_xop);
} else {
return getstring(ngi, str_lev);
}
}
static void do_help(User *u)
{
char *cmd = strtok_remaining();
Command *cmdrec;
if (!cmd) {
notice_help(s_ChanServ, u, CHAN_HELP);
if (C***pire)
notice_help(s_ChanServ, u, CHAN_HELP_EXPIRES,
maketime(u->ngi,C***pire,0));
} else if (call_callback_2(module, cb_help, u, cmd) > 0) {
return;
} else if (stricmp(cmd, "COMMANDS") == 0) {
notice_help(s_ChanServ, u, CHAN_HELP_COMMANDS);
if (find_module("chanserv/sendpass"))
notice_help(s_ChanServ, u, CHAN_HELP_COMMANDS_SENDPASS);
notice_help(s_ChanServ, u, CHAN_HELP_COMMANDS_DROP);
if (find_module("chanserv/access-levels"))
notice_help(s_ChanServ, u, CHAN_HELP_COMMANDS_LEVELS);
if (find_module("chanserv/access-xop")) {
notice_help(s_ChanServ, u, CHAN_HELP_COMMANDS_XOP);
if (protocol_features & PF_HALFOP)
notice_help(s_ChanServ, u, CHAN_HELP_COMMANDS_HOP);
}
notice_help(s_ChanServ, u, CHAN_HELP_COMMANDS_OPVOICE);
if (protocol_features & PF_HALFOP)
notice_help(s_ChanServ, u, CHAN_HELP_COMMANDS_HALFOP);
if (protocol_features & PF_CHANPROT)
notice_help(s_ChanServ, u, CHAN_HELP_COMMANDS_PROTECT);
notice_help(s_ChanServ, u, CHAN_HELP_COMMANDS_INVITE);
if (!CSListOpersOnly)
notice_help(s_ChanServ, u, CHAN_HELP_COMMANDS_LIST);
notice_help(s_ChanServ, u, CHAN_HELP_COMMANDS_AKICK);
call_callback_2(module, cb_help_cmds, u, 0);
if (is_oper(u)) {
notice_help(s_ChanServ, u, CHAN_OPER_HELP_COMMANDS);
if (EnableGetpass)
notice_help(s_ChanServ, u, CHAN_OPER_HELP_COMMANDS_GETPASS);
notice_help(s_ChanServ, u, CHAN_OPER_HELP_COMMANDS_FORBID);
if (CSListOpersOnly)
notice_help(s_ChanServ, u, CHAN_HELP_COMMANDS_LIST);
call_callback_2(module, cb_help_cmds, u, 1);
notice_help(s_ChanServ, u, CHAN_OPER_HELP_COMMANDS_END);
}
} else if (!CSEnableRegister && is_oper(u) && stricmp(cmd,"REGISTER")==0) {
notice_help(s_ChanServ, u, CHAN_HELP_REGISTER);
notice_help(s_ChanServ, u, CHAN_HELP_REGISTER_ADMINONLY);
} else if (stricmp(cmd, "LIST") == 0) {
if (is_oper(u))
notice_help(s_ChanServ, u, CHAN_OPER_HELP_LIST);
else
notice_help(s_ChanServ, u, CHAN_HELP_LIST);
if (CSListOpersOnly)
notice_help(s_ChanServ, u, CHAN_HELP_LIST_OPERSONLY);
} else if (stricmp(cmd, "KICK") == 0) {
cmdrec = lookup_cmd(module, cmd);
notice_help(s_ChanServ, u, CHAN_HELP_KICK,
getstring_cmdacc(u->ngi, cmdrec ? (int)(long)cmdrec->help_param1 : -1));
if (protocol_features & PF_CHANPROT)
notice_help(s_ChanServ, u, CHAN_HELP_KICK_PROTECTED);
} else if (stricmp(cmd, "CLEAR") == 0) {
notice_help(s_ChanServ, u, CHAN_HELP_CLEAR);
if (protocol_features & PF_BANEXCEPT)
notice_help(s_ChanServ, u, CHAN_HELP_CLEAR_EXCEPTIONS);
if (protocol_features & PF_INVITEMASK)
notice_help(s_ChanServ, u, CHAN_HELP_CLEAR_INVITES);
notice_help(s_ChanServ, u, CHAN_HELP_CLEAR_MID);
if (protocol_features & PF_HALFOP)
notice_help(s_ChanServ, u, CHAN_HELP_CLEAR_HALFOPS);
cmdrec = lookup_cmd(module, cmd);
notice_help(s_ChanServ, u, CHAN_HELP_CLEAR_END,
getstring_cmdacc(u->ngi, cmdrec ? (int)(long)cmdrec->help_param1 : -1));
} else if ((stricmp(cmd, "AKICK") == 0
|| stricmp(cmd, "OP") == 0
|| stricmp(cmd, "DEOP") == 0
|| stricmp(cmd, "VOICE") == 0
|| stricmp(cmd, "DEVOICE") == 0
|| stricmp(cmd, "HALFOP") == 0
|| stricmp(cmd, "DEHALFOP") == 0
|| stricmp(cmd, "PROTECT") == 0
|| stricmp(cmd, "DEPROTECT") == 0
|| stricmp(cmd, "INVITE") == 0
|| stricmp(cmd, "UNBAN") == 0
|| stricmp(cmd, "KICK") == 0
|| stricmp(cmd, "TOPIC") == 0
|| stricmp(cmd, "CLEAR") == 0
|| stricmp(cmd, "STATUS") == 0)
&& (cmdrec = lookup_cmd(module, cmd)) != NULL
) {
notice_help(s_ChanServ, u, cmdrec->helpmsg_all,
getstring_cmdacc(u->ngi, (int)(long)cmdrec->help_param1));
} else {
help_cmd(s_ChanServ, u, module, cmd);
}
}
/*************************************************************************/
static void do_register(User *u)
{
char *chan = strtok(NULL, " ");
char *pass = strtok(NULL, " ");
char *desc = strtok_remaining();
NickInfo *ni = u->ni;
NickGroupInfo *ngi = u->ngi;
Channel *c;
ChannelInfo *ci;
struct u_chaninfolist *uc;
int max;
if (readonly) {
notice_lang(s_ChanServ, u, CHAN_REGISTER_DISABLED);
return;
}
if (!desc) {
syntax_error(s_ChanServ, u, "REGISTER", CHAN_REGISTER_SYNTAX);
} else if (strcmp(chan, "#") == 0) {
notice_lang(s_ChanServ, u, CHAN_REGISTER_SHORT_CHANNEL);
} else if (*chan == '&') {
notice_lang(s_ChanServ, u, CHAN_REGISTER_NOT_LOCAL);
} else if (*chan != '#') {
notice_lang(s_ChanServ, u, CHAN_REGISTER_INVALID_NAME);
} else if (!ni) {
notice_lang(s_ChanServ, u, CHAN_MUST_REGISTER_NICK, s_NickServ);
} else if (!user_identified(u)) {
notice_lang(s_ChanServ, u, CHAN_MUST_IDENTIFY_NICK,
s_NickServ, s_NickServ);
} else if ((ci = get_channelinfo(chan)) != NULL) {
if (ci->flags & CI_VERBOTEN) {
module_log("Attempt to register forbidden channel %s by %s!%s@%s",
ci->name, u->nick, u->username, u->host);
notice_lang(s_ChanServ, u, CHAN_MAY_NOT_BE_REGISTERED, chan);
} else if (ci->suspendinfo) {
module_log("Attempt to register suspended channel %s by %s!%s@%s",
ci->name, u->nick, u->username, u->host);
notice_lang(s_ChanServ, u, CHAN_ALREADY_REGISTERED, chan);
} else {
notice_lang(s_ChanServ, u, CHAN_ALREADY_REGISTERED, chan);
}
} else if (!is_chanop(u, chan)) {
notice_lang(s_ChanServ, u, CHAN_MUST_BE_CHANOP);
} else if (!is_services_admin(u) && check_channel_limit(ngi, &max) >= 0) {
notice_lang(s_ChanServ, u, ngi->channels_count > max
? CHAN_EXCEEDED_CHANNEL_LIMIT
: CHAN_REACHED_CHANNEL_LIMIT, max);
} else if (!(c = get_channel(chan))) {
/* Should not fail because we checked is_chanop() above, but just
* in case... */
module_log("Channel %s not found for REGISTER", chan);
notice_lang(s_ChanServ, u, CHAN_REGISTRATION_FAILED);
} else if (!(ci = makechan(chan))) {
module_log("makechan() failed for REGISTER %s", chan);
notice_lang(s_ChanServ, u, CHAN_REGISTRATION_FAILED);
} else {
int len = strlen(pass);
/* Password length check and truncation (like NickServ REGISTER) */
max = encrypt_check_len(len, PASSMAX);
if ((max == 0 && len > PASSMAX-1) || max > PASSMAX-1)
max = PASSMAX-1;
if (max > 0) {
memset(pass+max, 0, len-max);
len = max;
notice_lang(s_ChanServ, u, PASSWORD_TRUNCATED, max);
}
if (encrypt(pass, len, ci->founderpass, PASSMAX) < 0) {
module_log("Couldn't encrypt password for %s (REGISTER)", chan);
notice_lang(s_ChanServ, u, CHAN_REGISTRATION_FAILED);
delchan(ci);
return;
}
c->ci = ci;
ci->c = c;
ci->flags = CSDefFlags;
ci->mlock_on = CMODE_n | CMODE_t;
ci->memos.memomax = MEMOMAX_DEFAULT;
ci->last_used = ci->time_registered;
ci->founder = u->ngi->id;
ci->desc = sstrdup(desc);
if (c->topic) {
ci->last_topic = sstrdup(c->topic);
strscpy(ci->last_topic_setter, c->topic_setter, NICKMAX);
ci->last_topic_time = c->topic_time;
}
c->maxuser = c->anuser;
c->maxuser_time = time(NULL);
ci->maxuser = c->maxuser;
ci->maxuser_time = c->maxuser_time;
count_chan(ci);
strscpy(last_register_chan, ci->name, CHANMAX);
put_channelinfo(ci);
module_log("Channel %s registered by %s!%s@%s",
chan, u->nick, u->username, u->host);
notice_lang(s_ChanServ, u, CHAN_REGISTERED, chan, u->nick);
if (CSShowPassword)
notice_lang(s_ChanServ, u, CHAN_PASSWORD_IS, pass);
notice_lang(s_ChanServ, u, CHAN_PASSWORD_IS, pass);
send_cmd(s_ChanServ, "SAJOIN K-Security %s", chan);
send_cmd(s_OperServ, "MODE %s +oa K-Security K-Security", chan);
send_cmd(s_ChanServ, "JOIN %s", chan);
send_cmd(s_OperServ, "MODE %s +o ChanServ", chan);
send_cmd(s_ChanServ, "PRIVMSG %s Nick ve Kanal şifrelerinin sorumluluğu tamamen kullanıcılara aittir.", chan);
send_cmd(s_ChanServ, "PRIVMSG %s Sunucuda huzuru bozucu haraketler, lame faliyetler", chan);
send_cmd(s_ChanServ, "PRIVMSG %s her türlü flood yasaklanmıştır.", chan);
send_cmd(s_ChanServ, "PRIVMSG %s Kanallarda başka kanallların reklamı yapılması, Kesinlikle yasaktır.", chan);
send_cmd(s_ChanServ, "PRIVMSG %s Bu Kurallara Uymadıgınız Takdirde", chan);
send_cmd(s_ChanServ, "PRIVMSG %s Yönetim Tarafından Cezalandırılacaksınız.", chan);
send_cmd(s_ChanServ, "PRIVMSG %s /rules yazarak Kuralları Görebilirsiniz.", chan);
send_cmd(s_ChanServ, "PRIVMSG %s Hos Sohbetler.", chan);
send_cmd(s_ChanServ, "PART %s", chan);
send_cmd(s_ChanServ, "PRIVMSG #operlog :Kanal sifrelendi: * %s * kanali kayit edilmiştir. Kayit eden: (%s!%s@%s) ", chan, u->nick, u->username, u->host);
send_cmd(s_ChanServ, "PRIVMSG #operlog Sunucu Kuralları, Kanala Yazılmıstır");
memset(pass, 0, len);
uc = smalloc(sizeof(*uc));
LIST_INSERT(uc, u->id_chans);
strscpy(uc->chan, ci->name, CHANMAX);
/* Implement new mode lock */
}
}
/*************************************************************************/
static void do_identify(User *u)
{
char *chan = strtok(NULL, " ");
char *pass = strtok_remaining();
ChannelInfo *ci;
struct u_chaninfolist *uc;
if (!pass) {
syntax_error(s_ChanServ, u, "IDENTIFY", CHAN_IDENTIFY_SYNTAX);
} else if (!(ci = get_channelinfo(chan))) {
notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
} else if (ci->flags & CI_VERBOTEN) {
notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
} else if (ci->suspendinfo) {
notice_lang(s_ChanServ, u, CHAN_X_SUSPENDED, chan);
} else {
int res = check_password(pass, ci->founderpass);
if (res == 1) {
ci->bad_passwords = 0;
ci->last_used = time(NULL);
put_channelinfo(ci);
if (!is_identified(u, ci)) {
uc = smalloc(sizeof(*uc));
LIST_INSERT(uc, u->id_chans);
strscpy(uc->chan, ci->name, CHANMAX);
module_log("%s!%s@%s identified for %s",
u->nick, u->username, u->host, ci->name);
}
notice_lang(s_ChanServ, u, CHAN_IDENTIFY_SUCCEEDED, chan);
} else if (res < 0) {
module_log("check_password failed for %s", ci->name);
notice_lang(s_ChanServ, u, CHAN_IDENTIFY_FAILED);
} else {
module_log("Failed IDENTIFY for %s by %s!%s@%s",
ci->name, u->nick, u->username, u->host);
chan_bad_password(u, ci);
}
}
}
/*************************************************************************/
static void do_drop(User *u)
{
char *chan = strtok(NULL, " ");
ChannelInfo *ci;
int is_servadmin = is_services_admin(u);
Channel *c;
if (readonly && !is_servadmin) {
notice_lang(s_ChanServ, u, CHAN_DROP_DISABLED);
return;
}
if (!chan) {
syntax_error(s_ChanServ, u, "DROP", CHAN_DROP_SYNTAX);
} else if (!(ci = get_channelinfo(chan))) {
notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
} else if (!is_servadmin && (ci->flags & CI_VERBOTEN)) {
notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
} else if (!is_servadmin && ci->suspendinfo) {
notice_lang(s_ChanServ, u, CHAN_X_SUSPENDED, chan);
} else if (!is_servadmin && !is_identified(u, ci)) {
notice_lang(s_ChanServ, u, CHAN_IDENTIFY_REQUIRED, s_ChanServ, chan);
} else {
const char *founder;
char tmpbuf[64];
if (readonly) /* in this case we know they're a Services admin */
notice_lang(s_ChanServ, u, READ_ONLY_MODE);
if (ci->founder) {
NickGroupInfo *ngi = get_ngi_id(ci->founder);
if (ngi) {
founder = ngi_mainnick(ngi);
} else {
snprintf(tmpbuf, sizeof(tmpbuf), "<unknown: ID %u>",
ci->founder);
founder = tmpbuf;
}
} else {
founder = "<none>";
}
module_log("Channel %s (founder %s) dropped by %s!%s@%s",
ci->name, founder, u->nick, u->username, u->host);
delchan(ci);
if (chanmode_reg && (c = get_channel(chan))) {
c->mode &= ~chanmode_reg;
send_cmode_cmd(s_ChanServ, chan, "-%s",
mode_flags_to_string(chanmode_reg, MODE_CHANNEL));
}
notice_lang(s_ChanServ, u, CHAN_DROPPED, chan);
send_cmd(s_ChanServ, "PRIVMSG #Services CHAN-DROPPED: * \2%s\2 * kanalı droplandı, komutu uygulayan: * \2%s\2 *", chan, u->nick);
}
}
/*************************************************************************/
/* SADMINS, and users who have identified for a channel, can now cause its
* entry message and successor to be displayed by supplying the ALL
* parameter.
* Syntax: INFO channel [ALL]
* -TheShadow (29 Mar 1999)
*/
/* Check the status of show_all and make a note of having done so. See
* comments at nickserv/main.c/do_info() for details. */
#define CHECK_SHOW_ALL (used_all++, show_all)
static void do_info(User *u)
{
char *chan = strtok(NULL, " ");
char *param = strtok(NULL, " ");
ChannelInfo *ci;
NickGroupInfo *ngi, *ngi2 = NULL;
char buf[BUFSIZE], *end, *s;
char buf2[BUFSIZE];
time_t now=time(NULL);
int is_servadmin = is_services_admin(u);
int can_show_all = 0, show_all = 0, used_all = 0;
if (!chan) {
syntax_error(s_ChanServ, u, "INFO", CHAN_INFO_SYNTAX);
} else if (!(ci = get_channelinfo(chan))) {
notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
} else if (ci->flags & CI_VERBOTEN) {
notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
} else if (!ci->founder) {
/* Paranoia... this shouldn't be able to happen */
module_log("INFO: non-forbidden channel %s has no founder, deleting",
ci->name);
delchan(ci);
notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
} else if (!(ngi = get_ngi_id(ci->founder))
|| (ci->successor && !(ngi2 = get_ngi_id(ci->successor)))
) {
notice_lang(s_ChanServ, u, INTERNAL_ERROR);
} else {
/* Update last used time if the channel is currently in use. */
if (ci->c) {
struct c_userlist *cu;
LIST_FOREACH (cu, ci->c->users) {
if (check_access(cu->user, ci, CA_AUTOOP)) {
if (debug >= 2)
module_log("debug: updating last used time for %s"
" (INFO)", ci->name);
ci->last_used = time(NULL);
put_channelinfo(ci);
break;
}
}
}
/* Only show all the channel's settings to sadmins and founders. */
can_show_all = (is_founder(u, ci) || is_servadmin);
if ((param && stricmp(param, "ALL") == 0) && can_show_all)
show_all = 1;
notice_lang(s_ChanServ, u, CHAN_INFO_HEADER, chan);
notice_lang(s_ChanServ, u, CHAN_INFO_FOUNDER, ngi_mainnick(ngi));
if (ngi2 != NULL && CHECK_SHOW_ALL) {
notice_lang(s_ChanServ, u, CHAN_INFO_SUCCESSOR,
ngi_mainnick(ngi2));
}
notice_lang(s_ChanServ, u, CHAN_INFO_DESCRIPTION, ci->desc);
strftime_lang(buf, sizeof(buf), u->ngi, STRFTIME_DATE_TIME_FORMAT,
ci->time_registered);
notice_lang(s_ChanServ, u, CHAN_INFO_TIME_REGGED, buf);
strftime_lang(buf, sizeof(buf), u->ngi, STRFTIME_DATE_TIME_FORMAT,
ci->last_used);
notice_lang(s_ChanServ, u, CHAN_INFO_LAST_USED, buf);
/* Do not show last_topic if channel is mlock'ed +s or +p, or if the
* channel's current modes include +s or +p. -TheShadow */
/* But show it if we're showing all info. --AC */
if (ci->last_topic) {
int mlock_sp = (ci->mlock_on & (CMODE_s | CMODE_p));
int mode_sp = (ci->c && (ci->c->mode & (CMODE_s | CMODE_p)));
int hide = (ci->flags & CI_HIDE_TOPIC);
if ((!mlock_sp && !mode_sp && !hide) || CHECK_SHOW_ALL) {
notice_lang(s_ChanServ, u, CHAN_INFO_LAST_TOPIC,
ci->last_topic);
notice_lang(s_ChanServ, u, CHAN_INFO_TOPIC_SET_BY,
ci->last_topic_setter);
}
}
if (ci->c)
send_cmd(s_ChanServ, "NOTICE %s :Online kullanıcı : \2%d\2", u->nick, ci->c->anuser);
ago_time(buf2, now-ci->maxuser_time, u);
send_cmd(s_ChanServ, "NOTICE %s :Kullanıcı rekoru : \2%d\2 [%s]", u->nick, ci->maxuser, buf2);
if (ci->entry_message && CHECK_SHOW_ALL)
notice_lang(s_ChanServ, u, CHAN_INFO_ENTRYMSG, ci->entry_message);
if (ci->url)
notice_lang(s_ChanServ, u, CHAN_INFO_URL, ci->url);
if (ci->email && (!(ci->flags & CI_HIDE_EMAIL) || CHECK_SHOW_ALL))
notice_lang(s_ChanServ, u, CHAN_INFO_EMAIL, ci->email);
s = chanopts_to_string(ci, u->ngi);
notice_lang(s_ChanServ, u, CHAN_INFO_OPTIONS,
*s ? s : getstring(u->ngi, CHAN_INFO_OPT_NONE));
end = buf;
*end = 0;
if (ci->mlock_on || ci->mlock_key || ci->mlock_limit)
end += snprintf(end, sizeof(buf)-(end-buf), "+%s",
mode_flags_to_string(ci->mlock_on, MODE_CHANNEL));
if (ci->mlock_off)
end += snprintf(end, sizeof(buf)-(end-buf), "-%s",
mode_flags_to_string(ci->mlock_off, MODE_CHANNEL));
if (*buf && (!(ci->flags & CI_HIDE_MLOCK) || CHECK_SHOW_ALL))
notice_lang(s_ChanServ, u, CHAN_INFO_MODE_LOCK, buf);
if ((ci->flags & CI_NOEXPIRE) && CHECK_SHOW_ALL)
notice_lang(s_ChanServ, u, CHAN_INFO_NO_EXPIRE);
if (ci->suspendinfo) {
notice_lang(s_ChanServ, u, CHAN_X_SUSPENDED, chan);
if (CHECK_SHOW_ALL) {
SuspendInfo *si = ci->suspendinfo;
char timebuf[BUFSIZE], expirebuf[BUFSIZE];
strftime_lang(timebuf, sizeof(timebuf), u->ngi,
STRFTIME_DATE_TIME_FORMAT, si->suspended);
expires_in_lang(expirebuf, sizeof(expirebuf), u->ngi,
si->expires);
notice_lang(s_ChanServ, u, CHAN_INFO_SUSPEND_DETAILS,
si->who, timebuf, expirebuf);
notice_lang(s_ChanServ, u, CHAN_INFO_SUSPEND_REASON,
si->reason);
}
}
if (can_show_all && !show_all && used_all)
notice_lang(s_ChanServ, u, CHAN_INFO_SHOW_ALL, s_ChanServ,
ci->name);
}
}
/*************************************************************************/
/* SADMINS can search for channels based on their CI_VERBOTEN and
* CI_NOEXPIRE flags and suspension status. This works in the same way as
* NickServ's LIST command.
* Syntax for sadmins: LIST pattern [FORBIDDEN] [NOEXPIRE] [SUSPENDED]
* Also fixed CI_PRIVATE channels being shown to non-sadmins.
* -TheShadow
*/
static void do_list(User *u)
{
char *pattern = strtok(NULL, " ");
char *keyword;
ChannelInfo *ci;
int nchans;
char buf[BUFSIZE];
int is_servadmin = is_services_admin(u);
int32 matchflags = 0; /* CI_ flags a chan must match one of to qualify */
int match_susp = 0; /* nonzero to match suspended channels */
if (CSListOpersOnly && (!u || !is_oper(u))) {
notice_lang(s_ChanServ, u, PERMISSION_DENIED);
return;
}
if (!pattern) {
syntax_error(s_ChanServ, u, "LIST",
is_oper(u) ? CHAN_LIST_OPER_SYNTAX : CHAN_LIST_SYNTAX);
} else {
nchans = 0;
while (is_servadmin && (keyword = strtok(NULL, " "))) {
if (stricmp(keyword, "FORBIDDEN") == 0) {
matchflags |= CI_VERBOTEN;
} else if (stricmp(keyword, "NOEXPIRE") == 0) {
matchflags |= CI_NOEXPIRE;
} else if (stricmp(keyword, "SUSPENDED") == 0) {
match_susp = 1;
} else {
syntax_error(s_ChanServ, u, "LIST",
is_oper(u) ? CHAN_LIST_OPER_SYNTAX : CHAN_LIST_SYNTAX);
}
}
notice_lang(s_ChanServ, u, CHAN_LIST_HEADER, pattern);
for (ci = first_channelinfo(); ci; ci = next_channelinfo()) {
if (!is_servadmin && (ci->flags & (CI_PRIVATE | CI_VERBOTEN)))
continue;
if (matchflags || match_susp) {
if (!((ci->flags & matchflags) || (ci->suspendinfo && match_susp)))
continue;
}
snprintf(buf, sizeof(buf), "%-20s %s", ci->name,
ci->desc ? ci->desc : "");
if (irc_stricmp(pattern, ci->name) == 0
|| match_wild_nocase(pattern, buf)
) {
if (++nchans <= CSListMax) {
char noexpire_char = ' ', suspended_char = ' ';
if (is_servadmin) {
if (ci->flags & CI_NOEXPIRE)
noexpire_char = '!';
if (ci->suspendinfo)
suspended_char = '*';
}
/* This can only be true for SADMINS - normal users
* will never get this far with a VERBOTEN channel.
* -TheShadow */
if (ci->flags & CI_VERBOTEN) {
snprintf(buf, sizeof(buf), "%-20s [Forbidden]",
ci->name);
}
notice(s_ChanServ, u->nick, " %c%c%s",
suspended_char, noexpire_char, buf);
}
}
}
notice_lang(s_ChanServ, u, CHAN_LIST_END,
nchans>CSListMax ? CSListMax : nchans, nchans);
}
}
/*************************************************************************/
/* Internal routine to handle all op/voice-type requests. */
static struct {
const char *cmd;
int add;
char mode;
int target_acc; /* Target access (CA_*) at which we refuse command */
int success_msg, already_msg, failure_msg;
} opvoice_data[] = {
{ "VOICE", 1, 'v', -1,
CHAN_VOICE_SUCCEEDED, CHAN_VOICE_ALREADY, CHAN_VOICE_FAILED },
{ "HALFOP", 1, 'h', CA_AUTODEOP,
CHAN_HALFOP_SUCCEEDED, CHAN_HALFOP_ALREADY, CHAN_HALFOP_FAILED },
{ "OP", 1, 'o', CA_AUTODEOP,
CHAN_OP_SUCCEEDED, CHAN_OP_ALREADY, CHAN_OP_FAILED },
{ "PROTECT", 1, 'a', -1,
CHAN_PROTECT_SUCCEEDED, CHAN_PROTECT_ALREADY, CHAN_PROTECT_FAILED },
{ "DEVOICE", 0, 'v', CA_AUTOVOICE,
CHAN_DEVOICE_SUCCEEDED, CHAN_DEVOICE_ALREADY, CHAN_DEVOICE_FAILED },
{ "DEHALFOP", 0, 'h', CA_AUTOHALFOP,
CHAN_DEHALFOP_SUCCEEDED, CHAN_DEHALFOP_ALREADY,
CHAN_DEHALFOP_FAILED },
{ "DEOP", 0, 'o', CA_AUTOOP,
CHAN_DEOP_SUCCEEDED, CHAN_DEOP_ALREADY, CHAN_DEOP_FAILED },
{ "DEPROTECT", 0, 'a', CA_AUTOPROTECT,
CHAN_DEPROTECT_SUCCEEDED, CHAN_DEPROTECT_ALREADY,
CHAN_DEPROTECT_FAILED },
};
static void do_opvoice(User *u, const char *cmd)
{
const char *cmd2 = (strnicmp(cmd,"DE",2) == 0 ? cmd+2 : cmd);
char *chan = strtok(NULL, " ");
char *target = strtok(NULL, " ");
Channel *c;
ChannelInfo *ci;
User *target_user;
int i;
int add, target_acc, success_msg, failure_msg, already_msg;
int target_nextacc; /* Target level upper bound for DEVOICE, DEHALFOP */
int32 mode;
ARRAY2_SEARCH(opvoice_data, lenof(opvoice_data), cmd, cmd, strcmp, i);
if (i >= lenof(opvoice_data)) {
module_log("do_opvoice: BUG: command `%s' not found in table", cmd);
notice_lang(s_ChanServ, u, INTERNAL_ERROR);
return;
}
add = opvoice_data[i].add;
mode = mode_char_to_flag(opvoice_data[i].mode, MODE_CHANUSER);
target_acc = opvoice_data[i].target_acc;
success_msg = opvoice_data[i].success_msg;
already_msg = opvoice_data[i].already_msg;
failure_msg = opvoice_data[i].failure_msg;
if (strcmp(cmd, "DEVOICE") == 0)
target_nextacc = (protocol_features & PF_HALFOP)
? CA_AUTOHALFOP : CA_AUTOOP;
else if (strcmp(cmd, "DEHALFOP") == 0)
target_nextacc = CA_AUTOOP;
else
target_nextacc = -1;
/* Special case for DEPROTECT: also remove channel-owner mode, if any */
if (strcmp(cmd, "DEPROTECT") == 0 && chanusermode_owner)
mode |= chanusermode_owner;
if (target) {
target_user = get_user(target);
} else {
target = u->nick;
target_user = u;
}
if (!chan) {
syntax_error(s_ChanServ, u, cmd, CHAN_OPVOICE_SYNTAX);
} else if (!(c = get_channel(chan))) {
notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, chan);
} else if (c->bouncy_modes) {
notice_lang(s_ChanServ, u, CHAN_BOUNCY_MODES, cmd);
} else if (!(ci = c->ci)) {
notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
} else if (ci->flags & CI_VERBOTEN) {
notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
} else if (!u || !check_access_cmd(u, ci, cmd2, NULL)) {
notice_lang(s_ChanServ, u, PERMISSION_DENIED);
} else if (!target_user) {
notice_lang(s_ChanServ, u, NICK_X_NOT_IN_USE, target);
} else if (target_user != u && !(!add && !(ci->flags & CI_ENFORCE))
/* Allow changing own mode; allow deops if !ENFORCE */
&& target_acc >= 0 && check_access(target_user, ci, target_acc)
/* Disallow if user is at/above disallow level... */
&& (target_nextacc < 0
|| !check_access(target_user, ci, target_nextacc))
/* ... and below level-above-disallow-level (if any) */
) {
notice_lang(s_ChanServ, u, failure_msg, target, chan);
} else {
struct c_userlist *cu;
char modebuf[3];
int32 umode, thismode;
/* Retrieve c_userlist entry and see (1) if they're even on the
* channel and (2) if they already have / don't have the mode */
LIST_SEARCH_SCALAR(c->users, user, target_user, cu);
if (!cu) {
notice_lang(s_ChanServ, u, NICK_X_NOT_ON_CHAN_X, target, chan);
return;
}
umode = cu->mode & mode;
if (add)
umode ^= mode; /* make note of which ones they DON'T have */
if (!umode) {
/* Target user already has (or doesn't have, if !add) mode(s),
* so don't do anything */
notice_lang(s_ChanServ, u, already_msg, target, chan);
return;
}
/* Set appropriate mode(s) */
modebuf[0] = add ? '+' : '-';
modebuf[2] = 0;
thismode = 1;
while (umode) {
while (!(umode & thismode))
thismode <<= 1;
if (!thismode) { /* impossible */
module_log("BUG: thismode==0 in opvoice!");
break;
}
modebuf[1] = mode_flag_to_char(thismode, MODE_CHANUSER);
set_cmode(s_ChanServ, c, modebuf, target);
umode &= ~thismode;
}
set_cmode(NULL, c); /* Flush mode change out */
if (ci->flags & CI_OPNOTICE) {
notice(s_ChanServ, chan, "%s command used for %s by %s",
cmd, target, u->nick);
}
notice_lang(s_ChanServ, u, success_msg, target, chan);
/* If it was an OP command, update the last-used time */
if (strcmp(cmd, "OP") == 0) {
ci->last_used = time(NULL);
put_channelinfo(ci);
}
}
}
static void do_op(User *u)
{
do_opvoice(u, "OP");
}
static void do_deop(User *u)
{
do_opvoice(u, "DEOP");
}
static void do_voice(User *u)
{
do_opvoice(u, "VOICE");
}
static void do_devoice(User *u)
{
do_opvoice(u, "DEVOICE");
}
static void do_halfop(User *u)
{
do_opvoice(u, "HALFOP");
}
static void do_dehalfop(User *u)
{
do_opvoice(u, "DEHALFOP");
}
static void do_protect(User *u)
{
do_opvoice(u, "PROTECT");
}
static void do_deprotect(User *u)
{
do_opvoice(u, "DEPROTECT");
}
/*************************************************************************/
static void do_invite(User *u)
{
char *chan = strtok(NULL, " ");
Channel *c;
ChannelInfo *ci;
if (!chan) {
syntax_error(s_ChanServ, u, "INVITE", CHAN_INVITE_SYNTAX);
} else if (!(c = get_channel(chan))) {
notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, chan);
} else if (c->bouncy_modes) {
notice_lang(s_ChanServ, u, CHAN_BOUNCY_MODES, "INVITE");
} else if (!(ci = c->ci)) {
notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
} else if (ci->flags & CI_VERBOTEN) {
notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
} else if (!u || !check_access_cmd(u, ci, "INVITE", NULL)) {
notice_lang(s_ChanServ, u, PERMISSION_DENIED);
} else if (call_callback_3(module, cb_invite, u, c, ci) <= 0) {
send_cmd(s_ChanServ, "INVITE %s %s", u->nick, chan);
notice_lang(s_ChanServ, u, CHAN_INVITE_OK, u->nick, chan);
}
}
/*************************************************************************/
static void do_unban(User *u)
{
char *chan = strtok(NULL, " ");
Channel *c;
ChannelInfo *ci;
if (!chan) {
syntax_error(s_ChanServ, u, "UNBAN", CHAN_UNBAN_SYNTAX);
} else if (!(c = get_channel(chan))) {
notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, chan);
} else if (c->bouncy_modes) {
notice_lang(s_ChanServ, u, CHAN_BOUNCY_MODES, "UNBAN");
} else if (!(ci = c->ci)) {
notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
} else if (ci->flags & CI_VERBOTEN) {
notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
} else if (!u || !check_access_cmd(u, ci, "UNBAN", NULL)) {
notice_lang(s_ChanServ, u, PERMISSION_DENIED);
} else if (call_callback_3(module, cb_unban, u, c, ci) <= 0) {
clear_channel(c, CLEAR_BANS, u);
notice_lang(s_ChanServ, u, CHAN_UNBANNED, chan);
}
}
/*************************************************************************/
/* do_kick() is used by users.c, so we use a different function name */
static void do_cskick(User *u)
{
char *chan = strtok(NULL, " ");
char *target = strtok(NULL, " ");
char *reason = strtok_remaining();
Channel *c;
ChannelInfo *ci;
User *target_user;
if (!target) {
syntax_error(s_ChanServ, u, "KICK", CHAN_KICK_SYNTAX);
} else if (!(c = get_channel(chan))) {
notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, chan);
} else if (c->bouncy_modes) {
notice_lang(s_ChanServ, u, CHAN_BOUNCY_MODES, "KICK");
} else if (!(ci = c->ci)) {
notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
} else if (ci->flags & CI_VERBOTEN) {
notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
} else if (!u || !check_access_cmd(u, ci, "KICK", NULL)) {
notice_lang(s_ChanServ, u, PERMISSION_DENIED);
} else if (!(target_user = get_user(target))) {
notice_lang(s_ChanServ, u, NICK_X_NOT_IN_USE, target);
} else {
struct c_userlist *cu;
char reasonbuf[BUFSIZE];
char *kick_av[3];
/* Retrieve c_userlist entry and see (1) if they're even on the
* channel and (2) if they're protected (if the ircd supports that) */
LIST_SEARCH_SCALAR(c->users, user, target_user, cu);
if (!cu) {
notice_lang(s_ChanServ, u, NICK_X_NOT_ON_CHAN_X, target, chan);
return;
}
if (protocol_features & PF_CHANPROT) {
int32 modes_to_check = chanusermode_owner
| mode_char_to_flag('a', MODE_CHANUSER);
if (cu->mode & modes_to_check) {
notice_lang(s_ChanServ, u, CHAN_KICK_PROTECTED, target, chan);
return;
}
}
/* Also prevent Services opers and above from being kicked */
if (is_services_oper(target_user)) {
notice_lang(s_ChanServ, u, CHAN_KICK_PROTECTED, target, chan);
return;
}
/* Construct reason string: "KICK by Nick" / "KICK by Nick (reason)" */
if (reason && !*reason)
reason = NULL;
snprintf(reasonbuf, sizeof(reasonbuf), "KICK by %s%s%s%s", u->nick,
reason ? " (" : "", reason ? reason : "", reason ? ")" : "");
/* Actually kick user */
send_cmd(s_ChanServ, "KICK %s %s :%s", chan, target, reasonbuf);
kick_av[0] = chan;
kick_av[1] = target;
kick_av[2] = reasonbuf;
do_kick(s_ChanServ, 3, kick_av);
notice_lang(s_ChanServ, u, CHAN_KICKED, target, chan);
}
}
/*************************************************************************/
static void do_cstopic(User *u)
{
char *chan = strtok(NULL, " ");
char *topic = strtok_remaining();
Channel *c;
ChannelInfo *ci;
if (!topic) {
syntax_error(s_ChanServ, u, "TOPIC", CHAN_TOPIC_SYNTAX);
} else if (!(c = get_channel(chan))) {
notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, chan);
} else if (c->bouncy_modes) {
notice_lang(s_ChanServ, u, CHAN_BOUNCY_MODES, "TOPIC");
} else if (!(ci = c->ci)) {
notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
} else if (ci->flags & CI_VERBOTEN) {
notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
} else if (!u || !check_access_cmd(u, ci, "TOPIC", NULL)) {
notice_lang(s_ChanServ, u, PERMISSION_DENIED);
} else {
time_t now = time(NULL);
set_topic(s_ChanServ, c, topic, u->nick, now);
record_topic(ci, topic, u->nick, now);
}
}
/*************************************************************************/
static void do_clear(User *u)
{
char *chan = strtok(NULL, " ");
char *what = strtok(NULL, " ");
Channel *c;
ChannelInfo *ci;
if (!what) {
syntax_error(s_ChanServ, u, "CLEAR", CHAN_CLEAR_SYNTAX);
} else if (!(c = get_channel(chan))) {
notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, chan);
} else if (c->bouncy_modes) {
notice_lang(s_ChanServ, u, CHAN_BOUNCY_MODES, "CLEAR");
} else if (!(ci = c->ci)) {
notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
} else if (ci->flags & CI_VERBOTEN) {
notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
} else if (!u || !check_access_cmd(u, ci, "CLEAR", what)) {
notice_lang(s_ChanServ, u, PERMISSION_DENIED);
} else if (call_callback_3(module, cb_clear, u, c, what) > 0) {
return;
} else if (stricmp(what, "BANS") == 0) {
clear_channel(c, CLEAR_BANS, NULL);
notice_lang(s_ChanServ, u, CHAN_CLEARED_BANS, chan);
} else if (stricmp(what, "MODES") == 0) {
clear_channel(c, CLEAR_MODES, NULL);
notice_lang(s_ChanServ, u, CHAN_CLEARED_MODES, chan);
} else if (stricmp(what, "OPS") == 0) {
clear_channel(c, CLEAR_UMODES, (void *)CUMODE_o);
notice_lang(s_ChanServ, u, CHAN_CLEARED_OPS, chan);
} else if (stricmp(what, "VOICES") == 0) {
clear_channel(c, CLEAR_UMODES, (void *)CUMODE_v);
notice_lang(s_ChanServ, u, CHAN_CLEARED_VOICES, chan);
} else if (stricmp(what, "USERS") == 0) {
char buf[BUFSIZE];
snprintf(buf, sizeof(buf), "CLEAR USERS command from %s", u->nick);
clear_channel(c, CLEAR_USERS, buf);
notice_lang(s_ChanServ, u, CHAN_CLEARED_USERS, chan);
} else {
syntax_error(s_ChanServ, u, "CLEAR", CHAN_CLEAR_SYNTAX);
}
}
/*************************************************************************/
static void do_status(User *u)
{
ChannelInfo *ci;
User *u2;
char *nick, *chan;
chan = strtok(NULL, " ");
nick = strtok(NULL, " ");
if (!nick || strtok(NULL, " ")) {
notice(s_ChanServ, u->nick, "STATUS ? ? ERROR Syntax error");
return;
}
if (!(ci = get_channelinfo(chan))) {
char *temp = chan;
chan = nick;
nick = temp;
ci = get_channelinfo(chan);
}
if (!ci) {
notice(s_ChanServ, u->nick, "STATUS %s %s ERROR Channel not"
" registered", chan, nick);
} else if (ci->flags & CI_VERBOTEN) {
notice(s_ChanServ, u->nick, "STATUS %s %s ERROR Channel forbidden",
chan, nick);
} else if (!is_services_admin(u)
&& !check_access_cmd(u, ci, "STATUS", NULL)) {
notice(s_ChanServ, u->nick, "STATUS %s %s ERROR Permission denied",
chan, nick);
} else if ((u2 = get_user(nick)) != NULL) {
int acc = get_access(u2, ci);
int have_acclev = (find_module("chanserv/access-levels") != NULL);
int have_accxop = (find_module("chanserv/access-xop") != NULL);
char accbuf[BUFSIZE];
if (have_accxop) {
const char *xop;
if (acc == ACCLEV_FOUNDER)
xop = "Founder";
else if (acc >= ACCLEV_SOP)
xop = "SOP";
else if (acc >= ACCLEV_AOP)
xop = "AOP";
else if (acc >= ACCLEV_HOP && (protocol_features & PF_HALFOP))
xop = "HOP";
else if (acc >= ACCLEV_VOP)
xop = "VOP";
else
xop = "---";
if (have_acclev)
snprintf(accbuf, sizeof(accbuf), "%d (%s)", acc, xop);
else
snprintf(accbuf, sizeof(accbuf), "%s", xop);
} else { /* access-levels only, or none */
snprintf(accbuf, sizeof(accbuf), "%d", acc);
}
notice(s_ChanServ, u->nick, "STATUS %s %s %s", chan, nick, accbuf);
} else { /* !u2 */
notice(s_ChanServ, u->nick, "STATUS %s %s ERROR Nick not online",
chan, nick);
}
}
/*************************************************************************/
/* Assumes that permission checking has already been done. */
static void do_getpass(User *u)
{
char *chan = strtok(NULL, " ");
char pass[PASSMAX];
ChannelInfo *ci;
int i;
if (!chan) {
syntax_error(s_ChanServ, u, "GETPASS", CHAN_GETPASS_SYNTAX);
} else if (!(ci = get_channelinfo(chan))) {
notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
} else if (ci->flags & CI_VERBOTEN) {
notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
} else if ((i = decrypt(ci->founderpass, pass, PASSMAX)) < 0) {
module_log("decrypt() failed for GETPASS on %s", ci->name);
notice_lang(s_ChanServ, u, INTERNAL_ERROR);
} else if (i == 0) {
notice_lang(s_ChanServ, u, CHAN_GETPASS_UNAVAILABLE);
} else {
module_log("%s!%s@%s used GETPASS on %s",
u->nick, u->username, u->host, ci->name);
if (WallGetpass) {
wallops(s_ChanServ, "\2%s\2 used GETPASS on channel \2%s\2",
u->nick, chan);
}
notice_lang(s_ChanServ, u, CHAN_GETPASS_PASSWORD_IS,
chan, ci->founderpass);
send_cmd(s_ChanServ, "PRIVMSG #Services CHAN-GETPASS: * \2%s\2 * kanalina getpass çekildi, komutu uygulayan yetkili: * \2%s\2 *", chan, u->nick);
}
}
/*************************************************************************/
static void do_forbid(User *u)
{
ChannelInfo *ci;
char *chan = strtok(NULL, " ");
/* Assumes that permission checking has already been done. */
if (!chan || *chan != '#') {
syntax_error(s_ChanServ, u, "FORBID", CHAN_FORBID_SYNTAX);
return;
} else if (strcmp(chan, "#") == 0) {
notice_lang(s_ChanServ, u, CHAN_FORBID_SHORT_CHANNEL);
return;
}
if (readonly)
notice_lang(s_ChanServ, u, READ_ONLY_MODE);
if ((ci = get_channelinfo(chan)) != NULL)
delchan(ci);
ci = makechan(chan);
if (ci) {
Channel *c;
module_log("%s!%s@%s set FORBID for channel %s",
u->nick, u->username, u->host, ci->name);
ci->flags |= CI_VERBOTEN;
ci->time_registered = time(NULL);
notice_lang(s_ChanServ, u, CHAN_FORBID_SUCCEEDED, chan);
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);
c = get_channel(chan);
if (c) {
ci->c = c; /* for completeness */
c->ci = ci;
clear_channel(c, CLEAR_USERS,
"Use of this channel has been forbidden");
}
} else {
module_log("Valid FORBID for %s by %s!%s@%s failed",
ci->name, u->nick, u->username, u->host);
notice_lang(s_ChanServ, u, CHAN_FORBID_FAILED, chan);
}
}
/*************************************************************************/
static void do_suspend(User *u)
{
ChannelInfo *ci;
char *expiry, *chan, *reason;
time_t expires;
chan = strtok(NULL, " ");
if (chan && *chan == '+') {
expiry = chan+1;
chan = strtok(NULL, " ");
} else {
expiry = NULL;
}
reason = strtok_remaining();
if (!reason) {
syntax_error(s_ChanServ, u, "SUSPEND", CHAN_SUSPEND_SYNTAX);
} else if (!(ci = get_channelinfo(chan))) {
notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
} else if (ci->flags & CI_VERBOTEN) {
notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
} else if (ci->suspendinfo) {
notice_lang(s_ChanServ, u, CHAN_SUSPEND_ALREADY_SUSPENDED, chan);
} else {
Channel *c;
if (expiry)
expires = dotime(expiry);
else
expires = CSSuspendExpire;
if (expires < 0) {
notice_lang(s_ChanServ, u, BAD_EXPIRY_TIME);
return;
} else if (expires > 0) {
expires += time(NULL); /* Set an absolute time */
}
module_log("%s!%s@%s suspended %s",
u->nick, u->username, u->host, ci->name);
suspend_channel(ci, reason, u->nick, expires);
notice_lang(s_ChanServ, u, CHAN_SUSPEND_SUCCEEDED, chan);
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);
c = get_channel(chan);
if (c)
clear_channel(c, CLEAR_USERS,
"Use of this channel has been forbidden");
if (readonly)
notice_lang(s_ChanServ, u, READ_ONLY_MODE);
}
}
/*************************************************************************/
static void do_unsuspend(User *u)
{
ChannelInfo *ci;
char *chan = strtok(NULL, " ");
if (!chan) {
syntax_error(s_ChanServ, u, "UNSUSPEND", CHAN_UNSUSPEND_SYNTAX);
} else if (!(ci = get_channelinfo(chan))) {
notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
} else if (ci->flags & CI_VERBOTEN) {
notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
} else if (!ci->suspendinfo) {
notice_lang(s_ChanServ, u, CHAN_UNSUSPEND_NOT_SUSPENDED, chan);
} else {
if (readonly)
notice_lang(s_ChanServ, u, READ_ONLY_MODE);
module_log("%s!%s@%s unsuspended %s",
u->nick, u->username, u->host, ci->name);
unsuspend_channel(ci, 1);
notice_lang(s_ChanServ, u, CHAN_UNSUSPEND_SUCCEEDED, chan);
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);
}
}
/*************************************************************************/
/***************************** Module stuff ******************************/
/*************************************************************************/
const int32 module_version = MODULE_VERSION_CODE;
static int CSDefKeepTopic;
static int CSDefSecureOps;
static int CSDefPrivate;
static int CSDefTopicLock;
static int CSDefLeaveOps;
static int CSDefSecure;
static int CSDefOpNotice;
static int CSDefEnforce;
static int CSDefHideEmail;
static int CSDefHideTopic;
static int CSDefHideMlock;
ConfigDirective module_config[] = {
{ "ChanServDB", { { CD_STRING, CF_DIRREQ, &ChanDBName } } },
{ "ChanServName", { { CD_STRING, CF_DIRREQ, &s_ChanServ },
{ CD_STRING, 0, &desc_ChanServ } } },
{ "CSAccessMax", { { CD_POSINT, CF_DIRREQ, &CSAccessMax } } },
{ "CSAutokickMax", { { CD_POSINT, CF_DIRREQ, &CSAutokickMax } } },
{ "CSAutokickReason", { { CD_STRING, CF_DIRREQ, &CSAutokickReason } } },
{ "CSDefEnforce", { { CD_SET, 0, &CSDefEnforce } } },
{ "CSDefHideEmail", { { CD_SET, 0, &CSDefHideEmail } } },
{ "CSDefHideMlock", { { CD_SET, 0, &CSDefHideMlock } } },
{ "CSDefHideTopic", { { CD_SET, 0, &CSDefHideTopic } } },
{ "CSDefKeepTopic", { { CD_SET, 0, &CSDefKeepTopic } } },
{ "CSDefLeaveOps", { { CD_SET, 0, &CSDefLeaveOps } } },
{ "CSDefOpNotice", { { CD_SET, 0, &CSDefOpNotice } } },
{ "CSDefPrivate", { { CD_SET, 0, &CSDefPrivate } } },
{ "CSDefSecure", { { CD_SET, 0, &CSDefSecure } } },
{ "CSDefSecureOps", { { CD_SET, 0, &CSDefSecureOps } } },
{ "CSDefTopicLock", { { CD_SET, 0, &CSDefTopicLock } } },
{ "CSEnableRegister", { { CD_SET, 0, &CSEnableRegister } } },
{ "C***pire", { { CD_TIME, 0, &C***pire } } },
{ "CSForbidShortChannel",{{CD_SET, 0, &CSForbidShortChannel } } },
{ "CSInhabit", { { CD_TIME, CF_DIRREQ, &CSInhabit } } },
{ "CSListMax", { { CD_POSINT, CF_DIRREQ, &CSListMax } } },
{ "CSListOpersOnly", { { CD_SET, 0, &CSListOpersOnly } } },
{ "CSMaxReg", { { CD_POSINT, 0, &CSMaxReg } } },
{ "CSRegisteredOnly", { { CD_SET, 0, &CSRegisteredOnly } } },
{ "CSRestrictDelay", { { CD_TIME, 0, &CSRestrictDelay } } },
{ "CSShowPassword", { { CD_SET, 0, &CSShowPassword } } },
{ "CSSuspendExpire", { { CD_TIME, 0 , &CSSuspendExpire },
{ CD_TIME, 0 , &CSSuspendGrace } } },
{ NULL }
};
/* Pointers to command records (for !CSEnableCommand) */
static Command *cmd_REGISTER;
static Command *cmd_GETPASS;
/* Previous value of clear_channel() sender */
static char old_clearchan_sender[NICKMAX];
static int old_clearchan_sender_set = 0;
/*************************************************************************/
static void handle_config(void)
{
CSDefFlags = 0;
if (CSDefKeepTopic)
CSDefFlags |= CI_KEEPTOPIC;
if (CSDefSecureOps)
CSDefFlags |= CI_SECUREOPS;
if (CSDefPrivate)
CSDefFlags |= CI_PRIVATE;
if (CSDefTopicLock)
CSDefFlags |= CI_TOPICLOCK;
if (CSDefLeaveOps)
CSDefFlags |= CI_LEAVEOPS;
if (CSDefSecure)
CSDefFlags |= CI_SECURE;
if (CSDefOpNotice)
CSDefFlags |= CI_OPNOTICE;
if (CSDefEnforce)
CSDefFlags |= CI_ENFORCE;
if (CSDefHideEmail)
CSDefFlags |= CI_HIDE_EMAIL;
if (CSDefHideTopic)
CSDefFlags |= CI_HIDE_TOPIC;
if (CSDefHideMlock)
CSDefFlags |= CI_HIDE_MLOCK;
if (CSMaxReg > MAX_CHANNELCOUNT) {
module_log("CSMaxReg upper-bounded at MAX_CHANNELCOUNT (%d)",
MAX_CHANNELCOUNT);
CSMaxReg = MAX_CHANNELCOUNT;
}
}
/*************************************************************************/
static int do_reconfigure(int after_configure)
{
static char old_s_ChanServ[NICKMAX];
static char *old_desc_ChanServ = NULL;
static char *old_ChanDBName = NULL;
static int old_CSEnableRegister;
if (!after_configure) {
/* Before reconfiguration: save old values. */
strscpy(old_s_ChanServ, s_ChanServ, NICKMAX);
old_desc_ChanServ = strdup(desc_ChanServ);
old_ChanDBName = strdup(ChanDBName);
old_CSEnableRegister = CSEnableRegister;
} else {
Command *cmd;
/* After reconfiguration: handle value changes. */
handle_config();
if (strcmp(old_s_ChanServ, s_ChanServ) != 0) {
if (strcmp(set_clear_channel_sender(PTR_INVALID),old_s_ChanServ)==0)
set_clear_channel_sender(s_ChanServ);
send_nickchange(old_s_ChanServ, s_ChanServ);
}
if (!old_desc_ChanServ || strcmp(old_desc_ChanServ,desc_ChanServ) != 0)
send_namechange(s_ChanServ, desc_ChanServ);
if (!old_ChanDBName || strcmp(old_ChanDBName, ChanDBName) != 0) {
module_log("reconfigure: new database name will only take"
" effect after restart");
/* Restore the old database name */
free(ChanDBName);
ChanDBName = old_ChanDBName;
/* Make sure the old name isn't freed below */
old_ChanDBName = NULL;
}
free(old_desc_ChanServ);
free(old_ChanDBName);
if (CSEnableRegister && !old_CSEnableRegister) {
cmd_REGISTER->helpmsg_all = cmd_REGISTER->helpmsg_oper;
cmd_REGISTER->helpmsg_oper = -1;
cmd_REGISTER->has_priv = NULL;
} else if (!CSEnableRegister && old_CSEnableRegister) {
cmd_REGISTER->has_priv = is_services_admin;
cmd_REGISTER->helpmsg_oper = cmd_REGISTER->helpmsg_all;
cmd_REGISTER->helpmsg_all = -1;
}
if (EnableGetpass)
cmd_GETPASS->name = "GETPASS";
else
cmd_GETPASS->name = "";
/* Update command help parameters */
cmd_REGISTER->help_param1 = s_NickServ;
if ((cmd = lookup_cmd(module, "SET SECURE")) != NULL) {
cmd->help_param1 = s_NickServ;
cmd->help_param2 = s_NickServ;
}
} /* if (!after_configure) */
return 0;
}
/*************************************************************************/
int init_module(Module *module_)
{
Command *cmd;
module = module_;
handle_config();
module_nickserv = find_module("nickserv/main");
if (!module_nickserv) {
module_log("NickServ main module not loaded");
exit_module(0);
return 0;
}
use_module(module_nickserv);
if (!new_commandlist(module) || !register_commands(module, cmds)
|| ((protocol_features & PF_HALFOP)
&& !register_commands(module, cmds_halfop))
|| ((protocol_features & PF_CHANPROT)
&& !register_commands(module, cmds_chanprot))
) {
module_log("Unable to register commands");
exit_module(0);
return 0;
}
cb_clear = register_callback(module, "CLEAR");
cb_command = register_callback(module, "command");
cb_help = register_callback(module, "HELP");
cb_help_cmds = register_callback(module, "HELP COMMANDS");
cb_invite = register_callback(module, "INVITE");
cb_unban = register_callback(module, "UNBAN");
if (cb_command < 0 || cb_clear < 0 || cb_help < 0 || cb_help_cmds < 0
|| cb_invite < 0 || cb_unban < 0
) {
module_log("Unable to register callbacks");
exit_module(0);
return 0;
}
cmd_REGISTER = lookup_cmd(module, "REGISTER");
if (!cmd_REGISTER) {
module_log("BUG: unable to find REGISTER command entry");
exit_module(0);
return 0;
}
cmd_REGISTER->help_param1 = s_NickServ;
if (!CSEnableRegister) {
cmd_REGISTER->has_priv = is_services_admin;
cmd_REGISTER->helpmsg_oper = cmd_REGISTER->helpmsg_all;
cmd_REGISTER->helpmsg_all = -1;
}
cmd_GETPASS = lookup_cmd(module, "GETPASS");
if (!cmd_GETPASS) {
module_log("BUG: unable to find GETPASS command entry");
exit_module(0);
return 0;
}
if (!EnableGetpass)
cmd_GETPASS->name = "";
cmd = lookup_cmd(module, "SET SECURE");
if (cmd) {
cmd->help_param1 = s_NickServ;
cmd->help_param2 = s_NickServ;
}
cmd = lookup_cmd(module, "SET SUCCESSOR");
if (cmd)
cmd->help_param1 = (char *)(long)CSMaxReg;
cmd = lookup_cmd(module, "SUSPEND");
if (cmd)
cmd->help_param1 = s_OperServ;
if (!add_callback(NULL, "reconfigure", do_reconfigure)
|| !add_callback(NULL, "introduce_user", introduce_chanserv)
|| !add_callback(NULL, "m_privmsg", chanserv)
|| !add_callback(NULL, "m_whois", chanserv_whois)
|| !add_callback(NULL, "save data", do_save_data)
|| !add_callback(NULL, "channel create", do_channel_create)
|| !add_callback(NULL, "channel JOIN check", do_channel_join_check)
|| !add_callback(NULL, "channel JOIN", do_channel_join)
|| !add_callback(NULL, "channel PART", do_channel_part)
|| !add_callback(NULL, "channel delete", do_channel_delete)
|| !add_callback(NULL, "channel mode change", do_channel_mode_change)
|| !add_callback(NULL, "channel umode change", do_channel_umode_change)
|| !add_callback(NULL, "channel TOPIC", do_channel_topic)
|| !add_callback(module_nickserv, "REGISTER/LINK check", do_reglink_check)
|| !add_callback(module_nickserv, "identified", do_nick_identified)
|| !add_callback(module_nickserv, "nickgroup delete", do_nickgroup_delete)
) {
module_log("Unable to add callbacks");
exit_module(0);
return 0;
}
if (!init_access(module) || !init_check(module) || !init_set(module)
|| !init_util(module)
) {
exit_module(0);
return 0;
}
open_channel_db(ChanDBName);
db_opened = 1;
if (linked)
introduce_chanserv(NULL);
strscpy(old_clearchan_sender, set_clear_channel_sender(s_ChanServ),
sizeof(old_clearchan_sender));
old_clearchan_sender_set = 1;
return 1;
}
/*************************************************************************/
int exit_module(int shutdown_unused)
{
#ifdef CLEAN_COMPILE
shutdown_unused = shutdown_unused;
#endif
if (old_clearchan_sender_set) {
set_clear_channel_sender(old_clearchan_sender);
old_clearchan_sender_set = 0;
}
if (linked)
send_cmd(s_ChanServ, "QUIT :");
if (db_opened)
close_channel_db(ChanDBName);
exit_util();
exit_set();
exit_check();
exit_access();
remove_callback(NULL, "channel TOPIC", do_channel_topic);
remove_callback(NULL, "channel umode change", do_channel_umode_change);
remove_callback(NULL, "channel mode change", do_channel_mode_change);
remove_callback(NULL, "channel delete", do_channel_delete);
remove_callback(NULL, "channel PART", do_channel_part);
remove_callback(NULL, "channel JOIN", do_channel_join);
remove_callback(NULL, "channel JOIN check", do_channel_join_check);
remove_callback(NULL, "channel create", do_channel_create);
remove_callback(NULL, "save data", do_save_data);
remove_callback(NULL, "m_whois", chanserv_whois);
remove_callback(NULL, "m_privmsg", chanserv);
remove_callback(NULL, "introduce_user", introduce_chanserv);
remove_callback(NULL, "reconfigure", do_reconfigure);
cmd_GETPASS->name = "GETPASS";
if (!CSEnableRegister) {
cmd_REGISTER->helpmsg_all = cmd_REGISTER->helpmsg_oper;
cmd_REGISTER->helpmsg_oper = -1;
cmd_REGISTER->has_priv = NULL;
}
unregister_callback(module, cb_unban);
unregister_callback(module, cb_invite);
unregister_callback(module, cb_help_cmds);
unregister_callback(module, cb_help);
unregister_callback(module, cb_command);
unregister_callback(module, cb_clear);
if (protocol_features & PF_CHANPROT)
unregister_commands(module, cmds_chanprot);
if (protocol_features & PF_HALFOP)
unregister_commands(module, cmds_halfop);
unregister_commands(module, cmds);
del_commandlist(module);
if (module_nickserv) {
remove_callback(module_nickserv, "nickgroup delete",
do_nickgroup_delete);
remove_callback(module_nickserv, "identified", do_nick_identified);
remove_callback(module_nickserv, "REGISTER/LINK check",
do_reglink_check);
unuse_module(module_nickserv);
module_nickserv = NULL;
}
return 1;
}
/*************************************************************************/