diff options
Diffstat (limited to 'Swiften/JID')
-rw-r--r-- | Swiften/JID/JID.cpp | 83 | ||||
-rw-r--r-- | Swiften/JID/JID.h | 43 | ||||
-rw-r--r-- | Swiften/JID/SConscript | 2 | ||||
-rw-r--r-- | Swiften/JID/UnitTest/JIDTest.cpp | 11 |
4 files changed, 114 insertions, 25 deletions
diff --git a/Swiften/JID/JID.cpp b/Swiften/JID/JID.cpp index 9b47ef7..fcd49f9 100644 --- a/Swiften/JID/JID.cpp +++ b/Swiften/JID/JID.cpp @@ -1,4 +1,4 @@ /* - * 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. @@ -19,10 +19,15 @@ #include <boost/algorithm/string/find_format.hpp> #include <boost/algorithm/string/finder.hpp> +#include <boost/optional.hpp> +#include <iostream> #include <sstream> -#include <stringprep.h> #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; @@ -39,4 +44,17 @@ 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); @@ -113,5 +131,8 @@ struct EscapedCharacterFormatter { #endif +namespace Swift { + JID::JID(const char* jid) : valid_(true) { + assert(jid); initializeFromString(std::string(jid)); } @@ -157,13 +178,12 @@ void JID::initializeFromString(const std::string& jid) { void JID::nameprepAndSetComponents(const std::string& node, const std::string& domain, const std::string& resource) { - if (domain.empty()) { + if (domain.empty() || !idnConverter->getIDNAEncoded(domain)) { 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); @@ -173,5 +193,12 @@ void JID::nameprepAndSetComponents(const std::string& node, const std::string& d r = nodePrepCache.insert(std::make_pair(node, std::string())); if (r.second) { - r.first->second = StringPrep::getPrepared(node, StringPrep::NamePrep); + try { + r.first->second = idnConverter->getStringPrepared(node, IDNConverter::XMPPNodePrep); + } + catch (...) { + nodePrepCache.erase(r.first); + valid_ = false; + return; + } } node_ = r.first->second; @@ -179,5 +206,12 @@ void JID::nameprepAndSetComponents(const std::string& node, const std::string& d r = domainPrepCache.insert(std::make_pair(domain, std::string())); if (r.second) { - r.first->second = StringPrep::getPrepared(domain, StringPrep::XMPPNodePrep); + try { + r.first->second = idnConverter->getStringPrepared(domain, IDNConverter::NamePrep); + } + catch (...) { + domainPrepCache.erase(r.first); + valid_ = false; + return; + } } domain_ = r.first->second; @@ -185,5 +219,12 @@ void JID::nameprepAndSetComponents(const std::string& node, const std::string& d r = resourcePrepCache.insert(std::make_pair(resource, std::string())); if (r.second) { - r.first->second = StringPrep::getPrepared(resource, StringPrep::XMPPResourcePrep); + try { + r.first->second = idnConverter->getStringPrepared(resource, IDNConverter::XMPPResourcePrep); + } + catch (...) { + resourcePrepCache.erase(r.first); + valid_ = false; + return; + } } resource_ = r.first->second; @@ -195,8 +236,4 @@ void JID::nameprepAndSetComponents(const std::string& node, const std::string& d } } - catch (const std::exception&) { - valid_ = false; - } -} std::string JID::toString() const { @@ -272,2 +309,18 @@ std::string JID::getUnescapedNode() const { //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; +} + +boost::optional<JID> JID::parse(const std::string& s) { + JID jid(s); + return jid.isValid() ? jid : boost::optional<JID>(); +} + +} diff --git a/Swiften/JID/JID.h b/Swiften/JID/JID.h index a4461ba..aefd3df 100644 --- a/Swiften/JID/JID.h +++ b/Swiften/JID/JID.h @@ -1,4 +1,4 @@ /* - * 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. @@ -8,8 +8,12 @@ #include <string> -//#include <iosfwd> -#include <iostream> +#include <iosfwd> + +#include <Swiften/Base/API.h> +#include <boost/optional/optional_fwd.hpp> namespace Swift { + class IDNConverter; + /** * This represents the JID used in XMPP @@ -23,5 +27,5 @@ namespace Swift { * guaranteed to work correctly if they do. */ - class JID { + class SWIFTEN_API JID { public: enum CompareType { @@ -44,4 +48,6 @@ namespace Swift { /** * See std::string constructor. + * + * Must not be NULL. */ JID(const char*); @@ -129,4 +135,12 @@ namespace Swift { } + /** + * Get the full JID with the supplied resource. + */ + JID withResource(const std::string& resource) const { + JID result(this->getNode(), this->getDomain(), resource); + return result; + } + std::string toString() const; @@ -145,8 +159,5 @@ namespace Swift { } - 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) { @@ -158,4 +169,17 @@ namespace Swift { } + /** + * Returns an empty optional if the JID is invalid, and an + * optional with a value if the JID is valid. + */ + static boost::optional<JID> parse(const std::string&); + + /** + * 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); @@ -169,3 +193,6 @@ namespace Swift { std::string resource_; }; + + SWIFTEN_API std::ostream& operator<<(std::ostream& os, const Swift::JID& j); } + diff --git a/Swiften/JID/SConscript b/Swiften/JID/SConscript index d347cd9..12565fc 100644 --- a/Swiften/JID/SConscript +++ b/Swiften/JID/SConscript @@ -2,6 +2,4 @@ Import("swiften_env") myenv = swiften_env.Clone() -myenv.MergeFlags(swiften_env["LIBIDN_FLAGS"]) - objects = myenv.SwiftenObject([ "JID.cpp", diff --git a/Swiften/JID/UnitTest/JIDTest.cpp b/Swiften/JID/UnitTest/JIDTest.cpp index 81d24ea..03203de 100644 --- a/Swiften/JID/UnitTest/JIDTest.cpp +++ b/Swiften/JID/UnitTest/JIDTest.cpp @@ -20,4 +20,5 @@ class JIDTest : public CppUnit::TestFixture CPPUNIT_TEST(testConstructorWithString_EmptyResource); CPPUNIT_TEST(testConstructorWithString_OnlyDomain); + CPPUNIT_TEST(testConstructorWithString_InvalidDomain); CPPUNIT_TEST(testConstructorWithString_UpperCaseNode); CPPUNIT_TEST(testConstructorWithString_UpperCaseDomain); @@ -25,4 +26,5 @@ class JIDTest : public CppUnit::TestFixture CPPUNIT_TEST(testConstructorWithString_EmptyNode); CPPUNIT_TEST(testConstructorWithString_IllegalResource); + CPPUNIT_TEST(testConstructorWithString_SpacesInNode); CPPUNIT_TEST(testConstructorWithStrings); CPPUNIT_TEST(testConstructorWithStrings_EmptyDomain); @@ -107,4 +109,8 @@ class JIDTest : public CppUnit::TestFixture } + void testConstructorWithString_InvalidDomain() { + CPPUNIT_ASSERT(!JID("foo@bar,baz").isValid()); + } + void testConstructorWithString_UpperCaseNode() { JID testling("Fo\xCE\xA9@bar"); @@ -138,4 +144,9 @@ class JIDTest : public CppUnit::TestFixture } + void testConstructorWithString_SpacesInNode() { + CPPUNIT_ASSERT(!JID(" alice@wonderland.lit").isValid()); + CPPUNIT_ASSERT(!JID("alice @wonderland.lit").isValid()); + } + void testConstructorWithStrings() { JID testling("foo", "bar", "baz"); |