#include "irc-macros.h"
#include "irc-write.h"
#include "client-cap.h"
+#include "op.h"
#include "exp.h"
#include "irc-info.h"
flags, Client_Hops(c), Client_Info(c));
}
-static const char *
-who_flags_status(const char *client_modes)
-{
- if (strchr(client_modes, 'a'))
- return "G"; /* away */
- return "H";
-}
-
/**
* Return channel user mode prefix(es).
*
{
bool is_visible, is_member, is_ircop;
CL2CHAN *cl2chan;
- const char *client_modes;
char flags[10];
CLIENT *c;
int count = 0;
is_member = Channel_IsMemberOf(Chan, Client);
/* Secret channel? */
- if (!is_member && strchr(Channel_Modes(Chan), 's'))
+ if (!is_member && Channel_HasMode(Chan, 's'))
return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG,
Client_ID(Client), Channel_Name(Chan));
for (; cl2chan ; cl2chan = Channel_NextMember(Chan, cl2chan)) {
c = Channel_GetClient(cl2chan);
- client_modes = Client_Modes(c);
- is_ircop = strchr(client_modes, 'o') != NULL;
+ is_ircop = Client_HasMode(c, 'o');
if (OnlyOps && !is_ircop)
continue;
- is_visible = strchr(client_modes, 'i') == NULL;
+ is_visible = Client_HasMode(c, 'i');
if (is_member || is_visible) {
- strlcpy(flags, who_flags_status(client_modes),
- sizeof(flags));
+ memset(flags, 0, sizeof(flags));
+
+ if (Client_HasMode(c, 'a'))
+ flags[0] = 'G'; /* away */
+ else
+ flags[0] = 'H';
+
if (is_ircop)
- strlcat(flags, "*", sizeof(flags));
+ flags[1] = '*';
who_flags_qualifier(Client, Channel_UserModes(Chan, c),
flags, sizeof(flags));
CL2CHAN *cl2chan;
CHANNEL *chan;
bool client_match, is_visible;
- char flags[4];
+ char flags[3];
int count = 0;
assert (Client != NULL);
if (IRC_CheckListTooBig(Client, count, MAX_RPL_WHO, "WHO"))
break;
- strlcpy(flags, who_flags_status(Client_Modes(c)), sizeof(flags));
- if (strchr(Client_Modes(c), 'o'))
- strlcat(flags, "*", sizeof(flags));
+ memset(flags, 0, sizeof(flags));
+
+ if (Client_HasMode(c, 'a'))
+ flags[0] = 'G'; /* away */
+ else
+ flags[0] = 'H';
+
+ if (Client_HasMode(c, 'o'))
+ flags[1] = '*';
if (!write_whoreply(Client, c, "*", flags))
return DISCONNECTED;
cl2chan = Channel_NextChannelOf(c, cl2chan);
/* Secret channel? */
- if (strchr(Channel_Modes(chan), 's')
+ if (Channel_HasMode(chan, 's')
&& !Channel_IsMemberOf(chan, Client))
continue;
return DISCONNECTED;
/* Connected using SSL? */
- if (Conn_UsesSSL(Client_Conn(c)) &&
- !IRC_WriteStrClient(from, RPL_WHOISSSL_MSG, Client_ID(from),
- Client_ID(c)))
- return DISCONNECTED;
+ if (Conn_UsesSSL(Client_Conn(c))) {
+ if (!IRC_WriteStrClient(from, RPL_WHOISSSL_MSG, Client_ID(from),
+ Client_ID(c)))
+ return DISCONNECTED;
+
+ /* Certificate fingerprint? */
+ if (Conn_GetCertFp(Client_Conn(c)) &&
+ from == c &&
+ !IRC_WriteStrClient(from, RPL_WHOISCERTFP_MSG,
+ Client_ID(from), Client_ID(c),
+ Conn_GetCertFp(Client_Conn(c))))
+ return DISCONNECTED;
+ }
/* Registered nickname? */
if (Client_HasMode(c, 'R') &&
(from == c || (!Conf_MorePrivacy && Client_HasMode(from, 'o')))) {
/* Client hostname */
if (!IRC_WriteStrClient(from, RPL_WHOISHOST_MSG,
- Client_ID(from), Client_ID(c), Client_Hostname(c),
- Conn_GetIPAInfo(Client_Conn(c))))
+ Client_ID(from), Client_ID(c),
+ Client_Hostname(c), Client_IPAText(c)))
return DISCONNECTED;
/* Client modes */
if (!IRC_WriteStrClient(from, RPL_WHOISMODES_MSG,
entry->id, entry->server, t_str);
}
-static bool
-Show_MOTD_Start(CLIENT *Client)
-{
- return IRC_WriteStrClient(Client, RPL_MOTDSTART_MSG,
- Client_ID( Client ), Client_ID( Client_ThisServer( )));
-}
-
-static bool
-Show_MOTD_Sendline(CLIENT *Client, const char *msg)
-{
- return IRC_WriteStrClient(Client, RPL_MOTD_MSG, Client_ID( Client ), msg);
-}
-
-static bool
-Show_MOTD_End(CLIENT *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
-static bool Show_MOTD_SSLInfo(CLIENT *Client)
+static bool
+Show_MOTD_SSLInfo(CLIENT *Client)
{
- bool ret = true;
- char buf[COMMAND_LEN] = "Connected using Cipher ";
-
- if (!Conn_GetCipherInfo(Client_Conn(Client), buf + 23, sizeof buf - 23))
- return true;
+ char buf[COMMAND_LEN];
+ char c_str[128];
+
+ if (Conn_GetCipherInfo(Client_Conn(Client), c_str, sizeof(c_str))) {
+ snprintf(buf, sizeof(buf), "Connected using Cipher %s", c_str);
+ if (!IRC_WriteStrClient(Client, RPL_MOTD_MSG,
+ Client_ID(Client), buf))
+ return false;
+ }
- if (!Show_MOTD_Sendline(Client, buf))
- ret = false;
+ if (Conn_GetCertFp(Client_Conn(Client))) {
+ snprintf(buf, sizeof(buf),
+ "Your client certificate fingerprint is: %s",
+ Conn_GetCertFp(Client_Conn(Client)));
+ if (!IRC_WriteStrClient(Client, RPL_MOTD_MSG,
+ Client_ID(Client), buf))
+ return false;
+ }
- return ret;
+ return true;
}
#else
-static inline bool
+static bool
Show_MOTD_SSLInfo(UNUSED CLIENT *c)
-{ return true; }
+{
+ return true;
+}
#endif
/* Global functions */
IRC_SetPenalty(Client, 1);
- _IRC_ARGC_LE_OR_RETURN_(Client, Req, 1)
_IRC_GET_SENDER_OR_RETURN_(prefix, Req, Client)
_IRC_GET_TARGET_SERVER_OR_RETURN_(target, Req, 0, prefix)
IRC_SetPenalty(Client, 2);
- _IRC_ARGC_LE_OR_RETURN_(Client, Req, 1)
_IRC_GET_SENDER_OR_RETURN_(prefix, Req, Client)
_IRC_GET_TARGET_SERVER_OR_RETURN_(target, Req, 0, prefix)
assert(Client != NULL);
assert(Req != NULL);
- _IRC_ARGC_GE_OR_RETURN_(Client, Req, 1)
-
strlcpy(rpl, RPL_ISON_MSG, sizeof rpl);
for (i = 0; i < Req->argc; i++) {
/* "All" ircd even parse ":<x> <y> ..." arguments and split
IRC_SetPenalty(Client, 1);
- _IRC_ARGC_LE_OR_RETURN_(Client, Req, 2)
_IRC_GET_SENDER_OR_RETURN_(from, Req, Client)
/* Get pointer to server mask or "*", if none given */
IRC_SetPenalty(Client, 1);
- _IRC_ARGC_LE_OR_RETURN_(Client, Req, 2)
_IRC_GET_SENDER_OR_RETURN_(from, Req, Client)
_IRC_GET_TARGET_SERVER_OR_RETURN_(target, Req, 1, from)
{
CLIENT *c;
- IRC_SetPenalty(Client, 1);
-
assert(Client != NULL);
assert(Req != NULL);
- _IRC_ARGC_LE_OR_RETURN_(Client, Req, 2)
+ IRC_SetPenalty(Client, 1);
if (Req->argc < 2 || strcmp(Req->argv[1], "0") == 0) {
for (c = Client_First(); c!= NULL; c = Client_Next(c)) {
IRC_SetPenalty(Client, 3);
- _IRC_ARGC_LE_OR_RETURN_(Client, Req, 1)
_IRC_GET_SENDER_OR_RETURN_(from, Req, Client)
_IRC_GET_TARGET_SERVER_OR_RETURN_(target, Req, 0, from)
IRC_SetPenalty(Client, 1);
- _IRC_ARGC_LE_OR_RETURN_(Client, Req, 2)
_IRC_GET_SENDER_OR_RETURN_(from, Req, Client)
_IRC_GET_TARGET_SERVER_OR_RETURN_(target, Req, 1, from)
while (c) {
if (Client_Type(c) == CLIENT_USER
&& Channel_FirstChannelOf(c) == NULL
- && !strchr(Client_Modes(c), 'i'))
+ && !Client_HasMode(c, 'i'))
{
/* its a user, concatenate ... */
if (rpl[strlen(rpl) - 1] != ':')
unsigned int days, hrs, mins;
struct list_head *list;
struct list_elem *list_item;
+ bool more_links = false;
assert(Client != NULL);
assert(Req != NULL);
IRC_SetPenalty(Client, 2);
- _IRC_ARGC_LE_OR_RETURN_(Client, Req, 2)
_IRC_GET_SENDER_OR_RETURN_(from, Req, Client)
_IRC_GET_TARGET_SERVER_OR_RETURN_(target, Req, 1, from)
case 'k': /* Server-local bans ("K-Lines") */
case 'K':
if (!Client_HasMode(from, 'o'))
- return IRC_WriteStrClient(from, ERR_NOPRIVILEGES_MSG,
+ return IRC_WriteErrClient(from, ERR_NOPRIVILEGES_MSG,
Client_ID(from));
if (query == 'g' || query == 'G')
list = Class_GetList(CLASS_GLINE);
list_item = Lists_GetNext(list_item);
}
break;
+ case 'L': /* Link status (servers and user links) */
+ if (!Op_Check(from, Req))
+ return Op_NoPrivileges(from, Req);
+ more_links = true;
+
case 'l': /* Link status (servers and own link) */
- case 'L':
time_now = time(NULL);
for (con = Conn_First(); con != NONE; con = Conn_Next(con)) {
cl = Conn_GetClient(con);
if (!cl)
continue;
- if ((Client_Type(cl) == CLIENT_SERVER)
- || (cl == Client)) {
- /* Server link or our own connection */
+ if (Client_Type(cl) == CLIENT_SERVER ||
+ cl == Client ||
+ (more_links && Client_Type(cl) == CLIENT_USER)) {
#ifdef ZLIB
if (Conn_Options(con) & CONN_ZIP) {
if (!IRC_WriteStrClient
{
assert(Client != NULL);
- IRC_SetPenalty(Client, 1);
-
- return IRC_WriteStrClient(Client, ERR_SUMMONDISABLED_MSG,
+ return IRC_WriteErrClient(Client, ERR_SUMMONDISABLED_MSG,
Client_ID(Client));
} /* IRC_SUMMON */
IRC_SetPenalty(Client, 1);
- _IRC_ARGC_LE_OR_RETURN_(Client, Req, 1)
_IRC_GET_SENDER_OR_RETURN_(from, Req, Client)
_IRC_GET_TARGET_SERVER_OR_RETURN_(target, Req, 0, from)
IRC_SetPenalty(Client, 1);
- _IRC_ARGC_GE_OR_RETURN_(Client, Req, 1)
-
if (Req->argc > 5)
max = 5;
else
{
assert(Client != NULL);
- IRC_SetPenalty(Client, 1);
-
- return IRC_WriteStrClient(Client, ERR_USERSDISABLED_MSG,
+ return IRC_WriteErrClient(Client, ERR_USERSDISABLED_MSG,
Client_ID(Client));
} /* IRC_USERS */
IRC_SetPenalty(Client, 1);
- _IRC_ARGC_LE_OR_RETURN_(Client, Req, 1)
_IRC_GET_SENDER_OR_RETURN_(prefix, Req, Client)
_IRC_GET_TARGET_SERVER_OR_RETURN_(target, Req, 0, prefix)
IRC_SetPenalty(Client, 1);
- _IRC_ARGC_LE_OR_RETURN_(Client, Req, 2)
-
only_ops = false;
if (Req->argc == 2) {
if (strcmp(Req->argv[1], "o") == 0)
only_ops = true;
#ifdef STRICT_RFC
- else
- return IRC_WriteStrClient(Client,
+ else {
+ IRC_SetPenalty(Client, 2);
+ return IRC_WriteErrClient(Client,
ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client),
Req->command);
+ }
#endif
}
IRC_SetPenalty(Client, 1);
- /* Bad number of parameters? */
- if (Req->argc < 1 || Req->argc > 2)
- return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
- Client_ID(Client), Req->command);
+ /* Wrong number of parameters? */
+ if (Req->argc < 1)
+ return IRC_WriteErrClient(Client, ERR_NONICKNAMEGIVEN_MSG,
+ Client_ID(Client));
+ _IRC_ARGC_LE_OR_RETURN_(Client, Req, 2)
_IRC_GET_SENDER_OR_RETURN_(from, Req, Client)
/* Get target server for this command */
if (!IRC_WHOIS_SendReply(Client, from, c))
return DISCONNECTED;
} else {
- if (!IRC_WriteStrClient(Client,
+ if (!IRC_WriteErrClient(Client,
ERR_NOSUCHNICK_MSG,
Client_ID(Client),
query))
}
if (got_wildcard) {
/* we already handled one wildcard query */
- if (!IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
+ if (!IRC_WriteErrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), query))
return DISCONNECTED;
continue;
}
if (match_count == 0)
- IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
+ IRC_WriteErrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client),
Req->argv[Req->argc - 1]);
}
assert( Client != NULL );
assert( Req != NULL );
- /* Do not reveal any info on disconnected users? */
- if (Conf_MorePrivacy)
- return CONNECTED;
-
/* Wrong number of parameters? */
if (Req->argc < 1)
- return IRC_WriteStrClient(Client, ERR_NONICKNAMEGIVEN_MSG,
+ return IRC_WriteErrClient(Client, ERR_NONICKNAMEGIVEN_MSG,
Client_ID(Client));
_IRC_ARGC_LE_OR_RETURN_(Client, Req, 3)
_IRC_GET_SENDER_OR_RETURN_(prefix, Req, Client)
_IRC_GET_TARGET_SERVER_OR_RETURN_(target, Req, 2, prefix)
+ /* Do not reveal any info on disconnected users? */
+ if (Conf_MorePrivacy)
+ return CONNECTED;
+
/* Forward? */
if (target != Client_ThisServer()) {
IRC_WriteStrClientPrefix(target, prefix, "WHOWAS %s %s %s",
break;
} while (i != last);
- if (nc == 0 && !IRC_WriteStrClient(prefix, ERR_WASNOSUCHNICK_MSG,
+ if (nc == 0 && !IRC_WriteErrClient(prefix, ERR_WASNOSUCHNICK_MSG,
Client_ID(prefix), nick))
return DISCONNECTED;
}
assert(Client != NULL);
- /* Users, services and serevers in the network */
+ /* Users, services and servers in the network */
if (!IRC_WriteStrClient(Client, RPL_LUSERCLIENT_MSG, Client_ID(Client),
Client_UserCount(), Client_ServiceCount(),
Client_ServerCount()))
len_tot = array_bytes(&Conf_Motd);
if (len_tot == 0 && !Conn_UsesSSL(Client_Conn(Client)))
- return IRC_WriteStrClient(Client, ERR_NOMOTD_MSG, Client_ID(Client));
+ return IRC_WriteErrClient(Client, ERR_NOMOTD_MSG, Client_ID(Client));
- if (!Show_MOTD_Start(Client))
+ if (!IRC_WriteStrClient(Client, RPL_MOTDSTART_MSG, Client_ID(Client),
+ Client_ID(Client_ThisServer())))
return DISCONNECTED;
line = array_start(&Conf_Motd);
assert(len_tot >= len_str);
len_tot -= len_str;
- if (!Show_MOTD_Sendline(Client, line))
+ if (!IRC_WriteStrClient(Client, RPL_MOTD_MSG, Client_ID(Client), line))
return DISCONNECTED;
line += len_str;
}
if (!Show_MOTD_SSLInfo(Client))
return DISCONNECTED;
- return Show_MOTD_End(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;
} /* IRC_Show_MOTD */
/**
return CONNECTED;
/* Secret channel? */
- if (!is_member && strchr(Channel_Modes(Chan), 's'))
+ if (!is_member && Channel_HasMode(Chan, 's'))
return CONNECTED;
snprintf(str, sizeof(str), RPL_NAMREPLY_MSG, Client_ID(Client), "=",
while (cl2chan) {
cl = Channel_GetClient(cl2chan);
- if (strchr(Client_Modes(cl), 'i'))
+ if (Client_HasMode(cl, 'i'))
is_visible = false;
else
is_visible = true;
IRC_Send_ISUPPORT(CLIENT * Client)
{
if (!IRC_WriteStrClient(Client, RPL_ISUPPORT1_MSG, Client_ID(Client),
- Conf_MaxJoins))
+ CHANTYPES, CHANTYPES, Conf_MaxJoins))
return DISCONNECTED;
return IRC_WriteStrClient(Client, RPL_ISUPPORT2_MSG, Client_ID(Client),
CHANNEL_NAME_LEN - 1, Conf_MaxNickLength - 1,