kabc Library API Documentation

resourceldap.cpp

00001 /*
00002     This file is part of libkabc.
00003     Copyright (c) 2002 Tobias Koenig <tokoe@kde.org>
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., 59 Temple Place - Suite 330,
00018     Boston, MA 02111-1307, USA.
00019 */
00020 
00021 #include <kdebug.h>
00022 #include <kglobal.h>
00023 #include <klineedit.h>
00024 #include <klocale.h>
00025 
00026 #include <stdlib.h>
00027 
00028 #include "resourceconfigwidget.h"
00029 #include "resourceldap.h"
00030 #include "resourceldapconfig.h"
00031 
00032 using namespace KABC;
00033 
00034 extern "C"
00035 {
00036   ResourceConfigWidget *config_widget( QWidget *parent ) {
00037     KGlobal::locale()->insertCatalogue("kabc_ldap");
00038     return new ResourceLDAPConfig( parent, "ResourceLDAPConfig" );
00039   }
00040 
00041   Resource *resource( AddressBook *ab, const KConfig *config ) {
00042     KGlobal::locale()->insertCatalogue("kabc_ldap");
00043     return new ResourceLDAP( ab, config );
00044   }
00045 }
00046 
00047 void addModOp( LDAPMod ***pmods, const QString &attr, const QString &value );
00048 
00049 ResourceLDAP::ResourceLDAP( AddressBook *ab, const KConfig *config )
00050   : Resource( ab )
00051 {
00052   mLdap = 0;
00053 
00054   mUser = config->readEntry( "LdapUser" );
00055   mPassword = cryptStr( config->readEntry( "LdapPassword" ) );
00056   mDn = config->readEntry( "LdapDn" );
00057   mHost = config->readEntry( "LdapHost" );
00058   mPort = config->readEntry( "LdapPort" );
00059   mFilter = config->readEntry( "LdapFilter" );
00060   mAnonymous = config->readBoolEntry( "LdapAnonymous" );
00061 }
00062 
00063 ResourceLDAP::ResourceLDAP( AddressBook *ab, const QString &user,
00064         const QString &password, const QString &dn,
00065         const QString &host, const QString &port, const QString &filter,
00066   const bool anonymous )
00067     : Resource( ab )
00068 {
00069   mLdap = 0;
00070 
00071   mUser = user;
00072   mPassword = password;
00073   mDn = dn;
00074   mHost = host;
00075   mPort = port;
00076   mFilter = filter;
00077   mAnonymous = anonymous;
00078 }
00079 
00080 Ticket *ResourceLDAP::requestSaveTicket()
00081 {
00082   if ( !addressBook() ) {
00083           kdDebug(5700) << "no addressbook" << endl;
00084     return 0;
00085   }
00086 
00087   return createTicket( this );
00088 }
00089 
00090 bool ResourceLDAP::open()
00091 {
00092   if ( mLdap )
00093           return false;
00094 
00095   if ( mPort.isEmpty() )
00096           mPort = "389";
00097 
00098   mLdap = ldap_init( mHost.local8Bit(), mPort.toInt() );
00099   if ( !mLdap ) {
00100           addressBook()->error( i18n( "Unable to connect to server '%1' on port '%2'" ).arg( mHost ).arg( mPort ) );
00101           return false;
00102   }
00103 
00104   if ( !mUser.isEmpty() && !mAnonymous ) {
00105           if ( ldap_simple_bind_s( mLdap, mUser.local8Bit(), mPassword.local8Bit() ) != LDAP_SUCCESS ) {
00106             addressBook()->error( i18n( "Unable to bind to server '%1'" ).arg( mHost ) );
00107       return false;
00108     }
00109 
00110     kdDebug(5700) << "ResourceLDAP: bind to server successfully" << endl;
00111   }
00112 
00113   int deref = LDAP_DEREF_ALWAYS;
00114   if ( ldap_set_option( mLdap, LDAP_OPT_DEREF, (void *) &deref ) != LDAP_OPT_SUCCESS ) {
00115     kdDebug(5700) << "ResourceLDAP: can't set 'deref' option" << endl;
00116     return false;
00117   }
00118 
00119   if ( ldap_set_option( mLdap, LDAP_OPT_REFERRALS, LDAP_OPT_ON ) != LDAP_OPT_SUCCESS ) {
00120     kdDebug(5700) << "ResourceLDAP: can't set 'referrals' option" << endl;
00121     return false;
00122   }
00123 
00124   return true;
00125 }
00126 
00127 void ResourceLDAP::close()
00128 {
00129   if ( ldap_unbind_s( mLdap ) != LDAP_SUCCESS ) {
00130     kdDebug(5700) << "ResourceLDAP: can't unbind from server" << endl;
00131     return;
00132   }
00133 
00134   mLdap = 0;
00135 }
00136 
00137 bool ResourceLDAP::load()
00138 {
00139   LDAPMessage *res;
00140   LDAPMessage *msg;
00141   BerElement *track;
00142   char *names;
00143   char **values;
00144 
00145   const char *LdapSearchAttr[ 9 ] = {
00146     "cn",
00147     "display-name",
00148     "givenname",
00149     "mail",
00150     "mailalias",
00151     "phoneNumber",
00152     "sn",
00153     "uid",
00154     0 };
00155 
00156   if ( ldap_search_s( mLdap, mDn.local8Bit(), LDAP_SCOPE_SUBTREE, QString( "(%1)" ).arg( mFilter ).local8Bit(),
00157       (char **)LdapSearchAttr, 0, &res ) != LDAP_SUCCESS ) {
00158     addressBook()->error( i18n( "Unable to search on server '%1'" ).arg( mHost ) );
00159     return false;
00160   }
00161 
00162   for ( msg = ldap_first_entry( mLdap, res ); msg; msg = ldap_next_entry( mLdap, msg ) ) {
00163     Addressee addr;
00164     addr.setResource( this );
00165     for ( names = ldap_first_attribute( mLdap, msg, &track ); names; names = ldap_next_attribute( mLdap, msg, track ) ) {
00166       values = ldap_get_values( mLdap, msg, names );
00167       for ( int i = 0; i < ldap_count_values( values ); ++i ) {
00168         QString name = QString::fromUtf8( names );
00169         QString value = QString::fromUtf8( values[ i ] ); 
00170 
00171         if ( name == "cn" ) {
00172           if ( !addr.formattedName().isEmpty() ) {
00173             QString fn = addr.formattedName();
00174             addr.setNameFromString( value );
00175             addr.setFormattedName( fn );
00176           } else
00177             addr.setNameFromString( value );
00178           continue;
00179         }
00180         if ( name == "display-name" ) {
00181           addr.setFormattedName( value );
00182           continue;
00183         }
00184         if ( name == "givenname" ) {
00185           addr.setGivenName( value );
00186           continue;
00187         }
00188         if ( name == "mail" ) {
00189           addr.insertEmail( value, true );
00190           continue;
00191         }
00192         if ( name == "mailalias" ) {
00193           addr.insertEmail( value, false );
00194           continue;
00195         }
00196         if ( name == "phoneNumber" ) {
00197           PhoneNumber phone;
00198           phone.setNumber( value );
00199           addr.insertPhoneNumber( phone );
00200           break; // read only the home number
00201         }
00202         if ( name == "sn" ) {
00203           addr.setFamilyName( value );
00204           continue;
00205         }
00206         if ( name == "uid" ) {
00207           addr.setUid( value );
00208           continue;
00209         }
00210       }
00211       ldap_value_free( values );
00212     }
00213     ber_free( track, 0 );
00214 
00215     addressBook()->insertAddressee( addr );
00216   }
00217 
00218   ldap_msgfree( res );
00219 
00220   return true;
00221 }
00222 
00223 bool ResourceLDAP::save( Ticket * )
00224 {
00225   AddressBook::Iterator it;
00226   for ( it = addressBook()->begin(); it != addressBook()->end(); ++it ) {
00227     if ( (*it).resource() == this && (*it).changed() ) {
00228       LDAPMod **mods = NULL;
00229 
00230       addModOp( &mods, "objectClass", "organizationalPerson" );
00231       addModOp( &mods, "objectClass", "person" );
00232       addModOp( &mods, "objectClass", "Top" );
00233       addModOp( &mods, "cn", (*it).assembledName() );
00234       addModOp( &mods, "display-name", (*it).formattedName() );
00235       addModOp( &mods, "givenname", (*it).givenName() );
00236       addModOp( &mods, "sn", (*it).familyName() );
00237       addModOp( &mods, "uid", (*it).uid() );
00238 
00239       QStringList emails = (*it).emails();
00240       QStringList::ConstIterator mailIt;
00241       bool first = true;
00242       for ( mailIt = emails.begin(); mailIt != emails.end(); ++mailIt ) {
00243         if ( first ) {
00244           addModOp( &mods, "mail", (*mailIt) );
00245           first = false;
00246         } else
00247           addModOp( &mods, "mailalias", (*mailIt) );
00248       }
00249 
00250       PhoneNumber number = (*it).phoneNumber( PhoneNumber::Home );
00251       addModOp( &mods, "phoneNumber", number.number() );
00252 
00253       QString dn = "cn=" + (*it).assembledName() + "," + mDn;
00254 
00255       int retval;
00256       if ( (retval = ldap_add_s( mLdap, dn.local8Bit(), mods )) != LDAP_SUCCESS )
00257          addressBook()->error( i18n( "Unable to modify '%1' on server '%2'" ).arg( (*it).uid() ).arg( mHost ) );
00258 
00259       ldap_mods_free( mods, 1 );
00260 
00261       // mark as unchanged
00262       (*it).setChanged( false );
00263     }
00264   }
00265 
00266   return true;
00267 }
00268 
00269 void ResourceLDAP::removeAddressee( const Addressee &addr )
00270 {
00271   LDAPMessage *res;
00272   LDAPMessage *msg;
00273 
00274   QString filter = QString( "(&(uid=%1)(%2))" ).arg( addr.uid() ).arg( mFilter );
00275 
00276   kdDebug(5700) << "ldap:removeAddressee" << filter << endl;
00277 
00278   ldap_search_s( mLdap, mDn.local8Bit(), LDAP_SCOPE_SUBTREE, filter.local8Bit(),
00279       0, 0, &res );
00280 
00281   for ( msg = ldap_first_entry( mLdap, res ); msg; msg = ldap_next_entry( mLdap, msg ) ) {
00282     char *dn = ldap_get_dn( mLdap, msg );
00283     kdDebug(5700) << "found " << dn << endl;
00284     if ( ldap_delete_s( mLdap, dn ) != LDAP_SUCCESS )
00285       addressBook()->error( i18n( "Unable to delete '%1' on server '%2'" ).arg( dn ).arg( mHost ) );
00286     ldap_memfree( dn );
00287   }
00288 
00289   ldap_msgfree( res );
00290 }
00291 
00292 QString ResourceLDAP::identifier() const
00293 {
00294   return mHost + "_" + mPort + "_" + mDn + "_" + mFilter;
00295 }
00296 
00297 void addModOp( LDAPMod ***pmods, const QString &attr, const QString &value )
00298 {
00299   if ( value.isNull() )
00300     return;
00301 
00302   LDAPMod       **mods;
00303 
00304   mods = *pmods;
00305 
00306   uint i = 0;
00307   if ( mods != 0 )
00308     for ( ; mods[ i ] != 0; ++i );
00309 
00310   if (( mods = (LDAPMod **)realloc( mods, (i + 2) * sizeof( LDAPMod * ))) == 0 ) {
00311     kdError() << "ResourceLDAP: realloc" << endl;
00312     return;
00313   }
00314 
00315   *pmods = mods;
00316   mods[ i + 1 ] = 0;
00317 
00318   mods[ i ] = new LDAPMod;
00319 
00320   mods[ i ]->mod_op = 0;
00321   mods[ i ]->mod_type = strdup( attr.utf8() );
00322   mods[ i ]->mod_values = new char*[2];
00323   mods[ i ]->mod_values[0] = strdup( value.utf8() );
00324   mods[ i ]->mod_values[1] = 0;
00325 }
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:29:21 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001