/* This file is part of libkldap. Copyright (c) 2004-2006 Szombathelyi György This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "ber.h" #include "kldap_config.h" #include #include #include #include #ifdef LDAP_FOUND #ifdef Q_OS_SOLARIS //krazy:exclude=cpp #define BC31 1 #endif #ifndef HAVE_WINLDAP_H #include #include #else #include #endif #ifndef LBER_USE_DER #define LBER_USE_DER 1 #endif #ifndef HAVE_BER_MEMFREE # ifndef HAVE_WINLDAP_H # define ber_memfree(x) ldap_memfree(x) # else # define ber_memfree(x) win_ldap_memfree(x) # endif #endif #endif using namespace KLDAP; class Ber::BerPrivate { public: #ifdef LDAP_FOUND BerElement *mBer; #endif }; #ifdef LDAP_FOUND Ber::Ber() : d( new BerPrivate ) { d->mBer = ber_alloc_t( LBER_USE_DER ); Q_ASSERT( d->mBer ); } Ber::Ber( const QByteArray &value ) : d( new BerPrivate ) { struct berval bv; bv.bv_val = (char *) value.data(); bv.bv_len = value.size(); d->mBer = ber_init( &bv ); Q_ASSERT( d->mBer ); } Ber::~Ber() { ber_free( d->mBer, 1 ); delete d; } Ber::Ber( const Ber &that ) : d( new BerPrivate ) { struct berval *bv; if ( ber_flatten( that.d->mBer, &bv ) == 0 ) { d->mBer = ber_init( bv ); ber_bvfree( bv ); } } Ber &Ber::operator=( const Ber &that ) { if ( this == &that ) { return *this; } struct berval *bv; if ( ber_flatten( that.d->mBer, &bv ) == 0 ) { d->mBer = ber_init( bv ); ber_bvfree( bv ); } return *this; } QByteArray Ber::flatten() const { QByteArray ret; struct berval *bv; if ( ber_flatten( d->mBer, &bv ) == 0 ) { ret = QByteArray( bv->bv_val, bv->bv_len ); ber_bvfree( bv ); } return ret; } int Ber::printf( const QString &format, ... ) { char fmt[2]; va_list args; va_start ( args, format ); fmt[1] = '\0'; int i = 0, ret = 0; while ( i < format.length() ) { fmt[0] = format[i].toLatin1(); i++; switch ( fmt[0] ) { case 'b': case 'e': case 'i': { ber_int_t v = va_arg( args, int ); ret = ber_printf( d->mBer, fmt, v ); break; } case 'B': { //FIXME: QBitArray vould be logical, but how to access the bits? QByteArray *B = va_arg( args, QByteArray * ); int Bc = va_arg( args, int ); ret = ber_printf( d->mBer, fmt, B->data(), Bc ); break; } case 'o': { QByteArray *o = va_arg( args, QByteArray * ); ret = ber_printf( d->mBer, fmt, o->data(), o->size() ); break; } case 'O': { QByteArray *O = va_arg( args, QByteArray * ); struct berval bv; bv.bv_val = (char *) O->data(); bv.bv_len = O->size(); ret = ber_printf( d->mBer, fmt, &bv ); break; } break; case 's': { QByteArray *s = va_arg( args, QByteArray * ); ret = ber_printf( d->mBer, fmt, s->data() ); break; } break; case 't': { unsigned int t = va_arg( args, unsigned int ); ret = ber_printf( d->mBer, fmt, t ); break; } break; case 'v': { QList *v = va_arg( args, QList * ); QVarLengthArray l( v->count()+1 ); int j; for ( j = 0; j < v->count(); j++ ) { l[j] = v->at( j ).data(); } l[j] = 0; ret = ber_printf( d->mBer, fmt, l.data() ); break; } case 'V': { QList *V = va_arg( args, QList * ); QVarLengthArray bv ( V->count()+1 ); QVarLengthArray bvs( V->count( ) ); int j; for ( j = 0; j < V->count(); j++ ) { bvs[j].bv_val = (char *) V->at( j ).data(); bvs[j].bv_len = V->at( j ).size(); bv[j] = &bvs[j]; } bv[V->count()] = 0; ret = ber_printf( d->mBer, fmt, bv.data() ); break; } case 'n': case '{': case '}': case '[': case ']': ret = ber_printf( d->mBer, fmt ); break; default: kWarning() << "Invalid BER format parameter: '" << fmt << "'"; ret = -1; } kDebug() << "ber_printf format:" << fmt << "ret:" << ret; if ( ret == -1 ) { break; } } va_end( args ); return ret; } int Ber::scanf( const QString &format, ... ) { char fmt[2]; va_list args; va_start ( args, format ); fmt[1] = '\0'; int i = 0, ret = 0; while ( i < format.length() ) { fmt[0] = format[i].toLatin1(); i++; switch ( fmt[0] ) { case 'l': case 'b': case 'e': case 'i': { int *v = va_arg( args, int * ); ret = ber_scanf( d->mBer, fmt, v ); break; } case 'B': { //FIXME: QBitArray vould be logical, but how to access the bits? QByteArray *B = va_arg( args, QByteArray * ); int *Bc = va_arg( args, int * ); char *c; ret = ber_scanf( d->mBer, fmt, &c, Bc ); if ( ret != -1 ) { *B = QByteArray( c, ( *Bc + 7 ) / 8 ); ber_memfree( c ); } break; } case 'o': { QByteArray *o = va_arg( args, QByteArray * ); struct berval bv; ret = ber_scanf( d->mBer, fmt, &bv ); if ( ret != -1 ) { *o = QByteArray( bv.bv_val, bv.bv_len ); ber_memfree( bv.bv_val ); } break; } case 'O': { QByteArray *O = va_arg( args, QByteArray * ); struct berval *bv; ret = ber_scanf( d->mBer, fmt, &bv ); if ( ret != -1 ) { *O = QByteArray( bv->bv_val, bv->bv_len ); ber_bvfree( bv ); } break; } break; case 'm': //the same as 'O', just *bv should not be freed. { QByteArray *m = va_arg( args, QByteArray * ); struct berval *bv; ret = ber_scanf( d->mBer, fmt, &bv ); if ( ret != -1 ) { *m = QByteArray( bv->bv_val, bv->bv_len ); } break; } case 'a': { QByteArray *a = va_arg( args, QByteArray * ); char *c; ret = ber_scanf( d->mBer, fmt, &c ); if ( ret != -1 ) { *a = QByteArray( c ); ber_memfree( c ); } break; } case 's': { QByteArray *s = va_arg( args, QByteArray * ); char buf[255]; ber_len_t l = sizeof( buf ); ret = ber_scanf( d->mBer, fmt, &buf, &l ); if ( ret != -1 ) { *s = QByteArray( buf, l ); } break; } case 't': case 'T': { unsigned int *t = va_arg( args, unsigned int * ); ret = ber_scanf( d->mBer, fmt, t ); break; } break; case 'v': { QList *v = va_arg( args, QList * ); char **c, **c2; ret = ber_scanf( d->mBer, fmt, &c ); if ( ret != -1 && c ) { c2 = c; while ( *c ) { v->append( QByteArray( *c ) ); ber_memfree( *c ); c++; } ber_memfree( (char *) c2 ); } break; } case 'V': { QList *v = va_arg( args, QList * ); struct berval **bv, **bv2; ret = ber_scanf( d->mBer, fmt, &bv ); if ( ret != -1 && bv ) { bv2 = bv; while ( *bv ) { v->append( QByteArray( ( *bv )->bv_val, ( *bv )->bv_len ) ); bv++; } ber_bvecfree( bv2 ); } break; } case 'x': case 'n': case '{': case '}': case '[': case ']': ret = ber_scanf( d->mBer, fmt ); break; default: kWarning() << "Invalid BER format parameter: '" << fmt << "'"; ret = -1; } kDebug() << "ber_scanf format:" << fmt << "ret:" << ret; if ( ret == -1 ) { break; } } va_end( args ); return ret; } unsigned int Ber::peekTag( int &size ) { unsigned int ret; ber_len_t len; ret = ber_peek_tag( d->mBer, &len ); size = len; return ret; } unsigned int Ber::skipTag( int &size ) { unsigned int ret; ber_len_t len; ret = ber_skip_tag( d->mBer, &len ); size = len; return ret; } #else Ber::Ber() : d( new BerPrivate ) { kError() << "LDAP support not compiled"; } Ber::Ber( const QByteArray & ) : d( new BerPrivate ) { kError() << "LDAP support not compiled"; } Ber::~Ber() { delete d; } Ber::Ber( const Ber & ) : d( new BerPrivate ) { kError() << "LDAP support not compiled"; } Ber &Ber::operator=( const Ber &that ) { if ( this == &that ) { return *this; } kError() << "LDAP support not compiled"; return *this; } QByteArray Ber::flatten() const { kError() << "LDAP support not compiled"; return QByteArray(); } int Ber::printf( const QString &format, ... ) { Q_UNUSED( format ); kError() << "LDAP support not compiled"; return -1; } int Ber::scanf( const QString &format, ... ) { Q_UNUSED( format ); kError() << "LDAP support not compiled"; return -1; } unsigned int Ber::peekTag( int &size ) { Q_UNUSED( size ); kError() << "LDAP support not compiled"; return 0; } unsigned int Ber::skipTag( int &size ) { Q_UNUSED( size ); kError() << "LDAP support not compiled"; return 0; } #endif