diff --git a/Authentication.cpp b/Authentication.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/Helpers.cpp b/Helpers.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/Channel.hpp b/Includes/Channel.hpp similarity index 100% rename from Channel.hpp rename to Includes/Channel.hpp diff --git a/Client.hpp b/Includes/Client.hpp similarity index 100% rename from Client.hpp rename to Includes/Client.hpp diff --git a/Includes/Macros.hpp b/Includes/Macros.hpp new file mode 100644 index 0000000..3d7b360 --- /dev/null +++ b/Includes/Macros.hpp @@ -0,0 +1,80 @@ +#ifndef MACROS_HPP +#define MACROS_HPP + +#define OO1 ":irc.l9oroch 001 " + nickname + " :Welcome to the MiniChat Network, " + nickname + '\n' +#define OO2 ":irc.l9oroch 002 " + nickname + " :Your host is MiniChat, running version 4.5" + '\n' +#define OO3 ":irc.l9oroch 003 " + nickname + " :This server was created " + formatCreationTime() + '\n' +#define OO4 ":irc.l9oroch 004 " + nickname + " MiniChat MiniChat(enterprise)-2.3(12)-netty(5.4c)-proxy(0.9) MiniChat" + '\n' + +#define JOIN_MESSAGE(nickname, channelName) (":" + nickname + " JOIN #" + channelName + "\n") +#define MODE_MESSAGE(channelName) (":irc.l9oroch MODE #" + channelName + " +nt\n") +#define NAMES_MESSAGE(nickname, channelName) (":irc.l9oroch 353 " + nickname + " = #" + channelName + " :@" + nickname + "\n") +#define NAMES_MESSAGE2(nickname, channelName) (":irc.l9oroch 353 " + nickname + " @ #" + channelName + " :") +#define END_OF_NAMES_MESSAGE(nickname, channelName) (":irc.l9oroch 366 " + nickname + " #" + channelName + " :End of /NAMES list.\n") +#define CHANNEL_MESSAGE(channelName, creationTimeMessage) (":irc.l9oroch 354 " + channelName + " " + creationTimeMessage + "\n") +#define TOPIC_MESSAGE(nickname, channelName, topic) (":irc.l9oroch 332 " + nickname + " #" + channelName + " :" + topic + " https://irc.com\n") +#define TOPIC_MESSAGE2(nicknamesender, channelname, topic) (":" + nicknamesender + " TOPIC #" + channelname + " :" + topic + "\n") + +#define PRIVATE_MESSAGE(senderFd, recipient, message) (":" + nicknames[senderFd] + " PRIVMSG " + recipient + " :" + message + "\r\n") +#define ERROR_MESSAGE(senderFd, recipient) (":server.host NOTICE " + nicknames[senderFd] + " :Error: User '" + recipient + "' not found or offline\r\n") +#define INVITE_MESSAGE(senderFd, recipient, channelName) (":" + nicknames[senderFd] + " INVITE " + recipient + " :#" + channelName + "\r\n") +#define KICK_MESSAGE(nicknamesender, channelname, usertokick, reason) (":" + nicknamesender + " KICK #" + channelname + " " + usertokick + " :" + reason + "\n") +#define KICK_MESSAGE2(channelName, fd, userToKick, reason) (":" + channels[channelName].getNickname(fd) + " KICK #" + channelName + " " + userToKick + " :" + reason + "\n") + +#define MODE_CHANGE_MESSAGE(channelname, mode, sender, receiver) \ + (mode == "+t" ? MODE_CHANGE_T(channelname, sender) : \ + (mode == "-t" ? MODE_CHANGE_MINUS_T(channelname, sender) : \ + (mode == "+o" ? MODE_CHANGE_O(channelname, sender, mode, receiver) : \ + (mode == "-o" ? MODE_CHANGE_MINUS_O(channelname, sender, mode, receiver) : \ + (mode == "+i" ? MODE_CHANGE_IK(channelname, sender, mode) : \ + (mode == "-i" ? MODE_CHANGE_IK(channelname, sender, mode) : \ + (mode == "+k" ? MODE_CHANGE_IK(channelname, sender, mode) : \ + (mode == "-k" ? MODE_CHANGE_IK(channelname, sender, mode) : \ + (mode == "+l" ? MODE_CHANGE_L(channelname, sender, mode) : \ + (mode == "-l" ? MODE_CHANGE_L(channelname, sender, mode) : "")))))))))) + +#define MODE_CHANGE_T(channelname, sender) (MODE_CHANGE_MINUS_T(channelname, sender)) +#define MODE_CHANGE_MINUS_T(channelname, sender) (":server.host MODE #" + channelname + " -t by " + sender + "\n") +#define MODE_CHANGE_O(channelname, sender, mode, receiver) (":server.host MODE #" + channelname + " " + mode + " by " + sender + " and set " + receiver + "as operator\n") +#define MODE_CHANGE_MINUS_O(channelname, sender, mode, receiver) (":server.host MODE #" + channelname + " " + mode + " by " + sender + " and unset " + receiver + "as operator\n") +#define MODE_CHANGE_IK(channelname, sender, mode) (":server.host MODE #" + channelname + " " + mode + " by " + sender + "\n") +#define MODE_CHANGE_L(channelname, sender, mode) (":server.host MODE #" + channelname + " " + mode + " by " + sender + "\n") + +#define ERROR_MESSAGE2(nick) (":server.host NOTICE " + nick + what) +#define ERROR_MESSAGE3(sender, channelName, userToKick) (":" + sender + " PRIVMSG #" + channelName + " :Error: the user : " + userToKick + " is not found or offline.\r\n") +#define ERROR_MESSAGE4(sender, channelName, userToKick) (":" + sender + " PRIVMSG #" + channelName + " :Error1: You are not authorized to execute this command " + userToKick + "\r\n") +#define ERROR_MESSAGE5() (":" + channels[channelName].getNickname(fd) + " PRIVMSG #" + channelName + " :Error: You are not authorized to execute this command " + "\r\n") +#define ERROR_MESSAGE6(sender, channelName) (":" + sender + " PRIVMSG #" + channelName + " :Error2: You are not authorized to execute this command\r\n") +#define ERROR_MESSAGE7(channelName, fd) (":" + channels[channelName].getNickname(fd) + " PRIVMSG #" + channelName + " :Error: You are not authorized to execute this command\r\n") + +#define CONGRATS_MSG(guessed) (":server.host PRIVMSG #:Congratulations ,you have guessed the number : " + guessed + " correctly\n") +#define GUESS_AGAIN(random) (":server.host PRIVMSG #:Sorry ,the correct one is : " + random + "\n") +#define GUESS_ERROR() (":server.host PRIVMSG # :Error: Invalid range or guess\n") +#define MODE_SET_MESSAGE(channelName, mode, fd, nick) (":server.host MODE #" + channelName + " " + mode + " by " + channels[channelName].getNickname(fd) + " and set " + nick + "as operator\n") +#define MODE_UNSET_MESSAGE(channelName, mode, fd, nick) (":server.host MODE #" + channelName + " " + mode + " by " + channels[channelName].getNickname(fd) + " and unset " + nick + "as operator\n") +#define TOPIC_CHANGE_MESSAGE(channelName, mode, fd) (":server.host MODE #" + channelName + " " + mode + " by " + channels[channelName].getNickname(fd) + "\n") + +#define BUFFER_SIZE 1024 +#define RED "\033[31m" +#define GREEN "\033[32m" +#define CYAN "\033[36m" +#define RESET "\033[0m" + +#define MINICHAT "\n$$\\ $$\\ $$\\ $$\\ $$$$$$\\ $$\\ $$\\ \n" \ + "$$$\\ $$$ |\\__| \\__|$$ __$$\\ $$ | $$ | \n" \ + "$$$$\\ $$$$ |$$\\ $$$$$$$\\ $$\\ $$ / \\__|$$$$$$$\\ $$$$$$\\ $$$$$$\\ \n" \ + "$$\\$$\\$$ $$ |$$ |$$ __$$\\ $$ |$$ | $$ __$$\\ \\____$$\\_$$ _| \n" \ + "$$ \\$$$ $$ |$$ |$$ | $$ |$$ |$$ | $$ | $$ | $$$$$$$ | $$ | \n" \ + "$$ |\\$ /$$ |$$ |$$ | $$ |$$ |$$ | $$\\ $$ | $$ |$$ __$$ | $$ |$$\\ \n" \ + "$$ | \\_/ $$ |$$ |$$ | $$ |$$ |\\$$$$$$ |$$ | $$ |\\$$$$$$$ | \\$$$$ |\n" \ + "\\__| \\__|\\__|\\__| \\__|\\__| \\______/ \\__| \\__| \\_______| \\____/ \n\n" + +extern int opperatorfd; +extern int issettop; +extern int isinvited; +extern int itHasPass; +extern int channelLimit; +extern int limitchannelforincrement; +extern int abaaba; + +#endif \ No newline at end of file diff --git a/Server.hpp b/Includes/Server.hpp similarity index 90% rename from Server.hpp rename to Includes/Server.hpp index f89fcdb..8a3dc2a 100644 --- a/Server.hpp +++ b/Includes/Server.hpp @@ -20,6 +20,7 @@ #include #include #include +#include "Macros.hpp" class Server { private: @@ -53,13 +54,19 @@ class Server { void handleInvitation(int senderFd, const std::string& recipient, std::string channelName); void broadcastMessage(const std::string& channel, const std::string& senderNickname, const std::string& msg); - void smallbroadcastMessagefortheckick(std::string nicknamesender , const std::string& channelname, const std::string& usertokick, const std::string& reason); + void smallBroadcastMsgForKick(std::string nicknamesender , const std::string& channelname, const std::string& usertokick, const std::string& reason); void smallbroadcastMessageforjoin(std::string nicknamesender , const std::string& channelname); void smallbroadcastMessageforTopic(std::string nicknamesender, const std::string& channelname, std::string topic); void smallbroadcastMOOD(std::string nicknamesender, const std::string& channelname, std::string mode, std::string receiver); int findUserFd1(const std::string& username); bool dontputthesamenick(const std::string& nickname); bool dontputthesameusername(const std::string& username); + std::string intToString(int number); + std::string trim(const std::string& str); + bool startsWith(const std::string& str, const std::string& prefix); + int stringToInt(const std::string& str); + bool isValidPassword(const std::string& passwordLine); + int randomInRange(int min, int max); // Server void init(); @@ -103,7 +110,4 @@ class Server { void handleChannelLimit(const std::string& nick, const std::string& channelName, const std::string& mode, int fd); }; -int randomInRange(int min, int max); -std::string intToString(int number); - #endif \ No newline at end of file diff --git a/Macros.hpp b/Macros.hpp deleted file mode 100644 index 84b520a..0000000 --- a/Macros.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef MACROS_HPP -#define MACROS_HPP - -#define OO1 ":irc.l9oroch 001 " + nickname + " :Welcome to the MiniChat Network, " + nickname + '\n' -#define OO2 ":irc.l9oroch 002 " + nickname + " :Your host is MiniChat, running version 4.5" + '\n' -#define OO3 ":irc.l9oroch 003 " + nickname + " :This server was created " + formatCreationTime() + '\n' -#define OO4 ":irc.l9oroch 004 " + nickname + " MiniChat MiniChat(enterprise)-2.3(12)-netty(5.4c)-proxy(0.9) MiniChat" + '\n' - -#define JOIN_MESSAGE(nickname, channelName) (":" + nickname + " JOIN #" + channelName + "\n") -#define MODE_MESSAGE(channelName) (":irc.l9oroch MODE #" + channelName + " +nt\n") -#define NAMES_MESSAGE(nickname, channelName) (":irc.l9oroch 353 " + nickname + " = #" + channelName + " :@" + nickname + "\n") -#define NAMES_MESSAGE2(nickname, channelName) (":irc.l9oroch 353 " + nickname + " @ #" + channelName + " :") -#define END_OF_NAMES_MESSAGE(nickname, channelName) (":irc.l9oroch 366 " + nickname + " #" + channelName + " :End of /NAMES list.\n") -#define CHANNEL_MESSAGE(channelName, creationTimeMessage) (":irc.l9oroch 354 " + channelName + " " + creationTimeMessage + "\n") -#define TOPIC_MESSAGE(nickname, channelName, topic) (":irc.l9oroch 332 " + nickname + " #" + channelName + " :" + topic + " https://irc.com\n") -#define PRIVATE_MESSAGE(senderFd, recipient, message) (":" + nicknames[senderFd] + " PRIVMSG " + recipient + " :" + message + "\r\n") -#define ERROR_MESSAGE(senderFd, recipient) (":server.host NOTICE " + nicknames[senderFd] + " :Error: User '" + recipient + "' not found or offline\r\n") - - - -#define BUFFER_SIZE 1024 -#define RED "\033[31m" -#define GREEN "\033[32m" -#define CYAN "\033[36m" -#define RESET "\033[0m" - -#define MINICHAT "\n$$\\ $$\\ $$\\ $$\\ $$$$$$\\ $$\\ $$\\ \n" \ - "$$$\\ $$$ |\\__| \\__|$$ __$$\\ $$ | $$ | \n" \ - "$$$$\\ $$$$ |$$\\ $$$$$$$\\ $$\\ $$ / \\__|$$$$$$$\\ $$$$$$\\ $$$$$$\\ \n" \ - "$$\\$$\\$$ $$ |$$ |$$ __$$\\ $$ |$$ | $$ __$$\\ \\____$$\\_$$ _| \n" \ - "$$ \\$$$ $$ |$$ |$$ | $$ |$$ |$$ | $$ | $$ | $$$$$$$ | $$ | \n" \ - "$$ |\\$ /$$ |$$ |$$ | $$ |$$ |$$ | $$\\ $$ | $$ |$$ __$$ | $$ |$$\\ \n" \ - "$$ | \\_/ $$ |$$ |$$ | $$ |$$ |\\$$$$$$ |$$ | $$ |\\$$$$$$$ | \\$$$$ |\n" \ - "\\__| \\__|\\__|\\__| \\__|\\__| \\______/ \\__| \\__| \\_______| \\____/ \n\n" - - -#endif \ No newline at end of file diff --git a/Makefile b/Makefile index 95fa56d..8e5843c 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,13 @@ NAME = ircserv -SRC = main.cpp Server.cpp Client.cpp Channel.cpp +SRC = main.cpp ./Srcs/Server.cpp ./Srcs/Client.cpp ./Srcs/Channel.cpp ./Srcs/Authentication.cpp \ + ./Srcs/Broadcast.cpp ./Srcs/Commands.cpp ./Srcs/Helpers.cpp ./Srcs/Modes.cpp OBJ = ${SRC:.cpp=.o} CXX = c++ -CXXFLAGS = -std=c++98 -fsanitize=address -g3 -Wall -Wextra -Werror +CXXFLAGS = -std=c++98 -fsanitize=address -g3 -Wall -Wextra -Werror -I ./Includes all : $(NAME) diff --git a/Modes.cpp b/Modes.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/Server.cpp b/Server.cpp deleted file mode 100644 index ca44df9..0000000 --- a/Server.cpp +++ /dev/null @@ -1,1164 +0,0 @@ -#include "Server.hpp" -#include "Macros.hpp" - -int opperatorfd = 0; -int issettop = 0; -int isinvited = 0; -int itHasPass = 0; -int channelLimit = 0; -int limitchannelforincrement = 0; -int abaaba = 0; - -bool Server::_signal = false; - -Server::Server() {} - -Server::~Server() {} - -std::string Server::getPassowrd() const { - return _password; -} - -std::string intToString(int number) { - std::stringstream ss; - ss << number; - return ss.str(); -} - -void Server::parseArgs(int ac, char **av) { - if (ac != 3) - throw std::runtime_error("Usage: ./ircserv "); - std::string port(av[1]); - std::string pwd(av[2]); - if (port.empty() || port.find_first_not_of("0123456789") != std::string::npos) - throw std::runtime_error("Error: Invalid arguments"); - - long _port = atol(av[1]); - if (!(_port >= 0 && _port <= 65535)) - throw std::runtime_error("Error: Invalid arguments"); - - if (pwd.empty()) - throw std::runtime_error("Error: Invalid arguments"); - - this->_port = _port; - this->_password = pwd; -} - -void Server::receiveSignal(int signum) { - _signal = true; - (void)signum; -} - -void Server::init() { - signal(SIGINT, receiveSignal); - signal(SIGQUIT, receiveSignal); - - createServerSocket(); - std::cout << GREEN << ">>> SERVER STARTED <<<" << RESET << std::endl; - std::cout << CYAN <<"Waiting for connections..." << RESET << std::endl; -} - -void Server::run() { - while (!_signal) { - int ret = poll(&_fds[0], _fds.size(), -1); - if (ret == -1 && !_signal) - throw std::runtime_error("Error: poll() failed"); - - for (size_t i = 0; i < _fds.size(); ++i) { - if (_fds[i].revents & POLLIN) { - if (_fds[i].fd == _serverSocketFd) - handleClientConnection(); - else - handleClientData(_fds[i].fd); - } - } - } - closeFds(); -} - -void Server::createServerSocket() { - _serverSocketFd = socket(AF_INET, SOCK_STREAM, 0); - if (_serverSocketFd == -1) - throw std::runtime_error("Error: failed to create socket"); - - int optval = 1; - if (setsockopt(_serverSocketFd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) - throw std::runtime_error("Error: setsockopt() failed"); - - if (fcntl(_serverSocketFd, F_SETFL, O_NONBLOCK) == -1) - throw std::runtime_error("Error: fcntl() failed"); - - bindServerSocket(); - - if (listen(_serverSocketFd, SOMAXCONN) == -1) - throw std::runtime_error("Error: listen() failed"); - - addPollfd(_serverSocketFd); -} - -void Server::bindServerSocket() { - struct sockaddr_in sa; - sa.sin_family = AF_INET; - sa.sin_port = htons(_port); - sa.sin_addr.s_addr = INADDR_ANY; - if (bind(_serverSocketFd, (struct sockaddr*)&sa, sizeof(sa)) == -1) { - throw std::runtime_error("Error: failed to bind socket"); - } -} - -void Server::addPollfd(int fd) { - struct pollfd newPollfd; - newPollfd.fd = fd; - newPollfd.events = POLLIN; - newPollfd.revents = 0; - _fds.push_back(newPollfd); -} - -void Server::handleClientConnection() { - struct sockaddr_in client_addr; - socklen_t clientAddrSize = sizeof(sockaddr_in); - int newFd = accept(_serverSocketFd, (struct sockaddr *)&client_addr, &clientAddrSize); - if (newFd == -1) - throw std::runtime_error("Error: accept() failed"); - - if (fcntl(newFd, F_SETFL, O_NONBLOCK) == -1) - throw std::runtime_error("Error: fcntl() failed"); - - std::string passwordRequest = "Please Enter The password Of This Server :\n"; - std::string art = MINICHAT; - - send(newFd, art.c_str(), art.length(), 0); - send(newFd, passwordRequest.c_str(), passwordRequest.length(), 0); - addPollfd(newFd); - _clients.push_back(Client(newFd)); - - std::cout << "Client <" << newFd << "> Connected" << std::endl; -} - -std::string trim(const std::string& str) { - size_t first = str.find_first_not_of(" \t\n\r"); - if (std::string::npos == first) { - return ""; - } - size_t last = str.find_last_not_of(" \t\n\r"); - return str.substr(first, last - first + 1); -} - -std::string Server::formatCreationTime() { - std::time_t currentTime = std::time(NULL); - std::tm* localTime = std::localtime(¤tTime); - - char buffer[80]; - std::strftime(buffer, sizeof(buffer), "%a %b %d %H:%M:%S %Y", localTime); - return std::string(buffer); -} - -std::string Server::constructCreationTimeMessage(const std::string& channelName) { - std::stringstream ss; - ss << "Channel #" << channelName << " created " << formatCreationTime(); - return ss.str(); -} - -std::string Server::constructJoinedTimeMessage(const std::string& channelName) { - std::stringstream ss; - ss << "Channel #" << channelName << " Joined " << formatCreationTime(); - return ss.str(); -} - -void Server::createChannel(const std::string& channelName, const std::string& nickname, int fd) { - // Check if the channel already exists - std::map::iterator it = channels.find(channelName); - if (it == channels.end()) { - isinvited = 0; - // Channel doesn't exist, so create it and add the user - addUserToChannel(nickname, channelName, fd); - } - else { - if (channels[channelName].findUserFdForKickRegulars(nickname) == -1 && channelLimit == 1) { - limitchannelforincrement = limitchannelforincrement + 1; - } - // Channel already exists, just add the user to it - it->second.addClient(nickname, fd); - // Send JOIN message to the client - sendJoinMsg(nickname, channelName, fd); - } -} - -void Server::addUserToChannel(const std::string& nickname, const std::string& channelName, int fd) { - Channel newChannel(channelName); - newChannel.addClient(nickname, fd); - newChannel.addOperator(nickname, fd); - opperatorfd = fd; - - std::string creationTimeMessage = constructCreationTimeMessage(channelName); - std::string joinMessage = JOIN_MESSAGE(nickname, channelName); - std::string modeMessage = MODE_MESSAGE(channelName); - std::string namesMessage = NAMES_MESSAGE(nickname, channelName); - std::string endOfNamesMessage = END_OF_NAMES_MESSAGE(nickname, channelName); - std::string channelMessage = CHANNEL_MESSAGE(channelName, creationTimeMessage); - - send(fd, joinMessage.c_str(), joinMessage.length(), 0); - send(fd, modeMessage.c_str(), modeMessage.length(), 0); - send(fd, namesMessage.c_str(), namesMessage.length(), 0); - send(fd, endOfNamesMessage.c_str(), endOfNamesMessage.length(), 0); - send(fd, channelMessage.c_str(), channelMessage.length(), 0); - - channels.insert(std::make_pair(channelName, newChannel)); -} - -void Server::sendJoinMsg(const std::string& nickname, const std::string& channelName, int fd) { - std::string operators = channels[channelName].getOperatorNickname(opperatorfd); - std::string operators1 = channels[channelName].getOperatorNickname(abaaba); - - std::string topic = channels[channelName].getTopic(); - std::string creationTimeMessage = constructJoinedTimeMessage(channelName); - std::string joinMessage = JOIN_MESSAGE(nickname, channelName); - std::string topicMessage = TOPIC_MESSAGE(nickname, channelName, topic); - - send(fd, joinMessage.c_str(), joinMessage.length(), 0); - send(fd, topicMessage.c_str(), topicMessage.length(), 0); - - std::string namesMessage = NAMES_MESSAGE2(nickname, channelName); - const std::vector& clients = channels[channelName].getClients(); - for (size_t i = 0; i < clients.size(); ++i) { - const std::string& user = clients[i]; - if (user == operators || user == operators1) { - namesMessage += "@" + user; - } else { - namesMessage += user; - } - if (i < clients.size() - 1) - namesMessage += " "; - } - namesMessage += "\n"; - std::string endOfNamesMessage = END_OF_NAMES_MESSAGE(nickname, channelName); - std::string channelMessage = CHANNEL_MESSAGE(channelName, creationTimeMessage); - - send(fd, namesMessage.c_str(), namesMessage.length(), 0); - send(fd, endOfNamesMessage.c_str(), endOfNamesMessage.length(), 0); - send(fd, channelMessage.c_str(), channelMessage.length(), 0); - - smallbroadcastMessageforjoin(nickname, channelName); -} - -bool startsWith(const std::string& str, const std::string& prefix) { - return str.substr(0, prefix.length()) == prefix; -} - -void Server::setNickname(int fd, const std::string& nickname) {nicknames[fd] = nickname;} - -void Server::setUsernames(int fd, const std::string& username) {usernames[fd] = username;} - -// handling private msg between users only -void Server::handlePrivateMessage(int senderFd, const std::string& recipient, const std::string& message) { - int recipientFd = findUserFd1(recipient); - if (recipientFd != -1) { - std::string privateMessage = PRIVATE_MESSAGE(senderFd, recipient, message); - send(recipientFd, privateMessage.c_str(), privateMessage.length(), 0); - } else { - std::string errorMessage = ERROR_MESSAGE(senderFd, recipient); - send(senderFd, errorMessage.c_str(), errorMessage.length(), 0); - } -} - -void Server::handleInvitation(int senderFd, const std::string& recipient, std::string channelName) { - int recipientFd = findUserFd1(recipient); - - if (recipientFd != -1) { - std::string inviteMessage = ":" + nicknames[senderFd] + " INVITE " + recipient + " :#" + channelName + "\r\n"; - send(recipientFd, inviteMessage.c_str(), inviteMessage.length(), 0); - } else { - std::string errorMessage = ERROR_MESSAGE(senderFd, recipient); - send(senderFd, errorMessage.c_str(), errorMessage.length(), 0); - } -} - -// find nicknames of the users to brodcast to -int Server::findUserFd1(const std::string& username) { - std::map::iterator it; - for (it = nicknames.begin(); it != nicknames.end(); ++it) { - if (it->second == username) { - return it->first; - } - } - return -1; -} - -bool Server::dontputthesamenick(const std::string& nickname) { - std::map::iterator it; - for (it = nicknames.begin(); it != nicknames.end(); ++it) { - if (it->second == nickname) { - return true; - } - } - return false; -} - -bool Server::dontputthesameusername(const std::string& username) { - std::map::iterator it; - for (it = usernames.begin(); it != usernames.end(); ++it) { - if (it->second == username) { - return true; - } - } - return false; -} - -// brodcasting msg to all nicks in the channel -void Server::broadcastMessage(const std::string& channel, const std::string& senderNickname, const std::string& msg) { - std::map::iterator it = channels.find(channel); - if (it == channels.end()) { - std::cerr << "Channel " << channel << " does not exist" << std::endl; - return; - } - - if (channels[channel].findUserFdForKickRegulars(senderNickname) == -1) { - return; - } - - std::string message = ":" + senderNickname + " PRIVMSG #" + channel + " :" + msg + "\r\n"; - const std::vector& clients = it->second.getClients(); - - for (size_t i = 0; i < clients.size(); ++i) { - const std::string& client = clients[i]; - - if (client == senderNickname) { - continue; - } - - int recipientFd = it->second.getUserFd(client); - - if (recipientFd != -1) { - std::cout << message << std::endl; - send(recipientFd, message.c_str(), message.size(), 0); - } else { - std::cerr << "Client " << client << " not found" << std::endl; - } - } -} - -void Server::smallbroadcastMessagefortheckick(std::string nicknamesender , const std::string& channelname, const std::string& usertokick, const std::string& reason) { - std::map::iterator it = channels.find(channelname); - if (it == channels.end()) { - std::cerr << "Channel " << channelname << " does not exist" << std::endl; - return; - } - std::string kickMessage = ":" + nicknamesender + " KICK #" + channelname + " " + usertokick + " :" + reason + "\n"; - - const std::vector& clients = it->second.getClients(); - - for (size_t i = 0; i < clients.size(); ++i) { - const std::string& client = clients[i]; - - if (client == nicknamesender) { - continue; - } - int recipientFd = it->second.getUserFd(client); - if (recipientFd != -1) { - send(recipientFd, kickMessage.c_str(), kickMessage.size(), 0); - } else { - std::cerr << "Client " << client << " not found" << std::endl; - } - } -} - -void Server::smallbroadcastMessageforjoin(std::string nickname , const std::string& channelName) { - std::map::iterator it = channels.find(channelName); - if (it == channels.end()) { - std::cerr << "Channel " << channelName << " does not exist" << std::endl; - return; - } - std::string joinMessage = JOIN_MESSAGE(nickname, channelName); - const std::vector& clients = it->second.getClients(); - - for (size_t i = 0; i < clients.size(); ++i) { - const std::string& client = clients[i]; - - if (client == nickname) { - continue; - } - int recipientFd = it->second.getUserFd(client); - if (recipientFd != -1) { - send(recipientFd, joinMessage.c_str(), joinMessage.size(), 0); - } else { - std::cerr << "Client " << client << " not found" << std::endl; - } - } -} - - -void Server::smallbroadcastMessageforTopic(std::string nicknamesender, const std::string& channelname, std::string topic) { - std::map::iterator it = channels.find(channelname); - if (it == channels.end()) { - std::cerr << "Channel " << channelname << " does not exist" << std::endl; - return; - } - - std::string topicMessage = ":" + nicknamesender + " TOPIC #" + channelname + " :" + topic + "\n"; - const std::vector& clients = it->second.getClients(); - - for (size_t i = 0; i < clients.size(); ++i) { - const std::string& client = clients[i]; - - if (client == nicknamesender) { - continue; - } - int recipientFd = it->second.getUserFd(client); - if (recipientFd != -1) { - send(recipientFd, topicMessage.c_str(), topicMessage.size(), 0); - } else { - std::cerr << "Client " << client << " not found" << std::endl; - } - } -} - -void Server::smallbroadcastMOOD(std::string nicknamesender, const std::string& channelname, std::string mode, std::string receiver) { - - std::map::iterator it = channels.find(channelname); - if (it == channels.end()) { - std::cerr << "Channel " << channelname << " does not exist" << std::endl; - return; - } - - std::string modeChangeMessage; - if (mode == "+t") { - modeChangeMessage = ":server.host MODE #" + channelname + " +t by " + nicknamesender + "\n"; - } else if(mode == "-t") { - modeChangeMessage = ":server.host MODE #" + channelname + " -t by " + nicknamesender + "\n"; - } else if (mode == "+o"){ - modeChangeMessage = ":server.host MODE #" + channelname + " " + mode + " by " + nicknamesender + " and set " + receiver + " as operator\n"; - } else if (mode == "-o"){ - modeChangeMessage = ":server.host MODE #" + channelname + " " + mode + " by " + nicknamesender + " and unset " + receiver + " as operator\n"; - } else if (mode == "+i"){ - modeChangeMessage = ":server.host MODE #" + channelname + " +i by " + nicknamesender + "\n"; - } else if (mode == "-i"){ - modeChangeMessage = ":server.host MODE #" + channelname + " -i by " + nicknamesender + "\n"; - } else if (mode == "+k"){ - modeChangeMessage = ":server.host MODE #" + channelname + " +k by " + nicknamesender + "\n"; - } else if (mode == "-k"){ - modeChangeMessage = ":server.host MODE #" + channelname + " -k by " + nicknamesender + "\n"; - } else if (mode == "-l"){ - modeChangeMessage = ":server.host MODE #" + channelname + " -l by " + nicknamesender + "\n"; - } else if (mode == "+l"){ - modeChangeMessage = ":server.host MODE #" + channelname + " +l by " + nicknamesender + "\n"; - } - - int senderFd = it->second.getUserFd(nicknamesender); - - const std::vector& clients = it->second.getClients(); - for (size_t i = 0; i < clients.size(); ++i) { - const std::string& client = clients[i]; - - int recipientFd = it->second.getUserFd(client); - if (recipientFd != -1 && recipientFd != senderFd) { - send(recipientFd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0); - } else { - std::cerr << "Client " << client << " not found or is the sender" << std::endl; - } - } -} - -int stringToInt(const std::string& str) { - std::stringstream ss(str); - int result; - ss >> result; - return result; -} - -bool isValidPassword(const std::string& passwordLine) { - if (!passwordLine.empty() && - ((passwordLine[0] == '"' && passwordLine.size() > 1 && passwordLine[passwordLine.size() - 1] == '"') || - (passwordLine[0] == '\'' && passwordLine.size() > 1 && passwordLine[passwordLine.size() - 1] == '\''))) { - return true; - } - return false; -} - -void Server::processPassword(Client& client, const std::string& command, int fd) { - std::string passwordLine = command.substr(command.find(" ") + 1); - passwordLine = trim(passwordLine); - - if (isValidPassword(passwordLine)) { - passwordLine = passwordLine.substr(1, passwordLine.size() - 2); - } - - if (passwordLine.empty()) { - std::string errorMessage = "Error: Password cannot be empty\n"; - send(fd, errorMessage.c_str(), errorMessage.length(), 0); - client.clearCommand(); - return; - } - - std::string serverPassword = getPassowrd(); - if (serverPassword != passwordLine) { - std::string errorMessage = "Error: Incorrect Password\n"; - send(fd, errorMessage.c_str(), errorMessage.length(), 0); - } else { - std::string confirmation = "Please Enter Your Nickname : \n"; - send(fd, confirmation.c_str(), confirmation.length(), 0); - client.setAuthentication(1); - } -} - -void Server::ping(const std::string& command, int fd) { - std::istringstream iss(command); - std::string serverHostname = command.substr(5); - std::string pongMessage = "PONG " + serverHostname + "\r\n"; - send(fd, pongMessage.c_str(), pongMessage.length(), 0); - std::cout << "PONG" << std::endl; -} - -void Server::processNickCmd(Client& client, const std::string& command, int fd) { - std::string cmd, nick; - std::istringstream iss(command); - iss >> cmd >> nick; - nick = trim(nick); - - // Check if there are more tokens after the nickname - std::string remaining; - if (iss >> remaining) { - std::string errorMessage = "Error: Command requires only 1 parameter\n"; - send(fd, errorMessage.c_str(), errorMessage.length(), 0); - client.clearCommand(); - return; - } - - // Validate the nickname - if (dontputthesamenick(nick)) { - std::string confirmation = "Please Use a Different Nickname : \n"; - send(fd, confirmation.c_str(), confirmation.length(), 0); - } - else { - setNickname(fd, nick); - for (size_t i = 0; i < _clients.size(); ++i) - { - if (_clients[i].getFd() == fd) { - _clients[i].setNick(nick); - std::cout << "Nickname set for client " << fd << ": " << nick << std::endl; - break; - } - } - std::string confirmation = "Please Enter Your Username : \n"; - send(fd, confirmation.c_str(), confirmation.length(), 0); - client.setAuthentication(2); - } -} - -void Server::welcome(const std::string& nickname, int fd){ - std::string one = OO1; - std::string two = OO2; - std::string tre = OO3; - std::string foor = OO4; - send(fd, one.c_str(), one.length(), 0); - send(fd, two.c_str(), two.length(), 0); - send(fd, tre.c_str(), tre.length(), 0); - send(fd, foor.c_str(), foor.length(), 0); -} - -void Server::processUserCmd(Client& client, const std::string& command, int fd) -{ - std::istringstream iss(command); - std::string cmd, username, dontworry, dontworry1, realname, nickname; - iss >> cmd >> username >> dontworry >> dontworry1 >> realname; - username = trim(username); - dontworry = trim(dontworry); - dontworry1 = trim(dontworry1); - realname = trim(realname); - - std::string reme; - if (iss.fail() || iss >> reme) { - std::string errorMessage = "Error: Command requires four parameters\n"; - send(fd, errorMessage.c_str(), errorMessage.length(), 0); - client.clearCommand(); - return; - } - - if (dontputthesameusername(username) == true) { - std::string confirmation = "Please Use a Different username : \n"; - send(fd, confirmation.c_str(), confirmation.length(), 0); - } - else { - setUsernames(fd, username); - for (size_t i = 0; i < _clients.size(); ++i) { - if (_clients[i].getFd() == fd) { - _clients[i].setUser(username); - _clients[i].setName(realname); - nickname = _clients[i].getNick(); - break; - } - } - welcome(nickname, fd); - } -} - -void Server::processJoinCmd(Client& client, const std::string& command, int fd) -{ - std::string nick; - for (size_t i = 0; i < _clients.size(); ++i) { - if (_clients[i].getFd() == fd) { - nick = _clients[i].getNick(); - break; - } - } - std::string channelName, pass ; - std::istringstream iss(command.substr(5)); - iss >> channelName ; - if (channelName[0] != '#') - { - std::string errorMessage = ":server.host NOTICE " + nick + " :Error: Channel start with #\r\n"; - send(fd, errorMessage.c_str(), errorMessage.length(), 0); - client.clearCommand(); - return; - } - channelName = channelName.substr(1); - channelName = trim(channelName); - std::getline(iss, pass); - pass = trim(pass); - - // Check if the channel already exists - std::map::iterator it = channels.find(channelName); - if (it != channels.end()) - { - // Channel already exists - if ((isinvited == 1 && channels[channelName].isInvited(nick)) || channels[channelName].isOperator(fd)) - { - // User is invited, create the channel - int check = channels[channelName].getChannelLimit(); - if (limitchannelforincrement < check || channelLimit == 0) - createChannel(channelName, nick, fd); - else { - std::string errorMessage = ":server.host NOTICE " + nick + " :Error: CHANNEL limit\r\n"; - send(fd, errorMessage.c_str(), errorMessage.length(), 0); - } - } - else if (isinvited == 0) { - if (itHasPass == 1 && channels[channelName].getPass() == pass) { - int check = channels[channelName].getChannelLimit(); - if (limitchannelforincrement < check || channelLimit == 0) - createChannel(channelName, nick, fd); - else { - std::string errorMessage = ":server.host NOTICE " + nick + " :Error: CHANNEL limit\r\n"; - send(fd, errorMessage.c_str(), errorMessage.length(), 0); - } - } - else if (itHasPass == 0) { - int check = channels[channelName].getChannelLimit(); - if (limitchannelforincrement < check || channelLimit == 0) - createChannel(channelName, nick, fd); - else { - std::string errorMessage = ":server.host NOTICE " + nick + " :Error: CHANNEL limit\r\n"; - send(fd, errorMessage.c_str(), errorMessage.length(), 0); - } - } else if (itHasPass == 1 && channels[channelName].getPass() != pass) - { - std::string errorMessage = ":server.host NOTICE " + nick + " :Error: you need a password for this channel\r\n"; - send(fd, errorMessage.c_str(), errorMessage.length(), 0); - } - - } - else { - // User is not invited, send error message - std::string errorMessage = ":server.host NOTICE " + nick + " :Error: you are not invited\r\n"; - send(fd, errorMessage.c_str(), errorMessage.length(), 0); - } - } - else - createChannel(channelName, nick, fd); -} - -void Server::processPrivmsgCmd(Client& client, const std::string& command, int fd) -{ - std::istringstream iss(command); - std::string cmd, recipient, message; - std::string niiick; - - iss >> cmd >> recipient; - recipient = trim(recipient); - std::getline(iss, message); - - if (iss.fail()) { - std::string errorMessage = "Error: You Just missing an argument(5)\n"; - send(fd, errorMessage.c_str(), errorMessage.length(), 0); - client.clearCommand(); - return; - } - - message = trim(message); - message = message.substr(1); - if (recipient[0] == '#') { - recipient = recipient.substr(1); - for (size_t i = 0; i < _clients.size(); ++i) { - if (_clients[i].getFd() == fd) { - niiick = _clients[i].getNick(); - break; - } - } - broadcastMessage(recipient, niiick, message); - } - else { - handlePrivateMessage(fd, recipient, message); - } -} - -void Server::processQuitCmd(int fd) { - cleanChannel(fd); - clientCleanup(fd); - std::cout << "Client <" << fd << "> Disconnected" << std::endl; -} - -void Server::processKickCmd(Client& client, const std::string& command, int fd) -{ - std::string channelName, userToKick, reason; - std::istringstream iss(command.substr(5)); - iss >> channelName >> userToKick; - - if (iss.fail()) { - std::string errorMessage = "Error: You Just missing an argument(4)\n"; - send(fd, errorMessage.c_str(), errorMessage.length(), 0); - client.clearCommand(); - return; - } - - std::getline(iss, reason); - channelName = channelName.substr(1); - channelName = trim(channelName); - userToKick = trim(userToKick); - reason = trim(reason); - - if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) { - int userFd = channels[channelName].findUserFdForKickRegulars(userToKick); - if (userFd != -1) { - channels[channelName].ejectUserfromusers(userFd); - channels[channelName].ejectUserfromivited(userToKick); - std::string kickMessage = ":" + channels[channelName].getNickname(fd) + " KICK #" + channelName + " " + userToKick + " :" + reason + "\n"; - smallbroadcastMessagefortheckick(channels[channelName].getNickname(fd), channelName, userToKick, reason); - send(fd, kickMessage.c_str(), kickMessage.length(), 0); - send(userFd , kickMessage.c_str(), kickMessage.length(), 0); - } - else { - std::string errorMessage = ":" + channels[channelName].getNickname(fd) + " PRIVMSG #" + channelName + " :Error: the user : " + userToKick + " is not found or offline." + "\r\n"; - send(fd, errorMessage.c_str(), errorMessage.size(), 0); - } - } - else { - std::string errorMessage = ":" + channels[channelName].getNickname(fd) + " PRIVMSG #" + channelName + " :Error1: You are not authorized to execute this command " + userToKick + "\r\n"; - send(fd, errorMessage.c_str(), errorMessage.size(), 0); - } -} - -void Server::processTopicCmd(Client& client, const std::string& command, int fd) -{ - std::string channelName, topic; - std::istringstream iss(command.substr(6)); - iss >> channelName; - std::getline(iss, topic); - - if (iss.fail()) { - std::string errorMessage = "Error: You Just missing an argument(3)\n"; - send(fd, errorMessage.c_str(), errorMessage.length(), 0); - client.clearCommand(); - return; - } - - channelName = channelName.substr(1); - channelName = trim(channelName); - topic = trim(topic); - topic = topic.substr(1); - - if ((channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) || issettop == 1) { - channels[channelName].setTopic(topic); - std::string topicMessage = ":" + channels[channelName].getNickname(fd) + " TOPIC #" + channelName + " :" + topic + "\n"; - send(fd, topicMessage.c_str(), topicMessage.size(), 0); - smallbroadcastMessageforTopic(channels[channelName].getNickname(fd), channelName, topic ); - } - else { - std::string errorMessage = ":" + channels[channelName].getNickname(fd) + " PRIVMSG #" + channelName + " :Error2: You are not authorized to execute this command " + "\r\n"; - send(fd, errorMessage.c_str(), errorMessage.size(), 0); - } -} - -void Server::processInviteCmd(Client& client, const std::string& command, int fd) { - std::string channelName, nickname; - std::istringstream iss(command.substr(7)); - iss >> nickname >> channelName; - - if (iss.fail()) { - std::string errorMessage = "Error: You Just missing an argument(2)\n"; - send(fd, errorMessage.c_str(), errorMessage.length(), 0); - client.clearCommand(); - return; - } - - channelName = trim(channelName); - nickname = trim(nickname); - channelName = channelName.substr(1); - - if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) { - channels[channelName].addClientinveted(nickname, fd); - handleInvitation(fd, nickname, channelName); - } - else { - std::string errorMessage = ":" + channels[channelName].getNickname(fd) + " PRIVMSG #" + channelName + " :Error3: You are not authorized to execute this command " + "\r\n"; - send(fd, errorMessage.c_str(), errorMessage.size(), 0); - } -} - -void Server::processBotCmd(Client& client, const std::string& command, int fd) { - std::string start, end, guessed; - std::istringstream iss(command.substr(4)); - iss >> start >> end >> guessed; - std::string reme; - - if (iss.fail() || iss >> reme) - { - std::string errorMessage = "Error: Command take 3 parameters\n"; - send(fd, errorMessage.c_str(), errorMessage.length(), 0); - client.clearCommand(); - return; - } - - start = trim(start); - end = trim(end); - guessed = trim(guessed); - - if (stringToInt(start) < stringToInt(end) && stringToInt(guessed) >= stringToInt(start) && stringToInt(guessed) <= stringToInt(end)) { - int r = randomInRange(stringToInt(start), stringToInt(end)); - std::string random = intToString(r); - if (random == guessed) { - std::string modeChangeMessage = ":server.host PRIVMSG #:Congratulations ,you have guessed the number : " + guessed + " correctly\n"; - send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0); - } - else { - std::string modeChangeMessage = ":server.host PRIVMSG #:Sorry ,the correct one is : " + random + "\n"; - send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0); - } - } - else { - std::string errorMessage = ":server.host PRIVMSG # :Error: Invalid range or guess\n"; - send(fd, errorMessage.c_str(), errorMessage.size(), 0); - } -} - -void Server::handleOpPrivilege(const std::string& nick, const std::string& channelName, const std::string& mode, int fd) { - if (mode == "+o") { - if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) { - channels[channelName].addOperator(nick, channels[channelName].getUserFd(nick)); - abaaba = channels[channelName].getUserFd(nick); - std::string modeChangeMessage = ":server.host MODE #" + channelName + " " + mode + " by " + channels[channelName].getNickname(fd) + " and set " + nick + " as operator\n"; - send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0); - smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick); - } - else { - std::string errorMessage = ":" + channels[channelName].getNickname(fd) + " PRIVMSG #" + channelName + " :Error: You are not authorized to execute this command " + "\r\n"; - send(fd, errorMessage.c_str(), errorMessage.size(), 0); - } - } - else if (mode == "-o") { - if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) { - channels[channelName].removeOperator(nick); - std::string modeChangeMessage = ":server.host MODE #" + channelName + " " + mode + " by " + channels[channelName].getNickname(fd) + " and unset " + nick + " as operator\n"; - send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0); - smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick); - } - else { - std::string errorMessage = ":" + channels[channelName].getNickname(fd) + " PRIVMSG #" + channelName + " :Error: You are not authorized to execute this command " + "\r\n"; - send(fd, errorMessage.c_str(), errorMessage.size(), 0); - } - } -} - -void Server::handleTopicRestriction(const std::string& nick, const std::string& channelName, const std::string& mode, int fd) { - if (mode == "-t") { - if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) { - std::string modeChangeMessage = ":server.host MODE #" + channelName + " " + mode + " by " + channels[channelName].getNickname(fd) + "\n"; - send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0); - smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick); - issettop = 1; - } - else { - std::string errorMessage = ":" + channels[channelName].getNickname(fd) + " PRIVMSG #" + channelName + " :Error: You are not authorized to execute this command " + "\r\n"; - send(fd, errorMessage.c_str(), errorMessage.size(), 0); - } - } - else if (mode == "+t") { - if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) { - std::string modeChangeMessage = ":server.host MODE #" + channelName + " " + mode + " by " + channels[channelName].getNickname(fd) + "\n"; - send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0); - smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick); - issettop = 0; - } - else { - std::string errorMessage = ":" + channels[channelName].getNickname(fd) + " PRIVMSG #" + channelName + " :Error: You are not authorized to execute this command " + "\r\n"; - send(fd, errorMessage.c_str(), errorMessage.size(), 0); - } - } -} - -void Server::handleInviteOnly(const std::string& nick, const std::string& channelName, const std::string& mode, int fd) { - if (mode == "+i") { - if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) { - std::string modeChangeMessage = ":server.host MODE #" + channelName + " +i by " + channels[channelName].getNickname(fd) + "\n"; - send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0); - smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick); - isinvited = 1; - - } - else if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd) == false) { - std::string errorMessage = ":" + channels[channelName].getNickname(fd) + " PRIVMSG #" + channelName + " :Error5: You are not authorized to execute this command " + "\r\n"; - send(fd, errorMessage.c_str(), errorMessage.size(), 0); - } - - } - else if (mode == "-i") { - if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) { - std::string modeChangeMessage = ":server.host MODE #" + channelName + " -i by " + channels[channelName].getNickname(fd) + "\n"; - send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0); - smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick); - isinvited = 0; - } - else { - std::string errorMessage = ":" + channels[channelName].getNickname(fd) + " PRIVMSG #" + channelName + " :Error6: You are not authorized to execute this command " + "\r\n"; - send(fd, errorMessage.c_str(), errorMessage.size(), 0); - } - } -} - -void Server::handleChannelKey(std::string& nick, const std::string& channelName, const std::string& mode, int fd) { - if (mode == "-k") { - if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) { - std::string modeChangeMessage = ":server.host MODE #" + channelName + " -k by " + channels[channelName].getNickname(fd) + "\n"; - send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0); - smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick); - itHasPass = 0; - } - else { - std::string errorMessage = ":" + channels[channelName].getNickname(fd) + " PRIVMSG #" + channelName + " :Error7: You are not authorized to execute this command " + "\r\n"; - send(fd, errorMessage.c_str(), errorMessage.size(), 0); - } - } - else if (mode == "+k") { - nick = trim(nick); - channels[channelName].setPass(nick); - if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) { - std::string modeChangeMessage = ":server.host MODE #" + channelName + " +k by " + channels[channelName].getNickname(fd) + "\n"; - send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0); - smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick); - itHasPass = 1; - } - else { - std::string errorMessage = ":" + channels[channelName].getNickname(fd) + " PRIVMSG #" + channelName + " :Error8: You are not authorized to execute this command " + "\r\n"; - send(fd, errorMessage.c_str(), errorMessage.size(), 0); - } - } -} - -void Server::handleChannelLimit(const std::string& nick, const std::string& channelName, const std::string& mode, int fd) { - if (mode == "+l") { - if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) { - int limit = stringToInt(nick); - channels[channelName].setlimitchannel(limit); - std::string modeChangeMessage = ":server.host MODE #" + channelName + " +l by " + channels[channelName].getNickname(fd) + "\n"; - send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0); - smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick); - channelLimit = 1; - } - else { - std::string errorMessage = ":" + channels[channelName].getNickname(fd) + " PRIVMSG #" + channelName + " :Error6: You are not authorized to execute this command " + "\r\n"; - send(fd, errorMessage.c_str(), errorMessage.size(), 0); - } - } - else if (mode == "-l") { - if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) { - std::string modeChangeMessage = ":server.host MODE #" + channelName + " -l by " + channels[channelName].getNickname(fd) + "\n"; - send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0); - smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick); - channelLimit = 0; - limitchannelforincrement = 0; - } - else { - std::string errorMessage = ":" + channels[channelName].getNickname(fd) + " PRIVMSG #" + channelName + " :Error6: You are not authorized to execute this command " + "\r\n"; - send(fd, errorMessage.c_str(), errorMessage.size(), 0); - } - } -} - -void Server::processModeCmd(Client& client, const std::string& command, int fd) { - std::string channelName, mode , nick; - std::istringstream iss(command.substr(5)); - iss >> channelName >> mode >> nick; - - if (channelName[0] != '#') { - client.clearCommand(); - return; - } - - channelName = channelName.substr(1); - channelName = trim(channelName); - mode = trim(mode); - size_t opt = mode.length() - 1; - - if (mode[opt] == 'o') - handleOpPrivilege(nick, channelName, mode, fd); - else if (mode[opt] == 't') - handleTopicRestriction(nick, channelName, mode, fd); - else if (mode[opt] == 'i') - handleInviteOnly(nick, channelName, mode, fd); - else if (mode[opt] == 'k') - handleChannelKey(nick, channelName, mode, fd); - else if (mode[opt] == 'l') - handleChannelLimit(nick, channelName, mode, fd); -} - -void Server::handleClientData(int fd) -{ - Client& client = getClientByFd(fd); - char buffer[BUFFER_SIZE]; - memset(buffer, 0, sizeof(buffer)); - - ssize_t bytesRead = recv(fd, buffer, BUFFER_SIZE - 1, 0); - if (bytesRead > 0) { - buffer[bytesRead] = '\0'; - client.appendCommand(buffer); - size_t newlinePos = client.getCommand().find_first_of("\r\n"); - if (newlinePos != std::string::npos) { - std::string command = client.getCommand().substr(0, newlinePos); - client.setCommand(command); - std::cout << "Received data from client " << fd << ": " << command << std::endl; - int auth = client.getAuthentication(); - - if ((startsWith(command, "PASS ") || startsWith(command, "pass ")) && auth == 0) - processPassword(client, command, fd); - else if ((startsWith(command, "NICK ") || startsWith(command, "nick ")) && auth == 1) - processNickCmd(client, command, fd); - else if ((startsWith(command, "USER ") || startsWith(command, "user ")) && auth == 2) - processUserCmd(client, command, fd); - else if (startsWith(command, "JOIN ") || startsWith(command, "join ")) - processJoinCmd(client, command, fd); - else if (startsWith(command, "PRIVMSG ") || startsWith(command, "privmsg ")) - processPrivmsgCmd(client, command, fd); - else if (startsWith(command, "KICK ") || startsWith(command, "kick ")) - processKickCmd(client, command, fd); - else if (startsWith(command, "TOPIC ") || startsWith(command, "topic ")) - processTopicCmd(client, command, fd); - else if (startsWith(command, "INVITE ") || startsWith(command, "invite ")) - processInviteCmd(client, command, fd); - else if (startsWith(command, "BOT ") || startsWith(command, "bot ")) - processBotCmd(client, command, fd); - else if (startsWith(command, "MODE ") || startsWith(command, "mode ")) - processModeCmd(client, command, fd); - else if (startsWith(command, "QUIT") || startsWith(command, "quit")) - processQuitCmd(fd); - else if (startsWith(command, "PING")) - ping(command, fd); - - client.clearCommand(); - } - } - - else if (bytesRead == 0) { - std::cout << "Client <" << fd << "> Disconnected" << std::endl; - cleanChannel(fd); - clientCleanup(fd); - } else if (bytesRead == -1) { - std::cerr << "Error reading data from client <" << fd << ">" << std::endl; - cleanChannel(fd); - clientCleanup(fd); - } -} - -void Server::clientCleanup(int fd) { - for (std::vector::iterator it = _fds.begin(); it != _fds.end(); ++it) { - if (it->fd == fd) { - _fds.erase(it); - close(fd); - break; - } - } - - for (std::vector::iterator it = _clients.begin(); it != _clients.end(); ++it) { - if (it->getFd() == fd) { - _clients.erase(it); - break; - } - } -} - -Client& Server::getClientByFd(int fd) { - size_t i = 0; - for (; i < _clients.size(); ++i) { - if (_clients[i].getFd() == fd) - break; - } - return _clients[i]; -} - -int randomInRange(int min, int max) -{ - if (min > max) { - return -1; - } - - int range_size = max - min + 1; - double random_double = (double)rand() / (RAND_MAX + 1.0) * range_size; - - return (int)random_double + min; -} - -void Server::closeFds() -{ - for (size_t i = 0; i < _clients.size(); i++){ - int fd = _clients[i].getFd(); - std::cout << "Client <" << fd << "> Disconnected" << std::endl; - close(fd); - } - - if (_serverSocketFd != -1) - close(_serverSocketFd); - _fds.clear(); -} - -void Server::cleanChannel(int fd) { - std::map::iterator it; - for (it = channels.begin(); it != channels.end(); ++it) - { - Channel& channel = it->second; - std::string nickname = channel.getNickname(fd); - if (channel.isUserInChannel(nickname)) { - channel.ejectUserfromusers(fd); - } - } - - std::map::iterator userIt; - userIt = usernames.find(fd); - if (userIt != usernames.end()) { - usernames.erase(userIt); - } - - std::map::iterator nickIt; - nickIt = nicknames.find(fd); - if (nickIt != nicknames.end()) { - nicknames.erase(nickIt); - } - - for (std::map::iterator it = channels.begin(); it != channels.end(); ++it) { - std::map &usersfdmap = it->second.getUserFdMap(); - for (std::map::iterator it2 = usersfdmap.begin(); it2 != usersfdmap.end(); ++it2) { - if (it2->second == fd) - usersfdmap.erase(it2); - } - } - for (std::map::iterator it1 = channels.begin(); it1 != channels.end(); ++it1) { - std::map &invitedusrmap = it1->second.invitedUserss(); - for (std::map::iterator it2 = invitedusrmap.begin(); it2 != invitedusrmap.end(); ++it2) { - if (it2->second == fd) - invitedusrmap.erase(it2); - } - } - for (std::map::iterator it2 = channels.begin(); it2 != channels.end(); ++it2) { - std::map &operatorsmap = it2->second.getOperators(); - for (std::map::iterator it2 = operatorsmap.begin(); it2 != operatorsmap.end(); ++it2) { - if (it2->second == fd) - operatorsmap.erase(it2); - } - } -} diff --git a/Srcs/Authentication.cpp b/Srcs/Authentication.cpp new file mode 100644 index 0000000..bfb2ee1 --- /dev/null +++ b/Srcs/Authentication.cpp @@ -0,0 +1,110 @@ +#include "Server.hpp" + +void Server::processPassword(Client& client, const std::string& command, int fd) { + std::string passwordLine = command.substr(command.find(" ") + 1); + passwordLine = trim(passwordLine); + + if (isValidPassword(passwordLine)) { + passwordLine = passwordLine.substr(1, passwordLine.size() - 2); + } + + if (passwordLine.empty()) { + std::string errorMessage = "Error: Password cannot be empty\n"; + send(fd, errorMessage.c_str(), errorMessage.length(), 0); + client.clearCommand(); + return; + } + + std::string serverPassword = getPassowrd(); + if (serverPassword != passwordLine) { + std::string errorMessage = "Error: Incorrect Password\n"; + send(fd, errorMessage.c_str(), errorMessage.length(), 0); + } else { + std::string confirmation = "Please Enter Your Nickname : \n"; + send(fd, confirmation.c_str(), confirmation.length(), 0); + client.setAuthentication(1); + } +} + +void Server::processNickCmd(Client& client, const std::string& command, int fd) { + std::string cmd, nick; + std::istringstream iss(command); + iss >> cmd >> nick; + nick = trim(nick); + + // Check if there are more tokens after the nickname + std::string remaining; + if (iss >> remaining) { + std::string errorMessage = "Error: Command requires only 1 parameter\n"; + send(fd, errorMessage.c_str(), errorMessage.length(), 0); + client.clearCommand(); + return; + } + + // Validate the nickname + if (dontputthesamenick(nick)) { + std::string confirmation = "Please Use a Different Nickname : \n"; + send(fd, confirmation.c_str(), confirmation.length(), 0); + } + else { + setNickname(fd, nick); + for (size_t i = 0; i < _clients.size(); ++i) + { + if (_clients[i].getFd() == fd) { + _clients[i].setNick(nick); + std::cout << "Nickname set for client " << fd << ": " << nick << std::endl; + break; + } + } + std::string confirmation = "Please Enter Your Username : \n"; + send(fd, confirmation.c_str(), confirmation.length(), 0); + client.setAuthentication(2); + } +} + +void Server::processUserCmd(Client& client, const std::string& command, int fd) +{ + std::istringstream iss(command); + std::string cmd, username, dontworry, dontworry1, realname, nickname; + iss >> cmd >> username >> dontworry >> dontworry1 >> realname; + username = trim(username); + dontworry = trim(dontworry); + dontworry1 = trim(dontworry1); + realname = trim(realname); + + std::string reme; + if (iss.fail() || iss >> reme) { + std::string errorMessage = "Error: Command requires four parameters\n"; + send(fd, errorMessage.c_str(), errorMessage.length(), 0); + client.clearCommand(); + return; + } + + if (dontputthesameusername(username) == true) { + std::string confirmation = "Please Use a Different username : \n"; + send(fd, confirmation.c_str(), confirmation.length(), 0); + } + else { + setUsernames(fd, username); + for (size_t i = 0; i < _clients.size(); ++i) { + if (_clients[i].getFd() == fd) { + _clients[i].setUser(username); + _clients[i].setName(realname); + nickname = _clients[i].getNick(); + break; + } + } + welcome(nickname, fd); + } +} + +void Server::welcome(const std::string& nickname, int fd){ + std::string one = OO1; + std::string two = OO2; + std::string tre = OO3; + std::string foor = OO4; + send(fd, one.c_str(), one.length(), 0); + send(fd, two.c_str(), two.length(), 0); + send(fd, tre.c_str(), tre.length(), 0); + send(fd, foor.c_str(), foor.length(), 0); +} diff --git a/Srcs/Authentication.o b/Srcs/Authentication.o new file mode 100644 index 0000000..6bed2aa Binary files /dev/null and b/Srcs/Authentication.o differ diff --git a/Srcs/Broadcast.cpp b/Srcs/Broadcast.cpp new file mode 100644 index 0000000..e93e63c --- /dev/null +++ b/Srcs/Broadcast.cpp @@ -0,0 +1,132 @@ +#include "Server.hpp" + +// brodcasting msg to all nicks in the channel +void Server::broadcastMessage(const std::string& channel, const std::string& senderNickname, const std::string& msg) { + std::map::iterator it = channels.find(channel); + if (it == channels.end()) { + std::cerr << "Channel " << channel << " does not exist" << std::endl; + return; + } + + if (channels[channel].findUserFdForKickRegulars(senderNickname) == -1) { + return; + } + + std::string message = ":" + senderNickname + " PRIVMSG #" + channel + " :" + msg + "\r\n"; + const std::vector& clients = it->second.getClients(); + + for (size_t i = 0; i < clients.size(); ++i) { + const std::string& client = clients[i]; + + if (client == senderNickname) { + continue; + } + + int recipientFd = it->second.getUserFd(client); + + if (recipientFd != -1) { + std::cout << message << std::endl; + send(recipientFd, message.c_str(), message.size(), 0); + } else { + std::cerr << "Client " << client << " not found" << std::endl; + } + } +} + +void Server::smallBroadcastMsgForKick(std::string sender , const std::string& channelname, const std::string& usertokick, const std::string& reason) { + std::map::iterator it = channels.find(channelname); + if (it == channels.end()) { + std::cerr << "Channel " << channelname << " does not exist" << std::endl; + return; + } + std::string kickMessage = KICK_MESSAGE(sender, channelname, usertokick, reason); + + const std::vector& clients = it->second.getClients(); + + for (size_t i = 0; i < clients.size(); ++i) { + const std::string& client = clients[i]; + + if (client == sender) { + continue; + } + int recipientFd = it->second.getUserFd(client); + if (recipientFd != -1) { + send(recipientFd, kickMessage.c_str(), kickMessage.size(), 0); + } else { + std::cerr << "Client " << client << " not found" << std::endl; + } + } +} + +void Server::smallbroadcastMessageforjoin(std::string nickname , const std::string& channelName) { + std::map::iterator it = channels.find(channelName); + if (it == channels.end()) { + std::cerr << "Channel " << channelName << " does not exist" << std::endl; + return; + } + std::string joinMessage = JOIN_MESSAGE(nickname, channelName); + const std::vector& clients = it->second.getClients(); + + for (size_t i = 0; i < clients.size(); ++i) { + const std::string& client = clients[i]; + + if (client == nickname) { + continue; + } + int recipientFd = it->second.getUserFd(client); + if (recipientFd != -1) { + send(recipientFd, joinMessage.c_str(), joinMessage.size(), 0); + } else { + std::cerr << "Client " << client << " not found" << std::endl; + } + } +} + +void Server::smallbroadcastMessageforTopic(std::string nicknamesender, const std::string& channelname, std::string topic) { + std::map::iterator it = channels.find(channelname); + if (it == channels.end()) { + std::cerr << "Channel " << channelname << " does not exist" << std::endl; + return; + } + + std::string topicMessage = TOPIC_MESSAGE2(nicknamesender, channelname, topic); + const std::vector& clients = it->second.getClients(); + + for (size_t i = 0; i < clients.size(); ++i) { + const std::string& client = clients[i]; + + if (client == nicknamesender) { + continue; + } + int recipientFd = it->second.getUserFd(client); + if (recipientFd != -1) { + send(recipientFd, topicMessage.c_str(), topicMessage.size(), 0); + } else { + std::cerr << "Client " << client << " not found" << std::endl; + } + } +} + +void Server::smallbroadcastMOOD(std::string sender, const std::string& channelname, std::string mode, std::string receiver) { + + std::map::iterator it = channels.find(channelname); + if (it == channels.end()) { + std::cerr << "Channel " << channelname << " does not exist" << std::endl; + return; + } + + std::string modeChangeMessage = MODE_CHANGE_MESSAGE(channelname, mode, sender, receiver); + + int senderFd = it->second.getUserFd(sender); + const std::vector& clients = it->second.getClients(); + for (size_t i = 0; i < clients.size(); ++i) { + const std::string& client = clients[i]; + + int recipientFd = it->second.getUserFd(client); + if (recipientFd != -1 && recipientFd != senderFd) { + send(recipientFd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0); + } else { + std::cerr << "Client " << client << " not found or is the sender" << std::endl; + } + } +} \ No newline at end of file diff --git a/Srcs/Broadcast.o b/Srcs/Broadcast.o new file mode 100644 index 0000000..64f69df Binary files /dev/null and b/Srcs/Broadcast.o differ diff --git a/Channel.cpp b/Srcs/Channel.cpp similarity index 67% rename from Channel.cpp rename to Srcs/Channel.cpp index 87d05ba..93332c8 100644 --- a/Channel.cpp +++ b/Srcs/Channel.cpp @@ -1,4 +1,5 @@ #include "Channel.hpp" +#include "Server.hpp" Channel::Channel(){} @@ -134,3 +135,44 @@ void Channel::removeOperator(const std::string& operatorName ) } } } + +void Server::createChannel(const std::string& channelName, const std::string& nickname, int fd) { + // Check if the channel already exists + std::map::iterator it = channels.find(channelName); + if (it == channels.end()) { + isinvited = 0; + // Channel doesn't exist, so create it and add the user + addUserToChannel(nickname, channelName, fd); + } + else { + if (channels[channelName].findUserFdForKickRegulars(nickname) == -1 && channelLimit == 1) { + limitchannelforincrement = limitchannelforincrement + 1; + } + // Channel already exists, just add the user to it + it->second.addClient(nickname, fd); + // Send JOIN message to the client + sendJoinMsg(nickname, channelName, fd); + } +} + +void Server::addUserToChannel(const std::string& nickname, const std::string& channelName, int fd) { + Channel newChannel(channelName); + newChannel.addClient(nickname, fd); + newChannel.addOperator(nickname, fd); + opperatorfd = fd; + + std::string creationTimeMessage = constructCreationTimeMessage(channelName); + std::string joinMessage = JOIN_MESSAGE(nickname, channelName); + std::string modeMessage = MODE_MESSAGE(channelName); + std::string namesMessage = NAMES_MESSAGE(nickname, channelName); + std::string endOfNamesMessage = END_OF_NAMES_MESSAGE(nickname, channelName); + std::string channelMessage = CHANNEL_MESSAGE(channelName, creationTimeMessage); + + send(fd, joinMessage.c_str(), joinMessage.length(), 0); + send(fd, modeMessage.c_str(), modeMessage.length(), 0); + send(fd, namesMessage.c_str(), namesMessage.length(), 0); + send(fd, endOfNamesMessage.c_str(), endOfNamesMessage.length(), 0); + send(fd, channelMessage.c_str(), channelMessage.length(), 0); + + channels.insert(std::make_pair(channelName, newChannel)); +} \ No newline at end of file diff --git a/Srcs/Channel.o b/Srcs/Channel.o new file mode 100644 index 0000000..83c9783 Binary files /dev/null and b/Srcs/Channel.o differ diff --git a/Client.cpp b/Srcs/Client.cpp similarity index 100% rename from Client.cpp rename to Srcs/Client.cpp diff --git a/Srcs/Client.o b/Srcs/Client.o new file mode 100644 index 0000000..400cf31 Binary files /dev/null and b/Srcs/Client.o differ diff --git a/Srcs/Commands.cpp b/Srcs/Commands.cpp new file mode 100644 index 0000000..55804f7 --- /dev/null +++ b/Srcs/Commands.cpp @@ -0,0 +1,263 @@ +#include "Server.hpp" + +void Server::ping(const std::string& command, int fd) { + std::istringstream iss(command); + std::string serverHostname = command.substr(5); + std::string pongMessage = "PONG " + serverHostname + "\r\n"; + send(fd, pongMessage.c_str(), pongMessage.length(), 0); + std::cout << "PONG" << std::endl; +} + +void Server::processJoinCmd(Client& client, const std::string& command, int fd) +{ + std::string nick; + for (size_t i = 0; i < _clients.size(); ++i) { + if (_clients[i].getFd() == fd) { + nick = _clients[i].getNick(); + break; + } + } + std::string channelName, pass ; + std::istringstream iss(command.substr(5)); + iss >> channelName ; + if (channelName[0] != '#') + { + std::string what = " :Error: Channel start with #\r\n"; + std::string errorMessage = ERROR_MESSAGE2(nick); + send(fd, errorMessage.c_str(), errorMessage.length(), 0); + client.clearCommand(); + return; + } + channelName = channelName.substr(1); + channelName = trim(channelName); + std::getline(iss, pass); + pass = trim(pass); + + // Check if the channel already exists + std::map::iterator it = channels.find(channelName); + if (it != channels.end()) + { + // Channel already exists + std::string what = " :Error: CHANNEL limit\r\n"; + if ((isinvited == 1 && channels[channelName].isInvited(nick)) || channels[channelName].isOperator(fd)) + { + // User is invited, create the channel + int check = channels[channelName].getChannelLimit(); + if (limitchannelforincrement < check || channelLimit == 0) + createChannel(channelName, nick, fd); + else { + std::string errorMessage = ERROR_MESSAGE2(nick); + send(fd, errorMessage.c_str(), errorMessage.length(), 0); + } + } + else if (isinvited == 0) { + if (itHasPass == 1 && channels[channelName].getPass() == pass) { + int check = channels[channelName].getChannelLimit(); + if (limitchannelforincrement < check || channelLimit == 0) + createChannel(channelName, nick, fd); + else { + std::string errorMessage = ERROR_MESSAGE2(nick); + send(fd, errorMessage.c_str(), errorMessage.length(), 0); + } + } + else if (itHasPass == 0) { + int check = channels[channelName].getChannelLimit(); + if (limitchannelforincrement < check || channelLimit == 0) + createChannel(channelName, nick, fd); + else { + std::string errorMessage = ERROR_MESSAGE2(nick); + send(fd, errorMessage.c_str(), errorMessage.length(), 0); + } + } + else if (itHasPass == 1 && channels[channelName].getPass() != pass) { + what = " :Error: you need a password for this channel\r\n"; + std::string errorMessage = ERROR_MESSAGE2(nick); + send(fd, errorMessage.c_str(), errorMessage.length(), 0); + } + + } + else { + // User is not invited, send error message + what = " :Error: you are not invited\r\n"; + std::string errorMessage = ERROR_MESSAGE2(nick); + send(fd, errorMessage.c_str(), errorMessage.length(), 0); + } + } + else + createChannel(channelName, nick, fd); +} + +void Server::processPrivmsgCmd(Client& client, const std::string& command, int fd) +{ + std::istringstream iss(command); + std::string cmd, recipient, message; + std::string niiick; + + iss >> cmd >> recipient; + recipient = trim(recipient); + std::getline(iss, message); + + if (iss.fail()) { + std::string errorMessage = "Error: You Just missing an argument(5)\n"; + send(fd, errorMessage.c_str(), errorMessage.length(), 0); + client.clearCommand(); + return; + } + + message = trim(message); + message = message.substr(1); + if (recipient[0] == '#') { + recipient = recipient.substr(1); + for (size_t i = 0; i < _clients.size(); ++i) { + if (_clients[i].getFd() == fd) { + niiick = _clients[i].getNick(); + break; + } + } + broadcastMessage(recipient, niiick, message); + } + else { + handlePrivateMessage(fd, recipient, message); + } +} + +void Server::processQuitCmd(int fd) { + cleanChannel(fd); + clientCleanup(fd); + std::cout << "Client <" << fd << "> Disconnected" << std::endl; +} + +void Server::processKickCmd(Client& client, const std::string& command, int fd) +{ + std::string channelName, userToKick, reason; + std::istringstream iss(command.substr(5)); + iss >> channelName >> userToKick; + + if (iss.fail()) { + std::string errorMessage = "Error: You Just missing an argument(4)\n"; + send(fd, errorMessage.c_str(), errorMessage.length(), 0); + client.clearCommand(); + return; + } + + std::getline(iss, reason); + channelName = channelName.substr(1); + channelName = trim(channelName); + userToKick = trim(userToKick); + reason = trim(reason); + + std::string sender = channels[channelName].getNickname(fd); + if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) { + int userFd = channels[channelName].findUserFdForKickRegulars(userToKick); + if (userFd != -1) { + channels[channelName].ejectUserfromusers(userFd); + channels[channelName].ejectUserfromivited(userToKick); + std::string kickMessage = KICK_MESSAGE2(channelName, fd, userToKick, reason); + smallBroadcastMsgForKick(sender, channelName, userToKick, reason); + send(fd, kickMessage.c_str(), kickMessage.length(), 0); + send(userFd , kickMessage.c_str(), kickMessage.length(), 0); + } + else { + std::string errorMessage = ERROR_MESSAGE3(sender, channelName, userToKick); + send(fd, errorMessage.c_str(), errorMessage.size(), 0); + } + } + else { + std::string errorMessage = ERROR_MESSAGE4(sender, channelName, userToKick); + send(fd, errorMessage.c_str(), errorMessage.size(), 0); + } +} + +void Server::processTopicCmd(Client& client, const std::string& command, int fd) +{ + std::string channelName, topic; + std::istringstream iss(command.substr(6)); + iss >> channelName; + std::getline(iss, topic); + + if (iss.fail()) { + std::string errorMessage = "Error: You Just missing an argument(3)\n"; + send(fd, errorMessage.c_str(), errorMessage.length(), 0); + client.clearCommand(); + return; + } + + channelName = channelName.substr(1); + channelName = trim(channelName); + topic = trim(topic); + topic = topic.substr(1); + + std::string sender = channels[channelName].getNickname(fd); + if ((channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) || issettop == 1) { + channels[channelName].setTopic(topic); + std::string topicMessage = TOPIC_MESSAGE2(sender, channelName, topic); + send(fd, topicMessage.c_str(), topicMessage.size(), 0); + smallbroadcastMessageforTopic(sender, channelName, topic); + } + else { + std::string errorMessage = ERROR_MESSAGE6(sender, channelName); + send(fd, errorMessage.c_str(), errorMessage.size(), 0); + } +} + +void Server::processInviteCmd(Client& client, const std::string& command, int fd) { + std::string channelName, nickname; + std::istringstream iss(command.substr(7)); + iss >> nickname >> channelName; + + if (iss.fail()) { + std::string errorMessage = "Error: You Just missing an argument(2)\n"; + send(fd, errorMessage.c_str(), errorMessage.length(), 0); + client.clearCommand(); + return; + } + + channelName = trim(channelName); + nickname = trim(nickname); + channelName = channelName.substr(1); + + if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) { + channels[channelName].addClientinveted(nickname, fd); + handleInvitation(fd, nickname, channelName); + } + else { + std::string errorMessage = ERROR_MESSAGE7(channelName, fd); + send(fd, errorMessage.c_str(), errorMessage.size(), 0); + } +} + +void Server::processBotCmd(Client& client, const std::string& command, int fd) { + std::string start, end, guessed; + std::istringstream iss(command.substr(4)); + iss >> start >> end >> guessed; + std::string reme; + + if (iss.fail() || iss >> reme) + { + std::string errorMessage = "Error: Command take 3 parameters\n"; + send(fd, errorMessage.c_str(), errorMessage.length(), 0); + client.clearCommand(); + return; + } + + start = trim(start); + end = trim(end); + guessed = trim(guessed); + + if (stringToInt(start) < stringToInt(end) && stringToInt(guessed) >= stringToInt(start) && stringToInt(guessed) <= stringToInt(end)) { + int r = randomInRange(stringToInt(start), stringToInt(end)); + std::string random = intToString(r); + if (random == guessed) { + std::string congratsMsg = CONGRATS_MSG(guessed); + send(fd, congratsMsg.c_str(), congratsMsg.size(), 0); + } + else { + std::string guessAgain = GUESS_AGAIN(random); + send(fd, guessAgain.c_str(), guessAgain.size(), 0); + } + } + else { + std::string errorMessage = GUESS_ERROR(); + send(fd, errorMessage.c_str(), errorMessage.size(), 0); + } +} \ No newline at end of file diff --git a/Srcs/Commands.o b/Srcs/Commands.o new file mode 100644 index 0000000..57cd4a4 Binary files /dev/null and b/Srcs/Commands.o differ diff --git a/Srcs/Helpers.cpp b/Srcs/Helpers.cpp new file mode 100644 index 0000000..35db2a8 --- /dev/null +++ b/Srcs/Helpers.cpp @@ -0,0 +1,193 @@ +#include "Server.hpp" + +void Server::parseArgs(int ac, char **av) { + if (ac != 3) + throw std::runtime_error("Usage: ./ircserv "); + std::string port(av[1]); + std::string pwd(av[2]); + if (port.empty() || port.find_first_not_of("0123456789") != std::string::npos) + throw std::runtime_error("Error: Invalid arguments"); + + long _port = atol(av[1]); + if (!(_port >= 0 && _port <= 65535)) + throw std::runtime_error("Error: Invalid arguments"); + + if (pwd.empty()) + throw std::runtime_error("Error: Invalid arguments"); + + this->_port = _port; + this->_password = pwd; +} + +std::string Server::intToString(int number) { + std::stringstream ss; + ss << number; + return ss.str(); +} + +std::string Server::trim(const std::string& str) { + size_t first = str.find_first_not_of(" \t\n\r"); + if (std::string::npos == first) { + return ""; + } + size_t last = str.find_last_not_of(" \t\n\r"); + return str.substr(first, last - first + 1); +} + +bool Server::startsWith(const std::string& str, const std::string& prefix) { + return str.substr(0, prefix.length()) == prefix; +} + +int Server::stringToInt(const std::string& str) { + std::stringstream ss(str); + int result; + ss >> result; + return result; +} + +bool Server::isValidPassword(const std::string& passwordLine) { + if (!passwordLine.empty() && + ((passwordLine[0] == '"' && passwordLine.size() > 1 && passwordLine[passwordLine.size() - 1] == '"') || + (passwordLine[0] == '\'' && passwordLine.size() > 1 && passwordLine[passwordLine.size() - 1] == '\''))) { + return true; + } + return false; +} + +std::string Server::formatCreationTime() { + std::time_t currentTime = std::time(NULL); + std::tm* localTime = std::localtime(¤tTime); + + char buffer[80]; + std::strftime(buffer, sizeof(buffer), "%a %b %d %H:%M:%S %Y", localTime); + return std::string(buffer); +} + +std::string Server::constructCreationTimeMessage(const std::string& channelName) { + std::stringstream ss; + ss << "Channel #" << channelName << " created " << formatCreationTime(); + return ss.str(); +} + +std::string Server::constructJoinedTimeMessage(const std::string& channelName) { + std::stringstream ss; + ss << "Channel #" << channelName << " Joined " << formatCreationTime(); + return ss.str(); +} + +void Server::closeFds() +{ + for (size_t i = 0; i < _clients.size(); i++){ + int fd = _clients[i].getFd(); + std::cout << "Client <" << fd << "> Disconnected" << std::endl; + close(fd); + } + + if (_serverSocketFd != -1) + close(_serverSocketFd); + _fds.clear(); +} + +void Server::cleanChannel(int fd) { + std::map::iterator it; + for (it = channels.begin(); it != channels.end(); ++it) + { + Channel& channel = it->second; + std::string nickname = channel.getNickname(fd); + if (channel.isUserInChannel(nickname)) { + channel.ejectUserfromusers(fd); + } + } + + std::map::iterator userIt; + userIt = usernames.find(fd); + if (userIt != usernames.end()) { + usernames.erase(userIt); + } + + std::map::iterator nickIt; + nickIt = nicknames.find(fd); + if (nickIt != nicknames.end()) { + nicknames.erase(nickIt); + } + + for (std::map::iterator it = channels.begin(); it != channels.end(); ++it) { + std::map &usersfdmap = it->second.getUserFdMap(); + for (std::map::iterator it2 = usersfdmap.begin(); it2 != usersfdmap.end(); ++it2) { + if (it2->second == fd) + usersfdmap.erase(it2); + } + } + for (std::map::iterator it1 = channels.begin(); it1 != channels.end(); ++it1) { + std::map &invitedusrmap = it1->second.invitedUserss(); + for (std::map::iterator it2 = invitedusrmap.begin(); it2 != invitedusrmap.end(); ++it2) { + if (it2->second == fd) + invitedusrmap.erase(it2); + } + } + for (std::map::iterator it2 = channels.begin(); it2 != channels.end(); ++it2) { + std::map &operatorsmap = it2->second.getOperators(); + for (std::map::iterator it2 = operatorsmap.begin(); it2 != operatorsmap.end(); ++it2) { + if (it2->second == fd) + operatorsmap.erase(it2); + } + } +} + +void Server::clientCleanup(int fd) { + for (std::vector::iterator it = _fds.begin(); it != _fds.end(); ++it) { + if (it->fd == fd) { + _fds.erase(it); + close(fd); + break; + } + } + + for (std::vector::iterator it = _clients.begin(); it != _clients.end(); ++it) { + if (it->getFd() == fd) { + _clients.erase(it); + break; + } + } +} + +int Server::randomInRange(int min, int max) +{ + if (min > max) { + return -1; + } + + int range_size = max - min + 1; + double random_double = (double)rand() / (RAND_MAX + 1.0) * range_size; + + return (int)random_double + min; +} + +// find nicknames of the users to brodcast to +int Server::findUserFd1(const std::string& username) { + std::map::iterator it; + for (it = nicknames.begin(); it != nicknames.end(); ++it) { + if (it->second == username) + return it->first; + } + return -1; +} + +bool Server::dontputthesamenick(const std::string& nickname) { + std::map::iterator it; + for (it = nicknames.begin(); it != nicknames.end(); ++it) { + if (it->second == nickname) + return true; + } + return false; +} + +bool Server::dontputthesameusername(const std::string& username) { + std::map::iterator it; + for (it = usernames.begin(); it != usernames.end(); ++it) { + if (it->second == username) { + return true; + } + } + return false; +} \ No newline at end of file diff --git a/Srcs/Helpers.o b/Srcs/Helpers.o new file mode 100644 index 0000000..5a59e9a Binary files /dev/null and b/Srcs/Helpers.o differ diff --git a/Srcs/Modes.cpp b/Srcs/Modes.cpp new file mode 100644 index 0000000..6f3b2b2 --- /dev/null +++ b/Srcs/Modes.cpp @@ -0,0 +1,170 @@ +#include "Server.hpp" + +void Server::processModeCmd(Client& client, const std::string& command, int fd) { + std::string channelName, mode , nick; + std::istringstream iss(command.substr(5)); + iss >> channelName >> mode >> nick; + + if (channelName[0] != '#') { + client.clearCommand(); + return; + } + + channelName = channelName.substr(1); + channelName = trim(channelName); + mode = trim(mode); + size_t opt = mode.length() - 1; + + if (mode[opt] == 'o') + handleOpPrivilege(nick, channelName, mode, fd); + else if (mode[opt] == 't') + handleTopicRestriction(nick, channelName, mode, fd); + else if (mode[opt] == 'i') + handleInviteOnly(nick, channelName, mode, fd); + else if (mode[opt] == 'k') + handleChannelKey(nick, channelName, mode, fd); + else if (mode[opt] == 'l') + handleChannelLimit(nick, channelName, mode, fd); +} + +void Server::handleOpPrivilege(const std::string& nick, const std::string& channelName, const std::string& mode, int fd) { + if (mode == "+o") { + if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) { + channels[channelName].addOperator(nick, channels[channelName].getUserFd(nick)); + abaaba = channels[channelName].getUserFd(nick); + std::string modeChangeMessage = MODE_SET_MESSAGE(channelName, mode, fd, nick); + send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0); + smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick); + } + else { + std::string errorMessage = ERROR_MESSAGE7(channelName, fd); + send(fd, errorMessage.c_str(), errorMessage.size(), 0); + } + } + else if (mode == "-o") { + if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) { + channels[channelName].removeOperator(nick); + std::string modeChangeMessage = MODE_UNSET_MESSAGE(channelName, mode, fd, nick); + send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0); + smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick); + } + else { + std::string errorMessage = ERROR_MESSAGE5(); + send(fd, errorMessage.c_str(), errorMessage.size(), 0); + } + } +} + +void Server::handleTopicRestriction(const std::string& nick, const std::string& channelName, const std::string& mode, int fd) { + if (mode == "-t") { + if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) { + std::string modeChangeMessage = TOPIC_CHANGE_MESSAGE(channelName, mode, fd); + send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0); + smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick); + issettop = 1; + } + else { + std::string errorMessage = ERROR_MESSAGE5(); + send(fd, errorMessage.c_str(), errorMessage.size(), 0); + } + } + else if (mode == "+t") { + if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) { + std::string modeChangeMessage = TOPIC_CHANGE_MESSAGE(channelName, mode, fd); + send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0); + smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick); + issettop = 0; + } + else { + std::string errorMessage = ERROR_MESSAGE5(); + send(fd, errorMessage.c_str(), errorMessage.size(), 0); + } + } +} + +void Server::handleInviteOnly(const std::string& nick, const std::string& channelName, const std::string& mode, int fd) { + if (mode == "+i") { + if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) { + std::string modeChangeMessage = MODE_SET_MESSAGE(channelName, mode, fd, nick); + send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0); + smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick); + isinvited = 1; + } + else if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd) == false) { + std::string errorMessage = ERROR_MESSAGE5(); + send(fd, errorMessage.c_str(), errorMessage.size(), 0); + } + + } + else if (mode == "-i") { + if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) { + std::string modeChangeMessage = MODE_UNSET_MESSAGE(channelName, mode, fd, nick);; + send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0); + smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick); + isinvited = 0; + } + else { + std::string errorMessage = ERROR_MESSAGE5(); + send(fd, errorMessage.c_str(), errorMessage.size(), 0); + } + } +} + +void Server::handleChannelKey(std::string& nick, const std::string& channelName, const std::string& mode, int fd) { + if (mode == "-k") { + if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) { + std::string modeChangeMessage = MODE_UNSET_MESSAGE(channelName, mode, fd, nick); + send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0); + smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick); + itHasPass = 0; + } + else { + std::string errorMessage = ERROR_MESSAGE5(); + send(fd, errorMessage.c_str(), errorMessage.size(), 0); + } + } + else if (mode == "+k") { + nick = trim(nick); + channels[channelName].setPass(nick); + if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) { + std::string modeChangeMessage = MODE_SET_MESSAGE(channelName, mode, fd, nick); + send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0); + smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick); + itHasPass = 1; + } + else { + std::string errorMessage = ERROR_MESSAGE5(); + send(fd, errorMessage.c_str(), errorMessage.size(), 0); + } + } +} + +void Server::handleChannelLimit(const std::string& nick, const std::string& channelName, const std::string& mode, int fd) { + if (mode == "+l") { + if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) { + int limit = stringToInt(nick); + channels[channelName].setlimitchannel(limit); + std::string modeChangeMessage = MODE_SET_MESSAGE(channelName, mode, fd, nick); + send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0); + smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick); + channelLimit = 1; + } + else { + std::string errorMessage = ERROR_MESSAGE5(); + send(fd, errorMessage.c_str(), errorMessage.size(), 0); + } + } + else if (mode == "-l") { + if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) { + std::string modeChangeMessage = MODE_UNSET_MESSAGE(channelName, mode, fd, nick); + send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0); + smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick); + channelLimit = 0; + limitchannelforincrement = 0; + } + else { + std::string errorMessage = ERROR_MESSAGE5(); + send(fd, errorMessage.c_str(), errorMessage.size(), 0); + } + } +} diff --git a/Srcs/Modes.o b/Srcs/Modes.o new file mode 100644 index 0000000..d43fdb5 Binary files /dev/null and b/Srcs/Modes.o differ diff --git a/Srcs/Server.cpp b/Srcs/Server.cpp new file mode 100644 index 0000000..92da1dd --- /dev/null +++ b/Srcs/Server.cpp @@ -0,0 +1,239 @@ +#include "Server.hpp" + +int opperatorfd = 0; +int issettop = 0; +int isinvited = 0; +int itHasPass = 0; +int channelLimit = 0; +int limitchannelforincrement = 0; +int abaaba = 0; + +bool Server::_signal = false; + +Server::Server() {} + +Server::~Server() {} + +std::string Server::getPassowrd() const { + return _password; +} + +void Server::receiveSignal(int signum) { + _signal = true; + (void)signum; +} + +Client& Server::getClientByFd(int fd) { + size_t i = 0; + for (; i < _clients.size(); ++i) { + if (_clients[i].getFd() == fd) + break; + } + return _clients[i]; +} + +void Server::setNickname(int fd, const std::string& nickname) {nicknames[fd] = nickname;} + +void Server::setUsernames(int fd, const std::string& username) {usernames[fd] = username;} + +void Server::init() { + signal(SIGINT, receiveSignal); + signal(SIGQUIT, receiveSignal); + + createServerSocket(); + std::cout << GREEN << ">>> SERVER STARTED <<<" << RESET << std::endl; + std::cout << CYAN <<"Waiting for connections..." << RESET << std::endl; +} + +void Server::run() { + while (!_signal) { + int ret = poll(&_fds[0], _fds.size(), -1); + if (ret == -1 && !_signal) + throw std::runtime_error("Error: poll() failed"); + + for (size_t i = 0; i < _fds.size(); ++i) { + if (_fds[i].revents & POLLIN) { + if (_fds[i].fd == _serverSocketFd) + handleClientConnection(); + else + handleClientData(_fds[i].fd); + } + } + } + closeFds(); +} + +void Server::createServerSocket() { + _serverSocketFd = socket(AF_INET, SOCK_STREAM, 0); + if (_serverSocketFd == -1) + throw std::runtime_error("Error: failed to create socket"); + + int optval = 1; + if (setsockopt(_serverSocketFd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) + throw std::runtime_error("Error: setsockopt() failed"); + + if (fcntl(_serverSocketFd, F_SETFL, O_NONBLOCK) == -1) + throw std::runtime_error("Error: fcntl() failed"); + + bindServerSocket(); + + if (listen(_serverSocketFd, SOMAXCONN) == -1) + throw std::runtime_error("Error: listen() failed"); + + addPollfd(_serverSocketFd); +} + +void Server::bindServerSocket() { + struct sockaddr_in sa; + sa.sin_family = AF_INET; + sa.sin_port = htons(_port); + sa.sin_addr.s_addr = INADDR_ANY; + if (bind(_serverSocketFd, (struct sockaddr*)&sa, sizeof(sa)) == -1) { + throw std::runtime_error("Error: failed to bind socket"); + } +} + +void Server::addPollfd(int fd) { + struct pollfd newPollfd; + newPollfd.fd = fd; + newPollfd.events = POLLIN; + newPollfd.revents = 0; + _fds.push_back(newPollfd); +} + +void Server::handleClientConnection() { + struct sockaddr_in client_addr; + socklen_t clientAddrSize = sizeof(sockaddr_in); + int newFd = accept(_serverSocketFd, (struct sockaddr *)&client_addr, &clientAddrSize); + if (newFd == -1) + throw std::runtime_error("Error: accept() failed"); + + if (fcntl(newFd, F_SETFL, O_NONBLOCK) == -1) + throw std::runtime_error("Error: fcntl() failed"); + + std::string passwordRequest = "Please Enter The password Of This Server :\n"; + std::string art = MINICHAT; + + send(newFd, art.c_str(), art.length(), 0); + send(newFd, passwordRequest.c_str(), passwordRequest.length(), 0); + addPollfd(newFd); + _clients.push_back(Client(newFd)); + + std::cout << "Client <" << newFd << "> Connected" << std::endl; +} + +void Server::sendJoinMsg(const std::string& nickname, const std::string& channelName, int fd) { + std::string operators = channels[channelName].getOperatorNickname(opperatorfd); + std::string operators1 = channels[channelName].getOperatorNickname(abaaba); + + std::string topic = channels[channelName].getTopic(); + std::string creationTimeMessage = constructJoinedTimeMessage(channelName); + std::string joinMessage = JOIN_MESSAGE(nickname, channelName); + std::string topicMessage = TOPIC_MESSAGE(nickname, channelName, topic); + + send(fd, joinMessage.c_str(), joinMessage.length(), 0); + send(fd, topicMessage.c_str(), topicMessage.length(), 0); + + std::string namesMessage = NAMES_MESSAGE2(nickname, channelName); + const std::vector& clients = channels[channelName].getClients(); + for (size_t i = 0; i < clients.size(); ++i) { + const std::string& user = clients[i]; + if (user == operators || user == operators1) { + namesMessage += "@" + user; + } else { + namesMessage += user; + } + if (i < clients.size() - 1) + namesMessage += " "; + } + namesMessage += "\n"; + std::string endOfNamesMessage = END_OF_NAMES_MESSAGE(nickname, channelName); + std::string channelMessage = CHANNEL_MESSAGE(channelName, creationTimeMessage); + + send(fd, namesMessage.c_str(), namesMessage.length(), 0); + send(fd, endOfNamesMessage.c_str(), endOfNamesMessage.length(), 0); + send(fd, channelMessage.c_str(), channelMessage.length(), 0); + + smallbroadcastMessageforjoin(nickname, channelName); +} + +// handling private msg between users only +void Server::handlePrivateMessage(int senderFd, const std::string& recipient, const std::string& message) { + int recipientFd = findUserFd1(recipient); + if (recipientFd != -1) { + std::string privateMessage = PRIVATE_MESSAGE(senderFd, recipient, message); + send(recipientFd, privateMessage.c_str(), privateMessage.length(), 0); + } else { + std::string errorMessage = ERROR_MESSAGE(senderFd, recipient); + send(senderFd, errorMessage.c_str(), errorMessage.length(), 0); + } +} + +void Server::handleInvitation(int senderFd, const std::string& recipient, std::string channelName) { + int recipientFd = findUserFd1(recipient); + + if (recipientFd != -1) { + std::string inviteMessage = INVITE_MESSAGE(senderFd, recipient, channelName); + send(recipientFd, inviteMessage.c_str(), inviteMessage.length(), 0); + } else { + std::string errorMessage = ERROR_MESSAGE(senderFd, recipient); + send(senderFd, errorMessage.c_str(), errorMessage.length(), 0); + } +} + +void Server::handleClientData(int fd) +{ + Client& client = getClientByFd(fd); + char buffer[BUFFER_SIZE]; + memset(buffer, 0, sizeof(buffer)); + + ssize_t bytesRead = recv(fd, buffer, BUFFER_SIZE - 1, 0); + if (bytesRead > 0) { + buffer[bytesRead] = '\0'; + client.appendCommand(buffer); + size_t newlinePos = client.getCommand().find_first_of("\r\n"); + if (newlinePos != std::string::npos) { + std::string command = client.getCommand().substr(0, newlinePos); + client.setCommand(command); + std::cout << "Received data from client " << fd << ": " << command << std::endl; + int auth = client.getAuthentication(); + + if ((startsWith(command, "PASS ") || startsWith(command, "pass ")) && auth == 0) + processPassword(client, command, fd); + else if ((startsWith(command, "NICK ") || startsWith(command, "nick ")) && auth == 1) + processNickCmd(client, command, fd); + else if ((startsWith(command, "USER ") || startsWith(command, "user ")) && auth == 2) + processUserCmd(client, command, fd); + else if (startsWith(command, "JOIN ") || startsWith(command, "join ")) + processJoinCmd(client, command, fd); + else if (startsWith(command, "PRIVMSG ") || startsWith(command, "privmsg ")) + processPrivmsgCmd(client, command, fd); + else if (startsWith(command, "KICK ") || startsWith(command, "kick ")) + processKickCmd(client, command, fd); + else if (startsWith(command, "TOPIC ") || startsWith(command, "topic ")) + processTopicCmd(client, command, fd); + else if (startsWith(command, "INVITE ") || startsWith(command, "invite ")) + processInviteCmd(client, command, fd); + else if (startsWith(command, "BOT ") || startsWith(command, "bot ")) + processBotCmd(client, command, fd); + else if (startsWith(command, "MODE ") || startsWith(command, "mode ")) + processModeCmd(client, command, fd); + else if (startsWith(command, "QUIT") || startsWith(command, "quit")) + processQuitCmd(fd); + else if (startsWith(command, "PING")) + ping(command, fd); + + client.clearCommand(); + } + } + + else if (bytesRead == 0) { + std::cout << "Client <" << fd << "> Disconnected" << std::endl; + cleanChannel(fd); + clientCleanup(fd); + } else if (bytesRead == -1) { + std::cerr << "Error reading data from client <" << fd << ">" << std::endl; + cleanChannel(fd); + clientCleanup(fd); + } +} diff --git a/Srcs/Server.o b/Srcs/Server.o new file mode 100644 index 0000000..7b3c127 Binary files /dev/null and b/Srcs/Server.o differ