Use case-insensitive comparisons for nicknames and channel names

This commit is contained in:
Les De Ridder 2017-04-13 22:20:49 +02:00
parent e4fdf0ac91
commit f60b3cc988
No known key found for this signature in database
GPG Key ID: 5EC132DFA85DB372
3 changed files with 72 additions and 31 deletions

View File

@ -205,7 +205,7 @@ class Connection
auto newNick = message.parameters[0];
if(!_server.isNickAvailable(newNick))
if(!_server.isNickAvailable(newNick) && newNick.toIRCLower != nick.toIRCLower)
{
send(Message(_server.name, "433", [nick, newNick, "Nickname already in use"]));
return;
@ -311,7 +311,7 @@ class Connection
{
sendErrNoSuchChannel(channel);
}
else if(!channels.canFind!(c => c.name == channel))
else if(!_server.canFindChannelByName(channel))
{
send(Message(_server.name, "442", [nick, channel, "You're not on that channel"], true));
}
@ -347,7 +347,7 @@ class Connection
if(Server.isValidChannelName(target))
{
if(!_server.channels.canFind!(c => c.name == target))
if(!_server.canFindChannelByName(target))
{
sendErrNoSuchNick(target);
}
@ -358,7 +358,7 @@ class Connection
}
else if(Server.isValidNick(target))
{
if(!_server.connections.canFind!(c => c.nick == target))
if(!_server.canFindConnectionByNick(target))
{
sendErrNoSuchNick(target);
}
@ -366,7 +366,7 @@ class Connection
{
_server.privmsgToUser(this, target, text);
auto targetUser = _server.connections.find!(c => c.nick == target)[0];
auto targetUser = _server.findConnectionByNick(target)[0];
if(targetUser.modes.canFind('a'))
{
sendRplAway(target, targetUser.awayMessage);
@ -393,14 +393,11 @@ class Connection
return;
}
if(Server.isValidChannelName(target))
if(Server.isValidChannelName(target) && _server.canFindChannelByName(target))
{
if(_server.channels.canFind!(c => c.name == target))
{
_server.noticeToChannel(this, target, text);
}
_server.noticeToChannel(this, target, text);
}
else if(Server.isValidNick(target) && _server.connections.canFind!(c => c.nick == target))
else if(Server.isValidNick(target) && _server.canFindConnectionByNick(target))
{
_server.noticeToUser(this, target, text);
}
@ -417,7 +414,7 @@ class Connection
auto mask = message.parameters[0];
auto operatorsOnly = message.parameters.length > 1 && message.parameters[1] == "o";
if(_server.isValidChannelName(mask) && _server.channels.canFind!(c => c.name == mask))
if(_server.isValidChannelName(mask) && _server.canFindChannelByName(mask))
{
_server.whoChannel(this, mask, operatorsOnly);
}
@ -459,7 +456,7 @@ class Connection
auto channelName = message.parameters[0];
if(message.parameters.length == 1)
{
if(!_server.channels.canFind!(c => c.name == channelName && (!(c.modes.canFind('s') || c.modes.canFind('p')) || c.members.canFind(this))))
if(!_server.channels.canFind!(c => c.name.toIRCLower == channelName.toIRCLower && (!(c.modes.canFind('s') || c.modes.canFind('p')) || c.members.canFind(this))))
{
//NOTE: The RFCs don't allow ERR_NOSUCHCHANNEL as a response to TOPIC
//TODO: If RFC-strictness is off, do send ERR_NOSUCHCHANNEL
@ -473,12 +470,12 @@ class Connection
else
{
auto newTopic = message.parameters[1];
if(!channels.canFind!(c => c.name == channelName))
if(!channels.canFind!(c => c.name.toIRCLower == channelName.toIRCLower))
{
sendErrNotOnChannel(channelName);
}
//TODO: Allow operators to set flags
else if(channels.find!(c => c.name == channelName).map!(c => c.modes.canFind('t') /* && this user isn't an operator */).array[0])
else if(channels.find!(c => c.name.toIRCLower == channelName.toIRCLower).map!(c => c.modes.canFind('t') /* && this user isn't an operator */).array[0])
{
sendErrChanopPrivsNeeded(channelName);
}
@ -505,7 +502,7 @@ class Connection
{
foreach(channelName; message.parameters[0].split(','))
{
if(_server.channels.canFind!(c => c.name == channelName && c.visibleTo(this)))
if(_server.channels.canFind!(c => c.name.toIRCLower == channelName.toIRCLower && c.visibleTo(this)))
{
_server.sendChannelNames(this, channelName);
}
@ -545,7 +542,7 @@ class Connection
}
auto targetNick = message.parameters[0];
auto targetUserRange = _server.connections.find!(c => c.nick == targetNick);
auto targetUserRange = _server.findConnectionByNick(targetNick);
if(targetUserRange.empty)
{
sendErrNoSuchNick(targetNick);
@ -554,7 +551,7 @@ class Connection
auto targetUser = targetUserRange[0];
auto channelName = message.parameters[1];
auto channelRange = _server.channels.find!(c => c.name == channelName);
auto channelRange = _server.findChannelByName(channelName);
if(channelRange.empty)
{
_server.invite(this, targetUser.nick, channelName);

View File

@ -1,6 +1,7 @@
module ircd.helpers;
import std.range;
import std.range : array, empty, front, popFront, save;
import std.algorithm : map;
//Based on std.path.globMatch (https://github.com/dlang/phobos/blob/v2.073.2/std/path.d#L3164)
//License: Boost License 1.0 (http://www.boost.org/LICENSE_1_0.txt)
@ -46,3 +47,26 @@ bool wildcardMatch(string input, string pattern)
return input.empty;
}
@safe pure
dchar toIRCLower(dchar input)
{
import std.uni : toLower;
switch(input)
{
case '[':
return '{';
case ']':
return '}';
case '\\':
return '|';
default:
return input.toLower;
}
}
@safe pure
string toIRCLower(string input)
{
import std.utf : byChar;
return input.map!toIRCLower.byChar.array.idup;
}

View File

@ -98,14 +98,34 @@ class Server
return true;
}
Connection[] findConnectionByNick(string nick)
{
return connections.find!(c => c.nick.toIRCLower == nick.toIRCLower);
}
bool canFindConnectionByNick(string nick)
{
return !findConnectionByNick(nick).empty;
}
bool isNickAvailable(string nick)
{
return !connections.canFind!(c => c.nick == nick);
return !canFindConnectionByNick(nick);
}
Channel[] findChannelByName(string name)
{
return channels.find!(c => c.name.toIRCLower == name.toIRCLower);
}
bool canFindChannelByName(string name)
{
return !findConnectionByNick(name).empty;
}
void join(Connection connection, string channelName)
{
auto channelRange = channels.find!(c => c.name == channelName);
auto channelRange = findChannelByName(channelName);
Channel channel;
if(channelRange.empty)
{
@ -133,7 +153,7 @@ class Server
void part(Connection connection, string channelName, string partMessage)
{
auto channel = connection.channels.array.find!(c => c.name == channelName)[0];
auto channel = connection.channels.array.find!(c => c.name.toIRCLower == channelName.toIRCLower)[0];
foreach(member; channel.members)
{
@ -186,7 +206,7 @@ class Server
{
//TODO: Check what RFCs say about secret/private channels
auto channel = channels.find!(c => c.name == channelName)[0];
auto channel = findChannelByName(channelName)[0];
foreach(c; channel.members.filter!(c => !operatorsOnly || c.isOperator)
.filter!(c => c.visibleTo(origin)))
{
@ -210,43 +230,43 @@ class Server
void privmsgToChannel(Connection sender, string target, string text)
{
auto channel = channels.find!(c => c.name == target)[0];
auto channel = findChannelByName(target)[0];
channel.sendPrivMsg(sender, text);
}
void privmsgToUser(Connection sender, string target, string text)
{
auto user = connections.find!(c => c.nick == target)[0];
auto user = findConnectionByNick(target)[0];
user.send(Message(sender.mask, "PRIVMSG", [target, text], true));
}
void noticeToChannel(Connection sender, string target, string text)
{
auto channel = channels.find!(c => c.name == target)[0];
auto channel = findChannelByName(target)[0];
channel.sendNotice(sender, text);
}
void noticeToUser(Connection sender, string target, string text)
{
auto user = connections.find!(c => c.nick == target)[0];
auto user = findConnectionByNick(target)[0];
user.send(Message(sender.mask, "NOTICE", [target, text], true));
}
void sendChannelTopic(Connection origin, string channelName)
{
auto channel = channels.find!(c => c.name == channelName)[0];
auto channel = findChannelByName(channelName)[0];
channel.sendTopic(origin);
}
void setChannelTopic(Connection origin, string channelName, string newTopic)
{
auto channel = channels.find!(c => c.name == channelName)[0];
auto channel = findChannelByName(channelName)[0];
channel.setTopic(origin, newTopic);
}
void sendChannelNames(Connection connection, string channelName)
{
auto channel = channels.find!(c => c.name == channelName)[0];
auto channel = findChannelByName(channelName)[0];
channel.sendNames(connection);
}
@ -339,7 +359,7 @@ class Server
void ison(Connection connection, string[] nicks)
{
auto reply = nicks.filter!(n => connections.canFind!(u => u.nick == n)).join(' ');
auto reply = nicks.filter!(n => canFindConnectionByNick(n)).join(' ');
connection.send(Message(name, "303", [connection.nick, reply], true));
}