diff --git a/ft_irc3/includes/AdditionalCommands.hpp b/ft_irc3/includes/AdditionalCommands.hpp index fa7e206..d5a13c7 100644 --- a/ft_irc3/includes/AdditionalCommands.hpp +++ b/ft_irc3/includes/AdditionalCommands.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/21 18:09:05 by fgras-ca #+# #+# */ -/* Updated: 2024/05/30 17:10:18 by fgras-ca ### ########.fr */ +/* Updated: 2024/06/01 18:48:32 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -22,30 +22,27 @@ #include "Who.hpp" #include "InviteHandler.hpp" #include "TopicHandler.hpp" +#include "KickHandler.hpp" #include #include #include -// Forward declarations class Server; class Client; class Channel; -class CommandHandler; - class AdditionalCommands { -private: - Server *_server; - CommandHandler *_commandhandler; - //InviteHandler *_inviteHandler; -public: - AdditionalCommands(Server *server); - void processCommand(Client *client, const std::string &command); - void broadcastChannelList(Client *client, Server *server); - void handlePartCommand(Server *server, Client *client, const std::string &command); - void handleNickCommand(Server *server, Client *client, const std::string &command); - void handlePrivmsgCommand(Server *server, Client *client, const std::string &command); + private: + Server *_server; + + public: + AdditionalCommands(Server *server); + void processCommand(Client *client, const std::string &command); + void broadcastChannelList(Client *client, Server *server); + void handlePartCommand(Server *server, Client *client, const std::string &command); + void handleNickCommand(Server *server, Client *client, const std::string &command); + void handlePrivmsgCommand(Server *server, Client *client, const std::string &command); }; -#endif // ADDITIONALCOMMANDS_HPP +#endif diff --git a/ft_irc3/includes/Channel.hpp b/ft_irc3/includes/Channel.hpp index 0586c72..fe35d5f 100644 --- a/ft_irc3/includes/Channel.hpp +++ b/ft_irc3/includes/Channel.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 12:41:35 by fgras-ca #+# #+# */ -/* Updated: 2024/05/30 18:32:18 by fgras-ca ### ########.fr */ +/* Updated: 2024/06/01 18:49:53 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -28,57 +28,53 @@ class Client; class Channel { -public: - Channel(const std::string &name); - ~Channel(); + public: + Channel(const std::string &name); + ~Channel(); - const std::string &getName() const; - void addClient(Client *client); - void removeClient(Client *client); - bool isEmpty() const; - const std::vector &getClients() const; - void addOperator(Client *client); - bool isOperator(Client *client) const; - void removeOperator(Client *client); // Ajouté - bool hasClient(Client *client) const; - void broadcast(const std::string &message, Client *_client, Server *_server); + const std::string &getName() const; + void addClient(Client *client); + void removeClient(Client *client); + bool isEmpty() const; + const std::vector &getClients() const; + void addOperator(Client *client); + bool isOperator(Client *client) const; + void removeOperator(Client *client); // Ajouté + bool hasClient(Client *client) const; + void broadcast(const std::string &message, Client *_client, Server *_server); + bool isBanned(Client *client) const; + bool isFull() const; + bool isInviteOnly() const; + bool isInvited(Client *client) const; + bool checkKey(const std::string &key) const; + const std::string &getTopic() const; + const std::string &getTopicSetter() const; + time_t getTopicTime() const; + void setTopic(const std::string &topic, const std::string &setter); - // Ajouts - bool isBanned(Client *client) const; - bool isFull() const; - bool isInviteOnly() const; - bool isInvited(Client *client) const; - bool checkKey(const std::string &key) const; - const std::string &getTopic() const; - const std::string &getTopicSetter() const; - time_t getTopicTime() const; - void setTopic(const std::string &topic, const std::string &setter); - - void setClientLimit(size_t limit); // Ajouté - size_t getClientLimit() const; // Ajouté - void setInviteOnly(bool inviteOnly); // Ajouté - void setKey(const std::string &key); // Ajouté - void setTopicProtection(bool protection); // Ajouté - std::string getModes() const; // Ajouté - bool getTopicProtection() const; - void addInvitedClient(Client* client); - - -private: - std::string _name; - std::vector _clients; - std::vector _operators; - std::set _bannedClients; - std::set _invitedClients; - std::string _key; - std::string _topic; - std::string _topicSetter; - time_t _topicTime; - size_t _clientLimit; - bool _inviteOnly; - bool _topicProtection; // Ajouté + void setClientLimit(size_t limit); + size_t getClientLimit() const; + void setInviteOnly(bool inviteOnly); + void setKey(const std::string &key); + void setTopicProtection(bool protection); + std::string getModes() const; + bool getTopicProtection() const; + void addInvitedClient(Client* client); + private: + std::string _name; + std::vector _clients; + std::vector _operators; + std::set _bannedClients; + std::set _invitedClients; + std::string _key; + std::string _topic; + std::string _topicSetter; + time_t _topicTime; + size_t _clientLimit; + bool _inviteOnly; + bool _topicProtection; }; -#endif // CHANNEL_HPP +#endif diff --git a/ft_irc3/includes/Client.hpp b/ft_irc3/includes/Client.hpp index 0b47f16..364d67b 100644 --- a/ft_irc3/includes/Client.hpp +++ b/ft_irc3/includes/Client.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 12:15:42 by fgras-ca #+# #+# */ -/* Updated: 2024/05/31 11:31:54 by fgras-ca ### ########.fr */ +/* Updated: 2024/06/01 18:47:36 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -35,13 +35,13 @@ public: void authenticate(); bool isOperator() const; void setOperator(bool isOperator); - + // Ajout des méthodes pour la gestion du statut "away" bool isAway() const; const std::string &getAwayMessage() const; void setAwayMessage(const std::string &message); void setAway(bool away); - const std::string &getkey() const; + std::string getKey() const; void setkey(const std::string &key); private: @@ -58,5 +58,4 @@ private: std::string _key; }; -#endif // CLIENT_HPP - +#endif diff --git a/ft_irc3/includes/ClientManager.hpp b/ft_irc3/includes/ClientManager.hpp index 21b744d..ae6f457 100644 --- a/ft_irc3/includes/ClientManager.hpp +++ b/ft_irc3/includes/ClientManager.hpp @@ -6,15 +6,13 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 18:30:07 by fgras-ca #+# #+# */ -/* Updated: 2024/05/28 14:17:28 by fgras-ca ### ########.fr */ +/* Updated: 2024/06/01 18:50:30 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef CLIENTMANAGER_HPP #define CLIENTMANAGER_HPP -#include -#include #include "Client.hpp" #include "Channel.hpp" #include "Server.hpp" @@ -33,21 +31,22 @@ #include #include #include +#include +#include class Server; class Client; class ClientManager { -public: - ClientManager(Server *server); - void acceptClient(); - void handleClient(int client_fd); - void removeClient(int client_fd); + public: + ClientManager(Server *server); + void acceptClient(); + void handleClient(int client_fd); + void removeClient(int client_fd); - -private: - Server *_server; + private: + Server *_server; }; #endif diff --git a/ft_irc3/includes/CommandHandler.hpp b/ft_irc3/includes/CommandHandler.hpp index d646203..3ca3a75 100644 --- a/ft_irc3/includes/CommandHandler.hpp +++ b/ft_irc3/includes/CommandHandler.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 18:14:12 by fgras-ca #+# #+# */ -/* Updated: 2024/05/30 12:42:22 by fgras-ca ### ########.fr */ +/* Updated: 2024/06/01 18:47:51 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -59,4 +59,4 @@ public: }; -#endif // COMMANDHANDLER_HPP \ No newline at end of file +#endif \ No newline at end of file diff --git a/ft_irc3/includes/InviteHandler.hpp b/ft_irc3/includes/InviteHandler.hpp index f1907d3..6d74f64 100644 --- a/ft_irc3/includes/InviteHandler.hpp +++ b/ft_irc3/includes/InviteHandler.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/30 13:01:50 by fgras-ca #+# #+# */ -/* Updated: 2024/05/30 17:48:41 by fgras-ca ### ########.fr */ +/* Updated: 2024/06/01 18:51:00 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -27,13 +27,14 @@ class Server; class Client; class Channel; -class InviteHandler { -public: - InviteHandler(Server* server); - void handleInviteCommand(Client* client, const std::string& command); +class InviteHandler +{ + public: + InviteHandler(Server* server); + void handleInviteCommand(Client* client, const std::string& command); -private: - Server* _server; + private: + Server* _server; }; -#endif // INVITEHANDLER_HPP +#endif diff --git a/ft_irc3/includes/Join.hpp b/ft_irc3/includes/Join.hpp index 1a9ed96..c44393a 100644 --- a/ft_irc3/includes/Join.hpp +++ b/ft_irc3/includes/Join.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/21 19:51:08 by fgras-ca #+# #+# */ -/* Updated: 2024/05/30 17:48:55 by fgras-ca ### ########.fr */ +/* Updated: 2024/06/01 18:51:10 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,15 +19,22 @@ #include "Channel.hpp" #include "RPL.hpp" #include "Utils.hpp" +#include "Server.hpp" +#include "Channel.hpp" +#include "Client.hpp" + +#include +#include +#include +#include class JoinHandler { -public: - void handleJoinCommand(Client *client, const std::string &channelName, Server *server); + public: + void handleJoinCommand(Client *client, const std::string &channelName, Server *server); + void sendJoinSuccess(Client *client, Channel *channel, Server *server); + std::string getUsersList(Channel *channel); -private: - void sendJoinSuccess(Client *client, Channel *channel, Server *server); - std::string getUsersList(Channel *channel); }; -#endif // JOIN_HPP +#endif diff --git a/ft_irc3/includes/KickHandler.hpp b/ft_irc3/includes/KickHandler.hpp new file mode 100644 index 0000000..7c00a4d --- /dev/null +++ b/ft_irc3/includes/KickHandler.hpp @@ -0,0 +1,35 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* KickHandler.hpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/01 16:59:42 by fgras-ca #+# #+# */ +/* Updated: 2024/06/01 18:51:26 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef KICKHANDLER_HPP +#define KICKHANDLER_HPP + +#include "Server.hpp" +#include "Client.hpp" +#include "Channel.hpp" +#include "Utils.hpp" + +#include +#include +#include + +class KickHandler +{ + public: + KickHandler(Server* server); + void handleKickCommand(Client* client, const std::string& command); + + private: + Server* _server; +}; + +#endif diff --git a/ft_irc3/includes/ModeHandler.hpp b/ft_irc3/includes/ModeHandler.hpp index 227c498..1505c4f 100644 --- a/ft_irc3/includes/ModeHandler.hpp +++ b/ft_irc3/includes/ModeHandler.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/30 11:12:57 by fgras-ca #+# #+# */ -/* Updated: 2024/05/31 11:21:04 by fgras-ca ### ########.fr */ +/* Updated: 2024/06/01 18:52:10 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -31,23 +31,22 @@ class Channel; class ModeHandler { -public: - ModeHandler(Server* server); - void handleModeCommand(Client* client, const std::string& command); + public: + ModeHandler(Server* server); + void handleModeCommand(Client* client, const std::string& command); -private: - Server* _server; + private: + Server* _server; - void handleUserMode(Client* client, const std::vector& tokens); - void handleChannelMode(Client* client, const std::vector& tokens); + void handleUserMode(Client* client, const std::vector& tokens); + void handleChannelMode(Client* client, const std::vector& tokens); - void setChannelMode(Client *client, Channel* channel, const std::string& mode, bool adding, const std::string& argument); - //void applyModeB(Channel* channel, bool adding, const std::string& argument); - void applyModeL(Channel* channel, bool adding, const std::string& argument); - void applyModeI(Channel* channel, bool adding); - void applyModeK(Client *client, Channel* channel, bool adding, const std::string& argument); - void applyModeT(Channel* channel, bool adding); - void applyModeO(Client *client, Channel* channel, bool adding, const std::string& argument); + void setChannelMode(Client *client, Channel* channel, const std::string& mode, bool adding, const std::string& argument); + void applyModeL(Client *client, Channel* channel, bool adding, const std::string& argument); + void applyModeI(Channel* channel, bool adding); + void applyModeK(Client *client, Channel* channel, bool adding, const std::string& argument); + void applyModeT(Channel* channel, bool adding); + void applyModeO(Client *client, Channel* channel, bool adding, const std::string& argument); }; -#endif // MODEHANDLER_HPP +#endif diff --git a/ft_irc3/includes/RPL.hpp b/ft_irc3/includes/RPL.hpp index 5a5d77c..a3ec3d1 100644 --- a/ft_irc3/includes/RPL.hpp +++ b/ft_irc3/includes/RPL.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/19 15:12:47 by fgras-ca #+# #+# */ -/* Updated: 2024/05/31 11:18:49 by fgras-ca ### ########.fr */ +/* Updated: 2024/06/01 18:58:37 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -15,6 +15,7 @@ #include #include + #include "Client.hpp" #include "Utils.hpp" @@ -25,16 +26,14 @@ #define CHANNEL_MODES_WITH_PARAMS "l" - -// Macros pour accéder aux champs du client #define CLIENT_FD(client) (client->getFd()) #define CLIENT_NICK(client) ((client)->getNickname()) #define CLIENT_USER(client) ((client)->getUser()) #define CLIENT_HOST(client) ((client)->getHost()) #define CLIENT_REALNAME(client) ((client)->getRealName()) -// Fonctions pour générer les réponses RPL -inline std::string RPL_WELCOME(Client* client) { +inline std::string RPL_WELCOME(Client* client) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 001 " << CLIENT_NICK(client) << " :Welcome to the Internet Relay Network " << CLIENT_NICK(client) @@ -42,21 +41,24 @@ inline std::string RPL_WELCOME(Client* client) { return oss.str(); } -inline std::string RPL_YOURHOST(Client* client) { +inline std::string RPL_YOURHOST(Client* client) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 002 " << CLIENT_NICK(client) << " :Your host is " << SERVER_NAME << ", running version " << SERVER_VERSION << "\r\n"; return oss.str(); } -inline std::string RPL_CREATED(Client* client) { +inline std::string RPL_CREATED(Client* client) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 003 " << CLIENT_NICK(client) << " :This server was created " << __DATE__ << "\r\n"; return oss.str(); } -inline std::string RPL_MYINFO(Client* client) { +inline std::string RPL_MYINFO(Client* client) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 004 " << CLIENT_NICK(client) << " " << SERVER_NAME << " " << SERVER_VERSION << " " @@ -65,26 +67,28 @@ inline std::string RPL_MYINFO(Client* client) { return oss.str(); } -inline std::string RPL_ISUPPORT(Client* client, const std::string& tokens) { +inline std::string RPL_ISUPPORT(Client* client, const std::string& tokens) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 005 " << CLIENT_NICK(client) << " " << tokens << " :are supported by this server\r\n"; return oss.str(); } -inline std::string RPL_UMODEIS(Client* client, const std::string& modes) { +inline std::string RPL_UMODEIS(Client* client, const std::string& modes) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 221 " << CLIENT_NICK(client) << " :" << modes << "\r\n"; return oss.str(); } -inline std::string RPL_AWAY(Client *client, const std::string& target, const std::string& message) { +inline std::string RPL_AWAY(Client *client, const std::string& target, const std::string& message) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 301 " << CLIENT_NICK(client) << " " << target << " :" << message << "\r\n"; return oss.str(); } -// WHOIS Command RPLs inline std::string RPL_WHOISUSER(Client *client, Client* target) { std::ostringstream oss; @@ -115,7 +119,6 @@ inline std::string RPL_ENDOFWHOIS(Client *client, const std::string& targetNick) return oss.str(); } -// RPL Channel List Messages inline std::string RPL_LIST(Client *client, const std::string& channel, int numVisible, const std::string& topic) { std::ostringstream oss; @@ -130,75 +133,83 @@ inline std::string RPL_LISTEND(Client *client) return oss.str(); } -// RPL Mode Messages -inline std::string RPL_CHANNELMODEIS(Client *client, const std::string& channel, const std::string& mode) +inline std::string RPL_CHANNELMODEIS(int clientFd, const std::string& channel, const std::string& mode) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 324 " << CLIENT_NICK(client) << " " << channel << " " << mode << "\r\n"; + oss << ":" << SERVER_NAME << " 324 " << clientFd << " " << channel << " " << mode << "\r\n"; return oss.str(); } -inline std::string RPL_CREATIONTIME(Client *client, const std::string& channel, time_t creationTime) { +inline std::string RPL_CREATIONTIME(Client *client, const std::string& channel, time_t creationTime) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 329 " << CLIENT_NICK(client) << " " << channel << " " << creationTime << "\r\n"; return oss.str(); } -inline std::string RPL_NOTOPIC(Client* client, const std::string& channel) { - std::ostringstream oss; - oss << ":" << SERVER_NAME << " 331 " << CLIENT_NICK(client) << " " << channel << " :No topic is set\r\n"; - return oss.str(); +inline std::string RPL_NOTOPIC(Client* client, const std::string& channel) +{ + std::ostringstream oss; + oss << ":" << SERVER_NAME << " 331 " << CLIENT_NICK(client) << " " << channel << " :No topic is set\r\n"; + return oss.str(); } -inline std::string RPL_TOPIC(Client* client, const std::string& channel, const std::string& topic) { - std::ostringstream oss; - oss << ":" << SERVER_NAME << " 332 " << CLIENT_NICK(client) << " " << channel << " :" << topic << "\r\n"; - return oss.str(); +inline std::string RPL_TOPIC(Client* client, const std::string& channel, const std::string& topic) +{ + std::ostringstream oss; + oss << ":" << SERVER_NAME << " 332 " << CLIENT_NICK(client) << " " << channel << " :" << topic << "\r\n"; + return oss.str(); } -inline std::string RPL_TOPICWHOTIME(Client* client, const std::string& channel, const std::string& setter, time_t setTime) { - std::ostringstream oss; - oss << ":" << SERVER_NAME << " 333 " << CLIENT_NICK(client) << " " << channel << " " << setter << " " << setTime << "\r\n"; - return oss.str(); +inline std::string RPL_TOPICWHOTIME(Client* client, const std::string& channel, const std::string& setter, time_t setTime) +{ + std::ostringstream oss; + oss << ":" << SERVER_NAME << " 333 " << CLIENT_NICK(client) << " " << channel << " " << setter << " " << setTime << "\r\n"; + return oss.str(); } -inline std::string RPL_INVITELIST(Client *client, const std::string& channel, const std::string& inviteMask) { +inline std::string RPL_INVITELIST(Client *client, const std::string& channel, const std::string& inviteMask) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 336 " << CLIENT_NICK(client) << " " << channel << " " << inviteMask << "\r\n"; return oss.str(); } -inline std::string RPL_ENDOFINVITELIST(Client *client, const std::string& channel) { +inline std::string RPL_ENDOFINVITELIST(Client *client, const std::string& channel) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 337 " << CLIENT_NICK(client) << " " << channel << " :End of channel invite list\r\n"; return oss.str(); } -// Ajoutez cette fonction pour RPL_INVITING -inline std::string RPL_INVITING(Client* client, const std::string& channel, const std::string& nick) { - std::ostringstream oss; - oss << ":" << SERVER_NAME << " 341 " << CLIENT_NICK(client) << " " << nick << " " << channel << "\r\n"; - return oss.str(); +inline std::string RPL_INVITING(Client* client, const std::string& channel) +{ + std::ostringstream oss; + oss << ":" << SERVER_NAME << " 341 " << CLIENT_NICK(client) << " " << CLIENT_NICK(client) << " " << channel << "\r\n"; + return oss.str(); } -inline std::string RPL_EXCEPTLIST(Client *client, const std::string& channel, const std::string& exceptionMask) { +inline std::string RPL_EXCEPTLIST(Client *client, const std::string& channel, const std::string& exceptionMask) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 348 " << CLIENT_NICK(client) << " " << channel << " " << exceptionMask << "\r\n"; return oss.str(); } -inline std::string RPL_ENDOFEXCEPTLIST(Client *client, const std::string& channel) { +inline std::string RPL_ENDOFEXCEPTLIST(Client *client, const std::string& channel) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 349 " << CLIENT_NICK(client) << " " << channel << " :End of channel exception list\r\n"; return oss.str(); } -inline std::string RPL_NAMREPLY(Client* client, const std::string& channel, const std::string& users) { +inline std::string RPL_NAMREPLY(Client* client, const std::string& channel, const std::string& users) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 353 " << CLIENT_NICK(client) << " = " << channel << " :" << users << "\r\n"; return oss.str(); } -// WHO Command RPLs + inline std::string RPL_WHOREPLY(const std::string& channel, Client* target) { std::ostringstream oss; @@ -208,39 +219,45 @@ inline std::string RPL_WHOREPLY(const std::string& channel, Client* target) return oss.str(); } -inline std::string RPL_ENDOFNAMES(Client* client, const std::string& channel) { +inline std::string RPL_ENDOFNAMES(Client* client, const std::string& channel) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 366 " << CLIENT_NICK(client) << " " << channel << " :End of /NAMES list\r\n"; return oss.str(); } -inline std::string RPL_BANLIST(Client *client, const std::string& channel, const std::string& banMask) { +inline std::string RPL_BANLIST(Client *client, const std::string& channel, const std::string& banMask) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 367 " << CLIENT_NICK(client) << " " << channel << " " << banMask << "\r\n"; return oss.str(); } -inline std::string RPL_ENDOFBANLIST(Client *client, const std::string& channel) { +inline std::string RPL_ENDOFBANLIST(Client *client, const std::string& channel) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 368 " << CLIENT_NICK(client) << " " << channel << " :End of channel ban list\r\n"; return oss.str(); } -inline std::string RPL_MOTD(Client* client, const std::string& line) { +inline std::string RPL_MOTD(Client* client, const std::string& line) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 372 " << CLIENT_NICK(client) << " :- " << line << "\r\n"; return oss.str(); } -inline std::string RPL_MOTDSTART(Client* client) { +inline std::string RPL_MOTDSTART(Client* client) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 375 " << CLIENT_NICK(client) << " :- " << SERVER_NAME << " Message of the day - \r\n"; return oss.str(); } -inline std::string RPL_ENDOFMOTD(Client* client) { +inline std::string RPL_ENDOFMOTD(Client* client) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 376 " << CLIENT_NICK(client) << " :End of /MOTD command.\r\n"; @@ -261,13 +278,15 @@ inline std::string ERR_NOSUCHCHANNEL(Client *client, const std::string& channel) return oss.str(); } -inline std::string ERR_CANNOTSENDTOCHAN(Client *client, const std::string& channel) { +inline std::string ERR_CANNOTSENDTOCHAN(Client *client, const std::string& channel) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 404 " << CLIENT_NICK(client) << " " << channel << " :Cannot send to channel\r\n"; return oss.str(); } -inline std::string ERR_TOOMANYCHANNELS(Client* client, const std::string& channel) { +inline std::string ERR_TOOMANYCHANNELS(Client* client, const std::string& channel) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 405 " << CLIENT_NICK(client) << " " << channel << " :You have joined too many channels\r\n"; return oss.str(); @@ -281,25 +300,29 @@ inline std::string ERR_NOORIGIN(Client* client) return oss.str(); } -inline std::string ERR_NORECIPIENT(Client *client, const std::string& command) { +inline std::string ERR_NORECIPIENT(Client *client, const std::string& command) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 411 " << CLIENT_NICK(client) << " :No recipient given (" << command << ")\r\n"; return oss.str(); } -inline std::string ERR_NOTEXTTOSEND(Client *client) { +inline std::string ERR_NOTEXTTOSEND(Client *client) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 412 " << CLIENT_NICK(client) << " :No text to send\r\n"; return oss.str(); } -inline std::string ERR_UNKNOWNCOMMAND(Client* client, const std::string& command) { +inline std::string ERR_UNKNOWNCOMMAND(Client* client, const std::string& command) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 421 " << CLIENT_NICK(client) << " " << command << " :Unknown command\r\n"; return oss.str(); } -inline std::string ERR_NOMOTD(Client* client) { +inline std::string ERR_NOMOTD(Client* client) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 422 " << CLIENT_NICK(client) << " :MOTD File is missing\r\n"; @@ -327,25 +350,28 @@ inline std::string ERR_NICKNAMEINUSE(Client* client, const std::string& nickname return oss.str(); } -inline std::string ERR_USERNOTINCHANNEL(Client *client, const std::string& nick, const std::string& channel) { +inline std::string ERR_USERNOTINCHANNEL(Client *client, const std::string& nick, const std::string& channel) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 441 " << CLIENT_NICK(client) << " " << nick << " " << channel << " :They aren't on that channel\r\n"; return oss.str(); } -inline std::string ERR_NOTONCHANNEL(Client *client, const std::string& channel) { +inline std::string ERR_NOTONCHANNEL(Client *client, const std::string& channel) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 442 " << CLIENT_NICK(client) << " " << channel << " :You're not on that channel\r\n"; return oss.str(); } // Ajoutez cette fonction pour ERR_USERONCHANNEL -inline std::string ERR_USERONCHANNEL(Client* client, const std::string& nick, const std::string& channel) { - std::ostringstream oss; - oss << ":" << SERVER_NAME << " 443 " << CLIENT_NICK(client) << " " << nick << " " << channel - << " :is already on channel\r\n"; - return oss.str(); +inline std::string ERR_USERONCHANNEL(Client* client, const std::string& nick, const std::string& channel) +{ + std::ostringstream oss; + oss << ":" << SERVER_NAME << " 443 " << CLIENT_NICK(client) << " " << nick << " " << channel + << " :is already on channel\r\n"; + return oss.str(); } inline std::string ERR_NOTREGISTERED(Client* client) @@ -378,43 +404,50 @@ inline std::string ERR_PASSWDMISMATCH(Client* client) return oss.str(); } -inline std::string ERR_INVALIDKEY(Client* client, const std::string& channel) { - std::ostringstream oss; - oss << ":" << SERVER_NAME << " 467 " << CLIENT_NICK(client) << " " << channel << " :Invalid key\r\n"; - return oss.str(); +inline std::string ERR_INVALIDKEY(Client* client, const std::string& channel) +{ + std::ostringstream oss; + oss << ":" << SERVER_NAME << " 467 " << CLIENT_NICK(client) << " " << channel << " :Invalid key\r\n"; + return oss.str(); } -inline std::string ERR_CHANNELISFULL(Client* client, const std::string& channel) { +inline std::string ERR_CHANNELISFULL(Client* client, const std::string& channel) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 471 " << CLIENT_NICK(client) << " " << channel << " :Cannot join channel (channel is full)\r\n"; return oss.str(); } -inline std::string ERR_UNKNOWNMODE(Client* client, char mode, const std::string& channelName) { - std::ostringstream oss; - oss << ":" << SERVER_NAME << " 472 " << CLIENT_NICK(client) << " " << mode << " :is unknown mode char to me for " << channelName << "\r\n"; - return oss.str(); +inline std::string ERR_UNKNOWNMODE(Client* client, char mode, const std::string& channelName) +{ + std::ostringstream oss; + oss << ":" << SERVER_NAME << " 472 " << CLIENT_NICK(client) << " " << mode << " :is unknown mode char to me for " << channelName << "\r\n"; + return oss.str(); } -inline std::string ERR_INVITEONLYCHAN(Client* client, const std::string& channel) { +inline std::string ERR_INVITEONLYCHAN(Client* client, const std::string& channel) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 473 " << CLIENT_NICK(client) << " " << channel << " :Cannot join channel (invite only)\r\n"; return oss.str(); } -inline std::string ERR_BANNEDFROMCHAN(Client* client, const std::string& channel) { +inline std::string ERR_BANNEDFROMCHAN(Client* client, const std::string& channel) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 474 " << CLIENT_NICK(client) << " " << channel << " :Cannot join channel (banned)\r\n"; return oss.str(); } -inline std::string ERR_BADCHANNELKEY(Client* client, const std::string& channel) { +inline std::string ERR_BADCHANNELKEY(Client* client, const std::string& channel) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 475 " << CLIENT_NICK(client) << " " << channel << " :Cannot join channel (incorrect key)\r\n"; return oss.str(); } -inline std::string ERR_BADCHANMASK(Client* client, const std::string& channel) { +inline std::string ERR_BADCHANMASK(Client* client, const std::string& channel) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 476 " << CLIENT_NICK(client) << " " << channel << " :Bad channel mask\r\n"; return oss.str(); @@ -434,25 +467,27 @@ inline std::string ERR_CHANOPRIVSNEEDED(Client *client, const std::string& chann return oss.str(); } -inline std::string ERR_UMODEUNKNOWNFLAG(Client *client) { +inline std::string ERR_UMODEUNKNOWNFLAG(Client *client) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 501 " << CLIENT_NICK(client) << " :Unknown MODE flag\r\n"; return oss.str(); } -inline std::string ERR_USERSDONTMATCH(Client *client) { +inline std::string ERR_USERSDONTMATCH(Client *client) +{ std::ostringstream oss; oss << ":" << SERVER_NAME << " 502 " << CLIENT_NICK(client) << " :Cannot change mode for other users\r\n"; return oss.str(); } -inline std::string ERR_INVALIDMODEPARAM(Client* client, const std::string& param) { - std::ostringstream oss; - oss << ":" << SERVER_NAME << " 696 " << CLIENT_NICK(client) << " " << param << " :Invalid mode parameter\r\n"; - return oss.str(); +inline std::string ERR_INVALIDMODEPARAM(Client* client, const std::string& param) +{ + std::ostringstream oss; + oss << ":" << SERVER_NAME << " 696 " << CLIENT_NICK(client) << " " << param << " :Invalid mode parameter\r\n"; + return oss.str(); } -// PONG Reply inline std::string RPL_PONG(const std::string& token) { std::ostringstream oss; @@ -460,7 +495,6 @@ inline std::string RPL_PONG(const std::string& token) return oss.str(); } -// CAP Command RPLs inline std::string RPL_CAP(Client *client, const std::string& subcommand, const std::string& capabilities) { std::ostringstream oss; @@ -476,7 +510,6 @@ inline std::string RPL_PASSACCEPTED(Client* client) return oss.str(); } -// Add this function to handle the CAP END response inline std::string RPL_CAPEND(Client *client) { std::ostringstream oss; @@ -484,4 +517,4 @@ inline std::string RPL_CAPEND(Client *client) return oss.str(); } -#endif // RPL_HPP +#endif diff --git a/ft_irc3/includes/Server.hpp b/ft_irc3/includes/Server.hpp index dfa42d9..ba21a90 100644 --- a/ft_irc3/includes/Server.hpp +++ b/ft_irc3/includes/Server.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 12:15:13 by fgras-ca #+# #+# */ -/* Updated: 2024/05/30 17:13:41 by fgras-ca ### ########.fr */ +/* Updated: 2024/06/01 19:01:40 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -46,48 +46,47 @@ class TopicHandler; class Server { -public: - Server(int port, const std::string &password); - ~Server(); - void run(); - void log(const std::string &message, const std::string &color = "\033[0m"); - void sendToClient(int client_fd, const std::string &message); + public: + Server(int port, const std::string &password); + ~Server(); + void run(); + void log(const std::string &message, const std::string &color = "\033[0m"); + void sendToClient(int client_fd, const std::string &message); - // Méthodes d'accès pour les canaux et les clients - std::map &getChannels(); - std::map &getClients(); - const std::string &getPassword() const; - void broadcast(const std::string &message); - Client* getClientByName(const std::string &name); // Ajoutez cette méthode - Channel* getChannelByName(const std::string &name); // Ajoutez cette méthode - void sendChannelListToClient(Client *client); - void disconnectClient(int clientFd); - bool MatchFd(const pollfd& pfd, int clientFd); - void removePollFd(int clientFd); + std::map &getChannels(); + std::map &getClients(); + const std::string &getPassword() const; + void broadcast(const std::string &message); + Client* getClientByName(const std::string &name); + Channel* getChannelByName(const std::string &name); + void sendChannelListToClient(Client *client); + void disconnectClient(int clientFd); + bool MatchFd(const pollfd& pfd, int clientFd); + void removePollFd(int clientFd); + protected: + int _server_fd; + int _port; + std::string _password; + std::map _clients; + std::map _channels; + std::vector _poll_fds; + ClientManager *_clientManager; + CommandHandler *_commandHandler; + ModeHandler *_modeHandler; + TopicHandler *_topicHandler; -protected: - int _server_fd; - int _port; - std::string _password; - std::map _clients; - std::map _channels; - std::vector _poll_fds; - ClientManager *_clientManager; - CommandHandler *_commandHandler; - ModeHandler *_modeHandler; - TopicHandler *_topicHandler; + friend class ClientManager; + friend class CommandHandler; + friend class ModeHandler; + friend class TopicHandler; - friend class ClientManager; - friend class CommandHandler; - friend class ModeHandler; - friend class TopicHandler; + private: + void initServer(); + void handleServerCommands(); + void acceptClient(); + void removeClient(int client_fd); -private: - void initServer(); - void handleServerCommands(); - void acceptClient(); - void removeClient(int client_fd); }; #endif diff --git a/ft_irc3/includes/TopicHandler.hpp b/ft_irc3/includes/TopicHandler.hpp index aec098c..b92ee40 100644 --- a/ft_irc3/includes/TopicHandler.hpp +++ b/ft_irc3/includes/TopicHandler.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/30 17:04:33 by fgras-ca #+# #+# */ -/* Updated: 2024/05/30 17:47:56 by fgras-ca ### ########.fr */ +/* Updated: 2024/06/01 19:02:10 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -24,15 +24,15 @@ class TopicHandler { -public: - TopicHandler(Server* server); - void handleTopicCommand(Client* client, const std::string& command); + public: + TopicHandler(Server* server); + void handleTopicCommand(Client* client, const std::string& command); -private: - void viewTopic(Client* client, Channel* channel); - void changeTopic(Client* client, Channel* channel, const std::string& topic); + private: + void viewTopic(Client* client, Channel* channel); + void changeTopic(Client* client, Channel* channel, const std::string& topic); - Server* _server; + Server* _server; }; #endif diff --git a/ft_irc3/includes/Utils.hpp b/ft_irc3/includes/Utils.hpp index c5108b5..31d0e71 100644 --- a/ft_irc3/includes/Utils.hpp +++ b/ft_irc3/includes/Utils.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 12:16:02 by fgras-ca #+# #+# */ -/* Updated: 2024/05/16 18:14:58 by fgras-ca ### ########.fr */ +/* Updated: 2024/06/01 15:13:40 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -18,12 +18,12 @@ #include #define RESET "\033[0m" -#define RED "\033[31m" -#define GREEN "\033[32m" -#define YELLOW "\033[33m" -#define BLUE "\033[34m" -#define MAGENTA "\033[35m" -#define CYAN "\033[36m" +#define RED "\033[1;31m" +#define GREEN "\033[1;32m" +#define YELLOW "\033[1;33m" +#define BLUE "\033[1;34m" +#define MAGENTA "\033[1;35m" +#define CYAN "\033[1;36m" std::vector split(const std::string &input, const std::string &delimiters); diff --git a/ft_irc3/includes/Welcome.hpp b/ft_irc3/includes/Welcome.hpp index 26c7082..aa3f330 100644 --- a/ft_irc3/includes/Welcome.hpp +++ b/ft_irc3/includes/Welcome.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/21 19:53:17 by fgras-ca #+# #+# */ -/* Updated: 2024/05/30 17:48:13 by fgras-ca ### ########.fr */ +/* Updated: 2024/06/01 19:02:40 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,13 +16,14 @@ #include "Client.hpp" #include "Server.hpp" #include "Utils.hpp" + #include class WelcomeHandler { -public: - void sendWelcomeMessages(Client *client, Server *server); - void sendMotd(Client *client, Server *server); + public: + void sendWelcomeMessages(Client *client, Server *server); + void sendMotd(Client *client, Server *server); }; -#endif // WELCOME_HPP +#endif diff --git a/ft_irc3/includes/Who.hpp b/ft_irc3/includes/Who.hpp index f8d0fe3..f32f32a 100644 --- a/ft_irc3/includes/Who.hpp +++ b/ft_irc3/includes/Who.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/17 16:08:48 by fgras-ca #+# #+# */ -/* Updated: 2024/05/21 18:04:10 by fgras-ca ### ########.fr */ +/* Updated: 2024/06/01 19:03:06 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -23,16 +23,16 @@ #include class Server; - class WhoHandler { -public: - WhoHandler(Server *server); - void handleWhoCommand(Client *client, const std::string &command); - void handleWhoisCommand(Client *client, const std::string &command); + public: + WhoHandler(Server *server); + void handleWhoCommand(Client *client, const std::string &command); + void handleWhoisCommand(Client *client, const std::string &command); + + private: + Server *_server; -private: - Server *_server; }; #endif diff --git a/ft_irc3/src/AdditionalCommands.cpp b/ft_irc3/src/AdditionalCommands.cpp index a2aa3c0..0106dcb 100644 --- a/ft_irc3/src/AdditionalCommands.cpp +++ b/ft_irc3/src/AdditionalCommands.cpp @@ -6,35 +6,34 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/16 15:27:29 by fgras-ca #+# #+# */ -/* Updated: 2024/05/30 17:12:30 by fgras-ca ### ########.fr */ +/* Updated: 2024/06/01 19:05:15 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ #include "AdditionalCommands.hpp" -AdditionalCommands::AdditionalCommands(Server *server) : _server(server) -{} +AdditionalCommands::AdditionalCommands(Server *server) : _server(server) {} void AdditionalCommands::processCommand(Client *client, const std::string &command) { - if (command.find("PART") == 0) - { - handlePartCommand(_server, client, command); - } - else if (command.find("PRIVMSG") == 0) - { - handlePrivmsgCommand(_server, client, command); - } - else if (command.find("WHO") == 0) - { - WhoHandler whoHandler(_server); - whoHandler.handleWhoCommand(client, command); - } + if (command.find("PART") == 0) + { + handlePartCommand(_server, client, command); + } + else if (command.find("PRIVMSG") == 0) + { + handlePrivmsgCommand(_server, client, command); + } + else if (command.find("WHO") == 0) + { + WhoHandler whoHandler(_server); + whoHandler.handleWhoCommand(client, command); + } else if (command.find("WHOIS") == 0) - { - WhoHandler whoHandler(_server); - whoHandler.handleWhoisCommand(client, command); - } + { + WhoHandler whoHandler(_server); + whoHandler.handleWhoisCommand(client, command); + } else if (command.find("INVITE") == 0) { InviteHandler inviteHandler(_server); @@ -46,17 +45,21 @@ void AdditionalCommands::processCommand(Client *client, const std::string &comma topichandler.handleTopicCommand(client, command); } else if (command.find("LIST") == 0) - { - broadcastChannelList(client, _server); - } - else - { - _server->sendToClient(client->getFd(), ERR_UNKNOWNCOMMAND(client, command)); - _server->log("Message from client " + client->getNickname() + ": " + command, MAGENTA); - } + { + broadcastChannelList(client, _server); + } + else if (command.find("KICK") == 0) + { + KickHandler kickHandler(_server); + kickHandler.handleKickCommand(client, command); + } + else + { + _server->sendToClient(client->getFd(), ERR_UNKNOWNCOMMAND(client, command)); + _server->log("Message from client " + client->getNickname() + ": " + command, MAGENTA); + } } - void AdditionalCommands::broadcastChannelList(Client *client, Server *server) { std::map &channels = server->getChannels(); @@ -70,115 +73,116 @@ void AdditionalCommands::broadcastChannelList(Client *client, Server *server) // Fonction pour gérer la commande PART void AdditionalCommands::handlePartCommand(Server *server, Client *client, const std::string &command) { - std::istringstream iss(command); - std::string cmd, channelNames; - iss >> cmd >> channelNames; + std::istringstream iss(command); + std::string cmd, channelNames; + iss >> cmd >> channelNames; - if (channelNames.empty()) { - server->sendToClient(client->getFd(), ERR_NEEDMOREPARAMS(client, "PART")); - return; - } + if (channelNames.empty()) + { + server->sendToClient(client->getFd(), ERR_NEEDMOREPARAMS(client, "PART")); + return; + } - std::vector channels = split(channelNames, ","); - std::map &channelMap = server->getChannels(); + std::vector channels = split(channelNames, ","); + std::map &channelMap = server->getChannels(); - for (size_t i = 0; i < channels.size(); ++i) { - std::string &channelName = channels[i]; - if (channelMap.find(channelName) == channelMap.end()) { - server->sendToClient(client->getFd(), ERR_NOSUCHCHANNEL(client, channelName)); - continue; - } + for (size_t i = 0; i < channels.size(); ++i) + { + std::string &channelName = channels[i]; + if (channelMap.find(channelName) == channelMap.end()) + { + server->sendToClient(client->getFd(), ERR_NOSUCHCHANNEL(client, channelName)); + continue; + } - Channel *channel = channelMap[channelName]; - if (!channel->hasClient(client)) { - server->sendToClient(client->getFd(), ERR_NOTONCHANNEL(client, channelName)); - continue; - } + Channel *channel = channelMap[channelName]; + if (!channel->hasClient(client)) { + server->sendToClient(client->getFd(), ERR_NOTONCHANNEL(client, channelName)); + continue; + } - channel->removeClient(client); + channel->removeClient(client); - std::ostringstream partMsg; - partMsg << ":" << client->getNickname() << " PART " << channelName << "\r\n"; - server->sendToClient(client->getFd(), partMsg.str()); + std::ostringstream partMsg; + partMsg << ":" << client->getNickname() << " PART " << channelName << "\r\n"; + server->sendToClient(client->getFd(), partMsg.str()); - if (channel->isEmpty()) { - delete channel; - channelMap.erase(channelName); - } + if (channel->isEmpty()) + { + delete channel; + channelMap.erase(channelName); + } - server->log("Client " + client->getNickname() + " left channel " + channelName, MAGENTA); - } + server->log("Client " + client->getNickname() + " left channel " + channelName, MAGENTA); + } } - -// Fonction pour gérer la commande PRIVMSG void AdditionalCommands::handlePrivmsgCommand(Server *server, Client *client, const std::string &command) { - std::istringstream iss(command); - std::string cmd, target, message; - iss >> cmd >> target; - getline(iss, message); + std::istringstream iss(command); + std::string cmd, target, message; + iss >> cmd >> target; + getline(iss, message); - // Enlever le ':' initial dans le message si présent - if (!message.empty() && message[0] == ':') - message = message.substr(1); + // Enlever le ':' initial dans le message si présent + if (!message.empty() && message[0] == ':') + message = message.substr(1); - if (target.empty()) { - server->sendToClient(client->getFd(), ERR_NORECIPIENT(client, "PRIVMSG")); - return; - } + if (target.empty()) + { + server->sendToClient(client->getFd(), ERR_NORECIPIENT(client, "PRIVMSG")); + return; + } - if (message.empty()) { - server->sendToClient(client->getFd(), ERR_NOTEXTTOSEND(client)); - return; - } + if (message.empty()) + { + server->sendToClient(client->getFd(), ERR_NOTEXTTOSEND(client)); + return; + } - // Récupérer les canaux du serveur - std::map &channels = server->getChannels(); + std::map &channels = server->getChannels(); - // Si la cible est un canal - if (channels.find(target) != channels.end()) - { - Channel *channel = channels[target]; + if (channels.find(target) != channels.end()) + { + Channel *channel = channels[target]; - // Vérifier les conditions spéciales du canal (ex: ban, modération) - if (channel->isBanned(client)) { - server->sendToClient(client->getFd(), ERR_CANNOTSENDTOCHAN(client, target)); - return; - } + if (channel->isBanned(client)) + { + server->sendToClient(client->getFd(), ERR_CANNOTSENDTOCHAN(client, target)); + return; + } - std::vector channelClients = channel->getClients(); + std::vector channelClients = channel->getClients(); - for (size_t i = 0; i < channelClients.size(); ++i) - { - // Envoyer le message à tous les clients du canal sauf l'émetteur - if (channelClients[i] != client) - { - std::stringstream privMsg; - privMsg << ":" << client->getNickname() << " PRIVMSG " << target << message << "\r\n"; - server->sendToClient(channelClients[i]->getFd(), privMsg.str()); - } - } - } - // Si la cible est un utilisateur - else - { - Client *targetClient = server->getClientByName(target); // Utiliser getClientByName pour trouver le client par nom + for (size_t i = 0; i < channelClients.size(); ++i) + { + if (channelClients[i] != client) + { + std::stringstream privMsg; + privMsg << ":" << client->getNickname() << " PRIVMSG " << target << message << "\r\n"; + server->sendToClient(channelClients[i]->getFd(), privMsg.str()); + } + } + } + else + { + Client *targetClient = server->getClientByName(target); - if (targetClient) - { - std::stringstream privMsg; - privMsg << ":" << client->getNickname() << " PRIVMSG " << target << message << "\r\n"; - server->sendToClient(targetClient->getFd(), privMsg.str()); + if (targetClient) + { + std::stringstream privMsg; + privMsg << ":" << client->getNickname() << " PRIVMSG " << target << message << "\r\n"; + server->sendToClient(targetClient->getFd(), privMsg.str()); - if (targetClient->isAway()) { - server->sendToClient(client->getFd(), RPL_AWAY(client, targetClient->getNickname(), targetClient->getAwayMessage())); - } - } - else - { - // Si la cible n'est ni un canal ni un utilisateur existant, envoyer un message d'erreur - server->sendToClient(client->getFd(), ERR_NOSUCHNICK(client, target)); - } - } + if (targetClient->isAway()) + { + server->sendToClient(client->getFd(), RPL_AWAY(client, targetClient->getNickname(), targetClient->getAwayMessage())); + } + } + else + { + // Si la cible n'est ni un canal ni un utilisateur existant, envoyer un message d'erreur + server->sendToClient(client->getFd(), ERR_NOSUCHNICK(client, target)); + } + } } diff --git a/ft_irc3/src/Channel.cpp b/ft_irc3/src/Channel.cpp index 4519698..cdd3220 100644 --- a/ft_irc3/src/Channel.cpp +++ b/ft_irc3/src/Channel.cpp @@ -6,50 +6,50 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 12:42:57 by fgras-ca #+# #+# */ -/* Updated: 2024/05/30 18:33:19 by fgras-ca ### ########.fr */ +/* Updated: 2024/06/01 19:06:40 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ #include "Channel.hpp" Channel::Channel(const std::string &name) - : _name(name), _clients(), _operators(), _bannedClients(), _invitedClients(), _key(""), _topic(""), _topicSetter(""), _topicTime(0), _clientLimit(50), _inviteOnly(false), _topicProtection(false) {} + : _name(name), _clients(), _operators(), _bannedClients(), _invitedClients(), _key(""), _topic(""), _topicSetter(""), _topicTime(time(NULL)), _clientLimit(50), _inviteOnly(false), _topicProtection(false) {} Channel::~Channel() {} const std::string &Channel::getName() const { - return _name; + return _name; } void Channel::addClient(Client *client) { - _clients.push_back(client); + _clients.push_back(client); } void Channel::removeClient(Client *client) { - _clients.erase(std::remove(_clients.begin(), _clients.end(), client), _clients.end()); + _clients.erase(std::remove(_clients.begin(), _clients.end(), client), _clients.end()); } bool Channel::isEmpty() const { - return _clients.empty(); + return _clients.empty(); } const std::vector &Channel::getClients() const { - return _clients; + return _clients; } void Channel::addOperator(Client *client) { - _operators.push_back(client); + _operators.push_back(client); } bool Channel::isOperator(Client *client) const { - return std::find(_operators.begin(), _operators.end(), client) != _operators.end(); + return std::find(_operators.begin(), _operators.end(), client) != _operators.end(); } void Channel::removeOperator(Client *client) @@ -59,99 +59,106 @@ void Channel::removeOperator(Client *client) bool Channel::hasClient(Client *client) const { - return std::find(_clients.begin(), _clients.end(), client) != _clients.end(); + return std::find(_clients.begin(), _clients.end(), client) != _clients.end(); } void Channel::broadcast(const std::string &message, Client *_client, Server *_server) { - for (std::vector::iterator it = _clients.begin(); it != _clients.end(); ++it) - { - if (*it != _client) - { - // Send message to each client except the sender - _server->sendToClient((*it)->getFd(), message); - } - } + for (std::vector::iterator it = _clients.begin(); it != _clients.end(); ++it) + { + if (*it != _client) + { + // Send message to each client except the sender + _server->sendToClient((*it)->getFd(), message); + } + } } bool Channel::isBanned(Client *client) const { - return _bannedClients.find(client) != _bannedClients.end(); + return _bannedClients.find(client) != _bannedClients.end(); } bool Channel::isFull() const { - return _clients.size() >= _clientLimit; + return _clients.size() >= _clientLimit; } bool Channel::isInviteOnly() const { - return _inviteOnly; + return _inviteOnly; } bool Channel::isInvited(Client *client) const { - return _invitedClients.find(client) != _invitedClients.end(); + return _invitedClients.find(client) != _invitedClients.end(); } bool Channel::checkKey(const std::string &key) const { - return _key.empty() || _key == key; + return _key.empty() || _key == key; } const std::string &Channel::getTopic() const { - return _topic; + return _topic; } const std::string &Channel::getTopicSetter() const { - return _topicSetter; + return _topicSetter; } time_t Channel::getTopicTime() const { - return _topicTime; + return _topicTime; } void Channel::setTopic(const std::string &topic, const std::string &setter) { - _topic = topic; - _topicSetter = setter; - _topicTime = std::time(NULL); + _topic = topic; + _topicSetter = setter; + _topicTime = std::time(NULL); } -void Channel::setClientLimit(size_t limit) { - _clientLimit = limit; +void Channel::setClientLimit(size_t limit) +{ + _clientLimit = limit; } -size_t Channel::getClientLimit() const { - return _clientLimit; +size_t Channel::getClientLimit() const +{ + return _clientLimit; } -void Channel::setInviteOnly(bool inviteOnly) { - _inviteOnly = inviteOnly; +void Channel::setInviteOnly(bool inviteOnly) +{ + _inviteOnly = inviteOnly; } -void Channel::setKey(const std::string &key) { - _key = key; +void Channel::setKey(const std::string &key) +{ + _key = key; } -void Channel::setTopicProtection(bool protection) { - _topicProtection = protection; +void Channel::setTopicProtection(bool protection) +{ + _topicProtection = protection; } -void Channel::addInvitedClient(Client* client) { - _invitedClients.insert(client); +void Channel::addInvitedClient(Client* client) +{ + _invitedClients.insert(client); } -std::string Channel::getModes() const { - std::string modes; - if (_inviteOnly) modes += 'i'; - if (!_key.empty()) modes += 'k'; - if (_clientLimit > 0) modes += 'l'; - if (_topicProtection) modes += 't'; - return modes; +std::string Channel::getModes() const +{ + std::string modes; + if (_inviteOnly) modes += 'i'; + if (!_key.empty()) modes += 'k'; + if (_clientLimit > 0) modes += 'l'; + if (_topicProtection) modes += 't'; + return modes; } bool Channel::getTopicProtection() const diff --git a/ft_irc3/src/Client.cpp b/ft_irc3/src/Client.cpp index 0c78d74..4a620da 100644 --- a/ft_irc3/src/Client.cpp +++ b/ft_irc3/src/Client.cpp @@ -6,14 +6,14 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 12:17:42 by fgras-ca #+# #+# */ -/* Updated: 2024/05/31 11:27:52 by fgras-ca ### ########.fr */ +/* Updated: 2024/06/01 19:06:29 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ #include "Client.hpp" Client::Client(int fd, const std::string &nickname, const std::string &user, const std::string &host, const std::string &password, const std::string &realname) - : _fd(fd), _nickname(nickname), _user(user), _host(host), _password(password), _realname(realname), _authenticated(false), _operator(false), _away(false) {} + : _fd(fd), _nickname(nickname), _user(user), _host(host), _password(password), _realname(realname), _authenticated(false), _operator(false), _away(false) {} int Client::getFd() const { @@ -110,7 +110,7 @@ void Client::setAway(bool away) _away = away; } -const std::string &Client::getkey() const +std::string Client::getKey() const { return _key; } diff --git a/ft_irc3/src/ClientManager.cpp b/ft_irc3/src/ClientManager.cpp index 24c7bf5..d4e637a 100644 --- a/ft_irc3/src/ClientManager.cpp +++ b/ft_irc3/src/ClientManager.cpp @@ -6,16 +6,14 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 18:32:23 by fgras-ca #+# #+# */ -/* Updated: 2024/05/28 14:32:28 by fgras-ca ### ########.fr */ +/* Updated: 2024/06/01 19:07:39 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ #include "ClientManager.hpp" ClientManager::ClientManager(Server *server) - : _server(server) -{ -} + : _server(server) {} void ClientManager::acceptClient() { @@ -26,7 +24,7 @@ void ClientManager::acceptClient() return; } - Client *newClient = new Client(client_fd, "", "", "", "", ""); // Fournir six arguments + Client *newClient = new Client(client_fd, "", "", "", "", ""); _server->_clients[client_fd] = newClient; struct pollfd client_pollfd; client_pollfd.fd = client_fd; @@ -72,7 +70,6 @@ void ClientManager::handleClient(int client_fd) while (std::getline(message_stream, line)) { - // Remove trailing '\r' and '\n' line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); line.erase(std::remove(line.begin(), line.end(), '\n'), line.end()); @@ -86,13 +83,11 @@ void ClientManager::handleClient(int client_fd) } } - void ClientManager::removeClient(int clientFd) { Client* client = _server->_clients[clientFd]; if (client) { - // Log the nickname being freed _server->log("Removing client: " + client->getNickname(), YELLOW); std::map::iterator it = _server->_channels.begin(); diff --git a/ft_irc3/src/CommandHandler.cpp b/ft_irc3/src/CommandHandler.cpp index d2c9c6a..99a4085 100644 --- a/ft_irc3/src/CommandHandler.cpp +++ b/ft_irc3/src/CommandHandler.cpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 18:26:34 by fgras-ca #+# #+# */ -/* Updated: 2024/05/30 16:53:35 by fgras-ca ### ########.fr */ +/* Updated: 2024/06/01 19:10:48 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -27,27 +27,40 @@ void CommandHandler::handleCommand(Client* client, const std::string& command) { std::vector tokens = split(command, " \n\r\t"); - if (tokens.empty()) { + if (tokens.empty()) + { return; } std::string commandType = tokens[0]; - if (commandType == "CAP") { + if (commandType == "CAP") + { handleCapCommand(client, tokens); - } else if (commandType == "PASS") { + } + else if (commandType == "PASS") + { handlePassCommand(client, tokens); - } else if (commandType == "NICK") { + } + else if (commandType == "NICK") + { handleNick(client, tokens); - } else if (commandType == "USER") { + } + else if (commandType == "USER") + { handleUser(client, tokens); - } else if (commandType == "QUIT") { + } + else if (commandType == "QUIT") + { handleQuitCommand(client, tokens); - } else if (commandType == "PING") + } + else if (commandType == "PING") { handlePingCommand(client, tokens); } - else if (commandType == "ERROR") { - if (tokens.size() > 1) { + else if (commandType == "ERROR") + { + if (tokens.size() > 1) + { handleErrorCommand(client, tokens[1]); } } @@ -55,19 +68,24 @@ void CommandHandler::handleCommand(Client* client, const std::string& command) { _modeHandler->handleModeCommand(client, command); } - else if (commandType == "JOIN") { + else if (commandType == "JOIN") + { + std::string joinParams = command.substr(command.find(" ") + 1); JoinHandler joinHandler; - joinHandler.handleJoinCommand(client, tokens[1], _server); + joinHandler.handleJoinCommand(client, joinParams, _server); } - else { - if (!client->isAuthenticated()) { + else + { + if (!client->isAuthenticated()) + { _server->sendToClient(client->getFd(), ERR_NOTREGISTERED(client)); _server->log("Client " + client->getNickname() + " attempted to send a command before registering.", RED); - } else { + } + else + { _additionalCommands->processCommand(client, command); } } - //std::cout << "Client " << client->getFd() << " " << client->getNickname() << " " << client->getUser() << " " << client->getPassword() << " " << client->getRealName() << std::endl; } void CommandHandler::handleCapCommand(Client* client, const std::vector& tokens) @@ -97,7 +115,6 @@ void CommandHandler::handleCapCommand(Client* client, const std::vectorsendToClient(client->getFd(), RPL_CAP(client, "ACK", requestedCapabilities)); } else if (subcommand == "END") @@ -112,31 +129,33 @@ void CommandHandler::handleCapCommand(Client* client, const std::vector& tokens) { - if (tokens.size() < 2) { + if (tokens.size() < 2) + { _server->sendToClient(client->getFd(), ERR_NEEDMOREPARAMS(client, "PASS")); return; } - if (client->isAuthenticated()) { + if (client->isAuthenticated()) + { _server->sendToClient(client->getFd(), ERR_ALREADYREGISTERED(client)); return; } - if (tokens[1] == _server->_password) { + if (tokens[1] == _server->_password) + { client->setPassword(tokens[1]); _server->sendToClient(client->getFd(), ":server NOTICE * :Password accepted\r\n"); _server->log("Client " + client->getNickname() + " provided correct password.", GREEN); } else { _server->sendToClient(client->getFd(), ERR_PASSWDMISMATCH(client)); _server->log("Client " + client->getNickname() + " failed authentication password.", RED); - // Optionally disconnect the client here } } bool CommandHandler::isValidNickname(const std::string& nickname) { - // Implement nickname validation according to IRC protocol - if (nickname.empty() || nickname[0] == '#' || nickname[0] == ':' || nickname.find(' ') != std::string::npos) { + if (nickname.empty() || nickname[0] == '#' || nickname[0] == ':' || nickname.find(' ') != std::string::npos) + { return false; } return true; @@ -144,8 +163,10 @@ bool CommandHandler::isValidNickname(const std::string& nickname) bool CommandHandler::isNicknameInUse(const std::string& nickname) { - for (std::map::iterator it = _server->_clients.begin(); it != _server->_clients.end(); ++it) { - if (it->second->getNickname() == nickname) { + for (std::map::iterator it = _server->_clients.begin(); it != _server->_clients.end(); ++it) + { + if (it->second->getNickname() == nickname) + { return true; } } @@ -154,19 +175,22 @@ bool CommandHandler::isNicknameInUse(const std::string& nickname) void CommandHandler::handleNick(Client* client, const std::vector& tokens) { - if (tokens.size() < 2) { + if (tokens.size() < 2) + { _server->sendToClient(client->getFd(), ERR_NONICKNAMEGIVEN(client)); return; } std::string newNick = tokens[1]; - if (!isValidNickname(newNick)) { + if (!isValidNickname(newNick)) + { _server->sendToClient(client->getFd(), ERR_ERRONEUSNICKNAME(client, newNick)); return; } - if (isNicknameInUse(newNick)) { + if (isNicknameInUse(newNick)) + { _server->sendToClient(client->getFd(), ERR_NICKNAMEINUSE(client, newNick)); return; } @@ -174,9 +198,9 @@ void CommandHandler::handleNick(Client* client, const std::vector& std::string oldNick = client->getNickname(); client->setNickname(newNick); - // Envoyer le message NICK à tous les clients connectés std::string nickMessage = ":" + oldNick + " NICK " + newNick + "\r\n"; - for (std::map::iterator it = _server->_clients.begin(); it != _server->_clients.end(); ++it) { + for (std::map::iterator it = _server->_clients.begin(); it != _server->_clients.end(); ++it) + { _server->sendToClient(it->second->getFd(), nickMessage); } @@ -188,7 +212,8 @@ void CommandHandler::handleNick(Client* client, const std::vector& void CommandHandler::handleUser(Client* client, const std::vector& tokens) { - if (tokens.size() < 5) { + if (tokens.size() < 5) + { _server->sendToClient(client->getFd(), ERR_NEEDMOREPARAMS(client, "USER")); std::ostringstream oss; @@ -198,7 +223,8 @@ void CommandHandler::handleUser(Client* client, const std::vector& return; } - if (client->isAuthenticated()) { + if (client->isAuthenticated()) + { _server->sendToClient(client->getFd(), ERR_ALREADYREGISTERED(client)); std::ostringstream oss; @@ -209,7 +235,7 @@ void CommandHandler::handleUser(Client* client, const std::vector& } std::string username = tokens[1]; - std::string realname = tokens[4].substr(1); // remove leading ':' + std::string realname = tokens[4].substr(1); client->setUser(username); client->setRealName(realname); @@ -218,12 +244,15 @@ void CommandHandler::handleUser(Client* client, const std::vector& oss << "Client " << client->getFd() << ": USER command set username to " << username << " and real name to " << realname; _server->log(oss.str(), BLUE); - if (client->getPassword() == _server->_password && !client->getNickname().empty()) { + if (client->getPassword() == _server->_password && !client->getNickname().empty()) + { client->authenticate(); WelcomeHandler welcomeHandler; welcomeHandler.sendWelcomeMessages(client, _server); _server->log("Client " + client->getNickname() + " authenticated.", GREEN); - } else { + } + else + { std::ostringstream oss; oss << "Client " << client->getFd() << ": USER command failed - authentication conditions not met."; _server->log(oss.str(), RED); diff --git a/ft_irc3/src/InviteHandler.cpp b/ft_irc3/src/InviteHandler.cpp index 86800fa..2b66b05 100644 --- a/ft_irc3/src/InviteHandler.cpp +++ b/ft_irc3/src/InviteHandler.cpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/30 13:02:09 by fgras-ca #+# #+# */ -/* Updated: 2024/05/30 16:53:59 by fgras-ca ### ########.fr */ +/* Updated: 2024/06/01 19:11:22 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,47 +14,54 @@ InviteHandler::InviteHandler(Server* server) : _server(server) {} -void InviteHandler::handleInviteCommand(Client* client, const std::string& command) { - std::istringstream iss(command); - std::string cmd, nickname, channelName; - iss >> cmd >> nickname >> channelName; +void InviteHandler::handleInviteCommand(Client* client, const std::string& command) +{ + std::istringstream iss(command); + std::string cmd, nickname, channelName; + iss >> cmd >> nickname >> channelName; - if (nickname.empty() || channelName.empty()) { - _server->sendToClient(client->getFd(), ERR_NEEDMOREPARAMS(client, "INVITE")); - return; - } + if (nickname.empty() || channelName.empty()) + { + _server->sendToClient(client->getFd(), ERR_NEEDMOREPARAMS(client, "INVITE")); + return; + } - Channel* channel = _server->getChannelByName(channelName); - if (!channel) { - _server->sendToClient(client->getFd(), ERR_NOSUCHCHANNEL(client, channelName)); - return; - } + Channel* channel = _server->getChannelByName(channelName); + if (!channel) + { + _server->sendToClient(client->getFd(), ERR_NOSUCHCHANNEL(client, channelName)); + return; + } - if (!channel->hasClient(client)) { - _server->sendToClient(client->getFd(), ERR_NOTONCHANNEL(client, channelName)); - return; - } + if (!channel->hasClient(client)) + { + _server->sendToClient(client->getFd(), ERR_NOTONCHANNEL(client, channelName)); + return; + } - if (!channel->isOperator(client) && channel->isInviteOnly()) { - _server->sendToClient(client->getFd(), ERR_CHANOPRIVSNEEDED(client, channelName)); - return; - } + if (!channel->isOperator(client) && channel->isInviteOnly()) + { + _server->sendToClient(client->getFd(), ERR_CHANOPRIVSNEEDED(client, channelName)); + return; + } - Client* targetClient = _server->getClientByName(nickname); - if (!targetClient) { - _server->sendToClient(client->getFd(), ERR_NOSUCHNICK(client, nickname)); - return; - } + Client* targetClient = _server->getClientByName(nickname); + if (!targetClient) + { + _server->sendToClient(client->getFd(), ERR_NOSUCHNICK(client, nickname)); + return; + } - if (channel->hasClient(targetClient)) { - _server->sendToClient(client->getFd(), ERR_USERONCHANNEL(client, nickname, channelName)); - return; - } + if (channel->hasClient(targetClient)) + { + _server->sendToClient(client->getFd(), ERR_USERONCHANNEL(client, nickname, channelName)); + return; + } - channel->addInvitedClient(targetClient); - _server->sendToClient(client->getFd(), RPL_INVITING(client, nickname, channelName)); + channel->addInvitedClient(targetClient); + _server->sendToClient(client->getFd(), RPL_INVITING(client, channel->getName())); - std::ostringstream inviteMsg; - inviteMsg << ":" << client->getNickname() << " INVITE " << nickname << " " << channelName << "\r\n"; - _server->sendToClient(targetClient->getFd(), inviteMsg.str()); + std::ostringstream inviteMsg; + inviteMsg << ":" << client->getNickname() << " INVITE " << nickname << " " << channelName << "\r\n"; + _server->sendToClient(targetClient->getFd(), inviteMsg.str()); } diff --git a/ft_irc3/src/Join.cpp b/ft_irc3/src/Join.cpp index 3bb7e92..8c10ce0 100644 --- a/ft_irc3/src/Join.cpp +++ b/ft_irc3/src/Join.cpp @@ -11,113 +11,157 @@ /* ************************************************************************** */ #include "Join.hpp" -void JoinHandler::handleJoinCommand(Client* client, const std::string& channelNames, Server* server) + +void JoinHandler::handleJoinCommand(Client* client, const std::string& params, Server* server) { - std::map& channels = server->getChannels(); - Channel* channel; + std::map& channels = server->getChannels(); + Channel* channel; - std::vector lst = split(channelNames, ","); - for (std::vector::iterator itl = lst.begin(); itl != lst.end(); ++itl) - { - const std::string& channelName = *itl; - std::cout << "hjoincmd .. " << channelName << std::endl; + server->log("Received JOIN command with params: " + params, RED); - if (channelName.empty()) - { - server->sendToClient(client->getFd(), ERR_NEEDMOREPARAMS(client, "JOIN")); - return; - } + // Split params into channel names and keys + std::vector parts = split(params, " "); + server->log("Split parts: ", RED); + for (size_t i = 0; i < parts.size(); ++i) + { + std::ostringstream oss; + oss << "Part " << i << ": " << parts[i]; + server->log(oss.str(), RED); + } + if (parts.empty()) + { + server->sendToClient(client->getFd(), ERR_NEEDMOREPARAMS(client, "JOIN")); + return; + } - if (channelName[0] == '0' && channelName.size() == 1) - { - // Leave all channels - return; - } + std::string channelNames = parts[0]; + std::string keys = (parts.size() > 1) ? parts[1] : ""; - if (channelName[0] != '#' && channelName[0] != '&') - { - server->sendToClient(client->getFd(), ERR_NOSUCHCHANNEL(client, channelName)); - return; - } + server->log("Split params: channelNames = " + channelNames + ", keys = " + keys, RED); - if (channels.find(channelName) == channels.end()) - { - channel = new Channel(channelName); - channels[channelName] = channel; - channel->addOperator(client); // Set client as operator for new channel - } - else - { - channel = channels[channelName]; - } + std::vector channelList = split(channelNames, ","); + std::vector keyList = split(keys, ","); - if (channel->isBanned(client)) - { - server->sendToClient(client->getFd(), ERR_BANNEDFROMCHAN(client, channelName)); - return; - } + server->log("channelList: ", RED); + for (size_t i = 0; i < channelList.size(); ++i) + { + server->log(channelList[i], RED); + } - if (channel->isFull()) - { - server->sendToClient(client->getFd(), ERR_CHANNELISFULL(client, channelName)); - return; - } + server->log("keyList: ", RED); + for (size_t i = 0; i < keyList.size(); ++i) + { + server->log(keyList[i], RED); + } - if (channel->isInviteOnly() && !channel->isInvited(client)) - { - server->sendToClient(client->getFd(), ERR_INVITEONLYCHAN(client, channelName)); - return; - } + for (size_t i = 0; i < channelList.size(); ++i) + { + const std::string& channelName = channelList[i]; + server->log("Processing channel: " + channelName, RED); - if (!channel->checkKey(client->getkey())) - { - server->sendToClient(client->getFd(), ERR_BADCHANNELKEY(client, channelName)); - return; - } + if (channelName.empty()) + { + server->sendToClient(client->getFd(), ERR_NEEDMOREPARAMS(client, "JOIN")); + return; + } - channel->addClient(client); - sendJoinSuccess(client, channel, server); - } + if (channelName[0] == '0' && channelName.size() == 1) + { + // Leave all channels + return; + } + + if (channelName[0] != '#' && channelName[0] != '&') + { + server->sendToClient(client->getFd(), ERR_NOSUCHCHANNEL(client, channelName)); + return; + } + + if (channels.find(channelName) == channels.end()) + { + channel = new Channel(channelName); + channels[channelName] = channel; + channel->addOperator(client); // Set client as operator for new channel + } + else + { + channel = channels[channelName]; + } + + if (channel->isBanned(client)) + { + server->sendToClient(client->getFd(), ERR_BANNEDFROMCHAN(client, channelName)); + return; + } + + if (channel->isFull()) + { + server->sendToClient(client->getFd(), ERR_CHANNELISFULL(client, channelName)); + return; + } + + if (channel->isInviteOnly() && !channel->isInvited(client)) + { + server->sendToClient(client->getFd(), ERR_INVITEONLYCHAN(client, channelName)); + return; + } + + // Extract the key for this channel, if provided + std::string key = (i < keyList.size()) ? keyList[i] : ""; + server->log("Using key: " + key + " for channel: " + channelName, RED); + + if (!channel->checkKey(key)) + { + server->sendToClient(client->getFd(), ERR_BADCHANNELKEY(client, channelName)); + return; + } + + channel->addClient(client); + sendJoinSuccess(client, channel, server); + } } - -void JoinHandler::sendJoinSuccess(Client *client, Channel *channel, Server *server) +void JoinHandler::sendJoinSuccess(Client* client, Channel* channel, Server* server) { - std::vector clients = channel->getClients(); - for (std::vector::iterator it = clients.begin(); it != clients.end(); ++it) - { - std::string joinMsg = ":" + client->getNickname() + " JOIN " + channel->getName() + "\r\n"; - server->sendToClient((*it)->getFd(), joinMsg); - } + std::vector clients = channel->getClients(); + for (std::vector::iterator it = clients.begin(); it != clients.end(); ++it) + { + std::string joinMsg = ":" + client->getNickname() + " JOIN " + channel->getName() + "\r\n"; + server->sendToClient((*it)->getFd(), joinMsg); + } - if (!channel->getTopic().empty()) - { - server->sendToClient(client->getFd(), RPL_TOPIC(client, channel->getName(), channel->getTopic())); - server->sendToClient(client->getFd(), RPL_TOPICWHOTIME(client, channel->getName(), channel->getTopicSetter(), channel->getTopicTime())); - } - else - { - server->sendToClient(client->getFd(), RPL_NOTOPIC(client, channel->getName())); - } + if (!channel->getTopic().empty()) + { + server->sendToClient(client->getFd(), RPL_TOPIC(client, channel->getName(), channel->getTopic())); + server->sendToClient(client->getFd(), RPL_TOPICWHOTIME(client, channel->getName(), channel->getTopicSetter(), channel->getTopicTime())); + } + else + { + server->sendToClient(client->getFd(), RPL_NOTOPIC(client, channel->getName())); + } - std::string usersList = getUsersList(channel); - server->sendToClient(client->getFd(), usersList); - } + std::ostringstream oss; + oss << RPL_CHANNELMODEIS(client->getFd(), channel->getName(), channel->getModes()); + oss << RPL_CREATIONTIME(client, channel->getName(), channel->getTopicTime()); + server->sendToClient(client->getFd(), oss.str()); + std::string usersList = getUsersList(channel); + server->sendToClient(client->getFd(), usersList); +} -std::string JoinHandler::getUsersList(Channel *channel) +std::string JoinHandler::getUsersList(Channel* channel) { - std::vector clients = channel->getClients(); - std::string users; - for (std::vector::iterator it = clients.begin(); it != clients.end(); ++it) - { - if (channel->isOperator((*it))) - users += "@"; - users += (*it)->getNickname() + " "; - } + std::vector clients = channel->getClients(); + std::string users; + for (std::vector::iterator it = clients.begin(); it != clients.end(); ++it) + { + if (channel->isOperator((*it))) + users += "@"; + users += (*it)->getNickname() + " "; + } - std::ostringstream oss; - oss << RPL_NAMREPLY(clients[0], channel->getName(), users); - oss << RPL_ENDOFNAMES(clients[0], channel->getName()); + std::ostringstream oss; + oss << RPL_NAMREPLY(clients[0], channel->getName(), users); + oss << RPL_ENDOFNAMES(clients[0], channel->getName()); return oss.str(); } diff --git a/ft_irc3/src/KickHandler.cpp b/ft_irc3/src/KickHandler.cpp new file mode 100644 index 0000000..5015c2c --- /dev/null +++ b/ft_irc3/src/KickHandler.cpp @@ -0,0 +1,68 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* KickHandler.cpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/01 17:00:31 by fgras-ca #+# #+# */ +/* Updated: 2024/06/01 19:12:13 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "KickHandler.hpp" + + + +KickHandler::KickHandler(Server* server) : _server(server) {} + +void KickHandler::handleKickCommand(Client* client, const std::string& command) +{ + std::vector tokens = split(command, " "); + if (tokens.size() < 3) + { + _server->sendToClient(client->getFd(), ERR_NEEDMOREPARAMS(client, "KICK")); + return; + } + + std::string channelName = tokens[1]; + std::string targetNickname = tokens[2]; + std::string comment = (tokens.size() > 3) ? tokens[3] : "Kicked by operator"; + + Channel* channel = _server->getChannelByName(channelName); + if (!channel) + { + _server->sendToClient(client->getFd(), ERR_NOSUCHCHANNEL(client, channelName)); + return; + } + + if (!channel->hasClient(client)) + { + _server->sendToClient(client->getFd(), ERR_NOTONCHANNEL(client, channelName)); + return; + } + + if (!channel->isOperator(client)) + { + _server->sendToClient(client->getFd(), ERR_CHANOPRIVSNEEDED(client, channelName)); + return; + } + + Client* targetClient = _server->getClientByName(targetNickname); + if (!targetClient) + { + _server->sendToClient(client->getFd(), ERR_NOSUCHNICK(client, targetNickname)); + return; + } + + if (!channel->hasClient(targetClient)) + { + _server->sendToClient(client->getFd(), ERR_USERNOTINCHANNEL(client, targetNickname, channelName)); + return; + } + + channel->removeClient(targetClient); + std::string kickMessage = ":" + client->getNickname() + " KICK " + channelName + " " + targetNickname + " :" + comment + "\r\n"; + channel->broadcast(kickMessage, NULL, _server); + _server->sendToClient(targetClient->getFd(), kickMessage); +} diff --git a/ft_irc3/src/ModeHandler.cpp b/ft_irc3/src/ModeHandler.cpp index d00f1c4..0a0a9c9 100644 --- a/ft_irc3/src/ModeHandler.cpp +++ b/ft_irc3/src/ModeHandler.cpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/30 11:13:08 by fgras-ca #+# #+# */ -/* Updated: 2024/05/31 11:20:45 by fgras-ca ### ########.fr */ +/* Updated: 2024/06/01 19:15:05 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,17 +19,21 @@ void ModeHandler::handleModeCommand(Client* client, const std::string& command) _server->log("Received MODE command: " + command, BLUE); std::vector tokens = split(command, " \n\r\t"); - if (tokens.size() < 2) { + if (tokens.size() < 2) + { _server->sendToClient(client->getFd(), ERR_NEEDMOREPARAMS(client, "MODE")); _server->log("MODE command error: Need more parameters", RED); return; } std::string target = tokens[1]; - if (target[0] == '#' || target[0] == '&') { + if (target[0] == '#' || target[0] == '&') + { _server->log("Handling channel mode for target: " + target, GREEN); handleChannelMode(client, tokens); - } else { + } + else + { _server->log("Handling user mode for target: " + target, GREEN); handleUserMode(client, tokens); } @@ -40,19 +44,22 @@ void ModeHandler::handleUserMode(Client* client, const std::vector& _server->log("Entered handleUserMode", MAGENTA); std::string target = tokens[1]; _server->log("User mode target: " + target, CYAN); - if (target != client->getNickname()) { + if (target != client->getNickname()) + { _server->sendToClient(client->getFd(), ERR_USERSDONTMATCH(client)); _server->log("User mode error: Users don't match", RED); return; } - if (tokens.size() == 2) { + if (tokens.size() == 2) + { _server->sendToClient(client->getFd(), RPL_UMODEIS(client, "")); _server->log("Sent user modes to client", GREEN); - } else { + } + else + { std::string modeString = tokens[2]; _server->log("Updating user modes: " + modeString, BLUE); - // Additional logging or mode handling logic can be added here } } @@ -62,22 +69,25 @@ void ModeHandler::handleChannelMode(Client* client, const std::vectorlog("Channel mode target: " + channelName, CYAN); Channel* channel = _server->getChannelByName(channelName); - if (!channel) { + if (!channel) + { _server->sendToClient(client->getFd(), ERR_NOSUCHCHANNEL(client, channelName)); _server->log("Channel mode error: No such channel " + channelName, RED); return; } - if (tokens.size() == 2) { + if (tokens.size() == 2) + { std::ostringstream oss; - oss << RPL_CHANNELMODEIS(client, channel->getName(), channel->getModes()); + oss << RPL_CHANNELMODEIS(client->getFd(), channel->getName(), channel->getModes()); oss << RPL_CREATIONTIME(client, channel->getName(), channel->getTopicTime()); _server->sendToClient(client->getFd(), oss.str()); _server->log("Sent channel modes to client", GREEN); return; } - if (!channel->isOperator(client)) { + if (!channel->isOperator(client)) + { _server->sendToClient(client->getFd(), ERR_CHANOPRIVSNEEDED(client, channelName)); _server->log("Channel mode error: Channel operator privileges needed for " + channelName, RED); return; @@ -87,21 +97,28 @@ void ModeHandler::handleChannelMode(Client* client, const std::vectorlog("Adding mode: " + std::string(1, mode), GREEN); - } else if (mode == '-') { + } else if (mode == '-') + { adding = false; _server->log("Removing mode: " + std::string(1, mode), RED); - } else if (mode == 'b' || mode == 'l' || mode == 'i' || mode == 'k' || mode == 't') { + } else if (mode == 'b' || mode == 'l' || mode == 'i' || mode == 'k' || mode == 't' || mode == 'o') + { std::string argument; - if (argIndex < tokens.size()) { + if (argIndex < tokens.size()) + { argument = tokens[argIndex++]; } setChannelMode(client, channel, std::string(1, mode), adding, argument); - } else { + } + else + { _server->sendToClient(client->getFd(), ERR_UNKNOWNMODE(client, mode, channelName)); _server->log("Unknown mode: " + std::string(1, mode), RED); } @@ -113,7 +130,7 @@ void ModeHandler::setChannelMode(Client *client, Channel* channel, const std::st _server->log("Setting channel mode: " + mode + " Adding: " + (adding ? "true" : "false") + " Argument: " + argument, GREEN); if (mode == "l") { - applyModeL(channel, adding, argument); + applyModeL(client, channel, adding, argument); } else if (mode == "i") { @@ -131,15 +148,24 @@ void ModeHandler::setChannelMode(Client *client, Channel* channel, const std::st applyModeO(client, channel, adding, argument); } -void ModeHandler::applyModeL(Channel* channel, bool adding, const std::string& argument) +void ModeHandler::applyModeL(Client *client, Channel* channel, bool adding, const std::string& argument) { - if (adding) { + if (adding) + { int limit = std::atoi(argument.c_str()); + if (limit <= 0) + { + _server->sendToClient(client->getFd(), ERR_INVALIDMODEPARAM(client, argument)); + _server->log("Invalid limit for mode +l: " + argument, RED); + return; + } std::ostringstream oss; oss << limit; _server->log("Applying mode L: Setting limit to " + oss.str(), GREEN); channel->setClientLimit(limit); - } else { + } + else + { _server->log("Applying mode L: Removing limit", RED); channel->setClientLimit(0); } @@ -153,16 +179,25 @@ void ModeHandler::applyModeI(Channel* channel, bool adding) void ModeHandler::applyModeK(Client *client, Channel* channel, bool adding, const std::string& argument) { - if (adding) { - if (argument.find(' ') != std::string::npos) { + if (adding) + { + if (argument.empty()) + { + _server->sendToClient(client->getFd(), ERR_NEEDMOREPARAMS(client, "MODE +k")); + _server->log("Mode +k error: No key provided", RED); + return; + } + if (argument.find(' ') != std::string::npos) + { _server->sendToClient(client->getFd(), ERR_INVALIDMODEPARAM(client, argument)); _server->log("Invalid key for mode +k: contains spaces", RED); return; } - // You can add more validation checks here if needed _server->log("Applying mode K: Setting key to " + argument, GREEN); channel->setKey(argument); - } else { + } + else + { _server->log("Applying mode K: Removing key", RED); channel->setKey(""); } @@ -177,24 +212,29 @@ void ModeHandler::applyModeT(Channel* channel, bool adding) void ModeHandler::applyModeO(Client* client, Channel* channel, bool adding, const std::string& argument) { Client* targetClient = _server->getClientByName(argument); - if (!targetClient) { + if (!targetClient) + { _server->sendToClient(client->getFd(), ERR_NOSUCHNICK(client, argument)); _server->log("Mode o error: No such client " + argument, RED); return; } - if (!channel->hasClient(targetClient)) { + if (!channel->hasClient(targetClient)) + { _server->sendToClient(client->getFd(), ERR_USERNOTINCHANNEL(client, argument, channel->getName())); _server->log("Mode o error: Client " + argument + " not in channel " + channel->getName(), RED); return; } - if (adding) { + if (adding) + { _server->log("Applying mode o: Adding operator " + argument, GREEN); channel->addOperator(targetClient); std::string message = ":" + client->getNickname() + " MODE " + channel->getName() + " +o " + targetClient->getNickname() + "\r\n"; channel->broadcast(message, NULL, _server); - } else { + } + else + { _server->log("Applying mode o: Removing operator " + argument, RED); channel->removeOperator(targetClient); std::string message = ":" + client->getNickname() + " MODE " + channel->getName() + " -o " + targetClient->getNickname() + "\r\n"; diff --git a/ft_irc3/src/Server.cpp b/ft_irc3/src/Server.cpp index aa31bf2..5e4439c 100644 --- a/ft_irc3/src/Server.cpp +++ b/ft_irc3/src/Server.cpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 12:17:12 by fgras-ca #+# #+# */ -/* Updated: 2024/05/30 17:14:19 by fgras-ca ### ########.fr */ +/* Updated: 2024/06/01 19:16:36 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -22,6 +22,7 @@ Server::~Server() { delete _clientManager; delete _commandHandler; + delete _topicHandler; for (std::map::iterator it = _clients.begin(); it != _clients.end(); ++it) { @@ -60,14 +61,14 @@ void Server::initServer() if (bind(_server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) { log("Failed to bind socket.", RED); - close(_server_fd); // Close the socket if bind fails + close(_server_fd); exit(EXIT_FAILURE); } if (listen(_server_fd, SOMAXCONN) == -1) { log("Failed to listen on socket.", RED); - close(_server_fd); // Close the socket if listen fails + close(_server_fd); exit(EXIT_FAILURE); } @@ -82,7 +83,6 @@ void Server::run() server_pollfd.revents = 0; _poll_fds.push_back(server_pollfd); - // Ajout de l'entrée pour les commandes serveur struct pollfd stdin_pollfd; stdin_pollfd.fd = STDIN_FILENO; stdin_pollfd.events = POLLIN; @@ -180,12 +180,12 @@ void Server::sendToClient(int client_fd, const std::string &message) { std::stringstream ss; ss << "Sent message to client " << client_fd << ": " << message; - log(ss.str(), BLUE); + log(ss.str(), YELLOW); } } std::map &Server::getClients() { - return _clients; + return _clients; } void Server::broadcast(const std::string &message) @@ -205,15 +205,17 @@ Client* Server::getClientByName(const std::string &name) return it->second; } } - return NULL; // Remplacez nullptr par NULL + return NULL; } -Channel* Server::getChannelByName(const std::string &name) { - std::map::iterator it = _channels.find(name); - if (it != _channels.end()) { - return it->second; - } - return NULL; +Channel* Server::getChannelByName(const std::string &name) +{ + std::map::iterator it = _channels.find(name); + if (it != _channels.end()) + { + return it->second; + } + return NULL; } void Server::sendChannelListToClient(Client *client) diff --git a/ft_irc3/src/TopicHandler.cpp b/ft_irc3/src/TopicHandler.cpp index 43bbdc9..f6fd3da 100644 --- a/ft_irc3/src/TopicHandler.cpp +++ b/ft_irc3/src/TopicHandler.cpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/30 17:04:58 by fgras-ca #+# #+# */ -/* Updated: 2024/05/30 18:05:42 by fgras-ca ### ########.fr */ +/* Updated: 2024/06/01 19:17:25 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,29 +19,35 @@ void TopicHandler::handleTopicCommand(Client* client, const std::string& command _server->log("Received TOPIC command: " + command, "\033[1;34m"); std::vector tokens = split(command, " \n\r\t"); - if (tokens.size() < 2) { + if (tokens.size() < 2) + { _server->sendToClient(client->getFd(), ERR_NEEDMOREPARAMS(client, "TOPIC")); - _server->log("TOPIC command error: Need more parameters", "\033[1;31m"); + _server->log("TOPIC command error: Need more parameters", RED); return; } std::string channelName = tokens[1]; Channel* channel = _server->getChannelByName(channelName); - if (!channel) { + if (!channel) + { _server->sendToClient(client->getFd(), ERR_NOSUCHCHANNEL(client, channelName)); - _server->log("TOPIC command error: No such channel " + channelName, "\033[1;31m"); + _server->log("TOPIC command error: No such channel " + channelName, RED); return; } - if (!channel->hasClient(client)) { + if (!channel->hasClient(client)) + { _server->sendToClient(client->getFd(), ERR_NOTONCHANNEL(client, channelName)); - _server->log("TOPIC command error: Client not on channel " + channelName, "\033[1;31m"); + _server->log("TOPIC command error: Client not on channel " + channelName, RED); return; } - if (tokens.size() == 2) { + if (tokens.size() == 2) + { viewTopic(client, channel); - } else { + } + else + { size_t topicStart = command.find(" :"); std::string topic = (topicStart != std::string::npos) ? command.substr(topicStart + 2) : ""; changeTopic(client, channel, topic); @@ -50,33 +56,39 @@ void TopicHandler::handleTopicCommand(Client* client, const std::string& command void TopicHandler::viewTopic(Client* client, Channel* channel) { - if (channel->getTopic().empty()) { + if (channel->getTopic().empty()) + { _server->sendToClient(client->getFd(), RPL_NOTOPIC(client, channel->getName())); - _server->log("No topic set for channel " + channel->getName(), "\033[1;32m"); - } else { + _server->log("No topic set for channel " + channel->getName(), GREEN); + } + else + { _server->sendToClient(client->getFd(), RPL_TOPIC(client, channel->getName(), channel->getTopic())); _server->sendToClient(client->getFd(), RPL_TOPICWHOTIME(client, channel->getName(), channel->getTopicSetter(), channel->getTopicTime())); - _server->log("Sent topic info for channel " + channel->getName(), "\033[1;32m"); + _server->log("Sent topic info for channel " + channel->getName(), GREEN); } } void TopicHandler::changeTopic(Client* client, Channel* channel, const std::string& topic) { - if (channel->getTopicProtection() && !channel->isOperator(client)) { + if (channel->getTopicProtection() && !channel->isOperator(client)) + { _server->sendToClient(client->getFd(), ERR_CHANOPRIVSNEEDED(client, channel->getName())); - _server->log("TOPIC command error: Channel operator privileges needed for " + channel->getName(), "\033[1;31m"); + _server->log("TOPIC command error: Channel operator privileges needed for " + channel->getName(), RED); return; } - if (topic == channel->getTopic()) { + if (topic == channel->getTopic()) + { _server->sendToClient(client->getFd(), RPL_TOPIC(client, channel->getName(), channel->getTopic())); - _server->log("TOPIC unchanged for channel " + channel->getName(), "\033[1;32m"); + _server->log("TOPIC unchanged for channel " + channel->getName(), GREEN); return; } channel->setTopic(topic, client->getNickname()); std::vector clients = channel->getClients(); - for (std::vector::iterator it = clients.begin(); it != clients.end(); ++it) { + for (std::vector::iterator it = clients.begin(); it != clients.end(); ++it) + { _server->sendToClient((*it)->getFd(), ":" + client->getNickname() + " TOPIC " + channel->getName() + " :" + topic + "\r\n"); }