diff options
author | Sebastien Helleu <flashcode@flashtux.org> | 2008-11-23 23:04:52 +0100 |
---|---|---|
committer | Sebastien Helleu <flashcode@flashtux.org> | 2008-11-23 23:04:52 +0100 |
commit | 2e52e54a3afa953e12e1e009b19a66202f0674a6 (patch) | |
tree | 08fa64e1c2b89498977ae33004f62c1757288910 /src | |
parent | 09bed16dbd39791b43f86a1c00279c7fdb5cbb58 (diff) | |
download | weechat-2e52e54a3afa953e12e1e009b19a66202f0674a6.zip |
Add support for more than one proxy, with proxy selection for each IRC server (task #6859)
Diffstat (limited to 'src')
32 files changed, 1444 insertions, 271 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index fe6d9f2fd..03c972493 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -27,6 +27,7 @@ wee-input.c wee-input.h wee-list.c wee-list.h wee-log.c wee-log.h wee-network.c wee-network.h +wee-proxy.c wee-proxy.h wee-string.c wee-string.h wee-upgrade.c wee-upgrade.h wee-upgrade-file.c wee-upgrade-file.h diff --git a/src/core/Makefile.am b/src/core/Makefile.am index c2c57442f..61af3722f 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -42,12 +42,14 @@ lib_weechat_core_a_SOURCES = weechat.c \ wee-log.h \ wee-network.c \ wee-network.h \ + wee-proxy.c \ + wee-proxy.h \ + wee-string.c \ + wee-string.h \ wee-upgrade.c \ wee-upgrade.h \ wee-upgrade-file.c \ wee-upgrade-file.h \ - wee-string.c \ - wee-string.h \ wee-utf8.c \ wee-utf8.h \ wee-util.c \ diff --git a/src/core/wee-command.c b/src/core/wee-command.c index 3164e995d..a04f306d7 100644 --- a/src/core/wee-command.c +++ b/src/core/wee-command.c @@ -37,8 +37,9 @@ #include "wee-hook.h" #include "wee-input.h" #include "wee-log.h" -#include "wee-upgrade.h" +#include "wee-proxy.h" #include "wee-string.h" +#include "wee-upgrade.h" #include "wee-utf8.h" #include "wee-list.h" #include "../gui/gui-bar.h" @@ -150,7 +151,6 @@ command_bar (void *data, struct t_gui_buffer *buffer, /* make C compiler happy */ (void) data; - (void) buffer; /* list of bars */ if ((argc == 1) @@ -2218,6 +2218,201 @@ command_plugin (void *data, struct t_gui_buffer *buffer, } /* + * command_proxy_list: list proxies + */ + +void +command_proxy_list () +{ + struct t_proxy *ptr_proxy; + + if (weechat_proxies) + { + gui_chat_printf (NULL, ""); + gui_chat_printf (NULL, _("List of proxies:")); + for (ptr_proxy = weechat_proxies; ptr_proxy; + ptr_proxy = ptr_proxy->next_proxy) + { + gui_chat_printf (NULL, + _(" %s%s%s: %s, %s/%d (%s), username: %s, " + "password: %s"), + GUI_COLOR(GUI_COLOR_CHAT_BUFFER), + ptr_proxy->name, + GUI_COLOR(GUI_COLOR_CHAT), + proxy_type_string[CONFIG_INTEGER(ptr_proxy->type)], + CONFIG_STRING(ptr_proxy->address), + CONFIG_INTEGER(ptr_proxy->port), + (CONFIG_INTEGER(ptr_proxy->ipv6)) ? "IPv6" : "IPv4", + (CONFIG_STRING(ptr_proxy->username) && + CONFIG_STRING(ptr_proxy->username)[0]) ? + CONFIG_STRING(ptr_proxy->username) : _("(none)"), + (CONFIG_STRING(ptr_proxy->password) && + CONFIG_STRING(ptr_proxy->password)[0]) ? + CONFIG_STRING(ptr_proxy->password) : _("(none)")); + } + } + else + gui_chat_printf (NULL, _("No proxy defined")); +} + +/* + * command_proxy: manage proxies + */ + +int +command_proxy (void *data, struct t_gui_buffer *buffer, + int argc, char **argv, char **argv_eol) +{ + int type; + long number; + char *error; + struct t_proxy *ptr_proxy; + + /* make C compiler happy */ + (void) data; + (void) buffer; + + /* list of bars */ + if ((argc == 1) + || ((argc == 2) && (string_strcasecmp (argv[1], "list") == 0))) + { + command_proxy_list (); + return WEECHAT_RC_OK; + } + + /* add a new proxy */ + if (string_strcasecmp (argv[1], "add") == 0) + { + if (argc < 6) + { + gui_chat_printf (NULL, + _("%sError: missing arguments for \"%s\" " + "command"), + gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], + "proxy"); + return WEECHAT_RC_ERROR; + } + type = proxy_search_type (argv[3]); + if (type < 0) + { + gui_chat_printf (NULL, + _("%sError: wrong type \"%s\" for proxy " + "\"%s\""), + gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], + argv[3], argv[2]); + return WEECHAT_RC_ERROR; + } + error = NULL; + number = strtol (argv[5], &error, 10); + if (error && !error[0]) + { + /* create proxy */ + if (proxy_new (argv[2], argv[3], "off", argv[4], argv[5], + (argc >= 7) ? argv[6] : NULL, + (argc >= 8) ? argv_eol[7] : NULL)) + { + gui_chat_printf (NULL, _("Proxy \"%s\" created"), + argv[2]); + } + else + { + gui_chat_printf (NULL, _("%sError: failed to create proxy " + "\"%s\""), + gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], + argv[2]); + } + } + else + { + gui_chat_printf (NULL, + _("%sError: wrong port \"%s\" for proxy " + "\"%s\""), + gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], + argv[5], argv[2]); + return WEECHAT_RC_ERROR; + } + + return WEECHAT_RC_OK; + } + + /* delete a proxy */ + if (string_strcasecmp (argv[1], "del") == 0) + { + if (argc < 3) + { + gui_chat_printf (NULL, + _("%sError: missing arguments for \"%s\" " + "command"), + gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], + "proxy"); + return WEECHAT_RC_ERROR; + } + if (string_strcasecmp (argv[2], "-all") == 0) + { + proxy_free_all (); + gui_chat_printf (NULL, _("All proxies have been deleted")); + } + else + { + ptr_proxy = proxy_search (argv[2]); + if (!ptr_proxy) + { + gui_chat_printf (NULL, + _("%sError: unknown proxy \"%s\""), + gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], + argv[2]); + return WEECHAT_RC_ERROR; + } + proxy_free (ptr_proxy); + gui_chat_printf (NULL, _("Proxy deleted")); + } + + return WEECHAT_RC_OK; + } + + /* set a proxy property */ + if (string_strcasecmp (argv[1], "set") == 0) + { + if (argc < 5) + { + gui_chat_printf (NULL, + _("%sError: missing arguments for \"%s\" " + "command"), + gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], + "proxy"); + return WEECHAT_RC_ERROR; + } + ptr_proxy = proxy_search (argv[2]); + if (!ptr_proxy) + { + gui_chat_printf (NULL, + _("%sError: unknown proxy \"%s\""), + gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], + argv[2]); + return WEECHAT_RC_ERROR; + } + if (!proxy_set (ptr_proxy, argv[3], argv_eol[4])) + { + gui_chat_printf (NULL, + _("%sError: unable to set option \"%s\" for " + "proxy \"%s\""), + gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], + argv[3], argv[2]); + return WEECHAT_RC_ERROR; + } + + return WEECHAT_RC_OK; + } + + gui_chat_printf (NULL, + _("%sError: unknown option for \"%s\" " + "command"), + gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], + "proxy"); + return WEECHAT_RC_ERROR; +} + +/* * command_quit: quit WeeChat */ @@ -3119,7 +3314,7 @@ command_init () "separator item1,item2,...] | [default] | " "[del barname|-all] | [set barname option value] | " "[hide|show barname] | [scroll barname buffer " - "scroll_value] | [list] | [listitems]"), + "scroll_value] | [list] | [listfull] | [listitems]"), N_(" add: add a new bar\n" " barname: name of bar (must be unique)\n" " type: root: outside windows),\n" @@ -3339,6 +3534,36 @@ command_init () "Without argument, this command lists loaded plugins."), "list|listfull|load|autoload|reload|unload %f|%p", &command_plugin, NULL); + hook_command (NULL, "proxy", + N_("manage proxies"), + N_("[add proxyname type address port [username " + "[password]]] | [del proxyname|-all] | [set " + "proxyname option value] | [list]"), + N_(" add: add a new proxy\n" + " proxyname: name of proxy (must be unique)\n" + " type: http, socks4 or socks5\n" + " address: IP or hostname\n" + " port: port\n" + " username: username (optional)\n" + " password: password (optional)\n" + " del: delete a proxy (or all proxies with -all)\n" + " set: set a value for a proxy property\n" + " option: option to change (for options list, look " + "at /set weechat.proxy.<proxyname>.*)\n" + " value: new value for option\n" + " list: list all proxies\n\n" + "Examples:\n" + " create a http proxy, running on local host, port 8888:\n" + " /proxy add local http 127.0.0.1 8888\n" + " create a http proxy using IPv6 protocol:\n" + " /proxy add local http 127.0.0.1 8888\n" + " /proxy set local ipv6 on\n" + " create a socks5 proxy with username/password:\n" + " /proxy add myproxy socks5 sample.host.org 3128 myuser mypass\n" + " delete a proxy:\n" + " /proxy del myproxy"), + "add|del|set|list %y name|type|ipv6|address|port|username|password", + &command_proxy, NULL); hook_command (NULL, "quit", N_("quit WeeChat"), "", "", diff --git a/src/core/wee-config.c b/src/core/wee-config.c index 362ff6692..83f60dfca 100644 --- a/src/core/wee-config.c +++ b/src/core/wee-config.c @@ -39,6 +39,7 @@ #include "wee-log.h" #include "wee-util.h" #include "wee-list.h" +#include "wee-proxy.h" #include "wee-string.h" #include "../gui/gui-bar.h" #include "../gui/gui-buffer.h" @@ -55,6 +56,7 @@ struct t_config_file *weechat_config_file = NULL; struct t_config_section *weechat_config_section_debug = NULL; +struct t_config_section *weechat_config_section_proxy = NULL; struct t_config_section *weechat_config_section_bar = NULL; /* config, startup section */ @@ -162,16 +164,6 @@ struct t_config_option *config_history_max_lines; struct t_config_option *config_history_max_commands; struct t_config_option *config_history_display_default; -/* config, proxy section */ - -struct t_config_option *config_proxy_use; -struct t_config_option *config_proxy_type; -struct t_config_option *config_proxy_ipv6; -struct t_config_option *config_proxy_address; -struct t_config_option *config_proxy_port; -struct t_config_option *config_proxy_username; -struct t_config_option *config_proxy_password; - /* config, plugin section */ struct t_config_option *config_plugin_autoload; @@ -451,6 +443,9 @@ config_weechat_reload (void *data, struct t_config_file *config_file) gui_keyboard_free_all (&gui_keys, &last_gui_key); gui_keyboard_default_bindings (); + /* remove all proxies */ + proxy_free_all (); + /* remove all bars */ gui_bar_free_all (); @@ -465,6 +460,7 @@ config_weechat_reload (void *data, struct t_config_file *config_file) if (rc == WEECHAT_CONFIG_READ_OK) { + proxy_use_temp_proxies (); gui_bar_use_temp_bars (); gui_bar_create_default (); } @@ -618,6 +614,75 @@ config_weechat_debug_set (const char *plugin_name, const char *value) } /* + * config_weechat_proxy_read: read proxy option in config file + */ + +int +config_weechat_proxy_read (void *data, struct t_config_file *config_file, + struct t_config_section *section, + const char *option_name, const char *value) +{ + char *pos_option, *proxy_name; + struct t_proxy *ptr_temp_proxy; + int index_option; + + /* make C compiler happy */ + (void) data; + (void) config_file; + (void) section; + + if (option_name) + { + pos_option = strchr (option_name, '.'); + if (pos_option) + { + proxy_name = string_strndup (option_name, pos_option - option_name); + if (proxy_name) + { + pos_option++; + for (ptr_temp_proxy = weechat_temp_proxies; ptr_temp_proxy; + ptr_temp_proxy = ptr_temp_proxy->next_proxy) + { + if (strcmp (ptr_temp_proxy->name, proxy_name) == 0) + break; + } + if (!ptr_temp_proxy) + { + /* create new temp proxy */ + ptr_temp_proxy = proxy_alloc (proxy_name); + if (ptr_temp_proxy) + { + /* add new temp proxy at end of queue */ + ptr_temp_proxy->prev_proxy = last_weechat_temp_proxy; + ptr_temp_proxy->next_proxy = NULL; + + if (!weechat_temp_proxies) + weechat_temp_proxies = ptr_temp_proxy; + else + last_weechat_temp_proxy->next_proxy = ptr_temp_proxy; + last_weechat_temp_proxy = ptr_temp_proxy; + } + } + + if (ptr_temp_proxy) + { + index_option = proxy_search_option (pos_option); + if (index_option >= 0) + { + proxy_create_option_temp (ptr_temp_proxy, index_option, + value); + } + } + + free (proxy_name); + } + } + } + + return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE; +} + +/* * config_weechat_bar_read: read bar option in config file */ @@ -1657,54 +1722,21 @@ config_weechat_init () N_("maximum number of commands to display by default in " "history listing (0 = unlimited)"), NULL, 0, INT_MAX, "5", NULL, NULL, NULL, NULL, NULL, NULL, NULL); - - /* proxy */ + + /* proxies */ ptr_section = config_file_new_section (weechat_config_file, "proxy", 0, 0, + &config_weechat_proxy_read, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL); + NULL, NULL); if (!ptr_section) { config_file_free (weechat_config_file); return 0; } - config_proxy_use = config_file_new_option ( - weechat_config_file, ptr_section, - "use", "boolean", - N_("use a proxy server"), - NULL, 0, 0, "off", NULL, NULL, NULL, NULL, NULL, NULL, NULL); - config_proxy_type = config_file_new_option ( - weechat_config_file, ptr_section, - "type", "integer", - N_("proxy type (http (default), socks4, socks5)"), - "http|socks4|socks5", 0, 0, "http", NULL, NULL, NULL, NULL, NULL, NULL, NULL); - config_proxy_ipv6 = config_file_new_option ( - weechat_config_file, ptr_section, - "ipv6", "boolean", - N_("connect to proxy using ipv6"), - NULL, 0, 0, "off", NULL, NULL, NULL, NULL, NULL, NULL, NULL); - config_proxy_address = config_file_new_option ( - weechat_config_file, ptr_section, - "address", "string", - N_("proxy server address (IP or hostname)"), - NULL, 0, 0, "", NULL, NULL, NULL, NULL, NULL, NULL, NULL); - config_proxy_port = config_file_new_option ( - weechat_config_file, ptr_section, - "port", "integer", - N_("port for connecting to proxy server"), - NULL, 0, 65535, "3128", NULL, NULL, NULL, NULL, NULL, NULL, NULL); - config_proxy_username = config_file_new_option ( - weechat_config_file, ptr_section, - "username", "string", - N_("username for proxy server"), - NULL, 0, 0, "", NULL, NULL, NULL, NULL, NULL, NULL, NULL); - config_proxy_password = config_file_new_option ( - weechat_config_file, ptr_section, - "password", "string", - N_("password for proxy server"), - NULL, 0, 0, "", NULL, NULL, NULL, NULL, NULL, NULL, NULL); - + weechat_config_section_proxy = ptr_section; + /* plugin */ ptr_section = config_file_new_section (weechat_config_file, "plugin", 0, 0, @@ -1826,6 +1858,7 @@ config_weechat_read () if (rc == WEECHAT_CONFIG_READ_OK) { config_change_day_change (NULL, NULL); + proxy_use_temp_proxies (); gui_bar_use_temp_bars (); gui_bar_create_default (); } diff --git a/src/core/wee-config.h b/src/core/wee-config.h index 9def6d0e5..0cdd30777 100644 --- a/src/core/wee-config.h +++ b/src/core/wee-config.h @@ -65,14 +65,8 @@ enum t_config_look_save_layout_on_exit CONFIG_LOOK_SAVE_LAYOUT_ON_EXIT_ALL, }; -enum t_config_proxy_type -{ - CONFIG_PROXY_TYPE_HTTP = 0, - CONFIG_PROXY_TYPE_SOCKS4, - CONFIG_PROXY_TYPE_SOCKS5, -}; - extern struct t_config_file *weechat_config_file; +extern struct t_config_section *weechat_config_section_proxy; extern struct t_config_section *weechat_config_section_bar; extern struct t_config_option *config_startup_command_after_plugins; @@ -170,14 +164,6 @@ extern struct t_config_option *config_history_max_lines; extern struct t_config_option *config_history_max_commands; extern struct t_config_option *config_history_display_default; -extern struct t_config_option *config_proxy_use; -extern struct t_config_option *config_proxy_type; -extern struct t_config_option *config_proxy_ipv6; -extern struct t_config_option *config_proxy_address; -extern struct t_config_option *config_proxy_port; -extern struct t_config_option *config_proxy_username; -extern struct t_config_option *config_proxy_password; - extern struct t_config_option *config_plugin_autoload; extern struct t_config_option *config_plugin_debug; extern struct t_config_option *config_plugin_extension; diff --git a/src/core/wee-hook.c b/src/core/wee-hook.c index 6c1bfb8b1..8e8627974 100644 --- a/src/core/wee-hook.c +++ b/src/core/wee-hook.c @@ -919,8 +919,9 @@ hook_fd_exec (fd_set *read_fds, fd_set *write_fds, fd_set *exception_fds) */ struct t_hook * -hook_connect (struct t_weechat_plugin *plugin, const char *address, int port, - int sock, int ipv6, void *gnutls_sess, const char *local_hostname, +hook_connect (struct t_weechat_plugin *plugin, const char *proxy, + const char *address, int port, int sock, int ipv6, + void *gnutls_sess, const char *local_hostname, t_hook_callback_connect *callback, void *callback_data) { struct t_hook *new_hook; @@ -948,6 +949,7 @@ hook_connect (struct t_weechat_plugin *plugin, const char *address, int port, new_hook->hook_data = new_hook_connect; new_hook_connect->callback = callback; + new_hook_connect->proxy = (proxy) ? strdup (proxy) : NULL; new_hook_connect->address = strdup (address); new_hook_connect->port = port; new_hook_connect->sock = sock; diff --git a/src/core/wee-hook.h b/src/core/wee-hook.h index 0b130e1b8..6e6dd0c27 100644 --- a/src/core/wee-hook.h +++ b/src/core/wee-hook.h @@ -128,6 +128,7 @@ typedef int (t_hook_callback_connect)(void *data, int status, struct t_hook_connect { t_hook_callback_connect *callback; /* connect callback */ + char *proxy; /* proxy (optional) */ char *address; /* peer address */ int port; /* peer port */ int sock; /* socket (created by caller) */ @@ -256,8 +257,9 @@ extern int hook_fd_set (fd_set *read_fds, fd_set *write_fds, extern void hook_fd_exec (fd_set *read_fds, fd_set *write_fds, fd_set *exception_fds); extern struct t_hook *hook_connect (struct t_weechat_plugin *plugin, - const char *address, int port, - int sock, int ipv6, void *gnutls_session, + const char *proxy, const char *address, + int port, int sock, int ipv6, + void *gnutls_session, const char *local_hostname, t_hook_callback_connect *callback, void *callback_data); diff --git a/src/core/wee-network.c b/src/core/wee-network.c index d4888c984..e30ecf7ef 100644 --- a/src/core/wee-network.c +++ b/src/core/wee-network.c @@ -41,6 +41,7 @@ #include "wee-network.h" #include "wee-hook.h" #include "wee-config.h" +#include "wee-proxy.h" #include "wee-string.h" #include "../plugins/plugin.h" @@ -154,19 +155,20 @@ network_base64encode (const char *from, char *to) */ int -network_pass_httpproxy (int sock, const char *address, int port) +network_pass_httpproxy (struct t_proxy *proxy, int sock, const char *address, + int port) { char buffer[256], authbuf[128], authbuf_base64[196]; int n, m; - if (CONFIG_STRING(config_proxy_username) - && CONFIG_STRING(config_proxy_username)[0]) + if (CONFIG_STRING(proxy->username) + && CONFIG_STRING(proxy->username)[0]) { /* authentification */ snprintf (authbuf, sizeof (authbuf), "%s:%s", - CONFIG_STRING(config_proxy_username), - (CONFIG_STRING(config_proxy_password)) ? - CONFIG_STRING(config_proxy_password) : ""); + CONFIG_STRING(proxy->username), + (CONFIG_STRING(proxy->password)) ? + CONFIG_STRING(proxy->password) : ""); network_base64encode (authbuf, authbuf_base64); n = snprintf (buffer, sizeof (buffer), "CONNECT %s:%d HTTP/1.0\r\nProxy-Authorization: Basic %s\r\n\r\n", @@ -248,22 +250,12 @@ network_resolve (const char *hostname, char *ip, int *version) */ int -network_pass_socks4proxy (int sock, const char *address, int port) +network_pass_socks4proxy (struct t_proxy *proxy, int sock, const char *address, + int port) { - /* - * socks4 protocol is explained here: - * http://en.wikipedia.org/wiki/SOCKS - * - */ + /* socks4 protocol is explained here: http://en.wikipedia.org/wiki/SOCKS */ - struct s_socks4 - { - char version; /* 1 byte */ /* socks version : 4 or 5 */ - char method; /* 1 byte */ /* socks method : connect (1) or bind (2) */ - unsigned short port; /* 2 bytes */ /* destination port */ - unsigned int address; /* 4 bytes */ /* destination address */ - char user[64]; /* username (64 characters seems to be enought) */ - } socks4; + struct t_network_socks4 socks4; unsigned char buffer[24]; char ip_addr[NI_MAXHOST]; @@ -272,7 +264,7 @@ network_pass_socks4proxy (int sock, const char *address, int port) socks4.port = htons (port); network_resolve (address, ip_addr, NULL); socks4.address = inet_addr (ip_addr); - strncpy (socks4.user, CONFIG_STRING(config_proxy_username), + strncpy (socks4.user, CONFIG_STRING(proxy->username), sizeof (socks4.user) - 1); send (sock, (char *) &socks4, 8 + strlen (socks4.user) + 1, 0); @@ -294,19 +286,15 @@ network_pass_socks4proxy (int sock, const char *address, int port) */ int -network_pass_socks5proxy (int sock, const char *address, int port) +network_pass_socks5proxy (struct t_proxy *proxy, int sock, const char *address, + int port) { /* * socks5 protocol is explained in RFC 1928 * socks5 authentication with username/pass is explained in RFC 1929 */ - struct s_sock5 - { - char version; /* 1 byte */ /* socks version : 4 or 5 */ - char nmethods; /* 1 byte */ /* size in byte(s) of field 'method', here 1 byte */ - char method; /* 1-255 bytes */ /* socks method : noauth (0), auth(user/pass) (2), ... */ - } socks5; + struct t_network_socks5 socks5; unsigned char buffer[288]; int username_len, password_len, addr_len, addr_buffer_len; unsigned char *addr_buffer; @@ -314,8 +302,8 @@ network_pass_socks5proxy (int sock, const char *address, int port) socks5.version = 5; socks5.nmethods = 1; - if (CONFIG_STRING(config_proxy_username) - && CONFIG_STRING(config_proxy_username)[0]) + if (CONFIG_STRING(proxy->username) + && CONFIG_STRING(proxy->username)[0]) socks5.method = 2; /* with authentication */ else socks5.method = 0; /* without authentication */ @@ -325,8 +313,8 @@ network_pass_socks5proxy (int sock, const char *address, int port) if (recv (sock, buffer, 2, 0) != 2) return 0; - if (CONFIG_STRING(config_proxy_username) - && CONFIG_STRING(config_proxy_username)[0]) + if (CONFIG_STRING(proxy->username) + && CONFIG_STRING(proxy->username)[0]) { /* with authentication */ /* -> socks server must respond with : @@ -338,16 +326,16 @@ network_pass_socks5proxy (int sock, const char *address, int port) return 0; /* authentication as in RFC 1929 */ - username_len = strlen (CONFIG_STRING(config_proxy_username)); - password_len = strlen (CONFIG_STRING(config_proxy_password)); + username_len = strlen (CONFIG_STRING(proxy->username)); + password_len = strlen (CONFIG_STRING(proxy->password)); /* make username/password buffer */ buffer[0] = 1; buffer[1] = (unsigned char) username_len; - memcpy(buffer + 2, CONFIG_STRING(config_proxy_username), username_len); + memcpy(buffer + 2, CONFIG_STRING(proxy->username), username_len); buffer[2 + username_len] = (unsigned char) password_len; memcpy (buffer + 3 + username_len, - CONFIG_STRING(config_proxy_password), password_len); + CONFIG_STRING(proxy->password), password_len); send (sock, buffer, 3 + username_len + password_len, 0); @@ -440,23 +428,26 @@ network_pass_socks5proxy (int sock, const char *address, int port) */ int -network_pass_proxy (int sock, const char *address, int port) +network_pass_proxy (const char *proxy, int sock, const char *address, int port) { int rc; + struct t_proxy *ptr_proxy; rc = 0; - if (CONFIG_BOOLEAN(config_proxy_use)) + + ptr_proxy = proxy_search (proxy); + if (ptr_proxy) { - switch (CONFIG_INTEGER(config_proxy_type)) + switch (CONFIG_INTEGER(ptr_proxy->type)) { - case CONFIG_PROXY_TYPE_HTTP: - rc = network_pass_httpproxy (sock, address, port); + case PROXY_TYPE_HTTP: + rc = network_pass_httpproxy (ptr_proxy, sock, address, port); break; - case CONFIG_PROXY_TYPE_SOCKS4: - rc = network_pass_socks4proxy (sock, address, port); + case PROXY_TYPE_SOCKS4: + rc = network_pass_socks4proxy (ptr_proxy, sock, address, port); break; - case CONFIG_PROXY_TYPE_SOCKS5: - rc = network_pass_socks5proxy (sock, address, port); + case PROXY_TYPE_SOCKS5: + rc = network_pass_socks5proxy (ptr_proxy, sock, address, port); break; } } @@ -470,30 +461,40 @@ network_pass_proxy (int sock, const char *address, int port) */ int -network_connect_to (int sock, unsigned long address, int port) +network_connect_to (const char *proxy, int sock, + unsigned long address, int port) { + struct t_proxy *ptr_proxy; struct sockaddr_in addr; struct hostent *hostent; char *ip4; int ret; - if (CONFIG_BOOLEAN(config_proxy_use)) + ptr_proxy = NULL; + if (proxy && proxy[0]) + { + ptr_proxy = proxy_search (proxy); + if (!ptr_proxy) + return 0; + } + + if (ptr_proxy) { memset (&addr, 0, sizeof (addr)); addr.sin_addr.s_addr = htonl (address); ip4 = inet_ntoa(addr.sin_addr); memset (&addr, 0, sizeof (addr)); - addr.sin_port = htons (CONFIG_INTEGER(config_proxy_port)); + addr.sin_port = htons (CONFIG_INTEGER(ptr_proxy->port)); addr.sin_family = AF_INET; - hostent = gethostbyname (CONFIG_STRING(config_proxy_address)); + hostent = gethostbyname (CONFIG_STRING(ptr_proxy->address)); if (!hostent) return 0; memcpy(&(addr.sin_addr), *(hostent->h_addr_list), sizeof(struct in_addr)); ret = connect (sock, (struct sockaddr *) &addr, sizeof (addr)); if ((ret == -1) && (errno != EINPROGRESS)) return 0; - if (!network_pass_proxy (sock, ip4, port)) + if (!network_pass_proxy (proxy, sock, ip4, port)) return 0; } else @@ -516,6 +517,7 @@ network_connect_to (int sock, unsigned long address, int port) void network_connect_child (struct t_hook *hook_connect) { + struct t_proxy *ptr_proxy; struct addrinfo hints, *res, *res_local, *ptr_res; char status_str[2], *ptr_address, *status_ok_with_address; char ipv4_address[INET_ADDRSTRLEN + 1], ipv6_address[INET6_ADDRSTRLEN + 1]; @@ -527,13 +529,27 @@ network_connect_child (struct t_hook *hook_connect) status_str[1] = '\0'; - if (CONFIG_BOOLEAN(config_proxy_use)) + ptr_proxy = NULL; + if (HOOK_CONNECT(hook_connect, proxy) + && HOOK_CONNECT(hook_connect, proxy)[0]) + { + ptr_proxy = proxy_search (HOOK_CONNECT(hook_connect, proxy)); + if (!ptr_proxy) + { + /* proxy not found */ + status_str[0] = '0' + WEECHAT_HOOK_CONNECT_PROXY_ERROR; + write (HOOK_CONNECT(hook_connect, child_write), status_str, 1); + return; + } + } + + if (ptr_proxy) { /* get info about peer */ memset (&hints, 0, sizeof (hints)); - hints.ai_family = (CONFIG_BOOLEAN(config_proxy_ipv6)) ? AF_INET6 : AF_INET; + hints.ai_family = (CONFIG_BOOLEAN(ptr_proxy->ipv6)) ? AF_INET6 : AF_INET; hints.ai_socktype = SOCK_STREAM; - if (getaddrinfo (CONFIG_STRING(config_proxy_address), NULL, &hints, &res) !=0) + if (getaddrinfo (CONFIG_STRING(ptr_proxy->address), NULL, &hints, &res) !=0) { /* address not found */ status_str[0] = '0' + WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND; @@ -547,8 +563,8 @@ network_connect_child (struct t_hook *hook_connect) write (HOOK_CONNECT(hook_connect, child_write), status_str, 1); return; } - if ((CONFIG_BOOLEAN(config_proxy_ipv6) && (res->ai_family != AF_INET6)) - || ((!CONFIG_BOOLEAN(config_proxy_ipv6) && (res->ai_family != AF_INET)))) + if ((CONFIG_BOOLEAN(ptr_proxy->ipv6) && (res->ai_family != AF_INET6)) + || ((!CONFIG_BOOLEAN(ptr_proxy->ipv6) && (res->ai_family != AF_INET)))) { /* IP address not found */ status_str[0] = '0' + WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND; @@ -557,10 +573,10 @@ network_connect_child (struct t_hook *hook_connect) return; } - if (CONFIG_BOOLEAN(config_proxy_ipv6)) - ((struct sockaddr_in6 *)(res->ai_addr))->sin6_port = htons (CONFIG_INTEGER(config_proxy_port)); + if (CONFIG_BOOLEAN(ptr_proxy->ipv6)) + ((struct sockaddr_in6 *)(res->ai_addr))->sin6_port = htons (CONFIG_INTEGER(ptr_proxy->port)); else - ((struct sockaddr_in *)(res->ai_addr))->sin_port = htons (CONFIG_INTEGER(config_proxy_port)); + ((struct sockaddr_in *)(res->ai_addr))->sin_port = htons (CONFIG_INTEGER(ptr_proxy->port)); /* connect to peer */ if (connect (HOOK_CONNECT(hook_connect, sock), @@ -573,7 +589,8 @@ network_connect_child (struct t_hook *hook_connect) return; } - if (!network_pass_proxy (HOOK_CONNECT(hook_connect, sock), + if (!network_pass_proxy (HOOK_CONNECT(hook_connect, proxy), + HOOK_CONNECT(hook_connect, sock), HOOK_CONNECT(hook_connect, address), HOOK_CONNECT(hook_connect, port))) { @@ -583,7 +600,7 @@ network_connect_child (struct t_hook *hook_connect) freeaddrinfo (res); return; } - + status_str[0] = '0' + WEECHAT_HOOK_CONNECT_OK; } else diff --git a/src/core/wee-network.h b/src/core/wee-network.h index 4f8031d57..056735751 100644 --- a/src/core/wee-network.h +++ b/src/core/wee-network.h @@ -22,10 +22,30 @@ struct t_hook; +struct t_network_socks4 +{ + char version; /* 1 byte : socks version: 4 or 5 */ + char method; /* 1 byte : socks method: connect (1) or bind (2) */ + unsigned short port; /* 2 bytes: destination port */ + unsigned int address; /* 4 bytes: destination address */ + char user[128]; /* username */ +}; + +struct t_network_socks5 +{ + char version; /* 1 byte: socks version : 4 or 5 */ + char nmethods; /* 1 byte: size in byte(s) of field 'method', */ + /* here 1 byte */ + char method; /* 1 byte: socks method : noauth (0), */ + /* auth(user/pass) (2), ... */ +}; + extern void network_init (); extern void network_end (); -extern int network_pass_proxy (int sock, const char *address, int port); -extern int network_connect_to (int sock, unsigned long address, int port); -extern void network_connect_with_fork (struct t_hook *); +extern int network_pass_proxy (const char *proxy, int sock, + const char *address, int port); +extern int network_connect_to (const char *proxy, int sock, + unsigned long address, int port); +extern void network_connect_with_fork (struct t_hook *hook_connect); #endif /* wee-network.h */ diff --git a/src/core/wee-proxy.c b/src/core/wee-proxy.c new file mode 100644 index 000000000..5c25c3431 --- /dev/null +++ b/src/core/wee-proxy.c @@ -0,0 +1,659 @@ +/* + * Copyright (c) 2003-2008 by FlashCode <flashcode@flashtux.org> + * See README for License detail, AUTHORS for developers list. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* wee-proxy.c: proxy functions */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdlib.h> +#include <string.h> + +#include "weechat.h" +#include "wee-proxy.h" +#include "wee-config.h" +#include "wee-log.h" +#include "wee-string.h" + + +char *proxy_option_string[PROXY_NUM_OPTIONS] = +{ "type", "ipv6", "address", "port", "username", "password" }; +char *proxy_type_string[PROXY_NUM_TYPES] = +{ "http", "socks4", "socks5" }; + +struct t_proxy *weechat_proxies = NULL; /* first proxy */ +struct t_proxy *last_weechat_proxy = NULL; /* last proxy */ + +struct t_proxy *weechat_temp_proxies = NULL; /* proxies used when */ +struct t_proxy *last_weechat_temp_proxy = NULL; /* reading config */ + + +/* + * proxy_search_option search a proxy option name + * return index of option in array + * "proxy_option_string", or -1 if not found + */ + +int +proxy_search_option (const char *option_name) +{ + int i; + + if (!option_name) + return -1; + + for (i = 0; i < PROXY_NUM_OPTIONS; i++) + { + if (string_strcasecmp (proxy_option_string[i], option_name) == 0) + return i; + } + + /* proxy option not found */ + return -1; +} + +/* + * proxy_search_type: search type number with string + * return -1 if type is not found + */ + +int +proxy_search_type (const char *type) +{ + int i; + + if (!type) + return -1; + + for (i = 0; i < PROXY_NUM_TYPES; i++) + { + if (string_strcasecmp (proxy_type_string[i], type) == 0) + return i; + } + + /* type not found */ + return -1; +} + +/* + * proxy_search: search a proxy by name + */ + +struct t_proxy * +proxy_search (const char *name) +{ + struct t_proxy *ptr_proxy; + + if (!name || !name[0]) + return NULL; + + for (ptr_proxy = weechat_proxies; ptr_proxy; + ptr_proxy = ptr_proxy->next_proxy) + { + if (strcmp (ptr_proxy->name, name) == 0) + return ptr_proxy; + } + + /* proxy not found */ + return NULL; +} + +/* + * proxy_search_with_option_name: search a proxy with name of option + * (like "local_proxy.address") + */ + +struct t_proxy * +proxy_search_with_option_name (const char *option_name) +{ + char *proxy_name, *pos_option; + struct t_proxy *ptr_proxy; + + ptr_proxy = NULL; + + pos_option = strchr (option_name, '.'); + if (pos_option) + { + proxy_name = string_strndup (option_name, pos_option - option_name); + if (proxy_name) + { + for (ptr_proxy = weechat_proxies; ptr_proxy; + ptr_proxy = ptr_proxy->next_proxy) + { + if (strcmp (ptr_proxy->name, proxy_name) == 0) + break; + } + free (proxy_name); + } + } + + return ptr_proxy; +} + +/* + * proxy_set_name: set name for a proxy + */ + +void +proxy_set_name (struct t_proxy *proxy, const char *name) +{ + int length; + char *option_name; + + if (!name || !name[0]) + return; + + length = strlen (name) + 64; + option_name = malloc (length); + if (option_name) + { + snprintf (option_name, length, "%s.type", name); + config_file_option_rename (proxy->type, option_name); + snprintf (option_name, length, "%s.ipv6", name); + config_file_option_rename (proxy->ipv6, option_name); + snprintf (option_name, length, "%s.address", name); + config_file_option_rename (proxy->address, option_name); + snprintf (option_name, length, "%s.port", name); + config_file_option_rename (proxy->port, option_name); + snprintf (option_name, length, "%s.username", name); + config_file_option_rename (proxy->username, option_name); + snprintf (option_name, length, "%s.password", name); + config_file_option_rename (proxy->password, option_name); + + if (proxy->name) + free (proxy->name); + proxy->name = strdup (name); + + free (option_name); + } +} + +/* + * proxy_set: set a property for a proxy + * return: 1 if ok, 0 if error + */ + +int +proxy_set (struct t_proxy *proxy, const char *property, const char *value) +{ + if (!proxy || !property || !value) + return 0; + + if (string_strcasecmp (property, "name") == 0) + { + proxy_set_name (proxy, value); + return 1; + } + else if (string_strcasecmp (property, "type") == 0) + { + config_file_option_set (proxy->type, value, 1); + return 1; + } + else if (string_strcasecmp (property, "ipv6") == 0) + { + config_file_option_set (proxy->ipv6, value, 1); + return 1; + } + else if (string_strcasecmp (property, "address") == 0) + { + config_file_option_set (proxy->address, value, 1); + return 1; + } + else if (string_strcasecmp (property, "port") == 0) + { + config_file_option_set (proxy->port, value, 1); + return 1; + } + else if (string_strcasecmp (property, "username") == 0) + { + config_file_option_set (proxy->username, value, 1); + return 1; + } + else if (string_strcasecmp (property, "password") == 0) + { + config_file_option_set (proxy->password, value, 1); + return 1; + } + + return 0; +} + +/* + * proxy_create_option: create an option for a proxy + */ + +struct t_config_option * +proxy_create_option (const char *proxy_name, int index_option, + const char *value) +{ + struct t_config_option *ptr_option; + int length; + char *option_name; + + ptr_option = NULL; + + length = strlen (proxy_name) + 1 + + strlen (proxy_option_string[index_option]) + 1; + option_name = malloc (length); + if (option_name) + { + snprintf (option_name, length, "%s.%s", + proxy_name, proxy_option_string[index_option]); + + switch (index_option) + { + case PROXY_OPTION_TYPE: + ptr_option = config_file_new_option ( + weechat_config_file, weechat_config_section_proxy, + option_name, "integer", + N_("proxy type (http (default), socks4, socks5)"), + "http|socks4|socks5", 0, 0, value, NULL, + NULL, NULL, NULL, NULL, NULL, NULL); + break; + case PROXY_OPTION_IPV6: + ptr_option = config_file_new_option ( + weechat_config_file, weechat_config_section_proxy, + option_name, "boolean", + N_("connect to proxy using ipv6"), + NULL, 0, 0, value, NULL, + NULL, NULL, NULL, NULL, NULL, NULL); + break; + case PROXY_OPTION_ADDRESS: + ptr_option = config_file_new_option ( + weechat_config_file, weechat_config_section_proxy, + option_name, "string", + N_("proxy server address (IP or hostname)"), + NULL, 0, 0, value, NULL, + NULL, NULL, NULL, NULL, NULL, NULL); + break; + case PROXY_OPTION_PORT: + ptr_option = config_file_new_option ( + weechat_config_file, weechat_config_section_proxy, + option_name, "integer", + N_("port for connecting to proxy server"), + NULL, 0, 65535, value, NULL, + NULL, NULL, NULL, NULL, NULL, NULL); + break; + case PROXY_OPTION_USERNAME: + ptr_option = config_file_new_option ( + weechat_config_file, weechat_config_section_proxy, + option_name, "string", + N_("username for proxy server"), + NULL, 0, 0, value, NULL, + NULL, NULL, NULL, NULL, NULL, NULL); + break; + case PROXY_OPTION_PASSWORD: + ptr_option = config_file_new_option ( + weechat_config_file, weechat_config_section_proxy, + option_name, "string", + N_("password for proxy server"), + NULL, 0, 0, value, NULL, + NULL, NULL, NULL, NULL, NULL, NULL); + break; + case PROXY_NUM_OPTIONS: + break; + } + free (option_name); + } + + return ptr_option; +} + +/* + * proxy_create_option_temp: create option for a temporary proxy (when reading + * config file) + */ + +void +proxy_create_option_temp (struct t_proxy *temp_proxy, int index_option, + const char *value) +{ + struct t_config_option *new_option; + + new_option = proxy_create_option (temp_proxy->name, + index_option, + value); + if (new_option) + { + switch (index_option) + { + case PROXY_OPTION_TYPE: + temp_proxy->type = new_option; + break; + case PROXY_OPTION_IPV6: + temp_proxy->ipv6 = new_option; + break; + case PROXY_OPTION_ADDRESS: + temp_proxy->address = new_option; + break; + case PROXY_OPTION_PORT: + temp_proxy->port = new_option; + break; + case PROXY_OPTION_USERNAME: + temp_proxy->username = new_option; + break; + case PROXY_OPTION_PASSWORD: + temp_proxy->password = new_option; + break; + } + } +} + +/* + * proxy_alloc: allocate and initialize new proxy structure + */ + +struct t_proxy * +proxy_alloc (const char *name) +{ + struct t_proxy *new_proxy; + + new_proxy = malloc (sizeof (*new_proxy)); + if (new_proxy) + { + new_proxy->name = strdup (name); + new_proxy->type = NULL; + new_proxy->ipv6 = NULL; + new_proxy->address = NULL; + new_proxy->port = NULL; + new_proxy->username = NULL; + new_proxy->password = NULL; + new_proxy->prev_proxy = NULL; + new_proxy->next_proxy = NULL; + } + + return new_proxy; +} + +/* + * proxy_new_with_options: create a new proxy with options + */ + +struct t_proxy * +proxy_new_with_options (const char *name, + struct t_config_option *type, + struct t_config_option *ipv6, + struct t_config_option *address, + struct t_config_option *port, + struct t_config_option *username, + struct t_config_option *password) +{ + struct t_proxy *new_proxy; + + /* create proxy */ + new_proxy = proxy_alloc (name); + if (new_proxy) + { + new_proxy->type = type; + new_proxy->ipv6 = ipv6; + new_proxy->address = address; + new_proxy->port = port; + new_proxy->username = username; + new_proxy->password = password; + + /* add proxy to proxies list */ + new_proxy->prev_proxy = last_weechat_proxy; + if (weechat_proxies) + last_weechat_proxy->next_proxy = new_proxy; + else + weechat_proxies = new_proxy; + last_weechat_proxy = new_proxy; + new_proxy->next_proxy = NULL; + } + + return new_proxy; +} + +/* + * proxy_new: create a new proxy + */ + +struct t_proxy * +proxy_new (const char *name, const char *type, const char *ipv6, + const char *address, const char *port, const char *username, + const char *password) +{ + struct t_config_option *option_type, *option_ipv6, *option_address; + struct t_config_option *option_port, *option_username, *option_password; + struct t_proxy *new_proxy; + + if (!name || !name[0]) + return NULL; + + /* it's not possible to create 2 proxies with same name */ + if (proxy_search (name)) + return NULL; + + /* look for type */ + if (proxy_search_type (type) < 0) + return NULL; + + option_type = proxy_create_option (name, PROXY_OPTION_TYPE, + type); + option_ipv6 = proxy_create_option (name, PROXY_OPTION_IPV6, + ipv6); + option_address = proxy_create_option (name, PROXY_OPTION_ADDRESS, + (address) ? address : ""); + option_port = proxy_create_option (name, PROXY_OPTION_PORT, + port); + option_username = proxy_create_option (name, PROXY_OPTION_USERNAME, + (username) ? username : ""); + option_password = proxy_create_option (name, PROXY_OPTION_PASSWORD, + (password) ? password : ""); + + new_proxy = proxy_new_with_options (name, option_type, option_ipv6, + option_address, option_port, + option_username, option_password); + if (!new_proxy) + { + if (option_type) + config_file_option_free (option_type); + if (option_ipv6) + config_file_option_free (option_ipv6); + if (option_address) + config_file_option_free (option_address); + if (option_port) + config_file_option_free (option_port); + if (option_username) + config_file_option_free (option_username); + if (option_password) + config_file_option_free (option_password); + } + + return new_proxy; +} + +/* + * proxy_use_temp_proxies: use temp proxies (created by reading config file) + */ + +void +proxy_use_temp_proxies () +{ + struct t_proxy *ptr_temp_proxy, *next_temp_proxy; + + for (ptr_temp_proxy = weechat_temp_proxies; ptr_temp_proxy; + ptr_temp_proxy = ptr_temp_proxy->next_proxy) + { + if (!ptr_temp_proxy->type) + ptr_temp_proxy->type = proxy_create_option (ptr_temp_proxy->name, + PROXY_OPTION_TYPE, + "http"); + if (!ptr_temp_proxy->ipv6) + ptr_temp_proxy->ipv6 = proxy_create_option (ptr_temp_proxy->name, + PROXY_OPTION_IPV6, + "off"); + if (!ptr_temp_proxy->address) + ptr_temp_proxy->address = proxy_create_option (ptr_temp_proxy->name, + PROXY_OPTION_ADDRESS, + "127.0.0.1"); + if (!ptr_temp_proxy->port) + ptr_temp_proxy->port = proxy_create_option (ptr_temp_proxy->name, + PROXY_OPTION_PORT, + "3128"); + if (!ptr_temp_proxy->username) + ptr_temp_proxy->username = proxy_create_option (ptr_temp_proxy->name, + PROXY_OPTION_USERNAME, + ""); + if (!ptr_temp_proxy->password) + ptr_temp_proxy->password = proxy_create_option (ptr_temp_proxy->name, + PROXY_OPTION_PASSWORD, + ""); + + if (ptr_temp_proxy->type && ptr_temp_proxy->ipv6 + && ptr_temp_proxy->address && ptr_temp_proxy->port + && ptr_temp_proxy->username && ptr_temp_proxy->password) + { + proxy_new_with_options (ptr_temp_proxy->name, + ptr_temp_proxy->type, + ptr_temp_proxy->ipv6, + ptr_temp_proxy->address, + ptr_temp_proxy->port, + ptr_temp_proxy->username, + ptr_temp_proxy->password); + } + else + { + if (ptr_temp_proxy->type) + { + config_file_option_free (ptr_temp_proxy->type); + ptr_temp_proxy->type = NULL; + } + if (ptr_temp_proxy->ipv6) + { + config_file_option_free (ptr_temp_proxy->ipv6); + ptr_temp_proxy->ipv6 = NULL; + } + if (ptr_temp_proxy->address) + { + config_file_option_free (ptr_temp_proxy->address); + ptr_temp_proxy->address = NULL; + } + if (ptr_temp_proxy->port) + { + config_file_option_free (ptr_temp_proxy->port); + ptr_temp_proxy->port = NULL; + } + if (ptr_temp_proxy->username) + { + config_file_option_free (ptr_temp_proxy->username); + ptr_temp_proxy->username = NULL; + } + if (ptr_temp_proxy->password) + { + config_file_option_free (ptr_temp_proxy->password); + ptr_temp_proxy->password = NULL; + } + } + } + + /* free all temp proxies */ + while (weechat_temp_proxies) + { + next_temp_proxy = weechat_temp_proxies->next_proxy; + + if (weechat_temp_proxies->name) + free (weechat_temp_proxies->name); + free (weechat_temp_proxies); + + weechat_temp_proxies = next_temp_proxy; + } + last_weechat_temp_proxy = NULL; +} + +/* + * proxy_free: delete a proxy + */ + +void +proxy_free (struct t_proxy *proxy) +{ + if (!proxy) + return; + + /* remove proxy from proxies list */ + if (proxy->prev_proxy) + (proxy->prev_proxy)->next_proxy = proxy->next_proxy; + if (proxy->next_proxy) + (proxy->next_proxy)->prev_proxy = proxy->prev_proxy; + if (weechat_proxies == proxy) + weechat_proxies = proxy->next_proxy; + if (last_weechat_proxy == proxy) + last_weechat_proxy = proxy->prev_proxy; + + /* free data */ + if (proxy->name) + free (proxy->name); + if (proxy->type) + config_file_option_free (proxy->type); + if (proxy->ipv6) + config_file_option_free (proxy->ipv6); + if (proxy->address) + config_file_option_free (proxy->address); + if (proxy->port) + config_file_option_free (proxy->port); + if (proxy->username) + config_file_option_free (proxy->username); + if (proxy->password) + config_file_option_free (proxy->password); + + free (proxy); +} + +/* + * proxy_free_all: delete all proxies + */ + +void +proxy_free_all () +{ + while (weechat_proxies) + { + proxy_free (weechat_proxies); + } +} + +/* + * proxy_print_log: print proxy infos in log (usually for crash dump) + */ + +void +proxy_print_log () +{ + struct t_proxy *ptr_proxy; + + for (ptr_proxy = weechat_proxies; ptr_proxy; + ptr_proxy = ptr_proxy->next_proxy) + { + log_printf (""); + log_printf ("[proxy (addr:0x%lx)]", ptr_proxy); + log_printf (" name . . . . . . . . . : '%s'", ptr_proxy->name); + log_printf (" type . . . . . . . . . : %d (%s)", + CONFIG_INTEGER(ptr_proxy->type), + proxy_type_string[CONFIG_INTEGER(ptr_proxy->type)]); + log_printf (" ipv6 . . . . . . . . . : %d", CONFIG_INTEGER(ptr_proxy->ipv6)); + log_printf (" address. . . . . . . . : '%s'", CONFIG_STRING(ptr_proxy->address)); + log_printf (" port . . . . . . . . . : %d", CONFIG_INTEGER(ptr_proxy->port)); + log_printf (" username . . . . . . . : '%s'", CONFIG_STRING(ptr_proxy->username)); + log_printf (" password . . . . . . . : '%s'", CONFIG_STRING(ptr_proxy->password)); + log_printf (" prev_proxy . . . . . . : 0x%lx", ptr_proxy->prev_proxy); + log_printf (" next_proxy . . . . . . : 0x%lx", ptr_proxy->next_proxy); + } +} diff --git a/src/core/wee-proxy.h b/src/core/wee-proxy.h new file mode 100644 index 000000000..9d2d34b9b --- /dev/null +++ b/src/core/wee-proxy.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2003-2008 by FlashCode <flashcode@flashtux.org> + * See README for License detail, AUTHORS for developers list. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef __WEECHAT_PROXY_H +#define __WEECHAT_PROXY_H 1 + +enum t_proxy_option +{ + PROXY_OPTION_TYPE = 0, + PROXY_OPTION_IPV6, + PROXY_OPTION_ADDRESS, + PROXY_OPTION_PORT, + PROXY_OPTION_USERNAME, + PROXY_OPTION_PASSWORD, + /* number of proxy options */ + PROXY_NUM_OPTIONS, +}; + +enum t_proxy_type +{ + PROXY_TYPE_HTTP = 0, + PROXY_TYPE_SOCKS4, + PROXY_TYPE_SOCKS5, + /* number of proxy types */ + PROXY_NUM_TYPES, +}; + +struct t_proxy +{ + char *name; /* proxy name */ + struct t_config_option *type; /* type: http, socks4, socks5 */ + struct t_config_option *ipv6; /* ipv6 ? or ipv4 ? */ + struct t_config_option *address; /* address (IP or hostname) */ + struct t_config_option *port; /* port */ + struct t_config_option *username; /* username (optional) */ + struct t_config_option *password; /* password (optional) */ + + struct t_proxy *prev_proxy; /* link to previous bar */ + struct t_proxy *next_proxy; /* link to next bar */ +}; + +/* variables */ + +extern char *proxy_type_string[]; +extern struct t_proxy *weechat_proxies; +extern struct t_proxy *last_weechat_proxy; +extern struct t_proxy *weechat_temp_proxies; +extern struct t_proxy *last_weechat_temp_proxy; + +/* functions */ + +extern int proxy_search_option (const char *option_name); +extern int proxy_search_type (const char *type); +extern struct t_proxy *proxy_search (const char *name); +extern int proxy_set (struct t_proxy *bar, const char *property, + const char *value); +extern void proxy_create_option_temp (struct t_proxy *temp_proxy, + int index_option, const char *value); +extern struct t_proxy *proxy_alloc (const char *name); +extern struct t_proxy *proxy_new (const char *name, + const char *type, + const char *ipv6, + const char *address, + const char *port, + const char *username, + const char *password); +extern void proxy_use_temp_proxies (); +extern void proxy_free (struct t_proxy *proxy); +extern void proxy_free_all (); +extern void proxy_print_log (); + +#endif /* wee-proxy.h */ diff --git a/src/gui/gui-bar.c b/src/gui/gui-bar.c index a72e98f8c..ac299dc3e 100644 --- a/src/gui/gui-bar.c +++ b/src/gui/gui-bar.c @@ -61,7 +61,7 @@ struct t_gui_bar *last_gui_temp_bar = NULL; /* * gui_bar_search_option search a bar option name * return index of option in array - * "gui_bar_option_str", or -1 if not found + * "gui_bar_option_string", or -1 if not found */ int @@ -92,9 +92,12 @@ gui_bar_search_type (const char *type) { int i; + if (!type) + return -1; + for (i = 0; i < GUI_BAR_NUM_TYPES; i++) { - if (string_strcasecmp (type, gui_bar_type_string[i]) == 0) + if (string_strcasecmp (gui_bar_type_string[i], type) == 0) return i; } @@ -112,9 +115,12 @@ gui_bar_search_position (const char *position) { int i; + if (!position) + return -1; + for (i = 0; i < GUI_BAR_NUM_POSITIONS; i++) { - if (string_strcasecmp (position, gui_bar_position_string[i]) == 0) + if (string_strcasecmp (gui_bar_position_string[i], position) == 0) return i; } @@ -877,7 +883,7 @@ gui_bar_set_size_max (struct t_gui_bar *bar, const char *size) } /* - * gui_bar_set: set a property for bar + * gui_bar_set: set a property for a bar * return: 1 if ok, 0 if error */ diff --git a/src/gui/gui-bar.h b/src/gui/gui-bar.h index aaf62a1c4..7338afc85 100644 --- a/src/gui/gui-bar.h +++ b/src/gui/gui-bar.h @@ -45,7 +45,7 @@ enum t_gui_bar_option GUI_BAR_OPTION_COLOR_BG, GUI_BAR_OPTION_SEPARATOR, GUI_BAR_OPTION_ITEMS, - /* number of bar types */ + /* number of bar options */ GUI_BAR_NUM_OPTIONS, }; @@ -98,15 +98,15 @@ struct t_gui_bar struct t_config_option *items; /* bar items */ /* internal vars */ - int conditions_count; /* number of conditions */ - char **conditions_array; /* exploded bar conditions */ - int items_count; /* number of bar items */ - char **items_array; /* exploded bar items */ + int conditions_count; /* number of conditions */ + char **conditions_array; /* exploded bar conditions */ + int items_count; /* number of bar items */ + char **items_array; /* exploded bar items */ struct t_gui_bar_window *bar_window; /* pointer to bar window */ - /* (for type root only) */ - int bar_refresh_needed; /* refresh for bar is needed? */ - struct t_gui_bar *prev_bar; /* link to previous bar */ - struct t_gui_bar *next_bar; /* link to next bar */ + /* (for type root only) */ + int bar_refresh_needed; /* refresh for bar is needed? */ + struct t_gui_bar *prev_bar; /* link to previous bar */ + struct t_gui_bar *next_bar; /* link to next bar */ }; /* variables */ diff --git a/src/gui/gui-completion.c b/src/gui/gui-completion.c index e53fd81af..fd09dd4ef 100644 --- a/src/gui/gui-completion.c +++ b/src/gui/gui-completion.c @@ -33,10 +33,11 @@ #include "../core/weechat.h" #include "../core/wee-config.h" #include "../core/wee-hook.h" +#include "../core/wee-list.h" #include "../core/wee-log.h" +#include "../core/wee-proxy.h" #include "../core/wee-string.h" #include "../core/wee-utf8.h" -#include "../core/wee-list.h" #include "../plugins/plugin.h" #include "../plugins/plugin-config.h" #include "gui-completion.h" @@ -321,7 +322,7 @@ gui_completion_list_add (struct t_gui_completion *completion, const char *word, } /* - * gui_completion_list_add_bars_names: add buffers names to completion list + * gui_completion_list_add_bars_names: add bars names to completion list */ void @@ -883,6 +884,23 @@ gui_completion_list_add_weechat_cmd (struct t_gui_completion *completion) } /* + * gui_completion_list_add_proxies_names: add proxies names to completion list + */ + +void +gui_completion_list_add_proxies_names (struct t_gui_completion *completion) +{ + struct t_proxy *ptr_proxy; + + for (ptr_proxy = weechat_proxies; ptr_proxy; + ptr_proxy = ptr_proxy->next_proxy) + { + gui_completion_list_add (completion, ptr_proxy->name, + 0, WEECHAT_LIST_POS_SORT); + } +} + +/* * gui_completion_custom: custom completion by a plugin */ @@ -983,6 +1001,9 @@ gui_completion_build_list_template (struct t_gui_completion *completion, case 'w': /* WeeChat commands */ gui_completion_list_add_weechat_cmd (completion); break; + case 'y': /* proxy names */ + gui_completion_list_add_proxies_names (completion); + break; case '(': /* custom completion by a plugin */ pos++; pos_end = strchr (pos, ')'); diff --git a/src/plugins/irc/irc-command.c b/src/plugins/irc/irc-command.c index b4a312037..033060285 100644 --- a/src/plugins/irc/irc-command.c +++ b/src/plugins/irc/irc-command.c @@ -620,6 +620,7 @@ irc_command_connect (void *data, struct t_gui_buffer *buffer, int argc, server_tmp.autoconnect, server_tmp.autoreconnect, server_tmp.autoreconnect_delay, + server_tmp.proxy, server_tmp.addresses, server_tmp.ipv6, server_tmp.ssl, @@ -2945,6 +2946,7 @@ irc_command_server (void *data, struct t_gui_buffer *buffer, int argc, server_tmp.autoconnect, server_tmp.autoreconnect, server_tmp.autoreconnect_delay, + server_tmp.proxy, server_tmp.addresses, server_tmp.ipv6, server_tmp.ssl, diff --git a/src/plugins/irc/irc-config.c b/src/plugins/irc/irc-config.c index 497e6bd4e..ec52f2af6 100644 --- a/src/plugins/irc/irc-config.c +++ b/src/plugins/irc/irc-config.c @@ -36,12 +36,12 @@ char *irc_config_server_option_string[IRC_CONFIG_NUM_SERVER_OPTIONS] = -{ "autoconnect", "autoreconnect", "autoreconnect_delay", "addresses", "ipv6", - "ssl", "password", "nicks", "username", "realname", "local_hostname", +{ "autoconnect", "autoreconnect", "autoreconnect_delay", "proxy", "addresses", + "ipv6", "ssl", "password", "nicks", "username", "realname", "local_hostname", "command", "command_delay", "autojoin", "autorejoin" }; char *irc_config_server_option_default[IRC_CONFIG_NUM_SERVER_OPTIONS] = -{ "off", "on", "30", "", "off", "off", "", "", "", "", "", "", "0", "", +{ "off", "on", "30", "", "", "off", "off", "", "", "", "", "", "", "0", "", "off", "" }; @@ -710,6 +710,17 @@ irc_config_server_new_option (struct t_config_file *config_file, callback_change, callback_change_data, callback_delete, callback_delete_data); break; + case IRC_CONFIG_SERVER_PROXY: + new_option = weechat_config_new_option ( + config_file, section, + option_name, "string", + N_("proxy used for this server (optional)"), + NULL, 0, 0, + irc_config_server_option_default[index_option], value, + NULL, NULL, + callback_change, callback_change_data, + callback_delete, callback_delete_data); + break; case IRC_CONFIG_SERVER_ADDRESSES: new_option = weechat_config_new_option ( config_file, section, diff --git a/src/plugins/irc/irc-config.h b/src/plugins/irc/irc-config.h index 3e0b70af9..229ab16a1 100644 --- a/src/plugins/irc/irc-config.h +++ b/src/plugins/irc/irc-config.h @@ -31,6 +31,7 @@ enum t_irc_config_server_option IRC_CONFIG_SERVER_AUTOCONNECT = 0, IRC_CONFIG_SERVER_AUTORECONNECT, IRC_CONFIG_SERVER_AUTORECONNECT_DELAY, + IRC_CONFIG_SERVER_PROXY, IRC_CONFIG_SERVER_ADDRESSES, IRC_CONFIG_SERVER_IPV6, IRC_CONFIG_SERVER_SSL, diff --git a/src/plugins/irc/irc-protocol.c b/src/plugins/irc/irc-protocol.c index 126c55acc..b200c7579 100644 --- a/src/plugins/irc/irc-protocol.c +++ b/src/plugins/irc/irc-protocol.c @@ -1573,6 +1573,7 @@ irc_protocol_cmd_privmsg (struct t_irc_server *server, const char *command, weechat_infolist_new_var_string (item, "local_nick", server->nick); weechat_infolist_new_var_string (item, "filename", pos_file); weechat_infolist_new_var_string (item, "size", pos_size); + weechat_infolist_new_var_string (item, "proxy", server->proxy); weechat_infolist_new_var_string (item, "address", pos_addr); weechat_infolist_new_var_integer (item, "port", atoi (pos_port)); weechat_hook_signal_send ("xfer_add", @@ -1905,6 +1906,7 @@ irc_protocol_cmd_privmsg (struct t_irc_server *server, const char *command, weechat_infolist_new_var_string (item, "type", "chat_recv"); weechat_infolist_new_var_string (item, "remote_nick", nick); weechat_infolist_new_var_string (item, "local_nick", server->nick); + weechat_infolist_new_var_string (item, "proxy", server->proxy); weechat_infolist_new_var_string (item, "address", pos_addr); weechat_infolist_new_var_integer (item, "port", atoi (pos_port)); weechat_hook_signal_send ("xfer_add", diff --git a/src/plugins/irc/irc-server.c b/src/plugins/irc/irc-server.c index a8e12b9c4..dd1319cc5 100644 --- a/src/plugins/irc/irc-server.c +++ b/src/plugins/irc/irc-server.c @@ -240,6 +240,11 @@ irc_server_set_with_option (struct t_irc_server *server, case IRC_CONFIG_SERVER_AUTORECONNECT_DELAY: server->autoreconnect_delay = weechat_config_integer (option); break; + case IRC_CONFIG_SERVER_PROXY: + if (server->proxy) + free (server->proxy); + server->proxy = strdup (weechat_config_string (option)); + break; case IRC_CONFIG_SERVER_ADDRESSES: irc_server_set_addresses (server, weechat_config_string (option)); break; @@ -333,6 +338,7 @@ irc_server_init (struct t_irc_server *server) server->autoconnect = IRC_CONFIG_SERVER_DEFAULT_AUTOCONNECT; server->autoreconnect = IRC_CONFIG_SERVER_DEFAULT_AUTORECONNECT; server->autoreconnect_delay = IRC_CONFIG_SERVER_DEFAULT_AUTORECONNECT_DELAY; + server->proxy = NULL; server->addresses = NULL; server->ipv6 = IRC_CONFIG_SERVER_DEFAULT_IPV6; server->ssl = IRC_CONFIG_SERVER_DEFAULT_SSL; @@ -722,6 +728,8 @@ irc_server_free_data (struct t_irc_server *server) /* free data */ if (server->name) free (server->name); + if (server->proxy) + free (server->proxy); if (server->addresses) free (server->addresses); if (server->addresses_array) @@ -817,8 +825,9 @@ irc_server_free_all () struct t_irc_server * irc_server_new (const char *name, int autoconnect, int autoreconnect, - int autoreconnect_delay, const char *addresses, int ipv6, - int ssl, const char *password, const char *nicks, + int autoreconnect_delay, const char *proxy, + const char *addresses, int ipv6, int ssl, + const char *password, const char *nicks, const char *username, const char *realname, const char *local_hostname, const char *command, int command_delay, const char *autojoin, int autorejoin) @@ -830,11 +839,11 @@ irc_server_new (const char *name, int autoconnect, int autoreconnect, if (weechat_irc_plugin->debug) { - weechat_log_printf ("Creating new server (name:%s, addresses:%s, " - "pwd:%s, nicks:%s, username:%s, realname:%s, " - "local_hostname: %s, command:%s, autojoin:%s, " - "autorejoin:%s)", - name, addresses, (password) ? password : "", + weechat_log_printf ("Creating new server (name:%s, proxy:%s, " + "addresses:%s, pwd:%s, nicks:%s, username:%s, " + "realname:%s, local_hostname: %s, command:%s, " + "autojoin:%s, autorejoin:%s)", + name, proxy, addresses, (password) ? password : "", (nicks) ? nicks : "", (username) ? username : "", (realname) ? realname : "", (local_hostname) ? local_hostname : "", @@ -849,6 +858,7 @@ irc_server_new (const char *name, int autoconnect, int autoreconnect, new_server->autoconnect = autoconnect; new_server->autoreconnect = autoreconnect; new_server->autoreconnect_delay = autoreconnect_delay; + new_server->proxy = (proxy) ? strdup (proxy) : NULL; irc_server_set_addresses (new_server, addresses); new_server->ipv6 = ipv6; new_server->ssl = ssl; @@ -898,6 +908,7 @@ irc_server_duplicate (struct t_irc_server *server, const char *new_server_name) server->autoconnect, server->autoreconnect, server->autoreconnect_delay, + server->proxy, server->addresses, server->ipv6, server->ssl, @@ -1993,15 +2004,11 @@ int irc_server_connect_cb (void *arg_server, int status, const char *ip_address) { struct t_irc_server *server; - int config_proxy_use; server = (struct t_irc_server *)arg_server; server->hook_connect = NULL; - config_proxy_use = weechat_config_boolean ( - weechat_config_get ("weechat.proxy.use")); - switch (status) { case WEECHAT_HOOK_CONNECT_OK: @@ -2020,7 +2027,7 @@ irc_server_connect_cb (void *arg_server, int status, const char *ip_address) break; case WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND: weechat_printf (server->buffer, - (config_proxy_use) ? + (server->proxy && server->proxy[0]) ? _("%s%s: proxy address \"%s\" not found") : _("%s%s: address \"%s\" not found"), irc_buffer_get_server_prefix (server, "error"), @@ -2031,7 +2038,7 @@ irc_server_connect_cb (void *arg_server, int status, const char *ip_address) break; case WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND: weechat_printf (server->buffer, - (config_proxy_use) ? + (server->proxy && server->proxy[0]) ? _("%s%s: proxy IP address not found") : _("%s%s: IP address not found"), irc_buffer_get_server_prefix (server, "error"), @@ -2041,7 +2048,7 @@ irc_server_connect_cb (void *arg_server, int status, const char *ip_address) break; case WEECHAT_HOOK_CONNECT_CONNECTION_REFUSED: weechat_printf (server->buffer, - (config_proxy_use) ? + (server->proxy && server->proxy[0]) ? _("%s%s: proxy connection refused") : _("%s%s: connection refused"), irc_buffer_get_server_prefix (server, "error"), @@ -2158,40 +2165,17 @@ irc_server_create_buffer (struct t_irc_server *server, int all_servers) int irc_server_connect (struct t_irc_server *server, int disable_autojoin) { - int set; - const char *config_proxy_type, *config_proxy_address; - int config_proxy_use, config_proxy_ipv6, config_proxy_port; - - if (!server->addresses || !server->addresses[0]) - { - weechat_printf (server->buffer, - _("%s%s: addresses not defined for server \"%s\", " - "cannot connect"), - irc_buffer_get_server_prefix (server, "error"), - IRC_PLUGIN_NAME, server->name); - return 0; - } - - if (!server->nicks || !server->nicks[0]) - { - weechat_printf (server->buffer, - _("%s%s: nicks not defined for server \"%s\", " - "cannot connect"), - irc_buffer_get_server_prefix (server, "error"), - IRC_PLUGIN_NAME, server->name); - return 0; - } + int set, length; + char *option_name; + struct t_config_option *proxy_type, *proxy_ipv6, *proxy_address, *proxy_port; + const char *str_proxy_type, *str_proxy_address; - config_proxy_use = weechat_config_boolean ( - weechat_config_get ("weechat.proxy.use")); - config_proxy_ipv6 = weechat_config_boolean ( - weechat_config_get ("weechat.proxy.ipv6")); - config_proxy_type = weechat_config_string ( - weechat_config_get ("weechat.proxy.type")); - config_proxy_address = weechat_config_string ( - weechat_config_get ("weechat.proxy.address")); - config_proxy_port = weechat_config_integer ( - weechat_config_get ("weechat.proxy.port")); + proxy_type = NULL; + proxy_ipv6 = NULL; + proxy_address = NULL; + proxy_port = NULL; + str_proxy_type = NULL; + str_proxy_address = NULL; if (!server->buffer) { @@ -2222,6 +2206,74 @@ irc_server_connect (struct t_irc_server *server, int disable_autojoin) "/command irc /server switch"); } + if (server->proxy && server->proxy[0]) + { + length = 32 + strlen (server->proxy) + 1; + option_name = malloc (length); + if (!option_name) + { + weechat_printf (server->buffer, + _("%s%s: not enough memory"), + irc_buffer_get_server_prefix (server, "error"), + IRC_PLUGIN_NAME); + return 0; + } + snprintf (option_name, length, "weechat.proxy.%s.type", + server->proxy); + proxy_type = weechat_config_get (option_name); + snprintf (option_name, length, "weechat.proxy.%s.ipv6", + server->proxy); + proxy_ipv6 = weechat_config_get (option_name); + snprintf (option_name, length, "weechat.proxy.%s.address", + server->proxy); + proxy_address = weechat_config_get (option_name); + snprintf (option_name, length, "weechat.proxy.%s.port", + server->proxy); + proxy_port = weechat_config_get (option_name); + free (option_name); + if (!proxy_type || !proxy_address) + { + weechat_printf (server->buffer, + _("%s%s: proxy \"%s\" not found for server " + "\"%s\", cannot connect"), + irc_buffer_get_server_prefix (server, "error"), + IRC_PLUGIN_NAME, server->proxy, server->name); + return 0; + } + str_proxy_type = weechat_config_string (proxy_type); + str_proxy_address = weechat_config_string (proxy_address); + if (!str_proxy_type[0] || !proxy_ipv6 || !str_proxy_address[0] + || !proxy_port) + { + weechat_printf (server->buffer, + _("%s%s: missing proxy settings, check options " + "for proxy \"%s\""), + irc_buffer_get_server_prefix (server, "error"), + IRC_PLUGIN_NAME, server->proxy); + return 0; + } + } + + if (!server->addresses || !server->addresses[0]) + { + weechat_printf (server->buffer, + _("%s%s: addresses not defined for server \"%s\", " + "cannot connect"), + irc_buffer_get_server_prefix (server, "error"), + IRC_PLUGIN_NAME, server->name); + return 0; + } + + if (!server->nicks || !server->nicks[0]) + { + weechat_printf (server->buffer, + _("%s%s: nicks not defined for server \"%s\", " + "cannot connect"), + irc_buffer_get_server_prefix (server, "error"), + IRC_PLUGIN_NAME, server->name); + return 0; + } + #ifndef HAVE_GNUTLS if (server->ssl) { @@ -2233,7 +2285,7 @@ irc_server_connect (struct t_irc_server *server, int disable_autojoin) return 0; } #endif - if (config_proxy_use) + if (proxy_type) { weechat_printf (server->buffer, _("%s%s: connecting to server %s/%d%s%s via %s " @@ -2244,18 +2296,20 @@ irc_server_connect (struct t_irc_server *server, int disable_autojoin) server->ports_array[server->current_address], (server->ipv6) ? " (IPv6)" : "", (server->ssl) ? " (SSL)" : "", - config_proxy_type, - config_proxy_address, config_proxy_port, - (config_proxy_ipv6) ? " (IPv6)" : ""); + str_proxy_type, + str_proxy_address, + weechat_config_integer (proxy_port), + (weechat_config_boolean (proxy_ipv6)) ? " (IPv6)" : ""); weechat_log_printf (_("Connecting to server %s/%d%s%s via %s proxy " "%s/%d%s..."), server->addresses_array[server->current_address], server->ports_array[server->current_address], (server->ipv6) ? " (IPv6)" : "", (server->ssl) ? " (SSL)" : "", - config_proxy_type, - config_proxy_address, config_proxy_port, - (config_proxy_ipv6) ? " (IPv6)" : ""); + str_proxy_type, + str_proxy_address, + weechat_config_integer (proxy_port), + (weechat_config_boolean (proxy_ipv6)) ? " (IPv6)" : ""); } else { @@ -2280,10 +2334,16 @@ irc_server_connect (struct t_irc_server *server, int disable_autojoin) irc_server_close_connection (server); /* create socket and set options */ - if (config_proxy_use) - server->sock = socket ((config_proxy_ipv6) ? AF_INET6 : AF_INET, SOCK_STREAM, 0); + if (proxy_type) + { + server->sock = socket ((weechat_config_integer (proxy_ipv6)) ? + AF_INET6 : AF_INET, + SOCK_STREAM, 0); + } else + { server->sock = socket ((server->ipv6) ? AF_INET6 : AF_INET, SOCK_STREAM, 0); + } if (server->sock == -1) { weechat_printf (server->buffer, @@ -2326,7 +2386,8 @@ irc_server_connect (struct t_irc_server *server, int disable_autojoin) server->disable_autojoin = disable_autojoin; - server->hook_connect = weechat_hook_connect (server->addresses_array[server->current_address], + server->hook_connect = weechat_hook_connect (server->proxy, + server->addresses_array[server->current_address], server->ports_array[server->current_address], server->sock, server->ipv6, @@ -2901,6 +2962,8 @@ irc_server_add_to_infolist (struct t_infolist *infolist, return 0; if (!weechat_infolist_new_var_integer (ptr_item, "autoreconnect_delay", server->autoreconnect_delay)) return 0; + if (!weechat_infolist_new_var_string (ptr_item, "proxy", server->proxy)) + return 0; if (!weechat_infolist_new_var_string (ptr_item, "addresses", server->addresses)) return 0; if (!weechat_infolist_new_var_integer (ptr_item, "ipv6", server->ipv6)) @@ -2988,6 +3051,7 @@ irc_server_print_log () weechat_log_printf (" autoconnect . . . . : %d", ptr_server->autoconnect); weechat_log_printf (" autoreconnect . . . : %d", ptr_server->autoreconnect); weechat_log_printf (" autoreconnect_delay : %d", ptr_server->autoreconnect_delay); + weechat_log_printf (" proxy . . . . . . . : '%s'", ptr_server->proxy); weechat_log_printf (" addresses . . . . . : '%s'", ptr_server->addresses); weechat_log_printf (" ipv6. . . . . . . . : %d", ptr_server->ipv6); weechat_log_printf (" ssl . . . . . . . . : %d", ptr_server->ssl); diff --git a/src/plugins/irc/irc-server.h b/src/plugins/irc/irc-server.h index 44a12eb13..1650f3637 100644 --- a/src/plugins/irc/irc-server.h +++ b/src/plugins/irc/irc-server.h @@ -63,6 +63,7 @@ struct t_irc_server int autoconnect; /* = 1 if auto connect at startup */ int autoreconnect; /* = 1 if auto reco when disconnected */ int autoreconnect_delay; /* delay before trying again reconnect */ + char *proxy; /* proxy used for this server (optional) */ char *addresses; /* server addresses (IP/name with port) */ int ipv6; /* use IPv6 protocol */ int ssl; /* SSL protocol */ @@ -157,6 +158,7 @@ extern void irc_server_free_all (); extern struct t_irc_server *irc_server_new (const char *name, int autoconnect, int autoreconnect, int autoreconnect_delay, + const char *proxy, const char *addresses, int ipv6, int ssl, diff --git a/src/plugins/scripts/lua/weechat-lua-api.c b/src/plugins/scripts/lua/weechat-lua-api.c index 77d1432e6..30b6577d9 100644 --- a/src/plugins/scripts/lua/weechat-lua-api.c +++ b/src/plugins/scripts/lua/weechat-lua-api.c @@ -2752,7 +2752,7 @@ weechat_lua_api_hook_connect_cb (void *data, int status, const char *ip_address) static int weechat_lua_api_hook_connect (lua_State *L) { - const char *address, *local_hostname, *function; + const char *proxy, *address, *local_hostname, *function; int n, port, sock, ipv6; char *result; @@ -2764,7 +2764,8 @@ weechat_lua_api_hook_connect (lua_State *L) WEECHAT_SCRIPT_MSG_NOT_INITIALIZED("hook_connect"); LUA_RETURN_EMPTY; } - + + proxy = NULL; address = NULL; port = 0; sock = 0; @@ -2773,13 +2774,14 @@ weechat_lua_api_hook_connect (lua_State *L) function = NULL; n = lua_gettop (lua_current_interpreter); - - if (n < 6) + + if (n < 7) { WEECHAT_SCRIPT_MSG_WRONG_ARGUMENTS("hook_connect"); LUA_RETURN_EMPTY; } - + + proxy = lua_tostring (lua_current_interpreter, -7); address = lua_tostring (lua_current_interpreter, -6); port = lua_tonumber (lua_current_interpreter, -5); sock = lua_tonumber (lua_current_interpreter, -4); @@ -2789,6 +2791,7 @@ weechat_lua_api_hook_connect (lua_State *L) result = script_ptr2str (script_api_hook_connect (weechat_lua_plugin, lua_current_script, + proxy, address, port, sock, diff --git a/src/plugins/scripts/perl/weechat-perl-api.c b/src/plugins/scripts/perl/weechat-perl-api.c index 5e6dfd17e..5507136a1 100644 --- a/src/plugins/scripts/perl/weechat-perl-api.c +++ b/src/plugins/scripts/perl/weechat-perl-api.c @@ -2299,7 +2299,7 @@ weechat_perl_api_hook_connect_cb (void *data, int status, static XS (XS_weechat_api_hook_connect) { - char *address, *local_hostname, *result; + char *proxy, *address, *local_hostname, *result; dXSARGS; /* make C compiler happy */ @@ -2311,25 +2311,27 @@ static XS (XS_weechat_api_hook_connect) PERL_RETURN_EMPTY; } - if (items < 6) + if (items < 7) { WEECHAT_SCRIPT_MSG_WRONG_ARGUMENTS("hook_connect"); PERL_RETURN_EMPTY; } - address = SvPV (ST (0), PL_na); - local_hostname = SvPV (ST (4), PL_na); + proxy = SvPV (ST (0), PL_na); + address = SvPV (ST (1), PL_na); + local_hostname = SvPV (ST (5), PL_na); result = script_ptr2str (script_api_hook_connect (weechat_perl_plugin, perl_current_script, + proxy, address, - SvIV (ST (1)), /* port */ - SvIV (ST (2)), /* sock */ - SvIV (ST (3)), /* ipv6 */ + SvIV (ST (2)), /* port */ + SvIV (ST (3)), /* sock */ + SvIV (ST (4)), /* ipv6 */ NULL, /* gnutls session */ local_hostname, &weechat_perl_api_hook_connect_cb, - SvPV (ST (5), PL_na))); /* perl function */ + SvPV (ST (6), PL_na))); /* perl function */ PERL_RETURN_STRING_FREE(result); } diff --git a/src/plugins/scripts/python/weechat-python-api.c b/src/plugins/scripts/python/weechat-python-api.c index 872c3cbbd..ab629def6 100644 --- a/src/plugins/scripts/python/weechat-python-api.c +++ b/src/plugins/scripts/python/weechat-python-api.c @@ -2453,7 +2453,7 @@ weechat_python_api_hook_connect_cb (void *data, int status, static PyObject * weechat_python_api_hook_connect (PyObject *self, PyObject *args) { - char *address, *local_hostname, *function, *result; + char *proxy, *address, *local_hostname, *function, *result; int port, sock, ipv6; PyObject *object; @@ -2465,7 +2465,8 @@ weechat_python_api_hook_connect (PyObject *self, PyObject *args) WEECHAT_SCRIPT_MSG_NOT_INITIALIZED("hook_connect"); PYTHON_RETURN_EMPTY; } - + + proxy = NULL; address = NULL; port = 0; sock = 0; @@ -2473,8 +2474,8 @@ weechat_python_api_hook_connect (PyObject *self, PyObject *args) local_hostname = NULL; function = NULL; - if (!PyArg_ParseTuple (args, "siiiss", &address, &port, &sock, &ipv6, - &local_hostname, &function)) + if (!PyArg_ParseTuple (args, "ssiiiss", &proxy, &address, &port, &sock, + &ipv6, &local_hostname, &function)) { WEECHAT_SCRIPT_MSG_WRONG_ARGUMENTS("hook_connect"); PYTHON_RETURN_EMPTY; @@ -2482,6 +2483,7 @@ weechat_python_api_hook_connect (PyObject *self, PyObject *args) result = script_ptr2str (script_api_hook_connect (weechat_python_plugin, python_current_script, + proxy, address, port, sock, diff --git a/src/plugins/scripts/ruby/weechat-ruby-api.c b/src/plugins/scripts/ruby/weechat-ruby-api.c index f2433becb..2e1209e71 100644 --- a/src/plugins/scripts/ruby/weechat-ruby-api.c +++ b/src/plugins/scripts/ruby/weechat-ruby-api.c @@ -2816,11 +2816,11 @@ weechat_ruby_api_hook_connect_cb (void *data, int status, */ static VALUE -weechat_ruby_api_hook_connect (VALUE class, VALUE address, VALUE port, - VALUE sock, VALUE ipv6, VALUE local_hostname, - VALUE function) +weechat_ruby_api_hook_connect (VALUE class, VALUE proxy, VALUE address, + VALUE port, VALUE sock, VALUE ipv6, + VALUE local_hostname, VALUE function) { - char *c_address, *c_local_hostname, *c_function, *result; + char *c_proxy, *c_address, *c_local_hostname, *c_function, *result; int c_port, c_sock, c_ipv6; VALUE return_value; @@ -2832,7 +2832,8 @@ weechat_ruby_api_hook_connect (VALUE class, VALUE address, VALUE port, WEECHAT_SCRIPT_MSG_NOT_INITIALIZED("hook_connect"); RUBY_RETURN_EMPTY; } - + + c_proxy = NULL; c_address = NULL; c_port = 0; c_sock = 0; @@ -2840,20 +2841,22 @@ weechat_ruby_api_hook_connect (VALUE class, VALUE address, VALUE port, c_local_hostname = NULL; c_function = NULL; - if (NIL_P (address) || NIL_P (port) || NIL_P (sock) || NIL_P (ipv6) - || NIL_P (local_hostname) || NIL_P (function)) + if (NIL_P (proxy) || NIL_P (address) || NIL_P (port) || NIL_P (sock) + || NIL_P (ipv6) || NIL_P (local_hostname) || NIL_P (function)) { WEECHAT_SCRIPT_MSG_WRONG_ARGUMENTS("hook_connect"); RUBY_RETURN_EMPTY; } - + + Check_Type (proxy, T_STRING); Check_Type (address, T_STRING); Check_Type (port, T_FIXNUM); Check_Type (sock, T_FIXNUM); Check_Type (ipv6, T_FIXNUM); Check_Type (local_hostname, T_STRING); Check_Type (function, T_STRING); - + + c_proxy = STR2CSTR (proxy); c_address = STR2CSTR (address); c_port = FIX2INT (port); c_sock = FIX2INT (sock); @@ -2863,6 +2866,7 @@ weechat_ruby_api_hook_connect (VALUE class, VALUE address, VALUE port, result = script_ptr2str (script_api_hook_connect (weechat_ruby_plugin, ruby_current_script, + c_proxy, c_address, c_port, c_sock, @@ -5633,7 +5637,7 @@ weechat_ruby_api_init (VALUE ruby_mWeechat) rb_define_module_function (ruby_mWeechat, "hook_command", &weechat_ruby_api_hook_command, 6); rb_define_module_function (ruby_mWeechat, "hook_timer", &weechat_ruby_api_hook_timer, 4); rb_define_module_function (ruby_mWeechat, "hook_fd", &weechat_ruby_api_hook_fd, 5); - rb_define_module_function (ruby_mWeechat, "hook_connect", &weechat_ruby_api_hook_connect, 6); + rb_define_module_function (ruby_mWeechat, "hook_connect", &weechat_ruby_api_hook_connect, 7); rb_define_module_function (ruby_mWeechat, "hook_print", &weechat_ruby_api_hook_print, 5); rb_define_module_function (ruby_mWeechat, "hook_signal", &weechat_ruby_api_hook_signal, 2); rb_define_module_function (ruby_mWeechat, "hook_signal_send", &weechat_ruby_api_hook_signal_send, 3); diff --git a/src/plugins/scripts/script-api.c b/src/plugins/scripts/script-api.c index c1b17bb60..40434ed62 100644 --- a/src/plugins/scripts/script-api.c +++ b/src/plugins/scripts/script-api.c @@ -744,8 +744,9 @@ script_api_hook_fd (struct t_weechat_plugin *weechat_plugin, struct t_hook * script_api_hook_connect (struct t_weechat_plugin *weechat_plugin, struct t_plugin_script *script, - const char *address, int port, int sock, int ipv6, - void *gnutls_sess, const char *local_hostname, + const char *proxy, const char *address, int port, + int sock, int ipv6, void *gnutls_sess, + const char *local_hostname, int (*callback)(void *data, int status, const char *ip_address), const char *function) { @@ -756,8 +757,8 @@ script_api_hook_connect (struct t_weechat_plugin *weechat_plugin, if (!new_script_callback) return NULL; - new_hook = weechat_hook_connect (address, port, sock, ipv6, gnutls_sess, - local_hostname, callback, + new_hook = weechat_hook_connect (proxy, address, port, sock, ipv6, + gnutls_sess, local_hostname, callback, new_script_callback); if (!new_hook) { diff --git a/src/plugins/scripts/script-api.h b/src/plugins/scripts/script-api.h index 2b7da7c2a..a3dafe8af 100644 --- a/src/plugins/scripts/script-api.h +++ b/src/plugins/scripts/script-api.h @@ -121,6 +121,7 @@ extern struct t_hook *script_api_hook_fd (struct t_weechat_plugin *weechat_plugi const char *function); extern struct t_hook *script_api_hook_connect (struct t_weechat_plugin *weechat_plugin, struct t_plugin_script *script, + const char *proxy, const char *address, int port, int sock, diff --git a/src/plugins/scripts/tcl/weechat-tcl-api.c b/src/plugins/scripts/tcl/weechat-tcl-api.c index 5d5818b02..382d0b5f5 100644 --- a/src/plugins/scripts/tcl/weechat-tcl-api.c +++ b/src/plugins/scripts/tcl/weechat-tcl-api.c @@ -2663,7 +2663,7 @@ weechat_tcl_api_hook_connect (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { Tcl_Obj *objp; - char *address, *local_hostname, *result; + char *proxy, *address, *local_hostname, *result; int i, port, sock, ipv6; /* make C compiler happy */ @@ -2675,25 +2675,27 @@ weechat_tcl_api_hook_connect (ClientData clientData, Tcl_Interp *interp, TCL_RETURN_EMPTY; } - if (objc < 6) + if (objc < 7) { WEECHAT_SCRIPT_MSG_WRONG_ARGUMENTS("hook_connect"); TCL_RETURN_EMPTY; } - if ((Tcl_GetIntFromObj (interp, objv[2], &port) != TCL_OK) - || (Tcl_GetIntFromObj (interp, objv[3], &sock) != TCL_OK) - || (Tcl_GetIntFromObj (interp, objv[4], &ipv6) != TCL_OK)) + if ((Tcl_GetIntFromObj (interp, objv[3], &port) != TCL_OK) + || (Tcl_GetIntFromObj (interp, objv[4], &sock) != TCL_OK) + || (Tcl_GetIntFromObj (interp, objv[5], &ipv6) != TCL_OK)) { WEECHAT_SCRIPT_MSG_WRONG_ARGUMENTS("hook_connect"); TCL_RETURN_EMPTY; } - address = Tcl_GetStringFromObj (objv[1], &i); - local_hostname = Tcl_GetStringFromObj (objv[5], &i); + proxy = Tcl_GetStringFromObj (objv[1], &i); + address = Tcl_GetStringFromObj (objv[2], &i); + local_hostname = Tcl_GetStringFromObj (objv[6], &i); result = script_ptr2str (script_api_hook_connect (weechat_tcl_plugin, tcl_current_script, + proxy, address, port, sock, @@ -2701,7 +2703,7 @@ weechat_tcl_api_hook_connect (ClientData clientData, Tcl_Interp *interp, NULL, /* gnutls session */ local_hostname, &weechat_tcl_api_hook_connect_cb, - Tcl_GetStringFromObj (objv[6], &i))); /* tcl function */ + Tcl_GetStringFromObj (objv[7], &i))); /* tcl function */ TCL_RETURN_STRING_FREE(result); } diff --git a/src/plugins/weechat-plugin.h b/src/plugins/weechat-plugin.h index 657bd6c7d..641310916 100644 --- a/src/plugins/weechat-plugin.h +++ b/src/plugins/weechat-plugin.h @@ -342,6 +342,7 @@ struct t_weechat_plugin int (*callback)(void *data), void *callback_data); struct t_hook *(*hook_connect) (struct t_weechat_plugin *plugin, + const char *proxy, const char *address, int port, int sock, @@ -518,8 +519,10 @@ struct t_weechat_plugin struct t_gui_buffer *buffer, const char *command); /* network */ - int (*network_pass_proxy) (int sock, const char *address, int port); - int (*network_connect_to) (int sock, unsigned long address, int port); + int (*network_pass_proxy) (const char *proxy, int sock, + const char *address, int port); + int (*network_connect_to) (const char *proxy, int sock, + unsigned long address, int port); /* infos */ const char *(*info_get) (struct t_weechat_plugin *plugin, @@ -870,11 +873,11 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin); weechat_plugin->hook_fd(weechat_plugin, __fd, __flag_read, \ __flag_write, __flag_exception, __callback, \ __data) -#define weechat_hook_connect(__address, __port, __sock, __ipv6, \ - __gnutls_sess, __local_hostname, \ +#define weechat_hook_connect(__proxy, __address, __port, __sock, \ + __ipv6, __gnutls_sess, __local_hostname, \ __callback, __data) \ - weechat_plugin->hook_connect(weechat_plugin, __address, __port, \ - __sock, __ipv6, __gnutls_sess, \ + weechat_plugin->hook_connect(weechat_plugin, __proxy, __address, \ + __port, __sock, __ipv6, __gnutls_sess, \ __local_hostname, __callback, __data) #define weechat_hook_print(__buffer, __tags, __msg, __strip__colors, \ __callback, __data) \ @@ -1014,10 +1017,12 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin); weechat_plugin->command(weechat_plugin, __buffer, __command) /* network */ -#define weechat_network_pass_proxy(__sock, __address, __port) \ - weechat_plugin->network_pass_proxy(__sock, __address, __port) -#define weechat_network_connect_to(__sock, __address, __port) \ - weechat_plugin->network_connect_to(__sock, __address, __port) +#define weechat_network_pass_proxy(__proxy, __sock, __address, __port) \ + weechat_plugin->network_pass_proxy(__proxy, __sock, __address, \ + __port) +#define weechat_network_connect_to(__proxy, __sock, __address, __port) \ + weechat_plugin->network_connect_to(__proxy, __sock, __address, \ + __port) /* infos */ #define weechat_info_get(__info_name, __arguments) \ diff --git a/src/plugins/xfer/xfer-dcc.c b/src/plugins/xfer/xfer-dcc.c index c44868f3a..f76d91484 100644 --- a/src/plugins/xfer/xfer-dcc.c +++ b/src/plugins/xfer/xfer-dcc.c @@ -167,7 +167,8 @@ xfer_dcc_recv_file_child (struct t_xfer *xfer) time_t last_sent, new_time; /* first connect to sender (blocking) */ - if (!weechat_network_connect_to (xfer->sock, xfer->address, xfer->port)) + if (!weechat_network_connect_to (xfer->proxy, xfer->sock, + xfer->address, xfer->port)) { xfer_network_write_pipe (xfer, XFER_STATUS_FAILED, XFER_ERROR_CONNECT_SENDER); diff --git a/src/plugins/xfer/xfer-network.c b/src/plugins/xfer/xfer-network.c index 229c962ce..f6848e61a 100644 --- a/src/plugins/xfer/xfer-network.c +++ b/src/plugins/xfer/xfer-network.c @@ -492,7 +492,8 @@ xfer_network_connect (struct t_xfer *xfer) { if (fcntl (xfer->sock, F_SETFL, O_NONBLOCK) == -1) return 0; - weechat_network_connect_to (xfer->sock, xfer->address, xfer->port); + weechat_network_connect_to (xfer->proxy, xfer->sock, xfer->address, + xfer->port); xfer->hook_fd = weechat_hook_fd (xfer->sock, 1, 0, 0, diff --git a/src/plugins/xfer/xfer.c b/src/plugins/xfer/xfer.c index 7fe2ad521..14856c3d4 100644 --- a/src/plugins/xfer/xfer.c +++ b/src/plugins/xfer/xfer.c @@ -457,10 +457,10 @@ xfer_alloc () struct t_xfer * xfer_new (const char *plugin_name, const char *plugin_id, enum t_xfer_type type, - enum t_xfer_protocol protocol, const char *remote_nick, const char *local_nick, - const char *filename, - unsigned long size, unsigned long address, int port, int sock, - const char *local_filename) + enum t_xfer_protocol protocol, const char *remote_nick, + const char *local_nick, const char *filename, + unsigned long size, const char *proxy, unsigned long address, + int port, int sock, const char *local_filename) { struct t_xfer *new_xfer; @@ -491,6 +491,7 @@ xfer_new (const char *plugin_name, const char *plugin_id, enum t_xfer_type type, else new_xfer->filename = strdup (_("xfer chat")); new_xfer->size = size; + new_xfer->proxy = (proxy) ? strdup (proxy) : NULL; new_xfer->address = address; new_xfer->port = port; @@ -657,7 +658,7 @@ xfer_add_cb (void *data, const char *signal, const char *type_data, void *signal { struct t_infolist *infolist; const char *plugin_name, *plugin_id, *str_type, *str_protocol; - const char *remote_nick, *local_nick, *filename; + const char *remote_nick, *local_nick, *filename, *proxy; int type, protocol; const char *weechat_dir; char *dir1, *dir2, *filename2, *short_filename, *pos; @@ -708,6 +709,7 @@ xfer_add_cb (void *data, const char *signal, const char *type_data, void *signal remote_nick = weechat_infolist_string (infolist, "remote_nick"); local_nick = weechat_infolist_string (infolist, "local_nick"); filename = weechat_infolist_string (infolist, "filename"); + proxy = weechat_infolist_string (infolist, "proxy"); protocol = XFER_NO_PROTOCOL; if (!plugin_name || !plugin_id || !str_type || !remote_nick || !local_nick) @@ -835,7 +837,7 @@ xfer_add_cb (void *data, const char *signal, const char *type_data, void *signal /* get local IP address */ sscanf (weechat_infolist_string (infolist, "address"), "%lu", &local_addr); - /* look up the IP address from dcc_own_ip, if set */ + /* look up the IP address from network_own_ip, if set */ if (weechat_config_string(xfer_config_network_own_ip) && weechat_config_string(xfer_config_network_own_ip)[0]) { @@ -970,11 +972,12 @@ xfer_add_cb (void *data, const char *signal, const char *type_data, void *signal if (XFER_IS_FILE(type)) ptr_xfer = xfer_new (plugin_name, plugin_id, type, protocol, remote_nick, local_nick, short_filename, - file_size, local_addr, port, sock, filename2); + file_size, proxy, local_addr, port, sock, + filename2); else ptr_xfer = xfer_new (plugin_name, plugin_id, type, protocol, - remote_nick, local_nick, NULL, 0, local_addr, - port, sock, NULL); + remote_nick, local_nick, NULL, 0, proxy, + local_addr, port, sock, NULL); if (!ptr_xfer) { @@ -1207,6 +1210,8 @@ xfer_add_to_infolist (struct t_infolist *infolist, struct t_xfer *xfer) snprintf (value, sizeof (value), "%lu", xfer->size); if (!weechat_infolist_new_var_string (ptr_item, "size", value)) return 0; + if (!weechat_infolist_new_var_string (ptr_item, "proxy", xfer->proxy)) + return 0; snprintf (value, sizeof (value), "%lu", xfer->address); if (!weechat_infolist_new_var_string (ptr_item, "address", value)) return 0; @@ -1295,6 +1300,7 @@ xfer_print_log () weechat_log_printf (" local_nick. . . . . : '%s'", ptr_xfer->local_nick); weechat_log_printf (" filename. . . . . . : '%s'", ptr_xfer->filename); weechat_log_printf (" size. . . . . . . . : %lu", ptr_xfer->size); + weechat_log_printf (" proxy . . . . . . . : '%s'", ptr_xfer->proxy); weechat_log_printf (" address . . . . . . : %lu", ptr_xfer->address); weechat_log_printf (" port. . . . . . . . : %d", ptr_xfer->port); diff --git a/src/plugins/xfer/xfer.h b/src/plugins/xfer/xfer.h index b4ebee9cf..2c5ad76b8 100644 --- a/src/plugins/xfer/xfer.h +++ b/src/plugins/xfer/xfer.h @@ -115,6 +115,7 @@ struct t_xfer char *local_nick; /* local nick */ char *filename; /* filename */ unsigned long size; /* file size */ + char *proxy; /* proxy to use (optional) */ unsigned long address; /* local or remote IP address */ int port; /* remote port */ |