+ // The flags for matching users to include.
+ std::bitset<UCHAR_MAX> flags;
+
+ // Whether we are matching using a wildcard or a flag.
+ bool fuzzy_match;
+
+ // The text to match against.
+ std::string matchtext;
+
+ // The WHO/WHOX responses we will send to the source.
+ std::vector<Numeric::Numeric> results;
+
+ // Whether the source requested a WHOX response.
+ bool whox;
+
+ // The fields to include in the WHOX response.
+ std::bitset<UCHAR_MAX> whox_fields;
+
+ // A user specified label for the WHOX response.
+ std::string whox_querytype;
+
+ WhoData(const std::vector<std::string>& parameters)
+ : whox(false)
+ {
+ // Find the matchtext and swap the 0 for a * so we can use InspIRCd::Match on it.
+ matchtext = parameters.size() > 2 ? parameters[2] : parameters[0];
+ if (matchtext == "0")
+ matchtext = "*";
+
+ // Fuzzy matches are when the source has not specified a specific user.
+ fuzzy_match = (parameters.size() > 1) || (matchtext.find_first_of("*?.") != std::string::npos);
+
+ // If flags have been specified by the source.
+ if (parameters.size() > 1)
+ {
+ std::bitset<UCHAR_MAX>* current_bitset = &flags;
+ for (std::string::const_iterator iter = parameters[1].begin(); iter != parameters[1].end(); ++iter)
+ {
+ unsigned char chr = static_cast<unsigned char>(*iter);
+
+ // If the source specifies a percentage the rest of the flags are WHOX fields.
+ if (chr == '%')
+ {
+ whox = true;
+ current_bitset = &whox_fields;
+ continue;
+ }
+
+ // If we are in WHOX mode and the source specifies a comma
+ // the rest of the parameter is the query type.
+ if (whox && chr == ',')
+ {
+ whox_querytype.assign(++iter, parameters[1].end());
+ break;
+ }
+
+ // The source specified a matching flag.
+ current_bitset->set(chr);
+ }
+ }
+ }
+};
+
+class CommandWho : public SplitCommand
+{
+ private: