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
58using namespace KLDAP;
59
60class Ber::BerPrivate
61{
62 public:
63#ifdef LDAP_FOUND
64 BerElement *mBer;
65#endif
66};
67
68#ifdef LDAP_FOUND
69Ber::Ber()
70 : d( new BerPrivate )
71{
72 d->mBer = ber_alloc_t( LBER_USE_DER );
73 Q_ASSERT( d->mBer );
74}
75
76Ber::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
86Ber::~Ber()
87{
88 ber_free( d->mBer, 1 );
89 delete d;
90}
91
92Ber::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
102Ber &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
116QByteArray 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
127int 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
232int 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
384unsigned 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
393unsigned 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
403Ber::Ber()
404 : d( new BerPrivate )
405{
406 kError() << "LDAP support not compiled";
407}
408
409Ber::Ber( const QByteArray & )
410 : d( new BerPrivate )
411{
412 kError() << "LDAP support not compiled";
413}
414
415Ber::~Ber()
416{
417 delete d;
418}
419
420Ber::Ber( const Ber & )
421 : d( new BerPrivate )
422{
423 kError() << "LDAP support not compiled";
424}
425
426Ber &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
435QByteArray Ber::flatten() const
436{
437 kError() << "LDAP support not compiled";
438 return QByteArray();
439}
440
441int Ber::printf( const QString &format, ... )
442{
443 Q_UNUSED( format );
444 kError() << "LDAP support not compiled";
445 return -1;
446}
447
448int Ber::scanf( const QString &format, ... )
449{
450 Q_UNUSED( format );
451 kError() << "LDAP support not compiled";
452 return -1;
453}
454
455unsigned int Ber::peekTag( int &size )
456{
457 Q_UNUSED( size );
458 kError() << "LDAP support not compiled";
459 return 0;
460}
461
462unsigned int Ber::skipTag( int &size )
463{
464 Q_UNUSED( size );
465 kError() << "LDAP support not compiled";
466 return 0;
467}
468
469#endif
470