KLdap

ldapclient.cpp
1/* kldapclient.cpp - LDAP access
2 * SPDX-FileCopyrightText: 2002 Klarälvdalens Datakonsult AB
3 * SPDX-FileContributor: Steffen Hansen <hansen@kde.org>
4 *
5 * Ported to KABC by Daniel Molkentin <molkentin@kde.org>
6 *
7 * SPDX-License-Identifier: LGPL-2.0-or-later
8 */
9
10#include "ldapclient.h"
11#include "ldapclient_core_debug.h"
12
13#include "kldapcore/ldapobject.h"
14#include "kldapcore/ldapserver.h"
15#include "kldapcore/ldapurl.h"
16#include "kldapcore/ldif.h"
17
18#include <KIO/TransferJob>
19
20#include <QPointer>
21
22using namespace KLDAPCore;
23class Q_DECL_HIDDEN LdapClient::LdapClientPrivate
24{
25public:
26 LdapClientPrivate(LdapClient *qq)
27 : q(qq)
28 {
29 }
30
31 ~LdapClientPrivate()
32 {
33 cancelQuery();
34 }
35
36 void cancelQuery();
37
38 void startParseLDIF();
39 void parseLDIF(const QByteArray &data);
40 void endParseLDIF();
41 void finishCurrentObject();
42
43 void slotData(KIO::Job *, const QByteArray &data);
44 void slotInfoMessage(KJob *, const QString &info);
45 void slotDone();
46
47 LdapClient *const q;
48
50 QString mScope;
51 QStringList mAttrs;
52
53 QPointer<KJob> mJob = nullptr;
54 bool mActive = false;
55
56 KLDAPCore::LdapObject mCurrentObject;
57 KLDAPCore::Ldif mLdif;
58 int mClientNumber = 0;
59 int mCompletionWeight = 0;
60};
61
62LdapClient::LdapClient(int clientNumber, QObject *parent)
63 : QObject(parent)
64 , d(new LdapClientPrivate(this))
65{
66 d->mClientNumber = clientNumber;
67 d->mCompletionWeight = 50 - d->mClientNumber;
68}
69
70LdapClient::~LdapClient() = default;
71
73{
74 return d->mActive;
75}
76
78{
79 d->mServer = server;
80}
81
83{
84 return d->mServer;
85}
86
88{
89 d->mAttrs = attrs;
90 d->mAttrs << QStringLiteral("objectClass"); // via objectClass we detect distribution lists
91}
92
94{
95 return d->mAttrs;
96}
97
98void LdapClient::setScope(const QString &scope)
99{
100 d->mScope = scope;
101}
102
104{
105 cancelQuery();
106 KLDAPCore::LdapUrl url{d->mServer.url()};
107
108 url.setAttributes(d->mAttrs);
109 url.setScope(d->mScope == QLatin1StringView("one") ? KLDAPCore::LdapUrl::One : KLDAPCore::LdapUrl::Sub);
110 const QString userFilter = url.filter();
111 QString finalFilter = filter;
112 // combine the filter set by the user in the config dialog (url.filter()) and the filter from this query
113 if (!userFilter.isEmpty()) {
114 finalFilter = QLatin1StringView("&(") + finalFilter + QLatin1StringView(")(") + userFilter + QLatin1Char(')');
115 }
116 url.setFilter(QLatin1Char('(') + finalFilter + QLatin1Char(')'));
117
118 qCDebug(LDAPCLIENT_CORE_LOG) << "LdapClient: Doing query:" << url.toDisplayString();
119
120 d->startParseLDIF();
121 d->mActive = true;
122 KIO::TransferJob *transfertJob = KIO::get(url, KIO::NoReload, KIO::HideProgressInfo);
123 d->mJob = transfertJob;
124 connect(transfertJob, &KIO::TransferJob::data, this, [this](KIO::Job *job, const QByteArray &data) {
125 d->slotData(job, data);
126 });
127 connect(d->mJob.data(), &KIO::TransferJob::infoMessage, this, [this](KJob *job, const QString &message) {
128 d->slotInfoMessage(job, message);
129 });
130 connect(d->mJob.data(), &KIO::TransferJob::result, this, [this]() {
131 d->slotDone();
132 });
133}
134
136{
137 d->cancelQuery();
138}
139
140void LdapClient::LdapClientPrivate::cancelQuery()
141{
142 if (mJob) {
143 mJob->kill();
144 mJob = nullptr;
145 }
146
147 mActive = false;
148}
149
150void LdapClient::LdapClientPrivate::slotData(KIO::Job *, const QByteArray &data)
151{
152 parseLDIF(data);
153}
154
155void LdapClient::LdapClientPrivate::slotInfoMessage(KJob *, const QString &info)
156{
157 qCDebug(LDAPCLIENT_CORE_LOG) << "Job said :" << info;
158}
159
160void LdapClient::LdapClientPrivate::slotDone()
161{
162 endParseLDIF();
163 mActive = false;
164 if (!mJob) {
165 return;
166 }
167 int err = mJob->error();
168 if (err && err != KIO::ERR_USER_CANCELED) {
169 Q_EMIT q->error(mJob->errorString());
170 }
171 Q_EMIT q->done();
172}
173
174void LdapClient::LdapClientPrivate::startParseLDIF()
175{
176 mCurrentObject.clear();
177 mLdif.startParsing();
178}
179
180void LdapClient::LdapClientPrivate::endParseLDIF()
181{
182}
183
184void LdapClient::LdapClientPrivate::finishCurrentObject()
185{
186 mCurrentObject.setDn(mLdif.dn());
187 KLDAPCore::LdapAttrValue objectclasses;
188 const KLDAPCore::LdapAttrMap::ConstIterator end = mCurrentObject.attributes().constEnd();
189 for (KLDAPCore::LdapAttrMap::ConstIterator it = mCurrentObject.attributes().constBegin(); it != end; ++it) {
190 if (it.key().toLower() == QLatin1StringView("objectclass")) {
191 objectclasses = it.value();
192 break;
193 }
194 }
195
196 bool groupofnames = false;
197 const KLDAPCore::LdapAttrValue::ConstIterator endValue(objectclasses.constEnd());
198 for (KLDAPCore::LdapAttrValue::ConstIterator it = objectclasses.constBegin(); it != endValue; ++it) {
199 const QByteArray sClass = (*it).toLower();
200 if (sClass == "groupofnames" || sClass == "kolabgroupofnames") {
201 groupofnames = true;
202 }
203 }
204
205 if (groupofnames) {
206 KLDAPCore::LdapAttrMap::ConstIterator it = mCurrentObject.attributes().find(QStringLiteral("mail"));
207 if (it == mCurrentObject.attributes().end()) {
208 // No explicit mail address found so far?
209 // Fine, then we use the address stored in the DN.
210 QString sMail;
211 const QStringList lMail = mCurrentObject.dn().toString().split(QStringLiteral(",dc="), Qt::SkipEmptyParts);
212 const int n = lMail.count();
213 if (n) {
214 if (lMail.first().startsWith(QLatin1StringView("cn="), Qt::CaseInsensitive)) {
215 sMail = lMail.first().simplified().mid(3);
216 if (1 < n) {
217 sMail.append(QLatin1Char('@'));
218 }
219 for (int i = 1; i < n; ++i) {
220 sMail.append(lMail.at(i));
221 if (i < n - 1) {
222 sMail.append(QLatin1Char('.'));
223 }
224 }
225 mCurrentObject.addValue(QStringLiteral("mail"), sMail.toUtf8());
226 }
227 }
228 }
229 }
230 Q_EMIT q->result(*q, mCurrentObject);
231 mCurrentObject.clear();
232}
233
234void LdapClient::LdapClientPrivate::parseLDIF(const QByteArray &data)
235{
236 // qCDebug(LDAPCLIENT_LOG) <<"LdapClient::parseLDIF(" << QCString(data.data(), data.size()+1) <<" )";
237 if (!data.isEmpty()) {
238 mLdif.setLdif(data);
239 } else {
240 mLdif.endLdif();
241 }
242 KLDAPCore::Ldif::ParseValue ret;
244 do {
245 ret = mLdif.nextItem();
246 switch (ret) {
247 case KLDAPCore::Ldif::Item: {
248 name = mLdif.attr();
249 const QByteArray value = mLdif.value();
250 mCurrentObject.addValue(name, value);
251 break;
252 }
253 case KLDAPCore::Ldif::EndEntry:
254 finishCurrentObject();
255 break;
256 default:
257 break;
258 }
259 } while (ret != KLDAPCore::Ldif::MoreData);
260}
261
263{
264 return d->mClientNumber;
265}
266
268{
269 return d->mCompletionWeight;
270}
271
273{
274 d->mCompletionWeight = weight;
275}
276
277#include "moc_ldapclient.cpp"
void data(KIO::Job *job, const QByteArray &data)
void result(KJob *job)
void infoMessage(KJob *job, const QString &message)
An object that represents a configured LDAP server.
Definition ldapclient.h:29
void startQuery(const QString &filter)
Starts the query with the given filter.
int completionWeight() const
Returns the completion weight of this client.
const KLDAPCore::LdapServer server() const
Returns the ldap server information that are used by this client.
void setAttributes(const QStringList &attributes)
Sets the LDAP attributes that should be returned in the query result.
void setServer(const KLDAPCore::LdapServer &server)
Sets the LDAP server information that shall be used by this client.
QStringList attributes() const
Returns the LDAP attributes that should be returned in the query result.
void setScope(const QString &scope)
Sets the scope of the LDAP query.
void setCompletionWeight(int weight)
Sets the completion weight of this client.
LdapClient(int clientNumber, QObject *parent=nullptr)
Creates a new ldap client.
int clientNumber() const
Returns the number of this client.
bool isActive() const
Returns whether this client is currently running a search query.
void cancelQuery()
Cancels a running query.
~LdapClient() override
Destroys the ldap client.
This class represents an LDAP Object.
Definition ldapobject.h:31
A class that contains LDAP server connection settings.
Definition ldapserver.h:27
A special url class for LDAP.
Definition ldapurl.h:30
void setAttributes(const QStringList &attributes)
Sets the attributes part of the LDAP url.
Definition ldapurl.cpp:87
Ldif.
Definition ldif.h:29
KIOCORE_EXPORT TransferJob * get(const QUrl &url, LoadType reload=NoReload, JobFlags flags=DefaultFlags)
HideProgressInfo
QString name(StandardAction id)
const QList< QKeySequence > & end()
bool isEmpty() const const
QByteArray toLower() const const
const_reference at(qsizetype i) const const
const_iterator constBegin() const const
const_iterator constEnd() const const
qsizetype count() const const
T & first()
T value(qsizetype i) const const
ConstIterator
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QString & append(QChar ch)
bool isEmpty() const const
QByteArray toUtf8() const const
CaseInsensitive
SkipEmptyParts
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Oct 11 2024 12:14:23 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.