summaryrefslogtreecommitdiffstats
path: root/ldap/servers/slapd/ava.c
blob: 9831315c8dd80458d06c27da0f2023fd5b96f892 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/** BEGIN COPYRIGHT BLOCK
 * Copyright 2001 Sun Microsystems, Inc.
 * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
 * All rights reserved.
 * END COPYRIGHT BLOCK **/
/* ava.c - routines for dealing with attribute value assertions */

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#ifndef _WIN32
#include <sys/socket.h>
#endif
#include "slap.h"

static void strcpy_special_undo();

int
get_ava(
    BerElement	*ber,
    struct ava	*ava
)
{
	char	*type;

	if ( ber_scanf( ber, "{ao}", &type, &ava->ava_value )
	    == LBER_ERROR ) {
		LDAPDebug( LDAP_DEBUG_ANY, "  get_ava ber_scanf\n", 0, 0, 0 );
		return( LDAP_PROTOCOL_ERROR );
	}
	ava->ava_type = slapi_attr_syntax_normalize(type);
	free( type );

	return( 0 );
}

void
ava_done(
    struct ava *ava
)
{
	slapi_ch_free( (void**)&(ava->ava_type) );
	slapi_ch_free( (void**)&(ava->ava_value.bv_val) );
}

int
rdn2ava(
    char	*rdn,
    struct ava	*ava
)
{
	char	*s;

	if ( (s = strchr( rdn, '=' )) == NULL ) {
		return( -1 );
	}
	*s++ = '\0';

	ava->ava_type = rdn;
	strcpy_special_undo( s, s );
	ava->ava_value.bv_val = s;
	ava->ava_value.bv_len = strlen( s );

	return( 0 );
}

/*
** This function takes a quoted attribute value of the form "abc",
** and strips off the enclosing quotes.  It also deals with quoted
** characters by removing the preceeding '\' character.
**
*/
static void
strcpy_special_undo( char *d, const char *s )
{
    const char *end = s + strlen(s);
	for ( ; *s; s++ )
	{
		switch ( *s )
		{
		case '"':
			break;
		case '\\':
            {
            /*
             * The '\' could be escaping a single character, ie \"
             * or could be escaping a hex byte, ie \01
             */
            int singlecharacter= 1;
            if ( s+2 < end )
            {
                int n = hexchar2int( s[1] );
                if ( n >= 0 )
                {
                    int n2 = hexchar2int( s[2] );
                    if ( n2 >= 0 )
                    {
                        singlecharacter= 0;
                        n = (n << 4) + n2;
                        if (n == 0)
                        {
                            /* don't change \00 */
                            *d++ = *++s;
                            *d++ = *++s;
                        }
                        else
                        {
                            /* change \xx to a single char */
                            ++s;
                            *(unsigned char*)(s+1) = n;
                        }
                    }
                }
            }
            if(singlecharacter)
            {
                s++;
                *d++ = *s;
            }
            break;
            }
		default:
			*d++ = *s;
			break;
		}
	}
	*d = '\0';
}