diff options
-rw-r--r-- | degesch.c | 99 |
1 files changed, 64 insertions, 35 deletions
@@ -2926,6 +2926,58 @@ irc_left_channel (struct channel *channel) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - static void +remove_conflicting_buffer (struct server *s, struct buffer *buffer) +{ + buffer_send_status (s->ctx, NULL, + "Removed buffer %s because of casemapping conflict", buffer->name); + if (s->ctx->current_buffer == buffer) + buffer_activate (s->ctx, s->buffer); + buffer_remove (s->ctx, buffer); +} + +static void +irc_try_readd_user (struct server *s, + struct user *user, struct buffer *buffer) +{ + if (str_map_find (&s->irc_users, user->nickname)) + { + // Remove user from all channels and destroy any PM buffer + user_ref (user); + LIST_FOR_EACH (struct user_channel, iter, user->channels) + irc_remove_user_from_channel (user, iter->channel); + if (buffer) + remove_conflicting_buffer (s, buffer); + user_unref (user); + } + else + { + str_map_set (&s->irc_users, user->nickname, user); + str_map_set (&s->irc_buffer_map, user->nickname, buffer); + } +} + +static void +irc_try_readd_channel (struct server *s, + struct channel *channel, struct buffer *buffer) +{ + if (str_map_find (&s->irc_channels, channel->name)) + { + // Remove all users from channel and destroy any channel buffer + channel_ref (channel); + LIST_FOR_EACH (struct channel_user, iter, channel->users) + irc_channel_unlink_user (channel, iter); + if (buffer) + remove_conflicting_buffer (s, buffer); + channel_unref (channel); + } + else + { + str_map_set (&s->irc_channels, channel->name, channel); + str_map_set (&s->irc_buffer_map, channel->name, buffer); + } +} + +static void irc_rehash_and_fix_conflicts (struct server *s) { // Save the old maps and initialize new ones @@ -2937,10 +2989,6 @@ irc_rehash_and_fix_conflicts (struct server *s) str_map_init (&s->irc_channels); str_map_init (&s->irc_buffer_map); - s->irc_users .free = old_users .free; - s->irc_channels .free = old_channels .free; - s->irc_buffer_map.free = old_buffer_map.free; - s->irc_users .key_xfrm = s->irc_strxfrm; s->irc_channels .key_xfrm = s->irc_strxfrm; s->irc_buffer_map.key_xfrm = s->irc_strxfrm; @@ -2949,46 +2997,27 @@ irc_rehash_and_fix_conflicts (struct server *s) // from server maps upon removing the last reference to them s->rehashing = true; - // TODO: "Removed similarly named buffer %s because of casemapping conflict" // XXX: to be perfectly sure, we should also check // whether any users collide with channels and vice versa + // Our own user always takes priority, add him first + if (s->irc_user) + irc_try_readd_user (s, s->irc_user, + str_map_find (&old_buffer_map, s->irc_user->nickname)); + struct str_map_iter iter; - str_map_iter_init (&iter, &old_users); struct user *user; + struct channel *channel; + + str_map_iter_init (&iter, &old_users); while ((user = str_map_iter_next (&iter))) - { - // FIXME: don't remove ourselves! - if (str_map_find (&s->irc_users, user->nickname)) - { - // TODO: move or merge any PM buffer and remove - // the user from channels and altogether - } - else - { - str_map_set (&s->irc_users, user->nickname, user); - str_map_set (&s->irc_buffer_map, user->nickname, - str_map_find (&old_buffer_map, user->nickname)); - } - } + irc_try_readd_user (s, user, + str_map_find (&old_buffer_map, user->nickname)); str_map_iter_init (&iter, &old_channels); - struct channel *channel; while ((channel = str_map_iter_next (&iter))) - { - if (str_map_find (&s->irc_channels, channel->name)) - { - // TODO: remove all users from the buffer - // and probably issue NAMES if registered and on the channel, - // and of course remove the colliding channel - } - else - { - str_map_set (&s->irc_channels, channel->name, user); - str_map_set (&s->irc_buffer_map, user->nickname, - str_map_find (&old_buffer_map, user->nickname)); - } - } + irc_try_readd_channel (s, channel, + str_map_find (&old_buffer_map, channel->name)); // Hopefully we've either moved or destroyed all the old content s->rehashing = false; |