File indexing completed on 2025-03-02 04:55:47
0001 /* 0002 This file is part of libkldap. 0003 SPDX-FileCopyrightText: 2004-2006 Szombathelyi György <gyurco@freemail.hu> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "ldapurl.h" 0009 0010 #include "ldap_core_debug.h" 0011 0012 using namespace KLDAPCore; 0013 0014 class Q_DECL_HIDDEN LdapUrl::LdapUrlPrivate 0015 { 0016 public: 0017 LdapUrlPrivate() 0018 : m_scope(Base) 0019 { 0020 } 0021 0022 QMap<QString, Extension> m_extensions; 0023 QStringList m_attributes; 0024 Scope m_scope; 0025 QString m_filter; 0026 }; 0027 0028 LdapUrl::LdapUrl() 0029 : d(new LdapUrlPrivate) 0030 { 0031 } 0032 0033 LdapUrl::LdapUrl(const QUrl &_url) 0034 : QUrl(_url) 0035 , d(new LdapUrlPrivate) 0036 { 0037 parseQuery(); 0038 } 0039 0040 LdapUrl::LdapUrl(const LdapUrl &that) 0041 : QUrl(that) 0042 , d(new LdapUrlPrivate) 0043 { 0044 *d = *that.d; 0045 } 0046 0047 LdapUrl &LdapUrl::operator=(const LdapUrl &that) 0048 { 0049 if (this == &that) { 0050 return *this; 0051 } 0052 0053 QUrl::operator=(that); 0054 *d = *that.d; 0055 0056 return *this; 0057 } 0058 0059 LdapUrl::~LdapUrl() = default; 0060 0061 void LdapUrl::setDn(const LdapDN &dn) 0062 { 0063 const QString tmp = dn.toString(); 0064 if (tmp.startsWith(QLatin1Char('/'))) { 0065 setPath(tmp); 0066 } else { 0067 setPath(QLatin1Char('/') + tmp); 0068 } 0069 } 0070 0071 LdapDN LdapUrl::dn() const 0072 { 0073 QString tmp = path(); 0074 if (tmp.startsWith(QLatin1Char('/'))) { 0075 tmp = tmp.mid(1); 0076 } 0077 const LdapDN tmpDN(tmp); 0078 return tmpDN; 0079 } 0080 0081 QStringList LdapUrl::attributes() const 0082 { 0083 return d->m_attributes; 0084 } 0085 0086 void LdapUrl::setAttributes(const QStringList &attributes) 0087 { 0088 d->m_attributes = attributes; 0089 updateQuery(); 0090 } 0091 0092 LdapUrl::Scope LdapUrl::scope() const 0093 { 0094 return d->m_scope; 0095 } 0096 0097 void LdapUrl::setScope(Scope scope) 0098 { 0099 d->m_scope = scope; 0100 updateQuery(); 0101 } 0102 0103 QString LdapUrl::filter() const 0104 { 0105 return d->m_filter; 0106 } 0107 0108 void LdapUrl::setFilter(const QString &filter) 0109 { 0110 d->m_filter = filter; 0111 updateQuery(); 0112 } 0113 0114 bool LdapUrl::hasExtension(const QString &key) const 0115 { 0116 return d->m_extensions.contains(key); 0117 } 0118 0119 LdapUrl::Extension LdapUrl::extension(const QString &key) const 0120 { 0121 QMap<QString, Extension>::const_iterator it; 0122 0123 it = d->m_extensions.constFind(key); 0124 if (it != d->m_extensions.constEnd()) { 0125 return *it; 0126 } else { 0127 Extension ext; 0128 ext.value = QLatin1StringView(""); 0129 ext.critical = false; 0130 return ext; 0131 } 0132 } 0133 0134 QString LdapUrl::extension(const QString &key, bool &critical) const 0135 { 0136 const Extension ext = extension(key); 0137 critical = ext.critical; 0138 return ext.value; 0139 } 0140 0141 void LdapUrl::setExtension(const QString &key, const LdapUrl::Extension &ext) 0142 { 0143 d->m_extensions[key] = ext; 0144 updateQuery(); 0145 } 0146 0147 void LdapUrl::setExtension(const QString &key, const QString &value, bool critical) 0148 { 0149 Extension ext; 0150 ext.value = value; 0151 ext.critical = critical; 0152 setExtension(key, ext); 0153 } 0154 0155 void LdapUrl::setExtension(const QString &key, int value, bool critical) 0156 { 0157 Extension ext; 0158 ext.value = QString::number(value); 0159 ext.critical = critical; 0160 setExtension(key, ext); 0161 } 0162 0163 void LdapUrl::removeExtension(const QString &key) 0164 { 0165 d->m_extensions.remove(key); 0166 updateQuery(); 0167 } 0168 0169 void LdapUrl::updateQuery() 0170 { 0171 QMap<QString, Extension>::const_iterator it; 0172 QString q(QLatin1Char('?')); 0173 0174 // set the attributes to query 0175 if (!d->m_attributes.isEmpty()) { 0176 q += d->m_attributes.join(QLatin1Char(',')); 0177 } 0178 0179 // set the scope 0180 q += QLatin1Char('?'); 0181 switch (d->m_scope) { 0182 case Sub: 0183 q += QStringLiteral("sub"); 0184 break; 0185 case One: 0186 q += QStringLiteral("one"); 0187 break; 0188 case Base: 0189 q += QStringLiteral("base"); 0190 break; 0191 } 0192 0193 // set the filter 0194 q += QLatin1Char('?'); 0195 if (d->m_filter != QLatin1StringView("(objectClass=*)") && !d->m_filter.isEmpty()) { 0196 q += QLatin1StringView(toPercentEncoding(d->m_filter)); 0197 } 0198 0199 // set the extensions 0200 q += QLatin1Char('?'); 0201 for (it = d->m_extensions.constBegin(); it != d->m_extensions.constEnd(); ++it) { 0202 if (it.value().critical) { 0203 q += QLatin1Char('!'); 0204 } 0205 q += it.key(); 0206 if (!it.value().value.isEmpty()) { 0207 q += QLatin1Char('=') + QLatin1StringView(toPercentEncoding(it.value().value)); 0208 } 0209 q += QLatin1Char(','); 0210 } 0211 while (q.endsWith(QLatin1Char('?')) || q.endsWith(QLatin1Char(','))) { 0212 q.remove(q.length() - 1, 1); 0213 } 0214 0215 setQuery(q); 0216 qCDebug(LDAP_LOG) << "LDAP URL updateQuery():" << toDisplayString(); 0217 } 0218 0219 void LdapUrl::parseQuery() 0220 { 0221 Extension ext; 0222 QStringList extensions; 0223 QString q = query(QUrl::FullyEncoded); 0224 // remove first ? 0225 if (q.startsWith(QLatin1Char('?'))) { 0226 q.remove(0, 1); 0227 } 0228 0229 // split into a list 0230 const QStringList url_items = q.split(QLatin1Char('?')); 0231 0232 d->m_attributes.clear(); 0233 d->m_scope = Base; 0234 d->m_filter = QStringLiteral("(objectClass=*)"); 0235 d->m_extensions.clear(); 0236 0237 int i = 0; 0238 QStringList::const_iterator end(url_items.constEnd()); 0239 for (QStringList::const_iterator it = url_items.constBegin(); it != end; ++it, i++) { 0240 switch (i) { 0241 case 0: 0242 d->m_attributes = (*it).split(QLatin1Char(','), Qt::SkipEmptyParts); 0243 break; 0244 case 1: 0245 if ((*it) == QLatin1StringView("sub")) { 0246 d->m_scope = Sub; 0247 } else if ((*it) == QLatin1StringView("one")) { 0248 d->m_scope = One; 0249 } 0250 break; 0251 case 2: 0252 d->m_filter = fromPercentEncoding((*it).toLatin1()); 0253 break; 0254 case 3: 0255 extensions = (*it).split(QLatin1Char(','), Qt::SkipEmptyParts); 0256 break; 0257 } 0258 } 0259 0260 QString name; 0261 QString value; 0262 QStringList::const_iterator end2(extensions.constEnd()); 0263 for (QStringList::const_iterator it = extensions.constBegin(); it != end2; ++it) { 0264 ext.critical = false; 0265 name = fromPercentEncoding((*it).section(QLatin1Char('='), 0, 0).toLatin1()).toLower(); 0266 value = fromPercentEncoding((*it).section(QLatin1Char('='), 1).toLatin1()); 0267 if (name.startsWith(QLatin1Char('!'))) { 0268 ext.critical = true; 0269 name.remove(0, 1); 0270 } 0271 qCDebug(LDAP_LOG) << "LdapUrl extensions name=" << name << "value:" << value; 0272 ext.value = value.replace(QLatin1StringView("%2"), QLatin1StringView(",")); 0273 setExtension(name, ext); 0274 } 0275 }