summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften/JID')
-rw-r--r--Swiften/JID/JID.cpp83
-rw-r--r--Swiften/JID/JID.h43
-rw-r--r--Swiften/JID/SConscript2
-rw-r--r--Swiften/JID/UnitTest/JIDTest.cpp11
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");