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 "config.h"
00026
00027
00028 #include <sys/types.h>
00029 #include <sys/socket.h>
00030 #include <sys/param.h>
00031 #include <errno.h>
00032 #include <netdb.h>
00033 #include <time.h>
00034 #include <arpa/inet.h>
00035 #include <netinet/in.h>
00036 #include <stdlib.h>
00037 #include <unistd.h>
00038
00039
00040 #include <tqapplication.h>
00041 #include <tqstring.h>
00042 #include <tqcstring.h>
00043 #include <tqstrlist.h>
00044 #include <tqstringlist.h>
00045 #include <tqshared.h>
00046 #include <tqdatetime.h>
00047 #include <tqtimer.h>
00048 #include <tqmutex.h>
00049 #include <tqguardedptr.h>
00050
00051
00052 #ifdef HAVE_IDNA_H
00053 # include <idna.h>
00054 #endif
00055
00056
00057 #include <tdelocale.h>
00058
00059
00060 #include "kresolver.h"
00061 #include "kresolver_p.h"
00062 #include "tdesocketaddress.h"
00063
00064 #ifdef NEED_MUTEX
00065 #warning "mutex"
00066 TQMutex getXXbyYYmutex;
00067 #endif
00068
00069 #ifdef __OpenBSD__
00070 #define USE_OPENBSD 1
00071 #endif
00072
00073 using namespace KNetwork;
00074 using namespace KNetwork::Internal;
00075
00077
00078
00079 class KNetwork::KResolverEntryPrivate: public TQShared
00080 {
00081 public:
00082 TDESocketAddress addr;
00083 int socktype;
00084 int protocol;
00085 TQString canonName;
00086 TQCString encodedName;
00087
00088 inline KResolverEntryPrivate() :
00089 socktype(0), protocol(0)
00090 { }
00091 };
00092
00093
00094 KResolverEntry::KResolverEntry() :
00095 d(0L)
00096 {
00097 }
00098
00099
00100 KResolverEntry::KResolverEntry(const TDESocketAddress& addr, int socktype, int protocol,
00101 const TQString& canonName, const TQCString& encodedName) :
00102 d(new KResolverEntryPrivate)
00103 {
00104 d->addr = addr;
00105 d->socktype = socktype;
00106 d->protocol = protocol;
00107 d->canonName = canonName;
00108 d->encodedName = encodedName;
00109 }
00110
00111
00112 KResolverEntry::KResolverEntry(const struct sockaddr* sa, TQ_UINT16 salen, int socktype,
00113 int protocol, const TQString& canonName,
00114 const TQCString& encodedName) :
00115 d(new KResolverEntryPrivate)
00116 {
00117 d->addr = TDESocketAddress(sa, salen);
00118 d->socktype = socktype;
00119 d->protocol = protocol;
00120 d->canonName = canonName;
00121 d->encodedName = encodedName;
00122 }
00123
00124
00125 KResolverEntry::KResolverEntry(const KResolverEntry& that) :
00126 d(0L)
00127 {
00128 *this = that;
00129 }
00130
00131
00132 KResolverEntry::~KResolverEntry()
00133 {
00134 if (d == 0L)
00135 return;
00136
00137 if (d->deref())
00138 delete d;
00139 }
00140
00141
00142 TDESocketAddress KResolverEntry::address() const
00143 {
00144 return d ? d->addr : TDESocketAddress();
00145 }
00146
00147
00148 TQ_UINT16 KResolverEntry::length() const
00149 {
00150 return d ? d->addr.length() : 0;
00151 }
00152
00153
00154 int KResolverEntry::family() const
00155 {
00156 return d ? d->addr.family() : AF_UNSPEC;
00157 }
00158
00159
00160 TQString KResolverEntry::canonicalName() const
00161 {
00162 return d ? d->canonName : TQString::null;
00163 }
00164
00165
00166 TQCString KResolverEntry::encodedName() const
00167 {
00168 return d ? d->encodedName : TQCString();
00169 }
00170
00171
00172 int KResolverEntry::socketType() const
00173 {
00174 return d ? d->socktype : 0;
00175 }
00176
00177
00178 int KResolverEntry::protocol() const
00179 {
00180 return d ? d->protocol : 0;
00181 }
00182
00183
00184 KResolverEntry& KResolverEntry::operator= (const KResolverEntry& that)
00185 {
00186
00187 if (that.d)
00188 that.d->ref();
00189
00190 if (d && d->deref())
00191 delete d;
00192
00193 d = that.d;
00194 return *this;
00195 }
00196
00198
00199
00200 class KNetwork::KResolverResultsPrivate
00201 {
00202 public:
00203 TQString node, service;
00204 int errorcode, syserror;
00205
00206 KResolverResultsPrivate() :
00207 errorcode(0), syserror(0)
00208 { }
00209 };
00210
00211
00212 KResolverResults::KResolverResults()
00213 : d(new KResolverResultsPrivate)
00214 {
00215 }
00216
00217
00218 KResolverResults::KResolverResults(const KResolverResults& other)
00219 : TQValueList<KResolverEntry>(other), d(new KResolverResultsPrivate)
00220 {
00221 *d = *other.d;
00222 }
00223
00224
00225 KResolverResults::~KResolverResults()
00226 {
00227 delete d;
00228 }
00229
00230
00231 KResolverResults&
00232 KResolverResults::operator= (const KResolverResults& other)
00233 {
00234 if (this == &other)
00235 return *this;
00236
00237
00238 *d = *other.d;
00239
00240
00241 TQValueList<KResolverEntry>::operator =(other);
00242
00243 return *this;
00244 }
00245
00246
00247 int KResolverResults::error() const
00248 {
00249 return d->errorcode;
00250 }
00251
00252
00253 int KResolverResults::systemError() const
00254 {
00255 return d->syserror;
00256 }
00257
00258
00259 void KResolverResults::setError(int errorcode, int systemerror)
00260 {
00261 d->errorcode = errorcode;
00262 d->syserror = systemerror;
00263 }
00264
00265
00266 TQString KResolverResults::nodeName() const
00267 {
00268 return d->node;
00269 }
00270
00271
00272 TQString KResolverResults::serviceName() const
00273 {
00274 return d->service;
00275 }
00276
00277
00278 void KResolverResults::setAddress(const TQString& node,
00279 const TQString& service)
00280 {
00281 d->node = node;
00282 d->service = service;
00283 }
00284
00285 void KResolverResults::virtual_hook( int, void* )
00286 { }
00287
00288
00290
00291
00292 TQStringList *KResolver::idnDomains = 0;
00293
00294
00295
00296 KResolver::KResolver(TQObject *parent, const char *name)
00297 : TQObject(parent, name), d(new KResolverPrivate(this))
00298 {
00299 }
00300
00301
00302 KResolver::KResolver(const TQString& nodename, const TQString& servicename,
00303 TQObject *parent, const char *name)
00304 : TQObject(parent, name), d(new KResolverPrivate(this, nodename, servicename))
00305 {
00306 }
00307
00308
00309 KResolver::~KResolver()
00310 {
00311 cancel(false);
00312 delete d;
00313 }
00314
00315
00316 int KResolver::status() const
00317 {
00318 return d->status;
00319 }
00320
00321
00322 int KResolver::error() const
00323 {
00324 return d->errorcode;
00325 }
00326
00327
00328 int KResolver::systemError() const
00329 {
00330 return d->syserror;
00331 }
00332
00333
00334 bool KResolver::isRunning() const
00335 {
00336 return d->status > 0 && d->status < Success;
00337 }
00338
00339
00340 TQString KResolver::nodeName() const
00341 {
00342 return d->input.node;
00343 }
00344
00345
00346 TQString KResolver::serviceName() const
00347 {
00348 return d->input.service;
00349 }
00350
00351
00352 void KResolver::setNodeName(const TQString& nodename)
00353 {
00354
00355 if (!isRunning())
00356 {
00357 d->input.node = nodename;
00358 d->status = Idle;
00359 d->results.setAddress(nodename, d->input.service);
00360 }
00361 }
00362
00363
00364 void KResolver::setServiceName(const TQString& service)
00365 {
00366
00367 if (!isRunning())
00368 {
00369 d->input.service = service;
00370 d->status = Idle;
00371 d->results.setAddress(d->input.node, service);
00372 }
00373 }
00374
00375
00376 void KResolver::setAddress(const TQString& nodename, const TQString& service)
00377 {
00378 setNodeName(nodename);
00379 setServiceName(service);
00380 }
00381
00382
00383 int KResolver::flags() const
00384 {
00385 return d->input.flags;
00386 }
00387
00388
00389 int KResolver::setFlags(int flags)
00390 {
00391 int oldflags = d->input.flags;
00392 if (!isRunning())
00393 {
00394 d->input.flags = flags;
00395 d->status = Idle;
00396 }
00397 return oldflags;
00398 }
00399
00400
00401 void KResolver::setFamily(int families)
00402 {
00403 if (!isRunning())
00404 {
00405 d->input.familyMask = families;
00406 d->status = Idle;
00407 }
00408 }
00409
00410
00411 void KResolver::setSocketType(int type)
00412 {
00413 if (!isRunning())
00414 {
00415 d->input.socktype = type;
00416 d->status = Idle;
00417 }
00418 }
00419
00420
00421 void KResolver::setProtocol(int protonum, const char *name)
00422 {
00423 if (isRunning())
00424 return;
00425
00426
00427
00428
00429
00430
00431 d->input.protocolName = name;
00432 if (protonum == 0 && name != 0L && *name != '\0')
00433 {
00434
00435 d->input.protocol = KResolver::protocolNumber(name);
00436 }
00437 else
00438 d->input.protocol = protonum;
00439 d->status = Idle;
00440 }
00441
00442 bool KResolver::start()
00443 {
00444 if (!isRunning())
00445 {
00446 d->results.empty();
00447
00448
00449 if (d->input.node.isEmpty() && d->input.service.isEmpty())
00450 {
00451 d->status = KResolver::Success;
00452 emitFinished();
00453 }
00454 else
00455 KResolverManager::manager()->enqueue(this, 0L);
00456 }
00457
00458 return true;
00459 }
00460
00461 bool KResolver::wait(int msec)
00462 {
00463 if (!isRunning())
00464 {
00465 emitFinished();
00466 return true;
00467 }
00468
00469 TQMutexLocker locker(&d->mutex);
00470
00471 if (!isRunning())
00472 {
00473
00474
00475
00476
00477
00478 emitFinished();
00479 return true;
00480 }
00481 else
00482 {
00483 TQTime t;
00484 t.start();
00485
00486 while (!msec || t.elapsed() < msec)
00487 {
00488
00489 d->waiting = true;
00490 if (msec)
00491 KResolverManager::manager()->notifyWaiters.wait(&d->mutex, msec - t.elapsed());
00492 else
00493 KResolverManager::manager()->notifyWaiters.wait(&d->mutex);
00494
00495
00496
00497 if (!isRunning())
00498 {
00499
00500 d->waiting = false;
00501 emitFinished();
00502 return true;
00503 }
00504 }
00505
00506
00507 d->waiting = false;
00508 return false;
00509 }
00510 }
00511
00512 void KResolver::cancel(bool emitSignal)
00513 {
00514 KResolverManager::manager()->dequeue(this);
00515 if (emitSignal)
00516 emitFinished();
00517 }
00518
00519 KResolverResults
00520 KResolver::results() const
00521 {
00522 if (!isRunning())
00523 return d->results;
00524
00525
00526 KResolverResults r;
00527 r.setAddress(d->input.node, d->input.service);
00528 r.setError(d->errorcode, d->syserror);
00529 return r;
00530 }
00531
00532 bool KResolver::event(TQEvent* e)
00533 {
00534 if (static_cast<int>(e->type()) == KResolverManager::ResolutionCompleted)
00535 {
00536 emitFinished();
00537 return true;
00538 }
00539
00540 return false;
00541 }
00542
00543 void KResolver::emitFinished()
00544 {
00545 if (isRunning())
00546 d->status = KResolver::Success;
00547
00548 TQGuardedPtr<TQObject> p = this;
00549
00550 emit finished(d->results);
00551
00552 if (p && d->deleteWhenDone)
00553 deleteLater();
00554 }
00555
00556 TQString KResolver::errorString(int errorcode, int syserror)
00557 {
00558
00559 static const char * const messages[] =
00560 {
00561 I18N_NOOP("no error"),
00562 I18N_NOOP("requested family not supported for this host name"),
00563 I18N_NOOP("temporary failure in name resolution"),
00564 I18N_NOOP("non-recoverable failure in name resolution"),
00565 I18N_NOOP("invalid flags"),
00566 I18N_NOOP("memory allocation failure"),
00567 I18N_NOOP("name or service not known"),
00568 I18N_NOOP("requested family not supported"),
00569 I18N_NOOP("requested service not supported for this socket type"),
00570 I18N_NOOP("requested socket type not supported"),
00571 I18N_NOOP("unknown error"),
00572 I18N_NOOP2("1: the i18n'ed system error code, from errno",
00573 "system error: %1")
00574 };
00575
00576
00577 if (errorcode == Canceled)
00578 return i18n("request was canceled");
00579
00580 if (errorcode > 0 || errorcode < SystemError)
00581 return TQString::null;
00582
00583 TQString msg = i18n(messages[-errorcode]);
00584 if (errorcode == SystemError)
00585 msg.arg(TQString::fromLocal8Bit(strerror(syserror)));
00586
00587 return msg;
00588 }
00589
00590 KResolverResults
00591 KResolver::resolve(const TQString& host, const TQString& service, int flags,
00592 int families)
00593 {
00594 KResolver qres(host, service, TQT_TQOBJECT(tqApp), "synchronous KResolver");
00595 qres.setFlags(flags);
00596 qres.setFamily(families);
00597 qres.start();
00598 qres.wait();
00599 return qres.results();
00600 }
00601
00602 bool KResolver::resolveAsync(TQObject* userObj, const char *userSlot,
00603 const TQString& host, const TQString& service,
00604 int flags, int families)
00605 {
00606 KResolver* qres = new KResolver(host, service, TQT_TQOBJECT(tqApp), "asynchronous KResolver");
00607 TQObject::connect(qres, TQT_SIGNAL(finished(KResolverResults)), userObj, userSlot);
00608 qres->setFlags(flags);
00609 qres->setFamily(families);
00610 qres->d->deleteWhenDone = true;
00611 return qres->start();
00612 }
00613
00614 TQStrList KResolver::protocolName(int protonum)
00615 {
00616 struct protoent *pe = 0L;
00617 #ifndef HAVE_GETPROTOBYNAME_R
00618 TQMutexLocker locker(&getXXbyYYmutex);
00619
00620 pe = getprotobynumber(protonum);
00621
00622 #else
00623 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API
00624 struct protoent protobuf;
00625 struct protoent_data pdata;
00626 ::memset(&pdata, 0, sizeof pdata);
00627
00628 if (getprotobynumber_r(protonum, &protobuf, &pdata) == 0)
00629 pe = &protobuf;
00630 else
00631 pe = 0;
00632
00633 # else
00634 size_t buflen = 1024;
00635 struct protoent protobuf;
00636 char *buf;
00637 do
00638 {
00639 buf = new char[buflen];
00640 # ifdef USE_SOLARIS // Solaris uses a 4 argument getprotobynumber_r which returns struct *protoent or NULL
00641 if ((pe = getprotobynumber_r(protonum, &protobuf, buf, buflen)) && (errno == ERANGE))
00642 # else
00643 if (getprotobynumber_r(protonum, &protobuf, buf, buflen, &pe) == ERANGE)
00644 # endif
00645 {
00646 pe = 0L;
00647 buflen += 1024;
00648 delete [] buf;
00649 }
00650 else
00651 break;
00652 }
00653 while (pe == 0L);
00654 # endif
00655 #endif
00656
00657
00658 TQStrList lst(true);
00659 if (pe != NULL)
00660 {
00661 lst.append(pe->p_name);
00662 for (char **p = pe->p_aliases; *p; p++)
00663 lst.append(*p);
00664 }
00665
00666 #ifdef HAVE_GETPROTOBYNAME_R
00667 # ifndef USE_OPENBSD
00668 delete [] buf;
00669 # endif
00670 #endif
00671
00672 return lst;
00673 }
00674
00675 TQStrList KResolver::protocolName(const char *protoname)
00676 {
00677 struct protoent *pe = 0L;
00678 #ifndef HAVE_GETPROTOBYNAME_R
00679 TQMutexLocker locker(&getXXbyYYmutex);
00680
00681 pe = getprotobyname(protoname);
00682
00683 #else
00684 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API
00685 struct protoent protobuf;
00686 struct protoent_data pdata;
00687 ::memset(&pdata, 0, sizeof pdata);
00688
00689 if (getprotobyname_r(protoname, &protobuf, &pdata) == 0)
00690 pe = &protobuf;
00691 else
00692 pe = 0;
00693
00694 # else
00695 size_t buflen = 1024;
00696 struct protoent protobuf;
00697 char *buf;
00698 do
00699 {
00700 buf = new char[buflen];
00701 # ifdef USE_SOLARIS // Solaris uses a 4 argument getprotobyname_r which returns struct *protoent or NULL
00702 if ((pe = getprotobyname_r(protoname, &protobuf, buf, buflen)) && (errno == ERANGE))
00703 # else
00704 if (getprotobyname_r(protoname, &protobuf, buf, buflen, &pe) == ERANGE)
00705 # endif
00706 {
00707 pe = 0L;
00708 buflen += 1024;
00709 delete [] buf;
00710 }
00711 else
00712 break;
00713 }
00714 while (pe == 0L);
00715 # endif
00716 #endif
00717
00718
00719 TQStrList lst(true);
00720 if (pe != NULL)
00721 {
00722 lst.append(pe->p_name);
00723 for (char **p = pe->p_aliases; *p; p++)
00724 lst.append(*p);
00725 }
00726
00727 #ifdef HAVE_GETPROTOBYNAME_R
00728 # ifndef USE_OPENBSD
00729 delete [] buf;
00730 # endif
00731 #endif
00732
00733 return lst;
00734 }
00735
00736 int KResolver::protocolNumber(const char *protoname)
00737 {
00738 struct protoent *pe = 0L;
00739 #ifndef HAVE_GETPROTOBYNAME_R
00740 TQMutexLocker locker(&getXXbyYYmutex);
00741
00742 pe = getprotobyname(protoname);
00743
00744 #else
00745 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API
00746 struct protoent protobuf;
00747 struct protoent_data pdata;
00748 ::memset(&pdata, 0, sizeof pdata);
00749
00750 if (getprotobyname_r(protoname, &protobuf, &pdata) == 0)
00751 pe = &protobuf;
00752 else
00753 pe = 0;
00754
00755 # else
00756 size_t buflen = 1024;
00757 struct protoent protobuf;
00758 char *buf;
00759 do
00760 {
00761 buf = new char[buflen];
00762 # ifdef USE_SOLARIS // Solaris uses a 4 argument getprotobyname_r which returns struct *protoent or NULL
00763 if ((pe = getprotobyname_r(protoname, &protobuf, buf, buflen)) && (errno == ERANGE))
00764 # else
00765 if (getprotobyname_r(protoname, &protobuf, buf, buflen, &pe) == ERANGE)
00766 # endif
00767 {
00768 pe = 0L;
00769 buflen += 1024;
00770 delete [] buf;
00771 }
00772 else
00773 break;
00774 }
00775 while (pe == 0L);
00776 # endif
00777 #endif
00778
00779
00780 int protonum = -1;
00781 if (pe != NULL)
00782 protonum = pe->p_proto;
00783
00784 #ifdef HAVE_GETPROTOBYNAME_R
00785 # ifndef USE_OPENBSD
00786 delete [] buf;
00787 # endif
00788 #endif
00789
00790 return protonum;
00791 }
00792
00793 int KResolver::servicePort(const char *servname, const char *protoname)
00794 {
00795 struct servent *se = 0L;
00796 #ifndef HAVE_GETSERVBYNAME_R
00797 TQMutexLocker locker(&getXXbyYYmutex);
00798
00799 se = getservbyname(servname, protoname);
00800
00801 #else
00802 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API
00803 struct servent servbuf;
00804 struct servent_data sdata;
00805 ::memset(&sdata, 0, sizeof sdata);
00806 if (getservbyname_r(servname, protoname, &servbuf, &sdata) == 0)
00807 se = &servbuf;
00808 else
00809 se = 0;
00810
00811 # else
00812 size_t buflen = 1024;
00813 struct servent servbuf;
00814 char *buf;
00815 do
00816 {
00817 buf = new char[buflen];
00818 # ifdef USE_SOLARIS // Solaris uses a 5 argument getservbyname_r which returns struct *servent or NULL
00819 if ((se = getservbyname_r(servname, protoname, &servbuf, buf, buflen)) && (errno == ERANGE))
00820 # else
00821 if (getservbyname_r(servname, protoname, &servbuf, buf, buflen, &se) == ERANGE)
00822 # endif
00823 {
00824 se = 0L;
00825 buflen += 1024;
00826 delete [] buf;
00827 }
00828 else
00829 break;
00830 }
00831 while (se == 0L);
00832 # endif
00833 #endif
00834
00835
00836 int servport = -1;
00837 if (se != NULL)
00838 servport = ntohs(se->s_port);
00839
00840 #ifdef HAVE_GETSERVBYNAME_R
00841 # ifndef USE_OPENBSD
00842 delete [] buf;
00843 # endif
00844 #endif
00845
00846 return servport;
00847 }
00848
00849 TQStrList KResolver::serviceName(const char* servname, const char *protoname)
00850 {
00851 struct servent *se = 0L;
00852 #ifndef HAVE_GETSERVBYNAME_R
00853 TQMutexLocker locker(&getXXbyYYmutex);
00854
00855 se = getservbyname(servname, protoname);
00856
00857 #else
00858 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API
00859 struct servent servbuf;
00860 struct servent_data sdata;
00861 ::memset(&sdata, 0, sizeof sdata);
00862 if (getservbyname_r(servname, protoname, &servbuf, &sdata) == 0)
00863 se = &servbuf;
00864 else
00865 se = 0;
00866
00867 # else
00868 size_t buflen = 1024;
00869 struct servent servbuf;
00870 char *buf;
00871 do
00872 {
00873 buf = new char[buflen];
00874 # ifdef USE_SOLARIS // Solaris uses a 5 argument getservbyname_r which returns struct *servent or NULL
00875 if ((se = getservbyname_r(servname, protoname, &servbuf, buf, buflen)) && (errno == ERANGE))
00876 # else
00877 if (getservbyname_r(servname, protoname, &servbuf, buf, buflen, &se) == ERANGE)
00878 # endif
00879 {
00880 se = 0L;
00881 buflen += 1024;
00882 delete [] buf;
00883 }
00884 else
00885 break;
00886 }
00887 while (se == 0L);
00888 # endif
00889 #endif
00890
00891
00892 TQStrList lst(true);
00893 if (se != NULL)
00894 {
00895 lst.append(se->s_name);
00896 for (char **p = se->s_aliases; *p; p++)
00897 lst.append(*p);
00898 }
00899
00900 #ifdef HAVE_GETSERVBYNAME_R
00901 # ifndef USE_OPENBSD
00902 delete [] buf;
00903 # endif
00904 #endif
00905
00906 return lst;
00907 }
00908
00909 TQStrList KResolver::serviceName(int port, const char *protoname)
00910 {
00911 struct servent *se = 0L;
00912 #ifndef HAVE_GETSERVBYPORT_R
00913 TQMutexLocker locker(&getXXbyYYmutex);
00914
00915 se = getservbyport(port, protoname);
00916
00917 #else
00918 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API
00919 struct servent servbuf;
00920 struct servent_data sdata;
00921 ::memset(&sdata, 0, sizeof sdata);
00922 if (getservbyport_r(port, protoname, &servbuf, &sdata) == 0)
00923 se = &servbuf;
00924 else
00925 se = 0;
00926
00927 # else
00928 size_t buflen = 1024;
00929 struct servent servbuf;
00930 char *buf;
00931 do
00932 {
00933 buf = new char[buflen];
00934 # ifdef USE_SOLARIS // Solaris uses a 5 argument getservbyport_r which returns struct *servent or NULL
00935 if ((se = getservbyport_r(port, protoname, &servbuf, buf, buflen)) && (errno == ERANGE))
00936 # else
00937 if (getservbyport_r(port, protoname, &servbuf, buf, buflen, &se) == ERANGE)
00938 # endif
00939 {
00940 se = 0L;
00941 buflen += 1024;
00942 delete [] buf;
00943 }
00944 else
00945 break;
00946 }
00947 while (se == 0L);
00948 # endif
00949 #endif
00950
00951
00952 TQStrList lst(true);
00953 if (se != NULL)
00954 {
00955 lst.append(se->s_name);
00956 for (char **p = se->s_aliases; *p; p++)
00957 lst.append(*p);
00958 }
00959
00960 #ifdef HAVE_GETSERVBYPORT_R
00961 # ifndef USE_OPENBSD
00962 delete [] buf;
00963 # endif
00964 #endif
00965
00966 return lst;
00967 }
00968
00969 TQString KResolver::localHostName()
00970 {
00971 TQCString name;
00972 int len;
00973
00974 #ifdef MAXHOSTNAMELEN
00975 len = MAXHOSTNAMELEN;
00976 #else
00977 len = 256;
00978 #endif
00979
00980 while (true)
00981 {
00982 name.resize(len);
00983
00984 if (gethostname(name.data(), len - 1) == 0)
00985 {
00986
00987
00988 name[len - 1] = '\0';
00989 break;
00990 }
00991
00992
00993 if (errno == ENAMETOOLONG || errno == EINVAL)
00994 len += 256;
00995 else
00996 {
00997
00998 name = TQCString();
00999 }
01000 }
01001
01002 if (name.isEmpty())
01003 return TQString::fromLatin1("localhost");
01004
01005 if (name.find('.') == -1)
01006 {
01007
01008
01009 KResolverResults results = resolve(name, "0", CanonName);
01010 if (results.isEmpty())
01011
01012 return TQString::fromLatin1("localhost");
01013 else
01014 return results.first().canonicalName();
01015 }
01016
01017 return domainToUnicode(name);
01018 }
01019
01020
01021
01022 static TQStringList splitLabels(const TQString& unicodeDomain);
01023 static TQCString ToASCII(const TQString& label);
01024 static TQString ToUnicode(const TQString& label);
01025
01026 static TQStringList *KResolver_initIdnDomains()
01027 {
01028 const char *kde_use_idn = getenv("TDE_USE_IDN");
01029 if (!kde_use_idn)
01030 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";
01031 return new TQStringList(TQStringList::split(':', TQString::fromLatin1(kde_use_idn).lower()));
01032 }
01033
01034
01035 TQCString KResolver::domainToAscii(const TQString& unicodeDomain)
01036 {
01037 if (!idnDomains)
01038 idnDomains = KResolver_initIdnDomains();
01039
01040 TQCString retval;
01041
01042
01043
01044
01045
01046 TQStringList input = splitLabels(unicodeDomain);
01047
01048
01049 if (input.count() && !idnDomains->contains(input[input.count()-1].lower()))
01050 return input.join(".").lower().latin1();
01051
01052
01053
01054
01055
01056 TQStringList::Iterator it = input.begin();
01057 const TQStringList::Iterator end = input.end();
01058 for ( ; it != end; ++it)
01059 {
01060 TQCString cs = ToASCII(*it);
01061 if (cs.isNull())
01062 return TQCString();
01063
01064
01065 if (!retval.isEmpty())
01066 retval += '.';
01067 retval += cs;
01068 }
01069
01070 return retval;
01071 }
01072
01073 TQString KResolver::domainToUnicode(const TQCString& asciiDomain)
01074 {
01075 return domainToUnicode(TQString::fromLatin1(asciiDomain));
01076 }
01077
01078
01079 TQString KResolver::domainToUnicode(const TQString& asciiDomain)
01080 {
01081 if (asciiDomain.isEmpty())
01082 return asciiDomain;
01083 if (!idnDomains)
01084 idnDomains = KResolver_initIdnDomains();
01085
01086 TQString retval;
01087
01088
01089
01090
01091
01092
01093
01094 TQStringList input = splitLabels(asciiDomain);
01095
01096
01097 if (input.count() && !idnDomains->contains(input[input.count()-1].lower()))
01098 return asciiDomain.lower();
01099
01100
01101
01102
01103
01104 TQStringList::Iterator it;
01105 const TQStringList::Iterator end = input.end();
01106 for (it = input.begin(); it != end; ++it)
01107 {
01108 TQString label = ToUnicode(*it).lower();
01109
01110
01111 if (!retval.isEmpty())
01112 retval += '.';
01113 retval += label;
01114 }
01115
01116 return retval;
01117 }
01118
01119 TQString KResolver::normalizeDomain(const TQString& domain)
01120 {
01121 return domainToUnicode(domainToAscii(domain));
01122 }
01123
01124 void KResolver::virtual_hook( int, void* )
01125 { }
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136 static TQStringList splitLabels(const TQString& unicodeDomain)
01137 {
01138
01139
01140
01141
01142
01143 static const unsigned int separators[] = { 0x002E, 0x3002, 0xFF0E, 0xFF61 };
01144
01145 TQStringList lst;
01146 int start = 0;
01147 uint i;
01148 for (i = 0; i < unicodeDomain.length(); i++)
01149 {
01150 unsigned int c = unicodeDomain[i].unicode();
01151
01152 if (c == separators[0] ||
01153 c == separators[1] ||
01154 c == separators[2] ||
01155 c == separators[3])
01156 {
01157
01158 lst << unicodeDomain.mid(start, i - start);
01159 start = i + 1;
01160 }
01161 }
01162 if ((long)i >= start)
01163
01164 lst << unicodeDomain.mid(start, i - start);
01165
01166 return lst;
01167 }
01168
01169 static TQCString ToASCII(const TQString& label)
01170 {
01171 #ifdef HAVE_IDNA_H
01172
01173
01174
01175 if (label.length() > 64)
01176 return (char*)0L;
01177
01178 if (label.length() == 0)
01179
01180 return TQCString("");
01181
01182 TQCString retval;
01183 char buf[65];
01184
01185 TQ_UINT32* ucs4 = new TQ_UINT32[label.length() + 1];
01186
01187 uint i;
01188 for (i = 0; i < label.length(); i++)
01189 ucs4[i] = (unsigned long)label[i].unicode();
01190 ucs4[i] = 0;
01191
01192 if (idna_to_ascii_4i(ucs4, label.length(), buf, 0) == IDNA_SUCCESS)
01193
01194 retval = buf;
01195
01196 delete [] ucs4;
01197 return retval;
01198 #else
01199 return label.latin1();
01200 #endif
01201 }
01202
01203 static TQString ToUnicode(const TQString& label)
01204 {
01205 #ifdef HAVE_IDNA_H
01206
01207
01208
01209 TQ_UINT32 *ucs4_input, *ucs4_output;
01210 size_t outlen;
01211
01212 ucs4_input = new TQ_UINT32[label.length() + 1];
01213 for (uint i = 0; i < label.length(); i++)
01214 ucs4_input[i] = (unsigned long)label[i].unicode();
01215
01216
01217 ucs4_output = new TQ_UINT32[outlen = label.length()];
01218
01219 idna_to_unicode_44i(ucs4_input, label.length(),
01220 ucs4_output, &outlen,
01221 0);
01222
01223 if (outlen > label.length())
01224 {
01225
01226 delete [] ucs4_output;
01227 ucs4_output = new TQ_UINT32[outlen];
01228
01229 idna_to_unicode_44i(ucs4_input, label.length(),
01230 ucs4_output, &outlen,
01231 0);
01232 }
01233
01234
01235 TQString result;
01236 result.setLength(outlen);
01237 for (uint i = 0; i < outlen; i++)
01238 result[i] = (unsigned int)ucs4_output[i];
01239
01240 delete [] ucs4_input;
01241 delete [] ucs4_output;
01242
01243 return result;
01244 #else
01245 return label;
01246 #endif
01247 }
01248
01249 #include "kresolver.moc"