diff options
Diffstat (limited to 'src/irc')
-rw-r--r-- | src/irc/core/irc-commands.c | 32 | ||||
-rw-r--r-- | src/irc/core/irc-servers.c | 37 | ||||
-rw-r--r-- | src/irc/core/irc-servers.h | 3 |
3 files changed, 72 insertions, 0 deletions
diff --git a/src/irc/core/irc-commands.c b/src/irc/core/irc-commands.c index bbb2ee05..d3eefbbf 100644 --- a/src/irc/core/irc-commands.c +++ b/src/irc/core/irc-commands.c @@ -43,6 +43,13 @@ is required */ #define LIST_MAX_CHANNELS_PASS 1000 +/* When /PARTing a channel, if there's more messages in output queue + than this, purge the output for channel. The idea behind this is that + if you accidentally pasted some large text and /PART the channel, the + text won't be fully pasted. Note that this counter is the whole size + of the output queue, not channel specific.. */ +#define MAX_COMMANDS_ON_PART_UNTIL_PURGE 10 + typedef struct { IRC_CHANNEL_REC *channel; char *ban; @@ -132,6 +139,10 @@ static void cmd_part(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item if (*channame == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); if (*msg == '\0') msg = (char *) settings_get_str("part_message"); + + if (server->cmdcount > MAX_COMMANDS_ON_PART_UNTIL_PURGE) + irc_server_purge_output(server, channame); + irc_send_cmdv(server, *msg == '\0' ? "PART %s" : "PART %s :%s", channame, msg); @@ -833,6 +844,24 @@ static void cmd_knockout(const char *data, IRC_SERVER_REC *server, cmd_params_free(free_arg); } +/* SYNTAX: SERVER PURGE [<target>] */ +static void cmd_server_purge(const char *data, IRC_SERVER_REC *server) +{ + char *target; + void *free_arg; + + g_return_if_fail(data != NULL); + if (!IS_IRC_SERVER(server) || !server->connected) + cmd_return_error(CMDERR_NOT_CONNECTED); + + if (!cmd_get_params(data, &free_arg, 1, &target)) + return; + + irc_server_purge_output(server, *target == '\0' ? NULL : target); + + cmd_params_free(free_arg); +} + /* destroy all knockouts in server */ static void sig_server_disconnected(IRC_SERVER_REC *server) { @@ -1060,6 +1089,7 @@ void irc_commands_init(void) command_bind("wallchops", NULL, (SIGNAL_FUNC) command_2self); command_bind("kickban", NULL, (SIGNAL_FUNC) cmd_kickban); command_bind("knockout", NULL, (SIGNAL_FUNC) cmd_knockout); + command_bind("server purge", NULL, (SIGNAL_FUNC) cmd_server_purge); signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed); signal_add("server disconnected", (SIGNAL_FUNC) sig_server_disconnected); @@ -1131,6 +1161,8 @@ void irc_commands_deinit(void) command_unbind("wallchops", (SIGNAL_FUNC) command_2self); command_unbind("kickban", (SIGNAL_FUNC) cmd_kickban); command_unbind("knockout", (SIGNAL_FUNC) cmd_knockout); + command_unbind("server purge", (SIGNAL_FUNC) cmd_server_purge); + signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed); signal_remove("server disconnected", (SIGNAL_FUNC) sig_server_disconnected); signal_remove("nickchange over", (SIGNAL_FUNC) sig_nickchange_over); diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index 0d07149f..11cef94d 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -187,6 +187,43 @@ IRC_SERVER_REC *irc_server_connect(IRC_SERVER_CONNECT_REC *conn) return server; } +/* Returns TRUE if `command' is sent to `target' */ +static int command_has_target(const char *cmd, const char *target) +{ + const char *p; + int len; + + /* just assume the command is in form "<command> <target> <data>" */ + p = strchr(cmd, ' '); + if (p == NULL) return FALSE; + p++; + + len = strlen(target); + return strncmp(p, target, len) == 0 && p[len] == ' '; +} + +/* Purge server output, either all or for specified target */ +void irc_server_purge_output(IRC_SERVER_REC *server, const char *target) +{ + GSList *tmp, *next; + char *cmd; + + if (target != NULL && *target == '\0') + target = NULL; + + for (tmp = server->cmdqueue; tmp != NULL; tmp = next) { + next = tmp->next; + cmd = tmp->data; + + if ((target == NULL || command_has_target(cmd, target)) && + g_strncasecmp(cmd, "PONG ", 5) != 0) { + server->cmdqueue = + g_slist_remove(server->cmdqueue, cmd); + server->cmdcount--; + } + } +} + static void sig_connected(IRC_SERVER_REC *server) { if (!IS_IRC_SERVER(server)) diff --git a/src/irc/core/irc-servers.h b/src/irc/core/irc-servers.h index e9d357ba..9a4f0ea8 100644 --- a/src/irc/core/irc-servers.h +++ b/src/irc/core/irc-servers.h @@ -91,6 +91,9 @@ typedef struct { IRC_SERVER_REC *irc_server_connect(IRC_SERVER_CONNECT_REC *conn); +/* Purge server output, either all or for specified target */ +void irc_server_purge_output(IRC_SERVER_REC *server, const char *target); + /* Return a string of all channels (and keys, if any have them) in server, like "#a,#b,#c,#d x,b_chan_key,x,x" or just "#e,#f,#g" */ char *irc_server_get_channels(IRC_SERVER_REC *server); |