mirror of
https://github.com/weechat/weechat.git
synced 2026-06-27 13:26:38 +02:00
Added new plugin "xfer" (used by irc plugin for DCC file and chat) (warning: initial commit, not working yet)
This commit is contained in:
@@ -14,17 +14,26 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
ADD_LIBRARY(irc MODULE irc.c irc.h irc-buffer.c irc-buffer.h irc-channel.c
|
||||
irc-channel.h irc-color.c irc-color.h irc-command.c irc-command.h
|
||||
irc-completion.c irc-completion.h irc-config.c irc-config.h irc-dcc.h
|
||||
irc-debug.c irc-debug.h irc-display.c irc-display.h irc-input.c irc-input.h
|
||||
irc-mode.c irc-mode.h irc-nick.c irc-nick.h irc-protocol.c irc-protocol.h
|
||||
ADD_LIBRARY(irc MODULE
|
||||
irc.c irc.h
|
||||
irc-buffer.c irc-buffer.h
|
||||
irc-channel.c irc-channel.h
|
||||
irc-color.c irc-color.h
|
||||
irc-command.c irc-command.h
|
||||
irc-completion.c irc-completion.h
|
||||
irc-config.c irc-config.h
|
||||
irc-dcc.c irc-dcc.h
|
||||
irc-debug.c irc-debug.h
|
||||
irc-display.c irc-display.h
|
||||
irc-input.c irc-input.h
|
||||
irc-mode.c irc-mode.h
|
||||
irc-nick.c irc-nick.h
|
||||
irc-protocol.c irc-protocol.h
|
||||
irc-server.c irc-server.h)
|
||||
SET_TARGET_PROPERTIES(irc PROPERTIES PREFIX "")
|
||||
|
||||
CHECK_INCLUDE_FILES("regex.h" HAVE_REGEX_H)
|
||||
CHECK_FUNCTION_EXISTS(regexec HAVE_REGEXEC)
|
||||
CHECK_FUNCTION_EXISTS(uname HAVE_UNAME)
|
||||
|
||||
TARGET_LINK_LIBRARIES(irc)
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ irc_la_SOURCES = irc.c \
|
||||
irc-completion.h \
|
||||
irc-config.c \
|
||||
irc-config.h \
|
||||
irc-dcc.c \
|
||||
irc-dcc.h \
|
||||
irc-debug.c \
|
||||
irc-debug.h \
|
||||
@@ -50,7 +51,5 @@ irc_la_SOURCES = irc.c \
|
||||
irc-server.c \
|
||||
irc-server.h
|
||||
|
||||
# irc-dcc.c
|
||||
|
||||
irc_la_LDFLAGS = -module
|
||||
irc_la_LIBADD = $(GNUTLS_LFLAGS)
|
||||
irc_la_LIBADD = $(IRC_LFLAGS) $(GNUTLS_LFLAGS)
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
#include <ctype.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "../weechat-plugin.h"
|
||||
#include "irc.h"
|
||||
@@ -855,16 +858,29 @@ int
|
||||
irc_command_dcc (void *data, struct t_gui_buffer *buffer, int argc,
|
||||
char **argv, char **argv_eol)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
socklen_t length;
|
||||
unsigned long address;
|
||||
struct t_plugin_infolist *infolist;
|
||||
struct t_plugin_infolist_item *item;
|
||||
char plugin_id[128], str_address[128];
|
||||
|
||||
IRC_GET_SERVER_CHANNEL(buffer);
|
||||
if (!ptr_server || !ptr_server->is_connected)
|
||||
return WEECHAT_RC_ERROR;
|
||||
|
||||
/* make compiler happy */
|
||||
/* make C compiler happy */
|
||||
(void) data;
|
||||
(void) argv_eol; // to remove!
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
/* use the local interface, from the server socket */
|
||||
memset (&addr, 0, sizeof (struct sockaddr_in));
|
||||
length = sizeof (addr);
|
||||
getsockname (ptr_server->sock, (struct sockaddr *) &addr, &length);
|
||||
addr.sin_family = AF_INET;
|
||||
address = ntohl (addr.sin_addr.s_addr);
|
||||
|
||||
/* DCC SEND file */
|
||||
if (weechat_strcasecmp (argv[1], "send") == 0)
|
||||
{
|
||||
@@ -872,8 +888,28 @@ irc_command_dcc (void *data, struct t_gui_buffer *buffer, int argc,
|
||||
{
|
||||
IRC_COMMAND_TOO_FEW_ARGUMENTS(ptr_server->buffer, "dcc send");
|
||||
}
|
||||
//irc_dcc_send_request (ptr_server, IRC_DCC_FILE_SEND,
|
||||
// argv[2], argv_eol[3]);
|
||||
infolist = weechat_infolist_new ();
|
||||
if (infolist)
|
||||
{
|
||||
item = weechat_infolist_new_item (infolist);
|
||||
if (item)
|
||||
{
|
||||
snprintf (plugin_id, sizeof (plugin_id),
|
||||
"irc_%x", (unsigned int)ptr_server);
|
||||
weechat_infolist_new_var_string (item, "plugin_id", plugin_id);
|
||||
weechat_infolist_new_var_string (item, "type", "file_send");
|
||||
weechat_infolist_new_var_string (item, "protocol", "dcc");
|
||||
weechat_infolist_new_var_string (item, "nick", argv[2]);
|
||||
weechat_infolist_new_var_string (item, "filename", argv_eol[3]);
|
||||
snprintf (str_address, sizeof (str_address),
|
||||
"%lu", address);
|
||||
weechat_infolist_new_var_string (item, "address", str_address);
|
||||
weechat_hook_signal_send ("xfer_add",
|
||||
WEECHAT_HOOK_SIGNAL_POINTER,
|
||||
infolist);
|
||||
}
|
||||
weechat_infolist_free (infolist);
|
||||
}
|
||||
}
|
||||
/* DCC CHAT */
|
||||
else if (weechat_strcasecmp (argv[1], "chat") == 0)
|
||||
@@ -882,8 +918,26 @@ irc_command_dcc (void *data, struct t_gui_buffer *buffer, int argc,
|
||||
{
|
||||
IRC_COMMAND_TOO_FEW_ARGUMENTS(ptr_server->buffer, "dcc chat");
|
||||
}
|
||||
//irc_dcc_send_request (ptr_server, IRC_DCC_CHAT_SEND,
|
||||
// argv[2], NULL);
|
||||
infolist = weechat_infolist_new ();
|
||||
if (infolist)
|
||||
{
|
||||
item = weechat_infolist_new_item (infolist);
|
||||
if (item)
|
||||
{
|
||||
snprintf (plugin_id, sizeof (plugin_id),
|
||||
"irc_%x", (unsigned int)ptr_server);
|
||||
weechat_infolist_new_var_string (item, "plugin_id", plugin_id);
|
||||
weechat_infolist_new_var_string (item, "type", "chat_send");
|
||||
weechat_infolist_new_var_string (item, "nick", argv[2]);
|
||||
snprintf (str_address, sizeof (str_address),
|
||||
"%lu", address);
|
||||
weechat_infolist_new_var_string (item, "address", str_address);
|
||||
weechat_hook_signal_send ("xfer_add",
|
||||
WEECHAT_HOOK_SIGNAL_POINTER,
|
||||
infolist);
|
||||
}
|
||||
weechat_infolist_free (infolist);
|
||||
}
|
||||
}
|
||||
/* close DCC CHAT */
|
||||
else if (weechat_strcasecmp (argv[1], "close") == 0)
|
||||
|
||||
+11
-107
@@ -33,7 +33,7 @@
|
||||
#include "irc-server.h"
|
||||
|
||||
|
||||
char *irc_config_server_option_str[IRC_CONFIG_NUM_SERVER_OPTIONS] =
|
||||
char *irc_config_server_option_string[IRC_CONFIG_NUM_SERVER_OPTIONS] =
|
||||
{ "autoconnect", "autoreconnect", "autoreconnect_delay", "addresses", "ipv6",
|
||||
"ssl", "password", "nicks", "username", "realname", "hostname", "command",
|
||||
"command_delay", "autojoin", "autorejoin", "notify_levels"
|
||||
@@ -47,7 +47,7 @@ struct t_config_file *irc_config_file = NULL;
|
||||
struct t_config_section *irc_config_section_server_default = NULL;
|
||||
struct t_config_section *irc_config_section_server = NULL;
|
||||
|
||||
/* config, look section */
|
||||
/* IRC config, look section */
|
||||
|
||||
struct t_config_option *irc_config_look_one_server_buffer;
|
||||
struct t_config_option *irc_config_look_open_near_server;
|
||||
@@ -59,7 +59,7 @@ struct t_config_option *irc_config_look_show_away_once;
|
||||
struct t_config_option *irc_config_look_notice_as_pv;
|
||||
struct t_config_option *irc_config_look_highlight;
|
||||
|
||||
/* config, network section */
|
||||
/* IRC config, network section */
|
||||
|
||||
struct t_config_option *irc_config_network_default_msg_part;
|
||||
struct t_config_option *irc_config_network_default_msg_quit;
|
||||
@@ -73,29 +73,14 @@ struct t_config_option *irc_config_network_colors_receive;
|
||||
struct t_config_option *irc_config_network_colors_send;
|
||||
struct t_config_option *irc_config_network_send_unknown_commands;
|
||||
|
||||
/* config, dcc section */
|
||||
|
||||
struct t_config_option *irc_config_dcc_auto_accept_files;
|
||||
struct t_config_option *irc_config_dcc_auto_accept_chats;
|
||||
struct t_config_option *irc_config_dcc_timeout;
|
||||
struct t_config_option *irc_config_dcc_blocksize;
|
||||
struct t_config_option *irc_config_dcc_fast_send;
|
||||
struct t_config_option *irc_config_dcc_port_range;
|
||||
struct t_config_option *irc_config_dcc_own_ip;
|
||||
struct t_config_option *irc_config_dcc_download_path;
|
||||
struct t_config_option *irc_config_dcc_upload_path;
|
||||
struct t_config_option *irc_config_dcc_convert_spaces;
|
||||
struct t_config_option *irc_config_dcc_auto_rename;
|
||||
struct t_config_option *irc_config_dcc_auto_resume;
|
||||
|
||||
/* config, log section */
|
||||
/* IRC config, log section */
|
||||
|
||||
struct t_config_option *irc_config_log_auto_log_server;
|
||||
struct t_config_option *irc_config_log_auto_log_channel;
|
||||
struct t_config_option *irc_config_log_auto_log_private;
|
||||
struct t_config_option *irc_config_log_hide_nickserv_pwd;
|
||||
|
||||
/* config, server section */
|
||||
/* IRC config, server section */
|
||||
|
||||
struct t_config_option *irc_config_server_default[IRC_CONFIG_NUM_SERVER_OPTIONS];
|
||||
|
||||
@@ -117,7 +102,7 @@ irc_config_search_server_option (char *option_name)
|
||||
|
||||
for (i = 0; i < IRC_CONFIG_NUM_SERVER_OPTIONS; i++)
|
||||
{
|
||||
if (weechat_strcasecmp (irc_config_server_option_str[i],
|
||||
if (weechat_strcasecmp (irc_config_server_option_string[i],
|
||||
option_name) == 0)
|
||||
return i;
|
||||
}
|
||||
@@ -757,9 +742,9 @@ irc_config_server_create_option (void *data, struct t_config_file *config_file,
|
||||
option_name,
|
||||
value,
|
||||
&irc_config_server_change_cb,
|
||||
irc_config_server_option_str[index_option],
|
||||
irc_config_server_option_string[index_option],
|
||||
&irc_config_server_delete_cb,
|
||||
irc_config_server_option_str[index_option]);
|
||||
irc_config_server_option_string[index_option]);
|
||||
|
||||
if (ptr_option)
|
||||
{
|
||||
@@ -857,10 +842,10 @@ irc_config_server_create_default_options (struct t_config_section *section)
|
||||
irc_config_file,
|
||||
section,
|
||||
i,
|
||||
irc_config_server_option_str[i],
|
||||
irc_config_server_option_string[i],
|
||||
default_value,
|
||||
&irc_config_server_default_change_cb,
|
||||
irc_config_server_option_str[i],
|
||||
irc_config_server_option_string[i],
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
@@ -1013,83 +998,6 @@ irc_config_init ()
|
||||
N_("send unknown commands to IRC server"),
|
||||
NULL, 0, 0, "off", NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
ptr_section = weechat_config_new_section (irc_config_file, "dcc",
|
||||
0, 0,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL);
|
||||
if (!ptr_section)
|
||||
{
|
||||
weechat_config_free (irc_config_file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
irc_config_dcc_auto_accept_files = weechat_config_new_option (
|
||||
irc_config_file, ptr_section,
|
||||
"auto_accept_files", "boolean",
|
||||
N_("automatically accept incoming dcc files (use carefully!)"),
|
||||
NULL, 0, 0, "off", NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
irc_config_dcc_auto_accept_chats = weechat_config_new_option (
|
||||
irc_config_file, ptr_section,
|
||||
"auto_accept_chats", "boolean",
|
||||
N_("automatically accept dcc chats (use carefully!)"),
|
||||
NULL, 0, 0, "off", NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
irc_config_dcc_timeout = weechat_config_new_option (
|
||||
irc_config_file, ptr_section,
|
||||
"timeout", "integer",
|
||||
N_("timeout for dcc request (in seconds)"),
|
||||
NULL, 5, INT_MAX, "300", NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
irc_config_dcc_blocksize = weechat_config_new_option (
|
||||
irc_config_file, ptr_section,
|
||||
"blocksize", "integer",
|
||||
N_("block size for dcc packets in bytes"),
|
||||
NULL, IRC_DCC_MIN_BLOCKSIZE, IRC_DCC_MAX_BLOCKSIZE, "65536",
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
irc_config_dcc_fast_send = weechat_config_new_option (
|
||||
irc_config_file, ptr_section,
|
||||
"fast_send", "boolean",
|
||||
N_("does not wait for ACK when sending file"),
|
||||
NULL, 0, 0, "on", NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
irc_config_dcc_port_range = weechat_config_new_option (
|
||||
irc_config_file, ptr_section,
|
||||
"port_range", "string",
|
||||
N_("restricts outgoing dcc to use only ports in the given range "
|
||||
"(useful for NAT) (syntax: a single port, ie. 5000 or a port "
|
||||
"range, ie. 5000-5015, empty value means any port)"),
|
||||
NULL, 0, 0, "", NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
irc_config_dcc_own_ip = weechat_config_new_option (
|
||||
irc_config_file, ptr_section,
|
||||
"own_ip", "string",
|
||||
N_("IP or DNS address used for outgoing dcc "
|
||||
"(if empty, local interface IP is used)"),
|
||||
NULL, 0, 0, "", NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
irc_config_dcc_download_path = weechat_config_new_option (
|
||||
irc_config_file, ptr_section,
|
||||
"download_path", "string",
|
||||
N_("path for writing incoming files with dcc"),
|
||||
NULL, 0, 0, "%h/dcc", NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
irc_config_dcc_upload_path = weechat_config_new_option (
|
||||
irc_config_file, ptr_section,
|
||||
"upload_path", "string",
|
||||
N_("path for reading files when sending thru dcc (when no path is "
|
||||
"specified)"),
|
||||
NULL, 0, 0, "~", NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
irc_config_dcc_convert_spaces = weechat_config_new_option (
|
||||
irc_config_file, ptr_section,
|
||||
"convert_spaces", "boolean",
|
||||
N_("convert spaces to underscores when sending files"),
|
||||
NULL, 0, 0, "on", NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
irc_config_dcc_auto_rename = weechat_config_new_option (
|
||||
irc_config_file, ptr_section,
|
||||
"auto_rename", "boolean",
|
||||
N_("rename incoming files if already exists (add '.1', '.2', ...)"),
|
||||
NULL, 0, 0, "on", NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
irc_config_dcc_auto_resume = weechat_config_new_option (
|
||||
irc_config_file, ptr_section,
|
||||
"auto_resume", "boolean",
|
||||
N_("automatically resume dcc transfer if connection with remote host "
|
||||
"is loosed"),
|
||||
NULL, 0, 0, "on", NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
ptr_section = weechat_config_new_section (irc_config_file, "log",
|
||||
0, 0,
|
||||
NULL, NULL, NULL, NULL,
|
||||
@@ -1162,11 +1070,7 @@ irc_config_init ()
|
||||
int
|
||||
irc_config_read ()
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = weechat_config_read (irc_config_file);
|
||||
|
||||
return rc;
|
||||
return weechat_config_read (irc_config_file);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -57,7 +57,7 @@ enum t_irc_config_server_option
|
||||
#define IRC_CONFIG_SERVER_DEFAULT_AUTOREJOIN 0
|
||||
|
||||
|
||||
extern char *irc_config_server_option_str[];
|
||||
extern char *irc_config_server_option_string[];
|
||||
extern struct t_config_file *irc_config;
|
||||
|
||||
extern struct t_config_option *irc_config_look_one_server_buffer;
|
||||
@@ -82,19 +82,6 @@ extern struct t_config_option *irc_config_network_colors_receive;
|
||||
extern struct t_config_option *irc_config_network_colors_send;
|
||||
extern struct t_config_option *irc_config_network_send_unknown_commands;
|
||||
|
||||
extern struct t_config_option *irc_config_dcc_auto_accept_files;
|
||||
extern struct t_config_option *irc_config_dcc_auto_accept_chats;
|
||||
extern struct t_config_option *irc_config_dcc_timeout;
|
||||
extern struct t_config_option *irc_config_dcc_blocksize;
|
||||
extern struct t_config_option *irc_config_dcc_fast_send;
|
||||
extern struct t_config_option *irc_config_dcc_port_range;
|
||||
extern struct t_config_option *irc_config_dcc_own_ip;
|
||||
extern struct t_config_option *irc_config_dcc_download_path;
|
||||
extern struct t_config_option *irc_config_dcc_upload_path;
|
||||
extern struct t_config_option *irc_config_dcc_convert_spaces;
|
||||
extern struct t_config_option *irc_config_dcc_auto_rename;
|
||||
extern struct t_config_option *irc_config_dcc_auto_resume;
|
||||
|
||||
extern struct t_config_option *irc_config_log_auto_log_server;
|
||||
extern struct t_config_option *irc_config_log_auto_log_channel;
|
||||
extern struct t_config_option *irc_config_log_auto_log_private;
|
||||
|
||||
+13
-1630
File diff suppressed because it is too large
Load Diff
@@ -63,20 +63,16 @@ irc_debug_printf (struct t_irc_server *server, int send, int modified,
|
||||
|
||||
if (!irc_debug_buffer)
|
||||
{
|
||||
/* search for irc debug buffer */
|
||||
irc_debug_buffer = weechat_buffer_search ("irc", "debug");
|
||||
irc_debug_buffer = weechat_buffer_new ("irc", "debug",
|
||||
NULL, NULL,
|
||||
&irc_debug_buffer_close_cb, NULL);
|
||||
|
||||
/* failed to create buffer ? then exit */
|
||||
if (!irc_debug_buffer)
|
||||
{
|
||||
irc_debug_buffer = weechat_buffer_new ("irc", "debug",
|
||||
NULL, NULL,
|
||||
&irc_debug_buffer_close_cb, NULL);
|
||||
/* failed to create buffer ? then exit */
|
||||
if (!irc_debug_buffer)
|
||||
return;
|
||||
|
||||
weechat_buffer_set (irc_debug_buffer,
|
||||
"title", _("IRC debug messages"));
|
||||
}
|
||||
return;
|
||||
|
||||
weechat_buffer_set (irc_debug_buffer,
|
||||
"title", _("IRC debug messages"));
|
||||
}
|
||||
|
||||
buf = weechat_iconv_to_internal (NULL, message);
|
||||
@@ -144,8 +140,6 @@ irc_debug_signal_debug_dump_cb (void *data, char *signal, char *type_data,
|
||||
|
||||
irc_server_print_log ();
|
||||
|
||||
//irc_dcc_print_log ();
|
||||
|
||||
weechat_log_printf ("");
|
||||
weechat_log_printf ("***** End of \"%s\" plugin dump *****",
|
||||
weechat_plugin->name);
|
||||
|
||||
+73
-388
@@ -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"
|
||||
@@ -2056,386 +2052,6 @@ irc_server_child_read_cb (void *arg_server)
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
@@ -3174,6 +2789,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)
|
||||
*/
|
||||
|
||||
@@ -186,6 +186,8 @@ extern void irc_server_disconnect (struct t_irc_server *server, int reconnect);
|
||||
extern void irc_server_disconnect_all ();
|
||||
extern void irc_server_free (struct t_irc_server *server);
|
||||
extern void irc_server_free_data (struct t_irc_server *server);
|
||||
extern int irc_server_xfer_send_ready_cb (void *data, char *signal,
|
||||
char *type_data, void *signal_data);
|
||||
extern void irc_server_print_log ();
|
||||
|
||||
#endif /* irc-server.h */
|
||||
|
||||
+3
-33
@@ -22,10 +22,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_GNUTLS
|
||||
#include <gnutls/gnutls.h>
|
||||
#endif
|
||||
|
||||
#include "../weechat-plugin.h"
|
||||
#include "irc.h"
|
||||
#include "irc-command.h"
|
||||
@@ -55,31 +51,6 @@ gnutls_certificate_credentials gnutls_xcred; /* gnutls client credentials */
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* irc_create_directories: create directories for IRC plugin
|
||||
*/
|
||||
|
||||
void
|
||||
irc_create_directories ()
|
||||
{
|
||||
char *weechat_dir, *dir1, *dir2;
|
||||
|
||||
/* create DCC download directory */
|
||||
weechat_dir = weechat_info_get ("weechat_dir");
|
||||
if (weechat_dir)
|
||||
{
|
||||
dir1 = weechat_string_replace (weechat_config_string (irc_config_dcc_download_path),
|
||||
"~", getenv ("HOME"));
|
||||
dir2 = weechat_string_replace (dir1, "%h", weechat_dir);
|
||||
if (dir2)
|
||||
(void) weechat_mkdir (dir2, 0700);
|
||||
if (dir1)
|
||||
free (dir1);
|
||||
if (dir2)
|
||||
free (dir2);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* irc_signal_quit_cb: callback for "quit" signal
|
||||
*/
|
||||
@@ -128,14 +99,13 @@ weechat_plugin_init (struct t_weechat_plugin *plugin)
|
||||
|
||||
if (irc_config_read () < 0)
|
||||
return WEECHAT_RC_ERROR;
|
||||
|
||||
irc_create_directories ();
|
||||
|
||||
|
||||
irc_command_init ();
|
||||
|
||||
|
||||
/* hook some signals */
|
||||
irc_debug_init ();
|
||||
weechat_hook_signal ("quit", &irc_signal_quit_cb, NULL);
|
||||
weechat_hook_signal ("xfer_send_ready", &irc_server_xfer_send_ready_cb, NULL);
|
||||
|
||||
/* hook completions */
|
||||
irc_completion_init ();
|
||||
|
||||
Reference in New Issue
Block a user