summaryrefslogtreecommitdiff
path: root/src/plugins/irc/irc-server.c
diff options
context:
space:
mode:
authorSebastien Helleu <flashcode@flashtux.org>2008-05-04 20:24:20 +0200
committerSebastien Helleu <flashcode@flashtux.org>2008-05-04 20:24:20 +0200
commite7a16efa0cf5123f87ef6d7072fbbb9ccdd42bac (patch)
treeee16107b4a6d1dc30b3db6fcb60f2c979d77bd4b /src/plugins/irc/irc-server.c
parentff526c31684cc825ae0542fb0d35e76720f6d6ea (diff)
downloadweechat-e7a16efa0cf5123f87ef6d7072fbbb9ccdd42bac.zip
Added new plugin "xfer" (used by irc plugin for DCC file and chat) (warning: initial commit, not working yet)
Diffstat (limited to 'src/plugins/irc/irc-server.c')
-rw-r--r--src/plugins/irc/irc-server.c461
1 files changed, 73 insertions, 388 deletions
diff --git a/src/plugins/irc/irc-server.c b/src/plugins/irc/irc-server.c
index fe6834771..bef2fdcaf 100644
--- a/src/plugins/irc/irc-server.c
+++ b/src/plugins/irc/irc-server.c
@@ -36,10 +36,6 @@
#include <arpa/inet.h>
#include <netdb.h>
-#ifdef HAVE_GNUTLS
-#include <gnutls/gnutls.h>
-#endif
-
#include "../weechat-plugin.h"
#include "irc.h"
#include "irc-server.h"
@@ -2057,386 +2053,6 @@ irc_server_child_read_cb (void *arg_server)
}
/*
- * irc_server_convbase64_8x3_to_6x4 : convert 3 bytes of 8 bits in 4 bytes of 6 bits
- */
-
-void
-irc_server_convbase64_8x3_to_6x4 (char *from, char *to)
-{
- unsigned char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
- 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 ];
-}
-
-/*
- * irc_server_base64encode: encode a string in base64
- */
-
-void
-irc_server_base64encode (char *from, char *to)
-{
- char *f, *t;
- int from_len;
-
- from_len = strlen(from);
-
- f = from;
- t = to;
-
- while (from_len >= 3)
- {
- irc_server_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];
- irc_server_convbase64_8x3_to_6x4 (rest, t);
- t[2] = t[3] = '=';
- break;
- case 2 :
- rest[0] = f[0];
- rest[1] = f[1];
- irc_server_convbase64_8x3_to_6x4 (rest, t);
- t[3] = '=';
- break;
- }
- t[4] = 0;
- }
-}
-
-/*
- * irc_server_pass_httpproxy: establish connection/authentification to an
- * http proxy
- * return :
- * - 0 if connexion throw proxy was successful
- * - 1 if connexion fails
- */
-
-int
-irc_server_pass_httpproxy (int sock, char *address, int port)
-{
-
- char buffer[256], authbuf[128], authbuf_base64[196];
- char *config_proxy_username, *config_proxy_password;
- int n, m;
-
- config_proxy_username = weechat_config_string (
- weechat_config_get ("weechat.proxy.username"));
- config_proxy_username = weechat_config_string (
- weechat_config_get ("weechat.proxy.password"));
-
- if (config_proxy_username && config_proxy_username[0])
- {
- /* authentification */
- snprintf (authbuf, sizeof (authbuf), "%s:%s",
- config_proxy_username,
- (config_proxy_password) ? config_proxy_password : "");
- irc_server_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;
-}
-
-/*
- * irc_server_resolve: resolve hostname on its IP address
- * (works with ipv4 and ipv6)
- * return :
- * - 0 if resolution was successful
- * - 1 if resolution fails
- */
-
-int
-irc_server_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;
-}
-
-/*
- * irc_server_pass_socks4proxy: establish connection/authentification thru a
- * socks4 proxy
- * return :
- * - 0 if connexion thru proxy was successful
- * - 1 if connexion fails
- */
-
-int
-irc_server_pass_socks4proxy (int sock, char *address, int port, char *username)
-{
- /*
- * 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);
- irc_server_resolve (address, ip_addr, NULL);
- socks4.address = inet_addr (ip_addr);
- strncpy (socks4.user, 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;
-}
-
-/*
- * irc_server_pass_socks5proxy: establish connection/authentification thru a
- * socks5 proxy
- * return :
- * - 0 if connexion thru proxy was successful
- * - 1 if connexion fails
- */
-
-int
-irc_server_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;
- char *config_proxy_username, *config_proxy_password;
-
- socks5.version = 5;
- socks5.nmethods = 1;
-
- config_proxy_username = weechat_config_string (
- weechat_config_get ("weechat.proxy.username"));
- config_proxy_username = weechat_config_string (
- weechat_config_get ("weechat.proxy.password"));
-
- if (config_proxy_username && 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_proxy_username && 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_proxy_username);
- password_len = strlen (config_proxy_password);
-
- /* make username/password buffer */
- buffer[0] = 1;
- buffer[1] = (unsigned char) username_len;
- memcpy(buffer + 2, config_proxy_username, username_len);
- buffer[2 + username_len] = (unsigned char) password_len;
- memcpy (buffer + 3 + username_len, 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;
-}
-
-/*
- * irc_server_pass_proxy: establish connection/authentification to a proxy
- * return :
- * - 0 if connexion throw proxy was successful
- * - 1 if connexion fails
- */
-
-int
-irc_server_pass_proxy (int sock, char *address, int port, char *username)
-{
- int rc;
- char *config_proxy_type;
-
- config_proxy_type = weechat_config_string (
- weechat_config_get ("weechat.proxy.type"));
-
- rc = 1;
- if (config_proxy_type)
- {
- if (weechat_strcasecmp (config_proxy_type, "http") == 0)
- rc = irc_server_pass_httpproxy (sock, address, port);
- if (weechat_strcasecmp (config_proxy_type, "socks4") == 0)
- rc = irc_server_pass_socks4proxy (sock, address, port, username);
- if (weechat_strcasecmp (config_proxy_type, "socks5") == 0)
- rc = irc_server_pass_socks5proxy (sock, address, port);
- }
- return rc;
-}
-
-/*
* irc_server_child: child process trying to connect to server
*/
@@ -2497,10 +2113,9 @@ irc_server_child (struct t_irc_server *server)
return 0;
}
- if (irc_server_pass_proxy (server->sock,
- server->addresses_array[server->current_address],
- server->ports_array[server->current_address],
- server->username))
+ if (weechat_network_pass_proxy (server->sock,
+ server->addresses_array[server->current_address],
+ server->ports_array[server->current_address]))
{
write (server->child_write, "4", 1);
freeaddrinfo (res);
@@ -3175,6 +2790,76 @@ irc_server_set_default_notify_level (struct t_irc_server *server, int notify)
}
/*
+ * irc_server_xfer_send_ready_cb: callback called when user send (file or chat)
+ * to someone and that xfer plugin successfully
+ * initialized xfer and is ready for sending
+ * in that case, irc plugin send message to
+ * remote nick and wait for "accept" reply
+ */
+
+int
+irc_server_xfer_send_ready_cb (void *data, char *signal, char *type_data,
+ void *signal_data)
+{
+ struct t_plugin_infolist *infolist;
+ struct t_irc_server *server, *ptr_server;
+ char *plugin_id, *type;
+
+ /* make C compiler happy */
+ (void) data;
+ (void) signal;
+ (void) type_data;
+
+ infolist = (struct t_plugin_infolist *)signal_data;
+
+ if (weechat_infolist_next (infolist))
+ {
+ plugin_id = weechat_infolist_string (infolist, "plugin_id");
+ if (plugin_id)
+ {
+ if (strncmp (plugin_id, "irc_", 4) == 0)
+ {
+ sscanf (plugin_id + 4, "%x", (unsigned int *)&server);
+ for (ptr_server = irc_servers; ptr_server;
+ ptr_server = ptr_server->next_server)
+ {
+ if (ptr_server == server)
+ break;
+ }
+ if (ptr_server)
+ {
+ type = weechat_infolist_string (infolist, "type");
+ if (type)
+ {
+ if (strcmp (type, "file_send") == 0)
+ {
+ irc_server_sendf (server,
+ "PRIVMSG %s :\01DCC SEND \"%s\" "
+ "%s %d %s\01\n",
+ weechat_infolist_string (infolist, "nick"),
+ weechat_infolist_string (infolist, "filename"),
+ weechat_infolist_string (infolist, "address"),
+ weechat_infolist_integer (infolist, "port"),
+ weechat_infolist_string (infolist, "size"));
+ }
+ else if (strcmp (type, "chat_send") == 0)
+ {
+ irc_server_sendf (server,
+ "PRIVMSG %s :\01DCC CHAT chat %s %d\01",
+ weechat_infolist_string (infolist, "nick"),
+ weechat_infolist_string (infolist, "address"),
+ weechat_infolist_integer (infolist, "port"));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return WEECHAT_RC_OK;
+}
+
+/*
* irc_server_print_log: print server infos in log (usually for crash dump)
*/