KLdap

ldapdn.cpp
1/*
2 This file is part of libkldap.
3 SPDX-FileCopyrightText: 2006 Sean Harmer <sh@theharmers.co.uk>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#include "ldapdn.h"
9
10#include "ldap_core_debug.h"
11#include <algorithm>
12
13using namespace KLDAPCore;
14
15class Q_DECL_HIDDEN LdapDN::LdapDNPrivate
16{
17public:
18 LdapDNPrivate() = default;
19
20 ~LdapDNPrivate() = default;
21
22 [[nodiscard]] bool isValidRDNString(const QString &rdn) const;
23 [[nodiscard]] QStringList splitOnNonEscapedChar(const QString &rdn, QChar ch) const;
24
25 QString m_dn;
26};
27
28bool LdapDN::LdapDNPrivate::isValidRDNString(const QString &rdn) const
29{
30 qCDebug(LDAP_CORE_LOG) << "Testing rdn:" << rdn;
31
32 // If it is a muli-valued rdn, split it into its constituent parts
33 const QStringList rdnParts = splitOnNonEscapedChar(rdn, QLatin1Char('+'));
34 const int rdnPartsSize(rdnParts.size());
35 if (rdnPartsSize > 1) {
36 for (int i = 0; i < rdnPartsSize; i++) {
37 if (!isValidRDNString(rdnParts.at(i))) {
38 return false;
39 }
40 }
41 return true;
42 }
43 // Split the rdn into the attribute name and value parts
44 const auto components = QStringView(rdn).split(QLatin1Char('='));
45 // We should have exactly two parts
46 if (components.size() != 2) {
47 return false;
48 }
49
50 return true;
51}
52
53QStringList LdapDN::LdapDNPrivate::splitOnNonEscapedChar(const QString &str, QChar ch) const
54{
55 QStringList strParts;
56 int index = 0;
57 int searchFrom = 0;
58 int strPartStartIndex = 0;
59 while ((index = str.indexOf(ch, searchFrom)) != -1) {
60 const QChar prev = str[std::max(0, index - 1)];
61 if (prev != QLatin1Char('\\')) {
62 // Found a component of a multi-valued RDN
63 // qCDebug(LDAP_CORE_LOG) << "Found" << ch << "at index" << index;
64 QString tmp = str.mid(strPartStartIndex, index - strPartStartIndex);
65 // qCDebug(LDAP_CORE_LOG) << "Adding part:" << tmp;
66 strParts.append(tmp);
67 strPartStartIndex = index + 1;
68 }
69
70 searchFrom = index + 1;
71 }
72
73 // Add on the part after the last found delimiter
74 QString tmp = str.mid(strPartStartIndex);
75 // qCDebug(LDAP_CORE_LOG) << "Adding part:" << tmp;
76 strParts.append(tmp);
77
78 return strParts;
79}
80
81LdapDN::LdapDN()
82 : d(new LdapDNPrivate)
83{
84}
85
86LdapDN::LdapDN(const QString &dn)
87 : d(new LdapDNPrivate)
88{
89 d->m_dn = dn;
90}
91
92LdapDN::LdapDN(const LdapDN &that)
93 : d(new LdapDNPrivate)
94{
95 *d = *that.d;
96}
97
98LdapDN &LdapDN::operator=(const LdapDN &that)
99{
100 if (this == &that) {
101 return *this;
102 }
103
104 *d = *that.d;
105 return *this;
106}
107
108LdapDN::~LdapDN() = default;
109
110void LdapDN::clear()
111{
112 d->m_dn.clear();
113}
114
115bool LdapDN::isEmpty() const
116{
117 return d->m_dn.isEmpty();
118}
119
120QString LdapDN::toString() const
121{
122 return d->m_dn;
123}
124
125QString LdapDN::toString(int depth) const
126{
127 const QStringList rdns = d->splitOnNonEscapedChar(d->m_dn, QLatin1Char(','));
128 if (depth >= rdns.size()) {
129 return {};
130 }
131
132 // Construct a DN down to the requested depth
133 QString dn;
134 for (int i = depth; i >= 0; i--) {
135 dn += rdns.at(rdns.size() - 1 - i) + QLatin1Char(',');
136 qCDebug(LDAP_CORE_LOG) << "dn =" << dn;
137 }
138 dn.chop(1); // Strip off the extraneous comma
139
140 return dn;
141}
142
143QString LdapDN::rdnString() const
144{
145 /** \TODO We should move this into the d pointer as we calculate rdns quite a lot */
146 const QStringList rdns = d->splitOnNonEscapedChar(d->m_dn, QLatin1Char(','));
147 return rdns.at(0);
148}
149
150QString LdapDN::rdnString(int depth) const
151{
152 const QStringList rdns = d->splitOnNonEscapedChar(d->m_dn, QLatin1Char(','));
153 if (depth >= rdns.size()) {
154 return {};
155 }
156 return rdns.at(rdns.size() - 1 - depth);
157}
158
159bool LdapDN::isValid() const
160{
161 qCDebug(LDAP_CORE_LOG) << "Testing dn:" << d->m_dn;
162
163 // Break the string into rdn's
164 const QStringList rdns = d->splitOnNonEscapedChar(d->m_dn, QLatin1Char(','));
165
166 // Test to see if each rdn is valid
167 const int rdnsSize(rdns.size());
168 for (int i = 0; i < rdnsSize; i++) {
169 if (!d->isValidRDNString(rdns.at(i))) {
170 return false;
171 }
172 }
173
174 return true;
175}
176
177int LdapDN::depth() const
178{
179 const QStringList rdns = d->splitOnNonEscapedChar(d->m_dn, QLatin1Char(','));
180 return rdns.size();
181}
182
183bool LdapDN::operator==(const LdapDN &rhs) const
184{
185 return d->m_dn == rhs.d->m_dn;
186}
187
188bool LdapDN::operator!=(const LdapDN &rhs) const
189{
190 return d->m_dn != rhs.d->m_dn;
191}
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
qsizetype size() const const
void chop(qsizetype n)
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
QString mid(qsizetype position, qsizetype n) const const
QList< QStringView > split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:16:07 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.