oid = $oid; } public function setDescription($desc) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs); } $this->description = $desc; } public function getOID() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs, $this->oid); } return $this->oid; } public function getDescription() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs, $this->description); } return $this->description; } /** * Gets whether this objectClass is flagged as obsolete by the LDAP server. */ public function getIsObsolete() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs, $this->is_obsolete); } return $this->is_obsolete; } /** * Return the objects name. * * param boolean $lower Return the name in lower case (default) * @param bool $lower * @return string The name */ public function getName($lower=true) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs, $this->name); } return $lower ? strtolower($this->name) : $this->name; } } /** * Represents an LDAP objectClass * * @package phpLDAPadmin * @subpackage Schema */ class ObjectClass extends SchemaItem { # The server ID that this objectclass belongs to. private $server_id = null; # Array of objectClass names from which this objectClass inherits private $sup_classes = array(); # One of STRUCTURAL, ABSTRACT, or AUXILIARY private $type; # Arrays of attribute names that this objectClass requires private $must_attrs = array(); # Arrays of attribute names that this objectClass allows, but does not require private $may_attrs = array(); # Arrays of attribute names that this objectClass has been forced to MAY attrs, due to configuration private $force_may = array(); # Array of objectClasses which inherit from this one (must be set at runtime explicitly by the caller) private $children_objectclasses = array(); # The objectclass hierarchy private $hierarchy = array(); /** * Creates a new ObjectClass object given a raw LDAP objectClass string. * @param $class * @param $server */ public function __construct($class,$server) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } $this->server_id = $server->getIndex(); $this->type = $server->getValue('server','schema_oclass_default'); $strings = preg_split('/[\s,]+/',$class,-1,PREG_SPLIT_DELIM_CAPTURE); $str_count = count($strings); for ($i=0; $i < $str_count; $i++) { switch ($strings[$i]) { case '(': break; case 'NAME': if ($strings[$i+1]!='(') { do { $i++; if (strlen($this->name) == 0) { $this->name = $strings[$i]; } else { $this->name .= ' ' . $strings[$i]; } } while (! preg_match('/\'$/s',$strings[$i])); } else { $i++; do { $i++; if (strlen($this->name) == 0) { $this->name = $strings[$i]; } else { $this->name .= ' ' . $strings[$i]; } } while (! preg_match('/\'$/s',$strings[$i])); do { $i++; } while (! preg_match('/\)+\)?/',$strings[$i])); } $this->name = preg_replace('/^\'/','',$this->name); $this->name = preg_replace('/\'$/','',$this->name); if (DEBUG_ENABLED) { debug_log('Case NAME returned (%s)', 8, 0, __FILE__, __LINE__, __METHOD__, $this->name); } break; case 'DESC': do { $i++; if (strlen($this->description) == 0) { $this->description .= $strings[$i]; } else { $this->description = $this->description . ' ' . $strings[$i]; } } while (! preg_match('/\'$/s',$strings[$i])); if (DEBUG_ENABLED) { debug_log('Case DESC returned (%s)', 8, 0, __FILE__, __LINE__, __METHOD__, $this->description); } break; case 'OBSOLETE': $this->is_obsolete = TRUE; if (DEBUG_ENABLED) { debug_log('Case OBSOLETE returned (%s)', 8, 0, __FILE__, __LINE__, __METHOD__, $this->is_obsolete); } break; case 'SUP': if ($strings[$i+1] != '(') { $i++; array_push($this->sup_classes,preg_replace("/'/",'',$strings[$i])); } else { $i++; do { $i++; if ($strings[$i] != '$') { array_push($this->sup_classes, preg_replace("/'/", '', $strings[$i])); } } while (! preg_match('/\)+\)?/',$strings[$i+1])); } if (DEBUG_ENABLED) { debug_log('Case SUP returned (%s)', 8, 0, __FILE__, __LINE__, __METHOD__, $this->sup_classes); } break; case 'ABSTRACT': $this->type = 'abstract'; if (DEBUG_ENABLED) { debug_log('Case ABSTRACT returned (%s)', 8, 0, __FILE__, __LINE__, __METHOD__, $this->type); } break; case 'STRUCTURAL': $this->type = 'structural'; if (DEBUG_ENABLED) { debug_log('Case STRUCTURAL returned (%s)', 8, 0, __FILE__, __LINE__, __METHOD__, $this->type); } break; case 'AUXILIARY': $this->type = 'auxiliary'; if (DEBUG_ENABLED) { debug_log('Case AUXILIARY returned (%s)', 8, 0, __FILE__, __LINE__, __METHOD__, $this->type); } break; case 'MUST': $attrs = array(); $i = $this->parseList(++$i,$strings,$attrs); if (DEBUG_ENABLED) { debug_log('parseList returned %d (%s)', 8, 0, __FILE__, __LINE__, __METHOD__, $i, $attrs); } foreach ($attrs as $string) { $attr = new ObjectClass_ObjectClassAttribute($string,$this->name); if ($server->isForceMay($attr->getName())) { array_push($this->force_may,$attr); array_push($this->may_attrs,$attr); } else { array_push($this->must_attrs, $attr); } } if (DEBUG_ENABLED) { debug_log('Case MUST returned (%s) (%s)', 8, 0, __FILE__, __LINE__, __METHOD__, $this->must_attrs, $this->force_may); } break; case 'MAY': $attrs = array(); $i = $this->parseList(++$i,$strings,$attrs); if (DEBUG_ENABLED) { debug_log('parseList returned %d (%s)', 8, 0, __FILE__, __LINE__, __METHOD__, $i, $attrs); } foreach ($attrs as $string) { $attr = new ObjectClass_ObjectClassAttribute($string,$this->name); array_push($this->may_attrs,$attr); } if (DEBUG_ENABLED) { debug_log('Case MAY returned (%s)', 8, 0, __FILE__, __LINE__, __METHOD__, $this->may_attrs); } break; default: if (preg_match('/[\d\.]+/i',$strings[$i]) && $i == 1) { $this->setOID($strings[$i]); if (DEBUG_ENABLED) { debug_log('Case default returned (%s)', 8, 0, __FILE__, __LINE__, __METHOD__, $this->getOID()); } } break; } } $this->description = preg_replace("/^\'/",'',$this->description); $this->description = preg_replace("/\'$/",'',$this->description); if (DEBUG_ENABLED) { debug_log('Returning () - NAME (%s), DESCRIPTION (%s), MUST (%s), MAY (%s), FORCE MAY (%s)', 9, 0, __FILE__, __LINE__, __METHOD__, $this->name, $this->description, $this->must_attrs, $this->may_attrs, $this->force_may); } } /** * Parse an LDAP schema list * @param $i * @param $strings * @param $attrs * @return */ private function parseList($i,$strings,&$attrs) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } /* * A list starts with a ( followed by a list of attributes separated by $ terminated by ) * The first token can therefore be a ( or a (NAME or a (NAME) * The last token can therefore be a ) or NAME) * The last token may be terminate by more than one bracket */ $string = $strings[$i]; if (! preg_match('/^\(/',$string)) { # A bareword only - can be terminated by a ) if the last item if (preg_match('/\)+$/',$string)) { $string = preg_replace('/\)+$/', '', $string); } array_push($attrs,$string); } elseif (preg_match('/^\(.*\)$/',$string)) { $string = preg_replace('/^\(/','',$string); $string = preg_replace('/\)+$/','',$string); array_push($attrs,$string); } else { # Handle the opening cases first if ($string == '(') { $i++; } elseif (preg_match('/^\(./',$string)) { $string = preg_replace('/^\(/','',$string); array_push($attrs,$string); $i++; } # Token is either a name, a $ or a ')' # NAME can be terminated by one or more ')' while (! preg_match('/\)+$/',$strings[$i])) { $string = $strings[$i]; if ($string == '$') { $i++; continue; } if (preg_match('/\)$/',$string)) { $string = preg_replace('/\)+$/', '', $string); } else { $i++; } array_push($attrs,$string); } } sort($attrs); if (DEBUG_ENABLED) { debug_log('Returning (%d,[%s],[%s])', 9, 0, __FILE__, __LINE__, __METHOD__, $i, $strings, $attrs); } return $i; } /** * This will return all our parent ObjectClass Objects */ public function getParents() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } if ((count($this->sup_classes) == 1) && ($this->sup_classes[0] == 'top')) { return array(); } $server = $_SESSION[APPCONFIG]->getServer($this->server_id); $return = array(); foreach ($this->sup_classes as $object_class) { array_push($return,$object_class); $oc = $server->getSchemaObjectClass($object_class); if ($oc) { $return = array_merge($return, $oc->getParents()); } } return $return; } /** * Gets an array of AttributeType objects that entries of this ObjectClass must define. * This differs from getMustAttrNames in that it returns an array of AttributeType objects * * @param bool $parents An array of ObjectClass objects to use when traversing * the inheritance tree. This presents some what of a bootstrapping problem * as we must fetch all objectClasses to determine through inheritance which * attributes this objectClass requires. * @return array The array of required AttributeType objects. * * @see getMustAttrNames * @see getMayAttrs * @see getMayAttrNames */ public function getMustAttrs($parents=false) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } if (! $parents) { return $this->must_attrs; } $server = $_SESSION[APPCONFIG]->getServer($this->server_id); $attrs = $this->must_attrs; foreach ($this->getParents() as $sup_class) { $sc = $server->getSchemaObjectClass($sup_class); $attrs = array_merge($attrs,$sc->getMustAttrs()); } masort($attrs,'name,source'); # Remove any duplicates foreach ($attrs as $index => $attr) { if (isset($allattr[$attr->getName()])) { unset($attrs[$index]); } else { $allattr[$attr->getName()] = 1; } } return $attrs; } /** * Gets an array of AttributeType objects that entries of this ObjectClass may define. * This differs from getMayAttrNames in that it returns an array of AttributeType objects * * @param bool $parents An array of ObjectClass objects to use when traversing * the inheritance tree. This presents some what of a bootstrapping problem * as we must fetch all objectClasses to determine through inheritance which * attributes this objectClass provides. * @return array The array of allowed AttributeType objects. * * @see getMustAttrNames * @see getMustAttrs * @see getMayAttrNames * @see AttributeType */ public function getMayAttrs($parents=false) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } if (! $parents) { return $this->may_attrs; } $server = $_SESSION[APPCONFIG]->getServer($this->server_id); $attrs = $this->may_attrs; foreach ($this->getParents() as $sup_class) { $sc = $server->getSchemaObjectClass($sup_class); $attrs = array_merge($attrs,$sc->getMayAttrs()); } masort($attrs,'name,source'); # Remove any duplicates foreach ($attrs as $index => $attr) { if (isset($allattr[$attr->name])) { unset($attrs[$index]); } else { $allattr[$attr->name] = 1; } } return $attrs; } public function getForceMayAttrs() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } return $this->force_may; } /** * Gets an array of attribute names (strings) that entries of this ObjectClass must define. * This differs from getMustAttrs in that it returns an array of strings rather than * array of AttributeType objects * * @param bool $parents An array of ObjectClass objects to use when traversing * the inheritance tree. This presents some what of a bootstrapping problem * as we must fetch all objectClasses to determine through inheritance which * attributes this objectClass provides. * @return array The array of allowed attribute names (strings). * * @see getMustAttrs * @see getMayAttrs * @see getMayAttrNames */ public function getMustAttrNames($parents=false) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } $attr_names = array(); foreach ($this->getMustAttrs($parents) as $attr) { array_push($attr_names, $attr->getName()); } return $attr_names; } /** * Gets an array of attribute names (strings) that entries of this ObjectClass must define. * This differs from getMayAttrs in that it returns an array of strings rather than * array of AttributeType objects * * @param bool $parents An array of ObjectClass objects to use when traversing * the inheritance tree. This presents some what of a bootstrapping problem * as we must fetch all objectClasses to determine through inheritance which * attributes this objectClass provides. * @return array The array of allowed attribute names (strings). * * @see getMustAttrs * @see getMayAttrs * @see getMustAttrNames */ public function getMayAttrNames($parents=false) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } $attr_names = array(); foreach ($this->getMayAttrs($parents) as $attr) { array_push($attr_names, $attr->getName()); } return $attr_names; } /** * Adds an objectClass to the list of objectClasses that inherit * from this objectClass. * * @param String $name The name of the objectClass to add * @return boolean Returns true on success or false on failure (objectclass already existed for example) */ public function addChildObjectClass($name) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } $name = trim($name); foreach ($this->children_objectclasses as $existing_objectclass) { if (strcasecmp($name, $existing_objectclass) == 0) { return FALSE; } } array_push($this->children_objectclasses,$name); } /** * Returns the array of objectClass names which inherit from this objectClass. * * @return Array Names of objectClasses which inherit from this objectClass. */ public function getChildObjectClasses() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } return $this->children_objectclasses; } /** * Gets the objectClass names from which this objectClass inherits. * * @return array An array of objectClass names (strings) */ public function getSupClasses() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } return $this->sup_classes; } /** * Return if this objectClass is related to $oclass * * @param array ObjectClasses that this attribute may be related to */ public function isRelated($oclass) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } # If I am in the array, we'll just return false if (in_array_ignore_case($this->name,$oclass)) { return FALSE; } $server = $_SESSION[APPCONFIG]->getServer($this->server_id); foreach ($oclass as $object_class) { $oc = $server->getSchemaObjectClass($object_class); if ($oc->isStructural() && in_array_ignore_case($this->getName(),$oc->getParents())) { return TRUE; } } return false; } /** * Gets the type of this objectClass: STRUCTURAL, ABSTRACT, or AUXILIARY. */ public function getType() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs, $this->type); } return $this->type; } /** * Adds the specified array of attributes to this objectClass' list of * MUST attributes. The resulting array of must attributes will contain * unique members. * * @param array $attr An array of attribute names (strings) to add. */ private function addMustAttrs($attr) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } if (! is_array($attr) || ! count($attr)) { return; } $this->must_attrs = array_values(array_unique(array_merge($this->must_attrs,$attr))); } /** * Behaves identically to addMustAttrs, but it operates on the MAY * attributes of this objectClass. * * @param array $attr An array of attribute names (strings) to add. */ private function addMayAttrs($attr) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } if (! is_array($attr) || ! count($attr)) { return; } $this->may_attrs = array_values(array_unique(array_merge($this->may_attrs,$attr))); } /** * Determine if an array is listed in the force_may attrs * @param $attr * @return bool */ public function isForceMay($attr) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } foreach ($this->force_may as $forcemay) { if ($forcemay->getName() == $attr) { return TRUE; } } return false; } public function isStructural() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } if ($this->type == 'structural') { return TRUE; } else { return FALSE; } } } /** * A simple class for representing AttributeTypes used only by the ObjectClass class. * Users should never instantiate this class. It represents an attribute internal to * an ObjectClass. If PHP supported inner-classes and variable permissions, this would * be interior to class ObjectClass and flagged private. The reason this class is used * and not the "real" class AttributeType is because this class supports the notion of * a "source" objectClass, meaning that it keeps track of which objectClass originally * specified it. This class is therefore used by the class ObjectClass to determine * inheritance. * * @package phpLDAPadmin * @subpackage Schema */ class ObjectClass_ObjectClassAttribute { # This Attribute's name (needs to be public, as we sort on it with masort). public $name; # This Attribute's root (needs to be public, as we sort on it with masort). public $source; /** * Creates a new ObjectClass_ObjectClassAttribute with specified name and source objectClass. * * @param string $name the name of the new attribute. * @param string $source the name of the ObjectClass which specifies this attribute. */ public function __construct($name,$source) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } $this->name = $name; $this->source = $source; } # Gets this attribute's name public function getName($lower=true) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs, $this->name); } return $lower ? strtolower($this->name) : $this->name; } # Gets the name of the ObjectClass which originally specified this attribute. public function getSource() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs, $this->source); } return $this->source; } } /** * Represents an LDAP AttributeType * * @package phpLDAPadmin * @subpackage Schema */ class AttributeType extends SchemaItem { # The attribute from which this attribute inherits (if any) private $sup_attribute = null; # The equality rule used private $equality = null; # The ordering of the attributeType private $ordering = null; # Boolean: supports substring matching? private $sub_str = null; # The full syntax string, ie 1.2.3.4{16} private $syntax = null; private $syntax_oid = null; # boolean: is single valued only? private $is_single_value = false; # boolean: is collective? private $is_collective = false; # boolean: can use modify? private $is_no_user_modification = false; # The usage string set by the LDAP schema private $usage = null; # An array of alias attribute names, strings private $aliases = array(); # The max number of characters this attribute can be private $max_length = null; # A string description of the syntax type (taken from the LDAPSyntaxes) private $type = null; # An array of objectClasses which use this attributeType (must be set by caller) private $used_in_object_classes = array(); # A list of object class names that require this attribute type. private $required_by_object_classes = array(); # This attribute has been forced a MAY attribute by the configuration. private $forced_as_may = false; /** * Creates a new AttributeType object from a raw LDAP AttributeType string. * @param $attr */ public function __construct($attr) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } $strings = preg_split('/[\s,]+/',$attr,-1,PREG_SPLIT_DELIM_CAPTURE); for($i=0; $iname)==0) { $this->name = $strings[$i]; } else { $this->name .= ' ' . $strings[$i]; } } while (! preg_match("/\'$/s",$strings[$i])); # This attribute has no aliases $this->aliases = array(); } else { $i++; do { # In case we came here becaues of a (' if (preg_match('/^\(/',$strings[$i])) { $strings[$i] = preg_replace('/^\(/', '', $strings[$i]); } else { $i++; } if (strlen($this->name) == 0) { $this->name = $strings[$i]; } else { $this->name .= ' ' . $strings[$i]; } } while (! preg_match("/\'$/s",$strings[$i])); # Add alias names for this attribute while ($strings[++$i] != ')') { $alias = $strings[$i]; $alias = preg_replace("/^\'/",'',$alias); $alias = preg_replace("/\'$/",'',$alias); $this->addAlias($alias); } } if (DEBUG_ENABLED) { debug_log('Case NAME returned (%s) (%s)', 8, 0, __FILE__, __LINE__, __METHOD__, $this->name, $this->aliases); } break; case 'DESC': do { $i++; if (strlen($this->description)==0) { $this->description .= $strings[$i]; } else { $this->description = $this->description . ' ' . $strings[$i]; } } while (! preg_match("/\'$/s",$strings[$i])); if (DEBUG_ENABLED) { debug_log('Case DESC returned (%s)', 8, 0, __FILE__, __LINE__, __METHOD__, $this->description); } break; case 'OBSOLETE': $this->is_obsolete = TRUE; if (DEBUG_ENABLED) { debug_log('Case OBSOLETE returned (%s)', 8, 0, __FILE__, __LINE__, __METHOD__, $this->is_obsolete); } break; case 'SUP': $i++; $this->sup_attribute = $strings[$i]; if (DEBUG_ENABLED) { debug_log('Case SUP returned (%s)', 8, 0, __FILE__, __LINE__, __METHOD__, $this->sup_attribute); } break; case 'EQUALITY': $i++; $this->equality = $strings[$i]; if (DEBUG_ENABLED) { debug_log('Case EQUALITY returned (%s)', 8, 0, __FILE__, __LINE__, __METHOD__, $this->equality); } break; case 'ORDERING': $i++; $this->ordering = $strings[$i]; if (DEBUG_ENABLED) { debug_log('Case ORDERING returned (%s)', 8, 0, __FILE__, __LINE__, __METHOD__, $this->ordering); } break; case 'SUBSTR': $i++; $this->sub_str = $strings[$i]; if (DEBUG_ENABLED) { debug_log('Case SUBSTR returned (%s)', 8, 0, __FILE__, __LINE__, __METHOD__, $this->sub_str); } break; case 'SYNTAX': $i++; $this->syntax = $strings[$i]; $this->syntax_oid = preg_replace('/{\d+}$/','',$this->syntax); # Does this SYNTAX string specify a max length (ie, 1.2.3.4{16}) if (preg_match('/{(\d+)}$/',$this->syntax,$this->max_length)) { $this->max_length = $this->max_length[1]; } else { $this->max_length = NULL; } if ($i < count($strings) - 1 && $strings[$i+1] == '{') { do { $i++; $this->name .= ' '.$strings[$i]; } while ($strings[$i] != '}'); } if (DEBUG_ENABLED) { debug_log('Case SYNTAX returned (%s) (%s) (%s)', 8, 0, __FILE__, __LINE__, __METHOD__, $this->syntax, $this->syntax_oid, $this->max_length); } break; case 'SINGLE-VALUE': $this->is_single_value = TRUE; if (DEBUG_ENABLED) { debug_log('Case SINGLE-VALUE returned (%s)', 8, 0, __FILE__, __LINE__, __METHOD__, $this->is_single_value); } break; case 'COLLECTIVE': $this->is_collective = TRUE; if (DEBUG_ENABLED) { debug_log('Case COLLECTIVE returned (%s)', 8, 0, __FILE__, __LINE__, __METHOD__, $this->is_collective); } break; case 'NO-USER-MODIFICATION': $this->is_no_user_modification = TRUE; if (DEBUG_ENABLED) { debug_log('Case NO-USER-MODIFICATION returned (%s)', 8, 0, __FILE__, __LINE__, __METHOD__, $this->is_no_user_modification); } break; case 'USAGE': $i++; $this->usage = $strings[$i]; if (DEBUG_ENABLED) { debug_log('Case USAGE returned (%s)', 8, 0, __FILE__, __LINE__, __METHOD__, $this->usage); } break; default: if (preg_match('/[\d\.]+/i',$strings[$i]) && $i == 1) { $this->setOID($strings[$i]); if (DEBUG_ENABLED) { debug_log('Case default returned (%s)', 8, 0, __FILE__, __LINE__, __METHOD__, $this->getOID()); } } } } $this->name = preg_replace("/^\'/",'',$this->name); $this->name = preg_replace("/\'$/",'',$this->name); $this->description = preg_replace("/^\'/",'',$this->description); $this->description = preg_replace("/\'$/",'',$this->description); $this->syntax = preg_replace("/^\'/",'',$this->syntax); $this->syntax = preg_replace("/\'$/",'',$this->syntax); $this->syntax_oid = preg_replace("/^\'/",'',$this->syntax_oid); $this->syntax_oid = preg_replace("/\'$/",'',$this->syntax_oid); $this->sup_attribute = preg_replace("/^\'/",'',$this->sup_attribute); $this->sup_attribute = preg_replace("/\'$/",'',$this->sup_attribute); if (DEBUG_ENABLED) { debug_log('Returning ()', 9, 0, __FILE__, __LINE__, __METHOD__); } } /** * Gets this attribute's usage string as defined by the LDAP server * * @return string */ public function getUsage() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs, $this->usage); } return $this->usage; } /** * Gets this attribute's parent attribute (if any). If this attribute does not * inherit from another attribute, null is returned. * * @return string */ public function getSupAttribute() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs, $this->sup_attribute); } return $this->sup_attribute; } /** * Gets this attribute's equality string * * @return string */ public function getEquality() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs, $this->equality); } return $this->equality; } /** * Gets this attribute's ordering specification. * * @return string */ public function getOrdering() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs, $this->ordering); } return $this->ordering; } /** * Gets this attribute's substring matching specification * * @return string */ public function getSubstr() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs, $this->sub_str); } return $this->sub_str; } /** * Gets the names of attributes that are an alias for this attribute (if any). * * @return array An array of names of attributes which alias this attribute or * an empty array if no attribute aliases this object. */ public function getAliases() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs, $this->aliases); } return $this->aliases; } /** * Returns whether the specified attribute is an alias for this one (based on this attribute's alias list). * * @param string $attr_name The name of the attribute to check. * @return boolean True if the specified attribute is an alias for this one, or false otherwise. */ public function isAliasFor($attr_name) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } foreach ($this->aliases as $alias_attr_name) { if (strcasecmp($alias_attr_name, $attr_name) == 0) { return TRUE; } } return false; } /** * Gets this attribute's raw syntax string (ie: "1.2.3.4{16}"). * * @return string The raw syntax string */ public function getSyntaxString() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs, $this->syntax); } return $this->syntax; } /** * Gets this attribute's syntax OID. Differs from getSyntaxString() in that this * function only returns the actual OID with any length specification removed. * Ie, if the syntax string is "1.2.3.4{16}", this function only retruns * "1.2.3.4". * * @return string The syntax OID string. */ public function getSyntaxOID() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs, $this->syntax_oid); } return $this->syntax_oid; } /** * Gets this attribute's the maximum length. If no maximum is defined by the LDAP server, null is returned. * * @return int The maximum length (in characters) of this attribute or null if no maximum is specified. */ public function getMaxLength() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs, $this->max_length); } return $this->max_length; } /** * Gets whether this attribute is single-valued. If this attribute only supports single values, true * is returned. If this attribute supports multiple values, false is returned. * * @return boolean Returns true if this attribute is single-valued or false otherwise. */ public function getIsSingleValue() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs, $this->is_single_value); } return $this->is_single_value; } /** * Sets whether this attribute is single-valued. * * @param boolean $is */ public function setIsSingleValue($is) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs); } $this->is_single_value = $is; } /** * Gets whether this attribute is collective. * * @return boolean Returns true if this attribute is collective and false otherwise. */ public function getIsCollective() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs, $this->is_collective); } return $this->is_collective; } /** * Gets whether this attribute is not modifiable by users. * * @return boolean Returns true if this attribute is not modifiable by users. */ public function getIsNoUserModification() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs, $this->is_no_user_modification); } return $this->is_no_user_modification; } /** * Gets this attribute's type * * @return string The attribute's type. */ public function getType() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs, $this->type); } return $this->type; } /** * Removes an attribute name from this attribute's alias array. * * @param string $remove_alias_name The name of the attribute to remove. * @return boolean true on success or false on failure (ie, if the specified * attribute name is not found in this attribute's list of aliases) */ public function removeAlias($remove_alias_name) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } foreach ($this->aliases as $i => $alias_name) { if (strcasecmp($alias_name,$remove_alias_name) == 0) { unset($this->aliases[$i]); $this->aliases = array_values($this->aliases); return true; } } return false; } /** * Adds an attribute name to the alias array. * * @param string $alias The name of a new attribute to add to this attribute's list of aliases. */ public function addAlias($alias) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } array_push($this->aliases,$alias); } /** * Sets this attriute's name. * * @param string $name The new name to give this attribute. */ public function setName($name) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs); } $this->name = $name; } /** * Sets this attriute's SUP attribute (ie, the attribute from which this attribute inherits). * * @param string $attr The name of the new parent (SUP) attribute */ public function setSupAttribute($attr) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs); } $this->sup_attribute = $attr; } /** * Sets this attribute's list of aliases. * * @param array $aliases The array of alias names (strings) */ public function setAliases($aliases) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs); } $this->aliases = $aliases; } /** * Sets this attribute's type. * * @param string $type The new type. */ public function setType($type) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs); } $this->type = $type; } /** * Adds an objectClass name to this attribute's list of "used in" objectClasses, * that is the list of objectClasses which provide this attribute. * * @param string $name The name of the objectClass to add. */ public function addUsedInObjectClass($name) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } foreach ($this->used_in_object_classes as $used_in_object_class) { if (DEBUG_ENABLED) { debug_log('Checking (%s) with (%s)', 8, 0, __FILE__, __LINE__, __METHOD__, $used_in_object_class, $name); } if (strcasecmp($used_in_object_class,$name) == 0) { return FALSE; } } array_push($this->used_in_object_classes,$name); } /** * Gets the list of "used in" objectClasses, that is the list of objectClasses * which provide this attribute. * * @return array An array of names of objectclasses (strings) which provide this attribute */ public function getUsedInObjectClasses() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs, $this->used_in_object_classes); } return $this->used_in_object_classes; } /** * Adds an objectClass name to this attribute's list of "required by" objectClasses, * that is the list of objectClasses which must have this attribute. * * @param string $name The name of the objectClass to add. */ public function addRequiredByObjectClass($name) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } foreach ($this->required_by_object_classes as $required_by_object_class) { if (strcasecmp($required_by_object_class, $name) == 0) { return FALSE; } } array_push($this->required_by_object_classes,$name); } /** * Gets the list of "required by" objectClasses, that is the list of objectClasses * which provide must have attribute. * * @return array An array of names of objectclasses (strings) which provide this attribute */ public function getRequiredByObjectClasses() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs, $this->required_by_object_classes); } return $this->required_by_object_classes; } /** * This function will mark this attribute as a forced MAY attribute */ public function setForceMay() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs); } $this->forced_as_may = true; } public function isForceMay() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs, $this->forced_as_may); } return $this->forced_as_may; } } /** * Represents an LDAP Syntax * * @package phpLDAPadmin * @subpackage Schema */ class Syntax extends SchemaItem { /** * Creates a new Syntax object from a raw LDAP syntax string. * @param $class */ public function __construct($class) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } $strings = preg_split('/[\s,]+/',$class,-1,PREG_SPLIT_DELIM_CAPTURE); for($i=0; $idescription) == 0) { $this->description .= $strings[$i]; } else { $this->description = $this->description . ' ' . $strings[$i]; } } while (! preg_match("/\'$/s",$strings[$i])); break; default: if (preg_match('/[\d\.]+/i',$strings[$i]) && $i == 1) { $this->setOID($strings[$i]); } } } $this->description = preg_replace("/^\'/",'',$this->description); $this->description = preg_replace("/\'$/",'',$this->description); } } /** * Represents an LDAP MatchingRule * * @package phpLDAPadmin * @subpackage Schema */ class MatchingRule extends SchemaItem { # This rule's syntax OID private $syntax = null; # An array of attribute names who use this MatchingRule private $used_by_attrs = array(); /** * Creates a new MatchingRule object from a raw LDAP MatchingRule string. * @param $strings */ public function __construct($strings) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } $strings = preg_split('/[\s,]+/',$strings,-1,PREG_SPLIT_DELIM_CAPTURE); for ($i=0; $iname) == 0) { $this->name = $strings[$i]; } else { $this->name .= ' ' . $strings[$i]; } } while (! preg_match("/\'$/s",$strings[$i])); } else { $i++; do { $i++; if (strlen($this->name) == 0) { $this->name = $strings[$i]; } else { $this->name .= ' ' . $strings[$i]; } } while (! preg_match("/\'$/s",$strings[$i])); do { $i++; } while (! preg_match('/\)+\)?/',$strings[$i])); } $this->name = preg_replace("/^\'/",'',$this->name); $this->name = preg_replace("/\'$/",'',$this->name); break; case 'DESC': do { $i++; if (strlen($this->description)==0) { $this->description .= $strings[$i]; } else { $this->description = $this->description . ' ' . $strings[$i]; } } while (! preg_match("/\'$/s",$strings[$i])); break; case 'OBSOLETE': $this->is_obsolete = TRUE; break; case 'SYNTAX': $this->syntax = $strings[++$i]; break; default: if (preg_match('/[\d\.]+/i',$strings[$i]) && $i == 1) { $this->setOID($strings[$i]); } } } $this->description = preg_replace("/^\'/",'',$this->description); $this->description = preg_replace("/\'$/",'',$this->description); } /** * Sets the list of used_by_attrs to the array specified by $attrs; * * @param array $attrs The array of attribute names (strings) which use this MatchingRule */ public function setUsedByAttrs($attrs) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs); } $this->used_by_attrs = $attrs; } /** * Adds an attribute name to the list of attributes who use this MatchingRule * * @param $attr * @return true if the attribute was added and false otherwise (already in the list) */ public function addUsedByAttr($attr) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } foreach ($this->used_by_attrs as $attr_name) { if (strcasecmp($attr_name, $attr) == 0) { return FALSE; } } array_push($this->used_by_attrs,$attr); return true; } /** * Gets an array of attribute names (strings) which use this MatchingRule * * @return array The array of attribute names (strings). */ public function getUsedByAttrs() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs, $this->used_by_attrs); } return $this->used_by_attrs; } } /** * Represents an LDAP schema matchingRuleUse entry * * @package phpLDAPadmin * @subpackage Schema */ class MatchingRuleUse extends SchemaItem { # An array of attribute names who use this MatchingRule private $used_by_attrs = array(); public function __construct($strings) { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 0, __FILE__, __LINE__, __METHOD__, $fargs); } $strings = preg_split('/[\s,]+/',$strings,-1,PREG_SPLIT_DELIM_CAPTURE); for($i=0; $iname) || strlen($this->name) == 0) { $this->name = $strings[$i]; } else { $this->name .= ' ' . $strings[$i]; } } while (! preg_match("/\'$/s",$strings[$i])); } else { $i++; do { $i++; if (strlen($this->name) == 0) { $this->name = $strings[$i]; } else { $this->name .= ' ' . $strings[$i]; } } while (! preg_match("/\'$/s",$strings[$i])); do { $i++; } while (! preg_match('/\)+\)?/',$strings[$i])); } $this->name = preg_replace("/^\'/",'',$this->name); $this->name = preg_replace("/\'$/",'',$this->name); break; case 'APPLIES': if ($strings[$i+1] != '(') { # Has a single attribute name $i++; $this->used_by_attrs = array($strings[$i]); } else { # Has multiple attribute names $i++; while ($strings[$i] != ')') { $i++; $new_attr = $strings[$i]; $new_attr = preg_replace("/^\'/",'',$new_attr); $new_attr = preg_replace("/\'$/",'',$new_attr); array_push($this->used_by_attrs,$new_attr); $i++; } } break; default: if (preg_match('/[\d\.]+/i',$strings[$i]) && $i == 1) { $this->setOID($strings[$i]); } } } sort($this->used_by_attrs); } /** * Gets an array of attribute names (strings) which use this MatchingRuleUse object. * * @return array The array of attribute names (strings). */ public function getUsedByAttrs() { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) { debug_log('Entered (%%)', 9, 1, __FILE__, __LINE__, __METHOD__, $fargs, $this->used_by_attrs); } return $this->used_by_attrs; } }