mirror of
https://github.com/irssi/irssi.git
synced 2024-09-01 04:14:16 -04:00
commit
437accdfa6
2
INSTALL
2
INSTALL
@ -5,7 +5,7 @@
|
|||||||
To compile Irssi you need:
|
To compile Irssi you need:
|
||||||
|
|
||||||
- meson-0.49 build system with ninja-1.5 or greater
|
- meson-0.49 build system with ninja-1.5 or greater
|
||||||
- glib-2.28 or greater
|
- glib-2.32 or greater
|
||||||
- openssl (for ssl support)
|
- openssl (for ssl support)
|
||||||
- perl-5.6 or greater (for Perl support)
|
- perl-5.6 or greater (for Perl support)
|
||||||
- terminfo or ncurses (for text frontend)
|
- terminfo or ncurses (for text frontend)
|
||||||
|
@ -40,7 +40,7 @@ make && sudo make install
|
|||||||
|
|
||||||
### Requirements
|
### Requirements
|
||||||
|
|
||||||
- [glib-2.28](https://wiki.gnome.org/Projects/GLib) or greater
|
- [glib-2.32](https://wiki.gnome.org/Projects/GLib) or greater
|
||||||
- [openssl](https://www.openssl.org/)
|
- [openssl](https://www.openssl.org/)
|
||||||
- [perl-5.6](https://www.perl.org/) or greater (for perl support)
|
- [perl-5.6](https://www.perl.org/) or greater (for perl support)
|
||||||
- terminfo or ncurses (for text frontend)
|
- terminfo or ncurses (for text frontend)
|
||||||
|
@ -273,7 +273,7 @@ for try in 1 2; do
|
|||||||
echo "*** trying without -lgmodule"
|
echo "*** trying without -lgmodule"
|
||||||
glib_modules=
|
glib_modules=
|
||||||
fi
|
fi
|
||||||
AM_PATH_GLIB_2_0(2.28.0,,, $glib_modules)
|
AM_PATH_GLIB_2_0(2.32.0,,, $glib_modules)
|
||||||
if test "$GLIB_LIBS"; then
|
if test "$GLIB_LIBS"; then
|
||||||
if test $glib_modules = gmodule; then
|
if test $glib_modules = gmodule; then
|
||||||
AC_DEFINE(HAVE_GMODULE)
|
AC_DEFINE(HAVE_GMODULE)
|
||||||
|
@ -166,7 +166,7 @@ message('*** Or alternatively install your distribution\'s package')
|
|||||||
message('*** On Debian: sudo apt-get install libglib2.0-dev')
|
message('*** On Debian: sudo apt-get install libglib2.0-dev')
|
||||||
message('*** On Redhat: dnf install glib2-devel')
|
message('*** On Redhat: dnf install glib2-devel')
|
||||||
if not require_glib_internal
|
if not require_glib_internal
|
||||||
glib_dep = dependency('glib-2.0', version : '>=2.28', required : not want_glib_internal, static : want_static_dependency)
|
glib_dep = dependency('glib-2.0', version : '>=2.32', required : not want_glib_internal, static : want_static_dependency)
|
||||||
else
|
else
|
||||||
glib_dep = dependency('', required : false)
|
glib_dep = dependency('', required : false)
|
||||||
endif
|
endif
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#define IRSSI_GLOBAL_CONFIG "irssi.conf" /* config file name in /etc/ */
|
#define IRSSI_GLOBAL_CONFIG "irssi.conf" /* config file name in /etc/ */
|
||||||
#define IRSSI_HOME_CONFIG "config" /* config file name in ~/.irssi/ */
|
#define IRSSI_HOME_CONFIG "config" /* config file name in ~/.irssi/ */
|
||||||
|
|
||||||
#define IRSSI_ABI_VERSION 34
|
#define IRSSI_ABI_VERSION 35
|
||||||
|
|
||||||
#define DEFAULT_SERVER_ADD_PORT 6667
|
#define DEFAULT_SERVER_ADD_PORT 6667
|
||||||
#define DEFAULT_SERVER_ADD_TLS_PORT 6697
|
#define DEFAULT_SERVER_ADD_TLS_PORT 6697
|
||||||
|
@ -724,6 +724,7 @@ void fe_events_numeric_init(void)
|
|||||||
signal_add("event 004", (SIGNAL_FUNC) event_received);
|
signal_add("event 004", (SIGNAL_FUNC) event_received);
|
||||||
signal_add("event 005", (SIGNAL_FUNC) event_received);
|
signal_add("event 005", (SIGNAL_FUNC) event_received);
|
||||||
signal_add("event 254", (SIGNAL_FUNC) event_received);
|
signal_add("event 254", (SIGNAL_FUNC) event_received);
|
||||||
|
signal_add("event 354", (SIGNAL_FUNC) event_received);
|
||||||
signal_add("event 364", (SIGNAL_FUNC) event_received);
|
signal_add("event 364", (SIGNAL_FUNC) event_received);
|
||||||
signal_add("event 365", (SIGNAL_FUNC) event_received);
|
signal_add("event 365", (SIGNAL_FUNC) event_received);
|
||||||
signal_add("event 381", (SIGNAL_FUNC) event_received);
|
signal_add("event 381", (SIGNAL_FUNC) event_received);
|
||||||
@ -814,6 +815,7 @@ void fe_events_numeric_deinit(void)
|
|||||||
signal_remove("event 004", (SIGNAL_FUNC) event_received);
|
signal_remove("event 004", (SIGNAL_FUNC) event_received);
|
||||||
signal_remove("event 005", (SIGNAL_FUNC) event_received);
|
signal_remove("event 005", (SIGNAL_FUNC) event_received);
|
||||||
signal_remove("event 254", (SIGNAL_FUNC) event_received);
|
signal_remove("event 254", (SIGNAL_FUNC) event_received);
|
||||||
|
signal_remove("event 354", (SIGNAL_FUNC) event_received);
|
||||||
signal_remove("event 364", (SIGNAL_FUNC) event_received);
|
signal_remove("event 364", (SIGNAL_FUNC) event_received);
|
||||||
signal_remove("event 365", (SIGNAL_FUNC) event_received);
|
signal_remove("event 365", (SIGNAL_FUNC) event_received);
|
||||||
signal_remove("event 381", (SIGNAL_FUNC) event_received);
|
signal_remove("event 381", (SIGNAL_FUNC) event_received);
|
||||||
|
@ -415,6 +415,7 @@ void fe_whois_init(void)
|
|||||||
signal_add("event 319", (SIGNAL_FUNC) event_whois_channels);
|
signal_add("event 319", (SIGNAL_FUNC) event_whois_channels);
|
||||||
signal_add("event 313", (SIGNAL_FUNC) event_whois_oper);
|
signal_add("event 313", (SIGNAL_FUNC) event_whois_oper);
|
||||||
signal_add("event 330", (SIGNAL_FUNC) event_whois_auth);
|
signal_add("event 330", (SIGNAL_FUNC) event_whois_auth);
|
||||||
|
signal_add("whois account", (SIGNAL_FUNC) event_whois_auth);
|
||||||
signal_add("event 377", (SIGNAL_FUNC) event_whois_usermode);
|
signal_add("event 377", (SIGNAL_FUNC) event_whois_usermode);
|
||||||
signal_add("event 378", (SIGNAL_FUNC) event_whois_realhost);
|
signal_add("event 378", (SIGNAL_FUNC) event_whois_realhost);
|
||||||
signal_add("event 379", (SIGNAL_FUNC) event_whois_modes);
|
signal_add("event 379", (SIGNAL_FUNC) event_whois_modes);
|
||||||
@ -438,6 +439,7 @@ void fe_whois_deinit(void)
|
|||||||
signal_remove("event 319", (SIGNAL_FUNC) event_whois_channels);
|
signal_remove("event 319", (SIGNAL_FUNC) event_whois_channels);
|
||||||
signal_remove("event 313", (SIGNAL_FUNC) event_whois_oper);
|
signal_remove("event 313", (SIGNAL_FUNC) event_whois_oper);
|
||||||
signal_remove("event 330", (SIGNAL_FUNC) event_whois_auth);
|
signal_remove("event 330", (SIGNAL_FUNC) event_whois_auth);
|
||||||
|
signal_remove("whois account", (SIGNAL_FUNC) event_whois_auth);
|
||||||
signal_remove("event 377", (SIGNAL_FUNC) event_whois_usermode);
|
signal_remove("event 377", (SIGNAL_FUNC) event_whois_usermode);
|
||||||
signal_remove("event 378", (SIGNAL_FUNC) event_whois_realhost);
|
signal_remove("event 378", (SIGNAL_FUNC) event_whois_realhost);
|
||||||
signal_remove("event 379", (SIGNAL_FUNC) event_whois_modes);
|
signal_remove("event 379", (SIGNAL_FUNC) event_whois_modes);
|
||||||
|
@ -50,22 +50,21 @@ loop:
|
|||||||
#include <irssi/src/irc/core/irc-channels.h>
|
#include <irssi/src/irc/core/irc-channels.h>
|
||||||
#include <irssi/src/irc/core/servers-redirect.h>
|
#include <irssi/src/irc/core/servers-redirect.h>
|
||||||
|
|
||||||
enum {
|
/* here are the WHOX commands we send. the full spec can be found on [1].
|
||||||
CHANNEL_QUERY_MODE,
|
|
||||||
CHANNEL_QUERY_WHO,
|
|
||||||
CHANNEL_QUERY_BMODE,
|
|
||||||
|
|
||||||
CHANNEL_QUERIES
|
(1) WHOX_CHANNEL_FULL_CMD for getting the user list when we join a channel. we request the fields
|
||||||
};
|
c (channel), u (user), h (host), n (nick), f (flags), d (hops), a (important, account!), and
|
||||||
|
r (the real name goes last because it os the only that can contain spaces.) we request all
|
||||||
|
those fields as they are also included in the "regular" WHO reply we would get without WHOX.
|
||||||
|
|
||||||
#define CHANNEL_IS_MODE_QUERY(a) ((a) != CHANNEL_QUERY_WHO)
|
(2) WHOX_USERACCOUNT_CMD for getting the account names of people that joined. this code is
|
||||||
|
obviously only used when we don't have extended-joins. we request n (nick) and a (account)
|
||||||
|
only, and we only send WHO nick with this command.
|
||||||
|
|
||||||
typedef struct {
|
[1] https://github.com/UndernetIRC/ircu2/blob/u2_10_12_branch/doc/readme.who
|
||||||
int current_query_type; /* query type that is currently being asked */
|
*/
|
||||||
GSList *current_queries; /* All channels that are currently being queried */
|
#define WHOX_CHANNEL_FULL_CMD "WHO %s %%tcuhnfdar," WHOX_CHANNEL_FULL_ID
|
||||||
|
#define WHOX_USERACCOUNT_CMD "WHO %s %%tna," WHOX_USERACCOUNT_ID
|
||||||
GSList *queries[CHANNEL_QUERIES]; /* All queries that need to be asked from server */
|
|
||||||
} SERVER_QUERY_REC;
|
|
||||||
|
|
||||||
static void sig_connected(IRC_SERVER_REC *server)
|
static void sig_connected(IRC_SERVER_REC *server)
|
||||||
{
|
{
|
||||||
@ -76,7 +75,9 @@ static void sig_connected(IRC_SERVER_REC *server)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
rec = g_new0(SERVER_QUERY_REC, 1);
|
rec = g_new0(SERVER_QUERY_REC, 1);
|
||||||
server->chanqueries = rec;
|
rec->accountqueries = g_hash_table_new_full(
|
||||||
|
(GHashFunc) i_istr_hash, (GCompareFunc) i_istr_equal, (GDestroyNotify) g_free, NULL);
|
||||||
|
server->chanqueries = rec;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sig_disconnected(IRC_SERVER_REC *server)
|
static void sig_disconnected(IRC_SERVER_REC *server)
|
||||||
@ -91,6 +92,7 @@ static void sig_disconnected(IRC_SERVER_REC *server)
|
|||||||
rec = server->chanqueries;
|
rec = server->chanqueries;
|
||||||
g_return_if_fail(rec != NULL);
|
g_return_if_fail(rec != NULL);
|
||||||
|
|
||||||
|
g_hash_table_destroy(rec->accountqueries);
|
||||||
for (n = 0; n < CHANNEL_QUERIES; n++)
|
for (n = 0; n < CHANNEL_QUERIES; n++)
|
||||||
g_slist_free(rec->queries[n]);
|
g_slist_free(rec->queries[n]);
|
||||||
g_slist_free(rec->current_queries);
|
g_slist_free(rec->current_queries);
|
||||||
@ -229,15 +231,19 @@ static void query_send(IRC_SERVER_REC *server, int query)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CHANNEL_QUERY_WHO:
|
case CHANNEL_QUERY_WHO:
|
||||||
cmd = g_strdup_printf("WHO %s", chanstr_commas);
|
if (server->isupport != NULL &&
|
||||||
|
g_hash_table_lookup(server->isupport, "whox") != NULL) {
|
||||||
|
cmd = g_strdup_printf(WHOX_CHANNEL_FULL_CMD, chanstr_commas);
|
||||||
|
} else {
|
||||||
|
cmd = g_strdup_printf("WHO %s", chanstr_commas);
|
||||||
|
}
|
||||||
|
|
||||||
server_redirect_event(server, "who",
|
server_redirect_event(server, "who", server->one_endofwho ? 1 : count, chanstr, -1,
|
||||||
server->one_endofwho ? 1 : count,
|
"chanquery abort", /* failure signal */
|
||||||
chanstr, -1,
|
"event 315", "chanquery who end", /* */
|
||||||
"chanquery abort",
|
"event 352", "silent event who", /* */
|
||||||
"event 315", "chanquery who end",
|
"event 354", "silent event whox", /* */
|
||||||
"event 352", "silent event who",
|
"", "chanquery abort", NULL);
|
||||||
"", "chanquery abort", NULL);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CHANNEL_QUERY_BMODE:
|
case CHANNEL_QUERY_BMODE:
|
||||||
@ -395,6 +401,146 @@ static void channel_got_query(IRC_CHANNEL_REC *chanrec, int query_type)
|
|||||||
query_check(chanrec->server);
|
query_check(chanrec->server);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void irc_channels_query_purge_accountquery(IRC_SERVER_REC *server, const char *nick)
|
||||||
|
{
|
||||||
|
GSList *tmp, *next, *prev;
|
||||||
|
REDIRECT_REC *redirect;
|
||||||
|
char *cmd, *target_cmd;
|
||||||
|
gboolean was_removed;
|
||||||
|
|
||||||
|
/* remove the marker */
|
||||||
|
was_removed = g_hash_table_remove(server->chanqueries->accountqueries, nick);
|
||||||
|
|
||||||
|
/* if it was removed we may have an outstanding query */
|
||||||
|
if (was_removed) {
|
||||||
|
target_cmd = g_strdup_printf(WHOX_USERACCOUNT_CMD "\r\n", nick);
|
||||||
|
|
||||||
|
/* remove queued WHO command */
|
||||||
|
prev = NULL;
|
||||||
|
for (tmp = server->cmdqueue; tmp != NULL; tmp = next) {
|
||||||
|
next = tmp->next->next;
|
||||||
|
cmd = tmp->data;
|
||||||
|
redirect = tmp->next->data;
|
||||||
|
|
||||||
|
if (g_strcmp0(cmd, target_cmd) == 0) {
|
||||||
|
if (prev != NULL)
|
||||||
|
prev->next = next;
|
||||||
|
else
|
||||||
|
server->cmdqueue = next;
|
||||||
|
|
||||||
|
/* remove the redirection */
|
||||||
|
g_slist_free_1(tmp->next);
|
||||||
|
if (redirect != NULL)
|
||||||
|
server_redirect_destroy(redirect);
|
||||||
|
|
||||||
|
/* remove the command */
|
||||||
|
g_slist_free_1(tmp);
|
||||||
|
g_free(cmd);
|
||||||
|
|
||||||
|
server->cmdcount--;
|
||||||
|
} else {
|
||||||
|
prev = tmp->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(target_cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void query_useraccount_error(IRC_SERVER_REC *server, const char *cmd, const char *arg)
|
||||||
|
{
|
||||||
|
/* query failed, ignore it but remove the marker */
|
||||||
|
g_hash_table_remove(server->chanqueries->accountqueries, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sig_event_join(IRC_SERVER_REC *server, const char *data, const char *nick,
|
||||||
|
const char *address)
|
||||||
|
{
|
||||||
|
char *params, *channel, *ptr, *account;
|
||||||
|
GSList *nicks, *tmp;
|
||||||
|
IRC_CHANNEL_REC *chanrec;
|
||||||
|
NICK_REC *nickrec;
|
||||||
|
|
||||||
|
g_return_if_fail(data != NULL);
|
||||||
|
|
||||||
|
if (i_slist_find_string(server->cap_active, CAP_EXTENDED_JOIN)) {
|
||||||
|
/* no need to chase accounts */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_ascii_strcasecmp(nick, server->nick) == 0) {
|
||||||
|
/* You joined, do nothing */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
params = event_get_params(data, 3, &channel, NULL, NULL);
|
||||||
|
|
||||||
|
ptr = strchr(channel, 7); /* ^G does something weird.. */
|
||||||
|
if (ptr != NULL)
|
||||||
|
*ptr = '\0';
|
||||||
|
|
||||||
|
/* find channel */
|
||||||
|
chanrec = irc_channel_find(server, channel);
|
||||||
|
if (chanrec == NULL) {
|
||||||
|
g_free(params);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(params);
|
||||||
|
|
||||||
|
if (!chanrec->wholist) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find nick */
|
||||||
|
nickrec = nicklist_find(CHANNEL(chanrec), nick);
|
||||||
|
if (nickrec == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nickrec->account != NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_hash_table_contains(server->chanqueries->accountqueries, nick)) {
|
||||||
|
/* query already sent */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
account = NULL;
|
||||||
|
|
||||||
|
/* Check if user is already in some other channel, get the account from there */
|
||||||
|
nicks = nicklist_get_same(SERVER(server), nick);
|
||||||
|
for (tmp = nicks; tmp != NULL; tmp = tmp->next->next) {
|
||||||
|
NICK_REC *rec = tmp->next->data;
|
||||||
|
|
||||||
|
if (rec->account != NULL) {
|
||||||
|
account = rec->account;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_slist_free(nicks);
|
||||||
|
|
||||||
|
if (account != NULL) {
|
||||||
|
nicklist_set_account(CHANNEL(chanrec), nickrec, account);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_hash_table_size(chanrec->nicks) < settings_get_int("channel_max_who_sync") &&
|
||||||
|
server->isupport != NULL && g_hash_table_lookup(server->isupport, "whox") != NULL) {
|
||||||
|
char *cmd;
|
||||||
|
server_redirect_event(server, "who user", 1, nick, -1,
|
||||||
|
"chanquery useraccount abort", /* failure signal */
|
||||||
|
"event 354", "silent event whox useraccount", /* */
|
||||||
|
"", "event empty", /* */
|
||||||
|
NULL);
|
||||||
|
cmd = g_strdup_printf(WHOX_USERACCOUNT_CMD, nick);
|
||||||
|
g_hash_table_add(server->chanqueries->accountqueries, g_strdup(nick));
|
||||||
|
/* queue the command */
|
||||||
|
irc_send_cmd_full(server, cmd, FALSE, FALSE, FALSE);
|
||||||
|
g_free(cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void event_channel_mode(IRC_SERVER_REC *server, const char *data,
|
static void event_channel_mode(IRC_SERVER_REC *server, const char *data,
|
||||||
const char *nick)
|
const char *nick)
|
||||||
{
|
{
|
||||||
@ -493,11 +639,14 @@ void channels_query_init(void)
|
|||||||
signal_add("channel joined", (SIGNAL_FUNC) sig_channel_joined);
|
signal_add("channel joined", (SIGNAL_FUNC) sig_channel_joined);
|
||||||
signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
|
signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
|
||||||
|
|
||||||
|
signal_add("event join", (SIGNAL_FUNC) sig_event_join);
|
||||||
|
|
||||||
signal_add("chanquery mode", (SIGNAL_FUNC) event_channel_mode);
|
signal_add("chanquery mode", (SIGNAL_FUNC) event_channel_mode);
|
||||||
signal_add("chanquery who end", (SIGNAL_FUNC) event_end_of_who);
|
signal_add("chanquery who end", (SIGNAL_FUNC) event_end_of_who);
|
||||||
|
|
||||||
signal_add("chanquery ban end", (SIGNAL_FUNC) event_end_of_banlist);
|
signal_add("chanquery ban end", (SIGNAL_FUNC) event_end_of_banlist);
|
||||||
signal_add("chanquery abort", (SIGNAL_FUNC) query_current_error);
|
signal_add("chanquery abort", (SIGNAL_FUNC) query_current_error);
|
||||||
|
signal_add("chanquery useraccount abort", (SIGNAL_FUNC) query_useraccount_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
void channels_query_deinit(void)
|
void channels_query_deinit(void)
|
||||||
@ -507,9 +656,12 @@ void channels_query_deinit(void)
|
|||||||
signal_remove("channel joined", (SIGNAL_FUNC) sig_channel_joined);
|
signal_remove("channel joined", (SIGNAL_FUNC) sig_channel_joined);
|
||||||
signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
|
signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
|
||||||
|
|
||||||
|
signal_remove("event join", (SIGNAL_FUNC) sig_event_join);
|
||||||
|
|
||||||
signal_remove("chanquery mode", (SIGNAL_FUNC) event_channel_mode);
|
signal_remove("chanquery mode", (SIGNAL_FUNC) event_channel_mode);
|
||||||
signal_remove("chanquery who end", (SIGNAL_FUNC) event_end_of_who);
|
signal_remove("chanquery who end", (SIGNAL_FUNC) event_end_of_who);
|
||||||
|
|
||||||
signal_remove("chanquery ban end", (SIGNAL_FUNC) event_end_of_banlist);
|
signal_remove("chanquery ban end", (SIGNAL_FUNC) event_end_of_banlist);
|
||||||
signal_remove("chanquery abort", (SIGNAL_FUNC) query_current_error);
|
signal_remove("chanquery abort", (SIGNAL_FUNC) query_current_error);
|
||||||
|
signal_remove("chanquery useraccount abort", (SIGNAL_FUNC) query_useraccount_error);
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,20 @@
|
|||||||
#define IS_IRC_CHANNEL(channel) \
|
#define IS_IRC_CHANNEL(channel) \
|
||||||
(IRC_CHANNEL(channel) ? TRUE : FALSE)
|
(IRC_CHANNEL(channel) ? TRUE : FALSE)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
CHANNEL_QUERY_MODE,
|
||||||
|
CHANNEL_QUERY_WHO,
|
||||||
|
CHANNEL_QUERY_BMODE,
|
||||||
|
|
||||||
|
CHANNEL_QUERIES
|
||||||
|
};
|
||||||
|
|
||||||
|
/* arbitrary 3-digit identifiers so we can find our WHOX responses */
|
||||||
|
#define WHOX_CHANNEL_FULL_ID "743"
|
||||||
|
#define WHOX_USERACCOUNT_ID "745"
|
||||||
|
|
||||||
|
#define CHANNEL_IS_MODE_QUERY(a) ((a) != CHANNEL_QUERY_WHO)
|
||||||
|
|
||||||
#define STRUCT_SERVER_REC IRC_SERVER_REC
|
#define STRUCT_SERVER_REC IRC_SERVER_REC
|
||||||
struct _IRC_CHANNEL_REC {
|
struct _IRC_CHANNEL_REC {
|
||||||
#include <irssi/src/core/channel-rec.h>
|
#include <irssi/src/core/channel-rec.h>
|
||||||
@ -22,6 +36,16 @@ struct _IRC_CHANNEL_REC {
|
|||||||
int last_massjoins; /* Massjoins when last checked in timeout function */
|
int last_massjoins; /* Massjoins when last checked in timeout function */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct _SERVER_QUERY_REC {
|
||||||
|
int current_query_type; /* query type that is currently being asked */
|
||||||
|
GSList *current_queries; /* All channels that are currently being queried */
|
||||||
|
|
||||||
|
GSList *queries[CHANNEL_QUERIES]; /* All queries that need to be asked from server */
|
||||||
|
GHashTable *accountqueries; /* Per-nick account queries */
|
||||||
|
} SERVER_QUERY_REC;
|
||||||
|
|
||||||
|
void irc_channels_query_purge_accountquery(IRC_SERVER_REC *server, const char *nick);
|
||||||
|
|
||||||
void irc_channels_init(void);
|
void irc_channels_init(void);
|
||||||
void irc_channels_deinit(void);
|
void irc_channels_deinit(void);
|
||||||
|
|
||||||
|
@ -438,15 +438,18 @@ static void cmd_whois(const char *data, IRC_SERVER_REC *server,
|
|||||||
query = get_redirect_nicklist(query, &free_nick);
|
query = get_redirect_nicklist(query, &free_nick);
|
||||||
|
|
||||||
str = g_strconcat(qserver, " ", query, NULL);
|
str = g_strconcat(qserver, " ", query, NULL);
|
||||||
server_redirect_event(server, "whois", 1, str, TRUE,
|
server_redirect_event(
|
||||||
NULL,
|
server, "whois", 1, str, TRUE, /* */
|
||||||
"event 318", "whois end",
|
NULL, /* */
|
||||||
"event 402", event_402,
|
"event 318", "whois end", /* */
|
||||||
"event 301", "whois away", /* 301 can come as a reply to /MSG, /WHOIS or /WHOWAS */
|
"event 402", event_402, /* */
|
||||||
"event 313", "whois oper",
|
"event 301", "whois away", /* 301 can come as a reply to /MSG, /WHOIS or /WHOWAS */
|
||||||
"event 401", (settings_get_bool("auto_whowas") ? "whois try whowas" : "whois event not found"),
|
"event 313", "whois oper", /* */
|
||||||
"event 311", "whois event",
|
"event 330", "whois account", /* */
|
||||||
"", "whois default event", NULL);
|
"event 401",
|
||||||
|
(settings_get_bool("auto_whowas") ? "whois try whowas" : "whois event not found"),
|
||||||
|
"event 311", "whois event", /* */
|
||||||
|
"", "whois default event", NULL);
|
||||||
g_free(str);
|
g_free(str);
|
||||||
|
|
||||||
server->whois_found = FALSE;
|
server->whois_found = FALSE;
|
||||||
|
@ -29,6 +29,34 @@
|
|||||||
#include <irssi/src/irc/core/modes.h>
|
#include <irssi/src/irc/core/modes.h>
|
||||||
#include <irssi/src/core/servers.h>
|
#include <irssi/src/core/servers.h>
|
||||||
|
|
||||||
|
static void nicklist_set_modes(IRC_CHANNEL_REC *channel, NICK_REC *rec, gboolean op,
|
||||||
|
gboolean halfop, gboolean voice, const char *prefixes,
|
||||||
|
gboolean send_changed)
|
||||||
|
{
|
||||||
|
gboolean changed = FALSE;
|
||||||
|
if (rec->op != op) {
|
||||||
|
rec->op = op;
|
||||||
|
changed = TRUE;
|
||||||
|
}
|
||||||
|
if (rec->halfop != halfop) {
|
||||||
|
rec->halfop = halfop;
|
||||||
|
changed = TRUE;
|
||||||
|
}
|
||||||
|
if (rec->voice != voice) {
|
||||||
|
rec->voice = voice;
|
||||||
|
changed = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prefixes != NULL && g_strcmp0(rec->prefixes, prefixes) != 0) {
|
||||||
|
g_strlcpy(rec->prefixes, prefixes, sizeof(rec->prefixes));
|
||||||
|
changed = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed && send_changed) {
|
||||||
|
signal_emit("nicklist changed", 3, channel, rec, rec->nick);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Add new nick to list */
|
/* Add new nick to list */
|
||||||
NICK_REC *irc_nicklist_insert(IRC_CHANNEL_REC *channel, const char *nick,
|
NICK_REC *irc_nicklist_insert(IRC_CHANNEL_REC *channel, const char *nick,
|
||||||
int op, int halfop, int voice, int send_massjoin,
|
int op, int halfop, int voice, int send_massjoin,
|
||||||
@ -42,14 +70,8 @@ NICK_REC *irc_nicklist_insert(IRC_CHANNEL_REC *channel, const char *nick,
|
|||||||
rec = g_new0(NICK_REC, 1);
|
rec = g_new0(NICK_REC, 1);
|
||||||
rec->nick = g_strdup(nick);
|
rec->nick = g_strdup(nick);
|
||||||
|
|
||||||
if (op) rec->op = TRUE;
|
|
||||||
if (halfop) rec->halfop = TRUE;
|
|
||||||
if (voice) rec->voice = TRUE;
|
|
||||||
rec->send_massjoin = send_massjoin;
|
rec->send_massjoin = send_massjoin;
|
||||||
|
nicklist_set_modes(channel, rec, op, halfop, voice, prefixes, FALSE);
|
||||||
if (prefixes != NULL) {
|
|
||||||
g_strlcpy(rec->prefixes, prefixes, sizeof(rec->prefixes));
|
|
||||||
}
|
|
||||||
|
|
||||||
nicklist_insert(CHANNEL(channel), rec);
|
nicklist_insert(CHANNEL(channel), rec);
|
||||||
return rec;
|
return rec;
|
||||||
@ -154,11 +176,14 @@ static void event_names_list(IRC_SERVER_REC *server, const char *data)
|
|||||||
if (host != NULL)
|
if (host != NULL)
|
||||||
*host++ = '\0';
|
*host++ = '\0';
|
||||||
|
|
||||||
if (nicklist_find((CHANNEL_REC *) chanrec, ptr) == NULL) {
|
rec = nicklist_find((CHANNEL_REC *) chanrec, ptr);
|
||||||
|
if (rec == NULL) {
|
||||||
rec = irc_nicklist_insert(chanrec, ptr, op, halfop,
|
rec = irc_nicklist_insert(chanrec, ptr, op, halfop,
|
||||||
voice, FALSE, prefixes);
|
voice, FALSE, prefixes);
|
||||||
if (host != NULL)
|
if (host != NULL)
|
||||||
nicklist_set_host(CHANNEL(chanrec), rec, host);
|
nicklist_set_host(CHANNEL(chanrec), rec, host);
|
||||||
|
} else {
|
||||||
|
nicklist_set_modes(chanrec, rec, op, halfop, voice, prefixes, TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,23 +221,13 @@ static void event_end_of_names(IRC_SERVER_REC *server, const char *data)
|
|||||||
g_free(params);
|
g_free(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void event_who(SERVER_REC *server, const char *data)
|
static void fill_who(SERVER_REC *server, const char *channel, const char *user, const char *host,
|
||||||
|
const char *nick, const char *stat, const char *hops, const char *account,
|
||||||
|
const char *realname)
|
||||||
{
|
{
|
||||||
char *params, *nick, *channel, *user, *host, *stat, *realname, *hops;
|
|
||||||
CHANNEL_REC *chanrec;
|
CHANNEL_REC *chanrec;
|
||||||
NICK_REC *nickrec;
|
NICK_REC *nickrec;
|
||||||
|
|
||||||
g_return_if_fail(data != NULL);
|
|
||||||
|
|
||||||
params = event_get_params(data, 8, NULL, &channel, &user, &host,
|
|
||||||
NULL, &nick, &stat, &realname);
|
|
||||||
|
|
||||||
/* get hop count */
|
|
||||||
hops = realname;
|
|
||||||
while (*realname != '\0' && *realname != ' ') realname++;
|
|
||||||
if (*realname == ' ')
|
|
||||||
*realname++ = '\0';
|
|
||||||
|
|
||||||
/* update host, realname, hopcount */
|
/* update host, realname, hopcount */
|
||||||
chanrec = channel_find(server, channel);
|
chanrec = channel_find(server, channel);
|
||||||
nickrec = chanrec == NULL ? NULL :
|
nickrec = chanrec == NULL ? NULL :
|
||||||
@ -223,15 +238,89 @@ static void event_who(SERVER_REC *server, const char *data)
|
|||||||
nicklist_set_host(chanrec, nickrec, str);
|
nicklist_set_host(chanrec, nickrec, str);
|
||||||
g_free(str);
|
g_free(str);
|
||||||
}
|
}
|
||||||
if (nickrec->realname == NULL)
|
if (nickrec->realname == NULL) {
|
||||||
nickrec->realname = g_strdup(realname);
|
nickrec->realname = g_strdup(realname);
|
||||||
|
}
|
||||||
|
if (nickrec->account == NULL && account != NULL) {
|
||||||
|
nicklist_set_account(chanrec, nickrec,
|
||||||
|
strcmp(account, "0") == 0 ? "*" : account);
|
||||||
|
}
|
||||||
sscanf(hops, "%d", &nickrec->hops);
|
sscanf(hops, "%d", &nickrec->hops);
|
||||||
}
|
}
|
||||||
|
|
||||||
nicklist_update_flags(server, nick,
|
nicklist_update_flags(server, nick,
|
||||||
strchr(stat, 'G') != NULL, /* gone */
|
strchr(stat, 'G') != NULL, /* gone */
|
||||||
strchr(stat, '*') != NULL); /* ircop */
|
strchr(stat, '*') != NULL); /* ircop */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void event_who(SERVER_REC *server, const char *data)
|
||||||
|
{
|
||||||
|
char *params, *nick, *channel, *user, *host, *stat, *realname, *hops;
|
||||||
|
|
||||||
|
g_return_if_fail(data != NULL);
|
||||||
|
|
||||||
|
params =
|
||||||
|
event_get_params(data, 8, NULL, &channel, &user, &host, NULL, &nick, &stat, &realname);
|
||||||
|
|
||||||
|
/* get hop count */
|
||||||
|
hops = realname;
|
||||||
|
while (*realname != '\0' && *realname != ' ')
|
||||||
|
realname++;
|
||||||
|
if (*realname == ' ')
|
||||||
|
*realname++ = '\0';
|
||||||
|
|
||||||
|
fill_who(server, channel, user, host, nick, stat, hops, NULL, realname);
|
||||||
|
|
||||||
|
g_free(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void event_whox_channel_full(SERVER_REC *server, const char *data)
|
||||||
|
{
|
||||||
|
char *params, *id, *nick, *channel, *user, *host, *stat, *hops, *account, *realname;
|
||||||
|
|
||||||
|
g_return_if_fail(data != NULL);
|
||||||
|
|
||||||
|
params = event_get_params(data, 10, NULL, &id, &channel, &user, &host, &nick, &stat, &hops,
|
||||||
|
&account, &realname);
|
||||||
|
|
||||||
|
if (g_strcmp0(id, WHOX_CHANNEL_FULL_ID) != 0) {
|
||||||
|
g_free(params);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fill_who(server, channel, user, host, nick, stat, hops, account, realname);
|
||||||
|
|
||||||
|
g_free(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void event_whox_useraccount(IRC_SERVER_REC *server, const char *data)
|
||||||
|
{
|
||||||
|
char *params, *id, *nick, *account;
|
||||||
|
GSList *nicks, *tmp;
|
||||||
|
|
||||||
|
g_return_if_fail(data != NULL);
|
||||||
|
|
||||||
|
params = event_get_params(data, 4, NULL, &id, &nick, &account);
|
||||||
|
|
||||||
|
if (g_strcmp0(id, WHOX_USERACCOUNT_ID) != 0) {
|
||||||
|
g_free(params);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_hash_table_remove(server->chanqueries->accountqueries, nick);
|
||||||
|
|
||||||
|
if (strcmp(account, "0") == 0) {
|
||||||
|
account = "*";
|
||||||
|
}
|
||||||
|
|
||||||
|
nicks = nicklist_get_same(SERVER(server), nick);
|
||||||
|
for (tmp = nicks; tmp != NULL; tmp = tmp->next->next) {
|
||||||
|
NICK_REC *rec = tmp->next->data;
|
||||||
|
|
||||||
|
if (rec->account == NULL || g_strcmp0(rec->account, account) != 0) {
|
||||||
|
nicklist_set_account(CHANNEL(tmp->data), rec, account);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_slist_free(nicks);
|
||||||
g_free(params);
|
g_free(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -415,7 +504,9 @@ static void event_nick(IRC_SERVER_REC *server, const char *data,
|
|||||||
server_change_nick(SERVER(server), nick);
|
server_change_nick(SERVER(server), nick);
|
||||||
}
|
}
|
||||||
|
|
||||||
nicklist_rename(SERVER(server), orignick, nick);
|
/* invalidate any outstanding accountqueries for the old nick */
|
||||||
|
irc_channels_query_purge_accountquery(server, orignick);
|
||||||
|
nicklist_rename(SERVER(server), orignick, nick);
|
||||||
g_free(params);
|
g_free(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -510,7 +601,10 @@ void irc_nicklist_init(void)
|
|||||||
{
|
{
|
||||||
signal_add_first("event nick", (SIGNAL_FUNC) event_nick);
|
signal_add_first("event nick", (SIGNAL_FUNC) event_nick);
|
||||||
signal_add_first("event 352", (SIGNAL_FUNC) event_who);
|
signal_add_first("event 352", (SIGNAL_FUNC) event_who);
|
||||||
|
signal_add_first("event 354", (SIGNAL_FUNC) event_whox_channel_full);
|
||||||
signal_add("silent event who", (SIGNAL_FUNC) event_who);
|
signal_add("silent event who", (SIGNAL_FUNC) event_who);
|
||||||
|
signal_add("silent event whox", (SIGNAL_FUNC) event_whox_channel_full);
|
||||||
|
signal_add("silent event whox useraccount", (SIGNAL_FUNC) event_whox_useraccount);
|
||||||
signal_add("silent event whois", (SIGNAL_FUNC) event_whois);
|
signal_add("silent event whois", (SIGNAL_FUNC) event_whois);
|
||||||
signal_add_first("event 311", (SIGNAL_FUNC) event_whois);
|
signal_add_first("event 311", (SIGNAL_FUNC) event_whois);
|
||||||
signal_add_first("whois away", (SIGNAL_FUNC) event_whois_away);
|
signal_add_first("whois away", (SIGNAL_FUNC) event_whois_away);
|
||||||
@ -534,7 +628,10 @@ void irc_nicklist_deinit(void)
|
|||||||
{
|
{
|
||||||
signal_remove("event nick", (SIGNAL_FUNC) event_nick);
|
signal_remove("event nick", (SIGNAL_FUNC) event_nick);
|
||||||
signal_remove("event 352", (SIGNAL_FUNC) event_who);
|
signal_remove("event 352", (SIGNAL_FUNC) event_who);
|
||||||
|
signal_remove("event 354", (SIGNAL_FUNC) event_whox_channel_full);
|
||||||
signal_remove("silent event who", (SIGNAL_FUNC) event_who);
|
signal_remove("silent event who", (SIGNAL_FUNC) event_who);
|
||||||
|
signal_remove("silent event whox", (SIGNAL_FUNC) event_whox_channel_full);
|
||||||
|
signal_remove("silent event whox useraccount", (SIGNAL_FUNC) event_whox_useraccount);
|
||||||
signal_remove("silent event whois", (SIGNAL_FUNC) event_whois);
|
signal_remove("silent event whois", (SIGNAL_FUNC) event_whois);
|
||||||
signal_remove("event 311", (SIGNAL_FUNC) event_whois);
|
signal_remove("event 311", (SIGNAL_FUNC) event_whois);
|
||||||
signal_remove("whois away", (SIGNAL_FUNC) event_whois_away);
|
signal_remove("whois away", (SIGNAL_FUNC) event_whois_away);
|
||||||
|
@ -136,7 +136,7 @@ struct _IRC_SERVER_REC {
|
|||||||
GSList *rejoin_channels; /* try to join to these channels after a while -
|
GSList *rejoin_channels; /* try to join to these channels after a while -
|
||||||
channels go here if they're "temporarily unavailable"
|
channels go here if they're "temporarily unavailable"
|
||||||
because of netsplits */
|
because of netsplits */
|
||||||
void *chanqueries;
|
struct _SERVER_QUERY_REC *chanqueries;
|
||||||
|
|
||||||
GHashTable *isupport;
|
GHashTable *isupport;
|
||||||
struct modes_type modes[256]; /* Stores the modes sent by a server in an isupport reply */
|
struct modes_type modes[256]; /* Stores the modes sent by a server in an isupport reply */
|
||||||
|
@ -39,12 +39,15 @@ static void event_join(IRC_SERVER_REC *server, const char *data,
|
|||||||
IRC_CHANNEL_REC *chanrec;
|
IRC_CHANNEL_REC *chanrec;
|
||||||
NICK_REC *nickrec;
|
NICK_REC *nickrec;
|
||||||
GSList *nicks, *tmp;
|
GSList *nicks, *tmp;
|
||||||
|
gboolean send_massjoin;
|
||||||
|
|
||||||
g_return_if_fail(data != NULL);
|
g_return_if_fail(data != NULL);
|
||||||
|
|
||||||
if (g_ascii_strcasecmp(nick, server->nick) == 0) {
|
if (g_ascii_strcasecmp(nick, server->nick) == 0) {
|
||||||
/* You joined, no need to do anything here */
|
/* You joined, do not massjoin */
|
||||||
return;
|
send_massjoin = FALSE;
|
||||||
|
} else {
|
||||||
|
send_massjoin = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
params = event_get_params(data, 3, &channel, &account, &realname);
|
params = event_get_params(data, 3, &channel, &account, &realname);
|
||||||
@ -68,14 +71,14 @@ static void event_join(IRC_SERVER_REC *server, const char *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* add user to nicklist */
|
/* add user to nicklist */
|
||||||
nickrec = irc_nicklist_insert(chanrec, nick, FALSE, FALSE, FALSE, TRUE, NULL);
|
nickrec = irc_nicklist_insert(chanrec, nick, FALSE, FALSE, FALSE, send_massjoin, NULL);
|
||||||
if (*account != '\0' && g_strcmp0(nickrec->account, account) != 0) {
|
if (*account != '\0' && g_strcmp0(nickrec->account, account) != 0) {
|
||||||
nicklist_set_account(CHANNEL(chanrec), nickrec, account);
|
nicklist_set_account(CHANNEL(chanrec), nickrec, account);
|
||||||
}
|
}
|
||||||
|
|
||||||
nicklist_set_host(CHANNEL(chanrec), nickrec, address);
|
nicklist_set_host(CHANNEL(chanrec), nickrec, address);
|
||||||
|
|
||||||
if (chanrec->massjoins == 0) {
|
if (send_massjoin && chanrec->massjoins == 0) {
|
||||||
/* no nicks waiting in massjoin queue */
|
/* no nicks waiting in massjoin queue */
|
||||||
chanrec->massjoin_start = time(NULL);
|
chanrec->massjoin_start = time(NULL);
|
||||||
chanrec->last_massjoins = 0;
|
chanrec->last_massjoins = 0;
|
||||||
@ -104,7 +107,9 @@ static void event_join(IRC_SERVER_REC *server, const char *data,
|
|||||||
nickrec->realname = g_strdup(realname);
|
nickrec->realname = g_strdup(realname);
|
||||||
}
|
}
|
||||||
|
|
||||||
chanrec->massjoins++;
|
if (send_massjoin) {
|
||||||
|
chanrec->massjoins++;
|
||||||
|
}
|
||||||
g_free(params);
|
g_free(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,6 +222,9 @@ static void event_quit(IRC_SERVER_REC *server, const char *data,
|
|||||||
nicklist_remove(CHANNEL(channel), nickrec);
|
nicklist_remove(CHANNEL(channel), nickrec);
|
||||||
}
|
}
|
||||||
g_slist_free(nicks);
|
g_slist_free(nicks);
|
||||||
|
|
||||||
|
/* invalidate any outstanding accountqueries for the nick */
|
||||||
|
irc_channels_query_purge_accountquery(server, nick);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void event_kick(IRC_SERVER_REC *server, const char *data)
|
static void event_kick(IRC_SERVER_REC *server, const char *data)
|
||||||
|
@ -442,7 +442,7 @@ static void redirect_abort(IRC_SERVER_REC *server, REDIRECT_REC *rec)
|
|||||||
g_free(str);
|
g_free(str);
|
||||||
|
|
||||||
if (rec->failure_signal != NULL)
|
if (rec->failure_signal != NULL)
|
||||||
signal_emit(rec->failure_signal, 1, server);
|
signal_emit(rec->failure_signal, 3, server, rec->cmd->name, rec->arg);
|
||||||
} else if (rec->last_signal != NULL) {
|
} else if (rec->last_signal != NULL) {
|
||||||
/* emit the last signal */
|
/* emit the last signal */
|
||||||
signal_emit(rec->last_signal, 1, server);
|
signal_emit(rec->last_signal, 1, server);
|
||||||
@ -697,7 +697,16 @@ void servers_redirect_init(void)
|
|||||||
NULL,
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
/* LIST */
|
/* WHO user */
|
||||||
|
server_redirect_register("who user", FALSE, 0, /* */
|
||||||
|
"event 352", 5, /* An element of the WHO */
|
||||||
|
"event 354", -1, /* WHOX element */
|
||||||
|
NULL, /* */
|
||||||
|
"event 315", 1, /* End of WHO */
|
||||||
|
NULL, /* */
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* LIST */
|
||||||
server_redirect_register("list", FALSE, 0,
|
server_redirect_register("list", FALSE, 0,
|
||||||
"event 321", 1, /* Begins the LIST */
|
"event 321", 1, /* Begins the LIST */
|
||||||
NULL,
|
NULL,
|
||||||
|
Loading…
Reference in New Issue
Block a user