ngIRCd - Next Generation IRC Server
http://ngircd.barton.de/
- (c)2001-2011 Alexander Barton and Contributors.
+ (c)2001-2012 Alexander Barton and Contributors.
ngIRCd is free software and published under the
terms of the GNU General Public License.
mode since description
a 0.3.0 User is away.
+ B 20 User is flagged as a "bot".
c 17 IRC operator wants to receive connect/disconnect NOTICEs.
C 19 Only users that share a channel are allowed to send messages.
i 0.0.1 User is "invisible".
k 0.6.0 Channel has a "key" (a password).
l 0.6.0 Channel has a user limit.
m 0.3.0 Channel is moderated, only "voiced" users can send messages.
+ M 20 Only registered users (and IRC Ops) can send messages.
n 0.3.0 Channel doesn't allow messages of users not being members.
O 18 Only IRC operators are allowed to join this channel.
P 0.5.0 Channel is "persistent".
mode since description
+ q 20? User is channel owner can only be set by a service, other
+ owner and irc op. Can promote other users to q, a, o, h, v.
+ a 20? User is channel admin and can promote other users to v, h, o
o 0.2.0 User is channel operator and can op/kick/... other members.
+ h 20? User is half op and can set channel modes imntvIbek and kick
+ voiced and normal users.
v 0.2.0 User is "voiced" and can speak even if channel is moderated.
GLOBAL void
Channel_Init( void )
{
- CHANNEL *sc;
-
My_Channels = NULL;
My_Cl2Chan = NULL;
-
- sc = Channel_Create("&SERVER");
- if (sc) {
- Channel_SetModes(sc, "mnPt");
- Channel_SetTopic(sc, Client_ThisServer(), "Server Messages");
- }
} /* Channel_Init */
}
+/**
+ * Generate predefined persistent channels and &SERVER
+ */
GLOBAL void
Channel_InitPredefined( void )
{
- /* Generate predefined persistent channels */
-
CHANNEL *new_chan;
const struct Conf_Channel *conf_chan;
const char *c;
}
if (channel_count)
array_free(&Conf_Channels);
+
+ /* Make sure the local &SERVER channel exists */
+ if (!Channel_Search("&SERVER")) {
+ new_chan = Channel_Create("&SERVER");
+ if (new_chan) {
+ Channel_SetModes(new_chan, "mnPt");
+ Channel_SetTopic(new_chan, Client_ThisServer(),
+ "Server Messages");
+ } else
+ Log(LOG_ERR, "Failed to create \"&SERVER\" channel!");
+ } else
+ LogDebug("Required channel \"&SERVER\" already exists, ok.");
} /* Channel_InitPredefined */
const char *Reason )
{
CHANNEL *chan;
+ char *ptr, *target_modes;
+ bool can_kick = false;
assert(Peer != NULL);
assert(Target != NULL);
/* Check that user is on the specified channel */
if (!Channel_IsMemberOf(chan, Origin)) {
IRC_WriteStrClient( Origin, ERR_NOTONCHANNEL_MSG,
- Client_ID(Origin), Name);
+ Client_ID(Origin), Name);
return;
}
+ }
- /* Check if user has operator status */
- if (!strchr(Channel_UserModes(chan, Origin), 'o')) {
- IRC_WriteStrClient(Origin, ERR_CHANOPRIVSNEEDED_MSG,
- Client_ID(Origin), Name);
+ if(Client_Type(Peer) == CLIENT_USER) {
+ /* Check if client has the rights to kick target */
+ ptr = Channel_UserModes(chan, Peer);
+ target_modes = Channel_UserModes(chan, Target);
+ while(*ptr) {
+ /* Owner can kick everyone */
+ if ( *ptr == 'q') {
+ can_kick = true;
+ break;
+ }
+ /* Admin can't kick owner */
+ if ( *ptr == 'a' ) {
+ if (!strchr(target_modes, 'q')) {
+ can_kick = true;
+ break;
+ }
+ }
+ /* Op can't kick owner | admin */
+ if ( *ptr == 'o' ) {
+ if (!strchr(target_modes, 'q') &&
+ !strchr(target_modes, 'a')) {
+ can_kick = true;
+ break;
+ }
+ }
+ /* Half Op can't kick owner | admin | op */
+ if ( *ptr == 'h' ) {
+ if (!strchr(target_modes, 'q') &&
+ !strchr(target_modes, 'a') &&
+ !strchr(target_modes, 'o')) {
+ can_kick = true;
+ break;
+ }
+ }
+ ptr++;
+ }
+
+ if(!can_kick) {
+ IRC_WriteStrClient(Origin, ERR_CHANOPPRIVTOLOW_MSG,
+ Client_ID(Origin), Name);
return;
}
}
static bool
Can_Send_To_Channel(CHANNEL *Chan, CLIENT *From)
{
- bool is_member, has_voice, is_op;
+ bool is_member, has_voice, is_halfop, is_op, is_chanadmin, is_owner;
- is_member = has_voice = is_op = false;
+ is_member = has_voice = is_halfop = is_op = is_chanadmin = is_owner = false;
/* The server itself always can send messages :-) */
if (Client_ThisServer() == From)
is_member = true;
if (strchr(Channel_UserModes(Chan, From), 'v'))
has_voice = true;
+ if (strchr(Channel_UserModes(Chan, From), 'h'))
+ is_halfop = true;
if (strchr(Channel_UserModes(Chan, From), 'o'))
is_op = true;
+ if (strchr(Channel_UserModes(Chan, From), 'a'))
+ is_chanadmin = true;
+ if (strchr(Channel_UserModes(Chan, From), 'q'))
+ is_owner = true;
}
/*
if (strchr(Channel_Modes(Chan), 'n') && !is_member)
return false;
- if (is_op || has_voice)
+ if (strchr(Channel_Modes(Chan), 'M') && !Client_HasMode(From, 'R')
+ && !Client_HasMode(From, 'o'))
+ return false;
+
+ if (has_voice || is_halfop || is_op || is_chanadmin || is_owner)
return true;
if (strchr(Channel_Modes(Chan), 'm'))
} /* Channel_CheckKey */
- /**
- * Check wether a client is allowed to administer a channel or not.
- *
- * @param Chan The channel to test.
- * @param Client The client from which the command has been received.
- * @param Origin The originator of the command (or NULL).
- * @param OnChannel Set to true if the originator is member of the channel.
- * @param AdminOk Set to true if the client is allowed to do
- * administrative tasks on this channel.
- * @param UseServerMode Set to true if ngIRCd should emulate "server mode",
- * that is send commands as if originating from a server
- * and not the originator of the command.
- */
- GLOBAL void
- Channel_CheckAdminRights(CHANNEL *Chan, CLIENT *Client, CLIENT *Origin,
- bool *OnChannel, bool *AdminOk, bool *UseServerMode)
- {
- assert (Chan != NULL);
- assert (Client != NULL);
- assert (OnChannel != NULL);
- assert (AdminOk != NULL);
- assert (UseServerMode != NULL);
-
- /* Use the client as origin, if no origin has been given (no prefix?) */
- if (!Origin)
- Origin = Client;
-
- *OnChannel = false;
- *AdminOk = false;
- *UseServerMode = false;
-
- if (Client_Type(Client) != CLIENT_USER
- && Client_Type(Client) != CLIENT_SERVER
- && Client_Type(Client) != CLIENT_SERVICE)
- return;
-
- /* Allow channel administration if the client is a server or service */
- if (Client_Type(Client) != CLIENT_USER) {
- *AdminOk = true;
- return;
- }
-
- *OnChannel = Channel_IsMemberOf(Chan, Origin);
-
- if (*OnChannel && strchr(Channel_UserModes(Chan, Origin), 'o')) {
- /* User is a channel operator */
- *AdminOk = true;
- } else if (Conf_OperCanMode) {
- /* IRC operators are allowed to administer channels as well */
- if (Client_OperByMe(Origin)) {
- *AdminOk = true;
- if (Conf_OperServerMode)
- *UseServerMode = true;
- }
- }
- } /* Channel_CheckAdminRights */
-
-
static CL2CHAN *
Get_First_Cl2Chan( CLIENT *Client, CHANNEL *Chan )
{
#endif
/** Supported user modes. */
-#define USERMODES "acCiorRswx"
+#define USERMODES "aBcCiorRswx"
/** Supported channel modes. */
- #define CHANMODES "beiIklmMnoOPrRstvz"
-#define CHANMODES "abehiIklmnoOPqrRstvz"
++#define CHANMODES "abehiIklmMnoOPqrRstvz"
/** Away message for users connected to linked servers. */
#define DEFAULT_AWAY_MSG "Away"
}
- static const char *
- who_flags_qualifier(CLIENT *Client, const char *chan_user_modes)
+ static char *
+ who_flags_qualifier(CLIENT *Client, const char *chan_user_modes, char *str, size_t len)
{
assert(Client != NULL);
-
- if (Client_Cap(Client) & CLIENT_CAP_MULTI_PREFIX) {
- if (strchr(chan_user_modes, 'o') &&
- strchr(chan_user_modes, 'v'))
- return "@+";
+
+ if (Client_Cap(Client) & CLIENT_CAP_MULTI_PREFIX) {
+ if (strchr(chan_user_modes, 'q'))
+ strlcat(str, "~", len);
+ if (strchr(chan_user_modes, 'a'))
+ strlcat(str, "&", len);
+ if (strchr(chan_user_modes, 'o'))
+ strlcat(str, "@", len);
+ if (strchr(chan_user_modes, 'h'))
+ strlcat(str, "&", len);
+ if (strchr(chan_user_modes, 'v'))
+ strlcat(str, "+", len);
+
+ return str;
}
-
- if (strchr(chan_user_modes, 'o'))
- return "@";
+
+ if (strchr(chan_user_modes, 'q'))
+ strlcat(str, "~", len);
+ else if (strchr(chan_user_modes, 'a'))
+ strlcat(str, "&", len);
+ else if (strchr(chan_user_modes, 'o'))
+ strlcat(str, "@", len);
+ else if (strchr(chan_user_modes, 'h'))
+ strlcat(str, "%", len);
else if (strchr(chan_user_modes, 'v'))
- return "+";
- return "";
+ strlcat(str, "+", len);
+
+ return str;
}
CL2CHAN *cl2chan;
const char *client_modes;
const char *chan_user_modes;
- char flags[8];
+ char flags[10];
CLIENT *c;
int count = 0;
assert( Client != NULL );
assert( Chan != NULL );
+ IRC_SetPenalty(Client, 1);
+
is_member = Channel_IsMemberOf(Chan, Client);
/* Secret channel? */
is_visible = strchr(client_modes, 'i') == NULL;
if (is_member || is_visible) {
- if (IRC_CheckListTooBig(Client, count, MAX_RPL_WHO, "WHO"))
- break;
-
strcpy(flags, who_flags_status(client_modes));
if (is_ircop)
strlcat(flags, "*", sizeof(flags));
chan_user_modes = Channel_UserModes(Chan, c);
- strlcat(flags, who_flags_qualifier(c, chan_user_modes),
- sizeof(flags));
-
+ who_flags_qualifier(c, chan_user_modes, flags, sizeof(flags));
+
if (!write_whoreply(Client, c, Channel_Name(Chan),
flags))
return DISCONNECTED;
count++;
}
}
+
+ /* If there are a lot of clients, augment penalty a bit */
+ if (count > MAX_RPL_WHO)
+ IRC_SetPenalty(Client, 1);
+
return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client),
Channel_Name(Chan));
}
if (Mask)
ngt_LowerStr(Mask);
+ IRC_SetPenalty(Client, 3);
for (c = Client_First(); c != NULL; c = Client_Next(c)) {
if (Client_Type(c) != CLIENT_USER)
continue;
chan = Channel_Search(Req->argv[0]);
if (chan) {
/* Members of a channel have been requested */
- IRC_SetPenalty(Client, 1);
return IRC_WHO_Channel(Client, chan, only_ops);
}
if (strcmp(Req->argv[0], "0") != 0) {
/* A mask has been given. But please note this RFC
* stupidity: "0" is same as no arguments ... */
- IRC_SetPenalty(Client, 3);
return IRC_WHO_Mask(Client, Req->argv[0], only_ops);
}
}
if (str[strlen(str) - 1] != ':')
strlcat(str, " ", sizeof(str));
- strlcat(str, who_flags_qualifier(c, Channel_UserModes(chan, c)),
- sizeof(str));
+ who_flags_qualifier(c, Channel_UserModes(chan, c), str, sizeof(str));
strlcat(str, Channel_Name(chan), sizeof(str));
if (strlen(str) > (LINE_LEN - CHANNEL_NAME_LEN - 4)) {
Client_ID(from), Client_ID(c)))
return DISCONNECTED;
+ /* IRC-Bot? */
+ if (Client_HasMode(c, 'B') &&
+ !IRC_WriteStrClient(from, RPL_WHOISBOT_MSG,
+ Client_ID(from), Client_ID(c)))
+ return DISCONNECTED;
+
/* Connected using SSL? */
if (Conn_UsesSSL(Client_Conn(c)) &&
!IRC_WriteStrClient(from, RPL_WHOISSSL_MSG, Client_ID(from),
static bool
Show_MOTD_End(CLIENT *Client)
{
- return IRC_WriteStrClient( Client, RPL_ENDOFMOTD_MSG, Client_ID( Client ));
+ if (!IRC_WriteStrClient(Client, RPL_ENDOFMOTD_MSG, Client_ID(Client)))
+ return DISCONNECTED;
+
+ if (*Conf_CloakHost)
+ return IRC_WriteStrClient(Client, RPL_HOSTHIDDEN_MSG,
+ Client_ID(Client),
+ Client_Hostname(Client));
+
+ return CONNECTED;
}
#ifdef SSL_SUPPORT
if (is_member || is_visible) {
if (str[strlen(str) - 1] != ':')
strlcat(str, " ", sizeof(str));
- if (Client_Cap(cl) & CLIENT_CAP_MULTI_PREFIX) {
- if (strchr(Channel_UserModes(Chan, cl), 'o') &&
- strchr(Channel_UserModes(Chan, cl), 'v'))
- strlcat(str, "@+", sizeof(str));
- } else {
- if (strchr(Channel_UserModes(Chan, cl), 'o'))
- strlcat(str, "@", sizeof(str));
- else if (strchr(Channel_UserModes(Chan, cl), 'v'))
- strlcat(str, "+", sizeof(str));
- }
+
+ who_flags_qualifier(cl, Channel_UserModes(Chan, cl), str, sizeof(str));
strlcat(str, Client_ID(cl), sizeof(str));
if (strlen(str) > (LINE_LEN - CLIENT_NICK_LEN - 4)) {
{
char the_modes[COMMAND_LEN], x[2], *mode_ptr;
bool ok, set;
+ bool send_RPL_HOSTHIDDEN_MSG = false;
int mode_arg;
size_t len;
ERR_NOPRIVILEGES_MSG,
Client_ID(Origin));
break;
+ case 'B': /* Bot */
+ if (Client_HasMode(Client, 'r'))
+ ok = IRC_WriteStrClient(Origin,
+ ERR_RESTRICTED_MSG,
+ Client_ID(Origin));
+ else
+ x[0] = 'B';
+ break;
case 'c': /* Receive connect notices
* (only settable by IRC operators!) */
if (!set || Client_Type(Client) == CLIENT_SERVER
ERR_RESTRICTED_MSG,
Client_ID(Origin));
break;
+ case 'R': /* Registered (not [un]settable by clients) */
+ if (Client_Type(Client) == CLIENT_SERVER)
+ x[0] = 'R';
+ else
+ ok = IRC_WriteStrClient(Origin,
+ ERR_NICKREGISTER_MSG,
+ Client_ID(Origin));
+ break;
case 'x': /* Cloak hostname */
if (Client_HasMode(Client, 'r'))
ok = IRC_WriteStrClient(Origin,
Client_ID(Origin));
else
x[0] = 'x';
+ send_RPL_HOSTHIDDEN_MSG = true;
break;
default:
if (Client_Type(Client) != CLIENT_SERVER) {
"MODE %s :%s",
Client_ID(Target),
the_modes);
+ if (send_RPL_HOSTHIDDEN_MSG)
+ IRC_WriteStrClient(Client, RPL_HOSTHIDDEN_MSG,
+ Client_ID(Client),
+ Client_HostnameCloaked(Client));
}
LogDebug("%s \"%s\": Mode change, now \"%s\".",
Client_TypeText(Target), Client_Mask(Target),
Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
{
char the_modes[COMMAND_LEN], the_args[COMMAND_LEN], x[2],
- argadd[CLIENT_PASS_LEN], *mode_ptr;
- bool connected, set, skiponce, retval, onchannel, modeok, use_servermode;
+ argadd[CLIENT_PASS_LEN], *mode_ptr, *o_mode_ptr;
+ bool connected, set, skiponce, retval, use_servermode,
+ is_halfop, is_op, is_admin, is_owner, is_machine, is_oper;
int mode_arg, arg_arg, mode_arg_count = 0;
CLIENT *client;
long l;
size_t len;
+ is_halfop = is_op = is_admin = is_owner = is_machine = is_oper = false;
+
if (Channel_IsModeless(Channel))
return IRC_WriteStrClient(Client, ERR_NOCHANMODES_MSG,
Client_ID(Client), Channel_Name(Channel));
if (Req->argc <= 1)
return Channel_Mode_Answer_Request(Origin, Channel);
- Channel_CheckAdminRights(Channel, Client, Origin,
- &onchannel, &modeok, &use_servermode);
+ /* Check if origin is oper and opers can use mode */
+ use_servermode = Conf_OperServerMode;
+ if(Client_OperByMe(Client) && Conf_OperCanMode) {
+ is_oper = true;
+ }
+
+ /* Check if client is a server/service */
+ if(Client_Type(Client) == CLIENT_SERVER ||
+ Client_Type(Client) == CLIENT_SERVICE) {
+ is_machine = true;
+ }
- if (!onchannel && !modeok)
+ /* Check if client is member of channel or an oper or an server/service */
+ if(!Channel_IsMemberOf(Channel, Client) && !is_oper && !is_machine)
return IRC_WriteStrClient(Origin, ERR_NOTONCHANNEL_MSG,
Client_ID(Origin),
Channel_Name(Channel));
/* Are there arguments left? */
if (arg_arg >= Req->argc)
arg_arg = -1;
+
+ if(!is_machine) {
+ o_mode_ptr = Channel_UserModes(Channel, Client);
+ while( *o_mode_ptr ) {
+ if ( *o_mode_ptr == 'q')
+ is_owner = true;
+ if ( *o_mode_ptr == 'a')
+ is_admin = true;
+ if ( *o_mode_ptr == 'o')
+ is_op = true;
+ if ( *o_mode_ptr == 'h')
+ is_halfop = true;
+ o_mode_ptr++;
+ }
+ }
/* Validate modes */
x[0] = '\0';
client = NULL;
switch (*mode_ptr) {
/* --- Channel modes --- */
+ case 'R': /* Registered users only */
+ case 's': /* Secret channel */
+ case 'z': /* Secure connections only */
+ if(!is_oper && !is_machine && !is_owner &&
+ !is_admin && !is_op) {
+ connected = IRC_WriteStrClient(Origin,
+ ERR_CHANOPRIVSNEEDED_MSG,
+ Client_ID(Origin), Channel_Name(Channel));
+ goto chan_exit;
+ }
case 'i': /* Invite only */
+ case 'M': /* Only identified nicks can write */
case 'm': /* Moderated */
case 'n': /* Only members can write */
- case 'R': /* Registered users only */
- case 's': /* Secret channel */
case 't': /* Topic locked */
- case 'z': /* Secure connections only */
- if (modeok)
+ if(is_oper || is_machine || is_owner ||
+ is_admin || is_op || is_halfop)
x[0] = *mode_ptr;
else
connected = IRC_WriteStrClient(Origin,
if (Mode_Limit_Reached(Client, mode_arg_count++))
goto chan_exit;
if (!set) {
- if (modeok)
+ if (is_oper || is_machine || is_owner ||
+ is_admin || is_op || is_halfop)
x[0] = *mode_ptr;
else
connected = IRC_WriteStrClient(Origin,
break;
}
if (arg_arg > mode_arg) {
- if (modeok) {
+ if (is_oper || is_machine || is_owner ||
+ is_admin || is_op || is_halfop) {
Channel_ModeDel(Channel, 'k');
Channel_SetKey(Channel,
Req->argv[arg_arg]);
if (Mode_Limit_Reached(Client, mode_arg_count++))
goto chan_exit;
if (!set) {
- if (modeok)
+ if (is_oper || is_machine || is_owner ||
+ is_admin || is_op || is_halfop)
x[0] = *mode_ptr;
else
connected = IRC_WriteStrClient(Origin,
break;
}
if (arg_arg > mode_arg) {
- if (modeok) {
+ if (is_oper || is_machine || is_owner ||
+ is_admin || is_op || is_halfop) {
l = atol(Req->argv[arg_arg]);
if (l > 0 && l < 0xFFFF) {
Channel_ModeDel(Channel, 'l');
}
break;
case 'O': /* IRC operators only */
- if (modeok) {
+ if (set) {
/* Only IRC operators are allowed to
* set the 'O' channel mode! */
- if (set && !(Client_OperByMe(Client)
- || Client_Type(Client) == CLIENT_SERVER))
+ if(is_oper || is_machine)
+ x[0] = 'O';
+ else
connected = IRC_WriteStrClient(Origin,
ERR_NOPRIVILEGES_MSG,
Client_ID(Origin));
- else
- x[0] = 'O';
- } else
+ } else if(is_oper || is_machine || is_owner ||
+ is_admin || is_op)
+ x[0] = 'O';
+ else
connected = IRC_WriteStrClient(Origin,
- ERR_CHANOPRIVSNEEDED_MSG,
- Client_ID(Origin),
- Channel_Name(Channel));
- break;
+ ERR_CHANOPRIVSNEEDED_MSG,
+ Client_ID(Origin),
+ Channel_Name(Channel));
+ break;
case 'P': /* Persistent channel */
- if (modeok) {
+ if (set) {
/* Only IRC operators are allowed to
* set the 'P' channel mode! */
- if (set && !(Client_OperByMe(Client)
- || Client_Type(Client) == CLIENT_SERVER))
+ if(is_oper || is_machine)
+ x[0] = 'P';
+ else
connected = IRC_WriteStrClient(Origin,
ERR_NOPRIVILEGES_MSG,
Client_ID(Origin));
- else
- x[0] = 'P';
- } else
+ } else if(is_oper || is_machine || is_owner ||
+ is_admin || is_op)
+ x[0] = 'P';
+ else
connected = IRC_WriteStrClient(Origin,
ERR_CHANOPRIVSNEEDED_MSG,
Client_ID(Origin),
Channel_Name(Channel));
break;
/* --- Channel user modes --- */
- case 'a':
- case 'h':
- case 'q':
- if (Client_Type(Client) != CLIENT_SERVER) {
+ case 'q': /* Owner */
+ case 'a': /* Channel admin */
+ if(!is_oper && !is_machine && !is_owner) {
connected = IRC_WriteStrClient(Origin,
ERR_CHANOPRIVSNEEDED_MSG,
Client_ID(Origin),
goto chan_exit;
}
case 'o': /* Channel operator */
+ if(!is_oper && !is_machine && !is_owner &&
+ !is_admin && !is_op) {
+ connected = IRC_WriteStrClient(Origin,
+ ERR_CHANOPRIVSNEEDED_MSG,
+ Client_ID(Origin),
+ Channel_Name(Channel));
+ goto chan_exit;
+ }
+ case 'h': /* Half Op */
+ if(!is_oper && !is_machine && !is_owner &&
+ !is_admin && !is_op) {
+ connected = IRC_WriteStrClient(Origin,
+ ERR_CHANOPRIVSNEEDED_MSG,
+ Client_ID(Origin),
+ Channel_Name(Channel));
+ goto chan_exit;
+ }
case 'v': /* Voice */
if (arg_arg > mode_arg) {
- if (modeok) {
+ if (is_oper || is_machine || is_owner ||
+ is_admin || is_op || is_halfop) {
client = Client_Search(Req->argv[arg_arg]);
if (client)
x[0] = *mode_ptr;
else
- connected = IRC_WriteStrClient(Client,
+ connected = IRC_WriteStrClient(Origin,
ERR_NOSUCHNICK_MSG,
- Client_ID(Client),
+ Client_ID(Origin),
Req->argv[arg_arg]);
} else {
connected = IRC_WriteStrClient(Origin,
goto chan_exit;
if (arg_arg > mode_arg) {
/* modify list */
- if (modeok) {
+ if (is_oper || is_machine || is_owner ||
+ is_admin || is_op || is_halfop) {
connected = set
? Add_To_List(*mode_ptr, Origin,
Client, Channel,
Conn_Close( Client_Conn( Client ), NULL, "Server not configured here", true);
return DISCONNECTED;
}
- if( strcmp( Client_Password( Client ), Conf_Server[i].pwd_in ) != 0 )
+ if( strcmp( Conn_Password( Client_Conn( Client ) ),
+ Conf_Server[i].pwd_in ) != 0 )
{
/* wrong password */
Log( LOG_ERR, "Connection %d: Got bad password from server \"%s\"!", Client_Conn( Client ), Req->argv[0] );
IRC_NJOIN( CLIENT *Client, REQUEST *Req )
{
char nick_in[COMMAND_LEN], nick_out[COMMAND_LEN], *channame, *ptr, modes[8];
- bool is_op, is_voiced;
+ bool is_owner, is_chanadmin, is_op, is_halfop, is_voiced;
CHANNEL *chan;
CLIENT *c;
is_op = is_voiced = false;
/* cut off prefixes */
- while(( *ptr == '@' ) || ( *ptr == '+' ))
- {
+ while(( *ptr == '~') || ( *ptr == '&' ) || ( *ptr == '@' ) ||
+ ( *ptr == '%') || ( *ptr == '+' ))
+ {
+ if( *ptr == '~' ) is_owner = true;
+ if( *ptr == '&' ) is_chanadmin = true;
if( *ptr == '@' ) is_op = true;
+ if( *ptr == 'h' ) is_halfop = true;
if( *ptr == '+' ) is_voiced = true;
ptr++;
}
chan = Channel_Search( channame );
assert( chan != NULL );
+ if( is_owner ) Channel_UserModeAdd( chan, c, 'q' );
+ if( is_chanadmin ) Channel_UserModeAdd( chan, c, 'a' );
if( is_op ) Channel_UserModeAdd( chan, c, 'o' );
+ if( is_halfop ) Channel_UserModeAdd( chan, c, 'h' );
if( is_voiced ) Channel_UserModeAdd( chan, c, 'v' );
/* announce to channel... */
}
if( nick_out[0] != '\0' ) strlcat( nick_out, ",", sizeof( nick_out ));
+ if( is_owner ) strlcat( nick_out, "~", sizeof( nick_out ));
+ if( is_chanadmin ) strlcat( nick_out, "&", sizeof( nick_out ));
if( is_op ) strlcat( nick_out, "@", sizeof( nick_out ));
+ if( is_halfop ) strlcat( nick_out, "%", sizeof( nick_out ));
if( is_voiced ) strlcat( nick_out, "+", sizeof( nick_out ));
strlcat( nick_out, ptr, sizeof( nick_out ));
}
#define RPL_YOURHOST_MSG "002 %s :Your host is %s, running version ngircd-%s (%s/%s/%s)"
#define RPL_CREATED_MSG "003 %s :This server has been started %s"
#define RPL_MYINFO_MSG "004 %s %s ngircd-%s %s %s"
- #define RPL_ISUPPORT1_MSG "005 %s RFC2812 IRCD=ngIRCd CASEMAPPING=ascii PREFIX=(ov)@+ CHANTYPES=#&+ CHANMODES=beI,k,l,imMnOPRstz CHANLIMIT=#&+:%d :are supported on this server"
-#define RPL_ISUPPORT1_MSG "005 %s RFC2812 IRCD=ngIRCd CASEMAPPING=ascii PREFIX=(qaohv)~&@%%+ CHANTYPES=#&+ CHANMODES=beI,k,l,imnOPRstz CHANLIMIT=#&+:%d :are supported on this server"
++#define RPL_ISUPPORT1_MSG "005 %s RFC2812 IRCD=ngIRCd CASEMAPPING=ascii PREFIX=(qaohv)~&@%%+ CHANTYPES=#&+ CHANMODES=beI,k,l,imMnOPRstz CHANLIMIT=#&+:%d :are supported on this server"
#define RPL_ISUPPORT2_MSG "005 %s CHANNELLEN=%d NICKLEN=%d TOPICLEN=%d AWAYLEN=%d KICKLEN=%d MODES=%d MAXLIST=beI:%d EXCEPTS=e INVEX=I PENALTY :are supported on this server"
#define RPL_TRACELINK_MSG "200 %s Link %s-%s %s %s V%s %ld %d %d"
#define RPL_NOTOPIC_MSG "331 %s %s :No topic is set"
#define RPL_TOPIC_MSG "332 %s %s :%s"
#define RPL_TOPICSETBY_MSG "333 %s %s %s %u"
+#define RPL_WHOISBOT_MSG "335 %s %s :is a IRC Bot"
#define RPL_INVITING_MSG "341 %s %s %s%s"
#define RPL_INVITELIST_MSG "346 %s %s %s"
#define RPL_ENDOFINVITELIST_MSG "347 %s %s :End of channel invite list"
#define RPL_YOUREOPER_MSG "381 %s :You are now an IRC Operator"
#define RPL_YOURESERVICE_MSG "383 %s :You are service %s"
#define RPL_TIME_MSG "391 %s %s :%s"
+#define RPL_HOSTHIDDEN_MSG "396 %s %s :is your displayed hostname now"
#define ERR_NOSUCHNICK_MSG "401 %s %s :No such nick or channel name"
#define ERR_NOSUCHSERVER_MSG "402 %s %s :No such server"
#define ERR_NOSUCHCHANNEL_MSG "403 %s %s :No such channel"
-#define ERR_CANNOTSENDTOCHAN_MSG "404 %s %s :Cannot send to channel"
+#define ERR_CANNOTSENDTOCHAN_MSG "404 %s %s :Cannot send to channel (+m) -- Moderated"
#define ERR_TOOMANYCHANNELS_MSG "405 %s %s :You have joined too many channels"
#define ERR_WASNOSUCHNICK_MSG "406 %s %s :There was no such nickname"
#define ERR_NOORIGIN_MSG "409 %s :No origin specified"
#define ERR_NONICKNAMEGIVEN_MSG "431 %s :No nickname given"
#define ERR_ERRONEUSNICKNAME_MSG "432 %s %s :Erroneous nickname"
#define ERR_NICKNAMETOOLONG_MSG "432 %s %s :Nickname too long, max. %u characters"
+#define ERR_FORBIDDENNICKNAME_MSG "432 %s %s :Nickname is forbidden/blocked"
#define ERR_NICKNAMEINUSE_MSG "433 %s %s :Nickname already in use"
#define ERR_USERNOTINCHANNEL_MSG "441 %s %s %s :They aren't on that channel"
#define ERR_NOTONCHANNEL_MSG "442 %s %s :You are not on that channel"
#define ERR_NEEDMOREPARAMS_MSG "461 %s %s :Syntax error"
#define ERR_ALREADYREGISTRED_MSG "462 %s :Connection already registered"
#define ERR_PASSWDMISMATCH_MSG "464 %s :Invalid password"
-#define ERR_CHANNELISFULL_MSG "471 %s %s :Cannot join channel (+l)"
-#define ERR_SECURECHANNEL_MSG "471 %s %s :Cannot join channel (+z)"
-#define ERR_OPONLYCHANNEL_MSG "471 %s %s :Cannot join channel (+O)"
-#define ERR_REGONLYCHANNEL_MSG "471 %s %s :Cannot join channel (+R)"
+#define ERR_CHANNELISFULL_MSG "471 %s %s :Cannot join channel (+l) -- Channel is too full, try later"
+#define ERR_SECURECHANNEL_MSG "471 %s %s :Cannot join channel (+z) -- SSL connections only"
+#define ERR_OPONLYCHANNEL_MSG "471 %s %s :Cannot join channel (+O) -- IRC opers only"
+#define ERR_REGONLYCHANNEL_MSG "471 %s %s :Cannot join channel (+R) -- Registered users only"
#define ERR_UNKNOWNMODE_MSG "472 %s %c :is unknown mode char for %s"
-#define ERR_INVITEONLYCHAN_MSG "473 %s %s :Cannot join channel (+i)"
-#define ERR_BANNEDFROMCHAN_MSG "474 %s %s :Cannot join channel (+b)"
-#define ERR_BADCHANNELKEY_MSG "475 %s %s :Cannot join channel (+k)"
+#define ERR_INVITEONLYCHAN_MSG "473 %s %s :Cannot join channel (+i) -- Invited users only"
+#define ERR_BANNEDFROMCHAN_MSG "474 %s %s :Cannot join channel (+b) -- You are banned"
+#define ERR_BADCHANNELKEY_MSG "475 %s %s :Cannot join channel (+k) -- Wrong channel key"
#define ERR_NOCHANMODES_MSG "477 %s %s :Channel doesn't support modes"
#define ERR_LISTFULL_MSG "478 %s %s %s: Channel list is full (%d)"
#define ERR_NOPRIVILEGES_MSG "481 %s :Permission denied"
#define ERR_CHANOPRIVSNEEDED_MSG "482 %s %s :You are not channel operator"
+ #define ERR_CHANOPPRIVTOLOW_MSG "482 %s %s :Your privileges are to low"
#define ERR_CANTKILLSERVER_MSG "483 %s :You can't kill a server!"
#define ERR_RESTRICTED_MSG "484 %s :Your connection is restricted"
+#define ERR_NICKREGISTER_MSG "484 %s :Cannot modify user mode (+R) -- Use IRC services"
#define ERR_NOOPERHOST_MSG "491 %s :Not configured for your host"
#define ERR_NOTONSAMECHANNEL_MSG "493 %s :You must share a common channel with %s"