kresolver.cpp
/* -*- C++ -*-
* Copyright (C) 2003-2005 Thiago Macieira <thiago.macieira@kdemail.net>
*
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
// System includes
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/param.h>
#include <errno.h>
#include <netdb.h>
#include <time.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <unistd.h>
// Qt includes
#include <qapplication.h>
#include <qstring.h>
#include <qcstring.h>
#include <qstrlist.h>
#include <qstringlist.h>
#include <qshared.h>
#include <qdatetime.h>
#include <qtimer.h>
#include <qmutex.h>
#include <qguardedptr.h>
// IDN
#ifdef HAVE_IDNA_H
# include <idna.h>
#endif
// KDE
#include <klocale.h>
// Us
#include "kresolver.h"
#include "kresolver_p.h"
#include "ksocketaddress.h"
#ifdef NEED_MUTEX
#warning "mutex"
QMutex getXXbyYYmutex;
#endif
using namespace KNetwork;
using namespace KNetwork::Internal;
// class KResolverEntry
class KNetwork::KResolverEntryPrivate: public QShared
{
public:
KSocketAddress addr;
int socktype;
int protocol;
QString canonName;
QCString encodedName;
inline KResolverEntryPrivate() :
socktype(0), protocol(0)
{ }
};
// default constructor
KResolverEntry::KResolverEntry() :
d(0L)
{
}
// constructor with stuff
KResolverEntry::KResolverEntry(const KSocketAddress& addr, int socktype, int protocol,
const QString& canonName, const QCString& encodedName) :
d(new KResolverEntryPrivate)
{
d->addr = addr;
d->socktype = socktype;
d->protocol = protocol;
d->canonName = canonName;
d->encodedName = encodedName;
}
// constructor with even more stuff
KResolverEntry::KResolverEntry(const struct sockaddr* sa, Q_UINT16 salen, int socktype,
int protocol, const QString& canonName,
const QCString& encodedName) :
d(new KResolverEntryPrivate)
{
d->addr = KSocketAddress(sa, salen);
d->socktype = socktype;
d->protocol = protocol;
d->canonName = canonName;
d->encodedName = encodedName;
}
// copy constructor
KResolverEntry::KResolverEntry(const KResolverEntry& that) :
d(0L)
{
*this = that;
}
// destructor
KResolverEntry::~KResolverEntry()
{
if (d == 0L)
return;
if (d->deref())
delete d;
}
// returns the socket address
KSocketAddress KResolverEntry::address() const
{
return d ? d->addr : KSocketAddress();
}
// returns the length
Q_UINT16 KResolverEntry::length() const
{
return d ? d->addr.length() : 0;
}
// returns the family
int KResolverEntry::family() const
{
return d ? d->addr.family() : AF_UNSPEC;
}
// returns the canonical name
QString KResolverEntry::canonicalName() const
{
return d ? d->canonName : QString::null;
}
// returns the encoded name
QCString KResolverEntry::encodedName() const
{
return d ? d->encodedName : QCString();
}
// returns the socket type
int KResolverEntry::socketType() const
{
return d ? d->socktype : 0;
}
// returns the protocol
int KResolverEntry::protocol() const
{
return d ? d->protocol : 0;
}
// assignment operator
KResolverEntry& KResolverEntry::operator= (const KResolverEntry& that)
{
// copy the data
if (that.d)
that.d->ref();
if (d && d->deref())
delete d;
d = that.d;
return *this;
}
// class KResolverResults
class KNetwork::KResolverResultsPrivate
{
public:
QString node, service;
int errorcode, syserror;
KResolverResultsPrivate() :
errorcode(0), syserror(0)
{ }
};
// default constructor
KResolverResults::KResolverResults()
: d(new KResolverResultsPrivate)
{
}
// copy constructor
KResolverResults::KResolverResults(const KResolverResults& other)
: QValueList<KResolverEntry>(other), d(new KResolverResultsPrivate)
{
*d = *other.d;
}
// destructor
KResolverResults::~KResolverResults()
{
delete d;
}
// assignment operator
KResolverResults&
KResolverResults::operator= (const KResolverResults& other)
{
if (this == &other)
return *this;
// copy over the other data
*d = *other.d;
// now let QValueList do the rest of the work
QValueList<KResolverEntry>::operator =(other);
return *this;
}
// gets the error code
int KResolverResults::error() const
{
return d->errorcode;
}
// gets the system errno
int KResolverResults::systemError() const
{
return d->syserror;
}
// sets the error codes
void KResolverResults::setError(int errorcode, int systemerror)
{
d->errorcode = errorcode;
d->syserror = systemerror;
}
// gets the hostname
QString KResolverResults::nodeName() const
{
return d->node;
}
// gets the service name
QString KResolverResults::serviceName() const
{
return d->service;
}
// sets the address
void KResolverResults::setAddress(const QString& node,
const QString& service)
{
d->node = node;
d->service = service;
}
void KResolverResults::virtual_hook( int, void* )
{ /*BASE::virtual_hook( id, data );*/ }
// class KResolver
QStringList *KResolver::idnDomains = 0;
// default constructor
KResolver::KResolver(QObject *parent, const char *name)
: QObject(parent, name), d(new KResolverPrivate(this))
{
}
// constructor with host and service
KResolver::KResolver(const QString& nodename, const QString& servicename,
QObject *parent, const char *name)
: QObject(parent, name), d(new KResolverPrivate(this, nodename, servicename))
{
}
// destructor
KResolver::~KResolver()
{
cancel(false);
delete d;
}
// get the status
int KResolver::status() const
{
return d->status;
}
// get the error code
int KResolver::error() const
{
return d->errorcode;
}
// get the errno
int KResolver::systemError() const
{
return d->syserror;
}
// are we running?
bool KResolver::isRunning() const
{
return d->status > 0 && d->status < Success;
}
// get the hostname
QString KResolver::nodeName() const
{
return d->input.node;
}
// get the service
QString KResolver::serviceName() const
{
return d->input.service;
}
// sets the hostname
void KResolver::setNodeName(const QString& nodename)
{
// don't touch those values if we're working!
if (!isRunning())
{
d->input.node = nodename;
d->status = Idle;
d->results.setAddress(nodename, d->input.service);
}
}
// sets the service
void KResolver::setServiceName(const QString& service)
{
// don't change if running
if (!isRunning())
{
d->input.service = service;
d->status = Idle;
d->results.setAddress(d->input.node, service);
}
}
// sets the address
void KResolver::setAddress(const QString& nodename, const QString& service)
{
setNodeName(nodename);
setServiceName(service);
}
// get the flags
int KResolver::flags() const
{
return d->input.flags;
}
// sets the flags
int KResolver::setFlags(int flags)
{
int oldflags = d->input.flags;
if (!isRunning())
{
d->input.flags = flags;
d->status = Idle;
}
return oldflags;
}
// sets the family mask
void KResolver::setFamily(int families)
{
if (!isRunning())
{
d->input.familyMask = families;
d->status = Idle;
}
}
// sets the socket type
void KResolver::setSocketType(int type)
{
if (!isRunning())
{
d->input.socktype = type;
d->status = Idle;
}
}
// sets the protocol
void KResolver::setProtocol(int protonum, const char *name)
{
if (isRunning())
return; // can't change now
// we copy the given protocol name. If it isn't an empty string
// and the protocol number was 0, we will look it up in /etc/protocols
// we also leave the error reporting to the actual lookup routines, in
// case the given protocol name doesn't exist
d->input.protocolName = name;
if (protonum == 0 && name != 0L && *name != '\0')
{
// must look up the protocol number
d->input.protocol = KResolver::protocolNumber(name);
}
else
d->input.protocol = protonum;
d->status = Idle;
}
bool KResolver::start()
{
if (!isRunning())
{
d->results.empty();
// is there anything to be queued?
if (d->input.node.isEmpty() && d->input.service.isEmpty())
{
d->status = KResolver::Success;
emitFinished();
}
else
KResolverManager::manager()->enqueue(this, 0L);
}
return true;
}
bool KResolver::wait(int msec)
{
if (!isRunning())
{
emitFinished();
return true;
}
QMutexLocker locker(&d->mutex);
if (!isRunning())
{
// it was running and no longer is?
// That means the manager has finished its processing and has posted
// an event for the signal to be emitted already. This means the signal
// will be emitted twice!
emitFinished();
return true;
}
else
{
QTime t;
t.start();
while (!msec || t.elapsed() < msec)
{
// wait on the manager to broadcast completion
d->waiting = true;
if (msec)
KResolverManager::manager()->notifyWaiters.wait(&d->mutex, msec - t.elapsed());
else
KResolverManager::manager()->notifyWaiters.wait(&d->mutex);
// the manager has processed
// see if this object is done
if (!isRunning())
{
// it's done
d->waiting = false;
emitFinished();
return true;
}
}
// if we've got here, we've timed out
d->waiting = false;
return false;
}
}
void KResolver::cancel(bool emitSignal)
{
KResolverManager::manager()->dequeue(this);
if (emitSignal)
emitFinished();
}
KResolverResults
KResolver::results() const
{
if (!isRunning())
return d->results;
// return a dummy, empty result
KResolverResults r;
r.setAddress(d->input.node, d->input.service);
r.setError(d->errorcode, d->syserror);
return r;
}
bool KResolver::event(QEvent* e)
{
if (static_cast<int>(e->type()) == KResolverManager::ResolutionCompleted)
{
emitFinished();
return true;
}
return false;
}
void KResolver::emitFinished()
{
if (isRunning())
d->status = KResolver::Success;
QGuardedPtr<QObject> p = this; // guard against deletion
emit finished(d->results);
if (p && d->deleteWhenDone)
deleteLater(); // in QObject
}
QString KResolver::errorString(int errorcode, int syserror)
{
// no i18n now...
static const char * const messages[] =
{
I18N_NOOP("no error"), // NoError
I18N_NOOP("requested family not supported for this host name"), // AddrFamily
I18N_NOOP("temporary failure in name resolution"), // TryAgain
I18N_NOOP("non-recoverable failure in name resolution"), // NonRecoverable
I18N_NOOP("invalid flags"), // BadFlags
I18N_NOOP("memory allocation failure"), // Memory
I18N_NOOP("name or service not known"), // NoName
I18N_NOOP("requested family not supported"), // UnsupportedFamily
I18N_NOOP("requested service not supported for this socket type"), // UnsupportedService
I18N_NOOP("requested socket type not supported"), // UnsupportedSocketType
I18N_NOOP("unknown error"), // UnknownError
I18N_NOOP2("1: the i18n'ed system error code, from errno",
"system error: %1") // SystemError
};
// handle the special value
if (errorcode == Canceled)
return i18n("request was canceled");
if (errorcode > 0 || errorcode < SystemError)
return QString::null;
QString msg = i18n(messages[-errorcode]);
if (errorcode == SystemError)
msg.arg(QString::fromLocal8Bit(strerror(syserror)));
return msg;
}
KResolverResults
KResolver::resolve(const QString& host, const QString& service, int flags,
int families)
{
KResolver qres(host, service, qApp, "synchronous KResolver");
qres.setFlags(flags);
qres.setFamily(families);
qres.start();
qres.wait();
return qres.results();
}
bool KResolver::resolveAsync(QObject* userObj, const char *userSlot,
const QString& host, const QString& service,
int flags, int families)
{
KResolver* qres = new KResolver(host, service, qApp, "asynchronous KResolver");
QObject::connect(qres, SIGNAL(finished(KResolverResults)), userObj, userSlot);
qres->setFlags(flags);
qres->setFamily(families);
qres->d->deleteWhenDone = true; // this is the only difference from the example code
return qres->start();
}
QStrList KResolver::protocolName(int protonum)
{
struct protoent *pe = 0L;
#ifndef HAVE_GETPROTOBYNAME_R
QMutexLocker locker(&getXXbyYYmutex);
pe = getprotobynumber(protonum);
#else
size_t buflen = 1024;
struct protoent protobuf;
char *buf;
do
{
buf = new char[buflen];
# ifdef USE_SOLARIS // Solaris uses a 4 argument getprotobynumber_r which returns struct *protoent or NULL
if ((pe = getprotobynumber_r(protonum, &protobuf, buf, buflen)) && (errno == ERANGE))
# else
if (getprotobynumber_r(protonum, &protobuf, buf, buflen, &pe) == ERANGE)
# endif
{
pe = 0L;
buflen += 1024;
delete [] buf;
}
else
break;
}
while (pe == 0L);
#endif
// Do common processing
QStrList lst(true); // use deep copies
if (pe != NULL)
{
lst.append(pe->p_name);
for (char **p = pe->p_aliases; *p; p++)
lst.append(*p);
}
#ifdef HAVE_GETPROTOBYNAME_R
delete [] buf;
#endif
return lst;
}
QStrList KResolver::protocolName(const char *protoname)
{
struct protoent *pe = 0L;
#ifndef HAVE_GETPROTOBYNAME_R
QMutexLocker locker(&getXXbyYYmutex);
pe = getprotobyname(protoname);
#else
size_t buflen = 1024;
struct protoent protobuf;
char *buf;
do
{
buf = new char[buflen];
# ifdef USE_SOLARIS // Solaris uses a 4 argument getprotobyname_r which returns struct *protoent or NULL
if ((pe = getprotobyname_r(protoname, &protobuf, buf, buflen)) && (errno == ERANGE))
# else
if (getprotobyname_r(protoname, &protobuf, buf, buflen, &pe) == ERANGE)
# endif
{
pe = 0L;
buflen += 1024;
delete [] buf;
}
else
break;
}
while (pe == 0L);
#endif
// Do common processing
QStrList lst(true); // use deep copies
if (pe != NULL)
{
lst.append(pe->p_name);
for (char **p = pe->p_aliases; *p; p++)
lst.append(*p);
}
#ifdef HAVE_GETPROTOBYNAME_R
delete [] buf;
#endif
return lst;
}
int KResolver::protocolNumber(const char *protoname)
{
struct protoent *pe = 0L;
#ifndef HAVE_GETPROTOBYNAME_R
QMutexLocker locker(&getXXbyYYmutex);
pe = getprotobyname(protoname);
#else
size_t buflen = 1024;
struct protoent protobuf;
char *buf;
do
{
buf = new char[buflen];
# ifdef USE_SOLARIS // Solaris uses a 4 argument getprotobyname_r which returns struct *protoent or NULL
if ((pe = getprotobyname_r(protoname, &protobuf, buf, buflen)) && (errno == ERANGE))
# else
if (getprotobyname_r(protoname, &protobuf, buf, buflen, &pe) == ERANGE)
# endif
{
pe = 0L;
buflen += 1024;
delete [] buf;
}
else
break;
}
while (pe == 0L);
#endif
// Do common processing
int protonum = -1;
if (pe != NULL)
protonum = pe->p_proto;
#ifdef HAVE_GETPROTOBYNAME_R
delete [] buf;
#endif
return protonum;
}
int KResolver::servicePort(const char *servname, const char *protoname)
{
struct servent *se = 0L;
#ifndef HAVE_GETSERVBYNAME_R
QMutexLocker locker(&getXXbyYYmutex);
se = getservbyname(servname, protoname);
#else
size_t buflen = 1024;
struct servent servbuf;
char *buf;
do
{
buf = new char[buflen];
# ifdef USE_SOLARIS // Solaris uses a 5 argument getservbyname_r which returns struct *servent or NULL
if ((se = getservbyname_r(servname, protoname, &servbuf, buf, buflen)) && (errno == ERANGE))
# else
if (getservbyname_r(servname, protoname, &servbuf, buf, buflen, &se) == ERANGE)
# endif
{
se = 0L;
buflen += 1024;
delete [] buf;
}
else
break;
}
while (se == 0L);
#endif
// Do common processing
int servport = -1;
if (se != NULL)
servport = ntohs(se->s_port);
#ifdef HAVE_GETSERVBYNAME_R
delete [] buf;
#endif
return servport;
}
QStrList KResolver::serviceName(const char* servname, const char *protoname)
{
struct servent *se = 0L;
#ifndef HAVE_GETSERVBYNAME_R
QMutexLocker locker(&getXXbyYYmutex);
se = getservbyname(servname, protoname);
#else
size_t buflen = 1024;
struct servent servbuf;
char *buf;
do
{
buf = new char[buflen];
# ifdef USE_SOLARIS // Solaris uses a 5 argument getservbyname_r which returns struct *servent or NULL
if ((se = getservbyname_r(servname, protoname, &servbuf, buf, buflen)) && (errno == ERANGE))
# else
if (getservbyname_r(servname, protoname, &servbuf, buf, buflen, &se) == ERANGE)
# endif
{
se = 0L;
buflen += 1024;
delete [] buf;
}
else
break;
}
while (se == 0L);
#endif
// Do common processing
QStrList lst(true); // use deep copies
if (se != NULL)
{
lst.append(se->s_name);
for (char **p = se->s_aliases; *p; p++)
lst.append(*p);
}
#ifdef HAVE_GETSERVBYNAME_R
delete [] buf;
#endif
return lst;
}
QStrList KResolver::serviceName(int port, const char *protoname)
{
struct servent *se = 0L;
#ifndef HAVE_GETSERVBYPORT_R
QMutexLocker locker(&getXXbyYYmutex);
se = getservbyport(port, protoname);
#else
size_t buflen = 1024;
struct servent servbuf;
char *buf;
do
{
buf = new char[buflen];
# ifdef USE_SOLARIS // Solaris uses a 5 argument getservbyport_r which returns struct *servent or NULL
if ((se = getservbyport_r(port, protoname, &servbuf, buf, buflen)) && (errno == ERANGE))
# else
if (getservbyport_r(port, protoname, &servbuf, buf, buflen, &se) == ERANGE)
# endif
{
se = 0L;
buflen += 1024;
delete [] buf;
}
else
break;
}
while (se == 0L);
#endif
// Do common processing
QStrList lst(true); // use deep copies
if (se != NULL)
{
lst.append(se->s_name);
for (char **p = se->s_aliases; *p; p++)
lst.append(*p);
}
#ifdef HAVE_GETSERVBYPORT_R
delete [] buf;
#endif
return lst;
}
QString KResolver::localHostName()
{
QCString name;
int len;
#ifdef MAXHOSTNAMELEN
len = MAXHOSTNAMELEN;
#else
len = 256;
#endif
while (true)
{
name.resize(len);
if (gethostname(name.data(), len - 1) == 0)
{
// Call succeeded, but it's not guaranteed to be NUL-terminated
// Note that some systems return success even if they did truncation
name[len - 1] = '\0';
break;
}
// Call failed
if (errno == ENAMETOOLONG || errno == EINVAL)
len += 256;
else
{
// Oops! Unknown error!
name = QCString();
}
}
if (name.isEmpty())
return QString::fromLatin1("localhost");
if (name.find('.') == -1)
{
// not fully qualified
// must resolve
KResolverResults results = resolve(name, "0", CanonName);
if (results.isEmpty())
// cannot find a valid hostname!
return QString::fromLatin1("localhost");
else
return results.first().canonicalName();
}
return domainToUnicode(name);
}
// forward declaration
static QStringList splitLabels(const QString& unicodeDomain);
static QCString ToASCII(const QString& label);
static QString ToUnicode(const QString& label);
static QStringList *KResolver_initIdnDomains()
{
const char *kde_use_idn = getenv("KDE_USE_IDN");
if (!kde_use_idn)
kde_use_idn = "ac:at:br:cat:ch:cl:cn:de:dk:fi:gr:hu:info:io:is:jp:kr:li:lt:museum:org:no:se:sh:th:tm:tw:vn";
return new QStringList(QStringList::split(':', QString::fromLatin1(kde_use_idn).lower()));
}
// implement the ToAscii function, as described by IDN documents
QCString KResolver::domainToAscii(const QString& unicodeDomain)
{
if (!idnDomains)
idnDomains = KResolver_initIdnDomains();
QCString retval;
// RFC 3490, section 4 describes the operation:
// 1) this is a query, so don't allow unassigned
// 2) split the domain into individual labels, without
// separators.
QStringList input = splitLabels(unicodeDomain);
// Do we allow IDN names for this TLD?
if (input.count() && !idnDomains->contains(input[input.count()-1].lower()))
return input.join(".").lower().latin1(); // No IDN allowed for this TLD
// 3) decide whether to enforce the STD3 rules for chars < 0x7F
// we don't enforce
// 4) for each label, apply ToASCII
QStringList::Iterator it = input.begin();
const QStringList::Iterator end = input.end();
for ( ; it != end; ++it)
{
QCString cs = ToASCII(*it);
if (cs.isNull())
return QCString(); // error!
// no, all is Ok.
if (!retval.isEmpty())
retval += '.';
retval += cs;
}
return retval;
}
QString KResolver::domainToUnicode(const QCString& asciiDomain)
{
return domainToUnicode(QString::fromLatin1(asciiDomain));
}
// implement the ToUnicode function, as described by IDN documents
QString KResolver::domainToUnicode(const QString& asciiDomain)
{
if (asciiDomain.isEmpty())
return asciiDomain;
if (!idnDomains)
idnDomains = KResolver_initIdnDomains();
QString retval;
// draft-idn-idna-14.txt, section 4 describes the operation:
// 1) this is a query, so don't allow unassigned
// besides, input is ASCII
// 2) split the domain into individual labels, without
// separators.
QStringList input = splitLabels(asciiDomain);
// Do we allow IDN names for this TLD?
if (input.count() && !idnDomains->contains(input[input.count()-1].lower()))
return asciiDomain.lower(); // No TLDs allowed
// 3) decide whether to enforce the STD3 rules for chars < 0x7F
// we don't enforce
// 4) for each label, apply ToUnicode
QStringList::Iterator it;
const QStringList::Iterator end = input.end();
for (it = input.begin(); it != end; ++it)
{
QString label = ToUnicode(*it).lower();
// ToUnicode can't fail
if (!retval.isEmpty())
retval += '.';
retval += label;
}
return retval;
}
QString KResolver::normalizeDomain(const QString& domain)
{
return domainToUnicode(domainToAscii(domain));
}
void KResolver::virtual_hook( int, void* )
{ /*BASE::virtual_hook( id, data );*/ }
// here follows IDN functions
// all IDN functions conform to the following documents:
// RFC 3454 - Preparation of Internationalized Strings
// RFC 3490 - Internationalizing Domain Names in Applications (IDNA)
// RFC 3491 - Nameprep: A Stringprep Profile for
// Internationalized Domain Names (IDN
// RFC 3492 - Punycode: A Bootstring encoding of Unicode
// for Internationalized Domain Names in Applications (IDNA)
static QStringList splitLabels(const QString& unicodeDomain)
{
// From RFC 3490 section 3.1:
// "Whenever dots are used as label separators, the following characters
// MUST be recognized as dots: U+002E (full stop), U+3002 (ideographic full
// stop), U+FF0E (fullwidth full stop), U+FF61 (halfwidth ideographic full
// stop)."
static const unsigned int separators[] = { 0x002E, 0x3002, 0xFF0E, 0xFF61 };
QStringList lst;
int start = 0;
uint i;
for (i = 0; i < unicodeDomain.length(); i++)
{
unsigned int c = unicodeDomain[i].unicode();
if (c == separators[0] ||
c == separators[1] ||
c == separators[2] ||
c == separators[3])
{
// found a separator!
lst << unicodeDomain.mid(start, i - start);
start = i + 1;
}
}
if ((long)i >= start)
// there is still one left
lst << unicodeDomain.mid(start, i - start);
return lst;
}
static QCString ToASCII(const QString& label)
{
#ifdef HAVE_IDNA_H
// We have idna.h, so we can use the idna_to_ascii
// function :)
if (label.length() > 64)
return (char*)0L; // invalid label
if (label.length() == 0)
// this is allowed
return QCString(""); // empty, not null
QCString retval;
char buf[65];
Q_UINT32* ucs4 = new Q_UINT32[label.length() + 1];
uint i;
for (i = 0; i < label.length(); i++)
ucs4[i] = (unsigned long)label[i].unicode();
ucs4[i] = 0; // terminate with NUL, just to be on the safe side
if (idna_to_ascii_4i(ucs4, label.length(), buf, 0) == IDNA_SUCCESS)
// success!
retval = buf;
delete [] ucs4;
return retval;
#else
return label.latin1();
#endif
}
static QString ToUnicode(const QString& label)
{
#ifdef HAVE_IDNA_H
// We have idna.h, so we can use the idna_to_unicode
// function :)
Q_UINT32 *ucs4_input, *ucs4_output;
size_t outlen;
ucs4_input = new Q_UINT32[label.length() + 1];
for (uint i = 0; i < label.length(); i++)
ucs4_input[i] = (unsigned long)label[i].unicode();
// try the same length for output
ucs4_output = new Q_UINT32[outlen = label.length()];
idna_to_unicode_44i(ucs4_input, label.length(),
ucs4_output, &outlen,
0);
if (outlen > label.length())
{
// it must have failed
delete [] ucs4_output;
ucs4_output = new Q_UINT32[outlen];
idna_to_unicode_44i(ucs4_input, label.length(),
ucs4_output, &outlen,
0);
}
// now set the answer
QString result;
result.setLength(outlen);
for (uint i = 0; i < outlen; i++)
result[i] = (unsigned int)ucs4_output[i];
delete [] ucs4_input;
delete [] ucs4_output;
return result;
#else
return label;
#endif
}
#include "kresolver.moc"
KNetwork::KResolverEntry::canonicalName
QString canonicalName() const
Retrieves the canonical name associated with this entry, if there is any.
Definition: kresolver.cpp:156
KNetwork::KResolverResults::operator=
KResolverResults & operator=(const KResolverResults &other)
Assignment operator.
Definition: kresolver.cpp:228
KNetwork::KResolver::serviceName
QString serviceName() const
The service name to which the resolution was/is to be performed.
Definition: kresolver.cpp:342
KNetwork::KResolverEntry::operator=
KResolverEntry & operator=(const KResolverEntry &other)
Assignment operator.
Definition: kresolver.cpp:180
KNetwork::KResolver::normalizeDomain
static QString normalizeDomain(const QString &domain)
Normalise a domain name.
Definition: kresolver.cpp:1034
KNetwork::KResolver::flags
int flags() const
Retrieves the flags set for the resolution.
Definition: kresolver.cpp:379
KNetwork::KResolverEntry::encodedName
QCString encodedName() const
Retrieves the encoded domain name associated with this entry, if there is any.
Definition: kresolver.cpp:162
KNetwork::KResolverResults::~KResolverResults
virtual ~KResolverResults()
Destructor.
Definition: kresolver.cpp:221
KNetwork::KResolverEntry
One resolution entry.
Definition: kresolver.h:66
KNetwork::KResolver::error
int error() const
Retrieve the error code in this object.
Definition: kresolver.cpp:318
KNetwork::KResolver::setFamily
void setFamily(int families)
Sets the allowed socket families.
Definition: kresolver.cpp:397
KNetwork::KResolver
Name and service resolution class.
Definition: kresolver.h:295
KNetwork::KResolver::setProtocol
void setProtocol(int protonum, const char *name=0L)
Sets the protocol we want.
Definition: kresolver.cpp:417
KNetwork::KSocketAddress
A generic socket address.
Definition: ksocketaddress.h:423
KNetwork::KResolver::resolve
static KResolverResults resolve(const QString &host, const QString &service, int flags=0, int families=KResolver::InternetFamily)
Resolve the nodename and service name synchronously.
Definition: kresolver.cpp:587
klocale.h
KNetwork::KResolverResults
Name and service resolution results.
Definition: kresolver.h:197
KNetwork::KResolver::status
int status() const
Retrieve the current status of this object.
Definition: kresolver.cpp:312
KNetwork::KResolver::localHostName
static QString localHostName()
Returns this machine's local hostname.
Definition: kresolver.cpp:884
KNetwork::KResolverEntry::protocol
int protocol() const
Retrieves the protocol associated with this entry.
Definition: kresolver.cpp:174
KNetwork::KResolver::domainToUnicode
static QString domainToUnicode(const QCString &asciiDomain)
Does the inverse of domainToAscii and return an Unicode domain name from the given ACE-encoded domain...
Definition: kresolver.cpp:988
KNetwork::KResolver::setServiceName
void setServiceName(const QString &service)
Sets the service name to be resolved.
Definition: kresolver.cpp:360
KNetwork::KResolver::results
KResolverResults results() const
Retrieves the results of this resolution.
Definition: kresolver.cpp:516
KNetwork::KResolver::wait
bool wait(int msec=0)
Waits for a request to finish resolving.
Definition: kresolver.cpp:457
KNetwork::KResolver::systemError
int systemError() const
Retrieve the associated system error code in this object.
Definition: kresolver.cpp:324
KNetwork::KResolverResults::systemError
int systemError() const
Retrieves the system error code, if any.
Definition: kresolver.cpp:249
KNetwork::KResolver::KResolver
KResolver(QObject *=0L, const char *=0L)
Default constructor.
Definition: kresolver.cpp:292
KNetwork::KResolver::errorString
QString errorString() const
Returns the textual representation of the error in this object.
Definition: kresolver.h:493
KNetwork::KResolver::event
virtual bool event(QEvent *)
Handles events.
Definition: kresolver.cpp:528
KNetwork::KResolverEntry::~KResolverEntry
~KResolverEntry()
Destructor.
Definition: kresolver.cpp:128
KNetwork::KResolverEntry::address
KSocketAddress address() const
Retrieves the socket address associated with this entry.
Definition: kresolver.cpp:138
KNetwork::KResolver::protocolName
static QStrList protocolName(int protonum)
Resolves a protocol number to its names.
Definition: kresolver.cpp:610
KNetwork::KResolver::resolveAsync
static bool resolveAsync(QObject *userObj, const char *userSlot, const QString &host, const QString &service, int flags=0, int families=KResolver::InternetFamily)
Start an asynchronous name resolution.
Definition: kresolver.cpp:598
KNetwork::KResolver::setNodeName
void setNodeName(const QString &nodename)
Sets the nodename for the resolution.
Definition: kresolver.cpp:348
KNetwork::KResolverEntry::length
Q_UINT16 length() const
Retrieves the length of the socket address structure.
Definition: kresolver.cpp:144
KNetwork::KResolverEntry::socketType
int socketType() const
Retrieves the socket type associated with this entry.
Definition: kresolver.cpp:168
KNetwork::KResolver::finished
void finished(KResolverResults results)
This signal is emitted whenever the resolution is finished, one way or another (success or failure)...
KNetwork::KResolverResults::setAddress
void setAddress(const QString &host, const QString &service)
Sets the new nodename and service name.
Definition: kresolver.cpp:274
KNetwork::KResolverEntry::family
int family() const
Retrieves the family associated with this socket address.
Definition: kresolver.cpp:150
KNetwork::KResolver::servicePort
static int servicePort(const char *servname, const char *protoname)
Resolves a service name to its port number.
Definition: kresolver.cpp:747
KNetwork::KResolverEntry::KResolverEntry
KResolverEntry()
Default constructor.
Definition: kresolver.cpp:90
KNetwork::KResolverResults::serviceName
QString serviceName() const
The service name to which the resolution was performed.
Definition: kresolver.cpp:268
KNetwork::KResolverResults::KResolverResults
KResolverResults()
Default constructor.
Definition: kresolver.cpp:208
KNetwork::KResolver::setSocketType
void setSocketType(int type)
Sets the socket type we want.
Definition: kresolver.cpp:407
KNetwork::KResolver::~KResolver
virtual ~KResolver()
Destructor.
Definition: kresolver.cpp:305
KNetwork::KResolver::nodeName
QString nodeName() const
The nodename to which the resolution was/is to be performed.
Definition: kresolver.cpp:336
KNetwork::KResolver::domainToAscii
static QCString domainToAscii(const QString &unicodeDomain)
Returns the domain name in an ASCII Compatible Encoding form, suitable for DNS lookups.
Definition: kresolver.cpp:950
KNetwork::KResolverResults::setError
void setError(int errorcode, int systemerror=0)
Sets the error codes.
Definition: kresolver.cpp:255
KNetwork::KResolver::cancel
void cancel(bool emitSignal=true)
Cancels a running request.
Definition: kresolver.cpp:508
KNetwork::KResolver::isRunning
bool isRunning() const
Returns true if this object is currently running.
Definition: kresolver.cpp:330
KNetwork::KResolver::setFlags
int setFlags(int flags)
Sets the flags.
Definition: kresolver.cpp:385
KNetwork::KResolverResults::nodeName
QString nodeName() const
The nodename to which the resolution was performed.
Definition: kresolver.cpp:262
KNetwork::KResolver::protocolNumber
static int protocolNumber(const char *protoname)
Resolves a protocol name to its number.
Definition: kresolver.cpp:704
KNetwork::KResolverResults::error
int error() const
Retrieves the error code associated with this resolution.
Definition: kresolver.cpp:243
KNetwork::KResolver::setAddress
void setAddress(const QString &node, const QString &service)
Sets both the host and the service names.
Definition: kresolver.cpp:372
KNetwork::KResolver::start
bool start()
Starts the name resolution asynchronously.
Definition: kresolver.cpp:438

KDE Home | KDE Accessibility Home | Description of Access Keys