1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
|
/*
* InspIRCd -- Internet Relay Chat Daemon
*
* Copyright (C) 2013, 2018-2022 Sadie Powell <sadie@witchery.services>
* Copyright (C) 2013 Adam <Adam@anope.org>
* Copyright (C) 2012-2013, 2016 Attila Molnar <attilamolnar@hush.com>
* Copyright (C) 2012 Robby <robby@chatbelgie.be>
* Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
* Copyright (C) 2008-2009 Robin Burchell <robin+git@viroteck.net>
* Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
* Copyright (C) 2005-2008 Craig Edwards <brain@inspircd.org>
*
* This file is part of InspIRCd. InspIRCd is free software: you can
* redistribute it and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation, version 2.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "inspircd.h"
#include "convto.h"
/*******************************************************
* This file contains classes and templates that deal
* with the comparison and hashing of 'irc strings'.
* An 'irc string' is a string which compares in a
* case insensitive manner, and as per RFC 1459 will
* treat [ identical to {, ] identical to }, and \
* as identical to |.
*
* There are functors that accept std::string and
* compare/hash them as type irc::string by using
* mapping arrays internally.
*******************************************************/
/** Separate from the other casemap tables so that code *can* still exclusively rely on RFC casemapping
* if it must.
*
* This is provided as a pointer so that modules can change it to their custom mapping tables,
* e.g. for national character support.
*/
CoreExport extern const unsigned char* national_case_insensitive_map;
/** Case insensitive map, ASCII rules.
* That is;
* [ != {, but A == a.
*/
CoreExport extern const unsigned char ascii_case_insensitive_map[256];
/** The irc namespace contains a number of helper classes.
*/
namespace irc
{
/** Check if two IRC object (e.g. nick or channel) names are equal.
* This function uses national_case_insensitive_map to determine equality, which, by default does comparison
* according to RFC 1459, treating certain otherwise non-identical characters as identical.
* @param s1 First string to compare
* @param s2 Second string to compare
* @return True if the two names are equal, false otherwise
*/
CoreExport bool equals(const std::string_view& s1, const std::string_view& s2);
/** Check whether \p needle exists within \p haystack.
* @param haystack The string to search within.
* @param needle The string to search for.
* @return Either the index at which \p needle was found or std::string::npos.
*/
CoreExport size_t find(const std::string_view& haystack, const std::string_view& needle);
/** This class returns true if two strings match.
* Case sensitivity is ignored, and the RFC 'character set'
* is adhered to
*/
struct StrHashComp final
{
/** The operator () does the actual comparison in hash_map
*/
bool operator()(const std::string& s1, const std::string& s2) const
{
return equals(s1, s2);
}
};
struct insensitive final
{
size_t CoreExport operator()(const std::string& s) const;
};
struct insensitive_swo
{
bool CoreExport operator()(const std::string& a, const std::string& b) const;
};
/** irc::sepstream allows for splitting token separated lists.
* Each successive call to sepstream::GetToken() returns
* the next token, until none remain, at which point the method returns
* false.
*/
class CoreExport sepstream
{
protected:
/** Original string.
*/
std::string tokens;
/** Separator value
*/
char sep;
/** Current string position
*/
size_t pos = 0;
/** If set then GetToken() can return an empty string
*/
bool allow_empty;
public:
/** Create a sepstream and fill it with the provided data
*/
sepstream(const std::string& source, char separator, bool allowempty = false);
/** Fetch the next token from the stream
* @param token The next token from the stream is placed here
* @return True if tokens still remain, false if there are none left
*/
bool GetToken(std::string& token);
/** Fetch the next numeric token from the stream
* @param token The next token from the stream is placed here
* @return True if tokens still remain, false if there are none left
*/
template<typename Numeric>
bool GetNumericToken(Numeric& token)
{
std::string str;
if (!GetToken(str))
return false;
token = ConvToNum<Numeric>(str);
return true;
}
/** Fetch the entire remaining stream, without tokenizing
* @return The remaining part of the stream
*/
std::string GetRemaining();
/** Returns true if the end of the stream has been reached
* @return True if the end of the stream has been reached, otherwise false
*/
bool StreamEnd();
};
/** A derived form of sepstream, which separates on commas
*/
class CoreExport commasepstream : public sepstream
{
public:
/** Initialize with comma separator
*/
commasepstream(const std::string& source, bool allowempty = false)
: sepstream(source, ',', allowempty)
{
}
};
/** A derived form of sepstream, which separates on spaces
*/
class CoreExport spacesepstream : public sepstream
{
public:
/** Initialize with space separator
*/
spacesepstream(const std::string& source, bool allowempty = false)
: sepstream(source, ' ', allowempty)
{
}
};
/** irc::tokenstream reads a string formatted as per RFC1459 and RFC2812.
* It will split the string into 'tokens' each containing one parameter
* from the string.
* For instance, if it is instantiated with the string:
* "PRIVMSG #test :foo bar baz qux"
* then each successive call to tokenstream::GetToken() will return
* "PRIVMSG", "#test", "foo bar baz qux", "".
* Note that if the whole string starts with a colon this is not taken
* to mean the string is all one parameter, and the first item in the
* list will be ":item". This is to allow for parsing 'source' fields
* from data.
*/
class CoreExport tokenstream
{
private:
/** The message we are parsing tokens from. */
std::string message;
/** The current position within the message. */
size_t position = 0;
public:
/** Create a tokenstream and fill it with the provided data. */
tokenstream(const std::string& msg, size_t start = 0, size_t end = std::string::npos);
/** Retrieves the underlying message. */
std::string& GetMessage() { return message; }
/** Retrieve the next \<middle> token in the token stream.
* @param token The next token available, or an empty string if none remain.
* @return True if tokens are left to be read, false if the last token was just retrieved.
*/
bool GetMiddle(std::string& token);
/** Retrieve the next \<trailing> token in the token stream.
* @param token The next token available, or an empty string if none remain.
* @return True if tokens are left to be read, false if the last token was just retrieved.
*/
bool GetTrailing(std::string& token);
};
/** The portparser class separates out a port range into integers.
* A port range may be specified in the input string in the form
* "6660,6661,6662-6669,7020". The end of the stream is indicated by
* a return value of 0 from portparser::GetToken(). If you attempt
* to specify an illegal range (e.g. one where start >= end, or
* start or end < 0) then GetToken() will return the first element
* of the pair of numbers.
*/
class CoreExport portparser
{
private:
/** Used to split on commas
*/
commasepstream sep;
/** Current position in a range of ports
*/
long in_range = 0;
/** Starting port in a range of ports
*/
long range_begin = 0;
/** Ending port in a range of ports
*/
long range_end = 0;
/** Allow overlapped port ranges
*/
bool overlapped;
/** Used to determine overlapping of ports
* without O(n) algorithm being used
*/
std::set<long> overlap_set;
/** Returns true if val overlaps an existing range
*/
bool Overlaps(long val);
public:
/** Create a portparser and fill it with the provided data
* @param source The source text to parse from
* @param allow_overlapped Allow overlapped ranges
*/
portparser(const std::string& source, bool allow_overlapped = true);
/** Fetch the next token from the stream
* @return The next port number is returned, or 0 if none remain
*/
long GetToken();
};
}
|