summaryrefslogtreecommitdiffstats
path: root/kdecore/network/kresolver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kdecore/network/kresolver.cpp')
-rw-r--r--kdecore/network/kresolver.cpp1164
1 files changed, 0 insertions, 1164 deletions
diff --git a/kdecore/network/kresolver.cpp b/kdecore/network/kresolver.cpp
deleted file mode 100644
index 93c029b8e..000000000
--- a/kdecore/network/kresolver.cpp
+++ /dev/null
@@ -1,1164 +0,0 @@
-/* -*- 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 <tqapplication.h>
-#include <tqstring.h>
-#include <tqcstring.h>
-#include <tqstrlist.h>
-#include <tqstringlist.h>
-#include <tqshared.h>
-#include <tqdatetime.h>
-#include <tqtimer.h>
-#include <tqmutex.h>
-#include <tqguardedptr.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"
-TQMutex getXXbyYYmutex;
-#endif
-
-using namespace KNetwork;
-using namespace KNetwork::Internal;
-
-/////////////////////////////////////////////
-// class KResolverEntry
-
-class KNetwork::KResolverEntryPrivate: public TQShared
-{
-public:
- KSocketAddress addr;
- int socktype;
- int protocol;
- TQString canonName;
- TQCString 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 TQString& canonName, const TQCString& 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, TQ_UINT16 salen, int socktype,
- int protocol, const TQString& canonName,
- const TQCString& 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
-TQ_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
-TQString KResolverEntry::canonicalName() const
-{
- return d ? d->canonName : TQString::null;
-}
-
-// returns the encoded name
-TQCString KResolverEntry::encodedName() const
-{
- return d ? d->encodedName : TQCString();
-}
-
-// 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:
- TQString node, service;
- int errorcode, syserror;
-
- KResolverResultsPrivate() :
- errorcode(0), syserror(0)
- { }
-};
-
-// default constructor
-KResolverResults::KResolverResults()
- : d(new KResolverResultsPrivate)
-{
-}
-
-// copy constructor
-KResolverResults::KResolverResults(const KResolverResults& other)
- : TQValueList<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 TQValueList do the rest of the work
- TQValueList<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
-TQString KResolverResults::nodeName() const
-{
- return d->node;
-}
-
-// gets the service name
-TQString KResolverResults::serviceName() const
-{
- return d->service;
-}
-
-// sets the address
-void KResolverResults::setAddress(const TQString& node,
- const TQString& service)
-{
- d->node = node;
- d->service = service;
-}
-
-void KResolverResults::virtual_hook( int, void* )
-{ /*BASE::virtual_hook( id, data );*/ }
-
-
-///////////////////////
-// class KResolver
-
-TQStringList *KResolver::idnDomains = 0;
-
-
-// default constructor
-KResolver::KResolver(TQObject *parent, const char *name)
- : TQObject(parent, name), d(new KResolverPrivate(this))
-{
-}
-
-// constructor with host and service
-KResolver::KResolver(const TQString& nodename, const TQString& servicename,
- TQObject *parent, const char *name)
- : TQObject(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
-TQString KResolver::nodeName() const
-{
- return d->input.node;
-}
-
-// get the service
-TQString KResolver::serviceName() const
-{
- return d->input.service;
-}
-
-// sets the hostname
-void KResolver::setNodeName(const TQString& 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 TQString& 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 TQString& nodename, const TQString& 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;
- }
-
- TQMutexLocker 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
- {
- TQTime 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(TQEvent* e)
-{
- if (static_cast<int>(e->type()) == KResolverManager::ResolutionCompleted)
- {
- emitFinished();
- return true;
- }
-
- return false;
-}
-
-void KResolver::emitFinished()
-{
- if (isRunning())
- d->status = KResolver::Success;
-
- TQGuardedPtr<TQObject> p = this; // guard against deletion
-
- emit finished(d->results);
-
- if (p && d->deleteWhenDone)
- deleteLater(); // in QObject
-}
-
-TQString 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 TQString::null;
-
- TQString msg = i18n(messages[-errorcode]);
- if (errorcode == SystemError)
- msg.arg(TQString::fromLocal8Bit(strerror(syserror)));
-
- return msg;
-}
-
-KResolverResults
-KResolver::resolve(const TQString& host, const TQString& service, int flags,
- int families)
-{
- KResolver qres(host, service, TQT_TQOBJECT(tqApp), "synchronous KResolver");
- qres.setFlags(flags);
- qres.setFamily(families);
- qres.start();
- qres.wait();
- return qres.results();
-}
-
-bool KResolver::resolveAsync(TQObject* userObj, const char *userSlot,
- const TQString& host, const TQString& service,
- int flags, int families)
-{
- KResolver* qres = new KResolver(host, service, TQT_TQOBJECT(tqApp), "asynchronous KResolver");
- TQObject::connect(qres, TQT_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();
-}
-
-TQStrList KResolver::protocolName(int protonum)
-{
- struct protoent *pe = 0L;
-#ifndef HAVE_GETPROTOBYNAME_R
- TQMutexLocker 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
- TQStrList 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;
-}
-
-TQStrList KResolver::protocolName(const char *protoname)
-{
- struct protoent *pe = 0L;
-#ifndef HAVE_GETPROTOBYNAME_R
- TQMutexLocker 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
- TQStrList 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
- TQMutexLocker 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
- TQMutexLocker 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;
-}
-
-TQStrList KResolver::serviceName(const char* servname, const char *protoname)
-{
- struct servent *se = 0L;
-#ifndef HAVE_GETSERVBYNAME_R
- TQMutexLocker 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
- TQStrList 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;
-}
-
-TQStrList KResolver::serviceName(int port, const char *protoname)
-{
- struct servent *se = 0L;
-#ifndef HAVE_GETSERVBYPORT_R
- TQMutexLocker 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
- TQStrList 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;
-}
-
-TQString KResolver::localHostName()
-{
- TQCString 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 = TQCString();
- }
- }
-
- if (name.isEmpty())
- return TQString::tqfromLatin1("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 TQString::tqfromLatin1("localhost");
- else
- return results.first().canonicalName();
- }
-
- return domainToUnicode(name);
-}
-
-
-// forward declaration
-static TQStringList splitLabels(const TQString& tqunicodeDomain);
-static TQCString ToASCII(const TQString& label);
-static TQString ToUnicode(const TQString& label);
-
-static TQStringList *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 TQStringList(TQStringList::split(':', TQString::tqfromLatin1(kde_use_idn).lower()));
-}
-
-// implement the ToAscii function, as described by IDN documents
-TQCString KResolver::domainToAscii(const TQString& tqunicodeDomain)
-{
- if (!idnDomains)
- idnDomains = KResolver_initIdnDomains();
-
- TQCString 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.
- TQStringList input = splitLabels(tqunicodeDomain);
-
- // 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
- TQStringList::Iterator it = input.begin();
- const TQStringList::Iterator end = input.end();
- for ( ; it != end; ++it)
- {
- TQCString cs = ToASCII(*it);
- if (cs.isNull())
- return TQCString(); // error!
-
- // no, all is Ok.
- if (!retval.isEmpty())
- retval += '.';
- retval += cs;
- }
-
- return retval;
-}
-
-TQString KResolver::domainToUnicode(const TQCString& asciiDomain)
-{
- return domainToUnicode(TQString::tqfromLatin1(asciiDomain));
-}
-
-// implement the ToUnicode function, as described by IDN documents
-TQString KResolver::domainToUnicode(const TQString& asciiDomain)
-{
- if (asciiDomain.isEmpty())
- return asciiDomain;
- if (!idnDomains)
- idnDomains = KResolver_initIdnDomains();
-
- TQString 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.
- TQStringList 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
- TQStringList::Iterator it;
- const TQStringList::Iterator end = input.end();
- for (it = input.begin(); it != end; ++it)
- {
- TQString label = ToUnicode(*it).lower();
-
- // ToUnicode can't fail
- if (!retval.isEmpty())
- retval += '.';
- retval += label;
- }
-
- return retval;
-}
-
-TQString KResolver::normalizeDomain(const TQString& 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 TQStringList splitLabels(const TQString& tqunicodeDomain)
-{
- // 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 };
-
- TQStringList lst;
- int start = 0;
- uint i;
- for (i = 0; i < tqunicodeDomain.length(); i++)
- {
- unsigned int c = tqunicodeDomain[i].tqunicode();
-
- if (c == separators[0] ||
- c == separators[1] ||
- c == separators[2] ||
- c == separators[3])
- {
- // found a separator!
- lst << tqunicodeDomain.mid(start, i - start);
- start = i + 1;
- }
- }
- if ((long)i >= start)
- // there is still one left
- lst << tqunicodeDomain.mid(start, i - start);
-
- return lst;
-}
-
-static TQCString ToASCII(const TQString& 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 TQCString(""); // empty, not null
-
- TQCString retval;
- char buf[65];
-
- TQ_UINT32* ucs4 = new TQ_UINT32[label.length() + 1];
-
- uint i;
- for (i = 0; i < label.length(); i++)
- ucs4[i] = (unsigned long)label[i].tqunicode();
- 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 TQString ToUnicode(const TQString& label)
-{
-#ifdef HAVE_IDNA_H
- // We have idna.h, so we can use the idna_to_tqunicode
- // function :)
-
- TQ_UINT32 *ucs4_input, *ucs4_output;
- size_t outlen;
-
- ucs4_input = new TQ_UINT32[label.length() + 1];
- for (uint i = 0; i < label.length(); i++)
- ucs4_input[i] = (unsigned long)label[i].tqunicode();
-
- // try the same length for output
- ucs4_output = new TQ_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 TQ_UINT32[outlen];
-
- idna_to_unicode_44i(ucs4_input, label.length(),
- ucs4_output, &outlen,
- 0);
- }
-
- // now set the answer
- TQString 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"