summaryrefslogtreecommitdiffabout
path: root/kabc/plugins/ldap/resourceldap.cpp
Unidiff
Diffstat (limited to 'kabc/plugins/ldap/resourceldap.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--kabc/plugins/ldap/resourceldap.cpp444
1 files changed, 444 insertions, 0 deletions
diff --git a/kabc/plugins/ldap/resourceldap.cpp b/kabc/plugins/ldap/resourceldap.cpp
new file mode 100644
index 0000000..1c54f63
--- a/dev/null
+++ b/kabc/plugins/ldap/resourceldap.cpp
@@ -0,0 +1,444 @@
1/*
2 This file is part of libkabc.
3 Copyright (c) 2002 Tobias Koenig <tokoe@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/*
22Enhanced Version of the file for platform independent KDE tools.
23Copyright (c) 2004 Ulf Schenk
24
25$Id$
26*/
27
28#include <kdebug.h>
29#include <kglobal.h>
30#include <klineedit.h>
31#include <klocale.h>
32#include <kconfig.h>
33#include <kstringhandler.h>
34
35#include <stdlib.h>
36
37#include "resourceldap.h"
38#include "resourceldapconfig.h"
39
40using namespace KABC;
41
42extern "C"
43{
44 void *init_kabc_ldap()
45 {
46 qDebug("resourceldap.cpp : init_kabc_ldap has to be changed");
47//US return new KRES::PluginFactory<ResourceLDAP,ResourceLDAPConfig>();
48 }
49}
50
51void addModOp( LDAPMod ***pmods, const QString &attr, const QString &value );
52
53
54ResourceLDAP::ResourceLDAP( const KConfig *config )
55 : Resource( config ), mPort( 389 ), mLdap( 0 )
56{
57 KConfig *cfg = (KConfig *)config;
58 if ( cfg ) {
59 mUser = cfg->readEntry( "LdapUser" );
60 mPassword = KStringHandler::obscure( cfg->readEntry( "LdapPassword" ) );
61 mDn = cfg->readEntry( "LdapDn" );
62 mHost = cfg->readEntry( "LdapHost" );
63 mPort = cfg->readNumEntry( "LdapPort", 389 );
64 mFilter = cfg->readEntry( "LdapFilter" );
65 mAnonymous = cfg->readBoolEntry( "LdapAnonymous" );
66
67 QStringList attributes = cfg->readListEntry( "LdapAttributes" );
68 for ( uint pos = 0; pos < attributes.count(); pos += 2 )
69 mAttributes.insert( attributes[ pos ], attributes[ pos + 1 ] );
70 }
71
72 /**
73 If you want to add new attributes, append them here, add a
74 translation string in the ctor of AttributesDialog and
75 handle them in the load() method below.
76 These are the default values from
77 */
78 if ( mAttributes.count() == 0 ) {
79 mAttributes.insert( "commonName", "cn" );
80 mAttributes.insert( "formattedName", "displayName" );
81 mAttributes.insert( "familyName", "sn" );
82 mAttributes.insert( "givenName", "givenName" );
83 mAttributes.insert( "mail", "mail" );
84 mAttributes.insert( "mailAlias", "" );
85 mAttributes.insert( "phoneNumber", "telephoneNumber" );
86 mAttributes.insert( "uid", "uid" );
87 }
88}
89
90void ResourceLDAP::writeConfig( KConfig *config )
91{
92 Resource::writeConfig( config );
93
94 config->writeEntry( "LdapUser", mUser );
95 config->writeEntry( "LdapPassword", KStringHandler::obscure( mPassword ) );
96 config->writeEntry( "LdapDn", mDn );
97 config->writeEntry( "LdapHost", mHost );
98 config->writeEntry( "LdapPort", mPort );
99 config->writeEntry( "LdapFilter", mFilter );
100 config->writeEntry( "LdapAnonymous", mAnonymous );
101
102 QStringList attributes;
103 QMap<QString, QString>::Iterator it;
104 for ( it = mAttributes.begin(); it != mAttributes.end(); ++it )
105 attributes << it.key() << it.data();
106
107 config->writeEntry( "LdapAttributes", attributes );
108}
109
110Ticket *ResourceLDAP::requestSaveTicket()
111{
112 if ( !addressBook() ) {
113 kdDebug(5700) << "no addressbook" << endl;
114 return 0;
115 }
116
117 return createTicket( this );
118}
119
120bool ResourceLDAP::doOpen()
121{
122 if ( mLdap )
123 return false;
124
125 if ( !mPort )
126 mPort = 389;
127
128 mLdap = ldap_init( mHost.local8Bit(), mPort );
129 if ( !mLdap ) {
130 addressBook()->error( i18n( "Unable to connect to server '%1' on port '%2'" ).arg( mHost ).arg( mPort ) );
131 return false;
132 }
133
134 if ( !mUser.isEmpty() && !mAnonymous ) {
135 if ( ldap_simple_bind_s( mLdap, mUser.local8Bit(), mPassword.local8Bit() ) != LDAP_SUCCESS ) {
136 addressBook()->error( i18n( "Unable to bind to server '%1'" ).arg( mHost ) );
137 return false;
138 }
139
140 kdDebug(5700) << "ResourceLDAP: bind to server successfully" << endl;
141 } else {
142 if ( ldap_simple_bind_s( mLdap, NULL, NULL ) != LDAP_SUCCESS ) {
143 addressBook()->error( i18n( "Unable to bind anonymously to server '%1'" ).arg( mHost ) );
144 return false;
145 }
146
147 kdDebug( 5700 ) << "ResourceLDAP: bind anonymously to server successfully" << endl;
148 }
149
150 int deref = LDAP_DEREF_ALWAYS;
151 if ( ldap_set_option( mLdap, LDAP_OPT_DEREF, (void *) &deref ) != LDAP_OPT_SUCCESS ) {
152 kdDebug(5700) << "ResourceLDAP: can't set 'deref' option" << endl;
153 return false;
154 }
155
156 if ( ldap_set_option( mLdap, LDAP_OPT_REFERRALS, LDAP_OPT_ON ) != LDAP_OPT_SUCCESS ) {
157 kdDebug(5700) << "ResourceLDAP: can't set 'referrals' option" << endl;
158 return false;
159 }
160
161 return true;
162}
163
164void ResourceLDAP::doClose()
165{
166 if ( ldap_unbind_s( mLdap ) != LDAP_SUCCESS ) {
167 kdDebug(5700) << "ResourceLDAP: can't unbind from server" << endl;
168 return;
169 }
170
171 mLdap = 0;
172}
173
174bool ResourceLDAP::load()
175{
176 LDAPMessage *res;
177 LDAPMessage *msg;
178 BerElement *track;
179 char *names;
180 char **values;
181
182 char **LdapSearchAttr = new char*[ mAttributes.count() + 1 ];
183
184 QMap<QString, QString>::Iterator it;
185 int i = 0;
186 for ( it = mAttributes.begin(); it != mAttributes.end(); ++it ) {
187 if ( !it.data().isEmpty() ) {
188 unsigned int len = it.data().utf8().length();
189 LdapSearchAttr[ i ] = new char[ len+1 ];
190 memcpy( LdapSearchAttr[ i ], it.data().utf8(), len );
191 LdapSearchAttr[ i ][ len ] = 0;
192 ++i;
193 }
194 }
195 LdapSearchAttr[ i ] = 0;
196
197 QString filter = mFilter;
198 if ( filter.isEmpty() )
199 filter = "cn=*";
200
201 int result;
202 if ( ( result = ldap_search_s( mLdap, mDn.local8Bit(), LDAP_SCOPE_SUBTREE, QString( "(%1)" ).arg( filter ).local8Bit(),
203 LdapSearchAttr, 0, &res ) != LDAP_SUCCESS ) ) {
204 addressBook()->error( i18n( "Unable to search on server '%1': %2" )
205 .arg( mHost )
206 .arg( ldap_err2string( result ) ) );
207
208 for ( i = 0; LdapSearchAttr[ i ]; ++i )
209 delete [] LdapSearchAttr[ i ];
210 delete [] LdapSearchAttr;
211
212 return false;
213 }
214
215 for ( msg = ldap_first_entry( mLdap, res ); msg; msg = ldap_next_entry( mLdap, msg ) ) {
216 Addressee addr;
217 addr.setResource( this );
218 for ( names = ldap_first_attribute( mLdap, msg, &track ); names; names = ldap_next_attribute( mLdap, msg, track ) ) {
219 values = ldap_get_values( mLdap, msg, names );
220 for ( int i = 0; i < ldap_count_values( values ); ++i ) {
221 QString name = QString::fromUtf8( names ).lower();
222 QString value = QString::fromUtf8( values[ i ] );
223
224 if ( name == mAttributes[ "commonName" ].lower() ) {
225 if ( !addr.formattedName().isEmpty() ) {
226 QString fn = addr.formattedName();
227 addr.setNameFromString( value );
228 addr.setFormattedName( fn );
229 } else
230 addr.setNameFromString( value );
231 } else if ( name == mAttributes[ "formattedName" ].lower() ) {
232 addr.setFormattedName( value );
233 } else if ( name == mAttributes[ "givenName" ].lower() ) {
234 addr.setGivenName( value );
235 } else if ( name == mAttributes[ "mail" ].lower() ) {
236 addr.insertEmail( value, true );
237 } else if ( name == mAttributes[ "mailAlias" ].lower() ) {
238 addr.insertEmail( value, false );
239 } else if ( name == mAttributes[ "phoneNumber" ].lower() ) {
240 PhoneNumber phone;
241 phone.setNumber( value );
242 addr.insertPhoneNumber( phone );
243 break; // read only the home number
244 } else if ( name == mAttributes[ "familyName" ].lower() ) {
245 addr.setFamilyName( value );
246 } else if ( name == mAttributes[ "uid" ].lower() ) {
247 addr.setUid( value );
248 }
249 }
250 ldap_value_free( values );
251 }
252 ber_free( track, 0 );
253
254 addressBook()->insertAddressee( addr );
255 }
256
257 ldap_msgfree( res );
258
259 for ( i = 0; LdapSearchAttr[ i ]; ++i )
260 delete [] LdapSearchAttr[ i ];
261 delete [] LdapSearchAttr;
262
263 return true;
264}
265
266bool ResourceLDAP::save( Ticket * )
267{
268 AddressBook::Iterator it;
269 for ( it = addressBook()->begin(); it != addressBook()->end(); ++it ) {
270 if ( (*it).resource() == this && (*it).changed() ) {
271 LDAPMod **mods = NULL;
272
273 addModOp( &mods, "objectClass", "organizationalPerson" );
274 addModOp( &mods, "objectClass", "person" );
275 addModOp( &mods, "objectClass", "Top" );
276 addModOp( &mods, mAttributes[ "commonName" ].utf8(), (*it).assembledName() );
277 addModOp( &mods, mAttributes[ "formattedName" ].utf8(), (*it).formattedName() );
278 addModOp( &mods, mAttributes[ "givenName" ].utf8(), (*it).givenName() );
279 addModOp( &mods, mAttributes[ "familyName" ].utf8(), (*it).familyName() );
280 addModOp( &mods, mAttributes[ "uid" ].utf8(), (*it).uid() );
281
282 QStringList emails = (*it).emails();
283 QStringList::ConstIterator mailIt;
284 bool first = true;
285 for ( mailIt = emails.begin(); mailIt != emails.end(); ++mailIt ) {
286 if ( first ) {
287 addModOp( &mods, mAttributes[ "mail" ].utf8(), (*mailIt) );
288 first = false;
289 } else
290 addModOp( &mods, mAttributes[ "mailAlias" ].utf8(), (*mailIt) );
291 }
292
293 PhoneNumber number = (*it).phoneNumber( PhoneNumber::Home );
294 addModOp( &mods, mAttributes[ "phoneNumber" ].utf8(), number.number() );
295
296 QString dn = "cn=" + (*it).assembledName() + "," + mDn;
297
298 int retval;
299 if ( (retval = ldap_add_s( mLdap, dn.local8Bit(), mods )) != LDAP_SUCCESS )
300 addressBook()->error( i18n( "Unable to modify '%1' on server '%2'" ).arg( (*it).uid() ).arg( mHost ) );
301
302 ldap_mods_free( mods, 1 );
303
304 // mark as unchanged
305 (*it).setChanged( false );
306 }
307 }
308
309 return true;
310}
311
312void ResourceLDAP::removeAddressee( const Addressee &addr )
313{
314 LDAPMessage *res;
315 LDAPMessage *msg;
316
317 QString filter = QString( "(&(uid=%1)(%2))" ).arg( addr.uid() ).arg( mFilter );
318
319 kdDebug(5700) << "ldap:removeAddressee" << filter << endl;
320
321 ldap_search_s( mLdap, mDn.local8Bit(), LDAP_SCOPE_SUBTREE, filter.local8Bit(),
322 0, 0, &res );
323
324 for ( msg = ldap_first_entry( mLdap, res ); msg; msg = ldap_next_entry( mLdap, msg ) ) {
325 char *dn = ldap_get_dn( mLdap, msg );
326 kdDebug(5700) << "found " << dn << endl;
327 if ( ldap_delete_s( mLdap, dn ) != LDAP_SUCCESS )
328 addressBook()->error( i18n( "Unable to delete '%1' on server '%2'" ).arg( dn ).arg( mHost ) );
329 ldap_memfree( dn );
330 }
331
332 ldap_msgfree( res );
333}
334
335void ResourceLDAP::setUser( const QString &user )
336{
337 mUser = user;
338}
339
340QString ResourceLDAP::user() const
341{
342 return mUser;
343}
344
345void ResourceLDAP::setPassword( const QString &password )
346{
347 mPassword = password;
348}
349
350QString ResourceLDAP::password() const
351{
352 return mPassword;
353}
354
355void ResourceLDAP::setDn( const QString &dn )
356{
357 mDn = dn;
358}
359
360QString ResourceLDAP::dn() const
361{
362 return mDn;
363}
364
365void ResourceLDAP::setHost( const QString &host )
366{
367 mHost = host;
368}
369
370QString ResourceLDAP::host() const
371{
372 return mHost;
373}
374
375void ResourceLDAP::setPort( int port )
376{
377 mPort = port;
378}
379
380int ResourceLDAP::port() const
381{
382 return mPort;
383}
384
385void ResourceLDAP::setFilter( const QString &filter )
386{
387 mFilter = filter;
388}
389
390QString ResourceLDAP::filter() const
391{
392 return mFilter;
393}
394
395void ResourceLDAP::setIsAnonymous( bool value )
396{
397 mAnonymous = value;
398}
399
400bool ResourceLDAP::isAnonymous() const
401{
402 return mAnonymous;
403}
404
405void ResourceLDAP::setAttributes( const QMap<QString, QString> &attributes )
406{
407 mAttributes = attributes;
408}
409
410QMap<QString, QString> ResourceLDAP::attributes() const
411{
412 return mAttributes;
413}
414
415void addModOp( LDAPMod ***pmods, const QString &attr, const QString &value )
416{
417 if ( value.isNull() )
418 return;
419
420 LDAPMod**mods;
421
422 mods = *pmods;
423
424 uint i = 0;
425 if ( mods != 0 )
426 for ( ; mods[ i ] != 0; ++i );
427
428 if (( mods = (LDAPMod **)realloc( mods, (i + 2) * sizeof( LDAPMod * ))) == 0 ) {
429 kdError() << "ResourceLDAP: realloc" << endl;
430 return;
431 }
432
433 *pmods = mods;
434 mods[ i + 1 ] = 0;
435
436 mods[ i ] = new LDAPMod;
437
438 mods[ i ]->mod_op = 0;
439 mods[ i ]->mod_type = strdup( attr.utf8() );
440 mods[ i ]->mod_values = new char*[ 2 ];
441 mods[ i ]->mod_values[ 0 ] = strdup( value.utf8() );
442 mods[ i ]->mod_values[ 1 ] = 0;
443}
444