diff options
Diffstat (limited to 'degesch.c')
-rw-r--r-- | degesch.c | 69 |
1 files changed, 58 insertions, 11 deletions
@@ -1048,7 +1048,7 @@ struct server struct str_map irc_buffer_map; ///< Maps IRC identifiers to buffers struct user *irc_user; ///< Our own user - char *irc_user_mode; ///< Our current user mode + struct str irc_user_mode; ///< Our current user modes char *irc_user_host; ///< Our current user@host // Server-specific information (from RPL_ISUPPORT): @@ -1091,6 +1091,8 @@ server_init (struct server *self, struct poller *poller) str_init (&self->read_buffer); self->state = IRC_DISCONNECTED; + str_init (&self->irc_user_mode); + // Defaults as per the RPL_ISUPPORT drafts, or RFC 1459 self->irc_tolower = irc_tolower; self->irc_strxfrm = irc_strxfrm; @@ -1151,7 +1153,7 @@ server_free (struct server *self) if (self->irc_user) user_unref (self->irc_user); - free (self->irc_user_mode); + str_free (&self->irc_user_mode); free (self->irc_user_host); free (self->irc_chantypes); @@ -3184,8 +3186,7 @@ on_irc_disconnected (struct server *s) s->irc_user = NULL; } - free (s->irc_user_mode); - s->irc_user_mode = NULL; + str_reset (&s->irc_user_mode); free (s->irc_user_host); s->irc_user_host = NULL; @@ -3703,8 +3704,8 @@ make_prompt (struct app_context *ctx, struct str *output) str_append (output, channel_user->prefixes.str); } str_append (output, s->irc_user->nickname); - if (*s->irc_user_mode) - str_append_printf (output, "(%s)", s->irc_user_mode); + if (s->irc_user_mode.len) + str_append_printf (output, "(%s)", s->irc_user_mode.str); } } @@ -3985,6 +3986,8 @@ mode_processor_next_param (struct mode_processor *self) return *self->params++; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + static void mode_processor_do_user (struct mode_processor *self) { @@ -4092,8 +4095,6 @@ mode_processor_step (struct mode_processor *self, char mode_char) return true; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - static void irc_handle_mode_channel (struct server *s, struct channel *channel, char **params) @@ -4115,6 +4116,52 @@ irc_handle_mode_channel } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +static bool +mode_processor_step_user (struct mode_processor *self, char mode_char) +{ + struct server *s = self->s; + + if (mode_char == '+') { self->adding = true; return true; } + if (mode_char == '-') { self->adding = false; return true; } + + struct str *modes = &s->irc_user_mode; + const char *pos = strchr (modes->str, mode_char); + if (self->adding == !!pos) + return true; + + if (self->adding) + { + str_append_c (modes, mode_char); + // TODO: sort the modes + } + else + str_remove_slice (modes, pos - modes->str, 1); + return true; +} + +static void +irc_handle_mode_user (struct server *s, char **params) +{ + struct mode_processor p; + mode_processor_init (&p); + + p.params = params; + p.s = s; + + const char *mode_string; + while ((mode_string = mode_processor_next_param (&p))) + { + mode_processor_step (&p, '+'); + while (*mode_string) + if (!mode_processor_step_user (&p, *mode_string++)) + break; + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + static void irc_handle_mode (struct server *s, const struct irc_message *msg) { @@ -4133,8 +4180,6 @@ irc_handle_mode (struct server *s, const struct irc_message *msg) char *modes = irc_to_utf8 (s->ctx, reconstructed); free (reconstructed); - // TODO: parse user mode changes - if (irc_is_channel (s, context)) { struct channel *channel = str_map_find (&s->irc_channels, context); @@ -4154,6 +4199,8 @@ irc_handle_mode (struct server *s, const struct irc_message *msg) } else if (irc_is_this_us (s, context)) { + irc_handle_mode_user (s, msg->params.vector + 1); + // FIXME: logging buffer_send_status (s->ctx, s->buffer, "User mode [%s] by %s", modes, who); @@ -4625,7 +4672,7 @@ static void irc_on_registered (struct server *s, const char *nickname) { s->irc_user = irc_get_or_make_user (s, nickname); - s->irc_user_mode = xstrdup (""); + str_reset (&s->irc_user_mode); s->irc_user_host = NULL; s->state = IRC_REGISTERED; |