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 "ber.h" |
22 | #include "kldap_config.h" |
23 | |
24 | #include <kdebug.h> |
25 | |
26 | #include <QtCore/QList> |
27 | #include <qvarlengtharray.h> |
28 | |
29 | #include <cstdarg> |
30 | |
31 | #ifdef LDAP_FOUND |
32 | |
33 | #ifdef Q_OS_SOLARIS //krazy:exclude=cpp |
34 | #define BC31 1 |
35 | #endif |
36 | |
37 | #ifndef HAVE_WINLDAP_H |
38 | #include <lber.h> |
39 | #include <ldap.h> |
40 | #else |
41 | #include <w32-ldap-help.h> |
42 | #endif |
43 | |
44 | #ifndef LBER_USE_DER |
45 | #define LBER_USE_DER 1 |
46 | #endif |
47 | |
48 | #ifndef HAVE_BER_MEMFREE |
49 | # ifndef HAVE_WINLDAP_H |
50 | # define ber_memfree(x) ldap_memfree(x) |
51 | # else |
52 | # define ber_memfree(x) win_ldap_memfree(x) |
53 | # endif |
54 | #endif |
55 | |
56 | #endif |
57 | |
58 | using namespace KLDAP; |
59 | |
60 | class Ber::BerPrivate |
61 | { |
62 | public: |
63 | #ifdef LDAP_FOUND |
64 | BerElement *mBer; |
65 | #endif |
66 | }; |
67 | |
68 | #ifdef LDAP_FOUND |
69 | Ber::Ber() |
70 | : d( new BerPrivate ) |
71 | { |
72 | d->mBer = ber_alloc_t( LBER_USE_DER ); |
73 | Q_ASSERT( d->mBer ); |
74 | } |
75 | |
76 | Ber::Ber( const QByteArray &value ) |
77 | : d( new BerPrivate ) |
78 | { |
79 | struct berval bv; |
80 | bv.bv_val = (char *) value.data(); |
81 | bv.bv_len = value.size(); |
82 | d->mBer = ber_init( &bv ); |
83 | Q_ASSERT( d->mBer ); |
84 | } |
85 | |
86 | Ber::~Ber() |
87 | { |
88 | ber_free( d->mBer, 1 ); |
89 | delete d; |
90 | } |
91 | |
92 | Ber::Ber( const Ber &that ) |
93 | : d( new BerPrivate ) |
94 | { |
95 | struct berval *bv; |
96 | if ( ber_flatten( that.d->mBer, &bv ) == 0 ) { |
97 | d->mBer = ber_init( bv ); |
98 | ber_bvfree( bv ); |
99 | } |
100 | } |
101 | |
102 | Ber &Ber::operator=( const Ber &that ) |
103 | { |
104 | if ( this == &that ) { |
105 | return *this; |
106 | } |
107 | |
108 | struct berval *bv; |
109 | if ( ber_flatten( that.d->mBer, &bv ) == 0 ) { |
110 | d->mBer = ber_init( bv ); |
111 | ber_bvfree( bv ); |
112 | } |
113 | return *this; |
114 | } |
115 | |
116 | QByteArray Ber::flatten() const |
117 | { |
118 | QByteArray ret; |
119 | struct berval *bv; |
120 | if ( ber_flatten( d->mBer, &bv ) == 0 ) { |
121 | ret = QByteArray( bv->bv_val, bv->bv_len ); |
122 | ber_bvfree( bv ); |
123 | } |
124 | return ret; |
125 | } |
126 | |
127 | int Ber::printf( const QString &format, ... ) |
128 | { |
129 | char fmt[2]; |
130 | va_list args; |
131 | va_start ( args, format ); |
132 | fmt[1] = '\0'; |
133 | |
134 | int i = 0, ret = 0; |
135 | while ( i < format.length() ) { |
136 | fmt[0] = format[i].toLatin1(); |
137 | i++; |
138 | switch ( fmt[0] ) { |
139 | case 'b': |
140 | case 'e': |
141 | case 'i': |
142 | { |
143 | ber_int_t v = va_arg( args, int ); |
144 | ret = ber_printf( d->mBer, fmt, v ); |
145 | break; |
146 | } |
147 | case 'B': |
148 | { |
149 | //FIXME: QBitArray vould be logical, but how to access the bits? |
150 | QByteArray *B = va_arg( args, QByteArray * ); |
151 | int Bc = va_arg( args, int ); |
152 | ret = ber_printf( d->mBer, fmt, B->data(), Bc ); |
153 | break; |
154 | } |
155 | case 'o': |
156 | { |
157 | QByteArray *o = va_arg( args, QByteArray * ); |
158 | ret = ber_printf( d->mBer, fmt, o->data(), o->size() ); |
159 | break; |
160 | } |
161 | case 'O': |
162 | { |
163 | QByteArray *O = va_arg( args, QByteArray * ); |
164 | struct berval bv; |
165 | bv.bv_val = (char *) O->data(); |
166 | bv.bv_len = O->size(); |
167 | ret = ber_printf( d->mBer, fmt, &bv ); |
168 | break; |
169 | } |
170 | break; |
171 | case 's': |
172 | { |
173 | QByteArray *s = va_arg( args, QByteArray * ); |
174 | ret = ber_printf( d->mBer, fmt, s->data() ); |
175 | break; |
176 | } |
177 | break; |
178 | case 't': |
179 | { |
180 | unsigned int t = va_arg( args, unsigned int ); |
181 | ret = ber_printf( d->mBer, fmt, t ); |
182 | break; |
183 | } |
184 | break; |
185 | case 'v': |
186 | { |
187 | QList<QByteArray> *v = va_arg( args, QList<QByteArray> * ); |
188 | QVarLengthArray<const char *> l( v->count()+1 ); |
189 | int j; |
190 | for ( j = 0; j < v->count(); j++ ) { |
191 | l[j] = v->at( j ).data(); |
192 | } |
193 | l[j] = 0; |
194 | ret = ber_printf( d->mBer, fmt, l.data() ); |
195 | break; |
196 | } |
197 | case 'V': |
198 | { |
199 | QList<QByteArray> *V = va_arg( args, QList<QByteArray> * ); |
200 | QVarLengthArray<struct berval *> bv ( V->count()+1 ); |
201 | QVarLengthArray<struct berval> bvs( V->count( ) ); |
202 | int j; |
203 | for ( j = 0; j < V->count(); j++ ) { |
204 | bvs[j].bv_val = (char *) V->at( j ).data(); |
205 | bvs[j].bv_len = V->at( j ).size(); |
206 | bv[j] = &bvs[j]; |
207 | } |
208 | bv[V->count()] = 0; |
209 | ret = ber_printf( d->mBer, fmt, bv.data() ); |
210 | break; |
211 | } |
212 | case 'n': |
213 | case '{': |
214 | case '}': |
215 | case '[': |
216 | case ']': |
217 | ret = ber_printf( d->mBer, fmt ); |
218 | break; |
219 | default: |
220 | kWarning() << "Invalid BER format parameter: '" << fmt << "'" ; |
221 | ret = -1; |
222 | } |
223 | kDebug() << "ber_printf format:" << fmt << "ret:" << ret; |
224 | if ( ret == -1 ) { |
225 | break; |
226 | } |
227 | } |
228 | va_end( args ); |
229 | return ret; |
230 | } |
231 | |
232 | int Ber::scanf( const QString &format, ... ) |
233 | { |
234 | char fmt[2]; |
235 | va_list args; |
236 | va_start ( args, format ); |
237 | fmt[1] = '\0'; |
238 | |
239 | int i = 0, ret = 0; |
240 | while ( i < format.length() ) { |
241 | fmt[0] = format[i].toLatin1(); |
242 | i++; |
243 | switch ( fmt[0] ) { |
244 | case 'l': |
245 | case 'b': |
246 | case 'e': |
247 | case 'i': |
248 | { |
249 | int *v = va_arg( args, int * ); |
250 | ret = ber_scanf( d->mBer, fmt, v ); |
251 | break; |
252 | } |
253 | case 'B': |
254 | { |
255 | //FIXME: QBitArray vould be logical, but how to access the bits? |
256 | QByteArray *B = va_arg( args, QByteArray * ); |
257 | int *Bc = va_arg( args, int * ); |
258 | char *c; |
259 | ret = ber_scanf( d->mBer, fmt, &c, Bc ); |
260 | if ( ret != -1 ) { |
261 | *B = QByteArray( c, ( *Bc + 7 ) / 8 ); |
262 | ber_memfree( c ); |
263 | } |
264 | break; |
265 | } |
266 | case 'o': |
267 | { |
268 | QByteArray *o = va_arg( args, QByteArray * ); |
269 | struct berval bv; |
270 | ret = ber_scanf( d->mBer, fmt, &bv ); |
271 | if ( ret != -1 ) { |
272 | *o = QByteArray( bv.bv_val, bv.bv_len ); |
273 | ber_memfree( bv.bv_val ); |
274 | } |
275 | break; |
276 | } |
277 | case 'O': |
278 | { |
279 | QByteArray *O = va_arg( args, QByteArray * ); |
280 | struct berval *bv; |
281 | ret = ber_scanf( d->mBer, fmt, &bv ); |
282 | if ( ret != -1 ) { |
283 | *O = QByteArray( bv->bv_val, bv->bv_len ); |
284 | ber_bvfree( bv ); |
285 | } |
286 | break; |
287 | } |
288 | break; |
289 | case 'm': //the same as 'O', just *bv should not be freed. |
290 | { |
291 | QByteArray *m = va_arg( args, QByteArray * ); |
292 | struct berval *bv; |
293 | ret = ber_scanf( d->mBer, fmt, &bv ); |
294 | if ( ret != -1 ) { |
295 | *m = QByteArray( bv->bv_val, bv->bv_len ); |
296 | } |
297 | break; |
298 | } |
299 | case 'a': |
300 | { |
301 | QByteArray *a = va_arg( args, QByteArray * ); |
302 | char *c; |
303 | ret = ber_scanf( d->mBer, fmt, &c ); |
304 | if ( ret != -1 ) { |
305 | *a = QByteArray( c ); |
306 | ber_memfree( c ); |
307 | } |
308 | break; |
309 | } |
310 | |
311 | case 's': |
312 | { |
313 | QByteArray *s = va_arg( args, QByteArray * ); |
314 | char buf[255]; |
315 | ber_len_t l = sizeof( buf ); |
316 | ret = ber_scanf( d->mBer, fmt, &buf, &l ); |
317 | if ( ret != -1 ) { |
318 | *s = QByteArray( buf, l ); |
319 | } |
320 | break; |
321 | } |
322 | case 't': |
323 | case 'T': |
324 | { |
325 | unsigned int *t = va_arg( args, unsigned int * ); |
326 | ret = ber_scanf( d->mBer, fmt, t ); |
327 | break; |
328 | } |
329 | break; |
330 | case 'v': |
331 | { |
332 | QList<QByteArray> *v = va_arg( args, QList<QByteArray> * ); |
333 | char **c, **c2; |
334 | ret = ber_scanf( d->mBer, fmt, &c ); |
335 | if ( ret != -1 && c ) { |
336 | c2 = c; |
337 | while ( *c ) { |
338 | v->append( QByteArray( *c ) ); |
339 | ber_memfree( *c ); |
340 | c++; |
341 | } |
342 | ber_memfree( (char *) c2 ); |
343 | } |
344 | break; |
345 | } |
346 | case 'V': |
347 | { |
348 | QList<QByteArray> *v = va_arg( args, QList<QByteArray> * ); |
349 | struct berval **bv, **bv2; |
350 | ret = ber_scanf( d->mBer, fmt, &bv ); |
351 | if ( ret != -1 && bv ) { |
352 | bv2 = bv; |
353 | while ( *bv ) { |
354 | v->append( QByteArray( ( *bv )->bv_val, ( *bv )->bv_len ) ); |
355 | bv++; |
356 | } |
357 | ber_bvecfree( bv2 ); |
358 | } |
359 | break; |
360 | } |
361 | case 'x': |
362 | case 'n': |
363 | case '{': |
364 | case '}': |
365 | case '[': |
366 | case ']': |
367 | ret = ber_scanf( d->mBer, fmt ); |
368 | break; |
369 | default: |
370 | kWarning() << "Invalid BER format parameter: '" << fmt << "'" ; |
371 | ret = -1; |
372 | } |
373 | |
374 | kDebug() << "ber_scanf format:" << fmt << "ret:" << ret; |
375 | if ( ret == -1 ) { |
376 | break; |
377 | } |
378 | |
379 | } |
380 | va_end( args ); |
381 | return ret; |
382 | } |
383 | |
384 | unsigned int Ber::peekTag( int &size ) |
385 | { |
386 | unsigned int ret; |
387 | ber_len_t len; |
388 | ret = ber_peek_tag( d->mBer, &len ); |
389 | size = len; |
390 | return ret; |
391 | } |
392 | |
393 | unsigned int Ber::skipTag( int &size ) |
394 | { |
395 | unsigned int ret; |
396 | ber_len_t len; |
397 | ret = ber_skip_tag( d->mBer, &len ); |
398 | size = len; |
399 | return ret; |
400 | } |
401 | #else |
402 | |
403 | Ber::Ber() |
404 | : d( new BerPrivate ) |
405 | { |
406 | kError() << "LDAP support not compiled" ; |
407 | } |
408 | |
409 | Ber::Ber( const QByteArray & ) |
410 | : d( new BerPrivate ) |
411 | { |
412 | kError() << "LDAP support not compiled" ; |
413 | } |
414 | |
415 | Ber::~Ber() |
416 | { |
417 | delete d; |
418 | } |
419 | |
420 | Ber::Ber( const Ber & ) |
421 | : d( new BerPrivate ) |
422 | { |
423 | kError() << "LDAP support not compiled" ; |
424 | } |
425 | |
426 | Ber &Ber::operator=( const Ber &that ) |
427 | { |
428 | if ( this == &that ) { |
429 | return *this; |
430 | } |
431 | kError() << "LDAP support not compiled" ; |
432 | return *this; |
433 | } |
434 | |
435 | QByteArray Ber::flatten() const |
436 | { |
437 | kError() << "LDAP support not compiled" ; |
438 | return QByteArray(); |
439 | } |
440 | |
441 | int Ber::printf( const QString &format, ... ) |
442 | { |
443 | Q_UNUSED( format ); |
444 | kError() << "LDAP support not compiled" ; |
445 | return -1; |
446 | } |
447 | |
448 | int Ber::scanf( const QString &format, ... ) |
449 | { |
450 | Q_UNUSED( format ); |
451 | kError() << "LDAP support not compiled" ; |
452 | return -1; |
453 | } |
454 | |
455 | unsigned int Ber::peekTag( int &size ) |
456 | { |
457 | Q_UNUSED( size ); |
458 | kError() << "LDAP support not compiled" ; |
459 | return 0; |
460 | } |
461 | |
462 | unsigned int Ber::skipTag( int &size ) |
463 | { |
464 | Q_UNUSED( size ); |
465 | kError() << "LDAP support not compiled" ; |
466 | return 0; |
467 | } |
468 | |
469 | #endif |
470 | |