diff options
Diffstat (limited to 'src/irc/core/irc-servers.c')
-rw-r--r-- | src/irc/core/irc-servers.c | 147 |
1 files changed, 144 insertions, 3 deletions
diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index c6d16b62..6e139c9b 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -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 */ |