summaryrefslogtreecommitdiff
path: root/degesch.c
diff options
context:
space:
mode:
Diffstat (limited to 'degesch.c')
-rw-r--r--degesch.c61
1 files changed, 33 insertions, 28 deletions
diff --git a/degesch.c b/degesch.c
index e90d393..fad77f3 100644
--- a/degesch.c
+++ b/degesch.c
@@ -4680,11 +4680,35 @@ irc_handle_rpl_namreply (struct server *s, const struct irc_message *msg)
}
static void
+irc_sync_channel_user (struct server *s, struct channel *channel,
+ const char *nickname, const char *prefixes)
+{
+ struct user *user = irc_get_or_make_user (s, nickname);
+ struct channel_user *channel_user =
+ irc_channel_get_user (channel, user);
+ if (!channel_user)
+ {
+ irc_channel_link_user (channel, user, prefixes);
+ return;
+ }
+
+ user_unref (user);
+
+ // 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
+ if (channel_user->prefixes.str[0] != prefixes[0])
+ {
+ str_reset (&channel_user->prefixes);
+ str_append (&channel_user->prefixes, prefixes);
+ }
+}
+
+static void
irc_process_names (struct server *s, struct channel *channel)
{
- struct str_map map;
- str_map_init (&map);
- map.key_xfrm = s->irc_strxfrm;
+ struct str_map present;
+ str_map_init (&present);
+ present.key_xfrm = s->irc_strxfrm;
struct str_vector *updates = &channel->names_buf;
for (size_t i = 0; i < updates->len; i++)
@@ -4694,38 +4718,19 @@ irc_process_names (struct server *s, struct channel *channel)
const char *nickname = item + n_prefixes;
// Store the nickname in a hashset
- str_map_set (&map, nickname, (void *) 1);
-
- char prefixes[n_prefixes + 1];
- memcpy (prefixes, item, n_prefixes);
- prefixes[n_prefixes] = '\0';
-
- struct user *user = irc_get_or_make_user (s, nickname);
- struct channel_user *channel_user =
- irc_channel_get_user (channel, user);
- if (!channel_user)
- {
- irc_channel_link_user (channel, user, prefixes);
- continue;
- }
-
- user_unref (user);
-
- // 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
- if (channel_user->prefixes.str[0] == prefixes[0])
- continue;
+ str_map_set (&present, nickname, (void *) 1);
- str_reset (&channel_user->prefixes);
- str_append (&channel_user->prefixes, prefixes);
+ char *prefixes = xstrndup (item, n_prefixes);
+ irc_sync_channel_user (s, channel, nickname, prefixes);
+ free (prefixes);
}
// Get rid of channel users missing from "updates"
LIST_FOR_EACH (struct channel_user, iter, channel->users)
- if (!str_map_find (&map, iter->user->nickname))
+ if (!str_map_find (&present, iter->user->nickname))
irc_channel_unlink_user (channel, iter);
- str_map_free (&map);
+ str_map_free (&present);
str_vector_reset (&channel->names_buf);
struct str_vector v;