You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
410 lines
7.5 KiB
410 lines
7.5 KiB
/*
|
|
* jid.cpp - class for verifying and manipulating Jabber IDs
|
|
* Copyright (C) 2003 Justin Karneges
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
*/
|
|
|
|
#include "xmpp.h"
|
|
|
|
#include <tqdict.h>
|
|
#include <stringprep.h>
|
|
|
|
using namespace XMPP;
|
|
|
|
//----------------------------------------------------------------------------
|
|
// StringPrepCache
|
|
//----------------------------------------------------------------------------
|
|
class StringPrepCache
|
|
{
|
|
public:
|
|
static bool nameprep(const TQString &in, int maxbytes, TQString *out)
|
|
{
|
|
if(in.isEmpty())
|
|
{
|
|
if(out)
|
|
*out = TQString();
|
|
return true;
|
|
}
|
|
|
|
StringPrepCache *that = get_instance();
|
|
|
|
Result *r = that->nameprep_table.find(in);
|
|
if(r)
|
|
{
|
|
if(!r->norm)
|
|
return false;
|
|
if(out)
|
|
*out = *(r->norm);
|
|
return true;
|
|
}
|
|
|
|
TQCString cs = in.utf8();
|
|
cs.resize(maxbytes);
|
|
if(stringprep(cs.data(), maxbytes, (Stringprep_profile_flags)0, stringprep_nameprep) != 0)
|
|
{
|
|
that->nameprep_table.insert(in, new Result);
|
|
return false;
|
|
}
|
|
|
|
TQString norm = TQString::fromUtf8(cs);
|
|
that->nameprep_table.insert(in, new Result(norm));
|
|
if(out)
|
|
*out = norm;
|
|
return true;
|
|
}
|
|
|
|
static bool nodeprep(const TQString &in, int maxbytes, TQString *out)
|
|
{
|
|
if(in.isEmpty())
|
|
{
|
|
if(out)
|
|
*out = TQString();
|
|
return true;
|
|
}
|
|
|
|
StringPrepCache *that = get_instance();
|
|
|
|
Result *r = that->nodeprep_table.find(in);
|
|
if(r)
|
|
{
|
|
if(!r->norm)
|
|
return false;
|
|
if(out)
|
|
*out = *(r->norm);
|
|
return true;
|
|
}
|
|
|
|
TQCString cs = in.utf8();
|
|
cs.resize(maxbytes);
|
|
if(stringprep(cs.data(), maxbytes, (Stringprep_profile_flags)0, stringprep_xmpp_nodeprep) != 0)
|
|
{
|
|
that->nodeprep_table.insert(in, new Result);
|
|
return false;
|
|
}
|
|
|
|
TQString norm = TQString::fromUtf8(cs);
|
|
that->nodeprep_table.insert(in, new Result(norm));
|
|
if(out)
|
|
*out = norm;
|
|
return true;
|
|
}
|
|
|
|
static bool resourceprep(const TQString &in, int maxbytes, TQString *out)
|
|
{
|
|
if(in.isEmpty())
|
|
{
|
|
if(out)
|
|
*out = TQString();
|
|
return true;
|
|
}
|
|
|
|
StringPrepCache *that = get_instance();
|
|
|
|
Result *r = that->resourceprep_table.find(in);
|
|
if(r)
|
|
{
|
|
if(!r->norm)
|
|
return false;
|
|
if(out)
|
|
*out = *(r->norm);
|
|
return true;
|
|
}
|
|
|
|
TQCString cs = in.utf8();
|
|
cs.resize(maxbytes);
|
|
if(stringprep(cs.data(), maxbytes, (Stringprep_profile_flags)0, stringprep_xmpp_resourceprep) != 0)
|
|
{
|
|
that->resourceprep_table.insert(in, new Result);
|
|
return false;
|
|
}
|
|
|
|
TQString norm = TQString::fromUtf8(cs);
|
|
that->resourceprep_table.insert(in, new Result(norm));
|
|
if(out)
|
|
*out = norm;
|
|
return true;
|
|
}
|
|
|
|
private:
|
|
class Result
|
|
{
|
|
public:
|
|
TQString *norm;
|
|
|
|
Result() : norm(0)
|
|
{
|
|
}
|
|
|
|
Result(const TQString &s) : norm(new TQString(s))
|
|
{
|
|
}
|
|
|
|
~Result()
|
|
{
|
|
delete norm;
|
|
}
|
|
};
|
|
|
|
TQDict<Result> nameprep_table;
|
|
TQDict<Result> nodeprep_table;
|
|
TQDict<Result> resourceprep_table;
|
|
|
|
static StringPrepCache *instance;
|
|
|
|
static StringPrepCache *get_instance()
|
|
{
|
|
if(!instance)
|
|
instance = new StringPrepCache;
|
|
return instance;
|
|
}
|
|
|
|
StringPrepCache()
|
|
{
|
|
nameprep_table.setAutoDelete(true);
|
|
nodeprep_table.setAutoDelete(true);
|
|
resourceprep_table.setAutoDelete(true);
|
|
}
|
|
};
|
|
|
|
StringPrepCache *StringPrepCache::instance = 0;
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Jid
|
|
//----------------------------------------------------------------------------
|
|
Jid::Jid()
|
|
{
|
|
valid = false;
|
|
}
|
|
|
|
Jid::~Jid()
|
|
{
|
|
}
|
|
|
|
Jid::Jid(const TQString &s)
|
|
{
|
|
set(s);
|
|
}
|
|
|
|
Jid::Jid(const char *s)
|
|
{
|
|
set(TQString(s));
|
|
}
|
|
|
|
Jid & Jid::operator=(const TQString &s)
|
|
{
|
|
set(s);
|
|
return *this;
|
|
}
|
|
|
|
Jid & Jid::operator=(const char *s)
|
|
{
|
|
set(TQString(s));
|
|
return *this;
|
|
}
|
|
|
|
void Jid::reset()
|
|
{
|
|
f = TQString();
|
|
b = TQString();
|
|
d = TQString();
|
|
n = TQString();
|
|
r = TQString();
|
|
valid = false;
|
|
}
|
|
|
|
void Jid::update()
|
|
{
|
|
// build 'bare' and 'full' jids
|
|
if(n.isEmpty())
|
|
b = d;
|
|
else
|
|
b = n + '@' + d;
|
|
|
|
b=b.lower(); // JID are not case sensitive
|
|
|
|
if(r.isEmpty())
|
|
f = b;
|
|
else
|
|
f = b + '/' + r;
|
|
if(f.isEmpty())
|
|
valid = false;
|
|
}
|
|
|
|
void Jid::set(const TQString &s)
|
|
{
|
|
TQString rest, domain, node, resource;
|
|
TQString norm_domain, norm_node, norm_resource;
|
|
int x = s.find('/');
|
|
if(x != -1) {
|
|
rest = s.mid(0, x);
|
|
resource = s.mid(x+1);
|
|
}
|
|
else {
|
|
rest = s;
|
|
resource = TQString();
|
|
}
|
|
if(!validResource(resource, &norm_resource)) {
|
|
reset();
|
|
return;
|
|
}
|
|
|
|
x = rest.find('@');
|
|
if(x != -1) {
|
|
node = rest.mid(0, x);
|
|
domain = rest.mid(x+1);
|
|
}
|
|
else {
|
|
node = TQString();
|
|
domain = rest;
|
|
}
|
|
if(!validDomain(domain, &norm_domain) || !validNode(node, &norm_node)) {
|
|
reset();
|
|
return;
|
|
}
|
|
|
|
valid = true;
|
|
d = norm_domain;
|
|
n = norm_node;
|
|
r = norm_resource;
|
|
update();
|
|
}
|
|
|
|
void Jid::set(const TQString &domain, const TQString &node, const TQString &resource)
|
|
{
|
|
TQString norm_domain, norm_node, norm_resource;
|
|
if(!validDomain(domain, &norm_domain) || !validNode(node, &norm_node) || !validResource(resource, &norm_resource)) {
|
|
reset();
|
|
return;
|
|
}
|
|
valid = true;
|
|
d = norm_domain;
|
|
n = norm_node;
|
|
r = norm_resource;
|
|
update();
|
|
}
|
|
|
|
void Jid::setDomain(const TQString &s)
|
|
{
|
|
if(!valid)
|
|
return;
|
|
TQString norm;
|
|
if(!validDomain(s, &norm)) {
|
|
reset();
|
|
return;
|
|
}
|
|
d = norm;
|
|
update();
|
|
}
|
|
|
|
void Jid::setNode(const TQString &s)
|
|
{
|
|
if(!valid)
|
|
return;
|
|
TQString norm;
|
|
if(!validNode(s, &norm)) {
|
|
reset();
|
|
return;
|
|
}
|
|
n = norm;
|
|
update();
|
|
}
|
|
|
|
void Jid::setResource(const TQString &s)
|
|
{
|
|
if(!valid)
|
|
return;
|
|
TQString norm;
|
|
if(!validResource(s, &norm)) {
|
|
reset();
|
|
return;
|
|
}
|
|
r = norm;
|
|
update();
|
|
}
|
|
|
|
Jid Jid::withNode(const TQString &s) const
|
|
{
|
|
Jid j = *this;
|
|
j.setNode(s);
|
|
return j;
|
|
}
|
|
|
|
Jid Jid::withResource(const TQString &s) const
|
|
{
|
|
Jid j = *this;
|
|
j.setResource(s);
|
|
return j;
|
|
}
|
|
|
|
bool Jid::isValid() const
|
|
{
|
|
return valid;
|
|
}
|
|
|
|
bool Jid::isEmpty() const
|
|
{
|
|
return f.isEmpty();
|
|
}
|
|
|
|
bool Jid::compare(const Jid &a, bool compareRes) const
|
|
{
|
|
// only compare valid jids
|
|
if(!valid || !a.valid)
|
|
return false;
|
|
|
|
if(compareRes ? (f != a.f) : (b != a.b))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Jid::validDomain(const TQString &s, TQString *norm)
|
|
{
|
|
/*TQCString cs = s.utf8();
|
|
cs.resize(1024);
|
|
if(stringprep(cs.data(), 1024, (Stringprep_profile_flags)0, stringprep_nameprep) != 0)
|
|
return false;
|
|
if(norm)
|
|
*norm = TQString::fromUtf8(cs);
|
|
return true;*/
|
|
return StringPrepCache::nameprep(s, 1024, norm);
|
|
}
|
|
|
|
bool Jid::validNode(const TQString &s, TQString *norm)
|
|
{
|
|
/*TQCString cs = s.utf8();
|
|
cs.resize(1024);
|
|
if(stringprep(cs.data(), 1024, (Stringprep_profile_flags)0, stringprep_xmpp_nodeprep) != 0)
|
|
return false;
|
|
if(norm)
|
|
*norm = TQString::fromUtf8(cs);
|
|
return true;*/
|
|
return StringPrepCache::nodeprep(s, 1024, norm);
|
|
}
|
|
|
|
bool Jid::validResource(const TQString &s, TQString *norm)
|
|
{
|
|
/*TQCString cs = s.utf8();
|
|
cs.resize(1024);
|
|
if(stringprep(cs.data(), 1024, (Stringprep_profile_flags)0, stringprep_xmpp_resourceprep) != 0)
|
|
return false;
|
|
if(norm)
|
|
*norm = TQString::fromUtf8(cs);
|
|
return true;*/
|
|
return StringPrepCache::resourceprep(s, 1024, norm);
|
|
}
|