1 #pragma ident "%Z%%M% %I% %E% SMI"
4 * The contents of this file are subject to the Netscape Public
5 * License Version 1.1 (the "License"); you may not use this file
6 * except in compliance with the License. You may obtain a copy of
7 * the License at http://www.mozilla.org/NPL/
9 * Software distributed under the License is distributed on an "AS
10 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11 * implied. See the License for the specific language governing
12 * rights and limitations under the License.
14 * The Original Code is Mozilla Communicator client code, released
17 * The Initial Developer of the Original Code is Netscape
18 * Communications Corporation. Portions created by Netscape are
19 * Copyright (C) 1998-1999 Netscape Communications Corporation. All
25 * Copyright (c) 1990 Regents of the University of Michigan.
26 * All rights reserved.
34 static char copyright
[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
42 internal_ldap_get_values( LDAP
*ld
, LDAPMessage
*entry
, const char *target
,
45 struct berelement ber
;
50 LDAPDebug( LDAP_DEBUG_TRACE
, "ldap_get_values\n", 0, 0, 0 );
52 if ( !NSLDAPI_VALID_LDAP_POINTER( ld
)) {
53 return( NULL
); /* punt */
55 if ( target
== NULL
||
56 !NSLDAPI_VALID_LDAPMESSAGE_ENTRY_POINTER( entry
)) {
57 LDAP_SET_LDERRNO( ld
, LDAP_PARAM_ERROR
, NULL
, NULL
);
63 /* skip sequence, dn, sequence of, and snag the first attr */
64 if ( ber_scanf( &ber
, "{x{{a", &attr
) == LBER_ERROR
) {
65 LDAP_SET_LDERRNO( ld
, LDAP_DECODING_ERROR
, NULL
, NULL
);
69 rc
= strcasecmp( (char *)target
, attr
);
73 if ( ber_scanf( &ber
, "x}{a", &attr
) == LBER_ERROR
) {
74 LDAP_SET_LDERRNO( ld
, LDAP_DECODING_ERROR
,
79 rc
= strcasecmp( (char *)target
, attr
);
89 * if we get this far, we've found the attribute and are sitting
90 * just before the set of values.
94 rc
= ber_scanf( &ber
, "[V]", &vals
);
96 rc
= ber_scanf( &ber
, "[v]", &vals
);
99 if ( rc
== LBER_ERROR
) {
100 rc
= LDAP_DECODING_ERROR
;
105 LDAP_SET_LDERRNO( ld
, rc
, NULL
, NULL
);
107 return(( rc
== LDAP_SUCCESS
) ? vals
: NULL
);
111 /* For language-sensitive attribute matching, we are looking for a
112 language tag that looks like one of the following:
120 The base language specification consists of two letters following
121 "lang-". After that, there may be additional language-specific
122 narrowings preceded by a "-". In our processing we go from the
123 specific to the general, preferring a complete subtype match, but
124 accepting a partial one. For example:
126 For a request for "cn;lang-en-us", we would return cn;lang-en-us
127 if present, otherwise cn;lang-en if present, otherwise cn.
129 Besides the language subtype, there may be other subtypes:
131 cn;lang-ja;binary (Unlikely!)
134 If not in the target, they are ignored. If they are in the target,
135 they must be in the attribute to match.
137 #define LANG_SUBTYPE_INDEX_NONE -1
138 #define LANG_SUBTYPE_INDEX_DUPLICATE -2
146 parse_subtypes( const char *target
, int *baseLenp
, char **langp
,
147 _SubStringIndex
**subs
, int *nsubtypes
)
152 _SubStringIndex
*result
= NULL
;
157 langIndex
= LANG_SUBTYPE_INDEX_NONE
;
162 targetLen
= strlen( target
);
164 /* Parse past base attribute */
165 nextToken
= strchr( target
, ';' );
166 if ( NULL
!= nextToken
) {
167 subtypeStart
= nextToken
- target
+ 1;
168 *baseLenp
= subtypeStart
- 1;
171 subtypeStart
= targetLen
;
172 *baseLenp
= subtypeStart
;
176 /* How many subtypes? */
177 nextToken
= (char *)target
+ subtypeStart
;
178 while ( nextToken
&& *nextToken
) {
179 char *thisToken
= nextToken
;
180 nextToken
= strchr( thisToken
, ';' );
181 if ( NULL
!= nextToken
)
183 if ( 0 == strncasecmp( thisToken
, "lang-", 5 ) ) {
184 /* If there was a previous lang tag, this is illegal! */
185 if ( langIndex
!= LANG_SUBTYPE_INDEX_NONE
) {
186 langIndex
= LANG_SUBTYPE_INDEX_DUPLICATE
;
190 langIndex
= nSubtypes
;
196 /* No language subtype? */
200 /* Allocate array of non-language subtypes */
201 if ( nSubtypes
> 0 ) {
202 result
= (_SubStringIndex
*)NSLDAPI_MALLOC( sizeof(*result
)
204 if (result
== NULL
) {
205 return LANG_SUBTYPE_INDEX_NONE
; /* Error */
207 memset( result
, 0, sizeof(*result
) * nSubtypes
);
212 nextToken
= (char *)target
+ subtypeStart
;
213 while ( nextToken
&& *nextToken
) {
214 char *thisToken
= nextToken
;
216 nextToken
= strchr( thisToken
, ';' );
217 if ( NULL
!= nextToken
) {
218 len
= nextToken
- thisToken
;
222 nextToken
= (char *)target
+ targetLen
;
223 len
= nextToken
- thisToken
;
225 if ( 0 == strncasecmp( thisToken
, "lang-", 5 ) ) {
227 *langp
= (char *)NSLDAPI_MALLOC( len
+ 1 );
228 if (*langp
== NULL
) {
230 NSLDAPI_FREE(result
);
231 return LANG_SUBTYPE_INDEX_NONE
; /* Error */
233 for( i
= 0; i
< len
; i
++ )
234 (*langp
)[i
] = toupper( target
[ind
+i
] );
238 result
[nSubtypes
].start
= thisToken
- target
;
239 result
[nSubtypes
].length
= len
;
244 *nsubtypes
= nSubtypes
;
250 check_lang_match( const char *target
, const char *baseTarget
,
251 _SubStringIndex
*targetTypes
,
252 int ntargetTypes
, char *targetLang
, char *attr
)
255 _SubStringIndex
*subtypes
;
263 /* Get all subtypes in the attribute name */
264 langIndex
= parse_subtypes( attr
, &baseLen
, &lang
, &subtypes
, &nsubtypes
);
266 /* Check if there any required non-language subtypes which are
267 not in this attribute */
268 for( i
= 0; i
< ntargetTypes
; i
++ ) {
269 char *t
= (char *)target
+targetTypes
[i
].start
;
270 int tlen
= targetTypes
[i
].length
;
272 for( j
= 0; j
< nsubtypes
; j
++ ) {
273 char *a
= attr
+ subtypes
[j
].start
;
274 int alen
= subtypes
[j
].length
;
275 if ( (tlen
== alen
) && !strncasecmp( t
, a
, tlen
) )
278 if ( j
>= nsubtypes
) {
284 if ( NULL
!= subtypes
)
285 NSLDAPI_FREE( subtypes
);
287 NSLDAPI_FREE( lang
);
291 /* If there was no language subtype... */
292 if ( langIndex
< 0 ) {
293 if ( NULL
!= subtypes
)
294 NSLDAPI_FREE( subtypes
);
296 NSLDAPI_FREE( lang
);
297 if ( LANG_SUBTYPE_INDEX_NONE
== langIndex
)
303 /* Okay, now check the language subtag */
305 while( targetLang
[i
] && lang
[i
] &&
306 (toupper(targetLang
[i
]) == toupper(lang
[i
])) )
309 /* The total length can't be longer than the requested subtype */
310 if ( !lang
[i
] || (lang
[i
] == ';') ) {
311 /* If the found subtype is shorter than the requested one, the next
312 character in the requested one should be "-" */
313 if ( !targetLang
[i
] || (targetLang
[i
] == '-') )
319 static int check_base_match( const char *target
, char *attr
)
323 while( target
[i
] && attr
[i
] && (toupper(target
[i
]) == toupper(attr
[i
])) )
325 rc
= ( !target
[i
] && (!attr
[i
] || (';' == attr
[i
])) );
330 internal_ldap_get_lang_values( LDAP
*ld
, LDAPMessage
*entry
,
331 const char *target
, char **type
, int lencall
)
333 struct berelement ber
;
338 _SubStringIndex
*subtypes
;
340 char *baseTarget
= NULL
;
345 char *bestType
= NULL
;
347 LDAPDebug( LDAP_DEBUG_TRACE
, "ldap_get_values\n", 0, 0, 0 );
349 if ( !NSLDAPI_VALID_LDAP_POINTER( ld
)) {
352 if ( (target
== NULL
) ||
353 !NSLDAPI_VALID_LDAPMESSAGE_ENTRY_POINTER( entry
)) {
354 LDAP_SET_LDERRNO( ld
, LDAP_PARAM_ERROR
, NULL
, NULL
);
358 /* A language check was requested, so see if there really is a
359 language subtype in the attribute spec */
360 langIndex
= parse_subtypes( target
, &len
, &lang
,
361 &subtypes
, &nsubtypes
);
362 if ( langIndex
< 0 ) {
363 if ( NULL
!= subtypes
) {
364 NSLDAPI_FREE( subtypes
);
367 vals
= internal_ldap_get_values( ld
, entry
, target
, lencall
);
369 *type
= nsldapi_strdup( target
);
372 /* Get just the base attribute name */
373 baseTarget
= (char *)NSLDAPI_MALLOC( len
+ 1 );
374 if (baseTarget
== NULL
) {
377 memcpy( baseTarget
, target
, len
);
381 ber
= *entry
->lm_ber
;
383 /* Process all attributes in the entry */
387 NSLDAPI_FREE( attr
);
390 /* skip sequence, dn, sequence of, and snag the first attr */
391 if ( ber_scanf( &ber
, "{x{{a", &attr
) == LBER_ERROR
) {
395 if ( ber_scanf( &ber
, "{a", &attr
) == LBER_ERROR
) {
400 if ( check_base_match( (const char *)baseTarget
, attr
) ) {
401 int thisMatch
= check_lang_match( target
, baseTarget
,
402 subtypes
, nsubtypes
, lang
, attr
);
403 if ( thisMatch
> bestMatch
) {
405 NSLDAPI_FREE( vals
);
407 bestMatch
= thisMatch
;
408 if ( NULL
!= bestType
)
409 NSLDAPI_FREE( bestType
);
416 rc
= ber_scanf( &ber
, "[V]}", &vals
);
418 rc
= ber_scanf( &ber
, "[v]}", &vals
);
421 ber_scanf( &ber
, "x}" );
425 NSLDAPI_FREE( lang
);
426 NSLDAPI_FREE( baseTarget
);
427 NSLDAPI_FREE( subtypes
);
431 else if ( NULL
!= bestType
)
432 NSLDAPI_FREE( bestType
);
434 if ( NULL
== vals
) {
435 rc
= LDAP_DECODING_ERROR
;
440 LDAP_SET_LDERRNO( ld
, rc
, NULL
, NULL
);
448 ldap_get_values( LDAP
*ld
, LDAPMessage
*entry
, const char *target
)
450 return( (char **) internal_ldap_get_values( ld
, entry
, target
, 0 ) );
455 ldap_get_values_len( LDAP
*ld
, LDAPMessage
*entry
, const char *target
)
457 return( (struct berval
**) internal_ldap_get_values( ld
, entry
, target
,
463 ldap_get_lang_values( LDAP
*ld
, LDAPMessage
*entry
, const char *target
,
466 return( (char **) internal_ldap_get_lang_values( ld
, entry
,
472 ldap_get_lang_values_len( LDAP
*ld
, LDAPMessage
*entry
, const char *target
,
475 return( (struct berval
**) internal_ldap_get_lang_values( ld
, entry
,