• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDECore

k3resolver.cpp

Go to the documentation of this file.
00001 /*  -*- C++ -*-
00002  *  Copyright (C) 2003-2005 Thiago Macieira <thiago@kde.org>
00003  *
00004  *
00005  *  Permission is hereby granted, free of charge, to any person obtaining
00006  *  a copy of this software and associated documentation files (the
00007  *  "Software"), to deal in the Software without restriction, including
00008  *  without limitation the rights to use, copy, modify, merge, publish,
00009  *  distribute, sublicense, and/or sell copies of the Software, and to
00010  *  permit persons to whom the Software is furnished to do so, subject to
00011  *  the following conditions:
00012  *
00013  *  The above copyright notice and this permission notice shall be included
00014  *  in all copies or substantial portions of the Software.
00015  *
00016  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00017  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00018  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00019  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00020  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00021  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00022  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023  */
00024 
00025 #include "k3resolver.h"
00026 #include "k3resolver_p.h"
00027 
00028 #include <config.h>
00029 #include <config-network.h>
00030 
00031 // System includes
00032 #include <sys/types.h>
00033 #include <sys/socket.h>
00034 #include <sys/param.h>
00035 #include <errno.h>
00036 #include <netdb.h>
00037 #include <time.h>
00038 #include <arpa/inet.h>
00039 #include <netinet/in.h>
00040 #include <stdlib.h>
00041 #include <unistd.h>
00042 
00043 // Qt includes
00044 #include <QCoreApplication>
00045 #include <QPointer>
00046 #include <QSet>
00047 
00048 #include <QStringList>
00049 #include <QSharedData>
00050 #include <QTime>
00051 #include <QTimer>
00052 
00053 // KDE
00054 #include <klocale.h>
00055 #include <kurl.h>
00056 
00057 // Us
00058 #include "k3socketaddress.h"
00059 
00060 #ifdef NEED_MUTEX
00061 #ifdef __GNUC__
00062 #warning "mutex"
00063 #endif
00064 QMutex getXXbyYYmutex;
00065 #endif
00066 
00067 #ifdef __OpenBSD__
00068 #define USE_OPENBSD 1
00069 #endif
00070 
00071 using namespace KNetwork;
00072 using namespace KNetwork::Internal;
00073 
00075 // class KResolverEntry
00076 
00077 class KNetwork::KResolverEntryPrivate: public QSharedData
00078 {
00079 public:
00080   KSocketAddress addr;
00081   int socktype;
00082   int protocol;
00083   QString canonName;
00084   QByteArray encodedName;
00085 
00086   inline KResolverEntryPrivate() :
00087     socktype(0), protocol(0)
00088   { }
00089 };
00090 
00091 // default constructor
00092 KResolverEntry::KResolverEntry() :
00093   d(0L)
00094 {
00095 }
00096 
00097 // constructor with stuff
00098 KResolverEntry::KResolverEntry(const KSocketAddress& addr, int socktype, int protocol,
00099                    const QString& canonName, const QByteArray& encodedName) :
00100   d(new KResolverEntryPrivate)
00101 {
00102   d->addr = addr;
00103   d->socktype = socktype;
00104   d->protocol = protocol;
00105   d->canonName = canonName;
00106   d->encodedName = encodedName;
00107 }
00108 
00109 // constructor with even more stuff
00110 KResolverEntry::KResolverEntry(const struct sockaddr* sa, quint16 salen, int socktype,
00111                    int protocol, const QString& canonName,
00112                    const QByteArray& encodedName) :
00113   d(new KResolverEntryPrivate)
00114 {
00115   d->addr = KSocketAddress(sa, salen);
00116   d->socktype = socktype;
00117   d->protocol = protocol;
00118   d->canonName = canonName;
00119   d->encodedName = encodedName;
00120 }
00121 
00122 // copy constructor
00123 KResolverEntry::KResolverEntry(const KResolverEntry& that) :
00124   d(0L)
00125 {
00126   *this = that;
00127 }
00128 
00129 // destructor
00130 KResolverEntry::~KResolverEntry()
00131 {
00132 }
00133 
00134 // returns the socket address
00135 KSocketAddress KResolverEntry::address() const
00136 {
00137   return d->addr;
00138 }
00139 
00140 // returns the length
00141 quint16 KResolverEntry::length() const
00142 {
00143   return d->addr.length();
00144 }
00145 
00146 // returns the family
00147 int KResolverEntry::family() const
00148 {
00149   return d->addr.family();
00150 }
00151 
00152 // returns the canonical name
00153 QString KResolverEntry::canonicalName() const
00154 {
00155   return d->canonName;
00156 }
00157 
00158 // returns the encoded name
00159 QByteArray KResolverEntry::encodedName() const
00160 {
00161   return d->encodedName;
00162 }
00163 
00164 // returns the socket type
00165 int KResolverEntry::socketType() const
00166 {
00167   return d->socktype;
00168 }
00169 
00170 // returns the protocol
00171 int KResolverEntry::protocol() const
00172 {
00173   return d->protocol;
00174 }
00175 
00176 // assignment operator
00177 KResolverEntry& KResolverEntry::operator= (const KResolverEntry& that)
00178 {
00179   d = that.d;
00180   return *this;
00181 }
00182 
00184 // class KResolverResults
00185 
00186 class KNetwork::KResolverResultsPrivate: public QSharedData
00187 {
00188 public:
00189   QString node, service;
00190   int errorcode, syserror;
00191 
00192   KResolverResultsPrivate() :
00193     errorcode(0), syserror(0)
00194   { }
00195 };
00196 
00197 // default constructor
00198 KResolverResults::KResolverResults()
00199   : d(new KResolverResultsPrivate)
00200 {
00201 }
00202 
00203 // copy constructor
00204 KResolverResults::KResolverResults(const KResolverResults& other)
00205   : QList<KResolverEntry>(other), d(new KResolverResultsPrivate)
00206 {
00207   d = other.d;
00208 }
00209 
00210 // destructor
00211 KResolverResults::~KResolverResults()
00212 {
00213 }
00214 
00215 // assignment operator
00216 KResolverResults&
00217 KResolverResults::operator= (const KResolverResults& other)
00218 {
00219   // copy over the other data
00220   d = other.d;
00221 
00222   // now let QList do the rest of the work
00223   QList<KResolverEntry>::operator =(other);
00224 
00225   return *this;
00226 }
00227 
00228 // gets the error code
00229 int KResolverResults::error() const
00230 {
00231   return d->errorcode;
00232 }
00233 
00234 // gets the system errno
00235 int KResolverResults::systemError() const
00236 {
00237   return d->syserror;
00238 }
00239 
00240 // sets the error codes
00241 void KResolverResults::setError(int errorcode, int systemerror)
00242 {
00243   d->errorcode = errorcode;
00244   d->syserror = systemerror;
00245 }
00246 
00247 // gets the hostname
00248 QString KResolverResults::nodeName() const
00249 {
00250   return d->node;
00251 }
00252 
00253 // gets the service name
00254 QString KResolverResults::serviceName() const
00255 {
00256   return d->service;
00257 }
00258 
00259 // sets the address
00260 void KResolverResults::setAddress(const QString& node,
00261                   const QString& service)
00262 {
00263   d->node = node;
00264   d->service = service;
00265 }
00266 
00267 void KResolverResults::virtual_hook( int, void* )
00268 { /*BASE::virtual_hook( id, data );*/ }
00269 
00270 
00272 // class KResolver
00273 
00274 // default constructor
00275 KResolver::KResolver(QObject *parent)
00276   : QObject(parent), d(new KResolverPrivate(this))
00277 {
00278 }
00279 
00280 // constructor with host and service
00281 KResolver::KResolver(const QString& nodename, const QString& servicename,
00282            QObject *parent)
00283   : QObject(parent), d(new KResolverPrivate(this, nodename, servicename))
00284 {
00285 }
00286 
00287 // destructor
00288 KResolver::~KResolver()
00289 {
00290   cancel(false);
00291   delete d;
00292 }
00293 
00294 // get the status
00295 int KResolver::status() const
00296 {
00297   return d->status;
00298 }
00299 
00300 // get the error code
00301 int KResolver::error() const
00302 {
00303   return d->errorcode;
00304 }
00305 
00306 // get the errno
00307 int KResolver::systemError() const
00308 {
00309   return d->syserror;
00310 }
00311 
00312 QString KResolver::errorString() const
00313 {
00314     return errorString(error(), systemError());
00315 }
00316 
00317 // are we running?
00318 bool KResolver::isRunning() const
00319 {
00320   return d->status > 0 && d->status < Success;
00321 }
00322 
00323 // get the hostname
00324 QString KResolver::nodeName() const
00325 {
00326   return d->input.node;
00327 }
00328 
00329 // get the service
00330 QString KResolver::serviceName() const
00331 {
00332   return d->input.service;
00333 }
00334 
00335 // sets the hostname
00336 void KResolver::setNodeName(const QString& nodename)
00337 {
00338   // don't touch those values if we're working!
00339   if (!isRunning())
00340     {
00341       d->input.node = nodename;
00342       d->status = Idle;
00343       d->results.setAddress(nodename, d->input.service);
00344     }
00345 }
00346 
00347 // sets the service
00348 void KResolver::setServiceName(const QString& service)
00349 {
00350   // don't change if running
00351   if (!isRunning())
00352     {
00353       d->input.service = service;
00354       d->status = Idle;
00355       d->results.setAddress(d->input.node, service);
00356     }
00357 }
00358 
00359 // sets the address
00360 void KResolver::setAddress(const QString& nodename, const QString& service)
00361 {
00362   setNodeName(nodename);
00363   setServiceName(service);
00364 }
00365 
00366 // get the flags
00367 int KResolver::flags() const
00368 {
00369   return d->input.flags;
00370 }
00371 
00372 // sets the flags
00373 int KResolver::setFlags(int flags)
00374 {
00375   int oldflags = d->input.flags;
00376   if (!isRunning())
00377     {
00378       d->input.flags = flags;
00379       d->status = Idle;
00380     }
00381   return oldflags;
00382 }
00383 
00384 // sets the family mask
00385 void KResolver::setFamily(int families)
00386 {
00387   if (!isRunning())
00388     {
00389       d->input.familyMask = families;
00390       d->status = Idle;
00391     }
00392 }
00393 
00394 // sets the socket type
00395 void KResolver::setSocketType(int type)
00396 {
00397   if (!isRunning())
00398     {
00399       d->input.socktype = type;
00400       d->status = Idle;
00401     }
00402 }
00403 
00404 // sets the protocol
00405 void KResolver::setProtocol(int protonum, const char *name)
00406 {
00407   if (isRunning())
00408     return;         // can't change now
00409 
00410   // we copy the given protocol name. If it isn't an empty string
00411   // and the protocol number was 0, we will look it up in /etc/protocols
00412   // we also leave the error reporting to the actual lookup routines, in
00413   // case the given protocol name doesn't exist
00414 
00415   d->input.protocolName = name;
00416   if (protonum == 0 && name != 0L && *name != '\0')
00417     {
00418       // must look up the protocol number
00419       d->input.protocol = KResolver::protocolNumber(name);
00420     }
00421   else
00422     d->input.protocol = protonum;
00423   d->status = Idle;
00424 }
00425 
00426 bool KResolver::start()
00427 {
00428   if (!isRunning())
00429     {
00430       d->results.empty();
00431 
00432       // is there anything to be queued?
00433       if (d->input.node.isEmpty() && d->input.service.isEmpty())
00434     {
00435       d->status = KResolver::Success;
00436       emitFinished();
00437     }
00438       else
00439     KResolverManager::manager()->enqueue(this, 0L);
00440     }
00441 
00442   return true;
00443 }
00444 
00445 bool KResolver::wait(int msec)
00446 {
00447   if (!isRunning())
00448     {
00449       emitFinished();
00450       return true;
00451     }
00452 
00453   QMutexLocker locker(&d->mutex);
00454 
00455   if (!isRunning())
00456     {
00457       // it was running and no longer is?
00458       // That means the manager has finished its processing and has posted
00459       // an event for the signal to be emitted already. This means the signal
00460       // will be emitted twice!
00461 
00462       emitFinished();
00463       return true;
00464     }
00465   else
00466     {
00467       QTime t;
00468       t.start();
00469 
00470       while (!msec || t.elapsed() < msec)
00471     {
00472       // wait on the manager to broadcast completion
00473       d->waiting = true;
00474       if (msec)
00475         KResolverManager::manager()->notifyWaiters.wait(&d->mutex, msec - t.elapsed());
00476       else
00477         KResolverManager::manager()->notifyWaiters.wait(&d->mutex);
00478 
00479       // the manager has processed
00480       // see if this object is done
00481       if (!isRunning())
00482         {
00483           // it's done
00484           d->waiting = false;
00485           emitFinished();
00486           return true;
00487         }
00488     }
00489 
00490       // if we've got here, we've timed out
00491       d->waiting = false;
00492       return false;
00493     }
00494 }
00495 
00496 void KResolver::cancel(bool emitSignal)
00497 {
00498   KResolverManager::manager()->dequeue(this);
00499   if (emitSignal)
00500     emitFinished();
00501 }
00502 
00503 KResolverResults
00504 KResolver::results() const
00505 {
00506   if (!isRunning())
00507     return d->results;
00508 
00509   // return a dummy, empty result
00510   KResolverResults r;
00511   r.setAddress(d->input.node, d->input.service);
00512   r.setError(d->errorcode, d->syserror);
00513   return r;
00514 }
00515 
00516 bool KResolver::event(QEvent* e)
00517 {
00518   if (static_cast<int>(e->type()) == KResolverManager::ResolutionCompleted)
00519     {
00520       emitFinished();
00521       return true;
00522     }
00523 
00524   return false;
00525 }
00526 
00527 void KResolver::emitFinished()
00528 {
00529   if (isRunning())
00530     d->status = KResolver::Success;
00531 
00532   QPointer<QObject> p = this; // guard against deletion
00533 
00534   emit finished(d->results);
00535 
00536   if (p && d->deleteWhenDone)
00537     deleteLater();      // in QObject
00538 }
00539 
00540 QString KResolver::errorString(int errorcode, int syserror)
00541 {
00542   // no i18n now...
00543   static const char messages[] =
00544   {
00545     I18N_NOOP("no error")"\0"   // NoError
00546     I18N_NOOP("requested family not supported for this host name")"\0" // AddrFamily
00547     I18N_NOOP("temporary failure in name resolution")"\0"   // TryAgain
00548     I18N_NOOP("non-recoverable failure in name resolution")"\0" // NonRecoverable
00549     I18N_NOOP("invalid flags")"\0"      // BadFlags
00550     I18N_NOOP("memory allocation failure")"\0"  // Memory
00551     I18N_NOOP("name or service not known")"\0"  // NoName
00552     I18N_NOOP("requested family not supported")"\0" // UnsupportedFamily
00553     I18N_NOOP("requested service not supported for this socket type")"\0" // UnsupportedService
00554     I18N_NOOP("requested socket type not supported")"\0"    // UnsupportedSocketType
00555     I18N_NOOP("unknown error")"\0"          // UnknownError
00556     I18N_NOOP2("1: the i18n'ed system error code, from errno",
00557           "system error: %1")"\0"       // SystemError
00558     "\0"
00559   };
00560   // index table generated by generate_string_table.pl
00561   static const int messages_indices[] = {
00562       0,    9,   59,   96,  139,  153,  179,  205,
00563       236,  289,  325,    0
00564   };
00565 
00566   // handle the special value
00567   if (errorcode == Canceled)
00568     return i18n("request was canceled");
00569 
00570   Q_ASSERT(int(SystemError) <= -(int)(sizeof(messages_indices)/sizeof(messages_indices[0])));
00571   if (errorcode > 0 || errorcode < SystemError)
00572     return QString();
00573 
00574   QString msg = i18n(messages + messages_indices[-errorcode]);
00575   if (errorcode == SystemError)
00576     msg.arg(QString::fromLocal8Bit(strerror(syserror)));
00577 
00578   return msg;
00579 }
00580 
00581 KResolverResults
00582 KResolver::resolve(const QString& host, const QString& service, int flags,
00583           int families)
00584 {
00585   KResolver qres(host, service, QCoreApplication::instance());
00586   qres.setObjectName("synchronous KResolver");
00587   qres.setFlags(flags);
00588   qres.setFamily(families);
00589   qres.start();
00590   qres.wait();
00591   return qres.results();
00592 }
00593 
00594 bool KResolver::resolveAsync(QObject* userObj, const char *userSlot,
00595                  const QString& host, const QString& service,
00596                  int flags, int families)
00597 {
00598   KResolver* qres = new KResolver(host, service, QCoreApplication::instance());
00599   QObject::connect(qres, SIGNAL(finished(const KNetwork::KResolverResults&)),
00600            userObj, userSlot);
00601   qres->setObjectName("asynchronous KResolver");
00602   qres->setFlags(flags);
00603   qres->setFamily(families);
00604   qres->d->deleteWhenDone = true; // this is the only difference from the example code
00605   return qres->start();
00606 }
00607 
00608 QList<QByteArray> KResolver::protocolName(int protonum)
00609 {
00610   struct protoent *pe;
00611 #ifndef HAVE_GETPROTOBYNAME_R
00612   QMutexLocker locker(&getXXbyYYmutex);
00613 
00614   pe = getprotobynumber(protonum);
00615 
00616 #else
00617 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API
00618   struct protoent protobuf;
00619   struct protoent_data pdata;
00620   ::memset(&pdata, 0, sizeof pdata);
00621 
00622   if (getprotobynumber_r(protonum, &protobuf, &pdata) == 0)
00623     pe = &protobuf;
00624   else
00625     pe = 0;
00626 
00627 # else
00628   size_t buflen = 1024;
00629   struct protoent protobuf;
00630   char *buf;
00631   do
00632     {
00633       buf = new char[buflen];
00634 #  ifdef Q_OS_SOLARIS // Solaris uses a 4 argument getprotobynumber_r which returns struct *protoent or NULL
00635       if ((pe = getprotobynumber_r(protonum, &protobuf, buf, buflen)) && (errno == ERANGE))
00636 #  else
00637       if (getprotobynumber_r(protonum, &protobuf, buf, buflen, &pe) == ERANGE)
00638 #  endif
00639     {
00640       buflen += 1024;
00641       delete [] buf;
00642     }
00643       else
00644     break;
00645     }
00646   while (pe == 0L);
00647 # endif
00648 #endif
00649 
00650   // Do common processing
00651   QList<QByteArray> lst;
00652   if (pe != NULL)
00653     {
00654       lst.append(pe->p_name);
00655       for (char **p = pe->p_aliases; *p; p++)
00656     lst.append(*p);
00657     }
00658 
00659 #ifdef HAVE_GETPROTOBYNAME_R
00660 # ifndef USE_OPENBSD
00661   delete [] buf;
00662 # endif
00663 #endif
00664 
00665   return lst;
00666 }
00667 
00668 QList<QByteArray> KResolver::protocolName(const char *protoname)
00669 {
00670   struct protoent *pe = 0L;
00671 #ifndef HAVE_GETPROTOBYNAME_R
00672   QMutexLocker locker(&getXXbyYYmutex);
00673 
00674   pe = getprotobyname(protoname);
00675 
00676 #else
00677 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API
00678   struct protoent protobuf;
00679   struct protoent_data pdata;
00680   ::memset(&pdata, 0, sizeof pdata);
00681 
00682   if (getprotobyname_r(protoname, &protobuf, &pdata) == 0)
00683     pe = &protobuf;
00684   else
00685     pe = 0;
00686 # else
00687   size_t buflen = 1024;
00688   struct protoent protobuf;
00689   char *buf;
00690   do
00691     {
00692       buf = new char[buflen];
00693 #  ifdef Q_OS_SOLARIS // Solaris uses a 4 argument getprotobyname_r which returns struct *protoent or NULL
00694       if ((pe = getprotobyname_r(protoname, &protobuf, buf, buflen)) && (errno == ERANGE))
00695 #  else
00696       if (getprotobyname_r(protoname, &protobuf, buf, buflen, &pe) == ERANGE)
00697 #  endif
00698     {
00699           pe = 0L;
00700       buflen += 1024;
00701       delete [] buf;
00702     }
00703       else
00704     break;
00705     }
00706   while (pe == 0L);
00707 # endif
00708 #endif
00709 
00710   // Do common processing
00711   QList<QByteArray> lst;
00712   if (pe != NULL)
00713     {
00714       lst.append(pe->p_name);
00715       for (char **p = pe->p_aliases; *p; p++)
00716     lst.append(*p);
00717     }
00718 
00719 #ifdef HAVE_GETPROTOBYNAME_R
00720 # ifndef USE_OPENBSD
00721   delete [] buf;
00722 # endif
00723 #endif
00724 
00725   return lst;
00726 }
00727 
00728 int KResolver::protocolNumber(const char *protoname)
00729 {
00730   struct protoent *pe = 0L;
00731 #ifndef HAVE_GETPROTOBYNAME_R
00732   QMutexLocker locker(&getXXbyYYmutex);
00733 
00734   pe = getprotobyname(protoname);
00735 
00736 #else
00737 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API
00738   struct protoent protobuf;
00739   struct protoent_data pdata;
00740   ::memset(&pdata, 0, sizeof pdata);
00741 
00742   if (getprotobyname_r(protoname, &protobuf, &pdata) == 0)
00743     pe = &protobuf;
00744   else
00745     pe = 0;
00746 
00747 # else
00748   size_t buflen = 1024;
00749   struct protoent protobuf;
00750   char *buf;
00751   do
00752     {
00753       buf = new char[buflen];
00754 #  ifdef Q_OS_SOLARIS // Solaris uses a 4 argument getprotobyname_r which returns struct *protoent or NULL
00755       if ((pe = getprotobyname_r(protoname, &protobuf, buf, buflen)) && (errno == ERANGE))
00756 #  else
00757       if (getprotobyname_r(protoname, &protobuf, buf, buflen, &pe) == ERANGE)
00758 #  endif
00759     {
00760           pe = 0L;
00761       buflen += 1024;
00762       delete [] buf;
00763     }
00764       else
00765     break;
00766     }
00767   while (pe == 0L);
00768 # endif
00769 #endif
00770 
00771   // Do common processing
00772   int protonum = -1;
00773   if (pe != NULL)
00774     protonum = pe->p_proto;
00775 
00776 #ifdef HAVE_GETPROTOBYNAME_R
00777 # ifndef USE_OPENBSD
00778   delete [] buf;
00779 # endif
00780 #endif
00781 
00782   return protonum;
00783 }
00784 
00785 int KResolver::servicePort(const char *servname, const char *protoname)
00786 {
00787   struct servent *se = 0L;
00788 #ifndef HAVE_GETSERVBYNAME_R
00789   QMutexLocker locker(&getXXbyYYmutex);
00790 
00791   se = getservbyname(servname, protoname);
00792 
00793 #else
00794 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API
00795   struct servent servbuf;
00796   struct servent_data sdata;
00797   ::memset(&sdata, 0, sizeof sdata);
00798   if (getservbyname_r(servname, protoname, &servbuf, &sdata) == 0)
00799     se = &servbuf;
00800   else
00801     se = 0;
00802 
00803 # else
00804   size_t buflen = 1024;
00805   struct servent servbuf;
00806   char *buf;
00807   do
00808     {
00809       buf = new char[buflen];
00810 #  ifdef Q_OS_SOLARIS // Solaris uses a 5 argument getservbyname_r which returns struct *servent or NULL
00811       if ((se = getservbyname_r(servname, protoname, &servbuf, buf, buflen)) && (errno == ERANGE))
00812 #  else
00813       if (getservbyname_r(servname, protoname, &servbuf, buf, buflen, &se) == ERANGE)
00814 #  endif
00815     {
00816           se = 0L;
00817       buflen += 1024;
00818       delete [] buf;
00819     }
00820       else
00821     break;
00822     }
00823   while (se == 0L);
00824 # endif
00825 #endif
00826 
00827   // Do common processing
00828   int servport = -1;
00829   if (se != NULL)
00830     servport = ntohs(se->s_port);
00831 
00832 #ifdef HAVE_GETSERVBYNAME_R
00833 # ifndef USE_OPENBSD
00834   delete [] buf;
00835 # endif
00836 #endif
00837 
00838   return servport;
00839 }
00840 
00841 QList<QByteArray> KResolver::serviceName(const char* servname, const char *protoname)
00842 {
00843   struct servent *se = 0L;
00844 #ifndef HAVE_GETSERVBYNAME_R
00845   QMutexLocker locker(&getXXbyYYmutex);
00846 
00847   se = getservbyname(servname, protoname);
00848 
00849 #else
00850 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API
00851   struct servent servbuf;
00852   struct servent_data sdata;
00853   ::memset(&sdata, 0, sizeof sdata);
00854   if (getservbyname_r(servname, protoname, &servbuf, &sdata) == 0)
00855     se = &servbuf;
00856   else
00857     se = 0;
00858 
00859 # else
00860   size_t buflen = 1024;
00861   struct servent servbuf;
00862   char *buf;
00863   do
00864     {
00865       buf = new char[buflen];
00866 #  ifdef Q_OS_SOLARIS // Solaris uses a 5 argument getservbyname_r which returns struct *servent or NULL
00867       if ((se = getservbyname_r(servname, protoname, &servbuf, buf, buflen)) && (errno == ERANGE))
00868 #  else
00869       if (getservbyname_r(servname, protoname, &servbuf, buf, buflen, &se) == ERANGE)
00870 #  endif
00871     {
00872           se = 0L;
00873       buflen += 1024;
00874       delete [] buf;
00875     }
00876       else
00877     break;
00878     }
00879   while (se == 0L);
00880 # endif
00881 #endif
00882 
00883   // Do common processing
00884   QList<QByteArray> lst;
00885   if (se != NULL)
00886     {
00887       lst.append(se->s_name);
00888       for (char **p = se->s_aliases; *p; p++)
00889     lst.append(*p);
00890     }
00891 
00892 #ifdef HAVE_GETSERVBYNAME_R
00893 # ifndef USE_OPENBSD
00894   delete [] buf;
00895 # endif
00896 #endif
00897 
00898   return lst;
00899 }
00900 
00901 QList<QByteArray> KResolver::serviceName(int port, const char *protoname)
00902 {
00903   struct servent *se = 0L;
00904 #ifndef HAVE_GETSERVBYPORT_R
00905   QMutexLocker locker(&getXXbyYYmutex);
00906 
00907   se = getservbyport(port, protoname);
00908 
00909 #else
00910 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API
00911   struct servent servbuf;
00912   struct servent_data sdata;
00913   ::memset(&sdata, 0, sizeof sdata);
00914   if (getservbyport_r(port, protoname, &servbuf, &sdata) == 0)
00915     se = &servbuf;
00916   else
00917     se = 0;
00918 
00919 # else
00920   size_t buflen = 1024;
00921   struct servent servbuf;
00922   char *buf;
00923   do
00924     {
00925       buf = new char[buflen];
00926 #  ifdef Q_OS_SOLARIS // Solaris uses a 5 argument getservbyport_r which returns struct *servent or NULL
00927       if ((se = getservbyport_r(port, protoname, &servbuf, buf, buflen)) && (errno == ERANGE))
00928 #  else
00929       if (getservbyport_r(port, protoname, &servbuf, buf, buflen, &se) == ERANGE)
00930 #  endif
00931     {
00932           se = 0L;
00933       buflen += 1024;
00934       delete [] buf;
00935     }
00936       else
00937     break;
00938     }
00939   while (se == 0L);
00940 # endif
00941 #endif
00942 
00943   // Do common processing
00944   QList<QByteArray> lst;
00945   if (se != NULL)
00946     {
00947       lst.append(se->s_name);
00948       for (char **p = se->s_aliases; *p; p++)
00949     lst.append(*p);
00950     }
00951 
00952 #ifdef HAVE_GETSERVBYPORT_R
00953 # ifndef USE_OPENBSD
00954   delete [] buf;
00955 # endif
00956 #endif
00957 
00958   return lst;
00959 }
00960 
00961 QString KResolver::localHostName()
00962 {
00963   QByteArray name;
00964   int len;
00965 
00966 #ifdef MAXHOSTNAMELEN
00967   len = MAXHOSTNAMELEN;
00968 #else
00969   len = 256;
00970 #endif
00971 
00972   while (true)
00973     {
00974       name.resize(len);
00975 
00976       if (gethostname(name.data(), len) == 0)
00977     {
00978       // Call succeeded, but it's not guaranteed to be NUL-terminated
00979       // Fortunately, QByteArray is always NUL-terminated
00980 
00981       // Note that some systems return success even if they did truncation
00982       break;
00983     }
00984 
00985       // Call failed
00986       if (errno == ENAMETOOLONG || errno == EINVAL)
00987     len += 256;
00988       else
00989     {
00990       // Oops! Unknown error!
00991       name.clear();
00992     }
00993     }
00994 
00995   if (name.isEmpty())
00996     return QLatin1String("localhost");
00997 
00998   if (name.indexOf('.') == -1)
00999     {
01000       // not fully qualified
01001       // must resolve
01002       KResolverResults results = resolve(name, "0", CanonName);
01003       if (results.isEmpty())
01004     // cannot find a valid hostname!
01005     return QLatin1String("localhost");
01006       else
01007     return results.first().canonicalName();
01008     }
01009 
01010   return domainToUnicode(name);
01011 }
01012 
01013 static void KResolver_initIdnDomains()
01014 {
01015   static bool init = false;
01016   if (!init)
01017     {
01018       QByteArray kde_use_idn = qgetenv("KDE_USE_IDN");
01019       if (!kde_use_idn.isEmpty())
01020         KUrl::setIdnWhitelist(QString::fromLatin1(kde_use_idn).toLower().split(':'));
01021       init = true;
01022     }
01023 }
01024 
01025 // implement the ToAscii function, as described by IDN documents
01026 QByteArray KResolver::domainToAscii(const QString& unicodeDomain)
01027 {
01028   KResolver_initIdnDomains();
01029   return KUrl::toAce(unicodeDomain);
01030 }
01031 
01032 QString KResolver::domainToUnicode(const QByteArray& asciiDomain)
01033 {
01034   return domainToUnicode(QString::fromLatin1(asciiDomain));
01035 }
01036 
01037 // implement the ToUnicode function, as described by IDN documents
01038 QString KResolver::domainToUnicode(const QString& asciiDomain)
01039 {
01040   if (asciiDomain.isEmpty())
01041     return asciiDomain;
01042   KResolver_initIdnDomains();
01043   return KUrl::fromAce(asciiDomain.toLatin1());
01044 }
01045 
01046 QString KResolver::normalizeDomain(const QString& domain)
01047 {
01048   return domainToUnicode(domainToAscii(domain));
01049 }
01050 
01051 void KResolver::virtual_hook( int, void* )
01052 { /*BASE::virtual_hook( id, data );*/ }
01053 
01054 // here follows IDN functions
01055 // all IDN functions conform to the following documents:
01056 //  RFC 3454 - Preparation of Internationalized Strings
01057 //  RFC 3490 - Internationalizing Domain Names in Applications (IDNA)
01058 //  RFC 3491 - Nameprep: A Stringprep Profile for
01059 //                Internationalized Domain Names (IDN
01060 //  RFC 3492 - Punycode: A Bootstring encoding of Unicode
01061 //          for Internationalized Domain Names in Applications (IDNA)
01062 
01063 #include "k3resolver.moc"

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal