degesch: correctly update user prefixes

This commit is contained in:
Přemysl Eric Janouch 2015-06-05 00:57:39 +02:00
parent c8aff23ab2
commit 7f57bed563
1 changed files with 30 additions and 26 deletions

View File

@ -820,13 +820,14 @@ struct channel_user
LIST_HEADER (struct channel_user) LIST_HEADER (struct channel_user)
struct user *user; ///< Reference to user struct user *user; ///< Reference to user
char *modes; ///< Ordered @+... characters struct str prefixes; ///< Ordered @+... characters
}; };
static struct channel_user * static struct channel_user *
channel_user_new (void) channel_user_new (void)
{ {
struct channel_user *self = xcalloc (1, sizeof *self); struct channel_user *self = xcalloc (1, sizeof *self);
str_init (&self->prefixes);
return self; return self;
} }
@ -834,7 +835,7 @@ static void
channel_user_destroy (struct channel_user *self) channel_user_destroy (struct channel_user *self)
{ {
user_unref (self->user); user_unref (self->user);
free (self->modes); str_free (&self->prefixes);
free (self); free (self);
} }
@ -3878,7 +3879,6 @@ irc_handle_join (struct server *s, const struct irc_message *msg)
struct channel_user *channel_user = channel_user_new (); struct channel_user *channel_user = channel_user_new ();
channel_user->user = user; channel_user->user = user;
channel_user->modes = xstrdup ("");
LIST_PREPEND (channel->users, channel_user); LIST_PREPEND (channel->users, channel_user);
// Finally log the message // Finally log the message
@ -3938,8 +3938,8 @@ struct mode_processor
char **params; ///< Mode string parameters char **params; ///< Mode string parameters
struct server *s; ///< Who does the changes struct server *s; ///< Server
struct channel *channel; ///< The channel we're modifying struct channel *channel; ///< The channel being modified
// Internals: // Internals:
@ -3978,24 +3978,27 @@ mode_processor_do_user (struct mode_processor *self)
if (!channel_user) if (!channel_user)
return; return;
char prefix = self->s->irc_chanuser_prefixes const char *all_prefixes = self->s->irc_chanuser_prefixes;
[strchr (self->s->irc_chanuser_modes, self->mode_char) const char *all_modes = self->s->irc_chanuser_modes;
- self->s->irc_chanuser_modes]; char prefix = all_prefixes[strchr (all_modes, self->mode_char) - all_modes];
// XXX: shouldn't this rather be a "struct str"? struct str *prefixes = &channel_user->prefixes;
char *modes = channel_user->modes; const char *pos = strchr (prefixes->str, prefix);
char *pos = strchr (modes, self->mode_char);
if (self->adding == !!pos) if (self->adding == !!pos)
return; return;
if (self->adding) if (self->adding)
{ {
// FIXME: this doesn't give two fucks about the correct order // Add the new mode prefix while retaining the right order
channel_user->modes = xstrdup_printf ("%s%c", modes, prefix); char *old_prefixes = str_steal (prefixes);
free (modes); str_init (prefixes);
for (const char *p = all_prefixes; *p; p++)
if (*p == prefix || strchr (old_prefixes, *p))
str_append_c (prefixes, *p);
free (old_prefixes);
} }
else else
memmove (pos, pos + 1, strlen (pos + 1)); str_remove_slice (prefixes, pos - prefixes->str, 1);
} }
static void static void
@ -4689,26 +4692,27 @@ irc_process_names (struct server *s, struct channel *channel)
for (size_t i = 0; i < updates->len; i++) for (size_t i = 0; i < updates->len; i++)
{ {
const char *item = updates->vector[i]; const char *item = updates->vector[i];
const char *nick = item + strspn (item, s->irc_chanuser_prefixes); size_t n_prefixes = strspn (item, s->irc_chanuser_prefixes);
char *modes = xstrndup (item, nick - item); const char *nick = item + n_prefixes;
char prefixes[n_prefixes + 1];
memcpy (prefixes, item, n_prefixes);
prefixes[n_prefixes] = '\0';
struct channel_user *channel_user = str_map_find (&map, nick); struct channel_user *channel_user = str_map_find (&map, nick);
if (!channel_user) if (!channel_user)
{ {
channel_user = channel_user_new (); channel_user = channel_user_new ();
channel_user->user = irc_get_or_make_user (s, nick); channel_user->user = irc_get_or_make_user (s, nick);
channel_user->modes = modes;
LIST_PREPEND (channel->users, channel_user); LIST_PREPEND (channel->users, channel_user);
} }
// If our idea of the user's modes disagrees with what the server's // If our idea of the user's modes disagrees with what the server's
// sent us (the most powerful modes differ), use the latter one // sent us (the most powerful modes differ), use the latter one
else if (channel_user->modes[0] != modes[0]) else if (channel_user->prefixes.str[0] == prefixes[0])
{ continue;
free (channel_user->modes);
channel_user->modes = modes; str_reset (&channel_user->prefixes);
} str_append (&channel_user->prefixes, prefixes);
else
free (modes);
} }
// TODO: get rid of channel users missing from "updates": // TODO: get rid of channel users missing from "updates":
@ -4721,7 +4725,7 @@ irc_process_names (struct server *s, struct channel *channel)
str_vector_init (&v); str_vector_init (&v);
LIST_FOR_EACH (struct channel_user, iter, channel->users) LIST_FOR_EACH (struct channel_user, iter, channel->users)
str_vector_add_owned (&v, str_vector_add_owned (&v,
xstrdup_printf ("%s%s", iter->modes, iter->user->nickname)); xstrdup_printf ("%s%s", iter->prefixes.str, iter->user->nickname));
char *all_users = join_str_vector (&v, ' '); char *all_users = join_str_vector (&v, ' ');
str_vector_free (&v); str_vector_free (&v);