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 "tdesocketaddress.h"
66 TQMutex getXXbyYYmutex;
74 using namespace KNetwork::Internal;
79 class KNetwork::KResolverEntryPrivate:
public TQShared
86 TQCString encodedName;
88 inline KResolverEntryPrivate() :
89 socktype(0), protocol(0)
101 const TQString& canonName,
const TQCString& encodedName) :
102 d(new KResolverEntryPrivate)
105 d->socktype = socktype;
107 d->canonName = canonName;
113 int protocol,
const TQString& canonName,
114 const TQCString& encodedName) :
115 d(new KResolverEntryPrivate)
118 d->socktype = socktype;
120 d->canonName = canonName;
150 return d ? d->addr.length() : 0;
156 return d ? d->addr.family() : AF_UNSPEC;
162 return d ? d->canonName : TQString::null;
168 return d ? d->encodedName : TQCString();
174 return d ? d->socktype : 0;
180 return d ? d->protocol : 0;
200 class KNetwork::KResolverResultsPrivate
203 TQString node, service;
204 int errorcode, syserror;
206 KResolverResultsPrivate() :
207 errorcode(0), syserror(0)
213 : d(new KResolverResultsPrivate)
219 : TQValueList<
KResolverEntry>(other), d(new KResolverResultsPrivate)
241 TQValueList<KResolverEntry>::operator =(other);
261 d->errorcode = errorcode;
262 d->syserror = systemerror;
279 const TQString& service)
282 d->service = service;
285 void KResolverResults::virtual_hook(
int,
void* )
292 TQStringList *KResolver::idnDomains = 0;
297 : TQObject(parent, name), d(new KResolverPrivate(this))
303 TQObject *parent,
const char *name)
304 : TQObject(parent, name), d(new KResolverPrivate(this, nodename, servicename))
336 return d->status > 0 && d->status < Success;
342 return d->input.node;
348 return d->input.service;
357 d->input.node = nodename;
359 d->results.setAddress(nodename, d->input.service);
369 d->input.service = service;
371 d->results.setAddress(d->input.node, service);
385 return d->input.flags;
391 int oldflags = d->input.flags;
394 d->input.flags =
flags;
405 d->input.familyMask = families;
415 d->input.socktype = type;
431 d->input.protocolName = name;
432 if (protonum == 0 && name != 0L && *name !=
'\0')
438 d->input.protocol = protonum;
449 if (d->input.node.isEmpty() && d->input.service.isEmpty())
451 d->status = KResolver::Success;
455 KResolverManager::manager()->enqueue(
this, 0L);
469 TQMutexLocker locker(&d->mutex);
486 while (!msec || t.elapsed() < msec)
491 KResolverManager::manager()->notifyWaiters.wait(&d->mutex, msec - t.elapsed());
493 KResolverManager::manager()->notifyWaiters.wait(&d->mutex);
514 KResolverManager::manager()->dequeue(
this);
527 r.
setAddress(d->input.node, d->input.service);
528 r.
setError(d->errorcode, d->syserror);
534 if (
static_cast<int>(e->type()) == KResolverManager::ResolutionCompleted)
543 void KResolver::emitFinished()
546 d->status = KResolver::Success;
548 TQGuardedPtr<TQObject> p =
this;
552 if (p && d->deleteWhenDone)
559 static const char *
const messages[] =
561 I18N_NOOP(
"no error"),
562 I18N_NOOP(
"requested family not supported for this host name"),
563 I18N_NOOP(
"temporary failure in name resolution"),
564 I18N_NOOP(
"non-recoverable failure in name resolution"),
565 I18N_NOOP(
"invalid flags"),
566 I18N_NOOP(
"memory allocation failure"),
567 I18N_NOOP(
"name or service not known"),
568 I18N_NOOP(
"requested family not supported"),
569 I18N_NOOP(
"requested service not supported for this socket type"),
570 I18N_NOOP(
"requested socket type not supported"),
571 I18N_NOOP(
"unknown error"),
572 I18N_NOOP2(
"1: the i18n'ed system error code, from errno",
577 if (errorcode == Canceled)
578 return i18n(
"request was canceled");
580 if (errorcode > 0 || errorcode < SystemError)
581 return TQString::null;
583 TQString msg = i18n(messages[-errorcode]);
584 if (errorcode == SystemError)
585 msg.arg(TQString::fromLocal8Bit(strerror(syserror)));
594 KResolver qres(host, service, TQT_TQOBJECT(tqApp),
"synchronous KResolver");
603 const TQString& host,
const TQString& service,
604 int flags,
int families)
606 KResolver* qres =
new KResolver(host, service, TQT_TQOBJECT(tqApp),
"asynchronous KResolver");
610 qres->d->deleteWhenDone =
true;
611 return qres->
start();
616 struct protoent *pe = 0L;
617 #ifndef HAVE_GETPROTOBYNAME_R
618 TQMutexLocker locker(&getXXbyYYmutex);
620 pe = getprotobynumber(protonum);
623 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API
624 struct protoent protobuf;
625 struct protoent_data pdata;
626 ::memset(&pdata, 0,
sizeof pdata);
628 if (getprotobynumber_r(protonum, &protobuf, &pdata) == 0)
634 size_t buflen = 1024;
635 struct protoent protobuf;
639 buf =
new char[buflen];
640 # ifdef USE_SOLARIS // Solaris uses a 4 argument getprotobynumber_r which returns struct *protoent or NULL
641 if ((pe = getprotobynumber_r(protonum, &protobuf, buf, buflen)) && (errno == ERANGE))
643 if (getprotobynumber_r(protonum, &protobuf, buf, buflen, &pe) == ERANGE)
661 lst.append(pe->p_name);
662 for (
char **p = pe->p_aliases; *p; p++)
666 #ifdef HAVE_GETPROTOBYNAME_R
677 struct protoent *pe = 0L;
678 #ifndef HAVE_GETPROTOBYNAME_R
679 TQMutexLocker locker(&getXXbyYYmutex);
681 pe = getprotobyname(protoname);
684 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API
685 struct protoent protobuf;
686 struct protoent_data pdata;
687 ::memset(&pdata, 0,
sizeof pdata);
689 if (getprotobyname_r(protoname, &protobuf, &pdata) == 0)
695 size_t buflen = 1024;
696 struct protoent protobuf;
700 buf =
new char[buflen];
701 # ifdef USE_SOLARIS // Solaris uses a 4 argument getprotobyname_r which returns struct *protoent or NULL
702 if ((pe = getprotobyname_r(protoname, &protobuf, buf, buflen)) && (errno == ERANGE))
704 if (getprotobyname_r(protoname, &protobuf, buf, buflen, &pe) == ERANGE)
722 lst.append(pe->p_name);
723 for (
char **p = pe->p_aliases; *p; p++)
727 #ifdef HAVE_GETPROTOBYNAME_R
738 struct protoent *pe = 0L;
739 #ifndef HAVE_GETPROTOBYNAME_R
740 TQMutexLocker locker(&getXXbyYYmutex);
742 pe = getprotobyname(protoname);
745 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API
746 struct protoent protobuf;
747 struct protoent_data pdata;
748 ::memset(&pdata, 0,
sizeof pdata);
750 if (getprotobyname_r(protoname, &protobuf, &pdata) == 0)
756 size_t buflen = 1024;
757 struct protoent protobuf;
761 buf =
new char[buflen];
762 # ifdef USE_SOLARIS // Solaris uses a 4 argument getprotobyname_r which returns struct *protoent or NULL
763 if ((pe = getprotobyname_r(protoname, &protobuf, buf, buflen)) && (errno == ERANGE))
765 if (getprotobyname_r(protoname, &protobuf, buf, buflen, &pe) == ERANGE)
782 protonum = pe->p_proto;
784 #ifdef HAVE_GETPROTOBYNAME_R
795 struct servent *se = 0L;
796 #ifndef HAVE_GETSERVBYNAME_R
797 TQMutexLocker locker(&getXXbyYYmutex);
799 se = getservbyname(servname, protoname);
802 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API
803 struct servent servbuf;
804 struct servent_data sdata;
805 ::memset(&sdata, 0,
sizeof sdata);
806 if (getservbyname_r(servname, protoname, &servbuf, &sdata) == 0)
812 size_t buflen = 1024;
813 struct servent servbuf;
817 buf =
new char[buflen];
818 # ifdef USE_SOLARIS // Solaris uses a 5 argument getservbyname_r which returns struct *servent or NULL
819 if ((se = getservbyname_r(servname, protoname, &servbuf, buf, buflen)) && (errno == ERANGE))
821 if (getservbyname_r(servname, protoname, &servbuf, buf, buflen, &se) == ERANGE)
838 servport = ntohs(se->s_port);
840 #ifdef HAVE_GETSERVBYNAME_R
851 struct servent *se = 0L;
852 #ifndef HAVE_GETSERVBYNAME_R
853 TQMutexLocker locker(&getXXbyYYmutex);
855 se = getservbyname(servname, protoname);
858 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API
859 struct servent servbuf;
860 struct servent_data sdata;
861 ::memset(&sdata, 0,
sizeof sdata);
862 if (getservbyname_r(servname, protoname, &servbuf, &sdata) == 0)
868 size_t buflen = 1024;
869 struct servent servbuf;
873 buf =
new char[buflen];
874 # ifdef USE_SOLARIS // Solaris uses a 5 argument getservbyname_r which returns struct *servent or NULL
875 if ((se = getservbyname_r(servname, protoname, &servbuf, buf, buflen)) && (errno == ERANGE))
877 if (getservbyname_r(servname, protoname, &servbuf, buf, buflen, &se) == ERANGE)
895 lst.append(se->s_name);
896 for (
char **p = se->s_aliases; *p; p++)
900 #ifdef HAVE_GETSERVBYNAME_R
911 struct servent *se = 0L;
912 #ifndef HAVE_GETSERVBYPORT_R
913 TQMutexLocker locker(&getXXbyYYmutex);
915 se = getservbyport(port, protoname);
918 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API
919 struct servent servbuf;
920 struct servent_data sdata;
921 ::memset(&sdata, 0,
sizeof sdata);
922 if (getservbyport_r(port, protoname, &servbuf, &sdata) == 0)
928 size_t buflen = 1024;
929 struct servent servbuf;
933 buf =
new char[buflen];
934 # ifdef USE_SOLARIS // Solaris uses a 5 argument getservbyport_r which returns struct *servent or NULL
935 if ((se = getservbyport_r(port, protoname, &servbuf, buf, buflen)) && (errno == ERANGE))
937 if (getservbyport_r(port, protoname, &servbuf, buf, buflen, &se) == ERANGE)
955 lst.append(se->s_name);
956 for (
char **p = se->s_aliases; *p; p++)
960 #ifdef HAVE_GETSERVBYPORT_R
974 #ifdef MAXHOSTNAMELEN
975 len = MAXHOSTNAMELEN;
984 if (gethostname(name.data(), len - 1) == 0)
988 name[len - 1] =
'\0';
993 if (errno == ENAMETOOLONG || errno == EINVAL)
1003 return TQString::fromLatin1(
"localhost");
1005 if (name.find(
'.') == -1)
1012 return TQString::fromLatin1(
"localhost");
1014 return results.first().canonicalName();
1022 static TQStringList splitLabels(
const TQString& unicodeDomain);
1023 static TQCString ToASCII(
const TQString& label);
1024 static TQString ToUnicode(
const TQString& label);
1026 static TQStringList *KResolver_initIdnDomains()
1028 const char *kde_use_idn = getenv(
"TDE_USE_IDN");
1030 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";
1031 return new TQStringList(TQStringList::split(
':', TQString::fromLatin1(kde_use_idn).lower()));
1038 idnDomains = KResolver_initIdnDomains();
1046 TQStringList input = splitLabels(unicodeDomain);
1049 if (input.count() && !idnDomains->contains(input[input.count()-1].lower()))
1050 return input.join(
".").lower().latin1();
1056 TQStringList::Iterator it = input.begin();
1057 const TQStringList::Iterator end = input.end();
1058 for ( ; it != end; ++it)
1060 TQCString cs = ToASCII(*it);
1065 if (!retval.isEmpty())
1081 if (asciiDomain.isEmpty())
1084 idnDomains = KResolver_initIdnDomains();
1094 TQStringList input = splitLabels(asciiDomain);
1097 if (input.count() && !idnDomains->contains(input[input.count()-1].lower()))
1098 return asciiDomain.lower();
1104 TQStringList::Iterator it;
1105 const TQStringList::Iterator end = input.end();
1106 for (it = input.begin(); it != end; ++it)
1108 TQString label = ToUnicode(*it).lower();
1111 if (!retval.isEmpty())
1124 void KResolver::virtual_hook(
int,
void* )
1136 static TQStringList splitLabels(
const TQString& unicodeDomain)
1143 static const unsigned int separators[] = { 0x002E, 0x3002, 0xFF0E, 0xFF61 };
1148 for (i = 0; i < unicodeDomain.length(); i++)
1150 unsigned int c = unicodeDomain[i].unicode();
1152 if (c == separators[0] ||
1153 c == separators[1] ||
1154 c == separators[2] ||
1158 lst << unicodeDomain.mid(start, i - start);
1162 if ((
long)i >= start)
1164 lst << unicodeDomain.mid(start, i - start);
1169 static TQCString ToASCII(
const TQString& label)
1175 if (
label.length() > 64)
1178 if (
label.length() == 0)
1180 return TQCString(
"");
1185 TQ_UINT32* ucs4 =
new TQ_UINT32[
label.length() + 1];
1188 for (i = 0; i <
label.length(); i++)
1189 ucs4[i] = (
unsigned long)
label[i].unicode();
1192 if (idna_to_ascii_4i(ucs4,
label.length(), buf, 0) == IDNA_SUCCESS)
1199 return label.latin1();
1203 static TQString ToUnicode(
const TQString& label)
1209 TQ_UINT32 *ucs4_input, *ucs4_output;
1212 ucs4_input =
new TQ_UINT32[
label.length() + 1];
1213 for (uint i = 0; i <
label.length(); i++)
1214 ucs4_input[i] = (
unsigned long)
label[i].unicode();
1217 ucs4_output =
new TQ_UINT32[outlen =
label.length()];
1219 idna_to_unicode_44i(ucs4_input,
label.length(),
1220 ucs4_output, &outlen,
1223 if (outlen >
label.length())
1226 delete [] ucs4_output;
1227 ucs4_output =
new TQ_UINT32[outlen];
1229 idna_to_unicode_44i(ucs4_input,
label.length(),
1230 ucs4_output, &outlen,
1236 result.setLength(outlen);
1237 for (uint i = 0; i < outlen; i++)
1238 result[i] = (
unsigned int)ucs4_output[i];
1240 delete [] ucs4_input;
1241 delete [] ucs4_output;
1249 #include "kresolver.moc"