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.
tdenetwork/kopete/protocols/jabber/libiris/iris/xmpp-core/jid.cpp

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