summaryrefslogtreecommitdiffstats
blob: 3ecd88122802710e4e1c1bb4463c60f15bfc763e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*
 * Copyright (c) 2010 Remko Tronçon
 * Licensed under the GNU General Public License v3.
 * See Documentation/Licenses/GPLv3.txt for more information.
 */

#define SWIFTEN_CACHE_JID_PREP

#include <vector>
#include <iostream>

#include <Swiften/Base/String.h>
#ifdef SWIFTEN_CACHE_JID_PREP
#include <boost/unordered_map.hpp>
#endif
#include <stringprep.h>

#include "Swiften/JID/JID.h"
#include "Swiften/IDN/StringPrep.h"

#ifdef SWIFTEN_CACHE_JID_PREP
typedef boost::unordered_map<std::string, Swift::String> PrepCache;

static PrepCache nodePrepCache;
static PrepCache domainPrepCache;
static PrepCache resourcePrepCache;
#endif

namespace Swift {

JID::JID(const char* jid) {
	initializeFromString(String(jid));
}

JID::JID(const String& jid) {
	initializeFromString(jid);
}

JID::JID(const String& node, const String& domain) : hasResource_(false) {
	nameprepAndSetComponents(node, domain, "");
}

JID::JID(const String& node, const String& domain, const String& resource) : hasResource_(true) {
	nameprepAndSetComponents(node, domain, resource);
}

void JID::initializeFromString(const String& jid) {
	if (jid.beginsWith('@')) {
		return;
	}

	String bare, resource;
	size_t slashIndex = jid.find('/');
	if (slashIndex != jid.npos()) {
		hasResource_ = true;
		bare = jid.getSubstring(0, slashIndex);
		resource = jid.getSubstring(slashIndex + 1, jid.npos());
	}
	else {
		hasResource_ = false;
		bare = jid;
	}
	std::pair<String,String> nodeAndDomain = bare.getSplittedAtFirst('@');
	if (nodeAndDomain.second.isEmpty()) {
		nameprepAndSetComponents("", nodeAndDomain.first, resource);
	}
	else {
		nameprepAndSetComponents(nodeAndDomain.first, nodeAndDomain.second, resource);
	}
}


void JID::nameprepAndSetComponents(const String& node, const String& domain, const String& resource) {
#ifndef SWIFTEN_CACHE_JID_PREP
	node_ = StringPrep::getPrepared(node, StringPrep::NamePrep);
	domain_ = StringPrep::getPrepared(domain, StringPrep::XMPPNodePrep);
	resource_ = StringPrep::getPrepared(resource, StringPrep::XMPPResourcePrep);
#else
	std::pair<PrepCache::iterator, bool> r;

	r = nodePrepCache.insert(std::make_pair(node.getUTF8String(), String()));
	if (r.second) {
		r.first->second = StringPrep::getPrepared(node, StringPrep::NamePrep);
	}
	node_ = r.first->second;

	r = domainPrepCache.insert(std::make_pair(domain.getUTF8String(), String()));
	if (r.second) {
		r.first->second = StringPrep::getPrepared(domain, StringPrep::XMPPNodePrep);
	}
	domain_ = r.first->second;

	r = resourcePrepCache.insert(std::make_pair(resource.getUTF8String(), String()));
	if (r.second) {
		r.first->second = StringPrep::getPrepared(resource, StringPrep::XMPPResourcePrep);
	}
	resource_ = r.first->second;
#endif
}

String JID::toString() const {
	String string;
	if (!node_.isEmpty()) {
		string += node_ + "@";
	}
	string += domain_;
	if (!isBare()) {
		string += "/" + resource_;
	}
	return string;
}

int JID::compare(const Swift::JID& o, CompareType compareType) const {
	if (node_ < o.node_) { return -1; }
	if (node_ > o.node_) { return 1; }
	if (domain_ < o.domain_) { return -1; }
	if (domain_ > o.domain_) { return 1; }
	if (compareType == WithResource) {
		if (hasResource_ != o.hasResource_) {
			return hasResource_ ? 1 : -1;
		}
		if (resource_ < o.resource_) { return -1; }
		if (resource_ > o.resource_) { return 1; }
	}
	return 0;
}

} // namespace Swift