degesch: NICK handling cleanup
This commit is contained in:
parent
9603bae003
commit
c3439175d7
86
degesch.c
86
degesch.c
|
@ -4357,27 +4357,6 @@ irc_handle_mode (struct server *s, const struct irc_message *msg)
|
|||
refresh_prompt (s->ctx);
|
||||
}
|
||||
|
||||
static struct buffer *
|
||||
irc_handle_buffer_collision (struct server *s,
|
||||
struct buffer *buffer, const char *new_name)
|
||||
{
|
||||
struct buffer *collision = str_map_find (&s->irc_buffer_map, new_name);
|
||||
if (!collision)
|
||||
return buffer;
|
||||
|
||||
// TODO: use full weechat-style buffer names
|
||||
// to prevent name collisions with the global buffer
|
||||
hard_assert (collision->type == buffer->type);
|
||||
|
||||
// When there's a collision, there's not much else we can do
|
||||
// other than somehow try to merge them
|
||||
buffer_merge (s->ctx, collision, buffer);
|
||||
if (s->ctx->current_buffer == buffer)
|
||||
buffer_activate (s->ctx, collision);
|
||||
buffer_remove (s->ctx, buffer);
|
||||
return collision;
|
||||
}
|
||||
|
||||
static void
|
||||
irc_handle_nick (struct server *s, const struct irc_message *msg)
|
||||
{
|
||||
|
@ -4392,17 +4371,16 @@ irc_handle_nick (struct server *s, const struct irc_message *msg)
|
|||
if (!user)
|
||||
return;
|
||||
|
||||
bool lexicographically_identical =
|
||||
!irc_server_strcmp (s, user->nickname, new_nickname);
|
||||
bool lexicographically_different =
|
||||
!!irc_server_strcmp (s, user->nickname, new_nickname);
|
||||
|
||||
// What the fuck, someone renamed themselves to ourselves
|
||||
// TODO: probably log a message and force a reconnect
|
||||
if (!lexicographically_identical
|
||||
if (lexicographically_different
|
||||
&& !irc_server_strcmp (s, new_nickname, s->irc_user->nickname))
|
||||
return;
|
||||
|
||||
// Log a message in any PM buffer and rename it;
|
||||
// we may even have one for ourselves
|
||||
// Log a message in any PM buffer (we may even have one for ourselves)
|
||||
struct buffer *pm_buffer =
|
||||
str_map_find (&s->irc_buffer_map, user->nickname);
|
||||
if (pm_buffer)
|
||||
|
@ -4413,21 +4391,45 @@ irc_handle_nick (struct server *s, const struct irc_message *msg)
|
|||
buffer_send (s->ctx, pm_buffer, BUFFER_LINE_NICK, 0,
|
||||
.who = who,
|
||||
.object = irc_to_utf8 (s->ctx, new_nickname));
|
||||
}
|
||||
|
||||
if (!lexicographically_identical)
|
||||
{
|
||||
// XXX: this code seems a bit ugly (but also necessary)
|
||||
user = user_ref (user);
|
||||
// The new nickname may collide with a user referenced by a PM buffer,
|
||||
// or in case of data inconsistency with the server, channels.
|
||||
// In the latter case we need the colliding user to leave all of them.
|
||||
struct user *user_collision = NULL;
|
||||
if (lexicographically_different
|
||||
&& (user_collision = str_map_find (&s->irc_users, new_nickname)))
|
||||
LIST_FOR_EACH (struct user_channel, iter, user_collision->channels)
|
||||
irc_remove_user_from_channel (user_collision, iter->channel);
|
||||
|
||||
pm_buffer = irc_handle_buffer_collision
|
||||
(s, pm_buffer, new_nickname);
|
||||
struct buffer *buffer_collision = NULL;
|
||||
if (lexicographically_different
|
||||
&& (buffer_collision = str_map_find (&s->irc_buffer_map, new_nickname)))
|
||||
{
|
||||
hard_assert (buffer_collision->type == BUFFER_PM);
|
||||
hard_assert (buffer_collision->user == user_collision);
|
||||
|
||||
user_unref (pm_buffer->user);
|
||||
pm_buffer->user = user;
|
||||
user_unref (buffer_collision->user);
|
||||
buffer_collision->user = user_ref (user);
|
||||
|
||||
str_map_set (&s->irc_buffer_map, user->nickname, NULL);
|
||||
str_map_set (&s->irc_buffer_map, new_nickname, pm_buffer);
|
||||
}
|
||||
// There's not much else we can do other than somehow try to merge
|
||||
// one buffer into the other. In our case, the original buffer wins.
|
||||
buffer_merge (s->ctx, buffer_collision, pm_buffer);
|
||||
if (s->ctx->current_buffer == pm_buffer)
|
||||
buffer_activate (s->ctx, buffer_collision);
|
||||
buffer_remove (s->ctx, pm_buffer);
|
||||
pm_buffer = buffer_collision;
|
||||
}
|
||||
|
||||
// The colliding user should be completely destroyed by now
|
||||
if (lexicographically_different)
|
||||
hard_assert (!str_map_find (&s->irc_users, new_nickname));
|
||||
|
||||
// Now we can rename the PM buffer to reflect the new nickname
|
||||
if (pm_buffer)
|
||||
{
|
||||
str_map_set (&s->irc_buffer_map, user->nickname, NULL);
|
||||
str_map_set (&s->irc_buffer_map, new_nickname, pm_buffer);
|
||||
|
||||
char *x = xstrdup_printf ("%s.%s", s->name, new_nickname);
|
||||
buffer_rename (s->ctx, pm_buffer, x);
|
||||
|
@ -4464,13 +4466,9 @@ irc_handle_nick (struct server *s, const struct irc_message *msg)
|
|||
}
|
||||
}
|
||||
|
||||
// Finally rename the user
|
||||
if (!lexicographically_identical)
|
||||
{
|
||||
// NOTE: this doesn't dereference anything
|
||||
str_map_set (&s->irc_users, user->nickname, NULL);
|
||||
str_map_set (&s->irc_users, new_nickname, user);
|
||||
}
|
||||
// Finally rename the user as it should be safe now
|
||||
str_map_set (&s->irc_users, user->nickname, NULL);
|
||||
str_map_set (&s->irc_users, new_nickname, user);
|
||||
|
||||
free (user->nickname);
|
||||
user->nickname = xstrdup (new_nickname);
|
||||
|
|
Loading…
Reference in New Issue