diff options
Diffstat (limited to 'src/irc')
-rw-r--r-- | src/irc/irc-channel.c | 56 | ||||
-rw-r--r-- | src/irc/irc-commands.c | 8 | ||||
-rw-r--r-- | src/irc/irc-dcc.c | 631 | ||||
-rw-r--r-- | src/irc/irc-display.c | 26 | ||||
-rw-r--r-- | src/irc/irc-recv.c | 275 | ||||
-rw-r--r-- | src/irc/irc-send.c | 65 | ||||
-rw-r--r-- | src/irc/irc-server.c | 38 | ||||
-rw-r--r-- | src/irc/irc.h | 19 |
8 files changed, 811 insertions, 307 deletions
diff --git a/src/irc/irc-channel.c b/src/irc/irc-channel.c index c4ba4e9b2..10faf44b0 100644 --- a/src/irc/irc-channel.c +++ b/src/irc/irc-channel.c @@ -25,6 +25,7 @@ #endif #include <stdlib.h> +#include <unistd.h> #include <string.h> #include "../common/weechat.h" @@ -53,6 +54,7 @@ channel_new (t_irc_server *server, int channel_type, char *channel_name, /* initialize new channel */ new_channel->type = channel_type; + new_channel->dcc_chat = NULL; new_channel->name = strdup (channel_name); new_channel->topic = NULL; memset (new_channel->modes, ' ', sizeof (new_channel->modes)); @@ -101,6 +103,14 @@ channel_free (t_irc_server *server, t_irc_channel *channel) if (channel->next_channel) (channel->next_channel)->prev_channel = channel->prev_channel; + /* close DCC CHAT */ + if ((t_irc_dcc *)(channel->dcc_chat) && + (!DCC_ENDED(((t_irc_dcc *)(channel->dcc_chat))->status))) + { + dcc_close ((t_irc_dcc *)(channel->dcc_chat), DCC_ABORTED); + dcc_redraw (1); + } + /* free data */ if (channel->name) free (channel->name); @@ -204,3 +214,49 @@ channel_set_away (t_irc_channel *channel, char *nick, int is_away) nick_set_away (channel, ptr_nick, is_away); } } + +/* + * channel_create_dcc: create DCC CHAT channel + */ + +int +channel_create_dcc (t_irc_dcc *ptr_dcc) +{ + t_irc_channel *ptr_channel; + + ptr_channel = channel_search (ptr_dcc->server, ptr_dcc->nick); + if (!ptr_channel) + ptr_channel = channel_new (ptr_dcc->server, CHAT_PRIVATE, + ptr_dcc->nick, 0); + if (!ptr_channel) + return 0; + + if (ptr_channel->dcc_chat && + (!DCC_ENDED(((t_irc_dcc *)(ptr_channel->dcc_chat))->status))) + return 0; + + ptr_channel->dcc_chat = ptr_dcc; + ptr_dcc->channel = ptr_channel; + gui_redraw_buffer (ptr_channel->buffer); + return 1; +} + +/* + * channel_remove_dcc: remove a DCC CHAT + */ + +void +channel_remove_dcc (t_irc_dcc *ptr_dcc) +{ + t_irc_channel *ptr_channel; + + for (ptr_channel = ptr_dcc->server->channels; ptr_channel; + ptr_channel = ptr_channel->next_channel) + { + if ((t_irc_dcc *)(ptr_channel->dcc_chat) == ptr_dcc) + { + ptr_channel->dcc_chat = NULL; + gui_redraw_buffer (ptr_channel->buffer); + } + } +} diff --git a/src/irc/irc-commands.c b/src/irc/irc-commands.c index 88cc8065b..54ea5c843 100644 --- a/src/irc/irc-commands.c +++ b/src/irc/irc-commands.c @@ -44,12 +44,12 @@ t_irc_command irc_commands[] = N_("nickname type"), N_("nickname: user to send ctcp to\ntype: \"action\" or \"version\""), 2, MAX_ARGS, 1, NULL, irc_cmd_send_ctcp, NULL }, - { "dcc", N_("starts DCC (file or chat)"), - N_("action nickname [file]"), - N_("action: 'send' (file) or 'chat'\n" + { "dcc", N_("starts DCC (file or chat) or close chat"), + N_("action [nickname [file]]"), + N_("action: 'send' (file) or 'chat' or 'close' (chat)\n" "nickname: nickname to send file or chat\n" "file: filename (on local host)"), - 2, MAX_ARGS, 1, NULL, irc_cmd_send_dcc, NULL }, + 1, MAX_ARGS, 1, NULL, irc_cmd_send_dcc, NULL }, { "deop", N_("removes channel operator status from nickname(s)"), N_("nickname [nickname]"), "", 1, MAX_ARGS, 1, irc_cmd_send_deop, NULL, NULL }, diff --git a/src/irc/irc-dcc.c b/src/irc/irc-dcc.c index 2d51c7e1a..6cc21774f 100644 --- a/src/irc/irc-dcc.c +++ b/src/irc/irc-dcc.c @@ -27,6 +27,7 @@ #include <stdlib.h> #include <unistd.h> #include <string.h> +#include <stdarg.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> @@ -70,7 +71,10 @@ dcc_connect (t_irc_dcc *ptr_dcc) { struct sockaddr_in addr; - ptr_dcc->status = DCC_CONNECTING; + if (ptr_dcc->type == DCC_CHAT_SEND) + ptr_dcc->status = DCC_WAITING; + else + ptr_dcc->status = DCC_CONNECTING; if (ptr_dcc->sock == -1) { @@ -81,8 +85,8 @@ dcc_connect (t_irc_dcc *ptr_dcc) if (fcntl (ptr_dcc->sock, F_SETFL, O_NONBLOCK) == -1) return 0; - /* for DCC SEND, listen to socket for a connection */ - if (ptr_dcc->type == DCC_FILE_SEND) + /* for sending (chat or file), listen to socket for a connection */ + if (DCC_IS_SEND(ptr_dcc->type)) { if (listen (ptr_dcc->sock, 1) == -1) return 0; @@ -90,8 +94,8 @@ dcc_connect (t_irc_dcc *ptr_dcc) return 0; } - /* for DCC RECV, connect to listening host */ - if (ptr_dcc->type == DCC_FILE_RECV) + /* for receiving (chat or file), connect to listening host */ + if (DCC_IS_RECV(ptr_dcc->type)) { memset (&addr, 0, sizeof (addr)); addr.sin_port = htons (ptr_dcc->port); @@ -125,6 +129,8 @@ dcc_free (t_irc_dcc *ptr_dcc) if (ptr_dcc->nick) free (ptr_dcc->nick); + if (ptr_dcc->unterminated_message) + free (ptr_dcc->unterminated_message); if (ptr_dcc->filename) free (ptr_dcc->filename); @@ -143,7 +149,7 @@ dcc_close (t_irc_dcc *ptr_dcc, int status) if (status == DCC_DONE) { - if ((ptr_dcc->type == DCC_FILE_SEND) || (ptr_dcc->type == DCC_FILE_RECV)) + if (DCC_IS_FILE(ptr_dcc->type)) { irc_display_prefix (ptr_dcc->server->buffer, PREFIX_INFO); gui_printf (ptr_dcc->server->buffer, _("DCC: file ")); @@ -167,6 +173,25 @@ dcc_close (t_irc_dcc *ptr_dcc, int status) gui_printf (ptr_dcc->server->buffer, _(": ok!\n")); } } + if (status == DCC_ABORTED) + { + if (DCC_IS_CHAT(ptr_dcc->type)) + { + irc_display_prefix (ptr_dcc->channel->buffer, PREFIX_INFO); + gui_printf (ptr_dcc->channel->buffer, _("DCC chat closed with ")); + gui_printf_color (ptr_dcc->channel->buffer, COLOR_WIN_CHAT_NICK, + "%s", ptr_dcc->nick); + gui_printf_color (ptr_dcc->channel->buffer, COLOR_WIN_CHAT_DARK, " ("); + gui_printf_color (ptr_dcc->channel->buffer, COLOR_WIN_CHAT_HOST, + "%d.%d.%d.%d", + ptr_dcc->addr >> 24, (ptr_dcc->addr >> 16) & 0xff, + (ptr_dcc->addr >> 8) & 0xff, ptr_dcc->addr & 0xff); + gui_printf_color (ptr_dcc->channel->buffer, COLOR_WIN_CHAT_DARK, ")\n"); + } + } + + if (DCC_IS_CHAT(ptr_dcc->type)) + channel_remove_dcc (ptr_dcc); if (ptr_dcc->sock != -1) { @@ -181,6 +206,39 @@ dcc_close (t_irc_dcc *ptr_dcc, int status) } /* + * dcc_channel_for_chat: create channel for DCC chat + */ + +void +dcc_channel_for_chat (t_irc_dcc *ptr_dcc) +{ + if (!channel_create_dcc (ptr_dcc)) + { + irc_display_prefix (ptr_dcc->server->buffer, PREFIX_ERROR); + gui_printf (ptr_dcc->server->buffer, + _("%s can't associate DCC chat with private buffer " + "(maybe private buffer has already DCC CHAT?)\n"), + WEECHAT_ERROR); + dcc_close (ptr_dcc, DCC_FAILED); + dcc_redraw (1); + return; + } + + irc_display_prefix (ptr_dcc->channel->buffer, PREFIX_INFO); + gui_printf_type (ptr_dcc->channel->buffer, MSG_TYPE_MSG, + _("Connected to ")); + gui_printf_color (ptr_dcc->channel->buffer, COLOR_WIN_CHAT_NICK, + "%s", ptr_dcc->nick); + gui_printf_color (ptr_dcc->channel->buffer, COLOR_WIN_CHAT_DARK, " ("); + gui_printf_color (ptr_dcc->channel->buffer, COLOR_WIN_CHAT_HOST, + "%d.%d.%d.%d", + ptr_dcc->addr >> 24, (ptr_dcc->addr >> 16) & 0xff, + (ptr_dcc->addr >> 8) & 0xff, ptr_dcc->addr & 0xff); + gui_printf_color (ptr_dcc->channel->buffer, COLOR_WIN_CHAT_DARK, ") "); + gui_printf (ptr_dcc->channel->buffer, _("via DCC chat\n")); +} + +/* * dcc_accept: accepts a DCC file or chat request */ @@ -197,67 +255,77 @@ dcc_accept (t_irc_dcc *ptr_dcc) else { ptr_dcc->status = DCC_ACTIVE; - ptr_home = getenv ("HOME"); - ptr_dcc->local_filename = (char *) malloc (strlen (cfg_dcc_download_path) + - strlen (ptr_dcc->nick) + - strlen (ptr_dcc->filename) + - ((cfg_dcc_download_path[0] == '~') ? - strlen (ptr_home) : 0) + - 4); - if (!ptr_dcc->local_filename) - { - dcc_close (ptr_dcc, DCC_FAILED); - dcc_redraw (1); - return; - } - if (cfg_dcc_download_path[0] == '~') - { - strcpy (ptr_dcc->local_filename, ptr_home); - strcat (ptr_dcc->local_filename, cfg_dcc_download_path + 1); - } - else - strcpy (ptr_dcc->local_filename, cfg_dcc_download_path); - if (ptr_dcc->local_filename[strlen (ptr_dcc->local_filename) - 1] != DIR_SEPARATOR_CHAR) - 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); - /* file already exists? */ - if (access (ptr_dcc->local_filename, F_OK) == 0) + /* DCC file => look for local filename and open it in writing mode */ + if (DCC_IS_FILE(ptr_dcc->type)) { - /* if auto rename is not set, then abort DCC */ - if (!cfg_dcc_auto_rename) + ptr_home = getenv ("HOME"); + ptr_dcc->local_filename = (char *) malloc (strlen (cfg_dcc_download_path) + + strlen (ptr_dcc->nick) + + strlen (ptr_dcc->filename) + + ((cfg_dcc_download_path[0] == '~') ? + strlen (ptr_home) : 0) + + 4); + if (!ptr_dcc->local_filename) { dcc_close (ptr_dcc, DCC_FAILED); dcc_redraw (1); return; } - - filename2 = (char *) malloc (strlen (ptr_dcc->local_filename) + 16); - if (!filename2) + if (cfg_dcc_download_path[0] == '~') { - dcc_close (ptr_dcc, DCC_FAILED); - dcc_redraw (1); - return; + strcpy (ptr_dcc->local_filename, ptr_home); + strcat (ptr_dcc->local_filename, cfg_dcc_download_path + 1); } - ptr_dcc->filename_suffix = 0; - do + else + strcpy (ptr_dcc->local_filename, cfg_dcc_download_path); + if (ptr_dcc->local_filename[strlen (ptr_dcc->local_filename) - 1] != DIR_SEPARATOR_CHAR) + 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); + + /* file already exists? */ + if (access (ptr_dcc->local_filename, F_OK) == 0) { - ptr_dcc->filename_suffix++; - sprintf (filename2, "%s.%d", - ptr_dcc->local_filename, - ptr_dcc->filename_suffix); + /* if auto rename is not set, then abort DCC */ + if (!cfg_dcc_auto_rename) + { + dcc_close (ptr_dcc, DCC_FAILED); + dcc_redraw (1); + return; + } + + filename2 = (char *) malloc (strlen (ptr_dcc->local_filename) + 16); + if (!filename2) + { + dcc_close (ptr_dcc, DCC_FAILED); + dcc_redraw (1); + return; + } + ptr_dcc->filename_suffix = 0; + do + { + ptr_dcc->filename_suffix++; + sprintf (filename2, "%s.%d", + ptr_dcc->local_filename, + ptr_dcc->filename_suffix); + } + while (access (filename2, F_OK) == 0); + + free (ptr_dcc->local_filename); + ptr_dcc->local_filename = strdup (filename2); + free (filename2); } - while (access (filename2, F_OK) == 0); - - free (ptr_dcc->local_filename); - ptr_dcc->local_filename = strdup (filename2); - free (filename2); + ptr_dcc->file = open (ptr_dcc->local_filename, + O_CREAT | O_TRUNC | O_WRONLY | O_NONBLOCK, + 0644); + } + else + { + /* DCC CHAT => associate DCC with channel */ + dcc_channel_for_chat (ptr_dcc); } - ptr_dcc->file = open (ptr_dcc->local_filename, - O_CREAT | O_TRUNC | O_WRONLY | O_NONBLOCK, - 0644); } dcc_redraw (1); } @@ -272,22 +340,31 @@ dcc_add (t_irc_server *server, int type, unsigned long addr, int port, char *nic { t_irc_dcc *new_dcc; + /* create new DCC struct */ if ((new_dcc = (t_irc_dcc *) malloc (sizeof (t_irc_dcc))) == NULL) { - gui_printf_nolog (server->buffer, - _("%s not enough memory for new DCC\n"), - WEECHAT_ERROR); + irc_display_prefix (server->buffer, PREFIX_ERROR); + gui_printf (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 = DCC_WAITING; 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; - new_dcc->filename = strdup (filename); + if (DCC_IS_CHAT(type)) + new_dcc->filename = strdup (_("DCC chat")); + else + new_dcc->filename = (filename) ? strdup (filename) : NULL; new_dcc->local_filename = (local_filename) ? strdup (local_filename) : NULL; new_dcc->filename_suffix = -1; new_dcc->size = size; @@ -302,6 +379,7 @@ dcc_add (t_irc_server *server, int type, unsigned long addr, int port, char *nic gui_current_window->dcc_first = NULL; gui_current_window->dcc_selected = NULL; + /* write info message on server buffer */ if (type == DCC_FILE_RECV) { irc_display_prefix (server->buffer, PREFIX_INFO); @@ -318,17 +396,11 @@ dcc_add (t_irc_server *server, int type, unsigned long addr, int port, char *nic gui_printf_color (server->buffer, COLOR_WIN_CHAT_CHANNEL, "%lu", size); gui_printf (server->buffer, _(" bytes\n")); } - if (type == DCC_FILE_SEND) { irc_display_prefix (server->buffer, PREFIX_INFO); gui_printf (server->buffer, _("Sending DCC file to ")); gui_printf_color (server->buffer, COLOR_WIN_CHAT_NICK, "%s", nick); - gui_printf_color (server->buffer, COLOR_WIN_CHAT_DARK, " ("); - gui_printf_color (server->buffer, COLOR_WIN_CHAT_HOST, - "%d.%d.%d.%d", - addr >> 24, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff); - gui_printf_color (server->buffer, COLOR_WIN_CHAT_DARK, ")"); gui_printf (server->buffer, ": "); gui_printf_color (server->buffer, COLOR_WIN_CHAT_CHANNEL, "%s", filename); gui_printf (server->buffer, _(" (local filename: ")); @@ -337,8 +409,26 @@ dcc_add (t_irc_server *server, int type, unsigned long addr, int port, char *nic gui_printf_color (server->buffer, COLOR_WIN_CHAT_CHANNEL, "%lu", size); gui_printf (server->buffer, _(" bytes\n")); } + if (type == DCC_CHAT_RECV) + { + irc_display_prefix (server->buffer, PREFIX_INFO); + gui_printf (server->buffer, _("Incoming DCC chat request from ")); + gui_printf_color (server->buffer, COLOR_WIN_CHAT_NICK, "%s", nick); + gui_printf_color (server->buffer, COLOR_WIN_CHAT_DARK, " ("); + gui_printf_color (server->buffer, COLOR_WIN_CHAT_HOST, + "%d.%d.%d.%d", + addr >> 24, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff); + gui_printf_color (server->buffer, COLOR_WIN_CHAT_DARK, ")\n"); + } + if (type == DCC_CHAT_SEND) + { + irc_display_prefix (server->buffer, PREFIX_INFO); + gui_printf (server->buffer, _("Sending DCC chat request to ")); + gui_printf_color (server->buffer, COLOR_WIN_CHAT_NICK, "%s\n", nick); + } - if (type == DCC_FILE_SEND) + /* connect if needed and redraw DCC buffer */ + if (DCC_IS_SEND(type)) { if (!dcc_connect (new_dcc)) { @@ -358,11 +448,11 @@ dcc_add (t_irc_server *server, int type, unsigned long addr, int port, char *nic } /* - * dcc_send: send DCC request (file or chat) + * dcc_send_request: send DCC request (file or chat) */ void -dcc_send (t_irc_server *server, char *nick, char *filename) +dcc_send_request (t_irc_server *server, int type, char *nick, char *filename) { char *ptr_home, *filename2, *short_filename, *pos; int spaces; @@ -371,57 +461,66 @@ dcc_send (t_irc_server *server, char *nick, char *filename) struct sockaddr_in addr; socklen_t length; unsigned long local_addr; + t_irc_dcc *ptr_dcc; - /* add home if filename not beginning with '/' (not for Win32) */ - #ifdef _WIN32 - filename2 = strdup (filename); - #else - if (filename[0] == '/') - filename2 = strdup (filename); - else + filename2 = NULL; + short_filename = NULL; + spaces = 0; + + if (type == DCC_FILE_SEND) { - ptr_home = getenv ("HOME"); - filename2 = (char *) malloc (strlen (cfg_dcc_upload_path) + - strlen (filename) + - ((cfg_dcc_upload_path[0] == '~') ? - strlen (ptr_home) : 0) + - 4); - if (!filename2) + /* add home if filename not beginning with '/' (not for Win32) */ + #ifdef _WIN32 + filename2 = strdup (filename); + #else + if (filename[0] == '/') + filename2 = strdup (filename); + else { - irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s not enough memory for DCC SEND\n"), - WEECHAT_ERROR); - return; + ptr_home = getenv ("HOME"); + filename2 = (char *) malloc (strlen (cfg_dcc_upload_path) + + strlen (filename) + + ((cfg_dcc_upload_path[0] == '~') ? + strlen (ptr_home) : 0) + + 4); + if (!filename2) + { + irc_display_prefix (server->buffer, PREFIX_ERROR); + gui_printf (server->buffer, + _("%s not enough memory for DCC SEND\n"), + WEECHAT_ERROR); + return; + } + if (cfg_dcc_upload_path[0] == '~') + { + strcpy (filename2, ptr_home); + strcat (filename2, cfg_dcc_upload_path + 1); + } + else + strcpy (filename2, cfg_dcc_upload_path); + if (filename2[strlen (filename2) - 1] != DIR_SEPARATOR_CHAR) + strcat (filename2, DIR_SEPARATOR); + strcat (filename2, filename); } - if (cfg_dcc_upload_path[0] == '~') + #endif + + /* check if file exists */ + if (stat (filename2, &st) == -1) { - strcpy (filename2, ptr_home); - strcat (filename2, cfg_dcc_upload_path + 1); + irc_display_prefix (server->buffer, PREFIX_ERROR); + gui_printf (server->buffer, + _("%s cannot access file \"%s\"\n"), + WEECHAT_ERROR, filename2); + if (filename2) + free (filename2); + return; } - else - strcpy (filename2, cfg_dcc_upload_path); - if (filename2[strlen (filename2) - 1] != DIR_SEPARATOR_CHAR) - strcat (filename2, DIR_SEPARATOR); - strcat (filename2, filename); - } - #endif - - /* check if file exists */ - if (stat (filename2, &st) == -1) - { - irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s cannot access file \"%s\"\n"), - WEECHAT_ERROR, filename2); - free (filename2); - return; } /* get local IP address */ memset (&addr, 0, sizeof (struct sockaddr_in)); length = sizeof (addr); - getsockname (server->sock4, (struct sockaddr *) &addr, &length); + getsockname (server->sock, (struct sockaddr *) &addr, &length); addr.sin_family = AF_INET; local_addr = ntohl (addr.sin_addr.s_addr); @@ -430,10 +529,11 @@ dcc_send (t_irc_server *server, char *nick, char *filename) if (sock == -1) { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s cannot create socket for DCC\n"), - WEECHAT_ERROR); - free (filename2); + gui_printf (server->buffer, + _("%s cannot create socket for DCC\n"), + WEECHAT_ERROR); + if (filename2) + free (filename2); return; } @@ -442,68 +542,243 @@ dcc_send (t_irc_server *server, char *nick, char *filename) if (bind (sock, (struct sockaddr *) &addr, sizeof (addr)) == -1) { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s cannot find port for DCC\n"), - WEECHAT_ERROR); + gui_printf (server->buffer, + _("%s cannot find port for DCC\n"), + WEECHAT_ERROR); close (sock); - free (filename2); + if (filename2) + free (filename2); return; } length = sizeof (addr); getsockname (sock, (struct sockaddr *) &addr, &length); port = ntohs (addr.sin_port); - /* 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 (type == DCC_FILE_SEND) { - if (pos[0] == ' ') + /* 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 (cfg_dcc_convert_spaces) - pos[0] = '_'; - else - spaces = 1; + if (pos[0] == ' ') + { + if (cfg_dcc_convert_spaces) + pos[0] = '_'; + else + spaces = 1; + } + pos++; } - pos++; } /* add DCC entry and listen to socket */ - if (!dcc_add (server, DCC_FILE_SEND, local_addr, port, nick, sock, - short_filename, filename2, st.st_size)) + if (type == DCC_CHAT_SEND) + ptr_dcc = dcc_add (server, DCC_CHAT_SEND, local_addr, port, nick, sock, + NULL, NULL, 0); + else + ptr_dcc = dcc_add (server, DCC_FILE_SEND, local_addr, port, nick, sock, + short_filename, filename2, st.st_size); + if (!ptr_dcc) { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s cannot send DCC\n"), - WEECHAT_ERROR); + gui_printf (server->buffer, + _("%s cannot send DCC\n"), + WEECHAT_ERROR); close (sock); - free (short_filename); - free (filename2); + if (short_filename) + free (short_filename); + if (filename2) + free (filename2); return; } /* send DCC request to nick */ - server_sendf (server, - (spaces) ? - "PRIVMSG %s :\01DCC SEND \"%s\" %lu %d %u\01\r\n" : - "PRIVMSG %s :\01DCC SEND %s %lu %d %u\01\r\n", - nick, short_filename, local_addr, port, - (unsigned long) st.st_size); - - free (short_filename); - free (filename2); + if (type == DCC_CHAT_SEND) + server_sendf (server, + "PRIVMSG %s :\01DCC CHAT chat %lu %d\01\r\n", + nick, local_addr, port); + else + server_sendf (server, + (spaces) ? + "PRIVMSG %s :\01DCC SEND \"%s\" %lu %d %u\01\r\n" : + "PRIVMSG %s :\01DCC SEND %s %lu %d %u\01\r\n", + nick, short_filename, local_addr, port, + (unsigned long) st.st_size); + + if (short_filename) + free (short_filename); + if (filename2) + free (filename2); } +/* + * dcc_chat_send: send data to remote host via DCC CHAT + */ + +int +dcc_chat_send (t_irc_dcc *ptr_dcc, char *buffer, int size_buf) +{ + if (!ptr_dcc) + return -1; + + return send (ptr_dcc->sock, buffer, size_buf, 0); +} + +/* + * dcc_chat_sendf: send formatted data to remote host via DCC CHAT + */ + +void +dcc_chat_sendf (t_irc_dcc *ptr_dcc, char *fmt, ...) +{ + va_list args; + static char buffer[4096]; + char *buf2; + int size_buf; + + if (!ptr_dcc || (ptr_dcc->sock == -1)) + return; + + va_start (args, fmt); + size_buf = vsnprintf (buffer, sizeof (buffer) - 1, fmt, 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); + #ifdef DEBUG + buffer[size_buf - 2] = '\0'; + gui_printf (ptr_dcc->server->buffer, "[DEBUG] Sending to remote host (DCC CHAT) >>> %s\n", buffer); + buffer[size_buf - 2] = '\r'; + #endif + buf2 = weechat_convert_encoding ((cfg_look_charset_internal && cfg_look_charset_internal[0]) ? + cfg_look_charset_internal : local_charset, + cfg_look_charset_encode, + buffer); + if (dcc_chat_send (ptr_dcc, buf2, strlen (buf2)) <= 0) + { + irc_display_prefix (ptr_dcc->server->buffer, PREFIX_ERROR); + gui_printf (ptr_dcc->server->buffer, _("%s error sending data to \"%s\" via DCC CHAT\n"), + WEECHAT_ERROR, ptr_dcc->nick); + dcc_close (ptr_dcc, DCC_FAILED); + } + free (buf2); +} /* - * dcc_handle: receive/send data for each active DCC + * dcc_chat_recv: receive data from DCC CHAT host + */ + +void +dcc_chat_recv (t_irc_dcc *ptr_dcc) +{ + static char buffer[4096 + 2]; + char *buf2, *pos, *ptr_buf, *next_ptr_buf; + int num_read; + + num_read = recv (ptr_dcc->sock, buffer, sizeof (buffer) - 2, 0); + if (num_read > 0) + { + buffer[num_read] = '\0'; + + buf2 = NULL; + ptr_buf = buffer; + if (ptr_dcc->unterminated_message) + { + buf2 = (char *) malloc (strlen (ptr_dcc->unterminated_message) + + strlen (buffer) + 1); + if (buf2) + { + strcpy (buf2, ptr_dcc->unterminated_message); + strcat (buf2, buffer); + } + ptr_buf = buf2; + free (ptr_dcc->unterminated_message); + ptr_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 + { + ptr_dcc->unterminated_message = strdup (ptr_buf); + ptr_buf = NULL; + next_ptr_buf = NULL; + } + } + + if (ptr_buf) + { + gui_printf_type_color (ptr_dcc->channel->buffer, + MSG_TYPE_NICK, + COLOR_WIN_CHAT_DARK, "<"); + if (strstr (ptr_buf, ptr_dcc->server->nick)) + { + gui_printf_type_color (ptr_dcc->channel->buffer, + MSG_TYPE_NICK | MSG_TYPE_HIGHLIGHT, + COLOR_WIN_CHAT_HIGHLIGHT, + "%s", ptr_dcc->nick); + if ( (cfg_look_infobar_delay_highlight > 0) + && (ptr_dcc->channel->buffer != gui_current_window->buffer) ) + gui_infobar_printf (cfg_look_infobar_delay_highlight, + COLOR_WIN_INFOBAR_HIGHLIGHT, + _("Private %s> %s"), + ptr_dcc->nick, ptr_buf); + } + else + gui_printf_type_color (ptr_dcc->channel->buffer, + MSG_TYPE_NICK, + COLOR_WIN_NICK_PRIVATE, + "%s", ptr_dcc->nick); + gui_printf_type_color (ptr_dcc->channel->buffer, + MSG_TYPE_NICK, + COLOR_WIN_CHAT_DARK, "> "); + gui_printf_type_color (ptr_dcc->channel->buffer, + MSG_TYPE_MSG, + COLOR_WIN_CHAT, "%s\n", ptr_buf); + } + + ptr_buf = next_ptr_buf; + } + + if (buf2) + free (buf2); + } + else + { + dcc_close (ptr_dcc, DCC_ABORTED); + dcc_redraw (1); + } +} + +/* + * dcc_handle: receive/send data for each active DCC (files only) */ void @@ -555,6 +830,47 @@ dcc_handle () ptr_dcc->addr = ntohl (addr.sin_addr.s_addr); ptr_dcc->status = DCC_ACTIVE; ptr_dcc->file = open (ptr_dcc->local_filename, O_RDONLY | O_NONBLOCK, 0644); + dcc_redraw (1); + } + } + } + } + + if (ptr_dcc->status == DCC_WAITING) + { + if (ptr_dcc->type == DCC_CHAT_SEND) + { + FD_ZERO (&read_fd); + FD_SET (ptr_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) + { + if (FD_ISSET (ptr_dcc->sock, &read_fd)) + { + length = sizeof (addr); + sock = accept (ptr_dcc->sock, (struct sockaddr *) &addr, &length); + close (ptr_dcc->sock); + ptr_dcc->sock = -1; + if (sock < 0) + { + dcc_close (ptr_dcc, DCC_FAILED); + dcc_redraw (1); + return; + } + ptr_dcc->sock = sock; + if (fcntl (ptr_dcc->sock, F_SETFL, O_NONBLOCK) == -1) + { + dcc_close (ptr_dcc, DCC_FAILED); + dcc_redraw (1); + return; + } + ptr_dcc->addr = ntohl (addr.sin_addr.s_addr); + ptr_dcc->status = DCC_ACTIVE; + dcc_redraw (1); + dcc_channel_for_chat (ptr_dcc); } } } @@ -562,6 +878,20 @@ dcc_handle () if (ptr_dcc->status == DCC_ACTIVE) { + if (DCC_IS_CHAT(ptr_dcc->type)) + { + FD_ZERO (&read_fd); + FD_SET (ptr_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) + { + if (FD_ISSET (ptr_dcc->sock, &read_fd)) + dcc_chat_recv (ptr_dcc); + } + } if (ptr_dcc->type == DCC_FILE_RECV) { num_read = recv (ptr_dcc->sock, buffer, sizeof (buffer), 0); @@ -596,6 +926,7 @@ dcc_handle () { if (cfg_dcc_blocksize > (int) sizeof (buffer)) { + irc_display_prefix (NULL, PREFIX_ERROR); gui_printf (NULL, _("%s DCC failed because blocksize is too " "big. Check value of \"dcc_blocksize\" option, " "max is %d.\n"), diff --git a/src/irc/irc-display.c b/src/irc/irc-display.c index ec5f135b0..4b5212fa3 100644 --- a/src/irc/irc-display.c +++ b/src/irc/irc-display.c @@ -52,9 +52,9 @@ irc_display_prefix (t_gui_buffer *buffer, char *prefix) if (prefix[0] == prefix[2]) { - gui_printf_color_type (buffer, type, COLOR_WIN_CHAT_PREFIX1, "%c", prefix[0]); - gui_printf_color_type (buffer, type, COLOR_WIN_CHAT_PREFIX2, "%c", prefix[1]); - gui_printf_color_type (buffer, type, COLOR_WIN_CHAT_PREFIX1, "%c ", prefix[2]); + gui_printf_type_color (buffer, type, COLOR_WIN_CHAT_PREFIX1, "%c", prefix[0]); + gui_printf_type_color (buffer, type, COLOR_WIN_CHAT_PREFIX2, "%c", prefix[1]); + gui_printf_type_color (buffer, type, COLOR_WIN_CHAT_PREFIX1, "%c ", prefix[2]); } else gui_printf_color (buffer, COLOR_WIN_CHAT_PREFIX1, "%s ", prefix); @@ -70,43 +70,43 @@ irc_display_nick (t_gui_buffer *buffer, t_irc_nick *nick, int message_type, int display_around, int color_nick, int no_nickmode) { if (display_around) - gui_printf_color_type (buffer, + gui_printf_type_color (buffer, message_type, COLOR_WIN_CHAT_DARK, "<"); if (cfg_look_nickmode) { if (nick->is_chanowner) - gui_printf_color_type (buffer, + gui_printf_type_color (buffer, message_type, COLOR_WIN_NICK_OP, "~"); else if (nick->is_chanadmin) - gui_printf_color_type (buffer, + gui_printf_type_color (buffer, message_type, COLOR_WIN_NICK_OP, "&"); else if (nick->is_op) - gui_printf_color_type (buffer, + gui_printf_type_color (buffer, message_type, COLOR_WIN_NICK_OP, "@"); else if (nick->is_halfop) - gui_printf_color_type (buffer, + gui_printf_type_color (buffer, message_type, COLOR_WIN_NICK_HALFOP, "%%"); else if (nick->has_voice) - gui_printf_color_type (buffer, + gui_printf_type_color (buffer, message_type, COLOR_WIN_NICK_VOICE, "+"); else if (cfg_look_nickmode_empty && !no_nickmode) - gui_printf_color_type (buffer, + gui_printf_type_color (buffer, message_type, COLOR_WIN_CHAT, " "); } if (color_nick < 0) - gui_printf_color_type (buffer, + gui_printf_type_color (buffer, message_type, COLOR_WIN_CHAT_HIGHLIGHT, "%s", nick->nick); else - gui_printf_color_type (buffer, + gui_printf_type_color (buffer, message_type, (color_nick) ? ((cfg_look_color_nicks) ? @@ -115,7 +115,7 @@ irc_display_nick (t_gui_buffer *buffer, t_irc_nick *nick, int message_type, "%s", nick->nick); if (display_around) - gui_printf_color_type (buffer, + gui_printf_type_color (buffer, message_type, COLOR_WIN_CHAT_DARK, "> "); } diff --git a/src/irc/irc-recv.c b/src/irc/irc-recv.c index 6b34d4cd2..ab69abe8d 100644 --- a/src/irc/irc-recv.c +++ b/src/irc/irc-recv.c @@ -160,9 +160,9 @@ irc_cmd_recv_join (t_irc_server *server, char *host, char *arguments) if (!ptr_channel) { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s cannot create new channel \"%s\"\n"), - WEECHAT_ERROR, arguments); + gui_printf (server->buffer, + _("%s cannot create new channel \"%s\"\n"), + WEECHAT_ERROR, arguments); return -1; } } @@ -227,9 +227,9 @@ irc_cmd_recv_kick (t_irc_server *server, char *host, char *arguments) if (!ptr_channel) { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s channel not found for \"%s\" command\n"), - WEECHAT_ERROR, "kick"); + gui_printf (server->buffer, + _("%s channel not found for \"%s\" command\n"), + WEECHAT_ERROR, "kick"); return -1; } @@ -260,9 +260,9 @@ irc_cmd_recv_kick (t_irc_server *server, char *host, char *arguments) else { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s nick not found for \"%s\" command\n"), - WEECHAT_ERROR, "kick"); + gui_printf (server->buffer, + _("%s nick not found for \"%s\" command\n"), + WEECHAT_ERROR, "kick"); return -1; } if (strcmp (pos_nick, server->nick) == 0) @@ -550,9 +550,9 @@ irc_cmd_recv_mode (t_irc_server *server, char *host, char *arguments) if (host == NULL) { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s \"%s\" command received without host\n"), - WEECHAT_ERROR, "mode"); + gui_printf (server->buffer, + _("%s \"%s\" command received without host\n"), + WEECHAT_ERROR, "mode"); return -1; } @@ -565,9 +565,9 @@ irc_cmd_recv_mode (t_irc_server *server, char *host, char *arguments) if (!pos) { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s \"%s\" command received without channel or nickname\n"), - WEECHAT_ERROR, "mode"); + gui_printf (server->buffer, + _("%s \"%s\" command received without channel or nickname\n"), + WEECHAT_ERROR, "mode"); return -1; } pos[0] = '\0'; @@ -595,9 +595,9 @@ irc_cmd_recv_mode (t_irc_server *server, char *host, char *arguments) else { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s channel not found for \"%s\" command\n"), - WEECHAT_ERROR, "mode"); + gui_printf (server->buffer, + _("%s channel not found for \"%s\" command\n"), + WEECHAT_ERROR, "mode"); return -1; } } @@ -635,9 +635,9 @@ irc_cmd_recv_nick (t_irc_server *server, char *host, char *arguments) if (host == NULL) { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s \"%s\" command received without host\n"), - WEECHAT_ERROR, "nick"); + gui_printf (server->buffer, + _("%s \"%s\" command received without host\n"), + WEECHAT_ERROR, "nick"); return -1; } @@ -753,9 +753,9 @@ irc_cmd_recv_notice (t_irc_server *server, char *host, char *arguments) else { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s nickname not found for \"%s\" command\n"), - WEECHAT_ERROR, "notice"); + gui_printf (server->buffer, + _("%s nickname not found for \"%s\" command\n"), + WEECHAT_ERROR, "notice"); return -1; } if (strncmp (pos, "\01VERSION", 8) == 0) @@ -846,9 +846,9 @@ irc_cmd_recv_part (t_irc_server *server, char *host, char *arguments) if (!host || !arguments) { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s \"%s\" command received without host or channel\n"), - WEECHAT_ERROR, "part"); + gui_printf (server->buffer, + _("%s \"%s\" command received without host or channel\n"), + WEECHAT_ERROR, "part"); return -1; } @@ -921,9 +921,9 @@ irc_cmd_recv_part (t_irc_server *server, char *host, char *arguments) else { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s channel not found for \"%s\" command\n"), - WEECHAT_ERROR, "part"); + gui_printf (server->buffer, + _("%s channel not found for \"%s\" command\n"), + WEECHAT_ERROR, "part"); return -1; } @@ -995,9 +995,9 @@ irc_cmd_recv_privmsg (t_irc_server *server, char *host, char *arguments) if (host == NULL) { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s \"%s\" command received without host\n"), - WEECHAT_ERROR, "privmsg"); + gui_printf (server->buffer, + _("%s \"%s\" command received without host\n"), + WEECHAT_ERROR, "privmsg"); return -1; } @@ -1036,7 +1036,7 @@ irc_cmd_recv_privmsg (t_irc_server *server, char *host, char *arguments) irc_display_prefix (ptr_channel->buffer, PREFIX_ACTION_ME); if (strstr (pos, server->nick)) { - gui_printf_color_type (ptr_channel->buffer, + gui_printf_type_color (ptr_channel->buffer, MSG_TYPE_MSG | MSG_TYPE_HIGHLIGHT, COLOR_WIN_CHAT_HIGHLIGHT, "%s", host); @@ -1050,7 +1050,7 @@ irc_cmd_recv_privmsg (t_irc_server *server, char *host, char *arguments) host, pos); } else - gui_printf_color_type (ptr_channel->buffer, + gui_printf_type_color (ptr_channel->buffer, MSG_TYPE_MSG, COLOR_WIN_CHAT_NICK, "%s", host); gui_printf_color (ptr_channel->buffer, @@ -1078,16 +1078,16 @@ irc_cmd_recv_privmsg (t_irc_server *server, char *host, char *arguments) else irc_display_nick (ptr_channel->buffer, ptr_nick, MSG_TYPE_NICK, 1, 1, 0); - gui_printf_color_type (ptr_channel->buffer, + gui_printf_type_color (ptr_channel->buffer, MSG_TYPE_MSG, COLOR_WIN_CHAT, "%s\n", pos); } else { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s nick not found for \"%s\" command\n"), - WEECHAT_ERROR, "privmsg"); + gui_printf (server->buffer, + _("%s nick not found for \"%s\" command\n"), + WEECHAT_ERROR, "privmsg"); return -1; } } @@ -1095,9 +1095,9 @@ irc_cmd_recv_privmsg (t_irc_server *server, char *host, char *arguments) else { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s channel not found for \"%s\" command\n"), - WEECHAT_ERROR, "privmsg"); + gui_printf (server->buffer, + _("%s channel not found for \"%s\" command\n"), + WEECHAT_ERROR, "privmsg"); return -1; } } @@ -1176,16 +1176,19 @@ irc_cmd_recv_privmsg (t_irc_server *server, char *host, char *arguments) /* incoming DCC file */ if (strncmp (pos, "\01DCC SEND", 9) == 0) { - pos2 = strchr (pos, '\01'); + /* check if DCC SEND is ok, i.e. with 0x01 at end */ + pos2 = strchr (pos + 1, '\01'); if (!pos2) { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s cannot parse \"%s\" command\n"), - WEECHAT_ERROR, "privmsg"); + gui_printf (server->buffer, + _("%s cannot parse \"%s\" command\n"), + WEECHAT_ERROR, "privmsg"); return -1; } pos2[0] = '\0'; + + /* DCC filename */ pos_file = pos + 9; while (pos_file[0] == ' ') pos_file++; @@ -1195,9 +1198,9 @@ irc_cmd_recv_privmsg (t_irc_server *server, char *host, char *arguments) if (!pos_size) { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s cannot parse \"%s\" command\n"), - WEECHAT_ERROR, "privmsg"); + gui_printf (server->buffer, + _("%s cannot parse \"%s\" command\n"), + WEECHAT_ERROR, "privmsg"); return -1; } pos2 = pos_size; @@ -1211,9 +1214,9 @@ irc_cmd_recv_privmsg (t_irc_server *server, char *host, char *arguments) if (!pos_port) { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s cannot parse \"%s\" command\n"), - WEECHAT_ERROR, "privmsg"); + gui_printf (server->buffer, + _("%s cannot parse \"%s\" command\n"), + WEECHAT_ERROR, "privmsg"); return -1; } pos2 = pos_port; @@ -1222,14 +1225,14 @@ irc_cmd_recv_privmsg (t_irc_server *server, char *host, char *arguments) pos2--; pos2[1] = '\0'; - /* look for DCC address (IP) */ + /* look for DCC IP address */ pos_addr = strrchr (pos_file, ' '); if (!pos_addr) { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s cannot parse \"%s\" command\n"), - WEECHAT_ERROR, "privmsg"); + gui_printf (server->buffer, + _("%s cannot parse \"%s\" command\n"), + WEECHAT_ERROR, "privmsg"); return -1; } pos2 = pos_addr; @@ -1244,6 +1247,74 @@ irc_cmd_recv_privmsg (t_irc_server *server, char *host, char *arguments) return 0; } + /* incoming DCC CHAT */ + if (strncmp (pos, "\01DCC CHAT", 9) == 0) + { + /* check if DCC CHAT is ok, i.e. with 0x01 at end */ + pos2 = strchr (pos + 1, '\01'); + if (!pos2) + { + irc_display_prefix (server->buffer, PREFIX_ERROR); + gui_printf (server->buffer, + _("%s cannot parse \"%s\" command\n"), + WEECHAT_ERROR, "privmsg"); + return -1; + } + pos2[0] = '\0'; + + /* CHAT type */ + pos_file = pos + 9; + while (pos_file[0] == ' ') + pos_file++; + + /* DCC IP address */ + pos_addr = strchr (pos_file, ' '); + if (!pos_addr) + { + irc_display_prefix (server->buffer, PREFIX_ERROR); + gui_printf (server->buffer, + _("%s cannot parse \"%s\" command\n"), + WEECHAT_ERROR, "privmsg"); + return -1; + } + pos_addr[0] = '\0'; + pos_addr++; + while (pos_addr[0] == ' ') + pos_addr++; + + /* look for DCC port */ + pos_port = strchr (pos_addr, ' '); + if (!pos_port) + { + irc_display_prefix (server->buffer, PREFIX_ERROR); + gui_printf (server->buffer, + _("%s cannot parse \"%s\" command\n"), + WEECHAT_ERROR, "privmsg"); + return -1; + } + pos_port[0] = '\0'; + pos_port++; + while (pos_port[0] == ' ') + pos_port++; + + if (strcasecmp (pos_file, "chat") != 0) + { + irc_display_prefix (server->buffer, PREFIX_ERROR); + gui_printf (server->buffer, + _("%s unknown DCC CHAT type received from "), + WEECHAT_ERROR); + gui_printf_color (server->buffer, COLOR_WIN_CHAT_NICK, + "%s", host); + gui_printf (server->buffer, ": \"%s\"\n", pos_file); + return -1; + } + + dcc_add (server, DCC_CHAT_RECV, (unsigned long) atol (pos_addr), + atoi (pos_port), host, -1, NULL, NULL, 0); + + return 0; + } + /* private message received => display it */ ptr_channel = channel_search (server, host); if (!ptr_channel) @@ -1252,9 +1323,9 @@ irc_cmd_recv_privmsg (t_irc_server *server, char *host, char *arguments) if (!ptr_channel) { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s cannot create new private window \"%s\"\n"), - WEECHAT_ERROR, host); + gui_printf (server->buffer, + _("%s cannot create new private window \"%s\"\n"), + WEECHAT_ERROR, host); return -1; } } @@ -1270,7 +1341,7 @@ irc_cmd_recv_privmsg (t_irc_server *server, char *host, char *arguments) irc_display_prefix (ptr_channel->buffer, PREFIX_ACTION_ME); if (strstr (pos, server->nick)) { - gui_printf_color_type (ptr_channel->buffer, + gui_printf_type_color (ptr_channel->buffer, MSG_TYPE_MSG | MSG_TYPE_HIGHLIGHT, COLOR_WIN_CHAT_HIGHLIGHT, "%s", host); @@ -1284,7 +1355,7 @@ irc_cmd_recv_privmsg (t_irc_server *server, char *host, char *arguments) host, pos); } else - gui_printf_color_type (ptr_channel->buffer, + gui_printf_type_color (ptr_channel->buffer, MSG_TYPE_MSG, COLOR_WIN_CHAT_NICK, "%s", host); gui_printf_color (ptr_channel->buffer, @@ -1292,12 +1363,12 @@ irc_cmd_recv_privmsg (t_irc_server *server, char *host, char *arguments) } else { - gui_printf_color_type (ptr_channel->buffer, + gui_printf_type_color (ptr_channel->buffer, MSG_TYPE_NICK, COLOR_WIN_CHAT_DARK, "<"); if (strstr (pos, server->nick)) { - gui_printf_color_type (ptr_channel->buffer, + gui_printf_type_color (ptr_channel->buffer, MSG_TYPE_NICK | MSG_TYPE_HIGHLIGHT, COLOR_WIN_CHAT_HIGHLIGHT, "%s", host); @@ -1309,14 +1380,14 @@ irc_cmd_recv_privmsg (t_irc_server *server, char *host, char *arguments) host, pos); } else - gui_printf_color_type (ptr_channel->buffer, + gui_printf_type_color (ptr_channel->buffer, MSG_TYPE_NICK, COLOR_WIN_NICK_PRIVATE, "%s", host); - gui_printf_color_type (ptr_channel->buffer, + gui_printf_type_color (ptr_channel->buffer, MSG_TYPE_NICK, COLOR_WIN_CHAT_DARK, "> "); - gui_printf_color_type (ptr_channel->buffer, + gui_printf_type_color (ptr_channel->buffer, MSG_TYPE_MSG, COLOR_WIN_CHAT, "%s\n", pos); } @@ -1324,9 +1395,9 @@ irc_cmd_recv_privmsg (t_irc_server *server, char *host, char *arguments) else { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s cannot parse \"%s\" command\n"), - WEECHAT_ERROR, "privmsg"); + gui_printf (server->buffer, + _("%s cannot parse \"%s\" command\n"), + WEECHAT_ERROR, "privmsg"); return -1; } } @@ -1348,9 +1419,9 @@ irc_cmd_recv_quit (t_irc_server *server, char *host, char *arguments) if (host == NULL) { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s \"%s\" command received without host\n"), - WEECHAT_ERROR, "quit"); + gui_printf (server->buffer, + _("%s \"%s\" command received without host\n"), + WEECHAT_ERROR, "quit"); return -1; } @@ -1500,9 +1571,9 @@ irc_cmd_recv_topic (t_irc_server *server, char *host, char *arguments) if (!string_is_channel (arguments)) { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s \"%s\" command received without channel\n"), - WEECHAT_ERROR, "topic"); + gui_printf (server->buffer, + _("%s \"%s\" command received without channel\n"), + WEECHAT_ERROR, "topic"); return -1; } @@ -2558,9 +2629,9 @@ irc_cmd_recv_332 (t_irc_server *server, char *host, char *arguments) else { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s channel not found for \"%s\" command\n"), - WEECHAT_ERROR, "332"); + gui_printf (server->buffer, + _("%s channel not found for \"%s\" command\n"), + WEECHAT_ERROR, "332"); return -1; } } @@ -2568,9 +2639,9 @@ irc_cmd_recv_332 (t_irc_server *server, char *host, char *arguments) else { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s cannot identify channel for \"%s\" command\n"), - WEECHAT_ERROR, "332"); + gui_printf (server->buffer, + _("%s cannot identify channel for \"%s\" command\n"), + WEECHAT_ERROR, "332"); return -1; } return 0; @@ -2625,36 +2696,36 @@ irc_cmd_recv_333 (t_irc_server *server, char *host, char *arguments) else { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s channel not found for \"%s\" command\n"), - WEECHAT_ERROR, "333"); + gui_printf (server->buffer, + _("%s channel not found for \"%s\" command\n"), + WEECHAT_ERROR, "333"); return -1; } } else { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s cannot identify date/time for \"%s\" command\n"), - WEECHAT_ERROR, "333"); + gui_printf (server->buffer, + _("%s cannot identify date/time for \"%s\" command\n"), + WEECHAT_ERROR, "333"); return -1; } } else { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s cannot identify nickname for \"%s\" command\n"), - WEECHAT_ERROR, "333"); + gui_printf (server->buffer, + _("%s cannot identify nickname for \"%s\" command\n"), + WEECHAT_ERROR, "333"); return -1; } } else { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s cannot identify channel for \"%s\" command\n"), - WEECHAT_ERROR, "333"); + gui_printf (server->buffer, + _("%s cannot identify channel for \"%s\" command\n"), + WEECHAT_ERROR, "333"); return -1; } return 0; @@ -2862,9 +2933,9 @@ irc_cmd_recv_353 (t_irc_server *server, char *host, char *arguments) if (pos[0] != ':') { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s cannot parse \"%s\" command\n"), - WEECHAT_ERROR, "353"); + gui_printf (server->buffer, + _("%s cannot parse \"%s\" command\n"), + WEECHAT_ERROR, "353"); return -1; } pos++; @@ -2908,9 +2979,9 @@ irc_cmd_recv_353 (t_irc_server *server, char *host, char *arguments) is_op, is_halfop, has_voice)) { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s cannot create nick \"%s\" for channel \"%s\"\n"), - WEECHAT_ERROR, pos_nick, ptr_channel->name); + gui_printf (server->buffer, + _("%s cannot create nick \"%s\" for channel \"%s\"\n"), + WEECHAT_ERROR, pos_nick, ptr_channel->name); } } } @@ -2919,9 +2990,9 @@ irc_cmd_recv_353 (t_irc_server *server, char *host, char *arguments) else { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, - _("%s cannot parse \"%s\" command\n"), - WEECHAT_ERROR, "353"); + gui_printf (server->buffer, + _("%s cannot parse \"%s\" command\n"), + WEECHAT_ERROR, "353"); return -1; } return 0; diff --git a/src/irc/irc-send.c b/src/irc/irc-send.c index 1226df884..8fc1ec071 100644 --- a/src/irc/irc-send.c +++ b/src/irc/irc-send.c @@ -246,7 +246,7 @@ irc_cmd_send_ctcp (t_irc_server *server, char *arguments) } /* - * irc_cmd_send_dcc: starts DCC (file or chat) + * irc_cmd_send_dcc: start DCC (file or chat) */ int @@ -254,8 +254,6 @@ irc_cmd_send_dcc (t_irc_server *server, char *arguments) { char *pos_nick, *pos_file; - /* TODO: develop DCC CHAT */ - /* DCC SEND file */ if (strncasecmp (arguments, "send", 4) == 0) { @@ -270,6 +268,7 @@ irc_cmd_send_dcc (t_irc_server *server, char *arguments) } while (pos_nick[0] == ' ') pos_nick++; + pos_file = strchr (pos_nick, ' '); if (!pos_file) { @@ -284,13 +283,41 @@ irc_cmd_send_dcc (t_irc_server *server, char *arguments) while (pos_file[0] == ' ') pos_file++; - dcc_send (server, pos_nick, pos_file); + dcc_send_request (server, DCC_FILE_SEND, pos_nick, pos_file); } else if (strncasecmp (arguments, "chat", 4) == 0) { + pos_nick = strchr (arguments, ' '); + if (!pos_nick) + { + irc_display_prefix (server->buffer, PREFIX_ERROR); + gui_printf_nolog (server->buffer, + _("%s wrong argument count for \"%s\" command\n"), + WEECHAT_ERROR, "dcc chat"); + return -1; + } + while (pos_nick[0] == ' ') + pos_nick++; + + dcc_send_request (server, DCC_CHAT_SEND, pos_nick, NULL); + } + else if (strcasecmp (arguments, "close") == 0) + { + if (BUFFER_IS_PRIVATE(gui_current_window->buffer) && + CHANNEL(gui_current_window->buffer)->dcc_chat) + { + dcc_close ((t_irc_dcc *)(CHANNEL(gui_current_window->buffer)->dcc_chat), + DCC_ABORTED); + dcc_redraw (1); + } + } + else + { irc_display_prefix (server->buffer, PREFIX_ERROR); - gui_printf_nolog (server->buffer, _("This command is not developed!\n")); - return 0; + gui_printf_nolog (server->buffer, + _("%s wrong arguments for \"%s\" command\n"), + WEECHAT_ERROR, "dcc"); + return -1; } return 0; @@ -630,7 +657,7 @@ irc_cmd_send_msg (t_irc_server *server, char *arguments) { irc_display_nick (ptr_channel->buffer, ptr_nick, MSG_TYPE_NICK, 1, 1, 0); - gui_printf_color_type (ptr_channel->buffer, + gui_printf_type_color (ptr_channel->buffer, MSG_TYPE_MSG, COLOR_WIN_CHAT, "%s\n", pos); } @@ -655,7 +682,7 @@ irc_cmd_send_msg (t_irc_server *server, char *arguments) { irc_display_nick (ptr_channel->buffer, ptr_nick, MSG_TYPE_NICK, 1, 1, 0); - gui_printf_color_type (ptr_channel->buffer, + gui_printf_type_color (ptr_channel->buffer, MSG_TYPE_MSG, COLOR_WIN_CHAT, "%s\n", pos); } @@ -691,13 +718,13 @@ irc_cmd_send_msg (t_irc_server *server, char *arguments) } } irc_display_prefix (server->buffer, PREFIX_SERVER); - gui_printf_color_type (server->buffer, + gui_printf_type_color (server->buffer, MSG_TYPE_NICK, COLOR_WIN_CHAT_DARK, "-"); - gui_printf_color_type (server->buffer, + gui_printf_type_color (server->buffer, MSG_TYPE_NICK, COLOR_WIN_CHAT_NICK, "%s", arguments); - gui_printf_color_type (server->buffer, + gui_printf_type_color (server->buffer, MSG_TYPE_NICK, COLOR_WIN_CHAT_DARK, "-"); gui_printf_color (server->buffer, @@ -722,17 +749,17 @@ irc_cmd_send_msg (t_irc_server *server, char *arguments) gui_draw_buffer_title (ptr_channel->buffer, 1); } - gui_printf_color_type (ptr_channel->buffer, + gui_printf_type_color (ptr_channel->buffer, MSG_TYPE_NICK, COLOR_WIN_CHAT_DARK, "<"); - gui_printf_color_type (ptr_channel->buffer, + gui_printf_type_color (ptr_channel->buffer, MSG_TYPE_NICK, COLOR_WIN_NICK_SELF, "%s", server->nick); - gui_printf_color_type (ptr_channel->buffer, + gui_printf_type_color (ptr_channel->buffer, MSG_TYPE_NICK, COLOR_WIN_CHAT_DARK, "> "); - gui_printf_color_type (ptr_channel->buffer, + gui_printf_type_color (ptr_channel->buffer, MSG_TYPE_MSG, COLOR_WIN_CHAT, "%s\n", pos); server_sendf (server, "PRIVMSG %s :%s\r\n", arguments, pos); @@ -1014,17 +1041,17 @@ irc_cmd_send_query (t_irc_server *server, char *arguments) /* display text if given */ if (pos) { - gui_printf_color_type (ptr_channel->buffer, + gui_printf_type_color (ptr_channel->buffer, MSG_TYPE_NICK, COLOR_WIN_CHAT_DARK, "<"); - gui_printf_color_type (ptr_channel->buffer, + gui_printf_type_color (ptr_channel->buffer, MSG_TYPE_NICK, COLOR_WIN_NICK_SELF, "%s", server->nick); - gui_printf_color_type (ptr_channel->buffer, + gui_printf_type_color (ptr_channel->buffer, MSG_TYPE_NICK, COLOR_WIN_CHAT_DARK, "> "); - gui_printf_color_type (ptr_channel->buffer, + gui_printf_type_color (ptr_channel->buffer, MSG_TYPE_MSG, COLOR_WIN_CHAT, "%s\n", pos); server_sendf (server, "PRIVMSG %s :%s\r\n", arguments, pos); diff --git a/src/irc/irc-server.c b/src/irc/irc-server.c index bb23fc956..191ef7dc9 100644 --- a/src/irc/irc-server.c +++ b/src/irc/irc-server.c @@ -82,7 +82,7 @@ server_init (t_irc_server *server) server->child_pid = 0; server->child_read = -1; server->child_write = -1; - server->sock4 = -1; + server->sock = -1; server->is_connected = 0; server->unterminated_message = NULL; server->nick = NULL; @@ -271,6 +271,10 @@ server_free (t_irc_server *server) { t_irc_server *new_irc_servers; + /* close any opened channel/private */ + while (server->channels) + channel_free (server, server->channels); + /* remove server from queue */ if (last_irc_server == server) last_irc_server = server->prev_server; @@ -364,12 +368,12 @@ server_new (char *name, int autoconnect, int autoreconnect, int autoreconnect_de */ int -server_send (t_irc_server * server, char *buffer, int size_buf) +server_send (t_irc_server *server, char *buffer, int size_buf) { if (!server) return -1; - return send (server->sock4, buffer, size_buf, 0); + return send (server->sock, buffer, size_buf, 0); } /* @@ -377,23 +381,23 @@ server_send (t_irc_server * server, char *buffer, int size_buf) */ void -server_sendf (t_irc_server * server, char *fmt, ...) +server_sendf (t_irc_server *server, char *fmt, ...) { va_list args; - static char buffer[1024]; + static char buffer[4096]; char *buf2; int size_buf; - + if (!server) return; - + va_start (args, fmt); size_buf = vsnprintf (buffer, sizeof (buffer) - 1, fmt, 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); @@ -632,7 +636,7 @@ server_recv (t_irc_server *server) static char buffer[4096 + 2]; int num_read; - num_read = recv (server->sock4, buffer, sizeof (buffer) - 2, 0); + num_read = recv (server->sock, buffer, sizeof (buffer) - 2, 0); if (num_read > 0) { buffer[num_read] = '\0'; @@ -687,10 +691,10 @@ server_close_connection (t_irc_server *server) server_kill_child (server); /* close network socket */ - if (server->sock4 != -1) + if (server->sock != -1) { - close (server->sock4); - server->sock4 = -1; + close (server->sock); + server->sock = -1; } /* free any pending message */ @@ -804,7 +808,7 @@ server_child (t_irc_server *server) } /* connect to server */ - error = connect (server->sock4, (struct sockaddr *) &addr, sizeof (addr)); + error = connect (server->sock, (struct sockaddr *) &addr, sizeof (addr)); if (error != 0) { write (server->child_write, "3", 1); @@ -849,8 +853,8 @@ server_connect (t_irc_server *server) server->child_write = child_pipe[1]; /* create socket and set options */ - server->sock4 = socket (AF_INET, SOCK_STREAM, 0); - if (server->sock4 == -1) + server->sock = socket (AF_INET, SOCK_STREAM, 0); + if (server->sock == -1) { irc_display_prefix (server->buffer, PREFIX_ERROR); gui_printf (server->buffer, @@ -861,7 +865,7 @@ server_connect (t_irc_server *server) /* set SO_REUSEADDR option for socket */ set = 1; - if (setsockopt (server->sock4, SOL_SOCKET, SO_REUSEADDR, + if (setsockopt (server->sock, SOL_SOCKET, SO_REUSEADDR, (void *) &set, sizeof (set)) == -1) { irc_display_prefix (server->buffer, PREFIX_ERROR); @@ -872,7 +876,7 @@ server_connect (t_irc_server *server) /* set SO_KEEPALIVE option for socket */ set = 1; - if (setsockopt (server->sock4, SOL_SOCKET, SO_KEEPALIVE, + if (setsockopt (server->sock, SOL_SOCKET, SO_KEEPALIVE, (void *) &set, sizeof (set)) == -1) { irc_display_prefix (server->buffer, PREFIX_ERROR); diff --git a/src/irc/irc.h b/src/irc/irc.h index 828bca973..755bb874b 100644 --- a/src/irc/irc.h +++ b/src/irc/irc.h @@ -71,6 +71,14 @@ #define DCC_FAILED 4 /* DCC failed */ #define DCC_ABORTED 5 /* DCC aborted by user */ +#define DCC_IS_CHAT(type) ((type == DCC_CHAT_RECV) || (type == DCC_CHAT_SEND)) +#define DCC_IS_FILE(type) ((type == DCC_FILE_RECV) || (type == DCC_FILE_SEND)) +#define DCC_IS_RECV(type) ((type == DCC_CHAT_RECV) || (type == DCC_FILE_RECV)) +#define DCC_IS_SEND(type) ((type == DCC_CHAT_SEND) || (type == DCC_FILE_SEND)) + +#define DCC_ENDED(status) ((status == DCC_DONE) || (status == DCC_FAILED) || \ + (status == DCC_ABORTED)) + /* nick types */ typedef struct t_irc_nick t_irc_nick; @@ -100,6 +108,7 @@ typedef struct t_irc_channel t_irc_channel; struct t_irc_channel { int type; /* channel type */ + void *dcc_chat; /* DCC CHAT pointer (NULL if not DCC) */ char *name; /* name of channel (exemple: "#abc") */ char *topic; /* topic of channel (host for private) */ char modes[NUM_CHANNEL_MODES+1];/* channel modes */ @@ -142,7 +151,7 @@ struct t_irc_server pid_t child_pid; /* pid of child process (connecting) */ int child_read; /* to read into child pipe */ int child_write; /* to write into child pipe */ - int sock4; /* socket for server */ + int sock; /* socket for server */ int is_connected; /* 1 if WeeChat is connected to server */ char *unterminated_message; /* beginning of a message in input buf */ char *nick; /* current nickname */ @@ -198,12 +207,14 @@ typedef struct t_irc_dcc t_irc_dcc; struct t_irc_dcc { t_irc_server *server; /* irc server */ + t_irc_channel *channel; /* irc channel (for DCC chat only) */ int type; /* DCC type (send or receive) */ int status; /* DCC status (waiting, sending, ..) */ unsigned long addr; /* IP address */ int port; /* port */ char *nick; /* remote nick */ int sock; /* socket for connection */ + char *unterminated_message; /* beginning of a message in input buf */ int file; /* local file (for reading or writing) */ char *filename; /* filename (given by sender) */ char *local_filename; /* local filename (with path) */ @@ -260,6 +271,8 @@ extern int string_is_channel (char *); extern void channel_remove_away (t_irc_channel *); extern void channel_check_away (t_irc_server *, t_irc_channel *); extern void channel_set_away (t_irc_channel *, char *, int); +extern int channel_create_dcc (t_irc_dcc *); +extern void channel_remove_dcc (t_irc_dcc *); /* nick functions (irc-nick.c) */ @@ -275,13 +288,15 @@ extern void nick_set_away (t_irc_channel *, t_irc_nick *, int); /* DCC functions (irc-dcc.c) */ +extern void dcc_redraw (int); extern void dcc_free (t_irc_dcc *); extern void dcc_close (t_irc_dcc *, int); extern void dcc_accept (t_irc_dcc *); extern t_irc_dcc *dcc_add (t_irc_server *, int, unsigned long, int, char *, int, char *, char *, unsigned long); +extern void dcc_send_request (t_irc_server *, int, char *, char *); +extern void dcc_chat_sendf (t_irc_dcc *, char *, ...); extern void dcc_handle (); -extern void dcc_send (t_irc_server *, char *, char *); extern void dcc_end (); /* IRC display (irc-diplay.c) */ |