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