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_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;
23using namespace KLDAPWidgets;
24class Q_DECL_HIDDEN LdapClient::LdapClientPrivate
25{
26public:
27 LdapClientPrivate(LdapClient *qq)
28 : q(qq)
29 {
30 }
31
32 ~LdapClientPrivate()
33 {
34 cancelQuery();
35 }
36
37 void cancelQuery();
38
39 void startParseLDIF();
40 void parseLDIF(const QByteArray &data);
41 void endParseLDIF();
42 void finishCurrentObject();
43
44 void slotData(KIO::Job *, const QByteArray &data);
45 void slotInfoMessage(KJob *, const QString &info);
46 void slotDone();
47
48 LdapClient *const q;
49
51 QString mScope;
52 QStringList mAttrs;
53
54 QPointer<KJob> mJob = nullptr;
55 bool mActive = false;
56
57 KLDAPCore::LdapObject mCurrentObject;
58 KLDAPCore::Ldif mLdif;
59 int mClientNumber = 0;
60 int mCompletionWeight = 0;
61};
62
63LdapClient::LdapClient(int clientNumber, QObject *parent)
64 : QObject(parent)
65 , d(new LdapClientPrivate(this))
66{
67 d->mClientNumber = clientNumber;
68 d->mCompletionWeight = 50 - d->mClientNumber;
69}
70
71LdapClient::~LdapClient() = default;
72
74{
75 return d->mActive;
76}
77
79{
80 d->mServer = server;
81}
82
84{
85 return d->mServer;
86}
87
89{
90 d->mAttrs = attrs;
91 d->mAttrs << QStringLiteral("objectClass"); // via objectClass we detect distribution lists
92}
93
95{
96 return d->mAttrs;
97}
98
99void LdapClient::setScope(const QString &scope)
100{
101 d->mScope = scope;
102}
103
105{
106 cancelQuery();
107 KLDAPCore::LdapUrl url{d->mServer.url()};
108
109 url.setAttributes(d->mAttrs);
110 url.setScope(d->mScope == QLatin1StringView("one") ? KLDAPCore::LdapUrl::One : KLDAPCore::LdapUrl::Sub);
111 const QString userFilter = url.filter();
112 QString finalFilter = filter;
113 // combine the filter set by the user in the config dialog (url.filter()) and the filter from this query
114 if (!userFilter.isEmpty()) {
115 finalFilter = QLatin1StringView("&(") + finalFilter + QLatin1StringView(")(") + userFilter + QLatin1Char(')');
116 }
117 url.setFilter(QLatin1Char('(') + finalFilter + QLatin1Char(')'));
118
119 qCDebug(LDAPCLIENT_LOG) << "LdapClient: Doing query:" << url.toDisplayString();
120
121 d->startParseLDIF();
122 d->mActive = true;
123 KIO::TransferJob *transfertJob = KIO::get(url, KIO::NoReload, KIO::HideProgressInfo);
124 d->mJob = transfertJob;
125 connect(transfertJob, &KIO::TransferJob::data, this, [this](KIO::Job *job, const QByteArray &data) {
126 d->slotData(job, data);
127 });
128 connect(d->mJob.data(), &KIO::TransferJob::infoMessage, this, [this](KJob *job, const QString &message) {
129 d->slotInfoMessage(job, message);
130 });
131 connect(d->mJob.data(), &KIO::TransferJob::result, this, [this]() {
132 d->slotDone();
133 });
134}
135
137{
138 d->cancelQuery();
139}
140
141void LdapClient::LdapClientPrivate::cancelQuery()
142{
143 if (mJob) {
144 mJob->kill();
145 mJob = nullptr;
146 }
147
148 mActive = false;
149}
150
151void LdapClient::LdapClientPrivate::slotData(KIO::Job *, const QByteArray &data)
152{
153 parseLDIF(data);
154}
155
156void LdapClient::LdapClientPrivate::slotInfoMessage(KJob *, const QString &info)
157{
158 qCDebug(LDAPCLIENT_LOG) << "Job said :" << info;
159}
160
161void LdapClient::LdapClientPrivate::slotDone()
162{
163 endParseLDIF();
164 mActive = false;
165 if (!mJob) {
166 return;
167 }
168 int err = mJob->error();
169 if (err && err != KIO::ERR_USER_CANCELED) {
170 Q_EMIT q->error(mJob->errorString());
171 }
172 Q_EMIT q->done();
173}
174
175void LdapClient::LdapClientPrivate::startParseLDIF()
176{
177 mCurrentObject.clear();
178 mLdif.startParsing();
179}
180
181void LdapClient::LdapClientPrivate::endParseLDIF()
182{
183}
184
185void LdapClient::LdapClientPrivate::finishCurrentObject()
186{
187 mCurrentObject.setDn(mLdif.dn());
188 KLDAPCore::LdapAttrValue objectclasses;
189 const KLDAPCore::LdapAttrMap::ConstIterator end = mCurrentObject.attributes().constEnd();
190 for (KLDAPCore::LdapAttrMap::ConstIterator it = mCurrentObject.attributes().constBegin(); it != end; ++it) {
191 if (it.key().toLower() == QLatin1StringView("objectclass")) {
192 objectclasses = it.value();
193 break;
194 }
195 }
196
197 bool groupofnames = false;
198 const KLDAPCore::LdapAttrValue::ConstIterator endValue(objectclasses.constEnd());
199 for (KLDAPCore::LdapAttrValue::ConstIterator it = objectclasses.constBegin(); it != endValue; ++it) {
200 const QByteArray sClass = (*it).toLower();
201 if (sClass == "groupofnames" || sClass == "kolabgroupofnames") {
202 groupofnames = true;
203 }
204 }
205
206 if (groupofnames) {
207 KLDAPCore::LdapAttrMap::ConstIterator it = mCurrentObject.attributes().find(QStringLiteral("mail"));
208 if (it == mCurrentObject.attributes().end()) {
209 // No explicit mail address found so far?
210 // Fine, then we use the address stored in the DN.
211 QString sMail;
212 const QStringList lMail = mCurrentObject.dn().toString().split(QStringLiteral(",dc="), Qt::SkipEmptyParts);
213 const int n = lMail.count();
214 if (n) {
215 if (lMail.first().startsWith(QLatin1StringView("cn="), Qt::CaseInsensitive)) {
216 sMail = lMail.first().simplified().mid(3);
217 if (1 < n) {
218 sMail.append(QLatin1Char('@'));
219 }
220 for (int i = 1; i < n; ++i) {
221 sMail.append(lMail.at(i));
222 if (i < n - 1) {
223 sMail.append(QLatin1Char('.'));
224 }
225 }
226 mCurrentObject.addValue(QStringLiteral("mail"), sMail.toUtf8());
227 }
228 }
229 }
230 }
231 Q_EMIT q->result(*q, mCurrentObject);
232 mCurrentObject.clear();
233}
234
235void LdapClient::LdapClientPrivate::parseLDIF(const QByteArray &data)
236{
237 // qCDebug(LDAPCLIENT_LOG) <<"LdapClient::parseLDIF(" << QCString(data.data(), data.size()+1) <<" )";
238 if (!data.isEmpty()) {
239 mLdif.setLdif(data);
240 } else {
241 mLdif.endLdif();
242 }
243 KLDAPCore::Ldif::ParseValue ret;
245 do {
246 ret = mLdif.nextItem();
247 switch (ret) {
248 case KLDAPCore::Ldif::Item: {
249 name = mLdif.attr();
250 const QByteArray value = mLdif.value();
251 mCurrentObject.addValue(name, value);
252 break;
253 }
254 case KLDAPCore::Ldif::EndEntry:
255 finishCurrentObject();
256 break;
257 default:
258 break;
259 }
260 } while (ret != KLDAPCore::Ldif::MoreData);
261}
262
264{
265 return d->mClientNumber;
266}
267
269{
270 return d->mCompletionWeight;
271}
272
274{
275 d->mCompletionWeight = weight;
276}
277
278#include "moc_ldapclient.cpp"
void data(KIO::Job *job, const QByteArray &data)
void result(KJob *job)
void infoMessage(KJob *job, const QString &message)
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
Ldif.
Definition ldif.h:29
An object that represents a configured LDAP server.
Definition ldapclient.h:34
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.
KIOCORE_EXPORT TransferJob * get(const QUrl &url, LoadType reload=NoReload, JobFlags flags=DefaultFlags)
HideProgressInfo
const QList< QKeySequence > & end()
QString name(StandardShortcut id)
bool isEmpty() const const
QByteArray toLower() const const
typedef ConstIterator
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
typedef ConstIterator
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QString & append(QChar ch)
void clear()
bool isEmpty() const const
QByteArray toUtf8() const const
CaseInsensitive
SkipEmptyParts
QString url(FormattingOptions options) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:18:34 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.