diff options
Diffstat (limited to 'Swiften/JID')
-rw-r--r-- | Swiften/JID/JID.cpp | 95 | ||||
-rw-r--r-- | Swiften/JID/JID.h | 24 | ||||
-rw-r--r-- | Swiften/JID/UnitTest/JIDTest.cpp | 6 |
3 files changed, 94 insertions, 31 deletions
diff --git a/Swiften/JID/JID.cpp b/Swiften/JID/JID.cpp index 0822595..7b51867 100644 --- a/Swiften/JID/JID.cpp +++ b/Swiften/JID/JID.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -18,11 +18,16 @@ #include <boost/assign/list_of.hpp> #include <boost/algorithm/string/find_format.hpp> #include <boost/algorithm/string/finder.hpp> +#include <iostream> #include <sstream> #include <Swiften/Base/String.h> #include <Swiften/JID/JID.h> -#include <Swiften/IDN/StringPrep.h> +#include <Swiften/IDN/IDNConverter.h> +#ifndef SWIFTEN_JID_NO_DEFAULT_IDN_CONVERTER +#include <boost/shared_ptr.hpp> +#include <Swiften/IDN/PlatformIDNConverter.h> +#endif using namespace Swift; @@ -37,6 +42,19 @@ static PrepCache resourcePrepCache; static const std::list<char> escapedChars = boost::assign::list_of(' ')('"')('&')('\'')('/')('<')('>')('@')(':'); +static IDNConverter* idnConverter = NULL; + +#ifndef SWIFTEN_JID_NO_DEFAULT_IDN_CONVERTER +namespace { + struct IDNInitializer { + IDNInitializer() : defaultIDNConverter(PlatformIDNConverter::create()) { + idnConverter = defaultIDNConverter.get(); + } + boost::shared_ptr<IDNConverter> defaultIDNConverter; + } initializer; +} +#endif + static std::string getEscaped(char c) { return makeString() << '\\' << std::hex << static_cast<int>(c); } @@ -111,6 +129,8 @@ struct EscapedCharacterFormatter { }; #endif +namespace Swift { + JID::JID(const char* jid) : valid_(true) { initializeFromString(std::string(jid)); } @@ -159,42 +179,58 @@ void JID::nameprepAndSetComponents(const std::string& node, const std::string& d valid_ = false; return; } - try { #ifndef SWIFTEN_CACHE_JID_PREP - node_ = StringPrep::getPrepared(node, StringPrep::NamePrep); - domain_ = StringPrep::getPrepared(domain, StringPrep::XMPPNodePrep); - resource_ = StringPrep::getPrepared(resource, StringPrep::XMPPResourcePrep); + node_ = idnConverter->getStringPrepared(node, IDNConverter::XMPPNodePrep); + domain_ = idnConverter->getStringPrepared(domain, IDNConverter::NamePrep); + resource_ = idnConverter->getStringPrepared(resource, IDNConverter::XMPPResourcePrep); #else - boost::mutex::scoped_lock lock(namePrepCacheMutex); + boost::mutex::scoped_lock lock(namePrepCacheMutex); - std::pair<PrepCache::iterator, bool> r; + std::pair<PrepCache::iterator, bool> r; - r = nodePrepCache.insert(std::make_pair(node, std::string())); - if (r.second) { - r.first->second = StringPrep::getPrepared(node, StringPrep::NamePrep); + r = nodePrepCache.insert(std::make_pair(node, std::string())); + if (r.second) { + try { + r.first->second = idnConverter->getStringPrepared(node, IDNConverter::XMPPNodePrep); } - node_ = r.first->second; - - r = domainPrepCache.insert(std::make_pair(domain, std::string())); - if (r.second) { - r.first->second = StringPrep::getPrepared(domain, StringPrep::XMPPNodePrep); + catch (...) { + nodePrepCache.erase(r.first); + valid_ = false; + return; } - domain_ = r.first->second; + } + node_ = r.first->second; - r = resourcePrepCache.insert(std::make_pair(resource, std::string())); - if (r.second) { - r.first->second = StringPrep::getPrepared(resource, StringPrep::XMPPResourcePrep); + r = domainPrepCache.insert(std::make_pair(domain, std::string())); + if (r.second) { + try { + r.first->second = idnConverter->getStringPrepared(domain, IDNConverter::NamePrep); } - resource_ = r.first->second; -#endif + catch (...) { + domainPrepCache.erase(r.first); + valid_ = false; + return; + } + } + domain_ = r.first->second; - if (domain_.empty()) { + r = resourcePrepCache.insert(std::make_pair(resource, std::string())); + if (r.second) { + try { + r.first->second = idnConverter->getStringPrepared(resource, IDNConverter::XMPPResourcePrep); + } + catch (...) { + resourcePrepCache.erase(r.first); valid_ = false; return; } } - catch (const std::exception&) { + resource_ = r.first->second; +#endif + + if (domain_.empty()) { valid_ = false; + return; } } @@ -270,3 +306,14 @@ std::string JID::getUnescapedNode() const { return result; //return boost::find_format_all_copy(node_, EscapedCharacterFinder(), EscapedCharacterFormatter()); } + +void JID::setIDNConverter(IDNConverter* converter) { + idnConverter = converter; +} + +std::ostream& operator<<(std::ostream& os, const JID& j) { + os << j.toString(); + return os; +} + +} diff --git a/Swiften/JID/JID.h b/Swiften/JID/JID.h index 08309d3..798860d 100644 --- a/Swiften/JID/JID.h +++ b/Swiften/JID/JID.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -7,12 +7,14 @@ #pragma once #include <string> -//#include <iosfwd> -#include <iostream> +#include <iosfwd> #include <Swiften/Base/API.h> + namespace Swift { + class IDNConverter; + /** * This represents the JID used in XMPP * (RFC6120 - http://tools.ietf.org/html/rfc6120 ). @@ -146,10 +148,7 @@ namespace Swift { return compare(b, Swift::JID::WithResource) < 0; } - friend std::ostream& operator<<(std::ostream& os, const Swift::JID& j) { - os << j.toString(); - return os; - } + SWIFTEN_API friend std::ostream& operator<<(std::ostream& os, const Swift::JID& j); friend bool operator==(const Swift::JID& a, const Swift::JID& b) { return a.compare(b, Swift::JID::WithResource) == 0; @@ -159,6 +158,14 @@ namespace Swift { return a.compare(b, Swift::JID::WithResource) != 0; } + + /** + * If Swiften was compiled with SWIFTEN_JID_NO_DEFAULT_IDN_CONVERTER (not default), use this method at + * the beginning of the program to set an IDN converter to use for JID IDN conversions. + * By default, this method shouldn't be used. + */ + static void setIDNConverter(IDNConverter*); + private: void nameprepAndSetComponents(const std::string& node, const std::string& domain, const std::string& resource); void initializeFromString(const std::string&); @@ -170,4 +177,7 @@ namespace Swift { bool hasResource_; std::string resource_; }; + + SWIFTEN_API std::ostream& operator<<(std::ostream& os, const Swift::JID& j); } + diff --git a/Swiften/JID/UnitTest/JIDTest.cpp b/Swiften/JID/UnitTest/JIDTest.cpp index 81d24ea..72ca884 100644 --- a/Swiften/JID/UnitTest/JIDTest.cpp +++ b/Swiften/JID/UnitTest/JIDTest.cpp @@ -24,6 +24,7 @@ class JIDTest : public CppUnit::TestFixture CPPUNIT_TEST(testConstructorWithString_UpperCaseResource); CPPUNIT_TEST(testConstructorWithString_EmptyNode); CPPUNIT_TEST(testConstructorWithString_IllegalResource); + CPPUNIT_TEST(testConstructorWithString_SpacesInNode); CPPUNIT_TEST(testConstructorWithStrings); CPPUNIT_TEST(testConstructorWithStrings_EmptyDomain); CPPUNIT_TEST(testIsBare); @@ -137,6 +138,11 @@ class JIDTest : public CppUnit::TestFixture CPPUNIT_ASSERT(!testling.isValid()); } + void testConstructorWithString_SpacesInNode() { + CPPUNIT_ASSERT(!JID(" alice@wonderland.lit").isValid()); + CPPUNIT_ASSERT(!JID("alice @wonderland.lit").isValid()); + } + void testConstructorWithStrings() { JID testling("foo", "bar", "baz"); |