1 /*
2  *
3  * (C) 2003-2020 Anope Team
4  * Contact us at team@anope.org
5  *
6  * Please read COPYING and README for further details.
7  *
8  * Based on the original code of Epona by Lara.
9  * Based on the original code of Services by Andy Church.
10  */
11 
12 #ifndef ANOPE_H
13 #define ANOPE_H
14 
15 #include <signal.h>
16 
17 #include "hashcomp.h"
18 
19 namespace Anope
20 {
21 	/**
22 	 * A wrapper string class around all the other string classes, this class will
23 	 * allow us to only require one type of string everywhere that can be converted
24 	 * at any time to a specific type of string.
25 	 */
26 	class CoreExport string
27 	{
28 	 private:
29 		/**
30 		 * The actual string is stored in an std::string as it can be converted to
31 		 * ci::string, or a C-style string at any time.
32 		 */
33 		std::string _string;
34 	 public:
35 		/**
36 		 * Extras.
37 		 */
38 		typedef std::string::iterator iterator;
39 		typedef std::string::const_iterator const_iterator;
40 		typedef std::string::reverse_iterator reverse_iterator;
41 		typedef std::string::const_reverse_iterator const_reverse_iterator;
42 		typedef std::string::size_type size_type;
43 		static const size_type npos = static_cast<size_type>(-1);
44 
45 		/**
46 		 * Constructors that can take in any type of string.
47 		 */
string()48 		string() : _string("") { }
string(char chr)49 		string(char chr) : _string() { _string = chr; }
string(size_type n,char chr)50 		string(size_type n, char chr) : _string(n, chr) { }
string(const char * _str)51 		string(const char *_str) : _string(_str) { }
string(const char * _str,size_type n)52 		string(const char *_str, size_type n) : _string(_str, n) { }
string(const std::string & _str)53 		string(const std::string &_str) : _string(_str) { }
string(const ci::string & _str)54 		string(const ci::string &_str) : _string(_str.c_str()) { }
55 		string(const string &_str, size_type pos, size_type n = npos) : _string(_str._string, pos, n) { }
string(InputIterator first,InputIterator last)56 		template <class InputIterator> string(InputIterator first, InputIterator last) : _string(first, last) { }
57 
58 		/**
59 		 * Assignment operators, so any type of string can be assigned to this class.
60 		 */
61 		inline string &operator=(char chr) { this->_string = chr; return *this; }
62 		inline string &operator=(const char *_str) { this->_string = _str; return *this; }
63 		inline string &operator=(const std::string &_str) { this->_string = _str; return *this; }
64 		inline string &operator=(const string &_str) { if (this != &_str) this->_string = _str._string; return *this; }
65 
66 		/**
67 		 * Equality operators, to compare to any type of string.
68 		 */
69 		inline bool operator==(const char *_str) const { return this->_string == _str; }
70 		inline bool operator==(const std::string &_str) const { return this->_string == _str; }
71 		inline bool operator==(const string &_str) const { return this->_string == _str._string; }
72 
equals_cs(const char * _str)73 		inline bool equals_cs(const char *_str) const { return this->_string == _str; }
equals_cs(const std::string & _str)74 		inline bool equals_cs(const std::string &_str) const { return this->_string == _str; }
equals_cs(const string & _str)75 		inline bool equals_cs(const string &_str) const { return this->_string == _str._string; }
76 
equals_ci(const char * _str)77 		inline bool equals_ci(const char *_str) const { return ci::string(this->_string.c_str()) == _str; }
equals_ci(const std::string & _str)78 		inline bool equals_ci(const std::string &_str) const { return ci::string(this->_string.c_str()) == _str.c_str(); }
equals_ci(const string & _str)79 		inline bool equals_ci(const string &_str) const { return ci::string(this->_string.c_str()) == _str._string.c_str(); }
80 
81 		/**
82 		 * Inequality operators, exact opposites of the above.
83 		 */
84 		inline bool operator!=(const char *_str) const { return !operator==(_str); }
85 		inline bool operator!=(const std::string &_str) const { return !operator==(_str); }
86 		inline bool operator!=(const string &_str) const { return !operator==(_str); }
87 
88 		/**
89 		 * Compound addition operators, overloaded to do concatenation.
90 		 */
91 		inline string &operator+=(char chr) { this->_string += chr; return *this; }
92 		inline string &operator+=(const char *_str) { this->_string += _str; return *this; }
93 		inline string &operator+=(const std::string &_str) { this->_string += _str; return *this; }
94 		inline string &operator+=(const string &_str) { if (this != &_str) this->_string += _str._string; return *this; }
95 
96 		/**
97 		 * Addition operators, overloaded to do concatenation.
98 		 */
99 		inline const string operator+(char chr) const { return string(*this) += chr; }
100 		inline const string operator+(const char *_str) const { return string(*this) += _str; }
101 		inline const string operator+(const std::string &_str) const { return string(*this) += _str; }
102 		inline const string operator+(const string &_str) const { return string(*this) += _str; }
103 
104 		friend const string operator+(char chr, const string &str);
105 		friend const string operator+(const char *_str, const string &str);
106 		friend const string operator+(const std::string &_str, const string &str);
107 
108 		/**
109 		 * Less-than operator.
110 		 */
111 		inline bool operator<(const string &_str) const { return this->_string < _str._string; }
112 
113 		/**
114 		 * The following functions return the various types of strings.
115 		 */
c_str()116 		inline const char *c_str() const { return this->_string.c_str(); }
data()117 		inline const char *data() const { return this->_string.data(); }
str()118 		inline std::string &str() { return this->_string; }
str()119 		inline const std::string &str() const { return this->_string; }
ci_str()120 		inline ci::string ci_str() const { return ci::string(this->_string.c_str()); }
121 
122 		/**
123 		 * Returns if the string is empty or not.
124 		 */
empty()125 		inline bool empty() const { return this->_string.empty(); }
126 
127 		/**
128 		 * Returns the string's length.
129 		 */
length()130 		inline size_type length() const { return this->_string.length(); }
131 
132 		/**
133 		 * Returns the size of the currently allocated storage space in the string object.
134 		 * This can be equal or greater than the length of the string.
135 		 */
capacity()136 		inline size_type capacity() const { return this->_string.capacity(); }
137 
138 		/**
139 		 * Add a char to the end of the string.
140 		 */
push_back(char c)141 		inline void push_back(char c) { return this->_string.push_back(c); }
142 
append(const string & s)143 		inline string& append(const string &s) { this->_string.append(s.str()); return *this; }
append(const char * s,size_t n)144 		inline string& append(const char *s, size_t n) { this->_string.append(s, n); return *this; }
145 
146 		/**
147 		 * Resizes the string content to n characters.
148 		 */
resize(size_type n)149 		inline void resize(size_type n) { return this->_string.resize(n); }
150 
151 		/**
152 		 * Erases characters from the string.
153 		 */
erase(const iterator & i)154 		inline iterator erase(const iterator &i) { return this->_string.erase(i); }
erase(const iterator & first,const iterator & last)155 		inline iterator erase(const iterator &first, const iterator &last) { return this->_string.erase(first, last); }
156 		inline void erase(size_type pos = 0, size_type n = std::string::npos) { this->_string.erase(pos, n); }
157 
158 		/**
159 		 * Trim leading and trailing white spaces from the string.
160 		 */
161 
162 		inline string& ltrim(const Anope::string &what = " \t\r\n")
163 		{
164 			while (!this->_string.empty() && what.find(this->_string[0]) != Anope::string::npos)
165 				this->_string.erase(this->_string.begin());
166 			return *this;
167 		}
168 
169 		inline string& rtrim(const Anope::string &what = " \t\r\n")
170 		{
171 			while (!this->_string.empty() && what.find(this->_string[this->_string.length() - 1]) != Anope::string::npos)
172 				this->_string.erase(this->_string.length() - 1);
173 			return *this;
174 		}
175 
176 		inline string& trim(const Anope::string &what = " \t\r\n")
177 		{
178 			this->ltrim(what);
179 			this->rtrim(what);
180 			return *this;
181 		}
182 
183 		/**
184 		 * Clears the string.
185 		 */
clear()186 		inline void clear() { this->_string.clear(); }
187 
188 		/**
189 		 * Find substrings of the string.
190 		 */
191 		inline size_type find(const string &_str, size_type pos = 0) const { return this->_string.find(_str._string, pos); }
192 		inline size_type find(char chr, size_type pos = 0) const { return this->_string.find(chr, pos); }
193 		inline size_type find_ci(const string &_str, size_type pos = 0) const { return ci::string(this->_string.c_str()).find(ci::string(_str._string.c_str()), pos); }
194 		inline size_type find_ci(char chr, size_type pos = 0) const { return ci::string(this->_string.c_str()).find(chr, pos); }
195 
196 		inline size_type rfind(const string &_str, size_type pos = npos) const { return this->_string.rfind(_str._string, pos); }
197 		inline size_type rfind(char chr, size_type pos = npos) const { return this->_string.rfind(chr, pos); }
198 		inline size_type rfind_ci(const string &_str, size_type pos = npos) const { return ci::string(this->_string.c_str()).rfind(ci::string(_str._string.c_str()), pos); }
199 		inline size_type rfind_ci(char chr, size_type pos = npos) const { return ci::string(this->_string.c_str()).rfind(chr, pos); }
200 
201 		inline size_type find_first_of(const string &_str, size_type pos = 0) const { return this->_string.find_first_of(_str._string, pos); }
202 		inline size_type find_first_of_ci(const string &_str, size_type pos = 0) const { return ci::string(this->_string.c_str()).find_first_of(ci::string(_str._string.c_str()), pos); }
203 
204 		inline size_type find_first_not_of(const string &_str, size_type pos = 0) const { return this->_string.find_first_not_of(_str._string, pos); }
205 		inline size_type find_first_not_of_ci(const string &_str, size_type pos = 0) const { return ci::string(this->_string.c_str()).find_first_not_of(ci::string(_str._string.c_str()), pos); }
206 
207 		inline size_type find_last_of(const string &_str, size_type pos = npos) const { return this->_string.find_last_of(_str._string, pos); }
208 		inline size_type find_last_of_ci(const string &_str, size_type pos = npos) const { return ci::string(this->_string.c_str()).find_last_of(ci::string(_str._string.c_str()), pos); }
209 
210 		inline size_type find_last_not_of(const string &_str, size_type pos = npos) const { return this->_string.find_last_not_of(_str._string, pos); }
211 		inline size_type find_last_not_of_ci(const string &_str, size_type pos = npos) const { return ci::string(this->_string.c_str()).find_last_not_of(ci::string(_str._string.c_str()), pos); }
212 
213 		/**
214 		 * Determine if string consists of only numbers.
215 		 */
is_number_only()216 		inline bool is_number_only() const { return this->find_first_not_of("0123456789.-") == npos; }
is_pos_number_only()217 		inline bool is_pos_number_only() const { return this->find_first_not_of("0123456789.") == npos; }
218 
219 		/**
220 		 * Replace parts of the string.
221 		 */
replace(size_type pos,size_type n,const string & _str)222 		inline string replace(size_type pos, size_type n, const string &_str) { return string(this->_string.replace(pos, n, _str._string)); }
replace(size_type pos,size_type n,const string & _str,size_type pos1,size_type n1)223 		inline string replace(size_type pos, size_type n, const string &_str, size_type pos1, size_type n1) { return string(this->_string.replace(pos, n, _str._string, pos1, n1)); }
replace(size_type pos,size_type n,size_type n1,char chr)224 		inline string replace(size_type pos, size_type n, size_type n1, char chr) { return string(this->_string.replace(pos, n, n1, chr)); }
replace(iterator first,iterator last,const string & _str)225 		inline string replace(iterator first, iterator last, const string &_str) { return string(this->_string.replace(first, last, _str._string)); }
replace(iterator first,iterator last,size_type n,char chr)226 		inline string replace(iterator first, iterator last, size_type n, char chr) { return string(this->_string.replace(first, last, n, chr)); }
replace(iterator first,iterator last,InputIterator f,InputIterator l)227 		template <class InputIterator> inline string replace(iterator first, iterator last, InputIterator f, InputIterator l) { return string(this->_string.replace(first, last, f, l)); }
replace_all_cs(const string & _orig,const string & _repl)228 		inline string replace_all_cs(const string &_orig, const string &_repl) const
229 		{
230 			Anope::string new_string = *this;
231 			size_type pos = new_string.find(_orig), orig_length = _orig.length(), repl_length = _repl.length();
232 			while (pos != npos)
233 			{
234 				new_string = new_string.substr(0, pos) + _repl + new_string.substr(pos + orig_length);
235 				pos = new_string.find(_orig, pos + repl_length);
236 			}
237 			return new_string;
238 		}
replace_all_ci(const string & _orig,const string & _repl)239 		inline string replace_all_ci(const string &_orig, const string &_repl) const
240 		{
241 			Anope::string new_string = *this;
242 			size_type pos = new_string.find_ci(_orig), orig_length = _orig.length(), repl_length = _repl.length();
243 			while (pos != npos)
244 			{
245 				new_string = new_string.substr(0, pos) + _repl + new_string.substr(pos + orig_length);
246 				pos = new_string.find_ci(_orig, pos + repl_length);
247 			}
248 			return new_string;
249 		}
250 
251 		/**
252 		 * Get the string in lowercase.
253 		 */
lower()254 		inline string lower() const
255 		{
256 			Anope::string new_string = *this;
257 			for (size_type i = 0; i < new_string.length(); ++i)
258 				new_string[i] = Anope::tolower(new_string[i]);
259 			return new_string;
260 		}
261 
262 		/**
263 		 * Get the string in uppercase.
264 		 */
upper()265 		inline string upper() const
266 		{
267 			Anope::string new_string = *this;
268 			for (size_type i = 0; i < new_string.length(); ++i)
269 				new_string[i] = Anope::toupper(new_string[i]);
270 			return new_string;
271 		}
272 
273 		/**
274 		 * Get a substring of the string.
275 		 */
276 		inline string substr(size_type pos = 0, size_type n = npos) const { return string(this->_string.substr(pos, n)); }
277 
278 		/**
279 		 * Iterators to the string.
280 		 */
begin()281 		inline iterator begin() { return this->_string.begin(); }
begin()282 		inline const_iterator begin() const { return this->_string.begin(); }
end()283 		inline iterator end() { return this->_string.end(); }
end()284 		inline const_iterator end() const { return this->_string.end(); }
rbegin()285 		inline reverse_iterator rbegin() { return this->_string.rbegin(); }
rbegin()286 		inline const_reverse_iterator rbegin() const { return this->_string.rbegin(); }
rend()287 		inline reverse_iterator rend() { return this->_string.rend(); }
rend()288 		inline const_reverse_iterator rend() const { return this->_string.rend(); }
289 
290 		/**
291 		 * Subscript operator, to access individual characters of the string.
292 		 */
293 		inline char &operator[](size_type n) { return this->_string[n]; }
294 		inline const char &operator[](size_type n) const { return this->_string[n]; }
295 
296 		/**
297 		 * Stream insertion operator, must be friend because they cannot be inside the class.
298 		 */
299 		friend std::ostream &operator<<(std::ostream &os, const string &_str);
300 		friend std::istream &operator>>(std::istream &is, string &_str);
301 	};
302 
303 	inline std::ostream &operator<<(std::ostream &os, const string &_str) { return os << _str._string; }
304 	/* This is not standard to make operator>> behave like operator<< in that it will allow extracting a whole line, not just one word */
305 	inline std::istream &operator>>(std::istream &is, string &_str) { return std::getline(is,  _str._string); }
306 
307 	inline const string operator+(char chr, const string &str) { string tmp(chr); tmp += str; return tmp; }
308 	inline const string operator+(const char *_str, const string &str) { string tmp(_str); tmp += str; return tmp; }
309 	inline const string operator+(const std::string &_str, const string &str) { string tmp(_str); tmp += str; return tmp; }
310 
311 	struct hash_ci
312 	{
operatorhash_ci313 		inline size_t operator()(const string &s) const
314 		{
315 			return TR1NS::hash<std::string>()(s.lower().str());
316 		}
317 	};
318 
319 	struct hash_cs
320 	{
operatorhash_cs321 		inline size_t operator()(const string &s) const
322 		{
323 			return TR1NS::hash<std::string>()(s.str());
324 		}
325 	};
326 
327 	struct compare
328 	{
operatorcompare329 		inline bool operator()(const string &s1, const string &s2) const
330 		{
331 			return s1.equals_ci(s2);
332 		}
333 	};
334 
335 	template<typename T> class map : public std::map<string, T, ci::less> { };
336 	template<typename T> class multimap : public std::multimap<string, T, ci::less> { };
337 	template<typename T> class hash_map : public TR1NS::unordered_map<string, T, hash_ci, compare> { };
338 
339 #ifndef REPRODUCIBLE_BUILD
340 	static const char *const compiled = __TIME__ " " __DATE__;
341 #endif
342 
343 	/** The time Anope started.
344 	 */
345 	extern CoreExport time_t StartTime;
346 
347 	/** The value to return from main()
348 	 */
349 	extern int ReturnValue;
350 
351 	extern sig_atomic_t Signal;
352 	extern CoreExport bool Quitting;
353 	extern CoreExport bool Restarting;
354 	extern CoreExport Anope::string QuitReason;
355 
356 	/** The current system time, which is pretty close to being accurate.
357 	 * Use this unless you need very specific time checks
358 	 */
359 	extern CoreExport time_t CurTime;
360 
361 	/** The debug level we are running at.
362 	 */
363 	extern CoreExport int Debug;
364 
365 	/** Other comand line options.
366 	 */
367 	extern CoreExport bool ReadOnly, NoFork, NoThird, NoExpire, ProtocolDebug;
368 
369 	/** The root of the services installation. Usually ~/services
370 	 */
371 	extern CoreExport Anope::string ServicesDir;
372 
373 	/** Services binary name (eg services)
374 	 */
375 	extern CoreExport Anope::string ServicesBin;
376 
377 	/** Various directory paths. These can be set at runtime by command line args
378 	 */
379 	extern CoreExport Anope::string ConfigDir;
380 	extern CoreExport Anope::string DataDir;
381 	extern CoreExport Anope::string ModuleDir;
382 	extern CoreExport Anope::string LocaleDir;
383 	extern CoreExport Anope::string LogDir;
384 
385 	/** The uplink we are currently connected to
386 	 */
387 	extern CoreExport int CurrentUplink;
388 
389 	/** Various methods to determine the Anope version running
390 	 */
391 	extern CoreExport string Version();
392 	extern CoreExport string VersionShort();
393 	extern CoreExport string VersionBuildString();
394 	extern CoreExport int VersionMajor();
395 	extern CoreExport int VersionMinor();
396 	extern CoreExport int VersionPatch();
397 
398 	/** Determines if we are still attached to the terminal, and can print
399 	 * messages to the user via stderr/stdout.
400 	 * @return true if still attached
401 	 */
402 	extern bool AtTerm();
403 
404 	/** Used to "fork" the process and go into the background during initial startup
405 	 * while we are AtTerm(). The actual fork is not done here, but earlier, and this
406 	 * simply notifys the parent via kill() to exit().
407 	 */
408 	extern void Fork();
409 
410 	/** Does something with the signal in Anope::Signal
411 	 */
412 	extern void HandleSignal();
413 
414 	/** One of the first functions called, does general initialization such as reading
415 	 * command line args, loading the configuration, doing the initial fork() if necessary,
416 	 * initializating language support, loading modules, and loading databases.
417 	 * @throws CoreException if something bad went wrong
418 	 */
419 	extern void Init(int ac, char **av);
420 
421 	/** Calls the save database event
422 	 */
423 	extern CoreExport void SaveDatabases();
424 
425 	/** Check whether two strings match.
426 	 * @param str The string to check against the pattern (e.g. foobar)
427 	 * @param mask The pattern to check (e.g. foo*bar)
428 	 * @param case_sensitive Whether or not the match is case sensitive, default false.
429 	 * @param use_regex Whether or not to try regex. case_sensitive is not used in regex.
430 	 */
431 	extern CoreExport bool Match(const string &str, const string &mask, bool case_sensitive = false, bool use_regex = false);
432 
433 	/** Converts a string to hex
434 	 * @param the data to be converted
435 	 * @return a anope::string containing the hex value
436 	 */
437 	extern CoreExport string Hex(const string &data);
438 	extern CoreExport string Hex(const char *data, unsigned len);
439 
440 	/** Converts a string from hex
441 	 * @param src The data to be converted
442 	 * @param dest The destination string
443 	 */
444 	extern CoreExport void Unhex(const string &src, string &dest);
445 	extern CoreExport void Unhex(const string &src, char *dest, size_t sz);
446 
447 	/** Base 64 encode a string
448 	 * @param src The string to encode
449 	 * @param target Where the encoded string is placed
450 	 */
451 	extern CoreExport void B64Encode(const string &src, string &target);
452 
453 	/** Base 64 decode a string
454 	 * @param src The base64 encoded string
455 	 * @param target The plain text result
456 	 */
457 	extern CoreExport void B64Decode(const string &src, string &target);
458 
459 	/** Encrypts what is in 'src' to 'dest'
460 	 * @param src The source string to encrypt
461 	 * @param dest The destination where the encrypted string is placed
462 	 */
463 	extern CoreExport void Encrypt(const Anope::string &src, Anope::string &dest);
464 
465 	/** Decrypts what is in 'src' to 'dest'.
466 	 * @param src The source string to decrypt
467 	 * @param dest The destination where the decrypted string is placed
468 	 * @return true if decryption was successful. This is usually not the case
469 	 * as most encryption methods we use are one way.
470 	 */
471 	extern CoreExport bool Decrypt(const Anope::string &src, Anope::string &dest);
472 
473 	/** Hashes a buffer with SipHash-2-4
474 	 * @param src The start of the buffer to hash
475 	 * @param src_sz The total number of bytes in the buffer
476 	 * @param key A 16 byte key to hash the buffer with.
477 	 */
478 	extern CoreExport uint64_t SipHash24(const void *src, unsigned long src_sz, const char key[16]);
479 
480 	/** Returns a sequence of data formatted as the format argument specifies.
481 	 ** After the format parameter, the function expects at least as many
482 	 ** additional arguments as specified in format.
483 	 * @param fmt Format of the Message
484 	 * @param ... any number of parameters
485 	 * @return a Anope::string
486 	 */
487 	extern CoreExport string printf(const char *fmt, ...);
488 
489 	/** Return the last error code
490 	 * @return The error code
491 	 */
492 	extern CoreExport int LastErrorCode();
493 
494 	/** Return the last error, uses errno/GetLastError() to determine this
495 	 * @return An error message
496 	 */
497 	extern CoreExport const string LastError();
498 
499 	/** Determines if a path is a file
500 	 */
501 	extern CoreExport bool IsFile(const Anope::string &file);
502 
503 	/** Converts a string into seconds
504 	 * @param s The string, eg 3d
505 	 * @return The time represented by the string, eg 259,200
506 	 */
507 	extern CoreExport time_t DoTime(const Anope::string &s);
508 
509 	/** Retrieves a human readable string representing the time in seconds
510 	 * @param seconds The time on seconds, eg 60
511 	 * @param nc The account to use language settings for to translate this string, if applicable
512 	 * @return A human readable string, eg "1 minute"
513 	 */
514 	extern CoreExport Anope::string Duration(time_t seconds, const NickCore *nc = NULL);
515 
516 	/** Generates a human readable string of type "expires in ..."
517 	 * @param expires time in seconds
518 	 * @param nc The account to use language settings for to translate this string, if applicable
519 	 * @return A human readable string, eg "expires in 5 days"
520 	 */
521 	extern CoreExport Anope::string Expires(time_t seconds, const NickCore *nc = NULL);
522 
523 	/** Converts a time in seconds (epoch) to a human readable format.
524 	 * @param t The time
525 	 * @param nc The account to use language settings for to translate this string, if applicable
526 	 * @param short_output If true, the output is just a date (eg, "Apr 12 20:18:22 2009 MSD"), else it includes the date and how long ago/from now that date is, (eg "Apr 12 20:18:22 2009 MSD (1313 days, 9 hours, 32 minutes ago)"
527 	 */
528 	extern CoreExport Anope::string strftime(time_t t, const NickCore *nc = NULL, bool short_output = false);
529 
530 	/** Normalize buffer, stripping control characters and colors
531 	 * @param A string to be parsed for control and color codes
532 	 * @return A string stripped of control and color codes
533 	 */
534 	extern CoreExport Anope::string NormalizeBuffer(const Anope::string &);
535 
536 	/** Main processing routine. Parses the message and takes the appropriate action.
537 	 * @param Raw message from the uplink
538 	 */
539 	extern void Process(const Anope::string &);
540 
541 	/** Does a blocking dns query and returns the first IP.
542 	 * @param host host to look up
543 	 * @param type inet addr type
544 	 * @return the IP if it was found, else the host
545 	 */
546 	extern Anope::string Resolve(const Anope::string &host, int type);
547 
548 	/** Generate a string of random letters and numbers
549 	 * @param len The length of the string returned
550 	 */
551 	extern CoreExport Anope::string Random(size_t len);
552 }
553 
554 /** sepstream allows for splitting token separated lists.
555  * Each successive call to sepstream::GetToken() returns
556  * the next token, until none remain, at which point the method returns
557  * an empty string.
558  */
559 class CoreExport sepstream
560 {
561  private:
562 	/** Original string.
563 	 */
564 	Anope::string tokens;
565 	/** Seperator value
566 	 */
567 	char sep;
568 	/** Current string position
569 	 */
570 	size_t pos;
571 	/** If set then GetToken() can return an empty string
572 	 */
573 	bool allow_empty;
574  public:
575 	/** Create a sepstream and fill it with the provided data
576 	 */
577 	sepstream(const Anope::string &source, char seperator, bool allowempty = false);
578 
579 	/** Fetch the next token from the stream
580 	 * @param token The next token from the stream is placed here
581 	 * @return True if tokens still remain, false if there are none left
582 	 */
583 	bool GetToken(Anope::string &token);
584 
585 	/** Gets token number 'num' from the stream
586 	 * @param token The token is placed here
587 	 * @param num The token number to featch
588 	 * @return True if the token was able to be fetched
589 	 */
590 	bool GetToken(Anope::string &token, int num);
591 
592 	/** Gets every token from this stream
593 	 * @param token Tokens are pushed back here
594 	 */
GetTokens(T & token)595 	template<typename T> void GetTokens(T& token)
596 	{
597 		token.clear();
598 		Anope::string t;
599 		while (this->GetToken(t))
600 			token.push_back(t);
601 	}
602 
603 	/** Gets token number 'num' from the stream and all remaining tokens.
604 	 * @param token The token is placed here
605 	 * @param num The token number to featch
606 	 * @return True if the token was able to be fetched
607 	 */
608 	bool GetTokenRemainder(Anope::string &token, int num);
609 
610 	/** Determines the number of tokens in this stream.
611 	 * @return The number of tokens in this stream
612 	 */
613 	int NumTokens();
614 
615 	/** Fetch the entire remaining stream, without tokenizing
616 	 * @return The remaining part of the stream
617 	 */
618 	const Anope::string GetRemaining();
619 
620 	/** Returns true if the end of the stream has been reached
621 	 * @return True if the end of the stream has been reached, otherwise false
622 	 */
623 	bool StreamEnd();
624 };
625 
626 /** A derived form of sepstream, which separates on commas
627  */
628 class commasepstream : public sepstream
629 {
630  public:
631 	/** Initialize with comma seperator
632 	 */
633 	commasepstream(const Anope::string &source, bool allowempty = false) : sepstream(source, ',', allowempty) { }
634 };
635 
636 /** A derived form of sepstream, which separates on spaces
637  */
638 class spacesepstream : public sepstream
639 {
640  public:
641 	/** Initialize with space seperator
642 	 */
spacesepstream(const Anope::string & source)643 	spacesepstream(const Anope::string &source) : sepstream(source, ' ') { }
644 };
645 
646 /** This class can be used on its own to represent an exception, or derived to represent a module-specific exception.
647  * When a module whishes to abort, e.g. within a constructor, it should throw an exception using ModuleException or
648  * a class derived from ModuleException. If a module throws an exception during its constructor, the module will not
649  * be loaded. If this happens, the error message returned by ModuleException::GetReason will be displayed to the user
650  * attempting to load the module, or dumped to the console if the ircd is currently loading for the first time.
651  */
652 class CoreException : public std::exception
653 {
654  protected:
655 	/** Holds the error message to be displayed
656 	 */
657 	Anope::string err;
658 	/** Source of the exception
659 	 */
660 	Anope::string source;
661  public:
662 	/** Default constructor, just uses the error mesage 'Core threw an exception'.
663 	 */
CoreException()664 	CoreException() : err("Core threw an exception"), source("The core") { }
665 	/** This constructor can be used to specify an error message before throwing.
666 	 */
CoreException(const Anope::string & message)667 	CoreException(const Anope::string &message) : err(message), source("The core") { }
668 	/** This constructor can be used to specify an error message before throwing,
669 	 * and to specify the source of the exception.
670 	 */
CoreException(const Anope::string & message,const Anope::string & src)671 	CoreException(const Anope::string &message, const Anope::string &src) : err(message), source(src) { }
672 	/** This destructor solves world hunger, cancels the world debt, and causes the world to end.
673 	 * Actually no, it does nothing. Never mind.
674 	 * @throws Nothing!
675 	 */
~CoreException()676 	virtual ~CoreException() throw() { }
677 	/** Returns the reason for the exception.
678 	 * The module should probably put something informative here as the user will see this upon failure.
679 	 */
GetReason()680 	virtual const Anope::string &GetReason() const
681 	{
682 		return err;
683 	}
684 
GetSource()685 	virtual const Anope::string &GetSource() const
686 	{
687 		return source;
688 	}
689 };
690 
691 class ModuleException : public CoreException
692 {
693  public:
694 	/** Default constructor, just uses the error mesage 'Module threw an exception'.
695 	 */
ModuleException()696 	ModuleException() : CoreException("Module threw an exception", "A Module") { }
697 
698 	/** This constructor can be used to specify an error message before throwing.
699 	 */
ModuleException(const Anope::string & message)700 	ModuleException(const Anope::string &message) : CoreException(message, "A Module") { }
701 	/** This destructor solves world hunger, cancels the world debt, and causes the world to end.
702 	 * Actually no, it does nothing. Never mind.
703 	 * @throws Nothing!
704 	 */
~ModuleException()705 	virtual ~ModuleException() throw() { }
706 };
707 
708 class ConvertException : public CoreException
709 {
710  public:
CoreException(reason)711 	ConvertException(const Anope::string &reason = "") : CoreException(reason) { }
712 
~ConvertException()713 	virtual ~ConvertException() throw() { }
714 };
715 
716 /** Convert something to a string
717  */
stringify(const T & x)718 template<typename T> inline Anope::string stringify(const T &x)
719 {
720 	std::ostringstream stream;
721 
722 	if (!(stream << x))
723 		throw ConvertException("Stringify fail");
724 
725 	return stream.str();
726 }
727 
728 template<typename T> inline void convert(const Anope::string &s, T &x, Anope::string &leftover, bool failIfLeftoverChars = true)
729 {
730 	leftover.clear();
731 	std::istringstream i(s.str());
732 	char c;
733 	if (!(i >> x))
734 		throw ConvertException("Convert fail");
735 	if (failIfLeftoverChars)
736 	{
737 		if (i.get(c))
738 			throw ConvertException("Convert fail");
739 	}
740 	else
741 	{
742 		std::string left;
743 		getline(i, left);
744 		leftover = left;
745 	}
746 }
747 
748 template<typename T> inline void convert(const Anope::string &s, T &x, bool failIfLeftoverChars = true)
749 {
750 	Anope::string Unused;
751 	convert(s, x, Unused, failIfLeftoverChars);
752 }
753 
754 template<typename T> inline T convertTo(const Anope::string &s, Anope::string &leftover, bool failIfLeftoverChars = true)
755 {
756 	T x;
757 	convert(s, x, leftover, failIfLeftoverChars);
758 	return x;
759 }
760 
761 template<typename T> inline T convertTo(const Anope::string &s, bool failIfLeftoverChars = true)
762 {
763 	T x;
764 	convert(s, x, failIfLeftoverChars);
765 	return x;
766 }
767 
768 /** Casts to be used instead of dynamic_cast, this uses dynamic_cast
769  * for debug builds and static_cast on releass builds
770  * to speed up the program because dynamic_cast relies on RTTI.
771  */
772 #ifdef DEBUG_BUILD
773 # include <typeinfo>
anope_dynamic_static_cast(O ptr)774 template<typename T, typename O> inline T anope_dynamic_static_cast(O ptr)
775 {
776 	T ret = dynamic_cast<T>(ptr);
777 	if (ptr != NULL && ret == NULL)
778 		throw CoreException(Anope::string("anope_dynamic_static_cast<") + typeid(T).name() + ">(" + typeid(O).name() + ") fail");
779 	return ret;
780 }
781 #else
anope_dynamic_static_cast(O ptr)782 template<typename T, typename O> inline T anope_dynamic_static_cast(O ptr)
783 {
784 	return static_cast<T>(ptr);
785 }
786 #endif
787 
788 #endif // ANOPE_H
789