File indexing completed on 2024-12-22 04:59:50
0001 /* 0002 SPDX-FileCopyrightText: 2004-2007 Szombathelyi György <gyurco@freemail.hu> 0003 0004 SPDX-License-Identifier: MIT 0005 0006 */ 0007 0008 #include "kio_ldap.h" 0009 #include "kldap_debug.h" 0010 0011 #include "kldapcore/ldif.h" 0012 0013 #include <KLocalizedString> 0014 #include <QCoreApplication> 0015 #include <QDebug> 0016 0017 #ifdef Q_OS_WIN 0018 #include <Winsock2.h> 0019 #else 0020 #include <netdb.h> 0021 #include <netinet/in.h> 0022 #endif 0023 #include <sys/stat.h> 0024 0025 using namespace KIO; 0026 using namespace KLDAPCore; 0027 0028 // Pseudo plugin class to embed meta data 0029 class KIOPluginForMetaData : public QObject 0030 { 0031 Q_OBJECT 0032 Q_PLUGIN_METADATA(IID "org.kde.kio.worker.ldap" FILE "ldap.json") 0033 }; 0034 0035 extern "C" { 0036 int Q_DECL_EXPORT kdemain(int argc, char **argv); 0037 } 0038 0039 /** 0040 * The main program. 0041 */ 0042 int kdemain(int argc, char **argv) 0043 { 0044 QCoreApplication app(argc, argv); // needed for QSocketNotifier 0045 app.setApplicationName(QStringLiteral("kio_ldap")); 0046 0047 qCDebug(KLDAP_LOG) << "Starting kio_ldap instance"; 0048 0049 if (argc != 4) { 0050 qCritical() << "Usage kio_ldap protocol pool app"; 0051 return -1; 0052 } 0053 0054 // let the protocol class do its work 0055 LDAPProtocol worker(argv[1], argv[2], argv[3]); 0056 worker.dispatchLoop(); 0057 0058 qCDebug(KLDAP_LOG) << "Done"; 0059 return 0; 0060 } 0061 0062 /** 0063 * Initialize the ldap worker 0064 */ 0065 LDAPProtocol::LDAPProtocol(const QByteArray &protocol, const QByteArray &pool, const QByteArray &app) 0066 : WorkerBase(protocol, pool, app) 0067 , mProtocol(protocol) 0068 { 0069 mOp.setConnection(mConn); 0070 qCDebug(KLDAP_LOG) << "LDAPProtocol::LDAPProtocol (" << protocol << ")"; 0071 } 0072 0073 LDAPProtocol::~LDAPProtocol() 0074 { 0075 closeConnection(); 0076 } 0077 0078 KIO::WorkerResult LDAPProtocol::LDAPErr(int err) 0079 { 0080 QString extramsg; 0081 if (mConnected) { 0082 if (err == KLDAP_SUCCESS) { 0083 err = mConn.ldapErrorCode(); 0084 } 0085 if (err != KLDAP_SUCCESS) { 0086 extramsg = i18n("\nAdditional info: ") + mConn.ldapErrorString(); 0087 } 0088 } 0089 if (err == KLDAP_SUCCESS) { 0090 return KIO::WorkerResult::pass(); 0091 } 0092 0093 qCDebug(KLDAP_LOG) << "error code: " << err << " msg: " << LdapConnection::errorString(err) << extramsg << "'"; 0094 QString msg; 0095 msg = mServer.url().toDisplayString(); 0096 if (!extramsg.isEmpty()) { 0097 msg += extramsg; 0098 } 0099 0100 /* FIXME: No need to close on all errors */ 0101 closeConnection(); 0102 0103 switch (err) { 0104 /* FIXME: is it worth mapping the following error codes to kio errors? 0105 0106 LDAP_OPERATIONS_ERROR 0107 LDAP_STRONG_AUTH_REQUIRED 0108 LDAP_PROTOCOL_ERROR 0109 LDAP_TIMELIMIT_EXCEEDED 0110 LDAP_SIZELIMIT_EXCEEDED 0111 LDAP_COMPARE_FALSE 0112 LDAP_COMPARE_TRUE 0113 LDAP_PARTIAL_RESULTS 0114 LDAP_NO_SUCH_ATTRIBUTE 0115 LDAP_UNDEFINED_TYPE 0116 LDAP_INAPPROPRIATE_MATCHING 0117 LDAP_CONSTRAINT_VIOLATION 0118 LDAP_INVALID_SYNTAX 0119 LDAP_NO_SUCH_OBJECT 0120 LDAP_ALIAS_PROBLEM 0121 LDAP_INVALID_DN_SYNTAX 0122 LDAP_IS_LEAF 0123 LDAP_ALIAS_DEREF_PROBLEM 0124 LDAP_INAPPROPRIATE_AUTH 0125 LDAP_BUSY 0126 LDAP_UNAVAILABLE 0127 LDAP_UNWILLING_TO_PERFORM 0128 LDAP_LOOP_DETECT 0129 LDAP_NAMING_VIOLATION 0130 LDAP_OBJECT_CLASS_VIOLATION 0131 LDAP_NOT_ALLOWED_ON_NONLEAF 0132 LDAP_NOT_ALLOWED_ON_RDN 0133 LDAP_NO_OBJECT_CLASS_MODS 0134 LDAP_OTHER 0135 LDAP_LOCAL_ERROR 0136 LDAP_ENCODING_ERROR 0137 LDAP_DECODING_ERROR 0138 LDAP_FILTER_ERROR 0139 */ 0140 case KLDAP_AUTH_UNKNOWN: 0141 case KLDAP_INVALID_CREDENTIALS: 0142 case KLDAP_STRONG_AUTH_NOT_SUPPORTED: 0143 return KIO::WorkerResult::fail(ERR_CANNOT_AUTHENTICATE, msg); 0144 case KLDAP_ALREADY_EXISTS: 0145 return KIO::WorkerResult::fail(ERR_FILE_ALREADY_EXIST, msg); 0146 case KLDAP_INSUFFICIENT_ACCESS: 0147 return KIO::WorkerResult::fail(ERR_ACCESS_DENIED, msg); 0148 case KLDAP_CONNECT_ERROR: 0149 case KLDAP_SERVER_DOWN: 0150 return KIO::WorkerResult::fail(ERR_CANNOT_CONNECT, msg); 0151 case KLDAP_TIMEOUT: 0152 return KIO::WorkerResult::fail(ERR_SERVER_TIMEOUT, msg); 0153 case KLDAP_PARAM_ERROR: 0154 return KIO::WorkerResult::fail(ERR_INTERNAL, msg); 0155 case KLDAP_NO_MEMORY: 0156 return KIO::WorkerResult::fail(ERR_OUT_OF_MEMORY, msg); 0157 0158 default: 0159 return KIO::WorkerResult::fail( 0160 KIO::ERR_WORKER_DEFINED, 0161 i18n("LDAP server returned the error: %1 %2\nThe LDAP URL was: %3", LdapConnection::errorString(err), extramsg, mServer.url().toDisplayString())); 0162 } 0163 } 0164 0165 void LDAPProtocol::controlsFromMetaData(LdapControls &serverctrls, LdapControls &clientctrls) 0166 { 0167 QString oid; 0168 bool critical; 0169 QByteArray value; 0170 int i = 0; 0171 while (hasMetaData(QStringLiteral("SERVER_CTRL%1").arg(i))) { 0172 const QByteArray val = metaData(QStringLiteral("SERVER_CTRL%1").arg(i)).toUtf8(); 0173 Ldif::splitControl(val, oid, critical, value); 0174 qCDebug(KLDAP_LOG) << "server ctrl #" << i << " value: " << val << " oid: " << oid << " critical: " << critical 0175 << " value: " << QString::fromUtf8(value.constData(), value.size()); 0176 LdapControl ctrl(oid, val, critical); 0177 serverctrls.append(ctrl); 0178 i++; 0179 } 0180 i = 0; 0181 while (hasMetaData(QStringLiteral("CLIENT_CTRL%1").arg(i))) { 0182 const QByteArray val = metaData(QStringLiteral("CLIENT_CTRL%1").arg(i)).toUtf8(); 0183 Ldif::splitControl(val, oid, critical, value); 0184 qCDebug(KLDAP_LOG) << "client ctrl #" << i << " value: " << val << " oid: " << oid << " critical: " << critical 0185 << " value: " << QString::fromUtf8(value.constData(), value.size()); 0186 LdapControl ctrl(oid, val, critical); 0187 clientctrls.append(ctrl); 0188 i++; 0189 } 0190 } 0191 0192 void LDAPProtocol::LDAPEntry2UDSEntry(const LdapDN &dn, UDSEntry &entry, const LdapUrl &usrc, bool dir) 0193 { 0194 int pos; 0195 entry.clear(); 0196 QString name = dn.toString(); 0197 if ((pos = name.indexOf(QLatin1Char(','))) > 0) { 0198 name.truncate(pos); 0199 } 0200 if ((pos = name.indexOf(QLatin1Char('='))) > 0) { 0201 name.remove(0, pos + 1); 0202 } 0203 name.replace(QLatin1Char(' '), QLatin1StringView("_")); 0204 if (!dir) { 0205 name += QLatin1StringView(".ldif"); 0206 } 0207 entry.fastInsert(KIO::UDSEntry::UDS_NAME, name); 0208 0209 // the file type 0210 entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, dir ? S_IFDIR : S_IFREG); 0211 0212 // the mimetype 0213 if (!dir) { 0214 entry.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, QStringLiteral("text/plain")); 0215 } 0216 0217 entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, dir ? 0500 : 0400); 0218 0219 // the url 0220 LdapUrl url = usrc; 0221 url.setPath(QLatin1Char('/') + dn.toString()); 0222 url.setScope(dir ? LdapUrl::One : LdapUrl::Base); 0223 entry.fastInsert(KIO::UDSEntry::UDS_URL, url.toDisplayString()); 0224 } 0225 0226 KIO::WorkerResult LDAPProtocol::changeCheck(const LdapUrl &url) 0227 { 0228 LdapServer server; 0229 server.setUrl(url); 0230 0231 if (mConnected) { 0232 if (server.host() != mServer.host() || server.port() != mServer.port() || server.baseDn() != mServer.baseDn() || server.user() != mServer.user() 0233 || server.bindDn() != mServer.bindDn() || server.realm() != mServer.realm() || server.password() != mServer.password() 0234 || server.timeLimit() != mServer.timeLimit() || server.sizeLimit() != mServer.sizeLimit() || server.version() != mServer.version() 0235 || server.security() != mServer.security() || server.auth() != mServer.auth() || server.mech() != mServer.mech()) { 0236 closeConnection(); 0237 mServer = server; 0238 return openConnection(); 0239 } 0240 return KIO::WorkerResult::pass(); 0241 } 0242 0243 mServer = server; 0244 return openConnection(); 0245 } 0246 0247 void LDAPProtocol::setHost(const QString &host, quint16 port, const QString &user, const QString &password) 0248 { 0249 if (mServer.host() != host || mServer.port() != port || mServer.user() != user || mServer.password() != password) { 0250 closeConnection(); 0251 } 0252 0253 mServer.host() = host; 0254 if (port > 0) { 0255 mServer.setPort(port); 0256 } else { 0257 struct servent *pse; 0258 if ((pse = getservbyname(mProtocol.constData(), "tcp")) == nullptr) { 0259 if (mProtocol == "ldaps") { 0260 mServer.setPort(636); 0261 } else { 0262 mServer.setPort(389); 0263 } 0264 } else { 0265 mServer.setPort(ntohs(pse->s_port)); 0266 } 0267 } 0268 mServer.setUser(user); 0269 mServer.setPassword(password); 0270 0271 qCDebug(KLDAP_LOG) << "setHost: " << host << " port: " << port << " user: " << user << " pass: [protected]"; 0272 } 0273 0274 KIO::WorkerResult LDAPProtocol::openConnection() 0275 { 0276 if (mConnected) { 0277 return KIO::WorkerResult::pass(); 0278 } 0279 0280 mConn.setServer(mServer); 0281 if (mConn.connect() != 0) { 0282 return KIO::WorkerResult::fail(ERR_CANNOT_CONNECT, mConn.connectionError()); 0283 } 0284 0285 mConnected = true; 0286 0287 AuthInfo info; 0288 info.url.setScheme(QLatin1StringView(mProtocol)); 0289 info.url.setHost(mServer.host()); 0290 info.url.setPort(mServer.port()); 0291 info.url.setUserName(mServer.user()); 0292 info.caption = i18n("LDAP Login"); 0293 info.comment = QString::fromLatin1(mProtocol) + QLatin1StringView("://") + mServer.host() + QLatin1Char(':') + QString::number(mServer.port()); 0294 info.commentLabel = i18n("site:"); 0295 info.username = mServer.auth() == LdapServer::SASL ? mServer.user() : mServer.bindDn(); 0296 info.password = mServer.password(); 0297 info.keepPassword = true; 0298 bool cached = checkCachedAuthentication(info); 0299 0300 bool firstauth = true; 0301 0302 while (true) { 0303 int retval = mOp.bind_s(); 0304 if (retval == 0) { 0305 break; 0306 } 0307 if (retval == KLDAP_INVALID_CREDENTIALS || retval == KLDAP_INSUFFICIENT_ACCESS || retval == KLDAP_INAPPROPRIATE_AUTH 0308 || retval == KLDAP_UNWILLING_TO_PERFORM) { 0309 if (firstauth && cached) { 0310 if (mServer.auth() == LdapServer::SASL) { 0311 mServer.setUser(info.username); 0312 } else { 0313 mServer.setBindDn(info.username); 0314 } 0315 mServer.setPassword(info.password); 0316 mConn.setServer(mServer); 0317 cached = false; 0318 } else { 0319 const int errorCode = firstauth ? openPasswordDialog(info) : openPasswordDialog(info, i18n("Invalid authorization information.")); 0320 if (!errorCode) { 0321 if (info.keepPassword) { // user asked password be save/remembered 0322 cacheAuthentication(info); 0323 } 0324 } else { 0325 closeConnection(); 0326 if (errorCode == ERR_USER_CANCELED) { 0327 return KIO::WorkerResult::fail(ERR_USER_CANCELED, i18n("LDAP connection canceled.")); 0328 } 0329 return KIO::WorkerResult::fail(errorCode, QString()); 0330 } 0331 if (mServer.auth() == LdapServer::SASL) { 0332 mServer.setUser(info.username); 0333 } else { 0334 mServer.setBindDn(info.username); 0335 } 0336 mServer.setPassword(info.password); 0337 firstauth = false; 0338 mConn.setServer(mServer); 0339 } 0340 } else { 0341 const KIO::WorkerResult errorResult = LDAPErr(retval); 0342 // TODO: ensure that LDAPErr(retval) always closes the connection, avoiding the explicit call 0343 closeConnection(); 0344 return errorResult; 0345 } 0346 } 0347 0348 qCDebug(KLDAP_LOG) << "connected!"; 0349 return KIO::WorkerResult::pass(); 0350 } 0351 0352 void LDAPProtocol::closeConnection() 0353 { 0354 if (mConnected) { 0355 mConn.close(); 0356 } 0357 mConnected = false; 0358 0359 qCDebug(KLDAP_LOG) << "connection closed!"; 0360 } 0361 0362 /** 0363 * Get the information contained in the URL. 0364 */ 0365 KIO::WorkerResult LDAPProtocol::get(const QUrl &_url) 0366 { 0367 qCDebug(KLDAP_LOG) << "get(" << _url << ")"; 0368 0369 LdapUrl usrc(_url); 0370 0371 const KIO::WorkerResult checkResult = changeCheck(usrc); 0372 if (!checkResult.success()) { 0373 return checkResult; 0374 } 0375 0376 LdapControls serverctrls; 0377 LdapControls clientctrls; 0378 controlsFromMetaData(serverctrls, clientctrls); 0379 if (mServer.pageSize()) { 0380 LdapControls ctrls = serverctrls; 0381 ctrls.append(LdapControl::createPageControl(mServer.pageSize())); 0382 qCDebug(KLDAP_LOG) << "page size: " << mServer.pageSize(); 0383 mOp.setServerControls(ctrls); 0384 } else { 0385 mOp.setServerControls(serverctrls); 0386 } 0387 mOp.setClientControls(clientctrls); 0388 int id; 0389 if ((id = mOp.search(usrc.dn(), usrc.scope(), usrc.filter(), usrc.attributes())) == -1) { 0390 return LDAPErr(); 0391 } 0392 0393 // tell the mimetype 0394 mimeType(QStringLiteral("text/plain")); 0395 // collect the result 0396 // QByteArray result; 0397 filesize_t processed_size = 0; 0398 0399 int ret; 0400 while (true) { 0401 ret = mOp.waitForResult(id, -1); 0402 if (ret == -1 || mConn.ldapErrorCode() != KLDAP_SUCCESS) { 0403 return LDAPErr(); 0404 } 0405 qCDebug(KLDAP_LOG) << " ldap_result: " << ret; 0406 if (ret == LdapOperation::RES_SEARCH_RESULT) { 0407 if (mServer.pageSize()) { 0408 QByteArray cookie; 0409 int estsize = -1; 0410 for (int i = 0; i < mOp.controls().count(); ++i) { 0411 qCDebug(KLDAP_LOG) << " control oid: " << mOp.controls().at(i).oid(); 0412 estsize = mOp.controls().at(i).parsePageControl(cookie); 0413 if (estsize != -1) { 0414 break; 0415 } 0416 } 0417 qCDebug(KLDAP_LOG) << " estimated size: " << estsize; 0418 if (estsize != -1 && !cookie.isEmpty()) { 0419 LdapControls ctrls{serverctrls}; // clazy:exclude=container-inside-loop 0420 qCDebug(KLDAP_LOG) << "page size: " << mServer.pageSize() << " estimated size: " << estsize; 0421 ctrls.append(LdapControl::createPageControl(mServer.pageSize(), cookie)); 0422 mOp.setServerControls(ctrls); 0423 if ((id = mOp.search(usrc.dn(), usrc.scope(), usrc.filter(), usrc.attributes())) == -1) { 0424 return LDAPErr(); 0425 } 0426 continue; 0427 } 0428 } 0429 break; 0430 } 0431 if (ret != LdapOperation::RES_SEARCH_ENTRY) { 0432 continue; 0433 } 0434 0435 QByteArray entry = mOp.object().toString().toUtf8() + '\n'; 0436 processed_size += entry.size(); 0437 data(entry); 0438 processedSize(processed_size); 0439 } 0440 0441 totalSize(processed_size); 0442 0443 // tell we are finished 0444 data(QByteArray()); 0445 return KIO::WorkerResult::pass(); 0446 } 0447 0448 /** 0449 * Test if the url contains a directory or a file. 0450 */ 0451 KIO::WorkerResult LDAPProtocol::stat(const QUrl &_url) 0452 { 0453 qCDebug(KLDAP_LOG) << "stat(" << _url << ")"; 0454 0455 LdapUrl usrc(_url); 0456 0457 const KIO::WorkerResult checkResult = changeCheck(usrc); 0458 if (!checkResult.success()) { 0459 return checkResult; 0460 } 0461 0462 int ret; 0463 int id; 0464 // look how many entries match 0465 const QStringList saveatt = usrc.attributes(); 0466 QStringList att{QStringLiteral("dn")}; 0467 0468 if ((id = mOp.search(usrc.dn(), usrc.scope(), usrc.filter(), att)) == -1) { 0469 return LDAPErr(); 0470 } 0471 0472 qCDebug(KLDAP_LOG) << "stat() getting result"; 0473 do { 0474 ret = mOp.waitForResult(id, -1); 0475 if (ret == -1 || mConn.ldapErrorCode() != KLDAP_SUCCESS) { 0476 return LDAPErr(); 0477 } 0478 if (ret == LdapOperation::RES_SEARCH_RESULT) { 0479 return KIO::WorkerResult::fail(ERR_DOES_NOT_EXIST, _url.toDisplayString()); 0480 } 0481 } while (ret != LdapOperation::RES_SEARCH_ENTRY); 0482 0483 mOp.abandon(id); 0484 0485 usrc.setAttributes(saveatt); 0486 0487 UDSEntry uds; 0488 bool critical; 0489 LDAPEntry2UDSEntry(usrc.dn(), uds, usrc, usrc.extension(QStringLiteral("x-dir"), critical) != QLatin1StringView("base")); 0490 0491 statEntry(uds); 0492 // we are done 0493 return KIO::WorkerResult::pass(); 0494 } 0495 0496 /** 0497 * Deletes one entry; 0498 */ 0499 KIO::WorkerResult LDAPProtocol::del(const QUrl &_url, bool) 0500 { 0501 qCDebug(KLDAP_LOG) << "del(" << _url << ")"; 0502 0503 LdapUrl usrc(_url); 0504 0505 const KIO::WorkerResult checkResult = changeCheck(usrc); 0506 if (!checkResult.success()) { 0507 return checkResult; 0508 } 0509 0510 LdapControls serverctrls; 0511 LdapControls clientctrls; 0512 controlsFromMetaData(serverctrls, clientctrls); 0513 mOp.setServerControls(serverctrls); 0514 mOp.setClientControls(clientctrls); 0515 0516 qCDebug(KLDAP_LOG) << " del: " << usrc.dn().toString().toUtf8(); 0517 int id; 0518 int ret; 0519 0520 if ((id = mOp.del(usrc.dn())) == -1) { 0521 return LDAPErr(); 0522 } 0523 ret = mOp.waitForResult(id, -1); 0524 if (ret == -1 || mConn.ldapErrorCode() != KLDAP_SUCCESS) { 0525 return LDAPErr(); 0526 } 0527 0528 return KIO::WorkerResult::pass(); 0529 } 0530 0531 KIO::WorkerResult LDAPProtocol::put(const QUrl &_url, int, KIO::JobFlags flags) 0532 { 0533 qCDebug(KLDAP_LOG) << "put(" << _url << ")"; 0534 0535 LdapUrl usrc(_url); 0536 0537 const KIO::WorkerResult checkResult = changeCheck(usrc); 0538 if (!checkResult.success()) { 0539 return checkResult; 0540 } 0541 0542 LdapControls serverctrls; 0543 LdapControls clientctrls; 0544 controlsFromMetaData(serverctrls, clientctrls); 0545 mOp.setServerControls(serverctrls); 0546 mOp.setClientControls(clientctrls); 0547 0548 LdapObject addObject; 0549 LdapOperation::ModOps modops; 0550 QByteArray buffer; 0551 int result = 0; 0552 Ldif::ParseValue ret; 0553 Ldif ldif; 0554 ret = Ldif::MoreData; 0555 int ldaperr; 0556 0557 do { 0558 if (ret == Ldif::MoreData) { 0559 dataReq(); // Request for data 0560 result = readData(buffer); 0561 ldif.setLdif(buffer); 0562 } 0563 if (result < 0) { 0564 // error 0565 return KIO::WorkerResult::fail(); 0566 } 0567 if (result == 0) { 0568 qCDebug(KLDAP_LOG) << "EOF!"; 0569 ldif.endLdif(); 0570 } 0571 do { 0572 ret = ldif.nextItem(); 0573 qCDebug(KLDAP_LOG) << "nextitem: " << ret; 0574 0575 switch (ret) { 0576 case Ldif::None: 0577 case Ldif::NewEntry: 0578 case Ldif::MoreData: 0579 break; 0580 case Ldif::EndEntry: 0581 ldaperr = KLDAP_SUCCESS; 0582 switch (ldif.entryType()) { 0583 case Ldif::Entry_None: 0584 return KIO::WorkerResult::fail(ERR_INTERNAL, i18n("The Ldif parser failed.")); 0585 case Ldif::Entry_Del: 0586 qCDebug(KLDAP_LOG) << "kio_ldap_del"; 0587 ldaperr = mOp.del_s(ldif.dn()); 0588 break; 0589 case Ldif::Entry_Modrdn: 0590 qCDebug(KLDAP_LOG) << "kio_ldap_modrdn olddn:" << ldif.dn().toString() << " newRdn: " << ldif.newRdn() 0591 << " newSuperior: " << ldif.newSuperior() << " deloldrdn: " << ldif.delOldRdn(); 0592 ldaperr = mOp.rename_s(ldif.dn(), ldif.newRdn(), ldif.newSuperior(), ldif.delOldRdn()); 0593 break; 0594 case Ldif::Entry_Mod: 0595 qCDebug(KLDAP_LOG) << "kio_ldap_mod"; 0596 ldaperr = mOp.modify_s(ldif.dn(), modops); 0597 modops.clear(); 0598 break; 0599 case Ldif::Entry_Add: 0600 qCDebug(KLDAP_LOG) << "kio_ldap_add " << ldif.dn().toString(); 0601 addObject.setDn(ldif.dn()); 0602 ldaperr = mOp.add_s(addObject); 0603 if (ldaperr == KLDAP_ALREADY_EXISTS && (flags & KIO::Overwrite)) { 0604 qCDebug(KLDAP_LOG) << ldif.dn().toString() << " already exists, delete first"; 0605 ldaperr = mOp.del_s(ldif.dn()); 0606 if (ldaperr == KLDAP_SUCCESS) { 0607 ldaperr = mOp.add_s(addObject); 0608 } 0609 } 0610 addObject.clear(); 0611 break; 0612 } 0613 if (ldaperr != KLDAP_SUCCESS) { 0614 qCDebug(KLDAP_LOG) << "put ldap error: " << ldaperr; 0615 return LDAPErr(ldaperr); 0616 } 0617 break; 0618 case Ldif::Item: 0619 switch (ldif.entryType()) { 0620 case Ldif::Entry_Mod: { 0621 LdapOperation::ModOp op; 0622 op.type = LdapOperation::Mod_None; 0623 switch (ldif.modType()) { 0624 case Ldif::Mod_None: 0625 op.type = LdapOperation::Mod_None; 0626 break; 0627 case Ldif::Mod_Add: 0628 op.type = LdapOperation::Mod_Add; 0629 break; 0630 case Ldif::Mod_Replace: 0631 op.type = LdapOperation::Mod_Replace; 0632 break; 0633 case Ldif::Mod_Del: 0634 op.type = LdapOperation::Mod_Del; 0635 break; 0636 } 0637 op.attr = ldif.attr(); 0638 if (!ldif.value().isNull()) { 0639 op.values.append(ldif.value()); 0640 } 0641 modops.append(op); 0642 break; 0643 } 0644 case Ldif::Entry_Add: 0645 if (!ldif.value().isEmpty()) { 0646 addObject.addValue(ldif.attr(), ldif.value()); 0647 } 0648 break; 0649 default: 0650 return KIO::WorkerResult::fail(ERR_INTERNAL, i18n("The Ldif parser failed.")); 0651 } 0652 break; 0653 case Ldif::Control: { 0654 LdapControl control; 0655 control.setControl(ldif.oid(), ldif.value(), ldif.isCritical()); 0656 serverctrls.append(control); 0657 mOp.setServerControls(serverctrls); 0658 break; 0659 } 0660 case Ldif::Err: 0661 return KIO::WorkerResult::fail(KIO::ERR_WORKER_DEFINED, i18n("Invalid Ldif file in line %1.", ldif.lineNumber())); 0662 } 0663 } while (ret != Ldif::MoreData); 0664 } while (result > 0); 0665 0666 return KIO::WorkerResult::pass(); 0667 } 0668 0669 /** 0670 * List the contents of a directory. 0671 */ 0672 KIO::WorkerResult LDAPProtocol::listDir(const QUrl &_url) 0673 { 0674 QStringList att; 0675 LdapUrl usrc(_url); 0676 0677 qCDebug(KLDAP_LOG) << "listDir(" << _url << ")"; 0678 0679 const KIO::WorkerResult checkResult = changeCheck(usrc); 0680 if (!checkResult.success()) { 0681 return checkResult; 0682 } 0683 0684 LdapUrl usrc2 = usrc; 0685 0686 const QStringList saveatt = usrc.attributes(); 0687 bool critical = true; 0688 bool isSub = (usrc.extension(QStringLiteral("x-dir"), critical) == QLatin1StringView("sub")); 0689 // look up the entries 0690 if (isSub) { 0691 att.append(QStringLiteral("dn")); 0692 usrc.setAttributes(att); 0693 } 0694 if (_url.query().isEmpty()) { 0695 usrc.setScope(LdapUrl::One); 0696 } 0697 int id; 0698 0699 if ((id = mOp.search(usrc.dn(), usrc.scope(), usrc.filter(), usrc.attributes())) == -1) { 0700 return LDAPErr(); 0701 } 0702 0703 usrc.setAttributes(QStringList() << QLatin1StringView("")); 0704 usrc.setExtension(QStringLiteral("x-dir"), QStringLiteral("base")); 0705 // publish the results 0706 UDSEntry uds; 0707 0708 int ret2; 0709 int id2; 0710 unsigned long total = 0; 0711 0712 int ret; 0713 while (true) { 0714 ret = mOp.waitForResult(id, -1); 0715 if (ret == -1 || mConn.ldapErrorCode() != KLDAP_SUCCESS) { 0716 return LDAPErr(); 0717 } 0718 if (ret == LdapOperation::RES_SEARCH_RESULT) { 0719 break; 0720 } 0721 if (ret != LdapOperation::RES_SEARCH_ENTRY) { 0722 continue; 0723 } 0724 qCDebug(KLDAP_LOG) << " ldap_result: " << ret; 0725 0726 total++; 0727 uds.clear(); 0728 0729 LDAPEntry2UDSEntry(mOp.object().dn(), uds, usrc); 0730 listEntry(uds); 0731 // processedSize( total ); 0732 qCDebug(KLDAP_LOG) << " total: " << total << " " << usrc.toDisplayString(); 0733 0734 // publish the sub-directories (if dirmode==sub) 0735 if (isSub) { 0736 LdapDN dn = mOp.object().dn(); 0737 usrc2.setDn(dn); 0738 usrc2.setScope(LdapUrl::One); 0739 usrc2.setAttributes(saveatt); 0740 usrc2.setFilter(usrc.filter()); 0741 qCDebug(KLDAP_LOG) << "search2 " << dn.toString(); 0742 if ((id2 = mOp.search(dn, LdapUrl::One, QString(), att)) != -1) { 0743 while (true) { 0744 qCDebug(KLDAP_LOG) << " next result "; 0745 ret2 = mOp.waitForResult(id2, -1); 0746 if (ret2 == -1 || ret2 == LdapOperation::RES_SEARCH_RESULT) { 0747 break; 0748 } 0749 if (ret2 == LdapOperation::RES_SEARCH_ENTRY) { 0750 LDAPEntry2UDSEntry(dn, uds, usrc2, true); 0751 listEntry(uds); 0752 total++; 0753 mOp.abandon(id2); 0754 break; 0755 } 0756 } 0757 } 0758 } 0759 } 0760 0761 // totalSize( total ); 0762 0763 uds.clear(); 0764 // we are done 0765 return KIO::WorkerResult::pass(); 0766 } 0767 0768 #include "kio_ldap.moc"