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 return true;
00467 else
00468 {
00469 QTime t;
00470 t.start();
00471
00472 while (!msec || t.elapsed() < msec)
00473 {
00474
00475 d->waiting = true;
00476 if (msec)
00477 KResolverManager::manager()->notifyWaiters.wait(&d->mutex, msec - t.elapsed());
00478 else
00479 KResolverManager::manager()->notifyWaiters.wait(&d->mutex);
00480
00481
00482
00483 if (!isRunning())
00484 {
00485
00486 d->waiting = false;
00487 emitFinished();
00488 return true;
00489 }
00490 }
00491
00492
00493 d->waiting = false;
00494 return false;
00495 }
00496 }
00497
00498 void KResolver::cancel(bool emitSignal)
00499 {
00500 KResolverManager::manager()->dequeue(this);
00501 if (emitSignal)
00502 emitFinished();
00503 }
00504
00505 KResolverResults
00506 KResolver::results() const
00507 {
00508 if (!isRunning())
00509 return d->results;
00510
00511
00512 KResolverResults r;
00513 r.setAddress(d->input.node, d->input.service);
00514 r.setError(d->errorcode, d->syserror);
00515 return r;
00516 }
00517
00518 bool KResolver::event(QEvent* e)
00519 {
00520 if (static_cast<int>(e->type()) == KResolverManager::ResolutionCompleted)
00521 {
00522 emitFinished();
00523 return true;
00524 }
00525
00526 return false;
00527 }
00528
00529 void KResolver::emitFinished()
00530 {
00531 if (isRunning())
00532 d->status = KResolver::Success;
00533
00534 QGuardedPtr<QObject> p = this;
00535
00536 emit finished(d->results);
00537
00538 if (p && d->deleteWhenDone)
00539 deleteLater();
00540 }
00541
00542 QString KResolver::errorString(int errorcode, int syserror)
00543 {
00544
00545 static const char * const messages[] =
00546 {
00547 I18N_NOOP("no error"),
00548 I18N_NOOP("requested family not supported for this host name"),
00549 I18N_NOOP("temporary failure in name resolution"),
00550 I18N_NOOP("non-recoverable failure in name resolution"),
00551 I18N_NOOP("invalid flags"),
00552 I18N_NOOP("memory allocation failure"),
00553 I18N_NOOP("name or service not known"),
00554 I18N_NOOP("requested family not supported"),
00555 I18N_NOOP("requested service not supported for this socket type"),
00556 I18N_NOOP("requested socket type not supported"),
00557 I18N_NOOP("unknown error"),
00558 I18N_NOOP2("1: the i18n'ed system error code, from errno",
00559 "system error: %1")
00560 };
00561
00562
00563 if (errorcode == Canceled)
00564 return i18n("request was canceled");
00565
00566 if (errorcode > 0 || errorcode < SystemError)
00567 return QString::null;
00568
00569 QString msg = i18n(messages[-errorcode]);
00570 if (errorcode == SystemError)
00571 msg.arg(QString::fromLocal8Bit(strerror(syserror)));
00572
00573 return msg;
00574 }
00575
00576 KResolverResults
00577 KResolver::resolve(const QString& host, const QString& service, int flags,
00578 int families)
00579 {
00580 KResolver qres(host, service, qApp, "synchronous KResolver");
00581 qres.setFlags(flags);
00582 qres.setFamily(families);
00583 qres.start();
00584 qres.wait();
00585 return qres.results();
00586 }
00587
00588 bool KResolver::resolveAsync(QObject* userObj, const char *userSlot,
00589 const QString& host, const QString& service,
00590 int flags, int families)
00591 {
00592 KResolver* qres = new KResolver(host, service, qApp, "asynchronous KResolver");
00593 QObject::connect(qres, SIGNAL(finished(KResolverResults)), userObj, userSlot);
00594 qres->setFlags(flags);
00595 qres->setFamily(families);
00596 qres->d->deleteWhenDone = true;
00597 return qres->start();
00598 }
00599
00600 QStrList KResolver::protocolName(int protonum)
00601 {
00602 struct protoent *pe;
00603 #ifndef HAVE_GETPROTOBYNAME_R
00604 QMutexLocker locker(&getXXbyYYmutex);
00605
00606 pe = getprotobynumber(protonum);
00607
00608 #else
00609 size_t buflen = 1024;
00610 struct protoent protobuf;
00611 char *buf;
00612 do
00613 {
00614 buf = new char[buflen];
00615 # ifdef USE_SOLARIS // Solaris uses a 4 argument getprotobynumber_r which returns struct *protoent or NULL
00616 if ((pe = getprotobynumber_r(protonum, &protobuf, buf, buflen)) && (errno == ERANGE))
00617 # else
00618 if (getprotobynumber_r(protonum, &protobuf, buf, buflen, &pe) == ERANGE)
00619 # endif
00620 {
00621 buflen += 1024;
00622 delete [] buf;
00623 }
00624 else
00625 break;
00626 }
00627 while (pe == 0L);
00628 #endif
00629
00630
00631 QStrList lst(true);
00632 if (pe != NULL)
00633 {
00634 lst.append(pe->p_name);
00635 for (char **p = pe->p_aliases; *p; p++)
00636 lst.append(*p);
00637 }
00638
00639 #ifdef HAVE_GETPROTOBYNAME_R
00640 delete [] buf;
00641 #endif
00642
00643 return lst;
00644 }
00645
00646 QStrList KResolver::protocolName(const char *protoname)
00647 {
00648 struct protoent *pe;
00649 #ifndef HAVE_GETPROTOBYNAME_R
00650 QMutexLocker locker(&getXXbyYYmutex);
00651
00652 pe = getprotobyname(protoname);
00653
00654 #else
00655 size_t buflen = 1024;
00656 struct protoent protobuf;
00657 char *buf;
00658 do
00659 {
00660 buf = new char[buflen];
00661 # ifdef USE_SOLARIS // Solaris uses a 4 argument getprotobyname_r which returns struct *protoent or NULL
00662 if ((pe = getprotobyname_r(protoname, &protobuf, buf, buflen)) && (errno == ERANGE))
00663 # else
00664 if (getprotobyname_r(protoname, &protobuf, buf, buflen, &pe) == ERANGE)
00665 # endif
00666 {
00667 buflen += 1024;
00668 delete [] buf;
00669 }
00670 else
00671 break;
00672 }
00673 while (pe == 0L);
00674 #endif
00675
00676
00677 QStrList lst(true);
00678 if (pe != NULL)
00679 {
00680 lst.append(pe->p_name);
00681 for (char **p = pe->p_aliases; *p; p++)
00682 lst.append(*p);
00683 }
00684
00685 #ifdef HAVE_GETPROTOBYNAME_R
00686 delete [] buf;
00687 #endif
00688
00689 return lst;
00690 }
00691
00692 int KResolver::protocolNumber(const char *protoname)
00693 {
00694 struct protoent *pe;
00695 #ifndef HAVE_GETPROTOBYNAME_R
00696 QMutexLocker locker(&getXXbyYYmutex);
00697
00698 pe = getprotobyname(protoname);
00699
00700 #else
00701 size_t buflen = 1024;
00702 struct protoent protobuf;
00703 char *buf;
00704 do
00705 {
00706 buf = new char[buflen];
00707 # ifdef USE_SOLARIS // Solaris uses a 4 argument getprotobyname_r which returns struct *protoent or NULL
00708 if ((pe = getprotobyname_r(protoname, &protobuf, buf, buflen)) && (errno == ERANGE))
00709 # else
00710 if (getprotobyname_r(protoname, &protobuf, buf, buflen, &pe) == ERANGE)
00711 # endif
00712 {
00713 buflen += 1024;
00714 delete [] buf;
00715 }
00716 else
00717 break;
00718 }
00719 while (pe == 0L);
00720 #endif
00721
00722
00723 int protonum = -1;
00724 if (pe != NULL)
00725 protonum = pe->p_proto;
00726
00727 #ifdef HAVE_GETPROTOBYNAME_R
00728 delete [] buf;
00729 #endif
00730
00731 return protonum;
00732 }
00733
00734 int KResolver::servicePort(const char *servname, const char *protoname)
00735 {
00736 struct servent *se;
00737 #ifndef HAVE_GETSERVBYNAME_R
00738 QMutexLocker locker(&getXXbyYYmutex);
00739
00740 se = getservbyname(servname, protoname);
00741
00742 #else
00743 size_t buflen = 1024;
00744 struct servent servbuf;
00745 char *buf;
00746 do
00747 {
00748 buf = new char[buflen];
00749 # ifdef USE_SOLARIS // Solaris uses a 5 argument getservbyname_r which returns struct *servent or NULL
00750 if ((se = getservbyname_r(servname, protoname, &servbuf, buf, buflen)) && (errno == ERANGE))
00751 # else
00752 if (getservbyname_r(servname, protoname, &servbuf, buf, buflen, &se) == ERANGE)
00753 # endif
00754 {
00755 buflen += 1024;
00756 delete [] buf;
00757 }
00758 else
00759 break;
00760 }
00761 while (se == 0L);
00762 #endif
00763
00764
00765 int servport = -1;
00766 if (se != NULL)
00767 servport = ntohs(se->s_port);
00768
00769 #ifdef HAVE_GETSERVBYNAME_R
00770 delete [] buf;
00771 #endif
00772
00773 return servport;
00774 }
00775
00776 QStrList KResolver::serviceName(const char* servname, const char *protoname)
00777 {
00778 struct servent *se;
00779 #ifndef HAVE_GETSERVBYNAME_R
00780 QMutexLocker locker(&getXXbyYYmutex);
00781
00782 se = getservbyname(servname, protoname);
00783
00784 #else
00785 size_t buflen = 1024;
00786 struct servent servbuf;
00787 char *buf;
00788 do
00789 {
00790 buf = new char[buflen];
00791 # ifdef USE_SOLARIS // Solaris uses a 5 argument getservbyname_r which returns struct *servent or NULL
00792 if ((se = getservbyname_r(servname, protoname, &servbuf, buf, buflen)) && (errno == ERANGE))
00793 # else
00794 if (getservbyname_r(servname, protoname, &servbuf, buf, buflen, &se) == ERANGE)
00795 # endif
00796 {
00797 buflen += 1024;
00798 delete [] buf;
00799 }
00800 else
00801 break;
00802 }
00803 while (se == 0L);
00804 #endif
00805
00806
00807 QStrList lst(true);
00808 if (se != NULL)
00809 {
00810 lst.append(se->s_name);
00811 for (char **p = se->s_aliases; *p; p++)
00812 lst.append(*p);
00813 }
00814
00815 #ifdef HAVE_GETSERVBYNAME_R
00816 delete [] buf;
00817 #endif
00818
00819 return lst;
00820 }
00821
00822 QStrList KResolver::serviceName(int port, const char *protoname)
00823 {
00824 struct servent *se;
00825 #ifndef HAVE_GETSERVBYPORT_R
00826 QMutexLocker locker(&getXXbyYYmutex);
00827
00828 se = getservbyport(port, protoname);
00829
00830 #else
00831 size_t buflen = 1024;
00832 struct servent servbuf;
00833 char *buf;
00834 do
00835 {
00836 buf = new char[buflen];
00837 # ifdef USE_SOLARIS // Solaris uses a 5 argument getservbyport_r which returns struct *servent or NULL
00838 if ((se = getservbyport_r(port, protoname, &servbuf, buf, buflen)) && (errno == ERANGE))
00839 # else
00840 if (getservbyport_r(port, protoname, &servbuf, buf, buflen, &se) == ERANGE)
00841 # endif
00842 {
00843 buflen += 1024;
00844 delete [] buf;
00845 }
00846 else
00847 break;
00848 }
00849 while (se == 0L);
00850 #endif
00851
00852
00853 QStrList lst(true);
00854 if (se != NULL)
00855 {
00856 lst.append(se->s_name);
00857 for (char **p = se->s_aliases; *p; p++)
00858 lst.append(*p);
00859 }
00860
00861 #ifdef HAVE_GETSERVBYPORT_R
00862 delete [] buf;
00863 #endif
00864
00865 return lst;
00866 }
00867
00868
00869 static QStringList splitLabels(const QString& unicodeDomain);
00870 static QCString ToASCII(const QString& label);
00871 static QString ToUnicode(const QString& label);
00872
00873 static QStringList *KResolver_initIdnDomains()
00874 {
00875 const char *kde_use_idn = getenv("KDE_USE_IDN");
00876 if (!kde_use_idn)
00877 kde_use_idn = "at:ch:cn:de:dk:kr:jp:li:no:se:tw";
00878 return new QStringList(QStringList::split(':', QString::fromLatin1(kde_use_idn).lower()));
00879 }
00880
00881
00882 QCString KResolver::domainToAscii(const QString& unicodeDomain)
00883 {
00884 if (!idnDomains)
00885 idnDomains = KResolver_initIdnDomains();
00886
00887 QCString retval;
00888
00889
00890
00891
00892
00893 QStringList input = splitLabels(unicodeDomain);
00894
00895
00896 if (input.count() && !idnDomains->contains(input[input.count()-1].lower()))
00897 return unicodeDomain.lower().latin1();
00898
00899
00900
00901
00902
00903 QStringList::Iterator it = input.begin();
00904 const QStringList::Iterator end = input.end();
00905 for ( ; it != end; ++it)
00906 {
00907 QCString cs = ToASCII(*it);
00908 if (cs.isNull())
00909 return QCString();
00910
00911
00912 if (!retval.isEmpty())
00913 retval += '.';
00914 retval += cs;
00915 }
00916
00917 return retval;
00918 }
00919
00920 QString KResolver::domainToUnicode(const QCString& asciiDomain)
00921 {
00922 return domainToUnicode(QString::fromLatin1(asciiDomain));
00923 }
00924
00925
00926 QString KResolver::domainToUnicode(const QString& asciiDomain)
00927 {
00928 if (asciiDomain.isEmpty())
00929 return asciiDomain;
00930 if (!idnDomains)
00931 idnDomains = KResolver_initIdnDomains();
00932
00933 QString retval;
00934
00935
00936
00937
00938
00939
00940
00941 QStringList input = splitLabels(asciiDomain);
00942
00943
00944 if (input.count() && !idnDomains->contains(input[input.count()-1].lower()))
00945 return asciiDomain.lower();
00946
00947
00948
00949
00950
00951 QStringList::Iterator it;
00952 const QStringList::Iterator end = input.end();
00953 for (it = input.begin(); it != end; ++it)
00954 {
00955 QString label = ToUnicode(*it).lower();
00956
00957
00958 if (!retval.isEmpty())
00959 retval += '.';
00960 retval += label;
00961 }
00962
00963 return retval;
00964 }
00965
00966 QString KResolver::normalizeDomain(const QString& domain)
00967 {
00968 return domainToUnicode(domainToAscii(domain));
00969 }
00970
00971 void KResolver::virtual_hook( int, void* )
00972 { }
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983 static QStringList splitLabels(const QString& unicodeDomain)
00984 {
00985
00986
00987
00988
00989
00990 static const unsigned int separators[] = { 0x002E, 0x3002, 0xFF0E, 0xFF61 };
00991
00992 QStringList lst;
00993 int start = 0;
00994 uint i;
00995 for (i = 0; i < unicodeDomain.length(); i++)
00996 {
00997 unsigned int c = unicodeDomain[i].unicode();
00998
00999 if (c == separators[0] ||
01000 c == separators[1] ||
01001 c == separators[2] ||
01002 c == separators[3])
01003 {
01004
01005 lst << unicodeDomain.mid(start, i - start);
01006 start = i + 1;
01007 }
01008 }
01009 if ((long)i >= start)
01010
01011 lst << unicodeDomain.mid(start, i - start);
01012
01013 return lst;
01014 }
01015
01016 static QCString ToASCII(const QString& label)
01017 {
01018 #ifdef HAVE_IDNA_H
01019
01020
01021
01022 if (label.length() > 64)
01023 return (char*)0L;
01024
01025 if (label.length() == 0)
01026
01027 return QCString("");
01028
01029 QCString retval;
01030 char buf[65];
01031
01032 Q_UINT32* ucs4 = new Q_UINT32[label.length() + 1];
01033
01034 uint i;
01035 for (i = 0; i < label.length(); i++)
01036 ucs4[i] = (unsigned long)label[i].unicode();
01037 ucs4[i] = 0;
01038
01039 if (idna_to_ascii_4i(ucs4, label.length(), buf, 0) == IDNA_SUCCESS)
01040
01041 retval = buf;
01042
01043 delete [] ucs4;
01044 return retval;
01045 #else
01046 return label.latin1();
01047 #endif
01048 }
01049
01050 static QString ToUnicode(const QString& label)
01051 {
01052 #ifdef HAVE_IDNA_H
01053
01054
01055
01056 Q_UINT32 *ucs4_input, *ucs4_output;
01057 size_t outlen;
01058
01059 ucs4_input = new Q_UINT32[label.length() + 1];
01060 for (uint i = 0; i < label.length(); i++)
01061 ucs4_input[i] = (unsigned long)label[i].unicode();
01062
01063
01064 ucs4_output = new Q_UINT32[outlen = label.length()];
01065
01066 idna_to_unicode_44i(ucs4_input, label.length(),
01067 ucs4_output, &outlen,
01068 0);
01069
01070 if (outlen > label.length())
01071 {
01072
01073 delete [] ucs4_output;
01074 ucs4_output = new Q_UINT32[outlen];
01075
01076 idna_to_unicode_44i(ucs4_input, label.length(),
01077 ucs4_output, &outlen,
01078 0);
01079 }
01080
01081
01082 QString result;
01083 result.setLength(outlen);
01084 for (uint i = 0; i < outlen; i++)
01085 result[i] = (unsigned int)ucs4_output[i];
01086
01087 delete [] ucs4_input;
01088 delete [] ucs4_output;
01089
01090 return result;
01091 #else
01092 return label;
01093 #endif
01094 }
01095
01096 #include "kresolver.moc"