• 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"
66 TQMutex getXXbyYYmutex;
67 #endif
68 
69 #ifdef __OpenBSD__
70 #define USE_OPENBSD 1
71 #endif
72 
73 using namespace KNetwork;
74 using namespace KNetwork::Internal;
75 
77 // class KResolverEntry
78 
79 class KNetwork::KResolverEntryPrivate: public TQShared
80 {
81 public:
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
94 KResolverEntry::KResolverEntry() :
95  d(0L)
96 {
97 }
98 
99 // constructor with stuff
100 KResolverEntry::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
112 KResolverEntry::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
125 KResolverEntry::KResolverEntry(const KResolverEntry& that) :
126  d(0L)
127 {
128  *this = that;
129 }
130 
131 // destructor
132 KResolverEntry::~KResolverEntry()
133 {
134  if (d == 0L)
135  return;
136 
137  if (d->deref())
138  delete d;
139 }
140 
141 // returns the socket address
142 TDESocketAddress KResolverEntry::address() const
143 {
144  return d ? d->addr : TDESocketAddress();
145 }
146 
147 // returns the length
148 TQ_UINT16 KResolverEntry::length() const
149 {
150  return d ? d->addr.length() : 0;
151 }
152 
153 // returns the family
154 int KResolverEntry::family() const
155 {
156  return d ? d->addr.family() : AF_UNSPEC;
157 }
158 
159 // returns the canonical name
160 TQString KResolverEntry::canonicalName() const
161 {
162  return d ? d->canonName : TQString::null;
163 }
164 
165 // returns the encoded name
166 TQCString KResolverEntry::encodedName() const
167 {
168  return d ? d->encodedName : TQCString();
169 }
170 
171 // returns the socket type
172 int KResolverEntry::socketType() const
173 {
174  return d ? d->socktype : 0;
175 }
176 
177 // returns the protocol
178 int KResolverEntry::protocol() const
179 {
180  return d ? d->protocol : 0;
181 }
182 
183 // assignment operator
184 KResolverEntry& 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 
200 class KNetwork::KResolverResultsPrivate
201 {
202 public:
203  TQString node, service;
204  int errorcode, syserror;
205 
206  KResolverResultsPrivate() :
207  errorcode(0), syserror(0)
208  { }
209 };
210 
211 // default constructor
212 KResolverResults::KResolverResults()
213  : d(new KResolverResultsPrivate)
214 {
215 }
216 
217 // copy constructor
218 KResolverResults::KResolverResults(const KResolverResults& other)
219  : TQValueList<KResolverEntry>(other), d(new KResolverResultsPrivate)
220 {
221  *d = *other.d;
222 }
223 
224 // destructor
225 KResolverResults::~KResolverResults()
226 {
227  delete d;
228 }
229 
230 // assignment operator
231 KResolverResults&
232 KResolverResults::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
247 int KResolverResults::error() const
248 {
249  return d->errorcode;
250 }
251 
252 // gets the system errno
253 int KResolverResults::systemError() const
254 {
255  return d->syserror;
256 }
257 
258 // sets the error codes
259 void KResolverResults::setError(int errorcode, int systemerror)
260 {
261  d->errorcode = errorcode;
262  d->syserror = systemerror;
263 }
264 
265 // gets the hostname
266 TQString KResolverResults::nodeName() const
267 {
268  return d->node;
269 }
270 
271 // gets the service name
272 TQString KResolverResults::serviceName() const
273 {
274  return d->service;
275 }
276 
277 // sets the address
278 void KResolverResults::setAddress(const TQString& node,
279  const TQString& service)
280 {
281  d->node = node;
282  d->service = service;
283 }
284 
285 void KResolverResults::virtual_hook( int, void* )
286 { /*BASE::virtual_hook( id, data );*/ }
287 
288 
290 // class KResolver
291 
292 TQStringList *KResolver::idnDomains = 0;
293 
294 
295 // default constructor
296 KResolver::KResolver(TQObject *parent, const char *name)
297  : TQObject(parent, name), d(new KResolverPrivate(this))
298 {
299 }
300 
301 // constructor with host and service
302 KResolver::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
309 KResolver::~KResolver()
310 {
311  cancel(false);
312  delete d;
313 }
314 
315 // get the status
316 int KResolver::status() const
317 {
318  return d->status;
319 }
320 
321 // get the error code
322 int KResolver::error() const
323 {
324  return d->errorcode;
325 }
326 
327 // get the errno
328 int KResolver::systemError() const
329 {
330  return d->syserror;
331 }
332 
333 // are we running?
334 bool KResolver::isRunning() const
335 {
336  return d->status > 0 && d->status < Success;
337 }
338 
339 // get the hostname
340 TQString KResolver::nodeName() const
341 {
342  return d->input.node;
343 }
344 
345 // get the service
346 TQString KResolver::serviceName() const
347 {
348  return d->input.service;
349 }
350 
351 // sets the hostname
352 void 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
364 void 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
376 void KResolver::setAddress(const TQString& nodename, const TQString& service)
377 {
378  setNodeName(nodename);
379  setServiceName(service);
380 }
381 
382 // get the flags
383 int KResolver::flags() const
384 {
385  return d->input.flags;
386 }
387 
388 // sets the flags
389 int 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
401 void 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
411 void 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
421 void 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 
442 bool 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 
461 bool 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 
512 void KResolver::cancel(bool emitSignal)
513 {
514  KResolverManager::manager()->dequeue(this);
515  if (emitSignal)
516  emitFinished();
517 }
518 
519 KResolverResults
520 KResolver::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 
532 bool 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 
543 void 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 QObject
554 }
555 
556 TQString 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 
590 KResolverResults
591 KResolver::resolve(const TQString& host, const TQString& service, int flags,
592  int families)
593 {
594  KResolver qres(host, service, TQT_TQOBJECT(tqApp), "synchronous KResolver");
595  qres.setFlags(flags);
596  qres.setFamily(families);
597  qres.start();
598  qres.wait();
599  return qres.results();
600 }
601 
602 bool 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, TQT_TQOBJECT(tqApp), "asynchronous KResolver");
607  TQObject::connect(qres, TQT_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 
614 TQStrList 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 
675 TQStrList 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 
736 int 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 
793 int 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 
849 TQStrList 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 
909 TQStrList 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 
969 TQString 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
1022 static TQStringList splitLabels(const TQString& unicodeDomain);
1023 static TQCString ToASCII(const TQString& label);
1024 static TQString ToUnicode(const TQString& label);
1025 
1026 static 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
1035 TQCString 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 
1073 TQString KResolver::domainToUnicode(const TQCString& asciiDomain)
1074 {
1075  return domainToUnicode(TQString::fromLatin1(asciiDomain));
1076 }
1077 
1078 // implement the ToUnicode function, as described by IDN documents
1079 TQString 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 
1119 TQString KResolver::normalizeDomain(const TQString& domain)
1120 {
1121  return domainToUnicode(domainToAscii(domain));
1122 }
1123 
1124 void 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 
1136 static 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 
1169 static 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 
1203 static 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::TDESocketAddress
A generic socket address.
Definition: tdesocketaddress.h:423
KNetwork::KResolverResults::operator=
KResolverResults & operator=(const KResolverResults &other)
Assignment operator.
Definition: kresolver.cpp:232
KNetwork::KResolverEntry::operator=
KResolverEntry & operator=(const KResolverEntry &other)
Assignment operator.
Definition: kresolver.cpp:184
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::flags
int flags() const
Retrieves the flags set for the resolution.
Definition: kresolver.cpp:383
KNetwork::KResolverResults::serviceName
TQString serviceName() const
The service name to which the resolution was performed.
Definition: kresolver.cpp:272
KNetwork::KResolverResults::~KResolverResults
virtual ~KResolverResults()
Destructor.
Definition: kresolver.cpp:225
KNetwork::KResolverEntry
One resolution entry.
Definition: kresolver.h:66
KNetwork::Internal
Definition: kresolver.h:47
KNetwork::KResolver::error
int error() const
Retrieve the error code in this object.
Definition: kresolver.cpp:322
KNetwork::KResolver::setFamily
void setFamily(int families)
Sets the allowed socket families.
Definition: kresolver.cpp:401
KNetwork::KResolver
Name and service resolution class.
Definition: kresolver.h:295
KNetwork::KResolver::setProtocol
void setProtocol(int protonum, const char *name=0L)
Sets the protocol we want.
Definition: kresolver.cpp:421
KNetwork::KResolverResults
Name and service resolution results.
Definition: kresolver.h:197
KNetwork::KResolver::status
int status() const
Retrieve the current status of this object.
Definition: kresolver.cpp:316
KNetwork::KResolver::event
virtual bool event(TQEvent *)
Handles events.
Definition: kresolver.cpp:532
KNetwork::KResolverEntry::protocol
int protocol() const
Retrieves the protocol associated with this entry.
Definition: kresolver.cpp:178
KNetwork::KResolver::results
KResolverResults results() const
Retrieves the results of this resolution.
Definition: kresolver.cpp:520
KNetwork::KResolverEntry::address
TDESocketAddress address() const
Retrieves the socket address associated with this entry.
Definition: kresolver.cpp:142
KNetwork::KResolver::serviceName
TQString serviceName() const
The service name to which the resolution was/is to be performed.
Definition: kresolver.cpp:346
KNetwork
A namespace to store all networking-related (socket) classes.
Definition: kbufferedsocket.h:36
KNetwork::KResolver::setServiceName
void setServiceName(const TQString &service)
Sets the service name to be resolved.
Definition: kresolver.cpp:364
KNetwork::KResolver::errorString
TQString errorString() const
Returns the textual representation of the error in this object.
Definition: kresolver.h:494
tdelocale.h
KNetwork::KResolver::wait
bool wait(int msec=0)
Waits for a request to finish resolving.
Definition: kresolver.cpp:461
KNetwork::KResolver::systemError
int systemError() const
Retrieve the associated system error code in this object.
Definition: kresolver.cpp:328
KNetwork::KResolverResults::systemError
int systemError() const
Retrieves the system error code, if any.
Definition: kresolver.cpp:253
KNetwork::KResolverResults::nodeName
TQString nodeName() const
The nodename to which the resolution was performed.
Definition: kresolver.cpp:266
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::KResolver::normalizeDomain
static TQString normalizeDomain(const TQString &domain)
Normalise a domain name.
Definition: kresolver.cpp:1119
KNetwork::KResolverEntry::encodedName
TQCString encodedName() const
Retrieves the encoded domain name associated with this entry, if there is any.
Definition: kresolver.cpp:166
KNetwork::KResolver::localHostName
static TQString localHostName()
Returns this machine's local hostname.
Definition: kresolver.cpp:969
KNetwork::KResolver::nodeName
TQString nodeName() const
The nodename to which the resolution was/is to be performed.
Definition: kresolver.cpp:340
KNetwork::KResolver::setAddress
void setAddress(const TQString &node, const TQString &service)
Sets both the host and the service names.
Definition: kresolver.cpp:376
KNetwork::KResolverResults::setAddress
void setAddress(const TQString &host, const TQString &service)
Sets the new nodename and service name.
Definition: kresolver.cpp:278
KNetwork::KResolverEntry::socketType
int socketType() const
Retrieves the socket type associated with this entry.
Definition: kresolver.cpp:172
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::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::KResolverEntry::family
int family() const
Retrieves the family associated with this socket address.
Definition: kresolver.cpp:154
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::setNodeName
void setNodeName(const TQString &nodename)
Sets the nodename for the resolution.
Definition: kresolver.cpp:352
KNetwork::KResolverEntry::KResolverEntry
KResolverEntry()
Default constructor.
Definition: kresolver.cpp:94
KNetwork::KResolverResults::KResolverResults
KResolverResults()
Default constructor.
Definition: kresolver.cpp:212
KNetwork::KResolver::setSocketType
void setSocketType(int type)
Sets the socket type we want.
Definition: kresolver.cpp:411
KNetwork::KResolver::~KResolver
virtual ~KResolver()
Destructor.
Definition: kresolver.cpp:309
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::KResolverResults::setError
void setError(int errorcode, int systemerror=0)
Sets the error codes.
Definition: kresolver.cpp:259
KNetwork::KResolver::cancel
void cancel(bool emitSignal=true)
Cancels a running request.
Definition: kresolver.cpp:512
KNetwork::KResolver::isRunning
bool isRunning() const
Returns true if this object is currently running.
Definition: kresolver.cpp:334
KNetwork::KResolver::setFlags
int setFlags(int flags)
Sets the flags.
Definition: kresolver.cpp:389
KNetwork::KResolver::KResolver
KResolver(TQObject *=0L, const char *=0L)
Default constructor.
Definition: kresolver.cpp:296
KNetwork::KResolver::protocolNumber
static int protocolNumber(const char *protoname)
Resolves a protocol name to its number.
Definition: kresolver.cpp:736
KNetwork::KResolverResults::error
int error() const
Retrieves the error code associated with this resolution.
Definition: kresolver.cpp:247
KNetwork::KResolver::start
bool start()
Starts the name resolution asynchronously.
Definition: kresolver.cpp:442
KNetwork::KResolver::protocolName
static TQStrList protocolName(int protonum)
Resolves a protocol number to its names.
Definition: kresolver.cpp:614
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::KResolverEntry::canonicalName
TQString canonicalName() const
Retrieves the canonical name associated with this entry, if there is any.
Definition: kresolver.cpp:160

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
  •     tdecore
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  • tdeioslave
  •   http
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdecore by doxygen 1.8.8
This website is maintained by Timothy Pearson.