aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--degesch.c99
1 files changed, 64 insertions, 35 deletions
diff --git a/degesch.c b/degesch.c
index a1920cb..50f29d4 100644
--- a/degesch.c
+++ b/degesch.c
@@ -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;