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

KLDAP Library

  • sources
  • kde-4.14
  • kdepimlibs
  • kldap
ldapsearch.cpp
1 /*
2  This file is part of libkldap.
3  Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
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., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301, USA.
19 */
20 
21 #include "ldapsearch.h"
22 #include "ldapdn.h"
23 #include "ldapdefs.h"
24 
25 #include <QtCore/QEventLoop>
26 #include <QtCore/QTimer>
27 
28 #include <kdebug.h>
29 #include <KLocalizedString>
30 using namespace KLDAP;
31 
32 //blocking the GUI for xxx milliseconds
33 #define LDAPSEARCH_BLOCKING_TIMEOUT 10
34 
35 class LdapSearch::Private
36 {
37  public:
38  Private( LdapSearch *parent )
39  : mParent( parent )
40  {
41  }
42 
43  void result();
44  bool connect();
45  void closeConnection();
46  bool startSearch( const LdapDN &base, LdapUrl::Scope scope,
47  const QString &filter, const QStringList &attributes,
48  int pagesize, int count );
49 
50  LdapSearch *mParent;
51  LdapConnection *mConn;
52  LdapOperation mOp;
53  bool mOwnConnection, mAbandoned;
54  int mId, mPageSize;
55  LdapDN mBase;
56  QString mFilter;
57  QStringList mAttributes;
58  LdapUrl::Scope mScope;
59 
60  QString mErrorString;
61  int mError;
62  int mCount, mMaxCount;
63  bool mFinished;
64 };
65 
66 void LdapSearch::Private::result()
67 {
68  if ( mAbandoned ) {
69  mOp.abandon( mId );
70  return;
71  }
72  int res = mOp.waitForResult( mId, LDAPSEARCH_BLOCKING_TIMEOUT );
73 
74  kDebug() << "LDAP result:" << res;
75 
76  if ( res != 0 &&
77  ( res == -1 ||
78  ( mConn->ldapErrorCode() != KLDAP_SUCCESS &&
79  mConn->ldapErrorCode() != KLDAP_SASL_BIND_IN_PROGRESS ) ) ) {
80  //error happened, but no timeout
81  mError = mConn->ldapErrorCode();
82  mErrorString = mConn->ldapErrorString();
83  emit mParent->result( mParent );
84  return;
85  }
86 
87  //binding
88  if ( res == LdapOperation::RES_BIND ) {
89 
90  QByteArray servercc;
91  servercc = mOp.serverCred();
92 
93  kDebug() << "LdapSearch RES_BIND";
94  if ( mConn->ldapErrorCode() == KLDAP_SUCCESS ) { //bind succeeded
95  kDebug() << "bind succeeded";
96  LdapControls savedctrls = mOp.serverControls();
97  if ( mPageSize ) {
98  LdapControls ctrls = savedctrls;
99  LdapControl::insert( ctrls, LdapControl::createPageControl( mPageSize ) );
100  mOp.setServerControls( ctrls );
101  }
102 
103  mId = mOp.search( mBase, mScope, mFilter, mAttributes );
104  mOp.setServerControls( savedctrls );
105  } else { //next bind step
106  kDebug() << "bind next step";
107  mId = mOp.bind( servercc );
108  }
109  if ( mId < 0 ) {
110  if ( mId == KLDAP_SASL_ERROR ) {
111  mError = mId;
112  mErrorString = mConn->saslErrorString();
113  } else {
114  mError = mConn->ldapErrorCode();
115  mErrorString = mConn->ldapErrorString();
116  }
117  emit mParent->result( mParent );
118  return;
119  }
120  QTimer::singleShot( 0, mParent, SLOT(result()) );
121  return;
122  }
123 
124  //End of entries
125  if ( res == LdapOperation::RES_SEARCH_RESULT ) {
126  if ( mPageSize ) {
127  QByteArray cookie;
128  int estsize = -1;
129  const int numberOfControls( mOp.controls().count() );
130  for ( int i = 0; i < numberOfControls; ++i ) {
131  estsize = mOp.controls()[i].parsePageControl( cookie );
132  if ( estsize != -1 ) {
133  break;
134  }
135  }
136  kDebug() << " estimated size:" << estsize;
137  if ( estsize != -1 && !cookie.isEmpty() ) {
138  LdapControls ctrls, savedctrls;
139  savedctrls = mOp.serverControls();
140  ctrls = savedctrls;
141  LdapControl::insert( ctrls, LdapControl::createPageControl ( mPageSize, cookie ) );
142  mOp.setServerControls( ctrls );
143  mId = mOp.search( mBase, mScope, mFilter, mAttributes );
144  mOp.setServerControls( savedctrls );
145  if ( mId == -1 ) {
146  mError = mConn->ldapErrorCode();
147  mErrorString = mConn->ldapErrorString();
148  emit mParent->result( mParent );
149  return;
150  }
151  //continue with the next page
152  QTimer::singleShot( 0, mParent, SLOT(result()) );
153  return;
154  }
155  }
156  mFinished = true;
157  emit mParent->result( mParent );
158  return;
159  }
160 
161  //Found an entry
162  if ( res == LdapOperation::RES_SEARCH_ENTRY ) {
163  emit mParent->data( mParent, mOp.object() );
164  mCount++;
165  }
166 
167  //If not reached the requested entries, continue
168  if ( mMaxCount <= 0 || mCount < mMaxCount ) {
169  QTimer::singleShot( 0, mParent, SLOT(result()) );
170  }
171  //If reached the requested entries, indicate it
172  if ( mMaxCount > 0 && mCount == mMaxCount ) {
173  kDebug() << mCount << " entries reached";
174  emit mParent->result( mParent );
175  }
176 }
177 
178 bool LdapSearch::Private::connect()
179 {
180  int ret = mConn->connect();
181  if ( ret != KLDAP_SUCCESS ) {
182  mError = ret;
183  mErrorString = mConn->connectionError();
184  closeConnection();
185  return false;
186  }
187  return true;
188 }
189 
190 void LdapSearch::Private::closeConnection()
191 {
192  if ( mOwnConnection && mConn ) {
193  delete mConn;
194  mConn = 0;
195  }
196 }
197 
198 //This starts the real job
199 bool LdapSearch::Private::startSearch( const LdapDN &base, LdapUrl::Scope scope,
200  const QString &filter,
201  const QStringList &attributes, int pagesize, int count )
202 {
203  kDebug() << "search: base=" << base.toString() << "scope=" << (int)scope
204  << "filter=" << filter << "attributes=" << attributes
205  << "pagesize=" << pagesize;
206  mAbandoned = false;
207  mError = 0;
208  mErrorString.clear();
209  mOp.setConnection( *mConn );
210  mPageSize = pagesize;
211  mBase = base;
212  mScope = scope;
213  mFilter = filter;
214  mAttributes = attributes;
215  mMaxCount = count;
216  mCount = 0;
217  mFinished = false;
218 
219  LdapControls savedctrls = mOp.serverControls();
220  if ( pagesize ) {
221  LdapControls ctrls = savedctrls;
222  mConn->setOption( 0x0008, NULL ); // Disable referals or paging won't work
223  LdapControl::insert( ctrls, LdapControl::createPageControl( pagesize ) );
224  mOp.setServerControls( ctrls );
225  }
226 
227  mId = mOp.bind();
228  if ( mId < 0 ) {
229  if ( mId == KLDAP_SASL_ERROR ) {
230  mError = mId;
231  mErrorString = mConn->saslErrorString();
232  } else {
233  mError = mConn->ldapErrorCode();
234  mErrorString = mConn->ldapErrorString();
235  if ( mError == -1 && mErrorString.isEmpty() ) {
236  mErrorString = i18n( "Cannot access to server. Please reconfigure it." );
237  }
238  }
239  return false;
240  }
241  kDebug() << "startSearch msg id=" << mId;
242 
243  //maybe do this with threads?- need thread-safe client libs!!!
244  QTimer::singleShot( 0, mParent, SLOT(result()) );
245 
246  return true;
247 }
248 
250 
251 LdapSearch::LdapSearch()
252  : d( new Private( this ) )
253 {
254  d->mOwnConnection = true;
255  d->mConn = 0;
256 }
257 
258 LdapSearch::LdapSearch( LdapConnection &connection )
259  : d( new Private( this ) )
260 {
261  d->mOwnConnection = false;
262  d->mConn = &connection;
263 }
264 
265 LdapSearch::~LdapSearch()
266 {
267  d->closeConnection();
268  delete d;
269 }
270 
271 void LdapSearch::setConnection( LdapConnection &connection )
272 {
273  d->closeConnection();
274  d->mOwnConnection = false;
275  d->mConn = &connection;
276 }
277 
278 void LdapSearch::setClientControls( const LdapControls &ctrls )
279 {
280  d->mOp.setClientControls( ctrls );
281 }
282 
283 void LdapSearch::setServerControls( const LdapControls &ctrls )
284 {
285  d->mOp.setServerControls( ctrls );
286 }
287 
288 bool LdapSearch::search( const LdapServer &server,
289  const QStringList &attributes, int count )
290 {
291  if ( d->mOwnConnection ) {
292  d->closeConnection();
293  d->mConn = new LdapConnection( server );
294  if ( !d->connect() ) {
295  return false;
296  }
297  }
298  return d->startSearch( server.baseDn(), server.scope(), server.filter(),
299  attributes, server.pageSize(), count );
300 }
301 
302 bool LdapSearch::search( const LdapUrl &url, int count )
303 {
304  if ( d->mOwnConnection ) {
305  d->closeConnection();
306  d->mConn = new LdapConnection( url );
307  if ( !d->connect() ) {
308  return false;
309  }
310  }
311  bool critical = true;
312  int pagesize = url.extension( QLatin1String( "x-pagesize" ), critical ).toInt();
313  return d->startSearch( url.dn(), url.scope(), url.filter(),
314  url.attributes(), pagesize, count );
315 }
316 
317 bool LdapSearch::search( const LdapDN &base, LdapUrl::Scope scope,
318  const QString &filter, const QStringList &attributes,
319  int pagesize, int count )
320 {
321  Q_ASSERT( !d->mOwnConnection );
322  return d->startSearch( base, scope, filter, attributes, pagesize, count );
323 }
324 
325 void LdapSearch::continueSearch()
326 {
327  Q_ASSERT( !d->mFinished );
328  d->mCount = 0;
329  QTimer::singleShot( 0, this, SLOT(result()) );
330 }
331 
332 bool LdapSearch::isFinished()
333 {
334  return d->mFinished;
335 }
336 
337 void LdapSearch::abandon()
338 {
339  d->mAbandoned = true;
340 }
341 
342 int LdapSearch::error() const
343 {
344  return d->mError;
345 }
346 
347 QString LdapSearch::errorString() const
348 {
349  return d->mErrorString;
350 }
351 
352 #include "moc_ldapsearch.cpp"
KLDAP::LdapServer::baseDn
LdapDN baseDn() const
Returns the baseDn of the LDAP connection.
Definition: ldapserver.cpp:106
QList::clear
void clear()
KLDAP::LdapSearch::setServerControls
void setServerControls(const LdapControls &ctrls)
Sets the server controls which will sent with each operation.
Definition: ldapsearch.cpp:283
QByteArray
KLDAP::LdapSearch::setConnection
void setConnection(LdapConnection &connection)
Sets the connection for this object to use for searches from now onwards, regardless of the LDAP Url ...
Definition: ldapsearch.cpp:271
KLDAP::LdapSearch::search
bool search(const LdapServer &server, const QStringList &attributes=QStringList(), int count=0)
Starts a search operation on the LDAP server.
Definition: ldapsearch.cpp:288
KLDAP::LdapSearch::abandon
void abandon()
Tries to abandon the search.
Definition: ldapsearch.cpp:337
KLDAP::LdapUrl::filter
QString filter() const
Returns the filter part of the LDAP url.
Definition: ldapurl.cpp:123
KLDAP::LdapUrl::attributes
QStringList attributes() const
Returns the attributes part of the LDAP url.
Definition: ldapurl.cpp:101
QByteArray::isEmpty
bool isEmpty() const
KLDAP::LdapControl::createPageControl
static LdapControl createPageControl(int pagesize, const QByteArray &cookie=QByteArray())
Creates a paging search control.
Definition: ldapcontrol.cpp:134
KLDAP::LdapSearch::LdapSearch
LdapSearch()
Constructs an LdapSearch object.
Definition: ldapsearch.cpp:251
KLDAP::LdapUrl
A special url class for LDAP.
Definition: ldapurl.h:42
KLDAP::LdapSearch::continueSearch
void continueSearch()
Continues the search (if you set count to non-zero in search(), and isFinished() is false) ...
Definition: ldapsearch.cpp:325
KLDAP::LdapSearch::errorString
QString errorString() const
Returns the error description of the search operation.
Definition: ldapsearch.cpp:347
KLDAP::LdapUrl::Scope
Scope
Describes the scope of the LDAP url.
Definition: ldapurl.h:58
KLDAP::LdapServer::pageSize
int pageSize() const
Returns the page size of the LDAP connection.
Definition: ldapserver.cpp:151
KLDAP::LdapUrl::scope
Scope scope() const
Returns the scope part of the LDAP url.
Definition: ldapurl.cpp:112
KLDAP::LdapServer::scope
LdapUrl::Scope scope() const
Returns the search scope of the LDAP connection.
Definition: ldapserver.cpp:136
KLDAP::LdapServer
A class that contains LDAP server connection settings.
Definition: ldapserver.h:38
QString
QList
QStringList
KLDAP::LdapConnection
This class represents a connection to an LDAP server.
Definition: ldapconnection.h:36
KLDAP::LdapSearch::result
void result(KLDAP::LdapSearch *search)
Emitted when the searching finished.
KLDAP::LdapSearch
This class starts a search operation on a LDAP server and returns the search values via a Qt signal...
Definition: ldapsearch.h:45
KLDAP::LdapSearch::setClientControls
void setClientControls(const LdapControls &ctrls)
Sets the client controls which will sent with each operation.
Definition: ldapsearch.cpp:278
KLDAP::LdapUrl::dn
LdapDN dn() const
Returns the dn part of the LDAP url.
Definition: ldapurl.cpp:91
QLatin1String
KLDAP::LdapOperation
This class allows sending an ldap operation (search, rename, modify, delete, compare, exop) to an LDAP server.
Definition: ldapoperation.h:43
KLDAP::LdapSearch::isFinished
bool isFinished()
Returns true if the search is finished else returns false.
Definition: ldapsearch.cpp:332
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject::parent
QObject * parent() const
KLDAP::LdapUrl::extension
Extension extension(const QString &extension) const
Returns the specified extension.
Definition: ldapurl.cpp:139
KLDAP::LdapControl::insert
static void insert(LdapControls &list, const LdapControl &ctrl)
Inserts a unique control against a list of controls.
Definition: ldapcontrol.cpp:145
KLDAP::LdapSearch::error
int error() const
Returns the error code of the search operation (0 if no error).
Definition: ldapsearch.cpp:342
KLDAP::LdapServer::filter
QString filter() const
Returns the filter string of the LDAP connection.
Definition: ldapserver.cpp:131
QTimer::singleShot
singleShot
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:37:58 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KLDAP Library

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

kdepimlibs API Reference

Skip menu "kdepimlibs API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2

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