diff options
author | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2011-11-06 15:56:40 -0600 |
---|---|---|
committer | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2011-11-06 15:56:40 -0600 |
commit | e16866e072f94410321d70daedbcb855ea878cac (patch) | |
tree | ee3f52eabde7da1a0e6ca845fb9c2813cf1558cf /kdecore/network/kresolver.cpp | |
parent | a58c20c1a7593631a1b50213c805507ebc16adaf (diff) | |
download | tdelibs-e16866e072f94410321d70daedbcb855ea878cac.tar.gz tdelibs-e16866e072f94410321d70daedbcb855ea878cac.zip |
Actually move the kde files that were renamed in the last commit
Diffstat (limited to 'kdecore/network/kresolver.cpp')
-rw-r--r-- | kdecore/network/kresolver.cpp | 1164 |
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" |