diff --git a/Client.cpp b/Client.cpp index 6ca0aa0..8270496 100644 --- a/Client.cpp +++ b/Client.cpp @@ -7,3 +7,39 @@ Client::Client(int fd, std::string addr) : _fd(fd), _addr(addr) {} Client::~Client() {} int Client::getFd() const {return _fd;} + + +void Client::setPassword(const std::string& password) { + pass = password; +} + +std::string Client::getPassowrd() const { + return pass; +} + +// Implementation of getter and setter functions for name +std::string Client::getName() const { + return name; +} + +void Client::setName(const std::string& newName) { + name = newName; +} + +// Implementation of getter and setter functions for nick +std::string Client::getNick() const { + return nick; +} + +void Client::setNick(const std::string& newNick) { + nick = newNick; +} + +// Implementation of getter and setter functions for user +std::string Client::getUser() const { + return user; +} + +void Client::setUser(const std::string& newUser) { + user = newUser; +} \ No newline at end of file diff --git a/Client.hpp b/Client.hpp index f00f124..0d67e8e 100644 --- a/Client.hpp +++ b/Client.hpp @@ -6,6 +6,10 @@ class Client { private: int _fd; + std::string pass; + std::string name; + std::string nick; + std::string user; std::string _addr; bool _isRegistered; public: @@ -14,6 +18,20 @@ class Client { ~Client(); int getFd() const; + std::string getPassowrd() const; + void setPassword(const std::string& password); // Function to set the password + // Getter and setter for name + std::string getName() const; + void setName(const std::string& newName); + + // Getter and setter for nick + std::string getNick() const; + void setNick(const std::string& newNick); + + // Getter and setter for user + std::string getUser() const; + void setUser(const std::string& newUser); + }; #endif \ No newline at end of file diff --git a/Makefile b/Makefile index 36346bc..bf0747e 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ NAME = ircserv -SRC = main.cpp Server.cpp Client.cpp +SRC = main.cpp Server.cpp Client.cpp channel.cpp OBJ = ${SRC:.cpp=.o} diff --git a/Server.cpp b/Server.cpp index 73c3a01..17f8d51 100644 --- a/Server.cpp +++ b/Server.cpp @@ -1,4 +1,5 @@ #include "Server.hpp" +int a = 0; bool Server::_signal = false; @@ -6,6 +7,14 @@ Server::Server() {} Server::~Server() {} +// void Server::setPassword(const std::string& password) { +// _password = password; +// } + +std::string Server::getPassowrd() const { + return _password; +} + void Server::parseArgs(int ac, char **av) { if (ac != 3) throw std::runtime_error("Usage: ./ircserv "); @@ -104,9 +113,12 @@ void Server::handleClientConnection() { if (newFd == -1) { throw std::runtime_error("Error: accept() failed"); } + std::string passwordRequest = "Please enter the password:\n"; + send(newFd, passwordRequest.c_str(), passwordRequest.length(), 0); addPollfd(newFd, POLLIN, 0); _clients.push_back(Client(newFd, inet_ntoa((client_addr.sin_addr)))); + std::cout << "Client <" << newFd << "> Connected" << std::endl; } @@ -137,17 +149,18 @@ std::string trim(const std::string& str) { // here i create the channel and add the nicks of the users with some checks -void Server::createChannel(const std::string& channelName, const std::string& nickname) { +void Server::createChannel(const std::string& channelName, const std::string& nickname, int fd) { // Check if the channel already exists - if (channels.find(channelName) == channels.end()) { - // Channel doesn't exist, so create it - std::vector users; - users.push_back(nickname); // Add the user to the channel - channels[channelName] = users; + std::map::iterator it = channels.find(channelName); + if (it == channels.end()) { + // Channel doesn't exist, so create it and add the user + Channel newChannel(channelName); + newChannel.addClient(nickname, fd); + channels.insert(std::make_pair(channelName, newChannel)); // Insert the new channel into the map std::cout << "Channel '" << channelName << "' created by '" << nickname << "'" << std::endl; } else { // Channel already exists, just add the user to it - channels[channelName].push_back(nickname); + it->second.addClient(nickname, fd); std::cout << "User '" << nickname << "' joined channel '" << channelName << "'" << std::endl; } } @@ -173,7 +186,7 @@ void sendResponse(int fd, const std::string& message) { const char* msg = message.c_str(); // Get the length of the message - size_t len = strlen(msg); + size_t len = strlen(msg); // Send the message to the client ssize_t bytesSent = send(fd, msg, len, 0); @@ -252,26 +265,26 @@ int Server::findUserFdforkickregulars(const std::string& username) { } return -1; // Return -1 if the nickname is not found } -//brodcasting msg to all nicks in the channel +// brodcasting msg to all nicks in the channel void Server::broadcastMessage(const std::string& channel, const std::string& senderNickname, const std::string& msg) { // Check if the channel exists - if (channels.find(channel) == channels.end()) { + debugPrintChannels(); + std::map::iterator it = channels.find(channel); + if (it == channels.end()) { std::cerr << "Channel " << channel << " does not exist" << std::endl; return; } - // Iterate through all clients in the channel and send the message -// Get a reference to the vector of clients in the channel - const std::vector& clients = channels[channel]; + // Get a reference to the vector of clients in the channel + const std::vector& clients = it->second.getClients(); - // Iterate over the vector using iterators - std::vector::const_iterator it; - for (it = clients.begin(); it != clients.end(); ++it) { + // Iterate over the vector of clients and send the message to each one + for (size_t i = 0; i < clients.size(); ++i) { // Get the current client nickname - const std::string& client = *it; + const std::string& client = clients[i]; // Find the file descriptor associated with the client nickname - int recipientFd = findUserFd1(client); + int recipientFd = it->second.getUserFd(client); // If the file descriptor is found, send the message to the client if (recipientFd != -1) { @@ -332,45 +345,119 @@ void Server::handleClientData(int fd) { std::cout << "Received data from client " << fd << ": " << command << std::endl; //******************* FROM THERE IM STARTING TOP GGG ************ . - if (startsWith(command, "SETNICK ")) { + if (startsWith(command, "pass")) + { + std::string cmd, password; + std::istringstream iss(command); + iss >> cmd >> password; + password = trim(password); // Remove leading/trailing whitespace + std::string passwordoftheserver = getPassowrd(); + if (passwordoftheserver != password) + { + std::string errorMessage = "Error: Incorrect password\n"; + send(fd, errorMessage.c_str(), errorMessage.length(), 0); + } + else { + std::string confirmation = "Welcome sir\n"; + send(fd, confirmation.c_str(), confirmation.length(), 0); + a = 1; + } + + // for (size_t i = 0; i < _clients.size(); ++i) { + // if (_clients[i].getFd() == fd) { + // _clients[i].setPassword(password); + // std::cout << "Password set for client " << fd << ": " << password << std::endl; + // break; + // } + // } + } + if (startsWith(command, "nick")) { + std::string cmd, nick; + std::istringstream iss(command); + iss >> cmd >> nick; + nick = trim(nick); + for (size_t i = 0; i < _clients.size(); ++i) { + if (_clients[i].getFd() == fd) { + _clients[i].setNick(nick); + std::cout << "Password set for client " << fd << ": " << nick << std::endl; + break; + } + } // Extract the nickname from the command - std::string nickname = command.substr(8); // Assuming "/setnick " is 9 characters long + // std::string nickname = command.substr(8); // Assuming "/setnick " is 9 characters long // Handle setting the nickname for the client's connection - setNickname(fd, nickname); + // Send a response back to the client confirming the action - sendResponse(fd, "Nickname set to: " + nickname + '\n'); - } else if (startsWith(command, "SETUSER ")) { + sendResponse(fd, "Nickname set to: " + nick + '\n'); + a = 2; + } else if (startsWith(command, "user")) { std::istringstream iss(command); - std::string cmd, username, privilege_level; - iss >> cmd >> username; + std::string cmd, username, dontworry, dontworry1, realname, nickname; + iss >> cmd >> username >> dontworry >> dontworry1 >> realname; + // Remove leading and trailing whitespace from parameters username = trim(username); - std::getline(iss, privilege_level); - privilege_level = trim(privilege_level); - std::cout << "this is the privilege : " << privilege_level << std::endl; + dontworry = trim(dontworry); + dontworry1 = trim(dontworry1); + realname = trim(realname); - if (privilege_level == "operator" ) - { - //si moskir hna atbda lkhdma dyalk - // std::cout << "we need to handle this " << std::endl; - setUsernameoperators(fd, username); - sendResponse(fd, "Username set to: " + username + " with privilege_level : " + privilege_level + '\n'); + 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; + } } - else if (privilege_level == "regular") { - setUsernameregular(fd, username); - sendResponse(fd, "Username set to: " + username + " with privilege_level : " + privilege_level + '\n'); - } + sendResponse(fd, "username set to: " + username + '\n'); + sendResponse(fd, "realname set to: " + realname + '\n'); + + std::string one = ":irc.topg 001 " + nickname + " :Welcome to the topg Network, " + nickname + '\n'; + std::string two = ":irc.topg 002 " + nickname + " :Your host is topg, running version 3030" + '\n'; + std::string tre = ":irc.topg 003 " + nickname + " :This server was created Tue Nov 30 2011 at 11:11:25 EET" + '\n'; + std::string foor = ":irc.topg 004 " + nickname + " topg tella(enterprise)-2.3(12)-netty(5.4c)-proxy(0.9) oOiwscrknfbghexzSjFI bhijklmMnoOstvcdSuU bkohv" + '\n'; + 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); + + + + + + + + + // if (privilege_level == "operator" ) + // { + // //si moskir hna atbda lkhdma dyalk + // // std::cout << "we need to handle this " << std::endl; + // setUsernameoperators(fd, username); + // sendResponse(fd, "Username set to: " + username + " with privilege_level : " + privilege_level + '\n'); + // } + // else if (privilege_level == "regular") { + // setUsernameregular(fd, username); + // sendResponse(fd, "Username set to: " + username + " with privilege_level : " + privilege_level + '\n'); + + // } // Process other commands or messages // processCommand(fd, command); } else if (startsWith(command, "JOIN ")) { - std::string chanelname = command.substr(5); + std::string user; + for (size_t i = 0; i < _clients.size(); ++i) { + if (_clients[i].getFd() == fd) { + user = _clients[i].getUser(); + break; + } + } + std::string chanelname = command.substr(6); chanelname = trim(chanelname); - createChannel(chanelname, nicknames[fd]); + createChannel(chanelname, user, fd); } else if (startsWith(command, "PRIVMSG ")) { // Extract the recipient and the message from the command @@ -425,7 +512,7 @@ void Server::handleClientData(int fd) { } else if (startsWith(command, "KICK ")) sendResponse(fd, "Error: You don't have permission to use this command.\n"); - + //**************** STOOOOOOP HERE TOP G ... break; } diff --git a/Server.hpp b/Server.hpp index c8c2add..829e189 100644 --- a/Server.hpp +++ b/Server.hpp @@ -16,6 +16,7 @@ #include "Client.hpp" #include #include +#include "channel.hpp" #define BUFFER_SIZE 1024 @@ -31,7 +32,8 @@ class Server { std::map nicknames; // Replace unordered_map with map std::map usernamesoperators; // Replace unordered_map with map std::map usernamesregulars; - std::map > channels; //here a chanel name and list of client in every chanel + // std::map > channels; //here a chanel name and list of client in every chanel + std::map channels; @@ -40,9 +42,11 @@ class Server { ~Server(); // THAT'S MY FUNCTIONS START FROM THERE void setNickname(int fd, const std::string& nickname); + std::string getPassowrd() const; + void setPassword(const std::string& password); void setUsernameoperators(int fd, const std::string& username); void setUsernameregular(int fd, const std::string& username); - void createChannel(const std::string& channel, const std::string& nickname); + void createChannel(const std::string& channel, const std::string& nickname, int fd); void handlePrivateMessage(int senderFd, const std::string& recipient, const std::string& message); void broadcastMessage(const std::string& channel, const std::string& senderNickname, const std::string& msg); int findUserFd1(const std::string& nickname); @@ -62,6 +66,14 @@ class Server { void handleClientData(int fd); void clientCleanup(int fd); void closeFds(); + + void debugPrintChannels() { + std::cout << "List of channels:" << std::endl; + std::map::iterator it; + for (it = channels.begin(); it != channels.end(); ++it) { + std::cout << "- " << it->first << std::endl; // Print the channel name (it->first) + } +} }; #endif \ No newline at end of file diff --git a/channel.cpp b/channel.cpp new file mode 100644 index 0000000..e69de29 diff --git a/channel.hpp b/channel.hpp new file mode 100644 index 0000000..4650333 --- /dev/null +++ b/channel.hpp @@ -0,0 +1,96 @@ +#ifndef CHANNEL_HPP +#define CHANNEL_HPP + + +#include +#include +#include +#include // Include for the send function +#include // Include for the strlen function +#include +#include +#include +#include +#include +#include +#include +#include "Client.hpp" +#include +#include + + +class Channel { +private: + std::string Channelname; + std::string topic; + std::string key; + std::vector users; + std::map nicknames; // Replace unordered_map with map + std::map userFdMap; // Mapping of usernames to file descriptors + + std::vector invitedUsers; + std::vector operators; + +public: + // Constructors + Channel(const std::string& name) : Channelname(name) {} + + // Destructor + ~Channel() {} + + // Add a client to the channel + + void addClient(const std::string& client, int fd) { + userFdMap[client] = fd; + } + + void addClient(const std::string& client) { + users.push_back(client); + } + + // Remove a client from the channel + void removeClient(const std::string& nickname) { + // Implement removal logic + // Iterate through clients vector, find the client by nickname, and remove it + } + + // Add an invited user to the channel + void inviteUser(const std::string& user) { + invitedUsers.push_back(user); + } + + // Remove an invited user from the channel + void uninviteUser(const std::string& user) { + // Implement removal logic + // Iterate through invitedUsers vector, find the user, and remove it + } + + // Add an operator to the channel + void addOperator(const std::string& operatorName) { + operators.push_back(operatorName); + } + + int getUserFd(const std::string& username) const { + std::map::const_iterator it = userFdMap.find(username); + if (it != userFdMap.end()) { + return it->second; + } + return -1; // Return -1 if username not found + } + + // Get all clients' usernames in the channel + std::vector getClients() const { + std::vector clients; + std::map::const_iterator it; + for (it = userFdMap.begin(); it != userFdMap.end(); ++it) { + clients.push_back(it->first); + } + return clients; + } + + // Remove an operator from the channel +}; + + + +#endif \ No newline at end of file diff --git a/todo.txt b/todo.txt new file mode 100644 index 0000000..b7dd059 --- /dev/null +++ b/todo.txt @@ -0,0 +1,44 @@ +remember the quote commande + +create object for each instence : channel and client and server + + +client : fd , pass ,name , nick , user , and remember the lastchannel * + + +channel : _limite : it's limite of the users joined the channel +-> nameofchannel +->topic +->key +->hastopic haskey and creationtime : if created . + +->victor of clients +->vicotr of invited users +->victor of operators +//tpic seter . +//tpic time . + + + + +this if for testing this how the commande behav : /connect liberachat + + + + +////remember this when you connect to irssi you need to prompte the client to put a password + + +//remmember the username have 4 parameter check rfc + + +after seting the data , password user , nick ---> responce 001, 002, 003, 004 + + +and make sure the irssi client need all the responce to recognized you as a server be awake + + + +rmreconns + +window close \ No newline at end of file