(Re)moved Jid deprecated methods
[iris.git] / src / xmpp / jid / jid.cpp
blobd1d33be79b4da03c056633af3ee69d36a14ccac2
1 /*
2 * jid.cpp - class for verifying and manipulating Jabber IDs
3 * Copyright (C) 2003 Justin Karneges
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 //#undef IRIS_XMPP_JID_DEPRECATED
22 #include "xmpp/jid/jid.h"
24 #include <QCoreApplication>
25 #include <QByteArray>
26 #include <QHash>
27 #include <libidn/stringprep.h>
29 #ifndef NO_IRISNET
30 #include "irisnetglobal_p.h"
31 #endif
33 using namespace XMPP;
36 //----------------------------------------------------------------------------
37 // StringPrepCache
38 //----------------------------------------------------------------------------
39 class StringPrepCache : public QObject
41 public:
42 static bool nameprep(const QString &in, int maxbytes, QString& out)
44 if (in.isEmpty()) {
45 out = QString();
46 return true;
49 StringPrepCache *that = get_instance();
51 Result *r = that->nameprep_table[in];
52 if (r) {
53 if(!r->norm) {
54 return false;
56 out = *(r->norm);
57 return true;
60 QByteArray cs = in.toUtf8();
61 cs.resize(maxbytes);
62 if(stringprep(cs.data(), maxbytes, (Stringprep_profile_flags)0, stringprep_nameprep) != 0)
64 that->nameprep_table.insert(in, new Result);
65 return false;
68 QString norm = QString::fromUtf8(cs);
69 that->nameprep_table.insert(in, new Result(norm));
70 out = norm;
71 return true;
74 static bool nodeprep(const QString &in, int maxbytes, QString& out)
76 if(in.isEmpty()) {
77 out = QString();
78 return true;
81 StringPrepCache *that = get_instance();
83 Result *r = that->nodeprep_table[in];
84 if(r) {
85 if(!r->norm) {
86 return false;
88 out = *(r->norm);
89 return true;
92 QByteArray cs = in.toUtf8();
93 cs.resize(maxbytes);
94 if(stringprep(cs.data(), maxbytes, (Stringprep_profile_flags)0, stringprep_xmpp_nodeprep) != 0) {
95 that->nodeprep_table.insert(in, new Result);
96 return false;
99 QString norm = QString::fromUtf8(cs);
100 that->nodeprep_table.insert(in, new Result(norm));
101 out = norm;
102 return true;
105 static bool resourceprep(const QString &in, int maxbytes, QString& out)
107 if(in.isEmpty()) {
108 out = QString();
109 return true;
112 StringPrepCache *that = get_instance();
114 Result *r = that->resourceprep_table[in];
115 if(r) {
116 if(!r->norm) {
117 return false;
119 out = *(r->norm);
120 return true;
123 QByteArray cs = in.toUtf8();
124 cs.resize(maxbytes);
125 if(stringprep(cs.data(), maxbytes, (Stringprep_profile_flags)0, stringprep_xmpp_resourceprep) != 0) {
126 that->resourceprep_table.insert(in, new Result);
127 return false;
130 QString norm = QString::fromUtf8(cs);
131 that->resourceprep_table.insert(in, new Result(norm));
132 out = norm;
133 return true;
136 static void cleanup()
138 delete instance;
139 instance = 0;
142 private:
143 class Result
145 public:
146 QString *norm;
148 Result() : norm(0)
152 Result(const QString &s) : norm(new QString(s))
156 ~Result()
158 delete norm;
162 QHash<QString,Result*> nameprep_table;
163 QHash<QString,Result*> nodeprep_table;
164 QHash<QString,Result*> resourceprep_table;
166 static StringPrepCache *instance;
168 static StringPrepCache *get_instance()
170 if(!instance)
172 instance = new StringPrepCache;
173 #ifndef NO_IRISNET
174 irisNetAddPostRoutine(cleanup);
175 #endif
177 return instance;
180 StringPrepCache()
184 ~StringPrepCache()
186 foreach(Result* r, nameprep_table) {
187 delete r;
189 nameprep_table.clear();
190 foreach(Result* r, nodeprep_table) {
191 delete r;
193 nodeprep_table.clear();
194 foreach(Result* r, resourceprep_table) {
195 delete r;
197 resourceprep_table.clear();
201 StringPrepCache *StringPrepCache::instance = 0;
203 //----------------------------------------------------------------------------
204 // Jid
205 //----------------------------------------------------------------------------
207 static inline bool validDomain(const QString &s, QString& norm)
209 return StringPrepCache::nameprep(s, 1024, norm);
212 static inline bool validNode(const QString &s, QString& norm)
214 return StringPrepCache::nodeprep(s, 1024, norm);
217 static inline bool validResource(const QString &s, QString& norm)
219 return StringPrepCache::resourceprep(s, 1024, norm);
222 Jid::Jid()
224 valid = false;
225 null = true;
228 Jid::~Jid()
232 Jid::Jid(const QString &s)
234 set(s);
237 Jid::Jid(const QString &node, const QString& domain, const QString& resource)
239 set(domain, node, resource);
242 Jid::Jid(const char *s)
244 set(QString(s));
247 Jid & Jid::operator=(const QString &s)
249 set(s);
250 return *this;
253 Jid & Jid::operator=(const char *s)
255 set(QString(s));
256 return *this;
259 void Jid::reset()
261 f = QString();
262 b = QString();
263 d = QString();
264 n = QString();
265 r = QString();
266 valid = false;
267 null = true;
270 void Jid::update()
272 // build 'bare' and 'full' jids
273 if(n.isEmpty())
274 b = d;
275 else
276 b = n + '@' + d;
277 if(r.isEmpty())
278 f = b;
279 else
280 f = b + '/' + r;
281 if(f.isEmpty())
282 valid = false;
283 null = f.isEmpty() && r.isEmpty();
286 void Jid::set(const QString &s)
288 QString rest, domain, node, resource;
289 QString norm_domain, norm_node, norm_resource;
290 int x = s.indexOf('/');
291 if(x != -1) {
292 rest = s.mid(0, x);
293 resource = s.mid(x+1);
295 else {
296 rest = s;
297 resource = QString();
299 if(!validResource(resource, norm_resource)) {
300 reset();
301 return;
304 x = rest.indexOf('@');
305 if(x != -1) {
306 node = rest.mid(0, x);
307 domain = rest.mid(x+1);
309 else {
310 node = QString();
311 domain = rest;
313 if(!validDomain(domain, norm_domain) || !validNode(node, norm_node)) {
314 reset();
315 return;
318 valid = true;
319 null = false;
320 d = norm_domain;
321 n = norm_node;
322 r = norm_resource;
323 update();
326 void Jid::set(const QString &domain, const QString &node, const QString &resource)
328 QString norm_domain, norm_node, norm_resource;
329 if(!validDomain(domain, norm_domain) || !validNode(node, norm_node) || !validResource(resource, norm_resource)) {
330 reset();
331 return;
333 valid = true;
334 null = false;
335 d = norm_domain;
336 n = norm_node;
337 r = norm_resource;
338 update();
341 void Jid::setDomain(const QString &s)
343 if(!valid)
344 return;
345 QString norm;
346 if(!validDomain(s, norm)) {
347 reset();
348 return;
350 d = norm;
351 update();
354 void Jid::setNode(const QString &s)
356 if(!valid)
357 return;
358 QString norm;
359 if(!validNode(s, norm)) {
360 reset();
361 return;
363 n = norm;
364 update();
367 void Jid::setResource(const QString &s)
369 if(!valid)
370 return;
371 QString norm;
372 if(!validResource(s, norm)) {
373 reset();
374 return;
376 r = norm;
377 update();
380 Jid Jid::withNode(const QString &s) const
382 Jid j = *this;
383 j.setNode(s);
384 return j;
387 Jid Jid::withDomain(const QString &s) const
389 Jid j = *this;
390 j.setDomain(s);
391 return j;
394 Jid Jid::withResource(const QString &s) const
396 Jid j = *this;
397 j.setResource(s);
398 return j;
401 bool Jid::isValid() const
403 return valid;
406 bool Jid::isEmpty() const
408 return f.isEmpty();
411 bool Jid::compare(const Jid &a, bool compareRes) const
413 if(null && a.null)
414 return true;
416 // only compare valid jids
417 if(!valid || !a.valid)
418 return false;
420 if(compareRes ? (f != a.f) : (b != a.b))
421 return false;
423 return true;