KDELibs4Support

k3resolver.cpp
1 /* -*- C++ -*-
2  * Copyright (C) 2003-2005 Thiago Macieira <[email protected]>
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 "k3resolver.h"
26 #include "k3resolver_p.h"
27 
28 #include <config-network.h>
29 
30 // System includes
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <sys/param.h>
34 #include <errno.h>
35 #include <netdb.h>
36 #include <time.h>
37 #include <arpa/inet.h>
38 #include <netinet/in.h>
39 #include <stdlib.h>
40 #include <unistd.h>
41 
42 // Qt includes
43 #include <QCoreApplication>
44 #include <QPointer>
45 #include <QSet>
46 #include <QUrl>
47 
48 #include <QStringList>
49 #include <QSharedData>
50 #include <QElapsedTimer>
51 
52 // KDE
53 #include <klocalizedstring.h>
54 
55 // Us
56 
57 #ifdef NEED_MUTEX
58 #ifdef __GNUC__
59 #warning "mutex"
60 #endif
61 QMutex getXXbyYYmutex;
62 #endif
63 
64 #ifdef __OpenBSD__
65 #define USE_OPENBSD 1
66 #endif
67 
68 using namespace KNetwork;
69 using namespace KNetwork::Internal;
70 
71 /////////////////////////////////////////////
72 // class KResolverEntry
73 
74 class KNetwork::KResolverEntryPrivate: public QSharedData
75 {
76 public:
77  KSocketAddress addr;
78  int socktype;
79  int protocol;
80  QString canonName;
81  QByteArray encodedName;
82 
83  inline KResolverEntryPrivate() :
84  socktype(0), protocol(0)
85  { }
86 };
87 
88 // default constructor
90  d(nullptr)
91 {
92 }
93 
94 // constructor with stuff
96  const QString &canonName, const QByteArray &encodedName) :
97  d(new KResolverEntryPrivate)
98 {
99  d->addr = addr;
100  d->socktype = socktype;
101  d->protocol = protocol;
102  d->canonName = canonName;
103  d->encodedName = encodedName;
104 }
105 
106 // constructor with even more stuff
107 KResolverEntry::KResolverEntry(const struct sockaddr *sa, quint16 salen, int socktype,
108  int protocol, const QString &canonName,
109  const QByteArray &encodedName) :
110  d(new KResolverEntryPrivate)
111 {
112  d->addr = KSocketAddress(sa, salen);
113  d->socktype = socktype;
114  d->protocol = protocol;
115  d->canonName = canonName;
116  d->encodedName = encodedName;
117 }
118 
119 // copy constructor
121  d(nullptr)
122 {
123  *this = that;
124 }
125 
126 // destructor
128 {
129 }
130 
131 // returns the socket address
133 {
134  return d->addr;
135 }
136 
137 // returns the length
138 quint16 KResolverEntry::length() const
139 {
140  return d->addr.length();
141 }
142 
143 // returns the family
145 {
146  return d->addr.family();
147 }
148 
149 // returns the canonical name
151 {
152  return d->canonName;
153 }
154 
155 // returns the encoded name
157 {
158  return d->encodedName;
159 }
160 
161 // returns the socket type
163 {
164  return d->socktype;
165 }
166 
167 // returns the protocol
169 {
170  return d->protocol;
171 }
172 
173 // assignment operator
175 {
176  d = that.d;
177  return *this;
178 }
179 
180 /////////////////////////////////////////////
181 // class KResolverResults
182 
183 class KNetwork::KResolverResultsPrivate: public QSharedData
184 {
185 public:
186  QString node, service;
187  int errorcode, syserror;
188 
189  KResolverResultsPrivate() :
190  errorcode(0), syserror(0)
191  { }
192 };
193 
194 // default constructor
196  : d(new KResolverResultsPrivate)
197 {
198 }
199 
200 // copy constructor
202  : QList<KResolverEntry>(other), d(new KResolverResultsPrivate)
203 {
204  d = other.d;
205 }
206 
207 // destructor
209 {
210 }
211 
212 // assignment operator
215 {
216  // copy over the other data
217  d = other.d;
218 
219  // now let QList do the rest of the work
221 
222  return *this;
223 }
224 
225 // gets the error code
227 {
228  return d->errorcode;
229 }
230 
231 // gets the system errno
233 {
234  return d->syserror;
235 }
236 
237 // sets the error codes
238 void KResolverResults::setError(int errorcode, int systemerror)
239 {
240  d->errorcode = errorcode;
241  d->syserror = systemerror;
242 }
243 
244 // gets the hostname
246 {
247  return d->node;
248 }
249 
250 // gets the service name
252 {
253  return d->service;
254 }
255 
256 // sets the address
258  const QString &service)
259 {
260  d->node = node;
261  d->service = service;
262 }
263 
265 {
266  /*BASE::virtual_hook( id, data );*/
267 }
268 
269 ///////////////////////
270 // class KResolver
271 
272 // default constructor
274  : QObject(parent), d(new KResolverPrivate(this))
275 {
276 }
277 
278 // constructor with host and service
279 KResolver::KResolver(const QString &nodename, const QString &servicename,
280  QObject *parent)
281  : QObject(parent), d(new KResolverPrivate(this, nodename, servicename))
282 {
283 }
284 
285 // destructor
287 {
288  cancel(false);
289  delete d;
290 }
291 
292 // get the status
293 int KResolver::status() const
294 {
295  return d->status;
296 }
297 
298 // get the error code
299 int KResolver::error() const
300 {
301  return d->errorcode;
302 }
303 
304 // get the errno
306 {
307  return d->syserror;
308 }
309 
311 {
312  return errorString(error(), systemError());
313 }
314 
315 // are we running?
317 {
318  return d->status > 0 && d->status < Success;
319 }
320 
321 // get the hostname
323 {
324  return d->input.node;
325 }
326 
327 // get the service
329 {
330  return d->input.service;
331 }
332 
333 // sets the hostname
334 void KResolver::setNodeName(const QString &nodename)
335 {
336  // don't touch those values if we're working!
337  if (!isRunning()) {
338  d->input.node = nodename;
339  d->status = Idle;
340  d->results.setAddress(nodename, d->input.service);
341  }
342 }
343 
344 // sets the service
345 void KResolver::setServiceName(const QString &service)
346 {
347  // don't change if running
348  if (!isRunning()) {
349  d->input.service = service;
350  d->status = Idle;
351  d->results.setAddress(d->input.node, service);
352  }
353 }
354 
355 // sets the address
356 void KResolver::setAddress(const QString &nodename, const QString &service)
357 {
358  setNodeName(nodename);
359  setServiceName(service);
360 }
361 
362 // get the flags
363 int KResolver::flags() const
364 {
365  return d->input.flags;
366 }
367 
368 // sets the flags
370 {
371  int oldflags = d->input.flags;
372  if (!isRunning()) {
373  d->input.flags = flags;
374  d->status = Idle;
375  }
376  return oldflags;
377 }
378 
379 // sets the family mask
380 void KResolver::setFamily(int families)
381 {
382  if (!isRunning()) {
383  d->input.familyMask = families;
384  d->status = Idle;
385  }
386 }
387 
388 // sets the socket type
390 {
391  if (!isRunning()) {
392  d->input.socktype = type;
393  d->status = Idle;
394  }
395 }
396 
397 // sets the protocol
398 void KResolver::setProtocol(int protonum, const char *name)
399 {
400  if (isRunning()) {
401  return; // can't change now
402  }
403 
404  // we copy the given protocol name. If it isn't an empty string
405  // and the protocol number was 0, we will look it up in /etc/protocols
406  // we also leave the error reporting to the actual lookup routines, in
407  // case the given protocol name doesn't exist
408 
409  d->input.protocolName = name;
410  if (protonum == 0 && name != nullptr && *name != '\0') {
411  // must look up the protocol number
412  d->input.protocol = KResolver::protocolNumber(name);
413  } else {
414  d->input.protocol = protonum;
415  }
416  d->status = Idle;
417 }
418 
420 {
421  if (!isRunning()) {
422  d->results.clear();
423 
424  // is there anything to be queued?
425  if (d->input.node.isEmpty() && d->input.service.isEmpty()) {
426  d->status = KResolver::Success;
427  emitFinished();
428  } else {
429  KResolverManager::manager()->enqueue(this, nullptr);
430  }
431  }
432 
433  return true;
434 }
435 
436 bool KResolver::wait(int msec)
437 {
438  if (!isRunning()) {
439  emitFinished();
440  return true;
441  }
442 
443  QMutexLocker locker(&d->mutex);
444 
445  if (!isRunning()) {
446  // it was running and no longer is?
447  // That means the manager has finished its processing and has posted
448  // an event for the signal to be emitted already. This means the signal
449  // will be emitted twice!
450 
451  emitFinished();
452  return true;
453  } else {
454  QElapsedTimer t;
455  t.start();
456 
457  while (!msec || t.elapsed() < msec) {
458  // wait on the manager to broadcast completion
459  d->waiting = true;
460  if (msec) {
461  KResolverManager::manager()->notifyWaiters.wait(&d->mutex, msec - t.elapsed());
462  } else {
463  KResolverManager::manager()->notifyWaiters.wait(&d->mutex);
464  }
465 
466  // the manager has processed
467  // see if this object is done
468  if (!isRunning()) {
469  // it's done
470  d->waiting = false;
471  emitFinished();
472  return true;
473  }
474  }
475 
476  // if we've got here, we've timed out
477  d->waiting = false;
478  return false;
479  }
480 }
481 
482 void KResolver::cancel(bool emitSignal)
483 {
484  KResolverManager::manager()->dequeue(this);
485  if (emitSignal) {
486  emitFinished();
487  }
488 }
489 
492 {
493  if (!isRunning()) {
494  return d->results;
495  }
496 
497  // return a dummy, empty result
499  r.setAddress(d->input.node, d->input.service);
500  r.setError(d->errorcode, d->syserror);
501  return r;
502 }
503 
505 {
506  if (static_cast<int>(e->type()) == KResolverManager::ResolutionCompleted) {
507  emitFinished();
508  return true;
509  }
510 
511  return QObject::event(e);
512 }
513 
514 void KResolver::emitFinished()
515 {
516  if (isRunning()) {
517  d->status = KResolver::Success;
518  }
519 
520  QPointer<QObject> p = this; // guard against deletion
521 
522  emit finished(d->results);
523 
524  if (p && d->deleteWhenDone) {
525  deleteLater(); // in QObject
526  }
527 }
528 
529 QString KResolver::errorString(int errorcode, int syserror)
530 {
531  // no i18n now...
532  static const char messages[] = {
533  I18N_NOOP("no error")"\0" // NoError
534  I18N_NOOP("requested family not supported for this host name")"\0" // AddrFamily
535  I18N_NOOP("temporary failure in name resolution")"\0" // TryAgain
536  I18N_NOOP("non-recoverable failure in name resolution")"\0" // NonRecoverable
537  I18N_NOOP("invalid flags")"\0" // BadFlags
538  I18N_NOOP("memory allocation failure")"\0" // Memory
539  I18N_NOOP("name or service not known")"\0" // NoName
540  I18N_NOOP("requested family not supported")"\0" // UnsupportedFamily
541  I18N_NOOP("requested service not supported for this socket type")"\0" // UnsupportedService
542  I18N_NOOP("requested socket type not supported")"\0" // UnsupportedSocketType
543  I18N_NOOP("unknown error")"\0" // UnknownError
544  I18N_NOOP2("1: the i18n'ed system error code, from errno",
545  "system error: %1")"\0" // SystemError
546  "\0"
547  };
548  // index table generated by generate_string_table.pl
549  static const int messages_indices[] = {
550  0, 9, 59, 96, 139, 153, 179, 205,
551  236, 289, 325, 0
552  };
553 
554  // handle the special value
555  if (errorcode == Canceled) {
556  return i18n("request was canceled");
557  }
558 
559  Q_ASSERT(int(SystemError) <= -(int)(sizeof(messages_indices) / sizeof(messages_indices[0])));
560  if (errorcode > 0 || errorcode < SystemError) {
561  return QString();
562  }
563 
564  QString msg = i18n(messages + messages_indices[-errorcode]);
565  if (errorcode == SystemError) {
566  msg = msg.arg(QString::fromLocal8Bit(strerror(syserror)));
567  }
568 
569  return msg;
570 }
571 
573 KResolver::resolve(const QString &host, const QString &service, int flags,
574  int families)
575 {
576  KResolver qres(host, service, QCoreApplication::instance());
577  qres.setObjectName(QString::fromLatin1("synchronous KResolver"));
578  qres.setFlags(flags);
579  qres.setFamily(families);
580  qres.start();
581  qres.wait();
582  return qres.results();
583 }
584 
585 bool KResolver::resolveAsync(QObject *userObj, const char *userSlot,
586  const QString &host, const QString &service,
587  int flags, int families)
588 {
589  KResolver *qres = new KResolver(host, service, QCoreApplication::instance());
591  userObj, userSlot);
592  qres->setObjectName(QString::fromLatin1("asynchronous KResolver"));
593  qres->setFlags(flags);
594  qres->setFamily(families);
595  qres->d->deleteWhenDone = true; // this is the only difference from the example code
596  return qres->start();
597 }
598 
600 {
601  struct protoent *pe;
602 #if !HAVE_GETPROTOBYNAME_R
603  QMutexLocker locker(&getXXbyYYmutex);
604 
605  pe = getprotobynumber(protonum);
606 
607 #else
608 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API
609  struct protoent protobuf;
610  struct protoent_data pdata;
611  ::memset(&pdata, 0, sizeof pdata);
612 
613  if (getprotobynumber_r(protonum, &protobuf, &pdata) == 0) {
614  pe = &protobuf;
615  } else {
616  pe = 0;
617  }
618 
619 # else
620  size_t buflen = 1024;
621  struct protoent protobuf;
622  char *buf;
623  do {
624  buf = new char[buflen];
625 # ifdef Q_OS_SOLARIS // Solaris uses a 4 argument getprotobynumber_r which returns struct *protoent or NULL
626  if ((pe = getprotobynumber_r(protonum, &protobuf, buf, buflen)) && (errno == ERANGE))
627 # else
628  if (getprotobynumber_r(protonum, &protobuf, buf, buflen, &pe) == ERANGE)
629 # endif
630  {
631  buflen += 1024;
632  delete [] buf;
633  } else {
634  break;
635  }
636  } while (pe == nullptr);
637 # endif
638 #endif
639 
640  // Do common processing
641  QList<QByteArray> lst;
642  if (pe != nullptr) {
643  lst.append(pe->p_name);
644  for (char **p = pe->p_aliases; *p; p++) {
645  lst.append(*p);
646  }
647  }
648 
649 #if HAVE_GETPROTOBYNAME_R
650 # ifndef USE_OPENBSD
651  delete [] buf;
652 # endif
653 #endif
654 
655  return lst;
656 }
657 
659 {
660  struct protoent *pe = nullptr;
661 #if !HAVE_GETPROTOBYNAME_R
662  QMutexLocker locker(&getXXbyYYmutex);
663 
664  pe = getprotobyname(protoname);
665 
666 #else
667 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API
668  struct protoent protobuf;
669  struct protoent_data pdata;
670  ::memset(&pdata, 0, sizeof pdata);
671 
672  if (getprotobyname_r(protoname, &protobuf, &pdata) == 0) {
673  pe = &protobuf;
674  } else {
675  pe = 0;
676  }
677 # else
678  size_t buflen = 1024;
679  struct protoent protobuf;
680  char *buf;
681  do {
682  buf = new char[buflen];
683 # ifdef Q_OS_SOLARIS // Solaris uses a 4 argument getprotobyname_r which returns struct *protoent or NULL
684  if ((pe = getprotobyname_r(protoname, &protobuf, buf, buflen)) && (errno == ERANGE))
685 # else
686  if (getprotobyname_r(protoname, &protobuf, buf, buflen, &pe) == ERANGE)
687 # endif
688  {
689  pe = nullptr;
690  buflen += 1024;
691  delete [] buf;
692  } else {
693  break;
694  }
695  } while (pe == nullptr);
696 # endif
697 #endif
698 
699  // Do common processing
700  QList<QByteArray> lst;
701  if (pe != nullptr) {
702  lst.append(pe->p_name);
703  for (char **p = pe->p_aliases; *p; p++) {
704  lst.append(*p);
705  }
706  }
707 
708 #if HAVE_GETPROTOBYNAME_R
709 # ifndef USE_OPENBSD
710  delete [] buf;
711 # endif
712 #endif
713 
714  return lst;
715 }
716 
717 int KResolver::protocolNumber(const char *protoname)
718 {
719  struct protoent *pe = nullptr;
720 #if !HAVE_GETPROTOBYNAME_R
721  QMutexLocker locker(&getXXbyYYmutex);
722 
723  pe = getprotobyname(protoname);
724 
725 #else
726 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API
727  struct protoent protobuf;
728  struct protoent_data pdata;
729  ::memset(&pdata, 0, sizeof pdata);
730 
731  if (getprotobyname_r(protoname, &protobuf, &pdata) == 0) {
732  pe = &protobuf;
733  } else {
734  pe = 0;
735  }
736 
737 # else
738  size_t buflen = 1024;
739  struct protoent protobuf;
740  char *buf;
741  do {
742  buf = new char[buflen];
743 # ifdef Q_OS_SOLARIS // Solaris uses a 4 argument getprotobyname_r which returns struct *protoent or NULL
744  if ((pe = getprotobyname_r(protoname, &protobuf, buf, buflen)) && (errno == ERANGE))
745 # else
746  if (getprotobyname_r(protoname, &protobuf, buf, buflen, &pe) == ERANGE)
747 # endif
748  {
749  pe = nullptr;
750  buflen += 1024;
751  delete [] buf;
752  } else {
753  break;
754  }
755  } while (pe == nullptr);
756 # endif
757 #endif
758 
759  // Do common processing
760  int protonum = -1;
761  if (pe != nullptr) {
762  protonum = pe->p_proto;
763  }
764 
765 #if HAVE_GETPROTOBYNAME_R
766 # ifndef USE_OPENBSD
767  delete [] buf;
768 # endif
769 #endif
770 
771  return protonum;
772 }
773 
774 int KResolver::servicePort(const char *servname, const char *protoname)
775 {
776  struct servent *se = nullptr;
777 #if !HAVE_GETSERVBYNAME_R
778  QMutexLocker locker(&getXXbyYYmutex);
779 
780  se = getservbyname(servname, protoname);
781 
782 #else
783 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API
784  struct servent servbuf;
785  struct servent_data sdata;
786  ::memset(&sdata, 0, sizeof sdata);
787  if (getservbyname_r(servname, protoname, &servbuf, &sdata) == 0) {
788  se = &servbuf;
789  } else {
790  se = 0;
791  }
792 
793 # else
794  size_t buflen = 1024;
795  struct servent servbuf;
796  char *buf;
797  do {
798  buf = new char[buflen];
799 # ifdef Q_OS_SOLARIS // Solaris uses a 5 argument getservbyname_r which returns struct *servent or NULL
800  if ((se = getservbyname_r(servname, protoname, &servbuf, buf, buflen)) && (errno == ERANGE))
801 # else
802  if (getservbyname_r(servname, protoname, &servbuf, buf, buflen, &se) == ERANGE)
803 # endif
804  {
805  se = nullptr;
806  buflen += 1024;
807  delete [] buf;
808  } else {
809  break;
810  }
811  } while (se == nullptr);
812 # endif
813 #endif
814 
815  // Do common processing
816  int servport = -1;
817  if (se != nullptr) {
818  servport = ntohs(se->s_port);
819  }
820 
821 #if HAVE_GETSERVBYNAME_R
822 # ifndef USE_OPENBSD
823  delete [] buf;
824 # endif
825 #endif
826 
827  return servport;
828 }
829 
830 QList<QByteArray> KResolver::serviceName(const char *servname, const char *protoname)
831 {
832  struct servent *se = nullptr;
833 #if !HAVE_GETSERVBYNAME_R
834  QMutexLocker locker(&getXXbyYYmutex);
835 
836  se = getservbyname(servname, protoname);
837 
838 #else
839 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API
840  struct servent servbuf;
841  struct servent_data sdata;
842  ::memset(&sdata, 0, sizeof sdata);
843  if (getservbyname_r(servname, protoname, &servbuf, &sdata) == 0) {
844  se = &servbuf;
845  } else {
846  se = 0;
847  }
848 
849 # else
850  size_t buflen = 1024;
851  struct servent servbuf;
852  char *buf;
853  do {
854  buf = new char[buflen];
855 # ifdef Q_OS_SOLARIS // Solaris uses a 5 argument getservbyname_r which returns struct *servent or NULL
856  if ((se = getservbyname_r(servname, protoname, &servbuf, buf, buflen)) && (errno == ERANGE))
857 # else
858  if (getservbyname_r(servname, protoname, &servbuf, buf, buflen, &se) == ERANGE)
859 # endif
860  {
861  se = nullptr;
862  buflen += 1024;
863  delete [] buf;
864  } else {
865  break;
866  }
867  } while (se == nullptr);
868 # endif
869 #endif
870 
871  // Do common processing
872  QList<QByteArray> lst;
873  if (se != nullptr) {
874  lst.append(se->s_name);
875  for (char **p = se->s_aliases; *p; p++) {
876  lst.append(*p);
877  }
878  }
879 
880 #if HAVE_GETSERVBYNAME_R
881 # ifndef USE_OPENBSD
882  delete [] buf;
883 # endif
884 #endif
885 
886  return lst;
887 }
888 
889 QList<QByteArray> KResolver::serviceName(int port, const char *protoname)
890 {
891  struct servent *se = nullptr;
892 #if !HAVE_GETSERVBYPORT_R
893  QMutexLocker locker(&getXXbyYYmutex);
894 
895  se = getservbyport(port, protoname);
896 
897 #else
898 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API
899  struct servent servbuf;
900  struct servent_data sdata;
901  ::memset(&sdata, 0, sizeof sdata);
902  if (getservbyport_r(port, protoname, &servbuf, &sdata) == 0) {
903  se = &servbuf;
904  } else {
905  se = 0;
906  }
907 
908 # else
909  size_t buflen = 1024;
910  struct servent servbuf;
911  char *buf;
912  do {
913  buf = new char[buflen];
914 # ifdef Q_OS_SOLARIS // Solaris uses a 5 argument getservbyport_r which returns struct *servent or NULL
915  if ((se = getservbyport_r(port, protoname, &servbuf, buf, buflen)) && (errno == ERANGE))
916 # else
917  if (getservbyport_r(port, protoname, &servbuf, buf, buflen, &se) == ERANGE)
918 # endif
919  {
920  se = nullptr;
921  buflen += 1024;
922  delete [] buf;
923  } else {
924  break;
925  }
926  } while (se == nullptr);
927 # endif
928 #endif
929 
930  // Do common processing
931  QList<QByteArray> lst;
932  if (se != nullptr) {
933  lst.append(se->s_name);
934  for (char **p = se->s_aliases; *p; p++) {
935  lst.append(*p);
936  }
937  }
938 
939 #if HAVE_GETSERVBYPORT_R
940 # ifndef USE_OPENBSD
941  delete [] buf;
942 # endif
943 #endif
944 
945  return lst;
946 }
947 
949 {
950  QByteArray name;
951  int len;
952 
953 #ifdef MAXHOSTNAMELEN
954  len = MAXHOSTNAMELEN;
955 #else
956  len = 256;
957 #endif
958 
959  while (true) {
960  name.resize(len);
961 
962  if (gethostname(name.data(), len) == 0) {
963  // Call succeeded, but it's not guaranteed to be NUL-terminated
964  // Fortunately, QByteArray is always NUL-terminated
965 
966  // Note that some systems return success even if they did truncation
967  break;
968  }
969 
970  // Call failed
971  if (errno == ENAMETOOLONG || errno == EINVAL) {
972  len += 256;
973  } else {
974  // Oops! Unknown error!
975  name.clear();
976  }
977  }
978 
979  if (name.isEmpty()) {
980  return QLatin1String("localhost");
981  }
982 
983  if (name.indexOf('.') == -1) {
984  // not fully qualified
985  // must resolve
987  if (results.isEmpty())
988  // cannot find a valid hostname!
989  {
990  return QLatin1String("localhost");
991  } else {
992  return results.first().canonicalName();
993  }
994  }
995 
996  return domainToUnicode(name);
997 }
998 
999 static void KResolver_initIdnDomains()
1000 {
1001  static bool init = false;
1002  if (!init) {
1003  QByteArray kde_use_idn = qgetenv("KDE_USE_IDN");
1004  if (!kde_use_idn.isEmpty()) {
1005  QUrl::setIdnWhitelist(QString::fromLatin1(kde_use_idn).toLower().split(QLatin1Char(':')));
1006  }
1007  init = true;
1008  }
1009 }
1010 
1011 // implement the ToAscii function, as described by IDN documents
1013 {
1014  KResolver_initIdnDomains();
1015  return QUrl::toAce(unicodeDomain);
1016 }
1017 
1019 {
1020  return domainToUnicode(QString::fromLatin1(asciiDomain));
1021 }
1022 
1023 // implement the ToUnicode function, as described by IDN documents
1025 {
1026  if (asciiDomain.isEmpty()) {
1027  return asciiDomain;
1028  }
1029  KResolver_initIdnDomains();
1030  return QUrl::fromAce(asciiDomain.toLatin1());
1031 }
1032 
1034 {
1035  return domainToUnicode(domainToAscii(domain));
1036 }
1037 
1038 void KResolver::virtual_hook(int, void *)
1039 {
1040  /*BASE::virtual_hook( id, data );*/
1041 }
1042 
1043 // here follows IDN functions
1044 // all IDN functions conform to the following documents:
1045 // RFC 3454 - Preparation of Internationalized Strings
1046 // RFC 3490 - Internationalizing Domain Names in Applications (IDNA)
1047 // RFC 3491 - Nameprep: A Stringprep Profile for
1048 // Internationalized Domain Names (IDN
1049 // RFC 3492 - Punycode: A Bootstring encoding of Unicode
1050 // for Internationalized Domain Names in Applications (IDNA)
1051 
void finished(const KNetwork::KResolverResults &results)
This signal is emitted whenever the resolution is finished, one way or another (success or failure)...
QString canonicalName() const
Retrieves the canonical name associated with this entry, if there is any.
Definition: k3resolver.cpp:150
KResolverResults & operator=(const KResolverResults &other)
Assignment operator.
Definition: k3resolver.cpp:214
#define I18N_NOOP2(context, text)
QString serviceName() const
The service name to which the resolution was/is to be performed.
Definition: k3resolver.cpp:328
QList< T > & operator=(const QList< T > &other)
QEvent::Type type() const const
QString fromAce(const QByteArray &domain)
KResolverEntry & operator=(const KResolverEntry &other)
Assignment operator.
Definition: k3resolver.cpp:174
void clear()
static QString normalizeDomain(const QString &domain)
Normalise a domain name.
int flags() const
Retrieves the flags set for the resolution.
Definition: k3resolver.cpp:363
virtual ~KResolverResults()
Destructor.
Definition: k3resolver.cpp:208
One resolution entry.
Definition: k3resolver.h:72
int error() const
Retrieve the error code in this object.
Definition: k3resolver.cpp:299
void setFamily(int families)
Sets the allowed socket families.
Definition: k3resolver.cpp:380
bool isEmpty() const const
Name and service resolution class.
Definition: k3resolver.h:312
A generic socket address.
QByteArray encodedName() const
Retrieves the encoded domain name associated with this entry, if there is any.
Definition: k3resolver.cpp:156
static KResolverResults resolve(const QString &host, const QString &service, int flags=0, int families=KResolver::InternetFamily)
Resolve the nodename and service name synchronously.
Definition: k3resolver.cpp:573
Name and service resolution results.
Definition: k3resolver.h:212
int status() const
Retrieve the current status of this object.
Definition: k3resolver.cpp:293
static QString localHostName()
Returns this machine&#39;s local hostname.
Definition: k3resolver.cpp:948
QString errorString() const
Returns the textual representation of the error in this object.
Definition: k3resolver.cpp:310
int protocol() const
Retrieves the protocol associated with this entry.
Definition: k3resolver.cpp:168
void setServiceName(const QString &service)
Sets the service name to be resolved.
Definition: k3resolver.cpp:345
KResolverResults results() const
Retrieves the results of this resolution.
Definition: k3resolver.cpp:491
virtual bool event(QEvent *e)
void resize(int size)
A namespace to store all networking-related (socket) classes.
int indexOf(char ch, int from) const const
QString fromLocal8Bit(const char *str, int size)
bool event(QEvent *) override
Handles events.
Definition: k3resolver.cpp:504
void append(const T &value)
bool wait(int msec=0)
Waits for a request to finish resolving.
Definition: k3resolver.cpp:436
int systemError() const
Retrieve the associated system error code in this object.
Definition: k3resolver.cpp:305
QByteArray toAce(const QString &domain)
bool isEmpty() const const
int systemError() const
Retrieves the system error code, if any.
Definition: k3resolver.cpp:232
void setObjectName(const QString &name)
bool isEmpty() const const
#define I18N_NOOP(text)
QCoreApplication * instance()
void deleteLater()
T & first()
~KResolverEntry()
Destructor.
Definition: k3resolver.cpp:127
static QList< QByteArray > protocolName(int protonum)
Resolves a protocol number to its names.
Definition: k3resolver.cpp:599
KSocketAddress address() const
Retrieves the socket address associated with this entry.
Definition: k3resolver.cpp:132
virtual void virtual_hook(int id, void *data)
Standard hack to add virtuals later.
static bool resolveAsync(QObject *userObj, const char *userSlot, const QString &host, const QString &service, int flags=0, int families=KResolver::InternetFamily)
Start an asynchronous name resolution.
Definition: k3resolver.cpp:585
QCA_EXPORT void init()
quint16 length() const
Retrieves the length of the socket address structure.
Definition: k3resolver.cpp:138
void setNodeName(const QString &nodename)
Sets the nodename for the resolution.
Definition: k3resolver.cpp:334
QString i18n(const char *text, const TYPE &arg...)
virtual void virtual_hook(int id, void *data)
Standard hack to add virtuals later.
Definition: k3resolver.cpp:264
QByteArray toLatin1() const const
int socketType() const
Retrieves the socket type associated with this entry.
Definition: k3resolver.cpp:162
void setProtocol(int protonum, const char *name=nullptr)
Sets the protocol we want.
Definition: k3resolver.cpp:398
static QString domainToUnicode(const QByteArray &asciiDomain)
Does the inverse of domainToAscii() and return an Unicode domain name from the given ACE-encoded doma...
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
void setAddress(const QString &host, const QString &service)
Sets the new nodename and service name.
Definition: k3resolver.cpp:257
void setIdnWhitelist(const QStringList &list)
int family() const
Retrieves the family associated with this socket address.
Definition: k3resolver.cpp:144
static int servicePort(const char *servname, const char *protoname)
Resolves a service name to its port number.
Definition: k3resolver.cpp:774
KResolverEntry()
Default constructor.
Definition: k3resolver.cpp:89
QString serviceName() const
The service name to which the resolution was performed.
Definition: k3resolver.cpp:251
char * data()
KResolverResults()
Default constructor.
Definition: k3resolver.cpp:195
void setSocketType(int type)
Sets the socket type we want.
Definition: k3resolver.cpp:389
QString fromLatin1(const char *str, int size)
QString nodeName() const
The nodename to which the resolution was/is to be performed.
Definition: k3resolver.cpp:322
~KResolver() override
Destructor.
Definition: k3resolver.cpp:286
void setError(int errorcode, int systemerror=0)
Sets the error codes.
Definition: k3resolver.cpp:238
void cancel(bool emitSignal=true)
Cancels a running request.
Definition: k3resolver.cpp:482
bool isRunning() const
Returns true if this object is currently running.
Definition: k3resolver.cpp:316
int setFlags(int flags)
Sets the flags.
Definition: k3resolver.cpp:369
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
QString nodeName() const
The nodename to which the resolution was performed.
Definition: k3resolver.cpp:245
qint64 elapsed() const const
static int protocolNumber(const char *protoname)
Resolves a protocol name to its number.
Definition: k3resolver.cpp:717
int error() const
Retrieves the error code associated with this resolution.
Definition: k3resolver.cpp:226
void setAddress(const QString &node, const QString &service)
Sets both the host and the service names.
Definition: k3resolver.cpp:356
bool start()
Starts the name resolution asynchronously.
Definition: k3resolver.cpp:419
static QByteArray domainToAscii(const QString &unicodeDomain)
Returns the domain name in an ASCII Compatible Encoding form, suitable for DNS lookups.
KResolver(QObject *parent=nullptr)
Default constructor.
Definition: k3resolver.cpp:273
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Mon Mar 8 2021 22:58:07 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.