diff options
Diffstat (limited to 'src/core/wee-proxy.c')
-rw-r--r-- | src/core/wee-proxy.c | 659 |
1 files changed, 659 insertions, 0 deletions
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); + } +} |