irctk

libircclient binding for scripts
git clone https://a3nm.net/git/irctk/
Log | Files | Refs | README

commit 3c497099822920b38c34fb62b95465d988832d96
parent 2226320bf9f041bf7a5e80d1b07d64ddc06cf7f0
Author: Antoine Amarilli <a3nm@a3nm.net>
Date:   Tue,  7 Aug 2012 21:57:46 +0200

fix channel password handling, add test for it

Diffstat:
irctk.c | 76++++++++++++++++++++++++++++++++++++++++++++--------------------------------
test/password.sh | 14++++++++++++++
2 files changed, 58 insertions(+), 32 deletions(-)

diff --git a/irctk.c b/irctk.c @@ -912,27 +912,6 @@ char* first_chan() else return args.nick; } -/* Join a channel, optionally suffixed with :PASSWORD */ -int join_channel(irc_session_t *s, char* chan) -{ - char *password = chan; - int pos = 0; - int ret; - // find the password if the password indicates a chan (last ':') - while (password[pos] != ':' && password[pos]) - pos++; - if (password[pos]) { - chan[pos] = 0; - password += pos + 1; - } else { - password = NULL; - } - ret = irc_cmd_join (s, chan, password); - if (password) - chan[pos] = ':'; - return ret; -} - const char *input_nick(const char *nick) { int c; const char *result; @@ -993,10 +972,10 @@ char* consume_word(char **from) return result; } -int do_say(irc_session_t *s, char *chan, char *line) { +int do_say(irc_session_t *s, char *chan, char *password, char *line) { /* TODO2 only join channels we haven't joined yet */ if (args.join) - join_channel(s, chan); + irc_cmd_join(s, chan, password); if (args.own) { mprintf("[%s] <%s%s> %s", chan, output_nick(args.nick), @@ -1007,12 +986,31 @@ int do_say(irc_session_t *s, char *chan, char *line) { return irc_cmd_msg(s, chan, line); } +/* If chan is suffixed by a password, modify it and return the modified offset */ +int get_password(char *chan) { + int pos = 0; + while (chan[pos] != ':' && chan[pos]) + pos++; + if (chan[pos]) { + chan[pos] = 0; + return pos; + } + return -1; +} + +void revert_password(char *chan, int pos) { + if (pos < 0) return; + chan[pos] = ':'; +} + /* Send a message or do a command */ /* Return value is 0 if OK, >0 if error, -1 if correctly exited */ int do_cmd_msg(irc_session_t *s, char *chan, char* line) { int rsl = 0; + int pw_pos = get_password(chan); + char *password = chan + pw_pos + 1; debug("do_cmd_msg %s %s\n", chan, line); @@ -1035,6 +1033,8 @@ int do_cmd_msg(irc_session_t *s, char *chan, char* line) } } else if ((arg = MATCH_CMD0(line, "join"))) { char *to_join = NULL; + // we must revert temporarily so that we can join + revert_password(chan, pw_pos); if (!*arg || *arg == '\n') { to_join = chan; } else if (*arg == ' ') { @@ -1042,13 +1042,19 @@ int do_cmd_msg(irc_session_t *s, char *chan, char* line) } if (to_join) { if (args.join) { - rsl = join_channel(s, to_join); + // now, get the right index + int pw_pos2 = get_password(to_join); + rsl = irc_cmd_join(s, to_join, to_join + pw_pos2 + 1); + // and revert + revert_password(to_join, pw_pos); } else { info("Will not join because --no-auto-join was set\n"); } } else { info("Unrecognized command: %s", line); } + // and we go back to the previous state + pw_pos = get_password(chan); } else if ((arg = MATCH_CMD(line, "topic"))) { rsl = irc_cmd_topic(s, chan, arg); } else if ((arg = MATCH_CMD0(line, "quit"))) { @@ -1073,10 +1079,10 @@ int do_cmd_msg(irc_session_t *s, char *chan, char* line) free(knick); } else if ((arg = MATCH_CMD0(line, "say"))) { // just a way to escape messages starting by '/' - rsl = do_say(s, chan, arg + (*arg?1:0)); + rsl = do_say(s, chan, password, arg + (*arg?1:0)); } else if (line[1] == ' ') { // another way, compatible with irssi: "/ /message" - rsl = do_say(s, chan, line + 2); + rsl = do_say(s, chan, password, line + 2); } else { info("Unrecognized or malformed command: %s", line); } @@ -1084,8 +1090,9 @@ int do_cmd_msg(irc_session_t *s, char *chan, char* line) // with correct user tracking! } else { /* TODO2 only join channels we haven't joined yet */ - if (args.join) - join_channel(s, chan); + if (args.join) { + rsl = irc_cmd_join(s, chan, password); + } if (args.track != NO) { char lline[MAX_LINE_LEN + MAX_NICK_LEN + 2]; @@ -1100,7 +1107,7 @@ int do_cmd_msg(irc_session_t *s, char *chan, char* line) break; } if (seppos == -1) { - rsl = do_say(s, chan, line); + rsl = do_say(s, chan, password, line); } else { char sep; sep = line[seppos]; @@ -1114,12 +1121,15 @@ int do_cmd_msg(irc_session_t *s, char *chan, char* line) pthread_mutex_unlock(&fifos.ctrl.mutex); line[seppos] = sep; strncat(lline, line + seppos, MAX_LINE_LEN-1); - rsl = do_say(s, chan, lline); + rsl = do_say(s, chan, password, lline); } } else { - rsl = do_say(s, chan, line); + rsl = do_say(s, chan, password, line); } } + + revert_password(chan, pw_pos); + if (rsl) return rsl; @@ -1417,7 +1427,9 @@ void event_connect (irc_session_t *session, const char *event, const char *origi for (i = 0; i < ctx->n_channels; i++) { debug("Attempt to join %s\n", ctx->channels[i]); - join_channel (session, ctx->channels[i]); + int pw_pos = get_password(ctx->channels[i]); + irc_cmd_join (session, ctx->channels[i], ctx->channels[i] + pw_pos + 1); + revert_password(ctx->channels[i], pw_pos); } } diff --git a/test/password.sh b/test/password.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +trap 'kill $(jobs -p)' EXIT + +(echo -e "/mode +n\n/mode +k hunter2"; tail -f /dev/null) | + ../irctk op@localhost \#test:useless > heard & +PID=$! +sleep 2 +echo ok | ../irctk ok@localhost \#test:hunter2 2>/dev/null >/dev/null +echo ko | ../irctk ko@localhost \#test:hunter3 2>/dev/null >/dev/null +sleep 2 +kill $PID +grep "ok" heard > /dev/null && grep -v "ko" heard > /dev/null +