diff options
54 files changed, 1069 insertions, 1529 deletions
diff --git a/include/base.h b/include/base.h index 6bcf76817..ab52545f9 100644 --- a/include/base.h +++ b/include/base.h @@ -18,9 +18,6 @@ #include <deque> #include <string> -/** A private data store for an Extensible class */ -typedef std::map<std::string,char*> ExtensibleStore; - /** The base class for all inspircd classes. * Wherever possible, all classes you create should inherit from this, * giving them the ability to be passed to various core functions @@ -29,126 +26,11 @@ typedef std::map<std::string,char*> ExtensibleStore; class CoreExport classbase { public: - /** Constructor. - * Sets the object's time - */ classbase(); - /** Destructor. - * Does sweet FA. - */ virtual ~classbase() { } }; -/** class Extensible is the parent class of many classes such as User and Channel. - * class Extensible implements a system which allows modules to 'extend' the class by attaching data within - * a map associated with the object. In this way modules can store their own custom information within user - * objects, channel objects and server objects, without breaking other modules (this is more sensible than using - * a flags variable, and each module defining bits within the flag as 'theirs' as it is less prone to conflict and - * supports arbitary data storage). - */ -class CoreExport Extensible : public classbase -{ - /** Private data store. - * Holds all extensible metadata for the class. - */ - ExtensibleStore Extension_Items; - -public: - - /** Extend an Extensible class. - * - * @param key The key parameter is an arbitary string which identifies the extension data - * @param p This parameter is a pointer to any data you wish to associate with the object - * - * You must provide a key to store the data as via the parameter 'key' and store the data - * in the templated parameter 'p'. - * The data will be inserted into the map. If the data already exists, you may not insert it - * twice, Extensible::Extend will return false in this case. - * - * @return Returns true on success, false if otherwise - */ - template<typename T> bool Extend(const std::string &key, T* p) - { - /* This will only add an item if it doesnt already exist, - * the return value is a std::pair of an iterator to the - * element, and a bool saying if it was actually inserted. - */ - return this->Extension_Items.insert(std::make_pair(key, (char*)p)).second; - } - - /** Extend an Extensible class. - * - * @param key The key parameter is an arbitary string which identifies the extension data - * - * You must provide a key to store the data as via the parameter 'key', this single-parameter - * version takes no 'data' parameter, this is used purely for boolean values. - * The key will be inserted into the map with a NULL 'data' pointer. If the key already exists - * then you may not insert it twice, Extensible::Extend will return false in this case. - * - * @return Returns true on success, false if otherwise - */ - bool Extend(const std::string &key) - { - /* This will only add an item if it doesnt already exist, - * the return value is a std::pair of an iterator to the - * element, and a bool saying if it was actually inserted. - */ - return this->Extension_Items.insert(std::make_pair(key, (char*)NULL)).second; - } - - /** Shrink an Extensible class. - * - * @param key The key parameter is an arbitary string which identifies the extension data - * - * You must provide a key name. The given key name will be removed from the classes data. If - * you provide a nonexistent key (case is important) then the function will return false. - * @return Returns true on success. - */ - bool Shrink(const std::string &key); - - /** Get an extension item. - * - * @param key The key parameter is an arbitary string which identifies the extension data - * @param p If you provide a non-existent key, this value will be NULL. Otherwise a pointer to the item you requested will be placed in this templated parameter. - * @return Returns true if the item was found and false if it was nor, regardless of wether 'p' is NULL. This allows you to store NULL values in Extensible. - */ - template<typename T> bool GetExt(const std::string &key, T* &p) - { - ExtensibleStore::iterator iter = this->Extension_Items.find(key); /* Find the item */ - if(iter != this->Extension_Items.end()) - { - p = (T*)iter->second; /* Item found */ - return true; - } - else - { - p = NULL; /* Item not found */ - return false; - } - } - - /** Get an extension item. - * - * @param key The key parameter is an arbitary string which identifies the extension data - * @return Returns true if the item was found and false if it was not. - * - * This single-parameter version only checks if the key exists, it does nothing with - * the 'data' field and is probably only useful in conjunction with the single-parameter - * version of Extend(). - */ - bool GetExt(const std::string &key) - { - return (this->Extension_Items.find(key) != this->Extension_Items.end()); - } - - /** Get a list of all extension items names. - * @param list A deque of strings to receive the list - * @return This function writes a list of all extension items stored in this object by name into the given deque and returns void. - */ - void GetExtList(std::deque<std::string> &list); -}; - /** BoolSet is a utility class designed to hold eight bools in a bitmask. * Use BoolSet::Set and BoolSet::Get to set and get bools in the bitmask, * and Unset and Invert for special operations upon them. diff --git a/include/extensible.h b/include/extensible.h new file mode 100644 index 000000000..0a33470b5 --- /dev/null +++ b/include/extensible.h @@ -0,0 +1,150 @@ +class Extensible; +class Module; + +/** Class represnting an extension of some object + */ +class CoreExport ExtensionItem +{ + public: + const std::string key; + Module* const owner; + ExtensionItem(const std::string& key, Module* owner); + /** Serialize this item into a string */ + virtual std::string serialize(Module* requestor, const Extensible* container, void* item) = 0; + /** Convert the string form back into an item */ + virtual void unserialize(Module* requestor, Extensible* container, const std::string& value) = 0; + /** Free the item */ + virtual void free(void* item) = 0; + + protected: + /** Get the item from the internal map */ + void* get_raw(const Extensible* container); + /** Set the item in the internal map; returns old value */ + void* set_raw(Extensible* container, void* value); + /** Remove the item from the internal map; returns old value */ + void* unset_raw(Extensible* container); +}; + +/** A private data store for an Extensible class */ +typedef std::map<std::string,void*> ExtensibleStore; + +/** class Extensible is the parent class of many classes such as User and Channel. + * class Extensible implements a system which allows modules to 'extend' the class by attaching data within + * a map associated with the object. In this way modules can store their own custom information within user + * objects, channel objects and server objects, without breaking other modules (this is more sensible than using + * a flags variable, and each module defining bits within the flag as 'theirs' as it is less prone to conflict and + * supports arbitary data storage). + */ +class CoreExport Extensible : public classbase +{ + /** Private data store. + * Holds all extensible metadata for the class. + */ + ExtensibleStore extensions; + typedef std::map<std::string, ExtensionItem*> ExtensibleTypes; + static ExtensibleTypes extension_types; + public: + /** + * Get the extension items for iteraton (i.e. for metadata sync during netburst) + */ + inline const ExtensibleStore& GetExtList() const { return extensions; } + static inline const ExtensibleTypes& GetTypeList() { return extension_types; } + static inline ExtensionItem* GetItem(const std::string& name) + { + ExtensibleTypes::iterator i = extension_types.find(name); + if (i == extension_types.end()) + return NULL; + return i->second; + } + + virtual ~Extensible(); + + static bool Register(ExtensionItem* item); + static void UnRegister(Module* module); + + // Friend access for the protected getter/setter + friend class ExtensionItem; +}; + +/** Base class for items that are NOT synchronized between servers */ +class CoreExport LocalExtItem : public ExtensionItem +{ + public: + LocalExtItem(const std::string& key, Module* owner); + // this is deliberately NOT virtual; don't subclass LocalExtItem if you want to sync data! + std::string serialize(Module* requestor, const Extensible* container, void* item); + void unserialize(Module* requestor, Extensible* container, const std::string& value); + virtual void free(void* item) = 0; +}; + +template<typename T> +class CoreExport SimpleExtItem : public LocalExtItem +{ + public: + SimpleExtItem(const std::string& Key, Module* parent) : LocalExtItem(Key, parent) + { + } + + inline T* get(const Extensible* container) + { + return static_cast<T*>(get_raw(container)); + } + + inline T* getNew(Extensible* container) + { + T* ptr = get(container); + if (!ptr) + { + ptr = new T; + set_raw(container, ptr); + } + return ptr; + } + + inline void set(Extensible* container, const T& value) + { + T* ptr = new T(value); + T* old = static_cast<T*>(set_raw(container, ptr)); + delete old; + } + + inline void set(Extensible* container, T* value) + { + T* old = static_cast<T*>(set_raw(container, value)); + delete old; + } + + inline void unset(Extensible* container) + { + T* old = static_cast<T*>(unset_raw(container)); + delete old; + } + + virtual void free(void* item) + { + delete static_cast<T*>(item); + } +}; + +typedef SimpleExtItem<std::string> LocalStringExt; + +class CoreExport LocalIntExt : public LocalExtItem +{ + public: + LocalIntExt(const std::string& key, Module* owner); + intptr_t get(const Extensible* container); + intptr_t set(Extensible* container, intptr_t value); + void free(void* item); +}; + +class CoreExport StringExtItem : public ExtensionItem +{ + public: + StringExtItem(const std::string& key, Module* owner); + std::string* get(const Extensible* container); + std::string serialize(Module* requestor, const Extensible* container, void* item); + void unserialize(Module* requestor, Extensible* container, const std::string& value); + void set(Extensible* container, const std::string& value); + void unset(Extensible* container); + void free(void* item); +}; diff --git a/include/inspircd.h b/include/inspircd.h index ae46569a0..a7eed47ff 100644 --- a/include/inspircd.h +++ b/include/inspircd.h @@ -75,6 +75,7 @@ typedef std::multimap< std::string, KeyValList > ConfigDataHash; #include "inspircd_config.h" #include "inspircd_version.h" +#include "extensible.h" #include "numerics.h" #include "uid.h" #include "users.h" diff --git a/include/modules.h b/include/modules.h index 3f779fe80..9e9686ad2 100644 --- a/include/modules.h +++ b/include/modules.h @@ -442,11 +442,10 @@ class ConfigReader; */ class CoreExport Module : public Extensible { - protected: + public: /** Creator/owner pointer */ InspIRCd* ServerInstance; - public: /** File that this module was loaded from */ std::string ModuleSourceFile; diff --git a/include/u_listmode.h b/include/u_listmode.h index 773ca421f..9d9b5f836 100644 --- a/include/u_listmode.h +++ b/include/u_listmode.h @@ -107,9 +107,6 @@ class ListModeRequest : public Request class ListModeBase : public ModeHandler { protected: - /** Storage key - */ - std::string infokey; /** Numeric to use when outputting the list */ unsigned int listnumeric; @@ -131,6 +128,10 @@ class ListModeBase : public ModeHandler limitlist chanlimits; public: + /** Storage key + */ + SimpleExtItem<modelist> extItem; + /** Constructor. * @param Instance The creator of this class * @param modechar Mode character @@ -141,18 +142,19 @@ class ListModeBase : public ModeHandler * @param ctag Configuration tag to get limits from */ ListModeBase(InspIRCd* Instance, Module* Creator, char modechar, const std::string &eolstr, unsigned int lnum, unsigned int eolnum, bool autotidy, const std::string &ctag = "banlist") - : ModeHandler(Instance, Creator, modechar, 1, 1, true, MODETYPE_CHANNEL, false), listnumeric(lnum), endoflistnumeric(eolnum), endofliststring(eolstr), tidy(autotidy), configtag(ctag) + : ModeHandler(Instance, Creator, modechar, 1, 1, true, MODETYPE_CHANNEL, false), + listnumeric(lnum), endoflistnumeric(eolnum), endofliststring(eolstr), tidy(autotidy), + configtag(ctag), extItem("listbase_mode_" + std::string(1, mode) + "_list", Creator) { this->DoRehash(); - infokey = "listbase_mode_" + std::string(1, mode) + "_list"; + Extensible::Register(&extItem); } /** See mode.h */ std::pair<bool,std::string> ModeSet(User*, User*, Channel* channel, const std::string ¶meter) { - modelist* el; - channel->GetExt(infokey, el); + modelist* el = extItem.get(channel); if (el) { for (modelist::iterator it = el->begin(); it != el->end(); it++) @@ -172,8 +174,7 @@ class ListModeBase : public ModeHandler */ virtual void DisplayList(User* user, Channel* channel) { - modelist* el; - channel->GetExt(infokey, el); + modelist* el = extItem.get(channel); if (el) { for (modelist::reverse_iterator it = el->rbegin(); it != el->rend(); ++it) @@ -195,8 +196,7 @@ class ListModeBase : public ModeHandler */ virtual void RemoveMode(Channel* channel, irc::modestacker* stack) { - modelist* el; - channel->GetExt(infokey, el); + modelist* el = extItem.get(channel); if (el) { irc::modestacker modestack(ServerInstance, false); @@ -271,8 +271,7 @@ class ListModeBase : public ModeHandler virtual ModeAction OnModeChange(User* source, User*, Channel* channel, std::string ¶meter, bool adding) { // Try and grab the list - modelist* el; - channel->GetExt(infokey, el); + modelist* el = extItem.get(channel); if (adding) { @@ -281,7 +280,7 @@ class ListModeBase : public ModeHandler { // Make one el = new modelist; - channel->Extend(infokey, el); + extItem.set(channel, el); } // Clean the mask up @@ -362,8 +361,7 @@ class ListModeBase : public ModeHandler el->erase(it); if (el->size() == 0) { - channel->Shrink(infokey); - delete el; + extItem.unset(channel); } return MODEACTION_ALLOW; } @@ -384,29 +382,6 @@ class ListModeBase : public ModeHandler return MODEACTION_DENY; } - /** Get Extensible key for this mode - */ - virtual std::string& GetInfoKey() - { - return infokey; - } - - /** Handle channel deletion. - * See modules.h. - * @param chan Channel being deleted - */ - virtual void DoChannelDelete(Channel* chan) - { - modelist* mlist; - chan->GetExt(infokey, mlist); - - if (mlist) - { - chan->Shrink(infokey); - delete mlist; - } - } - /** Syncronize channel item list with another server. * See modules.h * @param chan Channel to syncronize @@ -415,8 +390,7 @@ class ListModeBase : public ModeHandler */ virtual void DoSyncChannel(Channel* chan, Module* proto, void* opaque) { - modelist* mlist; - chan->GetExt(infokey, mlist); + modelist* mlist = extItem.get(chan); irc::modestacker modestack(ServerInstance, true); std::vector<std::string> stackresult; std::vector<TranslateType> types; @@ -493,8 +467,7 @@ class ListModeBase : public ModeHandler ListModeRequest* LM = (ListModeRequest*)request; if (strcmp("LM_CHECKLIST", request->GetId()) == 0) { - modelist* mlist; - LM->chan->GetExt(GetInfoKey(), mlist); + modelist* mlist = extItem.get(LM->chan); if (mlist) { std::string mask = LM->user->nick + "!" + LM->user->ident + "@" + LM->user->GetIPString(); @@ -508,8 +481,7 @@ class ListModeBase : public ModeHandler } else if (strcmp("LM_CHECKLIST_EX", request->GetId()) == 0) { - modelist* mlist; - LM->chan->GetExt(GetInfoKey(), mlist); + modelist* mlist = extItem.get(LM->chan); if (mlist) { diff --git a/include/users.h b/include/users.h index 5338deb4c..a6c36b7fd 100644 --- a/include/users.h +++ b/include/users.h @@ -274,6 +274,9 @@ class CoreExport User : public EventHandler */ InspIRCd* ServerInstance; + static LocalIntExt NICKForced; + static LocalStringExt OperQuit; + /** Contains a pointer to the connect class a user is on from - this will be NULL for remote connections. * The pointer is guarenteed to *always* be valid. :) */ @@ -977,7 +980,4 @@ class CoreExport UserResolver : public Resolver void OnError(ResolverError e, const std::string &errormessage); }; -/* Configuration callbacks */ -//class ServerConfig; - #endif diff --git a/src/base.cpp b/src/base.cpp index 7e0cf482a..4d0c17077 100644 --- a/src/base.cpp +++ b/src/base.cpp @@ -20,28 +20,12 @@ const int bitfields[] = {1,2,4,8,16,32,64,128}; const int inverted_bitfields[] = {~1,~2,~4,~8,~16,~32,~64,~128}; +std::map<std::string, ExtensionItem*> Extensible::extension_types; classbase::classbase() { } -bool Extensible::Shrink(const std::string &key) -{ - /* map::size_type map::erase( const key_type& key ); - * returns the number of elements removed, std::map - * is single-associative so this should only be 0 or 1 - */ - return this->Extension_Items.erase(key); -} - -void Extensible::GetExtList(std::deque<std::string> &list) -{ - for (ExtensibleStore::iterator u = Extension_Items.begin(); u != Extension_Items.end(); u++) - { - list.push_back(u->first); - } -} - void BoolSet::Set(int number) { this->bits |= bitfields[number]; @@ -94,3 +78,140 @@ bool BoolSet::operator=(BoolSet other) this->bits = other.bits; return true; } + +ExtensionItem::ExtensionItem(const std::string& Key, Module* mod) : key(Key), owner(mod) +{ +} + +void* ExtensionItem::get_raw(const Extensible* container) +{ + ExtensibleStore::const_iterator i = container->extensions.find(key); + if (i == container->extensions.end()) + return NULL; + return i->second; +} + +void* ExtensionItem::set_raw(Extensible* container, void* value) +{ + std::pair<ExtensibleStore::iterator,bool> rv = + container->extensions.insert(std::make_pair(key, value)); + if (rv.second) + { + return NULL; + } + else + { + void* old = rv.first->second; + rv.first->second = value; + return old; + } +} + +void* ExtensionItem::unset_raw(Extensible* container) +{ + ExtensibleStore::iterator i = container->extensions.find(key); + if (i == container->extensions.end()) + return NULL; + void* rv = i->second; + container->extensions.erase(i); + return rv; +} + +bool Extensible::Register(ExtensionItem* item) +{ + return Extensible::extension_types.insert(std::make_pair(item->key, item)).second; +} + +void Extensible::UnRegister(Module* module) +{ + ExtensibleTypes::iterator i = extension_types.begin(); + while (i != extension_types.end()) + { + ExtensibleTypes::iterator c = i++; + if (c->second->owner == module) + extension_types.erase(c); + } +} + +Extensible::~Extensible() +{ + for(ExtensibleStore::iterator i = extensions.begin(); i != extensions.end(); ++i) + { + ExtensionItem* type = extension_types[i->first]; + if (type) + type->free(i->second); + } +} + +LocalExtItem::LocalExtItem(const std::string& Key, Module* mod) : ExtensionItem(Key, mod) +{ +} + +std::string LocalExtItem::serialize(Module* requestor, const Extensible* container, void* item) +{ + return ""; +} + +void LocalExtItem::unserialize(Module* requestor, Extensible* container, const std::string& value) +{ +} + +LocalIntExt::LocalIntExt(const std::string& Key, Module* mod) : LocalExtItem(Key, mod) +{ +} + +intptr_t LocalIntExt::get(const Extensible* container) +{ + return reinterpret_cast<intptr_t>(get_raw(container)); +} + +intptr_t LocalIntExt::set(Extensible* container, intptr_t value) +{ + if (value) + return reinterpret_cast<intptr_t>(set_raw(container, reinterpret_cast<void*>(value))); + else + return reinterpret_cast<intptr_t>(unset_raw(container)); +} + +void LocalIntExt::free(void*) +{ +} + +StringExtItem::StringExtItem(const std::string& Key, Module* mod) : ExtensionItem(Key, mod) +{ +} + +std::string* StringExtItem::get(const Extensible* container) +{ + return static_cast<std::string*>(get_raw(container)); +} + +std::string StringExtItem::serialize(Module* requestor, const Extensible* container, void* item) +{ + return item ? *static_cast<std::string*>(item) : ""; +} + +void StringExtItem::unserialize(Module* requestor, Extensible* container, const std::string& value) +{ + if (value.empty()) + unset(container); + else + set(container, value); +} + +void StringExtItem::set(Extensible* container, const std::string& value) +{ + void* old = set_raw(container, new std::string(value)); + delete static_cast<std::string*>(old); +} + +void StringExtItem::unset(Extensible* container) +{ + void* old = unset_raw(container); + delete static_cast<std::string*>(old); +} + +void StringExtItem::free(void* item) +{ + delete static_cast<std::string*>(item); +} diff --git a/src/commands/cmd_nick.cpp b/src/commands/cmd_nick.cpp index 3851b36e6..6a181bda0 100644 --- a/src/commands/cmd_nick.cpp +++ b/src/commands/cmd_nick.cpp @@ -75,16 +75,16 @@ CmdResult CommandNick::Handle (const std::vector<std::string>& parameters, User if (((!ServerInstance->IsNick(parameters[0].c_str(), ServerInstance->Config->Limits.NickMax))) && (IS_LOCAL(user))) { - if (!user->GetExt("NICKForced")) + if (!User::NICKForced.get(user)) { if (parameters[0] == "0") { // Special case, Fake a /nick UIDHERE. Useful for evading "ERR: NICK IN USE" on connect etc. std::vector<std::string> p2; p2.push_back(user->uuid); - user->Extend("NICKForced"); + User::NICKForced.set(user, 1); this->Handle(p2, user); - user->Shrink("NICKForced"); + User::NICKForced.set(user, 0); return CMD_SUCCESS; } diff --git a/src/commands/cmd_quit.cpp b/src/commands/cmd_quit.cpp index 968374dec..46c728881 100644 --- a/src/commands/cmd_quit.cpp +++ b/src/commands/cmd_quit.cpp @@ -63,11 +63,10 @@ CmdResult CommandQuit::Handle (const std::vector<std::string>& parameters, User else quitmsg = parameters.size() ? parameters[0] : "Client exited"; - std::string* operquit; - if (user->GetExt("operquit", operquit)) + std::string* operquit = User::OperQuit.get(user); + if (operquit) { ServerInstance->Users->QuitUser(user, quitmsg, operquit->c_str()); - delete operquit; } else { diff --git a/src/commands/cmd_who.cpp b/src/commands/cmd_who.cpp index 61b5a0f60..329c0a2d5 100644 --- a/src/commands/cmd_who.cpp +++ b/src/commands/cmd_who.cpp @@ -78,7 +78,6 @@ bool CommandWho::whomatch(User* cuser, User* user, const char* matchtext) { bool match = false; bool positive = false; - char* dummy = NULL; if (user->registered != REG_ALL) return false; @@ -115,7 +114,7 @@ bool CommandWho::whomatch(User* cuser, User* user, const char* matchtext) * -- w00t */ if (opt_metadata) - match = user->GetExt(matchtext, dummy); + match = user->GetExtList().find(matchtext) != user->GetExtList().end(); else if (opt_realname) match = InspIRCd::Match(user->fullname, matchtext); else if (opt_showrealhost) diff --git a/src/dns.cpp b/src/dns.cpp index b2dbf40a7..94a01e64c 100644 --- a/src/dns.cpp +++ b/src/dns.cpp @@ -34,7 +34,6 @@ looks like this, walks like this or tastes like this. #include "inspircd_se_config.h" #endif -#include "dns.h" #include "inspircd.h" #include "socketengine.h" #include "configreader.h" diff --git a/src/inspsocket.cpp b/src/inspsocket.cpp index 1ec32742e..0350858e7 100644 --- a/src/inspsocket.cpp +++ b/src/inspsocket.cpp @@ -11,12 +11,10 @@ * --------------------------------------------------- */ -/* $Core */ - +#include "inspircd.h" #include "socket.h" #include "inspstring.h" #include "socketengine.h" -#include "inspircd.h" bool BufferedSocket::Readable() { diff --git a/src/modules.cpp b/src/modules.cpp index 59b52b5b1..c7509fad9 100644 --- a/src/modules.cpp +++ b/src/modules.cpp @@ -558,6 +558,7 @@ bool ModuleManager::Unload(const char* filename) this->DetachAll(modfind->second.second); Instance->Parser->RemoveCommands(modfind->second.second); + Extensible::UnRegister(modfind->second.second); delete modfind->second.second; delete modfind->second.first; diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp index f5133a1dc..97a5ebe0e 100644 --- a/src/modules/extra/m_ssl_gnutls.cpp +++ b/src/modules/extra/m_ssl_gnutls.cpp @@ -98,10 +98,11 @@ class ModuleSSLGnuTLS : public Module CommandStartTLS starttls; + GenericCap capHandler; public: ModuleSSLGnuTLS(InspIRCd* Me) - : Module(Me), starttls(Me, this) + : Module(Me), starttls(Me, this), capHandler(this, "tls") { ServerInstance->Modules->PublishInterface("BufferedSocketHook", this); @@ -266,13 +267,6 @@ class ModuleSSLGnuTLS : public Module ServerInstance->Users->QuitUser(user, "SSL module unloading"); user->DelIOHook(); } - if (user->GetExt("ssl_cert")) - { - ssl_cert* tofree; - user->GetExt("ssl_cert", tofree); - delete tofree; - user->Shrink("ssl_cert"); - } } } @@ -339,25 +333,16 @@ class ModuleSSLGnuTLS : public Module { if (static_cast<Extensible*>(ServerInstance->SE->GetRef(ISR->Sock->GetFd())) == static_cast<Extensible*>(ISR->Sock)) { - VerifyCertificate(session, ISR->Sock); return "OK"; } } } } - else if (strcmp("GET_FP", request->GetId()) == 0) + else if (strcmp("GET_CERT", request->GetId()) == 0) { - if (ISR->Sock->GetFd() > -1) - { - issl_session* session = &sessions[ISR->Sock->GetFd()]; - if (session->sess) - { - Extensible* ext = ISR->Sock; - ssl_cert* certinfo; - if (ext->GetExt("ssl_cert",certinfo)) - return certinfo->GetFingerprint().c_str(); - } - } + Module* sslinfo = ServerInstance->Modules->Find("m_sslinfo.so"); + if (sslinfo) + return sslinfo->OnRequest(request); } return NULL; } @@ -413,16 +398,6 @@ class ModuleSSLGnuTLS : public Module return; CloseSession(&sessions[fd]); - - EventHandler* user = ServerInstance->SE->GetRef(fd); - - if ((user) && (user->GetExt("ssl_cert"))) - { - ssl_cert* tofree; - user->GetExt("ssl_cert", tofree); - delete tofree; - user->Shrink("ssl_cert"); - } } virtual int OnRawSocketRead(int fd, char* buffer, unsigned int count, int &readresult) @@ -606,17 +581,13 @@ class ModuleSSLGnuTLS : public Module } else { - // Handshake complete. - // This will do for setting the ssl flag...it could be done earlier if it's needed. But this seems neater. - EventHandler *extendme = ServerInstance->SE->GetRef(fd); - if (extendme) - { - extendme->Extend("ssl"); - } - // Change the seesion state session->status = ISSL_HANDSHAKEN; + EventHandler* user = ServerInstance->SE->GetRef(fd); + + VerifyCertificate(session,user); + // Finish writing, if any left MakePollWrite(fd); @@ -630,7 +601,6 @@ class ModuleSSLGnuTLS : public Module // protocol module has propagated the NICK message. if (user->GetIOHook() == this && (IS_LOCAL(user))) { - ssl_cert* certdata = VerifyCertificate(&sessions[user->GetFd()],user); if (sessions[user->GetFd()].sess) { std::string cipher = gnutls_kx_get_name(gnutls_kx_get(sessions[user->GetFd()].sess)); @@ -638,10 +608,6 @@ class ModuleSSLGnuTLS : public Module cipher.append(gnutls_mac_get_name(gnutls_mac_get(sessions[user->GetFd()].sess))); user->WriteServ("NOTICE %s :*** You are connected using SSL cipher \"%s\"", user->nick.c_str(), cipher.c_str()); } - - ServerInstance->PI->SendMetaData(user, "ssl", "ON"); - if (certdata) - ServerInstance->PI->SendMetaData(user, "ssl_cert", certdata->GetMetaLine().c_str()); } } @@ -676,10 +642,14 @@ class ModuleSSLGnuTLS : public Module session->status = ISSL_NONE; } - ssl_cert* VerifyCertificate(issl_session* session, Extensible* user) + void VerifyCertificate(issl_session* session, Extensible* user) { if (!session->sess || !user) - return NULL; + return; + + Module* sslinfo = ServerInstance->Modules->Find("m_sslinfo.so"); + if (!sslinfo) + return; unsigned int status; const gnutls_datum_t* cert_list; @@ -692,8 +662,6 @@ class ModuleSSLGnuTLS : public Module size_t name_size = sizeof(name); ssl_cert* certinfo = new ssl_cert; - user->Extend("ssl_cert",certinfo); - /* This verification function uses the trusted CAs in the credentials * structure. So you must have installed one or more CA certificates. */ @@ -702,7 +670,7 @@ class ModuleSSLGnuTLS : public Module if (ret < 0) { certinfo->error = std::string(gnutls_strerror(ret)); - return certinfo; + goto info_done; } certinfo->invalid = (status & GNUTLS_CERT_INVALID); @@ -717,14 +685,14 @@ class ModuleSSLGnuTLS : public Module if (gnutls_certificate_type_get(session->sess) != GNUTLS_CRT_X509) { certinfo->error = "No X509 keys sent"; - return certinfo; + goto info_done; } ret = gnutls_x509_crt_init(&cert); if (ret < 0) { certinfo->error = gnutls_strerror(ret); - return certinfo; + goto info_done; } cert_list_size = 0; @@ -732,7 +700,7 @@ class ModuleSSLGnuTLS : public Module if (cert_list == NULL) { certinfo->error = "No certificate was found"; - return certinfo; + goto info_done_dealloc; } /* This is not a real world example, since we only check the first @@ -743,7 +711,7 @@ class ModuleSSLGnuTLS : public Module if (ret < 0) { certinfo->error = gnutls_strerror(ret); - return certinfo; + goto info_done_dealloc; } gnutls_x509_crt_get_dn(cert, name, &name_size); @@ -768,20 +736,15 @@ class ModuleSSLGnuTLS : public Module certinfo->error = "Not activated, or expired certificate"; } +info_done_dealloc: gnutls_x509_crt_deinit(cert); - - return certinfo; +info_done: + BufferedSocketFingerprintSubmission(user, this, sslinfo, certinfo).Send(); } void OnEvent(Event* ev) { - GenericCapHandler(ev, "tls", "tls"); - } - - void Prioritize() - { - Module* server = ServerInstance->Modules->Find("m_spanningtree.so"); - ServerInstance->Modules->SetPriority(this, I_OnPostConnect, PRIORITY_AFTER, &server); + capHandler.HandleEvent(ev); } }; diff --git a/src/modules/extra/m_ssl_openssl.cpp b/src/modules/extra/m_ssl_openssl.cpp index a8043457b..a33cf6bc2 100644 --- a/src/modules/extra/m_ssl_openssl.cpp +++ b/src/modules/extra/m_ssl_openssl.cpp @@ -293,13 +293,6 @@ class ModuleSSLOpenSSL : public Module ServerInstance->Users->QuitUser(user, "SSL module unloading"); user->DelIOHook(); } - if (user->GetExt("ssl_cert", dummy)) - { - ssl_cert* tofree; - user->GetExt("ssl_cert", tofree); - delete tofree; - user->Shrink("ssl_cert"); - } } } @@ -347,23 +340,14 @@ class ModuleSSLOpenSSL : public Module issl_session* session = &sessions[ISR->Sock->GetFd()]; if (session->sess) { - VerifyCertificate(session, (BufferedSocket*)ISR->Sock); return "OK"; } } - else if (strcmp("GET_FP", request->GetId()) == 0) + else if (strcmp("GET_CERT", request->GetId()) == 0) { - if (ISR->Sock->GetFd() > -1) - { - issl_session* session = &sessions[ISR->Sock->GetFd()]; - if (session->sess) - { - Extensible* ext = ISR->Sock; - ssl_cert* certinfo; - if (ext->GetExt("ssl_cert",certinfo)) - return certinfo->GetFingerprint().c_str(); - } - } + Module* sslinfo = ServerInstance->Modules->Find("m_sslinfo.so"); + if (sslinfo) + return sslinfo->OnRequest(request); } return NULL; } @@ -430,16 +414,6 @@ class ModuleSSLOpenSSL : public Module return; CloseSession(&sessions[fd]); - - EventHandler* user = ServerInstance->SE->GetRef(fd); - - if ((user) && (user->GetExt("ssl_cert", dummy))) - { - ssl_cert* tofree; - user->GetExt("ssl_cert", tofree); - delete tofree; - user->Shrink("ssl_cert"); - } } virtual int OnRawSocketRead(int fd, char* buffer, unsigned int count, int &readresult) @@ -691,10 +665,7 @@ class ModuleSSLOpenSSL : public Module // Handshake complete. // This will do for setting the ssl flag...it could be done earlier if it's needed. But this seems neater. EventHandler *u = ServerInstance->SE->GetRef(session->fd); - if (u) - { - u->Extend("ssl"); - } + VerifyCertificate(session, u); session->status = ISSL_OPEN; @@ -717,13 +688,8 @@ class ModuleSSLOpenSSL : public Module // protocol module has propagated the NICK message. if ((user->GetIOHook() == this) && (IS_LOCAL(user))) { - ssl_cert* certdata = VerifyCertificate(&sessions[user->GetFd()], user); if (sessions[user->GetFd()].sess) user->WriteServ("NOTICE %s :*** You are connected using SSL cipher \"%s\"", user->nick.c_str(), SSL_get_cipher(sessions[user->GetFd()].sess)); - - ServerInstance->PI->SendMetaData(user, "ssl", "ON"); - if (certdata) - ServerInstance->PI->SendMetaData(user, "ssl_cert", certdata->GetMetaLine().c_str()); } } @@ -767,10 +733,14 @@ class ModuleSSLOpenSSL : public Module errno = EIO; } - ssl_cert* VerifyCertificate(issl_session* session, Extensible* user) + void VerifyCertificate(issl_session* session, Extensible* user) { if (!session->sess || !user) - return NULL; + return; + + Module* sslinfo = ServerInstance->Modules->Find("m_sslinfo.so"); + if (!sslinfo) + return; X509* cert; ssl_cert* certinfo = new ssl_cert; @@ -778,14 +748,13 @@ class ModuleSSLOpenSSL : public Module unsigned char md[EVP_MAX_MD_SIZE]; const EVP_MD *digest = EVP_md5(); - user->Extend("ssl_cert",certinfo); - cert = SSL_get_peer_certificate((SSL*)session->sess); if (!cert) { certinfo->error = "Could not get peer certificate: "+std::string(get_error()); - return certinfo; + BufferedSocketFingerprintSubmission(user, this, sslinfo, certinfo).Send(); + return; } certinfo->invalid = (SSL_get_verify_result(session->sess) != X509_V_OK); @@ -819,7 +788,7 @@ class ModuleSSLOpenSSL : public Module } X509_free(cert); - return certinfo; + BufferedSocketFingerprintSubmission(user, this, sslinfo, certinfo).Send(); } void Prioritize() diff --git a/src/modules/m_antibear.cpp b/src/modules/m_antibear.cpp index 70a4a96fb..8eab13594 100644 --- a/src/modules/m_antibear.cpp +++ b/src/modules/m_antibear.cpp @@ -18,12 +18,11 @@ class ModuleAntiBear : public Module { - private: - + LocalIntExt bearExt; public: - ModuleAntiBear(InspIRCd* Me) : Module(Me) + ModuleAntiBear(InspIRCd* Me) : Module(Me), bearExt("antibear_timewait", this) { - + Extensible::Register(&bearExt); Implementation eventlist[] = { I_OnUserRegister, I_OnPreCommand }; ServerInstance->Modules->Attach(eventlist, this, 2); } @@ -39,7 +38,7 @@ class ModuleAntiBear : public Module virtual ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, User *user, bool validated, const std::string &original_line) { - if (command == "NOTICE" && !validated && parameters.size() > 1 && user->GetExt("antibear_timewait")) + if (command == "NOTICE" && !validated && parameters.size() > 1 && bearExt.get(user)) { if (!strncmp(parameters[1].c_str(), "\1TIME Mon May 01 18:54:20 2006", 30)) { @@ -55,7 +54,7 @@ class ModuleAntiBear : public Module return MOD_RES_DENY; } - user->Shrink("antibear_timewait"); + bearExt.set(user, 0); // Block the command, so the user doesn't receive a no such nick notice return MOD_RES_DENY; } @@ -68,7 +67,7 @@ class ModuleAntiBear : public Module user->WriteNumeric(439, "%s :This server has anti-spambot mechanisms enabled.", user->nick.c_str()); user->WriteNumeric(931, "%s :Malicious bots, spammers, and other automated systems of dubious origin are NOT welcome here.", user->nick.c_str()); user->WriteServ("PRIVMSG %s :\1TIME\1", user->nick.c_str()); - user->Extend("antibear_timewait"); + bearExt.set(user, 1); return MOD_RES_PASSTHRU; } }; diff --git a/src/modules/m_banexception.cpp b/src/modules/m_banexception.cpp index dafa47d2c..9137c09d9 100644 --- a/src/modules/m_banexception.cpp +++ b/src/modules/m_banexception.cpp @@ -61,8 +61,7 @@ public: { if (chan != NULL) { - modelist *list; - chan->GetExt(be.GetInfoKey(), list); + modelist *list = be.extItem.get(chan); if (!list) return MOD_RES_PASSTHRU; @@ -90,8 +89,7 @@ public: { if (chan != NULL) { - modelist *list; - chan->GetExt(be.GetInfoKey(), list); + modelist *list = be.extItem.get(chan); if (!list) return MOD_RES_PASSTHRU; @@ -114,8 +112,7 @@ public: { if (chan != NULL) { - modelist* list; - chan->GetExt(be.GetInfoKey(), list); + modelist *list = be.extItem.get(chan); if (!list) { @@ -146,11 +143,6 @@ public: be.DoSyncChannel(chan, proto, opaque); } - virtual void OnChannelDelete(Channel* chan) - { - be.DoChannelDelete(chan); - } - virtual void OnRehash(User* user) { be.DoRehash(); diff --git a/src/modules/m_banredirect.cpp b/src/modules/m_banredirect.cpp index 1a486325a..da08d06fb 100644 --- a/src/modules/m_banredirect.cpp +++ b/src/modules/m_banredirect.cpp @@ -38,7 +38,9 @@ typedef std::deque<std::string> StringDeque; class BanRedirect : public ModeWatcher { public: - BanRedirect(InspIRCd* Instance) : ModeWatcher(Instance, 'b', MODETYPE_CHANNEL) + SimpleExtItem<BanRedirectList> extItem; + BanRedirect(InspIRCd* Instance, Module* parent) : ModeWatcher(Instance, 'b', MODETYPE_CHANNEL), + extItem("banredirect", parent) { } @@ -145,10 +147,11 @@ class BanRedirect : public ModeWatcher if(adding) { /* It's a properly valid redirecting ban, and we're adding it */ - if(!channel->GetExt("banredirects", redirects)) + redirects = extItem.get(channel); + if (!redirects) { redirects = new BanRedirectList; - channel->Extend("banredirects", redirects); + extItem.set(channel, redirects); } /* Here 'param' doesn't have the channel on it yet */ @@ -160,7 +163,8 @@ class BanRedirect : public ModeWatcher else { /* Removing a ban, if there's no extensible there are no redirecting bans and we're fine. */ - if(channel->GetExt("banredirects", redirects)) + redirects = extItem.get(channel); + if (redirects) { /* But there were, so we need to remove the matching one if there is one */ @@ -173,8 +177,7 @@ class BanRedirect : public ModeWatcher if(redirects->empty()) { - delete redirects; - channel->Shrink("banredirects"); + extItem.unset(channel); } break; @@ -200,7 +203,7 @@ class ModuleBanRedirect : public Module public: ModuleBanRedirect(InspIRCd* Me) - : Module(Me), re(Me) + : Module(Me), re(Me, this) { nofollow = false; @@ -209,9 +212,9 @@ class ModuleBanRedirect : public Module OnRehash(NULL); + Extensible::Register(&re.extItem); Implementation list[] = { I_OnRehash, I_OnUserPreJoin, I_OnChannelDelete, I_OnCleanup }; Me->Modules->Attach(list, this, 4); - } virtual void OnChannelDelete(Channel* chan) @@ -224,9 +227,9 @@ class ModuleBanRedirect : public Module if(target_type == TYPE_CHANNEL) { Channel* chan = static_cast<Channel*>(item); - BanRedirectList* redirects; + BanRedirectList* redirects = re.extItem.get(chan); - if(chan->GetExt("banredirects", redirects)) + if(redirects) { irc::modestacker modestack(ServerInstance, false); StringDeque stackresult; @@ -250,9 +253,6 @@ class ModuleBanRedirect : public Module ServerInstance->SendMode(mode_junk, ServerInstance->FakeClient); mode_junk.erase(mode_junk.begin() + 1, mode_junk.end()); } - - delete redirects; - chan->Shrink("banredirects"); } } } @@ -273,9 +273,9 @@ class ModuleBanRedirect : public Module /* Return 1 to prevent the join, 0 to allow it */ if (chan) { - BanRedirectList* redirects; + BanRedirectList* redirects = re.extItem.get(chan); - if(chan->GetExt("banredirects", redirects)) + if (redirects) { /* We actually had some ban redirects to check */ diff --git a/src/modules/m_blockamsg.cpp b/src/modules/m_blockamsg.cpp index 104086bfe..5ce32ea8e 100644 --- a/src/modules/m_blockamsg.cpp +++ b/src/modules/m_blockamsg.cpp @@ -42,13 +42,15 @@ class ModuleBlockAmsg : public Module { int ForgetDelay; BlockAction action; + SimpleExtItem<BlockedMessage> blockamsg; public: - ModuleBlockAmsg(InspIRCd* Me) : Module(Me) + ModuleBlockAmsg(InspIRCd* Me) : Module(Me), blockamsg("blockamsg", this) { this->OnRehash(NULL); - Implementation eventlist[] = { I_OnRehash, I_OnPreCommand, I_OnCleanup }; - ServerInstance->Modules->Attach(eventlist, this, 3); + Extensible::Register(&blockamsg); + Implementation eventlist[] = { I_OnRehash, I_OnPreCommand }; + ServerInstance->Modules->Attach(eventlist, this, 2); } @@ -125,8 +127,7 @@ class ModuleBlockAmsg : public Module userchans = user->chans.size(); // Check that this message wasn't already sent within a few seconds. - BlockedMessage* m; - user->GetExt("amsgblock", m); + BlockedMessage* m = blockamsg.get(user); // If the message is identical and within the time. // We check the target is *not* identical, that'd straying into the realms of flood control. Which isn't what we're doing... @@ -157,26 +158,11 @@ class ModuleBlockAmsg : public Module else { m = new BlockedMessage(parameters[1], parameters[0].c_str(), ServerInstance->Time()); - user->Extend("amsgblock", (char*)m); + blockamsg.set(user, m); } } return MOD_RES_PASSTHRU; } - - void OnCleanup(int target_type, void* item) - { - if(target_type == TYPE_USER) - { - User* user = (User*)item; - BlockedMessage* m; - user->GetExt("amsgblock", m); - if(m) - { - delete m; - user->Shrink("amsgblock"); - } - } - } }; diff --git a/src/modules/m_callerid.cpp b/src/modules/m_callerid.cpp index 543f5d8a1..2e508399b 100644 --- a/src/modules/m_callerid.cpp +++ b/src/modules/m_callerid.cpp @@ -70,59 +70,59 @@ class callerid_data : public classbase } }; -/** Retrieves the callerid information for a given user record - * @param who The user to retrieve callerid information for - * @param extend true to add callerid information if it doesn't already exist, false to return NULL if it doesn't exist - * @return NULL if extend is false and it doesn't exist, a callerid_data instance otherwise. - */ -callerid_data* GetData(User* who, bool extend = true) +struct CallerIDExtInfo : public ExtensionItem { - callerid_data* dat; - if (who->GetExt("callerid_data", dat)) - return dat; - else + CallerIDExtInfo(Module* parent) + : ExtensionItem("callerid_data", parent) { - if (extend) - { - dat = new callerid_data; - who->Extend("callerid_data", dat); - return dat; - } - else - return NULL; } -} -void RemoveData(User* who) -{ - callerid_data* dat; - who->GetExt("callerid_data", dat); + std::string serialize(Module* requestor, const Extensible* container, void* item) + { + callerid_data* dat = static_cast<callerid_data*>(item); + return dat->ToString(requestor); + } - if (!dat) - return; + void unserialize(Module* requestor, Extensible* container, const std::string& value) + { + callerid_data* dat = new callerid_data(value, requestor->ServerInstance); + set_raw(container, dat); + } - // We need to walk the list of users on our accept list, and remove ourselves from their wholistsme. - for (std::set<User *>::iterator it = dat->accepting.begin(); it != dat->accepting.end(); it++) + callerid_data* get(User* user, bool create) { - callerid_data *targ = GetData(*it, false); + callerid_data* dat = static_cast<callerid_data*>(get_raw(user)); + if (!dat) + { + dat = new callerid_data; + set_raw(user, dat); + } + return dat; + } - if (!targ) - continue; // shouldn't happen, but oh well. + void free(void* item) + { + callerid_data* dat = static_cast<callerid_data*>(item); - for (std::list<callerid_data *>::iterator it2 = targ->wholistsme.begin(); it2 != targ->wholistsme.end(); it2++) + // We need to walk the list of users on our accept list, and remove ourselves from their wholistsme. + for (std::set<User *>::iterator it = dat->accepting.begin(); it != dat->accepting.end(); it++) { - if (*it2 == dat) + callerid_data *targ = this->get(*it, false); + + if (!targ) + continue; // shouldn't happen, but oh well. + + for (std::list<callerid_data *>::iterator it2 = targ->wholistsme.begin(); it2 != targ->wholistsme.end(); it2++) { - targ->wholistsme.erase(it2); - break; + if (*it2 == dat) + { + targ->wholistsme.erase(it2); + break; + } } } } - - who->Shrink("callerid_data"); - delete dat; -} - +}; class User_g : public SimpleUserModeHandler { @@ -133,8 +133,10 @@ public: class CommandAccept : public Command { public: + CallerIDExtInfo extInfo; unsigned int maxaccepts; - CommandAccept(InspIRCd* Instance, Module* Creator) : Command(Instance, Creator, "ACCEPT", 0, 1) + CommandAccept(InspIRCd* Instance, Module* Creator) : Command(Instance, Creator, "ACCEPT", 0, 1), + extInfo(Creator) { syntax = "{[+|-]<nicks>}|*}"; TRANSLATE2(TR_CUSTOM, TR_END); @@ -221,7 +223,7 @@ public: void ListAccept(User* user) { - callerid_data* dat = GetData(user, false); + callerid_data* dat = extInfo.get(user, false); if (dat) { for (std::set<User*>::iterator i = dat->accepting.begin(); i != dat->accepting.end(); ++i) @@ -233,7 +235,7 @@ public: bool AddAccept(User* user, User* whotoadd, bool quiet) { // Add this user to my accept list first, so look me up.. - callerid_data* dat = GetData(user, true); + callerid_data* dat = extInfo.get(user, true); if (dat->accepting.size() >= maxaccepts) { if (!quiet) @@ -250,7 +252,7 @@ public: } // Now, look them up, and add me to their list - callerid_data *targ = GetData(whotoadd, true); + callerid_data *targ = extInfo.get(whotoadd, true); targ->wholistsme.push_back(dat); user->WriteServ("NOTICE %s :%s is now on your accept list", user->nick.c_str(), whotoadd->nick.c_str()); @@ -260,7 +262,7 @@ public: bool RemoveAccept(User* user, User* whotoremove, bool quiet) { // Remove them from my list, so look up my list.. - callerid_data* dat = GetData(user, false); + callerid_data* dat = extInfo.get(user, false); if (!dat) { if (!quiet) @@ -280,7 +282,7 @@ public: dat->accepting.erase(i); // Look up their list to remove me. - callerid_data *dat2 = GetData(whotoremove, false); + callerid_data *dat2 = extInfo.get(whotoremove, false); if (!dat2) { // How the fuck is this possible. @@ -305,7 +307,7 @@ public: class ModuleCallerID : public Module { private: - CommandAccept mycommand; + CommandAccept cmd; User_g myumode; // Configuration variables: @@ -319,7 +321,7 @@ private: void RemoveFromAllAccepts(User* who) { // First, find the list of people who have me on accept - callerid_data *userdata = GetData(who, false); + callerid_data *userdata = cmd.extInfo.get(who, false); if (!userdata) return; @@ -339,17 +341,18 @@ private: } public: - ModuleCallerID(InspIRCd* Me) : Module(Me), mycommand(Me, this), myumode(Me, this) + ModuleCallerID(InspIRCd* Me) : Module(Me), cmd(Me, this), myumode(Me, this) { OnRehash(NULL); if (!ServerInstance->Modes->AddMode(&myumode)) throw ModuleException("Could not add usermode +g"); - ServerInstance->AddCommand(&mycommand); + ServerInstance->AddCommand(&cmd); + Extensible::Register(&cmd.extInfo); - Implementation eventlist[] = { I_OnRehash, I_OnUserPreNick, I_OnUserQuit, I_On005Numeric, I_OnUserPreNotice, I_OnUserPreMessage, I_OnCleanup }; - ServerInstance->Modules->Attach(eventlist, this, 7); + Implementation eventlist[] = { I_OnRehash, I_OnUserPreNick, I_OnUserQuit, I_On005Numeric, I_OnUserPreNotice, I_OnUserPreMessage }; + ServerInstance->Modules->Attach(eventlist, this, 6); } virtual ~ModuleCallerID() @@ -375,7 +378,7 @@ public: if (operoverride && IS_OPER(user)) return MOD_RES_PASSTHRU; - callerid_data* dat = GetData(dest, true); + callerid_data* dat = cmd.extInfo.get(dest, true); std::set<User*>::iterator i = dat->accepting.find(user); if (i == dat->accepting.end()) @@ -411,53 +414,22 @@ public: return MOD_RES_PASSTHRU; } - virtual void OnCleanup(int type, void* item) - { - if (type != TYPE_USER) - return; - - User* u = (User*)item; - /* Cleanup only happens on unload (before dtor), so keep this O(n) instead of O(n^2) which deferring to OnUserQuit would do. */ - RemoveData(u); - } - - virtual void OnSyncUser(User* user, Module* proto, void* opaque) - { - callerid_data* dat = GetData(user, false); - if (dat) - { - std::string str = dat->ToString(proto); - proto->ProtoSendMetaData(opaque, user, "callerid_data", str); - } - } - - virtual void OnDecodeMetaData(Extensible* target, const std::string& extname, const std::string& extdata) - { - User* u = dynamic_cast<User*>(target); - if (u && extname == "callerid_data") - { - callerid_data* dat = new callerid_data(extdata, ServerInstance); - u->Extend("callerid_data", dat); - } - } - - virtual ModResult OnUserPreNick(User* user, const std::string& newnick) + ModResult OnUserPreNick(User* user, const std::string& newnick) { if (!tracknick) RemoveFromAllAccepts(user); return MOD_RES_PASSTHRU; } - virtual void OnUserQuit(User* user, const std::string& message, const std::string& oper_message) + void OnUserQuit(User* user, const std::string& message, const std::string& oper_message) { RemoveFromAllAccepts(user); - RemoveData(user); } virtual void OnRehash(User* user) { ConfigReader Conf(ServerInstance); - mycommand.maxaccepts = Conf.ReadInteger("callerid", "maxaccepts", "16", 0, true); + cmd.maxaccepts = Conf.ReadInteger("callerid", "maxaccepts", "16", 0, true); operoverride = Conf.ReadFlag("callerid", "operoverride", "0", 0); tracknick = Conf.ReadFlag("callerid", "tracknick", "0", 0); notify_cooldown = Conf.ReadInteger("callerid", "cooldown", "60", 0, true); diff --git a/src/modules/m_cap.cpp b/src/modules/m_cap.cpp index 626b4c23c..160c7a9c9 100644 --- a/src/modules/m_cap.cpp +++ b/src/modules/m_cap.cpp @@ -35,7 +35,9 @@ CAP END class CommandCAP : public Command { public: - CommandCAP (InspIRCd* Instance, Module* mod) : Command(Instance, mod, "CAP", 0, 1, true) + LocalIntExt reghold; + CommandCAP (InspIRCd* Instance, Module* mod) : Command(Instance, mod, "CAP", 0, 1, true), + reghold("CAP_REGHOLD", mod) { } @@ -64,7 +66,7 @@ class CommandCAP : public Command Data.wanted.push_back(cap_); } - user->Extend("CAP_REGHOLD"); + reghold.set(user, 1); Event event((char*) &Data, this->creator, "cap_req"); event.Send(this->ServerInstance); @@ -82,7 +84,7 @@ class CommandCAP : public Command } else if (subcommand == "END") { - user->Shrink("CAP_REGHOLD"); + reghold.set(user, 0); } else if ((subcommand == "LS") || (subcommand == "LIST")) { @@ -92,7 +94,7 @@ class CommandCAP : public Command Data.user = user; Data.creator = this->creator; - user->Extend("CAP_REGHOLD"); + reghold.set(user, 1); Event event((char*) &Data, this->creator, subcommand == "LS" ? "cap_ls" : "cap_list"); event.Send(this->ServerInstance); @@ -112,7 +114,7 @@ class CommandCAP : public Command Data.user = user; Data.creator = this->creator; - user->Extend("CAP_REGHOLD"); + reghold.set(user, 1); Event event((char*) &Data, this->creator, "cap_clear"); event.Send(this->ServerInstance); @@ -130,33 +132,34 @@ class CommandCAP : public Command class ModuleCAP : public Module { - CommandCAP newcommand; + CommandCAP cmd; public: ModuleCAP(InspIRCd* Me) - : Module(Me), newcommand(Me, this) + : Module(Me), cmd(Me, this) { - ServerInstance->AddCommand(&newcommand); + ServerInstance->AddCommand(&cmd); + Extensible::Register(&cmd.reghold); Implementation eventlist[] = { I_OnCheckReady }; ServerInstance->Modules->Attach(eventlist, this, 1); } - virtual ModResult OnCheckReady(User* user) + ModResult OnCheckReady(User* user) { /* Users in CAP state get held until CAP END */ - if (user->GetExt("CAP_REGHOLD")) + if (cmd.reghold.get(user)) return MOD_RES_DENY; return MOD_RES_PASSTHRU; } - virtual ~ModuleCAP() + ~ModuleCAP() { } - virtual Version GetVersion() + Version GetVersion() { - return Version("$Id$", VF_VENDOR, API_VERSION); + return Version("Client CAP extension support", VF_VENDOR); } }; diff --git a/src/modules/m_cap.h b/src/modules/m_cap.h index ce5aec8ba..72c7a14a5 100644 --- a/src/modules/m_cap.h +++ b/src/modules/m_cap.h @@ -27,42 +27,53 @@ class CapData : public classbase Module* creator; }; -void GenericCapHandler(Event* ev, const std::string &extname, const std::string &cap) +class GenericCap { - if (ev->GetEventID() == "cap_req") + public: + LocalIntExt ext; + const std::string cap; + GenericCap(Module* parent, const std::string &Cap) : ext("cap_" + cap, parent), cap(Cap) { - CapData *data = (CapData *) ev->GetData(); - - std::vector<std::string>::iterator it; - if ((it = std::find(data->wanted.begin(), data->wanted.end(), cap)) != data->wanted.end()) - { - // we can handle this, so ACK it, and remove it from the wanted list - data->ack.push_back(*it); - data->wanted.erase(it); - data->user->Extend(extname); - } + Extensible::Register(&ext); } - if (ev->GetEventID() == "cap_ls") + void HandleEvent(Event* ev) { - CapData *data = (CapData *) ev->GetData(); - data->wanted.push_back(cap); - } + if (ev->GetEventID() == "cap_req") + { + CapData *data = (CapData *) ev->GetData(); - if (ev->GetEventID() == "cap_list") - { - CapData *data = (CapData *) ev->GetData(); + std::vector<std::string>::iterator it; + if ((it = std::find(data->wanted.begin(), data->wanted.end(), cap)) != data->wanted.end()) + { + // we can handle this, so ACK it, and remove it from the wanted list + data->ack.push_back(*it); + data->wanted.erase(it); + ext.set(data->user, 1); + } + } - if (data->user->GetExt(extname)) + if (ev->GetEventID() == "cap_ls") + { + CapData *data = (CapData *) ev->GetData(); data->wanted.push_back(cap); - } + } - if (ev->GetEventID() == "cap_clear") - { - CapData *data = (CapData *) ev->GetData(); - data->ack.push_back("-" + cap); - data->user->Shrink(extname); + if (ev->GetEventID() == "cap_list") + { + CapData *data = (CapData *) ev->GetData(); + + if (ext.get(data->user)) + data->wanted.push_back(cap); + } + + if (ev->GetEventID() == "cap_clear") + { + CapData *data = (CapData *) ev->GetData(); + data->ack.push_back("-" + cap); + ext.set(data->user, 0); + } } -} +}; #endif diff --git a/src/modules/m_cgiirc.cpp b/src/modules/m_cgiirc.cpp index 41c2154cc..c72e18390 100644 --- a/src/modules/m_cgiirc.cpp +++ b/src/modules/m_cgiirc.cpp @@ -53,11 +53,18 @@ typedef std::vector<CGIhost> CGIHostlist; */ class CommandWebirc : public Command { - bool notify; - public: - CGIHostlist Hosts; - CommandWebirc(InspIRCd* Instance, Module* Creator, bool bnotify) - : Command(Instance, Creator, "WEBIRC", 0, 4, true), notify(bnotify) + bool notify; + public: + StringExtItem realhost; + StringExtItem realip; + LocalStringExt webirc_hostname; + LocalStringExt webirc_ip; + + CGIHostlist Hosts; + CommandWebirc(InspIRCd* Instance, Module* Creator, bool bnotify) + : Command(Instance, Creator, "WEBIRC", 0, 4, true), notify(bnotify), + realhost("cgiirc_realhost", Creator), realip("cgiirc_realip", Creator), + webirc_hostname("cgiirc_webirc_hostname", Creator), webirc_ip("cgiirc_webirc_ip", Creator) { this->syntax = "password client hostname ip"; } @@ -72,12 +79,12 @@ class CommandWebirc : public Command { if(iter->type == WEBIRC && parameters[0] == iter->password) { - user->Extend("cgiirc_realhost", new std::string(user->host)); - user->Extend("cgiirc_realip", new std::string(user->GetIPString())); + realhost.set(user, user->host); + realip.set(user, user->GetIPString()); if (notify) ServerInstance->SNO->WriteGlobalSno('a', "Connecting user %s detected as using CGI:IRC (%s), changing real host to %s from %s", user->nick.c_str(), user->host.c_str(), parameters[2].c_str(), user->host.c_str()); - user->Extend("cgiirc_webirc_hostname", new std::string(parameters[2])); - user->Extend("cgiirc_webirc_ip", new std::string(parameters[3])); + webirc_hostname.set(user, parameters[2]); + webirc_ip.set(user, parameters[3]); return CMD_SUCCESS; } } @@ -142,6 +149,10 @@ public: { OnRehash(NULL); ServerInstance->AddCommand(&cmd); + Extensible::Register(&cmd.realhost); + Extensible::Register(&cmd.realip); + Extensible::Register(&cmd.webirc_hostname); + Extensible::Register(&cmd.webirc_ip); Implementation eventlist[] = { I_OnRehash, I_OnUserRegister, I_OnCleanup, I_OnSyncUser, I_OnDecodeMetaData, I_OnUserDisconnect, I_OnUserConnect }; ServerInstance->Modules->Attach(eventlist, this, 7); @@ -202,53 +213,6 @@ public: } } - virtual void OnCleanup(int target_type, void* item) - { - if(target_type == TYPE_USER) - { - User* user = (User*)item; - std::string* realhost; - std::string* realip; - - if(user->GetExt("cgiirc_realhost", realhost)) - { - delete realhost; - user->Shrink("cgiirc_realhost"); - } - - if(user->GetExt("cgiirc_realip", realip)) - { - delete realip; - user->Shrink("cgiirc_realip"); - } - } - } - - virtual void OnSyncUser(User* user, Module* proto, void* opaque) - { - std::string* data; - if (user->GetExt("cgiirc_realhost", data)) - proto->ProtoSendMetaData(opaque, user, "cgiirc_realhost", *data); - if (user->GetExt("cgiirc_realip", data)) - proto->ProtoSendMetaData(opaque, user, "cgiirc_realip", *data); - } - - virtual void OnDecodeMetaData(Extensible* target, const std::string &extname, const std::string &extdata) - { - User* dest = dynamic_cast<User*>(target); - std::string* bleh; - if(dest && ((extname == "cgiirc_realhost") || (extname == "cgiirc_realip")) && (!dest->GetExt(extname, bleh))) - { - dest->Extend(extname, new std::string(extdata)); - } - } - - virtual void OnUserDisconnect(User* user) - { - OnCleanup(TYPE_USER, user); - } - - virtual ModResult OnUserRegister(User* user) { for(CGIHostlist::iterator iter = cmd.Hosts.begin(); iter != cmd.Hosts.end(); iter++) @@ -290,22 +254,21 @@ public: virtual void OnUserConnect(User* user) { - std::string *webirc_hostname, *webirc_ip; - if(user->GetExt("cgiirc_webirc_hostname", webirc_hostname)) + std::string *webirc_hostname = cmd.webirc_hostname.get(user); + std::string *webirc_ip = cmd.webirc_ip.get(user); + if (webirc_hostname) { user->host.assign(*webirc_hostname, 0, 64); user->dhost.assign(*webirc_hostname, 0, 64); - delete webirc_hostname; user->InvalidateCache(); - user->Shrink("cgiirc_webirc_hostname"); + cmd.webirc_hostname.unset(user); } - if(user->GetExt("cgiirc_webirc_ip", webirc_ip)) + if (webirc_ip) { ServerInstance->Users->RemoveCloneCounts(user); user->SetClientIP(webirc_ip->c_str()); - delete webirc_ip; user->InvalidateCache(); - user->Shrink("cgiirc_webirc_ip"); + cmd.webirc_ip.unset(user); ServerInstance->Users->AddLocalClone(user); ServerInstance->Users->AddGlobalClone(user); user->CheckClass(); @@ -317,8 +280,8 @@ public: { if(IsValidHost(user->password)) { - user->Extend("cgiirc_realhost", new std::string(user->host)); - user->Extend("cgiirc_realip", new std::string(user->GetIPString())); + cmd.realhost.set(user, user->host); + cmd.realip.set(user, user->GetIPString()); user->host.assign(user->password, 0, 64); user->dhost.assign(user->password, 0, 64); user->InvalidateCache(); @@ -380,8 +343,8 @@ public: newip.s_addr = htonl(ipaddr); char* newipstr = inet_ntoa(newip); - user->Extend("cgiirc_realhost", new std::string(user->host)); - user->Extend("cgiirc_realip", new std::string(user->GetIPString())); + cmd.realhost.set(user, user->host); + cmd.realip.set(user, user->GetIPString()); ServerInstance->Users->RemoveCloneCounts(user); user->SetClientIP(newipstr); ServerInstance->Users->AddLocalClone(user); diff --git a/src/modules/m_chanfilter.cpp b/src/modules/m_chanfilter.cpp index 4f6ebf22a..4636d2372 100644 --- a/src/modules/m_chanfilter.cpp +++ b/src/modules/m_chanfilter.cpp @@ -76,11 +76,6 @@ class ModuleChanFilter : public Module ServerInstance->Modules->PublishInterface("ChannelBanList", this); } - virtual void OnChannelDelete(Channel* chan) - { - cf.DoChannelDelete(chan); - } - virtual void OnRehash(User* user) { ConfigReader Conf(ServerInstance); @@ -93,8 +88,7 @@ class ModuleChanFilter : public Module if (!IS_LOCAL(user) || (CHANOPS_EXEMPT(ServerInstance, 'g') && chan->GetStatus(user) == STATUS_OP)) return MOD_RES_PASSTHRU; - modelist* list; - chan->GetExt(cf.GetInfoKey(), list); + modelist* list = cf.extItem.get(chan); if (list) { diff --git a/src/modules/m_channelban.cpp b/src/modules/m_channelban.cpp index 8167b8aae..fd5d5d401 100644 --- a/src/modules/m_channelban.cpp +++ b/src/modules/m_channelban.cpp @@ -25,16 +25,16 @@ class ModuleBadChannelExtban : public Module ServerInstance->Modules->Attach(eventlist, this, 2); } - virtual ~ModuleBadChannelExtban() + ~ModuleBadChannelExtban() { } - virtual Version GetVersion() + Version GetVersion() { return Version("$Id$", VF_COMMON|VF_VENDOR,API_VERSION); } - virtual ModResult OnCheckBan(User *user, Channel *c) + ModResult OnCheckBan(User *user, Channel *c) { ModResult rv; for (UCListIter i = user->chans.begin(); i != user->chans.end(); i++) @@ -45,7 +45,7 @@ class ModuleBadChannelExtban : public Module return rv; } - virtual void On005Numeric(std::string &output) + void On005Numeric(std::string &output) { ServerInstance->AddExtBanChar('j'); } diff --git a/src/modules/m_check.cpp b/src/modules/m_check.cpp index 7f85b1869..964a8c075 100644 --- a/src/modules/m_check.cpp +++ b/src/modules/m_check.cpp @@ -20,7 +20,6 @@ class CommandCheck : public Command { public: - std::set<std::string> meta_seen; CommandCheck (InspIRCd* Instance, Module* parent) : Command(Instance,parent,"CHECK", "o", 1) { syntax = "<nickname>|<ip>|<hostmask>|<channel> <server>"; @@ -34,17 +33,20 @@ class CommandCheck : public Command return std::string(timebuf); } - void dumpExtra(User* user, std::string checkstr, Extensible* ext) + void dumpExt(User* user, std::string checkstr, Extensible* ext) { - std::deque<std::string> extlist; - ext->GetExtList(extlist); std::stringstream dumpkeys; - for(std::deque<std::string>::iterator i = extlist.begin(); i != extlist.end(); i++) + for(ExtensibleStore::const_iterator i = ext->GetExtList().begin(); i != ext->GetExtList().end(); i++) { - if (meta_seen.find(*i) == meta_seen.end()) - dumpkeys << " " << *i; + ExtensionItem* item = Extensible::GetItem(i->first); + std::string value; + if (item) + value = item->serialize(creator, ext, i->second); + if (value.empty()) + dumpkeys << " " << i->first; + else + ServerInstance->DumpText(user, checkstr + " meta:" + i->first + " " + value); } - meta_seen.clear(); if (!dumpkeys.str().empty()) ServerInstance->DumpText(user,checkstr + " metadata", dumpkeys); } @@ -118,8 +120,7 @@ class CommandCheck : public Command ServerInstance->DumpText(user,checkstr + " onchans", dump); - FOREACH_MOD_I(ServerInstance,I_OnSyncUser,OnSyncUser(targuser,creator,(void*)user)); - dumpExtra(user, checkstr, targuser); + dumpExt(user, checkstr, targuser); } else if (targchan) { @@ -152,8 +153,7 @@ class CommandCheck : public Command ServerInstance->DumpText(user, checkstr + " member " + tmpbuf); } - FOREACH_MOD_I(ServerInstance,I_OnSyncChannel,OnSyncChannel(targchan,creator,(void*)user)); - dumpExtra(user, checkstr, targchan); + dumpExt(user, checkstr, targchan); } else { @@ -203,24 +203,16 @@ class ModuleCheck : public Module ServerInstance->AddCommand(&mycommand); } - virtual ~ModuleCheck() - { - } - - virtual Version GetVersion() + ~ModuleCheck() { - return Version("$Id$", VF_VENDOR|VF_OPTCOMMON, API_VERSION); } - virtual void ProtoSendMetaData(void* opaque, Extensible* target, const std::string& name, const std::string& value) + Version GetVersion() { - User* user = static_cast<User*>(opaque); - ServerInstance->DumpText(user, std::string(":") + ServerInstance->Config->ServerName + " 304 " + std::string(user->nick) - + " :CHECK meta:" + name + " " + value); - mycommand.meta_seen.insert(name); + return Version("CHECK command, view user/channel details", VF_VENDOR|VF_OPTCOMMON); } - virtual std::string ProtoTranslate(Extensible* item) + std::string ProtoTranslate(Extensible* item) { User* u = dynamic_cast<User*>(item); Channel* c = dynamic_cast<Channel*>(item); diff --git a/src/modules/m_cloaking.cpp b/src/modules/m_cloaking.cpp index 2fa3b9e63..2a348ba8b 100644 --- a/src/modules/m_cloaking.cpp +++ b/src/modules/m_cloaking.cpp @@ -30,6 +30,7 @@ class CloakUser : public ModeHandler bool ipalways; Module* HashProvider; const char *xtab[4]; + LocalStringExt ext; /** This function takes a domain name string and returns just the last two domain parts, * or the last domain part if only two are available. Failing that it just returns what it was given. @@ -63,7 +64,8 @@ class CloakUser : public ModeHandler } CloakUser(InspIRCd* Instance, Module* source, Module* Hash) - : ModeHandler(Instance, source, 'x', 0, 0, false, MODETYPE_USER, false), HashProvider(Hash) + : ModeHandler(Instance, source, 'x', 0, 0, false, MODETYPE_USER, false), HashProvider(Hash), + ext("cloaked_host", source) { } @@ -95,14 +97,15 @@ class CloakUser : public ModeHandler * are connecting via localhost) -- this doesnt matter much. */ - std::string* cloak; + std::string* cloak = ext.get(dest); - if (!dest->GetExt("cloaked_host", cloak)) + if (!cloak) { /* Force creation of missing cloak */ creator->OnUserConnect(dest); + cloak = ext.get(dest); } - if (dest->GetExt("cloaked_host", cloak)) + if (cloak) { dest->ChangeDisplayedHost(cloak->c_str()); dest->SetMode('x',true); @@ -281,40 +284,35 @@ class ModuleCloaking : public Module } ServerInstance->Modules->UseInterface("HashRequest"); + Extensible::Register(&cu->ext); - Implementation eventlist[] = { I_OnRehash, I_OnUserDisconnect, I_OnCleanup, I_OnCheckBan, I_OnUserConnect, I_OnSyncUser, I_OnCleanup }; - ServerInstance->Modules->Attach(eventlist, this, 6); + Implementation eventlist[] = { I_OnRehash, I_OnCheckBan, I_OnUserConnect }; + ServerInstance->Modules->Attach(eventlist, this, 3); CloakExistingUsers(); } - void OnSyncUser(User* user, Module* proto,void* opaque) - { - std::string* cloak; - if (user->GetExt("cloaked_host", cloak) && proto->ProtoTranslate(NULL) == "?") - proto->ProtoSendMetaData(opaque, user, "cloaked_host", *cloak); - } - void CloakExistingUsers() { std::string* cloak; for (std::vector<User*>::iterator u = ServerInstance->Users->local_users.begin(); u != ServerInstance->Users->local_users.end(); u++) { - if (!(*u)->GetExt("cloaked_host", cloak)) + cloak = cu->ext.get(*u); + if (!cloak) { OnUserConnect(*u); } } } - virtual ModResult OnCheckBan(User* user, Channel* chan) + ModResult OnCheckBan(User* user, Channel* chan) { char mask[MAXBUF]; - std::string* tofree; + std::string* cloak = cu->ext.get(user); /* Check if they have a cloaked host, but are not using it */ - if (user->GetExt("cloaked_host", tofree) && *tofree != user->dhost) + if (cloak && *cloak != user->dhost) { - snprintf(mask, MAXBUF, "%s!%s@%s", user->nick.c_str(), user->ident.c_str(), tofree->c_str()); + snprintf(mask, MAXBUF, "%s!%s@%s", user->nick.c_str(), user->ident.c_str(), cloak->c_str()); for (BanList::iterator i = chan->bans.begin(); i != chan->bans.end(); i++) { if (InspIRCd::Match(mask,i->data)) @@ -334,45 +332,29 @@ class ModuleCloaking : public Module ServerInstance->Modules->SetPriority(this, I_OnUserConnect, PRIORITY_AFTER, &um); } - virtual void OnUserDisconnect(User* user) - { - std::string* tofree; - if (user->GetExt("cloaked_host", tofree)) - { - delete tofree; - user->Shrink("cloaked_host"); - } - } - - virtual void OnCleanup(int target_type, void* item) - { - if (target_type == TYPE_USER) - OnUserDisconnect((User*)item); - } - - virtual ~ModuleCloaking() + ~ModuleCloaking() { ServerInstance->Modes->DelMode(cu); delete cu; ServerInstance->Modules->DoneWithInterface("HashRequest"); } - virtual Version GetVersion() + Version GetVersion() { // returns the version number of the module to be // listed in /MODULES return Version("$Id$", VF_COMMON|VF_VENDOR,API_VERSION); } - virtual void OnRehash(User* user) + void OnRehash(User* user) { cu->DoRehash(); } - virtual void OnUserConnect(User* dest) + void OnUserConnect(User* dest) { - std::string* tofree; - if (dest->GetExt("cloaked_host", tofree)) + std::string* cloak = cu->ext.get(dest); + if (cloak) return; if (dest->host.find('.') != std::string::npos || dest->host.find(':') != std::string::npos) @@ -423,7 +405,7 @@ class ModuleCloaking : public Module b = cu->Cloak4(dest->GetIPString()); } - dest->Extend("cloaked_host", new std::string(b)); + cu->ext.set(dest,b); } } diff --git a/src/modules/m_conn_waitpong.cpp b/src/modules/m_conn_waitpong.cpp index 4da240138..b77116410 100644 --- a/src/modules/m_conn_waitpong.cpp +++ b/src/modules/m_conn_waitpong.cpp @@ -19,18 +19,18 @@ class ModuleWaitPong : public Module { bool sendsnotice; bool killonbadreply; - const char* extenstr; + LocalStringExt ext; public: ModuleWaitPong(InspIRCd* Me) - : Module(Me), extenstr("waitpong_pingstr") + : Module(Me), ext("waitpong_pingstr", this) { OnRehash(NULL); - Implementation eventlist[] = { I_OnUserRegister, I_OnCheckReady, I_OnPreCommand, I_OnRehash, I_OnUserDisconnect, I_OnCleanup }; - ServerInstance->Modules->Attach(eventlist, this, 6); + Implementation eventlist[] = { I_OnUserRegister, I_OnCheckReady, I_OnPreCommand, I_OnRehash }; + ServerInstance->Modules->Attach(eventlist, this, 4); } - virtual void OnRehash(User* user) + void OnRehash(User* user) { ConfigReader Conf(ServerInstance); @@ -45,43 +45,40 @@ class ModuleWaitPong : public Module killonbadreply = true; } - - char* RandString(unsigned int length) + std::string RandString() { - unsigned char* out = new unsigned char[length+1]; - for(unsigned int i = 0; i < length; i++) + char out[11]; + for(unsigned int i = 0; i < 10; i++) out[i] = ((rand() % 26) + 65); - out[length] = '\0'; + out[10] = '\0'; - return (char*)out; + return out; } - virtual ModResult OnUserRegister(User* user) + ModResult OnUserRegister(User* user) { - char* pingrpl = RandString(10); + std::string pingrpl = RandString(); - user->Write("PING :%s", pingrpl); + user->Write("PING :%s", pingrpl.c_str()); if(sendsnotice) - user->WriteServ("NOTICE %s :*** If you are having problems connecting due to ping timeouts, please type /quote PONG %s or /raw PONG %s now.", user->nick.c_str(), pingrpl, pingrpl); + user->WriteServ("NOTICE %s :*** If you are having problems connecting due to ping timeouts, please type /quote PONG %s or /raw PONG %s now.", user->nick.c_str(), pingrpl.c_str(), pingrpl.c_str()); - user->Extend(extenstr, pingrpl); + ext.set(user, pingrpl); return MOD_RES_PASSTHRU; } - virtual ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, User* user, bool validated, const std::string &original_line) + ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, User* user, bool validated, const std::string &original_line) { if (command == "PONG") { - char* pingrpl; - user->GetExt(extenstr, pingrpl); + std::string* pingrpl = ext.get(user); if (pingrpl) { - if (!parameters.empty() && (strcmp(pingrpl, parameters[0].c_str()) == 0)) + if (!parameters.empty() && *pingrpl == parameters[0]) { - delete[] pingrpl; - user->Shrink(extenstr); + ext.unset(user); return MOD_RES_DENY; } else @@ -95,47 +92,18 @@ class ModuleWaitPong : public Module return MOD_RES_PASSTHRU; } - virtual ModResult OnCheckReady(User* user) - { - char* pingrpl; - return user->GetExt(extenstr, pingrpl) ? MOD_RES_DENY : MOD_RES_PASSTHRU; - } - - virtual void OnUserDisconnect(User* user) - { - char* pingrpl; - user->GetExt(extenstr, pingrpl); - - if (pingrpl) - { - delete[] pingrpl; - user->Shrink(extenstr); - } - } - - virtual void OnCleanup(int target_type, void* item) + ModResult OnCheckReady(User* user) { - if (target_type == TYPE_USER) - { - User* user = (User*)item; - char* pingrpl; - user->GetExt(extenstr, pingrpl); - - if (pingrpl) - { - delete[] pingrpl; - user->Shrink(extenstr); - } - } + return ext.get(user) ? MOD_RES_DENY : MOD_RES_PASSTHRU; } - virtual ~ModuleWaitPong() + ~ModuleWaitPong() { } - virtual Version GetVersion() + Version GetVersion() { - return Version("$Id$", VF_VENDOR, API_VERSION); + return Version("Require pong prior to registration", VF_VENDOR); } }; diff --git a/src/modules/m_customtitle.cpp b/src/modules/m_customtitle.cpp index b2933aa54..fc99cd29f 100644 --- a/src/modules/m_customtitle.cpp +++ b/src/modules/m_customtitle.cpp @@ -20,7 +20,9 @@ class CommandTitle : public Command { public: - CommandTitle (InspIRCd* Instance, Module* Creator) : Command(Instance, Creator,"TITLE",0,2) + StringExtItem ctitle; + CommandTitle (InspIRCd* Instance, Module* Creator) : Command(Instance, Creator,"TITLE",0,2), + ctitle("ctitle", Creator) { syntax = "<user> <password>"; TRANSLATE3(TR_NICK, TR_TEXT, TR_END); @@ -60,17 +62,9 @@ class CommandTitle : public Command if (!strcmp(name.c_str(),parameters[0].c_str()) && !ServerInstance->PassCompare(user, pass.c_str(), parameters[1].c_str(), hash.c_str()) && OneOfMatches(TheHost,TheIP,host.c_str()) && !title.empty()) { - std::string* text; - if (user->GetExt("ctitle", text)) - { - user->Shrink("ctitle"); - delete text; - } + ctitle.set(user, title); - text = new std::string(title); - user->Extend("ctitle", text); - - ServerInstance->PI->SendMetaData(user, "ctitle", *text); + ServerInstance->PI->SendMetaData(user, "ctitle", title); if (!vhost.empty()) user->ChangeDisplayedHost(vhost.c_str()); @@ -95,11 +89,10 @@ class ModuleCustomTitle : public Module ModuleCustomTitle(InspIRCd* Me) : Module(Me), cmd(Me, this) { ServerInstance->AddCommand(&cmd); - Implementation eventlist[] = { I_OnDecodeMetaData, I_OnWhoisLine, I_OnSyncUser, I_OnUserQuit, I_OnCleanup }; - ServerInstance->Modules->Attach(eventlist, this, 5); + Extensible::Register(&cmd.ctitle); + ServerInstance->Modules->Attach(I_OnWhoisLine, this); } - // :kenny.chatspike.net 320 Brain Azhrarn :is getting paid to play games. ModResult OnWhoisLine(User* user, User* dest, int &numeric, std::string &text) { @@ -107,89 +100,23 @@ class ModuleCustomTitle : public Module if (numeric == 312) { /* Insert our numeric before 312 */ - std::string* ctitle; - if (dest->GetExt("ctitle", ctitle)) + const std::string* ctitle = cmd.ctitle.get(dest); + if (ctitle) { ServerInstance->SendWhoisLine(user, dest, 320, "%s %s :%s",user->nick.c_str(), dest->nick.c_str(), ctitle->c_str()); } } - /* Dont block anything */ + /* Don't block anything */ return MOD_RES_PASSTHRU; } - // Whenever the linking module wants to send out data, but doesnt know what the data - // represents (e.g. it is metadata, added to a User or Channel by a module) then - // this method is called. We should use the ProtoSendMetaData function after we've - // corrected decided how the data should look, to send the metadata on its way if - // it is ours. - virtual void OnSyncUser(User* user, Module* proto, void* opaque) - { - // check if this user has an ctitle field to send - std::string* ctitle; - if (user->GetExt("ctitle", ctitle)) - proto->ProtoSendMetaData(opaque,user,"ctitle",*ctitle); - } - - // when a user quits, tidy up their metadata - virtual void OnUserQuit(User* user, const std::string &message, const std::string &oper_message) - { - std::string* ctitle; - if (user->GetExt("ctitle", ctitle)) - { - user->Shrink("ctitle"); - delete ctitle; - } - } - - // if the module is unloaded, tidy up all our dangling metadata - virtual void OnCleanup(int target_type, void* item) - { - if (target_type == TYPE_USER) - { - User* user = (User*)item; - std::string* ctitle; - if (user->GetExt("ctitle", ctitle)) - { - user->Shrink("ctitle"); - delete ctitle; - } - } - } - - // Whenever the linking module receives metadata from another server and doesnt know what - // to do with it (of course, hence the 'meta') it calls this method, and it is up to each - // module in turn to figure out if this metadata key belongs to them, and what they want - // to do with it. - // In our case we're only sending a single string around, so we just construct a std::string. - // Some modules will probably get much more complex and format more detailed structs and classes - // in a textual way for sending over the link. - virtual void OnDecodeMetaData(Extensible* target, const std::string &extname, const std::string &extdata) - { - User* dest = dynamic_cast<User*>(target); - // check if its our metadata key, and its associated with a user - if (dest && (extname == "ctitle")) - { - std::string* text; - if (dest->GetExt("ctitle", text)) - { - dest->Shrink("ctitle"); - delete text; - } - if (!extdata.empty()) - { - text = new std::string(extdata); - dest->Extend("ctitle", text); - } - } - } - - virtual ~ModuleCustomTitle() + ~ModuleCustomTitle() { } - virtual Version GetVersion() + Version GetVersion() { - return Version("$Id$", VF_COMMON | VF_VENDOR, API_VERSION); + return Version("Custom Title for users", VF_COMMON | VF_VENDOR); } }; diff --git a/src/modules/m_ident.cpp b/src/modules/m_ident.cpp index 690d7b15c..e5c8940ec 100644 --- a/src/modules/m_ident.cpp +++ b/src/modules/m_ident.cpp @@ -280,11 +280,11 @@ class IdentRequestSocket : public EventHandler class ModuleIdent : public Module { - private: int RequestTimeout; ConfigReader *Conf; + SimpleExtItem<IdentRequestSocket> ext; public: - ModuleIdent(InspIRCd *Me) : Module(Me) + ModuleIdent(InspIRCd *Me) : Module(Me), ext("ident_socket", this) { Conf = new ConfigReader(ServerInstance); OnRehash(NULL); @@ -338,7 +338,7 @@ class ModuleIdent : public Module try { IdentRequestSocket *isock = new IdentRequestSocket(ServerInstance, user); - user->Extend("ident_socket", isock); + ext.set(user, isock); } catch (ModuleException &e) { @@ -355,8 +355,8 @@ class ModuleIdent : public Module virtual ModResult OnCheckReady(User *user) { /* Does user have an ident socket attached at all? */ - IdentRequestSocket *isock = NULL; - if (!user->GetExt("ident_socket", isock)) + IdentRequestSocket *isock = ext.get(user); + if (!isock) { ServerInstance->Logs->Log("m_ident",DEBUG, "No ident socket :("); return MOD_RES_PASSTHRU; @@ -413,12 +413,11 @@ class ModuleIdent : public Module virtual void OnUserDisconnect(User *user) { /* User disconnect (generic socket detatch event) */ - IdentRequestSocket *isock = NULL; - if (user->GetExt("ident_socket", isock)) + IdentRequestSocket *isock = ext.get(user); + if (isock) { isock->Close(); - delete isock; - user->Shrink("ident_socket"); + ext.unset(user); } } }; diff --git a/src/modules/m_inviteexception.cpp b/src/modules/m_inviteexception.cpp index 29d7eb5d5..0b3621af7 100644 --- a/src/modules/m_inviteexception.cpp +++ b/src/modules/m_inviteexception.cpp @@ -52,17 +52,16 @@ public: ServerInstance->Modules->Attach(eventlist, this, 3); } - virtual void On005Numeric(std::string &output) + void On005Numeric(std::string &output) { output.append(" INVEX=I"); } - virtual ModResult OnCheckInvite(User* user, Channel* chan) + ModResult OnCheckInvite(User* user, Channel* chan) { if(chan != NULL) { - modelist* list; - chan->GetExt(ie.GetInfoKey(), list); + modelist* list = ie.extItem.get(chan); if (list) { std::string mask = std::string(user->nick) + "!" + user->ident + "@" + user->GetIPString(); @@ -81,32 +80,27 @@ public: return MOD_RES_PASSTHRU; } - virtual const char* OnRequest(Request* request) + const char* OnRequest(Request* request) { return ie.DoOnRequest(request); } - virtual void OnCleanup(int target_type, void* item) + void OnCleanup(int target_type, void* item) { ie.DoCleanup(target_type, item); } - virtual void OnSyncChannel(Channel* chan, Module* proto, void* opaque) + void OnSyncChannel(Channel* chan, Module* proto, void* opaque) { ie.DoSyncChannel(chan, proto, opaque); } - virtual void OnChannelDelete(Channel* chan) - { - ie.DoChannelDelete(chan); - } - - virtual void OnRehash(User* user) + void OnRehash(User* user) { ie.DoRehash(); } - virtual Version GetVersion() + Version GetVersion() { return Version("$Id$", VF_VENDOR | VF_COMMON, API_VERSION); } diff --git a/src/modules/m_joinflood.cpp b/src/modules/m_joinflood.cpp index 180d58376..853ddee75 100644 --- a/src/modules/m_joinflood.cpp +++ b/src/modules/m_joinflood.cpp @@ -86,12 +86,14 @@ class joinfloodsettings : public classbase class JoinFlood : public ModeHandler { public: - JoinFlood(InspIRCd* Instance, Module* Creator) : ModeHandler(Instance, Creator, 'j', 1, 0, false, MODETYPE_CHANNEL, false) { } + SimpleExtItem<joinfloodsettings> ext; + JoinFlood(InspIRCd* Instance, Module* Creator) : ModeHandler(Instance, Creator, 'j', 1, 0, false, MODETYPE_CHANNEL, false), + ext("joinflood", Creator) { } ModePair ModeSet(User* source, User* dest, Channel* channel, const std::string ¶meter) { - joinfloodsettings* x; - if (channel->GetExt("joinflood",x)) + joinfloodsettings* x = ext.get(channel); + if (x) return std::make_pair(true, ConvToStr(x->joins)+":"+ConvToStr(x->secs)); else return std::make_pair(false, parameter); @@ -99,8 +101,6 @@ class JoinFlood : public ModeHandler ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding) { - joinfloodsettings* dummy; - if (adding) { char ndata[MAXBUF]; @@ -133,11 +133,12 @@ class JoinFlood : public ModeHandler } else { - if (!channel->GetExt("joinflood", dummy)) + joinfloodsettings* f = ext.get(channel); + if (!f) { parameter = ConvToStr(njoins) + ":" +ConvToStr(nsecs); - joinfloodsettings *f = new joinfloodsettings(ServerInstance, nsecs, njoins); - channel->Extend("joinflood", f); + f = new joinfloodsettings(ServerInstance, nsecs, njoins); + ext.set(channel, f); channel->SetModeParam('j', parameter); return MODEACTION_ALLOW; } @@ -155,12 +156,8 @@ class JoinFlood : public ModeHandler // new mode param, replace old with new if ((nsecs > 0) && (njoins > 0)) { - joinfloodsettings* f; - channel->GetExt("joinflood", f); - delete f; f = new joinfloodsettings(ServerInstance, nsecs, njoins); - channel->Shrink("joinflood"); - channel->Extend("joinflood", f); + ext.set(channel, f); channel->SetModeParam('j', parameter); return MODEACTION_ALLOW; } @@ -180,12 +177,10 @@ class JoinFlood : public ModeHandler } else { - if (channel->GetExt("joinflood", dummy)) + joinfloodsettings* f = ext.get(channel); + if (f) { - joinfloodsettings *f; - channel->GetExt("joinflood", f); - delete f; - channel->Shrink("joinflood"); + ext.unset(channel); channel->SetModeParam('j', ""); return MODEACTION_ALLOW; } @@ -207,37 +202,35 @@ class ModuleJoinFlood : public Module if (!ServerInstance->Modes->AddMode(&jf)) throw ModuleException("Could not add new modes!"); + Extensible::Register(&jf.ext); Implementation eventlist[] = { I_OnChannelDelete, I_OnUserPreJoin, I_OnUserJoin }; ServerInstance->Modules->Attach(eventlist, this, 3); } - virtual ModResult OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven) + ModResult OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven) { if (chan) { - joinfloodsettings *f; - if (chan->GetExt("joinflood", f)) + joinfloodsettings *f = jf.ext.get(chan); + if (f && f->islocked()) { - if (f->islocked()) - { - user->WriteNumeric(609, "%s %s :This channel is temporarily unavailable (+j). Please try again later.",user->nick.c_str(),chan->name.c_str()); - return MOD_RES_DENY; - } + user->WriteNumeric(609, "%s %s :This channel is temporarily unavailable (+j). Please try again later.",user->nick.c_str(),chan->name.c_str()); + return MOD_RES_DENY; } } return MOD_RES_PASSTHRU; } - virtual void OnUserJoin(User* user, Channel* channel, bool sync, bool &silent, bool created) + void OnUserJoin(User* user, Channel* channel, bool sync, bool &silent, bool created) { - joinfloodsettings *f; - /* We arent interested in JOIN events caused by a network burst */ if (sync) return; + joinfloodsettings *f = jf.ext.get(channel); + /* But all others are OK */ - if (channel->GetExt("joinflood",f)) + if (f) { f->addjoin(); if (f->shouldlock()) @@ -249,23 +242,12 @@ class ModuleJoinFlood : public Module } } - void OnChannelDelete(Channel* chan) - { - joinfloodsettings *f; - if (chan->GetExt("joinflood",f)) - { - delete f; - chan->Shrink("joinflood"); - } - } - - - virtual ~ModuleJoinFlood() + ~ModuleJoinFlood() { ServerInstance->Modes->DelMode(&jf); } - virtual Version GetVersion() + Version GetVersion() { return Version("$Id$", VF_COMMON | VF_VENDOR, API_VERSION); } diff --git a/src/modules/m_kicknorejoin.cpp b/src/modules/m_kicknorejoin.cpp index 04ecfffd7..47dec1803 100644 --- a/src/modules/m_kicknorejoin.cpp +++ b/src/modules/m_kicknorejoin.cpp @@ -15,7 +15,7 @@ /* $ModDesc: Provides channel mode +J (delay rejoin after kick) */ -inline int strtoint(const std::string &str) +static inline int strtoint(const std::string &str) { std::istringstream ss(str); int result; @@ -30,7 +30,9 @@ typedef std::map<User*, time_t> delaylist; class KickRejoin : public ModeHandler { public: - KickRejoin(InspIRCd* Instance, Module* Creator) : ModeHandler(Instance, Creator, 'J', 1, 0, false, MODETYPE_CHANNEL, false) { } + SimpleExtItem<delaylist> ext; + KickRejoin(InspIRCd* Instance, Module* Creator) : ModeHandler(Instance, Creator, 'J', 1, 0, false, MODETYPE_CHANNEL, false), + ext("norejoinusers", Creator) { } ModePair ModeSet(User* source, User* dest, Channel* channel, const std::string ¶meter) { @@ -44,14 +46,7 @@ class KickRejoin : public ModeHandler { if (!adding) { - // Taking the mode off, we need to clean up. - delaylist* dl; - - if (channel->GetExt("norejoinusers", dl)) - { - delete dl; - channel->Shrink("norejoinusers"); - } + ext.unset(channel); if (!channel->IsModeSet('J')) { @@ -105,7 +100,6 @@ class KickRejoin : public ModeHandler class ModuleKickNoRejoin : public Module { - KickRejoin kr; public: @@ -115,16 +109,17 @@ public: { if (!ServerInstance->Modes->AddMode(&kr)) throw ModuleException("Could not add new modes!"); - Implementation eventlist[] = { I_OnCleanup, I_OnChannelDelete, I_OnUserPreJoin, I_OnUserKick }; - ServerInstance->Modules->Attach(eventlist, this, 4); + Extensible::Register(&kr.ext); + Implementation eventlist[] = { I_OnUserPreJoin, I_OnUserKick }; + ServerInstance->Modules->Attach(eventlist, this, 2); } - virtual ModResult OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven) + ModResult OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven) { if (chan) { - delaylist* dl; - if (chan->GetExt("norejoinusers", dl)) + delaylist* dl = kr.ext.get(chan); + if (dl) { std::vector<User*> itemstoremove; @@ -149,56 +144,34 @@ public: dl->erase(itemstoremove[i]); if (!dl->size()) - { - // Now it's empty.. - delete dl; - chan->Shrink("norejoinusers"); - } + kr.ext.unset(chan); } } return MOD_RES_PASSTHRU; } - virtual void OnUserKick(User* source, User* user, Channel* chan, const std::string &reason, bool &silent) + void OnUserKick(User* source, User* user, Channel* chan, const std::string &reason, bool &silent) { if (chan->IsModeSet('J') && (source != user)) { - delaylist* dl; - if (!chan->GetExt("norejoinusers", dl)) + delaylist* dl = kr.ext.get(chan); + if (dl) { dl = new delaylist; - chan->Extend("norejoinusers", dl); + kr.ext.set(chan, dl); } (*dl)[user] = ServerInstance->Time() + strtoint(chan->GetModeParameter('J')); } } - virtual void OnChannelDelete(Channel* chan) - { - delaylist* dl; - - if (chan->GetExt("norejoinusers", dl)) - { - delete dl; - chan->Shrink("norejoinusers"); - } - } - - virtual void OnCleanup(int target_type, void* item) - { - if(target_type == TYPE_CHANNEL) - OnChannelDelete((Channel*)item); - } - - - virtual ~ModuleKickNoRejoin() + ~ModuleKickNoRejoin() { ServerInstance->Modes->DelMode(&kr); } - virtual Version GetVersion() + Version GetVersion() { - return Version("$Id$", VF_COMMON | VF_VENDOR, API_VERSION); + return Version("Channel mode J, kick-no-rejoin", VF_COMMON | VF_VENDOR); } }; diff --git a/src/modules/m_messageflood.cpp b/src/modules/m_messageflood.cpp index da1038512..7d0f59481 100644 --- a/src/modules/m_messageflood.cpp +++ b/src/modules/m_messageflood.cpp @@ -76,12 +76,14 @@ class floodsettings : public classbase class MsgFlood : public ModeHandler { public: - MsgFlood(InspIRCd* Instance, Module* Creator) : ModeHandler(Instance, Creator, 'f', 1, 0, false, MODETYPE_CHANNEL, false) { } + SimpleExtItem<floodsettings> ext; + MsgFlood(InspIRCd* Instance, Module* Creator) : ModeHandler(Instance, Creator, 'f', 1, 0, false, MODETYPE_CHANNEL, false), + ext("messageflood", Creator) { } ModePair ModeSet(User* source, User* dest, Channel* channel, const std::string ¶meter) { - floodsettings* x; - if (channel->GetExt("flood",x)) + floodsettings* x = ext.get(channel); + if (x) return std::make_pair(true, (x->ban ? "*" : "")+ConvToStr(x->lines)+":"+ConvToStr(x->secs)); else return std::make_pair(false, parameter); @@ -89,7 +91,7 @@ class MsgFlood : public ModeHandler ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding) { - floodsettings *f; + floodsettings *f = ext.get(channel); if (adding) { @@ -132,11 +134,11 @@ class MsgFlood : public ModeHandler } else { - if (!channel->GetExt("flood", f)) + if (!f) { parameter = std::string(ban ? "*" : "") + ConvToStr(nlines) + ":" +ConvToStr(nsecs); - floodsettings *fs = new floodsettings(ServerInstance,ban,nsecs,nlines); - channel->Extend("flood",fs); + f = new floodsettings(ServerInstance,ban,nsecs,nlines); + ext.set(channel, f); channel->SetModeParam('f', parameter); return MODEACTION_ALLOW; } @@ -153,10 +155,8 @@ class MsgFlood : public ModeHandler { if ((((nlines != f->lines) || (nsecs != f->secs) || (ban != f->ban))) && (((nsecs > 0) && (nlines > 0)))) { - delete f; floodsettings *fs = new floodsettings(ServerInstance,ban,nsecs,nlines); - channel->Shrink("flood"); - channel->Extend("flood",fs); + ext.set(channel, fs); channel->SetModeParam('f', parameter); return MODEACTION_ALLOW; } @@ -177,10 +177,9 @@ class MsgFlood : public ModeHandler } else { - if (channel->GetExt("flood", f)) + if (f) { - delete f; - channel->Shrink("flood"); + ext.unset(channel); channel->SetModeParam('f', ""); return MODEACTION_ALLOW; } @@ -201,8 +200,9 @@ class ModuleMsgFlood : public Module { if (!ServerInstance->Modes->AddMode(&mf)) throw ModuleException("Could not add new modes!"); - Implementation eventlist[] = { I_OnChannelDelete, I_OnUserPreNotice, I_OnUserPreMessage }; - ServerInstance->Modules->Attach(eventlist, this, 3); + Extensible::Register(&mf.ext); + Implementation eventlist[] = { I_OnUserPreNotice, I_OnUserPreMessage }; + ServerInstance->Modules->Attach(eventlist, this, 2); } ModResult ProcessMessages(User* user,Channel* dest, const std::string &text) @@ -212,8 +212,8 @@ class ModuleMsgFlood : public Module return MOD_RES_PASSTHRU; } - floodsettings *f; - if (dest->GetExt("flood", f)) + floodsettings *f = mf.ext.get(dest); + if (f) { f->addmessage(user); if (f->shouldkick(user)) @@ -246,7 +246,7 @@ class ModuleMsgFlood : public Module return MOD_RES_PASSTHRU; } - virtual ModResult OnUserPreMessage(User *user, void *dest, int target_type, std::string &text, char status, CUList &exempt_list) + ModResult OnUserPreMessage(User *user, void *dest, int target_type, std::string &text, char status, CUList &exempt_list) { if (target_type == TYPE_CHANNEL) return ProcessMessages(user,(Channel*)dest,text); @@ -254,7 +254,7 @@ class ModuleMsgFlood : public Module return MOD_RES_PASSTHRU; } - virtual ModResult OnUserPreNotice(User *user, void *dest, int target_type, std::string &text, char status, CUList &exempt_list) + ModResult OnUserPreNotice(User *user, void *dest, int target_type, std::string &text, char status, CUList &exempt_list) { if (target_type == TYPE_CHANNEL) return ProcessMessages(user,(Channel*)dest,text); @@ -262,23 +262,12 @@ class ModuleMsgFlood : public Module return MOD_RES_PASSTHRU; } - void OnChannelDelete(Channel* chan) - { - floodsettings* f; - if (chan->GetExt("flood", f)) - { - delete f; - chan->Shrink("flood"); - } - } - - - virtual ~ModuleMsgFlood() + ~ModuleMsgFlood() { ServerInstance->Modes->DelMode(&mf); } - virtual Version GetVersion() + Version GetVersion() { return Version("$Id$", VF_COMMON | VF_VENDOR, API_VERSION); } diff --git a/src/modules/m_namesx.cpp b/src/modules/m_namesx.cpp index 3aa8ec355..d0970ef9c 100644 --- a/src/modules/m_namesx.cpp +++ b/src/modules/m_namesx.cpp @@ -19,36 +19,29 @@ class ModuleNamesX : public Module { public: - - ModuleNamesX(InspIRCd* Me) - : Module(Me) + GenericCap cap; + ModuleNamesX(InspIRCd* Me) : Module(Me), cap(this, "multi-prefix") { - Implementation eventlist[] = { I_OnSyncUser, I_OnPreCommand, I_OnNamesListItem, I_On005Numeric, I_OnEvent }; - ServerInstance->Modules->Attach(eventlist, this, 5); + Implementation eventlist[] = { I_OnPreCommand, I_OnNamesListItem, I_On005Numeric, I_OnEvent }; + ServerInstance->Modules->Attach(eventlist, this, 4); } - virtual ~ModuleNamesX() - { - } - - void OnSyncUser(User* user, Module* proto,void* opaque) + ~ModuleNamesX() { - if (proto->ProtoTranslate(NULL) == "?" && user->GetExt("NAMESX")) - proto->ProtoSendMetaData(opaque, user, "NAMESX", "Enabled"); } - virtual Version GetVersion() + Version GetVersion() { - return Version("$Id$",VF_VENDOR,API_VERSION); + return Version("$Id$",VF_VENDOR); } - virtual void On005Numeric(std::string &output) + void On005Numeric(std::string &output) { output.append(" NAMESX"); } - virtual ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, User *user, bool validated, const std::string &original_line) + ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, User *user, bool validated, const std::string &original_line) { irc::string c = command.c_str(); /* We don't actually create a proper command handler class for PROTOCTL, @@ -60,16 +53,16 @@ class ModuleNamesX : public Module { if ((parameters.size()) && (!strcasecmp(parameters[0].c_str(),"NAMESX"))) { - user->Extend("NAMESX"); + cap.ext.set(user, 1); return MOD_RES_DENY; } } return MOD_RES_PASSTHRU; } - virtual void OnNamesListItem(User* issuer, User* user, Channel* channel, std::string &prefixes, std::string &nick) + void OnNamesListItem(User* issuer, User* user, Channel* channel, std::string &prefixes, std::string &nick) { - if (!issuer->GetExt("NAMESX")) + if (!cap.ext.get(issuer)) return; /* Some module hid this from being displayed, dont bother */ @@ -79,9 +72,9 @@ class ModuleNamesX : public Module prefixes = channel->GetAllPrefixChars(user); } - virtual void OnEvent(Event *ev) + void OnEvent(Event *ev) { - GenericCapHandler(ev, "NAMESX", "multi-prefix"); + cap.HandleEvent(ev); } }; diff --git a/src/modules/m_nickflood.cpp b/src/modules/m_nickflood.cpp index 17f3a35f0..898c7358d 100644 --- a/src/modules/m_nickflood.cpp +++ b/src/modules/m_nickflood.cpp @@ -90,12 +90,14 @@ class nickfloodsettings : public classbase class NickFlood : public ModeHandler { public: - NickFlood(InspIRCd* Instance, Module* Creator) : ModeHandler(Instance, Creator, 'F', 1, 0, false, MODETYPE_CHANNEL, false) { } + SimpleExtItem<nickfloodsettings> ext; + NickFlood(InspIRCd* Instance, Module* Creator) : ModeHandler(Instance, Creator, 'F', 1, 0, false, MODETYPE_CHANNEL, false), + ext("nickflood", Creator) { } ModePair ModeSet(User* source, User* dest, Channel* channel, const std::string ¶meter) { - nickfloodsettings* x; - if (channel->GetExt("nickflood",x)) + nickfloodsettings* x = ext.get(channel); + if (x) return std::make_pair(true, ConvToStr(x->nicks)+":"+ConvToStr(x->secs)); else return std::make_pair(false, parameter); @@ -103,8 +105,7 @@ class NickFlood : public ModeHandler ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding) { - nickfloodsettings* dummy; - + nickfloodsettings *f = ext.get(channel); if (adding) { char ndata[MAXBUF]; @@ -124,7 +125,6 @@ class NickFlood : public ModeHandler else data++; } if (secs) - { /* Set up the flood parameters for this channel */ int nnicks = atoi(nicks); @@ -137,11 +137,11 @@ class NickFlood : public ModeHandler } else { - if (!channel->GetExt("nickflood", dummy)) + if (!f) { parameter = ConvToStr(nnicks) + ":" +ConvToStr(nsecs); - nickfloodsettings *f = new nickfloodsettings(ServerInstance, nsecs, nnicks); - channel->Extend("nickflood", f); + f = new nickfloodsettings(ServerInstance, nsecs, nnicks); + ext.set(channel, f); channel->SetModeParam('F', parameter); return MODEACTION_ALLOW; } @@ -159,12 +159,8 @@ class NickFlood : public ModeHandler // new mode param, replace old with new if ((nsecs > 0) && (nnicks > 0)) { - nickfloodsettings* f; - channel->GetExt("nickflood", f); - delete f; f = new nickfloodsettings(ServerInstance, nsecs, nnicks); - channel->Shrink("nickflood"); - channel->Extend("nickflood", f); + ext.set(channel, f); channel->SetModeParam('F', parameter); return MODEACTION_ALLOW; } @@ -184,12 +180,9 @@ class NickFlood : public ModeHandler } else { - if (channel->GetExt("nickflood", dummy)) + if (f) { - nickfloodsettings *f; - channel->GetExt("nickflood", f); - delete f; - channel->Shrink("nickflood"); + ext.unset(channel); channel->SetModeParam('F', ""); return MODEACTION_ALLOW; } @@ -200,20 +193,21 @@ class NickFlood : public ModeHandler class ModuleNickFlood : public Module { - NickFlood jf; + NickFlood nf; public: ModuleNickFlood(InspIRCd* Me) - : Module(Me), jf(Me, this) + : Module(Me), nf(Me, this) { - if (!ServerInstance->Modes->AddMode(&jf)) + if (!ServerInstance->Modes->AddMode(&nf)) throw ModuleException("Could not add new modes!"); - Implementation eventlist[] = { I_OnChannelDelete, I_OnUserPreNick, I_OnUserPostNick }; - ServerInstance->Modules->Attach(eventlist, this, 3); + Extensible::Register(&nf.ext); + Implementation eventlist[] = { I_OnUserPreNick, I_OnUserPostNick }; + ServerInstance->Modules->Attach(eventlist, this, 2); } - virtual ModResult OnUserPreNick(User* user, const std::string &newnick) + ModResult OnUserPreNick(User* user, const std::string &newnick) { if (isdigit(newnick[0])) /* allow switches to UID */ return MOD_RES_PASSTHRU; @@ -222,8 +216,8 @@ class ModuleNickFlood : public Module { Channel *channel = i->first; - nickfloodsettings *f; - if (channel->GetExt("nickflood", f)) + nickfloodsettings *f = nf.ext.get(channel); + if (f) { if (CHANOPS_EXEMPT(ServerInstance, 'F') && channel->GetStatus(user) == STATUS_OP) continue; @@ -250,7 +244,7 @@ class ModuleNickFlood : public Module /* * XXX: HACK: We do the increment on the *POST* event here (instead of all together) because we have no way of knowing whether other modules would block a nickchange. */ - virtual void OnUserPostNick(User* user, const std::string &oldnick) + void OnUserPostNick(User* user, const std::string &oldnick) { if (isdigit(user->nick[0])) /* allow switches to UID */ return; @@ -259,8 +253,8 @@ class ModuleNickFlood : public Module { Channel *channel = i->first; - nickfloodsettings *f; - if (channel->GetExt("nickflood", f)) + nickfloodsettings *f = nf.ext.get(channel); + if (f) { if (CHANOPS_EXEMPT(ServerInstance, 'F') && channel->GetStatus(user) == STATUS_OP) return; @@ -275,25 +269,14 @@ class ModuleNickFlood : public Module return; } - void OnChannelDelete(Channel* chan) - { - nickfloodsettings *f; - if (chan->GetExt("nickflood",f)) - { - delete f; - chan->Shrink("nickflood"); - } - } - - - virtual ~ModuleNickFlood() + ~ModuleNickFlood() { - ServerInstance->Modes->DelMode(&jf); + ServerInstance->Modes->DelMode(&nf); } - virtual Version GetVersion() + Version GetVersion() { - return Version("$Id$", VF_COMMON | VF_VENDOR, API_VERSION); + return Version("Channel mode F - nick flood protection", VF_COMMON | VF_VENDOR); } }; diff --git a/src/modules/m_nicklock.cpp b/src/modules/m_nicklock.cpp index e7c9e0199..ddfc47455 100644 --- a/src/modules/m_nicklock.cpp +++ b/src/modules/m_nicklock.cpp @@ -19,9 +19,10 @@ */ class CommandNicklock : public Command { - public: - CommandNicklock (InspIRCd* Instance, Module* Creator) : Command(Instance, Creator,"NICKLOCK", "o", 2) + LocalIntExt& locked; + CommandNicklock (Module* Creator, LocalIntExt& ext) : Command(Creator->ServerInstance, Creator,"NICKLOCK", "o", 2), + locked(ext) { syntax = "<oldnick> <newnick>"; TRANSLATE3(TR_NICK, TR_TEXT, TR_END); @@ -58,11 +59,7 @@ class CommandNicklock : public Command /* If we made it this far, extend the user */ if (target && IS_LOCAL(target)) { - // This has to be done *here*, because this metadata must be stored netwide. - target->Extend("nick_locked", "ON"); - - /* Only send out nick from local server */ - target->Extend("nick_locked"); + locked.set(target, 1); std::string oldnick = target->nick; if (target->ForceNickChange(parameters[1].c_str())) @@ -91,7 +88,9 @@ class CommandNicklock : public Command class CommandNickunlock : public Command { public: - CommandNickunlock (InspIRCd* Instance, Module* Creator) : Command(Instance, Creator,"NICKUNLOCK", "o", 1) + LocalIntExt& locked; + CommandNickunlock (Module* Creator, LocalIntExt& ext) : Command(Creator->ServerInstance, Creator,"NICKUNLOCK", "o", 1), + locked(ext) { syntax = "<locked-nick>"; TRANSLATE2(TR_NICK, TR_END); @@ -119,7 +118,7 @@ class CommandNickunlock : public Command if (target && IS_LOCAL(target)) { - if (target->Shrink("nick_locked")) + if (locked.set(target, 0)) { ServerInstance->SNO->WriteGlobalSno('a', std::string(user->nick)+" used NICKUNLOCK on "+parameters[0]); user->WriteNumeric(945, "%s %s :Nickname now unlocked.",user->nick.c_str(),target->nick.c_str()); @@ -146,29 +145,30 @@ class CommandNickunlock : public Command class ModuleNickLock : public Module { + LocalIntExt locked; CommandNicklock cmd1; CommandNickunlock cmd2; public: ModuleNickLock(InspIRCd* Me) - : Module(Me), cmd1(Me, this), cmd2(Me, this) + : Module(Me), locked("nick_locked", this), cmd1(this, locked), cmd2(this, locked) { ServerInstance->AddCommand(&cmd1); ServerInstance->AddCommand(&cmd2); - Implementation eventlist[] = { I_OnUserPreNick, I_OnUserQuit, I_OnCleanup }; - ServerInstance->Modules->Attach(eventlist, this, 3); + Extensible::Register(&locked); + ServerInstance->Modules->Attach(I_OnUserPreNick, this); } - virtual ~ModuleNickLock() + ~ModuleNickLock() { } - virtual Version GetVersion() + Version GetVersion() { return Version("$Id$", VF_COMMON | VF_VENDOR, API_VERSION); } - virtual ModResult OnUserPreNick(User* user, const std::string &newnick) + ModResult OnUserPreNick(User* user, const std::string &newnick) { if (!IS_LOCAL(user)) return MOD_RES_PASSTHRU; @@ -176,10 +176,10 @@ class ModuleNickLock : public Module if (isdigit(newnick[0])) /* Allow a switch to a UID */ return MOD_RES_PASSTHRU; - if (user->GetExt("NICKForced")) /* Allow forced nick changes */ + if (User::NICKForced.get(user)) /* Allow forced nick changes */ return MOD_RES_PASSTHRU; - if (user->GetExt("nick_locked")) + if (locked.get(user)) { user->WriteNumeric(447, "%s :You cannot change your nickname (your nick is locked)",user->nick.c_str()); return MOD_RES_DENY; @@ -187,25 +187,11 @@ class ModuleNickLock : public Module return MOD_RES_PASSTHRU; } - virtual void OnUserQuit(User* user, const std::string &reason, const std::string &oper_message) - { - user->Shrink("nick_locked"); - } - void Prioritize() { Module *nflood = ServerInstance->Modules->Find("m_nickflood.so"); ServerInstance->Modules->SetPriority(this, I_OnUserPreJoin, PRIORITY_BEFORE, &nflood); } - - virtual void OnCleanup(int target_type, void* item) - { - if(target_type == TYPE_USER) - { - User* user = (User*)item; - user->Shrink("nick_locked"); - } - } }; MODULE_INIT(ModuleNickLock) diff --git a/src/modules/m_nonicks.cpp b/src/modules/m_nonicks.cpp index 769097ca0..029ae9d2e 100644 --- a/src/modules/m_nonicks.cpp +++ b/src/modules/m_nonicks.cpp @@ -79,7 +79,7 @@ class ModuleNoNickChange : public Module return MOD_RES_PASSTHRU; // Allow forced nick changes. - if (user->GetExt("NICKForced")) + if (User::NICKForced.get(user)) return MOD_RES_PASSTHRU; for (UCListIter i = user->chans.begin(); i != user->chans.end(); i++) diff --git a/src/modules/m_regonlycreate.cpp b/src/modules/m_regonlycreate.cpp index 5be303148..c3ecef202 100644 --- a/src/modules/m_regonlycreate.cpp +++ b/src/modules/m_regonlycreate.cpp @@ -34,7 +34,7 @@ class ModuleRegOnlyCreate : public Module if (IS_OPER(user)) return MOD_RES_PASSTHRU; - if ((!user->IsModeSet('r')) && (!user->GetExt("accountname"))) + if (user->GetExtList().find("accountname") == user->GetExtList().end() && !user->IsModeSet('r')) { // XXX. there may be a better numeric for this.. user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :You must have a registered nickname to create a new channel", user->nick.c_str(), cname); diff --git a/src/modules/m_safelist.cpp b/src/modules/m_safelist.cpp index bd1a54110..127b5f304 100644 --- a/src/modules/m_safelist.cpp +++ b/src/modules/m_safelist.cpp @@ -37,19 +37,23 @@ class ModuleSafeList : public Module size_t ServerNameSize; int global_listing; int LimitList; + SimpleExtItem<ListData> listData; + LocalIntExt listTime; public: - ModuleSafeList(InspIRCd* Me) : Module(Me) + ModuleSafeList(InspIRCd* Me) : Module(Me), listData("safelist_data", this), listTime("safelist_last", this) { OnRehash(NULL); - Implementation eventlist[] = { I_OnBufferFlushed, I_OnPreCommand, I_OnCleanup, I_OnUserQuit, I_On005Numeric, I_OnRehash }; - ServerInstance->Modules->Attach(eventlist, this, 6); + Extensible::Register(&listData); + Extensible::Register(&listTime); + Implementation eventlist[] = { I_OnBufferFlushed, I_OnPreCommand, I_On005Numeric, I_OnRehash }; + ServerInstance->Modules->Attach(eventlist, this, 4); } - virtual ~ModuleSafeList() + ~ModuleSafeList() { } - virtual void OnRehash(User* user) + void OnRehash(User* user) { ConfigReader MyConf(ServerInstance); ThrottleSecs = MyConf.ReadInteger("safelist", "throttle", "60", 0, true); @@ -58,7 +62,7 @@ class ModuleSafeList : public Module global_listing = 0; } - virtual Version GetVersion() + Version GetVersion() { return Version("$Id$",VF_VENDOR,API_VERSION); } @@ -68,7 +72,7 @@ class ModuleSafeList : public Module * OnPreCommand() * Intercept the LIST command. */ - virtual ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, User *user, bool validated, const std::string &original_line) + ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, User *user, bool validated, const std::string &original_line) { /* If the command doesnt appear to be valid, we dont want to mess with it. */ if (!validated) @@ -99,8 +103,7 @@ class ModuleSafeList : public Module } /* First, let's check if the user is currently /list'ing */ - ListData *ld; - user->GetExt("safelist_cache", ld); + ListData *ld = listData.get(user); if (ld) { @@ -125,32 +128,21 @@ class ModuleSafeList : public Module } } - time_t* last_list_time; - user->GetExt("safelist_last", last_list_time); - if (last_list_time) + time_t last_list_time = listTime.get(user); + if (last_list_time && ServerInstance->Time() < last_list_time + ThrottleSecs) { - if (ServerInstance->Time() < (*last_list_time)+ThrottleSecs) - { - user->WriteServ("NOTICE %s :*** Woah there, slow down a little, you can't /LIST so often!",user->nick.c_str()); - user->WriteNumeric(321, "%s Channel :Users Name",user->nick.c_str()); - user->WriteNumeric(323, "%s :End of channel list.",user->nick.c_str()); - return MOD_RES_DENY; - } - - delete last_list_time; - user->Shrink("safelist_last"); + user->WriteServ("NOTICE %s :*** Woah there, slow down a little, you can't /LIST so often!",user->nick.c_str()); + user->WriteNumeric(321, "%s Channel :Users Name",user->nick.c_str()); + user->WriteNumeric(323, "%s :End of channel list.",user->nick.c_str()); + return MOD_RES_DENY; } - /* * start at channel 0! ;) */ ld = new ListData(0,ServerInstance->Time(), (pcnt && (parameters[0][0] != '<' && parameters[0][0] != '>')) ? parameters[0] : "*", minusers, maxusers); - user->Extend("safelist_cache", ld); - - time_t* llt = new time_t; - *llt = ServerInstance->Time(); - user->Extend("safelist_last", llt); + listData.set(user, ld); + listTime.set(user, ServerInstance->Time()); user->WriteNumeric(321, "%s Channel :Users Name",user->nick.c_str()); @@ -159,11 +151,11 @@ class ModuleSafeList : public Module return MOD_RES_DENY; } - virtual void OnBufferFlushed(User* user) + void OnBufferFlushed(User* user) { char buffer[MAXBUF]; - ListData* ld; - if (user->GetExt("safelist_cache", ld)) + ListData* ld = listData.get(user); + if (ld) { Channel* chan = NULL; unsigned long amount_sent = 0; @@ -228,46 +220,17 @@ class ModuleSafeList : public Module while ((chan != NULL) && (amount_sent < (user->MyClass->GetSendqMax() / 4))); if (ld->list_ended) { - user->Shrink("safelist_cache"); - delete ld; - global_listing--; - } - } - } - - virtual void OnCleanup(int target_type, void* item) - { - if(target_type == TYPE_USER) - { - User* u = (User*)item; - ListData* ld; - u->GetExt("safelist_cache", ld); - if (ld) - { - u->Shrink("safelist_cache"); - delete ld; + listData.unset(user); global_listing--; } - time_t* last_list_time; - u->GetExt("safelist_last", last_list_time); - if (last_list_time) - { - delete last_list_time; - u->Shrink("safelist_last"); - } } } - virtual void On005Numeric(std::string &output) + void On005Numeric(std::string &output) { output.append(" SAFELIST"); } - virtual void OnUserQuit(User* user, const std::string &message, const std::string &oper_message) - { - this->OnCleanup(TYPE_USER,user); - } - }; MODULE_INIT(ModuleSafeList) diff --git a/src/modules/m_sasl.cpp b/src/modules/m_sasl.cpp index 1436afa3d..069fbdec8 100644 --- a/src/modules/m_sasl.cpp +++ b/src/modules/m_sasl.cpp @@ -37,8 +37,6 @@ class SaslAuthenticator : public classbase SaslAuthenticator(User *user_, std::string method, InspIRCd *instance, Module *ctor) : ServerInstance(instance), user(user_), state(SASL_INIT), state_announced(false) { - this->user->Extend("sasl_authenticator", this); - parameterlist params; params.push_back("*"); params.push_back("SASL"); @@ -147,18 +145,15 @@ class SaslAuthenticator : public classbase this->state_announced = true; } - - ~SaslAuthenticator() - { - this->user->Shrink("sasl_authenticator"); - this->AnnounceState(); - } }; class CommandAuthenticate : public Command { public: - CommandAuthenticate (InspIRCd* Instance, Module* Creator) : Command(Instance, Creator, "AUTHENTICATE", 0, 1, true) + SimpleExtItem<SaslAuthenticator>& authExt; + GenericCap& cap; + CommandAuthenticate (InspIRCd* Instance, Module* Creator, SimpleExtItem<SaslAuthenticator>& ext, GenericCap& Cap) + : Command(Instance, Creator, "AUTHENTICATE", 0, 1, true), authExt(ext), cap(Cap) { } @@ -167,14 +162,17 @@ class CommandAuthenticate : public Command /* Only allow AUTHENTICATE on unregistered clients */ if (user->registered != REG_ALL) { - if (!user->GetExt("sasl")) + if (!cap.ext.get(user)) return CMD_FAILURE; - SaslAuthenticator *sasl; - if (!(user->GetExt("sasl_authenticator", sasl))) - sasl = new SaslAuthenticator(user, parameters[0], ServerInstance, creator); + SaslAuthenticator *sasl = authExt.get(user); + if (!sasl) + authExt.set(user, new SaslAuthenticator(user, parameters[0], ServerInstance, creator)); else if (sasl->SendClientMessage(parameters) == false) // IAL abort extension --nenolod - delete sasl; + { + sasl->AnnounceState(); + authExt.unset(user); + } } return CMD_FAILURE; } @@ -183,7 +181,9 @@ class CommandAuthenticate : public Command class CommandSASL : public Command { public: - CommandSASL(InspIRCd* Instance, Module* Creator) : Command(Instance, Creator, "SASL", 0, 2) + SimpleExtItem<SaslAuthenticator>& authExt; + CommandSASL(InspIRCd* Instance, Module* Creator, SimpleExtItem<SaslAuthenticator>& ext) + : Command(Instance, Creator, "SASL", 0, 2), authExt(ext) { this->disabled = true; // should not be called by users } @@ -197,15 +197,15 @@ class CommandSASL : public Command return CMD_FAILURE; } - SaslAuthenticator *sasl; - if (!target->GetExt("sasl_authenticator", sasl)) + SaslAuthenticator *sasl = authExt.get(target); + if (!sasl) return CMD_FAILURE; SaslState state = sasl->ProcessInboundMessage(parameters); if (state == SASL_DONE) { - delete sasl; - target->Shrink("sasl"); + sasl->AnnounceState(); + authExt.unset(target); } return CMD_SUCCESS; } @@ -218,12 +218,13 @@ class CommandSASL : public Command class ModuleSASL : public Module { + SimpleExtItem<SaslAuthenticator> authExt; + GenericCap cap; CommandAuthenticate auth; CommandSASL sasl; public: - ModuleSASL(InspIRCd* Me) - : Module(Me), auth(Me, this), sasl(Me, this) + : Module(Me), authExt("sasl_auth", this), cap(this, "sasl"), auth(Me, this, authExt, cap), sasl(Me, this, authExt) { Implementation eventlist[] = { I_OnEvent, I_OnUserRegister, I_OnPostConnect, I_OnUserDisconnect, I_OnCleanup }; ServerInstance->Modules->Attach(eventlist, this, 5); @@ -235,60 +236,30 @@ class ModuleSASL : public Module ServerInstance->Logs->Log("m_sasl", DEFAULT, "WARNING: m_services_account.so and m_cap.so are not loaded! m_sasl.so will NOT function correctly until these two modules are loaded!"); } - virtual ModResult OnUserRegister(User *user) + ModResult OnUserRegister(User *user) { - SaslAuthenticator *sasl_; - if (user->GetExt("sasl_authenticator", sasl_)) + SaslAuthenticator *sasl_ = authExt.get(user); + if (sasl_) { sasl_->Abort(); - delete sasl_; - user->Shrink("sasl_authenticator"); + authExt.unset(user); } return MOD_RES_PASSTHRU; } - virtual void OnCleanup(int target_type, void *item) - { - if (target_type == TYPE_USER) - OnUserDisconnect((User*)item); - } - - virtual void OnUserDisconnect(User *user) - { - SaslAuthenticator *sasl_; - if (user->GetExt("sasl_authenticator", sasl_)) - { - delete sasl_; - user->Shrink("sasl_authenticator"); - } - } - - virtual void OnPostConnect(User* user) - { - if (!IS_LOCAL(user)) - return; - - std::string* str = NULL; - - if (user->GetExt("accountname", str)) - ServerInstance->PI->SendMetaData(user, "accountname", *str); - - return; - } - - virtual ~ModuleSASL() + ~ModuleSASL() { } - virtual Version GetVersion() + Version GetVersion() { return Version("$Id$",VF_VENDOR,API_VERSION); } - virtual void OnEvent(Event *ev) + void OnEvent(Event *ev) { - GenericCapHandler(ev, "sasl", "sasl"); + cap.HandleEvent(ev); } }; diff --git a/src/modules/m_services_account.cpp b/src/modules/m_services_account.cpp index cc65038d1..cbbfac0a4 100644 --- a/src/modules/m_services_account.cpp +++ b/src/modules/m_services_account.cpp @@ -104,9 +104,11 @@ class ModuleServicesAccount : public Module AUser_R m3; Channel_r m4; User_r m5; + StringExtItem accountname; public: ModuleServicesAccount(InspIRCd* Me) : Module(Me), - m1(Me, this), m2(Me, this), m3(Me, this), m4(Me, this), m5(Me, this) + m1(Me, this), m2(Me, this), m3(Me, this), m4(Me, this), m5(Me, this), + accountname("accountname", this) { if (!ServerInstance->Modes->AddMode(&m1) || !ServerInstance->Modes->AddMode(&m2) || @@ -129,8 +131,7 @@ class ModuleServicesAccount : public Module /* <- :twisted.oscnet.org 330 w00t2 w00t2 w00t :is logged in as */ virtual void OnWhois(User* source, User* dest) { - std::string *account; - dest->GetExt("accountname", account); + std::string *account = accountname.get(dest); if (account) { @@ -161,9 +162,8 @@ class ModuleServicesAccount : public Module if (!IS_LOCAL(user)) return MOD_RES_PASSTHRU; - std::string *account; - bool is_registered = user->GetExt("accountname", account); - is_registered = is_registered && !account->empty(); + std::string *account = accountname.get(user); + bool is_registered = account && !account->empty(); if ((ServerInstance->ULine(user->nick.c_str())) || (ServerInstance->ULine(user->server))) { @@ -208,8 +208,8 @@ class ModuleServicesAccount : public Module virtual ModResult OnCheckBan(User* user, Channel* chan) { - std::string* account; - if (!user->GetExt("accountname", account)) + std::string *account = accountname.get(user); + if (!account) return MOD_RES_PASSTHRU; return chan->GetExtBanStatus(*account, 'R'); } @@ -224,9 +224,8 @@ class ModuleServicesAccount : public Module if (!IS_LOCAL(user)) return MOD_RES_PASSTHRU; - std::string *account; - bool is_registered = user->GetExt("accountname", account); - is_registered = is_registered && !account->empty(); + std::string *account = accountname.get(user); + bool is_registered = account && !account->empty(); if (chan) { @@ -249,55 +248,6 @@ class ModuleServicesAccount : public Module return MOD_RES_PASSTHRU; } - // Whenever the linking module wants to send out data, but doesnt know what the data - // represents (e.g. it is metadata, added to a User or Channel by a module) then - // this method is called. We should use the ProtoSendMetaData function after we've - // corrected decided how the data should look, to send the metadata on its way if - // it is ours. - virtual void OnSyncUser(User* user, Module* proto, void* opaque) - { - // check if this user has an swhois field to send - std::string* account; - user->GetExt("accountname", account); - if (account) - { - // remove any accidental leading/trailing spaces - trim(*account); - - // call this function in the linking module, let it format the data how it - // sees fit, and send it on its way. We dont need or want to know how. - proto->ProtoSendMetaData(opaque,user,"accountname",*account); - } - } - - // when a user quits, tidy up their metadata - virtual void OnUserQuit(User* user, const std::string &message, const std::string &oper_message) - { - std::string* account; - user->GetExt("accountname", account); - if (account) - { - user->Shrink("accountname"); - delete account; - } - } - - // if the module is unloaded, tidy up all our dangling metadata - virtual void OnCleanup(int target_type, void* item) - { - if (target_type == TYPE_USER) - { - User* user = (User*)item; - std::string* account; - user->GetExt("accountname", account); - if (account) - { - user->Shrink("accountname"); - delete account; - } - } - } - // Whenever the linking module receives metadata from another server and doesnt know what // to do with it (of course, hence the 'meta') it calls this method, and it is up to each // module in turn to figure out if this metadata key belongs to them, and what they want @@ -311,19 +261,10 @@ class ModuleServicesAccount : public Module // check if its our metadata key, and its associated with a user if (dest && (extname == "accountname")) { - std::string* account; - if (dest->GetExt("accountname", account)) { - // remove old account so that we can set new (or leave unset) - dest->Shrink("accountname"); - delete account; - } - if (!extdata.empty()) { - account = new std::string(extdata); - // remove any accidental leading/trailing spaces + std::string *account = accountname.get(dest); trim(*account); - dest->Extend("accountname", account); if (IS_LOCAL(dest)) dest->WriteNumeric(900, "%s %s %s :You are now logged in as %s", diff --git a/src/modules/m_silence.cpp b/src/modules/m_silence.cpp index 9cf9f6d4e..779cb541e 100644 --- a/src/modules/m_silence.cpp +++ b/src/modules/m_silence.cpp @@ -93,7 +93,9 @@ class CommandSilence : public Command { unsigned int& maxsilence; public: - CommandSilence (InspIRCd* Instance, Module* Creator, unsigned int &max) : Command(Instance, Creator, "SILENCE", 0, 0), maxsilence(max) + SimpleExtItem<silencelist> ext; + CommandSilence (InspIRCd* Instance, Module* Creator, unsigned int &max) : Command(Instance, Creator, "SILENCE", 0, 0), + maxsilence(max), ext("silence_list", Creator) { syntax = "{[+|-]<mask> <p|c|i|n|t|a|x>}"; TRANSLATE3(TR_TEXT, TR_TEXT, TR_END); @@ -104,9 +106,7 @@ class CommandSilence : public Command if (!parameters.size()) { // no parameters, show the current silence list. - // Use Extensible::GetExt to fetch the silence list - silencelist* sl; - user->GetExt("silence_list", sl); + silencelist* sl = ext.get(user); // if the user has a silence list associated with their user record, show it if (sl) { @@ -143,8 +143,7 @@ class CommandSilence : public Command if (action == '-') { // fetch their silence list - silencelist* sl; - user->GetExt("silence_list", sl); + silencelist* sl = ext.get(user); // does it contain any entries and does it exist? if (sl) { @@ -158,8 +157,7 @@ class CommandSilence : public Command user->WriteNumeric(950, "%s %s :Removed %s %s from silence list",user->nick.c_str(), user->nick.c_str(), mask.c_str(), DecompPattern(pattern).c_str()); if (!sl->size()) { - delete sl; - user->Shrink("silence_list"); + ext.unset(user); } return CMD_SUCCESS; } @@ -170,13 +168,11 @@ class CommandSilence : public Command else if (action == '+') { // fetch the user's current silence list - silencelist* sl; - user->GetExt("silence_list", sl); - // what, they dont have one??? WE'RE ALL GONNA DIE! ...no, we just create an empty one. + silencelist* sl = ext.get(user); if (!sl) { sl = new silencelist; - user->Extend("silence_list", sl); + ext.set(user, sl); } if (sl->size() > maxsilence) { @@ -281,11 +277,11 @@ class ModuleSilence : public Module ServerInstance->AddCommand(&cmdsilence); ServerInstance->AddCommand(&cmdsvssilence); - Implementation eventlist[] = { I_OnRehash, I_OnBuildExemptList, I_OnUserQuit, I_On005Numeric, I_OnUserPreNotice, I_OnUserPreMessage, I_OnUserPreInvite }; - ServerInstance->Modules->Attach(eventlist, this, 7); + Implementation eventlist[] = { I_OnRehash, I_OnBuildExemptList, I_On005Numeric, I_OnUserPreNotice, I_OnUserPreMessage, I_OnUserPreInvite }; + ServerInstance->Modules->Attach(eventlist, this, 6); } - virtual void OnRehash(User* user) + void OnRehash(User* user) { ConfigReader Conf(ServerInstance); maxsilence = Conf.ReadInteger("silence", "maxentries", 0, true); @@ -293,26 +289,13 @@ class ModuleSilence : public Module maxsilence = 32; } - - virtual void OnUserQuit(User* user, const std::string &reason, const std::string &oper_message) - { - // when the user quits tidy up any silence list they might have just to keep things tidy - silencelist* sl; - user->GetExt("silence_list", sl); - if (sl) - { - delete sl; - user->Shrink("silence_list"); - } - } - - virtual void On005Numeric(std::string &output) + void On005Numeric(std::string &output) { // we don't really have a limit... output = output + " ESILENCE SILENCE=" + ConvToStr(maxsilence); } - virtual void OnBuildExemptList(MessageType message_type, Channel* chan, User* sender, char status, CUList &exempt_list, const std::string &text) + void OnBuildExemptList(MessageType message_type, Channel* chan, User* sender, char status, CUList &exempt_list, const std::string &text) { int public_silence = (message_type == MSG_PRIVMSG ? SILENCE_CHANNEL : SILENCE_CNOTICE); CUList *ulist; @@ -344,7 +327,7 @@ class ModuleSilence : public Module } } - virtual ModResult PreText(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list, int silence_type) + ModResult PreText(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list, int silence_type) { if (target_type == TYPE_USER && IS_LOCAL(((User*)dest))) { @@ -361,17 +344,17 @@ class ModuleSilence : public Module return MOD_RES_PASSTHRU; } - virtual ModResult OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list) + ModResult OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list) { return PreText(user, dest, target_type, text, status, exempt_list, SILENCE_PRIVATE); } - virtual ModResult OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list) + ModResult OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list) { return PreText(user, dest, target_type, text, status, exempt_list, SILENCE_NOTICE); } - virtual ModResult OnUserPreInvite(User* source,User* dest,Channel* channel, time_t timeout) + ModResult OnUserPreInvite(User* source,User* dest,Channel* channel, time_t timeout) { return MatchPattern(dest, source, SILENCE_INVITE); } @@ -382,8 +365,7 @@ class ModuleSilence : public Module if (!source || !dest) return MOD_RES_ALLOW; - silencelist* sl; - dest->GetExt("silence_list", sl); + silencelist* sl = cmdsilence.ext.get(dest); if (sl) { for (silencelist::const_iterator c = sl->begin(); c != sl->end(); c++) @@ -395,11 +377,11 @@ class ModuleSilence : public Module return MOD_RES_PASSTHRU; } - virtual ~ModuleSilence() + ~ModuleSilence() { } - virtual Version GetVersion() + Version GetVersion() { return Version("$Id$", VF_COMMON | VF_VENDOR, API_VERSION); } diff --git a/src/modules/m_spanningtree/hmac.cpp b/src/modules/m_spanningtree/hmac.cpp index 332e47585..348a453a6 100644 --- a/src/modules/m_spanningtree/hmac.cpp +++ b/src/modules/m_spanningtree/hmac.cpp @@ -128,17 +128,22 @@ bool TreeSocket::ComparePass(const Link& link, const std::string &theirs) this->auth_fingerprint = !link.Fingerprint.empty(); this->auth_challenge = !ourchallenge.empty() && !theirchallenge.empty(); - const char* fp = NULL; + std::string fp; if (GetHook()) - fp = BufferedSocketFingerprintRequest(this, Utils->Creator, GetHook()).Send(); - - if (fp) - ServerInstance->Logs->Log("m_spanningtree", DEFAULT, std::string("Server SSL fingerprint ") + fp); + { + BufferedSocketCertificateRequest req(this, Utils->Creator, GetHook()); + req.Send(); + if (req.cert) + { + fp = req.cert->GetFingerprint(); + ServerInstance->Logs->Log("m_spanningtree", DEFAULT, std::string("Server SSL fingerprint ") + fp); + } + } if (auth_fingerprint) { /* Require fingerprint to exist and match */ - if (!fp || link.Fingerprint != std::string(fp)) + if (link.Fingerprint != fp) return false; } diff --git a/src/modules/m_spanningtree/main.cpp b/src/modules/m_spanningtree/main.cpp index 726b0713e..5e30ced35 100644 --- a/src/modules/m_spanningtree/main.cpp +++ b/src/modules/m_spanningtree/main.cpp @@ -731,7 +731,7 @@ void ModuleSpanningTree::OnRemoteKill(User* source, User* dest, const std::strin if (!IS_LOCAL(source)) return; // Only start routing if we're origin. - dest->Extend("operquit", new std::string(operreason)); + User::OperQuit.set(dest, operreason); parameterlist params; params.push_back(":"+operreason); Utils->DoOneToMany(dest->uuid,"OPERQUIT",params); diff --git a/src/modules/m_spanningtree/netburst.cpp b/src/modules/m_spanningtree/netburst.cpp index 951d019ef..abefad728 100644 --- a/src/modules/m_spanningtree/netburst.cpp +++ b/src/modules/m_spanningtree/netburst.cpp @@ -17,6 +17,7 @@ #include "treesocket.h" #include "treeserver.h" #include "utils.h" +#include "main.h" /* $ModDep: m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/treesocket.h */ @@ -46,7 +47,7 @@ void TreeSocket::DoBurst(TreeServer* s) /* Send everything else (channel modes, xlines etc) */ this->SendChannelModes(s); this->SendXLines(s); - FOREACH_MOD_I(this->ServerInstance,I_OnSyncNetwork,OnSyncNetwork((Module*)Utils->Creator,(void*)this)); + FOREACH_MOD_I(this->ServerInstance,I_OnSyncNetwork,OnSyncNetwork(Utils->Creator,(void*)this)); this->WriteLine(endburst); this->ServerInstance->SNO->WriteToSnoMask('l',"Finished bursting to \2"+name+"\2."); } @@ -218,7 +219,18 @@ void TreeSocket::SendChannelModes(TreeServer* Current) snprintf(data,MAXBUF,":%s FTOPIC %s %lu %s :%s", sn, c->second->name.c_str(), (unsigned long)c->second->topicset, c->second->setby.c_str(), c->second->topic.c_str()); this->WriteLine(data); } - FOREACH_MOD_I(this->ServerInstance,I_OnSyncChannel,OnSyncChannel(c->second,(Module*)Utils->Creator,(void*)this)); + + for(ExtensibleStore::const_iterator i = c->second->GetExtList().begin(); i != c->second->GetExtList().end(); i++) + { + ExtensionItem* item = Extensible::GetItem(i->first); + std::string value; + if (item) + value = item->serialize(Utils->Creator, c->second, i->second); + if (!value.empty()) + Utils->Creator->ProtoSendMetaData(this, c->second, i->first, value); + } + + FOREACH_MOD_I(this->ServerInstance,I_OnSyncChannel,OnSyncChannel(c->second,Utils->Creator,this)); } } @@ -259,7 +271,17 @@ void TreeSocket::SendUsers(TreeServer* Current) } } - FOREACH_MOD_I(this->ServerInstance,I_OnSyncUser,OnSyncUser(u->second,(Module*)Utils->Creator,(void*)this)); + for(ExtensibleStore::const_iterator i = u->second->GetExtList().begin(); i != u->second->GetExtList().end(); i++) + { + ExtensionItem* item = Extensible::GetItem(i->first); + std::string value; + if (item) + value = item->serialize(Utils->Creator, u->second, i->second); + if (!value.empty()) + Utils->Creator->ProtoSendMetaData(this, u->second, i->first, value); + } + + FOREACH_MOD_I(this->ServerInstance,I_OnSyncUser,OnSyncUser(u->second,Utils->Creator,this)); } } } diff --git a/src/modules/m_spanningtree/operquit.cpp b/src/modules/m_spanningtree/operquit.cpp index 5260cd990..5cdee3bc6 100644 --- a/src/modules/m_spanningtree/operquit.cpp +++ b/src/modules/m_spanningtree/operquit.cpp @@ -30,7 +30,7 @@ bool TreeSocket::OperQuit(const std::string &prefix, parameterlist ¶ms) if (u) { - u->Extend("operquit", new std::string(params[0])); + User::OperQuit.set(u, params[0]); params[0] = ":" + params[0]; Utils->DoOneToAllButSender(prefix,"OPERQUIT",params,prefix); } diff --git a/src/modules/m_sslinfo.cpp b/src/modules/m_sslinfo.cpp index 715d9110a..bf02ed879 100644 --- a/src/modules/m_sslinfo.cpp +++ b/src/modules/m_sslinfo.cpp @@ -16,12 +16,63 @@ /* $ModDesc: Provides SSL metadata, including /WHOIS information and /SSLINFO command */ +class SSLCertExt : public ExtensionItem { + public: + SSLCertExt(Module* parent) : ExtensionItem("ssl_cert", parent) {} + ssl_cert* get(const Extensible* item) + { + return static_cast<ssl_cert*>(get_raw(item)); + } + void set(Extensible* item, ssl_cert* value) + { + ssl_cert* old = static_cast<ssl_cert*>(set_raw(item, value)); + delete old; + } + + std::string serialize(Module* requestor, const Extensible* container, void* item) + { + return static_cast<ssl_cert*>(item)->GetMetaLine(); + } + + void unserialize(Module* requestor, Extensible* container, const std::string& value) + { + ssl_cert* cert = new ssl_cert; + set(container, cert); + + std::stringstream s(value); + std::string v; + getline(s,v,' '); + + cert->invalid = (v.find('v') != std::string::npos); + cert->trusted = (v.find('T') != std::string::npos); + cert->revoked = (v.find('R') != std::string::npos); + cert->unknownsigner = (v.find('s') != std::string::npos); + if (v.find('E') != std::string::npos) + { + getline(s,cert->error,'\n'); + } + else + { + getline(s,cert->fingerprint,' '); + getline(s,cert->dn,' '); + getline(s,cert->issuer,'\n'); + } + } + + void free(void* item) + { + delete static_cast<ssl_cert*>(item); + } +}; + /** Handle /SSLINFO */ class CommandSSLInfo : public Command { public: - CommandSSLInfo(InspIRCd* Instance, Module* Creator) : Command(Instance, Creator, "SSLINFO", 0, 1) + SSLCertExt CertExt; + + CommandSSLInfo(InspIRCd* Instance, Module* Creator) : Command(Instance, Creator, "SSLINFO", 0, 1), CertExt(Creator) { this->syntax = "<nick>"; } @@ -29,11 +80,11 @@ class CommandSSLInfo : public Command CmdResult Handle (const std::vector<std::string> ¶meters, User *user) { User* target = ServerInstance->FindNick(parameters[0]); - ssl_cert* cert; if (target) { - if (target->GetExt("ssl_cert", cert)) + ssl_cert* cert = CertExt.get(target); + if (cert) { if (cert->GetError().length()) { @@ -63,93 +114,36 @@ class CommandSSLInfo : public Command class ModuleSSLInfo : public Module { CommandSSLInfo cmd; + public: ModuleSSLInfo(InspIRCd* Me) : Module(Me), cmd(Me, this) { ServerInstance->AddCommand(&cmd); + Extensible::Register(&cmd.CertExt); + Implementation eventlist[] = { I_OnSyncUser, I_OnDecodeMetaData, I_OnWhois, I_OnPreCommand }; ServerInstance->Modules->Attach(eventlist, this, 4); } - virtual ~ModuleSSLInfo() { } virtual Version GetVersion() { - return Version("$Id$", VF_VENDOR, API_VERSION); - } - - virtual void OnCleanup(int target_type, void* item) - { - if (target_type != TYPE_USER) - return; - User* user = static_cast<User*>(item); - user->Shrink("ssl_cert"); + return Version("SSL Certificate Utilities", VF_VENDOR); } virtual void OnWhois(User* source, User* dest) { - if(dest->GetExt("ssl")) + if (cmd.CertExt.get(dest)) { ServerInstance->SendWhoisLine(source, dest, 320, "%s %s :is using a secure connection", source->nick.c_str(), dest->nick.c_str()); } } - virtual void OnSyncUser(User* user, Module* proto, void* opaque) - { - if (user->GetExt("ssl")) - proto->ProtoSendMetaData(opaque, user, "ssl", "ON"); - - ssl_cert* cert; - if (user->GetExt("ssl_cert", cert)) - proto->ProtoSendMetaData(opaque, user, "ssl_cert", cert->GetMetaLine().c_str()); - } - - virtual void OnDecodeMetaData(Extensible* target, const std::string &extname, const std::string &extdata) - { - User* dest = dynamic_cast<User*>(target); - // check if its our metadata key, and its associated with a user - if (dest && (extname == "ssl")) - { - // if they dont already have an ssl flag, accept the remote server's - if (!dest->GetExt(extname)) - { - dest->Extend(extname); - } - } - else if (dest && (extname == "ssl_cert")) - { - if (dest->GetExt(extname)) - return; - - ssl_cert* cert = new ssl_cert; - dest->Extend(extname, cert); - - std::stringstream s(extdata); - std::string v; - getline(s,v,' '); - - cert->invalid = (v.find('v') != std::string::npos); - cert->trusted = (v.find('T') != std::string::npos); - cert->revoked = (v.find('R') != std::string::npos); - cert->unknownsigner = (v.find('s') != std::string::npos); - if (v.find('E') != std::string::npos) - { - getline(s,cert->error,'\n'); - } - else - { - getline(s,cert->fingerprint,' '); - getline(s,cert->dn,' '); - getline(s,cert->issuer,'\n'); - } - } - } - bool OneOfMatches(const char* host, const char* ip, const char* hostlist) { std::stringstream hl(hostlist); @@ -180,13 +174,11 @@ class ModuleSSLInfo : public Module std::string HashType; std::string FingerPrint; bool SSLOnly; - ssl_cert* cert = NULL; + ssl_cert* cert = cmd.CertExt.get(user); snprintf(TheHost,MAXBUF,"%s@%s",user->ident.c_str(),user->host.c_str()); snprintf(TheIP, MAXBUF,"%s@%s",user->ident.c_str(),user->GetIPString()); - user->GetExt("ssl_cert",cert); - for (int i = 0; i < cf.Enumerate("oper"); i++) { LoginName = cf.ReadValue("oper", "name", i); @@ -209,7 +201,7 @@ class ModuleSSLInfo : public Module if (Password.length() && ServerInstance->PassCompare(user, Password.c_str(),parameters[1].c_str(), HashType.c_str())) continue; - if (SSLOnly && !user->GetExt("ssl")) + if (SSLOnly && !cert) { user->WriteNumeric(491, "%s :This oper login name requires an SSL connection.", user->nick.c_str()); return MOD_RES_DENY; @@ -232,7 +224,20 @@ class ModuleSSLInfo : public Module return MOD_RES_PASSTHRU; } - + const char* OnRequest(Request* request) + { + if (strcmp("GET_CERT", request->GetId()) == 0) + { + BufferedSocketCertificateRequest* req = static_cast<BufferedSocketCertificateRequest*>(request); + req->cert = cmd.CertExt.get(req->item); + } + else if (strcmp("SET_CERT", request->GetId()) == 0) + { + BufferedSocketFingerprintSubmission* req = static_cast<BufferedSocketFingerprintSubmission*>(request); + cmd.CertExt.set(req->item, req->cert); + } + return NULL; + } }; MODULE_INIT(ModuleSSLInfo) diff --git a/src/modules/m_sslmodes.cpp b/src/modules/m_sslmodes.cpp index b19347ea7..a07252069 100644 --- a/src/modules/m_sslmodes.cpp +++ b/src/modules/m_sslmodes.cpp @@ -12,11 +12,10 @@ */ #include "inspircd.h" +#include "transport.h" /* $ModDesc: Provides support for unreal-style channel mode +z */ -static char* dummy; - /** Handle channel mode +z */ class SSLMode : public ModeHandler @@ -35,7 +34,9 @@ class SSLMode : public ModeHandler CUList* userlist = channel->GetUsers(); for(CUList::iterator i = userlist->begin(); i != userlist->end(); i++) { - if(!i->first->GetExt("ssl", dummy) && !ServerInstance->ULine(i->first->server)) + BufferedSocketCertificateRequest req(i->first, creator, i->first->GetIOHook()); + req.Send(); + if(!req.cert && !ServerInstance->ULine(i->first->server)) { source->WriteNumeric(ERR_ALLMUSTSSL, "%s %s :all members of the channel must be connected via SSL", source->nick.c_str(), channel->name.c_str()); return MODEACTION_DENY; @@ -74,16 +75,17 @@ class ModuleSSLModes : public Module { if (!ServerInstance->Modes->AddMode(&sslm)) throw ModuleException("Could not add new modes!"); - Implementation eventlist[] = { I_OnUserPreJoin }; - ServerInstance->Modules->Attach(eventlist, this, 1); + Implementation eventlist[] = { I_OnUserPreJoin, I_OnCheckBan, I_On005Numeric }; + ServerInstance->Modules->Attach(eventlist, this, 3); } - - virtual ModResult OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven) + ModResult OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven) { if(chan && chan->IsModeSet('z')) { - if(user->GetExt("ssl", dummy)) + BufferedSocketCertificateRequest req(user, this, user->GetIOHook()); + req.Send(); + if (req.cert) { // Let them in return MOD_RES_PASSTHRU; @@ -99,12 +101,26 @@ class ModuleSSLModes : public Module return MOD_RES_PASSTHRU; } - virtual ~ModuleSSLModes() + ModResult OnCheckBan(User *user, Channel *c) + { + BufferedSocketCertificateRequest req(user, this, user->GetIOHook()); + req.Send(); + if (req.cert) + return c->GetExtBanStatus(req.cert->GetFingerprint(), 'z'); + return MOD_RES_PASSTHRU; + } + + ~ModuleSSLModes() { ServerInstance->Modes->DelMode(&sslm); } - virtual Version GetVersion() + void On005Numeric(std::string &output) + { + ServerInstance->AddExtBanChar('z'); + } + + Version GetVersion() { return Version("$Id$", VF_COMMON | VF_VENDOR, API_VERSION); } diff --git a/src/modules/m_swhois.cpp b/src/modules/m_swhois.cpp index ebff25cb8..bd2447c2a 100644 --- a/src/modules/m_swhois.cpp +++ b/src/modules/m_swhois.cpp @@ -19,9 +19,9 @@ */ class CommandSwhois : public Command { - public: - CommandSwhois (InspIRCd* Instance, Module* Creator) : Command(Instance, Creator,"SWHOIS","o",2, 2) + StringExtItem swhois; + CommandSwhois (InspIRCd* Instance, Module* Creator) : Command(Instance, Creator,"SWHOIS","o",2,2), swhois("swhois", Creator) { syntax = "<nick> :<swhois>"; TRANSLATE3(TR_NICK, TR_TEXT, TR_END); @@ -37,16 +37,13 @@ class CommandSwhois : public Command return CMD_FAILURE; } - std::string* text; - if (dest->GetExt("swhois", text)) + std::string* text = swhois.get(dest); + if (text) { // We already had it set... if (!ServerInstance->ULine(user->server)) // Ulines set SWHOISes silently ServerInstance->SNO->WriteGlobalSno('a', "%s used SWHOIS to set %s's extra whois from '%s' to '%s'", user->nick.c_str(), dest->nick.c_str(), text->c_str(), parameters[1].c_str()); - - dest->Shrink("swhois"); - delete text; } else if (!ServerInstance->ULine(user->server)) { @@ -54,8 +51,10 @@ class CommandSwhois : public Command ServerInstance->SNO->WriteGlobalSno('a', "%s used SWHOIS to set %s's extra whois to '%s'", user->nick.c_str(), dest->nick.c_str(), parameters[1].c_str()); } - text = new std::string(parameters[1]); - dest->Extend("swhois", text); + if (parameters[1].empty()) + swhois.unset(dest); + else + swhois.set(dest, parameters[1]); /* Bug #376 - feature request - * To cut down on the amount of commands services etc have to recognise, this only sends METADATA across the network now @@ -63,14 +62,7 @@ class CommandSwhois : public Command * Sorry w00t i know this was your fix, but i got bored and wanted to clear down the tracker :) * -- Brain */ - ServerInstance->PI->SendMetaData(dest, "swhois", *text); - - // If it's an empty swhois, unset it (not ideal, but ok) - if (text->empty()) - { - dest->Shrink("swhois"); - delete text; - } + ServerInstance->PI->SendMetaData(dest, "swhois", parameters[1]); return CMD_SUCCESS; } @@ -81,25 +73,14 @@ class ModuleSWhois : public Module { CommandSwhois cmd; - ConfigReader* Conf; - public: ModuleSWhois(InspIRCd* Me) : Module(Me), cmd(Me, this) { - - Conf = new ConfigReader(ServerInstance); ServerInstance->AddCommand(&cmd); - Implementation eventlist[] = { I_OnDecodeMetaData, I_OnWhoisLine, I_OnSyncUser, I_OnUserQuit, I_OnCleanup, I_OnRehash, I_OnPostCommand }; - ServerInstance->Modules->Attach(eventlist, this, 7); - } - - void OnRehash(User* user) - { - delete Conf; - Conf = new ConfigReader(ServerInstance); + Implementation eventlist[] = { I_OnWhoisLine, I_OnPostCommand }; + ServerInstance->Modules->Attach(eventlist, this, 2); } - // :kenny.chatspike.net 320 Brain Azhrarn :is getting paid to play games. ModResult OnWhoisLine(User* user, User* dest, int &numeric, std::string &text) { @@ -107,8 +88,8 @@ class ModuleSWhois : public Module if (numeric == 312) { /* Insert our numeric before 312 */ - std::string* swhois; - if (dest->GetExt("swhois", swhois)) + std::string* swhois = cmd.swhois.get(dest); + if (swhois) { ServerInstance->SendWhoisLine(user, dest, 320, "%s %s :%s",user->nick.c_str(), dest->nick.c_str(), swhois->c_str()); } @@ -118,125 +99,51 @@ class ModuleSWhois : public Module return MOD_RES_PASSTHRU; } - // Whenever the linking module wants to send out data, but doesnt know what the data - // represents (e.g. it is metadata, added to a User or Channel by a module) then - // this method is called. We should use the ProtoSendMetaData function after we've - // corrected decided how the data should look, to send the metadata on its way if - // it is ours. - virtual void OnSyncUser(User* user, Module* proto, void* opaque) - { - // check if this user has an swhois field to send - std::string* swhois; - if (user->GetExt("swhois", swhois)) - proto->ProtoSendMetaData(opaque,user,"swhois",*swhois); - } - - // when a user quits, tidy up their metadata - virtual void OnUserQuit(User* user, const std::string &message, const std::string &oper_message) - { - std::string* swhois; - if (user->GetExt("swhois", swhois)) - { - user->Shrink("swhois"); - delete swhois; - } - } - - // if the module is unloaded, tidy up all our dangling metadata - virtual void OnCleanup(int target_type, void* item) - { - if (target_type != TYPE_USER) return; - User* user = static_cast<User*>(item); - std::string* swhois; - if (user && user->GetExt("swhois", swhois)) - { - user->Shrink("swhois"); - delete swhois; - } - } - - // Whenever the linking module receives metadata from another server and doesnt know what - // to do with it (of course, hence the 'meta') it calls this method, and it is up to each - // module in turn to figure out if this metadata key belongs to them, and what they want - // to do with it. - // In our case we're only sending a single string around, so we just construct a std::string. - // Some modules will probably get much more complex and format more detailed structs and classes - // in a textual way for sending over the link. - virtual void OnDecodeMetaData(Extensible* target, const std::string &extname, const std::string &extdata) - { - User* dest = dynamic_cast<User*>(target); - // check if its our metadata key, and its associated with a user - if (extname != "swhois" || !dest) - return; - - // if they already have an swhois field, trash it and replace it with the remote one. - std::string* text; - if (dest->GetExt("swhois", text)) - { - dest->Shrink("swhois"); - delete text; - } - - if (extdata.empty()) - return; - - text = new std::string(extdata); - dest->Extend("swhois", text); - } - - virtual void OnPostCommand(const std::string &command, const std::vector<std::string> ¶ms, User *user, CmdResult result, const std::string &original_line) + void OnPostCommand(const std::string &command, const std::vector<std::string> ¶ms, User *user, CmdResult result, const std::string &original_line) { if ((command != "OPER") || (result != CMD_SUCCESS)) return; + ConfigReader Conf(ServerInstance); std::string swhois; - for (int i = 0; i < Conf->Enumerate("oper"); i++) + for (int i = 0; i < Conf.Enumerate("oper"); i++) { - std::string name = Conf->ReadValue("oper", "name", i); + std::string name = Conf.ReadValue("oper", "name", i); if (name == params[0]) { - swhois = Conf->ReadValue("oper", "swhois", i); + swhois = Conf.ReadValue("oper", "swhois", i); break; } } if (!swhois.length()) { - for (int i = 0; i < Conf->Enumerate("type"); i++) + for (int i = 0; i < Conf.Enumerate("type"); i++) { - std::string type = Conf->ReadValue("type", "name", i); + std::string type = Conf.ReadValue("type", "name", i); if (type == user->oper) { - swhois = Conf->ReadValue("type", "swhois", i); + swhois = Conf.ReadValue("type", "swhois", i); break; } } } - std::string *old; - if (user->GetExt("swhois", old)) - { - user->Shrink("swhois"); - delete old; - } - if (!swhois.length()) return; - std::string *text = new std::string(swhois); - user->Extend("swhois", text); - ServerInstance->PI->SendMetaData(user, "swhois", *text); + cmd.swhois.set(user, swhois); + ServerInstance->PI->SendMetaData(user, "swhois", swhois); } - virtual ~ModuleSWhois() + ~ModuleSWhois() { - delete Conf; } - virtual Version GetVersion() + Version GetVersion() { return Version("$Id$", VF_COMMON | VF_VENDOR, API_VERSION); } diff --git a/src/modules/m_uhnames.cpp b/src/modules/m_uhnames.cpp index c72c6f814..af8f0690f 100644 --- a/src/modules/m_uhnames.cpp +++ b/src/modules/m_uhnames.cpp @@ -18,37 +18,30 @@ class ModuleUHNames : public Module { - CUList nl; public: + GenericCap cap; - ModuleUHNames(InspIRCd* Me) - : Module(Me) + ModuleUHNames(InspIRCd* Me) : Module(Me), cap(this, "userhost-in-names") { - Implementation eventlist[] = { I_OnEvent, I_OnSyncUser, I_OnPreCommand, I_OnNamesListItem, I_On005Numeric }; + Implementation eventlist[] = { I_OnEvent, I_OnPreCommand, I_OnNamesListItem, I_On005Numeric }; ServerInstance->Modules->Attach(eventlist, this, 5); } - virtual ~ModuleUHNames() + ~ModuleUHNames() { } - void OnSyncUser(User* user, Module* proto,void* opaque) - { - if (proto->ProtoTranslate(NULL) == "?" && user->GetExt("UHNAMES")) - proto->ProtoSendMetaData(opaque, user, "UHNAMES", "Enabled"); - } - - virtual Version GetVersion() + Version GetVersion() { return Version("$Id$",VF_VENDOR,API_VERSION); } - virtual void On005Numeric(std::string &output) + void On005Numeric(std::string &output) { output.append(" UHNAMES"); } - virtual ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, User *user, bool validated, const std::string &original_line) + ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, User *user, bool validated, const std::string &original_line) { irc::string c = command.c_str(); /* We don't actually create a proper command handler class for PROTOCTL, @@ -60,16 +53,16 @@ class ModuleUHNames : public Module { if ((parameters.size()) && (!strcasecmp(parameters[0].c_str(),"UHNAMES"))) { - user->Extend("UHNAMES"); + cap.ext.set(user, 1); return MOD_RES_DENY; } } return MOD_RES_PASSTHRU; } - virtual void OnNamesListItem(User* issuer, User* user, Channel* channel, std::string &prefixes, std::string &nick) + void OnNamesListItem(User* issuer, User* user, Channel* channel, std::string &prefixes, std::string &nick) { - if (!issuer->GetExt("UHNAMES")) + if (!cap.ext.get(issuer)) return; if (nick.empty()) @@ -78,9 +71,9 @@ class ModuleUHNames : public Module nick = user->GetFullHost(); } - virtual void OnEvent(Event* ev) + void OnEvent(Event* ev) { - GenericCapHandler(ev, "UHNAMES", "userhost-in-names"); + cap.HandleEvent(ev); } }; diff --git a/src/modules/m_watch.cpp b/src/modules/m_watch.cpp index 31edcc0e2..ab32c6740 100644 --- a/src/modules/m_watch.cpp +++ b/src/modules/m_watch.cpp @@ -138,6 +138,7 @@ class CommandWatch : public Command { unsigned int& MAX_WATCH; public: + SimpleExtItem<watchlist> ext; CmdResult remove_watch(User* user, const char* nick) { // removing an item from the list @@ -147,8 +148,8 @@ class CommandWatch : public Command return CMD_FAILURE; } - watchlist* wl; - if (user->GetExt("watchlist", wl)) + watchlist* wl = ext.get(user); + if (wl) { /* Yup, is on my list */ watchlist::iterator n = wl->find(nick); @@ -168,8 +169,7 @@ class CommandWatch : public Command if (wl->empty()) { - user->Shrink("watchlist"); - delete wl; + ext.unset(user); } watchentries::iterator x = whos_watching_me->find(nick); @@ -198,11 +198,11 @@ class CommandWatch : public Command return CMD_FAILURE; } - watchlist* wl; - if (!user->GetExt("watchlist", wl)) + watchlist* wl = ext.get(user); + if (!wl) { wl = new watchlist(); - user->Extend("watchlist", wl); + ext.set(user, wl); } if (wl->size() == MAX_WATCH) @@ -248,7 +248,8 @@ class CommandWatch : public Command return CMD_SUCCESS; } - CommandWatch (InspIRCd* Instance, Module* parent, unsigned int &maxwatch) : Command(Instance,parent,"WATCH",0,0), MAX_WATCH(maxwatch) + CommandWatch (InspIRCd* Instance, Module* parent, unsigned int &maxwatch) + : Command(Instance,parent,"WATCH",0,0), MAX_WATCH(maxwatch), ext("watchlist", parent) { syntax = "[C|L|S]|[+|-<nick>]"; TRANSLATE2(TR_TEXT, TR_END); /* we watch for a nick. not a UID. */ @@ -258,8 +259,8 @@ class CommandWatch : public Command { if (parameters.empty()) { - watchlist* wl; - if (user->GetExt("watchlist", wl)) + watchlist* wl = ext.get(user); + if (wl) { for (watchlist::iterator q = wl->begin(); q != wl->end(); q++) { @@ -277,8 +278,8 @@ class CommandWatch : public Command if (!strcasecmp(nick,"C")) { // watch clear - watchlist* wl; - if (user->GetExt("watchlist", wl)) + watchlist* wl = ext.get(user); + if (wl) { for (watchlist::iterator i = wl->begin(); i != wl->end(); i++) { @@ -297,14 +298,13 @@ class CommandWatch : public Command } } - delete wl; - user->Shrink("watchlist"); + ext.unset(user); } } else if (!strcasecmp(nick,"L")) { - watchlist* wl; - if (user->GetExt("watchlist", wl)) + watchlist* wl = ext.get(user); + if (wl) { for (watchlist::iterator q = wl->begin(); q != wl->end(); q++) { @@ -325,12 +325,12 @@ class CommandWatch : public Command } else if (!strcasecmp(nick,"S")) { - watchlist* wl; + watchlist* wl = ext.get(user); int you_have = 0; int youre_on = 0; std::string list; - if (user->GetExt("watchlist", wl)) + if (wl) { for (watchlist::iterator q = wl->begin(); q != wl->end(); q++) list.append(q->first.c_str()).append(" "); @@ -375,6 +375,7 @@ class Modulewatch : public Module whos_watching_me = new watchentries(); ServerInstance->AddCommand(&cmdw); ServerInstance->AddCommand(&sw); + Extensible::Register(&cmdw.ext); Implementation eventlist[] = { I_OnRehash, I_OnGarbageCollect, I_OnCleanup, I_OnUserQuit, I_OnPostConnect, I_OnUserPostNick, I_On005Numeric, I_OnSetAway }; ServerInstance->Modules->Attach(eventlist, this, 8); } @@ -424,16 +425,16 @@ class Modulewatch : public Module { (*n)->WriteNumeric(601, "%s %s %s %s %lu :went offline", (*n)->nick.c_str() ,user->nick.c_str(), user->ident.c_str(), user->dhost.c_str(), (unsigned long) ServerInstance->Time()); - watchlist* wl; - if ((*n)->GetExt("watchlist", wl)) + watchlist* wl = cmdw.ext.get(*n); + if (wl) /* We were on somebody's notify list, set ourselves offline */ (*wl)[user->nick.c_str()] = ""; } } /* Now im quitting, if i have a notify list, im no longer watching anyone */ - watchlist* wl; - if (user->GetExt("watchlist", wl)) + watchlist* wl = cmdw.ext.get(user); + if (wl) { /* Iterate every user on my watch list, and take me out of the whos_watching_me map for each one we're watching */ for (watchlist::iterator i = wl->begin(); i != wl->end(); i++) @@ -452,10 +453,6 @@ class Modulewatch : public Module whos_watching_me->erase(i2); } } - - /* User's quitting, we're done with this. */ - delete wl; - user->Shrink("watchlist"); } } @@ -470,21 +467,6 @@ class Modulewatch : public Module delete old_watch; } - virtual void OnCleanup(int target_type, void* item) - { - if (target_type == TYPE_USER) - { - watchlist* wl; - User* user = (User*)item; - - if (user->GetExt("watchlist", wl)) - { - user->Shrink("watchlist"); - delete wl; - } - } - } - virtual void OnPostConnect(User* user) { watchentries::iterator x = whos_watching_me->find(user->nick.c_str()); @@ -494,8 +476,8 @@ class Modulewatch : public Module { (*n)->WriteNumeric(600, "%s %s %s %s %lu :arrived online", (*n)->nick.c_str(), user->nick.c_str(), user->ident.c_str(), user->dhost.c_str(), (unsigned long) user->age); - watchlist* wl; - if ((*n)->GetExt("watchlist", wl)) + watchlist* wl = cmdw.ext.get(*n); + if (wl) /* We were on somebody's notify list, set ourselves online */ (*wl)[user->nick.c_str()] = std::string(user->ident).append(" ").append(user->dhost).append(" ").append(ConvToStr(user->age)); } @@ -511,8 +493,8 @@ class Modulewatch : public Module { for (std::deque<User*>::iterator n = new_offline->second.begin(); n != new_offline->second.end(); n++) { - watchlist* wl; - if ((*n)->GetExt("watchlist", wl)) + watchlist* wl = cmdw.ext.get(*n); + if (wl) { (*n)->WriteNumeric(601, "%s %s %s %s %lu :went offline", (*n)->nick.c_str(), oldnick.c_str(), user->ident.c_str(), user->dhost.c_str(), (unsigned long) user->age); (*wl)[oldnick.c_str()] = ""; @@ -524,8 +506,8 @@ class Modulewatch : public Module { for (std::deque<User*>::iterator n = new_online->second.begin(); n != new_online->second.end(); n++) { - watchlist* wl; - if ((*n)->GetExt("watchlist", wl)) + watchlist* wl = cmdw.ext.get(*n); + if (wl) { (*wl)[user->nick.c_str()] = std::string(user->ident).append(" ").append(user->dhost).append(" ").append(ConvToStr(user->age)); (*n)->WriteNumeric(600, "%s %s %s :arrived online", (*n)->nick.c_str(), user->nick.c_str(), (*wl)[user->nick.c_str()].c_str()); diff --git a/src/modules/transport.h b/src/modules/transport.h index 9f29ab3d8..ceb16cb73 100644 --- a/src/modules/transport.h +++ b/src/modules/transport.h @@ -23,8 +23,7 @@ * Because gnutls and openssl represent key information in * wildly different ways, this class allows it to be accessed * in a unified manner. These classes are attached to ssl- - * connected local users using Extensible::Extend() and the - * key 'ssl_cert'. + * connected local users using SSLCertExt */ class ssl_cert { @@ -184,11 +183,22 @@ class BufferedSocketNameRequest : public ISHRequest } }; -class BufferedSocketFingerprintRequest : public ISHRequest +struct BufferedSocketCertificateRequest : public Request { - public: - /** Initialize request as a fingerprint message */ - BufferedSocketFingerprintRequest(BufferedSocket* is, Module* Me, Module* Target) : ISHRequest(Me, Target, "GET_FP", is) + Extensible* const item; + ssl_cert* cert; + BufferedSocketCertificateRequest(Extensible* is, Module* Me, Module* Target) + : Request(Me, Target, "GET_CERT"), item(is), cert(NULL) + { + } +}; + +struct BufferedSocketFingerprintSubmission : public Request +{ + Extensible* const item; + ssl_cert* const cert; + BufferedSocketFingerprintSubmission(Extensible* is, Module* Me, Module* Target, ssl_cert* Cert) + : Request(Me, Target, "SET_CERT"), item(is), cert(Cert) { } }; diff --git a/src/users.cpp b/src/users.cpp index 63de155b7..4940df24e 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -25,14 +25,18 @@ unsigned long uniq_id = 1; static unsigned long* already_sent = NULL; +LocalIntExt User::NICKForced("NICKForced", NULL); +LocalStringExt User::OperQuit("OperQuit", NULL); + +static bool dummy_init = Extensible::Register(&User::NICKForced) ^ Extensible::Register(&User::OperQuit); void InitializeAlreadySent(SocketEngine* SE) { + (void)dummy_init; already_sent = new unsigned long[SE->GetMaxFds()]; memset(already_sent, 0, SE->GetMaxFds() * sizeof(unsigned long)); } - std::string User::ProcessNoticeMasks(const char *sm) { bool adding = true, oldadding = false; @@ -1028,11 +1032,9 @@ bool User::ForceNickChange(const char* newnick) this->InvalidateCache(); - this->Extend("NICKForced"); - + NICKForced.set(this, 1); FIRST_MOD_RESULT(ServerInstance, OnUserPreNick, MOD_RESULT, (this, newnick)); - - this->Shrink("NICKForced"); + NICKForced.set(this, 0); if (MOD_RESULT == MOD_RES_DENY) { @@ -1046,9 +1048,9 @@ bool User::ForceNickChange(const char* newnick) { std::vector<std::string> parameters; parameters.push_back(newnick); - this->Extend("NICKForced"); + NICKForced.set(this, 1); bool result = (ServerInstance->Parser->CallHandler("NICK", parameters, this) == CMD_SUCCESS); - this->Shrink("NICKForced"); + NICKForced.set(this, 0); return result; } |