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 input.
join(
".").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"