mirror of
https://github.com/weechat/weechat.git
synced 2026-06-30 14:56:39 +02:00
- added dcc_own_ip and dcc_port_range settings, patch by Jim Ramsay
- fixed bug when exiting DCC buffer (wrong input buffer)
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
WeeChat - Wee Enhanced Environment for Chat
|
||||
===========================================
|
||||
|
||||
ChangeLog - 2005-10-21
|
||||
ChangeLog - 2005-10-22
|
||||
|
||||
|
||||
Version 0.1.6 (under dev!):
|
||||
* added dcc_own_ip and dcc_port_range settings
|
||||
* full UTF-8 support, auto-detection of UTF-8 usage (locale)
|
||||
* added "Day changed to [date]" message when day changes
|
||||
* new plugin interface, rewritten from scratch: now loads dynamic C
|
||||
|
||||
+267
-236
File diff suppressed because it is too large
Load Diff
+14
-1
@@ -136,8 +136,11 @@ t_weechat_command weechat_commands[] =
|
||||
"Without argument, /unignore command lists all defined ignore."),
|
||||
0, 4, weechat_cmd_unignore, NULL },
|
||||
{ "window", N_("manage windows"),
|
||||
N_("[list | splith | splitv | [merge [down | up | left | right | all]]]"),
|
||||
N_("[list | -1 | +1 | b# | splith | splitv | [merge [down | up | left | right | all]]]"),
|
||||
N_("list: list opened windows (no parameter implies this list)\n"
|
||||
"-1: jump to previous window\n"
|
||||
"+1: jump to next window\n"
|
||||
"b#: jump to next window displaying buffer number #\n"
|
||||
"splith: split current window horizontally\n"
|
||||
"splitv: split current window vertically\n"
|
||||
"merge: merge window with another"),
|
||||
@@ -2511,6 +2514,8 @@ weechat_cmd_window (int argc, char **argv)
|
||||
{
|
||||
t_gui_window *ptr_win;
|
||||
int i;
|
||||
char *error;
|
||||
long number;
|
||||
|
||||
if ((argc == 0) || ((argc == 1) && (ascii_strcasecmp (argv[0], "list") == 0)))
|
||||
{
|
||||
@@ -2577,6 +2582,14 @@ weechat_cmd_window (int argc, char **argv)
|
||||
else
|
||||
gui_window_merge_auto (gui_current_window);
|
||||
}
|
||||
else if (ascii_strncasecmp (argv[0], "b", 1) == 0)
|
||||
{
|
||||
/* jump to window by buffer number */
|
||||
error = NULL;
|
||||
number = strtol (argv[0] + 1, &error, 10);
|
||||
if ((error) && (error[0] == '\0'))
|
||||
gui_switch_to_window_by_buffer (gui_current_window, number);
|
||||
}
|
||||
else if (ascii_strcasecmp (argv[0], "-1") == 0)
|
||||
gui_switch_to_previous_window (gui_current_window);
|
||||
else if (ascii_strcasecmp (argv[0], "+1") == 0)
|
||||
|
||||
+14
-1
@@ -420,7 +420,7 @@ t_config_option weechat_options_colors[] =
|
||||
{ "col_input_delimiters", N_("color for input text (delimiters)"),
|
||||
N_("color for input text (delimiters)"),
|
||||
OPTION_TYPE_COLOR, 0, 0, 0,
|
||||
"lightgreen", NULL, &cfg_col_input_delimiters, NULL, &config_change_color },
|
||||
"white", NULL, &cfg_col_input_delimiters, NULL, &config_change_color },
|
||||
{ "col_input_bg", N_("background for input window"),
|
||||
N_("background for input window"),
|
||||
OPTION_TYPE_COLOR, 0, 0, 0,
|
||||
@@ -677,6 +677,8 @@ int cfg_dcc_auto_accept_files;
|
||||
int cfg_dcc_auto_accept_chats;
|
||||
int cfg_dcc_timeout;
|
||||
int cfg_dcc_blocksize;
|
||||
char *cfg_dcc_port_range;
|
||||
char *cfg_dcc_own_ip;
|
||||
char *cfg_dcc_download_path;
|
||||
char *cfg_dcc_upload_path;
|
||||
int cfg_dcc_convert_spaces;
|
||||
@@ -700,6 +702,17 @@ t_config_option weechat_options_dcc[] =
|
||||
N_("block size for dcc packets in bytes (default: 65536)"),
|
||||
OPTION_TYPE_INT, 1024, 102400, 65536,
|
||||
NULL, NULL, &cfg_dcc_blocksize, NULL, &config_change_noop },
|
||||
{ "dcc_port_range", N_("allowed ports for outgoing dcc"),
|
||||
N_("restricts outgoing dcc to use only ports in the given range "
|
||||
"(useful for NAT) (syntax: a single port, ie. 5000 or a port "
|
||||
"range, ie. 5000-5015, empty value means any port)"),
|
||||
OPTION_TYPE_STRING, 0, 0, 0, "",
|
||||
NULL, NULL, &cfg_dcc_port_range, &config_change_noop },
|
||||
{ "dcc_own_ip", N_("IP address for outgoing dcc"),
|
||||
N_("IP or DNS address used for outgoing dcc "
|
||||
"(if empty, local interface IP is used)"),
|
||||
OPTION_TYPE_STRING, 0, 0, 0, "",
|
||||
NULL, NULL, &cfg_dcc_own_ip, &config_change_noop },
|
||||
{ "dcc_download_path", N_("path for incoming files with dcc"),
|
||||
N_("path for writing incoming files with dcc (default: user home)"),
|
||||
OPTION_TYPE_STRING, 0, 0, 0,
|
||||
|
||||
@@ -191,6 +191,8 @@ extern int cfg_dcc_auto_accept_files;
|
||||
extern int cfg_dcc_auto_accept_chats;
|
||||
extern int cfg_dcc_timeout;
|
||||
extern int cfg_dcc_blocksize;
|
||||
extern char *cfg_dcc_port_range;
|
||||
extern char *cfg_dcc_own_ip;
|
||||
extern char *cfg_dcc_download_path;
|
||||
extern char *cfg_dcc_upload_path;
|
||||
extern int cfg_dcc_convert_spaces;
|
||||
|
||||
@@ -256,10 +256,15 @@ gui_input_read ()
|
||||
|
||||
if ((gui_key_pressed (key_str) != 0) && (insert_ok))
|
||||
{
|
||||
gui_input_insert_string (gui_current_window, key_str, -1);
|
||||
gui_current_window->buffer->input_buffer_pos += utf8_strlen (key_str);
|
||||
gui_draw_buffer_input (gui_current_window->buffer, 0);
|
||||
gui_current_window->buffer->completion.position = -1;
|
||||
if (gui_current_window->buffer->dcc)
|
||||
gui_input_action_dcc (gui_current_window, key_str);
|
||||
else
|
||||
{
|
||||
gui_input_insert_string (gui_current_window, key_str, -1);
|
||||
gui_current_window->buffer->input_buffer_pos += utf8_strlen (key_str);
|
||||
gui_draw_buffer_input (gui_current_window->buffer, 0);
|
||||
gui_current_window->buffer->completion.position = -1;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
+100
-72
@@ -609,78 +609,89 @@ gui_input_optimize_buffer_size (t_gui_buffer *buffer)
|
||||
|
||||
/*
|
||||
* gui_input_action_dcc: execute an action on a DCC after a user input
|
||||
* return -1 if DCC buffer was closed due to action, 0 otherwise
|
||||
*/
|
||||
|
||||
void
|
||||
gui_input_action_dcc (t_gui_window *window, char action)
|
||||
gui_input_action_dcc (t_gui_window *window, char *actions)
|
||||
{
|
||||
t_irc_dcc *dcc_selected, *ptr_dcc, *ptr_dcc_next;
|
||||
t_gui_buffer *ptr_buffer;
|
||||
|
||||
dcc_selected = (window->dcc_selected) ?
|
||||
(t_irc_dcc *) window->dcc_selected : dcc_list;
|
||||
|
||||
switch (action)
|
||||
while (actions[0])
|
||||
{
|
||||
/* accept DCC */
|
||||
case 'a':
|
||||
case 'A':
|
||||
if (dcc_selected
|
||||
&& (DCC_IS_RECV(dcc_selected->status))
|
||||
&& (dcc_selected->status == DCC_WAITING))
|
||||
if (actions[0] >= 32)
|
||||
{
|
||||
dcc_selected = (window->dcc_selected) ?
|
||||
(t_irc_dcc *) window->dcc_selected : dcc_list;
|
||||
|
||||
switch (actions[0])
|
||||
{
|
||||
dcc_accept (dcc_selected);
|
||||
}
|
||||
break;
|
||||
/* cancel DCC */
|
||||
case 'c':
|
||||
case 'C':
|
||||
if (dcc_selected
|
||||
&& (!DCC_ENDED(dcc_selected->status)))
|
||||
{
|
||||
dcc_close (dcc_selected, DCC_ABORTED);
|
||||
gui_redraw_buffer (window->buffer);
|
||||
}
|
||||
break;
|
||||
/* purge old DCC */
|
||||
case 'p':
|
||||
case 'P':
|
||||
window->dcc_selected = NULL;
|
||||
ptr_dcc = dcc_list;
|
||||
while (ptr_dcc)
|
||||
{
|
||||
ptr_dcc_next = ptr_dcc->next_dcc;
|
||||
if (DCC_ENDED(ptr_dcc->status))
|
||||
dcc_free (ptr_dcc);
|
||||
ptr_dcc = ptr_dcc_next;
|
||||
}
|
||||
gui_redraw_buffer (window->buffer);
|
||||
break;
|
||||
/* close DCC window */
|
||||
case 'q':
|
||||
case 'Q':
|
||||
if (buffer_before_dcc)
|
||||
{
|
||||
gui_buffer_free (window->buffer, 1);
|
||||
gui_switch_to_buffer (window, buffer_before_dcc);
|
||||
}
|
||||
else
|
||||
gui_buffer_free (window->buffer, 1);
|
||||
gui_redraw_buffer (window->buffer);
|
||||
break;
|
||||
/* remove from DCC list */
|
||||
case 'r':
|
||||
case 'R':
|
||||
if (dcc_selected
|
||||
&& (DCC_ENDED(dcc_selected->status)))
|
||||
{
|
||||
if (dcc_selected->next_dcc)
|
||||
window->dcc_selected = dcc_selected->next_dcc;
|
||||
else
|
||||
/* accept DCC */
|
||||
case 'a':
|
||||
case 'A':
|
||||
if (dcc_selected
|
||||
&& (DCC_IS_RECV(dcc_selected->status))
|
||||
&& (dcc_selected->status == DCC_WAITING))
|
||||
{
|
||||
dcc_accept (dcc_selected);
|
||||
}
|
||||
break;
|
||||
/* cancel DCC */
|
||||
case 'c':
|
||||
case 'C':
|
||||
if (dcc_selected
|
||||
&& (!DCC_ENDED(dcc_selected->status)))
|
||||
{
|
||||
dcc_close (dcc_selected, DCC_ABORTED);
|
||||
gui_redraw_buffer (window->buffer);
|
||||
}
|
||||
break;
|
||||
/* purge old DCC */
|
||||
case 'p':
|
||||
case 'P':
|
||||
window->dcc_selected = NULL;
|
||||
dcc_free (dcc_selected);
|
||||
gui_redraw_buffer (window->buffer);
|
||||
ptr_dcc = dcc_list;
|
||||
while (ptr_dcc)
|
||||
{
|
||||
ptr_dcc_next = ptr_dcc->next_dcc;
|
||||
if (DCC_ENDED(ptr_dcc->status))
|
||||
dcc_free (ptr_dcc);
|
||||
ptr_dcc = ptr_dcc_next;
|
||||
}
|
||||
gui_redraw_buffer (window->buffer);
|
||||
break;
|
||||
/* close DCC window */
|
||||
case 'q':
|
||||
case 'Q':
|
||||
if (buffer_before_dcc)
|
||||
{
|
||||
ptr_buffer = window->buffer;
|
||||
gui_switch_to_buffer (window, buffer_before_dcc);
|
||||
gui_buffer_free (ptr_buffer, 0);
|
||||
}
|
||||
else
|
||||
gui_buffer_free (window->buffer, 1);
|
||||
gui_redraw_buffer (window->buffer);
|
||||
return;
|
||||
break;
|
||||
/* remove from DCC list */
|
||||
case 'r':
|
||||
case 'R':
|
||||
if (dcc_selected
|
||||
&& (DCC_ENDED(dcc_selected->status)))
|
||||
{
|
||||
if (dcc_selected->next_dcc)
|
||||
window->dcc_selected = dcc_selected->next_dcc;
|
||||
else
|
||||
window->dcc_selected = NULL;
|
||||
dcc_free (dcc_selected);
|
||||
gui_redraw_buffer (window->buffer);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
actions = utf8_next_char (actions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -697,16 +708,7 @@ gui_input_insert_string (t_gui_window *window, char *string, int pos)
|
||||
int size, length;
|
||||
char *ptr_start;
|
||||
|
||||
if (window->buffer->dcc)
|
||||
{
|
||||
while (string[0])
|
||||
{
|
||||
if (string[0] >= 32)
|
||||
gui_input_action_dcc (window, string[0]);
|
||||
string = utf8_next_char (string);
|
||||
}
|
||||
}
|
||||
else if (window->buffer->has_input)
|
||||
if (window->buffer->has_input)
|
||||
{
|
||||
if (pos == -1)
|
||||
pos = window->buffer->input_buffer_pos;
|
||||
@@ -1760,6 +1762,32 @@ gui_switch_to_next_window (t_gui_window *window)
|
||||
gui_redraw_buffer (gui_current_window->buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
* gui_switch_to_window_by_buffer: switch to next window displaying a buffer
|
||||
*/
|
||||
|
||||
void
|
||||
gui_switch_to_window_by_buffer (t_gui_window *window, int buffer_number)
|
||||
{
|
||||
t_gui_window *ptr_win;
|
||||
|
||||
if (!gui_ok)
|
||||
return;
|
||||
|
||||
ptr_win = (window->next_window) ? window->next_window : gui_windows;
|
||||
while (ptr_win != window)
|
||||
{
|
||||
if (ptr_win->buffer->number == buffer_number)
|
||||
{
|
||||
gui_current_window = ptr_win;
|
||||
gui_switch_to_buffer (gui_current_window, gui_current_window->buffer);
|
||||
gui_redraw_buffer (gui_current_window->buffer);
|
||||
return;
|
||||
}
|
||||
ptr_win = (ptr_win->next_window) ? ptr_win->next_window : gui_windows;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* gui_switch_to_dcc_buffer: switch to dcc buffer (create it if it does not exist)
|
||||
*/
|
||||
|
||||
@@ -331,6 +331,7 @@ extern t_gui_line *gui_new_line (t_gui_buffer *);
|
||||
extern t_gui_message *gui_new_message (t_gui_buffer *);
|
||||
extern void gui_input_clipboard_copy (char *, int);
|
||||
extern void gui_input_clipboard_paste (t_gui_window *);
|
||||
extern void gui_input_action_dcc (t_gui_window *, char *);
|
||||
extern int gui_input_insert_string (t_gui_window *, char *, int);
|
||||
extern void gui_input_return (t_gui_window *);
|
||||
extern void gui_input_tab (t_gui_window *);
|
||||
@@ -364,6 +365,7 @@ extern void gui_switch_to_previous_buffer (t_gui_window *);
|
||||
extern void gui_switch_to_next_buffer (t_gui_window *);
|
||||
extern void gui_switch_to_previous_window (t_gui_window *);
|
||||
extern void gui_switch_to_next_window (t_gui_window *);
|
||||
extern void gui_switch_to_window_by_buffer (t_gui_window *, int);
|
||||
extern void gui_switch_to_dcc_buffer (t_gui_window *);
|
||||
extern t_gui_buffer *gui_switch_to_buffer_by_number (t_gui_window *, int);
|
||||
extern void gui_move_buffer_to_number (t_gui_window *, int);
|
||||
|
||||
+93
-9
@@ -87,6 +87,26 @@ dcc_search (t_irc_server *server, int type, int status, int port)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* dcc_port_in_use: return 1 if a port is in used (by an active or connecting DCC)
|
||||
*/
|
||||
|
||||
int
|
||||
dcc_port_in_use (int port)
|
||||
{
|
||||
t_irc_dcc *ptr_dcc;
|
||||
|
||||
/* skip any currently used ports */
|
||||
for (ptr_dcc = dcc_list; ptr_dcc; ptr_dcc = ptr_dcc->next_dcc)
|
||||
{
|
||||
if ((ptr_dcc->port == port) && (!DCC_ENDED(ptr_dcc->status)))
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* port not in use */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* dcc_file_is_resumable: check if a file can be used for resuming a download
|
||||
*/
|
||||
@@ -748,9 +768,11 @@ void
|
||||
dcc_send_request (t_irc_server *server, int type, char *nick, char *filename)
|
||||
{
|
||||
char *ptr_home, *filename2, *short_filename, *pos;
|
||||
int spaces;
|
||||
int spaces, args, port_start, port_end;
|
||||
struct stat st;
|
||||
int sock, port;
|
||||
struct hostent *host;
|
||||
struct in_addr tmpaddr;
|
||||
struct sockaddr_in addr;
|
||||
socklen_t length;
|
||||
unsigned long local_addr;
|
||||
@@ -811,11 +833,32 @@ dcc_send_request (t_irc_server *server, int type, char *nick, char *filename)
|
||||
}
|
||||
|
||||
/* get local IP address */
|
||||
|
||||
/* look up the IP address from dcc_own_ip, if set */
|
||||
local_addr = 0;
|
||||
if (cfg_dcc_own_ip && cfg_dcc_own_ip[0])
|
||||
{
|
||||
host = gethostbyname (cfg_dcc_own_ip);
|
||||
if (host)
|
||||
{
|
||||
memcpy (&tmpaddr, host->h_addr_list[0], sizeof(struct in_addr));
|
||||
local_addr = ntohl (tmpaddr.s_addr);
|
||||
}
|
||||
else
|
||||
gui_printf (server->buffer,
|
||||
_("%s could not find address for '%s'. Falling back to local IP.\n"),
|
||||
WEECHAT_WARNING, cfg_dcc_own_ip);
|
||||
}
|
||||
|
||||
/* use the local interface, from the server socket */
|
||||
memset (&addr, 0, sizeof (struct sockaddr_in));
|
||||
length = sizeof (addr);
|
||||
getsockname (server->sock, (struct sockaddr *) &addr, &length);
|
||||
addr.sin_family = AF_INET;
|
||||
local_addr = ntohl (addr.sin_addr.s_addr);
|
||||
|
||||
/* fallback to the local IP address on the interface, if required */
|
||||
if (local_addr == 0)
|
||||
local_addr = ntohl (addr.sin_addr.s_addr);
|
||||
|
||||
/* open socket for DCC */
|
||||
sock = socket (AF_INET, SOCK_STREAM, 0);
|
||||
@@ -830,22 +873,63 @@ dcc_send_request (t_irc_server *server, int type, char *nick, char *filename)
|
||||
return;
|
||||
}
|
||||
|
||||
/* find port automatically */
|
||||
addr.sin_port = 0;
|
||||
if (bind (sock, (struct sockaddr *) &addr, sizeof (addr)) == -1)
|
||||
/* look for port */
|
||||
|
||||
port = 0;
|
||||
|
||||
if (cfg_dcc_port_range && cfg_dcc_port_range[0])
|
||||
{
|
||||
/* find a free port in the specified range */
|
||||
args = sscanf (cfg_dcc_port_range, "%d-%d", &port_start, &port_end);
|
||||
if (args > 0)
|
||||
{
|
||||
port = port_start;
|
||||
if (args == 1)
|
||||
port_end = port_start;
|
||||
|
||||
/* loop through the entire allowed port range */
|
||||
while (port <= port_end)
|
||||
{
|
||||
if (!dcc_port_in_use (port))
|
||||
{
|
||||
/* attempt to bind to the free port */
|
||||
addr.sin_port = htons (port);
|
||||
if (bind (sock, (struct sockaddr *) &addr, sizeof (addr)) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (port > port_end)
|
||||
port = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (port == 0)
|
||||
{
|
||||
/* find port automatically */
|
||||
addr.sin_port = 0;
|
||||
if (bind (sock, (struct sockaddr *) &addr, sizeof (addr)) == 0)
|
||||
{
|
||||
length = sizeof (addr);
|
||||
getsockname (sock, (struct sockaddr *) &addr, &length);
|
||||
port = ntohs (addr.sin_port);
|
||||
}
|
||||
else
|
||||
port = -1;
|
||||
}
|
||||
|
||||
if (port == -1)
|
||||
{
|
||||
/* Could not find any port to bind */
|
||||
irc_display_prefix (server->buffer, PREFIX_ERROR);
|
||||
gui_printf (server->buffer,
|
||||
_("%s cannot find port for DCC\n"),
|
||||
_("%s cannot find available port for DCC\n"),
|
||||
WEECHAT_ERROR);
|
||||
close (sock);
|
||||
if (filename2)
|
||||
free (filename2);
|
||||
return;
|
||||
}
|
||||
length = sizeof (addr);
|
||||
getsockname (sock, (struct sockaddr *) &addr, &length);
|
||||
port = ntohs (addr.sin_port);
|
||||
|
||||
if (type == DCC_FILE_SEND)
|
||||
{
|
||||
|
||||
+2
-1
@@ -1,10 +1,11 @@
|
||||
WeeChat - Wee Enhanced Environment for Chat
|
||||
===========================================
|
||||
|
||||
ChangeLog - 2005-10-21
|
||||
ChangeLog - 2005-10-22
|
||||
|
||||
|
||||
Version 0.1.6 (under dev!):
|
||||
* added dcc_own_ip and dcc_port_range settings
|
||||
* full UTF-8 support, auto-detection of UTF-8 usage (locale)
|
||||
* added "Day changed to [date]" message when day changes
|
||||
* new plugin interface, rewritten from scratch: now loads dynamic C
|
||||
|
||||
+361
-279
File diff suppressed because it is too large
Load Diff
+275
-241
File diff suppressed because it is too large
Load Diff
+279
-239
File diff suppressed because it is too large
Load Diff
+267
-236
File diff suppressed because it is too large
Load Diff
@@ -136,8 +136,11 @@ t_weechat_command weechat_commands[] =
|
||||
"Without argument, /unignore command lists all defined ignore."),
|
||||
0, 4, weechat_cmd_unignore, NULL },
|
||||
{ "window", N_("manage windows"),
|
||||
N_("[list | splith | splitv | [merge [down | up | left | right | all]]]"),
|
||||
N_("[list | -1 | +1 | b# | splith | splitv | [merge [down | up | left | right | all]]]"),
|
||||
N_("list: list opened windows (no parameter implies this list)\n"
|
||||
"-1: jump to previous window\n"
|
||||
"+1: jump to next window\n"
|
||||
"b#: jump to next window displaying buffer number #\n"
|
||||
"splith: split current window horizontally\n"
|
||||
"splitv: split current window vertically\n"
|
||||
"merge: merge window with another"),
|
||||
@@ -2511,6 +2514,8 @@ weechat_cmd_window (int argc, char **argv)
|
||||
{
|
||||
t_gui_window *ptr_win;
|
||||
int i;
|
||||
char *error;
|
||||
long number;
|
||||
|
||||
if ((argc == 0) || ((argc == 1) && (ascii_strcasecmp (argv[0], "list") == 0)))
|
||||
{
|
||||
@@ -2577,6 +2582,14 @@ weechat_cmd_window (int argc, char **argv)
|
||||
else
|
||||
gui_window_merge_auto (gui_current_window);
|
||||
}
|
||||
else if (ascii_strncasecmp (argv[0], "b", 1) == 0)
|
||||
{
|
||||
/* jump to window by buffer number */
|
||||
error = NULL;
|
||||
number = strtol (argv[0] + 1, &error, 10);
|
||||
if ((error) && (error[0] == '\0'))
|
||||
gui_switch_to_window_by_buffer (gui_current_window, number);
|
||||
}
|
||||
else if (ascii_strcasecmp (argv[0], "-1") == 0)
|
||||
gui_switch_to_previous_window (gui_current_window);
|
||||
else if (ascii_strcasecmp (argv[0], "+1") == 0)
|
||||
|
||||
@@ -420,7 +420,7 @@ t_config_option weechat_options_colors[] =
|
||||
{ "col_input_delimiters", N_("color for input text (delimiters)"),
|
||||
N_("color for input text (delimiters)"),
|
||||
OPTION_TYPE_COLOR, 0, 0, 0,
|
||||
"lightgreen", NULL, &cfg_col_input_delimiters, NULL, &config_change_color },
|
||||
"white", NULL, &cfg_col_input_delimiters, NULL, &config_change_color },
|
||||
{ "col_input_bg", N_("background for input window"),
|
||||
N_("background for input window"),
|
||||
OPTION_TYPE_COLOR, 0, 0, 0,
|
||||
@@ -677,6 +677,8 @@ int cfg_dcc_auto_accept_files;
|
||||
int cfg_dcc_auto_accept_chats;
|
||||
int cfg_dcc_timeout;
|
||||
int cfg_dcc_blocksize;
|
||||
char *cfg_dcc_port_range;
|
||||
char *cfg_dcc_own_ip;
|
||||
char *cfg_dcc_download_path;
|
||||
char *cfg_dcc_upload_path;
|
||||
int cfg_dcc_convert_spaces;
|
||||
@@ -700,6 +702,17 @@ t_config_option weechat_options_dcc[] =
|
||||
N_("block size for dcc packets in bytes (default: 65536)"),
|
||||
OPTION_TYPE_INT, 1024, 102400, 65536,
|
||||
NULL, NULL, &cfg_dcc_blocksize, NULL, &config_change_noop },
|
||||
{ "dcc_port_range", N_("allowed ports for outgoing dcc"),
|
||||
N_("restricts outgoing dcc to use only ports in the given range "
|
||||
"(useful for NAT) (syntax: a single port, ie. 5000 or a port "
|
||||
"range, ie. 5000-5015, empty value means any port)"),
|
||||
OPTION_TYPE_STRING, 0, 0, 0, "",
|
||||
NULL, NULL, &cfg_dcc_port_range, &config_change_noop },
|
||||
{ "dcc_own_ip", N_("IP address for outgoing dcc"),
|
||||
N_("IP or DNS address used for outgoing dcc "
|
||||
"(if empty, local interface IP is used)"),
|
||||
OPTION_TYPE_STRING, 0, 0, 0, "",
|
||||
NULL, NULL, &cfg_dcc_own_ip, &config_change_noop },
|
||||
{ "dcc_download_path", N_("path for incoming files with dcc"),
|
||||
N_("path for writing incoming files with dcc (default: user home)"),
|
||||
OPTION_TYPE_STRING, 0, 0, 0,
|
||||
|
||||
@@ -191,6 +191,8 @@ extern int cfg_dcc_auto_accept_files;
|
||||
extern int cfg_dcc_auto_accept_chats;
|
||||
extern int cfg_dcc_timeout;
|
||||
extern int cfg_dcc_blocksize;
|
||||
extern char *cfg_dcc_port_range;
|
||||
extern char *cfg_dcc_own_ip;
|
||||
extern char *cfg_dcc_download_path;
|
||||
extern char *cfg_dcc_upload_path;
|
||||
extern int cfg_dcc_convert_spaces;
|
||||
|
||||
@@ -256,10 +256,15 @@ gui_input_read ()
|
||||
|
||||
if ((gui_key_pressed (key_str) != 0) && (insert_ok))
|
||||
{
|
||||
gui_input_insert_string (gui_current_window, key_str, -1);
|
||||
gui_current_window->buffer->input_buffer_pos += utf8_strlen (key_str);
|
||||
gui_draw_buffer_input (gui_current_window->buffer, 0);
|
||||
gui_current_window->buffer->completion.position = -1;
|
||||
if (gui_current_window->buffer->dcc)
|
||||
gui_input_action_dcc (gui_current_window, key_str);
|
||||
else
|
||||
{
|
||||
gui_input_insert_string (gui_current_window, key_str, -1);
|
||||
gui_current_window->buffer->input_buffer_pos += utf8_strlen (key_str);
|
||||
gui_draw_buffer_input (gui_current_window->buffer, 0);
|
||||
gui_current_window->buffer->completion.position = -1;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
+100
-72
@@ -609,78 +609,89 @@ gui_input_optimize_buffer_size (t_gui_buffer *buffer)
|
||||
|
||||
/*
|
||||
* gui_input_action_dcc: execute an action on a DCC after a user input
|
||||
* return -1 if DCC buffer was closed due to action, 0 otherwise
|
||||
*/
|
||||
|
||||
void
|
||||
gui_input_action_dcc (t_gui_window *window, char action)
|
||||
gui_input_action_dcc (t_gui_window *window, char *actions)
|
||||
{
|
||||
t_irc_dcc *dcc_selected, *ptr_dcc, *ptr_dcc_next;
|
||||
t_gui_buffer *ptr_buffer;
|
||||
|
||||
dcc_selected = (window->dcc_selected) ?
|
||||
(t_irc_dcc *) window->dcc_selected : dcc_list;
|
||||
|
||||
switch (action)
|
||||
while (actions[0])
|
||||
{
|
||||
/* accept DCC */
|
||||
case 'a':
|
||||
case 'A':
|
||||
if (dcc_selected
|
||||
&& (DCC_IS_RECV(dcc_selected->status))
|
||||
&& (dcc_selected->status == DCC_WAITING))
|
||||
if (actions[0] >= 32)
|
||||
{
|
||||
dcc_selected = (window->dcc_selected) ?
|
||||
(t_irc_dcc *) window->dcc_selected : dcc_list;
|
||||
|
||||
switch (actions[0])
|
||||
{
|
||||
dcc_accept (dcc_selected);
|
||||
}
|
||||
break;
|
||||
/* cancel DCC */
|
||||
case 'c':
|
||||
case 'C':
|
||||
if (dcc_selected
|
||||
&& (!DCC_ENDED(dcc_selected->status)))
|
||||
{
|
||||
dcc_close (dcc_selected, DCC_ABORTED);
|
||||
gui_redraw_buffer (window->buffer);
|
||||
}
|
||||
break;
|
||||
/* purge old DCC */
|
||||
case 'p':
|
||||
case 'P':
|
||||
window->dcc_selected = NULL;
|
||||
ptr_dcc = dcc_list;
|
||||
while (ptr_dcc)
|
||||
{
|
||||
ptr_dcc_next = ptr_dcc->next_dcc;
|
||||
if (DCC_ENDED(ptr_dcc->status))
|
||||
dcc_free (ptr_dcc);
|
||||
ptr_dcc = ptr_dcc_next;
|
||||
}
|
||||
gui_redraw_buffer (window->buffer);
|
||||
break;
|
||||
/* close DCC window */
|
||||
case 'q':
|
||||
case 'Q':
|
||||
if (buffer_before_dcc)
|
||||
{
|
||||
gui_buffer_free (window->buffer, 1);
|
||||
gui_switch_to_buffer (window, buffer_before_dcc);
|
||||
}
|
||||
else
|
||||
gui_buffer_free (window->buffer, 1);
|
||||
gui_redraw_buffer (window->buffer);
|
||||
break;
|
||||
/* remove from DCC list */
|
||||
case 'r':
|
||||
case 'R':
|
||||
if (dcc_selected
|
||||
&& (DCC_ENDED(dcc_selected->status)))
|
||||
{
|
||||
if (dcc_selected->next_dcc)
|
||||
window->dcc_selected = dcc_selected->next_dcc;
|
||||
else
|
||||
/* accept DCC */
|
||||
case 'a':
|
||||
case 'A':
|
||||
if (dcc_selected
|
||||
&& (DCC_IS_RECV(dcc_selected->status))
|
||||
&& (dcc_selected->status == DCC_WAITING))
|
||||
{
|
||||
dcc_accept (dcc_selected);
|
||||
}
|
||||
break;
|
||||
/* cancel DCC */
|
||||
case 'c':
|
||||
case 'C':
|
||||
if (dcc_selected
|
||||
&& (!DCC_ENDED(dcc_selected->status)))
|
||||
{
|
||||
dcc_close (dcc_selected, DCC_ABORTED);
|
||||
gui_redraw_buffer (window->buffer);
|
||||
}
|
||||
break;
|
||||
/* purge old DCC */
|
||||
case 'p':
|
||||
case 'P':
|
||||
window->dcc_selected = NULL;
|
||||
dcc_free (dcc_selected);
|
||||
gui_redraw_buffer (window->buffer);
|
||||
ptr_dcc = dcc_list;
|
||||
while (ptr_dcc)
|
||||
{
|
||||
ptr_dcc_next = ptr_dcc->next_dcc;
|
||||
if (DCC_ENDED(ptr_dcc->status))
|
||||
dcc_free (ptr_dcc);
|
||||
ptr_dcc = ptr_dcc_next;
|
||||
}
|
||||
gui_redraw_buffer (window->buffer);
|
||||
break;
|
||||
/* close DCC window */
|
||||
case 'q':
|
||||
case 'Q':
|
||||
if (buffer_before_dcc)
|
||||
{
|
||||
ptr_buffer = window->buffer;
|
||||
gui_switch_to_buffer (window, buffer_before_dcc);
|
||||
gui_buffer_free (ptr_buffer, 0);
|
||||
}
|
||||
else
|
||||
gui_buffer_free (window->buffer, 1);
|
||||
gui_redraw_buffer (window->buffer);
|
||||
return;
|
||||
break;
|
||||
/* remove from DCC list */
|
||||
case 'r':
|
||||
case 'R':
|
||||
if (dcc_selected
|
||||
&& (DCC_ENDED(dcc_selected->status)))
|
||||
{
|
||||
if (dcc_selected->next_dcc)
|
||||
window->dcc_selected = dcc_selected->next_dcc;
|
||||
else
|
||||
window->dcc_selected = NULL;
|
||||
dcc_free (dcc_selected);
|
||||
gui_redraw_buffer (window->buffer);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
actions = utf8_next_char (actions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -697,16 +708,7 @@ gui_input_insert_string (t_gui_window *window, char *string, int pos)
|
||||
int size, length;
|
||||
char *ptr_start;
|
||||
|
||||
if (window->buffer->dcc)
|
||||
{
|
||||
while (string[0])
|
||||
{
|
||||
if (string[0] >= 32)
|
||||
gui_input_action_dcc (window, string[0]);
|
||||
string = utf8_next_char (string);
|
||||
}
|
||||
}
|
||||
else if (window->buffer->has_input)
|
||||
if (window->buffer->has_input)
|
||||
{
|
||||
if (pos == -1)
|
||||
pos = window->buffer->input_buffer_pos;
|
||||
@@ -1760,6 +1762,32 @@ gui_switch_to_next_window (t_gui_window *window)
|
||||
gui_redraw_buffer (gui_current_window->buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
* gui_switch_to_window_by_buffer: switch to next window displaying a buffer
|
||||
*/
|
||||
|
||||
void
|
||||
gui_switch_to_window_by_buffer (t_gui_window *window, int buffer_number)
|
||||
{
|
||||
t_gui_window *ptr_win;
|
||||
|
||||
if (!gui_ok)
|
||||
return;
|
||||
|
||||
ptr_win = (window->next_window) ? window->next_window : gui_windows;
|
||||
while (ptr_win != window)
|
||||
{
|
||||
if (ptr_win->buffer->number == buffer_number)
|
||||
{
|
||||
gui_current_window = ptr_win;
|
||||
gui_switch_to_buffer (gui_current_window, gui_current_window->buffer);
|
||||
gui_redraw_buffer (gui_current_window->buffer);
|
||||
return;
|
||||
}
|
||||
ptr_win = (ptr_win->next_window) ? ptr_win->next_window : gui_windows;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* gui_switch_to_dcc_buffer: switch to dcc buffer (create it if it does not exist)
|
||||
*/
|
||||
|
||||
@@ -331,6 +331,7 @@ extern t_gui_line *gui_new_line (t_gui_buffer *);
|
||||
extern t_gui_message *gui_new_message (t_gui_buffer *);
|
||||
extern void gui_input_clipboard_copy (char *, int);
|
||||
extern void gui_input_clipboard_paste (t_gui_window *);
|
||||
extern void gui_input_action_dcc (t_gui_window *, char *);
|
||||
extern int gui_input_insert_string (t_gui_window *, char *, int);
|
||||
extern void gui_input_return (t_gui_window *);
|
||||
extern void gui_input_tab (t_gui_window *);
|
||||
@@ -364,6 +365,7 @@ extern void gui_switch_to_previous_buffer (t_gui_window *);
|
||||
extern void gui_switch_to_next_buffer (t_gui_window *);
|
||||
extern void gui_switch_to_previous_window (t_gui_window *);
|
||||
extern void gui_switch_to_next_window (t_gui_window *);
|
||||
extern void gui_switch_to_window_by_buffer (t_gui_window *, int);
|
||||
extern void gui_switch_to_dcc_buffer (t_gui_window *);
|
||||
extern t_gui_buffer *gui_switch_to_buffer_by_number (t_gui_window *, int);
|
||||
extern void gui_move_buffer_to_number (t_gui_window *, int);
|
||||
|
||||
@@ -87,6 +87,26 @@ dcc_search (t_irc_server *server, int type, int status, int port)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* dcc_port_in_use: return 1 if a port is in used (by an active or connecting DCC)
|
||||
*/
|
||||
|
||||
int
|
||||
dcc_port_in_use (int port)
|
||||
{
|
||||
t_irc_dcc *ptr_dcc;
|
||||
|
||||
/* skip any currently used ports */
|
||||
for (ptr_dcc = dcc_list; ptr_dcc; ptr_dcc = ptr_dcc->next_dcc)
|
||||
{
|
||||
if ((ptr_dcc->port == port) && (!DCC_ENDED(ptr_dcc->status)))
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* port not in use */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* dcc_file_is_resumable: check if a file can be used for resuming a download
|
||||
*/
|
||||
@@ -748,9 +768,11 @@ void
|
||||
dcc_send_request (t_irc_server *server, int type, char *nick, char *filename)
|
||||
{
|
||||
char *ptr_home, *filename2, *short_filename, *pos;
|
||||
int spaces;
|
||||
int spaces, args, port_start, port_end;
|
||||
struct stat st;
|
||||
int sock, port;
|
||||
struct hostent *host;
|
||||
struct in_addr tmpaddr;
|
||||
struct sockaddr_in addr;
|
||||
socklen_t length;
|
||||
unsigned long local_addr;
|
||||
@@ -811,11 +833,32 @@ dcc_send_request (t_irc_server *server, int type, char *nick, char *filename)
|
||||
}
|
||||
|
||||
/* get local IP address */
|
||||
|
||||
/* look up the IP address from dcc_own_ip, if set */
|
||||
local_addr = 0;
|
||||
if (cfg_dcc_own_ip && cfg_dcc_own_ip[0])
|
||||
{
|
||||
host = gethostbyname (cfg_dcc_own_ip);
|
||||
if (host)
|
||||
{
|
||||
memcpy (&tmpaddr, host->h_addr_list[0], sizeof(struct in_addr));
|
||||
local_addr = ntohl (tmpaddr.s_addr);
|
||||
}
|
||||
else
|
||||
gui_printf (server->buffer,
|
||||
_("%s could not find address for '%s'. Falling back to local IP.\n"),
|
||||
WEECHAT_WARNING, cfg_dcc_own_ip);
|
||||
}
|
||||
|
||||
/* use the local interface, from the server socket */
|
||||
memset (&addr, 0, sizeof (struct sockaddr_in));
|
||||
length = sizeof (addr);
|
||||
getsockname (server->sock, (struct sockaddr *) &addr, &length);
|
||||
addr.sin_family = AF_INET;
|
||||
local_addr = ntohl (addr.sin_addr.s_addr);
|
||||
|
||||
/* fallback to the local IP address on the interface, if required */
|
||||
if (local_addr == 0)
|
||||
local_addr = ntohl (addr.sin_addr.s_addr);
|
||||
|
||||
/* open socket for DCC */
|
||||
sock = socket (AF_INET, SOCK_STREAM, 0);
|
||||
@@ -830,22 +873,63 @@ dcc_send_request (t_irc_server *server, int type, char *nick, char *filename)
|
||||
return;
|
||||
}
|
||||
|
||||
/* find port automatically */
|
||||
addr.sin_port = 0;
|
||||
if (bind (sock, (struct sockaddr *) &addr, sizeof (addr)) == -1)
|
||||
/* look for port */
|
||||
|
||||
port = 0;
|
||||
|
||||
if (cfg_dcc_port_range && cfg_dcc_port_range[0])
|
||||
{
|
||||
/* find a free port in the specified range */
|
||||
args = sscanf (cfg_dcc_port_range, "%d-%d", &port_start, &port_end);
|
||||
if (args > 0)
|
||||
{
|
||||
port = port_start;
|
||||
if (args == 1)
|
||||
port_end = port_start;
|
||||
|
||||
/* loop through the entire allowed port range */
|
||||
while (port <= port_end)
|
||||
{
|
||||
if (!dcc_port_in_use (port))
|
||||
{
|
||||
/* attempt to bind to the free port */
|
||||
addr.sin_port = htons (port);
|
||||
if (bind (sock, (struct sockaddr *) &addr, sizeof (addr)) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (port > port_end)
|
||||
port = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (port == 0)
|
||||
{
|
||||
/* find port automatically */
|
||||
addr.sin_port = 0;
|
||||
if (bind (sock, (struct sockaddr *) &addr, sizeof (addr)) == 0)
|
||||
{
|
||||
length = sizeof (addr);
|
||||
getsockname (sock, (struct sockaddr *) &addr, &length);
|
||||
port = ntohs (addr.sin_port);
|
||||
}
|
||||
else
|
||||
port = -1;
|
||||
}
|
||||
|
||||
if (port == -1)
|
||||
{
|
||||
/* Could not find any port to bind */
|
||||
irc_display_prefix (server->buffer, PREFIX_ERROR);
|
||||
gui_printf (server->buffer,
|
||||
_("%s cannot find port for DCC\n"),
|
||||
_("%s cannot find available port for DCC\n"),
|
||||
WEECHAT_ERROR);
|
||||
close (sock);
|
||||
if (filename2)
|
||||
free (filename2);
|
||||
return;
|
||||
}
|
||||
length = sizeof (addr);
|
||||
getsockname (sock, (struct sockaddr *) &addr, &length);
|
||||
port = ntohs (addr.sin_port);
|
||||
|
||||
if (type == DCC_FILE_SEND)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user