diff options
Diffstat (limited to 'Swiften/IDN/StringPrep.cpp')
-rw-r--r-- | Swiften/IDN/StringPrep.cpp | 89 |
1 files changed, 85 insertions, 4 deletions
diff --git a/Swiften/IDN/StringPrep.cpp b/Swiften/IDN/StringPrep.cpp index 9085569..dfaba06 100644 --- a/Swiften/IDN/StringPrep.cpp +++ b/Swiften/IDN/StringPrep.cpp @@ -1,23 +1,101 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2012 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include <Swiften/IDN/StringPrep.h> -extern "C" -{ +#if defined(HAVE_ICU) +#pragma GCC diagnostic ignored "-Wold-style-cast" +#include <Swiften/IDN/ICUConverter.h> +#include <unicode/usprep.h> +#include <unicode/ucnv.h> +#elif defined(HAVE_LIBIDN) +extern "C" { #include <stringprep.h> }; +#endif #include <vector> #include <cassert> #include <Swiften/Base/SafeAllocator.h> +#include <boost/shared_ptr.hpp> using namespace Swift; - namespace { +#if defined(HAVE_ICU) + +namespace { + static UStringPrepProfileType getICUProfileType(StringPrep::Profile profile) { + switch(profile) { + case StringPrep::NamePrep: return USPREP_RFC3491_NAMEPREP; break; + case StringPrep::XMPPNodePrep: return USPREP_RFC3920_NODEPREP; break; + case StringPrep::XMPPResourcePrep: return USPREP_RFC3920_RESOURCEPREP; break; + case StringPrep::SASLPrep: return USPREP_RFC4013_SASLPREP; break; + } + assert(false); + return USPREP_RFC3491_NAMEPREP; + } + + template<typename StringType> + std::vector<char, SafeAllocator<char> > getStringPrepared(const StringType& s, StringPrep::Profile profile) { + UErrorCode status = U_ZERO_ERROR; + ICUConverter converter; + + boost::shared_ptr<UStringPrepProfile> icuProfile(usprep_openByType(getICUProfileType(profile), &status), usprep_close); + assert(U_SUCCESS(status)); + + ICUConverter::ICUString icuInput = converter.convertToICUString(s); + ICUConverter::ICUString icuResult; + UParseError parseError; + icuResult.resize(icuInput.size()); + int icuResultLength = usprep_prepare(icuProfile.get(), vecptr(icuInput), icuInput.size(), vecptr(icuResult), icuResult.size(), USPREP_ALLOW_UNASSIGNED, &parseError, &status); icuResult.resize(icuResultLength); + if (status == U_BUFFER_OVERFLOW_ERROR) { + status = U_ZERO_ERROR; + icuResult.resize(icuResultLength); + icuResultLength = usprep_prepare(icuProfile.get(), vecptr(icuInput), icuInput.size(), vecptr(icuResult), icuResult.size(), USPREP_ALLOW_UNASSIGNED, &parseError, &status); icuResult.resize(icuResultLength); + } + if (U_FAILURE(status)) { + return std::vector<char, SafeAllocator<char> >(); + } + icuResult.resize(icuResultLength); + + return converter.convertToArray(icuResult); + } +} + +namespace Swift { + +std::string StringPrep::getPrepared(const std::string& s, Profile profile) { + if (s.empty()) { + return ""; + } + std::vector<char, SafeAllocator<char> > preparedData = getStringPrepared(s, profile); + if (preparedData.empty()) { + throw std::exception(); + } + return std::string(vecptr(preparedData)); +} + +SafeByteArray StringPrep::getPrepared(const SafeByteArray& s, Profile profile) { + if (s.empty()) { + return SafeByteArray(); + } + std::vector<char, SafeAllocator<char> > preparedData = getStringPrepared(s, profile); + if (preparedData.empty()) { + throw std::exception(); + } + return createSafeByteArray(reinterpret_cast<const char*>(vecptr(preparedData))); +} + +} + +//////////////////////////////////////////////////////////////////////////////// + +#elif defined(HAVE_LIBIDN) + +namespace { static const int MAX_STRINGPREP_SIZE = 1024; const Stringprep_profile* getLibIDNProfile(StringPrep::Profile profile) { @@ -63,3 +141,6 @@ SafeByteArray StringPrep::getPrepared(const SafeByteArray& s, Profile profile) { } } + +#endif + |