diff options
Diffstat (limited to 'Swiften/JID/JID.cpp')
| -rw-r--r-- | Swiften/JID/JID.cpp | 134 | 
1 files changed, 129 insertions, 5 deletions
| diff --git a/Swiften/JID/JID.cpp b/Swiften/JID/JID.cpp index e4611b3..2ebbdd6 100644 --- a/Swiften/JID/JID.cpp +++ b/Swiften/JID/JID.cpp @@ -7,17 +7,24 @@  #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> -#include "Swiften/JID/JID.h" -#include "Swiften/IDN/StringPrep.h" +#include <Swiften/JID/JID.h> +#include <Swiften/IDN/StringPrep.h> + +using namespace Swift;  #ifdef SWIFTEN_CACHE_JID_PREP  typedef boost::unordered_map<std::string, std::string> PrepCache; @@ -27,7 +34,81 @@ static PrepCache domainPrepCache;  static PrepCache resourcePrepCache;  #endif -namespace Swift { +static const std::list<char> escapedChars = boost::assign::list_of(' ')('"')('&')('\'')('/')('<')('>')('@')(':'); + +static std::string getEscaped(char c) { +	return makeString() << '\\' << std::hex << static_cast<int>(c); +} + +static 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())); +} + +// Disabling this code for now, since GCC4.5+boost1.42 (on ubuntu) seems to +// result in a bug. Replacing it with naive code. +#if 0 +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); +	} +}; +#endif  JID::JID(const char* jid) {  	initializeFromString(std::string(jid)); @@ -126,5 +207,48 @@ int JID::compare(const Swift::JID& o, CompareType compareType) const {  	return 0;  } -} // namespace Swift - +std::string JID::getEscapedNode(const std::string& node) { +	std::string result; +	for (std::string::const_iterator i = node.begin(); i != node.end(); ++i) { +		if (std::find(escapedChars.begin(), escapedChars.end(), *i) != escapedChars.end()) { +			result += getEscaped(*i); +			continue; +		} +		else if (*i == '\\') { +			// Check if we have an escaped dissalowed character sequence +			std::string::const_iterator innerBegin = i + 1; +			if (innerBegin != node.end() && innerBegin + 1 != node.end()) { +				std::string::const_iterator innerEnd = innerBegin + 2; +				unsigned char value; +				if (getEscapeSequenceValue(std::string(innerBegin, innerEnd), value)) { +					result += getEscaped(*i); +					continue; +				} +			} +		} +		result += *i; +	} +	return result; +	//return boost::find_format_all_copy(node, UnescapedCharacterFinder(), UnescapedCharacterFormatter()); +} +					 +std::string JID::getUnescapedNode() const { +	std::string result; +	for (std::string::const_iterator j = node_.begin(); j != node_.end();) { +		if (*j == '\\') { +			std::string::const_iterator innerEnd = j + 1; +			for (size_t i = 0; i < 2 && innerEnd != node_.end(); ++i, ++innerEnd) { +			} +			unsigned char value; +			if (getEscapeSequenceValue(std::string(j + 1, innerEnd), value)) { +				result += std::string(reinterpret_cast<const char*>(&value), 1); +				j = innerEnd; +				continue; +			} +		} +		result += *j; +		++j; +	} +	return result; +	//return boost::find_format_all_copy(node_, EscapedCharacterFinder(), EscapedCharacterFormatter()); +} | 
 Swift
 Swift