28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <sys/param.h>
34 #include <arpa/inet.h>
35 #include <netinet/in.h>
40 #include <tqapplication.h>
42 #include <tqcstring.h>
43 #include <tqstrlist.h>
44 #include <tqstringlist.h>
46 #include <tqdatetime.h>
49 #include <tqguardedptr.h>
60 #include "kresolver.h"
61 #include "kresolver_p.h"
62 #include "ksocketaddress.h"
66 TQMutex getXXbyYYmutex;
69 using namespace KNetwork;
70 using namespace KNetwork::Internal;
75 class KNetwork::KResolverEntryPrivate:
public TQShared
82 TQCString encodedName;
84 inline KResolverEntryPrivate() :
85 socktype(0), protocol(0)
97 const TQString& canonName,
const TQCString& encodedName) :
98 d(new KResolverEntryPrivate)
101 d->socktype = socktype;
103 d->canonName = canonName;
109 int protocol,
const TQString& canonName,
110 const TQCString& encodedName) :
111 d(new KResolverEntryPrivate)
114 d->socktype = socktype;
116 d->canonName = canonName;
146 return d ? d->addr.length() : 0;
152 return d ? d->addr.family() : AF_UNSPEC;
158 return d ? d->canonName : TQString::null;
164 return d ? d->encodedName : TQCString();
170 return d ? d->socktype : 0;
176 return d ? d->protocol : 0;
196 class KNetwork::KResolverResultsPrivate
199 TQString node, service;
200 int errorcode, syserror;
202 KResolverResultsPrivate() :
203 errorcode(0), syserror(0)
209 : d(new KResolverResultsPrivate)
215 : TQValueList<
KResolverEntry>(other), d(new KResolverResultsPrivate)
237 TQValueList<KResolverEntry>::operator =(other);
257 d->errorcode = errorcode;
258 d->syserror = systemerror;
275 const TQString& service)
278 d->service = service;
281 void KResolverResults::virtual_hook(
int,
void* )
288 TQStringList *KResolver::idnDomains = 0;
293 : TQObject(parent, name), d(new KResolverPrivate(this))
299 TQObject *parent,
const char *name)
300 : TQObject(parent, name), d(new KResolverPrivate(this, nodename, servicename))
332 return d->status > 0 && d->status < Success;
338 return d->input.node;
344 return d->input.service;
353 d->input.node = nodename;
355 d->results.setAddress(nodename, d->input.service);
365 d->input.service = service;
367 d->results.setAddress(d->input.node, service);
381 return d->input.flags;
387 int oldflags = d->input.flags;
390 d->input.flags =
flags;
401 d->input.familyMask = families;
411 d->input.socktype = type;
427 d->input.protocolName = name;
428 if (protonum == 0 && name != 0L && *name !=
'\0')
434 d->input.protocol = protonum;
445 if (d->input.node.isEmpty() && d->input.service.isEmpty())
447 d->status = KResolver::Success;
451 KResolverManager::manager()->enqueue(
this, 0L);
465 TQMutexLocker locker(&d->mutex);
482 while (!msec || t.elapsed() < msec)
487 KResolverManager::manager()->notifyWaiters.wait(&d->mutex, msec - t.elapsed());
489 KResolverManager::manager()->notifyWaiters.wait(&d->mutex);
510 KResolverManager::manager()->dequeue(
this);
523 r.
setAddress(d->input.node, d->input.service);
524 r.
setError(d->errorcode, d->syserror);
530 if (static_cast<int>(e->type()) == KResolverManager::ResolutionCompleted)
539 void KResolver::emitFinished()
542 d->status = KResolver::Success;
544 TQGuardedPtr<TQObject> p =
this;
548 if (p && d->deleteWhenDone)
555 static const char *
const messages[] =
557 I18N_NOOP(
"no error"),
558 I18N_NOOP(
"requested family not supported for this host name"),
559 I18N_NOOP(
"temporary failure in name resolution"),
560 I18N_NOOP(
"non-recoverable failure in name resolution"),
561 I18N_NOOP(
"invalid flags"),
562 I18N_NOOP(
"memory allocation failure"),
563 I18N_NOOP(
"name or service not known"),
564 I18N_NOOP(
"requested family not supported"),
565 I18N_NOOP(
"requested service not supported for this socket type"),
566 I18N_NOOP(
"requested socket type not supported"),
567 I18N_NOOP(
"unknown error"),
568 I18N_NOOP2(
"1: the i18n'ed system error code, from errno",
573 if (errorcode == Canceled)
574 return i18n(
"request was canceled");
576 if (errorcode > 0 || errorcode < SystemError)
577 return TQString::null;
579 TQString msg = i18n(messages[-errorcode]);
580 if (errorcode == SystemError)
581 msg.arg(TQString::fromLocal8Bit(strerror(syserror)));
590 KResolver qres(host, service, TQT_TQOBJECT(tqApp),
"synchronous KResolver");
599 const TQString& host,
const TQString& service,
600 int flags,
int families)
602 KResolver* qres =
new KResolver(host, service, TQT_TQOBJECT(tqApp),
"asynchronous KResolver");
606 qres->d->deleteWhenDone =
true;
607 return qres->
start();
612 struct protoent *pe = 0L;
613 #ifndef HAVE_GETPROTOBYNAME_R
614 TQMutexLocker locker(&getXXbyYYmutex);
616 pe = getprotobynumber(protonum);
619 size_t buflen = 1024;
620 struct protoent protobuf;
624 buf =
new char[buflen];
625 # ifdef USE_SOLARIS // Solaris uses a 4 argument getprotobynumber_r which returns struct *protoent or NULL
626 if ((pe = getprotobynumber_r(protonum, &protobuf, buf, buflen)) && (errno == ERANGE))
628 if (getprotobynumber_r(protonum, &protobuf, buf, buflen, &pe) == ERANGE)
645 lst.append(pe->p_name);
646 for (
char **p = pe->p_aliases; *p; p++)
650 #ifdef HAVE_GETPROTOBYNAME_R
659 struct protoent *pe = 0L;
660 #ifndef HAVE_GETPROTOBYNAME_R
661 TQMutexLocker locker(&getXXbyYYmutex);
663 pe = getprotobyname(protoname);
666 size_t buflen = 1024;
667 struct protoent protobuf;
671 buf =
new char[buflen];
672 # ifdef USE_SOLARIS // Solaris uses a 4 argument getprotobyname_r which returns struct *protoent or NULL
673 if ((pe = getprotobyname_r(protoname, &protobuf, buf, buflen)) && (errno == ERANGE))
675 if (getprotobyname_r(protoname, &protobuf, buf, buflen, &pe) == ERANGE)
692 lst.append(pe->p_name);
693 for (
char **p = pe->p_aliases; *p; p++)
697 #ifdef HAVE_GETPROTOBYNAME_R
706 struct protoent *pe = 0L;
707 #ifndef HAVE_GETPROTOBYNAME_R
708 TQMutexLocker locker(&getXXbyYYmutex);
710 pe = getprotobyname(protoname);
713 size_t buflen = 1024;
714 struct protoent protobuf;
718 buf =
new char[buflen];
719 # ifdef USE_SOLARIS // Solaris uses a 4 argument getprotobyname_r which returns struct *protoent or NULL
720 if ((pe = getprotobyname_r(protoname, &protobuf, buf, buflen)) && (errno == ERANGE))
722 if (getprotobyname_r(protoname, &protobuf, buf, buflen, &pe) == ERANGE)
738 protonum = pe->p_proto;
740 #ifdef HAVE_GETPROTOBYNAME_R
749 struct servent *se = 0L;
750 #ifndef HAVE_GETSERVBYNAME_R
751 TQMutexLocker locker(&getXXbyYYmutex);
753 se = getservbyname(servname, protoname);
756 size_t buflen = 1024;
757 struct servent servbuf;
761 buf =
new char[buflen];
762 # ifdef USE_SOLARIS // Solaris uses a 5 argument getservbyname_r which returns struct *servent or NULL
763 if ((se = getservbyname_r(servname, protoname, &servbuf, buf, buflen)) && (errno == ERANGE))
765 if (getservbyname_r(servname, protoname, &servbuf, buf, buflen, &se) == ERANGE)
781 servport = ntohs(se->s_port);
783 #ifdef HAVE_GETSERVBYNAME_R
792 struct servent *se = 0L;
793 #ifndef HAVE_GETSERVBYNAME_R
794 TQMutexLocker locker(&getXXbyYYmutex);
796 se = getservbyname(servname, protoname);
799 size_t buflen = 1024;
800 struct servent servbuf;
804 buf =
new char[buflen];
805 # ifdef USE_SOLARIS // Solaris uses a 5 argument getservbyname_r which returns struct *servent or NULL
806 if ((se = getservbyname_r(servname, protoname, &servbuf, buf, buflen)) && (errno == ERANGE))
808 if (getservbyname_r(servname, protoname, &servbuf, buf, buflen, &se) == ERANGE)
825 lst.append(se->s_name);
826 for (
char **p = se->s_aliases; *p; p++)
830 #ifdef HAVE_GETSERVBYNAME_R
839 struct servent *se = 0L;
840 #ifndef HAVE_GETSERVBYPORT_R
841 TQMutexLocker locker(&getXXbyYYmutex);
843 se = getservbyport(port, protoname);
846 size_t buflen = 1024;
847 struct servent servbuf;
851 buf =
new char[buflen];
852 # ifdef USE_SOLARIS // Solaris uses a 5 argument getservbyport_r which returns struct *servent or NULL
853 if ((se = getservbyport_r(port, protoname, &servbuf, buf, buflen)) && (errno == ERANGE))
855 if (getservbyport_r(port, protoname, &servbuf, buf, buflen, &se) == ERANGE)
872 lst.append(se->s_name);
873 for (
char **p = se->s_aliases; *p; p++)
877 #ifdef HAVE_GETSERVBYPORT_R
889 #ifdef MAXHOSTNAMELEN
890 len = MAXHOSTNAMELEN;
899 if (gethostname(name.data(), len - 1) == 0)
903 name[len - 1] =
'\0';
908 if (errno == ENAMETOOLONG || errno == EINVAL)
918 return TQString::fromLatin1(
"localhost");
920 if (name.find(
'.') == -1)
925 if (results.isEmpty())
927 return TQString::fromLatin1(
"localhost");
929 return results.first().canonicalName();
937 static TQStringList splitLabels(
const TQString& unicodeDomain);
938 static TQCString ToASCII(
const TQString& label);
939 static TQString ToUnicode(
const TQString& label);
941 static TQStringList *KResolver_initIdnDomains()
943 const char *kde_use_idn = getenv(
"KDE_USE_IDN");
945 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";
946 return new TQStringList(TQStringList::split(
':', TQString::fromLatin1(kde_use_idn).lower()));
953 idnDomains = KResolver_initIdnDomains();
961 TQStringList input = splitLabels(unicodeDomain);
964 if (input.count() && !idnDomains->contains(input[input.count()-1].lower()))
965 return input.join(
".").lower().latin1();
971 TQStringList::Iterator it = input.begin();
972 const TQStringList::Iterator end = input.end();
973 for ( ; it != end; ++it)
975 TQCString cs = ToASCII(*it);
980 if (!retval.isEmpty())
996 if (asciiDomain.isEmpty())
999 idnDomains = KResolver_initIdnDomains();
1009 TQStringList input = splitLabels(asciiDomain);
1012 if (input.count() && !idnDomains->contains(input[input.count()-1].lower()))
1013 return asciiDomain.lower();
1019 TQStringList::Iterator it;
1020 const TQStringList::Iterator end = input.end();
1021 for (it = input.begin(); it != end; ++it)
1023 TQString label = ToUnicode(*it).lower();
1026 if (!retval.isEmpty())
1039 void KResolver::virtual_hook(
int,
void* )
1051 static TQStringList splitLabels(
const TQString& unicodeDomain)
1058 static const unsigned int separators[] = { 0x002E, 0x3002, 0xFF0E, 0xFF61 };
1063 for (i = 0; i < unicodeDomain.length(); i++)
1065 unsigned int c = unicodeDomain[i].unicode();
1067 if (c == separators[0] ||
1068 c == separators[1] ||
1069 c == separators[2] ||
1073 lst << unicodeDomain.mid(start, i - start);
1077 if ((
long)i >= start)
1079 lst << unicodeDomain.mid(start, i - start);
1084 static TQCString ToASCII(
const TQString& label)
1090 if (label.length() > 64)
1093 if (label.length() == 0)
1095 return TQCString(
"");
1100 TQ_UINT32* ucs4 =
new TQ_UINT32[label.length() + 1];
1103 for (i = 0; i < label.length(); i++)
1104 ucs4[i] = (
unsigned long)label[i].unicode();
1107 if (idna_to_ascii_4i(ucs4, label.length(), buf, 0) == IDNA_SUCCESS)
1114 return label.latin1();
1118 static TQString ToUnicode(
const TQString& label)
1124 TQ_UINT32 *ucs4_input, *ucs4_output;
1127 ucs4_input =
new TQ_UINT32[label.length() + 1];
1128 for (uint i = 0; i < label.length(); i++)
1129 ucs4_input[i] = (
unsigned long)label[i].unicode();
1132 ucs4_output =
new TQ_UINT32[outlen = label.length()];
1134 idna_to_unicode_44i(ucs4_input, label.length(),
1135 ucs4_output, &outlen,
1138 if (outlen > label.length())
1141 delete [] ucs4_output;
1142 ucs4_output =
new TQ_UINT32[outlen];
1144 idna_to_unicode_44i(ucs4_input, label.length(),
1145 ucs4_output, &outlen,
1151 result.setLength(outlen);
1152 for (uint i = 0; i < outlen; i++)
1153 result[i] = (
unsigned int)ucs4_output[i];
1155 delete [] ucs4_input;
1156 delete [] ucs4_output;
1164 #include "kresolver.moc"