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

KDE's Doxygen guidelines are available online.