diff options
Diffstat (limited to 'src/plugins/irc')
-rw-r--r-- | src/plugins/irc/CMakeLists.txt | 21 | ||||
-rw-r--r-- | src/plugins/irc/Makefile.am | 5 | ||||
-rw-r--r-- | src/plugins/irc/irc-command.c | 66 | ||||
-rw-r--r-- | src/plugins/irc/irc-config.c | 118 | ||||
-rw-r--r-- | src/plugins/irc/irc-config.h | 15 | ||||
-rw-r--r-- | src/plugins/irc/irc-dcc.c | 1643 | ||||
-rw-r--r-- | src/plugins/irc/irc-debug.c | 24 | ||||
-rw-r--r-- | src/plugins/irc/irc-server.c | 461 | ||||
-rw-r--r-- | src/plugins/irc/irc-server.h | 2 | ||||
-rw-r--r-- | src/plugins/irc/irc.c | 36 |
10 files changed, 189 insertions, 2202 deletions
diff --git a/src/plugins/irc/CMakeLists.txt b/src/plugins/irc/CMakeLists.txt index 1a7d66d51..c4da9b459 100644 --- a/src/plugins/irc/CMakeLists.txt +++ b/src/plugins/irc/CMakeLists.txt @@ -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) diff --git a/src/plugins/irc/Makefile.am b/src/plugins/irc/Makefile.am index 8edaf725f..e4e25fe30 100644 --- a/src/plugins/irc/Makefile.am +++ b/src/plugins/irc/Makefile.am @@ -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) diff --git a/src/plugins/irc/irc-command.c b/src/plugins/irc/irc-command.c index fbde8a9ce..6cfa50d64 100644 --- a/src/plugins/irc/irc-command.c +++ b/src/plugins/irc/irc-command.c @@ -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) diff --git a/src/plugins/irc/irc-config.c b/src/plugins/irc/irc-config.c index b0fbcac51..d55719c8e 100644 --- a/src/plugins/irc/irc-config.c +++ b/src/plugins/irc/irc-config.c @@ -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); } /* diff --git a/src/plugins/irc/irc-config.h b/src/plugins/irc/irc-config.h index 7c3765513..dc161d94a 100644 --- a/src/plugins/irc/irc-config.h +++ b/src/plugins/irc/irc-config.h @@ -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; diff --git a/src/plugins/irc/irc-dcc.c b/src/plugins/irc/irc-dcc.c index 4ca82b0bb..5a4efe982 100644 --- a/src/plugins/irc/irc-dcc.c +++ b/src/plugins/irc/irc-dcc.c @@ -44,504 +44,11 @@ struct t_irc_dcc *irc_dcc_list = NULL; /* DCC files & chat list */ struct t_irc_dcc *irc_last_dcc = NULL; /* last DCC in list */ -char *irc_dcc_status_string[] = /* strings for DCC status */ -{ N_("Waiting"), N_("Connecting"), N_("Active"), N_("Done"), N_("Failed"), - N_("Aborted") }; - - -/* - * irc_dcc_redraw: redraw DCC buffer (and add to hotlist) - */ - -void -irc_dcc_redraw (char *hotlist) -{ - struct t_gui_buffer *ptr_buffer; - - ptr_buffer = weechat_buffer_search ("irc", "<dcc>"); - if (ptr_buffer && hotlist) - weechat_buffer_set (ptr_buffer, "hotlist", hotlist); -} - -/* - * irc_dcc_search: search a DCC - */ - -struct t_irc_dcc * -irc_dcc_search (struct t_irc_server *server, int type, int status, int port) -{ - struct t_irc_dcc *ptr_dcc; - - for (ptr_dcc = irc_dcc_list; ptr_dcc; ptr_dcc = ptr_dcc->next_dcc) - { - if ((ptr_dcc->server == server) - && (ptr_dcc->type == type) - && (ptr_dcc->status = status) - && (ptr_dcc->port == port)) - return ptr_dcc; - } - - /* DCC not found */ - return NULL; -} - -/* - * irc_dcc_port_in_use: return 1 if a port is in used - * (by an active or connecting DCC) - */ - -int -irc_dcc_port_in_use (int port) -{ - struct t_irc_dcc *ptr_dcc; - - /* skip any currently used ports */ - for (ptr_dcc = irc_dcc_list; ptr_dcc; ptr_dcc = ptr_dcc->next_dcc) - { - if ((ptr_dcc->port == port) && (!IRC_DCC_ENDED(ptr_dcc->status))) - return 1; - } - - /* port not in use */ - return 0; -} - -/* - * irc_dcc_file_is_resumable: check if a file can be used for resuming a download - */ - -int -irc_dcc_file_is_resumable (struct t_irc_dcc *ptr_dcc, char *filename) -{ - struct stat st; - - if (!weechat_config_boolean (irc_config_dcc_auto_resume)) - return 0; - - if (access (filename, W_OK) == 0) - { - if (stat (filename, &st) != -1) - { - if ((unsigned long) st.st_size < ptr_dcc->size) - { - ptr_dcc->start_resume = (unsigned long) st.st_size; - ptr_dcc->pos = st.st_size; - ptr_dcc->last_check_pos = st.st_size; - return 1; - } - } - } - - /* not resumable */ - return 0; -} - -/* - * irc_dcc_find_filename: find local filename for a DCC - * if type if file/recv, add a suffix (like .1) if needed - * if download is resumable, set "start_resume" to good value - */ - -void -irc_dcc_find_filename (struct t_irc_dcc *ptr_dcc) -{ - char *weechat_home, *dir1, *dir2, *filename2, *dir_separator; - - if (!IRC_DCC_IS_FILE(ptr_dcc->type)) - return; - - dir1 = weechat_string_replace (weechat_config_string (irc_config_dcc_download_path), - "~", - getenv ("HOME")); - if (!dir1) - return; - - weechat_home = weechat_info_get ("weechat_dir"); - if (!weechat_home) - { - free (dir1); - return; - } - dir2 = weechat_string_replace (dir1, "%h", weechat_home); - if (!dir2) - { - free (dir1); - return; - } - - ptr_dcc->local_filename = malloc (strlen (dir2) + - strlen (ptr_dcc->nick) + - strlen (ptr_dcc->filename) + 4); - if (!ptr_dcc->local_filename) - return; - - strcpy (ptr_dcc->local_filename, dir2); - dir_separator = weechat_info_get("dir_separator"); - if (dir_separator - && (ptr_dcc->local_filename[strlen (ptr_dcc->local_filename) - 1] != dir_separator[0])) - strcat (ptr_dcc->local_filename, dir_separator); - strcat (ptr_dcc->local_filename, ptr_dcc->nick); - strcat (ptr_dcc->local_filename, "."); - strcat (ptr_dcc->local_filename, ptr_dcc->filename); - - if (dir1) - free (dir1); - if (dir2 ) - free (dir2); - - /* file already exists? */ - if (access (ptr_dcc->local_filename, F_OK) == 0) - { - if (irc_dcc_file_is_resumable (ptr_dcc, ptr_dcc->local_filename)) - return; - - /* if auto rename is not set, then abort DCC */ - if (!irc_cfg_dcc_auto_rename) - { - irc_dcc_close (ptr_dcc, IRC_DCC_FAILED); - irc_dcc_redraw (WEECHAT_HOTLIST_MSG); - return; - } - - filename2 = malloc (strlen (ptr_dcc->local_filename) + 16); - if (!filename2) - { - irc_dcc_close (ptr_dcc, IRC_DCC_FAILED); - irc_dcc_redraw (WEECHAT_HOTLIST_MESSAGE); - return; - } - ptr_dcc->filename_suffix = 0; - do - { - ptr_dcc->filename_suffix++; - sprintf (filename2, "%s.%d", - ptr_dcc->local_filename, - ptr_dcc->filename_suffix); - if (access (filename2, F_OK) == 0) - { - if (irc_dcc_file_is_resumable (ptr_dcc, filename2)) - break; - } - else - break; - } - while (1); - - free (ptr_dcc->local_filename); - ptr_dcc->local_filename = strdup (filename2); - free (filename2); - } -} - -/* - * irc_dcc_calculate_speed: calculate DCC speed (for files only) - */ - -void -irc_dcc_calculate_speed (struct t_irc_dcc *ptr_dcc, int ended) -{ - time_t local_time, elapsed; - unsigned long bytes_per_sec_total; - - local_time = time (NULL); - if (ended || local_time > ptr_dcc->last_check_time) - { - if (ended) - { - /* calculate bytes per second (global) */ - elapsed = local_time - ptr_dcc->start_transfer; - if (elapsed == 0) - elapsed = 1; - ptr_dcc->bytes_per_sec = (ptr_dcc->pos - ptr_dcc->start_resume) / elapsed; - ptr_dcc->eta = 0; - } - else - { - /* calculate ETA */ - elapsed = local_time - ptr_dcc->start_transfer; - if (elapsed == 0) - elapsed = 1; - bytes_per_sec_total = (ptr_dcc->pos - ptr_dcc->start_resume) / elapsed; - if (bytes_per_sec_total == 0) - bytes_per_sec_total = 1; - ptr_dcc->eta = (ptr_dcc->size - ptr_dcc->pos) / bytes_per_sec_total; - - /* calculate bytes per second (since last check time) */ - elapsed = local_time - ptr_dcc->last_check_time; - if (elapsed == 0) - elapsed = 1; - ptr_dcc->bytes_per_sec = (ptr_dcc->pos - ptr_dcc->last_check_pos) / elapsed; - } - ptr_dcc->last_check_time = local_time; - ptr_dcc->last_check_pos = ptr_dcc->pos; - } -} - -/* - * irc_dcc_connect_to_sender: connect to sender - */ - -int -irc_dcc_connect_to_sender (struct t_irc_dcc *ptr_dcc) -{ - struct sockaddr_in addr; - struct hostent *hostent; - char *ip4; - int ret; - - if (cfg_proxy_use) - { - memset (&addr, 0, sizeof (addr)); - addr.sin_addr.s_addr = htonl (ptr_dcc->addr); - ip4 = inet_ntoa(addr.sin_addr); - - memset (&addr, 0, sizeof (addr)); - addr.sin_port = htons (cfg_proxy_port); - addr.sin_family = AF_INET; - if ((hostent = gethostbyname (cfg_proxy_address)) == NULL) - return 0; - memcpy(&(addr.sin_addr),*(hostent->h_addr_list), sizeof(struct in_addr)); - ret = connect (ptr_dcc->sock, (struct sockaddr *) &addr, sizeof (addr)); - if ((ret == -1) && (errno != EINPROGRESS)) - return 0; - if (irc_server_pass_proxy (ptr_dcc->sock, ip4, ptr_dcc->port, - ptr_dcc->server->username) == -1) - return 0; - } - else - { - memset (&addr, 0, sizeof (addr)); - addr.sin_port = htons (ptr_dcc->port); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl (ptr_dcc->addr); - ret = connect (ptr_dcc->sock, (struct sockaddr *) &addr, sizeof (addr)); - if ((ret == -1) && (errno != EINPROGRESS)) - return 0; - } - return 1; -} - -/* - * irc_dcc_connect: connect to another host - */ - -int -irc_dcc_connect (struct t_irc_dcc *ptr_dcc) -{ - if (ptr_dcc->type == IRC_DCC_CHAT_SEND) - ptr_dcc->status = IRC_DCC_WAITING; - else - ptr_dcc->status = IRC_DCC_CONNECTING; - - if (ptr_dcc->sock < 0) - { - ptr_dcc->sock = socket (AF_INET, SOCK_STREAM, 0); - if (ptr_dcc->sock < 0) - return 0; - } - - /* for chat or file sending, listen to socket for a connection */ - if (IRC_DCC_IS_SEND(ptr_dcc->type)) - { - if (fcntl (ptr_dcc->sock, F_SETFL, O_NONBLOCK) == -1) - return 0; - if (listen (ptr_dcc->sock, 1) == -1) - return 0; - if (fcntl (ptr_dcc->sock, F_SETFL, 0) == -1) - return 0; - } - - /* for chat receiving, connect to listening host */ - if (ptr_dcc->type == IRC_DCC_CHAT_RECV) - { - if (fcntl (ptr_dcc->sock, F_SETFL, O_NONBLOCK) == -1) - return 0; - irc_dcc_connect_to_sender (ptr_dcc); - } - - /* for file receiving, connection is made in child process (blocking) socket */ - - return 1; -} - -/* - * irc_dcc_free: free DCC struct and remove it from list - */ - -void -irc_dcc_free (struct t_irc_dcc *dcc) -{ - struct t_irc_dcc *new_dcc_list; - - if (!dcc) - return; - - /* DCC CHAT with channel => remove channel - (to prevent channel from becoming standard pv) */ - if (dcc->channel) - { - /* check if channel is used for another active DCC CHAT */ - if (!dcc->channel->dcc_chat - || (IRC_DCC_ENDED(dcc->channel->dcc_chat->status))) - { - gui_buffer_free (dcc->channel->buffer, 1); - if (dcc->channel) - irc_channel_free (dcc->server, dcc->channel); - } - } - - /* remove DCC from list */ - if (irc_last_dcc == dcc) - irc_last_dcc = dcc->prev_dcc; - if (dcc->prev_dcc) - { - (dcc->prev_dcc)->next_dcc = dcc->next_dcc; - new_dcc_list = irc_dcc_list; - } - else - new_dcc_list = dcc->next_dcc; - if (dcc->next_dcc) - (dcc->next_dcc)->prev_dcc = dcc->prev_dcc; - - /* free data */ - if (dcc->nick) - free (dcc->nick); - if (dcc->unterminated_message) - free (dcc->unterminated_message); - if (dcc->filename) - free (dcc->filename); - - free (dcc); - irc_dcc_list = new_dcc_list; -} - -/* - * irc_dcc_file_child_kill: kill child process and close pipe - */ - -void -irc_dcc_file_child_kill (struct t_irc_dcc *dcc) -{ - /* kill process */ - if (dcc->child_pid > 0) - { - kill (dcc->child_pid, SIGKILL); - waitpid (dcc->child_pid, NULL, 0); - dcc->child_pid = 0; - } - - /* close pipe used with child */ - if (dcc->child_read != -1) - { - close (dcc->child_read); - dcc->child_read = -1; - } - if (dcc->child_write != -1) - { - close (dcc->child_write); - dcc->child_write = -1; - } -} - -/* - * irc_dcc_close: close a DCC connection - */ - -void -irc_dcc_close (struct t_irc_dcc *dcc, int status) -{ - t_gui_buffer *ptr_buffer; - struct stat st; - - dcc->status = status; - - if ((status == IRC_DCC_DONE) || (status == IRC_DCC_ABORTED) - || (status == IRC_DCC_FAILED)) - { - if (IRC_DCC_IS_FILE(dcc->type)) - { - gui_chat_printf_info (dcc->server->buffer, - _("DCC: file %s%s%s"), - GUI_COLOR(GUI_COLOR_CHAT_CHANNEL), - dcc->filename, - GUI_COLOR(GUI_COLOR_CHAT)); - if (dcc->local_filename) - gui_chat_printf (dcc->server->buffer, - _(" (local filename: %s%s%s)"), - GUI_COLOR(GUI_COLOR_CHAT_CHANNEL), - dcc->local_filename, - GUI_COLOR(GUI_COLOR_CHAT)); - if (dcc->type == IRC_DCC_FILE_SEND) - gui_chat_printf (dcc->server->buffer, - _(" sent to ")); - else - gui_chat_printf (dcc->server->buffer, - _(" received from ")); - gui_chat_printf (dcc->server->buffer, "%s%s%s: %s\n", - GUI_COLOR(GUI_COLOR_CHAT_NICK), - dcc->nick, - GUI_COLOR(GUI_COLOR_CHAT), - (status == IRC_DCC_DONE) ? _("OK") : _("FAILED")); - irc_dcc_file_child_kill (dcc); - } - } - if (status == IRC_DCC_ABORTED) - { - if (IRC_DCC_IS_CHAT(dcc->type)) - { - if (dcc->channel) - ptr_buffer = dcc->channel->buffer; - else - ptr_buffer = dcc->server->buffer; - gui_chat_printf_info (ptr_buffer, - _("DCC chat closed with %s%s " - "%s(%s%d.%d.%d.%d%s)\n"), - GUI_COLOR(GUI_COLOR_CHAT_NICK), - dcc->nick, - GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS), - GUI_COLOR(GUI_COLOR_CHAT_HOST), - dcc->addr >> 24, - (dcc->addr >> 16) & 0xff, - (dcc->addr >> 8) & 0xff, - dcc->addr & 0xff, - GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS)); - } - } - - /* remove empty file if received file failed and nothing was transfered */ - if (((status == IRC_DCC_FAILED) || (status == IRC_DCC_ABORTED)) - && IRC_DCC_IS_FILE(dcc->type) - && IRC_DCC_IS_RECV(dcc->type) - && dcc->local_filename - && dcc->pos == 0) - { - /* erase file only if really empty on disk */ - if (stat (dcc->local_filename, &st) != -1) - { - if ((unsigned long) st.st_size == 0) - unlink (dcc->local_filename); - } - } - - if (IRC_DCC_IS_FILE(dcc->type)) - irc_dcc_calculate_speed (dcc, 1); - - if (dcc->sock >= 0) - { - close (dcc->sock); - dcc->sock = -1; - } - if (dcc->file >= 0) - { - close (dcc->file); - dcc->file = -1; - } -} /* * irc_dcc_channel_for_chat: create channel for DCC chat */ - +/* void irc_dcc_channel_for_chat (struct t_irc_dcc *dcc) { @@ -572,11 +79,11 @@ irc_dcc_channel_for_chat (struct t_irc_dcc *dcc) GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS), GUI_COLOR(GUI_COLOR_CHAT)); } - +*/ /* * irc_dcc_chat_remove_channel: remove a buffer for DCC chat */ - + /* void irc_dcc_chat_remove_channel (struct t_irc_channel *channel) { @@ -591,63 +98,11 @@ irc_dcc_chat_remove_channel (struct t_irc_channel *channel) ptr_dcc->channel = NULL; } } - -/* - * irc_dcc_recv_connect_init: connect to sender and init file or chat - */ - -void -irc_dcc_recv_connect_init (struct t_irc_dcc *dcc) -{ - if (!irc_dcc_connect (dcc)) - { - irc_dcc_close (dcc, IRC_DCC_FAILED); - irc_dcc_redraw (WEECHAT_HOTLIST_MESSAGE); - } - else - { - /* DCC file => launch child process */ - if (IRC_DCC_IS_FILE(dcc->type)) - { - dcc->status = IRC_DCC_CONNECTING; - irc_dcc_file_recv_fork (dcc); - } - else - { - /* DCC CHAT => associate DCC with channel */ - dcc->status = IRC_DCC_ACTIVE; - irc_dcc_channel_for_chat (dcc); - } - } - irc_dcc_redraw (WEECHAT_HOTLIST_MESSAGE); -} - -/* - * irc_dcc_accept: accepts a DCC file or chat request - */ - -void -irc_dcc_accept (struct t_irc_dcc *dcc) -{ - if (IRC_DCC_IS_FILE(dcc->type) && (dcc->start_resume > 0)) - { - dcc->status = IRC_DCC_CONNECTING; - irc_server_sendf (dcc->server, - (strchr (dcc->filename, ' ')) ? - "PRIVMSG %s :\01DCC RESUME \"%s\" %d %u\01\n" : - "PRIVMSG %s :\01DCC RESUME %s %d %u\01", - dcc->nick, dcc->filename, - dcc->port, dcc->start_resume); - irc_dcc_redraw (WEECHAT_HOTLIST_MESSAGE); - } - else - irc_dcc_recv_connect_init (dcc); -} - +*/ /* * irc_dcc_accept_resume: accepts a resume and inform the receiver */ - +/* void irc_dcc_accept_resume (struct t_irc_server *server, char *filename, int port, unsigned long pos_start) @@ -683,12 +138,12 @@ irc_dcc_accept_resume (struct t_irc_server *server, char *filename, int port, "position: %u): DCC not found or ended\n"), WEECHAT_ERROR, filename, port, pos_start); } - +*/ /* * irc_dcc_start_resume: called when "DCC ACCEPT" is received * (resume accepted by sender) */ - +/* void irc_dcc_start_resume (struct t_irc_server *server, char *filename, int port, unsigned long pos_start) @@ -711,1016 +166,11 @@ irc_dcc_start_resume (struct t_irc_server *server, char *filename, int port, "position: %u): DCC not found or ended\n"), WEECHAT_ERROR, filename, port, pos_start); } - -/* - * irc_dcc_alloc: allocate a new DCC file - */ - -struct t_irc_dcc * -irc_dcc_alloc () -{ - struct t_irc_dcc *new_dcc; - - /* create new DCC struct */ - if ((new_dcc = malloc (sizeof (*new_dcc))) == NULL) - return NULL; - - /* default values */ - new_dcc->server = NULL; - new_dcc->channel = NULL; - new_dcc->type = 0; - new_dcc->status = 0; - new_dcc->start_time = 0; - new_dcc->start_transfer = 0; - new_dcc->addr = 0; - new_dcc->port = 0; - new_dcc->nick = NULL; - new_dcc->sock = -1; - new_dcc->child_pid = 0; - new_dcc->child_read = -1; - new_dcc->child_write = -1; - new_dcc->unterminated_message = NULL; - new_dcc->fast_send = irc_cfg_dcc_fast_send; - new_dcc->file = -1; - new_dcc->filename = NULL; - new_dcc->local_filename = NULL; - new_dcc->filename_suffix = -1; - new_dcc->blocksize = irc_cfg_dcc_blocksize; - new_dcc->size = 0; - new_dcc->pos = 0; - new_dcc->ack = 0; - new_dcc->start_resume = 0; - new_dcc->last_check_time = 0; - new_dcc->last_check_pos = 0; - new_dcc->last_activity = 0; - new_dcc->bytes_per_sec = 0; - new_dcc->eta = 0; - - new_dcc->prev_dcc = NULL; - new_dcc->next_dcc = irc_dcc_list; - if (irc_dcc_list) - irc_dcc_list->prev_dcc = new_dcc; - else - irc_last_dcc = new_dcc; - irc_dcc_list = new_dcc; - - return new_dcc; -} - -/* - * irc_dcc_add: add a DCC file to queue - */ - -struct t_irc_dcc * -irc_dcc_add (struct t_irc_server *server, int type, unsigned long addr, int port, char *nick, - int sock, char *filename, char *local_filename, unsigned long size) -{ - struct t_irc_dcc *new_dcc; - - new_dcc = irc_dcc_alloc (); - if (!new_dcc) - { - gui_chat_printf_error (server->buffer, - _("%s not enough memory for new DCC\n"), - WEECHAT_ERROR); - return NULL; - } - - /* initialize new DCC */ - new_dcc->server = server; - new_dcc->channel = NULL; - new_dcc->type = type; - new_dcc->status = IRC_DCC_WAITING; - new_dcc->start_time = time (NULL); - new_dcc->start_transfer = time (NULL); - new_dcc->addr = addr; - new_dcc->port = port; - new_dcc->nick = strdup (nick); - new_dcc->sock = sock; - new_dcc->unterminated_message = NULL; - new_dcc->file = -1; - if (IRC_DCC_IS_CHAT(type)) - new_dcc->filename = strdup (_("DCC chat")); - else - new_dcc->filename = (filename) ? strdup (filename) : NULL; - new_dcc->local_filename = NULL; - new_dcc->filename_suffix = -1; - new_dcc->size = size; - new_dcc->pos = 0; - new_dcc->ack = 0; - new_dcc->start_resume = 0; - new_dcc->last_check_time = time (NULL); - new_dcc->last_check_pos = 0; - new_dcc->last_activity = time (NULL); - new_dcc->bytes_per_sec = 0; - new_dcc->eta = 0; - if (local_filename) - new_dcc->local_filename = strdup (local_filename); - else - irc_dcc_find_filename (new_dcc); - - gui_current_window->dcc_first = NULL; - gui_current_window->dcc_selected = NULL; - - /* write info message on server buffer */ - if (type == IRC_DCC_FILE_RECV) - { - gui_chat_printf_info (server->buffer, - _("Incoming DCC file from %s%s%s " - "(%s%d.%d.%d.%d%s)%s: %s%s%s, " - "%s%lu%s bytes\n"), - GUI_COLOR(GUI_COLOR_CHAT_NICK), - nick, - GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS), - GUI_COLOR(GUI_COLOR_CHAT_HOST), - addr >> 24, - (addr >> 16) & 0xff, - (addr >> 8) & 0xff, - addr & 0xff, - GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS), - GUI_COLOR(GUI_COLOR_CHAT), - GUI_COLOR(GUI_COLOR_CHAT_CHANNEL), - filename, - GUI_COLOR(GUI_COLOR_CHAT), - GUI_COLOR(GUI_COLOR_CHAT_CHANNEL), - size, - GUI_COLOR(GUI_COLOR_CHAT)); - irc_dcc_redraw (WEECHAT_HOTLIST_MESSAGE); - } - if (type == IRC_DCC_FILE_SEND) - { - gui_chat_printf_info (server->buffer, - _("Sending DCC file to %s%s%s: %s%s%s " - "(local filename: %s%s%s), %s%lu%s bytes\n"), - GUI_COLOR(GUI_COLOR_CHAT_NICK), - nick, - GUI_COLOR(GUI_COLOR_CHAT), - GUI_COLOR(GUI_COLOR_CHAT_CHANNEL), - filename, - GUI_COLOR(GUI_COLOR_CHAT), - GUI_COLOR(GUI_COLOR_CHAT_CHANNEL), - local_filename, - GUI_COLOR(GUI_COLOR_CHAT), - GUI_COLOR(GUI_COLOR_CHAT_CHANNEL), - size, - GUI_COLOR(GUI_COLOR_CHAT)); - irc_dcc_redraw (WEECHAT_HOTLIST_MESSAGE); - } - if (type == IRC_DCC_CHAT_RECV) - { - gui_chat_printf_info (server->buffer, - _("Incoming DCC chat request from %s%s%s " - "(%s%d.%d.%d.%d%s)\n"), - GUI_COLOR(GUI_COLOR_CHAT_NICK), - nick, - GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS), - GUI_COLOR(GUI_COLOR_CHAT_HOST), - addr >> 24, - (addr >> 16) & 0xff, - (addr >> 8) & 0xff, - addr & 0xff, - GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS)); - irc_dcc_redraw (WEECHAT_HOTLIST_MESSAGE); - } - if (type == IRC_DCC_CHAT_SEND) - { - gui_chat_printf_info (server->buffer, - _("Sending DCC chat request to %s%s\n"), - GUI_COLOR(GUI_COLOR_CHAT_NICK), - nick); - irc_dcc_redraw (WEECHAT_HOTLIST_MESSAGE); - } - - if (IRC_DCC_IS_FILE(type) && (!new_dcc->local_filename)) - { - irc_dcc_close (new_dcc, IRC_DCC_FAILED); - irc_dcc_redraw (WEECHAT_HOTLIST_MESSAGE); - return NULL; - } - - if (IRC_DCC_IS_FILE(type) && (new_dcc->start_resume > 0)) - { - gui_chat_printf_info (new_dcc->server->buffer, - _("DCC: file %s%s%s (local filename: %s%s%s) " - "will be resumed at position %u\n"), - GUI_COLOR(GUI_COLOR_CHAT_CHANNEL), - new_dcc->filename, - GUI_COLOR(GUI_COLOR_CHAT), - GUI_COLOR(GUI_COLOR_CHAT_CHANNEL), - new_dcc->local_filename, - GUI_COLOR(GUI_COLOR_CHAT), - new_dcc->start_resume); - irc_dcc_redraw (WEECHAT_HOTLIST_MESSAGE); - } - - /* connect if needed and redraw DCC buffer */ - if (IRC_DCC_IS_SEND(type)) - { - if (!irc_dcc_connect (new_dcc)) - { - irc_dcc_close (new_dcc, IRC_DCC_FAILED); - irc_dcc_redraw (WEECHAT_HOTLIST_MESSAGE); - return NULL; - } - } - - if ( ( (type == IRC_DCC_CHAT_RECV) && (irc_cfg_dcc_auto_accept_chats) ) - || ( (type == IRC_DCC_FILE_RECV) && (irc_cfg_dcc_auto_accept_files) ) ) - irc_dcc_accept (new_dcc); - else - irc_dcc_redraw (WEECHAT_HOTLIST_PRIVATE); - gui_status_draw (gui_current_window->buffer, 0); - - return new_dcc; -} - -/* - * irc_dcc_send_request: send DCC request (file or chat) - */ - -void -irc_dcc_send_request (struct t_irc_server *server, int type, char *nick, - char *filename) -{ - char *dir1, *dir2, *filename2, *short_filename, *pos; - int spaces, args, port_start, port_end; - struct stat st; - int sock, port; - struct hostent *host; - struct in_addr tmpaddr; - struct sockaddr_in addr; - socklen_t length; - unsigned long local_addr; - struct t_irc_dcc *ptr_dcc; - - filename2 = NULL; - short_filename = NULL; - spaces = 0; - - if (type == IRC_DCC_FILE_SEND) - { - /* add home if filename not beginning with '/' or '~' (not for Win32) */ -#ifdef _WIN32 - filename2 = strdup (filename); -#else - if (filename[0] == '/') - filename2 = strdup (filename); - else if (filename[0] == '~') - filename2 = weechat_strreplace (filename, "~", getenv ("HOME")); - else - { - dir1 = weechat_strreplace (irc_cfg_dcc_upload_path, "~", - getenv ("HOME")); - if (!dir1) - return; - dir2 = weechat_strreplace (dir1, "%h", weechat_home); - if (!dir2) - { - free (dir1); - return; - } - filename2 = malloc (strlen (dir2) + strlen (filename) + 4); - if (!filename2) - { - gui_chat_printf_error (server->buffer, - _("%s not enough memory for DCC SEND\n"), - WEECHAT_ERROR); - return; - } - strcpy (filename2, dir2); - if (filename2[strlen (filename2) - 1] != DIR_SEPARATOR_CHAR) - strcat (filename2, DIR_SEPARATOR); - strcat (filename2, filename); - if (dir1) - free (dir1); - if (dir2) - free (dir2); - } -#endif - - /* check if file exists */ - if (stat (filename2, &st) == -1) - { - gui_chat_printf_error (server->buffer, - _("%s cannot access file \"%s\"\n"), - WEECHAT_ERROR, filename2); - if (filename2) - free (filename2); - return; - } - } - - /* get local IP address */ - - /* look up the IP address from dcc_own_ip, if set */ - local_addr = 0; - if (irc_cfg_dcc_own_ip && irc_cfg_dcc_own_ip[0]) - { - host = gethostbyname (irc_cfg_dcc_own_ip); - if (host) - { - memcpy (&tmpaddr, host->h_addr_list[0], sizeof(struct in_addr)); - local_addr = ntohl (tmpaddr.s_addr); - } - else - gui_chat_printf (server->buffer, - _("%s could not find address for '%s'. Falling " - "back to local IP.\n"), - WEECHAT_WARNING, irc_cfg_dcc_own_ip); - } - - /* use the local interface, from the server socket */ - memset (&addr, 0, sizeof (struct sockaddr_in)); - length = sizeof (addr); - getsockname (server->sock, (struct sockaddr *) &addr, &length); - addr.sin_family = AF_INET; - - /* fallback to the local IP address on the interface, if required */ - if (local_addr == 0) - local_addr = ntohl (addr.sin_addr.s_addr); - - /* open socket for DCC */ - sock = socket (AF_INET, SOCK_STREAM, 0); - if (sock < 0) - { - gui_chat_printf_error (server->buffer, - _("%s cannot create socket for DCC\n"), - WEECHAT_ERROR); - if (filename2) - free (filename2); - return; - } - - /* look for port */ - - port = 0; - - if (irc_cfg_dcc_port_range && irc_cfg_dcc_port_range[0]) - { - /* find a free port in the specified range */ - args = sscanf (irc_cfg_dcc_port_range, "%d-%d", &port_start, &port_end); - if (args > 0) - { - port = port_start; - if (args == 1) - port_end = port_start; - - /* loop through the entire allowed port range */ - while (port <= port_end) - { - if (!irc_dcc_port_in_use (port)) - { - /* attempt to bind to the free port */ - addr.sin_port = htons (port); - if (bind (sock, (struct sockaddr *) &addr, sizeof (addr)) == 0) - break; - } - port++; - } - - if (port > port_end) - port = -1; - } - } - - if (port == 0) - { - /* find port automatically */ - addr.sin_port = 0; - if (bind (sock, (struct sockaddr *) &addr, sizeof (addr)) == 0) - { - length = sizeof (addr); - getsockname (sock, (struct sockaddr *) &addr, &length); - port = ntohs (addr.sin_port); - } - else - port = -1; - } - - if (port == -1) - { - /* Could not find any port to bind */ - gui_chat_printf_error (server->buffer, - _("%s cannot find available port for DCC\n"), - WEECHAT_ERROR); - close (sock); - if (filename2) - free (filename2); - return; - } - - if (type == IRC_DCC_FILE_SEND) - { - /* extract short filename (without path) */ - pos = strrchr (filename2, DIR_SEPARATOR_CHAR); - if (pos) - short_filename = strdup (pos + 1); - else - short_filename = strdup (filename2); - - /* convert spaces to underscore if asked and needed */ - pos = short_filename; - spaces = 0; - while (pos[0]) - { - if (pos[0] == ' ') - { - if (irc_cfg_dcc_convert_spaces) - pos[0] = '_'; - else - spaces = 1; - } - pos++; - } - } - - /* add DCC entry and listen to socket */ - if (type == IRC_DCC_CHAT_SEND) - ptr_dcc = irc_dcc_add (server, IRC_DCC_CHAT_SEND, local_addr, port, - nick, sock, NULL, NULL, 0); - else - ptr_dcc = irc_dcc_add (server, IRC_DCC_FILE_SEND, local_addr, port, - nick, sock, short_filename, filename2, - st.st_size); - if (!ptr_dcc) - { - gui_chat_printf_error (server->buffer, - _("%s cannot send DCC\n"), - WEECHAT_ERROR); - close (sock); - if (short_filename) - free (short_filename); - if (filename2) - free (filename2); - return; - } - - /* send DCC request to nick */ - if (type == IRC_DCC_CHAT_SEND) - irc_server_sendf (server, - "PRIVMSG %s :\01DCC CHAT chat %lu %d\01", - nick, local_addr, port); - else - irc_server_sendf (server, - (spaces) ? - "PRIVMSG %s :\01DCC SEND \"%s\" %lu %d %u\01\n" : - "PRIVMSG %s :\01DCC SEND %s %lu %d %u\01", - nick, short_filename, local_addr, port, - (unsigned long) st.st_size); - - if (short_filename) - free (short_filename); - if (filename2) - free (filename2); -} - -/* - * irc_dcc_chat_send: send data to remote host via DCC CHAT - */ - -int -irc_dcc_chat_send (struct t_irc_dcc *dcc, char *buffer, int size_buf) -{ - if (!dcc) - return -1; - - return send (dcc->sock, buffer, size_buf, 0); -} - -/* - * irc_dcc_chat_sendf: send formatted data to remote host via DCC CHAT - */ - -void -irc_dcc_chat_sendf (struct t_irc_dcc *dcc, char *format, ...) -{ - va_list args; - static char buffer[4096]; - int size_buf; - - if (!dcc || (dcc->sock < 0)) - return; - - va_start (args, format); - size_buf = vsnprintf (buffer, sizeof (buffer) - 1, format, args); - va_end (args); - - if ((size_buf == 0) || (strcmp (buffer, "\r\n") == 0)) - return; - - buffer[sizeof (buffer) - 1] = '\0'; - if ((size_buf < 0) || (size_buf > (int) (sizeof (buffer) - 1))) - size_buf = strlen (buffer); - - if (irc_dcc_chat_send (dcc, buffer, strlen (buffer)) <= 0) - { - gui_chat_printf_error (dcc->server->buffer, - _("%s error sending data to \"%s\" via DCC " - "CHAT\n"), - WEECHAT_ERROR, dcc->nick); - irc_dcc_close (dcc, IRC_DCC_FAILED); - } -} - -/* - * irc_dcc_chat_recv: receive data from DCC CHAT host - */ - -void -irc_dcc_chat_recv (struct t_irc_dcc *dcc) -{ - fd_set read_fd; - static struct timeval timeout; - static char buffer[4096 + 2]; - char *buf2, *pos, *ptr_buf, *next_ptr_buf; - int num_read; - - FD_ZERO (&read_fd); - FD_SET (dcc->sock, &read_fd); - timeout.tv_sec = 0; - timeout.tv_usec = 0; - - /* something to read on socket? */ - if (select (FD_SETSIZE, &read_fd, NULL, NULL, &timeout) <= 0) - return; - - if (!FD_ISSET (dcc->sock, &read_fd)) - return; - - /* there's something to read on socket! */ - num_read = recv (dcc->sock, buffer, sizeof (buffer) - 2, 0); - if (num_read > 0) - { - buffer[num_read] = '\0'; - - buf2 = NULL; - ptr_buf = buffer; - if (dcc->unterminated_message) - { - buf2 = malloc (strlen (dcc->unterminated_message) + - strlen (buffer) + 1); - if (buf2) - { - strcpy (buf2, dcc->unterminated_message); - strcat (buf2, buffer); - } - ptr_buf = buf2; - free (dcc->unterminated_message); - dcc->unterminated_message = NULL; - } - - while (ptr_buf && ptr_buf[0]) - { - next_ptr_buf = NULL; - pos = strstr (ptr_buf, "\r\n"); - if (pos) - { - pos[0] = '\0'; - next_ptr_buf = pos + 2; - } - else - { - pos = strstr (ptr_buf, "\n"); - if (pos) - { - pos[0] = '\0'; - next_ptr_buf = pos + 1; - } - else - { - dcc->unterminated_message = strdup (ptr_buf); - ptr_buf = NULL; - next_ptr_buf = NULL; - } - } - - if (ptr_buf) - { - if (irc_protocol_is_highlight (ptr_buf, dcc->server->nick)) - { - irc_display_nick (dcc->channel->buffer, NULL, - dcc->nick, - GUI_MSG_TYPE_NICK | GUI_MSG_TYPE_HIGHLIGHT, - 1, - GUI_COLOR(GUI_COLOR_CHAT_HIGHLIGHT), 0); - if ((cfg_look_infobar_delay_highlight > 0) - && (dcc->channel->buffer != gui_current_window->buffer)) - { - gui_infobar_printf (cfg_look_infobar_delay_highlight, - GUI_COLOR_INFOBAR_HIGHLIGHT, - _("Private %s> %s"), - dcc->nick, ptr_buf); - } - } - else - irc_display_nick (dcc->channel->buffer, NULL, - dcc->nick, - GUI_MSG_TYPE_NICK, 1, - GUI_COLOR(GUI_COLOR_CHAT_NICK_OTHER), 0); - gui_chat_printf_type (dcc->channel->buffer, - GUI_MSG_TYPE_MSG, - NULL, -1, - "%s%s\n", - GUI_COLOR(GUI_COLOR_CHAT), - ptr_buf); - } - - ptr_buf = next_ptr_buf; - } - - if (buf2) - free (buf2); - } - else - { - irc_dcc_close (dcc, IRC_DCC_ABORTED); - irc_dcc_redraw (WEECHAT_HOTLIST_MESSAGE); - } -} - -/* - * irc_dcc_file_create_pipe: create pipe for communication with child process - * return 1 if ok, 0 if error - */ - -int -irc_dcc_file_create_pipe (struct t_irc_dcc *dcc) -{ - int child_pipe[2]; - - if (pipe (child_pipe) < 0) - { - gui_chat_printf_error (dcc->server->buffer, - _("%s DCC: unable to create pipe\n"), - WEECHAT_ERROR); - irc_dcc_close (dcc, IRC_DCC_FAILED); - irc_dcc_redraw (WEECHAT_HOTLIST_MESSAGE); - return 0; - } - - dcc->child_read = child_pipe[0]; - dcc->child_write = child_pipe[1]; - return 1; -} - -/* - * irc_dcc_file_write_pipe: write data into pipe - */ - -void -irc_dcc_file_write_pipe (struct t_irc_dcc *dcc, int status, int error) -{ - char buffer[1 + 1 + 12 + 1]; /* status + error + pos + \0 */ - - snprintf (buffer, sizeof (buffer), "%c%c%012lu", - status + '0', error + '0', dcc->pos); - write (dcc->child_write, buffer, sizeof (buffer)); -} - -/* - * irc_dcc_file_send_child: child process for sending file - */ - -void -irc_dcc_file_send_child (struct t_irc_dcc *dcc) -{ - int num_read, num_sent; - static char buffer[IRC_DCC_MAX_BLOCKSIZE]; - uint32_t ack; - time_t last_sent, new_time; - - last_sent = time (NULL); - while (1) - { - /* read DCC ACK (sent by receiver) */ - if (dcc->pos > dcc->ack) - { - /* we should receive ACK for packets sent previously */ - while (1) - { - num_read = recv (dcc->sock, (char *) &ack, 4, MSG_PEEK); - if ((num_read < 1) && - ((num_read != -1) || (errno != EAGAIN))) - { - irc_dcc_file_write_pipe (dcc, IRC_DCC_FAILED, IRC_DCC_ERROR_SEND_BLOCK); - return; - } - if (num_read == 4) - { - recv (dcc->sock, (char *) &ack, 4, 0); - dcc->ack = ntohl (ack); - - /* DCC send ok? */ - if ((dcc->pos >= dcc->size) - && (dcc->ack >= dcc->size)) - { - irc_dcc_file_write_pipe (dcc, IRC_DCC_DONE, IRC_DCC_NO_ERROR); - return; - } - } - else - break; - } - } - - /* send a block to receiver */ - if ((dcc->pos < dcc->size) && - (dcc->fast_send || (dcc->pos <= dcc->ack))) - { - lseek (dcc->file, dcc->pos, SEEK_SET); - num_read = read (dcc->file, buffer, dcc->blocksize); - if (num_read < 1) - { - irc_dcc_file_write_pipe (dcc, IRC_DCC_FAILED, IRC_DCC_ERROR_READ_LOCAL); - return; - } - num_sent = send (dcc->sock, buffer, num_read, 0); - if (num_sent < 0) - { - /* socket is temporarily not available (receiver can't receive - amount of data we sent ?!) */ - if (errno == EAGAIN) - usleep (1000); - else - { - irc_dcc_file_write_pipe (dcc, IRC_DCC_FAILED, IRC_DCC_ERROR_SEND_BLOCK); - return; - } - } - if (num_sent > 0) - { - dcc->pos += (unsigned long) num_sent; - new_time = time (NULL); - if (last_sent != new_time) - { - last_sent = new_time; - irc_dcc_file_write_pipe (dcc, IRC_DCC_ACTIVE, IRC_DCC_NO_ERROR); - } - } - } - else - usleep (1000); - } -} - -/* - * irc_dcc_file_recv_child: child process for receiving file - */ - -void -irc_dcc_file_recv_child (struct t_irc_dcc *dcc) -{ - int num_read; - static char buffer[IRC_DCC_MAX_BLOCKSIZE]; - uint32_t pos; - time_t last_sent, new_time; - - /* first connect to sender (blocking) */ - if (!irc_dcc_connect_to_sender (dcc)) - { - irc_dcc_file_write_pipe (dcc, IRC_DCC_FAILED, IRC_DCC_ERROR_CONNECT_SENDER); - return; - } - - /* connection is ok, change DCC status (inform parent process) */ - irc_dcc_file_write_pipe (dcc, IRC_DCC_ACTIVE, IRC_DCC_NO_ERROR); - - last_sent = time (NULL); - while (1) - { - num_read = recv (dcc->sock, buffer, sizeof (buffer), 0); - if (num_read == -1) - { - /* socket is temporarily not available (sender is not fast ?!) */ - if (errno == EAGAIN) - usleep (1000); - else - { - irc_dcc_file_write_pipe (dcc, IRC_DCC_FAILED, IRC_DCC_ERROR_RECV_BLOCK); - return; - } - } - else - { - if (num_read == 0) - { - irc_dcc_file_write_pipe (dcc, IRC_DCC_FAILED, IRC_DCC_ERROR_RECV_BLOCK); - return; - } - - if (write (dcc->file, buffer, num_read) == -1) - { - irc_dcc_file_write_pipe (dcc, IRC_DCC_FAILED, IRC_DCC_ERROR_WRITE_LOCAL); - return; - } - - dcc->pos += (unsigned long) num_read; - pos = htonl (dcc->pos); - - /* we don't check return code, not a problem if an ACK send failed */ - send (dcc->sock, (char *) &pos, 4, 0); - - /* file received ok? */ - if (dcc->pos >= dcc->size) - { - irc_dcc_file_write_pipe (dcc, IRC_DCC_DONE, IRC_DCC_NO_ERROR); - return; - } - - new_time = time (NULL); - if (last_sent != new_time) - { - last_sent = new_time; - irc_dcc_file_write_pipe (dcc, IRC_DCC_ACTIVE, IRC_DCC_NO_ERROR); - } - } - } -} - -/* - * irc_dcc_file_child_read: read data from child via pipe - */ - -void -irc_dcc_file_child_read (struct t_irc_dcc *dcc) -{ - fd_set read_fd; - static struct timeval timeout; - char bufpipe[1 + 1 + 12 + 1]; - int num_read; - char *error; - - FD_ZERO (&read_fd); - FD_SET (dcc->child_read, &read_fd); - timeout.tv_sec = 0; - timeout.tv_usec = 0; - - /* something to read on child pipe? */ - if (select (FD_SETSIZE, &read_fd, NULL, NULL, &timeout) <= 0) - return; - - if (!FD_ISSET (dcc->child_read, &read_fd)) - return; - - /* there's something to read in pipe! */ - num_read = read (dcc->child_read, bufpipe, sizeof (bufpipe)); - if (num_read > 0) - { - error = NULL; - dcc->pos = strtol (bufpipe + 2, &error, 10); - dcc->last_activity = time (NULL); - irc_dcc_calculate_speed (dcc, 0); - - /* read error code */ - switch (bufpipe[1] - '0') - { - /* errors for sender */ - case IRC_DCC_ERROR_READ_LOCAL: - gui_chat_printf_error (dcc->server->buffer, - _("%s DCC: unable to read local " - "file\n"), - WEECHAT_ERROR); - break; - case IRC_DCC_ERROR_SEND_BLOCK: - gui_chat_printf_error (dcc->server->buffer, - _("%s DCC: unable to send block to " - "receiver\n"), - WEECHAT_ERROR); - break; - case IRC_DCC_ERROR_READ_ACK: - gui_chat_printf_error (dcc->server->buffer, - _("%s DCC: unable to read ACK from " - "receiver\n"), - WEECHAT_ERROR); - break; - /* errors for receiver */ - case IRC_DCC_ERROR_CONNECT_SENDER: - gui_chat_printf_error (dcc->server->buffer, - _("%s DCC: unable to connect to " - "sender\n"), - WEECHAT_ERROR); - break; - case IRC_DCC_ERROR_RECV_BLOCK: - gui_chat_printf_error (dcc->server->buffer, - _("%s DCC: unable to receive block " - "from sender\n"), - WEECHAT_ERROR); - break; - case IRC_DCC_ERROR_WRITE_LOCAL: - gui_chat_printf_error (dcc->server->buffer, - _("%s DCC: unable to write local " - "file\n"), - WEECHAT_ERROR); - break; - } - - /* read new DCC status */ - switch (bufpipe[0] - '0') - { - case IRC_DCC_ACTIVE: - if (dcc->status == IRC_DCC_CONNECTING) - { - /* connection was successful by child, init transfert times */ - dcc->status = IRC_DCC_ACTIVE; - dcc->start_transfer = time (NULL); - dcc->last_check_time = time (NULL); - irc_dcc_redraw (WEECHAT_HOTLIST_MESSAGE); - } - else - irc_dcc_redraw (WEECHAT_HOTLIST_LOW); - break; - case IRC_DCC_DONE: - irc_dcc_close (dcc, IRC_DCC_DONE); - irc_dcc_redraw (WEECHAT_HOTLIST_MESSAGE); - break; - case IRC_DCC_FAILED: - irc_dcc_close (dcc, IRC_DCC_FAILED); - irc_dcc_redraw (WEECHAT_HOTLIST_MESSAGE); - break; - } - } -} - -/* - * irc_dcc_file_send_fork: fork process for sending file - */ - -void -irc_dcc_file_send_fork (struct t_irc_dcc *dcc) -{ - pid_t pid; - - if (!irc_dcc_file_create_pipe (dcc)) - return; - - dcc->file = open (dcc->local_filename, O_RDONLY | O_NONBLOCK, 0644); - - switch (pid = fork ()) - { - /* fork failed */ - case -1: - gui_chat_printf_error (dcc->server->buffer, - _("%s DCC: unable to fork\n"), - WEECHAT_ERROR); - irc_dcc_close (dcc, IRC_DCC_FAILED); - irc_dcc_redraw (WEECHAT_HOTLIST_MESSAGE); - return; - /* child process */ - case 0: - setuid (getuid ()); - irc_dcc_file_send_child (dcc); - _exit (EXIT_SUCCESS); - } - - /* parent process */ - dcc->child_pid = pid; -} - -/* - * irc_dcc_file_recv_fork: fork process for receiving file - */ - -void -irc_dcc_file_recv_fork (struct t_irc_dcc *dcc) -{ - pid_t pid; - - if (!irc_dcc_file_create_pipe (dcc)) - return; - - if (dcc->start_resume > 0) - dcc->file = open (dcc->local_filename, - O_APPEND | O_WRONLY | O_NONBLOCK); - else - dcc->file = open (dcc->local_filename, - O_CREAT | O_TRUNC | O_WRONLY | O_NONBLOCK, - 0644); - - switch (pid = fork ()) - { - /* fork failed */ - case -1: - gui_chat_printf_error (dcc->server->buffer, - _("%s DCC: unable to fork\n"), - WEECHAT_ERROR); - irc_dcc_close (dcc, IRC_DCC_FAILED); - irc_dcc_redraw (WEECHAT_HOTLIST_MESSAGE); - return; - /* child process */ - case 0: - setuid (getuid ()); - irc_dcc_file_recv_child (dcc); - _exit (EXIT_SUCCESS); - } - - /* parent process */ - dcc->child_pid = pid; -} - +*/ /* * irc_dcc_handle: receive/send data for all active DCC */ - +/* void irc_dcc_handle () { @@ -1733,7 +183,7 @@ irc_dcc_handle () for (dcc = irc_dcc_list; dcc; dcc = dcc->next_dcc) { - /* check DCC timeout */ + // check DCC timeout if (IRC_DCC_IS_FILE(dcc->type) && !IRC_DCC_ENDED(dcc->status)) { if ((irc_cfg_dcc_timeout != 0) @@ -1757,7 +207,7 @@ irc_dcc_handle () timeout.tv_sec = 0; timeout.tv_usec = 0; - /* something to read on socket? */ + // something to read on socket? if (select (FD_SETSIZE, &read_fd, NULL, NULL, &timeout) > 0) { if (FD_ISSET (dcc->sock, &read_fd)) @@ -1815,7 +265,7 @@ irc_dcc_handle () timeout.tv_sec = 0; timeout.tv_usec = 0; - /* something to read on socket? */ + // something to read on socket? if (select (FD_SETSIZE, &read_fd, NULL, NULL, &timeout) > 0) { if (FD_ISSET (dcc->sock, &read_fd)) @@ -1855,71 +305,4 @@ irc_dcc_handle () } } } - -/* - * irc_dcc_end: close all opened sockets (called when WeeChat is exiting) - */ - -void -irc_dcc_end () -{ - struct t_irc_dcc *ptr_dcc; - - for (ptr_dcc = irc_dcc_list; ptr_dcc; ptr_dcc = ptr_dcc->next_dcc) - { - if (ptr_dcc->sock >= 0) - { - if (ptr_dcc->status == IRC_DCC_ACTIVE) - weechat_log_printf (_("Aborting active DCC: \"%s\" from %s"), - ptr_dcc->filename, ptr_dcc->nick); - irc_dcc_close (ptr_dcc, IRC_DCC_FAILED); - } - } -} - -/* - * irc_dcc_print_log: print DCC infos in log (usually for crash dump) - */ - -void -irc_dcc_print_log () -{ - struct t_irc_dcc *ptr_dcc; - - for (ptr_dcc = irc_dcc_list; ptr_dcc; ptr_dcc = ptr_dcc->next_dcc) - { - weechat_log_printf (""); - weechat_log_printf ("[DCC (addr:0x%x)]", ptr_dcc); - weechat_log_printf (" server. . . . . . . : 0x%x", ptr_dcc->server); - weechat_log_printf (" channel . . . . . . : 0x%x", ptr_dcc->channel); - weechat_log_printf (" type. . . . . . . . : %d", ptr_dcc->type); - weechat_log_printf (" status. . . . . . . : %d", ptr_dcc->status); - weechat_log_printf (" start_time. . . . . : %ld", ptr_dcc->start_time); - weechat_log_printf (" start_transfer. . . : %ld", ptr_dcc->start_transfer); - weechat_log_printf (" addr. . . . . . . . : %lu", ptr_dcc->addr); - weechat_log_printf (" port. . . . . . . . : %d", ptr_dcc->port); - weechat_log_printf (" nick. . . . . . . . : '%s'", ptr_dcc->nick); - weechat_log_printf (" sock. . . . . . . . : %d", ptr_dcc->sock); - weechat_log_printf (" child_pid . . . . . : %d", ptr_dcc->child_pid); - weechat_log_printf (" child_read. . . . . : %d", ptr_dcc->child_read); - weechat_log_printf (" child_write . . . . : %d", ptr_dcc->child_write); - weechat_log_printf (" unterminated_message: '%s'", ptr_dcc->unterminated_message); - weechat_log_printf (" fast_send . . . . . : %d", ptr_dcc->fast_send); - weechat_log_printf (" file. . . . . . . . : %d", ptr_dcc->file); - weechat_log_printf (" filename. . . . . . : '%s'", ptr_dcc->filename); - weechat_log_printf (" local_filename. . . : '%s'", ptr_dcc->local_filename); - weechat_log_printf (" filename_suffix . . : %d", ptr_dcc->filename_suffix); - weechat_log_printf (" blocksize . . . . . : %d", ptr_dcc->blocksize); - weechat_log_printf (" size. . . . . . . . : %lu", ptr_dcc->size); - weechat_log_printf (" pos . . . . . . . . : %lu", ptr_dcc->pos); - weechat_log_printf (" ack . . . . . . . . : %lu", ptr_dcc->ack); - weechat_log_printf (" start_resume. . . . : %lu", ptr_dcc->start_resume); - weechat_log_printf (" last_check_time . . : %ld", ptr_dcc->last_check_time); - weechat_log_printf (" last_check_pos. . . : %lu", ptr_dcc->last_check_pos); - weechat_log_printf (" last_activity . . . : %ld", ptr_dcc->last_activity); - weechat_log_printf (" bytes_per_sec . . . : %lu", ptr_dcc->bytes_per_sec); - weechat_log_printf (" eta . . . . . . . . : %lu", ptr_dcc->eta); - weechat_log_printf (" prev_dcc. . . . . . : 0x%x", ptr_dcc->prev_dcc); - weechat_log_printf (" next_dcc. . . . . . : 0x%x", ptr_dcc->next_dcc); - } -} +*/ diff --git a/src/plugins/irc/irc-debug.c b/src/plugins/irc/irc-debug.c index a652a4963..91fdf4ee4 100644 --- a/src/plugins/irc/irc-debug.c +++ b/src/plugins/irc/irc-debug.c @@ -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); 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) */ diff --git a/src/plugins/irc/irc-server.h b/src/plugins/irc/irc-server.h index cf18813ab..1593f3425 100644 --- a/src/plugins/irc/irc-server.h +++ b/src/plugins/irc/irc-server.h @@ -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 */ diff --git a/src/plugins/irc/irc.c b/src/plugins/irc/irc.c index a41d5a503..70dae0e2d 100644 --- a/src/plugins/irc/irc.c +++ b/src/plugins/irc/irc.c @@ -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" @@ -56,31 +52,6 @@ gnutls_certificate_credentials gnutls_xcred; /* gnutls client credentials */ /* - * 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 (); |