• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KDECore

k3socks.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002    Copyright (C) 2001-2003 George Staikos <staikos@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License version 2 as published by the Free Software Foundation.
00007 
00008    This library is distributed in the hope that it will be useful,
00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011    Library General Public License for more details.
00012 
00013    You should have received a copy of the GNU Library General Public License
00014    along with this library; see the file COPYING.LIB.  If not, write to
00015    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00016    Boston, MA 02110-1301, USA.
00017 */
00018 
00019 #include <config.h>
00020 #define I_KNOW_KSOCKS_ISNT_PUBLIC
00021 #include "k3socks.h" //krazy:exclude=includes (not public: you should know you need kde_socklen_t if you use this)
00022 #undef I_KNOW_KSOCKS_ISNT_PUBLIC
00023 
00024 #ifdef HAVE_SYS_TIME_H
00025 #include <sys/time.h>
00026 #endif
00027 
00028 #include <QtCore/QFile>
00029 #include <QtCore/QCharRef>
00030 #include <QtCore/QMap>
00031 
00032 #include <klocale.h>
00033 #include <kdebug.h>
00034 #include "klibloader.h"
00035 #include <kconfig.h>
00036 
00037 #include <sys/types.h>
00038 #include <sys/socket.h>
00039 
00040 #include <unistd.h>
00041 
00042 #include <kconfiggroup.h>
00043 
00044 // DO NOT RE-ORDER THESE.
00045 enum SymbolKeys {
00046       S_SOCKSinit    =  0,
00047       S_connect      =  1,
00048       S_read         =  2,
00049       S_write        =  3,
00050       S_recvfrom     =  4,
00051       S_sendto       =  5,
00052       S_recv         =  6,
00053       S_send         =  7,
00054       S_getsockname  =  8,
00055       S_getpeername  =  9,
00056       S_accept       = 10,
00057       S_select       = 11,
00058       S_listen       = 12,
00059       S_bind         = 13
00060      };
00061 
00062 
00063 extern "C" {
00064 // Function pointer table
00065 static int     (*F_SOCKSinit)   (char *) = 0L;
00066 static int     (*F_connect)     (int, const struct sockaddr *, kde_socklen_t) = 0L;
00067 static signed long int (*F_read)        (int, void *, unsigned long int) = 0L;
00068 static signed long int (*F_write)       (int, const void *, unsigned long int) = 0L;
00069 static int     (*F_recvfrom)    (int, void *, unsigned long int, int, struct sockaddr *,
00070                                  kde_socklen_t *) = 0L;
00071 static int     (*F_sendto)      (int, const void *, unsigned long int, int,
00072                                  const struct sockaddr *, kde_socklen_t) = 0L;
00073 static int     (*F_recv)        (int, void *, unsigned long int, int) = 0L;
00074 static int     (*F_send)        (int, const void *, unsigned long int, int) = 0L;
00075 static int     (*F_getsockname) (int, struct sockaddr *, kde_socklen_t *) = 0L;
00076 static int     (*F_getpeername) (int, struct sockaddr *, kde_socklen_t *) = 0L;
00077 static int     (*F_accept)      (int, struct sockaddr *, kde_socklen_t *) = 0L;
00078 static int     (*F_select)      (int, fd_set *, fd_set *, fd_set *,
00079                                                      struct timeval *) = 0L;
00080 static int     (*F_listen)      (int, int) = 0L;
00081 static int     (*F_bind)        (int, const struct sockaddr *, kde_socklen_t) = 0L;
00082 }
00083 
00084 
00085 class KSocksTable {
00086  public:
00087    KSocksTable();
00088   virtual ~KSocksTable();
00089 
00090    // The name of each symbol and it's SOCKS replacement
00091    QMap<SymbolKeys,QByteArray>  symbols;
00092    // The name of this library
00093    QString                   myname;
00094    bool                      hasWorkingAsyncConnect;
00095 };
00096 
00097 
00098 KSocksTable::KSocksTable() : myname(QString::fromLatin1("Unknown")), hasWorkingAsyncConnect(true) {
00099 }
00100 
00101 KSocksTable::~KSocksTable() {
00102 }
00103 
00104 
00105 /*
00106  *   How to add support for a new SOCKS package.
00107  *
00108  *   1) Subclass KSocksTable as is done below and write out all the symbols
00109  *   1.b) Give the class a "myname"
00110  *   2) Make sure that all possible library names are written into the
00111  *      _libNames string list.  Don't forget that different OSes name shared
00112  *      libraries differently.  Expect .so, .sl, .a (!) (AIX does this).
00113  *   3) Find a unique symbol in the library that we can use to identify that
00114  *      library and write out the test case in the constructor
00115  *   4) Make necessary changes to the KControl module in kdebase/kcontrol/....
00116  *   5) TEST!
00117  *
00118  */
00119 
00123 
00124 
00125 //
00126 //    Support for NEC SOCKS client
00127 //
00128 
00129 class KNECSocksTable : public KSocksTable {
00130   public:
00131     KNECSocksTable();
00132     virtual ~KNECSocksTable();
00133 };
00134 
00135 
00136 KNECSocksTable::KNECSocksTable() : KSocksTable() {
00137   myname = i18n("NEC SOCKS client");
00138   symbols.insert(S_SOCKSinit,   "SOCKSinit");
00139   symbols.insert(S_connect,     "connect");
00140   symbols.insert(S_read,        "read");
00141   symbols.insert(S_write,       "write");
00142   symbols.insert(S_recvfrom,    "recvfrom");
00143   symbols.insert(S_sendto,      "sendto");
00144   symbols.insert(S_recv,        "recv");
00145   symbols.insert(S_send,        "send");
00146   symbols.insert(S_getsockname, "getsockname");
00147   symbols.insert(S_getpeername, "getpeername");
00148   symbols.insert(S_accept,      "accept");
00149   symbols.insert(S_select,      "select");
00150   symbols.insert(S_listen,      "listen");
00151   symbols.insert(S_bind,        "bind");
00152 }
00153 
00154 KNECSocksTable::~KNECSocksTable() {
00155 }
00156 
00157 
00158 
00159 
00160 //
00161 //    Support for Dante SOCKS client
00162 //
00163 
00164 class KDanteSocksTable : public KSocksTable {
00165   public:
00166     KDanteSocksTable();
00167     virtual ~KDanteSocksTable();
00168 };
00169 
00170 KDanteSocksTable::KDanteSocksTable() : KSocksTable() {
00171   hasWorkingAsyncConnect = false;
00172   myname = i18n("Dante SOCKS client");
00173   symbols.insert(S_SOCKSinit,   "SOCKSinit");
00174   symbols.insert(S_connect,     "Rconnect");
00175   symbols.insert(S_read,        "Rread");
00176   symbols.insert(S_write,       "Rwrite");
00177   symbols.insert(S_recvfrom,    "Rrecvfrom");
00178   symbols.insert(S_sendto,      "Rsendto");
00179   symbols.insert(S_recv,        "Rrecv");
00180   symbols.insert(S_send,        "Rsend");
00181   symbols.insert(S_getsockname, "Rgetsockname");
00182   symbols.insert(S_getpeername, "Rgetpeername");
00183   symbols.insert(S_accept,      "Raccept");
00184   symbols.insert(S_select,      "Rselect");
00185   symbols.insert(S_listen,      "Rlisten");
00186   symbols.insert(S_bind,        "Rbind");
00187 }
00188 
00189 
00190 KDanteSocksTable::~KDanteSocksTable() {
00191 }
00192 
00193 
00194 
00198 
00199 class KSocks::KSocksPrivate
00200 {
00201 public:
00202     KSocksPrivate() :
00203         _useSocks(false),
00204         _hasSocks(false),
00205         _socksLib(0L),
00206         _st(0L)
00207     {}
00208 
00209     static int debugArea() { static int s_area = KDebug::registerArea("kdecore (KSocks)"); return s_area; }
00210 
00211     QList<QByteArray> _libNames;
00212     QList<QByteArray> _libPaths;
00213     bool _useSocks;
00214     bool _hasSocks;
00215     KLibrary* _socksLib;
00216     KSocksTable *_st;
00217 };
00218 
00219 KSocks *KSocks::_me = 0;
00220 #ifdef __CYGWIN__
00221 bool KSocks::_disabled = true;
00222 #else
00223 bool KSocks::_disabled = false;
00224 #endif
00225 
00226 void KSocks::disable()
00227 {
00228    if (!_me)
00229       _disabled = true;
00230 }
00231 
00232 KSocks *KSocks::self() {
00233   // Note that we don't use a static deleter here. It makes no sense and tends to cause crashes.
00234   if (!_me) {
00235      if (KGlobal::hasMainComponent()) {
00236         KConfigGroup cfg(KGlobal::config(), "Socks");
00237         _me = new KSocks(&cfg);
00238      } else {
00239         _disabled = true;
00240         _me = new KSocks(0);
00241      }
00242   }
00243   return _me;
00244 }
00245 
00246 void KSocks::setConfig(const KConfigGroup *config)
00247 {
00248   // We can change the config from disabled to enabled
00249   // but not the other way around.
00250   if (_me && _disabled) {
00251      delete _me;
00252      _me = 0;
00253      _disabled = false;
00254   }
00255   if (!_me)
00256     _me = new KSocks(config);
00257 }
00258 
00259 bool KSocks::activated() { return (_me != 0L); }
00260 
00261 // Function for the KControl module to test if the socks support works.
00262 KDECORE_EXPORT bool kdeHasSocks() { return KSocks::self()->hasSocks(); }
00263 
00264 KSocks::KSocks(const KConfigGroup *config)
00265   : d(new KSocksPrivate())
00266 {
00267    if (!config)
00268       return;
00269 
00270    if (!config->readEntry("SOCKS_enable", false)) {
00271       _disabled = true;
00272    }
00273 
00274    if (_disabled)
00275       return;
00276 
00277    d->_libPaths << ""
00278                 << "/usr/lib" KDELIBSUFF "/"
00279                 << "/usr/lib/"
00280                 << "/usr/local/lib" KDELIBSUFF "/"
00281                 << "/usr/local/lib/"
00282                 << "/usr/local/socks5/lib" KDELIBSUFF "/"
00283                 << "/usr/local/socks5/lib/"
00284                 << "/opt/socks5/lib" KDELIBSUFF "/"
00285                 << "/opt/socks5/lib/";
00286    d->_libNames << "libsocks.so"                  // Dante
00287                 << "libdsocksd.so.0"              // Dante 1.1.14-2 on
00288                                                   // Debian unstable 17-12-2003
00289                 << "libsocks5.so"                 // ?
00290                 << "libsocks5_sh.so";             // NEC
00291 
00292    // Add the custom library paths here
00293    QStringList newlibs = config->readEntry("SOCKS_lib_path", QStringList());
00294 
00295    for (QStringList::Iterator it = newlibs.begin();
00296                               it != newlibs.end();
00297                               ++it) {
00298       QString thisone = *it;
00299       if (thisone[thisone.length()-1] != QLatin1Char('/'))
00300           thisone += QLatin1Char('/');
00301       d->_libPaths << QFile::encodeName(thisone);
00302       kDebug(d->debugArea()) << "KSocks added a new library path: " << thisone;
00303    }
00304 
00305    // Load the proper libsocks and KSocksTable
00306    KLibLoader *ll = KLibLoader::self();
00307 
00308 
00309    int _meth = config->readEntry("SOCKS_method", 1);
00310          /****       Current methods
00311           *   1) Autodetect (read: any)     2) NEC
00312           *   3) Dante                      4) Custom
00313           */
00314 
00315    if (_meth == 4) {         // try to load^H^H^H^Hguess at a custom library
00316       d->_socksLib = ll->library(config->readPathEntry("SOCKS_lib", QString()));
00317       if (d->_socksLib && d->_socksLib->resolveFunction("Rconnect")) {  // Dante compatible?
00318          d->_st = new KDanteSocksTable;
00319          d->_useSocks = true;
00320          d->_hasSocks = true;
00321       } else if (d->_socksLib && d->_socksLib->resolveFunction("connect")) { // NEC compatible?
00322          d->_st = new KNECSocksTable;
00323          d->_useSocks = true;
00324          d->_hasSocks = true;
00325       } else if (d->_socksLib) {
00326          d->_socksLib->unload();
00327          d->_socksLib = 0L;
00328       }
00329    } else              // leave this here   "else for {}"
00330    for (QList<QByteArray>::const_iterator pit  = d->_libPaths.constBegin();
00331                               !d->_hasSocks && pit != d->_libPaths.constEnd();
00332                               ++pit)
00333    for (QList<QByteArray>::const_iterator it  = d->_libNames.constBegin();
00334                               it != d->_libNames.constEnd();
00335                               ++it) {
00336       d->_socksLib = ll->library(QString::fromLatin1(*pit + *it));
00337       if (d->_socksLib) {
00338          if ((_meth == 1 || _meth == 2) &&
00339             d-> _socksLib->resolveFunction("S5LogShowThreadIDS") != 0L) {  // NEC SOCKS
00340             kDebug(d->debugArea()) << "Found NEC SOCKS";
00341             d->_st = new KNECSocksTable;
00342             d->_useSocks = true;
00343             d->_hasSocks = true;
00344             break;
00345          } else if ((_meth == 1 || _meth == 3) &&
00346                     d->_socksLib->resolveFunction("sockaddr2ruleaddress") != 0L) { //Dante
00347             kDebug(d->debugArea()) << "Found Dante SOCKS";
00348             d->_st = new KDanteSocksTable;
00349             d->_useSocks = true;
00350             d->_hasSocks = true;
00351             break;
00352          } else {
00353            d->_socksLib->unload();
00354            d->_socksLib = 0L;
00355          }
00356       }
00357    }
00358 
00359    // Load in all the symbols
00360    if (d->_st) {
00361       for (QMap<SymbolKeys,QByteArray>::Iterator it  = d->_st->symbols.begin();
00362                                               it != d->_st->symbols.end();
00363                                               ++it) {
00364          switch(it.key()) {
00365          case S_SOCKSinit:
00366            F_SOCKSinit = (int (*)(char *))
00367                          d->_socksLib->resolveFunction(it.value());
00368           break;
00369          case S_connect:
00370            F_connect = (int (*)(int, const struct sockaddr *, kde_socklen_t))
00371                        d->_socksLib->resolveFunction(it.value());
00372           break;
00373          case S_read:
00374            F_read = (signed long int (*)(int, void *, unsigned long int))
00375                     d->_socksLib->resolveFunction(it.value());
00376           break;
00377          case S_write:
00378            F_write = (signed long int (*)(int, const void *, unsigned long int))
00379                      d->_socksLib->resolveFunction(it.value());
00380           break;
00381          case S_recvfrom:
00382            F_recvfrom = (int (*)(int, void *, unsigned long int, int,
00383                                  struct sockaddr *, kde_socklen_t *))
00384                         d->_socksLib->resolveFunction(it.value());
00385           break;
00386          case S_sendto:
00387            F_sendto = (int (*)(int, const void *, unsigned long int, int,
00388                                const struct sockaddr *, kde_socklen_t))
00389                       d->_socksLib->resolveFunction(it.value());
00390           break;
00391          case S_recv:
00392            F_recv = (int (*)(int, void *, unsigned long int, int))
00393                     d->_socksLib->resolveFunction(it.value());
00394           break;
00395          case S_send:
00396            F_send = (int (*)(int, const void *, unsigned long int, int))
00397                     d->_socksLib->resolveFunction(it.value());
00398           break;
00399          case S_getsockname:
00400            F_getsockname = (int (*)(int, struct sockaddr *, kde_socklen_t *))
00401                            d->_socksLib->resolveFunction(it.value());
00402           break;
00403          case S_getpeername:
00404            F_getpeername = (int (*)(int, struct sockaddr *, kde_socklen_t *))
00405                            d->_socksLib->resolveFunction(it.value());
00406           break;
00407          case S_accept:
00408            F_accept = (int (*)(int, struct sockaddr *, kde_socklen_t *))
00409                       d->_socksLib->resolveFunction(it.value());
00410           break;
00411          case S_select:
00412            F_select = (int (*)(int, fd_set *, fd_set *, fd_set *, struct timeval *))
00413                       d->_socksLib->resolveFunction(it.value());
00414           break;
00415          case S_listen:
00416            F_listen = (int (*)(int, int))
00417                       d->_socksLib->resolveFunction(it.value());
00418           break;
00419          case S_bind:
00420            F_bind = (int (*)(int, const struct sockaddr *, kde_socklen_t))
00421                     d->_socksLib->resolveFunction(it.value());
00422           break;
00423          default:
00424           kDebug(d->debugArea()) << "KSocks got a symbol it doesn't know about!";
00425           break;
00426          }
00427       }
00428 
00429       // Now we check for the critical stuff.
00430       if (F_SOCKSinit) {
00431          int rc = (*F_SOCKSinit)((char *)"KDE");
00432          if (rc != 0)
00433             stopSocks();
00434          else kDebug(d->debugArea()) << "SOCKS has been activated!";
00435       } else {
00436          stopSocks();
00437       }
00438    }
00439 }
00440 
00441 
00442 KSocks::~KSocks() {
00443    stopSocks();
00444    _me = 0;
00445    delete d;
00446 }
00447 
00448 void KSocks::die() {
00449    if (_me == this) {
00450       _me = 0;
00451       delete this;
00452    }
00453 }
00454 
00455 void KSocks::stopSocks() {
00456    if (d->_hasSocks) {
00457       // This library doesn't even provide the basics.
00458       // It's probably broken.  Let's abort.
00459       d->_useSocks = false;
00460       d->_hasSocks = false;
00461       if (d->_socksLib) {
00462          d->_socksLib->unload();
00463          d->_socksLib = 0L;
00464       }
00465       delete d->_st;
00466       d->_st = 0L;
00467    }
00468 }
00469 
00470 
00471 bool KSocks::usingSocks() {
00472    return d->_useSocks;
00473 }
00474 
00475 
00476 bool KSocks::hasSocks() {
00477    return d->_hasSocks;
00478 }
00479 
00480 
00481 void KSocks::disableSocks() {
00482    d->_useSocks = false;
00483 }
00484 
00485 
00486 void KSocks::enableSocks() {
00487    if (d->_hasSocks)
00488       d->_useSocks = true;
00489 }
00490 
00491 bool KSocks::hasWorkingAsyncConnect()
00492 {
00493    return (d->_useSocks && d->_st) ? d->_st->hasWorkingAsyncConnect : true;
00494 }
00495 
00496 
00497 /*
00498  *   REIMPLEMENTED FUNCTIONS FROM LIBC
00499  *
00500  */
00501 
00502 int KSocks::connect (int sockfd, const sockaddr *serv_addr,
00503                                                    kde_socklen_t addrlen) {
00504    if (d->_useSocks && F_connect)
00505       return (*F_connect)(sockfd, serv_addr, addrlen);
00506    else return ::connect(sockfd, (sockaddr*) serv_addr, (socklen_t)addrlen);
00507 }
00508 
00509 
00510 signed long int KSocks::read (int fd, void *buf, unsigned long int count) {
00511    if (d->_useSocks && F_read)
00512       return (*F_read)(fd, buf, count);
00513    else return ::read(fd, buf, count);
00514 }
00515 
00516 
00517 signed long int KSocks::write (int fd, const void *buf, unsigned long int count) {
00518    if (d->_useSocks && F_write)
00519       return (*F_write)(fd, buf, count);
00520    else return ::write(fd, buf, count);
00521 }
00522 
00523 
00524 int KSocks::recvfrom (int s, void *buf, unsigned long int len, int flags,
00525                                 sockaddr *from, kde_socklen_t *fromlen) {
00526    if (d->_useSocks && F_recvfrom) {
00527       return (*F_recvfrom)(s, buf, len, flags, from, fromlen);
00528    } else {
00529       socklen_t casted_len = (socklen_t) *fromlen;
00530       int rc = ::recvfrom(s, (char*) buf, len, flags, from, &casted_len);
00531       *fromlen = casted_len;
00532       return rc;
00533    }
00534 }
00535 
00536 
00537 int KSocks::sendto (int s, const void *msg, unsigned long int len, int flags,
00538                              const sockaddr *to, kde_socklen_t tolen) {
00539    if (d->_useSocks && F_sendto)
00540       return (*F_sendto)(s, msg, len, flags, to, tolen);
00541    else return ::sendto(s, (char*) msg, len, flags, to, (socklen_t)tolen);
00542 }
00543 
00544 
00545 int KSocks::recv (int s, void *buf, unsigned long int len, int flags) {
00546    if (d->_useSocks && F_recv)
00547       return (*F_recv)(s, buf, len, flags);
00548    else return ::recv(s, (char*) buf, len, flags);
00549 }
00550 
00551 
00552 int KSocks::send (int s, const void *msg, unsigned long int len, int flags) {
00553    if (d->_useSocks && F_send)
00554       return (*F_send)(s, msg, len, flags);
00555    else return ::send(s, (char*) msg, len, flags);
00556 }
00557 
00558 
00559 int KSocks::getsockname (int s, sockaddr *name, kde_socklen_t *namelen) {
00560    if (d->_useSocks && F_getsockname) {
00561       return (*F_getsockname)(s, name, namelen);
00562    } else {
00563      socklen_t casted_len = *namelen;
00564      int rc = ::getsockname(s, name, &casted_len);
00565      *namelen = casted_len;
00566      return rc;
00567    }
00568 }
00569 
00570 
00571 int KSocks::getpeername (int s, sockaddr *name, kde_socklen_t *namelen) {
00572    if (d->_useSocks && F_getpeername) {
00573       return (*F_getpeername)(s, name, namelen);
00574    } else {
00575       socklen_t casted_len = *namelen;
00576       int rc = ::getpeername(s, name, &casted_len);
00577       *namelen = casted_len;
00578       return rc;
00579    }
00580 }
00581 
00582 
00583 int KSocks::accept (int s, sockaddr *addr, kde_socklen_t *addrlen) {
00584    if (d->_useSocks && F_accept) {
00585      return (*F_accept)(s, addr, addrlen);
00586    } else {
00587       socklen_t casted_len = *addrlen;
00588       int rc = ::accept(s, addr, &casted_len);
00589       *addrlen = casted_len;
00590       return rc;
00591    }
00592 }
00593 
00594 
00595 int KSocks::select (int n, fd_set *readfds, fd_set *writefds,
00596                                 fd_set *exceptfds, struct timeval *timeout) {
00597    if (d->_useSocks && F_select)
00598       return (*F_select)(n, readfds, writefds, exceptfds, timeout);
00599    else return ::select(n, readfds, writefds, exceptfds, timeout);
00600 }
00601 
00602 
00603 int KSocks::listen (int s, int backlog) {
00604    if (d->_useSocks && F_listen)
00605       return (*F_listen)(s, backlog);
00606    else return ::listen(s, backlog);
00607 }
00608 
00609 
00610 int KSocks::bind (int sockfd, const sockaddr *my_addr, kde_socklen_t addrlen) {
00611    if (d->_useSocks && F_bind)
00612       return (*F_bind)(sockfd, my_addr, addrlen);
00613    else return ::bind(sockfd, my_addr, (socklen_t)addrlen);
00614 }
00615 
00616 int KSocks::bind (int sockfd, sockaddr *my_addr, kde_socklen_t addrlen) {
00617    if (d->_useSocks && F_bind)
00618       return (*F_bind)(sockfd, my_addr, addrlen);
00619    else return ::bind(sockfd, my_addr, (socklen_t)addrlen);
00620 }
00621 
00622 
00623 

KDECore

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal