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 #include <KLocale>
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 LdapControl::insert( ctrls, 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 LdapControl::insert( ctrls, 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=" << (int)scope
00203 << "filter=" << filter << "attributes=" << attributes
00204 << "pagesize=" << pagesize;
00205 mAbandoned = false;
00206 mError = 0;
00207 mErrorString.clear();
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 mConn->setOption( 0x0008, NULL );
00222 LdapControl::insert( ctrls, LdapControl::createPageControl( pagesize ) );
00223 mOp.setServerControls( ctrls );
00224 }
00225
00226 mId = mOp.bind();
00227 if ( mId < 0 ) {
00228 if ( mId == KLDAP_SASL_ERROR ) {
00229 mError = mId;
00230 mErrorString = mConn->saslErrorString();
00231 } else {
00232 mError = mConn->ldapErrorCode();
00233 mErrorString = mConn->ldapErrorString();
00234 if ( mError == -1 && mErrorString.isEmpty() ) {
00235 mErrorString = i18n( "Cannot access to server. Please reconfigure it." );
00236 }
00237 }
00238 return false;
00239 }
00240 kDebug() << "startSearch msg id=" << mId;
00241
00242
00243 QTimer::singleShot( 0, mParent, SLOT(result()) );
00244
00245 return true;
00246 }
00247
00249
00250 LdapSearch::LdapSearch()
00251 : d( new Private( this ) )
00252 {
00253 d->mOwnConnection = true;
00254 d->mConn = 0;
00255 }
00256
00257 LdapSearch::LdapSearch( LdapConnection &connection )
00258 : d( new Private( this ) )
00259 {
00260 d->mOwnConnection = false;
00261 d->mConn = &connection;
00262 }
00263
00264 LdapSearch::~LdapSearch()
00265 {
00266 d->closeConnection();
00267 delete d;
00268 }
00269
00270 void LdapSearch::setConnection( LdapConnection &connection )
00271 {
00272 d->closeConnection();
00273 d->mOwnConnection = false;
00274 d->mConn = &connection;
00275 }
00276
00277 void LdapSearch::setClientControls( const LdapControls &ctrls )
00278 {
00279 d->mOp.setClientControls( ctrls );
00280 }
00281
00282 void LdapSearch::setServerControls( const LdapControls &ctrls )
00283 {
00284 d->mOp.setServerControls( ctrls );
00285 }
00286
00287 bool LdapSearch::search( const LdapServer &server,
00288 const QStringList &attributes, int count )
00289 {
00290 if ( d->mOwnConnection ) {
00291 d->closeConnection();
00292 d->mConn = new LdapConnection( server );
00293 if ( !d->connect() ) {
00294 return false;
00295 }
00296 }
00297 return d->startSearch( server.baseDn(), server.scope(), server.filter(),
00298 attributes, server.pageSize(), count );
00299 }
00300
00301 bool LdapSearch::search( const LdapUrl &url, int count )
00302 {
00303 if ( d->mOwnConnection ) {
00304 d->closeConnection();
00305 d->mConn = new LdapConnection( url );
00306 if ( !d->connect() ) {
00307 return false;
00308 }
00309 }
00310 bool critical;
00311 int pagesize = url.extension( QLatin1String( "x-pagesize" ), critical ).toInt();
00312 return d->startSearch( url.dn(), url.scope(), url.filter(),
00313 url.attributes(), pagesize, count );
00314 }
00315
00316 bool LdapSearch::search( const LdapDN &base, LdapUrl::Scope scope,
00317 const QString &filter, const QStringList &attributes,
00318 int pagesize, int count )
00319 {
00320 Q_ASSERT( !d->mOwnConnection );
00321 return d->startSearch( base, scope, filter, attributes, pagesize, count );
00322 }
00323
00324 void LdapSearch::continueSearch()
00325 {
00326 Q_ASSERT( !d->mFinished );
00327 d->mCount = 0;
00328 QTimer::singleShot( 0, this, SLOT(result()) );
00329 }
00330
00331 bool LdapSearch::isFinished()
00332 {
00333 return d->mFinished;
00334 }
00335
00336 void LdapSearch::abandon()
00337 {
00338 d->mAbandoned = true;
00339 }
00340
00341 int LdapSearch::error() const
00342 {
00343 return d->mError;
00344 }
00345
00346 QString LdapSearch::errorString() const
00347 {
00348 return d->mErrorString;
00349 }
00350
00351 #include "ldapsearch.moc"