summaryrefslogtreecommitdiffstats
blob: 0fd2f004be3757be54b65d3af7330445cd2c8621 (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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
/*
 * Copyright (c) 2010-2016 Isode Limited.
 * All rights reserved.
 * See the COPYING file for more information.
 */

#pragma once

#include <string>
#include <iosfwd>

#include <Swiften/Base/API.h>
#include <boost/optional/optional_fwd.hpp>

namespace Swift {
	class IDNConverter;

	/**
	 * This represents the JID used in XMPP
	 * (RFC6120 - http://tools.ietf.org/html/rfc6120 ).
	 * For a description of format, see the RFC or page 14 of
	 * XMPP: The Definitive Guide (Saint-Andre et al.)
	 *
	 * Particularly - a Bare JID is a JID without a resource part.
	 *
	 * A JID can be invalid (when isValid() returns false). No member methods are 
	 * guaranteed to work correctly if they do.
	 */
	class SWIFTEN_API JID {
		public:
			enum CompareType {
				WithResource, WithoutResource
			};

			/**
			 * Create a JID from its String representation.
			 *
			 * e.g.
			 * wonderland.lit
			 * wonderland.lit/rabbithole
			 * alice@wonderland.lit
			 * alice@wonderland.lit/TeaParty
			 *
			 * @param jid String representation. Invalid JID if empty or invalid.
			 */
			JID(const std::string& jid = std::string());

			/**
			 * See std::string constructor.
			 *
			 * Must not be NULL.
			 */
			JID(const char*);

			/**
			 * Create a bare JID from the node and domain parts.
			 *
			 * JID("node@domain") == JID("node", "domain")
			 * unless you pass in empty values.
			 *
			 * @param node JID node part.
			 * @param domain JID domain part.
			 */
			JID(const std::string& node, const std::string& domain);
			/**
			 * Create a bare JID from the node, domain and resource parts.
			 *
			 * JID("node@domain/resource") == JID("node", "domain", "resource")
			 * unless you pass in empty values.
			 *
			 * @param node JID node part.
			 * @param domain JID domain part.
			 * @param resource JID resource part.
			 */
			JID(const std::string& node, const std::string& domain, const std::string& resource);

			/**
			 * @return Is a correctly-formatted JID.
			 */
			bool isValid() const {
				return valid_;
			}

			/**
			 * e.g. JID("node@domain").getNode() == "node"
			 * @return could be empty.
			 */
			const std::string& getNode() const {
				return node_;
			}

			/**
			 * e.g. JID("node@domain").getDomain() == "domain"
			 */
			const std::string& getDomain() const {
				return domain_;
			}

			/**
			 * e.g. JID("node@domain/resource").getResource() == "resource"
			 * @return could be empty.
			 */
			const std::string& getResource() const {
				return resource_;
			}

			/**
			 * Is a bare JID, i.e. has no resource part.
			 */
			bool isBare() const {
				return !hasResource_;
			}

			/**
			 * Returns the given node, escaped according to XEP-0106.
			 * The resulting node is a valid node for a JID, whereas the input value can contain characters
			 * that are not allowed.
			 */
			static std::string getEscapedNode(const std::string& node);

			/**
			 * Returns the node of the current JID, unescaped according to XEP-0106.
			 */
			std::string getUnescapedNode() const;

			/**
			 * Get the JID without a resource.
			 * @return Invalid if the original is invalid.
			 */
			JID toBare() const {
				JID result(*this);
				result.hasResource_ = false;
				result.resource_ = "";
				return result;
			}

			/**
			 * 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;

			bool equals(const JID& o, CompareType compareType) const {
				return compare(o, compareType) == 0;
			}

			int compare(const JID& o, CompareType compareType) const;

			operator std::string() const {
				return toString();
			}

			bool operator<(const Swift::JID& b) const {
				return compare(b, Swift::JID::WithResource) < 0;
			}

			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;
			}

			friend bool operator!=(const Swift::JID& a, const Swift::JID& b) {
				return a.compare(b, Swift::JID::WithResource) != 0;
			}

			/**
			 * 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);
			void initializeFromString(const std::string&);
	
		private:
			bool valid_;
			std::string node_;
			std::string domain_;
			bool hasResource_;
			std::string resource_;
	};
	
	SWIFTEN_API std::ostream& operator<<(std::ostream& os, const Swift::JID& j);
}