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