• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • 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,QString>  symbols;
00092    // The name of this library
00093    QString                   myname;
00094    bool                      hasWorkingAsyncConnect;
00095 };
00096 
00097 
00098 KSocksTable::KSocksTable() : myname("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     QStringList _libNames;
00209     QStringList _libPaths;
00210     bool _useSocks;
00211     bool _hasSocks;
00212     KLibrary* _socksLib;
00213     KSocksTable *_st;
00214 };
00215 
00216 KSocks *KSocks::_me = 0;
00217 #ifdef __CYGWIN__
00218 bool KSocks::_disabled = true;
00219 #else
00220 bool KSocks::_disabled = false;
00221 #endif
00222 
00223 void KSocks::disable()
00224 {
00225    if (!_me)
00226       _disabled = true;
00227 }
00228 
00229 KSocks *KSocks::self() {
00230   // Note that we don't use a static deleter here. It makes no sense and tends to cause crashes.
00231   if (!_me) {
00232      if (KGlobal::hasMainComponent()) {
00233         KConfigGroup cfg(KGlobal::config(), "Socks");
00234         _me = new KSocks(&cfg);
00235      } else {
00236         _disabled = true;
00237         _me = new KSocks(0);
00238      }
00239   }
00240   return _me;
00241 }
00242 
00243 void KSocks::setConfig(const KConfigGroup *config)
00244 {
00245   // We can change the config from disabled to enabled
00246   // but not the other way around.
00247   if (_me && _disabled) {
00248      delete _me;
00249      _me = 0;
00250      _disabled = false;
00251   }
00252   if (!_me)
00253     _me = new KSocks(config);
00254 }
00255 
00256 bool KSocks::activated() { return (_me != 0L); }
00257 
00258 // Function for the KControl module to test if the socks support works.
00259 KDECORE_EXPORT bool kdeHasSocks() { return KSocks::self()->hasSocks(); }
00260 
00261 KSocks::KSocks(const KConfigGroup *config)
00262   : d(new KSocksPrivate())
00263 {
00264    if (!config)
00265       return;
00266 
00267    if (!config->readEntry("SOCKS_enable", false)) {
00268       _disabled = true;
00269    }
00270 
00271    if (_disabled)
00272       return;
00273 
00274    d->_libPaths << ""
00275                 << "/usr/lib" KDELIBSUFF "/"
00276                 << "/usr/lib/"
00277                 << "/usr/local/lib" KDELIBSUFF "/"
00278                 << "/usr/local/lib/"
00279                 << "/usr/local/socks5/lib" KDELIBSUFF "/"
00280                 << "/usr/local/socks5/lib/"
00281                 << "/opt/socks5/lib" KDELIBSUFF "/"
00282                 << "/opt/socks5/lib/";
00283    d->_libNames << "libsocks.so"                  // Dante
00284                 << "libdsocksd.so.0"              // Dante 1.1.14-2 on
00285                                                   // Debian unstable 17-12-2003
00286                 << "libsocks5.so"                 // ?
00287                 << "libsocks5_sh.so";             // NEC
00288 
00289    // Add the custom library paths here
00290    QStringList newlibs = config->readEntry("SOCKS_lib_path", QStringList());
00291 
00292    for (QStringList::Iterator it = newlibs.begin();
00293                               it != newlibs.end();
00294                               ++it) {
00295       QString thisone = *it;
00296       if (thisone[thisone.length()-1] != '/') thisone += '/';
00297       d->_libPaths << thisone;
00298       kDebug(171) << "KSocks added a new library path: " << thisone;
00299    }
00300 
00301    // Load the proper libsocks and KSocksTable
00302    KLibLoader *ll = KLibLoader::self();
00303 
00304 
00305    int _meth = config->readEntry("SOCKS_method", 1);
00306          /****       Current methods
00307           *   1) Autodetect (read: any)     2) NEC
00308           *   3) Dante                      4) Custom
00309           */
00310 
00311    if (_meth == 4) {         // try to load^H^H^H^Hguess at a custom library
00312       d->_socksLib = ll->library(config->readPathEntry("SOCKS_lib", QString()));
00313       if (d->_socksLib && d->_socksLib->resolveFunction("Rconnect")) {  // Dante compatible?
00314          d->_st = new KDanteSocksTable;
00315          d->_useSocks = true;
00316          d->_hasSocks = true;
00317       } else if (d->_socksLib && d->_socksLib->resolveFunction("connect")) { // NEC compatible?
00318          d->_st = new KNECSocksTable;
00319          d->_useSocks = true;
00320          d->_hasSocks = true;
00321       } else if (d->_socksLib) {
00322          d->_socksLib->unload();
00323          d->_socksLib = 0L;
00324       }
00325    } else              // leave this here   "else for {}"
00326    for (QStringList::Iterator pit  = d->_libPaths.begin();
00327                               !d->_hasSocks && pit != d->_libPaths.end();
00328                               ++pit)
00329    for (QStringList::Iterator it  = d->_libNames.begin();
00330                               it != d->_libNames.end();
00331                               ++it) {
00332       d->_socksLib = ll->library(*pit + *it);
00333       if (d->_socksLib) {
00334          if ((_meth == 1 || _meth == 2) &&
00335             d-> _socksLib->resolveFunction("S5LogShowThreadIDS") != 0L) {  // NEC SOCKS
00336             kDebug(171) << "Found NEC SOCKS";
00337             d->_st = new KNECSocksTable;
00338             d->_useSocks = true;
00339             d->_hasSocks = true;
00340             break;
00341          } else if ((_meth == 1 || _meth == 3) &&
00342                     d->_socksLib->resolveFunction("sockaddr2ruleaddress") != 0L) { //Dante
00343             kDebug(171) << "Found Dante SOCKS";
00344             d->_st = new KDanteSocksTable;
00345             d->_useSocks = true;
00346             d->_hasSocks = true;
00347             break;
00348          } else {
00349            d->_socksLib->unload();
00350            d->_socksLib = 0L;
00351          }
00352       }
00353    }
00354 
00355    // Load in all the symbols
00356    if (d->_st) {
00357       for (QMap<SymbolKeys,QString>::Iterator it  = d->_st->symbols.begin();
00358                                               it != d->_st->symbols.end();
00359                                               ++it) {
00360          switch(it.key()) {
00361          case S_SOCKSinit:
00362            F_SOCKSinit = (int (*)(char *))
00363                          d->_socksLib->resolveFunction(it.value().toLatin1());
00364           break;
00365          case S_connect:
00366            F_connect = (int (*)(int, const struct sockaddr *, kde_socklen_t))
00367                        d->_socksLib->resolveFunction(it.value().toLatin1());
00368           break;
00369          case S_read:
00370            F_read = (signed long int (*)(int, void *, unsigned long int))
00371                     d->_socksLib->resolveFunction(it.value().toLatin1());
00372           break;
00373          case S_write:
00374            F_write = (signed long int (*)(int, const void *, unsigned long int))
00375                      d->_socksLib->resolveFunction(it.value().toLatin1());
00376           break;
00377          case S_recvfrom:
00378            F_recvfrom = (int (*)(int, void *, unsigned long int, int,
00379                                  struct sockaddr *, kde_socklen_t *))
00380                         d->_socksLib->resolveFunction(it.value().toLatin1());
00381           break;
00382          case S_sendto:
00383            F_sendto = (int (*)(int, const void *, unsigned long int, int,
00384                                const struct sockaddr *, kde_socklen_t))
00385                       d->_socksLib->resolveFunction(it.value().toLatin1());
00386           break;
00387          case S_recv:
00388            F_recv = (int (*)(int, void *, unsigned long int, int))
00389                     d->_socksLib->resolveFunction(it.value().toLatin1());
00390           break;
00391          case S_send:
00392            F_send = (int (*)(int, const void *, unsigned long int, int))
00393                     d->_socksLib->resolveFunction(it.value().toLatin1());
00394           break;
00395          case S_getsockname:
00396            F_getsockname = (int (*)(int, struct sockaddr *, kde_socklen_t *))
00397                            d->_socksLib->resolveFunction(it.value().toLatin1());
00398           break;
00399          case S_getpeername:
00400            F_getpeername = (int (*)(int, struct sockaddr *, kde_socklen_t *))
00401                            d->_socksLib->resolveFunction(it.value().toLatin1());
00402           break;
00403          case S_accept:
00404            F_accept = (int (*)(int, struct sockaddr *, kde_socklen_t *))
00405                       d->_socksLib->resolveFunction(it.value().toLatin1());
00406           break;
00407          case S_select:
00408            F_select = (int (*)(int, fd_set *, fd_set *, fd_set *, struct timeval *))
00409                       d->_socksLib->resolveFunction(it.value().toLatin1());
00410           break;
00411          case S_listen:
00412            F_listen = (int (*)(int, int))
00413                       d->_socksLib->resolveFunction(it.value().toLatin1());
00414           break;
00415          case S_bind:
00416            F_bind = (int (*)(int, const struct sockaddr *, kde_socklen_t))
00417                     d->_socksLib->resolveFunction(it.value().toLatin1());
00418           break;
00419          default:
00420           kDebug(171) << "KSocks got a symbol it doesn't know about!";
00421           break;
00422          }
00423       }
00424 
00425       // Now we check for the critical stuff.
00426       if (F_SOCKSinit) {
00427          int rc = (*F_SOCKSinit)((char *)"KDE");
00428          if (rc != 0)
00429             stopSocks();
00430          else kDebug(171) << "SOCKS has been activated!";
00431       } else {
00432          stopSocks();
00433       }
00434    }
00435 }
00436 
00437 
00438 KSocks::~KSocks() {
00439    stopSocks();
00440    _me = 0;
00441    delete d;
00442 }
00443 
00444 void KSocks::die() {
00445    if (_me == this) {
00446       _me = 0;
00447       delete this;
00448    }
00449 }
00450 
00451 void KSocks::stopSocks() {
00452    if (d->_hasSocks) {
00453       // This library doesn't even provide the basics.
00454       // It's probably broken.  Let's abort.
00455       d->_useSocks = false;
00456       d->_hasSocks = false;
00457       if (d->_socksLib) {
00458          d->_socksLib->unload();
00459          d->_socksLib = 0L;
00460       }
00461       delete d->_st;
00462       d->_st = 0L;
00463    }
00464 }
00465 
00466 
00467 bool KSocks::usingSocks() {
00468    return d->_useSocks;
00469 }
00470 
00471 
00472 bool KSocks::hasSocks() {
00473    return d->_hasSocks;
00474 }
00475 
00476 
00477 void KSocks::disableSocks() {
00478    d->_useSocks = false;
00479 }
00480 
00481 
00482 void KSocks::enableSocks() {
00483    if (d->_hasSocks)
00484       d->_useSocks = true;
00485 }
00486 
00487 bool KSocks::hasWorkingAsyncConnect()
00488 {
00489    return (d->_useSocks && d->_st) ? d->_st->hasWorkingAsyncConnect : true;
00490 }
00491 
00492 
00493 /*
00494  *   REIMPLEMENTED FUNCTIONS FROM LIBC
00495  *
00496  */
00497 
00498 int KSocks::connect (int sockfd, const sockaddr *serv_addr,
00499                                                    kde_socklen_t addrlen) {
00500    if (d->_useSocks && F_connect)
00501       return (*F_connect)(sockfd, serv_addr, addrlen);
00502    else return ::connect(sockfd, (sockaddr*) serv_addr, (socklen_t)addrlen);
00503 }
00504 
00505 
00506 signed long int KSocks::read (int fd, void *buf, unsigned long int count) {
00507    if (d->_useSocks && F_read)
00508       return (*F_read)(fd, buf, count);
00509    else return ::read(fd, buf, count);
00510 }
00511 
00512 
00513 signed long int KSocks::write (int fd, const void *buf, unsigned long int count) {
00514    if (d->_useSocks && F_write)
00515       return (*F_write)(fd, buf, count);
00516    else return ::write(fd, buf, count);
00517 }
00518 
00519 
00520 int KSocks::recvfrom (int s, void *buf, unsigned long int len, int flags,
00521                                 sockaddr *from, kde_socklen_t *fromlen) {
00522    if (d->_useSocks && F_recvfrom) {
00523       return (*F_recvfrom)(s, buf, len, flags, from, fromlen);
00524    } else {
00525       socklen_t casted_len = (socklen_t) *fromlen;
00526       int rc = ::recvfrom(s, (char*) buf, len, flags, from, &casted_len);
00527       *fromlen = casted_len;
00528       return rc;
00529    }
00530 }
00531 
00532 
00533 int KSocks::sendto (int s, const void *msg, unsigned long int len, int flags,
00534                              const sockaddr *to, kde_socklen_t tolen) {
00535    if (d->_useSocks && F_sendto)
00536       return (*F_sendto)(s, msg, len, flags, to, tolen);
00537    else return ::sendto(s, (char*) msg, len, flags, to, (socklen_t)tolen);
00538 }
00539 
00540 
00541 int KSocks::recv (int s, void *buf, unsigned long int len, int flags) {
00542    if (d->_useSocks && F_recv)
00543       return (*F_recv)(s, buf, len, flags);
00544    else return ::recv(s, (char*) buf, len, flags);
00545 }
00546 
00547 
00548 int KSocks::send (int s, const void *msg, unsigned long int len, int flags) {
00549    if (d->_useSocks && F_send)
00550       return (*F_send)(s, msg, len, flags);
00551    else return ::send(s, (char*) msg, len, flags);
00552 }
00553 
00554 
00555 int KSocks::getsockname (int s, sockaddr *name, kde_socklen_t *namelen) {
00556    if (d->_useSocks && F_getsockname) {
00557       return (*F_getsockname)(s, name, namelen);
00558    } else {
00559      socklen_t casted_len = *namelen;
00560      int rc = ::getsockname(s, name, &casted_len);
00561      *namelen = casted_len;
00562      return rc;
00563    }
00564 }
00565 
00566 
00567 int KSocks::getpeername (int s, sockaddr *name, kde_socklen_t *namelen) {
00568    if (d->_useSocks && F_getpeername) {
00569       return (*F_getpeername)(s, name, namelen);
00570    } else {
00571       socklen_t casted_len = *namelen;
00572       int rc = ::getpeername(s, name, &casted_len);
00573       *namelen = casted_len;
00574       return rc;
00575    }
00576 }
00577 
00578 
00579 int KSocks::accept (int s, sockaddr *addr, kde_socklen_t *addrlen) {
00580    if (d->_useSocks && F_accept) {
00581      return (*F_accept)(s, addr, addrlen);
00582    } else {
00583       socklen_t casted_len = *addrlen;
00584       int rc = ::accept(s, addr, &casted_len);
00585       *addrlen = casted_len;
00586       return rc;
00587    }
00588 }
00589 
00590 
00591 int KSocks::select (int n, fd_set *readfds, fd_set *writefds,
00592                                 fd_set *exceptfds, struct timeval *timeout) {
00593    if (d->_useSocks && F_select)
00594       return (*F_select)(n, readfds, writefds, exceptfds, timeout);
00595    else return ::select(n, readfds, writefds, exceptfds, timeout);
00596 }
00597 
00598 
00599 int KSocks::listen (int s, int backlog) {
00600    if (d->_useSocks && F_listen)
00601       return (*F_listen)(s, backlog);
00602    else return ::listen(s, backlog);
00603 }
00604 
00605 
00606 int KSocks::bind (int sockfd, const sockaddr *my_addr, kde_socklen_t addrlen) {
00607    if (d->_useSocks && F_bind)
00608       return (*F_bind)(sockfd, my_addr, addrlen);
00609    else return ::bind(sockfd, my_addr, (socklen_t)addrlen);
00610 }
00611 
00612 int KSocks::bind (int sockfd, sockaddr *my_addr, kde_socklen_t addrlen) {
00613    if (d->_useSocks && F_bind)
00614       return (*F_bind)(sockfd, my_addr, addrlen);
00615    else return ::bind(sockfd, my_addr, (socklen_t)addrlen);
00616 }
00617 
00618 
00619 

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
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
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