diff options
Diffstat (limited to 'src/irc/core/irc-servers.c')
-rw-r--r-- | src/irc/core/irc-servers.c | 136 |
1 files changed, 88 insertions, 48 deletions
diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index 13784f88..3117e345 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -32,6 +32,10 @@ #include "irc-queries.h" #include "irc-servers-setup.h" #include "irc-servers.h" +#include "irc-cap.h" +#include "sasl.h" + +#include "channels-setup.h" #include "channel-rejoin.h" #include "servers-idle.h" #include "servers-reconnect.h" @@ -71,13 +75,28 @@ static int isnickflag_func(SERVER_REC *server, char flag) static int ischannel_func(SERVER_REC *server, const char *data) { - if (*data == '@') { - /* @#channel, @+#channel */ - data++; - if (*data == '+' && ischannel(data[1])) - return 1; - } - return ischannel(*data); + IRC_SERVER_REC *irc_server = (IRC_SERVER_REC *) server; + char *chantypes, *statusmsg; + + g_return_val_if_fail(data != NULL, FALSE); + + /* empty string is no channel */ + if (*data == '\0') + return FALSE; + + chantypes = g_hash_table_lookup(irc_server->isupport, "chantypes"); + if (chantypes == NULL) + chantypes = "#&!+"; /* normal, local, secure, modeless */ + + statusmsg = g_hash_table_lookup(irc_server->isupport, "statusmsg"); + if (statusmsg == NULL) + statusmsg = "@"; + + data += strspn(data, statusmsg); + + /* strchr(3) considers the trailing NUL as part of the string, make sure + * we didn't advance too much. */ + return *data != '\0' && strchr(chantypes, *data) != NULL; } static char **split_line(const SERVER_REC *server, const char *line, @@ -85,6 +104,7 @@ static char **split_line(const SERVER_REC *server, const char *line, { const char *start = settings_get_str("split_line_start"); const char *end = settings_get_str("split_line_end"); + gboolean onspace = settings_get_bool("split_line_on_space"); char *recoded_start = recode_out(server, start, target); char *recoded_end = recode_out(server, end, target); char **lines; @@ -103,7 +123,7 @@ static char **split_line(const SERVER_REC *server, const char *line, return NULL; } - lines = recode_split(server, line, target, len); + lines = recode_split(server, line, target, len, onspace); for (i = 0; lines[i] != NULL; i++) { if (i != 0 && *start != '\0') { /* Not the first line. */ @@ -178,23 +198,15 @@ static char **split_message(SERVER_REC *server, const char *target, const char *msg) { IRC_SERVER_REC *ircserver = IRC_SERVER(server); - int userhostlen = MAX_USERHOST_LEN; g_return_val_if_fail(ircserver != NULL, NULL); g_return_val_if_fail(target != NULL, NULL); g_return_val_if_fail(msg != NULL, NULL); - /* - * If we have joined a channel, userhost will be set, so we can - * calculate the exact maximum length. - */ - if (ircserver->userhost != NULL) - userhostlen = strlen(ircserver->userhost); - - /* length calculation shamelessly stolen from splitlong.pl */ + /* length calculation shamelessly stolen from splitlong_safe.pl */ return split_line(SERVER(server), msg, target, 510 - strlen(":! PRIVMSG :") - - strlen(ircserver->nick) - userhostlen - + strlen(ircserver->nick) - MAX_USERHOST_LEN - strlen(target)); } @@ -202,7 +214,6 @@ static void server_init(IRC_SERVER_REC *server) { IRC_SERVER_CONNECT_REC *conn; char *address, *ptr, *username, *cmd; - GTimeVal now; g_return_if_fail(server != NULL); @@ -221,6 +232,13 @@ static void server_init(IRC_SERVER_REC *server) g_free(cmd); } + if (conn->sasl_mechanism != SASL_MECHANISM_NONE) + cap_toggle(server, "sasl", TRUE); + + cap_toggle(server, "multi-prefix", TRUE); + + irc_send_cmd_now(server, "CAP LS"); + if (conn->password != NULL && *conn->password != '\0') { /* send password */ cmd = g_strdup_printf("PASS %s", conn->password); @@ -270,9 +288,8 @@ static void server_init(IRC_SERVER_REC *server) /* prevent the queue from sending too early, we have a max cut off of 120 secs */ /* this will reset to 1 sec after we get the 001 event */ - g_get_current_time(&now); - memcpy(&((IRC_SERVER_REC *)server)->wait_cmd, &now, sizeof(GTimeVal)); - ((IRC_SERVER_REC *)server)->wait_cmd.tv_sec += 120; + g_get_current_time(&server->wait_cmd); + g_time_val_add(&server->wait_cmd, 120 * G_USEC_PER_SEC); } SERVER_REC *irc_server_init_connect(SERVER_CONNECT_REC *conn) @@ -293,7 +310,7 @@ SERVER_REC *irc_server_init_connect(SERVER_CONNECT_REC *conn) if (server->connrec->port <= 0) { server->connrec->port = - server->connrec->use_ssl ? 6697 : 6667; + server->connrec->use_tls ? 6697 : 6667; } server->cmd_queue_speed = ircconn->cmd_queue_speed > 0 ? @@ -311,7 +328,7 @@ SERVER_REC *irc_server_init_connect(SERVER_CONNECT_REC *conn) ircconn->max_whois : DEFAULT_MAX_WHOIS; server->max_msgs_in_cmd = ircconn->max_msgs > 0 ? ircconn->max_msgs : DEFAULT_MAX_MSGS; - server->connrec->use_ssl = conn->use_ssl; + server->connrec->use_tls = conn->use_tls; modes_server_init(server); @@ -321,6 +338,8 @@ SERVER_REC *irc_server_init_connect(SERVER_CONNECT_REC *conn) void irc_server_connect(SERVER_REC *server) { + g_return_if_fail(server != NULL); + if (!server_start_connect(server)) { server_connect_unref(server->connrec); g_free(server); @@ -416,7 +435,18 @@ static void sig_disconnected(IRC_SERVER_REC *server) server_redirect_destroy(tmp->next->data); } g_slist_free(server->cmdqueue); - server->cmdqueue = NULL; + server->cmdqueue = NULL; + + gslist_free_full(server->cap_active, (GDestroyNotify) g_free); + server->cap_active = NULL; + + gslist_free_full(server->cap_supported, (GDestroyNotify) g_free); + server->cap_supported = NULL; + + gslist_free_full(server->cap_queue, (GDestroyNotify) g_free); + server->cap_queue = NULL; + + g_free_and_null(server->sasl_buffer); /* these are dynamically allocated only if isupport was sent */ g_hash_table_foreach(server->isupport, @@ -458,18 +488,14 @@ void irc_server_send_action(IRC_SERVER_REC *server, const char *target, const ch char **irc_server_split_action(IRC_SERVER_REC *server, const char *target, const char *data) { - int userhostlen = MAX_USERHOST_LEN; - g_return_val_if_fail(server != NULL, NULL); g_return_val_if_fail(target != NULL, NULL); g_return_val_if_fail(data != NULL, NULL); - if (server->userhost != NULL) - userhostlen = strlen(server->userhost); - return split_line(SERVER(server), data, target, 510 - strlen(":! PRIVMSG :\001ACTION \001") - - strlen(server->nick) - userhostlen - strlen(target)); + strlen(server->nick) - MAX_USERHOST_LEN - + strlen(target)); } void irc_server_send_away(IRC_SERVER_REC *server, const char *reason) @@ -484,9 +510,11 @@ void irc_server_send_away(IRC_SERVER_REC *server, const char *reason) if (*reason != '\0') { server->away_reason = g_strdup(reason); reason = recoded = recode_out(SERVER(server), reason, NULL); + irc_send_cmdv(server, "AWAY :%s", reason); + } else { + irc_send_cmdv(server, "AWAY"); } - irc_send_cmdv(server, "AWAY :%s", reason); } g_free(recoded); } @@ -509,7 +537,7 @@ void irc_server_send_data(IRC_SERVER_REC *server, const char *data, int len) server->wait_cmd.tv_sec = 0; else { memcpy(&server->wait_cmd, &server->last_cmd, sizeof(GTimeVal)); - server->wait_cmd.tv_sec += 2 + len/100; + g_time_val_add(&server->wait_cmd, (2 + len/100) * G_USEC_PER_SEC); } } @@ -597,9 +625,16 @@ char *irc_server_get_channels(IRC_SERVER_REC *server) GString *chans, *keys; char *ret; int use_keys; + int rejoin_channels_mode; g_return_val_if_fail(server != NULL, FALSE); + rejoin_channels_mode = settings_get_choice("rejoin_channels_on_reconnect"); + + /* do we want to rejoin channels in the first place? */ + if(rejoin_channels_mode == 0) + return g_strdup(""); + chans = g_string_new(NULL); keys = g_string_new(NULL); use_keys = FALSE; @@ -607,22 +642,27 @@ char *irc_server_get_channels(IRC_SERVER_REC *server) /* get currently joined channels */ for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { CHANNEL_REC *channel = tmp->data; - - g_string_append_printf(chans, "%s,", channel->name); - g_string_append_printf(keys, "%s,", channel->key == NULL ? "x" : - channel->key); - if (channel->key != NULL) - use_keys = TRUE; + CHANNEL_SETUP_REC *setup = channel_setup_find(channel->name, channel->server->connrec->chatnet); + if ((setup != NULL && setup->autojoin && rejoin_channels_mode == 2) || rejoin_channels_mode == 1) { + g_string_append_printf(chans, "%s,", channel->name); + g_string_append_printf(keys, "%s,", channel->key == NULL ? "x" : channel->key); + if (channel->key != NULL) + use_keys = TRUE; + } } /* get also the channels that are in rejoin list */ for (tmp = server->rejoin_channels; tmp != NULL; tmp = tmp->next) { REJOIN_REC *rec = tmp->data; + CHANNEL_SETUP_REC *setup = channel_setup_find(rec->channel, server->tag); + + if ((setup != NULL && setup->autojoin && rejoin_channels_mode == 2) || rejoin_channels_mode == 1) { + g_string_append_printf(chans, "%s,", rec->channel); + g_string_append_printf(keys, "%s,", rec->key == NULL ? "x" : + rec->key); - g_string_append_printf(chans, "%s,", rec->channel); - g_string_append_printf(keys, "%s,", rec->key == NULL ? "x" : - rec->key); - if (rec->key != NULL) use_keys = TRUE; + if (rec->key != NULL) use_keys = TRUE; + } } if (chans->len > 0) { @@ -641,13 +681,12 @@ char *irc_server_get_channels(IRC_SERVER_REC *server) static void event_connected(IRC_SERVER_REC *server, const char *data, const char *from) { char *params, *nick; - GTimeVal now; g_return_if_fail(server != NULL); params = event_get_params(data, 1, &nick); - if (strcmp(server->nick, nick) != 0) { + if (g_strcmp0(server->nick, nick) != 0) { /* nick changed unexpectedly .. connected via proxy, etc. */ g_free(server->nick); server->nick = g_strdup(nick); @@ -664,8 +703,7 @@ static void event_connected(IRC_SERVER_REC *server, const char *data, const char server->real_connect_time = time(NULL); /* let the queue send now that we are identified */ - g_get_current_time(&now); - memcpy(&server->wait_cmd, &now, sizeof(GTimeVal)); + g_get_current_time(&server->wait_cmd); if (server->connrec->usermode != NULL) { /* Send the user mode, before the autosendcmd. @@ -753,7 +791,7 @@ static void event_isupport(IRC_SERVER_REC *server, const char *data) char **item, *sptr, *eptr; char **isupport; gpointer key, value; - + g_return_if_fail(server != NULL); server->isupport_sent = TRUE; @@ -979,9 +1017,11 @@ void irc_server_init_isupport(IRC_SERVER_REC *server) void irc_servers_init(void) { + settings_add_choice("servers", "rejoin_channels_on_reconnect", 1, "off;on;auto"); settings_add_str("misc", "usermode", DEFAULT_USER_MODE); settings_add_str("misc", "split_line_start", ""); settings_add_str("misc", "split_line_end", ""); + settings_add_bool("misc", "split_line_on_space", TRUE); settings_add_time("flood", "cmd_queue_speed", DEFAULT_CMD_QUEUE_SPEED); settings_add_int("flood", "cmds_max_at_once", DEFAULT_CMDS_MAX_AT_ONCE); |