[[project @ 2002-08-08 15:21:08 by unknown_lamer] unknown_lamer**20020808152108 Fixed a bug in String, and added a new class, DCCManager, for managing DCC Connections (ugh, it seems a bit kludgey, but I am working on some big changes to how the bot works right now...). Probably some other changes I forgot about. ] { addfile ./source/DCCManager.C addfile ./source/DCCManager.H hunk ./ChangeLog 1 +2002-08-08 Clinton Ebadi + + * source/String.C (String): The std::string copy constructor now + extracts the c_str of the std::string and then takes the strlen of + that before copying it. This fixes a bug with DCC where if you did + e.g. "!help" the bot would reply with "No TOPIC PRIVMSG FOUND" or + something like that, depending on what the last message was + because Socket will insert a \0 into its semi-static buffer, so + the len of the String will not equal the strlen of its char*. + +2002-08-07 Clinton Ebadi + + * source/DCCPerson.H: Removed destructor (I = idiot) + + * source/DCCConnection.H: DCCManager is now a friend of + DCCConnection (ugh, the bot has way too many friends). + + * source/DCCPerson.H: Added DCC member that returns a const + DCCConnection* (the dcc connection). This isn't saved anywhere + because when a DCCPerson is destroyed, its connection is also + destroyed. + + * source/Bot.H: dccConnections is now a DCCManager + + * source/DCCPerson.H: Added destructor + Added handleInput method + + * source/DCCManager.C: New file + (addConnection): Wrote method, add a DCCConection to the manager + + * source/DCCManager.H: New file + + * source/Interp.C (Startup): Register bot:DCC-chat-send + (Startup): Removed sendDCCChatMessage stuff + + * source/ScriptCommands.C (sendDCCChatMessage): New method: + sendDCCChatMessage (to, message) sends message to to. + + * source/DCCConnection.C (connect): Run DCC_CHAT_BEGIN hook with + one arg: from (user!nick@host). + + * source/DCCParser.C (parseLine): Runs DCC_CHAT_MESSAGE hook with + two args: from (user!nick@host) and line + +2002-08-06 Clinton Ebadi + + * source/Interp.C (Startup): Two new Scheme values: + hooks/dcc/chat-begin and hooks/dcc/chat-message for the + DCC_CHAT_BEGIN and DCC_CHAT_MESSAGE hooks. + + * source/BotInterp.H: Added two new enum values to Hook: + DCC_CHAT_BEGIN and DCC_CHAT_MESSAGE for the DCC chat start and DCC + chat message hooks + hunk ./NEWS 27 +- New hooks: hooks/dcc/chat-begin and + hooks/dcc/chat-message. chat-begin is called when the chat starts + and has one argument: the address (in user!nick@host + format). chat-message has two arguments: from (user!nick@host) and + message, which is the raw message (since there is no real protocol + for DCC). chat-start hooks are matched against the address and + chat-message hooks are matched against the text "ADDRESS MESSAGE" + where ADDRESS is the sender's address and MESSAGE is the message. hunk ./TODO 12 -* Make bot:random use the Guile RNG instead of C RNG (better?) - - definition would be (define (bot:random) (random BIG_NUMBER)) - - Just use max-fixnum from the test scripts for BIG_NUMBER hunk ./TODO 13 - - return an iterator to the hook and let the user kill it? + - return an iterator to the Hook hunk ./TODO 15 + - Scheme could pass Hook objects around and do nifty things hunk ./TODO 21 -* Make it possible to use Scheme functions in the Parser itself +* Finish adding hooks/send hooks hunk ./TODO 24 -* Add hooks for DCC CHAT? +* Add functions to talk to DCC chatters hunk ./TODO 33 -* DCC FILE support +* DCC FILE support (this can be done as a script) hunk ./TODO 40 +* Make it possible to use Scheme functions in the Parser itself +* Complete rewrite ;-) hunk ./bobot++.info 180 -hooks and tiny fugue (a MUD bot) hooks. The basic idea of a hook if -that you match a text against regular expression and call a function if -text in a message matches that regex. The different types of hooks -provided by Bobot++ correspond to the different classes of messages -that Bobot++ can recieve. A Hook also has several properties, including -its priority and whether or not it is a fallthrough hook. Higher -priority hooks are executed before lower priority hooks and fallthrough -hooks are executed before non-fallthrough hooks of the same priority. A -fallthrough hook can match and processing of hooks will continue; as -soon as the first non-fallthrough hooks matches processing of hooks -stops. +and tiny fugue (a MUD bot) hooks with a little bit of extra stuff added +in. The basic idea of a hook if that you match a text against regular +expression and call a function if text in a message matches that regex. +The different types of hooks provided by Bobot++ correspond to the +different classes of messages that Bobot++ can recieve. A Hook also has +several properties, including its priority and whether or not it is a +fallthrough hook. Higher priority hooks are executed before lower +priority hooks and fallthrough hooks are executed before +non-fallthrough hooks of the same priority. A fallthrough hook can +match and processing of hooks will continue; as soon as the first +non-fallthrough hooks matches processing of hooks stops. hunk ./bobot++.info 514 -Node: Creating a Hook6790 -Node: Hook Types7929 -Node: Scheme User Levels10869 -Node: Sending Messages11998 -Node: High Level Message Functions12595 -Node: Low Level Message Functions12809 -Node: Misc Scripting Stuff13562 -Node: Concept Index13981 -Node: Function Index14163 -Node: Variable Index14424 +Node: Creating a Hook6826 +Node: Hook Types7965 +Node: Scheme User Levels10905 +Node: Sending Messages12034 +Node: High Level Message Functions12631 +Node: Low Level Message Functions12845 +Node: Misc Scripting Stuff13598 +Node: Concept Index14017 +Node: Function Index14199 +Node: Variable Index14460 hunk ./source/Bot.C 35 +#include "DCCManager.H" hunk ./source/Bot.C 97 + dccConnections = new DCCManager (); hunk ./source/Bot.C 147 - DCCConnection *d; - while (dccConnections.size() != 0) { - d = *dccConnections.begin(); - dccConnections.erase(dccConnections.begin()); - delete d; - } - + delete dccConnections; hunk ./source/Bot.C 297 + dccConnections->checkStale (); hunk ./source/Bot.C 323 - for (std::list::iterator it = dccConnections.begin(); - it != dccConnections.end(); ++it) { - int s = (*it)->getFileDescriptor(); + DCC_MAP* dccmap = dccConnections->MAP (); + for (DCC_MAP::iterator it = dccmap->begin (); + it != dccmap->end(); ++it) { + int s = it->second->DCC()->getFileDescriptor(); hunk ./source/Bot.C 353 - std::list::iterator it = dccConnections.begin(); - std::list::iterator it2; +// std::list::iterator it = dccConnections.begin(); +// std::list::iterator it2; hunk ./source/Bot.C 356 - while (it != dccConnections.end()) { - it2 = it; - ++it; -#ifdef _HPUX_SOURCE - if (rd & (*it2)->getFileDescriptor()) { -#else - if (FD_ISSET((*it2)->getFileDescriptor(), &rd)) { -#endif - if ((*it2)->handleInput()) { - delete *it2; - dccConnections.erase(it2); - } - } - } +// while (it != dccConnections.end()) { +// it2 = it; +// ++it; +// #ifdef _HPUX_SOURCE +// if (rd & (*it2)->getFileDescriptor()) { +// #else +// if (FD_ISSET((*it2)->getFileDescriptor(), &rd)) { +// #endif +// if ((*it2)->handleInput()) { +// delete *it2; +// dccConnections.erase(it2); +// } +// } +// } +// } + dccConnections->checkInput (rd); hunk ./source/Bot.C 417 - std::list::iterator it2; +// std::list::iterator it2; hunk ./source/Bot.C 419 - for (std::list::iterator it = dccConnections.begin(); - it != dccConnections.end(); ) { - it2 = it; - ++it; - if ((*it2)->autoRemove && currentTime >= (std::time_t)((*it2)->lastSpoken + Bot::DCC_DELAY)) { - delete *it2; - dccConnections.erase(it2); - } - } +// for (std::list::iterator it = dccConnections.begin(); +// it != dccConnections.end(); ) { +// it2 = it; +// ++it; +// if ((*it2)->autoRemove && currentTime >= (std::time_t)((*it2)->lastSpoken + Bot::DCC_DELAY)) { +// delete *it2; +// dccConnections.erase(it2); +// } +// } hunk ./source/Bot.C 534 - dccConnections.push_back(d); + dccConnections->addConnection (d); hunk ./source/Bot.H 56 +class DCCManager; hunk ./source/Bot.H 103 - std::list dccConnections; + DCCManager* dccConnections; hunk ./source/BotInterp.H 68 - SEND_ACTION, SEND_CTCP, SEND_PUBLIC, SEND_MESSAGE + SEND_ACTION, SEND_CTCP, SEND_PUBLIC, SEND_MESSAGE, + // DCC hooks + DCC_CHAT_BEGIN, DCC_CHAT_MESSAGE hunk ./source/DCCConnection.C 20 +#include hunk ./source/DCCConnection.C 25 +#include "Person.H" +#include "BotInterp.H" +#include "Utils.H" hunk ./source/DCCConnection.C 40 + +#ifdef USESCRIPTS + // run hooks/dcc/chat-begin + DCCPerson *tmp = new DCCPerson (this); + bot->botInterp->RunHooks (Hook::DCC_CHAT_BEGIN, + tmp->getAddress (), + scm_list_n (Utils:: + string2SCM (tmp->getAddress ()), + SCM_UNDEFINED)); + delete tmp; +#endif + + hunk ./source/DCCConnection.C 59 - String line = socket.readLine(); + std::string line = socket.readLine(); hunk ./source/DCCConnection.H 49 + friend class DCCManager; hunk ./source/DCCManager.C 1 +// DCCManager.H -*- C++ -*- +// Copyright (c) 2002 Clinton Ebadi + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +#include "DCCManager.H" + +void +DCCManager::addConnection (DCCConnection *cnx) +{ + DCCPerson *person = new DCCPerson (cnx); + String temp = person->getAddress (); + if (dcc_map[temp]) + delete dcc_map[temp]; + dcc_map[person->getAddress ()] = person; +} + +bool +DCCManager::sendMessage (String to, String message) +{ + DCCPerson *person = dcc_map[to]; + if (!person) + return false; + + person->sendNotice (message); + return true; + return false; +} + +// checks for stale connections and removes them +void +DCCManager::checkStale () +{ + DCC_MAP::iterator it, it2; + DCCConnection const* temp_cnx; + + for (it = dcc_map.begin (),it2 = dcc_map.end (); + it != it2; ++it) + { + temp_cnx = it->second->DCC (); + if (temp_cnx->autoRemove && std::time (0) >= + (std::time_t)(temp_cnx->lastSpoken + Bot::DCC_DELAY)) + { + delete it->second; + dcc_map.erase (it); + } + } +} + +void +#ifdef _HPUX_SOURCE +DCCManager::checkInput (int rd) +#else +DCCManager::checkInput (fd_set rd) +#endif +{ + + DCC_MAP::iterator it = dcc_map.begin(); + DCC_MAP::iterator it2; + + while (it != dcc_map.end ()) + { + it2 = it; + ++it; +#ifdef _HPUX_SOURCE + if (rd & it2->second->DCC()->getFileDescriptor()) +#else + if (FD_ISSET(it2->second->DCC()->getFileDescriptor(), &rd)) +#endif + { + if (it2->second->handleInput()) + { + // I am an evil, evil person + delete const_cast (it2->second->DCC()); + delete it2->second; + dcc_map.erase(it2); + } + } + } +} + +DCCManager::~DCCManager () +{ + DCC_MAP::iterator it, it2; + it = dcc_map.begin (); + it2 = dcc_map.end(); + + for (; it != it2; ++it) + { + // I am an evil, evil person + delete const_cast (it->second->DCC()); + delete it->second; + } +} hunk ./source/DCCManager.H 1 +// DCCManager.H -*- C++ -*- +// Copyright (c) 2002 Clinton Ebadi + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +#ifndef DCC_MANAGER_H +#define DCC_MANAGER_H + +#include +#include +#include "DCCPerson.H" +#include "DCCConnection.H" +#include "String.H" + +typedef std::map > DCC_MAP; + +// Manages all active DCC connections and allows you to send a message +// to each one using the string representation of the user's address +class DCCManager +{ + DCC_MAP dcc_map; +public: + void addConnection (DCCConnection*); + bool sendMessage (String, String); + void checkStale (); +#ifdef _HPUX_SOURCE + void checkInput (int); +#else + void checkInput (fd_set); +#endif + DCC_MAP* MAP () { return &dcc_map; }; + ~DCCManager (); +}; + +#endif hunk ./source/DCCParser.C 19 +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + hunk ./source/DCCParser.C 25 -#include "Macros.H" hunk ./source/DCCParser.C 26 -#include "Bot.H" +#include "BotInterp.H" +#include "Utils.H" hunk ./source/DCCParser.C 33 +#ifdef USESCRIPTS + // Call hooks/dcc/chat-message hook functions + cnx->bot->botInterp->RunHooks (Hook::DCC_CHAT_MESSAGE, + from->getAddress () + " " + line, + scm_list_n (Utils:: + string2SCM (from->getAddress ()), + Utils::string2SCM (line), + SCM_UNDEFINED)); +#endif hunk ./source/DCCPerson.C 47 +bool +DCCPerson::handleInput () +{ + return dcc->handleInput (); +} + hunk ./source/DCCPerson.H 33 - String getNick() const; - String getAddress() const; + // String getNick() const; + // String getAddress() const; hunk ./source/DCCPerson.H 37 + bool handleInput (); + const DCCConnection* DCC () const { return dcc; }; hunk ./source/Interp.C 81 - // scm_c_define ("hooks/names", scm_long2num(Hook::NAMES)); hunk ./source/Interp.C 87 + // send hooks hunk ./source/Interp.C 92 - + // dcc hooks + scm_c_define ("hooks/dcc/chat-begin", + scm_long2num (Hook::DCC_CHAT_BEGIN)); + scm_c_define ("hooks/dcc/chat-message", + scm_long2num (Hook::DCC_CHAT_MESSAGE)); hunk ./source/Makefile.am 11 + DCCManager.H \ + DCCManager.C \ hunk ./source/Makefile.in 87 + DCCManager.H \ + DCCManager.C \ hunk ./source/Makefile.in 162 - DCCParser.$(OBJEXT) DCCPerson.$(OBJEXT) Interp.$(OBJEXT) \ - Main.$(OBJEXT) Mask.$(OBJEXT) Parser.$(OBJEXT) Person.$(OBJEXT) \ - Queue.$(OBJEXT) ScriptCommands.$(OBJEXT) Server.$(OBJEXT) \ - ServerConnection.$(OBJEXT) ServerList.$(OBJEXT) \ - ServerQueue.$(OBJEXT) ServerQueueItem.$(OBJEXT) \ - ShitEntry.$(OBJEXT) ShitList.$(OBJEXT) Socket.$(OBJEXT) \ - String.$(OBJEXT) StringTokenizer.$(OBJEXT) TodoList.$(OBJEXT) \ - User.$(OBJEXT) UserCommands.$(OBJEXT) UserList.$(OBJEXT) \ - Utils.$(OBJEXT) + DCCManager.$(OBJEXT) DCCParser.$(OBJEXT) DCCPerson.$(OBJEXT) \ + Interp.$(OBJEXT) Main.$(OBJEXT) Mask.$(OBJEXT) Parser.$(OBJEXT) \ + Person.$(OBJEXT) Queue.$(OBJEXT) ScriptCommands.$(OBJEXT) \ + Server.$(OBJEXT) ServerConnection.$(OBJEXT) \ + ServerList.$(OBJEXT) ServerQueue.$(OBJEXT) \ + ServerQueueItem.$(OBJEXT) ShitEntry.$(OBJEXT) \ + ShitList.$(OBJEXT) Socket.$(OBJEXT) String.$(OBJEXT) \ + StringTokenizer.$(OBJEXT) TodoList.$(OBJEXT) User.$(OBJEXT) \ + UserCommands.$(OBJEXT) UserList.$(OBJEXT) Utils.$(OBJEXT) hunk ./source/Makefile.in 185 -@AMDEP_TRUE@ $(DEPDIR)/DCCParser.Po $(DEPDIR)/DCCPerson.Po \ -@AMDEP_TRUE@ $(DEPDIR)/Interp.Po $(DEPDIR)/Main.Po \ -@AMDEP_TRUE@ $(DEPDIR)/Mask.Po $(DEPDIR)/Parser.Po \ -@AMDEP_TRUE@ $(DEPDIR)/Person.Po $(DEPDIR)/Queue.Po \ -@AMDEP_TRUE@ $(DEPDIR)/ScriptCommands.Po $(DEPDIR)/Server.Po \ -@AMDEP_TRUE@ $(DEPDIR)/ServerConnection.Po \ +@AMDEP_TRUE@ $(DEPDIR)/DCCManager.Po $(DEPDIR)/DCCParser.Po \ +@AMDEP_TRUE@ $(DEPDIR)/DCCPerson.Po $(DEPDIR)/Interp.Po \ +@AMDEP_TRUE@ $(DEPDIR)/Main.Po $(DEPDIR)/Mask.Po \ +@AMDEP_TRUE@ $(DEPDIR)/Parser.Po $(DEPDIR)/Person.Po \ +@AMDEP_TRUE@ $(DEPDIR)/Queue.Po $(DEPDIR)/ScriptCommands.Po \ +@AMDEP_TRUE@ $(DEPDIR)/Server.Po $(DEPDIR)/ServerConnection.Po \ hunk ./source/Makefile.in 265 +@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/DCCManager.Po@am__quote@ hunk ./source/ScriptCommands.C 31 +#include "DCCPerson.H" hunk ./source/ScriptCommands.C 605 - - hunk ./source/ScriptCommands.H 105 - hunk ./source/String.C 42 - len = s.length (); + // We do this instead of just s.length () because there might be a + // \0 in the string before the end (e.g. this is a message from the + // Socket's buffer). + const char* temp_str = s.c_str (); + len = strlen (temp_str); hunk ./source/String.C 48 - std::strcpy (p->s, s.c_str ()); + std::strcpy (p->s, temp_str); hunk ./source/UserCommands.C 45 +#include "DCCManager.H" hunk ./source/UserCommands.C 408 - for (std::list::iterator it = - cnx->bot->dccConnections.begin(); - it != cnx->bot->dccConnections.end(); + for (DCC_MAP::iterator it = + cnx->bot->dccConnections->MAP()->begin (); + it != cnx->bot->dccConnections->MAP()->end(); hunk ./source/UserCommands.C 412 - from->sendNotice((*it)->nuh.pad(32) + " " + + from->sendNotice(String(it->second->DCC()->nuh).pad(32) + " " + hunk ./source/UserCommands.C 414 - (*it)->lastSpoken))); + it->second->DCC()->lastSpoken))); }