mirror of
https://github.com/irssi/irssi.git
synced 2025-02-02 15:08:01 -05:00
isupport patch by David Leadbeater
git-svn-id: http://svn.irssi.org/repos/irssi/trunk@3211 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
parent
3ccbd0405b
commit
217283caea
@ -219,7 +219,7 @@ static void event_connected(SERVER_REC *server)
|
||||
|
||||
static int match_nick_flags(SERVER_REC *server, NICK_REC *nick, char flag)
|
||||
{
|
||||
const char *flags = server->get_nick_flags();
|
||||
const char *flags = server->get_nick_flags(server);
|
||||
|
||||
return strchr(flags, flag) == NULL ||
|
||||
(flag == flags[0] && nick->op) ||
|
||||
@ -259,7 +259,7 @@ void channel_send_autocommands(CHANNEL_REC *channel)
|
||||
continue;
|
||||
|
||||
nick = nicklist_find_mask(channel,
|
||||
channel->server->isnickflag(*botnick) ?
|
||||
channel->server->isnickflag(channel->server, *botnick) ?
|
||||
botnick+1 : botnick);
|
||||
if (nick != NULL &&
|
||||
match_nick_flags(channel->server, nick, *botnick)) {
|
||||
|
@ -345,7 +345,7 @@ static void cmd_msg(const char *data, SERVER_REC *server, WI_ITEM_REC *item)
|
||||
GHashTable *optlist;
|
||||
char *target, *origtarget, *msg;
|
||||
void *free_arg;
|
||||
int free_ret, target_type;
|
||||
int free_ret, target_type = SEND_TARGET_NICK;
|
||||
|
||||
g_return_if_fail(data != NULL);
|
||||
|
||||
@ -398,7 +398,6 @@ static void cmd_msg(const char *data, SERVER_REC *server, WI_ITEM_REC *item)
|
||||
|
||||
if (target != NULL)
|
||||
server->send_message(server, target, msg, target_type);
|
||||
|
||||
signal_emit(target != NULL && target_type == SEND_TARGET_CHANNEL ?
|
||||
"message own_public" : "message own_private", 4,
|
||||
server, msg, target, origtarget);
|
||||
|
@ -19,6 +19,7 @@ unsigned int send_massjoin:1; /* Waiting to be sent in massjoin signal */
|
||||
unsigned int op:1;
|
||||
unsigned int halfop:1;
|
||||
unsigned int voice:1;
|
||||
unsigned int other:7;
|
||||
|
||||
/*GHashTable *module_data;*/
|
||||
|
||||
|
@ -369,7 +369,10 @@ int nicklist_compare(NICK_REC *p1, NICK_REC *p2)
|
||||
* returns :-)
|
||||
* -- yath */
|
||||
|
||||
if (p1->op)
|
||||
/* Treat others as highest - should really use order in 005 numeric */
|
||||
if (p1->other)
|
||||
status1 = 5;
|
||||
else if (p1->op)
|
||||
status1 = 4;
|
||||
else if (p1->halfop)
|
||||
status1 = 3;
|
||||
@ -378,7 +381,9 @@ int nicklist_compare(NICK_REC *p1, NICK_REC *p2)
|
||||
else
|
||||
status1 = 1;
|
||||
|
||||
if (p2->op)
|
||||
if (p2->other)
|
||||
status2 = 5;
|
||||
else if (p2->op)
|
||||
status2 = 4;
|
||||
else if (p2->halfop)
|
||||
status2 = 3;
|
||||
|
@ -53,12 +53,12 @@ GSList *queries;
|
||||
channel keys etc. */
|
||||
void (*channels_join)(SERVER_REC *server, const char *data, int automatic);
|
||||
/* returns true if `flag' indicates a nick flag (op/voice/halfop) */
|
||||
int (*isnickflag)(char flag);
|
||||
int (*isnickflag)(SERVER_REC *server, char flag);
|
||||
/* returns true if `data' indicates a channel */
|
||||
int (*ischannel)(SERVER_REC *server, const char *data);
|
||||
/* returns all nick flag characters in order op, voice, halfop. If some
|
||||
of them aren't supported '\0' can be used. */
|
||||
const char *(*get_nick_flags)(void);
|
||||
const char *(*get_nick_flags)(SERVER_REC *server);
|
||||
/* send public or private message to server */
|
||||
void (*send_message)(SERVER_REC *server, const char *target,
|
||||
const char *msg, int target_type);
|
||||
|
@ -118,6 +118,7 @@ static void cmd_upgrade(const char *data)
|
||||
static void session_save_nick(CHANNEL_REC *channel, NICK_REC *nick,
|
||||
CONFIG_REC *config, CONFIG_NODE *node)
|
||||
{
|
||||
static char other[2];
|
||||
node = config_node_section(node, NULL, NODE_TYPE_BLOCK);
|
||||
|
||||
config_node_set_str(config, node, "nick", nick->nick);
|
||||
@ -125,6 +126,10 @@ static void session_save_nick(CHANNEL_REC *channel, NICK_REC *nick,
|
||||
config_node_set_bool(config, node, "halfop", nick->halfop);
|
||||
config_node_set_bool(config, node, "voice", nick->voice);
|
||||
|
||||
other[0] = nick->other;
|
||||
other[1] = '\0';
|
||||
config_node_set_str(config, node, "other", other);
|
||||
|
||||
signal_emit("session save nick", 4, channel, nick, config, node);
|
||||
}
|
||||
|
||||
|
@ -399,7 +399,9 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist)
|
||||
for (tmp = nicklist; tmp != NULL; tmp = tmp->next) {
|
||||
NICK_REC *rec = tmp->data;
|
||||
|
||||
if (rec->op)
|
||||
if (rec->other)
|
||||
nickmode[0] = rec->other;
|
||||
else if (rec->op)
|
||||
nickmode[0] = '@';
|
||||
else if (rec->halfop)
|
||||
nickmode[0] = '%';
|
||||
|
@ -116,12 +116,19 @@ char *expand_emphasis(WI_ITEM_REC *item, const char *text)
|
||||
static char *channel_get_nickmode_rec(NICK_REC *nickrec)
|
||||
{
|
||||
char *emptystr;
|
||||
static char nickmode[2]; /* FIXME: bad */
|
||||
|
||||
if (!settings_get_bool("show_nickmode"))
|
||||
return "";
|
||||
|
||||
emptystr = settings_get_bool("show_nickmode_empty") ? " " : "";
|
||||
|
||||
if (nickrec != NULL && nickrec->other) {
|
||||
nickmode[0] = nickrec->other;
|
||||
nickmode[1] = '\0';
|
||||
return nickmode;
|
||||
}
|
||||
|
||||
return nickrec == NULL ? emptystr :
|
||||
nickrec->op ? "@" :
|
||||
nickrec->halfop ? "%" :
|
||||
|
@ -945,6 +945,7 @@ void fe_events_numeric_init(void)
|
||||
signal_add("default event numeric", (SIGNAL_FUNC) event_numeric);
|
||||
signal_add("event 001", (SIGNAL_FUNC) event_received);
|
||||
signal_add("event 004", (SIGNAL_FUNC) event_received);
|
||||
signal_add("event 005", (SIGNAL_FUNC) event_received);
|
||||
signal_add("event 254", (SIGNAL_FUNC) event_received);
|
||||
signal_add("event 364", (SIGNAL_FUNC) event_received);
|
||||
signal_add("event 365", (SIGNAL_FUNC) event_received);
|
||||
@ -1033,6 +1034,7 @@ void fe_events_numeric_deinit(void)
|
||||
signal_remove("default event numeric", (SIGNAL_FUNC) event_numeric);
|
||||
signal_remove("event 001", (SIGNAL_FUNC) event_received);
|
||||
signal_remove("event 004", (SIGNAL_FUNC) event_received);
|
||||
signal_remove("event 005", (SIGNAL_FUNC) event_received);
|
||||
signal_remove("event 254", (SIGNAL_FUNC) event_received);
|
||||
signal_remove("event 364", (SIGNAL_FUNC) event_received);
|
||||
signal_remove("event 365", (SIGNAL_FUNC) event_received);
|
||||
|
@ -387,7 +387,7 @@ static void msg_mode(IRC_SERVER_REC *server, const char *channel,
|
||||
show = TRUE;
|
||||
nick++;
|
||||
} else {
|
||||
if (HAS_MODE_ARG(type, *mode) && *nick != NULL)
|
||||
if (HAS_MODE_ARG(server, type, *mode) && *nick != NULL)
|
||||
nick++;
|
||||
show = TRUE;
|
||||
}
|
||||
|
@ -623,9 +623,15 @@ static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item
|
||||
chanrec = irc_channel_find(server, channame);
|
||||
if (chanrec == NULL) cmd_param_error(CMDERR_CHAN_NOT_FOUND);
|
||||
|
||||
/* send notice to all ops */
|
||||
/* See if the server has advertised support of wallchops */
|
||||
if (g_hash_table_lookup(chanrec->server->isupport, "statusmsg") ||
|
||||
g_hash_table_lookup(chanrec->server->isupport, "wallchops"))
|
||||
irc_send_cmdv(server, "NOTICE @%s :%s", chanrec->name, msg);
|
||||
else {
|
||||
/* Fall back to manually noticing each op */
|
||||
nicks = NULL;
|
||||
g_hash_table_foreach(chanrec->nicks, (GHFunc) cmd_wall_hash, &nicks);
|
||||
g_hash_table_foreach(chanrec->nicks,
|
||||
(GHFunc) cmd_wall_hash, &nicks);
|
||||
|
||||
args = g_strconcat(chanrec->name, " ", msg, NULL);
|
||||
msg = parse_special_string(settings_get_str("wall_format"),
|
||||
@ -635,16 +641,21 @@ static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item
|
||||
for (tmp = nicks; tmp != NULL; tmp = tmp->next) {
|
||||
NICK_REC *rec = tmp->data;
|
||||
|
||||
if (rec != chanrec->ownnick)
|
||||
irc_send_cmdv(server, "NOTICE %s :%s", rec->nick, msg);
|
||||
if (rec != chanrec->ownnick) {
|
||||
irc_send_cmdv(server, "NOTICE %s :%s",
|
||||
rec->nick, msg);
|
||||
}
|
||||
}
|
||||
g_free(msg);
|
||||
g_slist_free(nicks);
|
||||
}
|
||||
|
||||
cmd_params_free(free_arg);
|
||||
}
|
||||
|
||||
/* SYNTAX: WALLCHOPS <channel> <message> */
|
||||
/* ircu is the only major server i can see which supports this
|
||||
and it supports NOTICE @#channel anyway */
|
||||
static void cmd_wallchops(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item)
|
||||
{
|
||||
char *channame, *msg;
|
||||
|
@ -82,10 +82,19 @@ static char *expando_usermode(SERVER_REC *server, void *item, int *free_ret)
|
||||
return IS_IRC_SERVER(server) ? IRC_SERVER(server)->usermode : "";
|
||||
}
|
||||
|
||||
/* expands to your usermode on channel, op '@', halfop '%', "+" voice */
|
||||
/* expands to your usermode on channel, op '@', halfop '%', "+" voice or other */
|
||||
static char *expando_cumode(SERVER_REC *server, void *item, int *free_ret)
|
||||
{
|
||||
if (IS_IRC_CHANNEL(item) && CHANNEL(item)->ownnick) {
|
||||
char other = NICK(CHANNEL(item)->ownnick)->other;
|
||||
if (other != '\0') {
|
||||
char *cumode = g_malloc(2);
|
||||
cumode[0] = other;
|
||||
cumode[1] = '\0';
|
||||
*free_ret = TRUE;
|
||||
return cumode;
|
||||
}
|
||||
|
||||
return NICK(CHANNEL(item)->ownnick)->op ? "@" :
|
||||
NICK(CHANNEL(item)->ownnick)->halfop ? "%" :
|
||||
NICK(CHANNEL(item)->ownnick)->voice ? "+" : "";
|
||||
|
@ -74,11 +74,32 @@ char *irc_nick_strip(const char *nick)
|
||||
return stripped;
|
||||
}
|
||||
|
||||
int irc_nickcmp_rfc1459(const char *m, const char *n)
|
||||
{
|
||||
while (*m != '\0' && *n != '\0') {
|
||||
if (to_rfc1459(*m) != to_rfc1459(*n))
|
||||
return -1;
|
||||
m++; n++;
|
||||
}
|
||||
return *m == *n ? 0 : 1;
|
||||
}
|
||||
|
||||
int irc_nickcmp_ascii(const char *m, const char *n)
|
||||
{
|
||||
while (*m != '\0' && *n != '\0') {
|
||||
if (to_ascii(*m) != to_ascii(*n))
|
||||
return -1;
|
||||
m++; n++;
|
||||
}
|
||||
return *m == *n ? 0 : 1;
|
||||
}
|
||||
|
||||
static void event_names_list(IRC_SERVER_REC *server, const char *data)
|
||||
{
|
||||
IRC_CHANNEL_REC *chanrec;
|
||||
NICK_REC *rec;
|
||||
char *params, *type, *channel, *names, *ptr;
|
||||
int op, halfop, voice;
|
||||
int op, halfop, voice, other;
|
||||
|
||||
g_return_if_fail(data != NULL);
|
||||
|
||||
@ -117,8 +138,8 @@ static void event_names_list(IRC_SERVER_REC *server, const char *data)
|
||||
showing "@+nick" and since none of these chars are valid
|
||||
nick chars, just check them until a non-nickflag char is
|
||||
found. FIXME: we just ignore owner char now. */
|
||||
op = halfop = voice = FALSE;
|
||||
while (isnickflag(*ptr)) {
|
||||
op = halfop = voice = other = FALSE;
|
||||
while (isnickflag(server, *ptr)) {
|
||||
switch (*ptr) {
|
||||
case '@':
|
||||
op = TRUE;
|
||||
@ -129,13 +150,17 @@ static void event_names_list(IRC_SERVER_REC *server, const char *data)
|
||||
case '+':
|
||||
voice = TRUE;
|
||||
break;
|
||||
default:
|
||||
other = *ptr;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
|
||||
if (nicklist_find((CHANNEL_REC *) chanrec, ptr) == NULL) {
|
||||
irc_nicklist_insert(chanrec, ptr, op, halfop,
|
||||
rec = irc_nicklist_insert(chanrec, ptr, op, halfop,
|
||||
voice, FALSE);
|
||||
if (other)
|
||||
rec->other = other;
|
||||
}
|
||||
}
|
||||
|
||||
@ -376,17 +401,24 @@ static void sig_usermode(SERVER_REC *server)
|
||||
nicklist_update_flags(server, server->nick, server->usermode_away, -1);
|
||||
}
|
||||
|
||||
static const char *get_nick_flags(void)
|
||||
static const char *get_nick_flags(SERVER_REC *server)
|
||||
{
|
||||
return "@+%";
|
||||
IRC_SERVER_REC *irc_server = (IRC_SERVER_REC *) server;
|
||||
static char *std = "@%+";
|
||||
char *prefix = g_hash_table_lookup(irc_server->isupport, "prefix");
|
||||
|
||||
if (prefix == NULL)
|
||||
return std;
|
||||
prefix = strchr(prefix, ')');
|
||||
if (prefix != NULL || *++prefix == '\0') /* FIXME: ugly to modify it */
|
||||
return std;
|
||||
return prefix;
|
||||
}
|
||||
|
||||
static void sig_connected(IRC_SERVER_REC *server)
|
||||
{
|
||||
if (IS_IRC_SERVER(server)) {
|
||||
server->get_nick_flags =
|
||||
(const char *(*)(void)) get_nick_flags;
|
||||
}
|
||||
if (IS_IRC_SERVER(server))
|
||||
server->get_nick_flags = get_nick_flags;
|
||||
}
|
||||
|
||||
void irc_nicklist_init(void)
|
||||
|
@ -10,7 +10,14 @@ NICK_REC *irc_nicklist_insert(IRC_CHANNEL_REC *channel, const char *nick,
|
||||
/* Remove all "extra" characters from `nick'. Like _nick_ -> nick */
|
||||
char *irc_nick_strip(const char *nick);
|
||||
|
||||
int irc_nickcmp_rfc1459(const char *, const char *);
|
||||
int irc_nickcmp_ascii(const char *, const char *);
|
||||
|
||||
void irc_nicklist_init(void);
|
||||
void irc_nicklist_deinit(void);
|
||||
|
||||
/* FIXME: to_rfc1459() is missing things */
|
||||
#define to_rfc1459(x) ((x) >= 65 && (x) <= 94 ? (x) + 32 : (x))
|
||||
#define to_ascii(x) ((x) >= 65 && (x) <= 94 ? (x) + 32 : (x))
|
||||
|
||||
#endif
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "signals.h"
|
||||
#include "misc.h"
|
||||
|
||||
#include "irc-nicklist.h"
|
||||
#include "irc-servers.h"
|
||||
#include "irc-queries.h"
|
||||
|
||||
@ -40,6 +41,20 @@ QUERY_REC *irc_query_create(const char *server_tag,
|
||||
return rec;
|
||||
}
|
||||
|
||||
QUERY_REC *irc_query_find(IRC_SERVER_REC *server, const char *nick)
|
||||
{
|
||||
GSList *tmp;
|
||||
|
||||
for (tmp = server->queries; tmp != NULL; tmp = tmp->next) {
|
||||
QUERY_REC *rec = tmp->data;
|
||||
|
||||
if (server->nick_comp_func(rec->name, nick) == 0)
|
||||
return rec;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void check_query_changes(IRC_SERVER_REC *server, const char *nick,
|
||||
const char *address, const char *target)
|
||||
{
|
||||
|
@ -14,8 +14,7 @@
|
||||
void irc_queries_init(void);
|
||||
void irc_queries_deinit(void);
|
||||
|
||||
#define irc_query_find(server, name) \
|
||||
query_find(SERVER(server), name)
|
||||
QUERY_REC *irc_query_find(IRC_SERVER_REC *server, const char *nick);
|
||||
|
||||
QUERY_REC *irc_query_create(const char *server_tag,
|
||||
const char *nick, int automatic);
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include "channels.h"
|
||||
#include "queries.h"
|
||||
|
||||
#include "irc-nicklist.h"
|
||||
#include "irc-queries.h"
|
||||
#include "irc-servers-setup.h"
|
||||
#include "irc-servers.h"
|
||||
#include "channel-rejoin.h"
|
||||
@ -55,9 +57,11 @@ void irc_servers_reconnect_deinit(void);
|
||||
|
||||
static int cmd_tag;
|
||||
|
||||
static int isnickflag_func(char flag)
|
||||
static int isnickflag_func(SERVER_REC *server, char flag)
|
||||
{
|
||||
return isnickflag(flag);
|
||||
IRC_SERVER_REC *irc_server = (IRC_SERVER_REC *) server;
|
||||
|
||||
return isnickflag(irc_server, flag);
|
||||
}
|
||||
|
||||
static int ischannel_func(SERVER_REC *server, const char *data)
|
||||
@ -157,6 +161,9 @@ static void server_init(IRC_SERVER_REC *server)
|
||||
conn->address, conn->port);
|
||||
}
|
||||
|
||||
server->isupport = g_hash_table_new((GHashFunc) g_istr_hash,
|
||||
(GCompareFunc) g_istr_equal);
|
||||
|
||||
server->cmdcount = 0;
|
||||
}
|
||||
|
||||
@ -198,6 +205,8 @@ SERVER_REC *irc_server_init_connect(SERVER_CONNECT_REC *conn)
|
||||
ircconn->max_msgs : DEFAULT_MAX_MSGS;
|
||||
server->connrec->use_ssl = conn->use_ssl;
|
||||
|
||||
modes_server_init(server);
|
||||
|
||||
server_connect_init((SERVER_REC *) server);
|
||||
return (SERVER_REC *) server;
|
||||
}
|
||||
@ -268,6 +277,9 @@ static void sig_connected(IRC_SERVER_REC *server)
|
||||
server->isnickflag = isnickflag_func;
|
||||
server->ischannel = ischannel_func;
|
||||
server->send_message = send_message;
|
||||
server->query_find_func =
|
||||
(QUERY_REC *(*)(SERVER_REC *, const char *)) irc_query_find;
|
||||
server->nick_comp_func = irc_nickcmp_ascii;
|
||||
|
||||
server->splits = g_hash_table_new((GHashFunc) g_istr_hash,
|
||||
(GCompareFunc) g_istr_equal);
|
||||
@ -276,6 +288,12 @@ static void sig_connected(IRC_SERVER_REC *server)
|
||||
server_init(server);
|
||||
}
|
||||
|
||||
static void isupport_destroy_hash(void *key, void *value)
|
||||
{
|
||||
g_free(key);
|
||||
g_free(value);
|
||||
}
|
||||
|
||||
static void sig_disconnected(IRC_SERVER_REC *server)
|
||||
{
|
||||
GSList *tmp;
|
||||
@ -291,6 +309,10 @@ static void sig_disconnected(IRC_SERVER_REC *server)
|
||||
g_slist_free(server->cmdqueue);
|
||||
server->cmdqueue = NULL;
|
||||
|
||||
g_hash_table_foreach(server->isupport, (GHFunc) isupport_destroy_hash, server);
|
||||
g_hash_table_destroy(server->isupport);
|
||||
server->isupport = NULL;
|
||||
|
||||
g_free_and_null(server->wanted_usermode);
|
||||
g_free_and_null(server->real_address);
|
||||
g_free_and_null(server->usermode);
|
||||
@ -452,7 +474,7 @@ static int sig_set_user_mode(IRC_SERVER_REC *server)
|
||||
|
||||
mode = server->connrec->usermode;
|
||||
newmode = server->usermode == NULL ? NULL :
|
||||
modes_join(server->usermode, mode, FALSE);
|
||||
modes_join(NULL, server->usermode, mode, FALSE);
|
||||
|
||||
if (newmode == NULL || strcmp(newmode, server->usermode) != 0) {
|
||||
/* change the user mode. we used to do some trickery to
|
||||
@ -521,6 +543,123 @@ static void event_server_info(IRC_SERVER_REC *server, const char *data)
|
||||
g_free(params);
|
||||
}
|
||||
|
||||
static void parse_chanmodes(IRC_SERVER_REC *server, const char *sptr)
|
||||
{
|
||||
mode_func_t *modefuncs[] = {
|
||||
modes_type_a,
|
||||
modes_type_b,
|
||||
modes_type_c,
|
||||
modes_type_d
|
||||
};
|
||||
char **item, **chanmodes;
|
||||
int i;
|
||||
|
||||
chanmodes = g_strsplit(sptr, ",", 5); /* ignore extras */
|
||||
|
||||
for (i = 0, item = chanmodes; *item != NULL && i < 4; item++, i++) {
|
||||
unsigned char *p = *item;
|
||||
while (*p != '\0') {
|
||||
server->modes[(int)*p].func = modefuncs[i];
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
g_strfreev(chanmodes);
|
||||
}
|
||||
|
||||
static void parse_prefix(IRC_SERVER_REC *server, const char *sptr)
|
||||
{
|
||||
const char *eptr;
|
||||
|
||||
if (*sptr++ != '(')
|
||||
return; /* Unknown prefix format */
|
||||
|
||||
eptr = strchr(sptr, ')');
|
||||
if (eptr == NULL)
|
||||
return;
|
||||
|
||||
eptr++;
|
||||
while (*sptr != '\0' && *eptr != '\0' && *sptr != ')' && *eptr != ' ') {
|
||||
server->modes[(int)(unsigned char) *sptr].func =
|
||||
modes_type_prefix;
|
||||
server->modes[(int)(unsigned char) *sptr].prefix = *eptr;
|
||||
server->prefix[(int)(unsigned char) *eptr] = *sptr;
|
||||
sptr++; eptr++;
|
||||
}
|
||||
}
|
||||
|
||||
static void event_isupport(IRC_SERVER_REC *server, const char *data)
|
||||
{
|
||||
char **item, *sptr, *eptr;
|
||||
char **isupport;
|
||||
|
||||
g_return_if_fail(server != NULL);
|
||||
|
||||
server->isupport_sent = TRUE;
|
||||
|
||||
sptr = strchr(data, ' ');
|
||||
if (sptr == NULL)
|
||||
return;
|
||||
sptr++;
|
||||
|
||||
isupport = g_strsplit(sptr, " ", -1);
|
||||
|
||||
for(item = isupport; *item != NULL; item++) {
|
||||
int removed = FALSE;
|
||||
gpointer key = NULL, value = NULL;
|
||||
|
||||
if (**item == ':')
|
||||
break;
|
||||
|
||||
sptr = strchr(*item, '=');
|
||||
if (sptr != NULL) {
|
||||
*sptr = '\0';
|
||||
sptr++;
|
||||
}
|
||||
|
||||
eptr = *item;
|
||||
if(*eptr == '-') {
|
||||
removed = TRUE;
|
||||
eptr++;
|
||||
}
|
||||
|
||||
if (!g_hash_table_lookup_extended(server->isupport, eptr,
|
||||
&key, &value) && removed)
|
||||
continue;
|
||||
|
||||
if (removed)
|
||||
g_hash_table_remove(server->isupport, eptr);
|
||||
else {
|
||||
g_hash_table_insert(server->isupport, g_strdup(eptr),
|
||||
g_strdup(sptr != NULL ? sptr : ""));
|
||||
}
|
||||
|
||||
g_free(key);
|
||||
g_free(value);
|
||||
}
|
||||
g_strfreev(isupport);
|
||||
|
||||
if ((sptr = g_hash_table_lookup(server->isupport, "CHANMODES")))
|
||||
parse_chanmodes(server, sptr);
|
||||
|
||||
/* This is after chanmode because some servers define modes in both */
|
||||
if ((sptr = g_hash_table_lookup(server->isupport, "PREFIX")))
|
||||
parse_prefix(server, sptr);
|
||||
|
||||
if ((sptr = g_hash_table_lookup(server->isupport, "MODES"))) {
|
||||
server->max_modes_in_cmd = atoi(sptr);
|
||||
if (server->max_modes_in_cmd < 1)
|
||||
server->max_modes_in_cmd = DEFAULT_MAX_MODES;
|
||||
}
|
||||
|
||||
if ((sptr = g_hash_table_lookup(server->isupport, "CASEMAPPING"))) {
|
||||
if (strstr(sptr, "rfc1459") != NULL)
|
||||
server->nick_comp_func = irc_nickcmp_rfc1459;
|
||||
else
|
||||
server->nick_comp_func = irc_nickcmp_ascii;
|
||||
}
|
||||
}
|
||||
|
||||
static void event_motd(IRC_SERVER_REC *server, const char *data, const char *from)
|
||||
{
|
||||
if (server->connected)
|
||||
@ -599,6 +738,7 @@ void irc_servers_init(void)
|
||||
signal_add_last("server quit", (SIGNAL_FUNC) sig_server_quit);
|
||||
signal_add("event 001", (SIGNAL_FUNC) event_connected);
|
||||
signal_add("event 004", (SIGNAL_FUNC) event_server_info);
|
||||
signal_add("event 005", (SIGNAL_FUNC) event_isupport);
|
||||
signal_add("event 375", (SIGNAL_FUNC) event_motd);
|
||||
signal_add_last("event 376", (SIGNAL_FUNC) event_end_of_motd);
|
||||
signal_add_last("event 422", (SIGNAL_FUNC) event_end_of_motd); /* no motd */
|
||||
@ -623,6 +763,7 @@ void irc_servers_deinit(void)
|
||||
signal_remove("server quit", (SIGNAL_FUNC) sig_server_quit);
|
||||
signal_remove("event 001", (SIGNAL_FUNC) event_connected);
|
||||
signal_remove("event 004", (SIGNAL_FUNC) event_server_info);
|
||||
signal_remove("event 005", (SIGNAL_FUNC) event_isupport);
|
||||
signal_remove("event 375", (SIGNAL_FUNC) event_motd);
|
||||
signal_remove("event 376", (SIGNAL_FUNC) event_end_of_motd);
|
||||
signal_remove("event 422", (SIGNAL_FUNC) event_end_of_motd); /* no motd */
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "chat-protocols.h"
|
||||
#include "servers.h"
|
||||
#include "modes.h"
|
||||
|
||||
/* returns IRC_SERVER_REC if it's IRC server, NULL if it isn't */
|
||||
#define IRC_SERVER(server) \
|
||||
@ -61,6 +62,7 @@ struct _IRC_SERVER_REC {
|
||||
unsigned int disable_lag:1; /* Disable lag detection (PING command doesn't exist) */
|
||||
unsigned int nick_collision:1; /* We're just now being killed because of nick collision */
|
||||
unsigned int motd_got:1; /* We've received MOTD */
|
||||
unsigned int isupport_sent:1; /* Server has sent us an isupport reply */
|
||||
|
||||
int max_kicks_in_cmd; /* max. number of people to kick with one /KICK command */
|
||||
int max_modes_in_cmd; /* max. number of mode changes in one /MODE command */
|
||||
@ -96,6 +98,12 @@ struct _IRC_SERVER_REC {
|
||||
channels go here if they're "temporarily unavailable"
|
||||
because of netsplits */
|
||||
void *chanqueries;
|
||||
|
||||
GHashTable *isupport;
|
||||
struct modes_type modes[256]; /* Stores the modes sent by a server in an isupport reply */
|
||||
char prefix[256];
|
||||
|
||||
int (*nick_comp_func)(const char *, const char *); /* Function for comparing nicknames on this server */
|
||||
};
|
||||
|
||||
SERVER_REC *irc_server_init_connect(SERVER_CONNECT_REC *conn);
|
||||
|
@ -22,15 +22,25 @@
|
||||
#include "signals.h"
|
||||
#include "net-sendbuffer.h"
|
||||
#include "lib-config/iconfig.h"
|
||||
#include "misc.h"
|
||||
|
||||
#include "irc-servers.h"
|
||||
#include "irc-channels.h"
|
||||
#include "irc-nicklist.h"
|
||||
|
||||
struct _isupport_data { CONFIG_REC *config; CONFIG_NODE *node; };
|
||||
|
||||
static void session_isupport_foreach(char *key, char *value, struct _isupport_data *data)
|
||||
{
|
||||
config_node_set_str(data->config, data->node, key, value);
|
||||
}
|
||||
|
||||
static void sig_session_save_server(IRC_SERVER_REC *server, CONFIG_REC *config,
|
||||
CONFIG_NODE *node)
|
||||
{
|
||||
GSList *tmp;
|
||||
CONFIG_NODE *isupport;
|
||||
struct _isupport_data isupport_data;
|
||||
|
||||
if (!IS_IRC_SERVER(server))
|
||||
return;
|
||||
@ -54,11 +64,19 @@ static void sig_session_save_server(IRC_SERVER_REC *server, CONFIG_REC *config,
|
||||
config_node_set_bool(config, node, "usermode_away", server->usermode_away);
|
||||
config_node_set_str(config, node, "away_reason", server->away_reason);
|
||||
config_node_set_bool(config, node, "emode_known", server->emode_known);
|
||||
|
||||
isupport = config_node_section(node, "isupport", NODE_TYPE_BLOCK);
|
||||
isupport_data.config = config;
|
||||
isupport_data.node = isupport;
|
||||
|
||||
g_hash_table_foreach(server->isupport, (GHFunc) session_isupport_foreach, &isupport_data);
|
||||
}
|
||||
|
||||
static void sig_session_restore_server(IRC_SERVER_REC *server,
|
||||
CONFIG_NODE *node)
|
||||
{
|
||||
GSList *tmp;
|
||||
|
||||
if (!IS_IRC_SERVER(server))
|
||||
return;
|
||||
|
||||
@ -69,12 +87,33 @@ static void sig_session_restore_server(IRC_SERVER_REC *server,
|
||||
server->usermode_away = config_node_get_bool(node, "usermode_away", FALSE);
|
||||
server->away_reason = g_strdup(config_node_get_str(node, "away_reason", NULL));
|
||||
server->emode_known = config_node_get_bool(node, "emode_known", FALSE);
|
||||
|
||||
if (server->isupport == NULL) {
|
||||
server->isupport = g_hash_table_new((GHashFunc) g_istr_hash,
|
||||
(GCompareFunc) g_istr_equal);
|
||||
}
|
||||
|
||||
node = config_node_section(node, "isupport", -1);
|
||||
tmp = config_node_first(node->value);
|
||||
if(tmp != NULL)
|
||||
server->isupport_sent = TRUE;
|
||||
|
||||
for (; tmp != NULL; tmp = config_node_next(tmp)) {
|
||||
node = tmp->data;
|
||||
if (node == NULL)
|
||||
break;
|
||||
|
||||
g_hash_table_insert(server->isupport, g_strdup(node->key),
|
||||
g_strdup(node->value));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void sig_session_restore_nick(IRC_CHANNEL_REC *channel,
|
||||
CONFIG_NODE *node)
|
||||
{
|
||||
const char *nick;
|
||||
char *other;
|
||||
int op, halfop, voice;
|
||||
NICK_REC *nickrec;
|
||||
|
||||
@ -89,6 +128,8 @@ static void sig_session_restore_nick(IRC_CHANNEL_REC *channel,
|
||||
voice = config_node_get_bool(node, "voice", FALSE);
|
||||
halfop = config_node_get_bool(node, "halfop", FALSE);
|
||||
nickrec = irc_nicklist_insert(channel, nick, op, halfop, voice, FALSE);
|
||||
other = config_node_get_str(node, "other", FALSE);
|
||||
nickrec->other = other[0];
|
||||
}
|
||||
|
||||
static void session_restore_channel(IRC_CHANNEL_REC *channel)
|
||||
|
@ -19,9 +19,8 @@ typedef struct _REDIRECT_REC REDIRECT_REC;
|
||||
((a) == '^' || (a) == '~' || \
|
||||
(a) == '+' || (a) == '=' || (a) == '-')
|
||||
|
||||
#define isnickflag(a) \
|
||||
((a) == '@' || (a) == '+' || (a) == '%' || /* op / voice */ \
|
||||
(a) == '%' || (a) == '.' || (a) == '!') /* extensions: half-op / owners */
|
||||
#define isnickflag(server, a) \
|
||||
(server->prefix[(int)(unsigned char) a] != '\0')
|
||||
|
||||
#define ischannel(a) \
|
||||
((a) == '#' || /* normal */ \
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
/* Change nick's mode in channel */
|
||||
static void nick_mode_change(IRC_CHANNEL_REC *channel, const char *nick,
|
||||
const char mode, int type, const char *setby)
|
||||
char mode, int type, const char *setby)
|
||||
{
|
||||
NICK_REC *nickrec;
|
||||
char modestr[2], typestr[2];
|
||||
@ -44,8 +44,10 @@ static void nick_mode_change(IRC_CHANNEL_REC *channel, const char *nick,
|
||||
if (nickrec == NULL) return; /* No /names list got yet */
|
||||
|
||||
if (mode == '@') nickrec->op = type == '+';
|
||||
if (mode == '+') nickrec->voice = type == '+';
|
||||
if (mode == '%') nickrec->halfop = type == '+';
|
||||
else if (mode == '+') nickrec->voice = type == '+';
|
||||
else if (mode == '%') nickrec->halfop = type == '+';
|
||||
else if (channel->server->prefix[(unsigned char) mode] != '\0')
|
||||
nickrec->other = (type == '+' ? mode : '\0');
|
||||
|
||||
modestr[0] = mode; modestr[1] = '\0';
|
||||
typestr[0] = type; typestr[1] = '\0';
|
||||
@ -97,13 +99,15 @@ static void mode_add_arg(GString *str, int pos, int updating, const char *arg)
|
||||
}
|
||||
|
||||
/* Add mode character to list sorted alphabetically */
|
||||
static void mode_add_sorted(GString *str, char mode, const char *arg)
|
||||
static void mode_add_sorted(IRC_SERVER_REC *server, GString *str,
|
||||
char mode, const char *arg, int user)
|
||||
{
|
||||
char *p;
|
||||
int updating, argpos = 0;
|
||||
|
||||
/* check that mode isn't already set */
|
||||
if (!HAS_MODE_ARG_SET(mode) && mode_is_set(str->str, mode))
|
||||
if ((!user && !HAS_MODE_ARG_SET(server, mode)) &&
|
||||
mode_is_set(str->str, mode))
|
||||
return;
|
||||
|
||||
updating = FALSE;
|
||||
@ -114,7 +118,7 @@ static void mode_add_sorted(GString *str, char mode, const char *arg)
|
||||
updating = TRUE;
|
||||
break;
|
||||
}
|
||||
if (HAS_MODE_ARG_SET(*p))
|
||||
if (!user && HAS_MODE_ARG_SET(server, *p))
|
||||
argpos++;
|
||||
}
|
||||
|
||||
@ -154,7 +158,7 @@ static void node_remove_arg(GString *str, int pos)
|
||||
}
|
||||
|
||||
/* remove mode (and it's argument) from string */
|
||||
static void mode_remove(GString *str, char mode)
|
||||
static void mode_remove(IRC_SERVER_REC *server, GString *str, char mode, int user)
|
||||
{
|
||||
char *p;
|
||||
int argpos = 0;
|
||||
@ -162,34 +166,91 @@ static void mode_remove(GString *str, char mode)
|
||||
for (p = str->str; *p != '\0' && *p != ' '; p++) {
|
||||
if (mode == *p) {
|
||||
g_string_erase(str, (int) (p-str->str), 1);
|
||||
if (HAS_MODE_ARG_SET(mode))
|
||||
if (!user && HAS_MODE_ARG_SET(server, mode))
|
||||
node_remove_arg(str, argpos);
|
||||
break;
|
||||
}
|
||||
if (HAS_MODE_ARG_SET(*p))
|
||||
if (!user && HAS_MODE_ARG_SET(server, *p))
|
||||
argpos++;
|
||||
}
|
||||
}
|
||||
|
||||
static void mode_set(GString *str, char type, char mode)
|
||||
static void mode_set(IRC_SERVER_REC *server, GString *str,
|
||||
char type, char mode, int user)
|
||||
{
|
||||
g_return_if_fail(str != NULL);
|
||||
|
||||
if (type == '-')
|
||||
mode_remove(str, mode);
|
||||
mode_remove(server, str, mode, user);
|
||||
else
|
||||
mode_add_sorted(str, mode, NULL);
|
||||
mode_add_sorted(server, str, mode, NULL, user);
|
||||
}
|
||||
|
||||
static void mode_set_arg(GString *str, char type, char mode, const char *arg)
|
||||
static void mode_set_arg(IRC_SERVER_REC *server, GString *str,
|
||||
char type, char mode, const char *arg)
|
||||
{
|
||||
g_return_if_fail(str != NULL);
|
||||
g_return_if_fail(type == '-' || arg != NULL);
|
||||
|
||||
if (type == '-')
|
||||
mode_remove(str, mode);
|
||||
mode_remove(server, str, mode, TRUE);
|
||||
else
|
||||
mode_add_sorted(str, mode, arg);
|
||||
mode_add_sorted(server, str, mode, arg, TRUE);
|
||||
}
|
||||
|
||||
/* Mode that needs a parameter of a mask for both setting and removing (eg: bans) */
|
||||
void modes_type_a(IRC_CHANNEL_REC *channel, const char *setby, char type,
|
||||
char mode, char *arg, GString *newmode)
|
||||
{
|
||||
/* Currently only +b is dealt with */
|
||||
if (mode == 'b') {
|
||||
if (type == '+')
|
||||
banlist_add(channel, arg, setby, time(NULL));
|
||||
else
|
||||
banlist_remove(channel, arg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Mode that needs parameter for both setting and removing (eg: +k) */
|
||||
void modes_type_b(IRC_CHANNEL_REC *channel, const char *setby, char type,
|
||||
char mode, char *arg, GString *newmode)
|
||||
{
|
||||
if (mode == 'k') {
|
||||
if (*arg == '\0' && type == '+')
|
||||
arg = channel->key != NULL ? channel->key : "???";
|
||||
mode_set_arg(channel->server, newmode, type, 'k', arg);
|
||||
|
||||
if (arg != channel->key) {
|
||||
g_free_and_null(channel->key);
|
||||
if (type == '+')
|
||||
channel->key = g_strdup(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Mode that needs parameter only for adding */
|
||||
void modes_type_c(IRC_CHANNEL_REC *channel, const char *setby,
|
||||
char type, char mode, char *arg, GString *newmode)
|
||||
{
|
||||
if (mode == 'l') {
|
||||
mode_set_arg(channel->server, newmode, type, 'l', arg);
|
||||
channel->limit = type == '-' ? 0 : atoi(arg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Mode that takes no parameter */
|
||||
void modes_type_d(IRC_CHANNEL_REC *channel, const char *setby,
|
||||
char type, char mode, char *arg, GString *newmode)
|
||||
{
|
||||
mode_set(channel->server, newmode, type, mode, FALSE);
|
||||
}
|
||||
|
||||
void modes_type_prefix(IRC_CHANNEL_REC *channel, const char *setby,
|
||||
char type, char mode, char *arg, GString *newmode)
|
||||
{
|
||||
int umode = (unsigned char) mode;
|
||||
nick_mode_change(channel, arg, channel->server->modes[umode].prefix,
|
||||
type, setby);
|
||||
}
|
||||
|
||||
int channel_mode_is_set(IRC_CHANNEL_REC *channel, char mode)
|
||||
@ -204,8 +265,10 @@ int channel_mode_is_set(IRC_CHANNEL_REC *channel, char mode)
|
||||
void parse_channel_modes(IRC_CHANNEL_REC *channel, const char *setby,
|
||||
const char *mode, int update_key)
|
||||
{
|
||||
IRC_SERVER_REC *server = channel->server;
|
||||
GString *newmode;
|
||||
char *dup, *modestr, *arg, *curmode, type;
|
||||
int umode;
|
||||
|
||||
g_return_if_fail(IS_IRC_CHANNEL(channel));
|
||||
g_return_if_fail(mode != NULL);
|
||||
@ -216,7 +279,7 @@ void parse_channel_modes(IRC_CHANNEL_REC *channel, const char *setby,
|
||||
dup = modestr = g_strdup(mode);
|
||||
curmode = cmd_get_param(&modestr);
|
||||
while (*curmode != '\0') {
|
||||
if (HAS_MODE_ARG(type, *curmode)) {
|
||||
if (HAS_MODE_ARG(server, type, *curmode)) {
|
||||
/* get the argument for the mode. NOTE: We don't
|
||||
get the +k's argument when joining to channel. */
|
||||
arg = cmd_get_param(&modestr);
|
||||
@ -229,54 +292,17 @@ void parse_channel_modes(IRC_CHANNEL_REC *channel, const char *setby,
|
||||
case '-':
|
||||
type = *curmode;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
if (type == '+')
|
||||
banlist_add(channel, arg, setby, time(NULL));
|
||||
else
|
||||
banlist_remove(channel, arg);
|
||||
break;
|
||||
case 'o':
|
||||
case 'O': /* channel owner in !channels */
|
||||
if (g_strcasecmp(channel->server->nick, arg) == 0)
|
||||
channel->chanop = type == '+';
|
||||
nick_mode_change(channel, arg, '@', type, setby);
|
||||
break;
|
||||
case 'h':
|
||||
nick_mode_change(channel, arg, '%', type, setby);
|
||||
break;
|
||||
case 'v':
|
||||
nick_mode_change(channel, arg, '+', type, setby);
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
mode_set_arg(newmode, type, 'l', arg);
|
||||
channel->limit = type == '-' ? 0 : atoi(arg);
|
||||
break;
|
||||
case 'k':
|
||||
if ((*arg == '\0' && type == '+') ||
|
||||
(channel->key != NULL && !update_key)) {
|
||||
arg = channel->key != NULL ? channel->key :
|
||||
"???";
|
||||
}
|
||||
mode_set_arg(newmode, type, 'k', arg);
|
||||
|
||||
if (arg != channel->key) {
|
||||
g_free_and_null(channel->key);
|
||||
if (type == '+')
|
||||
channel->key = g_strdup(arg);
|
||||
}
|
||||
break;
|
||||
case 'e':
|
||||
case 'I':
|
||||
case 'q':
|
||||
case 'd':
|
||||
/* Don't set it as channel mode */
|
||||
break;
|
||||
|
||||
default:
|
||||
mode_set(newmode, type, *curmode);
|
||||
break;
|
||||
umode = (unsigned char) *curmode;
|
||||
if (server->modes[umode].func != NULL) {
|
||||
server->modes[umode].func(channel, setby,
|
||||
type, *curmode, arg,
|
||||
newmode);
|
||||
} else {
|
||||
/* Treat unknown modes as ones without params */
|
||||
modes_type_d(channel, setby, type, *curmode,
|
||||
arg, newmode);
|
||||
}
|
||||
}
|
||||
|
||||
curmode++;
|
||||
@ -305,7 +331,8 @@ void parse_channel_modes(IRC_CHANNEL_REC *channel, const char *setby,
|
||||
/* add `mode' to `old' - return newly allocated mode.
|
||||
`channel' specifies if we're parsing channel mode and we should try
|
||||
to join mode arguments too. */
|
||||
char *modes_join(const char *old, const char *mode, int channel)
|
||||
char *modes_join(IRC_SERVER_REC *server, const char *old,
|
||||
const char *mode, int channel)
|
||||
{
|
||||
GString *newmode;
|
||||
char *dup, *modestr, *curmode, type;
|
||||
@ -324,10 +351,10 @@ char *modes_join(const char *old, const char *mode, int channel)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!channel || !HAS_MODE_ARG(type, *curmode))
|
||||
mode_set(newmode, type, *curmode);
|
||||
if (!channel || !HAS_MODE_ARG(server, type, *curmode))
|
||||
mode_set(server, newmode, type, *curmode, !channel);
|
||||
else {
|
||||
mode_set_arg(newmode, type, *curmode,
|
||||
mode_set_arg(server, newmode, type, *curmode,
|
||||
cmd_get_param(&modestr));
|
||||
}
|
||||
|
||||
@ -348,7 +375,7 @@ static void parse_user_mode(IRC_SERVER_REC *server, const char *modestr)
|
||||
g_return_if_fail(IS_IRC_SERVER(server));
|
||||
g_return_if_fail(modestr != NULL);
|
||||
|
||||
newmode = modes_join(server->usermode, modestr, FALSE);
|
||||
newmode = modes_join(NULL, server->usermode, modestr, FALSE);
|
||||
oldmode = server->usermode;
|
||||
server->usermode = newmode;
|
||||
server->server_operator = (strchr(newmode, 'o') != NULL);
|
||||
@ -430,7 +457,7 @@ static void sig_req_usermode_change(IRC_SERVER_REC *server, const char *data,
|
||||
&target, &mode);
|
||||
if (!ischannel(*target)) {
|
||||
/* we requested a user mode change, save this */
|
||||
mode = modes_join(server->wanted_usermode, mode, FALSE);
|
||||
mode = modes_join(NULL, server->wanted_usermode, mode, FALSE);
|
||||
g_free_not_null(server->wanted_usermode);
|
||||
server->wanted_usermode = mode;
|
||||
}
|
||||
@ -520,7 +547,7 @@ void channel_set_mode(IRC_SERVER_REC *server, const char *channel,
|
||||
}
|
||||
|
||||
if (count == server->max_modes_in_cmd &&
|
||||
HAS_MODE_ARG(type, *curmode)) {
|
||||
HAS_MODE_ARG(chanrec->server, type, *curmode)) {
|
||||
irc_send_cmdv(server, "MODE %s %s%s",
|
||||
channel, tmode->str, targs->str);
|
||||
|
||||
@ -535,7 +562,7 @@ void channel_set_mode(IRC_SERVER_REC *server, const char *channel,
|
||||
}
|
||||
g_string_append_c(tmode, *curmode);
|
||||
|
||||
if (HAS_MODE_ARG(type, *curmode)) {
|
||||
if (HAS_MODE_ARG(chanrec->server, type, *curmode)) {
|
||||
char *arg;
|
||||
|
||||
count++;
|
||||
@ -762,6 +789,29 @@ static void cmd_mode(const char *data, IRC_SERVER_REC *server,
|
||||
cmd_params_free(free_arg);
|
||||
}
|
||||
|
||||
void modes_server_init(IRC_SERVER_REC *server)
|
||||
{
|
||||
server->modes['b'].func = modes_type_a;
|
||||
server->modes['e'].func = modes_type_a;
|
||||
server->modes['I'].func = modes_type_a;
|
||||
|
||||
server->modes['h'].func = modes_type_prefix;
|
||||
server->modes['h'].prefix = '%';
|
||||
server->modes['o'].func = modes_type_prefix;
|
||||
server->modes['o'].prefix = '@';
|
||||
server->modes['O'].func = modes_type_prefix;
|
||||
server->modes['O'].prefix = '@';
|
||||
server->modes['v'].func = modes_type_prefix;
|
||||
server->modes['v'].prefix = '+';
|
||||
|
||||
server->prefix['%'] = 'h';
|
||||
server->prefix['@'] = 'o';
|
||||
server->prefix['+'] = 'v';
|
||||
|
||||
server->modes['l'].func = modes_type_b;
|
||||
server->modes['k'].func = modes_type_c;
|
||||
}
|
||||
|
||||
void modes_init(void)
|
||||
{
|
||||
settings_add_str("misc", "opermode", "");
|
||||
|
@ -1,30 +1,43 @@
|
||||
#ifndef __MODES_H
|
||||
#define __MODES_H
|
||||
|
||||
#include "irc-channels.h"
|
||||
|
||||
typedef void mode_func_t(IRC_CHANNEL_REC *, const char *, char, char,
|
||||
char *, GString *);
|
||||
|
||||
struct modes_type {
|
||||
mode_func_t *func;
|
||||
char prefix;
|
||||
};
|
||||
|
||||
/* modes that have argument always */
|
||||
#define HAS_MODE_ARG_ALWAYS(mode) \
|
||||
((mode) == 'b' || (mode) == 'e' || (mode) == 'I' || (mode) == 'q' || \
|
||||
(mode) == 'd' || (mode) == 'o' || (mode) == 'h' || (mode) == 'v' || \
|
||||
(mode) == 'O' || (mode) == 'k' || (mode) == 'f')
|
||||
#define HAS_MODE_ARG_ALWAYS(server, mode) \
|
||||
(server->modes[(int)(unsigned char) mode].func == modes_type_a || \
|
||||
server->modes[(int)(unsigned char) mode].func == modes_type_b || \
|
||||
server->modes[(int)(unsigned char) mode].func == modes_type_prefix)
|
||||
|
||||
/* modes that have argument when being set (+) */
|
||||
#define HAS_MODE_ARG_SET(mode) \
|
||||
(HAS_MODE_ARG_ALWAYS(mode) || (mode) == 'l')
|
||||
#define HAS_MODE_ARG_SET(server, mode) \
|
||||
(HAS_MODE_ARG_ALWAYS(server, mode) || \
|
||||
server->modes[(int)(unsigned char) mode].func == modes_type_c)
|
||||
|
||||
/* modes that have argument when being unset (-) */
|
||||
#define HAS_MODE_ARG_UNSET(mode) \
|
||||
HAS_MODE_ARG_ALWAYS(mode)
|
||||
#define HAS_MODE_ARG_UNSET(server, mode) \
|
||||
HAS_MODE_ARG_ALWAYS(server, mode)
|
||||
|
||||
#define HAS_MODE_ARG(type, mode) \
|
||||
((type) == '+' ? HAS_MODE_ARG_SET(mode) : HAS_MODE_ARG_UNSET(mode))
|
||||
#define HAS_MODE_ARG(server, type, mode) \
|
||||
((type) == '+' ? HAS_MODE_ARG_SET(server,mode) : \
|
||||
HAS_MODE_ARG_UNSET(server, mode))
|
||||
|
||||
void modes_init(void);
|
||||
void modes_deinit(void);
|
||||
void modes_server_init(IRC_SERVER_REC *);
|
||||
|
||||
/* add `mode' to `old' - return newly allocated mode.
|
||||
`channel' specifies if we're parsing channel mode and we should try
|
||||
to join mode arguments too. */
|
||||
char *modes_join(const char *old, const char *mode, int channel);
|
||||
char *modes_join(IRC_SERVER_REC *server, const char *old, const char *mode, int channel);
|
||||
|
||||
int channel_mode_is_set(IRC_CHANNEL_REC *channel, char mode);
|
||||
|
||||
@ -36,4 +49,10 @@ void channel_set_singlemode(IRC_CHANNEL_REC *channel, const char *nicks,
|
||||
void channel_set_mode(IRC_SERVER_REC *server, const char *channel,
|
||||
const char *mode);
|
||||
|
||||
mode_func_t modes_type_a;
|
||||
mode_func_t modes_type_b;
|
||||
mode_func_t modes_type_c;
|
||||
mode_func_t modes_type_d;
|
||||
mode_func_t modes_type_prefix;
|
||||
|
||||
#endif
|
||||
|
@ -135,6 +135,7 @@ static NETSPLIT_REC *netsplit_add(IRC_SERVER_REC *server, const char *nick,
|
||||
splitchan->op = nickrec->op;
|
||||
splitchan->halfop = nickrec->halfop;
|
||||
splitchan->voice = nickrec->voice;
|
||||
splitchan->other = nickrec->other;
|
||||
|
||||
rec->channels = g_slist_append(rec->channels, splitchan);
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ typedef struct {
|
||||
unsigned int op:1;
|
||||
unsigned int halfop:1;
|
||||
unsigned int voice:1;
|
||||
unsigned int other:7;
|
||||
} NETSPLIT_CHAN_REC;
|
||||
|
||||
void netsplit_init(void);
|
||||
|
@ -177,7 +177,9 @@ static void dump_join(IRC_CHANNEL_REC *channel, CLIENT_REC *client)
|
||||
else
|
||||
g_string_append_c(str, ' ');
|
||||
|
||||
if (nick->op)
|
||||
if (nick->other)
|
||||
g_string_append_c(str, nick->other);
|
||||
else if (nick->op)
|
||||
g_string_append_c(str, '@');
|
||||
else if (nick->halfop)
|
||||
g_string_append_c(str, '%');
|
||||
@ -213,8 +215,15 @@ void proxy_client_reset_nick(CLIENT_REC *client)
|
||||
client->nick = g_strdup(client->server->nick);
|
||||
}
|
||||
|
||||
static void proxy_dump_data_005(char *key, char *value, GString *output)
|
||||
{
|
||||
g_string_sprintfa(output, "%s=%s ", key, value);
|
||||
}
|
||||
|
||||
void proxy_dump_data(CLIENT_REC *client)
|
||||
{
|
||||
GString *isupport_out;
|
||||
|
||||
proxy_client_reset_nick(client);
|
||||
|
||||
/* welcome info */
|
||||
@ -225,6 +234,17 @@ void proxy_dump_data(CLIENT_REC *client)
|
||||
proxy_outdata(client, ":%s 004 %s %s %s oirw abiklmnopqstv\n", client->proxy_address, client->nick, client->proxy_address, IRSSI_VERSION);
|
||||
else
|
||||
proxy_outdata(client, ":%s 004 %s %s %s oirw abeIiklmnopqstv\n", client->proxy_address, client->nick, client->proxy_address, IRSSI_VERSION);
|
||||
|
||||
if (client->server->isupport_sent) {
|
||||
isupport_out = g_string_new(NULL);
|
||||
g_string_sprintf(isupport_out, ":%s 005 %s ", client->proxy_address, client->nick);
|
||||
/* FIXME: should be limited to 15 params */
|
||||
g_hash_table_foreach(client->server->isupport, proxy_dump_data_005, isupport_out);
|
||||
g_string_sprintfa(isupport_out, ":are supported by this server\n");
|
||||
proxy_outdata(client, "%s", isupport_out->str);
|
||||
g_string_free(isupport_out, TRUE);
|
||||
}
|
||||
|
||||
proxy_outdata(client, ":%s 251 %s :There are 0 users and 0 invisible on 1 servers\n", client->proxy_address, client->nick);
|
||||
proxy_outdata(client, ":%s 255 %s :I have 0 clients, 0 services and 0 servers\n", client->proxy_address, client->nick);
|
||||
proxy_outdata(client, ":%s 422 %s :MOTD File is missing\n", client->proxy_address, client->nick);
|
||||
|
@ -72,7 +72,7 @@ isnickflag(server, flag)
|
||||
Irssi::Server server
|
||||
char flag
|
||||
CODE:
|
||||
RETVAL = server->isnickflag(flag);
|
||||
RETVAL = server->isnickflag(server, flag);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
@ -89,7 +89,7 @@ char *
|
||||
get_nick_flags(server)
|
||||
Irssi::Server server
|
||||
CODE:
|
||||
RETVAL = (char *) server->get_nick_flags();
|
||||
RETVAL = (char *) server->get_nick_flags(server);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
|
@ -22,6 +22,7 @@ static void perl_irc_server_fill_hash(HV *hv, IRC_SERVER_REC *server)
|
||||
hv_store(hv, "max_msgs_in_cmd", 15, newSViv(server->max_msgs_in_cmd), 0);
|
||||
hv_store(hv, "max_modes_in_cmd", 16, newSViv(server->max_modes_in_cmd), 0);
|
||||
hv_store(hv, "max_whois_in_cmd", 16, newSViv(server->max_whois_in_cmd), 0);
|
||||
hv_store(hv, "isupport_sent", 13, newSViv(server->isupport_sent), 0);
|
||||
}
|
||||
|
||||
static void perl_ban_fill_hash(HV *hv, BAN_REC *ban)
|
||||
|
@ -4,14 +4,15 @@ MODULE = Irssi::Irc::Modes PACKAGE = Irssi::Irc
|
||||
PROTOTYPES: ENABLE
|
||||
|
||||
void
|
||||
modes_join(old, mode, channel)
|
||||
modes_join(server, old, mode, channel)
|
||||
Irssi::Irc::Server server
|
||||
char *old
|
||||
char *mode
|
||||
int channel
|
||||
PREINIT:
|
||||
char *ret;
|
||||
PPCODE:
|
||||
ret = modes_join(old, mode, channel);
|
||||
ret = modes_join(server, old, mode, channel);
|
||||
XPUSHs(sv_2mortal(new_pv(ret)));
|
||||
g_free(ret);
|
||||
|
||||
|
@ -129,3 +129,13 @@ CODE:
|
||||
RETVAL = (char *) server_redirect_peek_signal(server, event, args, &redirection);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
char *
|
||||
server_isupport(server, name)
|
||||
Irssi::Irc::Server server
|
||||
char *name
|
||||
CODE:
|
||||
RETVAL = (char *) g_hash_table_lookup(server->isupport, name);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
|
@ -436,6 +436,7 @@ void perl_nick_fill_hash(HV *hv, NICK_REC *nick)
|
||||
hv_store(hv, "op", 2, newSViv(nick->op), 0);
|
||||
hv_store(hv, "halfop", 6, newSViv(nick->halfop), 0);
|
||||
hv_store(hv, "voice", 5, newSViv(nick->voice), 0);
|
||||
hv_store(hv, "other", 5, newSViv(nick->other), 0);
|
||||
|
||||
hv_store(hv, "last_check", 10, newSViv(nick->last_check), 0);
|
||||
hv_store(hv, "send_massjoin", 13, newSViv(nick->send_massjoin), 0);
|
||||
|
Loading…
Reference in New Issue
Block a user