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