~ubuntu-branches/ubuntu/saucy/kopete/saucy-proposed

« back to all changes in this revision

Viewing changes to protocols/jabber/libiris/src/xmpp/jid/jid.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-06-21 02:22:39 UTC
  • Revision ID: package-import@ubuntu.com-20130621022239-63l3zc8p0nf26pt6
Tags: upstream-4.10.80
ImportĀ upstreamĀ versionĀ 4.10.80

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * jid.cpp - class for verifying and manipulating XMPP addresses
 
3
 * Copyright (C) 2003  Justin Karneges
 
4
 *
 
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.
 
9
 *
 
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.
 
14
 *
 
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
18
 *
 
19
 */
 
20
 
 
21
//#undef IRIS_XMPP_JID_DEPRECATED
 
22
#include "xmpp/jid/jid.h"
 
23
 
 
24
#include <QCoreApplication>
 
25
#include <libidn/stringprep.h>
 
26
 
 
27
#ifndef NO_IRISNET
 
28
#include "irisnetglobal_p.h"
 
29
#endif
 
30
 
 
31
using namespace XMPP;
 
32
 
 
33
 
 
34
//----------------------------------------------------------------------------
 
35
// StringPrepCache
 
36
//----------------------------------------------------------------------------
 
37
        StringPrepCache *StringPrepCache::instance = 0;
 
38
 
 
39
        bool StringPrepCache::nameprep(const QString &in, int maxbytes, QString& out)
 
40
        {
 
41
                if (in.trimmed().isEmpty()) {
 
42
                        out = QString();
 
43
                        return false; // empty names or just spaces are disallowed (rfc5892+rfc6122)
 
44
                }
 
45
 
 
46
                StringPrepCache *that = get_instance();
 
47
 
 
48
                Result *r = that->nameprep_table[in];
 
49
                if (r) {
 
50
                        if(!r->norm) {
 
51
                                return false;
 
52
                        }
 
53
                        out = *(r->norm);
 
54
                        return true;
 
55
                }
 
56
 
 
57
                QByteArray cs = in.toUtf8();
 
58
                cs.resize(maxbytes);
 
59
                if(stringprep(cs.data(), maxbytes, (Stringprep_profile_flags)0, stringprep_nameprep) != 0)
 
60
                {
 
61
                        that->nameprep_table.insert(in, new Result);
 
62
                        return false;
 
63
                }
 
64
 
 
65
                QString norm = QString::fromUtf8(cs);
 
66
                that->nameprep_table.insert(in, new Result(norm));
 
67
                out = norm;
 
68
                return true;
 
69
        }
 
70
 
 
71
        bool StringPrepCache::nodeprep(const QString &in, int maxbytes, QString& out)
 
72
        {
 
73
                if(in.isEmpty()) {
 
74
      out = QString();
 
75
                        return true;
 
76
                }
 
77
 
 
78
                StringPrepCache *that = get_instance();
 
79
 
 
80
                Result *r = that->nodeprep_table[in];
 
81
                if(r) {
 
82
                        if(!r->norm) {
 
83
                                return false;
 
84
                        }
 
85
                        out = *(r->norm);
 
86
                        return true;
 
87
                }
 
88
 
 
89
                QByteArray cs = in.toUtf8();
 
90
                cs.resize(maxbytes);
 
91
                if(stringprep(cs.data(), maxbytes, (Stringprep_profile_flags)0, stringprep_xmpp_nodeprep) != 0) {
 
92
                        that->nodeprep_table.insert(in, new Result);
 
93
                        return false;
 
94
                }
 
95
 
 
96
                QString norm = QString::fromUtf8(cs);
 
97
                that->nodeprep_table.insert(in, new Result(norm));
 
98
                out = norm;
 
99
                return true;
 
100
        }
 
101
 
 
102
        bool StringPrepCache::resourceprep(const QString &in, int maxbytes, QString& out)
 
103
        {
 
104
                if(in.isEmpty()) {
 
105
      out = QString();
 
106
                        return true;
 
107
                }
 
108
 
 
109
                StringPrepCache *that = get_instance();
 
110
 
 
111
                Result *r = that->resourceprep_table[in];
 
112
                if(r) {
 
113
                        if(!r->norm) {
 
114
                                return false;
 
115
                        }
 
116
                        out = *(r->norm);
 
117
                        return true;
 
118
                }
 
119
 
 
120
                QByteArray cs = in.toUtf8();
 
121
                cs.resize(maxbytes);
 
122
                if(stringprep(cs.data(), maxbytes, (Stringprep_profile_flags)0, stringprep_xmpp_resourceprep) != 0) {
 
123
                        that->resourceprep_table.insert(in, new Result);
 
124
                        return false;
 
125
                }
 
126
 
 
127
                QString norm = QString::fromUtf8(cs);
 
128
                that->resourceprep_table.insert(in, new Result(norm));
 
129
                out = norm;
 
130
                return true;
 
131
        }
 
132
 
 
133
        bool StringPrepCache::saslprep(const QString &in, int maxbytes, QString& out)
 
134
        {
 
135
                if(in.isEmpty()) {
 
136
          out = QString();
 
137
                        return true;
 
138
                }
 
139
 
 
140
                StringPrepCache *that = get_instance();
 
141
 
 
142
                Result *r = that->saslprep_table[in];
 
143
                if(r) {
 
144
                        if(!r->norm) {
 
145
                                return false;
 
146
                        }
 
147
                        out = *(r->norm);
 
148
                        return true;
 
149
                }
 
150
 
 
151
                QByteArray cs = in.toUtf8();
 
152
                cs.resize(maxbytes);
 
153
                if(stringprep(cs.data(), maxbytes, (Stringprep_profile_flags)0, stringprep_saslprep) != 0) {
 
154
                        that->saslprep_table.insert(in, new Result);
 
155
                        return false;
 
156
                }
 
157
 
 
158
                QString norm = QString::fromUtf8(cs);
 
159
                that->saslprep_table.insert(in, new Result(norm));
 
160
                out = norm;
 
161
                return true;
 
162
        }
 
163
 
 
164
        void StringPrepCache::cleanup()
 
165
        {
 
166
                delete instance;
 
167
                instance = 0;
 
168
        }
 
169
 
 
170
        StringPrepCache *StringPrepCache::get_instance()
 
171
        {
 
172
                if(!instance)
 
173
                {
 
174
                        instance = new StringPrepCache;
 
175
#ifndef NO_IRISNET
 
176
                        irisNetAddPostRoutine(cleanup);
 
177
#endif
 
178
                }
 
179
                return instance;
 
180
        }
 
181
 
 
182
        StringPrepCache::StringPrepCache()
 
183
                : QObject(QCoreApplication::instance())
 
184
        {
 
185
        }
 
186
 
 
187
        StringPrepCache::~StringPrepCache()
 
188
        {
 
189
                foreach(Result* r, nameprep_table) {
 
190
                        delete r;
 
191
                }
 
192
                nameprep_table.clear();
 
193
                foreach(Result* r, nodeprep_table) {
 
194
                        delete r;
 
195
                }
 
196
                nodeprep_table.clear();
 
197
                foreach(Result* r, resourceprep_table) {
 
198
                        delete r;
 
199
                }
 
200
                resourceprep_table.clear();
 
201
                foreach(Result* r, saslprep_table) {
 
202
                        delete r;
 
203
                }
 
204
                saslprep_table.clear();
 
205
        }
 
206
 
 
207
//----------------------------------------------------------------------------
 
208
// Jid
 
209
//----------------------------------------------------------------------------
 
210
//
 
211
static inline bool validDomain(const QString &s, QString& norm)
 
212
{
 
213
        return StringPrepCache::nameprep(s, 1024, norm);
 
214
}
 
215
 
 
216
static inline bool validNode(const QString &s, QString& norm)
 
217
{
 
218
        return StringPrepCache::nodeprep(s, 1024, norm);
 
219
}
 
220
 
 
221
static inline bool validResource(const QString &s, QString& norm)
 
222
{
 
223
        return StringPrepCache::resourceprep(s, 1024, norm);
 
224
}
 
225
 
 
226
Jid::Jid()
 
227
{
 
228
        valid = false;
 
229
        null = true;
 
230
}
 
231
 
 
232
Jid::~Jid()
 
233
{
 
234
}
 
235
 
 
236
Jid::Jid(const QString &s)
 
237
{
 
238
        set(s);
 
239
}
 
240
 
 
241
Jid::Jid(const QString &node, const QString& domain, const QString& resource)
 
242
{
 
243
        set(domain, node, resource);
 
244
}
 
245
 
 
246
Jid::Jid(const char *s)
 
247
{
 
248
        set(QString(s));
 
249
}
 
250
 
 
251
Jid & Jid::operator=(const QString &s)
 
252
{
 
253
        set(s);
 
254
        return *this;
 
255
}
 
256
 
 
257
Jid & Jid::operator=(const char *s)
 
258
{
 
259
        set(QString(s));
 
260
        return *this;
 
261
}
 
262
 
 
263
void Jid::reset()
 
264
{
 
265
        f = QString();
 
266
        b = QString();
 
267
        d = QString();
 
268
        n = QString();
 
269
        r = QString();
 
270
        valid = false;
 
271
        null = true;
 
272
}
 
273
 
 
274
void Jid::update()
 
275
{
 
276
        // build 'bare' and 'full' jids
 
277
        if(n.isEmpty())
 
278
                b = d;
 
279
        else
 
280
                b = n + '@' + d;
 
281
        if(r.isEmpty())
 
282
                f = b;
 
283
        else
 
284
                f = b + '/' + r;
 
285
        if(f.isEmpty())
 
286
                valid = false;
 
287
        null = f.isEmpty() && r.isEmpty();
 
288
}
 
289
 
 
290
void Jid::set(const QString &s)
 
291
{
 
292
        QString rest, domain, node, resource;
 
293
        QString norm_domain, norm_node, norm_resource;
 
294
        int x = s.indexOf('/');
 
295
        if(x != -1) {
 
296
                rest = s.mid(0, x);
 
297
                resource = s.mid(x+1);
 
298
        }
 
299
        else {
 
300
                rest = s;
 
301
                resource = QString();
 
302
        }
 
303
        if(!validResource(resource, norm_resource)) {
 
304
                reset();
 
305
                return;
 
306
        }
 
307
 
 
308
        x = rest.indexOf('@');
 
309
        if(x != -1) {
 
310
                node = rest.mid(0, x);
 
311
                domain = rest.mid(x+1);
 
312
        }
 
313
        else {
 
314
                node = QString();
 
315
                domain = rest;
 
316
        }
 
317
        if(!validDomain(domain, norm_domain) || !validNode(node, norm_node)) {
 
318
                reset();
 
319
                return;
 
320
        }
 
321
 
 
322
        valid = true;
 
323
        null = false;
 
324
        d = norm_domain;
 
325
        n = norm_node;
 
326
        r = norm_resource;
 
327
        update();
 
328
}
 
329
 
 
330
void Jid::set(const QString &domain, const QString &node, const QString &resource)
 
331
{
 
332
        QString norm_domain, norm_node, norm_resource;
 
333
        if(!validDomain(domain, norm_domain) ||
 
334
                        !validNode(node, norm_node) ||
 
335
                        !validResource(resource, norm_resource))
 
336
        {
 
337
                reset();
 
338
                return;
 
339
        }
 
340
        valid = true;
 
341
        null = false;
 
342
        d = norm_domain;
 
343
        n = norm_node;
 
344
        r = norm_resource;
 
345
        update();
 
346
}
 
347
 
 
348
void Jid::setDomain(const QString &s)
 
349
{
 
350
        if(!valid)
 
351
                return;
 
352
        QString norm;
 
353
        if(!validDomain(s, norm)) {
 
354
                reset();
 
355
                return;
 
356
        }
 
357
        d = norm;
 
358
        update();
 
359
}
 
360
 
 
361
void Jid::setNode(const QString &s)
 
362
{
 
363
        if(!valid)
 
364
                return;
 
365
        QString norm;
 
366
        if(!validNode(s, norm)) {
 
367
                reset();
 
368
                return;
 
369
        }
 
370
        n = norm;
 
371
        update();
 
372
}
 
373
 
 
374
void Jid::setResource(const QString &s)
 
375
{
 
376
        if(!valid)
 
377
                return;
 
378
        QString norm;
 
379
        if(!validResource(s, norm)) {
 
380
                reset();
 
381
                return;
 
382
        }
 
383
        r = norm;
 
384
        update();
 
385
}
 
386
 
 
387
Jid Jid::withNode(const QString &s) const
 
388
{
 
389
        Jid j = *this;
 
390
        j.setNode(s);
 
391
        return j;
 
392
}
 
393
 
 
394
Jid Jid::withDomain(const QString &s) const
 
395
{
 
396
        Jid j = *this;
 
397
        j.setDomain(s);
 
398
        return j;
 
399
}
 
400
 
 
401
Jid Jid::withResource(const QString &s) const
 
402
{
 
403
        Jid j = *this;
 
404
        j.setResource(s);
 
405
        return j;
 
406
}
 
407
 
 
408
bool Jid::isValid() const
 
409
{
 
410
        return valid;
 
411
}
 
412
 
 
413
bool Jid::isEmpty() const
 
414
{
 
415
        return f.isEmpty();
 
416
}
 
417
 
 
418
bool Jid::compare(const Jid &a, bool compareRes) const
 
419
{
 
420
        if(null && a.null)
 
421
                return true;
 
422
 
 
423
        // only compare valid jids
 
424
        if(!valid || !a.valid)
 
425
                return false;
 
426
 
 
427
        if(compareRes ? (f != a.f) : (b != a.b))
 
428
                return false;
 
429
 
 
430
        return true;
 
431
}