• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • Sitemap
  • Contact Us
 

KLDAP Library

ldapoperation.cpp

00001 /*
00002   This file is part of libkldap.
00003   Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
00004 
00005   This library is free software; you can redistribute it and/or
00006   modify it under the terms of the GNU Library General  Public
00007   License as published by the Free Software Foundation; either
00008   version 2 of the License, or (at your option) any later version.
00009 
00010   This library is distributed in the hope that it will be useful,
00011   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013   Library General Public License for more details.
00014 
00015   You should have received a copy of the GNU Library General Public License
00016   along with this library; see the file COPYING.LIB.  If not, write to
00017   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018   Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "ldapoperation.h"
00022 #include "kldap_config.h"
00023 
00024 #include <kdebug.h>
00025 
00026 #include <QtCore/QTime>
00027 
00028 #include <stdlib.h>
00029 #ifdef HAVE_SYS_TIME_H
00030 #include <sys/time.h>
00031 #endif
00032 
00033 #ifdef SASL2_FOUND
00034 #include <sasl/sasl.h>
00035 #endif
00036 
00037 #ifdef LDAP_FOUND
00038 #include <lber.h>
00039 #include <ldap.h>
00040 #endif
00041 
00042 #include "ldapdefs.h"
00043 
00044 using namespace KLDAP;
00045 
00046 #ifdef LDAP_FOUND
00047 static void extractControls( LdapControls &ctrls, LDAPControl **pctrls );
00048 #endif // LDAP_FOUND
00049 
00050 /*
00051    Returns the difference between msecs and elapsed. If msecs is -1,
00052    however, -1 is returned.
00053 */
00054 static int kldap_timeout_value( int msecs, int elapsed )
00055 {
00056   if ( msecs == -1 ) {
00057     return -1;
00058   }
00059 
00060   int timeout = msecs - elapsed;
00061   return timeout < 0 ? 0 : timeout;
00062 }
00063 
00064 class LdapOperation::LdapOperationPrivate
00065 {
00066   public:
00067     LdapOperationPrivate();
00068     ~LdapOperationPrivate();
00069 #ifdef LDAP_FOUND
00070     int processResult( int rescode, LDAPMessage *msg );
00071     int bind( const QByteArray &creds, SASL_Callback_Proc *saslproc, void *data, bool async );
00072 #endif
00073     LdapControls mClientCtrls, mServerCtrls, mControls;
00074     LdapObject mObject;
00075     QByteArray mExtOid, mExtData;
00076     QByteArray mServerCred;
00077     QString mMatchedDn;
00078     QList<QByteArray> mReferrals;
00079 
00080   LdapConnection *mConnection;
00081   };
00082 
00083 LdapOperation::LdapOperation()
00084   : d( new LdapOperationPrivate )
00085 {
00086   d->mConnection = 0;
00087 }
00088 
00089 LdapOperation::LdapOperation( LdapConnection &conn )
00090   : d( new LdapOperationPrivate )
00091 {
00092   setConnection( conn );
00093 }
00094 
00095 LdapOperation::~LdapOperation()
00096 {
00097   delete d;
00098 }
00099 
00100 void LdapOperation::setConnection( LdapConnection &conn )
00101 {
00102   d->mConnection = &conn;
00103 }
00104 
00105 LdapConnection &LdapOperation::connection()
00106 {
00107   return *d->mConnection;
00108 }
00109 
00110 void LdapOperation::setClientControls( const LdapControls &ctrls )
00111 {
00112   d->mClientCtrls = ctrls;
00113 }
00114 
00115 void LdapOperation::setServerControls( const LdapControls &ctrls )
00116 {
00117   d->mServerCtrls = ctrls;
00118 }
00119 
00120 LdapControls LdapOperation::clientControls() const
00121 {
00122   return d->mClientCtrls;
00123 }
00124 
00125 LdapControls LdapOperation::serverControls() const
00126 {
00127   return d->mServerCtrls;
00128 }
00129 
00130 LdapObject LdapOperation::object() const
00131 {
00132   return d->mObject;
00133 }
00134 
00135 LdapControls LdapOperation::controls() const
00136 {
00137   return d->mControls;
00138 }
00139 
00140 QByteArray LdapOperation::extendedOid() const
00141 {
00142   return d->mExtOid;
00143 }
00144 
00145 QByteArray LdapOperation::extendedData() const
00146 {
00147   return d->mExtData;
00148 }
00149 
00150 QString LdapOperation::matchedDn() const
00151 {
00152   return d->mMatchedDn;
00153 }
00154 
00155 QList<QByteArray> LdapOperation::referrals() const
00156 {
00157   return d->mReferrals;
00158 }
00159 
00160 QByteArray LdapOperation::serverCred() const
00161 {
00162   return d->mServerCred;
00163 }
00164 
00165 LdapOperation::LdapOperationPrivate::LdapOperationPrivate()
00166 {
00167 }
00168 
00169 LdapOperation::LdapOperationPrivate::~LdapOperationPrivate()
00170 {
00171 }
00172 
00173 #ifdef LDAP_FOUND
00174 
00175 #ifdef SASL2_FOUND
00176 static int kldap_sasl_interact( sasl_interact_t *interact, LdapOperation::SASL_Data *data )
00177 {
00178   if ( data->proc ) {
00179     for ( ; interact->id != SASL_CB_LIST_END; interact++ ) {
00180       switch ( interact->id ) {
00181       case SASL_CB_GETREALM:
00182         data->creds.fields |= LdapOperation::SASL_Realm;
00183         break;
00184       case SASL_CB_AUTHNAME:
00185         data->creds.fields |= LdapOperation::SASL_Authname;
00186         break;
00187       case SASL_CB_PASS:
00188         data->creds.fields |= LdapOperation::SASL_Password;
00189         break;
00190       case SASL_CB_USER:
00191         data->creds.fields |= LdapOperation::SASL_Authzid;
00192         break;
00193       }
00194     }
00195     int retval;
00196     if ( ( retval = data->proc( data->creds, data->data ) ) ) {
00197       return retval;
00198     }
00199   }
00200 
00201   QString value;
00202 
00203   while ( interact->id != SASL_CB_LIST_END ) {
00204     value.clear();
00205     switch( interact->id ) {
00206     case SASL_CB_GETREALM:
00207       value = data->creds.realm;
00208       kDebug() << "SASL_REALM=" << value;
00209       break;
00210     case SASL_CB_AUTHNAME:
00211       value = data->creds.authname;
00212       kDebug() << "SASL_AUTHNAME=" << value;
00213       break;
00214     case SASL_CB_PASS:
00215       value = data->creds.password;
00216       kDebug() << "SASL_PASSWD=[hidden]";
00217       break;
00218     case SASL_CB_USER:
00219       value = data->creds.authzid;
00220       kDebug() << "SASL_AUTHZID=" << value;
00221       break;
00222     }
00223     if ( value.isEmpty() ) {
00224       interact->result = NULL;
00225       interact->len = 0;
00226     } else {
00227       interact->result = strdup( value.toUtf8() );
00228       interact->len = strlen( (const char *)interact->result );
00229     }
00230     interact++;
00231   }
00232   return KLDAP_SUCCESS;
00233 }
00234 #endif
00235 
00236 int LdapOperation::LdapOperationPrivate::bind( const QByteArray &creds,
00237                                                SASL_Callback_Proc *saslproc,
00238                                                void *data, bool async )
00239 {
00240   Q_ASSERT( mConnection );
00241   LDAP *ld = (LDAP*) mConnection->handle();
00242   LdapServer server;
00243   server = mConnection->server();
00244 
00245   int ret;
00246 
00247   if ( server.auth() == LdapServer::SASL ) {
00248 #ifdef SASL2_FOUND
00249     sasl_conn_t *saslconn = (sasl_conn_t *)mConnection->saslHandle();
00250     sasl_interact_t *client_interact = NULL;
00251     const char *out = NULL;
00252     uint outlen;
00253     const char *mechusing = NULL;
00254     struct berval ccred, *scred;
00255     int saslresult;
00256     QByteArray sdata = creds;
00257 
00258     QString mech = server.mech();
00259     if ( mech.isEmpty() ) {
00260       mech = "DIGEST-MD5";
00261     }
00262 
00263     SASL_Data sasldata;
00264     sasldata.proc = saslproc;
00265     sasldata.data = data;
00266     sasldata.creds.fields = 0;
00267     sasldata.creds.realm = server.realm();
00268     sasldata.creds.authname = server.user();
00269     sasldata.creds.authzid = server.bindDn();
00270     sasldata.creds.password = server.password();
00271 
00272     do {
00273       if ( sdata.isEmpty() ) {
00274         do {
00275           saslresult = sasl_client_start( saslconn, mech.toLatin1(),
00276                                           &client_interact, &out, &outlen, &mechusing );
00277 
00278           if ( saslresult == SASL_INTERACT ) {
00279             if ( kldap_sasl_interact( client_interact, &sasldata ) != KLDAP_SUCCESS ) {
00280               return KLDAP_SASL_ERROR;
00281             }
00282           }
00283           kDebug() << "sasl_client_start mech: "
00284                    << mechusing << " outlen " << outlen
00285                    << " result: " << saslresult;
00286         } while ( saslresult == SASL_INTERACT );
00287         if ( saslresult != SASL_CONTINUE && saslresult != SASL_OK ) {
00288           return KLDAP_SASL_ERROR;
00289         }
00290 
00291       } else {
00292         kDebug() << "sasl_client_step";
00293         do {
00294           saslresult = sasl_client_step( saslconn, sdata.data(), sdata.size(),
00295                                          &client_interact, &out, &outlen );
00296           if ( saslresult == SASL_INTERACT ) {
00297             if ( kldap_sasl_interact( client_interact, &sasldata ) != KLDAP_SUCCESS ) {
00298               return KLDAP_SASL_ERROR;
00299             }
00300           }
00301         } while ( saslresult == SASL_INTERACT );
00302         kDebug() << "sasl_client_step result" << saslresult;
00303         if ( saslresult != SASL_CONTINUE && saslresult != SASL_OK ) {
00304           return KLDAP_SASL_ERROR;
00305         }
00306       }
00307 
00308       ccred.bv_val = (char*) out;
00309       ccred.bv_len = outlen;
00310 
00311       if ( async ) {
00312         kDebug() << "ldap_sasl_bind";
00313         int msgid;
00314         ret =
00315           ldap_sasl_bind( ld, server.bindDn().toUtf8().data(), mech.toLatin1(),
00316                           &ccred, 0, 0, &msgid );
00317         if ( ret == 0 ) {
00318           ret = msgid;
00319         }
00320         kDebug() << "ldap_sasl_bind msgid" << ret;
00321       } else {
00322         kDebug() << "ldap_sasl_bind_s";
00323         ret =
00324           ldap_sasl_bind_s( ld, server.bindDn().toUtf8().data(), mech.toLatin1(),
00325                             &ccred, 0, 0, &scred );
00326         kDebug() << "ldap_sasl_bind_s ret" << ret;
00327         if ( scred ) {
00328           sdata = QByteArray( scred->bv_val, scred->bv_len );
00329         } else {
00330           sdata = QByteArray();
00331         }
00332       }
00333     } while ( !async && ret == KLDAP_SASL_BIND_IN_PROGRESS );
00334 #else
00335     kError() << "SASL authentication is not available "
00336              << "(re-compile kldap with cyrus-sasl development).";
00337     return KLDAP_SASL_ERROR;
00338 #endif
00339   } else { //simple auth
00340     QByteArray bindname, pass;
00341     struct berval ccred;
00342     if ( server.auth() == LdapServer::Simple ) {
00343       bindname = server.bindDn().toUtf8();
00344       pass = server.password().toUtf8();
00345     }
00346     ccred.bv_val = pass.data();
00347     ccred.bv_len = pass.size();
00348     kDebug() << "binding to server, bindname: " << bindname << " password: *****";
00349 
00350     if ( async ) {
00351       kDebug() << "ldap_sasl_bind (simple)";
00352       int msgid;
00353       ret = ldap_sasl_bind( ld, bindname.data(), 0, &ccred, 0, 0, &msgid );
00354 //    ret = ldap_simple_bind( ld, bindname.data(),pass.data() );
00355       if ( ret == 0 ) {
00356         ret = msgid;
00357       }
00358     } else {
00359       kDebug() << "ldap_sasl_bind_s (simple)";
00360       ret = ldap_sasl_bind_s( ld, bindname.data(), 0, &ccred, 0, 0, 0 );
00361 //    ret = ldap_simple_bind_s( ld, bindname.data(), pass.data() );
00362     }
00363   }
00364   return ret;
00365 }
00366 
00367 int LdapOperation::LdapOperationPrivate::processResult( int rescode, LDAPMessage *msg )
00368 {
00369   //kDebug();
00370   int retval;
00371   LDAP *ld = (LDAP*) mConnection->handle();
00372 
00373   kDebug() << "rescode: " << rescode;
00374   switch ( rescode ) {
00375   case RES_SEARCH_ENTRY:
00376   {
00377     //kDebug() << "Found search entry";
00378     mObject.clear();
00379     LdapAttrMap attrs;
00380     char *name;
00381     struct berval **bvals;
00382     BerElement     *entry;
00383 
00384     char *dn = ldap_get_dn( ld, msg );
00385     mObject.setDn( QString::fromUtf8( dn ) );
00386     ldap_memfree( dn );
00387 
00388     // iterate over the attributes
00389     name = ldap_first_attribute( ld, msg, &entry );
00390     while ( name != 0 ) {
00391       // print the values
00392       bvals = ldap_get_values_len( ld, msg, name );
00393       LdapAttrValue values;
00394       if ( bvals ) {
00395         for ( int i = 0; bvals[i] != 0; i++ ) {
00396           char *val = bvals[i]->bv_val;
00397           unsigned long len = bvals[i]->bv_len;
00398           values.append( QByteArray( val, len ) );
00399         }
00400         ldap_value_free_len( bvals );
00401       }
00402       attrs[ QString::fromLatin1( name ) ] = values;
00403       ldap_memfree( name );
00404 
00405       // next attribute
00406       name = ldap_next_attribute( ld, msg, entry );
00407     }
00408     ber_free( entry, 0 );
00409     mObject.setAttributes( attrs );
00410     break;
00411   }
00412   case RES_SEARCH_REFERENCE:
00413     // Will only get this if following references is disabled. ignore it
00414     rescode = 0;
00415     break;
00416   case RES_EXTENDED:
00417   {
00418     char *retoid;
00419     struct berval *retdata;
00420     retval = ldap_parse_extended_result( ld, msg, &retoid, &retdata, 0 );
00421     if ( retval != KLDAP_SUCCESS ) {
00422       ldap_msgfree( msg );
00423       return -1;
00424     }
00425     mExtOid = retoid ? QByteArray( retoid ) : QByteArray();
00426     mExtData = retdata ? QByteArray( retdata->bv_val, retdata->bv_len ) : QByteArray();
00427     ldap_memfree( retoid );
00428     ber_bvfree( retdata );
00429     break;
00430   }
00431   case RES_BIND:
00432   {
00433     struct berval *servercred;
00434     retval = ldap_parse_sasl_bind_result( ld, msg, &servercred, 0 );
00435     if ( retval != KLDAP_SUCCESS && retval != KLDAP_SASL_BIND_IN_PROGRESS ) {
00436       kDebug() << "RES_BIND error: " << retval;
00437       ldap_msgfree( msg );
00438       return -1;
00439     }
00440     kDebug() << "RES_BIND rescode" << rescode << "retval:" << retval;
00441     mServerCred = servercred ? QByteArray( servercred->bv_val, servercred->bv_len ) : QByteArray();
00442     ber_bvfree( servercred );
00443     break;
00444   }
00445   default:
00446   {
00447     LDAPControl **serverctrls = 0;
00448     char *matcheddn = 0, *errmsg = 0;
00449     char **referralsp;
00450     int errcodep;
00451     retval =
00452       ldap_parse_result( ld, msg, &errcodep, &matcheddn, &errmsg, &referralsp,
00453                          &serverctrls, 0 );
00454     kDebug() << "rescode" << rescode << "retval:" << retval
00455                  << "matcheddn:" << matcheddn << "errcode:"
00456                  << errcodep << "errmsg:" << errmsg;
00457     if ( retval != KLDAP_SUCCESS ) {
00458       ldap_msgfree( msg );
00459       return -1;
00460     }
00461     mControls.clear();
00462     if ( serverctrls ) {
00463       extractControls( mControls, serverctrls );
00464       ldap_controls_free( serverctrls );
00465     }
00466     mReferrals.clear();
00467     if ( referralsp ) {
00468       char **tmp = referralsp;
00469       while ( *tmp ) {
00470         mReferrals.append( QByteArray( *tmp ) );
00471         ldap_memfree( *tmp );
00472         tmp++;
00473       }
00474       ldap_memfree( (char *) referralsp );
00475     }
00476     mMatchedDn.clear();
00477     if ( matcheddn ) {
00478       mMatchedDn = QString::fromUtf8( matcheddn );
00479       ldap_memfree( matcheddn );
00480     }
00481     if ( errmsg ) {
00482       ldap_memfree( errmsg );
00483     }
00484   }
00485   }
00486 
00487   ldap_msgfree( msg );
00488 
00489   return rescode;
00490 }
00491 
00492 static void addModOp( LDAPMod ***pmods, int mod_type, const QString &attr,
00493                       const QByteArray *value = 0 )
00494 {
00495   //  kDebug() << "type:" << mod_type << "attr:" << attr <<
00496   //    "value:" << QString::fromUtf8(value,value.size()) <<
00497   //    "size:" << value.size();
00498   LDAPMod **mods;
00499 
00500   mods = *pmods;
00501 
00502   uint i = 0;
00503 
00504   if ( mods == 0 ) {
00505     mods = (LDAPMod **)malloc( 2 * sizeof( LDAPMod * ) );
00506     mods[ 0 ] = (LDAPMod *)malloc( sizeof( LDAPMod ) );
00507     mods[ 1 ] = 0;
00508     memset( mods[ 0 ], 0, sizeof( LDAPMod ) );
00509   } else {
00510     while ( mods[ i ] != 0 &&
00511             ( strcmp( attr.toUtf8(), mods[i]->mod_type ) != 0 ||
00512               ( mods[ i ]->mod_op & ~LDAP_MOD_BVALUES ) != mod_type ) ) i++;
00513 
00514     if ( mods[ i ] == 0 ) {
00515       mods = (LDAPMod **)realloc( mods, ( i + 2 ) * sizeof( LDAPMod * ) );
00516       if ( mods == 0 ) {
00517         kError() << "addModOp: realloc";
00518         return;
00519       }
00520       mods[ i + 1 ] = 0;
00521       mods[ i ] = (LDAPMod *) malloc( sizeof( LDAPMod ) );
00522       memset( mods[ i ], 0, sizeof( LDAPMod ) );
00523     }
00524   }
00525 
00526   mods[ i ]->mod_op = mod_type | LDAP_MOD_BVALUES;
00527   if ( mods[ i ]->mod_type == 0 ) {
00528     mods[ i ]->mod_type = strdup( attr.toUtf8() );
00529   }
00530 
00531   *pmods = mods;
00532 
00533   if ( value == 0 ) {
00534     return;
00535   }
00536 
00537   int vallen = value->size();
00538   BerValue *berval;
00539   berval = (BerValue *) malloc( sizeof( BerValue ) );
00540   berval -> bv_len = vallen;
00541   if ( vallen > 0 ) {
00542     berval -> bv_val = (char *) malloc( vallen );
00543     memcpy( berval -> bv_val, value->data(), vallen );
00544   } else {
00545     berval -> bv_val = 0;
00546   }
00547 
00548   if ( mods[ i ] -> mod_vals.modv_bvals == 0 ) {
00549     mods[ i ]->mod_vals.modv_bvals =
00550       (BerValue **) malloc( sizeof( BerValue * ) * 2 );
00551     mods[ i ]->mod_vals.modv_bvals[ 0 ] = berval;
00552     mods[ i ]->mod_vals.modv_bvals[ 1 ] = 0;
00553 //    kDebug() << "new bervalue struct" << attr << value;
00554   } else {
00555     uint j = 0;
00556     while ( mods[ i ]->mod_vals.modv_bvals[ j ] != 0 ) {
00557       j++;
00558     }
00559     mods[ i ]->mod_vals.modv_bvals =
00560       (BerValue **)realloc( mods[ i ]->mod_vals.modv_bvals,
00561                             ( j + 2 ) * sizeof( BerValue * ) );
00562     if ( mods[ i ]->mod_vals.modv_bvals == 0 ) {
00563       kError() << "addModOp: realloc";
00564       free( berval );
00565       return;
00566     }
00567     mods[ i ]->mod_vals.modv_bvals[ j ] = berval;
00568     mods[ i ]->mod_vals.modv_bvals[ j+1 ] = 0;
00569     kDebug() << j << ". new bervalue";
00570   }
00571 }
00572 
00573 static void addControlOp( LDAPControl ***pctrls, const QString &oid,
00574                           const QByteArray &value, bool critical )
00575 {
00576   LDAPControl **ctrls;
00577   LDAPControl *ctrl = (LDAPControl *) malloc( sizeof( LDAPControl ) );
00578 
00579   ctrls = *pctrls;
00580 
00581   kDebug() << "oid:'" << oid << "' val: '" << value << "'";
00582   int vallen = value.size();
00583   ctrl->ldctl_value.bv_len = vallen;
00584   if ( vallen ) {
00585     ctrl->ldctl_value.bv_val = (char *) malloc( vallen );
00586     memcpy( ctrl->ldctl_value.bv_val, value.data(), vallen );
00587   } else {
00588     ctrl->ldctl_value.bv_val = 0;
00589   }
00590   ctrl->ldctl_iscritical = critical;
00591   ctrl->ldctl_oid = strdup( oid.toUtf8() );
00592 
00593   uint i = 0;
00594 
00595   if ( ctrls == 0 ) {
00596     ctrls = (LDAPControl **)malloc ( 2 * sizeof( LDAPControl * ) );
00597     ctrls[ 0 ] = 0;
00598     ctrls[ 1 ] = 0;
00599   } else {
00600     while ( ctrls[ i ] != 0 ) {
00601       i++;
00602     }
00603     ctrls[ i + 1 ] = 0;
00604     ctrls =
00605       (LDAPControl **)realloc( ctrls, ( i + 2 ) * sizeof( LDAPControl * ) );
00606   }
00607   ctrls[ i ] = ctrl;
00608   *pctrls = ctrls;
00609 }
00610 
00611 static void createControls( LDAPControl ***pctrls, const LdapControls &ctrls )
00612 {
00613   for ( int i = 0; i< ctrls.count(); ++i ) {
00614     addControlOp( pctrls, ctrls[i].oid(), ctrls[i].value(), ctrls[i].critical() );
00615   }
00616 }
00617 
00618 static void extractControls( LdapControls &ctrls, LDAPControl **pctrls )
00619 {
00620   LDAPControl *ctrl;
00621   LdapControl control;
00622   int i = 0;
00623 
00624   while ( pctrls[i] ) {
00625     ctrl = pctrls[ i ];
00626     control.setOid( QString::fromUtf8( ctrl->ldctl_oid ) );
00627     control.setValue( QByteArray( ctrl->ldctl_value.bv_val,
00628                                   ctrl->ldctl_value.bv_len ) );
00629     control.setCritical( ctrl->ldctl_iscritical );
00630     ctrls.append( control );
00631     i++;
00632   }
00633 }
00634 
00635 int LdapOperation::bind( const QByteArray &creds, SASL_Callback_Proc *saslproc, void *data )
00636 {
00637   return d->bind( creds, saslproc, data, true );
00638 }
00639 
00640 int LdapOperation::bind_s( SASL_Callback_Proc *saslproc, void *data )
00641 {
00642   return d->bind( QByteArray(), saslproc, data, false );
00643 }
00644 
00645 int LdapOperation::search( const LdapDN &base, LdapUrl::Scope scope,
00646                            const QString &filter, const QStringList &attributes )
00647 {
00648   Q_ASSERT( d->mConnection );
00649   LDAP *ld = (LDAP*) d->mConnection->handle();
00650 
00651   char **attrs = 0;
00652   int msgid;
00653 
00654   LDAPControl **serverctrls = 0, **clientctrls = 0;
00655   createControls( &serverctrls, d->mServerCtrls );
00656   createControls( &serverctrls, d->mClientCtrls );
00657 
00658   int count = attributes.count();
00659   if ( count > 0 ) {
00660     attrs = static_cast<char**>( malloc( ( count + 1 ) * sizeof( char * ) ) );
00661     for ( int i=0; i<count; i++ ) {
00662       attrs[i] = strdup( attributes.at(i).toUtf8() );
00663     }
00664     attrs[count] = 0;
00665   }
00666 
00667   int lscope = LDAP_SCOPE_BASE;
00668   switch ( scope ) {
00669   case LdapUrl::Base:
00670     lscope = LDAP_SCOPE_BASE;
00671     break;
00672   case LdapUrl::One:
00673     lscope = LDAP_SCOPE_ONELEVEL;
00674     break;
00675   case LdapUrl::Sub:
00676     lscope = LDAP_SCOPE_SUBTREE;
00677     break;
00678   }
00679 
00680   kDebug() << "asyncSearch() base=\"" << base.toString()
00681            << "\" scope=" << (int)scope
00682            << "filter=\"" << filter
00683            << "\" attrs=" << attributes;
00684   int retval =
00685     ldap_search_ext( ld, base.toString().toUtf8().data(), lscope,
00686                      filter.isEmpty() ? QByteArray( "objectClass=*" ).data() :
00687                                         filter.toUtf8().data(),
00688                      attrs, 0, serverctrls, clientctrls, 0,
00689                      d->mConnection->sizeLimit(), &msgid );
00690 
00691   ldap_controls_free( serverctrls );
00692   ldap_controls_free( clientctrls );
00693 
00694   // free the attributes list again
00695   if ( count > 0 ) {
00696     for ( int i=0; i<count; i++ ) {
00697       free( attrs[i] );
00698     }
00699     free( attrs );
00700   }
00701 
00702   if ( retval == 0 ) {
00703     retval = msgid;
00704   }
00705   return retval;
00706 }
00707 
00708 int LdapOperation::add( const LdapObject &object )
00709 {
00710   Q_ASSERT( d->mConnection );
00711   LDAP *ld = (LDAP*) d->mConnection->handle();
00712 
00713   int msgid;
00714   LDAPMod **lmod = 0;
00715 
00716   LDAPControl **serverctrls = 0, **clientctrls = 0;
00717   createControls( &serverctrls, d->mServerCtrls );
00718   createControls( &serverctrls, d->mClientCtrls );
00719 
00720   for ( LdapAttrMap::ConstIterator it = object.attributes().begin();
00721         it != object.attributes().end(); ++it ) {
00722     QString attr = it.key();
00723     for ( LdapAttrValue::ConstIterator it2 = (*it).begin(); it2 != (*it).end(); ++it2 ) {
00724       addModOp( &lmod, 0, attr, &(*it2) );
00725     }
00726   }
00727 
00728   int retval =
00729     ldap_add_ext( ld, object.dn().toString().toUtf8().data(), lmod, serverctrls,
00730                   clientctrls, &msgid );
00731 
00732   ldap_controls_free( serverctrls );
00733   ldap_controls_free( clientctrls );
00734   ldap_mods_free( lmod, 1 );
00735   if ( retval == 0 ) {
00736     retval = msgid;
00737   }
00738   return retval;
00739 }
00740 
00741 int LdapOperation::add_s( const LdapObject &object )
00742 {
00743   Q_ASSERT( d->mConnection );
00744   LDAP *ld = (LDAP*) d->mConnection->handle();
00745 
00746   LDAPMod **lmod = 0;
00747 
00748   LDAPControl **serverctrls = 0, **clientctrls = 0;
00749   createControls( &serverctrls, d->mServerCtrls );
00750   createControls( &serverctrls, d->mClientCtrls );
00751 
00752   for ( LdapAttrMap::ConstIterator it = object.attributes().begin();
00753         it != object.attributes().end(); ++it ) {
00754     QString attr = it.key();
00755     for ( LdapAttrValue::ConstIterator it2 = (*it).begin(); it2 != (*it).end(); ++it2 ) {
00756       addModOp( &lmod, 0, attr, &(*it2) );
00757     }
00758   }
00759 
00760   int retval =
00761     ldap_add_ext_s( ld, object.dn().toString().toUtf8().data(), lmod, serverctrls,
00762                     clientctrls );
00763 
00764   ldap_controls_free( serverctrls );
00765   ldap_controls_free( clientctrls );
00766   ldap_mods_free( lmod, 1 );
00767   return retval;
00768 }
00769 
00770 int LdapOperation::add( const LdapDN &dn, const ModOps &ops )
00771 {
00772   Q_ASSERT( d->mConnection );
00773   LDAP *ld = (LDAP*) d->mConnection->handle();
00774 
00775   int msgid;
00776   LDAPMod **lmod = 0;
00777 
00778   LDAPControl **serverctrls = 0, **clientctrls = 0;
00779   createControls( &serverctrls, d->mServerCtrls );
00780   createControls( &serverctrls, d->mClientCtrls );
00781 
00782   for ( int i = 0; i < ops.count(); ++i ) {
00783     for ( int j = 0; j < ops[i].values.count(); ++j ) {
00784       addModOp( &lmod, 0, ops[i].attr, &ops[i].values[j] );
00785     }
00786   }
00787 
00788   int retval =
00789     ldap_add_ext( ld, dn.toString().toUtf8().data(), lmod, serverctrls,
00790                   clientctrls, &msgid );
00791 
00792   ldap_controls_free( serverctrls );
00793   ldap_controls_free( clientctrls );
00794   ldap_mods_free( lmod, 1 );
00795   if ( retval == 0 ) {
00796     retval = msgid;
00797   }
00798   return retval;
00799 }
00800 
00801 int LdapOperation::add_s( const LdapDN &dn, const ModOps &ops )
00802 {
00803   Q_ASSERT( d->mConnection );
00804   LDAP *ld = (LDAP*) d->mConnection->handle();
00805 
00806   LDAPMod **lmod = 0;
00807 
00808   LDAPControl **serverctrls = 0, **clientctrls = 0;
00809   createControls( &serverctrls, d->mServerCtrls );
00810   createControls( &serverctrls, d->mClientCtrls );
00811 
00812   for ( int i = 0; i < ops.count(); ++i ) {
00813     for ( int j = 0; j < ops[i].values.count(); ++j ) {
00814       addModOp( &lmod, 0, ops[i].attr, &ops[i].values[j] );
00815     }
00816   }
00817   kDebug() << dn.toString();
00818   int retval =
00819     ldap_add_ext_s( ld, dn.toString().toUtf8().data(), lmod, serverctrls,
00820                     clientctrls );
00821 
00822   ldap_controls_free( serverctrls );
00823   ldap_controls_free( clientctrls );
00824   ldap_mods_free( lmod, 1 );
00825   return retval;
00826 }
00827 
00828 int LdapOperation::rename( const LdapDN &dn, const QString &newRdn,
00829                            const QString &newSuperior, bool deleteold )
00830 {
00831   Q_ASSERT( d->mConnection );
00832   LDAP *ld = (LDAP*) d->mConnection->handle();
00833 
00834   int msgid;
00835 
00836   LDAPControl **serverctrls = 0, **clientctrls = 0;
00837   createControls( &serverctrls, d->mServerCtrls );
00838   createControls( &serverctrls, d->mClientCtrls );
00839 
00840   int retval = ldap_rename( ld, dn.toString().toUtf8().data(), newRdn.toUtf8().data(),
00841                             newSuperior.isEmpty() ? (char *) 0 : newSuperior.toUtf8().data(),
00842                             deleteold, serverctrls, clientctrls, &msgid );
00843 
00844   ldap_controls_free( serverctrls );
00845   ldap_controls_free( clientctrls );
00846 
00847   if ( retval == 0 ) {
00848     retval = msgid;
00849   }
00850   return retval;
00851 }
00852 
00853 int LdapOperation::rename_s( const LdapDN &dn, const QString &newRdn,
00854                              const QString &newSuperior, bool deleteold )
00855 {
00856   Q_ASSERT( d->mConnection );
00857   LDAP *ld = (LDAP*) d->mConnection->handle();
00858 
00859   LDAPControl **serverctrls = 0, **clientctrls = 0;
00860   createControls( &serverctrls, d->mServerCtrls );
00861   createControls( &serverctrls, d->mClientCtrls );
00862 
00863   int retval = ldap_rename_s( ld, dn.toString().toUtf8().data(), newRdn.toUtf8().data(),
00864                               newSuperior.isEmpty() ? (char *) 0 : newSuperior.toUtf8().data(),
00865                               deleteold, serverctrls, clientctrls );
00866 
00867   ldap_controls_free( serverctrls );
00868   ldap_controls_free( clientctrls );
00869 
00870   return retval;
00871 }
00872 
00873 int LdapOperation::del( const LdapDN &dn )
00874 {
00875   Q_ASSERT( d->mConnection );
00876   LDAP *ld = (LDAP*) d->mConnection->handle();
00877 
00878   int msgid;
00879 
00880   LDAPControl **serverctrls = 0, **clientctrls = 0;
00881   createControls( &serverctrls, d->mServerCtrls );
00882   createControls( &serverctrls, d->mClientCtrls );
00883 
00884   int retval =
00885     ldap_delete_ext( ld, dn.toString().toUtf8().data(), serverctrls, clientctrls, &msgid );
00886 
00887   ldap_controls_free( serverctrls );
00888   ldap_controls_free( clientctrls );
00889 
00890   if ( retval == 0 ) {
00891     retval = msgid;
00892   }
00893   return retval;
00894 }
00895 
00896 int LdapOperation::del_s( const LdapDN &dn )
00897 {
00898   Q_ASSERT( d->mConnection );
00899   LDAP *ld = (LDAP*) d->mConnection->handle();
00900 
00901   LDAPControl **serverctrls = 0, **clientctrls = 0;
00902   createControls( &serverctrls, d->mServerCtrls );
00903   createControls( &serverctrls, d->mClientCtrls );
00904 
00905   int retval = ldap_delete_ext_s( ld, dn.toString().toUtf8().data(), serverctrls, clientctrls );
00906 
00907   ldap_controls_free( serverctrls );
00908   ldap_controls_free( clientctrls );
00909 
00910   return retval;
00911 }
00912 
00913 int LdapOperation::modify( const LdapDN &dn, const ModOps &ops )
00914 {
00915   Q_ASSERT( d->mConnection );
00916   LDAP *ld = (LDAP *)d->mConnection->handle();
00917 
00918   int msgid;
00919   LDAPMod **lmod = 0;
00920 
00921   LDAPControl **serverctrls = 0, **clientctrls = 0;
00922   createControls( &serverctrls, d->mServerCtrls );
00923   createControls( &serverctrls, d->mClientCtrls );
00924 
00925   for ( int i = 0; i < ops.count(); ++i ) {
00926     int mtype = 0;
00927     switch ( ops[i].type ) {
00928     case Mod_None:
00929       mtype = 0;
00930       break;
00931     case Mod_Add:
00932       mtype = LDAP_MOD_ADD;
00933       break;
00934     case Mod_Replace:
00935       mtype = LDAP_MOD_REPLACE;
00936       break;
00937     case Mod_Del:
00938       mtype = LDAP_MOD_DELETE;
00939       break;
00940     }
00941     addModOp( &lmod, mtype, ops[i].attr, 0 );
00942     for ( int j = 0; j < ops[i].values.count(); ++j ) {
00943       addModOp( &lmod, mtype, ops[i].attr, &ops[i].values[j] );
00944     }
00945   }
00946 
00947   int retval =
00948     ldap_modify_ext( ld, dn.toString().toUtf8().data(), lmod, serverctrls, clientctrls, &msgid );
00949 
00950   ldap_controls_free( serverctrls );
00951   ldap_controls_free( clientctrls );
00952   ldap_mods_free( lmod, 1 );
00953   if ( retval == 0 ) {
00954     retval = msgid;
00955   }
00956   return retval;
00957 }
00958 
00959 int LdapOperation::modify_s( const LdapDN &dn, const ModOps &ops )
00960 {
00961   Q_ASSERT( d->mConnection );
00962   LDAP *ld = (LDAP*) d->mConnection->handle();
00963 
00964   LDAPMod **lmod = 0;
00965 
00966   LDAPControl **serverctrls = 0, **clientctrls = 0;
00967   createControls( &serverctrls, d->mServerCtrls );
00968   createControls( &serverctrls, d->mClientCtrls );
00969 
00970   for ( int i = 0; i < ops.count(); ++i ) {
00971     int mtype = 0;
00972     switch ( ops[i].type ) {
00973     case Mod_None:
00974       mtype = 0;
00975       break;
00976     case Mod_Add:
00977       mtype = LDAP_MOD_ADD;
00978       break;
00979     case Mod_Replace:
00980       mtype = LDAP_MOD_REPLACE;
00981       break;
00982     case Mod_Del:
00983       mtype = LDAP_MOD_DELETE;
00984       break;
00985     }
00986     addModOp( &lmod, mtype, ops[i].attr, 0 );
00987     for ( int j = 0; j < ops[i].values.count(); ++j ) {
00988       addModOp( &lmod, mtype, ops[i].attr, &ops[i].values[j] );
00989     }
00990   }
00991 
00992   int retval =
00993     ldap_modify_ext_s( ld, dn.toString().toUtf8().data(), lmod, serverctrls, clientctrls );
00994 
00995   ldap_controls_free( serverctrls );
00996   ldap_controls_free( clientctrls );
00997   ldap_mods_free( lmod, 1 );
00998   return retval;
00999 }
01000 
01001 int LdapOperation::compare( const LdapDN &dn, const QString &attr, const QByteArray &value )
01002 {
01003   Q_ASSERT( d->mConnection );
01004   LDAP *ld = (LDAP*) d->mConnection->handle();
01005   int msgid;
01006 
01007   LDAPControl **serverctrls = 0, **clientctrls = 0;
01008   createControls( &serverctrls, d->mServerCtrls );
01009   createControls( &serverctrls, d->mClientCtrls );
01010 
01011   int vallen = value.size();
01012   BerValue *berval;
01013   berval = (BerValue *) malloc( sizeof( BerValue ) );
01014   berval -> bv_val = (char *) malloc( vallen );
01015   berval -> bv_len = vallen;
01016   memcpy( berval -> bv_val, value.data(), vallen );
01017 
01018   int retval = ldap_compare_ext( ld, dn.toString().toUtf8().data(), attr.toUtf8().data(), berval,
01019                                  serverctrls, clientctrls, &msgid );
01020 
01021   ber_bvfree( berval );
01022   ldap_controls_free( serverctrls );
01023   ldap_controls_free( clientctrls );
01024 
01025   if ( retval == 0 ) {
01026     retval = msgid;
01027   }
01028   return retval;
01029 }
01030 
01031 int LdapOperation::compare_s( const LdapDN &dn, const QString &attr, const QByteArray &value )
01032 {
01033   Q_ASSERT( d->mConnection );
01034   LDAP *ld = (LDAP*) d->mConnection->handle();
01035 
01036   LDAPControl **serverctrls = 0, **clientctrls = 0;
01037   createControls( &serverctrls, d->mServerCtrls );
01038   createControls( &serverctrls, d->mClientCtrls );
01039 
01040   int vallen = value.size();
01041   BerValue *berval;
01042   berval = (BerValue *) malloc( sizeof( BerValue ) );
01043   berval -> bv_val = (char *) malloc( vallen );
01044   berval -> bv_len = vallen;
01045   memcpy( berval -> bv_val, value.data(), vallen );
01046 
01047   int retval = ldap_compare_ext_s( ld, dn.toString().toUtf8().data(), attr.toUtf8().data(), berval,
01048                                    serverctrls, clientctrls );
01049 
01050   ber_bvfree( berval );
01051   ldap_controls_free( serverctrls );
01052   ldap_controls_free( clientctrls );
01053 
01054   return retval;
01055 }
01056 
01057 int LdapOperation::exop( const QString &oid, const QByteArray &data )
01058 {
01059   Q_ASSERT( d->mConnection );
01060 #if defined(HAVE_LDAP_EXTENDED_OPERATION) && defined(HAVE_LDAP_EXTENDED_OPERATION_PROTOTYPE)
01061   LDAP *ld = (LDAP*) d->mConnection->handle();
01062   int msgid;
01063 
01064   LDAPControl **serverctrls = 0, **clientctrls = 0;
01065   createControls( &serverctrls, d->mServerCtrls );
01066   createControls( &serverctrls, d->mClientCtrls );
01067 
01068   int vallen = data.size();
01069   BerValue *berval;
01070   berval = (BerValue *) malloc( sizeof( BerValue ) );
01071   berval -> bv_val = (char *) malloc( vallen );
01072   berval -> bv_len = vallen;
01073   memcpy( berval -> bv_val, data.data(), vallen );
01074 
01075   int retval = ldap_extended_operation( ld, oid.toUtf8().data(), berval,
01076                                         serverctrls, clientctrls, &msgid );
01077 
01078   ber_bvfree( berval );
01079   ldap_controls_free( serverctrls );
01080   ldap_controls_free( clientctrls );
01081 
01082   if ( retval == 0 ) {
01083     retval = msgid;
01084   }
01085   return retval;
01086 #else
01087   kError() << "Your LDAP client libraries don't support extended operations.";
01088   return -1;
01089 #endif
01090 }
01091 
01092 int LdapOperation::exop_s( const QString &oid, const QByteArray &data )
01093 {
01094 #if defined(HAVE_LDAP_EXTENDED_OPERATION) && defined(HAVE_LDAP_EXTENDED_OPERATION_PROTOTYPE)
01095   Q_ASSERT( d->mConnection );
01096   LDAP *ld = (LDAP*) d->mConnection->handle();
01097   BerValue *retdata;
01098   char *retoid;
01099 
01100   LDAPControl **serverctrls = 0, **clientctrls = 0;
01101   createControls( &serverctrls, d->mServerCtrls );
01102   createControls( &serverctrls, d->mClientCtrls );
01103 
01104   int vallen = data.size();
01105   BerValue *berval;
01106   berval = (BerValue *) malloc( sizeof( BerValue ) );
01107   berval -> bv_val = (char *) malloc( vallen );
01108   berval -> bv_len = vallen;
01109   memcpy( berval -> bv_val, data.data(), vallen );
01110 
01111   int retval = ldap_extended_operation_s( ld, oid.toUtf8().data(), berval,
01112                                           serverctrls, clientctrls, &retoid, &retdata );
01113 
01114   ber_bvfree( berval );
01115   ber_bvfree( retdata );
01116   free( retoid );
01117   ldap_controls_free( serverctrls );
01118   ldap_controls_free( clientctrls );
01119 
01120   return retval;
01121 #else
01122   kError() << "Your LDAP client libraries don't support extended operations.";
01123   return -1;
01124 #endif
01125 }
01126 
01127 int LdapOperation::abandon( int id )
01128 {
01129   Q_ASSERT( d->mConnection );
01130   LDAP *ld = (LDAP*) d->mConnection->handle();
01131 
01132   LDAPControl **serverctrls = 0, **clientctrls = 0;
01133   createControls( &serverctrls, d->mServerCtrls );
01134   createControls( &serverctrls, d->mClientCtrls );
01135 
01136   int retval = ldap_abandon_ext( ld, id, serverctrls, clientctrls );
01137 
01138   ldap_controls_free( serverctrls );
01139   ldap_controls_free( clientctrls );
01140 
01141   return retval;
01142 }
01143 
01144 int LdapOperation::waitForResult( int id, int msecs )
01145 {
01146   Q_ASSERT( d->mConnection );
01147   LDAP *ld = (LDAP*) d->mConnection->handle();
01148 
01149   LDAPMessage *msg;
01150   int rescode;
01151 
01152   QTime stopWatch;
01153   stopWatch.start();
01154   int attempt( 1 );
01155   int timeout( 0 );
01156 
01157   do {
01158     // Calculate the timeout value to use and assign it to a timeval structure
01159     // see man select (2) for details
01160     timeout = kldap_timeout_value( msecs, stopWatch.elapsed() );
01161     kDebug() << "(" << id << "," << msecs
01162              << "): Waiting" << timeout
01163              << "msecs for result. Attempt #" << attempt++;
01164     struct timeval tv;
01165     tv.tv_sec = timeout / 1000;
01166     tv.tv_usec = ( timeout % 1000 ) * 1000;
01167 
01168     // Wait for a result
01169     rescode = ldap_result( ld, id, 0, timeout < 0 ? 0 : &tv, &msg );
01170     if ( rescode == -1 ) {
01171       return -1;
01172     }
01173     // Act on the return code
01174     if ( rescode != 0 ) {
01175       // Some kind of result is available for processing
01176       return d->processResult( rescode, msg );
01177     }
01178   } while ( msecs == -1 || stopWatch.elapsed() < msecs );
01179 
01180   return 0; //timeout
01181 }
01182 
01183 #else
01184 
01185 int LdapOperation::bind( const QByteArray &creds, SASL_Callback_Proc *saslproc, void *data )
01186 {
01187   kError() << "LDAP support not compiled";
01188   return -1;
01189 }
01190 
01191 int LdapOperation::bind_s( SASL_Callback_Proc *saslproc, void *data )
01192 {
01193   kError() << "LDAP support not compiled";
01194   return -1;
01195 }
01196 
01197 int LdapOperation::search( const LdapDN &base, LdapUrl::Scope scope,
01198                            const QString &filter, const QStringList &attributes )
01199 {
01200   kError() << "LDAP support not compiled";
01201   return -1;
01202 }
01203 
01204 int LdapOperation::add( const LdapObject &object )
01205 {
01206   kError() << "LDAP support not compiled";
01207   return -1;
01208 }
01209 
01210 int LdapOperation::add_s( const LdapObject &object )
01211 {
01212   kError() << "LDAP support not compiled";
01213   return -1;
01214 }
01215 
01216 int LdapOperation::add( const LdapDN &dn, const ModOps &ops )
01217 {
01218   kError() << "LDAP support not compiled";
01219   return -1;
01220 }
01221 
01222 int LdapOperation::add_s( const LdapDN &dn, const ModOps &ops )
01223 {
01224   kError() << "LDAP support not compiled";
01225   return -1;
01226 }
01227 
01228 int LdapOperation::rename( const LdapDN &dn, const QString &newRdn,
01229                            const QString &newSuperior, bool deleteold )
01230 {
01231   kError() << "LDAP support not compiled";
01232   return -1;
01233 }
01234 
01235 int LdapOperation::rename_s( const LdapDN &dn, const QString &newRdn,
01236                              const QString &newSuperior, bool deleteold )
01237 {
01238   kError() << "LDAP support not compiled";
01239   return -1;
01240 }
01241 
01242 int LdapOperation::del( const LdapDN &dn )
01243 {
01244   kError() << "LDAP support not compiled";
01245   return -1;
01246 }
01247 
01248 int LdapOperation::del_s( const LdapDN &dn )
01249 {
01250   kError() << "LDAP support not compiled";
01251   return -1;
01252 }
01253 
01254 int LdapOperation::modify( const LdapDN &dn, const ModOps &ops )
01255 {
01256   kError() << "LDAP support not compiled";
01257   return -1;
01258 }
01259 
01260 int LdapOperation::modify_s( const LdapDN &dn, const ModOps &ops )
01261 {
01262   kError() << "LDAP support not compiled";
01263   return -1;
01264 }
01265 
01266 int LdapOperation::compare( const LdapDN &dn, const QString &attr, const QByteArray &value )
01267 {
01268   kError() << "LDAP support not compiled";
01269   return -1;
01270 }
01271 
01272 int LdapOperation::exop( const QString &oid, const QByteArray &data )
01273 {
01274   kError() << "LDAP support not compiled";
01275   return -1;
01276 }
01277 
01278 int LdapOperation::compare_s( const LdapDN &dn, const QString &attr, const QByteArray &value )
01279 {
01280   kError() << "LDAP support not compiled";
01281   return -1;
01282 }
01283 
01284 int LdapOperation::exop_s( const QString &oid, const QByteArray &data )
01285 {
01286   kError() << "LDAP support not compiled";
01287   return -1;
01288 }
01289 
01290 int LdapOperation::waitForResult( int id, int msecs )
01291 {
01292   kError() << "LDAP support not compiled";
01293   return -1;
01294 }
01295 
01296 int LdapOperation::abandon( int id )
01297 {
01298   kError() << "LDAP support not compiled";
01299   return -1;
01300 }
01301 
01302 #endif

KLDAP Library

Skip menu "KLDAP Library"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kblog
  • kcal
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.6.2-20100208
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