• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepim API Reference
  • KDE Home
  • Contact Us
 

libkdepim

  • sources
  • kde-4.14
  • kdepim
  • libkdepim
  • ldap
ldapclientsearch.cpp
Go to the documentation of this file.
1 /* kldapclient.cpp - LDAP access
2  * Copyright (C) 2002 Klarälvdalens Datakonsult AB
3  *
4  * Author: Steffen Hansen <hansen@kde.org>
5  *
6  * Ported to KABC by Daniel Molkentin <molkentin@kde.org>
7  *
8  * Copyright (C) 2013-2015 Laurent Montel <montel@kde.org>
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public License
21  * along with this library; see the file COPYING.LIB. If not, write to
22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  */
25 
26 #include "ldapclientsearch.h"
27 #include "ldapclientsearchconfig.h"
28 
29 #include "ldapclient.h"
30 #include "ldapsession.h"
31 #include "ldapqueryjob.h"
32 
33 #include <kldap/ldapserver.h>
34 #include <kldap/ldapurl.h>
35 #include <kldap/ldif.h>
36 
37 #include <KConfig>
38 #include <KConfigGroup>
39 #include <KDebug>
40 #include <KDirWatch>
41 #include <KProtocolInfo>
42 #include <KStandardDirs>
43 #include <kio/job.h>
44 
45 #include <QtCore/QPointer>
46 #include <QtCore/QTimer>
47 
48 
49 using namespace KLDAP;
50 
51 class LdapClientSearch::Private
52 {
53 public:
54  Private( LdapClientSearch *qq )
55  : q( qq ),
56  mActiveClients( 0 ),
57  mNoLDAPLookup( false )
58  {
59  mClientSearchConfig = new LdapClientSearchConfig;
60  }
61 
62  ~Private()
63  {
64  delete mClientSearchConfig;
65  }
66 
67  void readWeighForClient( LdapClient *client, const KConfigGroup &config, int clientNumber );
68  void readConfig();
69  void finish();
70  void makeSearchData( QStringList &ret, LdapResult::List &resList );
71 
72  void slotLDAPResult( const KLDAP::LdapClient &client, const KLDAP::LdapObject& );
73  void slotLDAPError( const QString& );
74  void slotLDAPDone();
75  void slotDataTimer();
76  void slotFileChanged( const QString& );
77 
78  LdapClientSearch *q;
79  QList<LdapClient*> mClients;
80  QStringList mAttributes;
81  QString mSearchText;
82  QString mFilter;
83  QTimer mDataTimer;
84  int mActiveClients;
85  bool mNoLDAPLookup;
86  QList<LdapResultObject> mResults;
87  QString mConfigFile;
88  LdapClientSearchConfig *mClientSearchConfig;
89 };
90 
91 LdapClientSearch::LdapClientSearch( QObject *parent )
92  : QObject( parent ), d( new Private( this ) )
93 {
94  if ( !KProtocolInfo::isKnownProtocol( KUrl( "ldap://localhost" ) ) ) {
95  d->mNoLDAPLookup = true;
96  return;
97  }
98 
99 
100  d->mAttributes << QLatin1String("cn")
101  << QLatin1String("mail")
102  << QLatin1String("givenname")
103  << QLatin1String("sn");
104 
105  // Set the filter, to make sure old usage (before 4.14) of this object still works.
106  d->mFilter = QString::fromLatin1("&(|(objectclass=person)(objectclass=groupOfNames)(mail=*))"
107  "(|(cn=%1*)(mail=%1*)(givenName=%1*)(sn=%1*))");
108 
109  d->readConfig();
110  connect( KDirWatch::self(), SIGNAL(dirty(QString)), this,
111  SLOT(slotFileChanged(QString)) );
112 
113 }
114 
115 LdapClientSearch::~LdapClientSearch()
116 {
117  delete d;
118 }
119 
120 void LdapClientSearch::Private::readWeighForClient( LdapClient *client, const KConfigGroup &config,
121  int clientNumber )
122 {
123  const int completionWeight = config.readEntry( QString::fromLatin1( "SelectedCompletionWeight%1" ).arg( clientNumber ), -1 );
124  if ( completionWeight != -1 ) {
125  client->setCompletionWeight( completionWeight );
126  }
127 }
128 
129 void LdapClientSearch::updateCompletionWeights()
130 {
131  KConfigGroup config( KLDAP::LdapClientSearchConfig::config(), "LDAP" );
132  for ( int i = 0; i < d->mClients.size(); ++i ) {
133  d->readWeighForClient( d->mClients[ i ], config, i );
134  }
135 }
136 
137 QList<LdapClient*> LdapClientSearch::clients() const
138 {
139  return d->mClients;
140 }
141 
142 QString LdapClientSearch::filter() const
143 {
144  return d->mFilter;
145 }
146 
147 void LdapClientSearch::setFilter(const QString &filter)
148 {
149  d->mFilter = filter;
150 }
151 
152 QStringList LdapClientSearch::attributes() const
153 {
154  return d->mAttributes;
155 }
156 
157 void LdapClientSearch::setAttributes(const QStringList &attrs)
158 {
159 
160  if ( attrs != d->mAttributes ) {
161  d->mAttributes = attrs;
162  d->readConfig();
163  }
164 }
165 
166 
167 void LdapClientSearch::Private::readConfig()
168 {
169  q->cancelSearch();
170  qDeleteAll( mClients );
171  mClients.clear();
172 
173  // stolen from KAddressBook
174  KConfigGroup config( KLDAP::LdapClientSearchConfig::config(), "LDAP" );
175  const int numHosts = config.readEntry( "NumSelectedHosts", 0 );
176  if ( !numHosts ) {
177  mNoLDAPLookup = true;
178  } else {
179  for ( int j = 0; j < numHosts; ++j ) {
180  LdapClient *ldapClient = new LdapClient( j, q );
181  KLDAP::LdapServer server;
182  mClientSearchConfig->readConfig( server, config, j, true );
183  if ( !server.host().isEmpty() ) {
184  mNoLDAPLookup = false;
185  }
186  ldapClient->setServer( server );
187 
188  readWeighForClient( ldapClient, config, j );
189 
190  ldapClient->setAttributes( mAttributes );
191 
192  q->connect( ldapClient, SIGNAL(result(KLDAP::LdapClient,KLDAP::LdapObject)),
193  q, SLOT(slotLDAPResult(KLDAP::LdapClient,KLDAP::LdapObject)) );
194  q->connect( ldapClient, SIGNAL(done()),
195  q, SLOT(slotLDAPDone()) );
196  q->connect( ldapClient, SIGNAL(error(QString)),
197  q, SLOT(slotLDAPError(QString)) );
198 
199  mClients.append( ldapClient );
200  }
201 
202  q->connect( &mDataTimer, SIGNAL(timeout()), SLOT(slotDataTimer()) );
203  }
204  mConfigFile = KStandardDirs::locateLocal( "config", QLatin1String("kabldaprc") );
205  KDirWatch::self()->addFile( mConfigFile );
206 }
207 
208 void LdapClientSearch::Private::slotFileChanged( const QString &file )
209 {
210  if ( file == mConfigFile ) {
211  readConfig();
212  }
213 }
214 
215 void LdapClientSearch::startSearch( const QString &txt )
216 {
217  if ( d->mNoLDAPLookup ) {
218  return;
219  }
220 
221  cancelSearch();
222 
223  int pos = txt.indexOf( QLatin1Char('\"') );
224  if ( pos >= 0 ) {
225  ++pos;
226  const int pos2 = txt.indexOf( QLatin1Char('\"'), pos );
227  if ( pos2 >= 0 ) {
228  d->mSearchText = txt.mid( pos, pos2 - pos );
229  } else {
230  d->mSearchText = txt.mid( pos );
231  }
232  } else {
233  d->mSearchText = txt;
234  }
235 
236  const QString filter = d->mFilter.arg( d->mSearchText );
237 
238  QList<LdapClient*>::Iterator it;
239  QList<LdapClient*>::Iterator end(d->mClients.end());
240  for ( it = d->mClients.begin(); it != end; ++it ) {
241  (*it)->startQuery( filter );
242  kDebug(5300) <<"LdapClientSearch::startSearch()" << filter;
243  ++d->mActiveClients;
244  }
245 }
246 
247 void LdapClientSearch::cancelSearch()
248 {
249  QList<LdapClient*>::Iterator it;
250  QList<LdapClient*>::Iterator end(d->mClients.end());
251  for ( it = d->mClients.begin(); it != end; ++it ) {
252  (*it)->cancelQuery();
253  }
254 
255  d->mActiveClients = 0;
256  d->mResults.clear();
257 }
258 
259 void LdapClientSearch::Private::slotLDAPResult( const LdapClient &client,
260  const KLDAP::LdapObject &obj )
261 {
262  LdapResultObject result;
263  result.client = &client;
264  result.object = obj;
265 
266  mResults.append( result );
267  if ( !mDataTimer.isActive() ) {
268  mDataTimer.setSingleShot( true );
269  mDataTimer.start( 500 );
270  }
271 }
272 
273 void LdapClientSearch::Private::slotLDAPError( const QString& )
274 {
275  slotLDAPDone();
276 }
277 
278 void LdapClientSearch::Private::slotLDAPDone()
279 {
280  if ( --mActiveClients > 0 ) {
281  return;
282  }
283 
284  finish();
285 }
286 
287 void LdapClientSearch::Private::slotDataTimer()
288 {
289  QStringList lst;
290  LdapResult::List reslist;
291 
292  emit q->searchData(mResults);
293 
294  makeSearchData( lst, reslist );
295  if ( !lst.isEmpty() ) {
296  emit q->searchData( lst );
297  }
298  if ( !reslist.isEmpty() ) {
299  emit q->searchData( reslist );
300  }
301 }
302 
303 void LdapClientSearch::Private::finish()
304 {
305  mDataTimer.stop();
306 
307  slotDataTimer(); // emit final bunch of data
308  emit q->searchDone();
309 }
310 
311 void LdapClientSearch::Private::makeSearchData( QStringList &ret, LdapResult::List &resList )
312 {
313 
314  QList< LdapResultObject >::ConstIterator it1;
315  QList< LdapResultObject >::ConstIterator end1(mResults.constEnd());
316  for ( it1 = mResults.constBegin(); it1 != end1; ++it1 ) {
317  QString name, mail, givenname, sn;
318  QStringList mails;
319  bool isDistributionList = false;
320  bool wasCN = false;
321  bool wasDC = false;
322 
323  //kDebug(5300) <<"\n\nLdapClientSearch::makeSearchData()";
324 
325  KLDAP::LdapAttrMap::ConstIterator it2;
326  for ( it2 = (*it1).object.attributes().constBegin();
327  it2 != (*it1).object.attributes().constEnd(); ++it2 ) {
328  QByteArray val = (*it2).first();
329  int len = val.size();
330  if ( len > 0 && '\0' == val[len-1] ) {
331  --len;
332  }
333  const QString tmp = QString::fromUtf8( val, len );
334  //kDebug(5300) <<" key: \"" << it2.key() <<"\" value: \"" << tmp <<"\"";
335  if ( it2.key() == QLatin1String("cn") ) {
336  name = tmp;
337  if ( mail.isEmpty() ) {
338  mail = tmp;
339  } else {
340  if ( wasCN ) {
341  mail.prepend( QLatin1String(".") );
342  } else {
343  mail.prepend( QLatin1String("@") );
344  }
345  mail.prepend( tmp );
346  }
347  wasCN = true;
348  } else if ( it2.key() == QLatin1String("dc") ) {
349  if ( mail.isEmpty() ) {
350  mail = tmp;
351  } else {
352  if ( wasDC ) {
353  mail.append( QLatin1String(".") );
354  } else {
355  mail.append( QLatin1String("@") );
356  }
357  mail.append( tmp );
358  }
359  wasDC = true;
360  } else if ( it2.key() == QLatin1String("mail") ) {
361  mail = tmp;
362  KLDAP::LdapAttrValue::ConstIterator it3 = it2.value().constBegin();
363  for ( ; it3 != it2.value().constEnd(); ++it3 ) {
364  mails.append( QString::fromUtf8( (*it3).data(), (*it3).size() ) );
365  }
366  } else if ( it2.key() == QLatin1String("givenName") ) {
367  givenname = tmp;
368  } else if ( it2.key() == QLatin1String("sn") ) {
369  sn = tmp;
370  } else if ( it2.key() == QLatin1String("objectClass") &&
371  (tmp == QLatin1String("groupOfNames") || tmp == QLatin1String("kolabGroupOfNames")) ) {
372  isDistributionList = true;
373  }
374  }
375 
376  if ( mails.isEmpty() ) {
377  if ( !mail.isEmpty() ) {
378  mails.append( mail );
379  }
380  if ( isDistributionList ) {
381  //kDebug(5300) <<"\n\nLdapClientSearch::makeSearchData() found a list:" << name;
382  ret.append( name );
383  // following lines commented out for bugfixing kolab issue #177:
384  //
385  // Unlike we thought previously we may NOT append the server name here.
386  //
387  // The right server is found by the SMTP server instead: Kolab users
388  // must use the correct SMTP server, by definition.
389  //
390  //mail = (*it1).client->base().simplified();
391  //mail.replace( ",dc=", ".", false );
392  //if( mail.startsWith("dc=", false) )
393  // mail.remove(0, 3);
394  //mail.prepend( '@' );
395  //mail.prepend( name );
396  //mail = name;
397  } else {
398  continue; // nothing, bad entry
399  }
400  } else if ( name.isEmpty() ) {
401  ret.append( mail );
402  } else {
403  ret.append( QString::fromLatin1( "%1 <%2>" ).arg( name ).arg( mail ) );
404  }
405 
406  LdapResult sr;
407  sr.dn = (*it1).object.dn();
408  sr.clientNumber = (*it1).client->clientNumber();
409  sr.completionWeight = (*it1).client->completionWeight();
410  sr.name = name;
411  sr.email = mails;
412  resList.append( sr );
413  }
414 
415  mResults.clear();
416 }
417 
418 bool LdapClientSearch::isAvailable() const
419 {
420  return !d->mNoLDAPLookup;
421 }
422 
423 #include "moc_ldapclientsearch.cpp"
QString::constBegin
const_iterator constBegin() const
QList::clear
void clear()
KLDAP::LdapResultObject::client
const LdapClient * client
Definition: ldapclientsearch.h:42
QString::indexOf
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
KLDAP::LdapClientSearch::isAvailable
bool isAvailable() const
Returns whether LDAP search is possible at all.
Definition: ldapclientsearch.cpp:418
QString::append
QString & append(QChar ch)
KLDAP::LdapResult::clientNumber
int clientNumber
The client the contact comes from (used for sorting in a ldap-only lookup).
Definition: ldapclientsearch.h:61
ldapclientsearch.h
QByteArray
KLDAP::LdapClientSearch::setFilter
void setFilter(const QString &)
Sets the filter for the Query.
Definition: ldapclientsearch.cpp:147
KLDAP::LdapClientSearch
Definition: ldapclientsearch.h:68
QString::prepend
QString & prepend(QChar ch)
ldapsession.h
KLDAP::LdapClientSearch::cancelSearch
void cancelSearch()
Cancels the currently running search query.
Definition: ldapclientsearch.cpp:247
KLDAP::LdapResult
Describes the result returned by an LdapClientSearch query.
Definition: ldapclientsearch.h:51
KLDAP::LdapResult::name
QString name
The full name of the contact.
Definition: ldapclientsearch.h:59
KLDAP::LdapClientSearch::clients
QList< LdapClient * > clients() const
Returns the list of configured LDAP clients.
Definition: ldapclientsearch.cpp:137
ldapclient.h
QList::append
void append(const T &value)
QString::fromUtf8
QString fromUtf8(const char *str, int size)
QTimer
QObject
ldapclientsearchconfig.h
QList::isEmpty
bool isEmpty() const
QString::isEmpty
bool isEmpty() const
KLDAP::LdapClient::setAttributes
void setAttributes(const QStringList &attributes)
Sets the LDAP attributes that should be returned in the query result.
Definition: ldapclient.cpp:119
QString
QList
KLDAP::LdapClientSearch::LdapClientSearch
LdapClientSearch(QObject *parent=0)
Creates a new ldap client search object.
Definition: ldapclientsearch.cpp:91
QStringList
KLDAP::LdapClientSearch::startSearch
void startSearch(const QString &query)
Starts the LDAP search on all configured LDAP clients with the given search query.
Definition: ldapclientsearch.cpp:215
QLatin1Char
KLDAP::LdapClientSearch::attributes
QStringList attributes() const
Returns the attributes, that are queried the LDAP Server.
Definition: ldapclientsearch.cpp:152
QString::mid
QString mid(int position, int n) const
KLDAP::LdapResultObject
Describes the result returned by an LdapClientSearch query.
Definition: ldapclientsearch.h:41
QLatin1String
KLDAP::LdapClient::setServer
void setServer(const KLDAP::LdapServer &server)
Sets the LDAP server information that shall be used by this client.
Definition: ldapclient.cpp:104
KLDAP::LdapClientSearch::~LdapClientSearch
~LdapClientSearch()
Destroys the ldap client search object.
Definition: ldapclientsearch.cpp:115
KLDAP::LdapClient::setCompletionWeight
void setCompletionWeight(int weight)
Sets the completion weight of this client.
Definition: ldapclient.cpp:317
QString::fromLatin1
QString fromLatin1(const char *str, int size)
KLDAP::LdapResultObject::object
KLDAP::LdapObject object
Definition: ldapclientsearch.h:43
QList::constBegin
const_iterator constBegin() const
KLDAP::LdapClientSearch::filter
QString filter() const
Returns the filter for the Query.
Definition: ldapclientsearch.cpp:142
QByteArray::size
int size() const
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
KLDAP::LdapResult::email
QStringList email
The list of emails of the contact.
Definition: ldapclientsearch.h:60
KLDAP::LdapClient
An object that represents a configured LDAP server.
Definition: ldapclient.h:46
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QList::begin
iterator begin()
KLDAP::LdapClientSearch::setAttributes
void setAttributes(const QStringList &)
Sets the attributes, that are queried the LDAP Server.
Definition: ldapclientsearch.cpp:157
KLDAP::LdapClientSearch::updateCompletionWeights
void updateCompletionWeights()
Updates the completion weights for the configured LDAP clients from the configuration file...
Definition: ldapclientsearch.cpp:129
KLDAP::LdapResult::completionWeight
int completionWeight
The weight of the contact (used for sorting in a completion list).
Definition: ldapclientsearch.h:62
KLDAP::LdapResult::dn
LdapDN dn
Definition: ldapclientsearch.h:58
ldapqueryjob.h
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:33:50 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

libkdepim

Skip menu "libkdepim"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules

kdepim API Reference

Skip menu "kdepim API Reference"
  • akonadi_next
  • akregator
  • blogilo
  • calendarsupport
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt2
  • kjots
  • kleopatra
  • kmail
  • knode
  • knotes
  • kontact
  • korgac
  • korganizer
  • ktimetracker
  • libkdepim
  • libkleo
  • libkpgp
  • mailcommon
  • messagelist
  • messageviewer
  • pimprint

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal