1/*
2 This file is part of libkldap.
3 Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21#include "ldapurl.h"
22
23#include <kdebug.h>
24
25#include <QtCore/QStringList>
26
27using namespace KLDAP;
28
29class LdapUrl::LdapUrlPrivate
30{
31 public:
32 LdapUrlPrivate()
33 : m_scope( Base )
34 {
35 }
36
37 QMap<QString, Extension> m_extensions;
38 QStringList m_attributes;
39 Scope m_scope;
40 QString m_filter;
41};
42
43LdapUrl::LdapUrl()
44 : d( new LdapUrlPrivate )
45{
46}
47
48LdapUrl::LdapUrl( const KUrl &_url )
49 : KUrl( _url ), d( new LdapUrlPrivate )
50{
51 QString tmp = path();
52 if ( tmp.startsWith( QLatin1Char('/') ) ) {
53 tmp = tmp.mid( 1 );
54 }
55 setPath( tmp );
56 parseQuery();
57}
58
59LdapUrl::LdapUrl( const LdapUrl &that )
60 : KUrl( that ), d( new LdapUrlPrivate )
61{
62 *d = *that.d;
63}
64
65LdapUrl &LdapUrl::operator=( const LdapUrl &that )
66{
67 if ( this == &that ) {
68 return *this;
69 }
70
71 KUrl::operator=( that );
72 *d = *that.d;
73
74 return *this;
75}
76
77LdapUrl::~LdapUrl()
78{
79 delete d;
80}
81
82void LdapUrl::setDn( const LdapDN &dn )
83{
84 QString tmp = dn.toString();
85 if ( tmp.startsWith( QLatin1Char('/') ) ) {
86 tmp = tmp.mid( 1 );
87 }
88 setPath( tmp );
89}
90
91LdapDN LdapUrl::dn() const
92{
93 QString tmp = path();
94 if ( tmp.startsWith( QLatin1Char('/') ) ) {
95 tmp = tmp.mid( 1 );
96 }
97 LdapDN tmpDN( tmp );
98 return tmpDN;
99}
100
101QStringList LdapUrl::attributes() const
102{
103 return d->m_attributes;
104}
105
106void LdapUrl::setAttributes( const QStringList &attributes )
107{
108 d->m_attributes=attributes;
109 updateQuery();
110}
111
112LdapUrl::Scope LdapUrl::scope() const
113{
114 return d->m_scope;
115}
116
117void LdapUrl::setScope( Scope scope )
118{
119 d->m_scope = scope;
120 updateQuery();
121}
122
123QString LdapUrl::filter() const
124{
125 return d->m_filter;
126}
127
128void LdapUrl::setFilter( const QString &filter )
129{
130 d->m_filter = filter;
131 updateQuery();
132}
133
134bool LdapUrl::hasExtension( const QString &key ) const
135{
136 return d->m_extensions.contains( key );
137}
138
139LdapUrl::Extension LdapUrl::extension( const QString &key ) const
140{
141 QMap<QString, Extension>::const_iterator it;
142
143 it = d->m_extensions.constFind( key );
144 if ( it != d->m_extensions.constEnd() ) {
145 return ( *it );
146 } else {
147 Extension ext;
148 ext.value = QLatin1String("");
149 ext.critical = false;
150 return ext;
151 }
152}
153
154QString LdapUrl::extension( const QString &key, bool &critical ) const
155{
156 Extension ext;
157
158 ext = extension( key );
159 critical = ext.critical;
160 return ext.value;
161}
162
163void LdapUrl::setExtension( const QString &key, const LdapUrl::Extension &ext )
164{
165 d->m_extensions[ key ] = ext;
166 updateQuery();
167}
168
169void LdapUrl::setExtension( const QString &key, const QString &value, bool critical )
170{
171 Extension ext;
172 ext.value = value;
173 ext.critical = critical;
174 setExtension( key, ext );
175}
176
177void LdapUrl::setExtension( const QString &key, int value, bool critical )
178{
179 Extension ext;
180 ext.value = QString::number( value );
181 ext.critical = critical;
182 setExtension( key, ext );
183}
184
185void LdapUrl::removeExtension( const QString &key )
186{
187 d->m_extensions.remove( key );
188 updateQuery();
189}
190
191void LdapUrl::updateQuery()
192{
193 QMap<QString, Extension>::const_iterator it;
194 QString q( QLatin1Char('?') );
195
196 // set the attributes to query
197 if ( !d->m_attributes.isEmpty() ) {
198 q += d->m_attributes.join( QLatin1String(",") );
199 }
200
201 // set the scope
202 q += QLatin1Char('?');
203 switch ( d->m_scope ) {
204 case Sub:
205 q += QLatin1String("sub");
206 break;
207 case One:
208 q += QLatin1String("one");
209 break;
210 case Base:
211 q += QLatin1String("base");
212 break;
213 }
214
215 // set the filter
216 q += QLatin1Char('?');
217 if ( d->m_filter != QLatin1String("(objectClass=*)") && !d->m_filter.isEmpty() ) {
218 q += QLatin1String(toPercentEncoding( d->m_filter ));
219 }
220
221 // set the extensions
222 q += QLatin1Char('?');
223 for ( it = d->m_extensions.constBegin(); it != d->m_extensions.constEnd(); ++it ) {
224 if ( it.value().critical ) {
225 q += QLatin1Char('!');
226 }
227 q += it.key();
228 if ( !it.value().value.isEmpty() ) {
229 q += QLatin1Char('=') + QLatin1String(toPercentEncoding( it.value().value ));
230 }
231 q += QLatin1Char(',');
232 }
233 while ( q.endsWith( QLatin1Char('?') ) || q.endsWith( QLatin1Char(',') ) ) {
234 q.remove( q.length() - 1, 1 );
235 }
236
237 setQuery( q );
238 kDebug() << "LDAP URL updateQuery():" << prettyUrl();
239}
240
241void LdapUrl::parseQuery()
242{
243 Extension ext;
244 QStringList extensions;
245 QString q = query();
246 // remove first ?
247 if ( q.startsWith( QLatin1Char('?') ) ) {
248 q.remove( 0, 1 );
249 }
250
251 // split into a list
252 QStringList url_items = q.split( QLatin1Char('?') );
253
254 d->m_attributes.clear();
255 d->m_scope = Base;
256 d->m_filter = QLatin1String("(objectClass=*)");
257 d->m_extensions.clear();
258
259 int i = 0;
260 QStringList::const_iterator end( url_items.constEnd() );
261 for ( QStringList::const_iterator it=url_items.constBegin();
262 it != end; ++it, i++ ) {
263 switch ( i ) {
264 case 0:
265 d->m_attributes = ( *it ).split( QLatin1Char(','), QString::SkipEmptyParts );
266 break;
267 case 1:
268 if ( ( *it ) == QLatin1String( "sub" ) ) {
269 d->m_scope = Sub;
270 } else if ( ( *it ) == QLatin1String( "one" ) ) {
271 d->m_scope = One;
272 }
273 break;
274 case 2:
275 d->m_filter = fromPercentEncoding( ( *it ).toLatin1() );
276 break;
277 case 3:
278 extensions = ( *it ).split( QLatin1Char(','), QString::SkipEmptyParts );
279 break;
280 }
281 }
282
283 QString name, value;
284 QStringList::const_iterator end2( extensions.constEnd() );
285 for ( QStringList::const_iterator it=extensions.constBegin();
286 it != end2; ++it ) {
287 ext.critical = false;
288 name = fromPercentEncoding( ( *it ).section( QLatin1Char('='), 0, 0 ).toLatin1() ).toLower();
289 value = fromPercentEncoding( ( *it ).section( QLatin1Char('='), 1 ).toLatin1() );
290 if ( name.startsWith( QLatin1Char('!') ) ) {
291 ext.critical = true;
292 name.remove( 0, 1 );
293 }
294 kDebug() << "LdapUrl extensions name=" << name << "value:" << value;
295 ext.value = value.replace( QLatin1String("%2"), QLatin1String(",") );
296 setExtension( name, ext );
297 }
298}
299