• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdecore
 

tdecore

  • tdecore
  • network
kresolver.cpp
1/*
2 * Copyright (C) 2003-2005 Thiago Macieira <thiago.macieira@kdemail.net>
3 *
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25#include "config.h"
26
27// System includes
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <sys/param.h>
31#include <errno.h>
32#include <netdb.h>
33#include <time.h>
34#include <arpa/inet.h>
35#include <netinet/in.h>
36#include <stdlib.h>
37#include <unistd.h>
38
39// Qt includes
40#include <tqapplication.h>
41#include <tqstring.h>
42#include <tqcstring.h>
43#include <tqstrlist.h>
44#include <tqstringlist.h>
45#include <tqshared.h>
46#include <tqdatetime.h>
47#include <tqtimer.h>
48#include <tqmutex.h>
49#include <tqguardedptr.h>
50
51// IDN
52#ifdef HAVE_IDNA_H
53# include <idna.h>
54#endif
55
56// KDE
57#include <tdelocale.h>
58
59// Us
60#include "kresolver.h"
61#include "kresolver_p.h"
62#include "tdesocketaddress.h"
63
64#ifdef NEED_MUTEX
65#warning "mutex"
66TQMutex getXXbyYYmutex;
67#endif
68
69#ifdef __OpenBSD__
70#define USE_OPENBSD 1
71#endif
72
73using namespace KNetwork;
74using namespace KNetwork::Internal;
75
77// class KResolverEntry
78
79class KNetwork::KResolverEntryPrivate: public TQShared
80{
81public:
82 TDESocketAddress addr;
83 int socktype;
84 int protocol;
85 TQString canonName;
86 TQCString encodedName;
87
88 inline KResolverEntryPrivate() :
89 socktype(0), protocol(0)
90 { }
91};
92
93// default constructor
94KResolverEntry::KResolverEntry() :
95 d(0L)
96{
97}
98
99// constructor with stuff
100KResolverEntry::KResolverEntry(const TDESocketAddress& addr, int socktype, int protocol,
101 const TQString& canonName, const TQCString& encodedName) :
102 d(new KResolverEntryPrivate)
103{
104 d->addr = addr;
105 d->socktype = socktype;
106 d->protocol = protocol;
107 d->canonName = canonName;
108 d->encodedName = encodedName;
109}
110
111// constructor with even more stuff
112KResolverEntry::KResolverEntry(const struct sockaddr* sa, TQ_UINT16 salen, int socktype,
113 int protocol, const TQString& canonName,
114 const TQCString& encodedName) :
115 d(new KResolverEntryPrivate)
116{
117 d->addr = TDESocketAddress(sa, salen);
118 d->socktype = socktype;
119 d->protocol = protocol;
120 d->canonName = canonName;
121 d->encodedName = encodedName;
122}
123
124// copy constructor
125KResolverEntry::KResolverEntry(const KResolverEntry& that) :
126 d(0L)
127{
128 *this = that;
129}
130
131// destructor
132KResolverEntry::~KResolverEntry()
133{
134 if (d == 0L)
135 return;
136
137 if (d->deref())
138 delete d;
139}
140
141// returns the socket address
142TDESocketAddress KResolverEntry::address() const
143{
144 return d ? d->addr : TDESocketAddress();
145}
146
147// returns the length
148TQ_UINT16 KResolverEntry::length() const
149{
150 return d ? d->addr.length() : 0;
151}
152
153// returns the family
154int KResolverEntry::family() const
155{
156 return d ? d->addr.family() : AF_UNSPEC;
157}
158
159// returns the canonical name
160TQString KResolverEntry::canonicalName() const
161{
162 return d ? d->canonName : TQString::null;
163}
164
165// returns the encoded name
166TQCString KResolverEntry::encodedName() const
167{
168 return d ? d->encodedName : TQCString();
169}
170
171// returns the socket type
172int KResolverEntry::socketType() const
173{
174 return d ? d->socktype : 0;
175}
176
177// returns the protocol
178int KResolverEntry::protocol() const
179{
180 return d ? d->protocol : 0;
181}
182
183// assignment operator
184KResolverEntry& KResolverEntry::operator= (const KResolverEntry& that)
185{
186 // copy the data
187 if (that.d)
188 that.d->ref();
189
190 if (d && d->deref())
191 delete d;
192
193 d = that.d;
194 return *this;
195}
196
198// class KResolverResults
199
200class KNetwork::KResolverResultsPrivate
201{
202public:
203 TQString node, service;
204 int errorcode, syserror;
205
206 KResolverResultsPrivate() :
207 errorcode(0), syserror(0)
208 { }
209};
210
211// default constructor
212KResolverResults::KResolverResults()
213 : d(new KResolverResultsPrivate)
214{
215}
216
217// copy constructor
218KResolverResults::KResolverResults(const KResolverResults& other)
219 : TQValueList<KResolverEntry>(other), d(new KResolverResultsPrivate)
220{
221 *d = *other.d;
222}
223
224// destructor
225KResolverResults::~KResolverResults()
226{
227 delete d;
228}
229
230// assignment operator
231KResolverResults&
232KResolverResults::operator= (const KResolverResults& other)
233{
234 if (this == &other)
235 return *this;
236
237 // copy over the other data
238 *d = *other.d;
239
240 // now let TQValueList do the rest of the work
241 TQValueList<KResolverEntry>::operator =(other);
242
243 return *this;
244}
245
246// gets the error code
247int KResolverResults::error() const
248{
249 return d->errorcode;
250}
251
252// gets the system errno
253int KResolverResults::systemError() const
254{
255 return d->syserror;
256}
257
258// sets the error codes
259void KResolverResults::setError(int errorcode, int systemerror)
260{
261 d->errorcode = errorcode;
262 d->syserror = systemerror;
263}
264
265// gets the hostname
266TQString KResolverResults::nodeName() const
267{
268 return d->node;
269}
270
271// gets the service name
272TQString KResolverResults::serviceName() const
273{
274 return d->service;
275}
276
277// sets the address
278void KResolverResults::setAddress(const TQString& node,
279 const TQString& service)
280{
281 d->node = node;
282 d->service = service;
283}
284
285void KResolverResults::virtual_hook( int, void* )
286{ /*BASE::virtual_hook( id, data );*/ }
287
288
290// class KResolver
291
292TQStringList *KResolver::idnDomains = 0;
293
294
295// default constructor
296KResolver::KResolver(TQObject *parent, const char *name)
297 : TQObject(parent, name), d(new KResolverPrivate(this))
298{
299}
300
301// constructor with host and service
302KResolver::KResolver(const TQString& nodename, const TQString& servicename,
303 TQObject *parent, const char *name)
304 : TQObject(parent, name), d(new KResolverPrivate(this, nodename, servicename))
305{
306}
307
308// destructor
309KResolver::~KResolver()
310{
311 cancel(false);
312 delete d;
313}
314
315// get the status
316int KResolver::status() const
317{
318 return d->status;
319}
320
321// get the error code
322int KResolver::error() const
323{
324 return d->errorcode;
325}
326
327// get the errno
328int KResolver::systemError() const
329{
330 return d->syserror;
331}
332
333// are we running?
334bool KResolver::isRunning() const
335{
336 return d->status > 0 && d->status < Success;
337}
338
339// get the hostname
340TQString KResolver::nodeName() const
341{
342 return d->input.node;
343}
344
345// get the service
346TQString KResolver::serviceName() const
347{
348 return d->input.service;
349}
350
351// sets the hostname
352void KResolver::setNodeName(const TQString& nodename)
353{
354 // don't touch those values if we're working!
355 if (!isRunning())
356 {
357 d->input.node = nodename;
358 d->status = Idle;
359 d->results.setAddress(nodename, d->input.service);
360 }
361}
362
363// sets the service
364void KResolver::setServiceName(const TQString& service)
365{
366 // don't change if running
367 if (!isRunning())
368 {
369 d->input.service = service;
370 d->status = Idle;
371 d->results.setAddress(d->input.node, service);
372 }
373}
374
375// sets the address
376void KResolver::setAddress(const TQString& nodename, const TQString& service)
377{
378 setNodeName(nodename);
379 setServiceName(service);
380}
381
382// get the flags
383int KResolver::flags() const
384{
385 return d->input.flags;
386}
387
388// sets the flags
389int KResolver::setFlags(int flags)
390{
391 int oldflags = d->input.flags;
392 if (!isRunning())
393 {
394 d->input.flags = flags;
395 d->status = Idle;
396 }
397 return oldflags;
398}
399
400// sets the family mask
401void KResolver::setFamily(int families)
402{
403 if (!isRunning())
404 {
405 d->input.familyMask = families;
406 d->status = Idle;
407 }
408}
409
410// sets the socket type
411void KResolver::setSocketType(int type)
412{
413 if (!isRunning())
414 {
415 d->input.socktype = type;
416 d->status = Idle;
417 }
418}
419
420// sets the protocol
421void KResolver::setProtocol(int protonum, const char *name)
422{
423 if (isRunning())
424 return; // can't change now
425
426 // we copy the given protocol name. If it isn't an empty string
427 // and the protocol number was 0, we will look it up in /etc/protocols
428 // we also leave the error reporting to the actual lookup routines, in
429 // case the given protocol name doesn't exist
430
431 d->input.protocolName = name;
432 if (protonum == 0 && name != 0L && *name != '\0')
433 {
434 // must look up the protocol number
435 d->input.protocol = KResolver::protocolNumber(name);
436 }
437 else
438 d->input.protocol = protonum;
439 d->status = Idle;
440}
441
442bool KResolver::start()
443{
444 if (!isRunning())
445 {
446 d->results.empty();
447
448 // is there anything to be queued?
449 if (d->input.node.isEmpty() && d->input.service.isEmpty())
450 {
451 d->status = KResolver::Success;
452 emitFinished();
453 }
454 else
455 KResolverManager::manager()->enqueue(this, 0L);
456 }
457
458 return true;
459}
460
461bool KResolver::wait(int msec)
462{
463 if (!isRunning())
464 {
465 emitFinished();
466 return true;
467 }
468
469 TQMutexLocker locker(&d->mutex);
470
471 if (!isRunning())
472 {
473 // it was running and no longer is?
474 // That means the manager has finished its processing and has posted
475 // an event for the signal to be emitted already. This means the signal
476 // will be emitted twice!
477
478 emitFinished();
479 return true;
480 }
481 else
482 {
483 TQTime t;
484 t.start();
485
486 while (!msec || t.elapsed() < msec)
487 {
488 // wait on the manager to broadcast completion
489 d->waiting = true;
490 if (msec)
491 KResolverManager::manager()->notifyWaiters.wait(&d->mutex, msec - t.elapsed());
492 else
493 KResolverManager::manager()->notifyWaiters.wait(&d->mutex);
494
495 // the manager has processed
496 // see if this object is done
497 if (!isRunning())
498 {
499 // it's done
500 d->waiting = false;
501 emitFinished();
502 return true;
503 }
504 }
505
506 // if we've got here, we've timed out
507 d->waiting = false;
508 return false;
509 }
510}
511
512void KResolver::cancel(bool emitSignal)
513{
514 KResolverManager::manager()->dequeue(this);
515 if (emitSignal)
516 emitFinished();
517}
518
519KResolverResults
520KResolver::results() const
521{
522 if (!isRunning())
523 return d->results;
524
525 // return a dummy, empty result
526 KResolverResults r;
527 r.setAddress(d->input.node, d->input.service);
528 r.setError(d->errorcode, d->syserror);
529 return r;
530}
531
532bool KResolver::event(TQEvent* e)
533{
534 if (static_cast<int>(e->type()) == KResolverManager::ResolutionCompleted)
535 {
536 emitFinished();
537 return true;
538 }
539
540 return false;
541}
542
543void KResolver::emitFinished()
544{
545 if (isRunning())
546 d->status = KResolver::Success;
547
548 TQGuardedPtr<TQObject> p = this; // guard against deletion
549
550 emit finished(d->results);
551
552 if (p && d->deleteWhenDone)
553 deleteLater(); // in TQObject
554}
555
556TQString KResolver::errorString(int errorcode, int syserror)
557{
558 // no i18n now...
559 static const char * const messages[] =
560 {
561 I18N_NOOP("no error"), // NoError
562 I18N_NOOP("requested family not supported for this host name"), // AddrFamily
563 I18N_NOOP("temporary failure in name resolution"), // TryAgain
564 I18N_NOOP("non-recoverable failure in name resolution"), // NonRecoverable
565 I18N_NOOP("invalid flags"), // BadFlags
566 I18N_NOOP("memory allocation failure"), // Memory
567 I18N_NOOP("name or service not known"), // NoName
568 I18N_NOOP("requested family not supported"), // UnsupportedFamily
569 I18N_NOOP("requested service not supported for this socket type"), // UnsupportedService
570 I18N_NOOP("requested socket type not supported"), // UnsupportedSocketType
571 I18N_NOOP("unknown error"), // UnknownError
572 I18N_NOOP2("1: the i18n'ed system error code, from errno",
573 "system error: %1") // SystemError
574 };
575
576 // handle the special value
577 if (errorcode == Canceled)
578 return i18n("request was canceled");
579
580 if (errorcode > 0 || errorcode < SystemError)
581 return TQString::null;
582
583 TQString msg = i18n(messages[-errorcode]);
584 if (errorcode == SystemError)
585 msg.arg(TQString::fromLocal8Bit(strerror(syserror)));
586
587 return msg;
588}
589
590KResolverResults
591KResolver::resolve(const TQString& host, const TQString& service, int flags,
592 int families)
593{
594 KResolver qres(host, service, tqApp, "synchronous KResolver");
595 qres.setFlags(flags);
596 qres.setFamily(families);
597 qres.start();
598 qres.wait();
599 return qres.results();
600}
601
602bool KResolver::resolveAsync(TQObject* userObj, const char *userSlot,
603 const TQString& host, const TQString& service,
604 int flags, int families)
605{
606 KResolver* qres = new KResolver(host, service, tqApp, "asynchronous KResolver");
607 TQObject::connect(qres, TQ_SIGNAL(finished(KResolverResults)), userObj, userSlot);
608 qres->setFlags(flags);
609 qres->setFamily(families);
610 qres->d->deleteWhenDone = true; // this is the only difference from the example code
611 return qres->start();
612}
613
614TQStrList KResolver::protocolName(int protonum)
615{
616 struct protoent *pe = 0L;
617#ifndef HAVE_GETPROTOBYNAME_R
618 TQMutexLocker locker(&getXXbyYYmutex);
619
620 pe = getprotobynumber(protonum);
621
622#else
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);
627
628 if (getprotobynumber_r(protonum, &protobuf, &pdata) == 0)
629 pe = &protobuf;
630 else
631 pe = 0;
632
633# else
634 size_t buflen = 1024;
635 struct protoent protobuf;
636 char *buf;
637 do
638 {
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))
642# else
643 if (getprotobynumber_r(protonum, &protobuf, buf, buflen, &pe) == ERANGE)
644# endif
645 {
646 pe = 0L;
647 buflen += 1024;
648 delete [] buf;
649 }
650 else
651 break;
652 }
653 while (pe == 0L);
654# endif
655#endif
656
657 // Do common processing
658 TQStrList lst(true); // use deep copies
659 if (pe != NULL)
660 {
661 lst.append(pe->p_name);
662 for (char **p = pe->p_aliases; *p; p++)
663 lst.append(*p);
664 }
665
666#ifdef HAVE_GETPROTOBYNAME_R
667# ifndef USE_OPENBSD
668 delete [] buf;
669# endif
670#endif
671
672 return lst;
673}
674
675TQStrList KResolver::protocolName(const char *protoname)
676{
677 struct protoent *pe = 0L;
678#ifndef HAVE_GETPROTOBYNAME_R
679 TQMutexLocker locker(&getXXbyYYmutex);
680
681 pe = getprotobyname(protoname);
682
683#else
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);
688
689 if (getprotobyname_r(protoname, &protobuf, &pdata) == 0)
690 pe = &protobuf;
691 else
692 pe = 0;
693
694# else
695 size_t buflen = 1024;
696 struct protoent protobuf;
697 char *buf;
698 do
699 {
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))
703# else
704 if (getprotobyname_r(protoname, &protobuf, buf, buflen, &pe) == ERANGE)
705# endif
706 {
707 pe = 0L;
708 buflen += 1024;
709 delete [] buf;
710 }
711 else
712 break;
713 }
714 while (pe == 0L);
715# endif
716#endif
717
718 // Do common processing
719 TQStrList lst(true); // use deep copies
720 if (pe != NULL)
721 {
722 lst.append(pe->p_name);
723 for (char **p = pe->p_aliases; *p; p++)
724 lst.append(*p);
725 }
726
727#ifdef HAVE_GETPROTOBYNAME_R
728# ifndef USE_OPENBSD
729 delete [] buf;
730# endif
731#endif
732
733 return lst;
734}
735
736int KResolver::protocolNumber(const char *protoname)
737{
738 struct protoent *pe = 0L;
739#ifndef HAVE_GETPROTOBYNAME_R
740 TQMutexLocker locker(&getXXbyYYmutex);
741
742 pe = getprotobyname(protoname);
743
744#else
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);
749
750 if (getprotobyname_r(protoname, &protobuf, &pdata) == 0)
751 pe = &protobuf;
752 else
753 pe = 0;
754
755# else
756 size_t buflen = 1024;
757 struct protoent protobuf;
758 char *buf;
759 do
760 {
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))
764# else
765 if (getprotobyname_r(protoname, &protobuf, buf, buflen, &pe) == ERANGE)
766# endif
767 {
768 pe = 0L;
769 buflen += 1024;
770 delete [] buf;
771 }
772 else
773 break;
774 }
775 while (pe == 0L);
776# endif
777#endif
778
779 // Do common processing
780 int protonum = -1;
781 if (pe != NULL)
782 protonum = pe->p_proto;
783
784#ifdef HAVE_GETPROTOBYNAME_R
785# ifndef USE_OPENBSD
786 delete [] buf;
787# endif
788#endif
789
790 return protonum;
791}
792
793int KResolver::servicePort(const char *servname, const char *protoname)
794{
795 struct servent *se = 0L;
796#ifndef HAVE_GETSERVBYNAME_R
797 TQMutexLocker locker(&getXXbyYYmutex);
798
799 se = getservbyname(servname, protoname);
800
801#else
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)
807 se = &servbuf;
808 else
809 se = 0;
810
811# else
812 size_t buflen = 1024;
813 struct servent servbuf;
814 char *buf;
815 do
816 {
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))
820# else
821 if (getservbyname_r(servname, protoname, &servbuf, buf, buflen, &se) == ERANGE)
822# endif
823 {
824 se = 0L;
825 buflen += 1024;
826 delete [] buf;
827 }
828 else
829 break;
830 }
831 while (se == 0L);
832# endif
833#endif
834
835 // Do common processing
836 int servport = -1;
837 if (se != NULL)
838 servport = ntohs(se->s_port);
839
840#ifdef HAVE_GETSERVBYNAME_R
841# ifndef USE_OPENBSD
842 delete [] buf;
843# endif
844#endif
845
846 return servport;
847}
848
849TQStrList KResolver::serviceName(const char* servname, const char *protoname)
850{
851 struct servent *se = 0L;
852#ifndef HAVE_GETSERVBYNAME_R
853 TQMutexLocker locker(&getXXbyYYmutex);
854
855 se = getservbyname(servname, protoname);
856
857#else
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)
863 se = &servbuf;
864 else
865 se = 0;
866
867# else
868 size_t buflen = 1024;
869 struct servent servbuf;
870 char *buf;
871 do
872 {
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))
876# else
877 if (getservbyname_r(servname, protoname, &servbuf, buf, buflen, &se) == ERANGE)
878# endif
879 {
880 se = 0L;
881 buflen += 1024;
882 delete [] buf;
883 }
884 else
885 break;
886 }
887 while (se == 0L);
888# endif
889#endif
890
891 // Do common processing
892 TQStrList lst(true); // use deep copies
893 if (se != NULL)
894 {
895 lst.append(se->s_name);
896 for (char **p = se->s_aliases; *p; p++)
897 lst.append(*p);
898 }
899
900#ifdef HAVE_GETSERVBYNAME_R
901# ifndef USE_OPENBSD
902 delete [] buf;
903# endif
904#endif
905
906 return lst;
907}
908
909TQStrList KResolver::serviceName(int port, const char *protoname)
910{
911 struct servent *se = 0L;
912#ifndef HAVE_GETSERVBYPORT_R
913 TQMutexLocker locker(&getXXbyYYmutex);
914
915 se = getservbyport(port, protoname);
916
917#else
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)
923 se = &servbuf;
924 else
925 se = 0;
926
927# else
928 size_t buflen = 1024;
929 struct servent servbuf;
930 char *buf;
931 do
932 {
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))
936# else
937 if (getservbyport_r(port, protoname, &servbuf, buf, buflen, &se) == ERANGE)
938# endif
939 {
940 se = 0L;
941 buflen += 1024;
942 delete [] buf;
943 }
944 else
945 break;
946 }
947 while (se == 0L);
948# endif
949#endif
950
951 // Do common processing
952 TQStrList lst(true); // use deep copies
953 if (se != NULL)
954 {
955 lst.append(se->s_name);
956 for (char **p = se->s_aliases; *p; p++)
957 lst.append(*p);
958 }
959
960#ifdef HAVE_GETSERVBYPORT_R
961# ifndef USE_OPENBSD
962 delete [] buf;
963# endif
964#endif
965
966 return lst;
967}
968
969TQString KResolver::localHostName()
970{
971 TQCString name;
972 int len;
973
974#ifdef MAXHOSTNAMELEN
975 len = MAXHOSTNAMELEN;
976#else
977 len = 256;
978#endif
979
980 while (true)
981 {
982 name.resize(len);
983
984 if (gethostname(name.data(), len - 1) == 0)
985 {
986 // Call succeeded, but it's not guaranteed to be NUL-terminated
987 // Note that some systems return success even if they did truncation
988 name[len - 1] = '\0';
989 break;
990 }
991
992 // Call failed
993 if (errno == ENAMETOOLONG || errno == EINVAL)
994 len += 256;
995 else
996 {
997 // Oops! Unknown error!
998 name = TQCString();
999 }
1000 }
1001
1002 if (name.isEmpty())
1003 return TQString::fromLatin1("localhost");
1004
1005 if (name.find('.') == -1)
1006 {
1007 // not fully qualified
1008 // must resolve
1009 KResolverResults results = resolve(name, "0", CanonName);
1010 if (results.isEmpty())
1011 // cannot find a valid hostname!
1012 return TQString::fromLatin1("localhost");
1013 else
1014 return results.first().canonicalName();
1015 }
1016
1017 return domainToUnicode(name);
1018}
1019
1020
1021// forward declaration
1022static TQStringList splitLabels(const TQString& unicodeDomain);
1023static TQCString ToASCII(const TQString& label);
1024static TQString ToUnicode(const TQString& label);
1025
1026static TQStringList *KResolver_initIdnDomains()
1027{
1028 const char *kde_use_idn = getenv("TDE_USE_IDN");
1029 if (!kde_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()));
1032}
1033
1034// implement the ToAscii function, as described by IDN documents
1035TQCString KResolver::domainToAscii(const TQString& unicodeDomain)
1036{
1037 if (!idnDomains)
1038 idnDomains = KResolver_initIdnDomains();
1039
1040 TQCString retval;
1041 // RFC 3490, section 4 describes the operation:
1042 // 1) this is a query, so don't allow unassigned
1043
1044 // 2) split the domain into individual labels, without
1045 // separators.
1046 TQStringList input = splitLabels(unicodeDomain);
1047
1048 // Do we allow IDN names for this TLD?
1049 if (input.count() && !idnDomains->contains(input[input.count()-1].lower()))
1050 return input.join(".").lower().latin1(); // No IDN allowed for this TLD
1051
1052 // 3) decide whether to enforce the STD3 rules for chars < 0x7F
1053 // we don't enforce
1054
1055 // 4) for each label, apply ToASCII
1056 TQStringList::Iterator it = input.begin();
1057 const TQStringList::Iterator end = input.end();
1058 for ( ; it != end; ++it)
1059 {
1060 TQCString cs = ToASCII(*it);
1061 if (cs.isNull())
1062 return TQCString(); // error!
1063
1064 // no, all is Ok.
1065 if (!retval.isEmpty())
1066 retval += '.';
1067 retval += cs;
1068 }
1069
1070 return retval;
1071}
1072
1073TQString KResolver::domainToUnicode(const TQCString& asciiDomain)
1074{
1075 return domainToUnicode(TQString::fromLatin1(asciiDomain));
1076}
1077
1078// implement the ToUnicode function, as described by IDN documents
1079TQString KResolver::domainToUnicode(const TQString& asciiDomain)
1080{
1081 if (asciiDomain.isEmpty())
1082 return asciiDomain;
1083 if (!idnDomains)
1084 idnDomains = KResolver_initIdnDomains();
1085
1086 TQString retval;
1087
1088 // draft-idn-idna-14.txt, section 4 describes the operation:
1089 // 1) this is a query, so don't allow unassigned
1090 // besides, input is ASCII
1091
1092 // 2) split the domain into individual labels, without
1093 // separators.
1094 TQStringList input = splitLabels(asciiDomain);
1095
1096 // Do we allow IDN names for this TLD?
1097 if (input.count() && !idnDomains->contains(input[input.count()-1].lower()))
1098 return asciiDomain.lower(); // No TLDs allowed
1099
1100 // 3) decide whether to enforce the STD3 rules for chars < 0x7F
1101 // we don't enforce
1102
1103 // 4) for each label, apply ToUnicode
1104 TQStringList::Iterator it;
1105 const TQStringList::Iterator end = input.end();
1106 for (it = input.begin(); it != end; ++it)
1107 {
1108 TQString label = ToUnicode(*it).lower();
1109
1110 // ToUnicode can't fail
1111 if (!retval.isEmpty())
1112 retval += '.';
1113 retval += label;
1114 }
1115
1116 return retval;
1117}
1118
1119TQString KResolver::normalizeDomain(const TQString& domain)
1120{
1121 return domainToUnicode(domainToAscii(domain));
1122}
1123
1124void KResolver::virtual_hook( int, void* )
1125{ /*BASE::virtual_hook( id, data );*/ }
1126
1127// here follows IDN functions
1128// all IDN functions conform to the following documents:
1129// RFC 3454 - Preparation of Internationalized Strings
1130// RFC 3490 - Internationalizing Domain Names in Applications (IDNA)
1131// RFC 3491 - Nameprep: A Stringprep Profile for
1132// Internationalized Domain Names (IDN
1133// RFC 3492 - Punycode: A Bootstring encoding of Unicode
1134// for Internationalized Domain Names in Applications (IDNA)
1135
1136static TQStringList splitLabels(const TQString& unicodeDomain)
1137{
1138 // From RFC 3490 section 3.1:
1139 // "Whenever dots are used as label separators, the following characters
1140 // MUST be recognized as dots: U+002E (full stop), U+3002 (ideographic full
1141 // stop), U+FF0E (fullwidth full stop), U+FF61 (halfwidth ideographic full
1142 // stop)."
1143 static const unsigned int separators[] = { 0x002E, 0x3002, 0xFF0E, 0xFF61 };
1144
1145 TQStringList lst;
1146 int start = 0;
1147 uint i;
1148 for (i = 0; i < unicodeDomain.length(); i++)
1149 {
1150 unsigned int c = unicodeDomain[i].unicode();
1151
1152 if (c == separators[0] ||
1153 c == separators[1] ||
1154 c == separators[2] ||
1155 c == separators[3])
1156 {
1157 // found a separator!
1158 lst << unicodeDomain.mid(start, i - start);
1159 start = i + 1;
1160 }
1161 }
1162 if ((long)i >= start)
1163 // there is still one left
1164 lst << unicodeDomain.mid(start, i - start);
1165
1166 return lst;
1167}
1168
1169static TQCString ToASCII(const TQString& label)
1170{
1171#ifdef HAVE_IDNA_H
1172 // We have idna.h, so we can use the idna_to_ascii
1173 // function :)
1174
1175 if (label.length() > 64)
1176 return (char*)0L; // invalid label
1177
1178 if (label.length() == 0)
1179 // this is allowed
1180 return TQCString(""); // empty, not null
1181
1182 TQCString retval;
1183 char buf[65];
1184
1185 TQ_UINT32* ucs4 = new TQ_UINT32[label.length() + 1];
1186
1187 uint i;
1188 for (i = 0; i < label.length(); i++)
1189 ucs4[i] = (unsigned long)label[i].unicode();
1190 ucs4[i] = 0; // terminate with NUL, just to be on the safe side
1191
1192 if (idna_to_ascii_4i(ucs4, label.length(), buf, 0) == IDNA_SUCCESS)
1193 // success!
1194 retval = buf;
1195
1196 delete [] ucs4;
1197 return retval;
1198#else
1199 return label.latin1();
1200#endif
1201}
1202
1203static TQString ToUnicode(const TQString& label)
1204{
1205#ifdef HAVE_IDNA_H
1206 // We have idna.h, so we can use the idna_to_unicode
1207 // function :)
1208
1209 TQ_UINT32 *ucs4_input, *ucs4_output;
1210 size_t outlen;
1211
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();
1215
1216 // try the same length for output
1217 ucs4_output = new TQ_UINT32[outlen = label.length()];
1218
1219 idna_to_unicode_44i(ucs4_input, label.length(),
1220 ucs4_output, &outlen,
1221 0);
1222
1223 if (outlen > label.length())
1224 {
1225 // it must have failed
1226 delete [] ucs4_output;
1227 ucs4_output = new TQ_UINT32[outlen];
1228
1229 idna_to_unicode_44i(ucs4_input, label.length(),
1230 ucs4_output, &outlen,
1231 0);
1232 }
1233
1234 // now set the answer
1235 TQString result;
1236 result.setLength(outlen);
1237 for (uint i = 0; i < outlen; i++)
1238 result[i] = (unsigned int)ucs4_output[i];
1239
1240 delete [] ucs4_input;
1241 delete [] ucs4_output;
1242
1243 return result;
1244#else
1245 return label;
1246#endif
1247}
1248
1249#include "kresolver.moc"
KNetwork::KResolverEntry
One resolution entry.
Definition: kresolver.h:67
KNetwork::KResolverEntry::protocol
int protocol() const
Retrieves the protocol associated with this entry.
Definition: kresolver.cpp:178
KNetwork::KResolverEntry::KResolverEntry
KResolverEntry()
Default constructor.
Definition: kresolver.cpp:94
KNetwork::KResolverEntry::length
TQ_UINT16 length() const
Retrieves the length of the socket address structure.
Definition: kresolver.cpp:148
KNetwork::KResolverEntry::~KResolverEntry
~KResolverEntry()
Destructor.
Definition: kresolver.cpp:132
KNetwork::KResolverEntry::socketType
int socketType() const
Retrieves the socket type associated with this entry.
Definition: kresolver.cpp:172
KNetwork::KResolverEntry::encodedName
TQCString encodedName() const
Retrieves the encoded domain name associated with this entry, if there is any.
Definition: kresolver.cpp:166
KNetwork::KResolverEntry::address
TDESocketAddress address() const
Retrieves the socket address associated with this entry.
Definition: kresolver.cpp:142
KNetwork::KResolverEntry::family
int family() const
Retrieves the family associated with this socket address.
Definition: kresolver.cpp:154
KNetwork::KResolverEntry::canonicalName
TQString canonicalName() const
Retrieves the canonical name associated with this entry, if there is any.
Definition: kresolver.cpp:160
KNetwork::KResolverEntry::operator=
KResolverEntry & operator=(const KResolverEntry &other)
Assignment operator.
Definition: kresolver.cpp:184
KNetwork::KResolverResults
Name and service resolution results.
Definition: kresolver.h:198
KNetwork::KResolverResults::KResolverResults
KResolverResults()
Default constructor.
Definition: kresolver.cpp:212
KNetwork::KResolverResults::~KResolverResults
virtual ~KResolverResults()
Destructor.
Definition: kresolver.cpp:225
KNetwork::KResolverResults::setAddress
void setAddress(const TQString &host, const TQString &service)
Sets the new nodename and service name.
Definition: kresolver.cpp:278
KNetwork::KResolverResults::systemError
int systemError() const
Retrieves the system error code, if any.
Definition: kresolver.cpp:253
KNetwork::KResolverResults::error
int error() const
Retrieves the error code associated with this resolution.
Definition: kresolver.cpp:247
KNetwork::KResolverResults::nodeName
TQString nodeName() const
The nodename to which the resolution was performed.
Definition: kresolver.cpp:266
KNetwork::KResolverResults::operator=
KResolverResults & operator=(const KResolverResults &other)
Assignment operator.
Definition: kresolver.cpp:232
KNetwork::KResolverResults::serviceName
TQString serviceName() const
The service name to which the resolution was performed.
Definition: kresolver.cpp:272
KNetwork::KResolverResults::setError
void setError(int errorcode, int systemerror=0)
Sets the error codes.
Definition: kresolver.cpp:259
KNetwork::KResolver
Name and service resolution class.
Definition: kresolver.h:296
KNetwork::KResolver::KResolver
KResolver(TQObject *=0L, const char *=0L)
Default constructor.
Definition: kresolver.cpp:296
KNetwork::KResolver::cancel
void cancel(bool emitSignal=true)
Cancels a running request.
Definition: kresolver.cpp:512
KNetwork::KResolver::results
KResolverResults results() const
Retrieves the results of this resolution.
Definition: kresolver.cpp:520
KNetwork::KResolver::nodeName
TQString nodeName() const
The nodename to which the resolution was/is to be performed.
Definition: kresolver.cpp:340
KNetwork::KResolver::domainToUnicode
static TQString domainToUnicode(const TQCString &asciiDomain)
Does the inverse of domainToAscii and return an Unicode domain name from the given ACE-encoded domain...
Definition: kresolver.cpp:1073
KNetwork::KResolver::status
int status() const
Retrieve the current status of this object.
Definition: kresolver.cpp:316
KNetwork::KResolver::protocolName
static TQStrList protocolName(int protonum)
Resolves a protocol number to its names.
Definition: kresolver.cpp:614
KNetwork::KResolver::errorString
TQString errorString() const
Returns the textual representation of the error in this object.
Definition: kresolver.h:494
KNetwork::KResolver::error
int error() const
Retrieve the error code in this object.
Definition: kresolver.cpp:322
KNetwork::KResolver::setProtocol
void setProtocol(int protonum, const char *name=0L)
Sets the protocol we want.
Definition: kresolver.cpp:421
KNetwork::KResolver::resolve
static KResolverResults resolve(const TQString &host, const TQString &service, int flags=0, int families=KResolver::InternetFamily)
Resolve the nodename and service name synchronously.
Definition: kresolver.cpp:591
KNetwork::KResolver::domainToAscii
static TQCString domainToAscii(const TQString &unicodeDomain)
Returns the domain name in an ASCII Compatible Encoding form, suitable for DNS lookups.
Definition: kresolver.cpp:1035
KNetwork::KResolver::event
virtual bool event(TQEvent *)
Handles events.
Definition: kresolver.cpp:532
KNetwork::KResolver::isRunning
bool isRunning() const
Returns true if this object is currently running.
Definition: kresolver.cpp:334
KNetwork::KResolver::systemError
int systemError() const
Retrieve the associated system error code in this object.
Definition: kresolver.cpp:328
KNetwork::KResolver::finished
void finished(KResolverResults results)
This signal is emitted whenever the resolution is finished, one way or another (success or failure).
KNetwork::KResolver::setFamily
void setFamily(int families)
Sets the allowed socket families.
Definition: kresolver.cpp:401
KNetwork::KResolver::servicePort
static int servicePort(const char *servname, const char *protoname)
Resolves a service name to its port number.
Definition: kresolver.cpp:793
KNetwork::KResolver::flags
int flags() const
Retrieves the flags set for the resolution.
Definition: kresolver.cpp:383
KNetwork::KResolver::protocolNumber
static int protocolNumber(const char *protoname)
Resolves a protocol name to its number.
Definition: kresolver.cpp:736
KNetwork::KResolver::setServiceName
void setServiceName(const TQString &service)
Sets the service name to be resolved.
Definition: kresolver.cpp:364
KNetwork::KResolver::~KResolver
virtual ~KResolver()
Destructor.
Definition: kresolver.cpp:309
KNetwork::KResolver::wait
bool wait(int msec=0)
Waits for a request to finish resolving.
Definition: kresolver.cpp:461
KNetwork::KResolver::resolveAsync
static bool resolveAsync(TQObject *userObj, const char *userSlot, const TQString &host, const TQString &service, int flags=0, int families=KResolver::InternetFamily)
Start an asynchronous name resolution.
Definition: kresolver.cpp:602
KNetwork::KResolver::setNodeName
void setNodeName(const TQString &nodename)
Sets the nodename for the resolution.
Definition: kresolver.cpp:352
KNetwork::KResolver::setFlags
int setFlags(int flags)
Sets the flags.
Definition: kresolver.cpp:389
KNetwork::KResolver::setSocketType
void setSocketType(int type)
Sets the socket type we want.
Definition: kresolver.cpp:411
KNetwork::KResolver::serviceName
TQString serviceName() const
The service name to which the resolution was/is to be performed.
Definition: kresolver.cpp:346
KNetwork::KResolver::normalizeDomain
static TQString normalizeDomain(const TQString &domain)
Normalise a domain name.
Definition: kresolver.cpp:1119
KNetwork::KResolver::start
bool start()
Starts the name resolution asynchronously.
Definition: kresolver.cpp:442
KNetwork::KResolver::setAddress
void setAddress(const TQString &node, const TQString &service)
Sets both the host and the service names.
Definition: kresolver.cpp:376
KNetwork::KResolver::localHostName
static TQString localHostName()
Returns this machine's local hostname.
Definition: kresolver.cpp:969
KNetwork::TDESocketAddress
A generic socket address.
Definition: tdesocketaddress.h:424
KNetwork
A namespace to store all networking-related (socket) classes.
Definition: kbufferedsocket.h:36
TDEStdAccel::label
TQString label(StdAccel id)
Returns a localized label for user-visible display.
Definition: tdestdaccel.cpp:156
tdelocale.h

tdecore

Skip menu "tdecore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdecore

Skip menu "tdecore"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdecore by doxygen 1.9.4
This website is maintained by Timothy Pearson.