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