mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-04-06 15:00:40 +08:00
Initial incomplete and broken version.
This commit is contained in:
parent
59865a5d9b
commit
b2b3581bc1
71
include/ldap_schema.h
Normal file
71
include/ldap_schema.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 1999 The OpenLDAP Foundation, Redwood City, California, USA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted only
|
||||
* as authorized by the OpenLDAP Public License. A copy of this
|
||||
* license is available at http://www.OpenLDAP.org/license.html or
|
||||
* in file LICENSE in the top-level directory of the distribution.
|
||||
*/
|
||||
/*
|
||||
* ldap-schema.h - Header for basic schema handling functions that can be
|
||||
* used by both clients and servers.
|
||||
*/
|
||||
|
||||
#ifndef _LDAP_SCHEMA_H
|
||||
#define _LDAP_SCHEMA_H 1
|
||||
|
||||
#include <ldap_cdefs.h>
|
||||
|
||||
LDAP_BEGIN_DECL
|
||||
|
||||
/* Codes for parsing errors */
|
||||
|
||||
#define SCHEMA_ERR_OUTOFMEM 1
|
||||
#define SCHEMA_ERR_UNEXPTOKEN 2
|
||||
#define SCHEMA_ERR_NOLEFTPAREN 3
|
||||
#define SCHEMA_ERR_NORIGHTPAREN 4
|
||||
#define SCHEMA_ERR_NODIGIT 5
|
||||
#define SCHEMA_ERR_BADNAME 6
|
||||
#define SCHEMA_ERR_BADDESC 7
|
||||
#define SCHEMA_ERR_BADSUP 8
|
||||
#define SCHEMA_ERR_DUPOPT 9
|
||||
|
||||
typedef struct ldap_attributetype {
|
||||
char *at_oid; /* REQUIRED */
|
||||
char **at_names; /* OPTIONAL */
|
||||
char *at_desc; /* OPTIONAL */
|
||||
int at_obsolete; /* 0=no, 1=yes */
|
||||
char *at_sup_oid; /* OPTIONAL */
|
||||
char *at_equality_oid; /* OPTIONAL */
|
||||
char *at_ordering_oid; /* OPTIONAL */
|
||||
char *at_substr_oid; /* OPTIONAL */
|
||||
char *at_syntax_oid; /* OPTIONAL */
|
||||
int at_syntax_len; /* OPTIONAL */
|
||||
int at_single_value; /* 0=no, 1=yes */
|
||||
int at_collective; /* 0=no, 1=yes */
|
||||
int at_no_user_mod; /* 0=no, 1=yes */
|
||||
int at_usage; /* 0=userApplications, 1=directoryOperation,
|
||||
2=distributedOperation, 3=dSAOperation */
|
||||
} LDAP_ATTRIBUTE_TYPE;
|
||||
|
||||
typedef struct ldap_objectclass {
|
||||
char *oc_oid; /* REQUIRED */
|
||||
char **oc_names; /* OPTIONAL */
|
||||
char *oc_desc; /* OPTIONAL */
|
||||
int oc_obsolete; /* 0=no, 1=yes */
|
||||
char **oc_sup_oids; /* OPTIONAL */
|
||||
int oc_kind; /* 0=ABSTRACT, 1=STRUCTURAL, 2=AUXILIARY */
|
||||
char **oc_at_oids_must; /* OPTIONAL */
|
||||
char **oc_at_oids_may; /* MAY */
|
||||
} LDAP_OBJECT_CLASS;
|
||||
|
||||
LDAP_F(LDAP_OBJECT_CLASS *) ldap_str2objectclass LDAP_P(( char * s, int * code, char ** errp ));
|
||||
LDAP_F(LDAP_ATTRIBUTE_TYPE) ldap_str2attributetype LDAP_P(( char * sval, char ** errp ));
|
||||
LDAP_F( char *) ldap_objectclass2str LDAP_P(( LDAP_OBJECT_CLASS * oc ));
|
||||
LDAP_F( char *) ldap_attributetype2str LDAP_P(( LDAP_ATTRIBUTE_TYPE * at ));
|
||||
|
||||
LDAP_END_DECL
|
||||
|
||||
#endif
|
||||
|
914
libraries/libldap/schema.c
Normal file
914
libraries/libldap/schema.c
Normal file
@ -0,0 +1,914 @@
|
||||
/*
|
||||
* Copyright 1999 The OpenLDAP Foundation, All Rights Reserved.
|
||||
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
|
||||
*
|
||||
* schema.c: parsing routines used by servers and clients to process
|
||||
* schema definitions
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <ac/ctype.h>
|
||||
#include <ac/string.h>
|
||||
#ifdef HAVE_MALLOC_H
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#include <lber.h>
|
||||
#include <ldap.h>
|
||||
#include <ldap_schema.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* When pretty printing the entities we will be appending to a buffer.
|
||||
* Since checking for overflow, realloc'ing and checking if no error
|
||||
* is extremely boring, we will use a pretection layer that will let
|
||||
* us blissfully ignore the error until the end. This layer is
|
||||
* implemented with the help of the next type.
|
||||
*/
|
||||
|
||||
typedef struct safe_string {
|
||||
char * val;
|
||||
int size;
|
||||
int pos;
|
||||
int at_whsp;
|
||||
} safe_string;
|
||||
|
||||
static safe_string *
|
||||
new_safe_string(int size)
|
||||
{
|
||||
safe_string * ss;
|
||||
|
||||
ss = malloc(sizeof(safe_string));
|
||||
if ( !ss )
|
||||
return(NULL);
|
||||
ss->size = size;
|
||||
ss->pos = 0;
|
||||
ss->val = malloc(size);
|
||||
ss->at_whsp = 0;
|
||||
if ( !ss->val ) {
|
||||
free(ss);
|
||||
return(NULL);
|
||||
}
|
||||
return ss;
|
||||
}
|
||||
|
||||
void
|
||||
safe_string_free(safe_string * ss)
|
||||
{
|
||||
if ( !ss )
|
||||
return;
|
||||
ldap_memfree(ss->val);
|
||||
ldap_memfree(ss);
|
||||
}
|
||||
|
||||
static char *
|
||||
safe_string_val(safe_string * ss)
|
||||
{
|
||||
return(ss->val);
|
||||
}
|
||||
|
||||
static int
|
||||
append_to_safe_string(safe_string * ss, char * s)
|
||||
{
|
||||
int l = strlen(s);
|
||||
char * temp;
|
||||
|
||||
/*
|
||||
* Some runaway process is trying to append to a string that
|
||||
* overflowed and we could not extend.
|
||||
*/
|
||||
if ( !ss->val )
|
||||
return -1;
|
||||
|
||||
/* We always make sure there is at least one position available */
|
||||
if ( ss->pos + l >= ss->size-1 ) {
|
||||
ss->size *= 2;
|
||||
temp = realloc(ss->val, ss->size);
|
||||
if ( !temp ) {
|
||||
/* Trouble, out of memory */
|
||||
free(ss->val);
|
||||
return -1;
|
||||
}
|
||||
ss->val = temp;
|
||||
}
|
||||
strncpy(&ss->val[ss->pos], s, l);
|
||||
ss->pos += l;
|
||||
if ( ss->pos > 0 && ss->val[ss->pos-1] == ' ' )
|
||||
ss->at_whsp = 1;
|
||||
else
|
||||
ss->at_whsp = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
print_literal(safe_string *ss, char *s)
|
||||
{
|
||||
return(append_to_safe_string(ss,s));
|
||||
}
|
||||
|
||||
static int
|
||||
print_whsp(safe_string *ss)
|
||||
{
|
||||
if ( ss->at_whsp )
|
||||
return(append_to_safe_string(ss,""));
|
||||
else
|
||||
return(append_to_safe_string(ss," "));
|
||||
}
|
||||
|
||||
static int
|
||||
print_numericoid(safe_string *ss, char *s)
|
||||
{
|
||||
return(append_to_safe_string(ss,s));
|
||||
}
|
||||
|
||||
/* This one is identical to print_qdescr */
|
||||
static int
|
||||
print_qdstring(safe_string *ss, char *s)
|
||||
{
|
||||
print_whsp(ss);
|
||||
print_literal(ss,"'");
|
||||
append_to_safe_string(ss,s);
|
||||
print_literal(ss,"'");
|
||||
return(print_whsp(ss));
|
||||
}
|
||||
|
||||
static int
|
||||
print_qdescr(safe_string *ss, char *s)
|
||||
{
|
||||
print_whsp(ss);
|
||||
print_literal(ss,"'");
|
||||
append_to_safe_string(ss,s);
|
||||
print_literal(ss,"'");
|
||||
return(print_whsp(ss));
|
||||
}
|
||||
|
||||
static int
|
||||
print_qdescrlist(safe_string *ss, char **sa)
|
||||
{
|
||||
char **sp;
|
||||
int ret = 0;
|
||||
|
||||
for (sp=sa; *sp; sp++) {
|
||||
ret = print_qdescr(ss,*sp);
|
||||
}
|
||||
/* If the list was empty, we return zero that is potentially
|
||||
* incorrect, but since we will still appending things, the
|
||||
* overflow will be detected later. Maybe FIX.
|
||||
*/
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static int
|
||||
print_qdescrs(safe_string *ss, char **sa)
|
||||
{
|
||||
/* The only way to represent an empty list is as a qdescrlist
|
||||
* so, if the list is empty we treat it as a long list.
|
||||
* Really, this is what the syntax mandates.
|
||||
*/
|
||||
if ( !sa[0] || ( sa[0] && sa[1] ) ) {
|
||||
print_whsp(ss);
|
||||
print_literal(ss,"(");
|
||||
print_qdescrlist(ss,sa);
|
||||
print_literal(ss,")");
|
||||
return(print_whsp(ss));
|
||||
} else {
|
||||
return(print_qdescr(ss,*sa));
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
print_woid(safe_string *ss, char *s)
|
||||
{
|
||||
print_whsp(ss);
|
||||
append_to_safe_string(ss,s);
|
||||
return print_whsp(ss);
|
||||
}
|
||||
|
||||
static int
|
||||
print_oidlist(safe_string *ss, char **sa)
|
||||
{
|
||||
char **sp;
|
||||
|
||||
for (sp=sa; *(sp+1); sp++) {
|
||||
print_woid(ss,*sp);
|
||||
print_literal(ss,"$");
|
||||
}
|
||||
return(print_woid(ss,*sp));
|
||||
}
|
||||
|
||||
static int
|
||||
print_oids(safe_string *ss, char **sa)
|
||||
{
|
||||
if ( sa[0] && sa[1] ) {
|
||||
print_literal(ss,"(");
|
||||
print_oidlist(ss,sa);
|
||||
print_whsp(ss);
|
||||
return(print_literal(ss,")"));
|
||||
} else {
|
||||
return(print_woid(ss,*sa));
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
print_noidlen(safe_string *ss, char *s, int l)
|
||||
{
|
||||
char buf[64];
|
||||
int ret;
|
||||
|
||||
ret = print_numericoid(ss,s);
|
||||
if ( l ) {
|
||||
sprintf(buf,"{%d}",l);
|
||||
ret = print_literal(ss,buf);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
char *
|
||||
ldap_objectclass2str( LDAP_OBJECT_CLASS * oc )
|
||||
{
|
||||
safe_string * ss;
|
||||
char * retstring;
|
||||
|
||||
ss = new_safe_string(256);
|
||||
if ( !ss )
|
||||
return NULL;
|
||||
|
||||
print_literal(ss,"(");
|
||||
print_whsp(ss);
|
||||
|
||||
print_numericoid(ss, oc->oc_oid);
|
||||
print_whsp(ss);
|
||||
|
||||
if ( oc->oc_names ) {
|
||||
print_literal(ss,"NAME");
|
||||
print_qdescrs(ss,oc->oc_names);
|
||||
}
|
||||
|
||||
if ( oc->oc_desc ) {
|
||||
print_literal(ss,"DESC");
|
||||
print_qdstring(ss,oc->oc_desc);
|
||||
}
|
||||
|
||||
if ( oc->oc_obsolete ) {
|
||||
print_literal(ss, "OBSOLETE");
|
||||
print_whsp(ss);
|
||||
}
|
||||
|
||||
if ( oc->oc_sup_oids ) {
|
||||
print_literal(ss,"SUP");
|
||||
print_oids(ss,oc->oc_sup_oids);
|
||||
}
|
||||
|
||||
switch (oc->oc_kind) {
|
||||
case 0:
|
||||
print_literal(ss,"ABSTRACT");
|
||||
break;
|
||||
case 1:
|
||||
print_literal(ss,"STRUCTURAL");
|
||||
break;
|
||||
case 2:
|
||||
print_literal(ss,"AUXILIARY");
|
||||
break;
|
||||
default:
|
||||
print_literal(ss,"KIND-UNKNOWN");
|
||||
break;
|
||||
}
|
||||
print_whsp(ss);
|
||||
|
||||
if ( oc->oc_at_oids_must ) {
|
||||
print_literal(ss,"MUST");
|
||||
print_whsp(ss);
|
||||
print_oids(ss,oc->oc_at_oids_must);
|
||||
print_whsp(ss);
|
||||
}
|
||||
|
||||
if ( oc->oc_at_oids_may ) {
|
||||
print_literal(ss,"MAY");
|
||||
print_whsp(ss);
|
||||
print_oids(ss,oc->oc_at_oids_may);
|
||||
print_whsp(ss);
|
||||
}
|
||||
|
||||
print_whsp(ss);
|
||||
print_literal(ss,")");
|
||||
|
||||
retstring = safe_string_val(ss);
|
||||
safe_string_free(ss);
|
||||
return(retstring);
|
||||
}
|
||||
|
||||
char *
|
||||
ldap_attributetype2str( LDAP_ATTRIBUTE_TYPE * at )
|
||||
{
|
||||
safe_string * ss;
|
||||
char * retstring;
|
||||
|
||||
ss = new_safe_string(256);
|
||||
if ( !ss )
|
||||
return NULL;
|
||||
|
||||
print_literal(ss,"(");
|
||||
print_whsp(ss);
|
||||
|
||||
print_numericoid(ss, at->at_oid);
|
||||
print_whsp(ss);
|
||||
|
||||
if ( at->at_names ) {
|
||||
print_literal(ss,"NAME");
|
||||
print_qdescrs(ss,at->at_names);
|
||||
}
|
||||
|
||||
if ( at->at_desc ) {
|
||||
print_literal(ss,"DESC");
|
||||
print_qdstring(ss,at->at_desc);
|
||||
}
|
||||
|
||||
if ( at->at_obsolete ) {
|
||||
print_literal(ss, "OBSOLETE");
|
||||
print_whsp(ss);
|
||||
}
|
||||
|
||||
if ( at->at_sup_oid ) {
|
||||
print_literal(ss,"SUP");
|
||||
print_woid(ss,at->at_sup_oid);
|
||||
}
|
||||
|
||||
if ( at->at_equality_oid ) {
|
||||
print_literal(ss,"EQUALITY");
|
||||
print_woid(ss,at->at_equality_oid);
|
||||
}
|
||||
|
||||
if ( at->at_ordering_oid ) {
|
||||
print_literal(ss,"ORDERING");
|
||||
print_woid(ss,at->at_ordering_oid);
|
||||
}
|
||||
|
||||
if ( at->at_substr_oid ) {
|
||||
print_literal(ss,"SUBSTR");
|
||||
print_woid(ss,at->at_substr_oid);
|
||||
}
|
||||
|
||||
if ( at->at_syntax_oid ) {
|
||||
print_literal(ss,"SYNTAX");
|
||||
print_noidlen(ss,at->at_syntax_oid,at->at_syntax_len);
|
||||
}
|
||||
|
||||
if ( at->at_single_value ) {
|
||||
print_literal(ss,"SINGLE-VALUE");
|
||||
print_whsp(ss);
|
||||
}
|
||||
|
||||
if ( at->at_collective ) {
|
||||
print_literal(ss,"COLLECTIVE");
|
||||
print_whsp(ss);
|
||||
}
|
||||
|
||||
if ( at->at_no_user_mod ) {
|
||||
print_literal(ss,"NO-USER-MODIFICATION");
|
||||
print_whsp(ss);
|
||||
}
|
||||
|
||||
if ( at->at_usage ) {
|
||||
print_literal(ss,"USAGE");
|
||||
print_whsp(ss);
|
||||
switch (at->at_usage) {
|
||||
case 1:
|
||||
print_literal(ss,"directoryOperation");
|
||||
break;
|
||||
case 2:
|
||||
print_literal(ss,"distributedOperation");
|
||||
break;
|
||||
case 3:
|
||||
print_literal(ss,"dSAOperation");
|
||||
break;
|
||||
default:
|
||||
print_literal(ss,"UNKNOWN");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
print_whsp(ss);
|
||||
print_literal(ss,")");
|
||||
|
||||
retstring = safe_string_val(ss);
|
||||
safe_string_free(ss);
|
||||
return(retstring);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is ripped from servers/slapd/charray.c that should be promoted
|
||||
* to -lldap or something so that it is used everywhere.
|
||||
*/
|
||||
static void
|
||||
charray_free( char **array )
|
||||
{
|
||||
char **a;
|
||||
|
||||
if ( array == NULL ) {
|
||||
return;
|
||||
}
|
||||
|
||||
for ( a = array; *a != NULL; a++ ) {
|
||||
if ( *a != NULL ) {
|
||||
free( *a );
|
||||
}
|
||||
}
|
||||
free( (char *) array );
|
||||
}
|
||||
|
||||
#define TK_NOENDQUOTE -2
|
||||
#define TK_OUTOFMEM -1
|
||||
#define TK_EOS 0
|
||||
#define TK_UNEXPCHAR 1
|
||||
#define TK_BAREWORD 2
|
||||
#define TK_QDSTRING 3
|
||||
#define TK_LEFTPAREN 4
|
||||
#define TK_RIGHTPAREN 5
|
||||
#define TK_DOLLAR 6
|
||||
#define TK_QDESCR TK_QDSTRING
|
||||
|
||||
struct token {
|
||||
int type;
|
||||
char *sval;
|
||||
};
|
||||
|
||||
static int
|
||||
get_token(char ** sp, char ** token_val)
|
||||
{
|
||||
int kind;
|
||||
char * p;
|
||||
char * q;
|
||||
char * res;
|
||||
|
||||
switch (**sp) {
|
||||
case '\0':
|
||||
kind = TK_EOS;
|
||||
(*sp)++;
|
||||
break;
|
||||
case '(':
|
||||
kind = TK_LEFTPAREN;
|
||||
(*sp)++;
|
||||
break;
|
||||
case ')':
|
||||
kind = TK_RIGHTPAREN;
|
||||
(*sp)++;
|
||||
break;
|
||||
case '$':
|
||||
kind = TK_DOLLAR;
|
||||
(*sp)++;
|
||||
break;
|
||||
case '\'':
|
||||
kind = TK_QDSTRING;
|
||||
(*sp)++;
|
||||
p = *sp;
|
||||
while ( **sp != '\'' && **sp != '\0' )
|
||||
(*sp)++;
|
||||
if ( **sp == '\'' ) {
|
||||
q = *sp;
|
||||
res = malloc(q-p+1);
|
||||
if ( !res ) {
|
||||
kind = TK_OUTOFMEM;
|
||||
} else {
|
||||
strncpy(res,p,q-p);
|
||||
res[q-p] = '\0';
|
||||
*token_val = res;
|
||||
}
|
||||
(*sp)++;
|
||||
} else {
|
||||
kind = TK_NOENDQUOTE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
kind = TK_BAREWORD;
|
||||
p = *sp;
|
||||
while ( !isspace(**sp) && **sp != '\0' )
|
||||
(*sp)++;
|
||||
q = *sp;
|
||||
res = malloc(q-p+1);
|
||||
if ( !res ) {
|
||||
kind = TK_OUTOFMEM;
|
||||
} else {
|
||||
strncpy(res,p,q-p);
|
||||
res[q-p] = '\0';
|
||||
*token_val = res;
|
||||
}
|
||||
break;
|
||||
/* kind = TK_UNEXPCHAR; */
|
||||
/* break; */
|
||||
}
|
||||
|
||||
return kind;
|
||||
}
|
||||
|
||||
/* Gobble optional whitespace */
|
||||
static void
|
||||
parse_whsp(char **sp)
|
||||
{
|
||||
while (isspace(**sp))
|
||||
(*sp)++;
|
||||
}
|
||||
|
||||
/* TBC:!!
|
||||
* General note for all parsers: to guarantee the algorithm halts they
|
||||
* must always advance the pointer even when an error is found. For
|
||||
* this one is not that important since an error here is fatal at the
|
||||
* upper layers, but it is a simple strategy that will not get in
|
||||
* endless loops.
|
||||
*/
|
||||
|
||||
/* Parse a sequence of dot-separated decimal strings */
|
||||
static char *
|
||||
parse_numericoid(char **sp, int *code)
|
||||
{
|
||||
char * res;
|
||||
char * start = *sp;
|
||||
int len;
|
||||
|
||||
/* Each iteration of this loops gets one decimal string */
|
||||
while (**sp) {
|
||||
if ( !isdigit(**sp) ) {
|
||||
/* Initial char is not a digit or char after dot is not a digit */
|
||||
*code = SCHEMA_ERR_NODIGIT;
|
||||
return NULL;
|
||||
}
|
||||
(*sp)++;
|
||||
while ( isdigit(**sp) )
|
||||
(*sp)++;
|
||||
if ( **sp != '.' )
|
||||
break;
|
||||
/* Otherwise, gobble the dot and loop again */
|
||||
(*sp)++;
|
||||
}
|
||||
/* At this point, *sp points at the char past the numericoid. Perfect. */
|
||||
len = *sp - start;
|
||||
res = malloc(len+1);
|
||||
if (!res) {
|
||||
*code = SCHEMA_ERR_OUTOFMEM;
|
||||
return(NULL);
|
||||
}
|
||||
strncpy(res,start,len);
|
||||
res[len] = '\0';
|
||||
return(res);
|
||||
}
|
||||
|
||||
/* Parse a qdescr or a list of them enclosed in () */
|
||||
static char **
|
||||
parse_qdescrs(char **sp, int *code)
|
||||
{
|
||||
char ** res;
|
||||
char ** res1;
|
||||
int kind;
|
||||
char * sval;
|
||||
int size;
|
||||
int pos;
|
||||
|
||||
parse_whsp(sp);
|
||||
kind = get_token(sp,&sval);
|
||||
if ( kind == TK_LEFTPAREN ) {
|
||||
/* Let's presume there will be at least 2 entries */
|
||||
size = 3;
|
||||
res = calloc(3,sizeof(char *));
|
||||
if ( !res ) {
|
||||
*code = SCHEMA_ERR_OUTOFMEM;
|
||||
return NULL;
|
||||
}
|
||||
pos = 0;
|
||||
while (1) {
|
||||
parse_whsp(sp);
|
||||
kind = get_token(sp,&sval);
|
||||
if ( kind == TK_RIGHTPAREN )
|
||||
break;
|
||||
if ( kind == TK_QDESCR ) {
|
||||
if ( pos == size-2 ) {
|
||||
size++;
|
||||
res1 = realloc(res,size*sizeof(char *));
|
||||
if ( !res1 ) {
|
||||
charray_free(res);
|
||||
*code = SCHEMA_ERR_OUTOFMEM;
|
||||
return(NULL);
|
||||
}
|
||||
res = res1;
|
||||
}
|
||||
res[pos] = sval;
|
||||
pos++;
|
||||
parse_whsp(sp);
|
||||
} else {
|
||||
charray_free(res);
|
||||
*code = SCHEMA_ERR_UNEXPTOKEN;
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
res[pos] = NULL;
|
||||
parse_whsp(sp);
|
||||
return(res);
|
||||
} else if ( kind == TK_QDESCR ) {
|
||||
res = calloc(2,sizeof(char *));
|
||||
if ( !res ) {
|
||||
*code = SCHEMA_ERR_OUTOFMEM;
|
||||
return NULL;
|
||||
}
|
||||
res[0] = sval;
|
||||
res[1] = NULL;
|
||||
parse_whsp(sp);
|
||||
return res;
|
||||
} else {
|
||||
*code = SCHEMA_ERR_BADNAME;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse a woid or a $-separated list of them enclosed in () */
|
||||
static char **
|
||||
parse_oids(char **sp, int *code)
|
||||
{
|
||||
char ** res;
|
||||
char ** res1;
|
||||
int kind;
|
||||
char * sval;
|
||||
int size;
|
||||
int pos;
|
||||
|
||||
/*
|
||||
* Strictly speaking, doing this here accepts whsp before the
|
||||
* ( at the begining of an oidlist, but his is harmless. Also,
|
||||
* we are very liberal in what we accept as an OID. Maybe
|
||||
* refine later.
|
||||
*/
|
||||
parse_whsp(sp);
|
||||
kind = get_token(sp,&sval);
|
||||
if ( kind == TK_LEFTPAREN ) {
|
||||
/* Let's presume there will be at least 2 entries */
|
||||
size = 3;
|
||||
res = calloc(3,sizeof(char *));
|
||||
if ( !res ) {
|
||||
*code = SCHEMA_ERR_OUTOFMEM;
|
||||
return NULL;
|
||||
}
|
||||
pos = 0;
|
||||
parse_whsp(sp);
|
||||
kind = get_token(sp,&sval);
|
||||
if ( kind == TK_BAREWORD ) {
|
||||
res[pos] = sval;
|
||||
pos++;
|
||||
} else {
|
||||
*code = SCHEMA_ERR_UNEXPTOKEN;
|
||||
charray_free(res);
|
||||
return NULL;
|
||||
}
|
||||
parse_whsp(sp);
|
||||
while (1) {
|
||||
kind = get_token(sp,&sval);
|
||||
if ( kind == TK_RIGHTPAREN )
|
||||
break;
|
||||
if ( kind == TK_DOLLAR ) {
|
||||
parse_whsp(sp);
|
||||
kind = get_token(sp,&sval);
|
||||
if ( kind == TK_BAREWORD ) {
|
||||
if ( pos == size-2 ) {
|
||||
size++;
|
||||
res1 = realloc(res,size*sizeof(char *));
|
||||
if ( !res1 ) {
|
||||
charray_free(res);
|
||||
*code = SCHEMA_ERR_OUTOFMEM;
|
||||
return(NULL);
|
||||
}
|
||||
res = res1;
|
||||
}
|
||||
res[pos] = sval;
|
||||
pos++;
|
||||
} else {
|
||||
*code = SCHEMA_ERR_UNEXPTOKEN;
|
||||
charray_free(res);
|
||||
return NULL;
|
||||
}
|
||||
parse_whsp(sp);
|
||||
} else {
|
||||
*code = SCHEMA_ERR_UNEXPTOKEN;
|
||||
charray_free(res);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
res[pos] = NULL;
|
||||
parse_whsp(sp);
|
||||
return(res);
|
||||
} else if ( kind == TK_BAREWORD ) {
|
||||
res = calloc(2,sizeof(char *));
|
||||
if ( !res ) {
|
||||
*code = SCHEMA_ERR_OUTOFMEM;
|
||||
return NULL;
|
||||
}
|
||||
res[0] = sval;
|
||||
res[1] = NULL;
|
||||
parse_whsp(sp);
|
||||
return res;
|
||||
} else {
|
||||
*code = SCHEMA_ERR_BADNAME;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
free_oc(LDAP_OBJECT_CLASS * oc)
|
||||
{
|
||||
ldap_memfree(oc->oc_oid);
|
||||
charray_free(oc->oc_names);
|
||||
ldap_memfree(oc->oc_desc);
|
||||
charray_free(oc->oc_sup_oids);
|
||||
charray_free(oc->oc_at_oids_must);
|
||||
charray_free(oc->oc_at_oids_may);
|
||||
ldap_memfree(oc);
|
||||
}
|
||||
|
||||
LDAP_OBJECT_CLASS *
|
||||
ldap_str2objectclass( char * s, int * code, char ** errp )
|
||||
{
|
||||
int kind;
|
||||
char * ss = s;
|
||||
char * sval;
|
||||
int seen_name = 0;
|
||||
int seen_desc = 0;
|
||||
int seen_obsolete = 0;
|
||||
int seen_sup = 0;
|
||||
int seen_kind = 0;
|
||||
int seen_must = 0;
|
||||
int seen_may = 0;
|
||||
LDAP_OBJECT_CLASS * oc;
|
||||
|
||||
*errp = s;
|
||||
oc = calloc(1,sizeof(LDAP_OBJECT_CLASS));
|
||||
|
||||
if ( !oc ) {
|
||||
*code = SCHEMA_ERR_OUTOFMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
kind = get_token(&ss,&sval);
|
||||
if ( kind != TK_LEFTPAREN ) {
|
||||
*code = SCHEMA_ERR_NOLEFTPAREN;
|
||||
free_oc(oc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
parse_whsp(&ss);
|
||||
oc->oc_oid = parse_numericoid(&ss,code);
|
||||
if ( !oc->oc_oid ) {
|
||||
*errp = ss;
|
||||
free_oc(oc);
|
||||
return NULL;
|
||||
}
|
||||
parse_whsp(&ss);
|
||||
|
||||
/*
|
||||
* Beyond this point we will be liberal an accept the items
|
||||
* in any order.
|
||||
*/
|
||||
while (1) {
|
||||
kind = get_token(&ss,&sval);
|
||||
switch (kind) {
|
||||
case TK_EOS:
|
||||
*code = SCHEMA_ERR_NORIGHTPAREN;
|
||||
*errp = ss;
|
||||
free_oc(oc);
|
||||
return NULL;
|
||||
case TK_RIGHTPAREN:
|
||||
return oc;
|
||||
case TK_BAREWORD:
|
||||
if ( !strcmp(sval,"NAME") ) {
|
||||
if ( seen_name ) {
|
||||
*code = SCHEMA_ERR_DUPOPT;
|
||||
*errp = ss;
|
||||
free_oc(oc);
|
||||
return(NULL);
|
||||
}
|
||||
seen_name = 1;
|
||||
oc->oc_names = parse_qdescrs(&ss,code);
|
||||
if ( !oc->oc_names ) {
|
||||
if ( *code != SCHEMA_ERR_OUTOFMEM )
|
||||
*code = SCHEMA_ERR_BADNAME;
|
||||
*errp = ss;
|
||||
free_oc(oc);
|
||||
return NULL;
|
||||
}
|
||||
} else if ( !strcmp(sval,"DESC") ) {
|
||||
if ( seen_desc ) {
|
||||
*code = SCHEMA_ERR_DUPOPT;
|
||||
*errp = ss;
|
||||
free_oc(oc);
|
||||
return(NULL);
|
||||
}
|
||||
seen_desc = 1;
|
||||
parse_whsp(&ss);
|
||||
kind = get_token(&ss,&sval);
|
||||
if ( kind != TK_QDSTRING ) {
|
||||
*code = SCHEMA_ERR_UNEXPTOKEN;
|
||||
*errp = ss;
|
||||
free(oc);
|
||||
return NULL;
|
||||
}
|
||||
oc->oc_desc = sval;
|
||||
parse_whsp(&ss);
|
||||
} else if ( !strcmp(sval,"OBSOLETE") ) {
|
||||
if ( seen_obsolete ) {
|
||||
*code = SCHEMA_ERR_DUPOPT;
|
||||
*errp = ss;
|
||||
free_oc(oc);
|
||||
return(NULL);
|
||||
}
|
||||
seen_obsolete = 1;
|
||||
oc->oc_obsolete = 1;
|
||||
parse_whsp(&ss);
|
||||
} else if ( !strcmp(sval,"SUP") ) {
|
||||
if ( seen_sup ) {
|
||||
*code = SCHEMA_ERR_DUPOPT;
|
||||
*errp = ss;
|
||||
free_oc(oc);
|
||||
return(NULL);
|
||||
}
|
||||
seen_sup = 1;
|
||||
/* Netscape DS is broken or I have not
|
||||
understood the syntax. */
|
||||
/* oc->oc_sup_oids = parse_oids(&ss,code); */
|
||||
oc->oc_sup_oids = parse_qdescrs(&ss,code);
|
||||
if ( !oc->oc_sup_oids ) {
|
||||
*errp = ss;
|
||||
free_oc(oc);
|
||||
return NULL;
|
||||
}
|
||||
} else if ( !strcmp(sval,"ABSTRACT") ) {
|
||||
if ( seen_kind ) {
|
||||
*code = SCHEMA_ERR_DUPOPT;
|
||||
*errp = ss;
|
||||
free_oc(oc);
|
||||
return(NULL);
|
||||
}
|
||||
seen_kind = 1;
|
||||
oc->oc_kind = 0;
|
||||
parse_whsp(&ss);
|
||||
} else if ( !strcmp(sval,"STRUCTURAL") ) {
|
||||
if ( seen_kind ) {
|
||||
*code = SCHEMA_ERR_DUPOPT;
|
||||
*errp = ss;
|
||||
free_oc(oc);
|
||||
return(NULL);
|
||||
}
|
||||
seen_kind = 1;
|
||||
oc->oc_kind = 1;
|
||||
parse_whsp(&ss);
|
||||
} else if ( !strcmp(sval,"AUXILIARY") ) {
|
||||
if ( seen_kind ) {
|
||||
*code = SCHEMA_ERR_DUPOPT;
|
||||
*errp = ss;
|
||||
free_oc(oc);
|
||||
return(NULL);
|
||||
}
|
||||
seen_kind = 1;
|
||||
oc->oc_kind = 2;
|
||||
parse_whsp(&ss);
|
||||
} else if ( !strcmp(sval,"MUST") ) {
|
||||
if ( seen_must ) {
|
||||
*code = SCHEMA_ERR_DUPOPT;
|
||||
*errp = ss;
|
||||
free_oc(oc);
|
||||
return(NULL);
|
||||
}
|
||||
seen_must = 1;
|
||||
oc->oc_at_oids_must = parse_oids(&ss,code);
|
||||
if ( !oc->oc_at_oids_must ) {
|
||||
*errp = ss;
|
||||
free_oc(oc);
|
||||
return NULL;
|
||||
}
|
||||
parse_whsp(&ss);
|
||||
} else if ( !strcmp(sval,"MAY") ) {
|
||||
if ( seen_may ) {
|
||||
*code = SCHEMA_ERR_DUPOPT;
|
||||
*errp = ss;
|
||||
free_oc(oc);
|
||||
return(NULL);
|
||||
}
|
||||
seen_may = 1;
|
||||
oc->oc_at_oids_may = parse_oids(&ss,code);
|
||||
if ( !oc->oc_at_oids_may ) {
|
||||
*errp = ss;
|
||||
free_oc(oc);
|
||||
return NULL;
|
||||
}
|
||||
parse_whsp(&ss);
|
||||
} else {
|
||||
*code = SCHEMA_ERR_UNEXPTOKEN;
|
||||
*errp = ss;
|
||||
free_oc(oc);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
*code = SCHEMA_ERR_UNEXPTOKEN;
|
||||
*errp = ss;
|
||||
free_oc(oc);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user