diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/CMakeLists.txt | 21 | ||||
-rw-r--r-- | src/core/Makefile.am | 2 | ||||
-rw-r--r-- | src/core/wee-command.c | 6 | ||||
-rw-r--r-- | src/core/wee-config-file.c | 4 | ||||
-rw-r--r-- | src/core/wee-config.c | 59 | ||||
-rw-r--r-- | src/core/wee-config.h | 8 | ||||
-rw-r--r-- | src/core/wee-network.c | 456 | ||||
-rw-r--r-- | src/core/wee-network.h | 26 |
8 files changed, 506 insertions, 76 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 22ab230bc..7ff067270 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -14,11 +14,22 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # -SET(LIB_CORE_SRC weechat.c weechat.h wee-backtrace.c wee-backtrace.h -wee-command.c wee-command.h wee-config.c wee-config.h wee-config-file.c -wee-config-file.h wee-debug.c wee-debug.h wee-hook.c wee-hook.h wee-input.c -wee-input.h wee-list.c wee-list.h wee-log.c wee-log.h wee-string.c wee-string.h -wee-upgrade.c wee-upgrade.h wee-utf8.c wee-utf8.h wee-util.c wee-util.h) +SET(LIB_CORE_SRC +weechat.c weechat.h +wee-backtrace.c wee-backtrace.h +wee-command.c wee-command.h +wee-config.c wee-config.h +wee-config-file.c wee-config-file.h +wee-debug.c wee-debug.h +wee-hook.c wee-hook.h +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-string.c wee-string.h +wee-upgrade.c wee-upgrade.h +wee-utf8.c wee-utf8.h +wee-util.c wee-util.h) # Check for flock support INCLUDE(CheckSymbolExists) diff --git a/src/core/Makefile.am b/src/core/Makefile.am index aff3c408c..32d24c438 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -38,6 +38,8 @@ lib_weechat_core_a_SOURCES = weechat.c \ wee-list.h \ wee-log.c \ wee-log.h \ + wee-network.c \ + wee-network.h \ wee-upgrade.c \ wee-upgrade.h \ wee-string.c \ diff --git a/src/core/wee-command.c b/src/core/wee-command.c index 31a995047..4ce2393fe 100644 --- a/src/core/wee-command.c +++ b/src/core/wee-command.c @@ -93,12 +93,12 @@ command_bar (void *data, struct t_gui_buffer *buffer, GUI_COLOR(GUI_COLOR_CHAT_BUFFER), ptr_bar->name, GUI_COLOR(GUI_COLOR_CHAT), - gui_bar_type_str[CONFIG_INTEGER(ptr_bar->type)], + gui_bar_type_string[CONFIG_INTEGER(ptr_bar->type)], (CONFIG_STRING(ptr_bar->conditions) && CONFIG_STRING(ptr_bar->conditions)[0]) ? CONFIG_STRING(ptr_bar->conditions) : "-", - gui_bar_position_str[CONFIG_INTEGER(ptr_bar->position)], - gui_bar_filling_str[CONFIG_INTEGER(ptr_bar->filling)], + gui_bar_position_string[CONFIG_INTEGER(ptr_bar->position)], + gui_bar_filling_string[CONFIG_INTEGER(ptr_bar->filling)], ((CONFIG_INTEGER(ptr_bar->position) == GUI_BAR_POSITION_BOTTOM) || (CONFIG_INTEGER(ptr_bar->position) == GUI_BAR_POSITION_TOP)) ? _("height") : _("width"), diff --git a/src/core/wee-config-file.c b/src/core/wee-config-file.c index 7dad5d34e..d639d2512 100644 --- a/src/core/wee-config-file.c +++ b/src/core/wee-config-file.c @@ -42,7 +42,7 @@ struct t_config_file *config_files = NULL; struct t_config_file *last_config_file = NULL; -char *config_option_type_str[CONFIG_NUM_OPTION_TYPES] = +char *config_option_type_string[CONFIG_NUM_OPTION_TYPES] = { "boolean", "integer", "string", "color" }; char *config_boolean_true[] = { "on", "yes", "y", "true", "t", "1", NULL }; char *config_boolean_false[] = { "off", "no", "n", "false", "f", "0", NULL }; @@ -367,7 +367,7 @@ config_file_new_option (struct t_config_file *config_file, var_type = -1; for (i = 0; i < CONFIG_NUM_OPTION_TYPES; i++) { - if (string_strcasecmp (type, config_option_type_str[i]) == 0) + if (string_strcasecmp (type, config_option_type_string[i]) == 0) { var_type = i; break; diff --git a/src/core/wee-config.c b/src/core/wee-config.c index d6733fb54..48191e78a 100644 --- a/src/core/wee-config.c +++ b/src/core/wee-config.c @@ -164,14 +164,6 @@ struct t_config_option *config_color_nicklist_prefix4; struct t_config_option *config_color_nicklist_prefix5; struct t_config_option *config_color_nicklist_more; struct t_config_option *config_color_nicklist_separator; -struct t_config_option *config_color_info; -struct t_config_option *config_color_info_bg; -struct t_config_option *config_color_info_waiting; -struct t_config_option *config_color_info_connecting; -struct t_config_option *config_color_info_active; -struct t_config_option *config_color_info_done; -struct t_config_option *config_color_info_failed; -struct t_config_option *config_color_info_aborted; /* config, history section */ @@ -1440,56 +1432,7 @@ config_weechat_init () N_("text color for nicklist separator"), NULL, GUI_COLOR_NICKLIST_SEPARATOR, 0, "blue", NULL, NULL, &config_change_color, NULL, NULL, NULL); - /* status info */ - config_color_info = config_file_new_option ( - weechat_config_file, ptr_section, - "info", "color", - N_("text color for status info"), - NULL, GUI_COLOR_INFO, 0, "default", - NULL, NULL, &config_change_color, NULL, NULL, NULL); - config_color_info_bg = config_file_new_option ( - weechat_config_file, ptr_section, - "info_bg", "color", - N_("background color for status info"), - NULL, -1, 0, "default", - NULL, NULL, &config_change_color, NULL, NULL, NULL); - config_color_info_waiting = config_file_new_option ( - weechat_config_file, ptr_section, - "info_waiting", "color", - N_("text color for \"waiting\" status info"), - NULL, GUI_COLOR_INFO_WAITING, 0, "lightcyan", - NULL, NULL, &config_change_color, NULL, NULL, NULL); - config_color_info_connecting = config_file_new_option ( - weechat_config_file, ptr_section, - "info_connecting", "color", - N_("text color for \"connecting\" status info"), - NULL, GUI_COLOR_INFO_CONNECTING, 0, "yellow", - NULL, NULL, &config_change_color, NULL, NULL, NULL); - config_color_info_active = config_file_new_option ( - weechat_config_file, ptr_section, - "info_active", "color", - N_("text color for \"active\" status info"), - NULL, GUI_COLOR_INFO_ACTIVE, 0, "lightblue", - NULL, NULL, &config_change_color, NULL, NULL, NULL); - config_color_info_done = config_file_new_option ( - weechat_config_file, ptr_section, - "info_done", "color", - N_("text color for \"done\" status info"), - NULL, GUI_COLOR_INFO_DONE, 0, "lightgreen", - NULL, NULL, &config_change_color, NULL, NULL, NULL); - config_color_info_failed = config_file_new_option ( - weechat_config_file, ptr_section, - "info_failed", "color", - N_("text color for \"failed\" status info"), - NULL, GUI_COLOR_INFO_FAILED, 0, "lightred", - NULL, NULL, &config_change_color, NULL, NULL, NULL); - config_color_info_aborted = config_file_new_option ( - weechat_config_file, ptr_section, - "info_aborted", "color", - N_("text color for \"aborted\" status info"), - NULL, GUI_COLOR_INFO_ABORTED, 0, "lightred", - NULL, NULL, &config_change_color, NULL, NULL, NULL); - + /* history */ ptr_section = config_file_new_section (weechat_config_file, "history", 0, 0, diff --git a/src/core/wee-config.h b/src/core/wee-config.h index 47b81ffb5..66126dda0 100644 --- a/src/core/wee-config.h +++ b/src/core/wee-config.h @@ -152,14 +152,6 @@ extern struct t_config_option *config_color_nicklist_prefix4; extern struct t_config_option *config_color_nicklist_prefix5; extern struct t_config_option *config_color_nicklist_more; extern struct t_config_option *config_color_nicklist_separator; -extern struct t_config_option *config_color_info; -extern struct t_config_option *config_color_info_bg; -extern struct t_config_option *config_color_info_waiting; -extern struct t_config_option *config_color_info_connecting; -extern struct t_config_option *config_color_info_active; -extern struct t_config_option *config_color_info_done; -extern struct t_config_option *config_color_info_failed; -extern struct t_config_option *config_color_info_aborted; extern struct t_config_option *config_history_max_lines; extern struct t_config_option *config_history_max_commands; diff --git a/src/core/wee-network.c b/src/core/wee-network.c new file mode 100644 index 000000000..1c9e5dc63 --- /dev/null +++ b/src/core/wee-network.c @@ -0,0 +1,456 @@ +/* + * 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-network.c: network functions for WeeChat */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <errno.h> + +#include "weechat.h" +#include "wee-network.h" +#include "wee-config.h" +#include "wee-string.h" + + +/* + * network_convbase64_8x3_to_6x4 : convert 3 bytes of 8 bits in 4 bytes of 6 bits + */ + +void +network_convbase64_8x3_to_6x4 (char *from, char *to) +{ + unsigned char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz0123456789+/"; + + to[0] = base64_table [ (from[0] & 0xfc) >> 2 ]; + to[1] = base64_table [ ((from[0] & 0x03) << 4) + ((from[1] & 0xf0) >> 4) ]; + to[2] = base64_table [ ((from[1] & 0x0f) << 2) + ((from[2] & 0xc0) >> 6) ]; + to[3] = base64_table [ from[2] & 0x3f ]; +} + +/* + * network_base64encode: encode a string in base64 + */ + +void +network_base64encode (char *from, char *to) +{ + char *f, *t; + int from_len; + + from_len = strlen (from); + + f = from; + t = to; + + while (from_len >= 3) + { + network_convbase64_8x3_to_6x4 (f, t); + f += 3 * sizeof (*f); + t += 4 * sizeof (*t); + from_len -= 3; + } + + if (from_len > 0) + { + char rest[3] = { 0, 0, 0 }; + switch (from_len) + { + case 1 : + rest[0] = f[0]; + network_convbase64_8x3_to_6x4 (rest, t); + t[2] = t[3] = '='; + break; + case 2 : + rest[0] = f[0]; + rest[1] = f[1]; + network_convbase64_8x3_to_6x4 (rest, t); + t[3] = '='; + break; + } + t[4] = 0; + } +} + +/* + * network_pass_httpproxy: establish connection/authentification to an + * http proxy + * return : + * - 0 if connexion throw proxy was successful + * - 1 if connexion fails + */ + +int +network_pass_httpproxy (int sock, 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]) + { + /* authentification */ + snprintf (authbuf, sizeof (authbuf), "%s:%s", + CONFIG_STRING(config_proxy_username), + (CONFIG_STRING(config_proxy_password)) ? + CONFIG_STRING(config_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", + address, port, authbuf_base64); + } + else + { + /* no authentification */ + n = snprintf (buffer, sizeof (buffer), + "CONNECT %s:%d HTTP/1.0\r\n\r\n", address, port); + } + + m = send (sock, buffer, n, 0); + if (n != m) + return 1; + + n = recv (sock, buffer, sizeof (buffer), 0); + + /* success result must be like: "HTTP/1.0 200 OK" */ + if (n < 12) + return 1; + + if (memcmp (buffer, "HTTP/", 5) || memcmp (buffer + 9, "200", 3)) + return 1; + + return 0; +} + +/* + * network_resolve: resolve hostname on its IP address + * (works with ipv4 and ipv6) + * return : + * - 0 if resolution was successful + * - 1 if resolution fails + */ + +int +network_resolve (char *hostname, char *ip, int *version) +{ + char ipbuffer[NI_MAXHOST]; + struct addrinfo *res; + + if (version != NULL) + *version = 0; + + res = NULL; + + if (getaddrinfo (hostname, NULL, NULL, &res) != 0) + return 1; + + if (!res) + return 1; + + if (getnameinfo (res->ai_addr, res->ai_addrlen, ipbuffer, sizeof(ipbuffer), + NULL, 0, NI_NUMERICHOST) != 0) + { + freeaddrinfo (res); + return 1; + } + + if ((res->ai_family == AF_INET) && (version != NULL)) + *version = 4; + if ((res->ai_family == AF_INET6) && (version != NULL)) + *version = 6; + + strcpy (ip, ipbuffer); + + freeaddrinfo (res); + + return 0; +} + +/* + * network_pass_socks4proxy: establish connection/authentification thru a + * socks4 proxy + * return : + * - 0 if connexion thru proxy was successful + * - 1 if connexion fails + */ + +int +network_pass_socks4proxy (int sock, char *address, int port) +{ + /* + * socks4 protocol is explained here: + * http://archive.socks.permeo.com/protocol/socks4.protocol + * + */ + + 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 long address; /* 4 bytes */ /* destination address */ + char user[64]; /* username (64 characters seems to be enought) */ + } socks4; + unsigned char buffer[24]; + char ip_addr[NI_MAXHOST]; + + socks4.version = 4; + socks4.method = 1; + socks4.port = htons (port); + network_resolve (address, ip_addr, NULL); + socks4.address = inet_addr (ip_addr); + strncpy (socks4.user, CONFIG_STRING(config_proxy_username), + sizeof (socks4.user) - 1); + + send (sock, (char *) &socks4, 8 + strlen (socks4.user) + 1, 0); + recv (sock, buffer, sizeof (buffer), 0); + + if (buffer[0] == 0 && buffer[1] == 90) + return 0; + + return 1; +} + +/* + * network_pass_socks5proxy: establish connection/authentification thru a + * socks5 proxy + * return : + * - 0 if connexion thru proxy was successful + * - 1 if connexion fails + */ + +int +network_pass_socks5proxy (int sock, 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; + unsigned char buffer[288]; + int username_len, password_len, addr_len, addr_buffer_len; + unsigned char *addr_buffer; + + socks5.version = 5; + socks5.nmethods = 1; + + if (CONFIG_STRING(config_proxy_username) + && CONFIG_STRING(config_proxy_username)[0]) + socks5.method = 2; /* with authentication */ + else + socks5.method = 0; /* without authentication */ + + send (sock, (char *) &socks5, sizeof(socks5), 0); + /* server socks5 must respond with 2 bytes */ + if (recv (sock, buffer, 2, 0) != 2) + return 1; + + if (CONFIG_STRING(config_proxy_username) + && CONFIG_STRING(config_proxy_username)[0]) + { + /* with authentication */ + /* -> socks server must respond with : + * - socks version (buffer[0]) = 5 => socks5 + * - socks method (buffer[1]) = 2 => authentication + */ + + if (buffer[0] != 5 || buffer[1] != 2) + return 1; + + /* authentication as in RFC 1929 */ + username_len = strlen (CONFIG_STRING(config_proxy_username)); + password_len = strlen (CONFIG_STRING(config_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); + buffer[2 + username_len] = (unsigned char) password_len; + memcpy (buffer + 3 + username_len, + CONFIG_STRING(config_proxy_password), password_len); + + send (sock, buffer, 3 + username_len + password_len, 0); + + /* server socks5 must respond with 2 bytes */ + if (recv (sock, buffer, 2, 0) != 2) + return 1; + + /* buffer[1] = auth state, must be 0 for success */ + if (buffer[1] != 0) + return 1; + } + else + { + /* without authentication */ + /* -> socks server must respond with : + * - socks version (buffer[0]) = 5 => socks5 + * - socks method (buffer[1]) = 0 => no authentication + */ + if (!(buffer[0] == 5 && buffer[1] == 0)) + return 1; + } + + /* authentication successful then giving address/port to connect */ + addr_len = strlen(address); + addr_buffer_len = 4 + 1 + addr_len + 2; + addr_buffer = malloc (addr_buffer_len * sizeof(*addr_buffer)); + if (!addr_buffer) + return 1; + addr_buffer[0] = 5; /* version 5 */ + addr_buffer[1] = 1; /* command: 1 for connect */ + addr_buffer[2] = 0; /* reserved */ + addr_buffer[3] = 3; /* address type : ipv4 (1), domainname (3), ipv6 (4) */ + addr_buffer[4] = (unsigned char) addr_len; + memcpy (addr_buffer + 5, address, addr_len); /* server address */ + *((unsigned short *) (addr_buffer + 5 + addr_len)) = htons (port); /* server port */ + + send (sock, addr_buffer, addr_buffer_len, 0); + free (addr_buffer); + + /* dialog with proxy server */ + if (recv (sock, buffer, 4, 0) != 4) + return 1; + + if (!(buffer[0] == 5 && buffer[1] == 0)) + return 1; + + /* buffer[3] = address type */ + switch (buffer[3]) + { + case 1: + /* ipv4 + * server socks return server bound address and port + * address of 4 bytes and port of 2 bytes (= 6 bytes) + */ + if (recv (sock, buffer, 6, 0) != 6) + return 1; + break; + case 3: + /* domainname + * server socks return server bound address and port + */ + /* reading address length */ + if (recv (sock, buffer, 1, 0) != 1) + return 1; + addr_len = buffer[0]; + /* reading address + port = addr_len + 2 */ + if (recv (sock, buffer, addr_len + 2, 0) != (addr_len + 2)) + return 1; + break; + case 4: + /* ipv6 + * server socks return server bound address and port + * address of 16 bytes and port of 2 bytes (= 18 bytes) + */ + if (recv (sock, buffer, 18, 0) != 18) + return 1; + break; + default: + return 1; + } + + return 0; +} + +/* + * network_pass_proxy: establish connection/authentification to a proxy + * return : + * - 0 if connexion throw proxy was successful + * - 1 if connexion fails + */ + +int +network_pass_proxy (int sock, char *address, int port) +{ + int rc; + + rc = 1; + if (CONFIG_BOOLEAN(config_proxy_type)) + { + if (string_strcasecmp (CONFIG_STRING(config_proxy_type), "http") == 0) + rc = network_pass_httpproxy (sock, address, port); + if (string_strcasecmp (CONFIG_STRING(config_proxy_type), "socks4") == 0) + rc = network_pass_socks4proxy (sock, address, port); + if (string_strcasecmp (CONFIG_STRING(config_proxy_type), "socks5") == 0) + rc = network_pass_socks5proxy (sock, address, port); + } + return rc; +} + +/* + * network_connect_to: connect to a remote host + * return 1 if ok, 0 if failed + */ + +int +network_connect_to (int sock, unsigned long address, int port) +{ + struct sockaddr_in addr; + struct hostent *hostent; + char *ip4; + int ret; + + if (CONFIG_BOOLEAN(config_proxy_type)) + { + 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_family = AF_INET; + hostent = gethostbyname (CONFIG_STRING(config_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) == -1) + return 0; + } + else + { + memset (&addr, 0, sizeof (addr)); + addr.sin_port = htons (port); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl (address); + ret = connect (sock, (struct sockaddr *) &addr, sizeof (addr)); + if ((ret == -1) && (errno != EINPROGRESS)) + return 0; + } + return 1; +} diff --git a/src/core/wee-network.h b/src/core/wee-network.h new file mode 100644 index 000000000..cf4c61f73 --- /dev/null +++ b/src/core/wee-network.h @@ -0,0 +1,26 @@ +/* + * 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_NETWORK_H +#define __WEECHAT_NETWORK_H 1 + +extern int network_pass_proxy (int sock, char *address, int port); +extern int network_connect_to (int sock, unsigned long address, int port); + +#endif /* wee-network.h */ |