00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "ldapsearch.h"
00022 #include "ldapdn.h"
00023 #include "ldapdefs.h"
00024
00025 #include <QtCore/QEventLoop>
00026 #include <QtCore/QTimer>
00027
00028 #include <kdebug.h>
00029
00030 using namespace KLDAP;
00031
00032
00033 #define LDAPSEARCH_BLOCKING_TIMEOUT 10
00034
00035 class LdapSearch::Private
00036 {
00037 public:
00038 Private( LdapSearch *parent )
00039 : mParent( parent )
00040 {
00041 }
00042
00043 void result();
00044 bool connect();
00045 void closeConnection();
00046 bool startSearch( const LdapDN &base, LdapUrl::Scope scope,
00047 const QString &filter, const QStringList &attributes,
00048 int pagesize, int count );
00049
00050 LdapSearch *mParent;
00051 LdapConnection *mConn;
00052 LdapOperation mOp;
00053 bool mOwnConnection, mAbandoned;
00054 int mId, mPageSize;
00055 LdapDN mBase;
00056 QString mFilter;
00057 QStringList mAttributes;
00058 LdapUrl::Scope mScope;
00059
00060 QString mErrorString;
00061 int mError;
00062 int mCount, mMaxCount;
00063 bool mFinished;
00064 };
00065
00066 void LdapSearch::Private::result()
00067 {
00068 if ( mAbandoned ) {
00069 mOp.abandon( mId );
00070 return;
00071 }
00072 int res = mOp.waitForResult( mId, LDAPSEARCH_BLOCKING_TIMEOUT );
00073
00074 kDebug() << "LDAP result:" << res;
00075
00076 if ( res != 0 &&
00077 ( res == -1 ||
00078 ( mConn->ldapErrorCode() != KLDAP_SUCCESS &&
00079 mConn->ldapErrorCode() != KLDAP_SASL_BIND_IN_PROGRESS ) ) ) {
00080
00081 mError = mConn->ldapErrorCode();
00082 mErrorString = mConn->ldapErrorString();
00083 emit mParent->result( mParent );
00084 return;
00085 }
00086
00087
00088 if ( res == LdapOperation::RES_BIND ) {
00089
00090 QByteArray servercc;
00091 servercc = mOp.serverCred();
00092
00093 kDebug() << "LdapSearch RES_BIND";
00094 if ( mConn->ldapErrorCode() == KLDAP_SUCCESS ) {
00095 kDebug() << "bind succeeded";
00096 LdapControls savedctrls = mOp.serverControls();
00097 if ( mPageSize ) {
00098 LdapControls ctrls = savedctrls;
00099 ctrls.append( LdapControl::createPageControl( mPageSize ) );
00100 mOp.setServerControls( ctrls );
00101 }
00102
00103 mId = mOp.search( mBase, mScope, mFilter, mAttributes );
00104 mOp.setServerControls( savedctrls );
00105 } else {
00106 kDebug() << "bind next step";
00107 mId = mOp.bind( servercc );
00108 }
00109 if ( mId < 0 ) {
00110 if ( mId == KLDAP_SASL_ERROR ) {
00111 mError = mId;
00112 mErrorString = mConn->saslErrorString();
00113 } else {
00114 mError = mConn->ldapErrorCode();
00115 mErrorString = mConn->ldapErrorString();
00116 }
00117 emit mParent->result( mParent );
00118 return;
00119 }
00120 QTimer::singleShot( 0, mParent, SLOT(result()) );
00121 return;
00122 }
00123
00124
00125 if ( res == LdapOperation::RES_SEARCH_RESULT ) {
00126 if ( mPageSize ) {
00127 QByteArray cookie;
00128 int estsize = -1;
00129 for ( int i = 0; i < mOp.controls().count(); ++i ) {
00130 estsize = mOp.controls()[i].parsePageControl( cookie );
00131 if ( estsize != -1 ) {
00132 break;
00133 }
00134 }
00135 kDebug() << " estimated size:" << estsize;
00136 if ( estsize != -1 && !cookie.isEmpty() ) {
00137 LdapControls ctrls, savedctrls;
00138 savedctrls = mOp.serverControls();
00139 ctrls = savedctrls;
00140 ctrls.append( LdapControl::createPageControl( mPageSize, cookie ) );
00141 mOp.setServerControls( ctrls );
00142 mId = mOp.search( mBase, mScope, mFilter, mAttributes );
00143 mOp.setServerControls( savedctrls );
00144 if ( mId == -1 ) {
00145 mError = mConn->ldapErrorCode();
00146 mErrorString = mConn->ldapErrorString();
00147 emit mParent->result( mParent );
00148 return;
00149 }
00150
00151 QTimer::singleShot( 0, mParent, SLOT(result()) );
00152 return;
00153 }
00154 }
00155 mFinished = true;
00156 emit mParent->result( mParent );
00157 return;
00158 }
00159
00160
00161 if ( res == LdapOperation::RES_SEARCH_ENTRY ) {
00162 emit mParent->data( mParent, mOp.object() );
00163 mCount++;
00164 }
00165
00166
00167 if ( mMaxCount <= 0 || mCount < mMaxCount ) {
00168 QTimer::singleShot( 0, mParent, SLOT(result()) );
00169 }
00170
00171 if ( mMaxCount > 0 && mCount == mMaxCount ) {
00172 kDebug() << mCount << " entries reached";
00173 emit mParent->result( mParent );
00174 }
00175 }
00176
00177 bool LdapSearch::Private::connect()
00178 {
00179 int ret = mConn->connect();
00180 if ( ret != KLDAP_SUCCESS ) {
00181 mError = ret;
00182 mErrorString = mConn->connectionError();
00183 closeConnection();
00184 return false;
00185 }
00186 return true;
00187 }
00188
00189 void LdapSearch::Private::closeConnection()
00190 {
00191 if ( mOwnConnection && mConn ) {
00192 delete mConn;
00193 mConn = 0;
00194 }
00195 }
00196
00197
00198 bool LdapSearch::Private::startSearch( const LdapDN &base, LdapUrl::Scope scope,
00199 const QString &filter,
00200 const QStringList &attributes, int pagesize, int count )
00201 {
00202 kDebug() << "search: base=" << base.toString() << "scope=" << scope
00203 << "filter=" << filter << "attributes=" << attributes
00204 << "pagesize=" << pagesize;
00205 mAbandoned = false;
00206 mError = 0;
00207 mErrorString = QString();
00208 mOp.setConnection( *mConn );
00209 mPageSize = pagesize;
00210 mBase = base;
00211 mScope = scope;
00212 mFilter = filter;
00213 mAttributes = attributes;
00214 mMaxCount = count;
00215 mCount = 0;
00216 mFinished = false;
00217
00218 LdapControls savedctrls = mOp.serverControls();
00219 if ( pagesize ) {
00220 LdapControls ctrls = savedctrls;
00221 ctrls.append( LdapControl::createPageControl( pagesize ) );
00222 mOp.setServerControls( ctrls );
00223 }
00224
00225 mId = mOp.bind();
00226 if ( mId < 0 ) {
00227 if ( mId == KLDAP_SASL_ERROR ) {
00228 mError = mId;
00229 mErrorString = mConn->saslErrorString();
00230 } else {
00231 mError = mConn->ldapErrorCode();
00232 mErrorString = mConn->ldapErrorString();
00233 }
00234 return false;
00235 }
00236 kDebug() << "startSearch msg id=" << mId;
00237
00238
00239 QTimer::singleShot( 0, mParent, SLOT(result()) );
00240
00241 return true;
00242 }
00243
00245
00246 LdapSearch::LdapSearch()
00247 : d( new Private( this ) )
00248 {
00249 d->mOwnConnection = true;
00250 d->mConn = 0;
00251 }
00252
00253 LdapSearch::LdapSearch( LdapConnection &connection )
00254 : d( new Private( this ) )
00255 {
00256 d->mOwnConnection = false;
00257 d->mConn = &connection;
00258 }
00259
00260 LdapSearch::~LdapSearch()
00261 {
00262 d->closeConnection();
00263 delete d;
00264 }
00265
00266 void LdapSearch::setConnection( LdapConnection &connection )
00267 {
00268 d->closeConnection();
00269 d->mOwnConnection = false;
00270 d->mConn = &connection;
00271 }
00272
00273 void LdapSearch::setClientControls( const LdapControls &ctrls )
00274 {
00275 d->mOp.setClientControls( ctrls );
00276 }
00277
00278 void LdapSearch::setServerControls( const LdapControls &ctrls )
00279 {
00280 d->mOp.setServerControls( ctrls );
00281 }
00282
00283 bool LdapSearch::search( const LdapServer &server,
00284 const QStringList &attributes, int count )
00285 {
00286 if ( d->mOwnConnection ) {
00287 d->closeConnection();
00288 d->mConn = new LdapConnection( server );
00289 if ( !d->connect() ) {
00290 return false;
00291 }
00292 }
00293 return d->startSearch( server.baseDn(), server.scope(), server.filter(),
00294 attributes, server.pageSize(), count );
00295 }
00296
00297 bool LdapSearch::search( const LdapUrl &url, int count )
00298 {
00299 if ( d->mOwnConnection ) {
00300 d->closeConnection();
00301 d->mConn = new LdapConnection( url );
00302 if ( !d->connect() ) {
00303 return false;
00304 }
00305 }
00306 bool critical;
00307 int pagesize = url.extension( QLatin1String( "x-pagesize" ), critical ).toInt();
00308 return d->startSearch( url.dn(), url.scope(), url.filter(),
00309 url.attributes(), pagesize, count );
00310 }
00311
00312 bool LdapSearch::search( const LdapDN &base, LdapUrl::Scope scope,
00313 const QString &filter, const QStringList &attributes,
00314 int pagesize, int count )
00315 {
00316 Q_ASSERT( !d->mOwnConnection );
00317 return d->startSearch( base, scope, filter, attributes, pagesize, count );
00318 }
00319
00320 void LdapSearch::continueSearch()
00321 {
00322 Q_ASSERT( !d->mFinished );
00323 d->mCount = 0;
00324 QTimer::singleShot( 0, this, SLOT(result()) );
00325 }
00326
00327 bool LdapSearch::isFinished()
00328 {
00329 return d->mFinished;
00330 }
00331
00332 void LdapSearch::abandon()
00333 {
00334 d->mAbandoned = true;
00335 }
00336
00337 int LdapSearch::error() const
00338 {
00339 return d->mError;
00340 }
00341
00342 QString LdapSearch::errorString() const
00343 {
00344 return d->mErrorString;
00345 }
00346
00347 #include "ldapsearch.moc"