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