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