diff options
Diffstat (limited to 'Swiften/JID/JID.cpp')
| -rw-r--r-- | Swiften/JID/JID.cpp | 82 | 
1 files changed, 82 insertions, 0 deletions
diff --git a/Swiften/JID/JID.cpp b/Swiften/JID/JID.cpp index e4611b3..00adf34 100644 --- a/Swiften/JID/JID.cpp +++ b/Swiften/JID/JID.cpp @@ -7,12 +7,17 @@  #define SWIFTEN_CACHE_JID_PREP  #include <vector> +#include <list>  #include <iostream>  #include <string>  #ifdef SWIFTEN_CACHE_JID_PREP  #include <boost/unordered_map.hpp>  #endif +#include <boost/assign/list_of.hpp> +#include <boost/algorithm/string/find_format.hpp> +#include <boost/algorithm/string/finder.hpp> +#include <sstream>  #include <stringprep.h>  #include <Swiften/Base/String.h> @@ -27,6 +32,75 @@ static PrepCache domainPrepCache;  static PrepCache resourcePrepCache;  #endif +static const std::list<char> escapedChars = boost::assign::list_of(' ')('"')('&')('\'')('/')('<')('>')('@')(':'); + +bool getEscapeSequenceValue(const std::string& sequence, unsigned char& value) { +	std::stringstream s; +	unsigned int v; +	s << std::hex << sequence; +	s >> v; +	value = static_cast<unsigned char>(v); +	return (!s.fail() && !s.bad() && (value == 0x5C || std::find(escapedChars.begin(), escapedChars.end(), value) != escapedChars.end())); +} + +struct UnescapedCharacterFinder { +	template<typename Iterator>	boost::iterator_range<Iterator> operator()(Iterator begin, Iterator end) { +		for (; begin != end; ++begin) { +			if (std::find(escapedChars.begin(), escapedChars.end(), *begin) != escapedChars.end()) { +				return boost::iterator_range<Iterator>(begin, begin + 1); +			} +			else if (*begin == '\\') { +				// Check if we have an escaped dissalowed character sequence +				Iterator innerBegin = begin + 1; +				if (innerBegin != end && innerBegin + 1 != end) { +					Iterator innerEnd = innerBegin + 2; +					unsigned char value; +					if (getEscapeSequenceValue(std::string(innerBegin, innerEnd), value)) { +						return boost::iterator_range<Iterator>(begin, begin + 1); +					} +				} +			} +		} +		return boost::iterator_range<Iterator>(end, end); +	} +}; + +struct UnescapedCharacterFormatter { +	template<typename FindResult>	std::string operator()(const FindResult& match) const { +		std::ostringstream s; +		s << '\\' << std::hex << static_cast<int>(*match.begin()); +		return s.str(); +	} +}; + +struct EscapedCharacterFinder { +	template<typename Iterator>	boost::iterator_range<Iterator> operator()(Iterator begin, Iterator end) { +		for (; begin != end; ++begin) { +			if (*begin == '\\') { +				Iterator innerEnd = begin + 1; +				for (size_t i = 0; i < 2 && innerEnd != end; ++i, ++innerEnd) { +				} +				unsigned char value; +				if (getEscapeSequenceValue(std::string(begin + 1, innerEnd), value)) { +					return boost::iterator_range<Iterator>(begin, innerEnd); +				} +			} +		} +		return boost::iterator_range<Iterator>(end, end); +	} +}; + +struct EscapedCharacterFormatter { +	template<typename FindResult>	std::string operator()(const FindResult& match) const { +		unsigned char value; +		if (getEscapeSequenceValue(std::string(match.begin() + 1, match.end()), value)) { +			return std::string(reinterpret_cast<const char*>(&value), 1); +		} +		return boost::copy_range<std::string>(match); +	} +}; + +  namespace Swift {  JID::JID(const char* jid) { @@ -126,5 +200,13 @@ int JID::compare(const Swift::JID& o, CompareType compareType) const {  	return 0;  } +std::string JID::getEscapedNode(const std::string& node) { +	return boost::find_format_all_copy(node, UnescapedCharacterFinder(), UnescapedCharacterFormatter()); +} + +std::string JID::getUnescapedNode() const { +	return boost::find_format_all_copy(node_, EscapedCharacterFinder(), EscapedCharacterFormatter()); +} +  } // namespace Swift  | 
 Swift