summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemko Tronçon <git@el-tramo.be>2011-04-15 20:53:27 (GMT)
committerRemko Tronçon <git@el-tramo.be>2011-04-18 19:11:44 (GMT)
commit8e1bdd6727a2e0d4e5b0894a83905c275348b037 (patch)
treefc943fabc48f3bb780f82c096eecdefd39fd69b4 /Swiften/JID/JID.cpp
parenta4e59529239902ac352e791767db63a31e2e0634 (diff)
downloadswift-8e1bdd6727a2e0d4e5b0894a83905c275348b037.zip
swift-8e1bdd6727a2e0d4e5b0894a83905c275348b037.tar.bz2
JID escaping algorithm refactoring.
Made algorithm more efficient. Fixed some incorrect escaping. Added more tests from the XEP.
Diffstat (limited to 'Swiften/JID/JID.cpp')
-rw-r--r--Swiften/JID/JID.cpp106
1 files changed, 76 insertions, 30 deletions
diff --git a/Swiften/JID/JID.cpp b/Swiften/JID/JID.cpp
index 5fd7524..00adf34 100644
--- a/Swiften/JID/JID.cpp
+++ b/Swiften/JID/JID.cpp
@@ -7,13 +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/algorithm/string/replace.hpp>
+#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>
@@ -28,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) {
@@ -128,38 +201,11 @@ int JID::compare(const Swift::JID& o, CompareType compareType) const {
}
std::string JID::getEscapedNode(const std::string& node) {
- std::string escaped = node;
-
- boost::algorithm::replace_all(escaped, "\\", "\\5c");
- boost::algorithm::replace_all(escaped, " ", "\\20");
- boost::algorithm::replace_all(escaped, "\"", "\\22");
- boost::algorithm::replace_all(escaped, "&", "\\26");
- boost::algorithm::replace_all(escaped, "'", "\\27");
- boost::algorithm::replace_all(escaped, "/", "\\2f");
- boost::algorithm::replace_all(escaped, "<", "\\3c");
- boost::algorithm::replace_all(escaped, ">", "\\3e");
- boost::algorithm::replace_all(escaped, "@", "\\40");
- boost::algorithm::replace_all(escaped, ":", "\\3a");
-
- return escaped;
+ return boost::find_format_all_copy(node, UnescapedCharacterFinder(), UnescapedCharacterFormatter());
}
std::string JID::getUnescapedNode() const {
- std::string unescaped = node_;
-
- boost::algorithm::replace_all(unescaped, "\\20", " ");
- boost::algorithm::replace_all(unescaped, "\\22", "\"");
- boost::algorithm::replace_all(unescaped, "\\26", "&");
- boost::algorithm::replace_all(unescaped, "\\27", "'");
- boost::algorithm::replace_all(unescaped, "\\2f", "/");
- boost::algorithm::replace_all(unescaped, "\\3c", "<");
- boost::algorithm::replace_all(unescaped, "\\3e", ">");
- boost::algorithm::replace_all(unescaped, "\\40", "@");
- boost::algorithm::replace_all(unescaped, "\\3a", ":");
- boost::algorithm::replace_all(unescaped, "\\5c", "\\");
-
-
- return unescaped;
+ return boost::find_format_all_copy(node_, EscapedCharacterFinder(), EscapedCharacterFormatter());
}
} // namespace Swift