]> git.sur5r.net Git - openldap/blobdiff - libraries/libldap/getdn.c
prepare for ldap_bv2dn()
[openldap] / libraries / libldap / getdn.c
index 5c3e042ed92203fade388fbb468ef2ea9abe60de..f3c60465fd42b44a6bca5f3f58fe3164b1d50d24 100644 (file)
@@ -1,6 +1,6 @@
 /* $OpenLDAP$ */
 /*
- * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
  */
 /*  Portions
@@ -25,7 +25,7 @@
 /* extension to UFN that turns trailing "dc=value" rdns in DNS style,
  * e.g. "ou=People,dc=openldap,dc=org" => "People, openldap.org" */
 #define DC_IN_UFN
-/* #define PRETTY_ESCAPE */
+#define PRETTY_ESCAPE
 
 /* parsing/printing routines */
 static int str2strval( const char *str, struct berval *val, 
@@ -111,7 +111,7 @@ ldap_dn2ufn( LDAP_CONST char *dn )
        Debug( LDAP_DEBUG_TRACE, "ldap_dn2ufn\n", 0, 0, 0 );
 
        ( void )ldap_dn_normalize( dn, LDAP_DN_FORMAT_LDAP, 
-                                  &out, LDAP_DN_FORMAT_UFN );
+               &out, LDAP_DN_FORMAT_UFN );
        
        return( out );
 }
@@ -174,7 +174,7 @@ ldap_explode_rdn( LDAP_CONST char *rdn, int notypes )
         * FIXME: we prefer efficiency over checking if the _ENTIRE_
         * dn can be parsed
         */
-       if ( ldap_str2rdn( rdn, &tmpRDN, &p, LDAP_DN_FORMAT_LDAP ) 
+       if ( ldap_str2rdn( rdn, &tmpRDN, (char **) &p, LDAP_DN_FORMAT_LDAP ) 
                        != LDAP_SUCCESS ) {
                return( NULL );
        }
@@ -299,7 +299,8 @@ ldap_dn2ad_canonical( LDAP_CONST char *dn )
  *     LDAP_DN_FORMAT_AD_CANONICAL     (?)
  */
 int
-ldap_dn_normalize( const char *dnin, unsigned fin, char **dnout, unsigned fout )
+ldap_dn_normalize( LDAP_CONST char *dnin,
+       unsigned fin, char **dnout, unsigned fout )
 {
        int     rc;
        LDAPDN  *tmpDN = NULL;
@@ -383,10 +384,12 @@ ldap_dn_normalize( const char *dnin, unsigned fin, char **dnout, unsigned fout )
 #define LDAP_DN_NE(c) \
        ( LDAP_DN_RDN_SEP_V2(c) || LDAP_DN_AVA_SEP(c) \
          || LDAP_DN_QUOTES(c) || (c) == '<' || (c) == '>' )
+#define LDAP_DN_MAYESCAPE(c) \
+       ( LDAP_DN_ESCAPE(c) || LDAP_DN_NE(c) \
+         || LDAP_DN_ASCII_SPACE(c) || LDAP_DN_OCTOTHORPE(c) )
 #define LDAP_DN_NEEDESCAPE(c) \
        ( LDAP_DN_ESCAPE(c) || LDAP_DN_NE(c) )
-#define LDAP_DN_NEEDESCAPE_LEAD(c) \
-       ( LDAP_DN_ASCII_SPACE(c) || LDAP_DN_OCTOTHORPE(c) || LDAP_DN_NE(c) )
+#define LDAP_DN_NEEDESCAPE_LEAD(c)     LDAP_DN_MAYESCAPE(c)
 #define LDAP_DN_NEEDESCAPE_TRAIL(c) \
        ( LDAP_DN_ASCII_SPACE(c) || LDAP_DN_NEEDESCAPE(c) )
 #define LDAP_DN_WILLESCAPE_CHAR(c) \
@@ -533,9 +536,9 @@ ldap_avafree( LDAPAVA *ava )
 
 #if 0
        /* la_attr is now contiguous with ava, not freed separately */
-       free( ava->la_attr.bv_val );
+       LDAP_FREE( ava->la_attr.bv_val );
 #endif
-       free( ava->la_value.bv_val );
+       LDAP_FREE( ava->la_value.bv_val );
 
        LDAP_FREE( ava );
 }
@@ -586,17 +589,42 @@ ldap_dnfree( LDAPDN *dn )
  * and readable as soon as it works as expected.
  */
 
-#define        TMP_SLOTS       256
+/*
+ * Default sizes of AVA and RDN static working arrays; if required
+ * the are dynamically resized.  The values can be tuned in case
+ * of special requirements (e.g. very deep DN trees or high number 
+ * of AVAs per RDN).
+ */
+#define        TMP_AVA_SLOTS   8
+#define        TMP_RDN_SLOTS   32
+
+int
+ldap_bv2dn( struct berval *bv, LDAPDN **dn, unsigned flags )
+{
+       assert( bv );
+       assert( dn );
+       
+       /* 
+        * FIXME: ldap_bv2dn() and ldap_str2dn() will be swapped,
+        * i.e. ldap_str2dn() will become a wrapper for ldap_bv2dn()
+        */
+       if ( bv->bv_len != strlen( bv->bv_val ) ) {
+               return LDAP_INVALID_DN_SYNTAX;
+       }
+
+       return ldap_str2dn( bv->bv_val, dn, flags );
+}
 
 int
-ldap_str2dn( const char *str, LDAPDN **dn, unsigned flags )
+ldap_str2dn( LDAP_CONST char *str, LDAPDN **dn, unsigned flags )
 {
        const char      *p;
-       int             rc = LDAP_INVALID_DN_SYNTAX;
+       int             rc = LDAP_DECODING_ERROR;
        int             nrdns = 0;
 
        LDAPDN          *newDN = NULL;
-       LDAPRDN         *newRDN = NULL, *tmpDN[TMP_SLOTS];
+       LDAPRDN         *newRDN = NULL, *tmpDN_[TMP_RDN_SLOTS], **tmpDN = tmpDN_;
+       int             num_slots = TMP_RDN_SLOTS;
        
        assert( str );
        assert( dn );
@@ -615,14 +643,15 @@ ldap_str2dn( const char *str, LDAPDN **dn, unsigned flags )
        /* unsupported in str2dn */
        case LDAP_DN_FORMAT_UFN:
        case LDAP_DN_FORMAT_AD_CANONICAL:
-               return( LDAP_INVALID_DN_SYNTAX );
+               return LDAP_PARAM_ERROR;
 
+       case LDAP_DN_FORMAT_LBER:
        default:
-               return( LDAP_OTHER );
+               return LDAP_PARAM_ERROR;
        }
 
        if ( str[ 0 ] == '\0' ) {
-               return( LDAP_SUCCESS );
+               return LDAP_SUCCESS;
        }
 
        p = str;
@@ -636,7 +665,12 @@ ldap_str2dn( const char *str, LDAPDN **dn, unsigned flags )
                        goto parsing_error;
                }
                p++;
-               
+
+       /*
+        * actually we do not want to accept by default the DCE form,
+        * we do not want to auto-detect it
+        */
+#if 0
        } else if ( LDAP_DN_LDAP( flags ) ) {
                /*
                 * if dn starts with '/' let's make it a DCE dn
@@ -645,12 +679,13 @@ ldap_str2dn( const char *str, LDAPDN **dn, unsigned flags )
                        flags |= LDAP_DN_FORMAT_DCE;
                        p++;
                }
+#endif
        }
 
        for ( ; p[ 0 ]; p++ ) {
                int             err;
                
-               err = ldap_str2rdn( p, &newRDN, &p, flags );
+               err = ldap_str2rdn( p, &newRDN, (char **) &p, flags );
                if ( err != LDAP_SUCCESS ) {
                        goto parsing_error;
                }
@@ -662,7 +697,7 @@ ldap_str2dn( const char *str, LDAPDN **dn, unsigned flags )
                        switch ( LDAP_DN_FORMAT( flags ) ) {
                        case LDAP_DN_FORMAT_LDAPV3:
                                if ( !LDAP_DN_RDN_SEP( p[ 0 ] ) ) {
-                                       rc = LDAP_OTHER;
+                                       rc = LDAP_DECODING_ERROR;
                                        goto parsing_error;
                                }
                                break;
@@ -670,14 +705,14 @@ ldap_str2dn( const char *str, LDAPDN **dn, unsigned flags )
                        case LDAP_DN_FORMAT_LDAP:
                        case LDAP_DN_FORMAT_LDAPV2:
                                if ( !LDAP_DN_RDN_SEP_V2( p[ 0 ] ) ) {
-                                       rc = LDAP_OTHER;
+                                       rc = LDAP_DECODING_ERROR;
                                        goto parsing_error;
                                }
                                break;
        
                        case LDAP_DN_FORMAT_DCE:
                                if ( !LDAP_DN_RDN_SEP_DCE( p[ 0 ] ) ) {
-                                       rc = LDAP_OTHER;
+                                       rc = LDAP_DECODING_ERROR;
                                        goto parsing_error;
                                }
                                break;
@@ -688,7 +723,31 @@ ldap_str2dn( const char *str, LDAPDN **dn, unsigned flags )
                tmpDN[nrdns++] = newRDN;
                newRDN = NULL;
 
-               assert (nrdns < TMP_SLOTS);
+               /*
+                * make the static RDN array dynamically rescalable
+                */
+               if ( nrdns == num_slots ) {
+                       LDAPRDN **tmp;
+
+                       if ( tmpDN == tmpDN_ ) {
+                               tmp = LDAP_MALLOC( num_slots * 2 * sizeof( LDAPRDN * ) );
+                               if ( tmp == NULL ) {
+                                       rc = LDAP_NO_MEMORY;
+                                       goto parsing_error;
+                               }
+                               AC_MEMCPY( tmp, tmpDN, num_slots * sizeof( LDAPRDN * ) );
+
+                       } else {
+                               tmp = LDAP_REALLOC( tmpDN, num_slots * 2 * sizeof( LDAPRDN * ) );
+                               if ( tmp == NULL ) {
+                                       rc = LDAP_NO_MEMORY;
+                                       goto parsing_error;
+                               }
+                       }
+
+                       tmpDN = tmp;
+                       num_slots *= 2;
+               }
                                
                if ( p[ 0 ] == '\0' ) {
                        /* 
@@ -724,11 +783,16 @@ parsing_error:;
                ldap_rdnfree( newRDN );
        }
 
-       for (nrdns-- ;nrdns>=0; nrdns-- )
+       for ( nrdns-- ;nrdns >= 0; nrdns-- ) {
                ldap_rdnfree( tmpDN[nrdns] );
+       }
 
 return_result:;
 
+       if ( tmpDN != tmpDN_ ) {
+               LDAP_FREE( tmpDN );
+       }
+
        Debug( LDAP_DEBUG_TRACE, "<= ldap_str2dn(%s,%u)=%d\n", str, flags, rc );
        *dn = newDN;
        
@@ -744,12 +808,14 @@ return_result:;
  * corresponds to the rdn separator or to '\0' in case the string is over.
  */
 int
-ldap_str2rdn( const char *str, LDAPRDN **rdn, const char **n, unsigned flags )
+ldap_str2rdn( LDAP_CONST char *str, LDAPRDN **rdn,
+       char **n_in, unsigned flags )
 {
+       const char  **n = (const char **) n_in;
        const char      *p;
        int             navas = 0;
        int             state = B4AVA;
-       int             rc = LDAP_INVALID_DN_SYNTAX;
+       int             rc = LDAP_DECODING_ERROR;
        int             attrTypeEncoding = LDAP_AVA_STRING, 
                        attrValueEncoding = LDAP_AVA_STRING;
 
@@ -757,13 +823,16 @@ ldap_str2rdn( const char *str, LDAPRDN **rdn, const char **n, unsigned flags )
        struct berval   attrValue = { 0, NULL };
 
        LDAPRDN         *newRDN = NULL;
-       LDAPAVA         *tmpRDN[TMP_SLOTS];
+       LDAPAVA         *tmpRDN_[TMP_AVA_SLOTS], **tmpRDN = tmpRDN_;
+       int             num_slots = TMP_AVA_SLOTS;
        
        assert( str );
        assert( rdn || flags & LDAP_DN_SKIP );
        assert( n );
 
+#if 0
        Debug( LDAP_DEBUG_TRACE, "=> ldap_str2rdn(%s,%u)\n%s", str, flags, "" );
+#endif
 
        if ( rdn ) {
                *rdn = NULL;
@@ -780,14 +849,15 @@ ldap_str2rdn( const char *str, LDAPRDN **rdn, const char **n, unsigned flags )
        /* unsupported in str2dn */
        case LDAP_DN_FORMAT_UFN:
        case LDAP_DN_FORMAT_AD_CANONICAL:
-               return( LDAP_INVALID_DN_SYNTAX );
+               return LDAP_PARAM_ERROR;
 
+       case LDAP_DN_FORMAT_LBER:
        default:
-               return( LDAP_OTHER );
+               return LDAP_PARAM_ERROR;
        }
 
        if ( str[ 0 ] == '\0' ) {
-               return( LDAP_SUCCESS );
+               return LDAP_SUCCESS;
        }
 
        p = str;
@@ -1036,7 +1106,12 @@ ldap_str2rdn( const char *str, LDAPRDN **rdn, const char **n, unsigned flags )
                         * here STRING means RFC 2253 string
                         * FIXME: what about DCE strings? 
                         */
-                       state = B4STRINGVALUE;
+                       if ( !p[ 0 ] ) {
+                               /* empty value */
+                               state = GOTAVA;
+                       } else {
+                               state = B4STRINGVALUE;
+                       }
                        break;
 
                case B4BINARYVALUE:
@@ -1100,13 +1175,41 @@ ldap_str2rdn( const char *str, LDAPRDN **rdn, const char **n, unsigned flags )
                                 */
                                ava = ldapava_new( &attrType, &attrValue, 
                                                attrValueEncoding );
+                               
                                if ( ava == NULL ) {
                                        rc = LDAP_NO_MEMORY;
                                        goto parsing_error;
                                }
                                tmpRDN[navas++] = ava;
 
-                               assert(navas < TMP_SLOTS);
+                               attrValue.bv_val = NULL;
+                               attrValue.bv_len = 0;
+
+                               /*
+                                * prepare room for new AVAs if needed
+                                */
+                               if (navas == num_slots) {
+                                       LDAPAVA **tmp;
+                                       
+                                       if ( tmpRDN == tmpRDN_ ) {
+                                               tmp = LDAP_MALLOC( num_slots * 2 * sizeof( LDAPAVA * ) );
+                                               if ( tmp == NULL ) {
+                                                       rc = LDAP_NO_MEMORY;
+                                                       goto parsing_error;
+                                               }
+                                               AC_MEMCPY( tmp, tmpRDN, num_slots * sizeof( LDAPAVA * ) );
+
+                                       } else {
+                                               tmp = LDAP_REALLOC( tmpRDN, num_slots * 2 * sizeof( LDAPAVA * ) );
+                                               if ( tmp == NULL ) {
+                                                       rc = LDAP_NO_MEMORY;
+                                                       goto parsing_error;
+                                               }
+                                       }
+
+                                       tmpRDN = tmp;
+                                       num_slots *= 2;
+                               }
                        }
                        
                        /* 
@@ -1179,13 +1282,21 @@ parsing_error:;
                free( attrValue.bv_val );
        }
 
-       for (navas-- ; navas>=0; navas-- )
+       for ( navas-- ; navas >= 0; navas-- ) {
                ldap_avafree( tmpRDN[navas] );
+       }
 
 return_result:;
 
+       if ( tmpRDN != tmpRDN_ ) {
+               LDAP_FREE( tmpRDN );
+       }
+
+#if 0
        Debug( LDAP_DEBUG_TRACE, "<= ldap_str2rdn(%*s)=%d\n", 
                        p - str, str, rc );
+#endif
+
        if ( rdn ) {
                *rdn = newRDN;
        }
@@ -1202,7 +1313,7 @@ static int
 str2strval( const char *str, struct berval *val, const char **next, unsigned flags, unsigned *retFlags )
 {
        const char      *p, *startPos, *endPos = NULL;
-       ber_len_t       len, escapes, unescapes;
+       ber_len_t       len, escapes;
 
        assert( str );
        assert( val );
@@ -1210,15 +1321,13 @@ str2strval( const char *str, struct berval *val, const char **next, unsigned fla
 
        *next = NULL;
 
-       for ( startPos = p = str, escapes = 0, unescapes = 0; p[ 0 ]; p++ ) {
+       for ( startPos = p = str, escapes = 0; p[ 0 ]; p++ ) {
                if ( LDAP_DN_ESCAPE( p[ 0 ] ) ) {
                        p++;
                        if ( p[ 0 ] == '\0' ) {
                                return( 1 );
                        }
-                       if ( ( p == startPos + 1 && LDAP_DN_NEEDESCAPE_LEAD( p[ 0 ] ) )
-                                       || ( LDAP_DN_VALUE_END( p[ 1 ] ) && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) )
-                                       || LDAP_DN_NEEDESCAPE( p[ 0 ] ) ) {
+                       if ( LDAP_DN_MAYESCAPE( p[ 0 ] ) ) {
                                escapes++;
                                continue;
                        }
@@ -1245,14 +1354,15 @@ str2strval( const char *str, struct berval *val, const char **next, unsigned fla
                                return( 1 );
                        }
                        /* 
-                        * FIXME: we allow escaping 
+                        * we do not allow escaping 
                         * of chars that don't need 
                         * to and do not belong to 
-                        * HEXDIGITS (we also allow
-                        * single hexdigit; maybe we 
-                        * shouldn't).
+                        * HEXDIGITS
                         */
-                       unescapes++;
+                       return( 1 );
+
+               } else if (!LDAP_DN_ASCII_PRINTABLE( p[ 0 ] ) ) {
+                       *retFlags = LDAP_AVA_NONPRINTABLE;
 
                } else if ( ( LDAP_DN_LDAP( flags ) && LDAP_DN_VALUE_END_V2( p[ 0 ] ) ) 
                                || ( LDAP_DN_LDAPV3( flags ) && LDAP_DN_VALUE_END( p[ 0 ] ) ) ) {
@@ -1295,10 +1405,10 @@ str2strval( const char *str, struct berval *val, const char **next, unsigned fla
        /*
         * FIXME: test memory?
         */
-       len = ( endPos ? endPos : p ) - startPos - escapes - unescapes;
+       len = ( endPos ? endPos : p ) - startPos - escapes;
        val->bv_len = len;
 
-       if ( escapes == 0 && unescapes == 0 ) {
+       if ( escapes == 0 ) {
                val->bv_val = LDAP_STRNDUP( startPos, len );
 
        } else {
@@ -1308,9 +1418,7 @@ str2strval( const char *str, struct berval *val, const char **next, unsigned fla
                for ( s = 0, d = 0; d < len; ) {
                        if ( LDAP_DN_ESCAPE( startPos[ s ] ) ) {
                                s++;
-                               if ( ( s == 0 && LDAP_DN_NEEDESCAPE_LEAD( startPos[ s ] ) )
-                                               || ( s == len - 1 && LDAP_DN_NEEDESCAPE_TRAIL( startPos[ s ] ) )
-                                               || LDAP_DN_NEEDESCAPE( startPos[ s ] ) ) {
+                               if ( LDAP_DN_MAYESCAPE( startPos[ s ] ) ) {
                                        val->bv_val[ d++ ] = 
                                                startPos[ s++ ];
                                        
@@ -1322,12 +1430,8 @@ str2strval( const char *str, struct berval *val, const char **next, unsigned fla
                                        s += 2;
                                        
                                } else {
-                                       /*
-                                        * we allow escaping of chars
-                                        * that do not need to 
-                                        */
-                                       val->bv_val[ d++ ] = 
-                                               startPos[ s++ ];
+                                       /* we should never get here */
+                                       assert( 0 );
                                }
 
                        } else {
@@ -1336,7 +1440,7 @@ str2strval( const char *str, struct berval *val, const char **next, unsigned fla
                }
 
                val->bv_val[ d ] = '\0';
-               assert( strlen( val->bv_val ) == len );
+               assert( d == len );
        }
 
        return( 0 );
@@ -1806,8 +1910,18 @@ strval2strlen( struct berval *val, unsigned flags, ber_len_t *len )
                return( 0 );
        }
 
-       for ( l = 0, p = val->bv_val; p[ 0 ]; p += cl ) {
-               cl = LDAP_UTF8_CHARLEN( p );
+       for ( l = 0, p = val->bv_val; p < val->bv_val + val->bv_len; p += cl ) {
+
+               /* 
+                * escape '%x00' 
+                */
+               if ( p[ 0 ] == '\0' ) {
+                       cl = 1;
+                       l += 3;
+                       continue;
+               }
+
+               cl = LDAP_UTF8_CHARLEN2( p, cl );
                if ( cl == 0 ) {
                        /* illegal utf-8 char! */
                        return( -1 );
@@ -1816,7 +1930,7 @@ strval2strlen( struct berval *val, unsigned flags, ber_len_t *len )
                        ber_len_t cnt;
 
                        for ( cnt = 1; cnt < cl; cnt++ ) {
-                               if ( ( p[ cnt ] & 0x80 ) == 0x00 ) {
+                               if ( ( p[ cnt ] & 0xc0 ) != 0x80 ) {
                                        return( -1 );
                                }
                        }
@@ -1826,7 +1940,11 @@ strval2strlen( struct berval *val, unsigned flags, ber_len_t *len )
                                || ( p == val->bv_val && LDAP_DN_NEEDESCAPE_LEAD( p[ 0 ] ) )
                                || ( !p[ 1 ] && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) ) ) {
 #ifdef PRETTY_ESCAPE
+#if 0
                        if ( LDAP_DN_WILLESCAPE_HEX( flags, p[ 0 ] ) ) {
+#else
+                       if ( LDAP_DN_WILLESCAPE_CHAR( p[ 0 ] ) ) {
+#endif
 
                                /* 
                                 * there might be some chars we want 
@@ -1875,7 +1993,26 @@ strval2str( struct berval *val, char *str, unsigned flags, ber_len_t *len )
         * of the value
         */
        for ( s = 0, d = 0, end = val->bv_len - 1; s < val->bv_len; ) {
-               ber_len_t       cl = LDAP_UTF8_CHARLEN( &val->bv_val[ s ] );
+               ber_len_t       cl;
+
+               /* 
+                * escape '%x00' 
+                */
+               if ( val->bv_val[ s ] == '\0' ) {
+                       cl = 1;
+                       str[ d++ ] = '\\';
+                       str[ d++ ] = '0';
+                       str[ d++ ] = '0';
+                       s++;
+                       continue;
+               }
+               
+               /*
+                * The length was checked in strval2strlen();
+                * LDAP_UTF8_CHARLEN() should suffice
+                */
+               cl = LDAP_UTF8_CHARLEN2( &val->bv_val[ s ], cl );
+               assert( cl > 0 );
                
                /* 
                 * there might be some chars we want to escape in form
@@ -1883,7 +2020,11 @@ strval2str( struct berval *val, char *str, unsigned flags, ber_len_t *len )
                 */
                if ( ( cl > 1 && !LDAP_DN_IS_PRETTY( flags ) ) 
 #ifdef PRETTY_ESCAPE
+#if 0
                                || LDAP_DN_WILLESCAPE_HEX( flags, val->bv_val[ s ] ) 
+#else
+                               || LDAP_DN_WILLESCAPE_CHAR( val->bv_val[ s ] ) 
+#endif
 #else /* ! PRETTY_ESCAPE */
                                || LDAP_DN_NEEDESCAPE( val->bv_val[ s ] )
                                || ( d == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) )
@@ -2232,7 +2373,7 @@ dn2domain( LDAPDN *dn, struct berval *bv, int pos, int *iRDN )
                        l += ava->la_value.bv_len;
 
                } else {
-                       AC_MEMCPY( str + ava->la_value.bv_len + 1, bv->bv_val, l);
+                       AC_MEMCPY( str + ava->la_value.bv_len + 1, bv->bv_val + pos, l);
                        AC_MEMCPY( str, ava->la_value.bv_val, 
                                        ava->la_value.bv_len );
                        str[ ava->la_value.bv_len ] = '.';
@@ -2597,6 +2738,10 @@ ldap_rdn2str( LDAPRDN *rdn, char **str, unsigned flags )
 
        assert( str );
 
+       if((flags & LDAP_DN_FORMAT_MASK) == LDAP_DN_FORMAT_LBER) {
+               return LDAP_PARAM_ERROR;
+       }
+
        rc = ldap_rdn2bv( rdn, &bv, flags );
        *str = bv.bv_val;
        return rc;
@@ -2625,36 +2770,36 @@ ldap_rdn2bv( LDAPRDN *rdn, struct berval *bv, unsigned flags )
        switch ( LDAP_DN_FORMAT( flags ) ) {
        case LDAP_DN_FORMAT_LDAPV3:
                if ( rdn2strlen( rdn, flags, &l, strval2strlen ) ) {
-                       return( LDAP_OTHER );
+                       return LDAP_DECODING_ERROR;
                }
                break;
 
        case LDAP_DN_FORMAT_LDAPV2:
                if ( rdn2strlen( rdn, flags, &l, strval2IA5strlen ) ) {
-                       return( LDAP_OTHER );
+                       return LDAP_DECODING_ERROR;
                }
                break;
 
        case LDAP_DN_FORMAT_UFN:
                if ( rdn2UFNstrlen( rdn, flags, &l ) ) {
-                       return( LDAP_OTHER );
+                       return LDAP_DECODING_ERROR;
                }
                break;
 
        case LDAP_DN_FORMAT_DCE:
                if ( rdn2DCEstrlen( rdn, flags, &l ) ) {
-                       return( LDAP_OTHER );
+                       return LDAP_DECODING_ERROR;
                }
                break;
 
        case LDAP_DN_FORMAT_AD_CANONICAL:
                if ( rdn2ADstrlen( rdn, flags, &l ) ) {
-                       return( LDAP_OTHER );
+                       return LDAP_DECODING_ERROR;
                }
                break;
 
        default:
-               return( LDAP_INVALID_DN_SYNTAX );
+               return( LDAP_PARAM_ERROR );
        }
 
        bv->bv_val = LDAP_MALLOC( l + 1 );
@@ -2687,18 +2832,18 @@ ldap_rdn2bv( LDAPRDN *rdn, struct berval *bv, unsigned flags )
 
        default:
                /* need at least one of the previous */
-               return( LDAP_OTHER );
+               return LDAP_PARAM_ERROR;
        }
 
        if ( rc ) {
                ldap_memfree( bv->bv_val );
-               return( LDAP_OTHER );
+               return rc;
        }
 
        bv->bv_len = l - back;
        bv->bv_val[ bv->bv_len ] = '\0';
 
-       return( LDAP_SUCCESS );
+       return LDAP_SUCCESS;
 }
 
 /*
@@ -2720,6 +2865,10 @@ int ldap_dn2str( LDAPDN *dn, char **str, unsigned flags )
 
        assert( str );
 
+       if((flags & LDAP_DN_FORMAT_MASK) == LDAP_DN_FORMAT_LBER) {
+               return LDAP_PARAM_ERROR;
+       }
+       
        rc = ldap_dn2bv( dn, &bv, flags );
        *str = bv.bv_val;
        return rc;
@@ -2728,7 +2877,7 @@ int ldap_dn2str( LDAPDN *dn, char **str, unsigned flags )
 int ldap_dn2bv( LDAPDN *dn, struct berval *bv, unsigned flags )
 {
        int             iRDN;
-       int             rc = LDAP_OTHER;
+       int             rc = LDAP_ENCODING_ERROR;
        ber_len_t       len, l;
 
        /* stringifying helpers for LDAPv3/LDAPv2 */
@@ -2736,7 +2885,6 @@ int ldap_dn2bv( LDAPDN *dn, struct berval *bv, unsigned flags )
        int ( *sv2s ) ( struct berval *v, char *s, unsigned f, ber_len_t *l );
 
        assert( bv );
-
        bv->bv_len = 0;
        bv->bv_val = NULL;
 
@@ -2755,13 +2903,13 @@ int ldap_dn2bv( LDAPDN *dn, struct berval *bv, unsigned flags )
        case LDAP_DN_FORMAT_LDAPV3:
                sv2l = strval2strlen;
                sv2s = strval2str;
-               goto got_funcs;
 
+               if( 0 ) {
        case LDAP_DN_FORMAT_LDAPV2:
-               sv2l = strval2IA5strlen;
-               sv2s = strval2IA5str;
-got_funcs:
-               
+                       sv2l = strval2IA5strlen;
+                       sv2s = strval2IA5str;
+               }
+
                for ( iRDN = 0, len = 0; dn[ 0 ][ iRDN ]; iRDN++ ) {
                        ber_len_t       rdnl;
                        LDAPRDN         *rdn = dn[ 0 ][ iRDN ];
@@ -2804,7 +2952,6 @@ got_funcs:
                break;
 
        case LDAP_DN_FORMAT_UFN: {
-
                /*
                 * FIXME: quoting from RFC 1781:
                 *
@@ -2919,11 +3066,10 @@ got_funcs:
 #endif /* DC_IN_UFN */
                
                rc = LDAP_SUCCESS;
-               break;
-       }
 
-       case LDAP_DN_FORMAT_DCE:
+       } break;
 
+       case LDAP_DN_FORMAT_DCE:
                for ( iRDN = 0, len = 0; dn[ 0 ][ iRDN ]; iRDN++ ) {
                        ber_len_t       rdnl;
                        LDAPRDN         *rdn = dn[ 0 ][ iRDN ];
@@ -2962,7 +3108,6 @@ got_funcs:
                break;
 
        case LDAP_DN_FORMAT_AD_CANONICAL: {
-               
                /*
                 * Sort of UFN for DCE DNs: a slash ('/') separated
                 * global->local DN with no types; strictly speaking,
@@ -3019,7 +3164,7 @@ got_funcs:
                        if ( flags & LDAP_DN_PEDANTIC ) {
                                LDAP_FREE( bv->bv_val );
                                bv->bv_val = NULL;
-                               rc = LDAP_INVALID_DN_SYNTAX;
+                               rc = LDAP_ENCODING_ERROR;
                                break;
                        }
 
@@ -3044,16 +3189,15 @@ got_funcs:
                bv->bv_val[ bv->bv_len ] = '\0';
 
                rc = LDAP_SUCCESS;
-               break;
-       }
+       } break;
 
        default:
-               return( LDAP_INVALID_DN_SYNTAX );
-
+               return LDAP_PARAM_ERROR;
        }
 
        Debug( LDAP_DEBUG_TRACE, "<= ldap_dn2bv(%s,%u)=%d\n",
                bv->bv_val, flags, rc );
+
 return_results:;
        return( rc );
 }