| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687 |
- /** BEGIN COPYRIGHT BLOCK
- * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
- * Copyright (C) 2005 Red Hat, Inc.
- * All rights reserved.
- *
- * License: GPL (version 3 or any later version).
- * See LICENSE for details.
- * END COPYRIGHT BLOCK **/
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- /* attrsyntax.c */
- #include "slap.h"
- #include <plhash.h>
- /*
- * Note: if both the oid2asi and name2asi locks are acquired at the
- * same time, the old2asi one should be acquired first,
- */
- /*
- * This hashtable maps the oid to the struct asyntaxinfo for that oid.
- */
- static PLHashTable *oid2asi = NULL;
- /* read/write lock to protect table */
- static Slapi_RWLock *oid2asi_lock = NULL;
- static PLHashTable *internalasi = NULL;
- /* global attribute linked list */
- static asyntaxinfo *global_at = NULL;
- /*
- * This hashtable maps the name or alias of the attribute to the
- * syntax info structure for that attribute. An attribute type has as
- * many entries in the name2asi table as it has names and aliases, but
- * all entries point to the same struct asyntaxinfo.
- */
- static PLHashTable *name2asi = NULL;
- /* read/write lock to protect table */
- static Slapi_RWLock *name2asi_lock = NULL;
- /*
- * For the schema reload task, we need to use separate temporary hashtables & linked lists
- */
- static PLHashTable *oid2asi_tmp = NULL;
- static PLHashTable *name2asi_tmp = NULL;
- static asyntaxinfo *global_at_tmp = NULL;
- static int asi_locking = 1;
- #define AS_LOCK_READ(l) if (asi_locking) { slapi_rwlock_rdlock(l); }
- #define AS_LOCK_WRITE(l) if (asi_locking) { slapi_rwlock_wrlock(l); }
- #define AS_UNLOCK_READ(l) if (asi_locking) { slapi_rwlock_unlock(l); }
- #define AS_UNLOCK_WRITE(l) if (asi_locking) { slapi_rwlock_unlock(l); }
- static struct asyntaxinfo *default_asi = NULL;
- static void *attr_syntax_get_plugin_by_name_with_default( const char *type );
- static void attr_syntax_delete_no_lock( struct asyntaxinfo *asip,
- PRBool remove_from_oid_table, PRUint32 schema_flags );
- static struct asyntaxinfo *attr_syntax_get_by_oid_locking_optional( const
- char *oid, PRBool use_lock, PRUint32 schema_flags);
- static void attr_syntax_insert( struct asyntaxinfo *asip );
- static void attr_syntax_insert_tmp( struct asyntaxinfo *asip );
- static void attr_syntax_remove( struct asyntaxinfo *asip );
- #ifdef ATTR_LDAP_DEBUG
- static void attr_syntax_print();
- #endif
- static int attr_syntax_init(void);
- struct asyntaxinfo *
- attr_syntax_get_global_at()
- {
- return global_at;
- }
- void
- attr_syntax_read_lock(void)
- {
- if (0 != attr_syntax_init()) return;
- AS_LOCK_READ(oid2asi_lock);
- AS_LOCK_READ(name2asi_lock);
- }
- void
- attr_syntax_write_lock(void)
- {
- if (0 != attr_syntax_init()) return;
- AS_LOCK_WRITE(oid2asi_lock);
- AS_LOCK_WRITE(name2asi_lock);
- }
- void
- attr_syntax_unlock_read(void)
- {
- AS_UNLOCK_READ(name2asi_lock);
- AS_UNLOCK_READ(oid2asi_lock);
- }
- void
- attr_syntax_unlock_write(void)
- {
- AS_UNLOCK_WRITE(name2asi_lock);
- AS_UNLOCK_WRITE(oid2asi_lock);
- }
- #if 0
- static int
- check_oid( const char *oid ) {
- int i = 0, length_oid = 0, rc = 0;
- if ( oid == NULL) {
- /* this is bad */
- LDAPDebug (LDAP_DEBUG_ANY, "NULL passed to check_oid\n",0,0,0);
- return 0;
- }
-
- length_oid = strlen(oid);
- if (length_oid < 4) {
- /* this is probably bad */
- LDAPDebug (LDAP_DEBUG_ANY, "Bad oid %s passed to check_oid\n",oid,0,0);
- return 0;
- }
- rc = strcasecmp(oid+(length_oid-4), "-oid");
- if ( 0 == rc ) {
- return 1;
- }
- /* If not, the OID must begin and end with a digit, and contain only
- digits and dots */
-
- if ( !isdigit(oid[0]) ||
- !isdigit(oid[length_oid-1]) ) {
- LDAPDebug (LDAP_DEBUG_ANY, "Non numeric oid %s passed to check_oid\n",oid,0,0);
- return 0;
- }
- /* check to see that it contains only digits and dots */
- for ( i = 0; i < length_oid; i++ ) {
- if ( !isdigit(oid[i]) && oid[i] != '.' ){
- LDAPDebug (LDAP_DEBUG_ANY, "Non numeric oid %s passed to check_oid\n",oid,0,0);
- return 0;
- }
- }
- /* The oid is OK if we're here */
- return 1;
-
- }
- #endif
- #define NBUCKETS(ht) (1 << (PL_HASH_BITS - (ht)->shift))
- #if 0
- static int
- attr_syntax_check_oids()
- {
- int ii = 0;
- int nbad = 0;
- AS_LOCK_READ(oid2asi_lock);
- ii = NBUCKETS(oid2asi);
- for (;ii;--ii) {
- PLHashEntry *he = oid2asi->buckets[ii-1];
- for (; he; he = he->next) {
- if (!check_oid(he->key)) {
- LDAPDebug(LDAP_DEBUG_ANY, "Error: bad oid %s in bucket %d\n",
- he->key, ii-1, 0);
- nbad++;
- }
- }
- }
- AS_UNLOCK_READ(oid2asi_lock);
- return nbad;
- }
- #endif
- void
- attr_syntax_free( struct asyntaxinfo *a )
- {
- if (!a) {
- return;
- }
- cool_charray_free( a->asi_aliases );
- slapi_ch_free_string(&a->asi_name );
- slapi_ch_free_string(&a->asi_desc );
- slapi_ch_free_string(&a->asi_oid );
- slapi_ch_free_string(&a->asi_superior );
- slapi_ch_free_string(&a->asi_mr_equality );
- slapi_ch_free_string(&a->asi_mr_ordering );
- slapi_ch_free_string(&a->asi_mr_substring );
- slapi_ch_free_string(&a->asi_syntax_oid);
- schema_free_extensions(a->asi_extensions);
- slapi_ch_free( (void **) &a );
- }
- static struct asyntaxinfo *
- attr_syntax_new()
- {
- return (struct asyntaxinfo *)slapi_ch_calloc(1, sizeof(struct asyntaxinfo));
- }
- /*
- * Given an OID, return the syntax info. If there is more than one
- * attribute syntax with the same OID (i.e. aliases), the first one
- * will be returned. This is usually the "canonical" one, but it may
- * not be.
- *
- * Note: once the caller is finished using it, the structure returned must
- * be returned by calling to attr_syntax_return().
- */
- struct asyntaxinfo *
- attr_syntax_get_by_oid(const char *oid, PRUint32 schema_flags)
- {
- return attr_syntax_get_by_oid_locking_optional( oid, PR_TRUE, schema_flags);
- }
- /*
- * A version of attr_syntax_get_by_oid() that allows you to bypass using
- * a lock to access the global oid hash table.
- *
- * Note: once the caller is finished using it, the structure must be
- * returned by calling attr_syntax_return_locking_optional() with the
- * same use_lock parameter.
- */
- static struct asyntaxinfo *
- attr_syntax_get_by_oid_locking_optional( const char *oid, PRBool use_lock, PRUint32 schema_flags )
- {
- struct asyntaxinfo *asi = 0;
- PLHashTable *ht = oid2asi;
- int using_tmp_ht = 0;
- if (schema_flags & DSE_SCHEMA_LOCKED){
- ht = oid2asi_tmp;
- using_tmp_ht = 1;
- use_lock = 0;
- }
- if (ht)
- {
- if ( use_lock ) {
- AS_LOCK_READ(oid2asi_lock);
- }
- if (!using_tmp_ht){
- /*
- * The oid2asi pointer could have been rewritten by the schema_reload task
- * while waiting on the lock, so grab it again.
- */
- ht = oid2asi;
- }
- asi = (struct asyntaxinfo *)PL_HashTableLookup_const(ht, oid);
- if (asi)
- {
- PR_AtomicIncrement( &asi->asi_refcnt );
- }
- if ( use_lock ) {
- AS_UNLOCK_READ(oid2asi_lock);
- }
- }
- return asi;
- }
- /*
- * Add the syntax info pointer to the look-up-by-oid table.
- * The lock parameter is used by the initialization code. Normally, we want
- * to acquire a write lock before we modify the table, but during
- * initialization, we are running in single threaded mode, so we don't have
- * to worry about resource contention.
- */
- static void
- attr_syntax_add_by_oid(const char *oid, struct asyntaxinfo *a, PRUint32 schema_flags, int lock)
- {
- if (0 != attr_syntax_init()) return;
- if(schema_flags & DSE_SCHEMA_LOCKED){
- PL_HashTableAdd(oid2asi_tmp, oid, a);
- } else {
- if (lock) {
- AS_LOCK_WRITE(oid2asi_lock);
- }
- PL_HashTableAdd(oid2asi, oid, a);
- if (lock) {
- AS_UNLOCK_WRITE(oid2asi_lock);
- }
- }
- }
- /*
- * Return the syntax info given an attribute name. The name may be the
- * "canonical" name, an alias, or an OID. The given name need not be
- * normalized since the look up is done case insensitively.
- *
- * Note: once the caller is finished using it, the structure returned must
- * be returned by calling to attr_syntax_return().
- */
- struct asyntaxinfo *
- attr_syntax_get_by_name(const char *name, PRUint32 schema_flags)
- {
- return attr_syntax_get_by_name_locking_optional(name, PR_TRUE, schema_flags);
- }
- struct asyntaxinfo *
- attr_syntax_get_by_name_with_default(const char *name)
- {
- struct asyntaxinfo *asi = NULL;
- asi = attr_syntax_get_by_name_locking_optional(name, PR_TRUE, 0);
- if (asi == NULL)
- asi = attr_syntax_get_by_name(ATTR_WITH_OCTETSTRING_SYNTAX, 0);
- if ( asi == NULL )
- asi = default_asi;
- return asi;
- }
- /*
- * A version of attr_syntax_get_by_name() that allows you to bypass using
- * a lock around the global name hashtable.
- *
- * Note: once the caller is finished using it, the structure must be
- * returned by calling attr_syntax_return_locking_optional() with the
- * same use_lock parameter.
- */
- struct asyntaxinfo *
- attr_syntax_get_by_name_locking_optional(const char *name, PRBool use_lock, PRUint32 schema_flags)
- {
- struct asyntaxinfo *asi = 0;
- PLHashTable *ht = name2asi;
- int using_tmp_ht = 0;
- if (schema_flags & DSE_SCHEMA_LOCKED){
- ht = name2asi_tmp;
- using_tmp_ht = 1;
- use_lock = 0;
- }
- if (ht)
- {
- if ( use_lock ) {
- AS_LOCK_READ(name2asi_lock);
- }
- if(!using_tmp_ht){
- /*
- * The name2asi pointer could have been rewritten by the schema_reload task
- * while waiting on the lock, so grab it again.
- */
- ht = name2asi;
- }
- asi = (struct asyntaxinfo *)PL_HashTableLookup_const(ht, name);
- if ( NULL != asi ) {
- PR_AtomicIncrement( &asi->asi_refcnt );
- }
- if ( use_lock ) {
- AS_UNLOCK_READ(name2asi_lock);
- }
- }
- if (!asi) /* given name may be an OID */
- asi = attr_syntax_get_by_oid_locking_optional(name, use_lock, schema_flags);
- return asi;
- }
- /*
- * Give up a reference to an asi.
- * If the asi has been marked for delete, free it. This would be a bit
- * easier if we could upgrade a read lock to a write one... but NSPR does
- * not support that paradigm.
- */
- void
- attr_syntax_return( struct asyntaxinfo *asi )
- {
- attr_syntax_return_locking_optional( asi, PR_TRUE );
- }
- void
- attr_syntax_return_locking_optional(struct asyntaxinfo *asi, PRBool use_lock)
- {
- int locked = 0;
- if(use_lock) {
- AS_LOCK_READ(name2asi_lock);
- locked = 1;
- }
- if ( NULL != asi ) {
- PRBool delete_it = PR_FALSE;
- if ( 0 == PR_AtomicDecrement( &asi->asi_refcnt )) {
- delete_it = asi->asi_marked_for_delete;
- }
- if (delete_it) {
- if ( asi->asi_marked_for_delete ) { /* one final check */
- if(use_lock) {
- AS_UNLOCK_READ(name2asi_lock);
- AS_LOCK_WRITE(name2asi_lock);
- }
- /* ref count is 0 and it's flagged for
- * deletion, so it's safe to free now */
- attr_syntax_remove(asi);
- attr_syntax_free(asi);
- if(use_lock) {
- AS_UNLOCK_WRITE(name2asi_lock);
- locked = 0;
- }
- }
- }
- }
- if(locked) {
- AS_UNLOCK_READ(name2asi_lock);
- }
- }
- /*
- * Add the syntax info to the look-up-by-name table. The asi_name and
- * elements of the asi_aliasses field of the syntax info are the keys.
- * These need not be normalized since the look up table is case insensitive.
- * The lock parameter is used by the initialization code. Normally, we want
- * to acquire a write lock before we modify the table, but during
- * initialization, we are running in single threaded mode, so we don't have
- * to worry about resource contention.
- */
- static void
- attr_syntax_add_by_name(struct asyntaxinfo *a, PRUint32 schema_flags, int lock)
- {
- if (0 != attr_syntax_init()) return;
- if (schema_flags & DSE_SCHEMA_LOCKED ){
- /* insert the attr into the temp global linked list */
- attr_syntax_insert_tmp(a);
- PL_HashTableAdd(name2asi_tmp, a->asi_name, a);
- if ( a->asi_aliases != NULL ) {
- int i;
- for ( i = 0; a->asi_aliases[i] != NULL; ++i ) {
- PL_HashTableAdd(name2asi_tmp, a->asi_aliases[i], a);
- }
- }
- } else {
- if (lock) {
- AS_LOCK_WRITE(name2asi_lock);
- }
- /* insert the attr into the global linked list */
- attr_syntax_insert(a);
- PL_HashTableAdd(name2asi, a->asi_name, a);
- if ( a->asi_aliases != NULL ) {
- int i;
- for ( i = 0; a->asi_aliases[i] != NULL; ++i ) {
- PL_HashTableAdd(name2asi, a->asi_aliases[i], a);
- }
- }
- if (lock) {
- AS_UNLOCK_WRITE(name2asi_lock);
- }
- }
- }
- /*
- * Delete the attribute syntax and all entries corresponding to aliases
- * and oids.
- */
- void
- attr_syntax_delete( struct asyntaxinfo *asi, PRUint32 schema_flags )
- {
- PR_ASSERT( asi );
- if (oid2asi && name2asi) {
- AS_LOCK_WRITE(oid2asi_lock);
- AS_LOCK_WRITE(name2asi_lock);
- attr_syntax_delete_no_lock( asi, PR_TRUE, schema_flags );
- AS_UNLOCK_WRITE(name2asi_lock);
- AS_UNLOCK_WRITE(oid2asi_lock);
- }
- }
- /*
- * Dispose of a node. The caller is responsible for locking. See
- * attr_syntax_delete() for an example.
- */
- static void
- attr_syntax_delete_no_lock( struct asyntaxinfo *asi,
- PRBool remove_from_oidtable, PRUint32 schema_flags )
- {
- PLHashTable *ht = NULL;
- int using_tmp_ht = 0;
- int i;
- if (schema_flags & DSE_SCHEMA_LOCKED){
- using_tmp_ht = 1;
- }
- if (oid2asi && remove_from_oidtable ) {
- if (using_tmp_ht){
- ht = oid2asi_tmp;
- } else {
- ht = oid2asi;
- }
- PL_HashTableRemove(ht, asi->asi_oid);
- }
- if(name2asi) {
- if (using_tmp_ht){
- ht = name2asi_tmp;
- } else {
- ht = name2asi;
- }
- PL_HashTableRemove(ht, asi->asi_name);
- if ( asi->asi_aliases != NULL ) {
- for ( i = 0; asi->asi_aliases[i] != NULL; ++i ) {
- PL_HashTableRemove(ht, asi->asi_aliases[i]);
- }
- }
- if ( asi->asi_refcnt > 0 ) {
- asi->asi_marked_for_delete = PR_TRUE;
- } else {
- /* This is ok, but the correct thing is to call delete first,
- * then to call return. The last return will then take care of
- * the free. The only way this free would happen here is if
- * you return the syntax before calling delete. */
- attr_syntax_remove(asi);
- attr_syntax_free(asi);
- }
- }
- }
- /*
- * Look up the attribute type in the syntaxes and return a copy of the
- * normalised attribute type. If it's not there then return a normalised
- * copy of what the caller gave us.
- *
- * Warning: The caller must free the returned string.
- */
- char *
- slapi_attr_syntax_normalize( const char *s )
- {
- struct asyntaxinfo *asi = NULL;
- char *r = NULL;
- if((asi=attr_syntax_get_by_name(s, 0)) != NULL ) {
- r = slapi_ch_strdup(asi->asi_name);
- attr_syntax_return( asi );
- }
- if ( NULL == asi ) {
- slapi_ch_free_string( &r );
- r = attr_syntax_normalize_no_lookup( s );
- }
- return r;
- }
- /*
- * flags:
- * 0 -- same as slapi_attr_syntax_normalize
- * ATTR_SYNTAX_NORM_ORIG_ATTR -- In addition to slapi_attr_syntax_normalize,
- * a space and following characters are removed
- * from the given string 's'.
- */
- char *
- slapi_attr_syntax_normalize_ext( char *s, int flags )
- {
- struct asyntaxinfo *asi = NULL;
- char *r = NULL;
- if((asi=attr_syntax_get_by_name(s, flags)) != NULL ) {
- r = slapi_ch_strdup(asi->asi_name);
- attr_syntax_return( asi );
- }
- if ( NULL == asi ) {
- slapi_ch_free_string( &r );
- r = attr_syntax_normalize_no_lookup_ext( s, flags );
- }
- return r;
- }
- /*
- * attr_syntax_exists: return 1 if attr_name exists, 0 otherwise
- *
- */
- int
- attr_syntax_exists(const char *attr_name)
- {
- struct asyntaxinfo *asi;
- char *check_attr_name = NULL;
- char *p = NULL;
- int free_attr = 0;
- /* Ignore any attribute subtypes. */
- if ((p = strchr(attr_name, ';'))) {
- int check_attr_len = p - attr_name + 1;
- check_attr_name = (char *)slapi_ch_malloc(check_attr_len);
- PR_snprintf(check_attr_name, check_attr_len, "%s", attr_name);
- free_attr = 1;
- } else {
- check_attr_name = (char *)attr_name;
- }
- asi = attr_syntax_get_by_name(check_attr_name, 0);
- attr_syntax_return( asi );
- if (free_attr) {
- slapi_ch_free_string(&check_attr_name);
- }
- if ( asi != NULL )
- {
- return 1;
- }
- return 0;
- }
- static void default_dirstring_normalize_int(char *s, int trim_spaces);
- static
- int default_dirstring_filter_ava( struct berval *bvfilter, Slapi_Value **bvals,int ftype, Slapi_Value **retVal )
- {
- return(0);
- }
- static
- int default_dirstring_values2keys( Slapi_PBlock *pb, Slapi_Value **bvals,Slapi_Value ***ivals, int ftype )
- {
- int numbvals = 0;
- Slapi_Value **nbvals, **nbvlp;
- Slapi_Value **bvlp;
- char *c;
- if (NULL == ivals) {
- return 1;
- }
- *ivals = NULL;
- if (NULL == bvals) {
- return 1;
- }
- switch ( ftype ) {
- case LDAP_FILTER_EQUALITY:
- /* allocate a new array for the normalized values */
- for ( bvlp = bvals; bvlp && *bvlp; bvlp++ ) {
- numbvals++;
- }
- nbvals = (Slapi_Value **) slapi_ch_calloc( (numbvals + 1), sizeof(Slapi_Value *));
- for ( bvlp = bvals, nbvlp = nbvals; bvlp && *bvlp; bvlp++, nbvlp++ ) {
- c = slapi_ch_strdup(slapi_value_get_string(*bvlp));
- default_dirstring_normalize_int( c, 1 );
- *nbvlp = slapi_value_new_string_passin(c);
- c = NULL;
- }
- *ivals = nbvals;
- break;
- case LDAP_FILTER_APPROX:
- case LDAP_FILTER_SUBSTRINGS:
- default:
- /* default plugin only handles equality so far */
- LDAPDebug( LDAP_DEBUG_ANY,
- "default_dirstring_values2keys: unsupported ftype 0x%x\n",
- ftype, 0, 0 );
- break;
- }
- return(0);
- }
- static
- int default_dirstring_assertion2keys_ava(Slapi_PBlock *pb,Slapi_Value *val,Slapi_Value ***ivals,int ftype )
- {
- return(0);
- }
- static
- int default_dirstring_cmp(struct berval *v1,struct berval *v2, int normalize)
- {
- return(0);
- }
- static
- void default_dirstring_normalize(Slapi_PBlock *pb, char *s, int trim_spaces, char **alt)
- {
- default_dirstring_normalize_int(s, trim_spaces);
- }
- static
- void default_dirstring_normalize_int(char *s, int trim_spaces)
- {
- char *head = s;
- char *d;
- int prevspace, curspace;
- if (NULL == s) {
- return;
- }
- d = s;
- if (trim_spaces) {
- /* strip leading blanks */
- while (ldap_utf8isspace(s)) {
- LDAP_UTF8INC(s);
- }
- }
- /* handle value of all spaces - turn into single space */
- if ( *s == '\0' && s != d ) {
- *d++ = ' ';
- *d = '\0';
- return;
- }
- prevspace = 0;
- while ( *s ) {
- int ssz, dsz;
- curspace = ldap_utf8isspace(s);
- /* compress multiple blanks */
- if ( prevspace && curspace ) {
- LDAP_UTF8INC(s);
- continue;
- }
- prevspace = curspace;
- slapi_utf8ToLower((unsigned char*)s, (unsigned char *)d, &ssz, &dsz);
- s += ssz;
- d += dsz;
- }
- *d = '\0';
- /* strip trailing blanks */
- if (prevspace && trim_spaces) {
- char *nd;
- nd = ldap_utf8prev(d);
- while (nd && nd >= head && ldap_utf8isspace(nd)) {
- d = nd;
- nd = ldap_utf8prev(d);
- *d = '\0';
- }
- }
- }
- static struct slapdplugin *
- attr_syntax_default_plugin ( const char *nameoroid )
- {
- struct slapdplugin *pi = NULL;
- /*
- * create a new plugin structure and
- * set the plugin function pointers.
- */
- pi = (struct slapdplugin *)slapi_ch_calloc(1, sizeof(struct slapdplugin));
- pi->plg_dn = slapi_ch_strdup("default plugin for directory string syntax");
- pi->plg_closed = 0;
- pi->plg_syntax_oid = slapi_ch_strdup(nameoroid);
- pi->plg_syntax_filter_ava = (IFP) default_dirstring_filter_ava;
- pi->plg_syntax_values2keys = (IFP) default_dirstring_values2keys;
- pi->plg_syntax_assertion2keys_ava = (IFP) default_dirstring_assertion2keys_ava;
- pi->plg_syntax_compare = (IFP) default_dirstring_cmp;
- pi->plg_syntax_normalize = (VFPV) default_dirstring_normalize;
- return (pi);
- }
- /* check syntax */
- static void *
- attr_syntax_get_plugin_by_name_with_default( const char *type )
- {
- struct asyntaxinfo *asi;
- void *plugin = NULL;
- /*
- * first we look for this attribute type explictly
- */
- if ( (asi = attr_syntax_get_by_name(type, 0)) == NULL ) {
- /*
- * no syntax for this type... return Octet String
- * syntax. we accomplish this by looking up a well known
- * attribute type that has that syntax.
- */
- asi = attr_syntax_get_by_name(ATTR_WITH_OCTETSTRING_SYNTAX, 0);
- if (asi == NULL)
- asi = default_asi;
- }
- if ( NULL != asi ) {
- plugin = asi->asi_plugin;
- attr_syntax_return( asi );
- }
- return( plugin );
- }
- static struct asyntaxinfo *
- attr_syntax_dup( struct asyntaxinfo *a )
- {
- struct asyntaxinfo *newas = attr_syntax_new();
- newas->asi_aliases = cool_charray_dup( a->asi_aliases );
- newas->asi_name = slapi_ch_strdup( a->asi_name );
- newas->asi_desc = slapi_ch_strdup( a->asi_desc );
- newas->asi_superior = slapi_ch_strdup( a->asi_superior );
- newas->asi_mr_equality = slapi_ch_strdup( a->asi_mr_equality );
- newas->asi_mr_ordering = slapi_ch_strdup( a->asi_mr_ordering );
- newas->asi_mr_substring = slapi_ch_strdup( a->asi_mr_substring );
- newas->asi_extensions = schema_copy_extensions( a->asi_extensions );
- newas->asi_plugin = a->asi_plugin;
- newas->asi_flags = a->asi_flags;
- newas->asi_oid = slapi_ch_strdup( a->asi_oid);
- newas->asi_syntaxlength = a->asi_syntaxlength;
- newas->asi_mr_eq_plugin = a->asi_mr_eq_plugin;
- newas->asi_mr_ord_plugin = a->asi_mr_ord_plugin;
- newas->asi_mr_sub_plugin = a->asi_mr_sub_plugin;
- newas->asi_syntax_oid = slapi_ch_strdup(a->asi_syntax_oid);
- newas->asi_next = NULL;
- newas->asi_prev = NULL;
- return( newas );
- }
- static void
- attr_syntax_insert(struct asyntaxinfo *asip )
- {
- /* Insert at top of list */
- asip->asi_prev = NULL;
- asip->asi_next = global_at;
- if(global_at){
- global_at->asi_prev = asip;
- global_at = asip;
- } else {
- global_at = asip;
- }
- }
- static void
- attr_syntax_insert_tmp(struct asyntaxinfo *asip )
- {
- /* Insert at top of list */
- asip->asi_prev = NULL;
- asip->asi_next = global_at_tmp;
- if(global_at_tmp){
- global_at_tmp->asi_prev = asip;
- global_at_tmp = asip;
- } else {
- global_at_tmp = asip;
- }
- }
- static void
- attr_syntax_remove(struct asyntaxinfo *asip )
- {
- struct asyntaxinfo *prev, *next;
- prev = asip->asi_prev;
- next = asip->asi_next;
- if(prev){
- prev->asi_next = next;
- if(next){
- next->asi_prev = prev;
- }
- } else {
- if(next){
- next->asi_prev = NULL;
- }
- global_at = next;
- }
- }
- /*
- * Add a new attribute type to the schema.
- *
- * Returns an LDAP error code (LDAP_SUCCESS if all goes well).
- */
- int
- attr_syntax_add( struct asyntaxinfo *asip, PRUint32 schema_flags )
- {
- int i, rc = LDAP_SUCCESS;
- int nolock = asip->asi_flags & SLAPI_ATTR_FLAG_NOLOCKING;
- struct asyntaxinfo *oldas_from_oid = NULL, *oldas_from_name = NULL;
- /* attr names may have subtypes in them, and we may not want this
- if strip_subtypes is true, the ; and anything after it in the
- attr name or alias will be stripped */
- /*int strip_subtypes = 1;*/
- /* make sure the oid is unique */
- if ( NULL != ( oldas_from_oid = attr_syntax_get_by_oid_locking_optional(
- asip->asi_oid, !nolock, schema_flags))) {
- if ( 0 == (asip->asi_flags & SLAPI_ATTR_FLAG_OVERRIDE)) {
- /* failure - OID is in use; no override flag */
- rc = LDAP_TYPE_OR_VALUE_EXISTS;
- goto cleanup_and_return;
- }
- }
- /*
- * Make sure the primary name is unique OR, if override is allowed, that
- * the primary name and OID point to the same schema definition.
- */
- if ( NULL != ( oldas_from_name = attr_syntax_get_by_name_locking_optional(
- asip->asi_name, !nolock, schema_flags))) {
- if ( 0 == (asip->asi_flags & SLAPI_ATTR_FLAG_OVERRIDE)
- || ( oldas_from_oid != oldas_from_name )) {
- /* failure; no override flag OR OID and name don't match */
- rc = LDAP_TYPE_OR_VALUE_EXISTS;
- goto cleanup_and_return;
- }
- /* Flag for deletion. We are going to override this attr */
- attr_syntax_delete(oldas_from_name, schema_flags);
- } else if ( NULL != oldas_from_oid ) {
- /* failure - OID is in use but name does not exist */
- rc = LDAP_TYPE_OR_VALUE_EXISTS;
- goto cleanup_and_return;
- }
- if ( NULL != asip->asi_aliases ) {
- /* make sure the aliases are unique */
- for (i = 0; asip->asi_aliases[i] != NULL; ++i) {
- struct asyntaxinfo *tmpasi;
- if ( NULL != ( tmpasi =
- attr_syntax_get_by_name_locking_optional(
- asip->asi_aliases[i], !nolock, schema_flags))) {
- if (asip->asi_flags & SLAPI_ATTR_FLAG_OVERRIDE) {
- /* Flag for tmpasi for deletion. It will be free'd
- * when attr_syntax_return is called. */
- attr_syntax_delete(tmpasi, schema_flags);
- } else {
- /* failure - one of the aliases is already in use */
- rc = LDAP_TYPE_OR_VALUE_EXISTS;
- }
- attr_syntax_return_locking_optional( tmpasi, !nolock );
- if ( LDAP_SUCCESS != rc ) {
- goto cleanup_and_return;
- }
- }
- }
- }
- /* the no lock flag is not worth keeping around */
- asip->asi_flags &= ~SLAPI_ATTR_FLAG_NOLOCKING;
- /* ditto for the override one */
- asip->asi_flags &= ~SLAPI_ATTR_FLAG_OVERRIDE;
-
- attr_syntax_add_by_oid( asip->asi_oid, asip, schema_flags, !nolock);
- attr_syntax_add_by_name( asip, schema_flags, !nolock);
- cleanup_and_return:
- attr_syntax_return_locking_optional( oldas_from_oid, !nolock );
- attr_syntax_return_locking_optional( oldas_from_name, !nolock );
- return rc;
- }
- static int
- attr_syntax_create_default( const char *name, const char *oid,
- const char *syntax, unsigned long extraflags )
- {
- int rc = 0;
- char *names[2];
- unsigned long std_flags = SLAPI_ATTR_FLAG_STD_ATTR | SLAPI_ATTR_FLAG_OPATTR;
- names[0] = (char *)name;
- names[1] = NULL;
- if (default_asi)
- return (rc);
- rc = attr_syntax_create( oid, names,
- "internal server defined attribute type",
- NULL, /* superior */
- NULL, NULL, NULL, /* matching rules */
- NULL, syntax,
- SLAPI_SYNTAXLENGTH_NONE,
- std_flags | extraflags,
- &default_asi );
- if ( rc == 0 && default_asi->asi_plugin == 0)
- default_asi->asi_plugin = attr_syntax_default_plugin (syntax );
- return (rc);
- }
- /*
- * Returns an LDAP result code.
- */
- int
- attr_syntax_create(
- const char *attr_oid,
- char *const *attr_names,
- const char *attr_desc,
- const char *attr_superior,
- const char *mr_equality,
- const char *mr_ordering,
- const char *mr_substring,
- schemaext *extensions,
- const char *attr_syntax,
- int syntaxlength,
- unsigned long flags,
- struct asyntaxinfo **asip
- )
- {
- char *s;
- struct asyntaxinfo a;
- int rc = LDAP_SUCCESS;
- /* XXXmcs: had to cast away const in many places below */
- memset(&a, 0, sizeof(a));
- *asip = NULL;
- a.asi_name = slapi_ch_strdup(attr_names[0]);
- if ( NULL != attr_names[1] ) {
- a.asi_aliases = (char **)&attr_names[1]; /* all but the zero'th element */
- }
- a.asi_desc = (char*)attr_desc;
- a.asi_oid = (char*)attr_oid;
- a.asi_superior = (char*)attr_superior;
- a.asi_mr_equality = (char*)mr_equality;
- a.asi_mr_ordering = (char*)mr_ordering;
- a.asi_mr_substring = (char*)mr_substring;
- a.asi_extensions = extensions;
- a.asi_plugin = plugin_syntax_find( attr_syntax );
- a.asi_syntax_oid = (char *)attr_syntax ;
- a.asi_syntaxlength = syntaxlength;
- /* ideally, we would report an error and fail to start if there was some problem
- with the matching rule - but since this functionality is new, and we might
- cause havoc if lots of servers failed to start because of bogus schema, we
- just report an error here - at some point in the future, we should actually
- report an error and exit, or allow the user to control the behavior - for
- now, just log an error, and address each case
- */
- if (mr_equality && !slapi_matchingrule_is_compat(mr_equality, attr_syntax)) {
- slapi_log_error(SLAPI_LOG_FATAL, "attr_syntax_create",
- "Error: the EQUALITY matching rule [%s] is not compatible "
- "with the syntax [%s] for the attribute [%s]\n",
- mr_equality, attr_syntax, attr_names[0]);
- #ifdef ENFORCE_MR_SYNTAX_COMPAT
- rc = LDAP_INAPPROPRIATE_MATCHING;
- goto done;
- #endif /* ENFORCE_MR_SYNTAX_COMPAT */
- }
- a.asi_mr_eq_plugin = plugin_mr_find( mr_equality );
- if (mr_ordering && !slapi_matchingrule_is_compat(mr_ordering, attr_syntax)) {
- slapi_log_error(SLAPI_LOG_FATAL, "attr_syntax_create",
- "Error: the ORDERING matching rule [%s] is not compatible "
- "with the syntax [%s] for the attribute [%s]\n",
- mr_ordering, attr_syntax, attr_names[0]);
- #ifdef ENFORCE_MR_SYNTAX_COMPAT
- rc = LDAP_INAPPROPRIATE_MATCHING;
- goto done;
- #endif /* ENFORCE_MR_SYNTAX_COMPAT */
- }
- a.asi_mr_ord_plugin = plugin_mr_find( mr_ordering );
- if (mr_substring && !slapi_matchingrule_is_compat(mr_substring, attr_syntax)) {
- slapi_log_error(SLAPI_LOG_FATAL, "attr_syntax_create",
- "Error: the SUBSTR matching rule [%s] is not compatible "
- "with the syntax [%s] for the attribute [%s]\n",
- mr_substring, attr_syntax, attr_names[0]);
- #ifdef ENFORCE_MR_SYNTAX_COMPAT
- rc = LDAP_INAPPROPRIATE_MATCHING;
- goto done;
- #endif /* ENFORCE_MR_SYNTAX_COMPAT */
- }
- a.asi_mr_sub_plugin = plugin_mr_find( mr_substring );
- a.asi_flags = flags;
- /*
- * If the 'return exact case' option is on (the default), we store the
- * first name (the canonical one) unchanged so that attribute names are
- * returned exactly as they appear in the schema configuration files.
- * But if 'return exact case' has been turned off, we convert the name
- * to lowercase. In Netscape Directory Server 4.x and earlier versions,
- * the default was to convert to lowercase.
- */
- if (!config_get_return_exact_case()) {
- for (s = a.asi_name; *s; ++s) {
- *s = TOLOWER(*s);
- }
- }
- *asip = attr_syntax_dup(&a);
- #ifdef ENFORCE_MR_SYNTAX_COMPAT
- done:
- #endif /* ENFORCE_MR_SYNTAX_COMPAT */
- slapi_ch_free((void **)&a.asi_name);
- return rc;
- }
- /*
- * slapi_attr_type2plugin - return the plugin handling the attribute type
- * if type is unknown, we return the caseIgnoreString plugin used by the
- * objectClass attribute type.
- */
- int
- slapi_attr_type2plugin( const char *type, void **pi )
- {
- char buf[SLAPD_TYPICAL_ATTRIBUTE_NAME_MAX_LENGTH];
- char *tmp, *basetype;
- int rc;
- basetype = buf;
- if ( (tmp = slapi_attr_basetype( type, buf, sizeof(buf) )) != NULL ) {
- basetype = tmp;
- }
- rc = -1;
- *pi = attr_syntax_get_plugin_by_name_with_default( basetype );
- if ( NULL != *pi ) {
- rc = 0;
- }
- slapi_ch_free_string(&tmp);
- return( rc );
- }
- /* deprecated -- not MT safe (pointer into asi is returned!) */
- int
- slapi_attr_get_oid( const Slapi_Attr *a, char **oid )
- {
- struct asyntaxinfo *asi = attr_syntax_get_by_name(a->a_type, 0);
- if (asi) {
- *oid = asi->asi_oid;
- attr_syntax_return(asi);
- return( 0 );
- } else {
- *oid = NULL;
- return( -1 );
- }
- }
- /* The caller must dispose of oid by calling slapi_ch_free(). */
- int
- slapi_attr_get_oid_copy( const Slapi_Attr *a, char **oidp )
- {
- struct asyntaxinfo *asi = attr_syntax_get_by_name(a->a_type, 0);
- if (asi) {
- *oidp = slapi_ch_strdup( asi->asi_oid );
- attr_syntax_return(asi);
- return( 0 );
- } else {
- *oidp = NULL;
- return( -1 );
- }
- }
- /* Returns the oid of the syntax of the Slapi_Attr that's passed in.
- * The caller must dispose of oid by calling slapi_ch_free_string(). */
- int
- slapi_attr_get_syntax_oid_copy( const Slapi_Attr *a, char **oidp )
- {
- const char *oid;
- if (a && ((oid = attr_get_syntax_oid(a)))) {
- *oidp = slapi_ch_strdup(oid);
- return( 0 );
- } else {
- *oidp = NULL;
- return( -1 );
- }
- }
- int
- slapi_attr_is_dn_syntax_attr(Slapi_Attr *attr)
- {
- const char *syntaxoid = NULL;
- int dn_syntax = 0; /* not DN, by default */
- if (attr && attr->a_flags & SLAPI_ATTR_FLAG_SYNTAX_IS_DN)
- /* it was checked before */
- return(1);
- if (attr && attr->a_plugin == NULL) {
- slapi_attr_init_syntax (attr);
- }
- if (attr && attr->a_plugin) { /* If not set, there is no way to get the info */
- if ((syntaxoid = attr_get_syntax_oid(attr))) {
- dn_syntax = ((0 == strcmp(syntaxoid, NAMEANDOPTIONALUID_SYNTAX_OID))
- || (0 == strcmp(syntaxoid, DN_SYNTAX_OID)));
- }
- if (dn_syntax)
- attr->a_flags |= SLAPI_ATTR_FLAG_SYNTAX_IS_DN;
- }
- return dn_syntax;
- }
- int
- slapi_attr_is_dn_syntax_type(char *type)
- {
- const char *syntaxoid = NULL;
- int dn_syntax = 0; /* not DN, by default */
- struct asyntaxinfo * asi;
- asi = attr_syntax_get_by_name(type, 0);
- if (asi && asi->asi_plugin) { /* If not set, there is no way to get the info */
- if ((syntaxoid = asi->asi_plugin->plg_syntax_oid)) {
- dn_syntax = ((0 == strcmp(syntaxoid, NAMEANDOPTIONALUID_SYNTAX_OID))
- || (0 == strcmp(syntaxoid, DN_SYNTAX_OID)));
- }
- }
- return dn_syntax;
- }
- #ifdef ATTR_LDAP_DEBUG
- PRIntn
- attr_syntax_printnode(PLHashEntry *he, PRIntn i, void *arg)
- {
- char *alias = (char *)he->key;
- struct asyntaxinfo *a = (struct asyntaxinfo *)he->value;
- schemaext *ext = a->asi_extensions;
- printf( " name: %s\n", a->asi_name );
- printf( "\t flags : 0x%x\n", a->asi_flags );
- printf( "\t alias : %s\n", alias );
- printf( "\t desc : %s\n", a->asi_desc );
- printf( "\t oid : %s\n", a->asi_oid );
- printf( "\t superior : %s\n", a->asi_superior );
- printf( "\t mr_equality : %s\n", a->asi_mr_equality );
- printf( "\t mr_ordering : %s\n", a->asi_mr_ordering );
- printf( "\t mr_substring: %s\n", a->asi_mr_substring );
- while( ext ) {
- for ( i = 0; ext->values && ext->values[i]; i++ ) {
- printf( "\t %s : %s\n", ext->term, ext->values[i]);
- }
- ext = ext->next;
- }
- printf( "\tplugin: %p\n", a->asi_plugin );
- printf( "--------------\n" );
- return HT_ENUMERATE_NEXT;
- }
- void
- attr_syntax_print()
- {
- printf( "*** attr_syntax_print ***\n" );
- PL_HashTableEnumerateEntries(name2asi, attr_syntax_printnode, 0);
- }
- #endif
- /* lowercase the attr name and chop trailing spaces */
- /* note that s may contain options also, e.g., userCertificate;binary */
- char *
- attr_syntax_normalize_no_lookup_ext( char *s, int flags )
- {
- char *save, *tmps;
- tmps = slapi_ch_strdup(s);
- for ( save = tmps; (*tmps != '\0') && (*tmps != ' '); tmps++ )
- {
- *tmps = TOLOWER( *tmps );
- }
- *tmps = '\0';
- if (flags & ATTR_SYNTAX_NORM_ORIG_ATTR) {
- /* Chop trailing spaces + following strings */
- *(s + (tmps - save)) = '\0';
- }
- return save;
- }
- char *
- attr_syntax_normalize_no_lookup( const char *s )
- {
- char *save, *tmps;
- tmps = slapi_ch_strdup(s);
- for ( save = tmps; (*tmps != '\0') && (*tmps != ' '); tmps++ )
- {
- *tmps = TOLOWER( *tmps );
- }
- *tmps = '\0';
- return save;
- }
- struct enum_arg_wrapper {
- AttrEnumFunc aef;
- void *arg;
- };
- PRIntn
- attr_syntax_enumerate_internal(PLHashEntry *he, PRIntn i, void *arg)
- {
- struct enum_arg_wrapper *eaw = (struct enum_arg_wrapper *)arg;
- int rc;
- rc = (eaw->aef)((struct asyntaxinfo *)he->value, eaw->arg);
- if ( ATTR_SYNTAX_ENUM_STOP == rc ) {
- rc = HT_ENUMERATE_STOP;
- } else if ( ATTR_SYNTAX_ENUM_REMOVE == rc ) {
- rc = HT_ENUMERATE_REMOVE;
- } else {
- rc = HT_ENUMERATE_NEXT;
- }
- return rc;
- }
- static void
- attr_syntax_enumerate_attrs_ext( PLHashTable *ht,
- AttrEnumFunc aef, void *arg )
- {
- struct enum_arg_wrapper eaw;
- eaw.aef = aef;
- eaw.arg = arg;
- if (!ht)
- return;
- PL_HashTableEnumerateEntries(ht, attr_syntax_enumerate_internal, &eaw);
- }
- void
- attr_syntax_enumerate_attrs(AttrEnumFunc aef, void *arg, PRBool writelock )
- {
- if (!oid2asi)
- return;
- if ( writelock ) {
- AS_LOCK_WRITE(oid2asi_lock);
- AS_LOCK_WRITE(name2asi_lock);
- } else {
- AS_LOCK_READ(oid2asi_lock);
- AS_LOCK_READ(name2asi_lock);
- }
- attr_syntax_enumerate_attrs_ext(oid2asi, aef, arg);
- if ( writelock ) {
- AS_UNLOCK_WRITE(name2asi_lock);
- AS_UNLOCK_WRITE(oid2asi_lock);
- } else {
- AS_UNLOCK_READ(name2asi_lock);
- AS_UNLOCK_READ(oid2asi_lock);
- }
- }
- struct attr_syntax_enum_flaginfo {
- unsigned long asef_flag;
- };
- static int
- attr_syntax_clear_flag_callback(struct asyntaxinfo *asip, void *arg)
- {
- struct attr_syntax_enum_flaginfo *fi;
- PR_ASSERT( asip != NULL );
- fi = (struct attr_syntax_enum_flaginfo *)arg;
- PR_ASSERT( fi != NULL );
- asip->asi_flags &= ~(fi->asef_flag);
- return ATTR_SYNTAX_ENUM_NEXT;
- }
- static int
- attr_syntax_delete_if_not_flagged(struct asyntaxinfo *asip, void *arg)
- {
- struct attr_syntax_enum_flaginfo *fi;
- PR_ASSERT( asip != NULL );
- fi = (struct attr_syntax_enum_flaginfo *)arg;
- PR_ASSERT( fi != NULL );
- if ( 0 == ( asip->asi_flags & fi->asef_flag )) {
- attr_syntax_delete_no_lock( asip, PR_FALSE, 0 );
- return ATTR_SYNTAX_ENUM_REMOVE;
- } else {
- return ATTR_SYNTAX_ENUM_NEXT;
- }
- }
- static int
- attr_syntax_force_to_delete(struct asyntaxinfo *asip, void *arg)
- {
- struct attr_syntax_enum_flaginfo *fi;
- PR_ASSERT( asip != NULL );
- fi = (struct attr_syntax_enum_flaginfo *)arg;
- PR_ASSERT( fi != NULL );
- attr_syntax_delete_no_lock( asip, PR_FALSE, 0 );
- return ATTR_SYNTAX_ENUM_REMOVE;
- }
- /*
- * Clear 'flag' within all attribute definitions.
- */
- void
- attr_syntax_all_clear_flag( unsigned long flag )
- {
- struct attr_syntax_enum_flaginfo fi;
- memset( &fi, 0, sizeof(fi));
- fi.asef_flag = flag;
- attr_syntax_enumerate_attrs( attr_syntax_clear_flag_callback,
- (void *)&fi, PR_TRUE );
- }
- /*
- * Delete all attribute definitions that do not contain any bits of 'flag'
- * in their flags.
- */
- void
- attr_syntax_delete_all_not_flagged( unsigned long flag )
- {
- struct attr_syntax_enum_flaginfo fi;
- memset( &fi, 0, sizeof(fi));
- fi.asef_flag = flag;
- attr_syntax_enumerate_attrs( attr_syntax_delete_if_not_flagged,
- (void *)&fi, PR_TRUE );
- }
- /*
- * Delete all attribute definitions
- */
- void
- attr_syntax_delete_all()
- {
- struct attr_syntax_enum_flaginfo fi;
- memset( &fi, 0, sizeof(fi));
- attr_syntax_enumerate_attrs( attr_syntax_force_to_delete,
- (void *)&fi, PR_TRUE );
- }
- /*
- * Delete all attribute definitions without attr_syntax lock.
- * The caller is responsible for the lock.
- */
- void
- attr_syntax_delete_all_for_schemareload(unsigned long flag)
- {
- struct attr_syntax_enum_flaginfo fi;
- memset(&fi, 0, sizeof(fi));
- fi.asef_flag = flag;
- attr_syntax_enumerate_attrs_ext(oid2asi, attr_syntax_delete_if_not_flagged,
- (void *)&fi);
- }
- #define ATTR_DEFAULT_SYNTAX_OID "1.1"
- #define ATTR_DEFAULT_SYNTAX "defaultdirstringsyntax"
- static int
- attr_syntax_init(void)
- {
- int schema_modify_enabled = config_get_schemamod();
- if (!schema_modify_enabled) asi_locking = 0;
- if (!oid2asi)
- {
- oid2asi = PL_NewHashTable(2047, hashNocaseString,
- hashNocaseCompare,
- PL_CompareValues, 0, 0);
- if ( asi_locking && NULL == ( oid2asi_lock = slapi_new_rwlock())) {
- if(oid2asi) PL_HashTableDestroy(oid2asi);
- oid2asi = NULL;
- slapi_log_error( SLAPI_LOG_FATAL, "attr_syntax_init",
- "slapi_new_rwlock() for oid2asi lock failed\n" );
- return 1;
- }
- }
- if (!oid2asi_tmp)
- {
- /* temporary hash table for schema reload */
- oid2asi_tmp = PL_NewHashTable(2047, hashNocaseString,
- hashNocaseCompare,
- PL_CompareValues, 0, 0);
- }
- if (!name2asi)
- {
- name2asi = PL_NewHashTable(2047, hashNocaseString,
- hashNocaseCompare,
- PL_CompareValues, 0, 0);
- if ( asi_locking && NULL == ( name2asi_lock = slapi_new_rwlock())) {
- if(name2asi) PL_HashTableDestroy(name2asi);
- name2asi = NULL;
- slapi_log_error( SLAPI_LOG_FATAL, "attr_syntax_init",
- "slapi_new_rwlock() for oid2asi lock failed\n" );
- return 1;
- }
- /* add a default syntax plugin as fallback, required during startup
- */
- attr_syntax_create_default( ATTR_DEFAULT_SYNTAX,
- ATTR_DEFAULT_SYNTAX_OID,
- DIRSTRING_SYNTAX_OID,
- SLAPI_ATTR_FLAG_NOUSERMOD| SLAPI_ATTR_FLAG_NOEXPOSE);
- }
- if (!name2asi_tmp)
- {
- /* temporary hash table for schema reload */
- name2asi_tmp = PL_NewHashTable(2047, hashNocaseString,
- hashNocaseCompare,
- PL_CompareValues, 0, 0);
- }
- return 0;
- }
- int
- slapi_attr_syntax_exists(const char *attr_name)
- {
- return attr_syntax_exists(attr_name);
- }
- /*
- * Keep the internally added schema in the hash table,
- * which are re-added if the schema is reloaded.
- */
- static int
- attr_syntax_internal_asi_add_ht(struct asyntaxinfo *asip)
- {
- if (!internalasi) {
- internalasi = PL_NewHashTable(64, hashNocaseString,
- hashNocaseCompare,
- PL_CompareValues, 0, 0);
- }
- if (!internalasi) {
- slapi_log_error(SLAPI_LOG_FATAL, "attr_syntax_internal_asi_add_ht",
- "Failed to create HashTable.\n");
- return 1;
- }
- if (!PL_HashTableLookup(internalasi, asip->asi_oid)) {
- struct asyntaxinfo *asip_copy = attr_syntax_dup(asip);
- if (!asip_copy) {
- slapi_log_error(SLAPI_LOG_FATAL, "attr_syntax_internal_asi_add_ht",
- "Failed to duplicate asyntaxinfo: %s.\n",
- asip->asi_name);
- return 1;
- }
- PL_HashTableAdd(internalasi, asip_copy->asi_oid, asip_copy);
- }
- return 0;
- }
- /*
- * Add an attribute syntax using some default flags, etc.
- * Returns an LDAP error code (LDAP_SUCCESS if all goes well)
- */
- int
- slapi_add_internal_attr_syntax( const char *name, const char *oid,
- const char *syntax, const char *mr_equality, unsigned long extraflags )
- {
- int rc = LDAP_SUCCESS;
- struct asyntaxinfo *asip;
- char *names[2];
- unsigned long std_flags = SLAPI_ATTR_FLAG_STD_ATTR | SLAPI_ATTR_FLAG_OPATTR;
- names[0] = (char *)name;
- names[1] = NULL;
- rc = attr_syntax_create( oid, names,
- "internal server defined attribute type",
- NULL, /* superior */
- mr_equality, NULL, NULL, /* matching rules */
- NULL, syntax,
- SLAPI_SYNTAXLENGTH_NONE,
- std_flags | extraflags,
- &asip );
- if ( rc == LDAP_SUCCESS ) {
- rc = attr_syntax_add( asip, 0 );
- if ( rc == LDAP_SUCCESS ) {
- if (attr_syntax_internal_asi_add_ht(asip)) {
- slapi_log_error(SLAPI_LOG_FATAL,
- "slapi_add_internal_attr_syntax",
- "Failed to stash internal asyntaxinfo: %s.\n",
- asip->asi_name);
- }
- } else {
- attr_syntax_free(asip);
- }
- }
- return rc;
- }
- /* Adding internal asyncinfo via slapi_reload_internal_attr_syntax */
- static int
- attr_syntax_internal_asi_add(struct asyntaxinfo *asip, void *arg)
- {
- struct asyntaxinfo *asip_copy;
- int rc = 0;
- if (!asip) {
- return 1;
- }
- /* Copy is needed since when reloading the schema,
- * existing syntax info is cleaned up. */
- asip_copy = attr_syntax_dup(asip);
- rc = attr_syntax_add(asip_copy, 0);
- if (LDAP_SUCCESS != rc) {
- attr_syntax_free(asip_copy);
- }
- return rc;
- }
- /* Reload internal attribute syntax stashed in the internalasi hashtable. */
- int
- slapi_reload_internal_attr_syntax()
- {
- int rc = LDAP_SUCCESS;
- if (!internalasi) {
- slapi_log_error(SLAPI_LOG_TRACE, "attr_reload_internal_attr_syntax",
- "No internal attribute syntax to reload.\n");
- return rc;
- }
- attr_syntax_enumerate_attrs_ext(internalasi, attr_syntax_internal_asi_add, NULL);
- return rc;
- }
- /*
- * See if the attribute at1 is in the list of at2. Change by name, and oid(if necessary).
- */
- struct asyntaxinfo *
- attr_syntax_find(struct asyntaxinfo *at1, struct asyntaxinfo *at2)
- {
- struct asyntaxinfo *asi;
- for(asi = at2; asi != NULL; asi = asi->asi_next){
- if(strcasecmp(at1->asi_name, asi->asi_name) == 0 || strcmp(at1->asi_oid, asi->asi_oid) == 0){
- /* found it */
- return asi;
- }
- }
- return NULL;
- }
- /*
- * schema reload - now that we have loaded the schema into temporary
- * hash tables and linked lists, swap out the old for the new. Then
- * reload the internal attr syntaxes
- */
- void
- attr_syntax_swap_ht()
- {
- struct asyntaxinfo *next;
- /* Remove the old hash tables */
- PL_HashTableDestroy(name2asi);
- PL_HashTableDestroy(oid2asi);
- /* Free the global attr linked list */
- while(global_at){
- next = global_at->asi_next;
- attr_syntax_free(global_at);
- global_at = next;
- }
- /*
- * Swap the hash table/linked list pointers, and set the
- * temporary pointers to NULL
- */
- name2asi = name2asi_tmp;
- name2asi_tmp = NULL;
- oid2asi = oid2asi_tmp;
- oid2asi_tmp = NULL;
- global_at = global_at_tmp;
- global_at_tmp = NULL;
- }
|