• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kio

kacl.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002    Copyright (C) 2005 Till Adam <adam@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 as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017    Boston, MA 02110-1301, USA.
00018 */
00019 // $Id: kacl.cpp 424977 2005-06-13 15:13:22Z tilladam $
00020 
00021 #ifdef HAVE_CONFIG_H
00022 #include <config.h>
00023 #endif
00024 
00025 #include <sys/types.h>
00026 #include <pwd.h>
00027 #include <grp.h>
00028 #include <sys/stat.h>
00029 #ifdef USE_POSIX_ACL
00030 #ifdef HAVE_NON_POSIX_ACL_EXTENSIONS
00031 #include <acl/libacl.h>
00032 #else
00033 #include <posixacladdons.h>
00034 #endif
00035 #endif
00036 #include <qintdict.h>
00037 
00038 #include <kdebug.h>
00039 
00040 #include "kacl.h"
00041 
00042 
00043 #ifdef USE_POSIX_ACL
00044 static void printACL( acl_t acl, const QString &comment );
00045 static QString aclAsString(const acl_t acl);
00046 #endif
00047 
00048 class KACL::KACLPrivate {
00049 public:
00050     KACLPrivate() : m_acl( 0 ) { init(); }
00051 #ifdef USE_POSIX_ACL
00052     KACLPrivate( acl_t acl )
00053         : m_acl( acl ) { init(); }
00054     ~KACLPrivate() { if ( m_acl ) acl_free( m_acl ); }
00055 #endif
00056     void init() {
00057         m_usercache.setAutoDelete( true );
00058         m_groupcache.setAutoDelete( true );
00059     }
00060     // helpers
00061 #ifdef USE_POSIX_ACL
00062     bool setMaskPermissions( unsigned short v );
00063     QString getUserName( uid_t uid ) const;
00064     QString getGroupName( gid_t gid ) const;
00065     bool setAllUsersOrGroups( const QValueList< QPair<QString, unsigned short> > &list, acl_tag_t type );
00066     bool setNamedUserOrGroupPermissions( const QString& name, unsigned short permissions, acl_tag_t type );
00067 
00068     acl_t m_acl;
00069 #else
00070     int m_acl;
00071 #endif
00072     mutable QIntDict<QString> m_usercache;
00073     mutable QIntDict<QString> m_groupcache;
00074 };
00075 
00076 KACL::KACL( const QString &aclString )
00077     : d( new KACLPrivate )
00078 {
00079     setACL( aclString );
00080 }
00081 
00082 KACL::KACL( mode_t basePermissions )
00083 #ifdef USE_POSIX_ACL
00084     : d( new KACLPrivate( acl_from_mode( basePermissions ) ) )
00085 #else
00086     : d( new KACLPrivate )
00087 #endif
00088 {
00089 #ifndef USE_POSIX_ACL
00090     Q_UNUSED( basePermissions );
00091 #endif
00092 }
00093 
00094 KACL::KACL()
00095     : d( new KACLPrivate )
00096 {
00097 }
00098 
00099 KACL::KACL( const KACL& rhs )
00100     : d( new KACLPrivate )
00101 {
00102     setACL( rhs.asString() );
00103 }
00104 
00105 KACL::~KACL()
00106 {
00107     delete d;
00108 }
00109 
00110 bool KACL::operator==( const KACL& rhs ) const {
00111 #ifdef USE_POSIX_ACL
00112     return ( acl_cmp( d->m_acl, rhs.d->m_acl ) == 0 );
00113 #else
00114     Q_UNUSED( rhs );
00115     return true;
00116 #endif
00117 }
00118 
00119 bool KACL::isValid() const
00120 {
00121     bool valid = false;
00122 #ifdef USE_POSIX_ACL
00123     if ( d->m_acl ) {
00124         valid = ( acl_valid( d->m_acl ) == 0 );
00125     }
00126 #endif
00127     return valid;
00128 }
00129 
00130 bool KACL::isExtended() const
00131 {
00132 #ifdef USE_POSIX_ACL
00133     return ( acl_equiv_mode( d->m_acl, NULL ) != 0 );
00134 #else
00135     return false;
00136 #endif
00137 }
00138 
00139 #ifdef USE_POSIX_ACL
00140 static acl_entry_t entryForTag( acl_t acl, acl_tag_t tag )
00141 {
00142     acl_entry_t entry;
00143     int ret = acl_get_entry( acl, ACL_FIRST_ENTRY, &entry );
00144     while ( ret == 1 ) {
00145         acl_tag_t currentTag;
00146         acl_get_tag_type( entry, &currentTag );
00147         if ( currentTag == tag )
00148             return entry;
00149         ret = acl_get_entry( acl, ACL_NEXT_ENTRY, &entry );
00150     }
00151     return 0;
00152 }
00153 
00154 static unsigned short entryToPermissions( acl_entry_t entry )
00155 {
00156     if ( entry == 0 ) return 0;
00157     acl_permset_t permset;
00158     if ( acl_get_permset( entry, &permset ) != 0 ) return 0;
00159     return( acl_get_perm( permset, ACL_READ ) << 2 |
00160             acl_get_perm( permset, ACL_WRITE ) << 1 |
00161             acl_get_perm( permset, ACL_EXECUTE ) );
00162 }
00163 
00164 static void permissionsToEntry( acl_entry_t entry, unsigned short v )
00165 {
00166     if ( entry == 0 ) return;
00167     acl_permset_t permset;
00168     if ( acl_get_permset( entry, &permset ) != 0 ) return;
00169     acl_clear_perms( permset );
00170     if ( v & 4 ) acl_add_perm( permset, ACL_READ );
00171     if ( v & 2 ) acl_add_perm( permset, ACL_WRITE );
00172     if ( v & 1 ) acl_add_perm( permset, ACL_EXECUTE );
00173 }
00174 
00175 static void printACL( acl_t acl, const QString &comment )
00176 {
00177     kdDebug() << comment << aclAsString( acl ) << endl;
00178 }
00179 
00180 static int getUidForName( const QString& name )
00181 {
00182     struct passwd *user = getpwnam( name.latin1() );
00183     if ( user )
00184         return user->pw_uid;
00185     else
00186         return -1;
00187 }
00188 
00189 static int getGidForName( const QString& name )
00190 {
00191     struct group *group = getgrnam( name.latin1() );
00192     if ( group )
00193         return group->gr_gid;
00194     else
00195         return -1;
00196 }
00197 #endif
00198 // ------------------ begin API implementation ------------
00199 
00200 unsigned short KACL::ownerPermissions() const
00201 {
00202 #ifdef USE_POSIX_ACL
00203     return entryToPermissions( entryForTag( d->m_acl, ACL_USER_OBJ ) );
00204 #else
00205     return 0;
00206 #endif
00207 }
00208 
00209 bool KACL::setOwnerPermissions( unsigned short v )
00210 {
00211 #ifdef USE_POSIX_ACL
00212     permissionsToEntry( entryForTag( d->m_acl, ACL_USER_OBJ ), v );
00213 #else
00214     Q_UNUSED( v );
00215 #endif
00216     return true;
00217 }
00218 
00219 unsigned short KACL::owningGroupPermissions() const
00220 {
00221 #ifdef USE_POSIX_ACL
00222     return entryToPermissions( entryForTag( d->m_acl, ACL_GROUP_OBJ ) );
00223 #else
00224     return 0;
00225 #endif
00226 }
00227 
00228 bool KACL::setOwningGroupPermissions( unsigned short v )
00229 {
00230 #ifdef USE_POSIX_ACL
00231     permissionsToEntry( entryForTag( d->m_acl, ACL_GROUP_OBJ ), v );
00232 #else
00233     Q_UNUSED( v );
00234 #endif
00235     return true;
00236 }
00237 
00238 unsigned short KACL::othersPermissions() const
00239 {
00240 #ifdef USE_POSIX_ACL
00241     return entryToPermissions( entryForTag( d->m_acl, ACL_OTHER ) );
00242 #else
00243     return 0;
00244 #endif
00245 }
00246 
00247 bool KACL::setOthersPermissions( unsigned short v )
00248 {
00249 #ifdef USE_POSIX_ACL
00250     permissionsToEntry( entryForTag( d->m_acl, ACL_OTHER ), v );
00251 #else
00252     Q_UNUSED( v );
00253 #endif
00254     return true;
00255 }
00256 
00257 mode_t KACL::basePermissions() const
00258 {
00259     mode_t perms( 0 );
00260 #ifdef USE_POSIX_ACL
00261     if ( ownerPermissions() & ACL_READ ) perms |= S_IRUSR;
00262     if ( ownerPermissions() & ACL_WRITE ) perms |= S_IWUSR;
00263     if ( ownerPermissions() & ACL_EXECUTE ) perms |= S_IXUSR;
00264     if ( owningGroupPermissions() & ACL_READ ) perms |= S_IRGRP;
00265     if ( owningGroupPermissions() & ACL_WRITE ) perms |= S_IWGRP;
00266     if ( owningGroupPermissions() & ACL_EXECUTE ) perms |= S_IXGRP;
00267     if ( othersPermissions() & ACL_READ ) perms |= S_IROTH;
00268     if ( othersPermissions() & ACL_WRITE ) perms |= S_IWOTH;
00269     if ( othersPermissions() & ACL_EXECUTE ) perms |= S_IXOTH;
00270 #endif
00271    return perms;
00272 }
00273 
00274 unsigned short KACL::maskPermissions( bool &exists ) const
00275 {
00276     exists = true;
00277 #ifdef USE_POSIX_ACL
00278     acl_entry_t entry = entryForTag( d->m_acl, ACL_MASK );
00279     if ( entry == 0 ) {
00280         exists = false;
00281         return 0;
00282     }
00283     return entryToPermissions( entry );
00284 #else
00285     return 0;
00286 #endif
00287 }
00288 
00289 #ifdef USE_POSIX_ACL
00290 bool KACL::KACLPrivate::setMaskPermissions( unsigned short v )
00291 {
00292     acl_entry_t entry = entryForTag( m_acl, ACL_MASK );
00293     if ( entry == 0 ) {
00294         acl_create_entry( &m_acl, &entry );
00295         acl_set_tag_type( entry, ACL_MASK );
00296     }
00297     permissionsToEntry( entry, v );
00298     return true;
00299 }
00300 #endif
00301 
00302 bool KACL::setMaskPermissions( unsigned short v )
00303 {
00304 #ifdef USE_POSIX_ACL
00305     return d->setMaskPermissions( v );
00306 #else
00307     Q_UNUSED( v );
00308     return true;
00309 #endif
00310 }
00311 
00312 /**************************
00313  * Deal with named users  *
00314  **************************/
00315 unsigned short KACL::namedUserPermissions( const QString& name, bool *exists ) const
00316 {
00317 #ifdef USE_POSIX_ACL
00318     acl_entry_t entry;
00319     uid_t id;
00320     *exists = false;
00321     int ret = acl_get_entry( d->m_acl, ACL_FIRST_ENTRY, &entry );
00322     while ( ret == 1 ) {
00323         acl_tag_t currentTag;
00324         acl_get_tag_type( entry, &currentTag );
00325         if ( currentTag ==  ACL_USER ) {
00326             id = *( (uid_t*) acl_get_qualifier( entry ) );
00327             if ( d->getUserName( id ) == name ) {
00328                 *exists = true;
00329                 return entryToPermissions( entry );
00330             }
00331         }
00332         ret = acl_get_entry( d->m_acl, ACL_NEXT_ENTRY, &entry );
00333     }
00334 #else
00335     Q_UNUSED( name );
00336     Q_UNUSED( exists );
00337 #endif
00338     return 0;
00339 }
00340 
00341 #ifdef USE_POSIX_ACL
00342 bool KACL::KACLPrivate::setNamedUserOrGroupPermissions( const QString& name, unsigned short permissions, acl_tag_t type )
00343 {
00344     bool allIsWell = true;
00345     acl_t newACL = acl_dup( m_acl );
00346     acl_entry_t entry;
00347     bool createdNewEntry = false;
00348     bool found = false;
00349     int ret = acl_get_entry( newACL, ACL_FIRST_ENTRY, &entry );
00350     while ( ret == 1 ) {
00351         acl_tag_t currentTag;
00352         acl_get_tag_type( entry, &currentTag );
00353         if ( currentTag == type ) {
00354             int id = * (int*)acl_get_qualifier( entry );
00355             const QString entryName = type == ACL_USER? getUserName( id ): getGroupName( id );
00356             if ( entryName == name ) {
00357               // found him, update
00358               permissionsToEntry( entry, permissions );
00359               found = true;
00360               break;
00361             }
00362         }
00363         ret = acl_get_entry( newACL, ACL_NEXT_ENTRY, &entry );
00364     }
00365     if ( !found ) {
00366         acl_create_entry( &newACL, &entry );
00367         acl_set_tag_type(  entry, type );
00368         int id = type == ACL_USER? getUidForName( name ): getGidForName( name );
00369         if ( id == -1 ||  acl_set_qualifier( entry, &id ) != 0 ) {
00370             acl_delete_entry( newACL, entry );
00371             allIsWell = false;
00372         } else {
00373             permissionsToEntry( entry, permissions );
00374             createdNewEntry = true;
00375         }
00376     }
00377     if ( allIsWell && createdNewEntry ) {
00378         // 23.1.1 of 1003.1e states that as soon as there is a named user or
00379         // named group entry, there needs to be a mask entry as well, so add
00380         // one, if the user hasn't explicitely set one.
00381         if ( entryForTag( newACL, ACL_MASK ) == 0 ) {
00382             acl_calc_mask( &newACL );
00383         }
00384     }
00385 
00386     if ( !allIsWell || acl_valid( newACL ) != 0 ) {
00387         acl_free( newACL );
00388         allIsWell = false;
00389     } else {
00390         acl_free( m_acl );
00391         m_acl = newACL;
00392     }
00393     return allIsWell;
00394 }
00395 #endif
00396 
00397 bool KACL::setNamedUserPermissions( const QString& name, unsigned short permissions )
00398 {
00399 #ifdef USE_POSIX_ACL
00400     return d->setNamedUserOrGroupPermissions( name, permissions, ACL_USER );
00401 #else
00402     Q_UNUSED( name );
00403     Q_UNUSED( permissions );
00404     return true;
00405 #endif
00406 }
00407 
00408 ACLUserPermissionsList KACL::allUserPermissions() const
00409 {
00410     ACLUserPermissionsList list;
00411 #ifdef USE_POSIX_ACL
00412     acl_entry_t entry;
00413     uid_t id;
00414     int ret = acl_get_entry( d->m_acl, ACL_FIRST_ENTRY, &entry );
00415     while ( ret == 1 ) {
00416         acl_tag_t currentTag;
00417         acl_get_tag_type( entry, &currentTag );
00418         if ( currentTag ==  ACL_USER ) {
00419             id = *( (uid_t*) acl_get_qualifier( entry ) );
00420             QString name = d->getUserName( id );
00421             unsigned short permissions = entryToPermissions( entry );
00422             ACLUserPermissions pair = qMakePair( name, permissions );
00423             list.append( pair );
00424         }
00425         ret = acl_get_entry( d->m_acl, ACL_NEXT_ENTRY, &entry );
00426     }
00427 #endif
00428     return list;
00429 }
00430 
00431 #ifdef USE_POSIX_ACL
00432 bool KACL::KACLPrivate::setAllUsersOrGroups( const QValueList< QPair<QString, unsigned short> > &list, acl_tag_t type )
00433 {
00434     bool allIsWell = true;
00435     bool atLeastOneUserOrGroup = false;
00436 
00437     // make working copy, in case something goes wrong
00438     acl_t newACL = acl_dup( m_acl );
00439     acl_entry_t entry;
00440 
00441 //printACL( newACL, "Before cleaning: " );
00442     // clear user entries
00443     int ret = acl_get_entry( newACL, ACL_FIRST_ENTRY, &entry );
00444     while ( ret == 1 ) {
00445         acl_tag_t currentTag;
00446         acl_get_tag_type( entry, &currentTag );
00447         if ( currentTag ==  type ) {
00448             acl_delete_entry( newACL, entry );
00449             // we have to start from the beginning, the iterator is
00450             // invalidated, on deletion
00451             ret = acl_get_entry( newACL, ACL_FIRST_ENTRY, &entry );
00452         } else {
00453             ret = acl_get_entry( newACL, ACL_NEXT_ENTRY, &entry );
00454         }
00455     }
00456 //printACL( newACL, "After cleaning out entries: " );
00457 
00458     // now add the entries from the list
00459     QValueList< QPair<QString, unsigned short> >::const_iterator it = list.constBegin();
00460     while ( it != list.constEnd() ) {
00461         acl_create_entry( &newACL, &entry );
00462         acl_set_tag_type( entry, type );
00463         int id = type == ACL_USER? getUidForName( (*it).first):getGidForName( (*it).first );
00464         if ( id == -1 || acl_set_qualifier( entry, &id ) != 0 ) {
00465             // user or group doesn't exist => error
00466             acl_delete_entry( newACL, entry );
00467             allIsWell = false;
00468             break;
00469         } else {
00470             permissionsToEntry( entry, (*it).second );
00471             atLeastOneUserOrGroup = true;
00472         }
00473         ++it;
00474     }
00475 //printACL( newACL, "After adding entries: " );
00476     if ( allIsWell && atLeastOneUserOrGroup ) {
00477         // 23.1.1 of 1003.1e states that as soon as there is a named user or
00478         // named group entry, there needs to be a mask entry as well, so add
00479         // one, if the user hasn't explicitely set one.
00480         if ( entryForTag( newACL, ACL_MASK ) == 0 ) {
00481             acl_calc_mask( &newACL );
00482         }
00483     }
00484     if ( allIsWell && ( acl_valid( newACL ) == 0 ) ) {
00485         acl_free( m_acl );
00486         m_acl = newACL;
00487     } else {
00488         acl_free( newACL );
00489     }
00490     return allIsWell;
00491 }
00492 #endif
00493 
00494 bool KACL::setAllUserPermissions( const ACLUserPermissionsList &users )
00495 {
00496 #ifdef USE_POSIX_ACL
00497     return d->setAllUsersOrGroups( users, ACL_USER );
00498 #else
00499     Q_UNUSED( users );
00500     return true;
00501 #endif
00502 }
00503 
00504 
00505 /**************************
00506  * Deal with named groups  *
00507  **************************/
00508 
00509 unsigned short KACL::namedGroupPermissions( const QString& name, bool *exists ) const
00510 {
00511     *exists = false;
00512 #ifdef USE_POSIX_ACL
00513     acl_entry_t entry;
00514     gid_t id;
00515     int ret = acl_get_entry( d->m_acl, ACL_FIRST_ENTRY, &entry );
00516     while ( ret == 1 ) {
00517         acl_tag_t currentTag;
00518         acl_get_tag_type( entry, &currentTag );
00519         if ( currentTag ==  ACL_GROUP ) {
00520             id = *( (gid_t*) acl_get_qualifier( entry ) );
00521             if ( d->getGroupName( id ) == name ) {
00522                 *exists = true;
00523                 return entryToPermissions( entry );
00524             }
00525         }
00526         ret = acl_get_entry( d->m_acl, ACL_NEXT_ENTRY, &entry );
00527     }
00528 #else
00529     Q_UNUSED( name );
00530 #endif
00531     return 0;
00532 }
00533 
00534 bool KACL::setNamedGroupPermissions( const QString& name, unsigned short permissions )
00535 {
00536 #ifdef USE_POSIX_ACL
00537     return d->setNamedUserOrGroupPermissions( name, permissions, ACL_GROUP );
00538 #else
00539     Q_UNUSED( name );
00540     Q_UNUSED( permissions );
00541     return true;
00542 #endif
00543 }
00544 
00545 
00546 ACLGroupPermissionsList KACL::allGroupPermissions() const
00547 {
00548     ACLGroupPermissionsList list;
00549 #ifdef USE_POSIX_ACL
00550     acl_entry_t entry;
00551     gid_t id;
00552     int ret = acl_get_entry( d->m_acl, ACL_FIRST_ENTRY, &entry );
00553     while ( ret == 1 ) {
00554         acl_tag_t currentTag;
00555         acl_get_tag_type( entry, &currentTag );
00556         if ( currentTag ==  ACL_GROUP ) {
00557             id = *( (gid_t*) acl_get_qualifier( entry ) );
00558             QString name = d->getGroupName( id );
00559             unsigned short permissions = entryToPermissions( entry );
00560             ACLGroupPermissions pair = qMakePair( name, permissions );
00561             list.append( pair );
00562         }
00563         ret = acl_get_entry( d->m_acl, ACL_NEXT_ENTRY, &entry );
00564     }
00565 #endif
00566     return list;
00567 }
00568 
00569 bool KACL::setAllGroupPermissions( const ACLGroupPermissionsList &groups )
00570 {
00571 #ifdef USE_POSIX_ACL
00572     return d->setAllUsersOrGroups( groups, ACL_GROUP );
00573 #else
00574     Q_UNUSED( groups );
00575     return true;
00576 #endif
00577 }
00578 
00579 /**************************
00580  * from and to string     *
00581  **************************/
00582 
00583 bool KACL::setACL( const QString &aclStr )
00584 {
00585     bool ret = false;
00586 #ifdef USE_POSIX_ACL
00587     if ( aclStr.isEmpty() )
00588         return false;
00589 
00590     acl_t temp = acl_from_text( aclStr.latin1() );
00591     if ( acl_valid( temp ) != 0 ) {
00592         // TODO errno is set, what to do with it here?
00593         acl_free( temp );
00594     } else {
00595         if ( d->m_acl )
00596             acl_free( d->m_acl );
00597         d->m_acl = temp;
00598         ret = true;
00599     }
00600 #else
00601     Q_UNUSED( aclStr );
00602 #endif
00603     return ret;
00604 }
00605 
00606 QString KACL::asString() const
00607 {
00608 #ifdef USE_POSIX_ACL
00609     return aclAsString( d->m_acl );
00610 #else
00611     return QString::null;
00612 #endif
00613 }
00614 
00615 
00616 // helpers
00617 
00618 #ifdef USE_POSIX_ACL
00619 QString KACL::KACLPrivate::getUserName( uid_t uid ) const
00620 {
00621     QString *temp;
00622     temp = m_usercache.find( uid );
00623     if ( !temp ) {
00624         struct passwd *user = getpwuid( uid );
00625         if ( user ) {
00626             m_usercache.insert( uid, new QString(QString::fromLatin1(user->pw_name)) );
00627             return QString::fromLatin1( user->pw_name );
00628         }
00629         else
00630             return QString::number( uid );
00631     }
00632     else
00633         return *temp;
00634 }
00635 
00636 
00637 QString KACL::KACLPrivate::getGroupName( gid_t gid ) const
00638 {
00639     QString *temp;
00640     temp = m_groupcache.find( gid );
00641     if ( !temp ) {
00642         struct group *grp = getgrgid( gid );
00643         if ( grp ) {
00644             m_groupcache.insert( gid, new QString(QString::fromLatin1(grp->gr_name)) );
00645             return QString::fromLatin1( grp->gr_name );
00646         }
00647         else
00648             return QString::number( gid );
00649     }
00650     else
00651         return *temp;
00652 }
00653 
00654 static QString aclAsString(const acl_t acl)
00655 {
00656     char *aclString = acl_to_text( acl, 0 );
00657     QString ret = QString::fromLatin1( aclString );
00658     acl_free( (void*)aclString );
00659     return ret;
00660 }
00661 
00662 
00663 #endif
00664 
00665 void KACL::virtual_hook( int, void* )
00666 { /*BASE::virtual_hook( id, data );*/ }
00667 
00668 QDataStream & operator<< ( QDataStream & s, const KACL & a )
00669 {
00670     s << a.asString();
00671     return s;
00672 }
00673 
00674 QDataStream & operator>> ( QDataStream & s, KACL & a )
00675 {
00676     QString str;
00677     s >> str;
00678     a.setACL( str );
00679     return s;
00680 }
00681 
00682 // vim:set ts=8 sw=4:

kio

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

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
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