1 /* 2 * InspIRCd -- Internet Relay Chat Daemon 3 * 4 * Copyright (C) 2013, 2017-2020 Sadie Powell <sadie@witchery.services> 5 * Copyright (C) 2012, 2014-2015 Attila Molnar <attilamolnar@hush.com> 6 * Copyright (C) 2012 Robby <robby@chatbelgie.be> 7 * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org> 8 * 9 * This file is part of InspIRCd. InspIRCd is free software: you can 10 * redistribute it and/or modify it under the terms of the GNU General Public 11 * License as published by the Free Software Foundation, version 2. 12 * 13 * This program is distributed in the hope that it will be useful, but WITHOUT 14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 16 * details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 20 */ 21 22 23 #pragma once 24 25 /** DEPRECATED: use {To,From}{Human,Internal,Network} instead. */ 26 enum SerializeFormat 27 { 28 FORMAT_USER, 29 FORMAT_INTERNAL, 30 FORMAT_NETWORK, 31 FORMAT_PERSIST 32 }; 33 34 /** Base class for logic that extends an Extensible object. */ 35 class CoreExport ExtensionItem : public ServiceProvider, public usecountbase 36 { 37 public: 38 /** Types of Extensible that an ExtensionItem can apply to. */ 39 enum ExtensibleType 40 { 41 /** The ExtensionItem applies to a User object. */ 42 EXT_USER, 43 44 /** The ExtensionItem applies to a Channel object. */ 45 EXT_CHANNEL, 46 47 /** The ExtensionItem applies to a Membership object. */ 48 EXT_MEMBERSHIP 49 }; 50 51 /** The type of Extensible that this ExtensionItem applies to. */ 52 const ExtensibleType type; 53 54 /** Initializes an instance of the ExtensionItem class. 55 * @param key The name of the extension item (e.g. ssl_cert). 56 * @param exttype The type of Extensible that this ExtensionItem applies to. 57 * @param owner The module which created this ExtensionItem. 58 */ 59 ExtensionItem(const std::string& key, ExtensibleType exttype, Module* owner); 60 61 /** Destroys an instance of the ExtensionItem class. */ 62 virtual ~ExtensionItem(); 63 64 /** Sets an ExtensionItem using a value in the internal format. 65 * @param container A container the ExtensionItem should be set on. 66 * @param value A value in the internal format. 67 */ 68 virtual void FromInternal(Extensible* container, const std::string& value); 69 70 /** Sets an ExtensionItem using a value in the network format. 71 * @param container A container the ExtensionItem should be set on. 72 * @param value A value in the network format. 73 */ 74 virtual void FromNetwork(Extensible* container, const std::string& value); 75 76 /** Gets an ExtensionItem's value in a human-readable format. 77 * @param container The container the ExtensionItem is set on. 78 * @param item The value to convert to a human-readable format. 79 * @return The value specified in \p item in a human readable format. 80 */ 81 virtual std::string ToHuman(const Extensible* container, void* item) const; 82 /** Gets an ExtensionItem's value in the internal format. 83 * @param container The container the ExtensionItem is set on. 84 * @param item The value to convert to the internal format. 85 * @return The value specified in \p item in the internal format. 86 */ 87 virtual std::string ToInternal(const Extensible* container, void* item) const ; 88 89 /** Gets an ExtensionItem's value in the network format. 90 * @param container The container the ExtensionItem is set on. 91 * @param item The value to convert to the network format. 92 * @return The value specified in \p item in the network format. 93 */ 94 virtual std::string ToNetwork(const Extensible* container, void* item) const; 95 96 /** Deallocates the specified ExtensionItem value. 97 * @param container The container that the ExtensionItem is set on. 98 * @param item The item to deallocate. 99 */ 100 virtual void free(Extensible* container, void* item) = 0; 101 102 /** Registers this object with the ExtensionManager. */ 103 void RegisterService() CXX11_OVERRIDE; 104 105 /** DEPRECATED: use To{Human,Internal,Network} instead. */ 106 DEPRECATED_METHOD(virtual std::string serialize(SerializeFormat format, const Extensible* container, void* item) const); 107 108 /** DEPRECATED: use From{Internal,Network} instead. */ 109 DEPRECATED_METHOD(virtual void unserialize(SerializeFormat format, Extensible* container, const std::string& value)); 110 111 protected: 112 /** Retrieves the value for this ExtensionItem from the internal map. 113 * @param container The container that the ExtensionItem is set on. 114 * @return Either the value of this ExtensionItem or NULL if it is not set. 115 */ 116 void* get_raw(const Extensible* container) const; 117 118 /** Stores a value for this ExtensionItem in the internal map and returns the old value if one was set. 119 * @param container A container the ExtensionItem should be set on. 120 * @param value The value to set on the specified container. 121 * @return Either the old value or NULL if one is not set. 122 */ 123 void* set_raw(Extensible* container, void* value); 124 125 /** Removes the value for this ExtensionItem from the internal map and returns it. 126 * @param container A container the ExtensionItem should be removed from. 127 * @return Either the old value or NULL if one is not set. 128 */ 129 void* unset_raw(Extensible* container); 130 }; 131 132 /** class Extensible is the parent class of many classes such as User and Channel. 133 * class Extensible implements a system which allows modules to 'extend' the class by attaching data within 134 * a map associated with the object. In this way modules can store their own custom information within user 135 * objects, channel objects and server objects, without breaking other modules (this is more sensible than using 136 * a flags variable, and each module defining bits within the flag as 'theirs' as it is less prone to conflict and 137 * supports arbitrary data storage). 138 */ 139 class CoreExport Extensible 140 : public classbase 141 , public Serializable 142 { 143 public: 144 typedef insp::flat_map<reference<ExtensionItem>, void*> ExtensibleStore; 145 146 // Friend access for the protected getter/setter 147 friend class ExtensionItem; 148 private: 149 /** Private data store. 150 * Holds all extensible metadata for the class. 151 */ 152 ExtensibleStore extensions; 153 154 /** True if this Extensible has been culled. 155 * A warning is generated if false on destruction. 156 */ 157 unsigned int culled:1; 158 public: 159 /** 160 * Get the extension items for iteration (i.e. for metadata sync during netburst) 161 */ GetExtList()162 inline const ExtensibleStore& GetExtList() const { return extensions; } 163 164 Extensible(); 165 CullResult cull() CXX11_OVERRIDE; 166 virtual ~Extensible(); 167 void doUnhookExtensions(const std::vector<reference<ExtensionItem> >& toRemove); 168 169 /** 170 * Free all extension items attached to this Extensible 171 */ 172 void FreeAllExtItems(); 173 174 /** @copydoc Serializable::Deserialize */ 175 bool Deserialize(Data& data) CXX11_OVERRIDE; 176 177 /** @copydoc Serializable::Deserialize */ 178 bool Serialize(Serializable::Data& data) CXX11_OVERRIDE; 179 }; 180 181 class CoreExport ExtensionManager 182 { 183 public: 184 typedef std::map<std::string, reference<ExtensionItem> > ExtMap; 185 186 bool Register(ExtensionItem* item); 187 void BeginUnregister(Module* module, std::vector<reference<ExtensionItem> >& list); 188 ExtensionItem* GetItem(const std::string& name); 189 190 /** Get all registered extensions keyed by their names 191 * @return Const map of ExtensionItem pointers keyed by their names 192 */ GetExts()193 const ExtMap& GetExts() const { return types; } 194 195 private: 196 ExtMap types; 197 }; 198 199 /** DEPRECATED: use ExtensionItem instead. */ 200 typedef ExtensionItem LocalExtItem; 201 202 template <typename T, typename Del = stdalgo::defaultdeleter<T> > 203 class SimpleExtItem : public ExtensionItem 204 { 205 public: SimpleExtItem(const std::string & Key,ExtensibleType exttype,Module * parent)206 SimpleExtItem(const std::string& Key, ExtensibleType exttype, Module* parent) 207 : ExtensionItem(Key, exttype, parent) 208 { 209 } 210 ~SimpleExtItem()211 virtual ~SimpleExtItem() 212 { 213 } 214 get(const Extensible * container)215 inline T* get(const Extensible* container) const 216 { 217 return static_cast<T*>(get_raw(container)); 218 } 219 set(Extensible * container,const T & value)220 inline void set(Extensible* container, const T& value) 221 { 222 T* ptr = new T(value); 223 T* old = static_cast<T*>(set_raw(container, ptr)); 224 free(container, old); 225 } 226 set(Extensible * container,T * value)227 inline void set(Extensible* container, T* value) 228 { 229 T* old = static_cast<T*>(set_raw(container, value)); 230 free(container, old); 231 } 232 unset(Extensible * container)233 inline void unset(Extensible* container) 234 { 235 T* old = static_cast<T*>(unset_raw(container)); 236 free(container, old); 237 } 238 free(Extensible * container,void * item)239 void free(Extensible* container, void* item) CXX11_OVERRIDE 240 { 241 Del del; 242 del(static_cast<T*>(item)); 243 } 244 }; 245 246 class CoreExport LocalStringExt : public SimpleExtItem<std::string> 247 { 248 public: 249 LocalStringExt(const std::string& key, ExtensibleType exttype, Module* owner); 250 virtual ~LocalStringExt(); 251 std::string ToInternal(const Extensible* container, void* item) const CXX11_OVERRIDE; 252 void FromInternal(Extensible* container, const std::string& value) CXX11_OVERRIDE; 253 }; 254 255 class CoreExport LocalIntExt : public ExtensionItem 256 { 257 public: 258 LocalIntExt(const std::string& key, ExtensibleType exttype, Module* owner); 259 virtual ~LocalIntExt(); 260 std::string ToInternal(const Extensible* container, void* item) const CXX11_OVERRIDE; 261 void FromInternal(Extensible* container, const std::string& value) CXX11_OVERRIDE; 262 intptr_t get(const Extensible* container) const; 263 intptr_t set(Extensible* container, intptr_t value); unset(Extensible * container)264 void unset(Extensible* container) { set(container, 0); } 265 void free(Extensible* container, void* item) CXX11_OVERRIDE; 266 }; 267 268 class CoreExport StringExtItem : public ExtensionItem 269 { 270 public: 271 StringExtItem(const std::string& key, ExtensibleType exttype, Module* owner); 272 virtual ~StringExtItem(); 273 std::string* get(const Extensible* container) const; 274 std::string ToNetwork(const Extensible* container, void* item) const CXX11_OVERRIDE; 275 void FromNetwork(Extensible* container, const std::string& value) CXX11_OVERRIDE; 276 void set(Extensible* container, const std::string& value); 277 void unset(Extensible* container); 278 void free(Extensible* container, void* item) CXX11_OVERRIDE; 279 }; 280