00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "k3resolver.h"
00026 #include "k3resolver_p.h"
00027
00028 #include <config.h>
00029 #include <config-network.h>
00030
00031
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
00044 #include <QCoreApplication>
00045 #include <QPointer>
00046 #include <QSet>
00047
00048 #include <QStringList>
00049 #include <QSharedData>
00050 #include <QTime>
00051 #include <QTimer>
00052
00053
00054 #include <klocale.h>
00055 #include <kurl.h>
00056
00057
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
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
00092 KResolverEntry::KResolverEntry() :
00093 d(0L)
00094 {
00095 }
00096
00097
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
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
00123 KResolverEntry::KResolverEntry(const KResolverEntry& that) :
00124 d(0L)
00125 {
00126 *this = that;
00127 }
00128
00129
00130 KResolverEntry::~KResolverEntry()
00131 {
00132 }
00133
00134
00135 KSocketAddress KResolverEntry::address() const
00136 {
00137 return d->addr;
00138 }
00139
00140
00141 quint16 KResolverEntry::length() const
00142 {
00143 return d->addr.length();
00144 }
00145
00146
00147 int KResolverEntry::family() const
00148 {
00149 return d->addr.family();
00150 }
00151
00152
00153 QString KResolverEntry::canonicalName() const
00154 {
00155 return d->canonName;
00156 }
00157
00158
00159 QByteArray KResolverEntry::encodedName() const
00160 {
00161 return d->encodedName;
00162 }
00163
00164
00165 int KResolverEntry::socketType() const
00166 {
00167 return d->socktype;
00168 }
00169
00170
00171 int KResolverEntry::protocol() const
00172 {
00173 return d->protocol;
00174 }
00175
00176
00177 KResolverEntry& KResolverEntry::operator= (const KResolverEntry& that)
00178 {
00179 d = that.d;
00180 return *this;
00181 }
00182
00184
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
00198 KResolverResults::KResolverResults()
00199 : d(new KResolverResultsPrivate)
00200 {
00201 }
00202
00203
00204 KResolverResults::KResolverResults(const KResolverResults& other)
00205 : QList<KResolverEntry>(other), d(new KResolverResultsPrivate)
00206 {
00207 d = other.d;
00208 }
00209
00210
00211 KResolverResults::~KResolverResults()
00212 {
00213 }
00214
00215
00216 KResolverResults&
00217 KResolverResults::operator= (const KResolverResults& other)
00218 {
00219
00220 d = other.d;
00221
00222
00223 QList<KResolverEntry>::operator =(other);
00224
00225 return *this;
00226 }
00227
00228
00229 int KResolverResults::error() const
00230 {
00231 return d->errorcode;
00232 }
00233
00234
00235 int KResolverResults::systemError() const
00236 {
00237 return d->syserror;
00238 }
00239
00240
00241 void KResolverResults::setError(int errorcode, int systemerror)
00242 {
00243 d->errorcode = errorcode;
00244 d->syserror = systemerror;
00245 }
00246
00247
00248 QString KResolverResults::nodeName() const
00249 {
00250 return d->node;
00251 }
00252
00253
00254 QString KResolverResults::serviceName() const
00255 {
00256 return d->service;
00257 }
00258
00259
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 { }
00269
00270
00272
00273
00274
00275 KResolver::KResolver(QObject *parent)
00276 : QObject(parent), d(new KResolverPrivate(this))
00277 {
00278 }
00279
00280
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
00288 KResolver::~KResolver()
00289 {
00290 cancel(false);
00291 delete d;
00292 }
00293
00294
00295 int KResolver::status() const
00296 {
00297 return d->status;
00298 }
00299
00300
00301 int KResolver::error() const
00302 {
00303 return d->errorcode;
00304 }
00305
00306
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
00318 bool KResolver::isRunning() const
00319 {
00320 return d->status > 0 && d->status < Success;
00321 }
00322
00323
00324 QString KResolver::nodeName() const
00325 {
00326 return d->input.node;
00327 }
00328
00329
00330 QString KResolver::serviceName() const
00331 {
00332 return d->input.service;
00333 }
00334
00335
00336 void KResolver::setNodeName(const QString& nodename)
00337 {
00338
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
00348 void KResolver::setServiceName(const QString& service)
00349 {
00350
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
00360 void KResolver::setAddress(const QString& nodename, const QString& service)
00361 {
00362 setNodeName(nodename);
00363 setServiceName(service);
00364 }
00365
00366
00367 int KResolver::flags() const
00368 {
00369 return d->input.flags;
00370 }
00371
00372
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
00385 void KResolver::setFamily(int families)
00386 {
00387 if (!isRunning())
00388 {
00389 d->input.familyMask = families;
00390 d->status = Idle;
00391 }
00392 }
00393
00394
00395 void KResolver::setSocketType(int type)
00396 {
00397 if (!isRunning())
00398 {
00399 d->input.socktype = type;
00400 d->status = Idle;
00401 }
00402 }
00403
00404
00405 void KResolver::setProtocol(int protonum, const char *name)
00406 {
00407 if (isRunning())
00408 return;
00409
00410
00411
00412
00413
00414
00415 d->input.protocolName = name;
00416 if (protonum == 0 && name != 0L && *name != '\0')
00417 {
00418
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
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
00458
00459
00460
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
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
00480
00481 if (!isRunning())
00482 {
00483
00484 d->waiting = false;
00485 emitFinished();
00486 return true;
00487 }
00488 }
00489
00490
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
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;
00533
00534 emit finished(d->results);
00535
00536 if (p && d->deleteWhenDone)
00537 deleteLater();
00538 }
00539
00540 QString KResolver::errorString(int errorcode, int syserror)
00541 {
00542
00543 static const char messages[] =
00544 {
00545 I18N_NOOP("no error")"\0"
00546 I18N_NOOP("requested family not supported for this host name")"\0"
00547 I18N_NOOP("temporary failure in name resolution")"\0"
00548 I18N_NOOP("non-recoverable failure in name resolution")"\0"
00549 I18N_NOOP("invalid flags")"\0"
00550 I18N_NOOP("memory allocation failure")"\0"
00551 I18N_NOOP("name or service not known")"\0"
00552 I18N_NOOP("requested family not supported")"\0"
00553 I18N_NOOP("requested service not supported for this socket type")"\0"
00554 I18N_NOOP("requested socket type not supported")"\0"
00555 I18N_NOOP("unknown error")"\0"
00556 I18N_NOOP2("1: the i18n'ed system error code, from errno",
00557 "system error: %1")"\0"
00558 "\0"
00559 };
00560
00561 static const int messages_indices[] = {
00562 0, 9, 59, 96, 139, 153, 179, 205,
00563 236, 289, 325, 0
00564 };
00565
00566
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;
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
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
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
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
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
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
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
00979
00980
00981
00982 break;
00983 }
00984
00985
00986 if (errno == ENAMETOOLONG || errno == EINVAL)
00987 len += 256;
00988 else
00989 {
00990
00991 name.clear();
00992 }
00993 }
00994
00995 if (name.isEmpty())
00996 return QLatin1String("localhost");
00997
00998 if (name.indexOf('.') == -1)
00999 {
01000
01001
01002 KResolverResults results = resolve(name, "0", CanonName);
01003 if (results.isEmpty())
01004
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
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
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 { }
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063 #include "k3resolver.moc"