mirror of
https://github.com/reactos/rosev_ircsystem.git
synced 2024-11-23 03:49:45 +00:00
[ROSEV_IRCSYSTEM]
- Allow everybody (also unidentified users) to participate as observers in IRC discussions. This feature is configurable per channel. - Implement basic client statuses (NoStatus and Voice) to distinguish between participating members and observers. This requires changing the per-channel client set to a client map (CClient object -> Client status). - Distinguish between the statuses in logs generated by the built-in LogBot. - Don't include observers when running a vote using the built-in VoteBot. - Move the UserPasshashMap from CNickServ to CConfiguration, because we need to check whether the nickname is protected at NICK messages. Rename "NickServ_Users.ini" to "Users.ini" to reflect this change. - Update the documentation accordingly. svn path=/trunk/rosev_ircsystem/; revision=1269
This commit is contained in:
parent
77d5571a45
commit
107d4ceef9
Binary file not shown.
8
conf/Channel_Observers.ini
Normal file
8
conf/Channel_Observers.ini
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# This file controls whether unidentified users may observe the discussions
|
||||||
|
# on each channel. They cannot participate in any way.
|
||||||
|
#
|
||||||
|
# Just add a <channelname>=true|false line for each channel.
|
||||||
|
# The default value is false.
|
||||||
|
|
||||||
|
openchannel=true
|
||||||
|
lonelychannel=false
|
@ -2,6 +2,9 @@
|
|||||||
# this channel.
|
# this channel.
|
||||||
# Just add a <channelname>=<nickname> line for each channel and user.
|
# Just add a <channelname>=<nickname> line for each channel and user.
|
||||||
#
|
#
|
||||||
|
# Every user not listed here can still join as an observer if this option
|
||||||
|
# has been enabled in Channel_Observers.ini.
|
||||||
|
#
|
||||||
# The server only allows A-Z, a-z and _ characters for user names.
|
# The server only allows A-Z, a-z and _ characters for user names.
|
||||||
|
|
||||||
openchannel=Arthur
|
openchannel=Arthur
|
||||||
|
@ -2,21 +2,21 @@
|
|||||||
* PROJECT: ReactOS Deutschland e.V. IRC System
|
* PROJECT: ReactOS Deutschland e.V. IRC System
|
||||||
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
||||||
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
||||||
* COPYRIGHT: Copyright 2010 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
* COPYRIGHT: Copyright 2010-2011 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
||||||
* AUTHORS: Colin Finck <colin@reactos.org>
|
* AUTHORS: Colin Finck <colin@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <precomp.h>
|
#include <precomp.h>
|
||||||
|
|
||||||
CChannel::CChannel(const std::string& Name, const std::string& Topic, const std::set<std::string>& AllowedUsers)
|
CChannel::CChannel(const std::string& Name, const std::string& Topic, const std::set<std::string>& AllowedUsers, bool AllowObservers)
|
||||||
: m_Name(Name), m_Topic(Topic), m_AllowedUsers(AllowedUsers)
|
: m_Name(Name), m_Topic(Topic), m_AllowedUsers(AllowedUsers), m_AllowObservers(AllowObservers)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CChannel::AddClient(CClient* Client)
|
CChannel::AddClient(CClient* Client, CChannel::ClientStatus Status)
|
||||||
{
|
{
|
||||||
m_Clients.insert(Client);
|
m_Clients.insert(std::make_pair(Client, Status));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -2,25 +2,33 @@
|
|||||||
* PROJECT: ReactOS Deutschland e.V. IRC System
|
* PROJECT: ReactOS Deutschland e.V. IRC System
|
||||||
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
||||||
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
||||||
* COPYRIGHT: Copyright 2010 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
* COPYRIGHT: Copyright 2010-2011 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
||||||
* AUTHORS: Colin Finck <colin@reactos.org>
|
* AUTHORS: Colin Finck <colin@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class CChannel : private boost::noncopyable
|
class CChannel : private boost::noncopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CChannel(const std::string& Name, const std::string& Topic, const std::set<std::string>& AllowedUsers);
|
enum ClientStatus
|
||||||
|
{
|
||||||
|
NoStatus,
|
||||||
|
Voice
|
||||||
|
};
|
||||||
|
|
||||||
void AddClient(CClient* Client);
|
CChannel(const std::string& Name, const std::string& Topic, const std::set<std::string>& AllowedUsers, bool AllowObservers);
|
||||||
|
|
||||||
|
void AddClient(CClient* Client, CChannel::ClientStatus Status);
|
||||||
|
bool DoAllowObservers() const { return m_AllowObservers; }
|
||||||
const std::set<std::string>& GetAllowedUsers() const { return m_AllowedUsers; }
|
const std::set<std::string>& GetAllowedUsers() const { return m_AllowedUsers; }
|
||||||
const std::set<CClient*>& GetClients() const { return m_Clients; }
|
const std::map<CClient*, ClientStatus>& GetClients() const { return m_Clients; }
|
||||||
const std::string& GetName() const { return m_Name; }
|
const std::string& GetName() const { return m_Name; }
|
||||||
const std::string& GetTopic() const { return m_Topic; }
|
const std::string& GetTopic() const { return m_Topic; }
|
||||||
void RemoveClient(CClient* Client);
|
void RemoveClient(CClient* Client);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::set<std::string> m_AllowedUsers;
|
std::set<std::string> m_AllowedUsers;
|
||||||
std::set<CClient*> m_Clients;
|
bool m_AllowObservers;
|
||||||
|
std::map<CClient*, ClientStatus> m_Clients;
|
||||||
std::string m_Name;
|
std::string m_Name;
|
||||||
std::string m_Topic;
|
std::string m_Topic;
|
||||||
};
|
};
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* PROJECT: ReactOS Deutschland e.V. IRC System
|
* PROJECT: ReactOS Deutschland e.V. IRC System
|
||||||
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
||||||
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
||||||
* COPYRIGHT: Copyright 2010 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
* COPYRIGHT: Copyright 2010-2011 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
||||||
* AUTHORS: Colin Finck <colin@reactos.org>
|
* AUTHORS: Colin Finck <colin@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -123,6 +123,27 @@ CConfiguration::ReadConfigFiles()
|
|||||||
|
|
||||||
MotdStream.close();
|
MotdStream.close();
|
||||||
|
|
||||||
|
/* Users file */
|
||||||
|
boost::program_options::parsed_options UsersParsedOptions(boost::program_options::parse_config_file<char>(std::string(m_ConfigPath).append(USERS_FILE).c_str(), NULL, true));
|
||||||
|
for(std::vector< boost::program_options::basic_option<char> >::const_iterator it = UsersParsedOptions.options.begin(); it != UsersParsedOptions.options.end(); ++it)
|
||||||
|
{
|
||||||
|
/* Convert the hexadecimal string passhash into a binary one */
|
||||||
|
const std::string& HexPasshash = it->value[0];
|
||||||
|
boost::array<char, SHA512_DIGEST_LENGTH> BinaryPasshash;
|
||||||
|
|
||||||
|
if(HexPasshash.length() != 2 * SHA512_DIGEST_LENGTH)
|
||||||
|
BOOST_THROW_EXCEPTION(Error("Length of a passhash must be 128 characters!") << Passhash_Info(HexPasshash));
|
||||||
|
|
||||||
|
for(int i = 0; i < SHA512_DIGEST_LENGTH; ++i)
|
||||||
|
BinaryPasshash[i] = static_cast<char>(strtol(HexPasshash.substr(2 * i, 2).c_str(), NULL, 16));
|
||||||
|
|
||||||
|
/* Lowercase the nickname for comparison purposes */
|
||||||
|
std::string NicknameLowercased(it->string_key);
|
||||||
|
std::transform(NicknameLowercased.begin(), NicknameLowercased.end(), NicknameLowercased.begin(), tolower);
|
||||||
|
|
||||||
|
m_UserPasshashMap.insert(std::make_pair(NicknameLowercased, BinaryPasshash));
|
||||||
|
}
|
||||||
|
|
||||||
/* Sanity checks */
|
/* Sanity checks */
|
||||||
if(m_Name.empty())
|
if(m_Name.empty())
|
||||||
BOOST_THROW_EXCEPTION(Error("You need to specify a server name!"));
|
BOOST_THROW_EXCEPTION(Error("You need to specify a server name!"));
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* PROJECT: ReactOS Deutschland e.V. IRC System
|
* PROJECT: ReactOS Deutschland e.V. IRC System
|
||||||
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
||||||
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
||||||
* COPYRIGHT: Copyright 2010 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
* COPYRIGHT: Copyright 2010-2011 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
||||||
* AUTHORS: Colin Finck <colin@reactos.org>
|
* AUTHORS: Colin Finck <colin@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -30,6 +30,7 @@ public:
|
|||||||
unsigned short GetPort() const { return m_Port; }
|
unsigned short GetPort() const { return m_Port; }
|
||||||
const std::string& GetSSLCertificateFile() const { return m_SSLCertificateFile; }
|
const std::string& GetSSLCertificateFile() const { return m_SSLCertificateFile; }
|
||||||
const std::string& GetSSLPrivateKeyFile() const { return m_SSLPrivateKeyFile; }
|
const std::string& GetSSLPrivateKeyFile() const { return m_SSLPrivateKeyFile; }
|
||||||
|
const std::map< std::string, boost::array<char, SHA512_DIGEST_LENGTH> >& GetUserPasshashMap() const { return m_UserPasshashMap; }
|
||||||
bool ParseParameters(int argc, char* argv[]);
|
bool ParseParameters(int argc, char* argv[]);
|
||||||
void ReadConfigFiles();
|
void ReadConfigFiles();
|
||||||
|
|
||||||
@ -52,5 +53,6 @@ private:
|
|||||||
bool m_Verbose;
|
bool m_Verbose;
|
||||||
bool m_UseIPv4;
|
bool m_UseIPv4;
|
||||||
bool m_UseIPv6;
|
bool m_UseIPv6;
|
||||||
|
std::map< std::string, boost::array<char, SHA512_DIGEST_LENGTH> > m_UserPasshashMap;
|
||||||
bool m_UseSSL;
|
bool m_UseSSL;
|
||||||
};
|
};
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* PROJECT: ReactOS Deutschland e.V. IRC System
|
* PROJECT: ReactOS Deutschland e.V. IRC System
|
||||||
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
||||||
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
||||||
* COPYRIGHT: Copyright 2010 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
* COPYRIGHT: Copyright 2010-2011 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
||||||
* AUTHORS: Colin Finck <colin@reactos.org>
|
* AUTHORS: Colin Finck <colin@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -44,6 +44,25 @@ CIRCServer::_AddAcceptor(const boost::asio::ip::tcp::acceptor::protocol_type& Pr
|
|||||||
m_Acceptors.push_back(Acceptor);
|
m_Acceptors.push_back(Acceptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CIRCServer::_CheckForPresetNickname(CNetworkClient* Client)
|
||||||
|
{
|
||||||
|
/* If this is a preset nickname, the user needs to identify within a given timeframe. */
|
||||||
|
const std::map< std::string, boost::array<char, SHA512_DIGEST_LENGTH> >& UserPasshashMap = m_Configuration.GetUserPasshashMap();
|
||||||
|
if(UserPasshashMap.find(Client->GetNicknameLowercased()) != UserPasshashMap.end())
|
||||||
|
{
|
||||||
|
Client->SendNotice(NULL, "This nickname is protected.");
|
||||||
|
Client->SendNotice(NULL, "Please identify with your password in the next " BOOST_PP_STRINGIZE(IDENTIFY_TIMEOUT) " seconds or you will be disconnected.");
|
||||||
|
Client->SendNotice(NULL, "Use the command /NS IDENTIFY <password> to do so.");
|
||||||
|
Client->RestartIdentifyTimer();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* It isn't, so cancel the identify timer and force the client to respond to regular pings again. */
|
||||||
|
Client->RestartPingTimer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CIRCServer::_HandleNewConnection(boost::asio::ip::tcp::acceptor* Acceptor, const boost::system::error_code& ErrorCode)
|
CIRCServer::_HandleNewConnection(boost::asio::ip::tcp::acceptor* Acceptor, const boost::system::error_code& ErrorCode)
|
||||||
{
|
{
|
||||||
@ -94,10 +113,8 @@ CIRCServer::_WelcomeClient(CNetworkClient* Client)
|
|||||||
Due to some reason, ircd-seven and other IRC servers use the nickname instead of a full prefix here. */
|
Due to some reason, ircd-seven and other IRC servers use the nickname instead of a full prefix here. */
|
||||||
Client->SendIRCMessage(boost::str(boost::format(":%1% MODE %1% :+i") % Client->GetNickname()));
|
Client->SendIRCMessage(boost::str(boost::format(":%1% MODE %1% :+i") % Client->GetNickname()));
|
||||||
|
|
||||||
/* The client also has to identify within a given timeframe. */
|
/* At the end of the initial login, the user should know whether he needs to identify or not. */
|
||||||
Client->SendNotice(NULL, "Please identify with your password in the next " BOOST_PP_STRINGIZE(IDENTIFY_TIMEOUT) " seconds or you will be disconnected.");
|
_CheckForPresetNickname(Client);
|
||||||
Client->SendNotice(NULL, "Use the command /NS IDENTIFY <password> to do so.");
|
|
||||||
Client->StartIdentifyTimer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -132,14 +149,14 @@ CIRCServer::DisconnectNetworkClient(CNetworkClient* Client, const std::string& R
|
|||||||
{
|
{
|
||||||
/* Send a QUIT response to all members of all channels, in which this client is a member of,
|
/* Send a QUIT response to all members of all channels, in which this client is a member of,
|
||||||
but only once for each member. */
|
but only once for each member. */
|
||||||
const std::set<CClient*>& Clients = (*ChannelIt)->GetClients();
|
const std::map<CClient*, CChannel::ClientStatus>& Clients = (*ChannelIt)->GetClients();
|
||||||
for(std::set<CClient*>::const_iterator ClientIt = Clients.begin(); ClientIt != Clients.end(); ++ClientIt)
|
for(std::map<CClient*, CChannel::ClientStatus>::const_iterator ClientIt = Clients.begin(); ClientIt != Clients.end(); ++ClientIt)
|
||||||
{
|
{
|
||||||
if(HandledClients.find(*ClientIt) == HandledClients.end())
|
if(HandledClients.find(ClientIt->first) == HandledClients.end())
|
||||||
{
|
{
|
||||||
/* This client has not received the QUIT message yet */
|
/* This client has not received the QUIT message yet */
|
||||||
(*ClientIt)->SendIRCMessage(Response);
|
ClientIt->first->SendIRCMessage(Response);
|
||||||
HandledClients.insert(*ClientIt);
|
HandledClients.insert(ClientIt->first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,6 +230,20 @@ CIRCServer::Init()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check which channels allow observers. */
|
||||||
|
std::set<std::string> ChannelObserversSet;
|
||||||
|
|
||||||
|
boost::program_options::parsed_options ChannelObserversParsedOptions(boost::program_options::parse_config_file<char>(std::string(ConfigPath).append(CHANNEL_OBSERVERS_FILE).c_str(), NULL, true));
|
||||||
|
for(std::vector< boost::program_options::basic_option<char> >::const_iterator OptionIt = ChannelObserversParsedOptions.options.begin(); OptionIt != ChannelObserversParsedOptions.options.end(); ++OptionIt)
|
||||||
|
{
|
||||||
|
/* Lowercase the channel name for comparison */
|
||||||
|
std::string ChannelNameLowercased(OptionIt->string_key);
|
||||||
|
std::transform(ChannelNameLowercased.begin(), ChannelNameLowercased.end(), ChannelNameLowercased.begin(), tolower);
|
||||||
|
|
||||||
|
if(OptionIt->value[0] == "true")
|
||||||
|
ChannelObserversSet.insert(ChannelNameLowercased);
|
||||||
|
}
|
||||||
|
|
||||||
/* Add the preset channels */
|
/* Add the preset channels */
|
||||||
boost::program_options::parsed_options ChannelsParsedOptions(boost::program_options::parse_config_file<char>(std::string(ConfigPath).append(CHANNELS_FILE).c_str(), NULL, true));
|
boost::program_options::parsed_options ChannelsParsedOptions(boost::program_options::parse_config_file<char>(std::string(ConfigPath).append(CHANNELS_FILE).c_str(), NULL, true));
|
||||||
if(ChannelsParsedOptions.options.empty())
|
if(ChannelsParsedOptions.options.empty())
|
||||||
@ -238,8 +269,12 @@ CIRCServer::Init()
|
|||||||
if(ChannelUsersIt == ChannelUsersMap.end())
|
if(ChannelUsersIt == ChannelUsersMap.end())
|
||||||
BOOST_THROW_EXCEPTION(Error("No allowed users were set for this channel!") << ChannelName_Info(OptionIt->string_key));
|
BOOST_THROW_EXCEPTION(Error("No allowed users were set for this channel!") << ChannelName_Info(OptionIt->string_key));
|
||||||
|
|
||||||
|
/* Check whether observers are allowed for this channel. */
|
||||||
|
std::set<std::string>::const_iterator ChannelObserversIt = ChannelObserversSet.find(ChannelNameLowercased);
|
||||||
|
bool AllowObservers = (ChannelObserversIt != ChannelObserversSet.end());
|
||||||
|
|
||||||
/* Insert the channel name lowercased for comparisons, but leave the original spelling in the object */
|
/* Insert the channel name lowercased for comparisons, but leave the original spelling in the object */
|
||||||
m_Channels.insert(ChannelNameLowercased, new CChannel(OptionIt->string_key, OptionIt->value[0], ChannelUsersIt->second));
|
m_Channels.insert(ChannelNameLowercased, new CChannel(OptionIt->string_key, OptionIt->value[0], ChannelUsersIt->second, AllowObservers));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set up an acceptor for every IP stack (if desired) */
|
/* Set up an acceptor for every IP stack (if desired) */
|
||||||
@ -308,10 +343,11 @@ CIRCServer::ReceiveMessage_JOIN(CClient* Sender, const std::vector<std::string>&
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ROSEV-SPECIFIC: Only allow joining after the user has identified. */
|
/* ROSEV-SPECIFIC: Don't allow joining if the user still has to identify. */
|
||||||
if(!Sender->GetUserState().IsIdentified)
|
const std::map< std::string, boost::array<char, SHA512_DIGEST_LENGTH> >& UserPasshashMap = m_Configuration.GetUserPasshashMap();
|
||||||
|
if(UserPasshashMap.find(Sender->GetNicknameLowercased()) != UserPasshashMap.end() && !Sender->GetUserState().IsIdentified)
|
||||||
{
|
{
|
||||||
Sender->SendNotice(NULL, "You have to identify before joining a channel!");
|
Sender->SendNotice(NULL, "Please identify first!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -340,27 +376,30 @@ CIRCServer::ReceiveMessage_JOIN(CClient* Sender, const std::vector<std::string>&
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* ROSEV-SPECIFIC: For network clients, only allow joining channels this user is allowed to join */
|
/* ROSEV-SPECIFIC: Virtual clients and clients on the list of allowed users automatically get voice.
|
||||||
|
If we don't allow observers, only these clients may even join. */
|
||||||
const std::set<std::string>& AllowedUsers = it->second->GetAllowedUsers();
|
const std::set<std::string>& AllowedUsers = it->second->GetAllowedUsers();
|
||||||
if(Sender->IsNetworkClient() && AllowedUsers.find(Sender->GetNicknameLowercased()) == AllowedUsers.end())
|
bool IsVoicedClient = (!Sender->IsNetworkClient() || AllowedUsers.find(Sender->GetNicknameLowercased()) != AllowedUsers.end());
|
||||||
|
|
||||||
|
if(!IsVoicedClient && !it->second->DoAllowObservers())
|
||||||
{
|
{
|
||||||
Sender->SendNotice(NULL, "You are not on the list of allowed users for this channel!");
|
Sender->SendNotice(NULL, "You are not allowed to join this channel!");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Check if the user is already part of this channel */
|
/* Check if the user is already part of this channel */
|
||||||
const std::set<CClient*>& Clients = it->second->GetClients();
|
const std::map<CClient*, CChannel::ClientStatus>& Clients = it->second->GetClients();
|
||||||
if(Clients.find(Sender) == Clients.end())
|
if(Clients.find(Sender) == Clients.end())
|
||||||
{
|
{
|
||||||
/* Join this channel */
|
/* Join this channel */
|
||||||
it->second->AddClient(Sender);
|
it->second->AddClient(Sender, (IsVoicedClient ? CChannel::Voice : CChannel::NoStatus));
|
||||||
Sender->AddJoinedChannel(it->second);
|
Sender->AddJoinedChannel(it->second);
|
||||||
|
|
||||||
/* Send a JOIN response to all channel members (including this new one) */
|
/* Send a JOIN response to all channel members (including this new one) */
|
||||||
std::string Response(boost::str(boost::format(":%s JOIN #%s") % Sender->GetPrefix() % it->second->GetName()));
|
std::string Response(boost::str(boost::format(":%s JOIN #%s") % Sender->GetPrefix() % it->second->GetName()));
|
||||||
|
|
||||||
for(std::set<CClient*>::const_iterator ClientIt = Clients.begin(); ClientIt != Clients.end(); ++ClientIt)
|
for(std::map<CClient*, CChannel::ClientStatus>::const_iterator ClientIt = Clients.begin(); ClientIt != Clients.end(); ++ClientIt)
|
||||||
(*ClientIt)->SendIRCMessage(Response);
|
ClientIt->first->SendIRCMessage(Response);
|
||||||
|
|
||||||
/* Send the results of respective TOPIC and NAMES commands */
|
/* Send the results of respective TOPIC and NAMES commands */
|
||||||
std::vector<std::string> CallParameters;
|
std::vector<std::string> CallParameters;
|
||||||
@ -434,15 +473,18 @@ CIRCServer::ReceiveMessage_NAMES(CClient* Sender, const std::vector<std::string>
|
|||||||
{
|
{
|
||||||
/* Return a string list of joined nicknames.
|
/* Return a string list of joined nicknames.
|
||||||
ROSEV-SPECIFIC: We don't support any operators or voiced people. */
|
ROSEV-SPECIFIC: We don't support any operators or voiced people. */
|
||||||
const std::set<CClient*>& Clients = it->second->GetClients();
|
const std::map<CClient*, CChannel::ClientStatus>& Clients = it->second->GetClients();
|
||||||
std::string NicknameList;
|
std::string NicknameList;
|
||||||
|
|
||||||
for(std::set<CClient*>::const_iterator ClientIt = Clients.begin(); ClientIt != Clients.end(); ++ClientIt)
|
for(std::map<CClient*, CChannel::ClientStatus>::const_iterator ClientIt = Clients.begin(); ClientIt != Clients.end(); ++ClientIt)
|
||||||
{
|
{
|
||||||
if(!NicknameList.empty())
|
if(!NicknameList.empty())
|
||||||
NicknameList.append(" ");
|
NicknameList.append(" ");
|
||||||
|
|
||||||
NicknameList.append((*ClientIt)->GetNickname());
|
if(ClientIt->second == CChannel::Voice)
|
||||||
|
NicknameList.append("+");
|
||||||
|
|
||||||
|
NicknameList.append(ClientIt->first->GetNickname());
|
||||||
}
|
}
|
||||||
|
|
||||||
Sender->SendNumericReply(RPL_NAMREPLY) % Channel % NicknameList;
|
Sender->SendNumericReply(RPL_NAMREPLY) % Channel % NicknameList;
|
||||||
@ -520,15 +562,22 @@ CIRCServer::ReceiveMessage_NICK(CClient* Sender, const std::vector<std::string>&
|
|||||||
if(!CurrentNickname.empty())
|
if(!CurrentNickname.empty())
|
||||||
{
|
{
|
||||||
const std::string& CurrentNicknameLowercased = NetSender->GetNicknameLowercased();
|
const std::string& CurrentNicknameLowercased = NetSender->GetNicknameLowercased();
|
||||||
|
|
||||||
std::map<std::string, CClient*>::iterator it = m_Nicknames.find(CurrentNicknameLowercased);
|
std::map<std::string, CClient*>::iterator it = m_Nicknames.find(CurrentNicknameLowercased);
|
||||||
|
|
||||||
|
/* ROSEV-SPECIFIC: Don't allow changing the nickname if the user has already identified */
|
||||||
if(it->second->GetUserState().IsIdentified)
|
if(it->second->GetUserState().IsIdentified)
|
||||||
{
|
{
|
||||||
/* ROSEV-SPECIFIC: Don't allow changing the nickname if the user has already identified */
|
|
||||||
NetSender->SendNotice(NULL, "You cannot change your nickname after having identified!");
|
NetSender->SendNotice(NULL, "You cannot change your nickname after having identified!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ROSEV-SPECIFIC: Don't allow changing the nickname if the user has already joined a channel */
|
||||||
|
if(it->second->GetJoinedChannels().size() > 0)
|
||||||
|
{
|
||||||
|
NetSender->SendNotice(NULL, "You cannot change your nickname after having joined a channel!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_Nicknames.erase(it);
|
m_Nicknames.erase(it);
|
||||||
NetSender->SendIRCMessage(boost::str(boost::format(":%s NICK %s") % NetSender->GetPrefix() % NewNickname));
|
NetSender->SendIRCMessage(boost::str(boost::format(":%s NICK %s") % NetSender->GetPrefix() % NewNickname));
|
||||||
}
|
}
|
||||||
@ -537,17 +586,22 @@ CIRCServer::ReceiveMessage_NICK(CClient* Sender, const std::vector<std::string>&
|
|||||||
m_Nicknames.insert(std::make_pair(NewNicknameLowercased, NetSender));
|
m_Nicknames.insert(std::make_pair(NewNicknameLowercased, NetSender));
|
||||||
NetSender->SetNickname(NewNickname, NewNicknameLowercased);
|
NetSender->SetNickname(NewNickname, NewNicknameLowercased);
|
||||||
|
|
||||||
/* Check if we have already registered with a nickname before */
|
/* Check if we have already registered with a nickname before. */
|
||||||
CClient::UserState State = NetSender->GetUserState();
|
CClient::UserState State = NetSender->GetUserState();
|
||||||
if(_IsUserRegistered(State))
|
if(_IsUserRegistered(State))
|
||||||
return;
|
{
|
||||||
|
/* The nickname has just been changed, so we need to recheck whether it's a preset one. */
|
||||||
|
_CheckForPresetNickname(NetSender);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We have not, so store this and send the welcome messages if the USER message has also been sent. */
|
||||||
|
State.HasSentNickMessage = true;
|
||||||
|
NetSender->SetUserState(State);
|
||||||
|
|
||||||
/* We have not, so store this and send the welcome messages */
|
if(State.HasSentUserMessage)
|
||||||
State.HasSentNickMessage = true;
|
_WelcomeClient(NetSender);
|
||||||
NetSender->SetUserState(State);
|
}
|
||||||
|
|
||||||
if(_IsUserRegistered(State))
|
|
||||||
_WelcomeClient(NetSender);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -619,7 +673,7 @@ CIRCServer::ReceiveMessage_PART(CClient* Sender, const std::vector<std::string>&
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Check if the user is part of this channel */
|
/* Check if the user is part of this channel */
|
||||||
const std::set<CClient*>& Clients = it->second->GetClients();
|
const std::map<CClient*, CChannel::ClientStatus>& Clients = it->second->GetClients();
|
||||||
if(Clients.find(Sender) == Clients.end())
|
if(Clients.find(Sender) == Clients.end())
|
||||||
{
|
{
|
||||||
Sender->SendNumericReply(ERR_NOTONCHANNEL) % Channel;
|
Sender->SendNumericReply(ERR_NOTONCHANNEL) % Channel;
|
||||||
@ -630,8 +684,8 @@ CIRCServer::ReceiveMessage_PART(CClient* Sender, const std::vector<std::string>&
|
|||||||
ROSEV-SPECIFIC: Messages supplied to the PART command are ignored. */
|
ROSEV-SPECIFIC: Messages supplied to the PART command are ignored. */
|
||||||
std::string Response(boost::str(boost::format(":%s PART #%s") % Sender->GetPrefix() % it->second->GetName()));
|
std::string Response(boost::str(boost::format(":%s PART #%s") % Sender->GetPrefix() % it->second->GetName()));
|
||||||
|
|
||||||
for(std::set<CClient*>::const_iterator ClientIt = Clients.begin(); ClientIt != Clients.end(); ++ClientIt)
|
for(std::map<CClient*, CChannel::ClientStatus>::const_iterator ClientIt = Clients.begin(); ClientIt != Clients.end(); ++ClientIt)
|
||||||
(*ClientIt)->SendIRCMessage(Response);
|
ClientIt->first->SendIRCMessage(Response);
|
||||||
|
|
||||||
/* Leave the channel */
|
/* Leave the channel */
|
||||||
it->second->RemoveClient(Sender);
|
it->second->RemoveClient(Sender);
|
||||||
@ -725,11 +779,11 @@ CIRCServer::ReceiveMessage_PRIVMSG(CClient* Sender, const std::vector<std::strin
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is this client part of this channel? */
|
/* ROSEV-SPECIFIC: Only joined clients with voice status may send anything. */
|
||||||
const std::set<CChannel*>& JoinedChannels = Sender->GetJoinedChannels();
|
const std::map<CClient*, CChannel::ClientStatus>& Clients = it->second->GetClients();
|
||||||
std::set<CChannel*>::const_iterator JoinedIt = JoinedChannels.find(const_cast<CChannel*>(it->second));
|
std::map<CClient*, CChannel::ClientStatus>::const_iterator ClientIt = Clients.find(Sender);
|
||||||
|
|
||||||
if(JoinedIt == JoinedChannels.end())
|
if(ClientIt == Clients.end() || ClientIt->second == CChannel::NoStatus)
|
||||||
{
|
{
|
||||||
Sender->SendNumericReply(ERR_CANNOTSENDTOCHAN) % Channel;
|
Sender->SendNumericReply(ERR_CANNOTSENDTOCHAN) % Channel;
|
||||||
return;
|
return;
|
||||||
@ -737,11 +791,10 @@ CIRCServer::ReceiveMessage_PRIVMSG(CClient* Sender, const std::vector<std::strin
|
|||||||
|
|
||||||
/* Send the message to all channel members but not back to this client */
|
/* Send the message to all channel members but not back to this client */
|
||||||
std::string Response(boost::str(boost::format(":%s PRIVMSG #%s :%s") % Sender->GetPrefix() % it->second->GetName() % Parameters[1]));
|
std::string Response(boost::str(boost::format(":%s PRIVMSG #%s :%s") % Sender->GetPrefix() % it->second->GetName() % Parameters[1]));
|
||||||
const std::set<CClient*>& Clients = it->second->GetClients();
|
|
||||||
|
|
||||||
for(std::set<CClient*>::const_iterator ClientIt = Clients.begin(); ClientIt != Clients.end(); ++ClientIt)
|
for(std::map<CClient*, CChannel::ClientStatus>::const_iterator ClientIt = Clients.begin(); ClientIt != Clients.end(); ++ClientIt)
|
||||||
if(*ClientIt != Sender)
|
if(ClientIt->first != Sender)
|
||||||
(*ClientIt)->SendIRCMessage(Response);
|
ClientIt->first->SendIRCMessage(Response);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -838,14 +891,15 @@ CIRCServer::ReceiveMessage_USER(CClient* Sender, const std::vector<std::string>&
|
|||||||
|
|
||||||
/* Modify and check the user state */
|
/* Modify and check the user state */
|
||||||
CClient::UserState State = NetSender->GetUserState();
|
CClient::UserState State = NetSender->GetUserState();
|
||||||
if(_IsUserRegistered(State))
|
if(!_IsUserRegistered(State))
|
||||||
return;
|
{
|
||||||
|
/* We have not yet registered, so store this and send the welcome messages if the NICK message has also been sent. */
|
||||||
|
State.HasSentUserMessage = true;
|
||||||
|
NetSender->SetUserState(State);
|
||||||
|
|
||||||
State.HasSentUserMessage = true;
|
if(State.HasSentNickMessage)
|
||||||
NetSender->SetUserState(State);
|
_WelcomeClient(NetSender);
|
||||||
|
}
|
||||||
if(_IsUserRegistered(State))
|
|
||||||
_WelcomeClient(NetSender);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* PROJECT: ReactOS Deutschland e.V. IRC System
|
* PROJECT: ReactOS Deutschland e.V. IRC System
|
||||||
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
||||||
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
||||||
* COPYRIGHT: Copyright 2010 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
* COPYRIGHT: Copyright 2010-2011 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
||||||
* AUTHORS: Colin Finck <colin@reactos.org>
|
* AUTHORS: Colin Finck <colin@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -47,6 +47,7 @@ private:
|
|||||||
|
|
||||||
inline void _Accept(boost::asio::ip::tcp::acceptor* Acceptor);
|
inline void _Accept(boost::asio::ip::tcp::acceptor* Acceptor);
|
||||||
void _AddAcceptor(const boost::asio::ip::tcp::acceptor::protocol_type& Protocol);
|
void _AddAcceptor(const boost::asio::ip::tcp::acceptor::protocol_type& Protocol);
|
||||||
|
void _CheckForPresetNickname(CNetworkClient* Client);
|
||||||
void _HandleNewConnection(boost::asio::ip::tcp::acceptor* Acceptor, const boost::system::error_code& ErrorCode);
|
void _HandleNewConnection(boost::asio::ip::tcp::acceptor* Acceptor, const boost::system::error_code& ErrorCode);
|
||||||
std::string _HandleSSLPassword() const;
|
std::string _HandleSSLPassword() const;
|
||||||
inline bool _IsUserRegistered(const CClient::UserState& ClientUserState);
|
inline bool _IsUserRegistered(const CClient::UserState& ClientUserState);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* PROJECT: ReactOS Deutschland e.V. IRC System
|
* PROJECT: ReactOS Deutschland e.V. IRC System
|
||||||
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
||||||
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
||||||
* COPYRIGHT: Copyright 2010 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
* COPYRIGHT: Copyright 2010-2011 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
||||||
* AUTHORS: Colin Finck <colin@reactos.org>
|
* AUTHORS: Colin Finck <colin@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -26,7 +26,41 @@ CLogBot::_GetLogTimestamp()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CLogBot::_LogJoinOrPart(CClient* Sender, const std::vector<std::string>& Parameters, const std::string& LogMessage)
|
CLogBot::_LogMessage_JOIN(CClient* Sender, const std::vector<std::string>& Parameters)
|
||||||
|
{
|
||||||
|
/* Expect a channel as the first and only parameter */
|
||||||
|
assert(Parameters.size() == 1);
|
||||||
|
assert(Parameters[0][0] == '#');
|
||||||
|
|
||||||
|
/* Lowercase it for searching */
|
||||||
|
std::string ChannelNameLowercased(Parameters[0].substr(1));
|
||||||
|
std::transform(ChannelNameLowercased.begin(), ChannelNameLowercased.end(), ChannelNameLowercased.begin(), tolower);
|
||||||
|
|
||||||
|
/* Check if we log this channel */
|
||||||
|
boost::ptr_map<std::string, std::ofstream>::iterator ChannelStreamIt = m_ChannelStreamMap.find(ChannelNameLowercased);
|
||||||
|
if(ChannelStreamIt == m_ChannelStreamMap.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Determine the status of this client */
|
||||||
|
const boost::ptr_map<std::string, CChannel>& Channels = m_IRCServer.GetChannels();
|
||||||
|
boost::ptr_map<std::string, CChannel>::const_iterator ChannelIt = Channels.find(ChannelNameLowercased);
|
||||||
|
assert(ChannelIt != Channels.end());
|
||||||
|
|
||||||
|
const std::map<CClient*, CChannel::ClientStatus>& Clients = ChannelIt->second->GetClients();
|
||||||
|
std::map<CClient*, CChannel::ClientStatus>::const_iterator ClientIt = Clients.find(Sender);
|
||||||
|
assert(ClientIt != Clients.end());
|
||||||
|
|
||||||
|
/* Finally log the message */
|
||||||
|
(*ChannelStreamIt->second) << boost::str(boost::format("%s %s has joined %s%s\n")
|
||||||
|
% _GetLogTimestamp()
|
||||||
|
% Sender->GetNickname()
|
||||||
|
% Parameters[0]
|
||||||
|
% (ClientIt->second == CChannel::Voice ? " with voice status" : "")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CLogBot::_LogMessage_PART(CClient* Sender, const std::vector<std::string>& Parameters)
|
||||||
{
|
{
|
||||||
/* Expect a channel as the first and only parameter */
|
/* Expect a channel as the first and only parameter */
|
||||||
assert(Parameters.size() == 1);
|
assert(Parameters.size() == 1);
|
||||||
@ -39,20 +73,7 @@ CLogBot::_LogJoinOrPart(CClient* Sender, const std::vector<std::string>& Paramet
|
|||||||
/* Check if we log this channel and add a message in this case */
|
/* Check if we log this channel and add a message in this case */
|
||||||
boost::ptr_map<std::string, std::ofstream>::iterator ChannelStreamIt = m_ChannelStreamMap.find(ChannelNameLowercased);
|
boost::ptr_map<std::string, std::ofstream>::iterator ChannelStreamIt = m_ChannelStreamMap.find(ChannelNameLowercased);
|
||||||
if(ChannelStreamIt != m_ChannelStreamMap.end())
|
if(ChannelStreamIt != m_ChannelStreamMap.end())
|
||||||
(*ChannelStreamIt->second) << boost::str(boost::format(LogMessage) % _GetLogTimestamp() % Sender->GetNickname() % Parameters[0]);
|
(*ChannelStreamIt->second) << boost::str(boost::format("%s %s has left %s\n") % _GetLogTimestamp() % Sender->GetNickname() % Parameters[0]);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
CLogBot::_LogMessage_JOIN(CClient* Sender, const std::vector<std::string>& Parameters)
|
|
||||||
{
|
|
||||||
_LogJoinOrPart(Sender, Parameters, "%s %s has joined %s\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CLogBot::_LogMessage_PART(CClient* Sender, const std::vector<std::string>& Parameters)
|
|
||||||
{
|
|
||||||
_LogJoinOrPart(Sender, Parameters, "%s %s has left %s\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* PROJECT: ReactOS Deutschland e.V. IRC System
|
* PROJECT: ReactOS Deutschland e.V. IRC System
|
||||||
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
||||||
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
||||||
* COPYRIGHT: Copyright 2010 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
* COPYRIGHT: Copyright 2010-2011 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
||||||
* AUTHORS: Colin Finck <colin@reactos.org>
|
* AUTHORS: Colin Finck <colin@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -20,7 +20,6 @@ private:
|
|||||||
std::map<std::string, void (CLogBot::*)(CClient*, const std::vector<std::string>&)> m_CommandHandlers;
|
std::map<std::string, void (CLogBot::*)(CClient*, const std::vector<std::string>&)> m_CommandHandlers;
|
||||||
|
|
||||||
std::string _GetLogTimestamp();
|
std::string _GetLogTimestamp();
|
||||||
void _LogJoinOrPart(CClient* Sender, const std::vector<std::string>& Parameters, const std::string& LogMessage);
|
|
||||||
void _LogMessage_JOIN(CClient* Sender, const std::vector<std::string>& Parameters);
|
void _LogMessage_JOIN(CClient* Sender, const std::vector<std::string>& Parameters);
|
||||||
void _LogMessage_PART(CClient* Sender, const std::vector<std::string>& Parameters);
|
void _LogMessage_PART(CClient* Sender, const std::vector<std::string>& Parameters);
|
||||||
void _LogMessage_PRIVMSG(CClient* Sender, const std::vector<std::string>& Parameters);
|
void _LogMessage_PRIVMSG(CClient* Sender, const std::vector<std::string>& Parameters);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* PROJECT: ReactOS Deutschland e.V. IRC System
|
* PROJECT: ReactOS Deutschland e.V. IRC System
|
||||||
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
||||||
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
||||||
* COPYRIGHT: Copyright 2010 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
* COPYRIGHT: Copyright 2010-2011 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
||||||
* AUTHORS: Colin Finck <colin@reactos.org>
|
* AUTHORS: Colin Finck <colin@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -266,6 +266,14 @@ CNetworkClient::Init()
|
|||||||
_Receive();
|
_Receive();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CNetworkClient::RestartIdentifyTimer()
|
||||||
|
{
|
||||||
|
m_Timer.cancel();
|
||||||
|
m_Timer.expires_from_now(boost::posix_time::seconds(IDENTIFY_TIMEOUT));
|
||||||
|
m_Timer.async_wait(boost::bind(&CNetworkClient::_IdentifyDeadline, shared_from_this(), boost::asio::placeholders::error));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CNetworkClient::RestartPingTimer()
|
CNetworkClient::RestartPingTimer()
|
||||||
{
|
{
|
||||||
@ -344,11 +352,3 @@ CNetworkClient::Shutdown()
|
|||||||
|
|
||||||
m_ShutdownCompleted = true;
|
m_ShutdownCompleted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
CNetworkClient::StartIdentifyTimer()
|
|
||||||
{
|
|
||||||
m_Timer.cancel();
|
|
||||||
m_Timer.expires_from_now(boost::posix_time::seconds(IDENTIFY_TIMEOUT));
|
|
||||||
m_Timer.async_wait(boost::bind(&CNetworkClient::_IdentifyDeadline, shared_from_this(), boost::asio::placeholders::error));
|
|
||||||
}
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* PROJECT: ReactOS Deutschland e.V. IRC System
|
* PROJECT: ReactOS Deutschland e.V. IRC System
|
||||||
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
||||||
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
||||||
* COPYRIGHT: Copyright 2010 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
* COPYRIGHT: Copyright 2010-2011 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
||||||
* AUTHORS: Colin Finck <colin@reactos.org>
|
* AUTHORS: Colin Finck <colin@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -14,6 +14,7 @@ public:
|
|||||||
void Init();
|
void Init();
|
||||||
virtual bool IsInitialized() const = 0;
|
virtual bool IsInitialized() const = 0;
|
||||||
bool IsNetworkClient() const { return true; }
|
bool IsNetworkClient() const { return true; }
|
||||||
|
void RestartIdentifyTimer();
|
||||||
void RestartPingTimer();
|
void RestartPingTimer();
|
||||||
void SetNickname(const std::string& Nickname, const std::string& NicknameLowercased);
|
void SetNickname(const std::string& Nickname, const std::string& NicknameLowercased);
|
||||||
void SetUserState(const CClient::UserState& NewUserState);
|
void SetUserState(const CClient::UserState& NewUserState);
|
||||||
@ -22,7 +23,6 @@ public:
|
|||||||
CNumericReplyFormatter SendNumericReply(short Code);
|
CNumericReplyFormatter SendNumericReply(short Code);
|
||||||
void SendPrivateMessage(CClient* Sender, const std::string& PrivateMessage);
|
void SendPrivateMessage(CClient* Sender, const std::string& PrivateMessage);
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
void StartIdentifyTimer();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
char m_InputBuffer[2 * IRC_MESSAGE_LENGTH];
|
char m_InputBuffer[2 * IRC_MESSAGE_LENGTH];
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* PROJECT: ReactOS Deutschland e.V. IRC System
|
* PROJECT: ReactOS Deutschland e.V. IRC System
|
||||||
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
||||||
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
||||||
* COPYRIGHT: Copyright 2010 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
* COPYRIGHT: Copyright 2010-2011 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
||||||
* AUTHORS: Colin Finck <colin@reactos.org>
|
* AUTHORS: Colin Finck <colin@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -20,26 +20,6 @@ CNickServ::CNickServ(CIRCServer& IRCServer)
|
|||||||
bool
|
bool
|
||||||
CNickServ::Init()
|
CNickServ::Init()
|
||||||
{
|
{
|
||||||
/* Load the NickServ-specific configuration (just the extra Users file for now) */
|
|
||||||
std::string ConfigFile(m_IRCServer.GetConfiguration().GetConfigPath());
|
|
||||||
ConfigFile.append(NICKSERV_USERS_FILE);
|
|
||||||
|
|
||||||
boost::program_options::parsed_options UsersParsedOptions(boost::program_options::parse_config_file<char>(ConfigFile.c_str(), NULL, true));
|
|
||||||
for(std::vector< boost::program_options::basic_option<char> >::const_iterator it = UsersParsedOptions.options.begin(); it != UsersParsedOptions.options.end(); ++it)
|
|
||||||
{
|
|
||||||
/* Convert the hexadecimal string passhash into a binary one */
|
|
||||||
const std::string& HexPasshash = it->value[0];
|
|
||||||
boost::array<char, SHA512_DIGEST_LENGTH> BinaryPasshash;
|
|
||||||
|
|
||||||
if(HexPasshash.length() != 2 * SHA512_DIGEST_LENGTH)
|
|
||||||
BOOST_THROW_EXCEPTION(Error("Length of a passhash must be 128 characters!") << Passhash_Info(HexPasshash));
|
|
||||||
|
|
||||||
for(int i = 0; i < SHA512_DIGEST_LENGTH; ++i)
|
|
||||||
BinaryPasshash[i] = static_cast<char>(strtol(HexPasshash.substr(2 * i, 2).c_str(), NULL, 16));
|
|
||||||
|
|
||||||
m_UserPasshashMap.insert(std::make_pair(it->string_key, BinaryPasshash));
|
|
||||||
}
|
|
||||||
|
|
||||||
Info("NickServ is enabled.\n");
|
Info("NickServ is enabled.\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -72,7 +52,7 @@ CNickServ::_ReceiveCommand_GHOST(CNetworkClient* Sender, const std::vector<std::
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!_VerifyCredentials(Sender, Parameters[0], Parameters[1]))
|
if(!_VerifyCredentials(Sender, NicknameLowercased, Parameters[1]))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* The password is correct, so disconnect the user */
|
/* The password is correct, so disconnect the user */
|
||||||
@ -152,7 +132,7 @@ CNickServ::_ReceiveCommand_IDENTIFY(CNetworkClient* Sender, const std::vector<st
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!_VerifyCredentials(Sender, Sender->GetNickname(), Parameters[0]))
|
if(!_VerifyCredentials(Sender, Sender->GetNicknameLowercased(), Parameters[0]))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* The password is correct, so this user has successfully identified! */
|
/* The password is correct, so this user has successfully identified! */
|
||||||
@ -164,15 +144,15 @@ CNickServ::_ReceiveCommand_IDENTIFY(CNetworkClient* Sender, const std::vector<st
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CNickServ::_VerifyCredentials(CNetworkClient* Sender, const std::string& Nickname, const std::string& Password)
|
CNickServ::_VerifyCredentials(CNetworkClient* Sender, const std::string& NicknameLowercased, const std::string& Password)
|
||||||
{
|
{
|
||||||
/* Find the user */
|
/* Find the user */
|
||||||
std::map< std::string, boost::array<char, SHA512_DIGEST_LENGTH> >::const_iterator it = m_UserPasshashMap.find(Nickname);
|
const std::map< std::string, boost::array<char, SHA512_DIGEST_LENGTH> >& UserPasshashMap = m_IRCServer.GetConfiguration().GetUserPasshashMap();
|
||||||
|
std::map< std::string, boost::array<char, SHA512_DIGEST_LENGTH> >::const_iterator it = UserPasshashMap.find(NicknameLowercased);
|
||||||
|
|
||||||
if(it == m_UserPasshashMap.end())
|
if(it == UserPasshashMap.end())
|
||||||
{
|
{
|
||||||
Sender->SendNotice(this, "No password is known for this nickname!");
|
Sender->SendNotice(this, "No password is known for this nickname!");
|
||||||
Sender->SendNotice(this, "Ensure that your nickname is spelled correctly (it is case-sensitive).");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* PROJECT: ReactOS Deutschland e.V. IRC System
|
* PROJECT: ReactOS Deutschland e.V. IRC System
|
||||||
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
||||||
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
||||||
* COPYRIGHT: Copyright 2010 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
* COPYRIGHT: Copyright 2010-2011 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
||||||
* AUTHORS: Colin Finck <colin@reactos.org>
|
* AUTHORS: Colin Finck <colin@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -16,10 +16,9 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<std::string, void (CNickServ::*)(CNetworkClient*, const std::vector<std::string>&)> m_CommandHandlers;
|
std::map<std::string, void (CNickServ::*)(CNetworkClient*, const std::vector<std::string>&)> m_CommandHandlers;
|
||||||
std::map< std::string, boost::array<char, SHA512_DIGEST_LENGTH> > m_UserPasshashMap;
|
|
||||||
|
|
||||||
void _ReceiveCommand_GHOST(CNetworkClient* Sender, const std::vector<std::string>& Parameters);
|
void _ReceiveCommand_GHOST(CNetworkClient* Sender, const std::vector<std::string>& Parameters);
|
||||||
void _ReceiveCommand_HELP(CNetworkClient* Sender, const std::vector<std::string>& Parameters);
|
void _ReceiveCommand_HELP(CNetworkClient* Sender, const std::vector<std::string>& Parameters);
|
||||||
void _ReceiveCommand_IDENTIFY(CNetworkClient* Sender, const std::vector<std::string>& Parameters);
|
void _ReceiveCommand_IDENTIFY(CNetworkClient* Sender, const std::vector<std::string>& Parameters);
|
||||||
bool _VerifyCredentials(CNetworkClient* Sender, const std::string& Nickname, const std::string& Password);
|
bool _VerifyCredentials(CNetworkClient* Sender, const std::string& NicknameLowercased, const std::string& Password);
|
||||||
};
|
};
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* PROJECT: ReactOS Deutschland e.V. IRC System
|
* PROJECT: ReactOS Deutschland e.V. IRC System
|
||||||
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
||||||
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
||||||
* COPYRIGHT: Copyright 2010 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
* COPYRIGHT: Copyright 2010-2011 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
||||||
* AUTHORS: Colin Finck <colin@reactos.org>
|
* AUTHORS: Colin Finck <colin@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -116,29 +116,29 @@ CVoteBot::_ReceiveCommand_START(CClient* Sender)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save a copy of the currently present network clients, so that no one else can vote.
|
/* Collect all clients that may vote. These only include network clients with a status.
|
||||||
If a client leaves during the vote, he is also excluded (see CVoteBot::SendIRCMessage). */
|
If a client leaves during the vote, he is also excluded (see CVoteBot::SendIRCMessage). */
|
||||||
const std::set<CClient*>& Clients = m_Channel->GetClients();
|
const std::map<CClient*, CChannel::ClientStatus>& Clients = m_Channel->GetClients();
|
||||||
for(std::set<CClient*>::const_iterator it = Clients.begin(); it != Clients.end(); ++it)
|
for(std::map<CClient*, CChannel::ClientStatus>::const_iterator it = Clients.begin(); it != Clients.end(); ++it)
|
||||||
{
|
{
|
||||||
if((*it)->IsNetworkClient())
|
if(it->first->IsNetworkClient() && it->second != CChannel::NoStatus)
|
||||||
{
|
{
|
||||||
/* Preselect the "Abstention" option for the client.
|
/* Preselect the "Abstention" option for the client.
|
||||||
If he casts his vote, it is simply overwritten. */
|
If he casts his vote, it is simply overwritten. */
|
||||||
CVoteBot::VoteParameters VoteParameter = {0};
|
CVoteBot::VoteParameters VoteParameter = {0};
|
||||||
m_Votes.insert(std::make_pair(*it, VoteParameter));
|
m_Votes.insert(std::make_pair(it->first, VoteParameter));
|
||||||
|
|
||||||
/* Inform him about the question and the possible options.
|
/* Inform him about the question and the possible options.
|
||||||
Deliberately use private messages instead of notices as latter ones can appear in channels when using clients like ChatZilla. */
|
Deliberately use private messages instead of notices as latter ones can appear in channels when using clients like ChatZilla. */
|
||||||
(*it)->SendPrivateMessage(this, std::string(m_CurrentAdminNickname).append(" has set up a vote and I want your opinion."));
|
it->first->SendPrivateMessage(this, std::string(m_CurrentAdminNickname).append(" has set up a vote and I want your opinion."));
|
||||||
(*it)->SendPrivateMessage(this, std::string("Question: ").append(m_Question));
|
it->first->SendPrivateMessage(this, std::string("Question: ").append(m_Question));
|
||||||
(*it)->SendPrivateMessage(this, "Possible options:");
|
it->first->SendPrivateMessage(this, "Possible options:");
|
||||||
|
|
||||||
for(size_t i = 0; i < m_Options.size(); ++i)
|
for(size_t i = 0; i < m_Options.size(); ++i)
|
||||||
(*it)->SendPrivateMessage(this, boost::str(boost::format(" %u - %s") % i % m_Options[i]));
|
it->first->SendPrivateMessage(this, boost::str(boost::format(" %u - %s") % i % m_Options[i]));
|
||||||
|
|
||||||
(*it)->SendPrivateMessage(this, "Please send me the number of your option.");
|
it->first->SendPrivateMessage(this, "Please send me the number of your option.");
|
||||||
(*it)->SendPrivateMessage(this, boost::str(boost::format("If you don't answer within %u minutes, your vote will be counted as \"%s\".") % m_TimeLimitInMinutes % m_AbstentionTranslation));
|
it->first->SendPrivateMessage(this, boost::str(boost::format("If you don't answer within %u minutes, your vote will be counted as \"%s\".") % m_TimeLimitInMinutes % m_AbstentionTranslation));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,7 +149,7 @@ CVoteBot::_ReceiveCommand_START(CClient* Sender)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Finally report this to the channel as well */
|
/* Finally report this to the channel as well */
|
||||||
_SendToChannel(std::string(m_CurrentAdminNickname).append(" has set up a vote and I'm asking all of you in private messages now."));
|
_SendToChannel(std::string(m_CurrentAdminNickname).append(" has set up a vote and I'm asking all participating members in private messages now."));
|
||||||
|
|
||||||
/* The vote process officially starts... now! */
|
/* The vote process officially starts... now! */
|
||||||
m_Timer.expires_from_now(boost::posix_time::minutes(m_TimeLimitInMinutes));
|
m_Timer.expires_from_now(boost::posix_time::minutes(m_TimeLimitInMinutes));
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* PROJECT: ReactOS Deutschland e.V. IRC System
|
* PROJECT: ReactOS Deutschland e.V. IRC System
|
||||||
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
* LICENSE: GNU GPL v2 or any later version as published by the Free Software Foundation
|
||||||
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
* with the additional exemption that compiling, linking, and/or using OpenSSL is allowed
|
||||||
* COPYRIGHT: Copyright 2010 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
* COPYRIGHT: Copyright 2010-2011 ReactOS Deutschland e.V. <deutschland@reactos.org>
|
||||||
* AUTHORS: Colin Finck <colin@reactos.org>
|
* AUTHORS: Colin Finck <colin@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -49,11 +49,12 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define CHANNELS_FILE PATH_SEPARATOR "Channels.ini"
|
#define CHANNELS_FILE PATH_SEPARATOR "Channels.ini"
|
||||||
|
#define CHANNEL_OBSERVERS_FILE PATH_SEPARATOR "Channel_Observers.ini"
|
||||||
#define CHANNEL_USERS_FILE PATH_SEPARATOR "Channel_Users.ini"
|
#define CHANNEL_USERS_FILE PATH_SEPARATOR "Channel_Users.ini"
|
||||||
#define LOGBOT_FILE PATH_SEPARATOR "LogBot.ini"
|
#define LOGBOT_FILE PATH_SEPARATOR "LogBot.ini"
|
||||||
#define MAIN_CONFIG_FILE PATH_SEPARATOR "MainConfig.ini"
|
#define MAIN_CONFIG_FILE PATH_SEPARATOR "MainConfig.ini"
|
||||||
#define MOTD_FILE PATH_SEPARATOR "Motd.txt"
|
#define MOTD_FILE PATH_SEPARATOR "Motd.txt"
|
||||||
#define NICKSERV_USERS_FILE PATH_SEPARATOR "NickServ_Users.ini"
|
#define USERS_FILE PATH_SEPARATOR "Users.ini"
|
||||||
#define VOTEBOTMANAGER_FILE PATH_SEPARATOR "VoteBotManager.ini"
|
#define VOTEBOTMANAGER_FILE PATH_SEPARATOR "VoteBotManager.ini"
|
||||||
#define VOTEBOT_INDIVIDUAL_FILE PATH_SEPARATOR "VoteBot_%s.ini"
|
#define VOTEBOT_INDIVIDUAL_FILE PATH_SEPARATOR "VoteBot_%s.ini"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user