author | zautrix <zautrix> | 2004-06-26 19:01:18 (UTC) |
---|---|---|
committer | zautrix <zautrix> | 2004-06-26 19:01:18 (UTC) |
commit | b9aad1f15dc600e4dbe4c62d3fcced6363188ba3 (patch) (unidiff) | |
tree | 2c3d4004fb21c72cba65793859f9bcd8ffd3a49c /kabc/plugins/ldap/resourceldap.cpp | |
download | kdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.zip kdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.tar.gz kdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.tar.bz2 |
Initial revision
Diffstat (limited to 'kabc/plugins/ldap/resourceldap.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | kabc/plugins/ldap/resourceldap.cpp | 444 |
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 | /* | ||
22 | Enhanced Version of the file for platform independent KDE tools. | ||
23 | Copyright (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 | |||
40 | using namespace KABC; | ||
41 | |||
42 | extern "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 | |||
51 | void addModOp( LDAPMod ***pmods, const QString &attr, const QString &value ); | ||
52 | |||
53 | |||
54 | ResourceLDAP::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 | |||
90 | void 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 | |||
110 | Ticket *ResourceLDAP::requestSaveTicket() | ||
111 | { | ||
112 | if ( !addressBook() ) { | ||
113 | kdDebug(5700) << "no addressbook" << endl; | ||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | return createTicket( this ); | ||
118 | } | ||
119 | |||
120 | bool 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 | |||
164 | void 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 | |||
174 | bool 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 | |||
266 | bool 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 | |||
312 | void 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 | |||
335 | void ResourceLDAP::setUser( const QString &user ) | ||
336 | { | ||
337 | mUser = user; | ||
338 | } | ||
339 | |||
340 | QString ResourceLDAP::user() const | ||
341 | { | ||
342 | return mUser; | ||
343 | } | ||
344 | |||
345 | void ResourceLDAP::setPassword( const QString &password ) | ||
346 | { | ||
347 | mPassword = password; | ||
348 | } | ||
349 | |||
350 | QString ResourceLDAP::password() const | ||
351 | { | ||
352 | return mPassword; | ||
353 | } | ||
354 | |||
355 | void ResourceLDAP::setDn( const QString &dn ) | ||
356 | { | ||
357 | mDn = dn; | ||
358 | } | ||
359 | |||
360 | QString ResourceLDAP::dn() const | ||
361 | { | ||
362 | return mDn; | ||
363 | } | ||
364 | |||
365 | void ResourceLDAP::setHost( const QString &host ) | ||
366 | { | ||
367 | mHost = host; | ||
368 | } | ||
369 | |||
370 | QString ResourceLDAP::host() const | ||
371 | { | ||
372 | return mHost; | ||
373 | } | ||
374 | |||
375 | void ResourceLDAP::setPort( int port ) | ||
376 | { | ||
377 | mPort = port; | ||
378 | } | ||
379 | |||
380 | int ResourceLDAP::port() const | ||
381 | { | ||
382 | return mPort; | ||
383 | } | ||
384 | |||
385 | void ResourceLDAP::setFilter( const QString &filter ) | ||
386 | { | ||
387 | mFilter = filter; | ||
388 | } | ||
389 | |||
390 | QString ResourceLDAP::filter() const | ||
391 | { | ||
392 | return mFilter; | ||
393 | } | ||
394 | |||
395 | void ResourceLDAP::setIsAnonymous( bool value ) | ||
396 | { | ||
397 | mAnonymous = value; | ||
398 | } | ||
399 | |||
400 | bool ResourceLDAP::isAnonymous() const | ||
401 | { | ||
402 | return mAnonymous; | ||
403 | } | ||
404 | |||
405 | void ResourceLDAP::setAttributes( const QMap<QString, QString> &attributes ) | ||
406 | { | ||
407 | mAttributes = attributes; | ||
408 | } | ||
409 | |||
410 | QMap<QString, QString> ResourceLDAP::attributes() const | ||
411 | { | ||
412 | return mAttributes; | ||
413 | } | ||
414 | |||
415 | void 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 | |||