aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--degesch.c69
1 files changed, 58 insertions, 11 deletions
diff --git a/degesch.c b/degesch.c
index 933b5c8..54a2ff0 100644
--- a/degesch.c
+++ b/degesch.c
@@ -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;