1*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
2*0Sstevel@tonic-gate
3*0Sstevel@tonic-gate /*
4*0Sstevel@tonic-gate * The contents of this file are subject to the Netscape Public
5*0Sstevel@tonic-gate * License Version 1.1 (the "License"); you may not use this file
6*0Sstevel@tonic-gate * except in compliance with the License. You may obtain a copy of
7*0Sstevel@tonic-gate * the License at http://www.mozilla.org/NPL/
8*0Sstevel@tonic-gate *
9*0Sstevel@tonic-gate * Software distributed under the License is distributed on an "AS
10*0Sstevel@tonic-gate * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11*0Sstevel@tonic-gate * implied. See the License for the specific language governing
12*0Sstevel@tonic-gate * rights and limitations under the License.
13*0Sstevel@tonic-gate *
14*0Sstevel@tonic-gate * The Original Code is Mozilla Communicator client code, released
15*0Sstevel@tonic-gate * March 31, 1998.
16*0Sstevel@tonic-gate *
17*0Sstevel@tonic-gate * The Initial Developer of the Original Code is Netscape
18*0Sstevel@tonic-gate * Communications Corporation. Portions created by Netscape are
19*0Sstevel@tonic-gate * Copyright (C) 1998-1999 Netscape Communications Corporation. All
20*0Sstevel@tonic-gate * Rights Reserved.
21*0Sstevel@tonic-gate *
22*0Sstevel@tonic-gate * Contributor(s):
23*0Sstevel@tonic-gate */
24*0Sstevel@tonic-gate /*
25*0Sstevel@tonic-gate * Copyright (c) 1990 Regents of the University of Michigan.
26*0Sstevel@tonic-gate * All rights reserved.
27*0Sstevel@tonic-gate */
28*0Sstevel@tonic-gate /*
29*0Sstevel@tonic-gate * getvalues.c
30*0Sstevel@tonic-gate */
31*0Sstevel@tonic-gate
32*0Sstevel@tonic-gate #if 0
33*0Sstevel@tonic-gate #ifndef lint
34*0Sstevel@tonic-gate static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
35*0Sstevel@tonic-gate #endif
36*0Sstevel@tonic-gate #endif
37*0Sstevel@tonic-gate
38*0Sstevel@tonic-gate #include "ldap-int.h"
39*0Sstevel@tonic-gate
40*0Sstevel@tonic-gate
41*0Sstevel@tonic-gate static void **
internal_ldap_get_values(LDAP * ld,LDAPMessage * entry,const char * target,int lencall)42*0Sstevel@tonic-gate internal_ldap_get_values( LDAP *ld, LDAPMessage *entry, const char *target,
43*0Sstevel@tonic-gate int lencall )
44*0Sstevel@tonic-gate {
45*0Sstevel@tonic-gate struct berelement ber;
46*0Sstevel@tonic-gate char *attr;
47*0Sstevel@tonic-gate int rc;
48*0Sstevel@tonic-gate void **vals;
49*0Sstevel@tonic-gate
50*0Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "ldap_get_values\n", 0, 0, 0 );
51*0Sstevel@tonic-gate
52*0Sstevel@tonic-gate if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
53*0Sstevel@tonic-gate return( NULL ); /* punt */
54*0Sstevel@tonic-gate }
55*0Sstevel@tonic-gate if ( target == NULL ||
56*0Sstevel@tonic-gate !NSLDAPI_VALID_LDAPMESSAGE_ENTRY_POINTER( entry )) {
57*0Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL );
58*0Sstevel@tonic-gate return( NULL );
59*0Sstevel@tonic-gate }
60*0Sstevel@tonic-gate
61*0Sstevel@tonic-gate ber = *entry->lm_ber;
62*0Sstevel@tonic-gate
63*0Sstevel@tonic-gate /* skip sequence, dn, sequence of, and snag the first attr */
64*0Sstevel@tonic-gate if ( ber_scanf( &ber, "{x{{a", &attr ) == LBER_ERROR ) {
65*0Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL );
66*0Sstevel@tonic-gate return( NULL );
67*0Sstevel@tonic-gate }
68*0Sstevel@tonic-gate
69*0Sstevel@tonic-gate rc = strcasecmp( (char *)target, attr );
70*0Sstevel@tonic-gate NSLDAPI_FREE( attr );
71*0Sstevel@tonic-gate if ( rc != 0 ) {
72*0Sstevel@tonic-gate while ( 1 ) {
73*0Sstevel@tonic-gate if ( ber_scanf( &ber, "x}{a", &attr ) == LBER_ERROR ) {
74*0Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR,
75*0Sstevel@tonic-gate NULL, NULL );
76*0Sstevel@tonic-gate return( NULL );
77*0Sstevel@tonic-gate }
78*0Sstevel@tonic-gate
79*0Sstevel@tonic-gate rc = strcasecmp( (char *)target, attr );
80*0Sstevel@tonic-gate if ( rc == 0 ) {
81*0Sstevel@tonic-gate NSLDAPI_FREE( attr );
82*0Sstevel@tonic-gate break;
83*0Sstevel@tonic-gate }
84*0Sstevel@tonic-gate NSLDAPI_FREE( attr );
85*0Sstevel@tonic-gate }
86*0Sstevel@tonic-gate }
87*0Sstevel@tonic-gate
88*0Sstevel@tonic-gate /*
89*0Sstevel@tonic-gate * if we get this far, we've found the attribute and are sitting
90*0Sstevel@tonic-gate * just before the set of values.
91*0Sstevel@tonic-gate */
92*0Sstevel@tonic-gate
93*0Sstevel@tonic-gate if ( lencall ) {
94*0Sstevel@tonic-gate rc = ber_scanf( &ber, "[V]", &vals );
95*0Sstevel@tonic-gate } else {
96*0Sstevel@tonic-gate rc = ber_scanf( &ber, "[v]", &vals );
97*0Sstevel@tonic-gate }
98*0Sstevel@tonic-gate
99*0Sstevel@tonic-gate if ( rc == LBER_ERROR ) {
100*0Sstevel@tonic-gate rc = LDAP_DECODING_ERROR;
101*0Sstevel@tonic-gate } else {
102*0Sstevel@tonic-gate rc = LDAP_SUCCESS;
103*0Sstevel@tonic-gate }
104*0Sstevel@tonic-gate
105*0Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, rc, NULL, NULL );
106*0Sstevel@tonic-gate
107*0Sstevel@tonic-gate return(( rc == LDAP_SUCCESS ) ? vals : NULL );
108*0Sstevel@tonic-gate }
109*0Sstevel@tonic-gate
110*0Sstevel@tonic-gate
111*0Sstevel@tonic-gate /* For language-sensitive attribute matching, we are looking for a
112*0Sstevel@tonic-gate language tag that looks like one of the following:
113*0Sstevel@tonic-gate
114*0Sstevel@tonic-gate cn
115*0Sstevel@tonic-gate cn;lang-en
116*0Sstevel@tonic-gate cn;lang-en-us
117*0Sstevel@tonic-gate cn;lang-ja
118*0Sstevel@tonic-gate cn;lang-ja-JP-kanji
119*0Sstevel@tonic-gate
120*0Sstevel@tonic-gate The base language specification consists of two letters following
121*0Sstevel@tonic-gate "lang-". After that, there may be additional language-specific
122*0Sstevel@tonic-gate narrowings preceded by a "-". In our processing we go from the
123*0Sstevel@tonic-gate specific to the general, preferring a complete subtype match, but
124*0Sstevel@tonic-gate accepting a partial one. For example:
125*0Sstevel@tonic-gate
126*0Sstevel@tonic-gate For a request for "cn;lang-en-us", we would return cn;lang-en-us
127*0Sstevel@tonic-gate if present, otherwise cn;lang-en if present, otherwise cn.
128*0Sstevel@tonic-gate
129*0Sstevel@tonic-gate Besides the language subtype, there may be other subtypes:
130*0Sstevel@tonic-gate
131*0Sstevel@tonic-gate cn;lang-ja;binary (Unlikely!)
132*0Sstevel@tonic-gate cn;lang-ja;phonetic
133*0Sstevel@tonic-gate
134*0Sstevel@tonic-gate If not in the target, they are ignored. If they are in the target,
135*0Sstevel@tonic-gate they must be in the attribute to match.
136*0Sstevel@tonic-gate */
137*0Sstevel@tonic-gate #define LANG_SUBTYPE_INDEX_NONE -1
138*0Sstevel@tonic-gate #define LANG_SUBTYPE_INDEX_DUPLICATE -2
139*0Sstevel@tonic-gate
140*0Sstevel@tonic-gate typedef struct {
141*0Sstevel@tonic-gate int start;
142*0Sstevel@tonic-gate int length;
143*0Sstevel@tonic-gate } _SubStringIndex;
144*0Sstevel@tonic-gate
145*0Sstevel@tonic-gate static int
parse_subtypes(const char * target,int * baseLenp,char ** langp,_SubStringIndex ** subs,int * nsubtypes)146*0Sstevel@tonic-gate parse_subtypes( const char *target, int *baseLenp, char **langp,
147*0Sstevel@tonic-gate _SubStringIndex **subs, int *nsubtypes )
148*0Sstevel@tonic-gate {
149*0Sstevel@tonic-gate int nSubtypes = 0;
150*0Sstevel@tonic-gate int ind = 0;
151*0Sstevel@tonic-gate char *nextToken;
152*0Sstevel@tonic-gate _SubStringIndex *result = NULL;
153*0Sstevel@tonic-gate int langIndex;
154*0Sstevel@tonic-gate int targetLen;
155*0Sstevel@tonic-gate int subtypeStart;
156*0Sstevel@tonic-gate
157*0Sstevel@tonic-gate langIndex = LANG_SUBTYPE_INDEX_NONE;
158*0Sstevel@tonic-gate *subs = NULL;
159*0Sstevel@tonic-gate *langp = NULL;
160*0Sstevel@tonic-gate *baseLenp = 0;
161*0Sstevel@tonic-gate *nsubtypes = 0;
162*0Sstevel@tonic-gate targetLen = strlen( target );
163*0Sstevel@tonic-gate
164*0Sstevel@tonic-gate /* Parse past base attribute */
165*0Sstevel@tonic-gate nextToken = strchr( target, ';' );
166*0Sstevel@tonic-gate if ( NULL != nextToken ) {
167*0Sstevel@tonic-gate subtypeStart = nextToken - target + 1;
168*0Sstevel@tonic-gate *baseLenp = subtypeStart - 1;
169*0Sstevel@tonic-gate }
170*0Sstevel@tonic-gate else {
171*0Sstevel@tonic-gate subtypeStart = targetLen;
172*0Sstevel@tonic-gate *baseLenp = subtypeStart;
173*0Sstevel@tonic-gate }
174*0Sstevel@tonic-gate ind = subtypeStart;
175*0Sstevel@tonic-gate
176*0Sstevel@tonic-gate /* How many subtypes? */
177*0Sstevel@tonic-gate nextToken = (char *)target + subtypeStart;
178*0Sstevel@tonic-gate while ( nextToken && *nextToken ) {
179*0Sstevel@tonic-gate char *thisToken = nextToken;
180*0Sstevel@tonic-gate nextToken = strchr( thisToken, ';' );
181*0Sstevel@tonic-gate if ( NULL != nextToken )
182*0Sstevel@tonic-gate nextToken++;
183*0Sstevel@tonic-gate if ( 0 == strncasecmp( thisToken, "lang-", 5 ) ) {
184*0Sstevel@tonic-gate /* If there was a previous lang tag, this is illegal! */
185*0Sstevel@tonic-gate if ( langIndex != LANG_SUBTYPE_INDEX_NONE ) {
186*0Sstevel@tonic-gate langIndex = LANG_SUBTYPE_INDEX_DUPLICATE;
187*0Sstevel@tonic-gate return langIndex;
188*0Sstevel@tonic-gate }
189*0Sstevel@tonic-gate else {
190*0Sstevel@tonic-gate langIndex = nSubtypes;
191*0Sstevel@tonic-gate }
192*0Sstevel@tonic-gate } else {
193*0Sstevel@tonic-gate nSubtypes++;
194*0Sstevel@tonic-gate }
195*0Sstevel@tonic-gate }
196*0Sstevel@tonic-gate /* No language subtype? */
197*0Sstevel@tonic-gate if ( langIndex < 0 )
198*0Sstevel@tonic-gate return langIndex;
199*0Sstevel@tonic-gate
200*0Sstevel@tonic-gate /* Allocate array of non-language subtypes */
201*0Sstevel@tonic-gate if ( nSubtypes > 0 ) {
202*0Sstevel@tonic-gate result = (_SubStringIndex *)NSLDAPI_MALLOC( sizeof(*result)
203*0Sstevel@tonic-gate * nSubtypes );
204*0Sstevel@tonic-gate if (result == NULL) {
205*0Sstevel@tonic-gate return LANG_SUBTYPE_INDEX_NONE; /* Error */
206*0Sstevel@tonic-gate }
207*0Sstevel@tonic-gate memset( result, 0, sizeof(*result) * nSubtypes );
208*0Sstevel@tonic-gate }
209*0Sstevel@tonic-gate ind = 0;
210*0Sstevel@tonic-gate nSubtypes = 0;
211*0Sstevel@tonic-gate ind = subtypeStart;
212*0Sstevel@tonic-gate nextToken = (char *)target + subtypeStart;
213*0Sstevel@tonic-gate while ( nextToken && *nextToken ) {
214*0Sstevel@tonic-gate char *thisToken = nextToken;
215*0Sstevel@tonic-gate int len;
216*0Sstevel@tonic-gate nextToken = strchr( thisToken, ';' );
217*0Sstevel@tonic-gate if ( NULL != nextToken ) {
218*0Sstevel@tonic-gate len = nextToken - thisToken;
219*0Sstevel@tonic-gate nextToken++;
220*0Sstevel@tonic-gate }
221*0Sstevel@tonic-gate else {
222*0Sstevel@tonic-gate nextToken = (char *)target + targetLen;
223*0Sstevel@tonic-gate len = nextToken - thisToken;
224*0Sstevel@tonic-gate }
225*0Sstevel@tonic-gate if ( 0 == strncasecmp( thisToken, "lang-", 5 ) ) {
226*0Sstevel@tonic-gate int i;
227*0Sstevel@tonic-gate *langp = (char *)NSLDAPI_MALLOC( len + 1 );
228*0Sstevel@tonic-gate if (*langp == NULL) {
229*0Sstevel@tonic-gate if (result != NULL)
230*0Sstevel@tonic-gate NSLDAPI_FREE(result);
231*0Sstevel@tonic-gate return LANG_SUBTYPE_INDEX_NONE; /* Error */
232*0Sstevel@tonic-gate }
233*0Sstevel@tonic-gate for( i = 0; i < len; i++ )
234*0Sstevel@tonic-gate (*langp)[i] = toupper( target[ind+i] );
235*0Sstevel@tonic-gate (*langp)[len] = 0;
236*0Sstevel@tonic-gate }
237*0Sstevel@tonic-gate else {
238*0Sstevel@tonic-gate result[nSubtypes].start = thisToken - target;
239*0Sstevel@tonic-gate result[nSubtypes].length = len;
240*0Sstevel@tonic-gate nSubtypes++;
241*0Sstevel@tonic-gate }
242*0Sstevel@tonic-gate }
243*0Sstevel@tonic-gate *subs = result;
244*0Sstevel@tonic-gate *nsubtypes = nSubtypes;
245*0Sstevel@tonic-gate return langIndex;
246*0Sstevel@tonic-gate }
247*0Sstevel@tonic-gate
248*0Sstevel@tonic-gate
249*0Sstevel@tonic-gate static int
check_lang_match(const char * target,const char * baseTarget,_SubStringIndex * targetTypes,int ntargetTypes,char * targetLang,char * attr)250*0Sstevel@tonic-gate check_lang_match( const char *target, const char *baseTarget,
251*0Sstevel@tonic-gate _SubStringIndex *targetTypes,
252*0Sstevel@tonic-gate int ntargetTypes, char *targetLang, char *attr )
253*0Sstevel@tonic-gate {
254*0Sstevel@tonic-gate int langIndex;
255*0Sstevel@tonic-gate _SubStringIndex *subtypes;
256*0Sstevel@tonic-gate int baseLen;
257*0Sstevel@tonic-gate char *lang;
258*0Sstevel@tonic-gate int nsubtypes;
259*0Sstevel@tonic-gate int mismatch = 0;
260*0Sstevel@tonic-gate int match = -1;
261*0Sstevel@tonic-gate int i;
262*0Sstevel@tonic-gate
263*0Sstevel@tonic-gate /* Get all subtypes in the attribute name */
264*0Sstevel@tonic-gate langIndex = parse_subtypes( attr, &baseLen, &lang, &subtypes, &nsubtypes );
265*0Sstevel@tonic-gate
266*0Sstevel@tonic-gate /* Check if there any required non-language subtypes which are
267*0Sstevel@tonic-gate not in this attribute */
268*0Sstevel@tonic-gate for( i = 0; i < ntargetTypes; i++ ) {
269*0Sstevel@tonic-gate char *t = (char *)target+targetTypes[i].start;
270*0Sstevel@tonic-gate int tlen = targetTypes[i].length;
271*0Sstevel@tonic-gate int j;
272*0Sstevel@tonic-gate for( j = 0; j < nsubtypes; j++ ) {
273*0Sstevel@tonic-gate char *a = attr + subtypes[j].start;
274*0Sstevel@tonic-gate int alen = subtypes[j].length;
275*0Sstevel@tonic-gate if ( (tlen == alen) && !strncasecmp( t, a, tlen ) )
276*0Sstevel@tonic-gate break;
277*0Sstevel@tonic-gate }
278*0Sstevel@tonic-gate if ( j >= nsubtypes ) {
279*0Sstevel@tonic-gate mismatch = 1;
280*0Sstevel@tonic-gate break;
281*0Sstevel@tonic-gate }
282*0Sstevel@tonic-gate }
283*0Sstevel@tonic-gate if ( mismatch ) {
284*0Sstevel@tonic-gate if ( NULL != subtypes )
285*0Sstevel@tonic-gate NSLDAPI_FREE( subtypes );
286*0Sstevel@tonic-gate if ( NULL != lang )
287*0Sstevel@tonic-gate NSLDAPI_FREE( lang );
288*0Sstevel@tonic-gate return -1;
289*0Sstevel@tonic-gate }
290*0Sstevel@tonic-gate
291*0Sstevel@tonic-gate /* If there was no language subtype... */
292*0Sstevel@tonic-gate if ( langIndex < 0 ) {
293*0Sstevel@tonic-gate if ( NULL != subtypes )
294*0Sstevel@tonic-gate NSLDAPI_FREE( subtypes );
295*0Sstevel@tonic-gate if ( NULL != lang )
296*0Sstevel@tonic-gate NSLDAPI_FREE( lang );
297*0Sstevel@tonic-gate if ( LANG_SUBTYPE_INDEX_NONE == langIndex )
298*0Sstevel@tonic-gate return 0;
299*0Sstevel@tonic-gate else
300*0Sstevel@tonic-gate return -1;
301*0Sstevel@tonic-gate }
302*0Sstevel@tonic-gate
303*0Sstevel@tonic-gate /* Okay, now check the language subtag */
304*0Sstevel@tonic-gate i = 0;
305*0Sstevel@tonic-gate while( targetLang[i] && lang[i] &&
306*0Sstevel@tonic-gate (toupper(targetLang[i]) == toupper(lang[i])) )
307*0Sstevel@tonic-gate i++;
308*0Sstevel@tonic-gate
309*0Sstevel@tonic-gate /* The total length can't be longer than the requested subtype */
310*0Sstevel@tonic-gate if ( !lang[i] || (lang[i] == ';') ) {
311*0Sstevel@tonic-gate /* If the found subtype is shorter than the requested one, the next
312*0Sstevel@tonic-gate character in the requested one should be "-" */
313*0Sstevel@tonic-gate if ( !targetLang[i] || (targetLang[i] == '-') )
314*0Sstevel@tonic-gate match = i;
315*0Sstevel@tonic-gate }
316*0Sstevel@tonic-gate return match;
317*0Sstevel@tonic-gate }
318*0Sstevel@tonic-gate
check_base_match(const char * target,char * attr)319*0Sstevel@tonic-gate static int check_base_match( const char *target, char *attr )
320*0Sstevel@tonic-gate {
321*0Sstevel@tonic-gate int i = 0;
322*0Sstevel@tonic-gate int rc;
323*0Sstevel@tonic-gate while( target[i] && attr[i] && (toupper(target[i]) == toupper(attr[i])) )
324*0Sstevel@tonic-gate i++;
325*0Sstevel@tonic-gate rc = ( !target[i] && (!attr[i] || (';' == attr[i])) );
326*0Sstevel@tonic-gate return rc;
327*0Sstevel@tonic-gate }
328*0Sstevel@tonic-gate
329*0Sstevel@tonic-gate static void **
internal_ldap_get_lang_values(LDAP * ld,LDAPMessage * entry,const char * target,char ** type,int lencall)330*0Sstevel@tonic-gate internal_ldap_get_lang_values( LDAP *ld, LDAPMessage *entry,
331*0Sstevel@tonic-gate const char *target, char **type, int lencall )
332*0Sstevel@tonic-gate {
333*0Sstevel@tonic-gate struct berelement ber;
334*0Sstevel@tonic-gate char *attr = NULL;
335*0Sstevel@tonic-gate int rc;
336*0Sstevel@tonic-gate void **vals = NULL;
337*0Sstevel@tonic-gate int langIndex;
338*0Sstevel@tonic-gate _SubStringIndex *subtypes;
339*0Sstevel@tonic-gate int nsubtypes;
340*0Sstevel@tonic-gate char *baseTarget = NULL;
341*0Sstevel@tonic-gate int bestMatch = 0;
342*0Sstevel@tonic-gate char *lang = NULL;
343*0Sstevel@tonic-gate int len;
344*0Sstevel@tonic-gate int firstAttr = 1;
345*0Sstevel@tonic-gate char *bestType = NULL;
346*0Sstevel@tonic-gate
347*0Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "ldap_get_values\n", 0, 0, 0 );
348*0Sstevel@tonic-gate
349*0Sstevel@tonic-gate if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
350*0Sstevel@tonic-gate return( NULL );
351*0Sstevel@tonic-gate }
352*0Sstevel@tonic-gate if ( (target == NULL) ||
353*0Sstevel@tonic-gate !NSLDAPI_VALID_LDAPMESSAGE_ENTRY_POINTER( entry )) {
354*0Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL );
355*0Sstevel@tonic-gate return( NULL );
356*0Sstevel@tonic-gate }
357*0Sstevel@tonic-gate
358*0Sstevel@tonic-gate /* A language check was requested, so see if there really is a
359*0Sstevel@tonic-gate language subtype in the attribute spec */
360*0Sstevel@tonic-gate langIndex = parse_subtypes( target, &len, &lang,
361*0Sstevel@tonic-gate &subtypes, &nsubtypes );
362*0Sstevel@tonic-gate if ( langIndex < 0 ) {
363*0Sstevel@tonic-gate if ( NULL != subtypes ) {
364*0Sstevel@tonic-gate NSLDAPI_FREE( subtypes );
365*0Sstevel@tonic-gate subtypes = NULL;
366*0Sstevel@tonic-gate }
367*0Sstevel@tonic-gate vals = internal_ldap_get_values( ld, entry, target, lencall );
368*0Sstevel@tonic-gate if ( NULL != type )
369*0Sstevel@tonic-gate *type = nsldapi_strdup( target );
370*0Sstevel@tonic-gate return vals;
371*0Sstevel@tonic-gate } else {
372*0Sstevel@tonic-gate /* Get just the base attribute name */
373*0Sstevel@tonic-gate baseTarget = (char *)NSLDAPI_MALLOC( len + 1 );
374*0Sstevel@tonic-gate if (baseTarget == NULL) {
375*0Sstevel@tonic-gate return( NULL );
376*0Sstevel@tonic-gate }
377*0Sstevel@tonic-gate memcpy( baseTarget, target, len );
378*0Sstevel@tonic-gate baseTarget[len] = 0;
379*0Sstevel@tonic-gate }
380*0Sstevel@tonic-gate
381*0Sstevel@tonic-gate ber = *entry->lm_ber;
382*0Sstevel@tonic-gate
383*0Sstevel@tonic-gate /* Process all attributes in the entry */
384*0Sstevel@tonic-gate while ( 1 ) {
385*0Sstevel@tonic-gate int foundMatch = 0;
386*0Sstevel@tonic-gate if ( NULL != attr )
387*0Sstevel@tonic-gate NSLDAPI_FREE( attr );
388*0Sstevel@tonic-gate if ( firstAttr ) {
389*0Sstevel@tonic-gate firstAttr = 0;
390*0Sstevel@tonic-gate /* skip sequence, dn, sequence of, and snag the first attr */
391*0Sstevel@tonic-gate if ( ber_scanf( &ber, "{x{{a", &attr ) == LBER_ERROR ) {
392*0Sstevel@tonic-gate break;
393*0Sstevel@tonic-gate }
394*0Sstevel@tonic-gate } else {
395*0Sstevel@tonic-gate if ( ber_scanf( &ber, "{a", &attr ) == LBER_ERROR ) {
396*0Sstevel@tonic-gate break;
397*0Sstevel@tonic-gate }
398*0Sstevel@tonic-gate }
399*0Sstevel@tonic-gate
400*0Sstevel@tonic-gate if ( check_base_match( (const char *)baseTarget, attr ) ) {
401*0Sstevel@tonic-gate int thisMatch = check_lang_match( target, baseTarget,
402*0Sstevel@tonic-gate subtypes, nsubtypes, lang, attr );
403*0Sstevel@tonic-gate if ( thisMatch > bestMatch ) {
404*0Sstevel@tonic-gate if ( vals )
405*0Sstevel@tonic-gate NSLDAPI_FREE( vals );
406*0Sstevel@tonic-gate foundMatch = 1;
407*0Sstevel@tonic-gate bestMatch = thisMatch;
408*0Sstevel@tonic-gate if ( NULL != bestType )
409*0Sstevel@tonic-gate NSLDAPI_FREE( bestType );
410*0Sstevel@tonic-gate bestType = attr;
411*0Sstevel@tonic-gate attr = NULL;
412*0Sstevel@tonic-gate }
413*0Sstevel@tonic-gate }
414*0Sstevel@tonic-gate if ( foundMatch ) {
415*0Sstevel@tonic-gate if ( lencall ) {
416*0Sstevel@tonic-gate rc = ber_scanf( &ber, "[V]}", &vals );
417*0Sstevel@tonic-gate } else {
418*0Sstevel@tonic-gate rc = ber_scanf( &ber, "[v]}", &vals );
419*0Sstevel@tonic-gate }
420*0Sstevel@tonic-gate } else {
421*0Sstevel@tonic-gate ber_scanf( &ber, "x}" );
422*0Sstevel@tonic-gate }
423*0Sstevel@tonic-gate }
424*0Sstevel@tonic-gate
425*0Sstevel@tonic-gate NSLDAPI_FREE( lang );
426*0Sstevel@tonic-gate NSLDAPI_FREE( baseTarget );
427*0Sstevel@tonic-gate NSLDAPI_FREE( subtypes );
428*0Sstevel@tonic-gate
429*0Sstevel@tonic-gate if ( NULL != type )
430*0Sstevel@tonic-gate *type = bestType;
431*0Sstevel@tonic-gate else if ( NULL != bestType )
432*0Sstevel@tonic-gate NSLDAPI_FREE( bestType );
433*0Sstevel@tonic-gate
434*0Sstevel@tonic-gate if ( NULL == vals ) {
435*0Sstevel@tonic-gate rc = LDAP_DECODING_ERROR;
436*0Sstevel@tonic-gate } else {
437*0Sstevel@tonic-gate rc = LDAP_SUCCESS;
438*0Sstevel@tonic-gate }
439*0Sstevel@tonic-gate
440*0Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, rc, NULL, NULL );
441*0Sstevel@tonic-gate
442*0Sstevel@tonic-gate return( vals );
443*0Sstevel@tonic-gate }
444*0Sstevel@tonic-gate
445*0Sstevel@tonic-gate
446*0Sstevel@tonic-gate char **
447*0Sstevel@tonic-gate LDAP_CALL
ldap_get_values(LDAP * ld,LDAPMessage * entry,const char * target)448*0Sstevel@tonic-gate ldap_get_values( LDAP *ld, LDAPMessage *entry, const char *target )
449*0Sstevel@tonic-gate {
450*0Sstevel@tonic-gate return( (char **) internal_ldap_get_values( ld, entry, target, 0 ) );
451*0Sstevel@tonic-gate }
452*0Sstevel@tonic-gate
453*0Sstevel@tonic-gate struct berval **
454*0Sstevel@tonic-gate LDAP_CALL
ldap_get_values_len(LDAP * ld,LDAPMessage * entry,const char * target)455*0Sstevel@tonic-gate ldap_get_values_len( LDAP *ld, LDAPMessage *entry, const char *target )
456*0Sstevel@tonic-gate {
457*0Sstevel@tonic-gate return( (struct berval **) internal_ldap_get_values( ld, entry, target,
458*0Sstevel@tonic-gate 1 ) );
459*0Sstevel@tonic-gate }
460*0Sstevel@tonic-gate
461*0Sstevel@tonic-gate char **
462*0Sstevel@tonic-gate LDAP_CALL
ldap_get_lang_values(LDAP * ld,LDAPMessage * entry,const char * target,char ** type)463*0Sstevel@tonic-gate ldap_get_lang_values( LDAP *ld, LDAPMessage *entry, const char *target,
464*0Sstevel@tonic-gate char **type )
465*0Sstevel@tonic-gate {
466*0Sstevel@tonic-gate return( (char **) internal_ldap_get_lang_values( ld, entry,
467*0Sstevel@tonic-gate target, type, 0 ) );
468*0Sstevel@tonic-gate }
469*0Sstevel@tonic-gate
470*0Sstevel@tonic-gate struct berval **
471*0Sstevel@tonic-gate LDAP_CALL
ldap_get_lang_values_len(LDAP * ld,LDAPMessage * entry,const char * target,char ** type)472*0Sstevel@tonic-gate ldap_get_lang_values_len( LDAP *ld, LDAPMessage *entry, const char *target,
473*0Sstevel@tonic-gate char **type )
474*0Sstevel@tonic-gate {
475*0Sstevel@tonic-gate return( (struct berval **) internal_ldap_get_lang_values( ld, entry,
476*0Sstevel@tonic-gate target, type, 1 ) );
477*0Sstevel@tonic-gate }
478*0Sstevel@tonic-gate
479