diff options
Diffstat (limited to 'src/plugins/irc/irc-server.c')
-rw-r--r-- | src/plugins/irc/irc-server.c | 252 |
1 files changed, 195 insertions, 57 deletions
diff --git a/src/plugins/irc/irc-server.c b/src/plugins/irc/irc-server.c index dd785c29a..2e43afab5 100644 --- a/src/plugins/irc/irc-server.c +++ b/src/plugins/irc/irc-server.c @@ -1,7 +1,7 @@ /* * irc-server.c - I/O communication with IRC servers * - * Copyright (C) 2003-2017 Sébastien Helleu <flashcode@flashtux.org> + * Copyright (C) 2003-2018 Sébastien Helleu <flashcode@flashtux.org> * Copyright (C) 2005-2010 Emmanuel Bouthenot <kolter@openics.org> * Copyright (C) 2012 Simon Arlott * @@ -29,6 +29,7 @@ #include <stdio.h> #include <stdarg.h> #include <string.h> +#include <ctype.h> #include <time.h> #ifdef _WIN32 #include <winsock.h> @@ -117,6 +118,7 @@ char *irc_server_options[IRC_SERVER_NUM_OPTIONS][2] = { "msg_part", "WeeChat ${info:version}" }, { "msg_quit", "WeeChat ${info:version}" }, { "notify", "" }, + { "split_msg_max_length", "512" }, }; char *irc_server_casemapping_string[IRC_SERVER_NUM_CASEMAPPING] = @@ -337,6 +339,152 @@ irc_server_strncasecmp (struct t_irc_server *server, } /* + * Evaluates a string using the server as context: + * ${irc_server.xxx} and ${server} are replaced by a server option and the + * server name. + * + * Returns the evaluated string. + * + * Note: result must be freed after use. + */ + +char * +irc_server_eval_expression (struct t_irc_server *server, const char *string) +{ + struct t_hashtable *pointers, *extra_vars; + char *value; + + pointers = weechat_hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_POINTER, + NULL, NULL); + extra_vars = weechat_hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + + if (server) + { + if (pointers) + weechat_hashtable_set (pointers, "irc_server", server); + if (extra_vars) + weechat_hashtable_set (extra_vars, "server", server->name); + } + + value = weechat_string_eval_expression (string, + pointers, extra_vars, NULL); + + if (pointers) + weechat_hashtable_free (pointers); + if (extra_vars) + weechat_hashtable_free (extra_vars); + + return value; +} + +/* + * Evaluates and returns the fingerprint. + * + * Returns the evaluated fingerprint, NULL if the fingerprint option is + * invalid. + * + * Note: result must be freed after use. + */ + +char * +irc_server_eval_fingerprint (struct t_irc_server *server) +{ +#ifdef HAVE_GNUTLS + const char *ptr_fingerprint; + char *fingerprint_eval, **fingerprints, *str_sizes; + int i, j, rc, algo, length; + + ptr_fingerprint = IRC_SERVER_OPTION_STRING(server, + IRC_SERVER_OPTION_SSL_FINGERPRINT); + + /* empty fingerprint is just ignored (considered OK) */ + if (!ptr_fingerprint || !ptr_fingerprint[0]) + return strdup (""); + + /* evaluate fingerprint */ + fingerprint_eval = irc_server_eval_expression (server, ptr_fingerprint); + if (!fingerprint_eval || !fingerprint_eval[0]) + { + weechat_printf ( + server->buffer, + _("%s%s: the evaluated fingerprint for server \"%s\" must not be " + "empty"), + weechat_prefix ("error"), + IRC_PLUGIN_NAME, + server->name); + if (fingerprint_eval) + free (fingerprint_eval); + return NULL; + } + + /* split fingerprint */ + fingerprints = weechat_string_split (fingerprint_eval, ",", 0, 0, NULL); + if (!fingerprints) + return fingerprint_eval; + + rc = 0; + for (i = 0; fingerprints[i]; i++) + { + length = strlen (fingerprints[i]); + algo = irc_server_fingerprint_search_algo_with_size (length * 4); + if (algo < 0) + { + rc = -1; + break; + } + for (j = 0; j < length; j++) + { + if (!isxdigit ((unsigned char)fingerprints[i][j])) + { + rc = -2; + break; + } + } + if (rc < 0) + break; + } + weechat_string_free_split (fingerprints); + switch (rc) + { + case -1: /* invalid size */ + str_sizes = irc_server_fingerprint_str_sizes (); + weechat_printf ( + server->buffer, + _("%s%s: invalid fingerprint size for server \"%s\", the " + "number of hexadecimal digits must be " + "one of: %s"), + weechat_prefix ("error"), + IRC_PLUGIN_NAME, + server->name, + (str_sizes) ? str_sizes : "?"); + if (str_sizes) + free (str_sizes); + free (fingerprint_eval); + return NULL; + case -2: /* invalid content */ + weechat_printf ( + server->buffer, + _("%s%s: invalid fingerprint for server \"%s\", it must " + "contain only hexadecimal digits (0-9, " + "a-f)"), + weechat_prefix ("error"), IRC_PLUGIN_NAME, server->name); + free (fingerprint_eval); + return NULL; + } + return fingerprint_eval; +#else + return strdup (""); +#endif /* HAVE_GNUTLS */ +} + +/* * Checks if SASL is enabled on server. * * Returns: @@ -353,12 +501,12 @@ irc_server_sasl_enabled (struct t_irc_server *server) sasl_mechanism = IRC_SERVER_OPTION_INTEGER( server, IRC_SERVER_OPTION_SASL_MECHANISM); - sasl_username = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_USERNAME), - NULL, NULL, NULL); - sasl_password = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_PASSWORD), - NULL, NULL, NULL); + sasl_username = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_USERNAME)); + sasl_password = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_PASSWORD)); sasl_key = IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_KEY); /* @@ -422,8 +570,7 @@ irc_server_set_addresses (struct t_irc_server *server, const char *addresses) if (addresses && addresses[0]) { - addresses_eval = weechat_string_eval_expression (addresses, - NULL, NULL, NULL); + addresses_eval = irc_server_eval_expression (server, addresses); if (server->addresses_eval && (strcmp (server->addresses_eval, addresses_eval) == 0)) { @@ -550,7 +697,7 @@ irc_server_set_nicks (struct t_irc_server *server, const char *nicks) } /* evaluate value */ - nicks2 = weechat_string_eval_expression (nicks, NULL, NULL, NULL); + nicks2 = irc_server_eval_expression (server, nicks); /* set new nicks */ server->nicks_array = weechat_string_split ( @@ -2498,7 +2645,10 @@ irc_server_sendf (struct t_irc_server *server, int flags, const char *tags, (new_msg) ? new_msg : items[i], NULL); - /* split message if needed (max is 512 bytes including final "\r\n") */ + /* + * split message if needed (max is 512 bytes by default, + * including the final "\r\n") + */ hashtable = irc_message_split (server, (new_msg) ? new_msg : items[i]); if (hashtable) @@ -2707,8 +2857,8 @@ void irc_server_msgq_flush () { struct t_irc_message *next; - char *ptr_data, *new_msg, *new_msg2, *ptr_msg, *ptr_msg2, *ptr_msg3, *pos; - char *tags, *nick, *host, *command, *channel, *arguments; + char *ptr_data, *new_msg, *new_msg2, *ptr_msg, *ptr_msg2, *pos; + char *nick, *host, *command, *channel, *arguments; char *msg_decoded, *msg_decoded_without_color; char str_modifier[128], modifier_data[256]; int pos_channel, pos_text, pos_decode; @@ -2773,7 +2923,7 @@ irc_server_msgq_flush () } irc_message_parse (irc_recv_msgq->server, ptr_msg, - &tags, NULL, &nick, &host, + NULL, NULL, &nick, &host, &command, &channel, &arguments, NULL, NULL, NULL, &pos_channel, &pos_text); @@ -2860,25 +3010,9 @@ irc_server_msgq_flush () else { /* message not redirected, display it */ - ptr_msg3 = ptr_msg2; - if (ptr_msg3[0] == '@') - { - /* skip tags in message */ - ptr_msg3 = strchr (ptr_msg3, ' '); - if (ptr_msg3) - { - while (ptr_msg3[0] == ' ') - { - ptr_msg3++; - } - } - else - ptr_msg3 = ptr_msg2; - } irc_protocol_recv_command ( irc_recv_msgq->server, - ptr_msg3, - tags, + ptr_msg2, command, channel); } @@ -3508,15 +3642,15 @@ irc_server_login (struct t_irc_server *server) const char *capabilities; char *password, *username, *realname, *username2; - password = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_PASSWORD), - NULL, NULL, NULL); - username = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_USERNAME), - NULL, NULL, NULL); - realname = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_REALNAME), - NULL, NULL, NULL); + password = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_PASSWORD)); + username = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_USERNAME)); + realname = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_REALNAME)); capabilities = IRC_SERVER_OPTION_STRING( server, IRC_SERVER_OPTION_CAPABILITIES); @@ -4235,8 +4369,12 @@ irc_server_gnutls_callback (const void *pointer, void *data, /* get fingerprint option in server */ ptr_fingerprint = IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SSL_FINGERPRINT); - fingerprint_eval = weechat_string_eval_expression (ptr_fingerprint, - NULL, NULL, NULL); + fingerprint_eval = irc_server_eval_fingerprint (server); + if (!fingerprint_eval) + { + rc = -1; + goto end; + } /* set match options */ fingerprint_match = (ptr_fingerprint && ptr_fingerprint[0]) ? 0 : 1; @@ -4969,9 +5107,9 @@ irc_server_autojoin_create_buffers (struct t_irc_server *server) return; /* evaluate server option "autojoin" */ - autojoin = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_AUTOJOIN), - NULL, NULL, NULL); + autojoin = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_AUTOJOIN)); /* extract channel names from autojoin option */ if (autojoin && autojoin[0]) @@ -5042,9 +5180,9 @@ irc_server_autojoin_channels (struct t_irc_server *server) else { /* auto-join when connecting to server for first time */ - autojoin = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_AUTOJOIN), - NULL, NULL, NULL); + autojoin = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_AUTOJOIN)); if (!server->disable_autojoin && autojoin && autojoin[0]) irc_command_join_server (server, autojoin, 0, 0); if (autojoin) @@ -6079,26 +6217,26 @@ irc_server_print_log () weechat_log_printf (" chantypes. . . . . . : '%s'", ptr_server->chantypes); weechat_log_printf (" chanmodes. . . . . . : '%s'", ptr_server->chanmodes); weechat_log_printf (" monitor. . . . . . . : %d", ptr_server->monitor); - weechat_log_printf (" monitor_time . . . . : %ld", ptr_server->monitor_time); + weechat_log_printf (" monitor_time . . . . : %lld", (long long)ptr_server->monitor_time); weechat_log_printf (" reconnect_delay. . . : %d", ptr_server->reconnect_delay); - weechat_log_printf (" reconnect_start. . . : %ld", ptr_server->reconnect_start); - weechat_log_printf (" command_time . . . . : %ld", ptr_server->command_time); + weechat_log_printf (" reconnect_start. . . : %lld", (long long)ptr_server->reconnect_start); + weechat_log_printf (" command_time . . . . : %lld", (long long)ptr_server->command_time); weechat_log_printf (" reconnect_join . . . : %d", ptr_server->reconnect_join); weechat_log_printf (" disable_autojoin . . : %d", ptr_server->disable_autojoin); weechat_log_printf (" is_away. . . . . . . : %d", ptr_server->is_away); weechat_log_printf (" away_message . . . . : '%s'", ptr_server->away_message); - weechat_log_printf (" away_time. . . . . . : %ld", ptr_server->away_time); + weechat_log_printf (" away_time. . . . . . : %lld", (long long)ptr_server->away_time); weechat_log_printf (" lag. . . . . . . . . : %d", ptr_server->lag); weechat_log_printf (" lag_displayed. . . . : %d", ptr_server->lag_displayed); weechat_log_printf (" lag_check_time . . . : tv_sec:%d, tv_usec:%d", ptr_server->lag_check_time.tv_sec, ptr_server->lag_check_time.tv_usec); - weechat_log_printf (" lag_next_check . . . : %ld", ptr_server->lag_next_check); - weechat_log_printf (" lag_last_refresh . . : %ld", ptr_server->lag_last_refresh); + weechat_log_printf (" lag_next_check . . . : %lld", (long long)ptr_server->lag_next_check); + weechat_log_printf (" lag_last_refresh . . : %lld", (long long)ptr_server->lag_last_refresh); weechat_log_printf (" cmd_list_regexp. . . : 0x%lx", ptr_server->cmd_list_regexp); - weechat_log_printf (" last_user_message. . : %ld", ptr_server->last_user_message); - weechat_log_printf (" last_away_check. . . : %ld", ptr_server->last_away_check); - weechat_log_printf (" last_data_purge. . . : %ld", ptr_server->last_data_purge); + weechat_log_printf (" last_user_message. . : %lld", (long long)ptr_server->last_user_message); + weechat_log_printf (" last_away_check. . . : %lld", (long long)ptr_server->last_away_check); + weechat_log_printf (" last_data_purge. . . : %lld", (long long)ptr_server->last_data_purge); for (i = 0; i < IRC_SERVER_NUM_OUTQUEUES_PRIO; i++) { weechat_log_printf (" outqueue[%02d] . . . . : 0x%lx", i, ptr_server->outqueue[i]); |