1
0
mirror of https://github.com/weechat/weechat.git synced 2026-06-28 22:06:38 +02:00

IRC DCC chat and file (without resume) reintroduced, via xfer plugin (called by /dcc command)

This commit is contained in:
Sebastien Helleu
2008-05-06 16:51:30 +02:00
parent e7a16efa0c
commit e9603acb1a
37 changed files with 2155 additions and 1271 deletions
+20 -28
View File
@@ -894,12 +894,14 @@ irc_command_dcc (void *data, struct t_gui_buffer *buffer, int argc,
item = weechat_infolist_new_item (infolist);
if (item)
{
weechat_infolist_new_var_string (item, "plugin_name", weechat_plugin->name);
snprintf (plugin_id, sizeof (plugin_id),
"irc_%x", (unsigned int)ptr_server);
"%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, "remote_nick", argv[2]);
weechat_infolist_new_var_string (item, "local_nick", ptr_server->nick);
weechat_infolist_new_var_string (item, "filename", argv_eol[3]);
snprintf (str_address, sizeof (str_address),
"%lu", address);
@@ -924,11 +926,13 @@ irc_command_dcc (void *data, struct t_gui_buffer *buffer, int argc,
item = weechat_infolist_new_item (infolist);
if (item)
{
weechat_infolist_new_var_string (item, "plugin_name", weechat_plugin->name);
snprintf (plugin_id, sizeof (plugin_id),
"irc_%x", (unsigned int)ptr_server);
"%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]);
weechat_infolist_new_var_string (item, "remote_nick", argv[2]);
weechat_infolist_new_var_string (item, "local_nick", ptr_server->nick);
snprintf (str_address, sizeof (str_address),
"%lu", address);
weechat_infolist_new_var_string (item, "address", str_address);
@@ -939,17 +943,6 @@ irc_command_dcc (void *data, struct t_gui_buffer *buffer, int argc,
weechat_infolist_free (infolist);
}
}
/* close DCC CHAT */
else if (weechat_strcasecmp (argv[1], "close") == 0)
{
if (ptr_channel && (ptr_channel != IRC_CHANNEL_TYPE_CHANNEL)
&& (ptr_channel->dcc_chat))
{
//irc_dcc_close (ptr_channel->dcc_chat,
// IRC_DCC_ABORTED);
//irc_dcc_redraw (1);
}
}
/* unknown DCC action */
else
{
@@ -3589,7 +3582,7 @@ irc_command_init ()
"given, away status is removed)"),
"-all", &irc_command_away, NULL);
weechat_hook_command ("ban",
N_("bans nicks or hosts"),
N_("ban nicks or hosts"),
N_("[channel] [nickname [nickname ...]]"),
N_(" channel: channel for ban\n"
"nickname: user or host to ban"),
@@ -3627,28 +3620,27 @@ irc_command_init ()
"users)"),
"%(irc_msg_part)", &irc_command_cycle, NULL);
weechat_hook_command ("dcc",
N_("starts DCC (file or chat) or close chat"),
N_("start DCC (file or chat)"),
N_("action [nickname [file]]"),
N_(" action: 'send' (file) or 'chat' or 'close' "
"(chat)\n"
N_(" action: 'send' (file) or 'chat'\n"
"nickname: nickname to send file or chat\n"
" file: filename (on local host)"),
"chat|send|close %n %f",
"chat|send %n %f",
&irc_command_dcc, NULL);
weechat_hook_command ("dehalfop",
N_("removes half channel operator status from "
N_("remove half channel operator status from "
"nickname(s)"),
N_("[nickname [nickname]]"),
"",
NULL, &irc_command_dehalfop, NULL);
weechat_hook_command ("deop",
N_("removes channel operator status from "
N_("remove channel operator status from "
"nickname(s)"),
N_("[nickname [nickname]]"),
"",
NULL, &irc_command_deop, NULL);
weechat_hook_command ("devoice",
N_("removes voice from nickname(s)"),
N_("remove voice from nickname(s)"),
N_("[nickname [nickname]]"),
"",
NULL, &irc_command_devoice, NULL);
@@ -3664,7 +3656,7 @@ irc_command_init ()
"servername: server name to disconnect"),
"%(irc_servers)|-all", &irc_command_disconnect, NULL);
weechat_hook_command ("halfop",
N_("gives half channel operator status to "
N_("give half channel operator status to "
"nickname(s)"),
N_("[nickname [nickname]]"),
"",
@@ -3798,7 +3790,7 @@ irc_command_init ()
" text: text to send"),
"%n %-", &irc_command_notice, NULL);
weechat_hook_command ("op",
N_("gives channel operator status to nickname(s)"),
N_("give channel operator status to nickname(s)"),
N_("nickname [nickname]"),
"",
NULL, &irc_command_op, NULL);
@@ -3961,7 +3953,7 @@ irc_command_init ()
N_("target: server"),
NULL, &irc_command_trace, NULL);
weechat_hook_command ("unban",
N_("unbans nicks or hosts"),
N_("unban nicks or hosts"),
N_("[channel] nickname [nickname ...]"),
N_(" channel: channel for unban\n"
"nickname: user or host to unban"),
@@ -3977,14 +3969,14 @@ irc_command_init ()
N_("target: server"),
NULL, &irc_command_users, NULL);
weechat_hook_command ("version",
N_("gives the version info of nick or server "
N_("give the version info of nick or server "
"(current or specified)"),
N_("[server | nickname]"),
N_(" server: server name\n"
"nickname: nickname"),
"%n", &irc_command_version, NULL);
weechat_hook_command ("voice",
N_("gives voice to nickname(s)"),
N_("give voice to nickname(s)"),
N_("[nickname [nickname]]"),
"",
NULL, &irc_command_voice, NULL);
+1 -174
View File
@@ -45,41 +45,7 @@ struct t_irc_dcc *irc_dcc_list = NULL; /* DCC files & chat list */
struct t_irc_dcc *irc_last_dcc = NULL; /* last DCC in list */
/*
* irc_dcc_channel_for_chat: create channel for DCC chat
*/
/*
void
irc_dcc_channel_for_chat (struct t_irc_dcc *dcc)
{
if (!irc_channel_create_dcc (dcc))
{
gui_chat_printf_error (dcc->server->buffer,
_("%s can't associate DCC chat with private "
"buffer (maybe private buffer has already "
"DCC CHAT?)\n"),
WEECHAT_ERROR);
irc_dcc_close (dcc, IRC_DCC_FAILED);
irc_dcc_redraw (WEECHAT_HOTLIST_MESSAGE);
return;
}
gui_chat_printf_type (dcc->channel->buffer, GUI_MSG_TYPE_MSG,
cfg_look_prefix_info, cfg_col_chat_prefix_info,
_("Connected to %s%s %s(%s%d.%d.%d.%d%s)%s via DCC "
"chat\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),
GUI_COLOR(GUI_COLOR_CHAT));
}
*/
/*
* irc_dcc_chat_remove_channel: remove a buffer for DCC chat
*/
@@ -167,142 +133,3 @@ irc_dcc_start_resume (struct t_irc_server *server, char *filename, int port,
WEECHAT_ERROR, filename, port, pos_start);
}
*/
/*
* irc_dcc_handle: receive/send data for all active DCC
*/
/*
void
irc_dcc_handle ()
{
struct t_irc_dcc *dcc;
fd_set read_fd;
static struct timeval timeout;
int sock;
struct sockaddr_in addr;
socklen_t length;
for (dcc = irc_dcc_list; dcc; dcc = dcc->next_dcc)
{
// check DCC timeout
if (IRC_DCC_IS_FILE(dcc->type) && !IRC_DCC_ENDED(dcc->status))
{
if ((irc_cfg_dcc_timeout != 0)
&& (time (NULL) > dcc->last_activity + irc_cfg_dcc_timeout))
{
gui_chat_printf_error (dcc->server->buffer,
_("%s DCC: timeout\n"),
WEECHAT_ERROR);
irc_dcc_close (dcc, IRC_DCC_FAILED);
irc_dcc_redraw (WEECHAT_HOTLIST_MESSAGE);
continue;
}
}
if (dcc->status == IRC_DCC_CONNECTING)
{
if (dcc->type == IRC_DCC_FILE_SEND)
{
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)
{
if (FD_ISSET (dcc->sock, &read_fd))
{
dcc->last_activity = time (NULL);
length = sizeof (addr);
sock = accept (dcc->sock,
(struct sockaddr *) &addr, &length);
close (dcc->sock);
dcc->sock = -1;
if (sock < 0)
{
gui_chat_printf_error (dcc->server->buffer,
_("%s DCC: unable to "
"create socket for "
"sending file\n"),
WEECHAT_ERROR);
irc_dcc_close (dcc, IRC_DCC_FAILED);
irc_dcc_redraw (WEECHAT_HOTLIST_MESSAGE);
continue;
}
dcc->sock = sock;
if (fcntl (dcc->sock, F_SETFL, O_NONBLOCK) == -1)
{
gui_chat_printf_error (dcc->server->buffer,
_("%s DCC: unable to set "
"'nonblock' option for "
"socket\n"),
WEECHAT_ERROR);
irc_dcc_close (dcc, IRC_DCC_FAILED);
irc_dcc_redraw (WEECHAT_HOTLIST_MESSAGE);
continue;
}
dcc->addr = ntohl (addr.sin_addr.s_addr);
dcc->status = IRC_DCC_ACTIVE;
dcc->start_transfer = time (NULL);
irc_dcc_redraw (WEECHAT_HOTLIST_MESSAGE);
irc_dcc_file_send_fork (dcc);
}
}
}
if (dcc->type == IRC_DCC_FILE_RECV)
{
if (dcc->child_read != -1)
irc_dcc_file_child_read (dcc);
}
}
if (dcc->status == IRC_DCC_WAITING)
{
if (dcc->type == IRC_DCC_CHAT_SEND)
{
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)
{
if (FD_ISSET (dcc->sock, &read_fd))
{
length = sizeof (addr);
sock = accept (dcc->sock, (struct sockaddr *) &addr, &length);
close (dcc->sock);
dcc->sock = -1;
if (sock < 0)
{
irc_dcc_close (dcc, IRC_DCC_FAILED);
irc_dcc_redraw (WEECHAT_HOTLIST_MESSAGE);
continue;
}
dcc->sock = sock;
if (fcntl (dcc->sock, F_SETFL, O_NONBLOCK) == -1)
{
irc_dcc_close (dcc, IRC_DCC_FAILED);
irc_dcc_redraw (WEECHAT_HOTLIST_MESSAGE);
continue;
}
dcc->addr = ntohl (addr.sin_addr.s_addr);
dcc->status = IRC_DCC_ACTIVE;
irc_dcc_redraw (WEECHAT_HOTLIST_MESSAGE);
irc_dcc_channel_for_chat (dcc);
}
}
}
}
if (dcc->status == IRC_DCC_ACTIVE)
{
if (IRC_DCC_IS_CHAT(dcc->type))
irc_dcc_chat_recv (dcc);
else
irc_dcc_file_child_read (dcc);
}
}
}
*/
+68 -29
View File
@@ -1331,6 +1331,9 @@ irc_protocol_cmd_privmsg (struct t_irc_server *server, char *command,
{
char *nick, *host, *pos_args, *pos_end_01, *pos, *pos_message;
char *dcc_args, *pos_file, *pos_addr, *pos_port, *pos_size, *pos_start_resume; /* for DCC */
struct t_plugin_infolist *infolist;
struct t_plugin_infolist_item *item;
char plugin_id[128];
struct t_irc_channel *ptr_channel;
struct t_irc_nick *ptr_nick;
int highlight_displayed, look_infobar_delay_highlight;
@@ -1644,11 +1647,9 @@ irc_protocol_cmd_privmsg (struct t_irc_server *server, char *command,
"privmsg");
return WEECHAT_RC_ERROR;
}
pos_end_01[0] = '\0';
dcc_args = strdup (pos_args + 9);
pos_end_01[0] = '\01';
dcc_args = weechat_strndup (pos_args + 9, pos_end_01 - pos_args - 9);
if (!dcc_args)
{
weechat_printf (server->buffer,
@@ -1722,7 +1723,33 @@ irc_protocol_cmd_privmsg (struct t_irc_server *server, char *command,
pos--;
}
pos[1] = '\0';
/* add DCC file via xfer plugin */
infolist = weechat_infolist_new ();
if (infolist)
{
item = weechat_infolist_new_item (infolist);
if (item)
{
weechat_infolist_new_var_string (item, "plugin_name", weechat_plugin->name);
snprintf (plugin_id, sizeof (plugin_id),
"%x", (unsigned int)server);
weechat_infolist_new_var_string (item, "plugin_id", plugin_id);
weechat_infolist_new_var_string (item, "type", "file_recv");
weechat_infolist_new_var_string (item, "protocol", "dcc");
weechat_infolist_new_var_string (item, "remote_nick", nick);
weechat_infolist_new_var_string (item, "local_nick", server->nick);
weechat_infolist_new_var_string (item, "filename", pos_file);
weechat_infolist_new_var_string (item, "size", pos_size);
weechat_infolist_new_var_string (item, "address", pos_addr);
weechat_infolist_new_var_integer (item, "port", atoi (pos_port));
weechat_hook_signal_send ("xfer_add",
WEECHAT_HOOK_SIGNAL_POINTER,
infolist);
}
weechat_infolist_free (infolist);
}
/* TODO: add DCC file */
//irc_dcc_add (server, IRC_DCC_FILE_RECV,
// strtoul (pos_addr, NULL, 10),
@@ -1751,11 +1778,9 @@ irc_protocol_cmd_privmsg (struct t_irc_server *server, char *command,
"privmsg");
return WEECHAT_RC_ERROR;
}
pos_end_01[0] = '\0';
dcc_args = strdup (pos_args + 11);
pos_end_01[0] = '\01';
dcc_args = weechat_strndup (pos_args + 11, pos_end_01 - pos_args - 11);
if (!dcc_args)
{
weechat_printf (server->buffer,
@@ -1825,7 +1850,7 @@ irc_protocol_cmd_privmsg (struct t_irc_server *server, char *command,
}
/* incoming DCC ACCEPT (resume accepted by sender) */
if (strncmp (pos, "\01DCC ACCEPT", 11) == 0)
if (strncmp (pos_args, "\01DCC ACCEPT", 11) == 0)
{
/* check if DCC ACCEPT is ok, i.e. with 0x01 at end */
pos_end_01 = strchr (pos_args + 1, '\01');
@@ -1837,11 +1862,9 @@ irc_protocol_cmd_privmsg (struct t_irc_server *server, char *command,
"privmsg");
return WEECHAT_RC_ERROR;
}
pos_end_01[0] = '\0';
dcc_args = strdup (pos_args + 11);
pos_end_01[0] = '\01';
dcc_args = weechat_strndup (pos_args + 11, pos_end_01 - pos_args - 11);
if (!dcc_args)
{
weechat_printf (server->buffer,
@@ -1911,7 +1934,7 @@ irc_protocol_cmd_privmsg (struct t_irc_server *server, char *command,
}
/* incoming DCC CHAT */
if (strncmp (pos, "\01DCC CHAT", 9) == 0)
if (strncmp (pos_args, "\01DCC CHAT", 9) == 0)
{
/* check if DCC CHAT is ok, i.e. with 0x01 at end */
pos_end_01 = strchr (pos_args + 1, '\01');
@@ -1924,10 +1947,8 @@ irc_protocol_cmd_privmsg (struct t_irc_server *server, char *command,
return WEECHAT_RC_ERROR;
}
pos_end_01[0] = '\0';
dcc_args = strdup (pos_args + 9);
pos_end_01[0] = '\01';
dcc_args = weechat_strndup (pos_args + 9, pos_end_01 - pos_args - 9);
if (!dcc_args)
{
weechat_printf (server->buffer,
@@ -1944,7 +1965,7 @@ irc_protocol_cmd_privmsg (struct t_irc_server *server, char *command,
{
pos_file++;
}
/* DCC IP address */
pos_addr = strchr (pos_file, ' ');
if (!pos_addr)
@@ -1995,11 +2016,29 @@ irc_protocol_cmd_privmsg (struct t_irc_server *server, char *command,
return WEECHAT_RC_ERROR;
}
/* TODO: add DCC chat */
//irc_dcc_add (server, IRC_DCC_CHAT_RECV,
// strtoul (pos_addr, NULL, 10),
// atoi (pos_port), nick, -1, NULL, NULL, 0);
/* add DCC chat via xfer plugin */
infolist = weechat_infolist_new ();
if (infolist)
{
item = weechat_infolist_new_item (infolist);
if (item)
{
weechat_infolist_new_var_string (item, "plugin_name", weechat_plugin->name);
snprintf (plugin_id, sizeof (plugin_id),
"%x", (unsigned int)server);
weechat_infolist_new_var_string (item, "plugin_id", plugin_id);
weechat_infolist_new_var_string (item, "type", "chat_recv");
weechat_infolist_new_var_string (item, "remote_nick", nick);
weechat_infolist_new_var_string (item, "local_nick", server->nick);
weechat_infolist_new_var_string (item, "address", pos_addr);
weechat_infolist_new_var_integer (item, "port", atoi (pos_port));
weechat_hook_signal_send ("xfer_add",
WEECHAT_HOOK_SIGNAL_POINTER,
infolist);
}
weechat_infolist_free (infolist);
}
weechat_hook_signal_send ("irc_dcc",
WEECHAT_HOOK_SIGNAL_STRING,
argv_eol[0]);
@@ -2012,7 +2051,7 @@ irc_protocol_cmd_privmsg (struct t_irc_server *server, char *command,
/* private message received => display it */
ptr_channel = irc_channel_search (server, nick);
if (strncmp (pos, "\01ACTION ", 8) == 0)
if (strncmp (pos_args, "\01ACTION ", 8) == 0)
{
if (!ptr_channel)
{
+36 -33
View File
@@ -2803,8 +2803,9 @@ irc_server_xfer_send_ready_cb (void *data, char *signal, char *type_data,
{
struct t_plugin_infolist *infolist;
struct t_irc_server *server, *ptr_server;
char *plugin_id, *type;
char *plugin_name, *plugin_id, *type, *filename;
int spaces_in_name;
/* make C compiler happy */
(void) data;
(void) signal;
@@ -2814,42 +2815,44 @@ irc_server_xfer_send_ready_cb (void *data, char *signal, char *type_data,
if (weechat_infolist_next (infolist))
{
plugin_name = weechat_infolist_string (infolist, "plugin_name");
plugin_id = weechat_infolist_string (infolist, "plugin_id");
if (plugin_id)
if (plugin_name && (strcmp (plugin_name, "irc") == 0) && plugin_id)
{
if (strncmp (plugin_id, "irc_", 4) == 0)
sscanf (plugin_id, "%x", (unsigned int *)&server);
for (ptr_server = irc_servers; ptr_server;
ptr_server = ptr_server->next_server)
{
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 (ptr_server == server)
break;
}
if (ptr_server)
{
type = weechat_infolist_string (infolist, "type");
if (type)
if (strcmp (type, "file_send") == 0)
{
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"));
}
filename = weechat_infolist_string (infolist, "filename");
spaces_in_name = (strchr (filename, ' ') != NULL);
irc_server_sendf (server,
"PRIVMSG %s :\01DCC SEND %s%s%s "
"%s %d %s\01",
weechat_infolist_string (infolist, "remote_nick"),
(spaces_in_name) ? "\"" : "",
filename,
(spaces_in_name) ? "\"" : "",
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, "remote_nick"),
weechat_infolist_string (infolist, "address"),
weechat_infolist_integer (infolist, "port"));
}
}
}
+4 -2
View File
@@ -111,7 +111,8 @@ plugin_infolist_new_var_integer (struct t_plugin_infolist_item *item,
new_var->name = strdup (name);
new_var->type = PLUGIN_INFOLIST_INTEGER;
new_var->value = malloc (sizeof (int));
*((int *)new_var->value) = value;
if (new_var->value)
*((int *)new_var->value) = value;
new_var->prev_var = item->last_var;
new_var->next_var = NULL;
@@ -208,7 +209,8 @@ plugin_infolist_new_var_time (struct t_plugin_infolist_item *item,
new_var->name = strdup (name);
new_var->type = PLUGIN_INFOLIST_TIME;
new_var->value = malloc (sizeof (time_t));
*((time_t *)new_var->value) = time;
if (new_var->value)
*((time_t *)new_var->value) = time;
new_var->prev_var = item->last_var;
new_var->next_var = NULL;
+1
View File
@@ -372,6 +372,7 @@ plugin_load (char *filename)
new_plugin->buffer_new = &gui_buffer_new;
new_plugin->buffer_search = &gui_buffer_search_by_category_name;
new_plugin->buffer_clear = &gui_buffer_clear;
new_plugin->buffer_close = &gui_buffer_close;
new_plugin->buffer_get_string = &gui_buffer_get_string;
new_plugin->buffer_get_pointer = &gui_buffer_get_pointer;
+37
View File
@@ -3290,6 +3290,42 @@ weechat_lua_api_buffer_search (lua_State *L)
LUA_RETURN_STRING_FREE(result);
}
/*
* weechat_lua_api_buffer_clear: clear a buffer
*/
static int
weechat_lua_api_buffer_clear (lua_State *L)
{
const char *buffer;
int n;
/* make C compiler happy */
(void) L;
if (!lua_current_script)
{
WEECHAT_SCRIPT_MSG_NOT_INITIALIZED("buffer_clear");
LUA_RETURN_ERROR;
}
buffer = NULL;
n = lua_gettop (lua_current_interpreter);
if (n < 1)
{
WEECHAT_SCRIPT_MSG_WRONG_ARGUMENTS("buffer_clear");
LUA_RETURN_ERROR;
}
buffer = lua_tostring (lua_current_interpreter, -1);
weechat_buffer_clear (script_str2ptr ((char *)buffer));
LUA_RETURN_OK;
}
/*
* weechat_lua_api_buffer_close: close a buffer
*/
@@ -4794,6 +4830,7 @@ const struct luaL_reg weechat_lua_api_funcs[] = {
{ "unhook_all", &weechat_lua_api_unhook_all },
{ "buffer_new", &weechat_lua_api_buffer_new },
{ "buffer_search", &weechat_lua_api_buffer_search },
{ "buffer_clear", &weechat_lua_api_buffer_clear },
{ "buffer_close", &weechat_lua_api_buffer_close },
{ "buffer_get_string", &weechat_lua_api_buffer_get_string },
{ "buffer_get_pointer", &weechat_lua_api_buffer_get_pointer },
@@ -2750,6 +2750,34 @@ static XS (XS_weechat_buffer_search)
PERL_RETURN_STRING_FREE(result);
}
/*
* weechat::buffer_clear: clear a buffer
*/
static XS (XS_weechat_buffer_clear)
{
dXSARGS;
/* make C compiler happy */
(void) cv;
if (!perl_current_script)
{
WEECHAT_SCRIPT_MSG_NOT_INITIALIZED("buffer_clear");
PERL_RETURN_ERROR;
}
if (items < 1)
{
WEECHAT_SCRIPT_MSG_WRONG_ARGUMENTS("buffer_clear");
PERL_RETURN_ERROR;
}
weechat_buffer_clear (script_str2ptr (SvPV (ST (0), PL_na))); /* buffer */
PERL_RETURN_OK;
}
/*
* weechat::buffer_close: close a buffer
*/
@@ -3867,6 +3895,7 @@ weechat_perl_api_init (pTHX)
newXS ("weechat::unhook_all", XS_weechat_unhook_all, "weechat");
newXS ("weechat::buffer_new", XS_weechat_buffer_new, "weechat");
newXS ("weechat::buffer_search", XS_weechat_buffer_search, "weechat");
newXS ("weechat::buffer_clear", XS_weechat_buffer_clear, "weechat");
newXS ("weechat::buffer_close", XS_weechat_buffer_close, "weechat");
newXS ("weechat::buffer_get_string", XS_weechat_buffer_get_string, "weechat");
newXS ("weechat::buffer_get_pointer", XS_weechat_buffer_get_pointer, "weechat");
@@ -2918,6 +2918,37 @@ weechat_python_api_buffer_search (PyObject *self, PyObject *args)
PYTHON_RETURN_STRING_FREE(result);
}
/*
* weechat_python_api_buffer_clear: clear a buffer
*/
static PyObject *
weechat_python_api_buffer_clear (PyObject *self, PyObject *args)
{
char *buffer;
/* make C compiler happy */
(void) self;
if (!python_current_script)
{
WEECHAT_SCRIPT_MSG_NOT_INITIALIZED("buffer_clear");
PYTHON_RETURN_ERROR;
}
buffer = NULL;
if (!PyArg_ParseTuple (args, "s", &buffer))
{
WEECHAT_SCRIPT_MSG_WRONG_ARGUMENTS("buffer_clear");
PYTHON_RETURN_ERROR;
}
weechat_buffer_clear (script_str2ptr (buffer));
PYTHON_RETURN_OK;
}
/*
* weechat_python_api_buffer_close: close a buffer
*/
@@ -4110,6 +4141,7 @@ PyMethodDef weechat_python_funcs[] =
{ "unhook_all", &weechat_python_api_unhook_all, METH_VARARGS, "" },
{ "buffer_new", &weechat_python_api_buffer_new, METH_VARARGS, "" },
{ "buffer_search", &weechat_python_api_buffer_search, METH_VARARGS, "" },
{ "buffer_clear", &weechat_python_api_buffer_clear, METH_VARARGS, "" },
{ "buffer_close", &weechat_python_api_buffer_close, METH_VARARGS, "" },
{ "buffer_get_string", &weechat_python_api_buffer_get_string, METH_VARARGS, "" },
{ "buffer_get_pointer", &weechat_python_api_buffer_get_pointer, METH_VARARGS, "" },
@@ -3348,6 +3348,41 @@ weechat_ruby_api_buffer_search (VALUE class, VALUE category, VALUE name)
RUBY_RETURN_STRING_FREE(result);
}
/*
* weechat_ruby_api_buffer_clear: clear a buffer
*/
static VALUE
weechat_ruby_api_buffer_clear (VALUE class, VALUE buffer)
{
char *c_buffer;
/* make C compiler happy */
(void) class;
if (!ruby_current_script)
{
WEECHAT_SCRIPT_MSG_NOT_INITIALIZED("buffer_clear");
RUBY_RETURN_ERROR;
}
c_buffer = NULL;
if (NIL_P (buffer))
{
WEECHAT_SCRIPT_MSG_WRONG_ARGUMENTS("buffer_clear");
RUBY_RETURN_ERROR;
}
Check_Type (buffer, T_STRING);
c_buffer = STR2CSTR (buffer);
weechat_buffer_clear (script_str2ptr (c_buffer));
RUBY_RETURN_OK;
}
/*
* weechat_ruby_api_buffer_close: close a buffer
*/
@@ -4714,6 +4749,7 @@ weechat_ruby_api_init (VALUE ruby_mWeechat)
rb_define_module_function (ruby_mWeechat, "unhook_all", &weechat_ruby_api_unhook_all, 0);
rb_define_module_function (ruby_mWeechat, "buffer_new", &weechat_ruby_api_buffer_new, 4);
rb_define_module_function (ruby_mWeechat, "buffer_search", &weechat_ruby_api_buffer_search, 2);
rb_define_module_function (ruby_mWeechat, "buffer_clear", &weechat_ruby_api_buffer_clear, 1);
rb_define_module_function (ruby_mWeechat, "buffer_close", &weechat_ruby_api_buffer_close, 1);
rb_define_module_function (ruby_mWeechat, "buffer_get_string", &weechat_ruby_api_buffer_get_string, 2);
rb_define_module_function (ruby_mWeechat, "buffer_get_pointer", &weechat_ruby_api_buffer_get_pointer, 2);
+3
View File
@@ -335,6 +335,7 @@ struct t_weechat_plugin
struct t_gui_buffer *buffer),
void *close_callback_data);
struct t_gui_buffer *(*buffer_search) (char *category, char *name);
void (*buffer_clear) (struct t_gui_buffer *buffer);
void (*buffer_close) (struct t_gui_buffer *buffer, int switch_to_another);
char *(*buffer_get_string) (struct t_gui_buffer *buffer, char *property);
void *(*buffer_get_pointer) (struct t_gui_buffer *buffer, char *property);
@@ -749,6 +750,8 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin);
weechat_plugin->buffer_search(__category, __name)
#define weechat_current_buffer \
weechat_plugin->buffer_search(NULL, NULL)
#define weechat_buffer_clear(__buffer) \
weechat_plugin->buffer_clear(__buffer)
#define weechat_buffer_close(__buffer, __switch_to_another) \
weechat_plugin->buffer_close(__buffer, __switch_to_another)
#define weechat_buffer_get_string(__buffer, __property) \
+1
View File
@@ -18,6 +18,7 @@ ADD_LIBRARY(xfer MODULE
xfer.c xfer.h
xfer-buffer.c xfer-buffer.h
xfer-chat.c xfer-chat.h
xfer-command.c xfer-command.h
xfer-config.c xfer-config.h
xfer-dcc.c xfer-dcc.h
xfer-file.c xfer-file.h
+2
View File
@@ -26,6 +26,8 @@ xfer_la_SOURCES = xfer.c \
xfer-buffer.h \
xfer-chat.c \
xfer-chat.h \
xfer-command.c \
xfer-command.h \
xfer-config.c \
xfer-config.h \
xfer-dcc.c \
+252 -50
View File
@@ -21,17 +21,262 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "../weechat-plugin.h"
#include "xfer.h"
#include "xfer-buffer.h"
#include "xfer-config.h"
#include "xfer-network.h"
struct t_gui_buffer *xfer_buffer = NULL;
int xfer_buffer_selected_line = 0;
/*
* xfer_buffer_refresh: update a xfer in buffer and update hotlist for xfer buffer
*/
void
xfer_buffer_refresh (char *hotlist)
{
struct t_xfer *ptr_xfer;
char str_color[256], status[64], date[128], *progress_bar, format[128];
char format_per_sec[128], bytes_per_sec[256], eta[128];
int i, length, line, progress_bar_size, num_bars, num_unit;
int num_unit_per_sec;
unsigned long pct_complete;
char *unit_name[] = { N_("bytes"), N_("KB"), N_("MB"), N_("GB") };
char *unit_format[] = { "%.0f", "%.1f", "%.02f", "%.02f" };
float unit_divide[] = { 1, 1024, 1024*1024, 1024*1024*1024 };
struct tm *date_tmp;
if (xfer_buffer)
{
weechat_buffer_clear (xfer_buffer);
line = 0;
for (ptr_xfer = xfer_list; ptr_xfer; ptr_xfer = ptr_xfer->next_xfer)
{
snprintf (str_color, sizeof (str_color),
"%s,%s",
weechat_config_string (xfer_config_color_text),
weechat_config_string (xfer_config_color_text_bg));
/* display first line with remote nick and filename */
weechat_printf_y (xfer_buffer, line * 2,
"%s%s%-25s %s%s%s",
weechat_color(str_color),
(line == xfer_buffer_selected_line) ?
"*** " : " ",
ptr_xfer->remote_nick,
(XFER_IS_FILE(ptr_xfer->type)) ? "\"" : "",
(XFER_IS_FILE(ptr_xfer->type)) ?
ptr_xfer->filename : _("xfer chat"),
(XFER_IS_FILE(ptr_xfer->type)) ? "\"" : "");
snprintf (status, sizeof (status),
"%s", _(xfer_status_string[ptr_xfer->status]));
length = strlen (status);
if (length < 20)
{
for (i = 0; i < 20 - length; i++)
{
strcat (status, " ");
}
}
if (XFER_IS_CHAT(ptr_xfer->type))
{
/* display second line for chat with status and date */
date_tmp = localtime (&(ptr_xfer->start_time));
strftime (date, sizeof (date),
"%a, %d %b %Y %H:%M:%S", date_tmp);
weechat_printf_y (xfer_buffer, (line * 2) + 1,
"%s%s%s %s%s %s%s%s",
weechat_color(str_color),
(line == xfer_buffer_selected_line) ?
"*** " : " ",
(XFER_IS_SEND(ptr_xfer->type)) ?
"<<--" : "-->>",
weechat_color(weechat_config_string (xfer_config_color_status[ptr_xfer->status])),
status,
weechat_color ("reset"),
weechat_color (str_color),
date);
}
else
{
/* build progress bar */
progress_bar = NULL;
progress_bar_size = weechat_config_integer (xfer_config_look_progress_bar_size);
if (progress_bar_size > 0)
{
progress_bar = malloc (1 + progress_bar_size + 1 + 1);
strcpy (progress_bar, "[");
if (ptr_xfer->size == 0)
{
if (ptr_xfer->status == XFER_STATUS_DONE)
num_bars = progress_bar_size;
else
num_bars = 0;
}
else
num_bars = (int)(((float)(ptr_xfer->pos)/(float)(ptr_xfer->size)) * (float)progress_bar_size);
for (i = 0; i < num_bars - 1; i++)
{
strcat (progress_bar, "=");
}
if (num_bars > 0)
strcat (progress_bar, ">");
for (i = 0; i < progress_bar_size - num_bars; i++)
{
strcat (progress_bar, " ");
}
strcat (progress_bar, "]");
}
/* computes pourcentage */
if (ptr_xfer->size < 1024*10)
num_unit = 0;
else if (ptr_xfer->size < 1024*1024)
num_unit = 1;
else if (ptr_xfer->size < 1024*1024*1024)
num_unit = 2;
else
num_unit = 3;
if (ptr_xfer->size == 0)
{
if (ptr_xfer->status == XFER_STATUS_DONE)
pct_complete = 100;
else
pct_complete = 0;
}
else
pct_complete = (unsigned long)(((float)(ptr_xfer->pos)/(float)(ptr_xfer->size)) * 100);
snprintf (format, sizeof (format),
"%%s%%s%%s %%s%%s%%s%%s %%3lu%%%% %s %%s / %s %%s (%%s%%s)",
unit_format[num_unit],
unit_format[num_unit]);
/* bytes per second */
bytes_per_sec[0] = '\0';
if (ptr_xfer->bytes_per_sec < 1024*10)
num_unit_per_sec = 0;
else if (ptr_xfer->bytes_per_sec < 1024*1024)
num_unit_per_sec = 1;
else if (ptr_xfer->bytes_per_sec < 1024*1024*1024)
num_unit_per_sec = 2;
else
num_unit_per_sec = 3;
snprintf (format_per_sec, sizeof (format_per_sec),
"%s %%s/s",
unit_format[num_unit_per_sec]);
snprintf (bytes_per_sec, sizeof (bytes_per_sec),
format_per_sec,
((float)ptr_xfer->bytes_per_sec) / ((float)(unit_divide[num_unit_per_sec])),
_(unit_name[num_unit_per_sec]));
/* ETA */
eta[0] = '\0';
if (ptr_xfer->status == XFER_STATUS_ACTIVE)
{
snprintf (eta, sizeof (eta),
"%s: %.2lu:%.2lu:%.2lu - ",
_("ETA"),
ptr_xfer->eta / 3600,
(ptr_xfer->eta / 60) % 60,
ptr_xfer->eta % 60);
}
/* display second line for file with status, progress bar and estimated time */
weechat_printf_y (xfer_buffer, (line * 2) + 1,
format,
weechat_color(str_color),
(line == xfer_buffer_selected_line) ?
"*** " : " ",
(XFER_IS_SEND(ptr_xfer->type)) ?
"<<--" : "-->>",
weechat_color(weechat_config_string (xfer_config_color_status[ptr_xfer->status])),
status,
weechat_color (str_color),
(progress_bar) ? progress_bar : "",
pct_complete,
((float)(ptr_xfer->pos)) / unit_divide[num_unit],
_(unit_name[num_unit]),
((float)(ptr_xfer->size)) / unit_divide[num_unit],
_(unit_name[num_unit]),
eta,
bytes_per_sec);
}
line++;
}
weechat_buffer_set (xfer_buffer, "hotlist", hotlist);
}
}
/*
* xfer_buffer_input_cb: callback called when user send data to xfer list
* buffer
*/
int
xfer_buffer_input_cb (void *data, struct t_gui_buffer *buffer,
char *input_data)
{
struct t_xfer *xfer, *ptr_xfer, *next_xfer;
/* make C compiler happy */
(void) data;
(void) buffer;
xfer = xfer_search_by_number (xfer_buffer_selected_line);
/* accept xfer */
if (weechat_strcasecmp (input_data, "a") == 0)
{
if (xfer && XFER_IS_RECV(xfer->type)
&& (xfer->status == XFER_STATUS_WAITING))
{
xfer_network_accept (xfer);
}
}
/* cancel xfer */
else if (weechat_strcasecmp (input_data, "c") == 0)
{
if (xfer && !XFER_HAS_ENDED(xfer->status))
{
xfer_close (xfer, XFER_STATUS_ABORTED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
}
/* purge old xfer */
else if (weechat_strcasecmp (input_data, "p") == 0)
{
ptr_xfer = xfer_list;
while (ptr_xfer)
{
next_xfer = ptr_xfer->next_xfer;
if (XFER_HAS_ENDED(ptr_xfer->status))
xfer_free (ptr_xfer);
ptr_xfer = next_xfer;
}
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
/* remove xfer */
else if (weechat_strcasecmp (input_data, "r") == 0)
{
if (xfer && XFER_HAS_ENDED(xfer->status))
{
xfer_free (xfer);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
}
return WEECHAT_RC_OK;
}
/*
* xfer_buffer_close_cb: callback called when xfer buffer is closed
*/
@@ -57,61 +302,18 @@ xfer_buffer_open ()
{
if (!xfer_buffer)
{
xfer_buffer = weechat_buffer_new ("xfer", "xfer",
NULL, NULL,
xfer_buffer = weechat_buffer_new ("xfer", "list",
&xfer_buffer_input_cb, NULL,
&xfer_buffer_close_cb, NULL);
/* failed to create buffer ? then exit */
if (!xfer_buffer)
return;
weechat_buffer_set (xfer_buffer, "type", "free");
weechat_buffer_set (xfer_buffer, "title", _("Xfer list"));
}
}
/*
* xfer_buffer_refresh: update a xfer in buffer and update hotlist for xfer buffer
*/
void
xfer_buffer_refresh (char *hotlist)
{
struct t_xfer *ptr_xfer;
char str_color[256];
int line;
if (xfer_buffer)
{
line = 0;
for (ptr_xfer = xfer_list; ptr_xfer; ptr_xfer = ptr_xfer->next_xfer)
{
if (XFER_IS_FILE(ptr_xfer->type))
{
snprintf (str_color, sizeof (str_color),
"%s,%s",
weechat_config_string (xfer_config_color_text),
weechat_config_string (xfer_config_color_text_bg));
weechat_printf_y (xfer_buffer, line * 2,
"%s%s%-20s \"%s\"",
weechat_color(str_color),
(line == xfer_buffer_selected_line) ?
"*** " : " ",
ptr_xfer->nick, ptr_xfer->filename);
weechat_printf_y (xfer_buffer, (line * 2) + 1,
"%s%s%s %s%-15s ",
weechat_color(str_color),
(line == xfer_buffer_selected_line) ?
"*** " : " ",
(XFER_IS_SEND(ptr_xfer->type)) ?
"<<--" : "-->>",
weechat_color(
weechat_config_string (
xfer_config_color_status[ptr_xfer->status])),
_(xfer_status_string[ptr_xfer->status]));
}
line++;
}
weechat_buffer_set (xfer_buffer, "hotlist", hotlist);
weechat_buffer_set (xfer_buffer, "key_bind_meta2-A", "/xfer up");
weechat_buffer_set (xfer_buffer, "key_bind_meta2-B", "/xfer down");
weechat_buffer_set (xfer_buffer, "display", "1");
}
}
+3 -2
View File
@@ -21,8 +21,9 @@
#define __WEECHAT_XFER_DISPLAY_H 1
extern struct t_gui_buffer *xfer_buffer;
extern int xfer_buffer_selected_line;
extern void xfer_buffer_open ();
extern void xfer_buffer_refresh (char *hotlist);
extern void xfer_buffer_open ();
#endif /* xfer.h */
#endif /* xfer-buffer.h */
+97 -19
View File
@@ -74,37 +74,25 @@ xfer_chat_sendf (struct t_xfer *xfer, char *format, ...)
{
weechat_printf (NULL,
_("%s%s: error sending data to \"%s\" via xfer chat"),
weechat_prefix ("error"), "xfer", xfer->nick);
weechat_prefix ("error"), "xfer", xfer->remote_nick);
xfer_close (xfer, XFER_STATUS_FAILED);
}
}
/*
* xfer_chat_recv: receive data from xfer chat remote host
* xfer_chat_recv_cb: receive data from xfer chat remote host
*/
void
xfer_chat_recv (struct t_xfer *xfer)
int
xfer_chat_recv_cb (void *arg_xfer)
{
fd_set read_fd;
static struct timeval timeout;
struct t_xfer *xfer;
static char buffer[4096 + 2];
char *buf2, *pos, *ptr_buf, *next_ptr_buf;
int num_read;
FD_ZERO (&read_fd);
FD_SET (xfer->sock, &read_fd);
timeout.tv_sec = 0;
timeout.tv_usec = 0;
xfer = (struct t_xfer *)arg_xfer;
/* something to read on socket? */
if (select (FD_SETSIZE, &read_fd, NULL, NULL, &timeout) <= 0)
return;
if (!FD_ISSET (xfer->sock, &read_fd))
return;
/* there's something to read on socket! */
num_read = recv (xfer->sock, buffer, sizeof (buffer) - 2, 0);
if (num_read > 0)
{
@@ -144,7 +132,7 @@ xfer_chat_recv (struct t_xfer *xfer)
if (ptr_buf)
{
weechat_printf (xfer->buffer, "%s\t%s", xfer->nick, ptr_buf);
weechat_printf (xfer->buffer, "%s\t%s", xfer->remote_nick, ptr_buf);
}
ptr_buf = next_ptr_buf;
@@ -158,4 +146,94 @@ xfer_chat_recv (struct t_xfer *xfer)
xfer_close (xfer, XFER_STATUS_ABORTED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
return WEECHAT_RC_OK;
}
/*
* xfer_chat_buffer_input_cb: callback called when user send data to xfer chat
* buffer
*/
int
xfer_chat_buffer_input_cb (void *data, struct t_gui_buffer *buffer,
char *input_data)
{
struct t_xfer *xfer;
xfer = (struct t_xfer *)data;
if (!XFER_HAS_ENDED(xfer->status))
{
xfer_chat_sendf (xfer, "%s\n", input_data);
if (!XFER_HAS_ENDED(xfer->status))
{
weechat_printf (buffer,
"%s\t%s",
xfer->local_nick,
input_data);
}
}
return WEECHAT_RC_OK;
}
/*
* xfer_chat_close_buffer_cb: callback called when a buffer with direct chat
* is closed
*/
int
xfer_chat_buffer_close_cb (void *data, struct t_gui_buffer *buffer)
{
struct t_xfer *xfer;
/* make C compiler happy */
(void) buffer;
xfer = (struct t_xfer *)data;
if (!XFER_HAS_ENDED(xfer->status))
{
xfer_close (xfer, XFER_STATUS_ABORTED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
xfer->buffer = NULL;
return WEECHAT_RC_OK;
}
/*
* xfer_chat_open_buffer: create channel for DCC chat
*/
void
xfer_chat_open_buffer (struct t_xfer *xfer)
{
char *name;
int length;
length = strlen (xfer->plugin_name) + 1 + strlen (xfer->remote_nick) + 1;
name = malloc (length);
if (name)
{
snprintf (name, length, "%s_%s", xfer->plugin_name, xfer->remote_nick);
xfer->buffer = weechat_buffer_new ("xfer", name,
&xfer_chat_buffer_input_cb, xfer,
&xfer_chat_buffer_close_cb, xfer);
if (xfer->buffer)
{
weechat_buffer_set (xfer->buffer, "title", _("xfer chat"));
weechat_printf (xfer->buffer,
_("Connected to %s (%d.%d.%d.%d) via "
"xfer chat"),
xfer->remote_nick,
xfer->address >> 24,
(xfer->address >> 16) & 0xff,
(xfer->address >> 8) & 0xff,
xfer->address & 0xff);
}
free (name);
}
}
+2
View File
@@ -20,5 +20,7 @@
#ifndef __WEECHAT_XFER_CHAT_H
#define __WEECHAT_XFER_CHAT_H 1
extern int xfer_chat_recv_cb (void *arg_xfer);
extern void xfer_chat_open_buffer (struct t_xfer *xfer);
#endif /* xfer-chat.h */
+83
View File
@@ -0,0 +1,83 @@
/*
* Copyright (c) 2003-2008 by FlashCode <flashcode@flashtux.org>
* See README for License detail, AUTHORS for developers list.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* xfer-command.c: xfer command */
#include <stdlib.h>
#include <string.h>
#include "../weechat-plugin.h"
#include "xfer.h"
#include "xfer-buffer.h"
/*
* xfer_command_xfer: command /xfer
*/
int
xfer_command_xfer (void *data, struct t_gui_buffer *buffer, int argc,
char **argv, char **argv_eol)
{
/* make C compiler happy */
(void) data;
(void) buffer;
(void) argc;
(void) argv;
(void) argv_eol;
if (!xfer_buffer)
xfer_buffer_open ();
if (argc > 1)
{
if (strcmp (argv[1], "up") == 0)
{
if (xfer_buffer_selected_line > 0)
{
xfer_buffer_selected_line--;
xfer_buffer_refresh (NULL);
}
}
else if (strcmp (argv[1], "down") == 0)
{
if (xfer_buffer_selected_line < xfer_count - 1)
{
xfer_buffer_selected_line++;
xfer_buffer_refresh (NULL);
}
}
}
return WEECHAT_RC_OK;
}
/*
* xfer_command: xfer command
*/
void
xfer_command_init ()
{
weechat_hook_command ("xfer",
N_("xfer control"),
"",
_("Open buffer with xfer list"),
NULL, &xfer_command_xfer, NULL);
}
+25
View File
@@ -0,0 +1,25 @@
/*
* Copyright (c) 2003-2008 by FlashCode <flashcode@flashtux.org>
* See README for License detail, AUTHORS for developers list.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __WEECHAT_XFER_COMMAND_H
#define __WEECHAT_XFER_COMMAND_H 1
extern void xfer_command_init ();
#endif /* xfer-command.h */
+7
View File
@@ -32,6 +32,7 @@ struct t_config_file *xfer_config_file = NULL;
/* xfer config, look section */
struct t_config_option *xfer_config_look_auto_open_buffer;
struct t_config_option *xfer_config_look_progress_bar_size;
/* xfer config, color section */
@@ -104,6 +105,12 @@ xfer_config_init ()
N_("auto open xfer buffer and switch to it when a new xfer is added "
"to list"),
NULL, 0, 0, "on", NULL, NULL, NULL, NULL, NULL, NULL);
xfer_config_look_progress_bar_size = weechat_config_new_option (
xfer_config_file, ptr_section,
"progress_bar_size", "integer",
N_("size of progress bar, in chars (if 0, progress bar is disabled)"),
NULL, 0, XFER_CONFIG_PROGRESS_BAR_MAX_SIZE, "20",
NULL, NULL, NULL, NULL, NULL, NULL);
ptr_section = weechat_config_new_section (xfer_config_file, "color",
0, 0,
+3
View File
@@ -22,9 +22,12 @@
#define XFER_CONFIG_NAME "xfer"
#define XFER_CONFIG_PROGRESS_BAR_MAX_SIZE 256
extern struct t_config_file *xfer_config;
extern struct t_config_option *xfer_config_look_auto_open_buffer;
extern struct t_config_option *xfer_config_look_progress_bar_size;
extern struct t_config_option *xfer_config_color_text;
extern struct t_config_option *xfer_config_color_text_bg;
-1
View File
@@ -31,7 +31,6 @@
#include "../weechat-plugin.h"
#include "xfer.h"
#include "xfer-dcc.h"
#include "xfer-network.h"
+2 -2
View File
@@ -101,7 +101,7 @@ xfer_file_find_filename (struct t_xfer *xfer)
}
xfer->local_filename = malloc (strlen (dir2) +
strlen (xfer->nick) +
strlen (xfer->remote_nick) +
strlen (xfer->filename) + 4);
if (!xfer->local_filename)
return;
@@ -111,7 +111,7 @@ xfer_file_find_filename (struct t_xfer *xfer)
if (dir_separator
&& (xfer->local_filename[strlen (xfer->local_filename) - 1] != dir_separator[0]))
strcat (xfer->local_filename, dir_separator);
strcat (xfer->local_filename, xfer->nick);
strcat (xfer->local_filename, xfer->remote_nick);
strcat (xfer->local_filename, ".");
strcat (xfer->local_filename, xfer->filename);
+263 -74
View File
@@ -28,58 +28,17 @@
#include <sys/socket.h>
#include <signal.h>
#include <time.h>
#include <netdb.h>
#include "../weechat-plugin.h"
#include "xfer.h"
#include "xfer-network.h"
#include "xfer-buffer.h"
#include "xfer-chat.h"
#include "xfer-config.h"
#include "xfer-dcc.h"
#include "xfer-file.h"
/*
* xfer_network_connect: connect to another host
*/
int
xfer_network_connect (struct t_xfer *xfer)
{
if (xfer->type == XFER_TYPE_CHAT_SEND)
xfer->status = XFER_STATUS_WAITING;
else
xfer->status = XFER_STATUS_CONNECTING;
if (xfer->sock < 0)
{
xfer->sock = socket (AF_INET, SOCK_STREAM, 0);
if (xfer->sock < 0)
return 0;
}
/* for chat or file sending, listen to socket for a connection */
if (XFER_IS_SEND(xfer->type))
{
if (fcntl (xfer->sock, F_SETFL, O_NONBLOCK) == -1)
return 0;
if (listen (xfer->sock, 1) == -1)
return 0;
if (fcntl (xfer->sock, F_SETFL, 0) == -1)
return 0;
}
/* for chat receiving, connect to listening host */
if (xfer->type == XFER_TYPE_CHAT_RECV)
{
if (fcntl (xfer->sock, F_SETFL, O_NONBLOCK) == -1)
return 0;
weechat_network_connect_to (xfer->sock, xfer->address, xfer->port);
}
/* for file receiving, connection is made in child process (blocking) */
return 1;
}
/*
* xfer_network_create_pipe: create pipe for communication with child process
* return 1 if ok, 0 if error
@@ -312,36 +271,6 @@ xfer_network_recv_file_fork (struct t_xfer *xfer)
xfer);
}
/*
* xfer_network_connect_init: connect to sender and init file or chat
*/
void
xfer_network_connect_init (struct t_xfer *xfer)
{
if (!xfer_network_connect (xfer))
{
xfer_close (xfer, XFER_STATUS_FAILED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
else
{
/* for a file: launch child process */
if (XFER_IS_FILE(xfer->type))
{
xfer->status = XFER_STATUS_CONNECTING;
xfer_network_recv_file_fork (xfer);
}
else
{
/* for a chat => associate with buffer */
xfer->status = XFER_STATUS_ACTIVE;
// TODO: create buffer for xfer chat
}
}
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
/*
* xfer_network_child_kill: kill child process and close pipe
*/
@@ -369,3 +298,263 @@ xfer_network_child_kill (struct t_xfer *xfer)
xfer->child_write = -1;
}
}
/*
* xfer_network_fd_cb: callback called when data is available on xfer socket
*/
int
xfer_network_fd_cb (void *arg_xfer)
{
struct t_xfer *xfer;
int sock;
struct sockaddr_in addr;
socklen_t length;
xfer = (struct t_xfer *)arg_xfer;
if (xfer->status == XFER_STATUS_CONNECTING)
{
if (xfer->type == XFER_TYPE_FILE_SEND)
{
xfer->last_activity = time (NULL);
length = sizeof (addr);
sock = accept (xfer->sock,
(struct sockaddr *) &addr, &length);
weechat_unhook (xfer->hook_fd);
xfer->hook_fd = NULL;
close (xfer->sock);
xfer->sock = -1;
if (sock < 0)
{
weechat_printf (NULL,
_("%s%s: unable to create socket for sending "
"file"),
weechat_prefix ("error"), "xfer");
xfer_close (xfer, XFER_STATUS_FAILED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
return WEECHAT_RC_OK;
}
xfer->sock = sock;
if (fcntl (xfer->sock, F_SETFL, O_NONBLOCK) == -1)
{
weechat_printf (NULL,
_("%s%s: unable to set option \"nonblock\" "
"for socket"),
weechat_prefix ("error"), "xfer");
xfer_close (xfer, XFER_STATUS_FAILED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
return WEECHAT_RC_OK;
}
xfer->address = ntohl (addr.sin_addr.s_addr);
xfer->status = XFER_STATUS_ACTIVE;
xfer->start_transfer = time (NULL);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
xfer_network_send_file_fork (xfer);
}
/*
if (xfer->type == XFER_TYPE_FILE_RECV)
{
if (xfer->child_read != -1)
irc_dcc_file_child_read (dcc);
}
*/
}
if (xfer->status == XFER_STATUS_WAITING)
{
if (xfer->type == XFER_TYPE_CHAT_SEND)
{
length = sizeof (addr);
sock = accept (xfer->sock, (struct sockaddr *) &addr, &length);
weechat_unhook (xfer->hook_fd);
xfer->hook_fd = NULL;
close (xfer->sock);
xfer->sock = -1;
if (sock < 0)
{
weechat_printf (NULL,
_("%s%s: unable to create socket for sending "
"file"),
weechat_prefix ("error"), "xfer");
xfer_close (xfer, XFER_STATUS_FAILED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
return WEECHAT_RC_OK;
}
xfer->sock = sock;
if (fcntl (xfer->sock, F_SETFL, O_NONBLOCK) == -1)
{
weechat_printf (NULL,
_("%s%s: unable to set option \"nonblock\" "
"for socket"),
weechat_prefix ("error"), "xfer");
xfer_close (xfer, XFER_STATUS_FAILED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
return WEECHAT_RC_OK;
}
xfer->address = ntohl (addr.sin_addr.s_addr);
xfer->status = XFER_STATUS_ACTIVE;
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
xfer->hook_fd = weechat_hook_fd (xfer->sock,
1, 0, 0,
&xfer_chat_recv_cb,
xfer);
xfer_chat_open_buffer (xfer);
}
}
/*
if (xfer->status == XFER_STATUS_ACTIVE)
{
if (XFER_IS_CHAT(dcc->type))
{
irc_dcc_chat_recv (dcc);
}
else
irc_dcc_file_child_read (dcc);
}
*/
return WEECHAT_RC_OK;
}
/*
* xfer_network_timer_cb: callback called to check if there's a timeout for xfer
* (called only one time for xfer)
*/
int
xfer_network_timer_cb (void *arg_xfer)
{
struct t_xfer *xfer;
xfer = (struct t_xfer *)arg_xfer;
if ((xfer->status == XFER_STATUS_WAITING)
|| (xfer->status == XFER_STATUS_CONNECTING))
{
weechat_printf (NULL,
_("%s%s: timeout for \"%s\" with %s"),
weechat_prefix ("error"), "xfer",
xfer->filename, xfer->remote_nick);
xfer_close (xfer, XFER_STATUS_FAILED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
return WEECHAT_RC_OK;
}
/*
* xfer_network_connect: connect to another host
*/
int
xfer_network_connect (struct t_xfer *xfer)
{
if (xfer->type == XFER_TYPE_CHAT_SEND)
xfer->status = XFER_STATUS_WAITING;
else
xfer->status = XFER_STATUS_CONNECTING;
if (xfer->sock < 0)
{
xfer->sock = socket (AF_INET, SOCK_STREAM, 0);
if (xfer->sock < 0)
return 0;
}
if (XFER_IS_SEND(xfer->type))
{
/* listen to socket */
if (fcntl (xfer->sock, F_SETFL, O_NONBLOCK) == -1)
return 0;
if (listen (xfer->sock, 1) == -1)
return 0;
if (fcntl (xfer->sock, F_SETFL, 0) == -1)
return 0;
xfer->hook_fd = weechat_hook_fd (xfer->sock,
1, 0, 0,
&xfer_network_fd_cb,
xfer);
/* add timeout */
if (weechat_config_integer (xfer_config_network_timeout) > 0)
{
xfer->hook_timer = weechat_hook_timer (weechat_config_integer (xfer_config_network_timeout) * 1000,
0, 1,
&xfer_network_timer_cb,
xfer);
}
}
/* for chat receiving, connect to listening host */
if (xfer->type == XFER_TYPE_CHAT_RECV)
{
if (fcntl (xfer->sock, F_SETFL, O_NONBLOCK) == -1)
return 0;
weechat_network_connect_to (xfer->sock, xfer->address, xfer->port);
xfer->hook_fd = weechat_hook_fd (xfer->sock,
1, 0, 0,
&xfer_chat_recv_cb,
xfer);
}
/* for file receiving, connection is made in child process (blocking) */
return 1;
}
/*
* xfer_network_connect_init: connect to sender and init file or chat
*/
void
xfer_network_connect_init (struct t_xfer *xfer)
{
if (!xfer_network_connect (xfer))
{
xfer_close (xfer, XFER_STATUS_FAILED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
else
{
/* for a file: launch child process */
if (XFER_IS_FILE(xfer->type))
{
xfer->status = XFER_STATUS_CONNECTING;
xfer_network_recv_file_fork (xfer);
}
else
{
/* for a chat => associate with buffer */
xfer->status = XFER_STATUS_ACTIVE;
xfer_chat_open_buffer (xfer);
}
}
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
/*
* xfer_network_accept: accept a xfer file or chat request
*/
void
xfer_network_accept (struct t_xfer *xfer)
{
if (XFER_IS_FILE(xfer->type) && (xfer->start_resume > 0))
{
xfer->status = XFER_STATUS_CONNECTING;
xfer_send_signal (xfer, "xfer_accepted");
/*
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);
*/
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
else
xfer_network_connect_init (xfer);
}
+2 -1
View File
@@ -20,11 +20,12 @@
#ifndef __WEECHAT_XFER_NETWORK_H
#define __WEECHAT_XFER_NETWORK_H 1
extern int xfer_network_connect (struct t_xfer *xfer);
extern int xfer_network_create_pipe (struct t_xfer *xfer);
extern void xfer_network_write_pipe (struct t_xfer *xfer, int status,
int error);
extern void xfer_network_connect_init (struct t_xfer *xfer);
extern void xfer_network_child_kill (struct t_xfer *xfer);
extern int xfer_network_connect (struct t_xfer *xfer);
extern void xfer_network_accept (struct t_xfer *xfer);
#endif /* xfer-network.h */
+395 -356
View File
@@ -32,6 +32,7 @@
#include "../weechat-plugin.h"
#include "xfer.h"
#include "xfer-buffer.h"
#include "xfer-command.h"
#include "xfer-config.h"
#include "xfer-file.h"
#include "xfer-network.h"
@@ -64,6 +65,7 @@ char *xfer_status_string[] = /* strings for status */
struct t_xfer *xfer_list = NULL; /* list of files/chats */
struct t_xfer *last_xfer = NULL; /* last file/chat in list */
int xfer_count = 0; /* number of xfer */
int xfer_debug = 0;
@@ -155,339 +157,25 @@ xfer_search (enum t_xfer_type type, enum t_xfer_status status, int port)
}
/*
* xfer_port_in_use: return 1 if a port is in used
* (by an active or connecting xfer)
* xfer_search_by_number: search a xfer by number (first xfer is 0)
*/
int
xfer_port_in_use (int port)
struct t_xfer *
xfer_search_by_number (int number)
{
struct t_xfer *ptr_xfer;
int i;
/* skip any currently used ports */
i = 0;
for (ptr_xfer = xfer_list; ptr_xfer; ptr_xfer = ptr_xfer->next_xfer)
{
if ((ptr_xfer->port == port) && (!XFER_HAS_ENDED(ptr_xfer->status)))
return 1;
if (i == number)
return ptr_xfer;
i++;
}
/* port not in use */
return 0;
}
/*
* xfer_send_signal: send a signal for a xfer
*/
void
xfer_send_signal (struct t_xfer *xfer, char *signal)
{
struct t_plugin_infolist *infolist;
struct t_plugin_infolist_item *item;
char str_long[128];
infolist = weechat_infolist_new ();
if (infolist)
{
item = weechat_infolist_new_item (infolist);
if (item)
{
weechat_infolist_new_var_string (item, "plugin_id",
xfer->plugin_id);
weechat_infolist_new_var_string (item, "type",
xfer_type_string[xfer->type]);
weechat_infolist_new_var_string (item, "protocol",
xfer_protocol_string[xfer->protocol]);
weechat_infolist_new_var_string (item, "nick",
xfer->nick);
weechat_infolist_new_var_string (item, "filename",
xfer->filename);
snprintf (str_long, sizeof (str_long), "%lu", xfer->size);
weechat_infolist_new_var_string (item, "size",
str_long);
snprintf (str_long, sizeof (str_long), "%lu", xfer->address);
weechat_infolist_new_var_string (item, "address",
str_long);
weechat_infolist_new_var_integer (item, "port",
xfer->port);
weechat_hook_signal_send (signal, WEECHAT_HOOK_SIGNAL_POINTER,
infolist);
}
weechat_infolist_free (infolist);
}
}
/*
* xfer_alloc: allocate a new xfer
*/
struct t_xfer *
xfer_alloc ()
{
struct t_xfer *new_xfer;
time_t time_now;
/* create new xfer struct */
if ((new_xfer = malloc (sizeof (*new_xfer))) == NULL)
return NULL;
time_now = time (NULL);
/* default values */
new_xfer->filename = NULL;
new_xfer->size = 0;
new_xfer->address = 0;
new_xfer->port = 0;
new_xfer->nick = NULL;
new_xfer->type = 0;
new_xfer->protocol = 0;
new_xfer->status = 0;
new_xfer->buffer = NULL;
new_xfer->fast_send = weechat_config_boolean (xfer_config_network_fast_send);
new_xfer->blocksize = weechat_config_integer (xfer_config_network_blocksize);
new_xfer->start_time = time_now;
new_xfer->start_transfer = time_now;
new_xfer->sock = -1;
new_xfer->child_pid = 0;
new_xfer->child_read = -1;
new_xfer->child_write = -1;
new_xfer->hook_fd = NULL;
new_xfer->unterminated_message = NULL;
new_xfer->file = -1;
new_xfer->local_filename = NULL;
new_xfer->filename_suffix = -1;
new_xfer->pos = 0;
new_xfer->ack = 0;
new_xfer->start_resume = 0;
new_xfer->last_check_time = time_now;
new_xfer->last_check_pos = time_now;
new_xfer->last_activity = 0;
new_xfer->bytes_per_sec = 0;
new_xfer->eta = 0;
new_xfer->prev_xfer = NULL;
new_xfer->next_xfer = xfer_list;
if (xfer_list)
xfer_list->prev_xfer = new_xfer;
else
last_xfer = new_xfer;
xfer_list = new_xfer;
return new_xfer;
}
/*
* xfer_accept: accept a xfer file or chat request
*/
void
xfer_accept (struct t_xfer *xfer)
{
if (XFER_IS_FILE(xfer->type) && (xfer->start_resume > 0))
{
xfer->status = XFER_STATUS_CONNECTING;
xfer_send_signal (xfer, "xfer_accepted");
/*
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);
*/
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
else
xfer_network_connect_init (xfer);
}
/*
* xfer_new: add a xfer to list
*/
struct t_xfer *
xfer_new (char *plugin_id, enum t_xfer_type type,
enum t_xfer_protocol protocol, char *nick, char *filename,
unsigned long size, unsigned long address, int port, int sock,
char *local_filename)
{
struct t_xfer *new_xfer;
new_xfer = xfer_alloc ();
if (!new_xfer)
{
weechat_printf (NULL,
_("%s%s: not enough memory for new xfer"),
weechat_prefix ("error"), "xfer");
return NULL;
}
if (!xfer_buffer
&& weechat_config_boolean (xfer_config_look_auto_open_buffer))
{
xfer_buffer_open ();
}
/* initialize new xfer */
new_xfer->plugin_id = strdup (plugin_id);
new_xfer->type = type;
new_xfer->protocol = protocol;
new_xfer->nick = strdup (nick);
if (XFER_IS_FILE(type))
new_xfer->filename = (filename) ? strdup (filename) : NULL;
new_xfer->size = size;
new_xfer->address = address;
new_xfer->port = port;
new_xfer->status = XFER_STATUS_WAITING;
new_xfer->sock = sock;
if (local_filename)
new_xfer->local_filename = strdup (local_filename);
else
xfer_file_find_filename (new_xfer);
/* write info message on server buffer */
switch (type)
{
case XFER_TYPE_FILE_RECV:
weechat_printf (NULL,
_("%s: incoming file from %s "
"(%d.%d.%d.%d): %s, %lu bytes (protocol: %s)"),
"xfer",
nick,
address >> 24,
(address >> 16) & 0xff,
(address >> 8) & 0xff,
address & 0xff,
filename,
size,
xfer_protocol_string[protocol]);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
break;
case XFER_TYPE_FILE_SEND:
weechat_printf (NULL,
_("%s: sending file to %s: %s "
"(local filename: %s), %lu bytes (protocol: %s)"),
"xfer",
nick,
filename,
local_filename,
size,
xfer_protocol_string[protocol]);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
break;
case XFER_TYPE_CHAT_RECV:
weechat_printf (NULL,
_("%s: incoming chat request from %s "
"(%d.%d.%d.%d)"),
"xfer",
nick,
address >> 24,
(address >> 16) & 0xff,
(address >> 8) & 0xff,
address & 0xff);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
break;
case XFER_TYPE_CHAT_SEND:
weechat_printf (NULL,
_("%s: sending chat request to %s"),
"xfer",
nick);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
break;
case XFER_NUM_TYPES:
break;
}
if (XFER_IS_FILE(type) && (!new_xfer->local_filename))
{
xfer_close (new_xfer, XFER_STATUS_FAILED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
return NULL;
}
if (XFER_IS_FILE(type) && (new_xfer->start_resume > 0))
{
weechat_printf (NULL,
_("%s: file %s (local filename: %s) "
"will be resumed at position %u"),
"xfer",
new_xfer->filename,
new_xfer->local_filename,
new_xfer->start_resume);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
/* connect if needed and display again xfer buffer */
if (XFER_IS_SEND(type))
{
if (!xfer_network_connect (new_xfer))
{
xfer_close (new_xfer, XFER_STATUS_FAILED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
return NULL;
}
}
if ( ( (type == XFER_TYPE_CHAT_RECV)
&& (weechat_config_boolean (xfer_config_file_auto_accept_chats)) )
|| ( (type == XFER_TYPE_FILE_RECV)
&& (weechat_config_boolean (xfer_config_file_auto_accept_files)) ) )
xfer_accept (new_xfer);
else
xfer_buffer_refresh (WEECHAT_HOTLIST_PRIVATE);
return new_xfer;
}
/*
* xfer_free: free xfer struct and remove it from list
*/
void
xfer_free (struct t_xfer *xfer)
{
struct t_xfer *new_xfer_list;
if (!xfer)
return;
/* close chat buffer */
if (xfer->buffer)
{
/* TODO: close chat buffer */
}
/* remove xfer from list */
if (last_xfer == xfer)
last_xfer = xfer->prev_xfer;
if (xfer->prev_xfer)
{
(xfer->prev_xfer)->next_xfer = xfer->next_xfer;
new_xfer_list = xfer_list;
}
else
new_xfer_list = xfer->next_xfer;
if (xfer->next_xfer)
(xfer->next_xfer)->prev_xfer = xfer->prev_xfer;
/* free data */
if (xfer->plugin_id)
free (xfer->plugin_id);
if (xfer->nick)
free (xfer->nick);
if (xfer->filename)
free (xfer->filename);
if (xfer->unterminated_message)
free (xfer->unterminated_message);
if (xfer->local_filename)
free (xfer->local_filename);
free (xfer);
xfer_list = new_xfer_list;
/* xfer not found */
return NULL;
}
/*
@@ -503,15 +191,27 @@ xfer_close (struct t_xfer *xfer, enum t_xfer_status status)
if (XFER_HAS_ENDED(xfer->status))
{
if (xfer->hook_fd)
{
weechat_unhook (xfer->hook_fd);
xfer->hook_fd = NULL;
}
if (xfer->hook_timer)
{
weechat_unhook (xfer->hook_timer);
xfer->hook_timer = NULL;
}
if (XFER_IS_FILE(xfer->type))
{
weechat_printf (NULL,
_("%s: file %s %s %s: %s"),
_("%s%s: file %s %s %s: %s"),
(xfer->status == XFER_STATUS_DONE) ?
"" : weechat_prefix ("error"),
"xfer",
xfer->filename,
(xfer->type == XFER_TYPE_FILE_SEND) ?
_("sent to") : _("received from"),
xfer->nick,
xfer->remote_nick,
(xfer->status == XFER_STATUS_DONE) ?
_("OK") : _("FAILED"));
xfer_network_child_kill (xfer);
@@ -525,7 +225,7 @@ xfer_close (struct t_xfer *xfer, enum t_xfer_status status)
_("%s: chat closed with %s "
"(%d.%d.%d.%d)"),
"xfer",
xfer->nick,
xfer->remote_nick,
xfer->address >> 24,
(xfer->address >> 16) & 0xff,
(xfer->address >> 8) & 0xff,
@@ -564,6 +264,335 @@ xfer_close (struct t_xfer *xfer, enum t_xfer_status status)
}
}
/*
* xfer_port_in_use: return 1 if a port is in used
* (by an active or connecting xfer)
*/
int
xfer_port_in_use (int port)
{
struct t_xfer *ptr_xfer;
/* skip any currently used ports */
for (ptr_xfer = xfer_list; ptr_xfer; ptr_xfer = ptr_xfer->next_xfer)
{
if ((ptr_xfer->port == port) && (!XFER_HAS_ENDED(ptr_xfer->status)))
return 1;
}
/* port not in use */
return 0;
}
/*
* xfer_send_signal: send a signal for a xfer
*/
void
xfer_send_signal (struct t_xfer *xfer, char *signal)
{
struct t_plugin_infolist *infolist;
struct t_plugin_infolist_item *item;
char str_long[128];
infolist = weechat_infolist_new ();
if (infolist)
{
item = weechat_infolist_new_item (infolist);
if (item)
{
weechat_infolist_new_var_string (item, "plugin_name",
xfer->plugin_name);
weechat_infolist_new_var_string (item, "plugin_id",
xfer->plugin_id);
weechat_infolist_new_var_string (item, "type",
xfer_type_string[xfer->type]);
weechat_infolist_new_var_string (item, "protocol",
xfer_protocol_string[xfer->protocol]);
weechat_infolist_new_var_string (item, "remote_nick",
xfer->remote_nick);
weechat_infolist_new_var_string (item, "local_nick",
xfer->local_nick);
weechat_infolist_new_var_string (item, "filename",
xfer->filename);
snprintf (str_long, sizeof (str_long), "%lu", xfer->size);
weechat_infolist_new_var_string (item, "size",
str_long);
snprintf (str_long, sizeof (str_long), "%lu", xfer->address);
weechat_infolist_new_var_string (item, "address",
str_long);
weechat_infolist_new_var_integer (item, "port",
xfer->port);
weechat_hook_signal_send (signal, WEECHAT_HOOK_SIGNAL_POINTER,
infolist);
}
weechat_infolist_free (infolist);
}
}
/*
* xfer_alloc: allocate a new xfer
*/
struct t_xfer *
xfer_alloc ()
{
struct t_xfer *new_xfer;
time_t time_now;
/* create new xfer struct */
if ((new_xfer = malloc (sizeof (*new_xfer))) == NULL)
return NULL;
time_now = time (NULL);
/* default values */
new_xfer->filename = NULL;
new_xfer->size = 0;
new_xfer->address = 0;
new_xfer->port = 0;
new_xfer->remote_nick = NULL;
new_xfer->local_nick = NULL;
new_xfer->type = 0;
new_xfer->protocol = 0;
new_xfer->status = 0;
new_xfer->buffer = NULL;
new_xfer->fast_send = weechat_config_boolean (xfer_config_network_fast_send);
new_xfer->blocksize = weechat_config_integer (xfer_config_network_blocksize);
new_xfer->start_time = time_now;
new_xfer->start_transfer = time_now;
new_xfer->sock = -1;
new_xfer->child_pid = 0;
new_xfer->child_read = -1;
new_xfer->child_write = -1;
new_xfer->hook_fd = NULL;
new_xfer->hook_timer = NULL;
new_xfer->unterminated_message = NULL;
new_xfer->file = -1;
new_xfer->local_filename = NULL;
new_xfer->filename_suffix = -1;
new_xfer->pos = 0;
new_xfer->ack = 0;
new_xfer->start_resume = 0;
new_xfer->last_check_time = time_now;
new_xfer->last_check_pos = time_now;
new_xfer->last_activity = 0;
new_xfer->bytes_per_sec = 0;
new_xfer->eta = 0;
new_xfer->prev_xfer = NULL;
new_xfer->next_xfer = xfer_list;
if (xfer_list)
xfer_list->prev_xfer = new_xfer;
else
last_xfer = new_xfer;
xfer_list = new_xfer;
xfer_count++;
return new_xfer;
}
/*
* xfer_new: add a xfer to list
*/
struct t_xfer *
xfer_new (char *plugin_name, char *plugin_id, enum t_xfer_type type,
enum t_xfer_protocol protocol, char *remote_nick, char *local_nick,
char *filename,
unsigned long size, unsigned long address, int port, int sock,
char *local_filename)
{
struct t_xfer *new_xfer;
new_xfer = xfer_alloc ();
if (!new_xfer)
{
weechat_printf (NULL,
_("%s%s: not enough memory for new xfer"),
weechat_prefix ("error"), "xfer");
return NULL;
}
if (!xfer_buffer
&& weechat_config_boolean (xfer_config_look_auto_open_buffer))
{
xfer_buffer_open ();
}
/* initialize new xfer */
new_xfer->plugin_name = strdup (plugin_name);
new_xfer->plugin_id = strdup (plugin_id);
new_xfer->type = type;
new_xfer->protocol = protocol;
new_xfer->remote_nick = strdup (remote_nick);
new_xfer->local_nick = (local_nick) ? strdup (local_nick) : NULL;
if (XFER_IS_FILE(type))
new_xfer->filename = (filename) ? strdup (filename) : NULL;
else
new_xfer->filename = strdup (_("xfer chat"));
new_xfer->size = size;
new_xfer->address = address;
new_xfer->port = port;
new_xfer->status = XFER_STATUS_WAITING;
new_xfer->sock = sock;
if (local_filename)
new_xfer->local_filename = strdup (local_filename);
else
xfer_file_find_filename (new_xfer);
/* write info message on server buffer */
switch (type)
{
case XFER_TYPE_FILE_RECV:
weechat_printf (NULL,
_("%s: incoming file from %s "
"(%d.%d.%d.%d): %s, %lu bytes (protocol: %s)"),
"xfer",
remote_nick,
address >> 24,
(address >> 16) & 0xff,
(address >> 8) & 0xff,
address & 0xff,
filename,
size,
xfer_protocol_string[protocol]);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
break;
case XFER_TYPE_FILE_SEND:
weechat_printf (NULL,
_("%s: sending file to %s: %s "
"(local filename: %s), %lu bytes (protocol: %s)"),
"xfer",
remote_nick,
filename,
local_filename,
size,
xfer_protocol_string[protocol]);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
break;
case XFER_TYPE_CHAT_RECV:
weechat_printf (NULL,
_("%s: incoming chat request from %s "
"(%d.%d.%d.%d)"),
"xfer",
remote_nick,
address >> 24,
(address >> 16) & 0xff,
(address >> 8) & 0xff,
address & 0xff);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
break;
case XFER_TYPE_CHAT_SEND:
weechat_printf (NULL,
_("%s: sending chat request to %s"),
"xfer",
remote_nick);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
break;
case XFER_NUM_TYPES:
break;
}
if (XFER_IS_FILE(type) && (!new_xfer->local_filename))
{
xfer_close (new_xfer, XFER_STATUS_FAILED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
return NULL;
}
if (XFER_IS_FILE(type) && (new_xfer->start_resume > 0))
{
weechat_printf (NULL,
_("%s: file %s (local filename: %s) "
"will be resumed at position %u"),
"xfer",
new_xfer->filename,
new_xfer->local_filename,
new_xfer->start_resume);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
}
/* connect if needed and display again xfer buffer */
if (XFER_IS_SEND(type))
{
if (!xfer_network_connect (new_xfer))
{
xfer_close (new_xfer, XFER_STATUS_FAILED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
return NULL;
}
}
if ( ( (type == XFER_TYPE_FILE_RECV)
&& (weechat_config_boolean (xfer_config_file_auto_accept_files)) )
|| ( (type == XFER_TYPE_CHAT_RECV)
&& (weechat_config_boolean (xfer_config_file_auto_accept_chats)) ) )
xfer_network_accept (new_xfer);
else
xfer_buffer_refresh (WEECHAT_HOTLIST_PRIVATE);
return new_xfer;
}
/*
* xfer_free: free xfer struct and remove it from list
*/
void
xfer_free (struct t_xfer *xfer)
{
struct t_xfer *new_xfer_list;
if (!xfer)
return;
if (xfer->buffer)
{
weechat_buffer_close (xfer->buffer, 1);
}
/* remove xfer from list */
if (last_xfer == xfer)
last_xfer = xfer->prev_xfer;
if (xfer->prev_xfer)
{
(xfer->prev_xfer)->next_xfer = xfer->next_xfer;
new_xfer_list = xfer_list;
}
else
new_xfer_list = xfer->next_xfer;
if (xfer->next_xfer)
(xfer->next_xfer)->prev_xfer = xfer->prev_xfer;
/* free data */
if (xfer->plugin_id)
free (xfer->plugin_id);
if (xfer->remote_nick)
free (xfer->remote_nick);
if (xfer->local_nick)
free (xfer->local_nick);
if (xfer->filename)
free (xfer->filename);
if (xfer->unterminated_message)
free (xfer->unterminated_message);
if (xfer->local_filename)
free (xfer->local_filename);
free (xfer);
xfer_list = new_xfer_list;
xfer_count--;
if (xfer_buffer_selected_line >= xfer_count)
xfer_buffer_selected_line = (xfer_count == 0) ? 0 : xfer_count - 1;
}
/*
* xfer_add_cb: callback for "xfer_add" signal
*/
@@ -572,7 +601,8 @@ int
xfer_add_cb (void *data, char *signal, char *type_data, void *signal_data)
{
struct t_plugin_infolist *infolist;
char *plugin_id, *str_type, *nick, *filename, *str_protocol;
char *plugin_name, *plugin_id, *str_type, *str_protocol;
char *remote_nick, *local_nick, *filename;
int type, protocol;
char *weechat_dir, *dir1, *dir2, *filename2, *short_filename, *pos;
int spaces, args, port_start, port_end;
@@ -612,14 +642,16 @@ xfer_add_cb (void *data, char *signal, char *type_data, void *signal_data)
return WEECHAT_RC_ERROR;
}
plugin_name = weechat_infolist_string (infolist, "plugin_name");
plugin_id = weechat_infolist_string (infolist, "plugin_id");
str_type = weechat_infolist_string (infolist, "type");
nick = weechat_infolist_string (infolist, "nick");
filename = weechat_infolist_string (infolist, "filename");
str_protocol = weechat_infolist_string (infolist, "protocol");
remote_nick = weechat_infolist_string (infolist, "remote_nick");
local_nick = weechat_infolist_string (infolist, "local_nick");
filename = weechat_infolist_string (infolist, "filename");
protocol = XFER_NO_PROTOCOL;
if (!plugin_id || !str_type || !nick)
if (!plugin_name || !plugin_id || !str_type || !remote_nick || !local_nick)
{
weechat_printf (NULL,
_("%s%s: missing arguments"),
@@ -636,19 +668,11 @@ xfer_add_cb (void *data, char *signal, char *type_data, void *signal_data)
return WEECHAT_RC_ERROR;
}
if (XFER_IS_FILE(type) && !filename)
if (XFER_IS_FILE(type) && (!filename || !str_protocol))
{
weechat_printf (NULL,
_("%s%s: filename missing for type \"%s\""),
weechat_prefix ("error"), "xfer", str_type);
return WEECHAT_RC_ERROR;
}
if (XFER_IS_FILE(type) && !str_protocol)
{
weechat_printf (NULL,
_("%s%s: protocol missing for type \"%s\""),
weechat_prefix ("error"), "xfer", str_type);
_("%s%s: missing arguments"),
weechat_prefix ("error"), "xfer");
return WEECHAT_RC_ERROR;
}
@@ -670,11 +694,10 @@ xfer_add_cb (void *data, char *signal, char *type_data, void *signal_data)
if (type == XFER_TYPE_FILE_RECV)
{
filename2 = weechat_infolist_string (infolist, "filename");
filename2 = strdup (filename);
sscanf (weechat_infolist_string (infolist, "size"), "%lu", &file_size);
port = weechat_infolist_integer (infolist, "port");
}
if (type == XFER_TYPE_FILE_SEND)
{
/* add home if filename not beginning with '/' or '~' (not for Win32) */
@@ -744,7 +767,7 @@ xfer_add_cb (void *data, char *signal, char *type_data, void *signal_data)
if (XFER_IS_RECV(type))
{
sscanf (weechat_infolist_string (infolist, "address"), "%lu", &local_addr);
sscanf (weechat_infolist_string (infolist, "size"), "%lu", &file_size);
port = weechat_infolist_integer (infolist, "port");
}
else
{
@@ -848,7 +871,7 @@ xfer_add_cb (void *data, char *signal, char *type_data, void *signal_data)
}
}
if (type == XFER_TYPE_FILE_SEND)
if (XFER_IS_FILE(type))
{
/* extract short filename (without path) */
pos = strrchr (filename2, DIR_SEPARATOR_CHAR);
@@ -872,14 +895,25 @@ xfer_add_cb (void *data, char *signal, char *type_data, void *signal_data)
pos++;
}
}
if (type == XFER_TYPE_FILE_RECV)
{
if (filename2)
{
free (filename2);
filename2 = NULL;
}
}
/* add xfer entry and listen to socket if type is file or chat "send" */
if (XFER_IS_FILE(type))
ptr_xfer = xfer_new (plugin_id, type, protocol, nick, short_filename,
ptr_xfer = xfer_new (plugin_name, plugin_id, type, protocol,
remote_nick, local_nick, short_filename,
file_size, local_addr, port, sock, filename2);
else
ptr_xfer = xfer_new (plugin_id, type, protocol, nick, NULL, 0,
local_addr, port, sock, NULL);
ptr_xfer = xfer_new (plugin_name, plugin_id, type, protocol,
remote_nick, local_nick, NULL, 0, local_addr,
port, sock, NULL);
if (!ptr_xfer)
{
@@ -896,7 +930,8 @@ xfer_add_cb (void *data, char *signal, char *type_data, void *signal_data)
}
/* send signal if type is file or chat "send" */
xfer_send_signal (ptr_xfer, "xfer_send_ready");
if (XFER_IS_SEND(ptr_xfer->type))
xfer_send_signal (ptr_xfer, "xfer_send_ready");
if (short_filename)
free (short_filename);
@@ -919,11 +954,13 @@ xfer_print_log ()
{
weechat_log_printf ("");
weechat_log_printf ("[xfer (addr:0x%x)]", ptr_xfer);
weechat_log_printf (" plugin_name . . . . : '%s'", ptr_xfer->plugin_name);
weechat_log_printf (" plugin_id . . . . . : '%s'", ptr_xfer->plugin_id);
weechat_log_printf (" type. . . . . . . . : %d (%s)",
ptr_xfer->type,
xfer_type_string[ptr_xfer->type]);
weechat_log_printf (" nick. . . . . . . . : '%s'", ptr_xfer->nick);
weechat_log_printf (" remote_nick . . . . : '%s'", ptr_xfer->remote_nick);
weechat_log_printf (" local_nick. . . . . : '%s'", ptr_xfer->local_nick);
weechat_log_printf (" filename. . . . . . : '%s'", ptr_xfer->filename);
weechat_log_printf (" size. . . . . . . . : %lu", ptr_xfer->size);
weechat_log_printf (" address . . . . . . : %lu", ptr_xfer->address);
@@ -1002,6 +1039,8 @@ weechat_plugin_init (struct t_weechat_plugin *plugin)
xfer_create_directories ();
xfer_command_init ();
weechat_hook_signal ("xfer_add", &xfer_add_cb, NULL);
weechat_hook_signal ("debug_dump", &xfer_debug_dump_cb, NULL);
@@ -1029,10 +1068,10 @@ weechat_plugin_end (struct t_weechat_plugin *plugin)
weechat_printf (NULL,
_("%s%s: aborting active xfer: \"%s\" from %s"),
weechat_prefix ("error"), "xfer",
ptr_xfer->filename, ptr_xfer->nick);
weechat_log_printf (_("%s: aborting active xfer: \"%s\" from %s"),
"xfer",
ptr_xfer->filename, ptr_xfer->nick);
ptr_xfer->filename, ptr_xfer->remote_nick);
weechat_log_printf (_("%s%s: aborting active xfer: \"%s\" from %s"),
"", "xfer",
ptr_xfer->filename, ptr_xfer->remote_nick);
}
xfer_close (ptr_xfer, XFER_STATUS_FAILED);
}
+9 -3
View File
@@ -106,10 +106,12 @@ enum t_xfer_error
struct t_xfer
{
/* data received by xfer to initiate a transfer */
char *plugin_id; /* plugin identifier */
char *plugin_name; /* plugin name */
char *plugin_id; /* id used by plugin */
enum t_xfer_type type; /* xfer type (send/recv file) */
enum t_xfer_protocol protocol; /* xfer protocol (for file transfer) */
char *nick; /* remote nick */
char *remote_nick; /* remote nick */
char *local_nick; /* local nick */
char *filename; /* filename */
unsigned long size; /* file size */
unsigned long address; /* local or remote IP address */
@@ -127,6 +129,7 @@ struct t_xfer
int child_read; /* to read into child pipe */
int child_write; /* to write into child pipe */
struct t_hook *hook_fd; /* hook for socket or child pipe */
struct t_hook *hook_timer; /* timeout for recever accept */
char *unterminated_message; /* beginning of a message */
int file; /* local file (read or write) */
char *local_filename; /* local filename (with path) */
@@ -148,9 +151,12 @@ extern char *xfer_type_string[];
extern char *xfer_protocol_string[];
extern char *xfer_status_string[];
extern struct t_xfer *xfer_list, *last_xfer;
extern int xfer_count;
extern int xfer_debug;
extern struct t_xfer *xfer_search_by_number (int number);
extern void xfer_close (struct t_xfer *xfer, enum t_xfer_status status);
extern struct t_xfer *xfer_alloc ();
extern void xfer_send_signal (struct t_xfer *xfer, char *signal);
extern void xfer_free (struct t_xfer *xfer);
#endif /* xfer.h */