diff --git a/README.md b/README.md index 598953de..50c4e115 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Take a look at the [Docker Container](https://github.com/leenooks/phpLDAPadmin/w The update to v2 is progressing well - here is a list of work to do and done: -- [ ] Creating new LDAP entries +- [X] Creating new LDAP entries - [ ] Delete existing LDAP entries - [X] Updating existing LDAP Entries - [X] Password attributes diff --git a/app/Classes/LDAP/Attribute.php b/app/Classes/LDAP/Attribute.php index 4ae4c195..a60ce120 100644 --- a/app/Classes/LDAP/Attribute.php +++ b/app/Classes/LDAP/Attribute.php @@ -311,707 +311,4 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator { $this->is_rdn = TRUE; } - - /** - * Return the name of the attribute. - * - * @param boolean $lower - Return the attribute in normal or lower case (default lower) - * @param boolean $real - Return the real attribute name (with ;binary, or just the name) - * @return string Attribute name - * - public function getName($lower=true,$real=false) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs,$this->name); - - if ($real) - return $lower ? strtolower($this->name) : $this->name; - else - return $lower ? strtolower($this->real_attr_name()) : $this->real_attr_name(); - } - - public function getValues() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->values); - - return $this->values; - } - - public function getOldValues() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->oldvalues); - - return $this->oldvalues; - } - - public function getValueCount() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs,$this->values); - - return count($this->values); - } - - public function getSource() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->source); - - return $this->source; - } - - /** - * Autovalue is called after the attribute is initialised, and thus the values from the ldap server will be set. - * - public function autoValue($new_val) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); - - if ($this->values) - return; - - $this->values = $new_val; - } - - public function initValue($new_val) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); - - if ($this->values || $this->oldvalues) { - debug_dump(array('new_val'=>$new_val,'this'=>$this)); - debug_dump_backtrace('new and/or old values are set',1); - } - - $this->values = $new_val; - } - - public function clearValue() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $this->values = array(); - } - - public function setOldValue($val) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); - - $this->oldvalues = $val; - } - - public function setValue($new_val) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); - - if ($this->values) { - if ($this->values == $new_val) - return; - - if ($this->oldvalues) { - debug_dump($this); - debug_dump_backtrace('old values are set',1); - } else - $this->oldvalues = $this->values; - } - - if ($new_val == $this->values) - return; - - $this->values = $new_val; - $this->justModified(); - } - - public function addValue($new_val,$i=-1) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); - - if ($i < 0) - $i = $this->getValueCount(); - - $old_val = $this->getValue($i); - if (is_null($old_val) || ($old_val != $new_val)) - $this->justModified(); - - $this->values[$i] = $new_val; - } - - public function delValue($i=-1) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); - - if ($i < 0) - $this->setValue(array()); - - if (! $this->hasBeenModified()) - $this->oldvalues = $this->values; - - if (isset($this->values[$i])) { - unset($this->values[$i]); - $this->values = array_values($this->values); - $this->justModified(); - } - } - - public function justModified() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $this->modified = true; - } - - public function hasBeenModified() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->modified); - - return $this->modified; - } - - public function isForceDelete() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->forcedelete); - - return $this->forcedelete; - } - - public function setForceDelete() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $this->forcedelete = true; - $this->oldvalues = $this->values; - $this->values = array(); - $this->justModified(); - } - - public function isRequired() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); - - if ($this->getMinValueCount() > 0) - return true; - elseif ($this->ldaptype == 'must') - return true; - elseif ($this->isRDN()) - return true; - else - return false; - } - - public function isMay() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); - - if (($this->ldaptype == 'may') && ! $this->isRequired()) - return true; - else - return false; - } - - public function setType($type) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); - - $this->type = strtolower($type); - } - - public function getType() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->type); - - return $this->type; - } - - public function setLDAPtype($type) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); - - $this->ldaptype = strtolower($type); - } - - public function getLDAPtype() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->ldaptype); - - return $this->ldaptype; - } - - public function setProperties($properties) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); - - foreach ($properties as $index => $value) { - if ($index == 'maxvalnb') { - $this->setMaxValueCount($value); - continue; - - } elseif ($index == 'minvalnb') { - $this->setMinValueCount($value); - continue; - - } elseif ($index == 'maxlength') { - $this->setMinValueCount($value); - continue; - - } elseif ($index == 'hidden') { - $this->visible = $value; - continue; - - } elseif (in_array($index,array('cols','rows'))) { - # @todo To be implemented - continue; - } - - if (isset($this->$index)) - $this->$index = $value; - else { - debug_dump($this); - debug_dump_backtrace(sprintf('Unknown property (%s) with value (%s) for (%s)',$index,$value,$this->getName()),1); - } - } - } - - public function setRequired() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); - - if ($this->getMinValueCount() <= 0) - $this->setMinValueCount(1); - } - - public function setOptional() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); - - $this->setMinValueCount(0); - } - - public function isReadOnly() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->readonly); - - return $this->readonly; - } - - public function setReadOnly() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $this->readonly = true; - } - - public function isMultiple() { - return false; - } - - public function isVisible() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); - - return $this->visible && (! $this->forcehide); - } - - public function hide() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $this->visible = false; - } - - public function show() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $this->visible = true; - } - - public function haveFriendlyName() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); - - return $_SESSION[APPCONFIG]->haveFriendlyName($this); - } - - public function getFriendlyName() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->display); - - if ($this->display) - return $this->display; - else - return $_SESSION[APPCONFIG]->getFriendlyName($this); - } - - public function setDescription($description) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); - - $this->description = $description; - } - - public function getDescription() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->description); - - return $this->description; - } - - public function setIcon($icon) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); - - $this->icon = $icon; - } - - public function getIcon() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->icon); - - return $this->icon ? sprintf('%s/%s',IMGDIR,$this->icon) : ''; - } - - public function getHint() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->hint); - - return $this->hint; - } - - public function setHint($hint) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); - - $this->hint = $hint; - } - - public function getMaxLength() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->maxlength); - - return $this->maxlength; - } - - public function setMaxLength($maxlength) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); - - $this->maxlength = $maxlength; - } - - public function getSize() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->size); - - return $this->size; - } - - public function setSize($size) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); - - $this->size = $size; - } - - public function getSpacer() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->spacer); - - return $this->spacer; - } - - public function getPage() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->page); - - return $this->page; - } - public function setPage($page) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); - - $this->page = $page; - } - - public function getOnChange() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->onchange); - - return $this->onchange; - } - - public function getHelper() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->helper); - - return $this->helper; - } - - public function getHelperValue() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->helpervalue); - - return $this->helpervalue; - } - - public function getVerify() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->verify); - - return $this->verify; - } - - /** - * Capture all the LDAP details we are interested in - * - * @param sattr Schema Attribute - * - private function setLDAPdetails($sattr) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); - - # By default, set this as a MAY attribute, later processing should make it a MUST attribute if it is. - if (! $this->ldaptype) - $this->ldaptype = 'may'; - - # Store our Aliases - foreach ($sattr->getAliases() as $alias) - array_push($this->aliases,strtolower($alias)); - - if ($sattr->getIsSingleValue()) - $this->setMaxValueCount(1); - } - - /** - * Return a list of aliases for this Attribute (as defined by the schema) - * This list will be lowercase. - * - public function getAliases() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->aliases); - - return $this->aliases; - } - - public function getAutoValue() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->autovalue); - - return $this->autovalue; - } - - public function getPostValue() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->postvalue); - - return $this->postvalue; - } - - public function setPostValue($postvalue) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs); - - $this->postvalue = $postvalue; - } - - public function setXML($values) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); - - # Mostly all the time, this should be an array - if (is_array($values)) - foreach ($values as $index => $value) - switch ($index) { - # Helpers should be accompanied with a attribute. - case 'helper': - if (! isset($values['post']) && ! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning')) - system_message(array( - 'title'=>sprintf('%s [%s]',_('Missing [post] setting in XML file'),$index), - 'body'=>_('[helper] needs an accompanying [post] action.'), - 'type'=>'warn')); - - if (isset($value['value']) && ! is_array($value['value']) && preg_match('/^=php\.(\w+)\((.*)\)$/',$value['value'],$matches)) { - $this->helpervalue['function'] = $matches[1]; - $this->helpervalue['args'] = $matches[2]; - - unset ($value['value']); - } - - foreach ($value as $i => $detail) { - if (! in_array($i,array('default','display','id','value'))) { - if (! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning')) - system_message(array( - 'title'=>sprintf('%s [%s]',_('Unknown XML setting'),$i), - 'body'=>sprintf('%s [%s]',_('Unknown XML type setting for helper will be ignored.'),$detail), - 'type'=>'warn')); - - unset($value[$i]); - } - } - - $this->$index = $value; - - break; - - case 'hidden': $value ? $this->visible = false : $this->visible = true; - break; - - case 'spacer': $value ? $this->$index = true : $this->$index = false; - break; - - # Essentially, we ignore type, it is used to select an Attribute type in the Factory. But we'll generated a warning if there is an unknown type. - case 'type': - if (! in_array($value,array('password','multiselect','select','textarea')) && ! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning')) - system_message(array( - 'title'=>sprintf('%s [%s]',_('Unknown XML setting'),$index), - 'body'=>sprintf('%s [%s]',_('Unknown XML type setting will be ignored.'),$value), - 'type'=>'warn')); - - break; - - case 'post': - if (preg_match('/^=php\.(\w+)\((.*)\)$/',$value,$matches)) { - $this->postvalue['function'] = $matches[1]; - $this->postvalue['args'] = $matches[2]; - - } else - if (! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning')) - system_message(array( - 'title'=>sprintf('%s [%s]',_('Unknown XML setting'),$index), - 'body'=>sprintf('%s [%s]',_('Unknown XML type setting will be ignored.'),$value), - 'type'=>'warn')); - - case 'value': - if (is_array($value)) - foreach ($value as $x => $y) { - if (! $this->haveMoreValues()) { - system_message(array( - 'title'=>_('Automatically removed attribute values from template'), - 'body'=>sprintf('%s [%s]',_('Template defines more values than can be accepted by attribute.'),$this->getName(true)), - 'type'=>'warn')); - - $this->clearValue(); - - break; - - } else - $this->addValue($x,$y); - } - - else - # Check to see if the value is auto generated. - if (preg_match('/^=php\.(\w+)\((.*)\)$/',$value,$matches)) { - $this->autovalue['function'] = $matches[1]; - $this->autovalue['args'] = $matches[2]; - - # We'll add a hint too - if (! $this->hint) - $this->hint = _('Automatically determined'); - - } else - $this->addValue($value); - - break; - - # Queries - case 'ordersort': - - # Creation/Editing Templates - case 'cols': - case 'default': - case 'display': - case 'hint': - case 'icon': - case 'maxlength': - case 'onchange': - case 'order': - case 'page': - case 'readonly': - case 'rows': - case 'size': - case 'values': - case 'verify': $this->$index = $value; - break; - - case 'max': - if ($this->getMaxValueCount() == -1) - $this->setMaxValueCount($value); - - default: - if (! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning')) - system_message(array( - 'title'=>sprintf('%s [%s]',_('Unknown XML setting'),$index), - 'body'=>sprintf('%s [%s]',_('Unknown attribute setting will be ignored.'),serialize($value)), - 'type'=>'warn')); - } - - elseif (is_string($values) && (strlen($values) > 0)) - $this->values = array($values); - } - - /** - * Display the values removed in an attribute. - * - public function getRemovedValues() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); - - return array_diff($this->getOldValues(),$this->getValues()); - } - - /** - * Display the values removed in an attribute. - * - public function getAddedValues() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); - - return array_diff($this->getValues(),$this->getOldValues()); - } - - /** - * Prunes off anything after the ";" in an attr name. This is useful for - * attributes that may have ";binary" appended to their names. With - * real_attr_name(), you can more easily fetch these attributes' schema - * with their "real" attribute name. - * - * @param string $attr_name The name of the attribute to examine. - * @return string - * - private function real_attr_name() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->name); - - return preg_replace('/;.*$/U','',$this->name); - } - - /** - * Does this attribute need supporting JS - * - public function needJS($type=null) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',5,0,__FILE__,__LINE__,__METHOD__,$fargs); - - if (is_null($type)) { - foreach (array('focus','blur','validate') as $type) - if ($this->needJS($type)) - return true; - - return false; - - } elseif ($type == 'focus') { - # We dont have any focus javascript routines. - return false; - - } elseif ($type == 'blur') { - if ($this->onchange || $this->isRequired()) - return true; - else - return false; - - } elseif ($type == 'validate') { - if ($this->isRequired()) - return true; - else - return false; - - } else - debug_dump_backtrace(sprintf('Unknown JS request %s',$type),1); - } - */ } \ No newline at end of file diff --git a/app/Classes/LDAP/Schema/AttributeType.php b/app/Classes/LDAP/Schema/AttributeType.php index 25ddc8e7..49d8f841 100644 --- a/app/Classes/LDAP/Schema/AttributeType.php +++ b/app/Classes/LDAP/Schema/AttributeType.php @@ -418,18 +418,6 @@ final class AttributeType extends Base { return $this->ordering; } - /** - * 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; - } /** * Gets this attribute's substring matching specification * @@ -465,29 +453,6 @@ final class AttributeType extends Base { return $this->syntax_oid; } - /** - * 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 type - * - * @return string The attribute's type. - * @deprecated use $this->type; - */ - public function getType() - { - return $this->type; - } - /** * Gets this attribute's usage string as defined by the LDAP server * @@ -511,23 +476,6 @@ final class AttributeType extends Base { return $this->used_in_object_classes; } - /** - * 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; - } - /** * @return bool * @deprecated use $this->forced_as_may @@ -563,9 +511,6 @@ final class AttributeType extends Base { * 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; } @@ -589,18 +534,6 @@ final class AttributeType extends Base { $this->sup_attribute = trim($attr); } - /** - * 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; - } - /** * Return Request validation array * diff --git a/app/Classes/LDAP/Server.php b/app/Classes/LDAP/Server.php index cf9124ca..cf2e3695 100644 --- a/app/Classes/LDAP/Server.php +++ b/app/Classes/LDAP/Server.php @@ -338,16 +338,6 @@ final class Server break; - /* - case 'matchingruleuse': - if (isset($this->matchingruleuse)) - return is_null($key) ? $this->matchingruleuse : $this->matchingruleuse->get($key); - else - $this->matchingruleuse = collect(); - - break; - */ - case 'objectclasses': if (isset($this->objectclasses)) return $this->objectclasses; @@ -381,21 +371,6 @@ final class Server $o = new AttributeType($line); $this->attributetypes->put($o->name_lc,$o); - - /* - if (isset($syntaxes[$attr->getSyntaxOID()])) { - $syntax = $syntaxes[$attr->getSyntaxOID()]; - $attr->setType($syntax->getDescription()); - } - $this->attributetypes[$attr->getName()] = $attr; - */ - - /** - * bug 856832: create an entry in the $attrs_oid array too. This - * will be a ref to the $attrs entry for maintenance and performance - * reasons - */ - //$attrs_oid[$attr->getOID()] = &$attrs[$attr->getName()]; } // go back and add data from aliased attributeTypes diff --git a/htdocs/common.php b/htdocs/common.php deleted file mode 100644 index de4122c5..00000000 --- a/htdocs/common.php +++ /dev/null @@ -1,14 +0,0 @@ - diff --git a/htdocs/create.php b/htdocs/create.php deleted file mode 100644 index e9c69fb7..00000000 --- a/htdocs/create.php +++ /dev/null @@ -1,103 +0,0 @@ -getIndex(),get_request('template','REQUEST',false,'none')); -$request['page']->setContainer(get_request('container','REQUEST',true)); -$request['page']->accept(); -$request['template'] = $request['page']->getTemplate(); - -if ((! $request['template']->getContainer() || ! $app['server']->dnExists($request['template']->getContainer())) && ! get_request('create_base')) - error(sprintf(_('The container you specified (%s) does not exist. Please try again.'),$request['template']->getContainer()),'error','index.php'); - -# Check if the container is a leaf - we shouldnt really return a hit here, the template engine shouldnt have allowed a user to attempt to create an entry... -$tree = get_cached_item($app['server']->getIndex(),'tree'); - -$request['container'] = $tree->getEntry($request['template']->getContainer()); -if (! $request['container'] && ! get_request('create_base')) { - $tree->addEntry($request['template']->getContainer()); - $request['container'] = $tree->getEntry($request['template']->getContainer()); -} - -# Check our RDN -if (! count($request['template']->getRDNAttrs())) - error(_('The were no attributes marked as an RDN attribute.'),'error','index.php'); -if (! $request['template']->getRDN()) - error(_('The RDN field is empty?'),'error','index.php'); - -# Some other attribute checking... -foreach ($request['template']->getAttributes() as $attribute) { - # Check that our Required Attributes have a value - we shouldnt really return a hit here, the template engine shouldnt have allowed this to slip through. - if ($attribute->isRequired() && ! count($attribute->getValues())) - error(sprintf(_('You left the value blank for required attribute (%s).'), - $attribute->getName(false)),'error','index.php'); -} - -# Create the entry -$add_result = $app['server']->add($request['template']->getDN(),$request['template']->getLDAPadd()); - -if ($add_result) { - $action_number = $_SESSION[APPCONFIG]->getValue('appearance','action_after_creation'); - $href = sprintf('cmd=template_engine&server_id=%s',$app['server']->getIndex()); - - if ($request['redirect']) - $redirect_url = $request['redirect']; - - else if ($action_number == 2) - $redirect_url = sprintf('cmd.php?%s&template=%s&container=%s', - $href,'default',$request['template']->getContainerEncode()); - - else - $redirect_url = sprintf('cmd.php?%s&template=%s&dn=%s', - $href,'default',$request['template']->getDNEncode()); - - if ($action_number == 1 || $action_number == 2) - printf('',$redirect_url); - - if ($action_number == 1 || $action_number == 2) { - $create_message = sprintf('%s %s: %s %s', - _('Creation successful!'),_('DN'),$request['template']->getDN(),_('has been created.')); - - if (isAjaxEnabled()) - $redirect_url .= sprintf('&refresh=SID_%s_nodes&noheader=1',$app['server']->getIndex()); - - system_message(array( - 'title'=>_('Create Entry'), - 'body'=>$create_message, - 'type'=>'info'), - $redirect_url); - - } else { - $request['page']->drawTitle(_('Entry created')); - $request['page']->drawSubTitle(sprintf('%s: %s   %s: %s', - _('Server'),$app['server']->getName(),_('Distinguished Name'),$request['template']->getDN())); - - echo '
'; - echo '
'; - printf('%s.', - htmlspecialchars($href),rawurlencode($request['template']->getDN()),_('Display the new created entry')); - echo '
'; - printf('%s.', - htmlspecialchars($href),rawurlencode($request['template']->getContainer()),_('Create another entry')); - echo '
'; - } -} -?> diff --git a/htdocs/create_confirm.php b/htdocs/create_confirm.php deleted file mode 100644 index 96a30a85..00000000 --- a/htdocs/create_confirm.php +++ /dev/null @@ -1,142 +0,0 @@ -getIndex(),get_request('template','REQUEST',false,'none')); -$request['page']->setContainer(get_request('container','REQUEST',true)); -$request['page']->accept(); -$request['template'] = $request['page']->getTemplate(); - -if (! $request['template']->getContainer() || ! $app['server']->dnExists($request['template']->getContainer())) - error(sprintf(_('The container you specified (%s) does not exist. Please try again.'),$request['template']->getContainer()),'error','index.php'); - -# Check if the container is a leaf - we shouldnt really return a hit here, the template engine shouldnt have allowed a user to attempt to create an entry... -$tree = get_cached_item($app['server']->getIndex(),'tree'); - -$request['container'] = $tree->getEntry($request['template']->getContainer()); -if (! $request['container']) { - $tree->addEntry($request['template']->getContainer()); - $request['container'] = $tree->getEntry($request['template']->getContainer()); -} - -# Check our RDN -if (! count($request['template']->getRDNAttrs())) - error(_('The were no attributes marked as an RDN attribute.'),'error','index.php'); -if (! $request['template']->getRDN()) - error(_('The RDN field is empty?'),'error','index.php'); - -# Some other attribute checking... -foreach ($request['template']->getAttributes() as $attribute) { - # Check that our Required Attributes have a value - we shouldnt really return a hit here, the template engine shouldnt have allowed this to slip through. - if ($attribute->isRequired() && ! count($attribute->getValues())) - error(sprintf(_('You left the value blank for required attribute (%s).'), - $attribute->getName(false)),'error','index.php'); -} - -# Check for unique attributes -$app['server']->checkUniqueAttrs($request['template']->getDN(),$request['template']->getLDAPadd()); - -$request['page']->drawTitle(_('Create LDAP Entry')); -$request['page']->drawSubTitle(sprintf('%s: %s   %s: %s', - _('Server'),$app['server']->getName(),_('Container'),$request['template']->getContainer())); - -# Confirm the creation -if (count($request['template']->getLDAPadd(true))) { - echo '
'; - echo _('Do you want to create this entry?'); - echo '

'; - echo '
'; - - echo "\n\n"; - echo '
'; - echo '
'; - echo ''; - printf('',$app['server']->getIndex()); - printf('',$request['template']->getContainerEncode(false)); - printf('',$request['template']->getID()); - foreach ($request['template']->getRDNAttrs() as $rdn) - printf('',htmlspecialchars($rdn)); - echo "\n"; - - $request['page']->drawHiddenAttributes(); - echo '
'; - - echo ''; - echo "\n"; - - printf('', - _('Attribute'),_('New Value'),_('Skip')); - echo "\n\n"; - - $counter = 0; - printf('',$counter%2 ? 'even' : 'odd',htmlspecialchars($request['template']->getDN())); - - foreach ($request['template']->getLDAPadd(true) as $attribute) { - $counter++; - - printf('',$counter%2 ? 'even' : 'odd'); - printf('',$attribute->getFriendlyName()); - - # Show NEW Values - echo ''; - - # Show SKIP Option - $input_disabled = ''; - $input_onclick = ''; - - if ($attribute->isRequired()) - $input_disabled = 'disabled="disabled"'; - - printf('', - htmlspecialchars($attribute->getName()),htmlspecialchars($attribute->getName()),$input_disabled,$input_onclick); - echo ''; - echo "\n\n"; - } - - echo '
%s%s%s
%s
%s'; - $request['page']->draw('CurrentValues',$attribute); - echo '
'; - - echo '
'; - echo '
'; - - printf('', - _('Commit'), - (isAjaxEnabled() ? sprintf('onclick="return ajSUBMIT(\'BODY\',document.getElementById(\'create_form\'),\'%s\');"',_('Updating Object')) : '')); - - printf('', - _('Cancel'), - (isAjaxEnabled() ? sprintf('onclick="return ajDISPLAY(\'BODY\',\'cmd=template_engine&server_id=%s&container=%s\',\'%s\');"',$app['server']->getIndex(),$request['template']->getContainer(),_('Retrieving DN')) : '')); - - echo '
'; - echo '
'; - echo '
'; - -} else { - $href = sprintf('cmd=template_engine&server_id=%s&dn=%s', - $app['server']->getIndex(),$request['template']->getDNEncode()); - - echo '
'; - echo _('You made no changes'); - - if (isAjaxEnabled()) - printf(' %s.', - htmlspecialchars($href),htmlspecialchars($href),_('Retrieving DN'),_('Go back')); - else - printf(' %s.',htmlspecialchars($href),_('Go back')); - - echo '
'; -} -?> diff --git a/htdocs/password_checker.php b/htdocs/password_checker.php deleted file mode 100644 index c616e2e7..00000000 --- a/htdocs/password_checker.php +++ /dev/null @@ -1,88 +0,0 @@ -%s',_('Password Checker Tool')); - -echo '
'; -echo ''; -printf('',$request['attribute']); - -echo ''; - -echo ''; -printf('',_('Compare')); -printf('', - (obfuscate_password_display($request['enc_type']) ? 'password' : 'text'),htmlspecialchars($request['hash'])); -echo ''; - -echo ''; -printf('',_('To')); -printf('', - htmlspecialchars($request['password'])); -echo ''; - -echo ''; -echo ''; - -echo ''; -echo ''; -echo '
%s
%s
 '; - -if ($request['action'] == 'compare') { - echo '    '; - - if (password_check($request['hash'],$request['password'],$request['attribute'])) - printf('%s',_('Passwords match!')); - else - printf('%s',_('Passwords do not match!')); - - echo ''; -} - -echo '
'; -echo '
'; - -# Pull our password from the form that opened this window. -if ($request['componentid']) { - echo ''; -} - -# Capture the output and put into the body of the page. -$www['body'] = new block(); -$www['body']->SetBody(ob_get_contents()); -$www['page']->block_add('body',$www['body']); -ob_end_clean(); - -# Render the popup. -$www['page']->display(array('CONTROL'=>false,'FOOT'=>false,'HEAD'=>false,'TREE'=>false)); -?> diff --git a/lib/ds.php b/lib/ds.php deleted file mode 100644 index 4b272279..00000000 --- a/lib/ds.php +++ /dev/null @@ -1,735 +0,0 @@ -', any custom extra connection to ds. - */ - abstract public function login($user=null,$pass=null,$method=null); - - /** - * Query the datasource - */ - abstract public function query($query,$method,$index=null,$debug=false); - - /** - * Return error details from previous operation - */ - abstract protected function getErrorMessage(); - abstract protected function getErrorNum(); - - /** - * Functions that set and verify object configuration details - */ - public function setDefaults($defaults) { - foreach ($defaults as $key => $details) - foreach ($details as $setting => $value) - $this->default->{$key}[$setting] = $value; - } - - public function isDefaultKey($key) { - return isset($this->default->$key); - } - - public function isDefaultSetting($key,$setting) { - return array_key_exists($setting,$this->default->{$key}); - } - - /** - * Return a configuration value - */ - public function getValue($key,$setting,$fatal=true) { - if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',17,1,__FILE__,__LINE__,__METHOD__,$fargs); - - if (isset($this->custom->{$key}[$setting])) - return $this->custom->{$key}[$setting]; - - elseif (isset($this->default->{$key}[$setting]) && array_key_exists('default',$this->default->{$key}[$setting])) - return $this->default->{$key}[$setting]['default']; - - elseif ($fatal) - debug_dump_backtrace("Error trying to get a non-existant value ($key,$setting)",1); - - else - return null; - } - - /** - * Set a configuration value - */ - public function setValue($key,$setting,$value) { - if (isset($this->custom->{$key}[$setting])) - system_message(array( - 'title'=>_('Configuration setting already defined.'), - 'body'=>sprintf('A call has been made to reset a configuration value (%s,%s,%s)', - $key,$setting,$value), - 'type'=>'info')); - - $this->custom->{$key}[$setting] = $value; - } - - /** - * Return the untested config items - */ - public function untested() { - $result = array(); - - foreach ($this->default as $option => $details) - foreach ($details as $param => $values) - if (isset($values['untested']) && $values['untested']) - array_push($result,sprintf('%s.%s',$option,$param)); - - return $result; - } - - /** - * Get the name of this datastore - */ - public function getName() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); - - return $this->getValue('server','name'); - } - - /** - * Functions that enable login and logout of the application - */ - /** - * Return the authentication type for this object - */ - public function getAuthType() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); - - switch ($this->getValue('login','auth_type')) { - case 'cookie': - case 'config': - case 'http': - case 'proxy': - case 'session': - case 'sasl': - return $this->getValue('login','auth_type'); - - default: - die(sprintf('Error: %s hasnt been configured for auth_type %s',__METHOD__, - $this->getValue('login','auth_type'))); - } - } - - /** - * Get the login name of the user logged into this datastore's connection method - * If this returns null, we are not logged in. - * If this returns '', we are logged in with anonymous - */ - public function getLogin($method=null) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $method = $this->getMethod($method); - - # For anonymous binds - if ($method == 'anon') - if (isset($_SESSION['USER'][$this->index][$method]['name'])) - return ''; - else - return null; - - switch ($this->getAuthType()) { - case 'cookie': - if (! isset($_COOKIE[$method.'-USER'])) - # If our bind_id is set, we'll pass that back for logins. - return (! is_null($this->getValue('login','bind_id')) && $method == 'login') ? $this->getValue('login','bind_id') : null; - else - return blowfish_decrypt($_COOKIE[$method.'-USER']); - - case 'config': - if (! isset($_SESSION['USER'][$this->index][$method]['name'])) - return $this->getValue('login','bind_id'); - else - return blowfish_decrypt($_SESSION['USER'][$this->index][$method]['name']); - - case 'proxy': - if (! isset($_SESSION['USER'][$this->index][$method]['proxy'])) - return $this->getValue('login','bind_id'); - else - return blowfish_decrypt($_SESSION['USER'][$this->index][$method]['proxy']); - - case 'http': - case 'session': - case 'sasl': - if (! isset($_SESSION['USER'][$this->index][$method]['name'])) - # If our bind_id is set, we'll pass that back for logins. - return (! is_null($this->getValue('login','bind_id')) && $method == 'login') ? $this->getValue('login','bind_id') : null; - else - return blowfish_decrypt($_SESSION['USER'][$this->index][$method]['name']); - - default: - die(sprintf('Error: %s hasnt been configured for auth_type %s',__METHOD__,$this->getAuthType())); - } - } - - /** - * Set the login details of the user logged into this datastore's connection method - */ - protected function setLogin($user,$pass,$method=null) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $method = $this->getMethod($method); - - switch ($this->getAuthType()) { - case 'cookie': - set_cookie($method.'-USER',blowfish_encrypt($user),NULL,'/'); - set_cookie($method.'-PASS',blowfish_encrypt($pass),NULL,'/'); - return true; - - case 'config': - return true; - - case 'proxy': - if (isset($_SESSION['USER'][$this->index][$method]['proxy'])) - unset($_SESSION['USER'][$this->index][$method]['proxy']); - - case 'http': - case 'session': - case 'sasl': - $_SESSION['USER'][$this->index][$method]['name'] = blowfish_encrypt($user); - $_SESSION['USER'][$this->index][$method]['pass'] = blowfish_encrypt($pass); - - return true; - - default: - die(sprintf('Error: %s hasnt been configured for auth_type %s',__METHOD__,$this->getAuthType())); - } - } - - /** - * Get the login password of the user logged into this datastore's connection method - */ - protected function getPassword($method=null) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $method = $this->getMethod($method); - - # For anonymous binds - if ($method == 'anon') - if (isset($_SESSION['USER'][$this->index][$method]['name'])) - return ''; - else - return null; - - switch ($this->getAuthType()) { - case 'cookie': - if (! isset($_COOKIE[$method.'-PASS'])) - # If our bind_id is set, we'll pass that back for logins. - return (! is_null($this->getValue('login','bind_pass')) && $method == 'login') ? $this->getValue('login','bind_pass') : null; - else - return blowfish_decrypt($_COOKIE[$method.'-PASS']); - - case 'config': - case 'proxy': - if (! isset($_SESSION['USER'][$this->index][$method]['pass'])) - return $this->getValue('login','bind_pass'); - else - return blowfish_decrypt($_SESSION['USER'][$this->index][$method]['pass']); - - case 'http': - case 'session': - case 'sasl': - if (! isset($_SESSION['USER'][$this->index][$method]['pass'])) - # If our bind_pass is set, we'll pass that back for logins. - return (! is_null($this->getValue('login','bind_pass')) && $method == 'login') ? $this->getValue('login','bind_pass') : null; - else - return blowfish_decrypt($_SESSION['USER'][$this->index][$method]['pass']); - - default: - die(sprintf('Error: %s hasnt been configured for auth_type %s',__METHOD__,$this->getAuthType())); - } - } - - /** - * Return if this datastore's connection method has been logged into - */ - public function isLoggedIn($method=null) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); - - static $CACHE = array(); - - $method = $this->getMethod($method); - - if (isset($CACHE[$this->index][$method]) && ! is_null($CACHE[$this->index][$method])) - return $CACHE[$this->index][$method]; - - $CACHE[$this->index][$method] = null; - - # For some authentication types, we need to do the login here - switch ($this->getAuthType()) { - case 'config': - if (! $CACHE[$this->index][$method] = $this->login($this->getLogin($method),$this->getPassword($method),$method)) - system_message(array( - 'title'=>_('Unable to login.'), - 'body'=>_('Your configuration file has authentication set to CONFIG based authentication, however, the userid/password failed to login'), - 'type'=>'error')); - - break; - - case 'http': - # If our auth vars are not set, throw up a login box. - if (! isset($_SERVER['PHP_AUTH_USER'])) { - # If this server is not in focus, skip the basic auth prompt. - if (get_request('server_id','REQUEST') != $this->getIndex()) { - $CACHE[$this->index][$method] = false; - break; - } - - header(sprintf('WWW-Authenticate: Basic realm="%s %s"',app_name(),_('login'))); - - if ($_SERVER['SERVER_PROTOCOL'] == 'HTTP/1.0') - header('HTTP/1.0 401 Unauthorized'); // http 1.0 method - else - header('Status: 401 Unauthorized'); // http 1.1 method - - # If we still dont have login details... - if (! isset($_SERVER['PHP_AUTH_USER'])) { - system_message(array( - 'title'=>_('Unable to login.'), - 'body'=>_('Your configuration file has authentication set to HTTP based authentication, however, there was none presented'), - 'type'=>'error')); - - $CACHE[$this->index][$method] = false; - } - - # Check our auth vars are valid. - } else { - if (! $this->login($_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW'],$method)) { - system_message(array( - 'title'=>_('Unable to login.'), - 'body'=>_('Your HTTP based authentication is not accepted by the LDAP server'), - 'type'=>'error')); - - $CACHE[$this->index][$method] = false; - - } else - $CACHE[$this->index][$method] = true; - } - - break; - - case 'proxy': - $CACHE[$this->index][$method] = $this->login($this->getValue('login','bind_id'),$this->getValue('login','bind_pass'),$method); - - break; - - case 'sasl': - # Propogate any given Kerberos credential cache location - if (isset($_ENV['REDIRECT_KRB5CCNAME'])) - putenv(sprintf('KRB5CCNAME=%s',$_ENV['REDIRECT_KRB5CCNAME'])); - elseif (isset($_SERVER['KRB5CCNAME'])) - putenv(sprintf('KRB5CCNAME=%s',$_SERVER['KRB5CCNAME'])); - - # Map the SASL auth ID to a DN - $regex = $this->getValue('login', 'sasl_dn_regex'); - $replacement = $this->getValue('login', 'sasl_dn_replacement'); - - if ($regex && $replacement) { - $userDN = preg_replace($regex, $replacement, $_SERVER['REMOTE_USER']); - - $CACHE[$this->index][$method] = $this->login($userDN, '', $method); - - # Otherwise, use the user name as is - # For GSSAPI Authentication + mod_auth_kerb and Basic Authentication - } else - $CACHE[$this->index][$method] = $this->login(isset($_SERVER['REMOTE_USER']) ? $_SERVER['REMOTE_USER'] : '', '', $method); - - break; - - default: - $CACHE[$this->index][$method] = is_null($this->getLogin($method)) ? false : true; - } - - return $CACHE[$this->index][$method]; - } - - /** - * Logout of this datastore's connection method - */ - public function logout($method=null) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $method = $this->getMethod($method); - - unset ($_SESSION['cache'][$this->index]); - - switch ($this->getAuthType()) { - case 'cookie': - set_cookie($method.'-USER','',time()-3600,'/'); - set_cookie($method.'-PASS','',time()-3600,'/'); - - case 'config': - return true; - - case 'http': - case 'proxy': - case 'session': - case 'sasl': - if (isset($_SESSION['USER'][$this->index][$method])) - unset($_SESSION['USER'][$this->index][$method]); - - return true; - - default: - die(sprintf('Error: %s hasnt been configured for auth_type %s',__METHOD__,$this->getAuthType())); - } - } - - /** - * Functions that return the condition of the datasource - */ - public function isVisible() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); - - return $this->getValue('server','visible'); - } - - public function isReadOnly() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); - - if (! trim($this->getLogin(null)) && $_SESSION[APPCONFIG]->getValue('appearance','anonymous_bind_implies_read_only')) - return true; - else - return $this->getValue('server','read_only'); - } - - public function getIndex() { - if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',17,1,__FILE__,__LINE__,__METHOD__,$fargs,$this->index); - - return $this->index; - } - - /** - * Work out which connection method to use. - * If a method is passed, then it will be passed back. If no method is passed, then we'll - * check to see if the user is logged in. If they are, then 'user' is used, otherwise - * 'anon' is used. - * - * @param int Server ID - * @return string Connection Method - */ - protected function getMethod($method=null) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); - - static $CACHE = array(); - - # Immediately return if method is set. - if (! is_null($method)) - return $method; - - # If we have been here already, then return our result - if (isset($CACHE[$this->index]) && ! is_null($CACHE)) - return $CACHE[$this->index]; - - $CACHE[$this->index] = 'anon'; - - if ($this->isLoggedIn('user')) - $CACHE[$this->index] = 'user'; - - return $CACHE[$this->index]; - } - - /** - * This method should be overridden in application specific ds files - */ - public function isSessionValid() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',17,1,__FILE__,__LINE__,__METHOD__,$fargs,true); - - return true; - } - - /** - * Return the time left in seconds until this connection times out. If there is not timeout, - * this function will return null. - */ - public function inactivityTime() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); - - if ($this->isLoggedIn() && ! in_array($this->getAuthType(),array('config','http'))) - return time()+($this->getValue('login','timeout')*60); - else - return null; - } -} - -/** - * The list of database sources - * - * @package phpLDAPadmin - * @subpackage DataStore - */ -class Datastore { - # Out DS index id - private $index; - # List of all the objects - private $objects = array(); - # Default settings - private $default; - - public function __construct() { - $this->default = new StdClass; - - $this->default->server['id'] = array( - 'desc'=>'Server ID', - 'default'=>null); - - $this->default->server['name'] = array( - 'desc'=>'Server name', - 'default'=>null); - - # Connectivity Info - $this->default->server['host'] = array( - 'desc'=>'Host Name', - 'default'=>'127.0.0.1'); - - $this->default->server['port'] = array( - 'desc'=>'Port Number', - 'default'=>null); - - # Read or write only access - $this->default->server['read_only'] = array( - 'desc'=>'Server is in READ ONLY mode', - 'default'=>false); - - $this->default->server['visible'] = array( - 'desc'=>'Whether this server is visible', - 'default'=>true); - - $this->default->server['hide_noaccess_base'] = array( - 'desc'=>'If base DNs are not accessible, hide them instead of showing create', - 'default'=>false); - - # Authentication Information - $this->default->login['auth_type'] = array( - 'desc'=>'Authentication Type', - 'default'=>'session'); - -/* - /* ID to login to this application, this assumes that there is - * application authentication on top of authentication required to - * access the data source ** - $this->default->login['auth_id'] = array( - 'desc'=>'User Login ID to login to this DS', - 'untested'=>true, - 'default'=>null); - - $this->default->login['auth_pass'] = array( - 'desc'=>'User Login Password to login to this DS', - 'untested'=>true, - 'default'=>null); -*/ - - $this->default->login['auth_text'] = array( - 'desc'=>'Text to show at the login prompt', - 'default'=>null); - - $this->default->login['bind_id'] = array( - 'desc'=>'User Login ID to bind to this DS', - 'default'=>null); - - $this->default->login['bind_dn_template'] = array( - 'desc'=>'Template string for user login DN to bind to this DS. Use \'%s\' where user input should be inserted.', - 'default'=>null); - - $this->default->login['bind_pass'] = array( - 'desc'=>'User Login Password to bind to this DS', - 'default'=>null); - - $this->default->login['timeout'] = array( - 'desc'=>'Session timout in seconds', - 'default'=>session_cache_expire()-1); - - $this->default->login['sasl_dn_regex'] = array( - 'desc'=>'SASL authorization id to user dn PCRE regular expression', - 'untested'=>true, - 'default'=>null); - - $this->default->login['sasl_dn_replacement'] = array( - 'desc'=>'SASL authorization id to user dn PCRE regular expression replacement string', - 'untested'=>true, - 'default'=>null); - - # Prefix for custom pages - $this->default->custom['pages_prefix'] = array( - 'desc'=>'Prefix name for custom pages', - 'default'=>'custom_'); - } - - /** - * Create a new database object - */ - public function newServer($type) { - if (class_exists($type)) { - $this->index = count($this->objects)+1; - $this->objects[$this->index] = new $type($this->index); - - $this->objects[$this->index]->setDefaults($this->default); - return $this->index; - - } else { - printf('ERROR: Class [%s] doesnt exist',$type); - die(); - } - } - - /** - * Set values for a database object. - */ - public function setValue($key,$setting,$value) { - if (! $this->objects[$this->index]->isDefaultKey($key)) - error("ERROR: Setting a key [$key] that isnt predefined.",'error',true); - - if (! $this->objects[$this->index]->isDefaultSetting($key,$setting)) - error("ERROR: Setting a index [$key,$setting] that isnt predefined.",'error',true); - - # Test if its should be an array or not. - if (is_array($this->objects[$this->index]->getValue($key,$setting)) && ! is_array($value)) - error("Error in configuration file, {$key}['$setting'] SHOULD be an array of values.",'error',true); - - if (! is_array($this->objects[$this->index]->getValue($key,$setting)) && is_array($value)) - error("Error in configuration file, {$key}['$setting'] should NOT be an array of values.",'error',true); - - # Store the value in the object. - $this->objects[$this->index]->setValue($key,$setting,$value); - } - - /** - * Get a list of all the configured servers. - * - * @param boolean Only show visible servers. - * @return array list of all configured servers. - */ - public function getServerList($isVisible=true) { - if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); - - static $CACHE; - - if (isset($CACHE[$isVisible])) - return $CACHE[$isVisible]; - - $CACHE[$isVisible] = array(); - - # Debugging incase objects is not set. - if (! $this->objects) { - print "
";
-			debug_print_backtrace();
-			die();
-		}
-
-		foreach ($this->objects as $id => $server)
-			if (! $isVisible || ($isVisible && $server->getValue('server','visible')))
-				$CACHE[$isVisible][$id] = $server;
-
-		masort($CACHE[$isVisible],'name');
-
-		return $CACHE[$isVisible];
-	}
-
-	/**
-	 * Return an object Instance of a configured database.
-	 *
-	 * @param int Index
-	 * @return object Datastore instance object.
-	 */
-	public function Instance($index=null) {
-		if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		# If no index defined, then pick the lowest one.
-		if (is_null($index) || ! trim($index) || ! is_numeric($index))
-			$index = min($this->GetServerList())->getIndex();
-
-		if (! isset($this->objects[$index]))
-			debug_dump_backtrace(sprintf('Error: Datastore instance [%s] doesnt exist?',htmlspecialchars($index)),1);
-
-		if (defined('DEBUG_ENABLED') && DEBUG_ENABLED)
-			debug_log('Returning instance of database (%s)',3,0,__FILE__,__LINE__,__METHOD__,$index);
-
-		return $this->objects[$index];
-	}
-
-	/**
-	 * Return an object Instance of a configured database.
-	 *
-	 * @param string Name of the instance to retrieve
-	 * @return object Datastore instance object.
-	 */
-	public function InstanceName($name=null) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		foreach ($this->getServerList(false) as $index)
-			if ($this->objects[$index]->getName() == $name)
-				return $this->objects[$index];
-
-		# If we get here, then no object with the name exists.
-		return null;
-	}
-
-	/**
-	 * Return an object Instance of a configured database.
-	 *
-	 * @param string ID of the instance to retrieve
-	 * @return object Datastore instance object.
-	 */
-	public function InstanceId($id=null) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		foreach ($this->getServerList(false) as $index)
-			if ($this->objects[$index->getIndex()]->getValue('server','id') == $id)
-				return $this->objects[$index->getIndex()];
-
-		# If we get here, then no object with the name exists.
-		return null;
-	}
-}
-?>
diff --git a/lib/ds_ldap.php b/lib/ds_ldap.php
deleted file mode 100644
index e46a63b1..00000000
--- a/lib/ds_ldap.php
+++ /dev/null
@@ -1,1581 +0,0 @@
-index = $index;
-		$this->type = 'ldap';
-
-		# Additional values that can go in our config.php
-		$this->custom = new StdClass;
-		$this->default = new StdClass;
-
-/*
- * Not used by PLA
-		# Database Server Variables
-		$this->default->server['db'] = array(
-			'desc'=>'Database Name',
-			'untested'=>true,
-			'default'=>null);
-*/
-
-		/* This was created for IDS - since it doesnt present STRUCTURAL against objectClasses
-		 * definitions when reading the schema.*/
-		$this->default->server['schema_oclass_default'] = array(
-			'desc'=>'When reading the schema, and it doesnt specify objectClass type, default it to this',
-			'default'=>null);
-
-		$this->default->server['base'] = array(
-			'desc'=>'LDAP Base DNs',
-			'default'=>array());
-
-		$this->default->server['tls'] = array(
-			'desc'=>'Connect using TLS',
-			'default'=>false);
-
-		# Login Details
-		$this->default->login['attr'] = array(
-			'desc'=>'Attribute to use to find the users DN',
-			'default'=>'dn');
-
-		$this->default->login['anon_bind'] = array(
-			'desc'=>'Enable anonymous bind logins',
-			'default'=>true);
-
-		$this->default->login['allowed_dns'] = array(
-			'desc'=>'Limit logins to users who match any of the following LDAP filters',
-			'default'=>array());
-
-		$this->default->login['base'] = array(
-			'desc'=>'Limit logins to users who are in these base DNs',
-			'default'=>array());
-
-		$this->default->login['class'] = array(
-			'desc'=>'Strict login to users containing a specific objectClasses',
-			'default'=>array());
-
-		$this->default->proxy['attr'] = array(
-			'desc'=>'Attribute to use to find the users DN for proxy based authentication',
-			'default'=>array());
-
-		# SASL configuration
-		$this->default->sasl['mech'] = array(
-			'desc'=>'SASL mechanism used while binding LDAP server',
-			'default'=>'GSSAPI');
-
-		$this->default->sasl['realm'] = array(
-			'desc'=>'SASL realm name',
-			'untested'=>true,
-			'default'=>null);
-
-		$this->default->sasl['authz_id'] = array(
-			'desc'=>'SASL authorization id',
-			'untested'=>true,
-			'default'=>null);
-
-		$this->default->sasl['authz_id_regex'] = array(
-			'desc'=>'SASL authorization id PCRE regular expression',
-			'untested'=>true,
-			'default'=>null);
-
-		$this->default->sasl['authz_id_replacement'] = array(
-			'desc'=>'SASL authorization id PCRE regular expression replacement string',
-			'untested'=>true,
-			'default'=>null);
-
-		$this->default->sasl['props'] = array(
-			'desc'=>'SASL properties',
-			'untested'=>true,
-			'default'=>null);
-	}
-
-	/**
-	 * Required ABSTRACT functions
-	 */
-	/**
-	 * Connect and Bind to the Database
-	 *
-	 * @param string Which connection method resource to use
-	 * @return resource|null Connection resource if successful, null if not.
-	 */
-	protected function connect($method,$debug=false,$new=false) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		static $CACHE = array();
-
-		$method = $this->getMethod($method);
-		$bind = array();
-
-		if (isset($CACHE[$this->index][$method]) && $CACHE[$this->index][$method])
-			return $CACHE[$this->index][$method];
-
-		# Check if we have logged in and therefore need to use those details as our bind.
-		$bind['id'] = is_null($this->getLogin($method)) && $method != 'anon' ? $this->getLogin('user') : $this->getLogin($method);
-		$bind['pass'] = is_null($this->getPassword($method)) && $method != 'anon' ? $this->getPassword('user') : $this->getPassword($method);
-
-		# If our bind id is still null, we are not logged in.
-		if (is_null($bind['id']) && ! in_array($method,array('anon','login')))
-			return null;
-
-		# If we bound to the LDAP server with these details for a different connection, return that resource
-		if (isset($CACHE[$this->index]) && ! $new)
-			foreach ($CACHE[$this->index] as $cachedmethod => $resource) {
-				if (($this->getLogin($cachedmethod) == $bind['id']) && ($this->getPassword($cachedmethod) == $bind['pass'])) {
-					$CACHE[$this->index][$method] = $resource;
-
-					return $CACHE[$this->index][$method];
-				}
-			}
-
-		$CACHE[$this->index][$method] = null;
-
-		# No identifiable connection exists, lets create a new one.
-		if (DEBUG_ENABLED)
-			debug_log('Creating NEW connection [%s] for index [%s]',16,0,__FILE__,__LINE__,__METHOD__,
-				$method,$this->index);
-
-		if (function_exists('run_hook'))
-			run_hook('pre_connect',array('server_id'=>$this->index,'method'=>$method));
-
-		if ($this->getValue('server','port'))
-			$resource = ldap_connect($this->getValue('server','host'),$this->getValue('server','port'));
-		else
-			$resource = ldap_connect($this->getValue('server','host'));
-
-		$CACHE[$this->index][$method] = $resource;
-
-		if (DEBUG_ENABLED)
-			debug_log('LDAP Resource [%s], Host [%s], Port [%s]',16,0,__FILE__,__LINE__,__METHOD__,
-				$resource,$this->getValue('server','host'),$this->getValue('server','port'));
-
-		if (! is_resource($resource))
-			debug_dump_backtrace('UNHANDLED, $resource is not a resource',1);
-
-		# Go with LDAP version 3 if possible (needed for renaming and Novell schema fetching)
-		ldap_set_option($resource,LDAP_OPT_PROTOCOL_VERSION,3);
-
-		/* Disabling this makes it possible to browse the tree for Active Directory, and seems
-		 * to not affect other LDAP servers (tested with OpenLDAP) as phpLDAPadmin explicitly
-		 * specifies deref behavior for each ldap_search operation. */
-		ldap_set_option($resource,LDAP_OPT_REFERRALS,0);
-
-		/* Enabling manageDsaIt to be able to browse through glued entries
-		 * 2.16.840.1.113730.3.4.2 :  "ManageDsaIT Control" "RFC 3296" "The client may provide
-		 * the ManageDsaIT control with an operation to indicate that the operation is intended
-		 * to manage objects within the DSA (server) Information Tree. The control causes
-		 * Directory-specific entries (DSEs), regardless of type, to be treated as normal entries
-		 * allowing clients to interrogate and update these entries using LDAP operations." */
-		ldap_set_option($resource,LDAP_OPT_SERVER_CONTROLS,array(array('oid'=>'2.16.840.1.113730.3.4.2')));
-
-		# Try to fire up TLS is specified in the config
-		if ($this->isTLSEnabled())
-			$this->startTLS($resource);
-
-		# If SASL has been configured for binding, then start it now.
-		if ($this->isSASLEnabled())
-			$bind['result'] = $this->startSASL($resource,$method,$bind['id'],$bind['pass']);
-
-		# Normal bind...
-		else
-			$bind['result'] = @ldap_bind($resource,$bind['id'],$bind['pass']);
-
-		if ($debug)
-			debug_dump(array('method'=>$method,'bind'=>$bind,'USER'=>$_SESSION['USER']));
-
-		if (DEBUG_ENABLED)
-			debug_log('Resource [%s], Bind Result [%s]',16,0,__FILE__,__LINE__,__METHOD__,$resource,$bind);
-
-		if (! $bind['result']) {
-			if (DEBUG_ENABLED)
-				debug_log('Leaving with FALSE, bind FAILed',16,0,__FILE__,__LINE__,__METHOD__);
-
-			$this->noconnect = true;
-
-			system_message(array(
-				'title'=>sprintf('%s %s',_('Unable to connect to LDAP server'),$this->getName()),
-				'body'=>sprintf('%s: %s (%s) for %s',_('Error'),$this->getErrorMessage($method),$this->getErrorNum($method),$method),
-				'type'=>'error'));
-
-			$CACHE[$this->index][$method] = null;
-
-		} else {
-			$this->noconnect = false;
-
-			# If this is a proxy session, we need to switch to the proxy user
-			if ($this->isProxyEnabled() && $bind['id'] && $method != 'anon')
-				if (! $this->startProxy($resource,$method)) {
-					$this->noconnect = true;
-					$CACHE[$this->index][$method] = null;
-				}
-		}
-
-		if (function_exists('run_hook'))
-			run_hook('post_connect',array('server_id'=>$this->index,'method'=>$method,'id'=>$bind['id']));
-
-		if ($debug)
-			debug_dump(array($method=>$CACHE[$this->index][$method]));
-
-		return $CACHE[$this->index][$method];
-	}
-
-	/**
-	 * Login to the database with the application user/password
-	 *
-	 * @return boolean true|false for successful login.
-	 */
-	public function login($user=null,$pass=null,$method=null,$new=false) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		$userDN = null;
-
-		# Get the userDN from the username.
-		if (! is_null($user)) {
-			# If login,attr is set to DN, then user should be a DN
-			if (($this->getValue('login','attr') == 'dn') || $method != 'user')
-				$userDN = $this->getValue('login', 'bind_dn_template') ? $this->fillDNTemplate($user) : $user;
-			else
-				$userDN = $this->getLoginID($user,'login');
-
-			if (! $userDN && $this->getValue('login','fallback_dn') && strpos($user, '='))
-				$userDN = $user;
-
-			if (! $userDN)
-				return false;
-
-		} else {
-			if (in_array($method,array('user','anon'))) {
-				$method = 'anon';
-				$userDN = '';
-				$pass = '';
-
-			} else {
-				$userDN = $this->getLogin('user');
-				$pass = $this->getPassword('user');
-			}
-		}
-
-		if (! $this->isAnonBindAllowed() && ! trim($userDN))
-			return false;
-
-		# Temporarily set our user details
-		$this->setLogin($userDN,$pass,$method);
-
-		$connect = $this->connect($method,false,$new);
-
-		# If we didnt log in...
-		if (! is_resource($connect) || $this->noconnect || ! $this->userIsAllowedLogin($userDN)) {
-			$this->logout($method);
-
-			return false;
-
-		} else
-			return true;
-	}
-
-	/**
-	 * Perform a query to the Database
-	 *
-	 * @param string query to perform
-	 *	$query['base']
-	 *	$query['filter']
-	 *	$query['scope']
-	 *	$query['attrs'] = array();
-	 *	$query['deref']
-	 * @param string Which connection method resource to use
-	 * @param string Index items according to this key
-	 * @param boolean Enable debugging output
-	 * @return array|null Results of query.
-	 */
-	public function query($query,$method,$index=null,$debug=false) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		$attrs_only = 0;
-
-		# Defaults
-		if (! isset($query['attrs']))
-			$query['attrs'] = array();
-		else
-			# Re-index the attrs, PHP throws an error if the keys are not sequential from 0.
-			$query['attrs'] = array_values($query['attrs']);
-
-		if (! isset($query['base'])) {
-			$bases = $this->getBaseDN();
-			$query['base'] = array_shift($bases);
-		}
-
-		if (! isset($query['deref']))
-			$query['deref'] = $_SESSION[APPCONFIG]->getValue('deref','search');
-		if (! isset($query['filter']))
-			$query['filter'] = '(&(objectClass=*))';
-		if (! isset($query['scope']))
-			$query['scope'] = 'sub';
-		if (! isset($query['size_limit']))
-			$query['size_limit'] = 0;
-		if (! isset($query['time_limit']))
-			$query['time_limit'] = 0;
-
-		if ($query['scope'] == 'base' && ! isset($query['baseok']))
-			system_message(array(
-				'title'=>sprintf('Dont call %s',__METHOD__),
-				'body'=>sprintf('Use getDNAttrValues for base queries [%s]',$query['base']),
-				'type'=>'info'));
-
-		if (is_array($query['base'])) {
-			system_message(array(
-				'title'=>_('Invalid BASE for query'),
-				'body'=>_('The query was cancelled because of an invalid base.'),
-				'type'=>'error'));
-
-			return array();
-		}
-
-		if (DEBUG_ENABLED)
-			debug_log('%s search PREPARE.',16,0,__FILE__,__LINE__,__METHOD__,$query['scope']);
-
-		if ($debug)
-			debug_dump(array('query'=>$query,'server'=>$this->getIndex(),'con'=>$this->connect($method)));
-
-		$resource = $this->connect($method,$debug);
-
-		switch ($query['scope']) {
-			case 'base':
-				$search = @ldap_read($resource,$query['base'],$query['filter'],$query['attrs'],$attrs_only,$query['size_limit'],$query['time_limit'],$query['deref']);
-				break;
-
-			case 'one':
-				$search = @ldap_list($resource,$query['base'],$query['filter'],$query['attrs'],$attrs_only,$query['size_limit'],$query['time_limit'],$query['deref']);
-				break;
-
-			case 'sub':
-			default:
-				$search = @ldap_search($resource,$query['base'],$query['filter'],$query['attrs'],$attrs_only,$query['size_limit'],$query['time_limit'],$query['deref']);
-				break;
-		}
-
-		if ($debug)
-			debug_dump(array('method'=>$method,'search'=>$search,'error'=>$this->getErrorMessage()));
-
-		if (DEBUG_ENABLED)
-			debug_log('Search scope [%s] base [%s] filter [%s] attrs [%s] COMPLETE (%s).',16,0,__FILE__,__LINE__,__METHOD__,
-				$query['scope'],$query['base'],$query['filter'],$query['attrs'],is_null($search));
-
-		if (! $search)
-			return array();
-
-		$return = array();
-
-		# Get the first entry identifier
-		if ($entries = ldap_get_entries($resource,$search)) {
-			# Remove the count
-			if (isset($entries['count']))
-				unset($entries['count']);
-
-			# Iterate over the entries
-			foreach ($entries as $a => $entry) {
-				if (! isset($entry['dn']))
-					debug_dump_backtrace('No DN?',1);
-
-				# Remove the none entry references.
-				if (! is_array($entry)) {
-					unset($entries[$a]);
-					continue;
-				}
-
-				$dn = $entry['dn'];
-				unset($entry['dn']);
-
-				# Iterate over the attributes
-				foreach ($entry as $b => $attrs) {
-					# Remove the none entry references.
-					if (! is_array($attrs)) {
-						unset($entry[$b]);
-						continue;
-					}
-
-					# Remove the count
-					if (isset($entry[$b]['count']))
-						unset($entry[$b]['count']);
-				}
-
-				# Our queries always include the DN (the only value not an array).
-				$entry['dn'] = $dn;
-				$return[$dn] = $entry;
-			}
-
-			# Sort our results
-			foreach ($return as $key=> $values)
-				ksort($return[$key]);
-		}
-
-		if (DEBUG_ENABLED)
-			debug_log('Returning (%s)',17,0,__FILE__,__LINE__,__METHOD__,$return);
-
-		return $return;
-	}
-
-	/**
-	 * Get the last error string
-	 *
-	 * @param string Which connection method resource to use
-	 */
-	public function getErrorMessage($method=null) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		return ldap_error($this->connect($method));
-	}
-
-	/**
-	 * Get the last error number
-	 *
-	 * @param string Which connection method resource to use
-	 */
-	public function getErrorNum($method=null) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		return ldap_errno($this->connect($method));
-	}
-
-	/**
-	 * Additional functions
-	 */
-	/**
-	 * Get a user ID
-	 *
-	 * @param string Which connection method resource to use
-	 */
-	public function getLoginID($user,$method=null) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		$query['filter'] = sprintf('(&(%s=%s)%s)',
-			$this->getValue('login','attr'),$user,
-			$this->getLoginClass() ? sprintf('(objectclass=%s)',join(')(objectclass=',$this->getLoginClass())) : '');
-		$query['attrs'] = array('dn');
-
-		$result = array();
-		foreach ($this->getLoginBaseDN() as $base) {
-			$query['base'] = $base;
-			$result = $this->query($query,$method);
-
-			if (count($result) == 1)
-				break;
-		}
-
-		if (count($result) != 1)
-			return null;
-
-		$detail = array_shift($result);
-
-		if (! isset($detail['dn']))
-			die('ERROR: DN missing?');
-		else
-			return $detail['dn'];
-	}
-
-	/**
-	 * Return the login base DNs
-	 * If no login base DNs are defined, then the LDAP server Base DNs are used.
-	 */
-	private function getLoginBaseDN() {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,1,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		if ($this->getValue('login','base'))
-			return $this->getValue('login','base');
-		else
-			return $this->getBaseDN();
-	}
-
-	private function fillDNTemplate($user) {
-		foreach($this->getLoginBaseDN() as $base)
-			if(substr_compare($user, $base, -strlen($base)) === 0)
-				return $user; // $user already passed as DN
-
-		// fill template
-		return sprintf($this->getValue('login', 'bind_dn_template'), preg_replace('/([,\\\\#+<>;"=])/', '\\\\$1', $user));
-	}
-
-	/**
-	 * Return the login classes that a user must have to login
-	 */
-	private function getLoginClass() {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,1,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		return $this->getValue('login','class');
-	}
-
-	/**
-	 * Return if anonymous bind is allowed in the configuration
-	 */
-	public function isAnonBindAllowed() {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		return $this->getValue('login','anon_bind');
-	}
-
-	/**
-	 * Fetches whether TLS has been configured for use with a certain server.
-	 *
-	 * Users may configure phpLDAPadmin to use TLS in config,php thus:
-	 * 
-	 *	$servers->setValue('server','tls',true|false);
-	 * 
-	 *
-	 * @return boolean
-	 */
-	private function isTLSEnabled() {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		if ($this->getValue('server','tls') && ! function_exists('ldap_start_tls')) {
-				error(_('TLS has been enabled in your config, but your PHP install does not support TLS. TLS will be disabled.'),'warn');
-			return false;
-
-		} else
-			return $this->getValue('server','tls');
-	}
-
-	/**
-	 * If TLS is configured, then start it
-	 */
-	private function startTLS($resource) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		if (! $this->getValue('server','tls') || (function_exists('ldap_start_tls') && ! @ldap_start_tls($resource))) {
-			system_message(array(
-				'title'=>sprintf('%s (%s)',_('Could not start TLS.'),$this->getName()),
-				'body'=>sprintf('%s: %s',_('Error'),_('Could not start TLS. Please check your LDAP server configuration.')),
-				'type'=>'error'));
-
-			return false;
-
-		} else
-			return true;
-	}
-
-	/**
-	 * Fetches whether SASL has been configured for use with a certain server.
-	 *
-	 * Users may configure phpLDAPadmin to use SASL in config,php thus:
-	 * 
-	 *	$servers->setValue('login','auth_type','sasl');
-	 * OR
-	 *      $servers->setValue('sasl','mech','PLAIN');
-	 * 
-	 *
-	 * @return boolean
-	 */
-	private function isSASLEnabled() {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		if (! in_array($this->getValue('login','auth_type'), array('sasl'))) {
-			// check if SASL mech uses login from other auth_types
-			if (! in_array(strtolower($this->getValue('sasl', 'mech')), array('plain')))
-				return false;
-		}
-
-		if (! function_exists('ldap_sasl_bind')) {
-			error(_('SASL has been enabled in your config, but your PHP install does not support SASL. SASL will be disabled.'),'warn');
-
-			return false;
-		}
-
-		# If we get here, SASL must be configured.
-		return true;
-	}
-
-	/**
-	 * If SASL is configured, then start it
-	 * To be able to use SASL, PHP should have been compliled with --with-ldap-sasl=DIR
-	 *
-	 * @todo This has not been tested, please let the developers know if this function works as expected.
-	 */
-	private function startSASL($resource,$method,$login,$pass) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		static $CACHE = array();
-
-		# We shouldnt be doing SASL binds for anonymous queries?
-		if ($method == 'anon')
-			return false;
-
-		# At the moment, we have only implemented GSSAPI and PLAIN
-		if (! in_array(strtolower($this->getValue('sasl','mech')),array('gssapi','plain'))) {
-			system_message(array(
-				'title'=>_('SASL Method not implemented'),
-				'body'=>sprintf('%s: %s %s',_('Error'),$this->getValue('sasl','mech'),_('has not been implemented yet')),
-				'type'=>'error'));
-
-			return false;
-		}
-
-		if (strtolower($this->getValue('sasl','mech')) == 'plain') {
-			return @ldap_sasl_bind($resource,NULL,$pass,'PLAIN',
-					       $this->getValue('sasl','realm'),
-					       $login,
-					       $this->getValue('sasl','props'));
-		}
-
-		if (! isset($CACHE['login_dn']))
-			$CACHE['login_dn'] = $login;
-
-		$CACHE['authz_id'] = '';
-
-		/*
-		# Do we need to rewrite authz_id?
-		if (! isset($CACHE['authz_id']))
-			if (! trim($this->getValue('sasl','authz_id')) && strtolower($this->getValue('sasl','mech')) != 'gssapi') {
-				if (DEBUG_ENABLED)
-					debug_log('Rewriting bind DN [%s] -> authz_id with regex [%s] and replacement [%s].',9,0,__FILE__,__LINE__,__METHOD__,
-						$CACHE['login_dn'],
-						$this->getValue('sasl','authz_id_regex'),
-						$this->getValue('sasl','authz_id_replacement'));
-
-				$CACHE['authz_id'] = @preg_replace($this->getValue('sasl','authz_id_regex'),
-					$this->getValue('sasl','authz_id_replacement'),$CACHE['login_dn']);
-
-				# Invalid regex?
-				if (is_null($CACHE['authz_id']))
-					error(sprintf(_('It seems that sasl_authz_id_regex "%s" contains invalid PCRE regular expression. The error is "%s".'),
-						$this->getValue('sasl','authz_id_regex'),(isset($php_errormsg) ? $php_errormsg : '')),
-						'error','index.php');
-
-				if (DEBUG_ENABLED)
-					debug_log('Resource [%s], SASL OPTIONS: mech [%s], realm [%s], authz_id [%s], props [%s]',9,0,__FILE__,__LINE__,__METHOD__,
-						$resource,
-						$this->getValue('sasl','mech'),
-						$this->getValue('sasl','realm'),
-						$CACHE['authz_id'],
-						$this->getValue('sasl','props'));
-
-			} else
-				$CACHE['authz_id'] = $this->getValue('sasl','authz_id');
-		*/
-
-		# @todo this function is different in PHP5.1 and PHP5.2
-		return @ldap_sasl_bind($resource,NULL,'',
-			$this->getValue('sasl','mech'),
-			$this->getValue('sasl','realm'),
-			$CACHE['authz_id'],
-			$this->getValue('sasl','props'));
-	}
-
-	/**
-	 * Fetches whether PROXY AUTH has been configured for use with a certain server.
-	 *
-	 * Users may configure phpLDAPadmin to use PROXY AUTH in config,php thus:
-	 * 
-	 *	$servers->setValue('login','auth_type','proxy');
-	 * 
-	 *
-	 * @return boolean
-	 */
-	private function isProxyEnabled() {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		return $this->getValue('login','auth_type') == 'proxy' ? true : false;
-	}
-
-	/**
-	 * If PROXY AUTH is configured, then start it
-	 */
-	private function startProxy($resource,$method) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		$rootdse = $this->getRootDSE();
-
-		if (! (isset($rootdse['supportedcontrol']) && in_array('2.16.840.1.113730.3.4.18',$rootdse['supportedcontrol']))) {
-			system_message(array(
-				'title'=>sprintf('%s %s',_('Unable to start proxy connection'),$this->getName()),
-				'body'=>sprintf('%s: %s',_('Error'),_('Your LDAP server doesnt seem to support this control')),
-				'type'=>'error'));
-
-			return false;
-		}
-
-		$filter = '(&';
-		$dn = '';
-
-		$missing = false;
-		foreach ($this->getValue('proxy','attr') as $attr => $var) {
-			if (! isset($_SERVER[$var])) {
-				system_message(array(
-					'title'=>sprintf('%s %s',_('Unable to start proxy connection'),$this->getName()),
-					'body'=>sprintf('%s: %s (%s)',_('Error'),_('Attribute doesnt exist'),$var),
-					'type'=>'error'));
-
-				$missing = true;
-
-			} else {
-				if ($attr == 'dn') {
-					$dn = $var;
-
-					break;
-
-				} else
-					$filter .= sprintf('(%s=%s)',$attr,$_SERVER[$var]);
-			}
-		}
-
-		if ($missing)
-			return false;
-
-		$filter .= ')';
-
-		if (! $dn) {
-			$query['filter'] = $filter;
-
-			foreach ($this->getBaseDN() as $base) {
-				$query['base'] = $base;
-
-				if ($search = $this->query($query,$method))
-					break;
-			}
-
-			if (count($search) != 1) {
-				system_message(array(
-					'title'=>sprintf('%s %s',_('Unable to start proxy connection'),$this->getName()),
-					'body'=>sprintf('%s: %s (%s)',_('Error'),_('Search for DN returned the incorrect number of results'),count($search)),
-					'type'=>'error'));
-
-				return false;
-			}
-
-			$search = array_pop($search);
-			$dn = $search['dn'];
-		}
-
-		$ctrl = array(
-			'oid'=>'2.16.840.1.113730.3.4.18',
-			'value'=>sprintf('dn:%s',$dn),
-			'iscritical' => true);
-
-		if (! ldap_set_option($resource,LDAP_OPT_SERVER_CONTROLS,array($ctrl))) {
-			system_message(array(
-				'title'=>sprintf('%s %s',_('Unable to start proxy connection'),$this->getName()),
-				'body'=>sprintf('%s: %s (%s) for %s',_('Error'),$this->getErrorMessage($method),$this->getErrorNum($method),$method),
-				'type'=>'error'));
-
-			return false;
-		}
-
-		$_SESSION['USER'][$this->index][$method]['proxy'] = blowfish_encrypt($dn);
-
-		return true;
-	}
-
-	/**
-	 * Modify attributes of a DN
-	 */
-	public function modify($dn,$attrs,$method=null) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		# We need to supress the error here - programming should detect and report it.
-		return @ldap_mod_replace($this->connect($method),$dn,$attrs);
-	}
-
-	/**
-	 * Gets the root DN of the specified LDAPServer, or null if it
-	 * can't find it (ie, the server won't give it to us, or it isnt
-	 * specified in the configuration file).
-	 *
-	 * Tested with OpenLDAP 2.0, Netscape iPlanet, and Novell eDirectory 8.7 (nldap.com)
-	 * Please report any and all bugs!!
-	 *
-	 * Please note: On FC systems, it seems that php_ldap uses /etc/openldap/ldap.conf in
-	 * the search base if it is blank - so edit that file and comment out the BASE line.
-	 *
-	 * @param string Which connection method resource to use
-	 * @return array dn|null The root DN of the server on success (string) or null on error.
-	 * @todo Sort the entries, so that they are in the correct DN order.
-	 */
-	public function getBaseDN($method=null) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		static $CACHE;
-
-		$method = $this->getMethod($method);
-		$result = array();
-
-		if (isset($CACHE[$this->index][$method]))
-			return $CACHE[$this->index][$method];
-
-		# If the base is set in the configuration file, then just return that.
-		if (count($this->getValue('server','base'))) {
-			if (DEBUG_ENABLED)
-				debug_log('Return BaseDN from Config [%s]',17,0,__FILE__,__LINE__,__METHOD__,implode('|',$this->getValue('server','base')));
-
-			$CACHE[$this->index][$method] = $this->getValue('server','base');
-
-		# We need to figure it out.
-		} else {
-			if (DEBUG_ENABLED)
-				debug_log('Connect to LDAP to find BaseDN',80,0,__FILE__,__LINE__,__METHOD__);
-
-			# Set this to empty, in case we loop back here looking for the baseDNs
-			$CACHE[$this->index][$method] = array();
-
-			$results = $this->getDNAttrValues('',$method);
-
-			if (isset($results['namingcontexts'])) {
-				if (DEBUG_ENABLED)
-					debug_log('LDAP Entries:%s',80,0,__FILE__,__LINE__,__METHOD__,implode('|',$results['namingcontexts']));
-
-				$result = $results['namingcontexts'];
-			}
-
-			$CACHE[$this->index][$method] = $result;
-		}
-
-		return $CACHE[$this->index][$method];
-	}
-
-	/**
-	 * Gets whether an entry exists based on its DN. If the entry exists,
-	 * returns true. Otherwise returns false.
-	 *
-	 * @param string The DN of the entry of interest.
-	 * @param string Which connection method resource to use
-	 * @return boolean
-	 */
-	public function dnExists($dn,$method=null) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		$results = $this->getDNAttrValues($dn,$method);
-
-		if ($results)
-			return $results;
-		else
-			return false;
-	}
-
-	/**
-	 * Given a DN string, this returns the top container portion of the string.
-	 *
-	 * @param string The DN whose container string to return.
-	 * @return string The container
-	 */
-	public function getContainerTop($dn) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		$return = $dn;
-
-		foreach ($this->getBaseDN() as $base) {
-			if (preg_match("/${base}$/i",$dn)) {
-				$return = $base;
-				break;
-			}
-		}
-
-		if (DEBUG_ENABLED)
-			debug_log('Returning (%s)',17,0,__FILE__,__LINE__,__METHOD__,$return);
-
-		return $return;
-	}
-
-	/**
-	 * Given a DN string and a path like syntax, this returns the parent container portion of the string.
-	 *
-	 * @param string The DN whose container string to return.
-	 * @param string Either '/', '.' or something like '../../'
-	 * @return string The container
-	 */
-	public function getContainerPath($dn,$path='..') {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		$top = $this->getContainerTop($dn);
-
-		if ($path[0] == '/') {
-			$dn = $top;
-			$path = substr($path,1);
-
-		} elseif ($path == '.') {
-			return $dn;
-		}
-
-		$parenttree = explode('/',$path);
-
-		foreach ($parenttree as $key => $value) {
-			if ($value == '..') {
-				if ($this->getContainer($dn))
-					$dn = $this->getContainer($dn);
-
-				if ($dn == $top)
-					break;
-
-			} elseif($value)
-				$dn = sprintf('%s,%s',$value,$dn);
-
-			else
-				break;
-		}
-
-		if (! $dn) {
-			debug_dump(array(__METHOD__,'dn'=>$dn,'path'=>$path));
-			debug_dump_backtrace('Container is empty?',1);
-		}
-
-		return $dn;
-	}
-
-	/**
-	 * Given a DN string, this returns the parent container portion of the string.
-	 * For example. given 'cn=Manager,dc=example,dc=com', this function returns
-	 * 'dc=example,dc=com'.
-	 *
-	 * @param string The DN whose container string to return.
-	 * @return string The container
-	 */
-	public function getContainer($dn) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		$parts = $this->explodeDN($dn);
-
-		if (count($parts) <= 1)
-			$return = null;
-
-		else {
-			$return = $parts[1];
-
-			for ($i=2;$i
-	 *	dc=example,dc=com
-	 *		ou=People
-	 *			cn=Dave
-	 *			cn=Fred
-	 *			cn=Joe
-	 *		ou=More People
-	 *			cn=Mark
-	 *			cn=Bob
-	 * 
-	 *
-	 * Calling getContainerContents("ou=people,dc=example,dc=com")
-	 * would return the following list:
-	 *
-	 * 
-	 *	cn=Dave
-	 *	cn=Fred
-	 *	cn=Joe
-	 *	ou=More People
-	 * 
-	 *
-	 * @param string The DN of the entry whose children to return.
-	 * @param string Which connection method resource to use
-	 * @param int (optional) The maximum number of entries to return.
-	 *            If unspecified, no limit is applied to the number of entries in the returned.
-	 * @param string (optional) An LDAP filter to apply when fetching children, example: "(objectClass=inetOrgPerson)"
-	 * @param constant (optional) The LDAP deref setting to use in the query
-	 * @return array An array of DN strings listing the immediate children of the specified entry.
-	 */
-	public function getContainerContents($dn,$method=null,$size_limit=0,$filter='(objectClass=*)',$deref=LDAP_DEREF_NEVER) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		$return = array();
-
-		$query = array();
-		$query['base'] = $this->escapeDN($dn);
-		$query['attrs'] = array('dn');
-		$query['filter'] = $filter;
-		$query['deref'] = $deref;
-		$query['scope'] = 'one';
-		$query['size_limit'] = $size_limit;
-		$results = $this->query($query,$method);
-
-		if ($results) {
-			foreach ($results as $index => $entry) {
-				$child_dn = $entry['dn'];
-				array_push($return,$child_dn);
-			}
-		}
-
-		if (DEBUG_ENABLED)
-			debug_log('Returning (%s)',17,0,__FILE__,__LINE__,__METHOD__,$return);
-
-		# Sort the results
-		asort($return);
-
-		return $return;
-	}
-
-	/**
-	 * Explode a DN into an array of its RDN parts.
-	 *
-	 * @param string The DN to explode.
-	 * @param int (optional) Whether to include attribute names (see http://php.net/ldap_explode_dn for details)
-	 *
-	 * @return array An array of RDN parts of this format:
-	 * 
-	 *	Array
-	 *		(
-	 *			[0] => uid=ppratt
-	 *			[1] => ou=People
-	 *			[2] => dc=example
-	 *			[3] => dc=com
-	 *		)
-	 * 
-	 *
-	 * NOTE: When a multivalue RDN is passed to ldap_explode_dn, the results returns with 'value + value';
-	 */
-	private function explodeDN($dn,$with_attributes=0) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		static $CACHE;
-
-		if (isset($CACHE['explode'][$dn][$with_attributes])) {
-			if (DEBUG_ENABLED)
-				debug_log('Return CACHED result (%s) for (%s)',1,0,__FILE__,__LINE__,__METHOD__,
-					$CACHE['explode'][$dn][$with_attributes],$dn);
-
-			return $CACHE['explode'][$dn][$with_attributes];
-		}
-
-		$dn = addcslashes($dn,'<>+";');
-
-		# split the dn
-		$result[0] = ldap_explode_dn($this->escapeDN($dn),0);
-		$result[1] = ldap_explode_dn($this->escapeDN($dn),1);
-		if (! $result[$with_attributes]) {
-			if (DEBUG_ENABLED)
-				debug_log('Returning NULL - NO result.',1,0,__FILE__,__LINE__,__METHOD__);
-
-			return array();
-		}
-
-		# Remove our count value that ldap_explode_dn returns us.
-		unset($result[0]['count']);
-		unset($result[1]['count']);
-
-		# Record the forward and reverse entries in the cache.
-		foreach ($result as $key => $value) {
-			# translate hex code into ascii for display
-			$result[$key] = $this->unescapeDN($value);
-
-			$CACHE['explode'][implode(',',$result[0])][$key] = $result[$key];
-			$CACHE['explode'][implode(',',array_reverse($result[0]))][$key] = array_reverse($result[$key]);
-		}
-
-		if (DEBUG_ENABLED)
-			debug_log('Returning (%s)',17,0,__FILE__,__LINE__,__METHOD__,$result[$with_attributes]);
-
-		return $result[$with_attributes];
-	}
-
-	/**
-	 * Parse a DN and escape any special characters
-	 */
-	protected function escapeDN($dn) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		if (! trim($dn))
-			return $dn;
-
-		# Check if the RDN has a comma and escape it.
-		while (preg_match('/([^\\\\]),(\s*[^=]*\s*),/',$dn))
-			$dn = preg_replace('/([^\\\\]),(\s*[^=]*\s*),/','$1\\\\2C$2,',$dn);
-
-		$dn = preg_replace('/([^\\\\]),(\s*[^=]*\s*)([^,])$/','$1\\\\2C$2$3',$dn);
-
-		if (DEBUG_ENABLED)
-			debug_log('Returning (%s)',17,0,__FILE__,__LINE__,__METHOD__,$dn);
-
-		return $dn;
-	}
-
-	/**
-	 * Parse a DN and unescape any special characters
-	 */
-	private function unescapeDN($dn) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		if (is_array($dn)) {
-			$a = array();
-			foreach ($dn as $key => $rdn) {
-				$a[$key] = preg_replace_callback('/\\\([0-9A-Fa-f]{2})/', function($m) { return chr(hexdec('${m[1]}')); }, $rdn);
-			}
-			return $a;
-
-		} else {
-			return preg_replace_callback('/\\\([0-9A-Fa-f]{2})/', function($m) { return chr(hexdec('${m[1]}')); }, $dn);
-		}
-	}
-
-	/** Schema Methods **/
-
-	/**
-	 * Much like getDNAttrValues(), but only returns the values for
-	 * one attribute of an object. Example calls:
-	 *
-	 * 
-	 *	print_r(getDNAttrValue('cn=Bob,ou=people,dc=example,dc=com','sn'));
-	 *	Array (
-	 *		[0] => Smith
-	 *	)
-	 *
-	 * print_r(getDNAttrValue('cn=Bob,ou=people,dc=example,dc=com','objectClass'));
-	 *	Array (
-	 *		[0] => top
-	 *		[1] => person
-	 *	)
-	 * 
-	 *
-	 * @param string The distinguished name (DN) of the entry whose attributes/values to fetch.
-	 * @param string The attribute whose value(s) to return (ie, "objectClass", "cn", "userPassword")
-	 * @param string Which connection method resource to use
-	 * @param constant For aliases and referrals, this parameter specifies whether to
-	 *            follow references to the referenced DN or to fetch the attributes for
-	 *            the referencing DN. See http://php.net/ldap_search for the 4 valid
-	 *            options.
-	 * @return array
-	 * @see getDNAttrValues
-	 * @todo Caching these values may be problematic with multiple calls and different deref values.
-	 */
-	public function getDNAttrValue($dn,$attr,$method=null,$deref=LDAP_DEREF_NEVER) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		# Ensure our attr is in lowercase
-		$attr = strtolower($attr);
-
-		$values = $this->getDNAttrValues($dn,$method,$deref);
-
-		if (isset($values[$attr]))
-			return $values[$attr];
-		else
-			return array();
-	}
-
-	/**
-	 * Gets the attributes/values of an entry. Returns an associative array whose
-	 * keys are attribute value names and whose values are arrays of values for
-	 * said attribute.
-	 *
-	 * Optionally, callers may specify true for the parameter
-	 * $lower_case_attr_names to force all keys in the associate array (attribute
-	 * names) to be lower case.
-	 *
-	 * Example of its usage:
-	 * 
-	 * print_r(getDNAttrValues('cn=Bob,ou=pepole,dc=example,dc=com')
-	 *	Array (
-	 *		[objectClass] => Array (
-	 *			[0] => person
-	 *			[1] => top
-	 *		)
-	 *		[cn] => Array (
-	 *			[0] => Bob
-	 *		)
-	 *		[sn] => Array (
-	 *			[0] => Jones
-	 *		)
-	 *		[dn] => Array (
-	 *			[0] => cn=Bob,ou=pepole,dc=example,dc=com
-	 *		)
-	 *	)
-	 * 
-	 *
-	 * @param string The distinguished name (DN) of the entry whose attributes/values to fetch.
-	 * @param string Which connection method resource to use
-	 * @param constant For aliases and referrals, this parameter specifies whether to
-	 *            follow references to the referenced DN or to fetch the attributes for
-	 *            the referencing DN. See http://php.net/ldap_search for the 4 valid
-	 *            options.
-	 * @return array
-	 * @see getDNSysAttrs
-	 * @see getDNAttrValue
-	 */
-	public function getDNAttrValues($dn,$method=null,$deref=LDAP_DEREF_NEVER,$attrs=array('*','+'),$nocache=false) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		static $CACHE;
-
-		$cacheindex = null;
-		$method = $this->getMethod($method);
-
-		if (in_array('*',$attrs) && in_array('+',$attrs))
-			$cacheindex = '&';
-		elseif (in_array('+',$attrs))
-			$cacheindex = '+';
-		elseif (in_array('*',$attrs))
-			$cacheindex = '*';
-
-		if (! $nocache && ! is_null($cacheindex) && isset($CACHE[$this->index][$method][$dn][$cacheindex])) {
-			$results = $CACHE[$this->index][$method][$dn][$cacheindex];
-
-			if (DEBUG_ENABLED)
-				debug_log('Returning (%s)',17,0,__FILE__,__LINE__,__METHOD__,$results);
-
-		} else {
-			$query = array();
-			$query['base'] = $this->escapeDN($dn);
-			$query['scope'] = 'base';
-			$query['deref'] = $deref;
-			$query['attrs'] = $attrs;
-			$query['baseok'] = true;
-			$results = $this->query($query,$method);
-
-			if (count($results))
-				$results = array_pop($results);
-
-			$results = array_change_key_case($results);
-
-			# Covert all our result key values to an array
-			foreach ($results as $key => $values)
-				if (! is_array($results[$key]))
-					$results[$key] = array($results[$key]);
-
-			# Finally sort the results
-			ksort($results);
-
-			if (! is_null($cacheindex) && count($results))
-				$CACHE[$this->index][$method][$dn][$cacheindex] = $results;
-		}
-
-		return $results;
-	}
-
-	/**
-	 * Returns true if the attribute specified is required to take as input a DN.
-	 * Some examples include 'distinguishedName', 'member' and 'uniqueMember'.
-	 *
-	 * @param string $attr_name The name of the attribute of interest (case insensitive)
-	 * @return boolean
-	 */
-	function isDNAttr($attr_name,$method=null) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		# Simple test first
-		$dn_attrs = array('aliasedObjectName');
-		foreach ($dn_attrs as $dn_attr)
-			if (strcasecmp($attr_name,$dn_attr) == 0)
-				return true;
-
-		# Now look at the schema OID
-		$sattr = $this->getSchemaAttribute($attr_name);
-		if (! $sattr)
-			return false;
-
-		$syntax_oid = $sattr->getSyntaxOID();
-		if ('1.3.6.1.4.1.1466.115.121.1.12' == $syntax_oid)
-		 	return true;
-		if ('1.3.6.1.4.1.1466.115.121.1.34' == $syntax_oid)
-			return true;
-
-		$syntaxes = $this->SchemaSyntaxes($method);
-		if (! isset($syntaxes[$syntax_oid]))
-			return false;
-
-		$syntax_desc = $syntaxes[ $syntax_oid ]->getDescription();
-		if (strpos(strtolower($syntax_desc),'distinguished name'))
-			return true;
-
-		return false;
-	}
-
-	/**
-	 * Used to determine if the specified attribute is indeed a jpegPhoto. If the
-	 * specified attribute is one that houses jpeg data, true is returned. Otherwise
-	 * this function returns false.
-	 *
-	 * @param string $attr_name The name of the attribute to test.
-	 * @return boolean
-	 * @see draw_jpeg_photo
-	 */
-	function isJpegPhoto($attr_name) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		# easy quick check
-		if (! strcasecmp($attr_name,'jpegPhoto') || ! strcasecmp($attr_name,'photo'))
-			return true;
-
-		# go to the schema and get the Syntax OID
-		$sattr = $this->getSchemaAttribute($attr_name);
-		if (! $sattr)
-			return false;
-
-		$oid = $sattr->getSyntaxOID();
-		$type = $sattr->getType();
-
-		if (! strcasecmp($type,'JPEG') || ($oid == '1.3.6.1.4.1.1466.115.121.1.28'))
-			return true;
-
-		return false;
-	}
-
-	/**
-	 * Given an attribute name and server ID number, this function returns
-	 * whether the attrbiute contains boolean data. This is useful for
-	 * developers who wish to display the contents of a boolean attribute
-	 * with a drop-down.
-	 *
-	 * @param string $attr_name The name of the attribute to test.
-	 * @return boolean
-	 */
-	function isAttrBoolean($attr_name) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		$type = ($sattr = $this->getSchemaAttribute($attr_name)) ? $sattr->getType() : null;
-
-		if (! strcasecmp('boolean',$type) ||
-			! strcasecmp('isCriticalSystemObject',$attr_name) ||
-			! strcasecmp('showInAdvancedViewOnly',$attr_name))
-			return true;
-
-		else
-			return false;
-	}
-
-	/**
-	 * Given an attribute name and server ID number, this function returns
-	 * whether the attribute may contain binary data. This is useful for
-	 * developers who wish to display the contents of an arbitrary attribute
-	 * but don't want to dump binary data on the page.
-	 *
-	 * @param string $attr_name The name of the attribute to test.
-	 * @return boolean
-	 *
-	 * @see isJpegPhoto
-	 */
-	function isAttrBinary($attr_name) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		/**
-		 * Determining if an attribute is binary can be an expensive operation.
-		 * We cache the results for each attr name on each server in the $attr_cache
-		 * to speed up subsequent calls. The $attr_cache looks like this:
-		 *
-		 * Array
-		 * 0 => Array
-		 *	'objectclass' => false
-		 *	'cn' => false
-		 *	'usercertificate' => true
-		 * 1 => Array
-		 *	'jpegphoto' => true
-		 *	'cn' => false
-		 */
-
-		static $attr_cache;
-
-		$attr_name = strtolower($attr_name);
-
-		if (isset($attr_cache[$this->index][$attr_name]))
-			return $attr_cache[$this->index][$attr_name];
-
-		if ($attr_name == 'userpassword') {
-			$attr_cache[$this->index][$attr_name] = false;
-			return false;
-		}
-
-		# Quick check: If the attr name ends in ";binary", then it's binary.
-		if (strcasecmp(substr($attr_name,strlen($attr_name) - 7),';binary') == 0) {
-			$attr_cache[$this->index][$attr_name] = true;
-			return true;
-		}
-
-		# See what the server schema says about this attribute
-		$sattr = $this->getSchemaAttribute($attr_name);
-		if (! is_object($sattr)) {
-
-			/* Strangely, some attributeTypes may not show up in the server
-			 * schema. This behavior has been observed in MS Active Directory.*/
-			$type = null;
-			$syntax = null;
-
-		} else {
-			$type = $sattr->getType();
-			$syntax = $sattr->getSyntaxOID();
-		}
-
-		if (strcasecmp($type,'Certificate') == 0 ||
-			strcasecmp($type,'Binary') == 0 ||
-			strcasecmp($attr_name,'usercertificate') == 0 ||
-			strcasecmp($attr_name,'usersmimecertificate') == 0 ||
-			strcasecmp($attr_name,'networkaddress') == 0 ||
-			strcasecmp($attr_name,'objectGUID') == 0 ||
-			strcasecmp($attr_name,'objectSID') == 0 ||
-			strcasecmp($attr_name,'auditingPolicy') == 0 ||
-			strcasecmp($attr_name,'jpegPhoto') == 0 ||
-			strcasecmp($attr_name,'krbExtraData') == 0 ||
-			strcasecmp($attr_name,'krbPrincipalKey') == 0 ||
-			$syntax == '1.3.6.1.4.1.1466.115.121.1.10' ||
-			$syntax == '1.3.6.1.4.1.1466.115.121.1.28' ||
-			$syntax == '1.3.6.1.4.1.1466.115.121.1.5' ||
-			$syntax == '1.3.6.1.4.1.1466.115.121.1.8' ||
-			$syntax == '1.3.6.1.4.1.1466.115.121.1.9'
-		) {
-
-			$attr_cache[$this->index][$attr_name] = true;
-			return true;
-
-		} else {
-			$attr_cache[$this->index][$attr_name] = false;
-			return false;
-		}
-	}
-
-	/**
-	 * This function will test if a user is a member of a group.
-	 *
-	 * Inputs:
-	 * @param string $user membership value that is being checked
-	 * @param dn $group DN to see if user is a member
-	 * @return bool true|false
-	 */
-	function userIsMember($user,$group) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		$user = strtolower($user);
-		$group = $this->getDNAttrValues($group);
-
-		# If you are using groupOfNames objectClass
-		if (array_key_exists('member',$group) && ! is_array($group['member']))
-			$group['member'] = array($group['member']);
-
-		if (array_key_exists('member',$group) &&
-			in_array($user,arrayLower($group['member'])))
-
-			return true;
-
-		# If you are using groupOfUniqueNames objectClass
-		if (array_key_exists('uniquemember',$group) && ! is_array($group['uniquemember']))
-			$group['uniquemember'] = array($group['uniquemember']);
-
-		if (array_key_exists('uniquemember',$group) &&
-			in_array($user,arrayLower($group['uniquemember'])))
-
-			return true;
-
-		return false;
-	}
-
-	/**
-	 * This function will determine if the user is allowed to login based on a filter
-	 */
-	protected function userIsAllowedLogin($dn) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		$dn = trim(strtolower($dn));
-
-		if (! $this->getValue('login','allowed_dns'))
-			return true;
-
-        foreach ($this->getValue('login','allowed_dns') as $login_allowed_dn) {
-            if (DEBUG_ENABLED)
-                debug_log('Working through (%s)',80,0,__FILE__,__LINE__,__METHOD__,$login_allowed_dn);
-
-            /* Check if $login_allowed_dn is an ldap search filter
-             * Is first occurence of 'filter=' (case ensitive) at position 0 ? */
-            if (preg_match('/^\([&|]\(/',$login_allowed_dn)) {
-				$query = array();
-                $query['filter'] = $login_allowed_dn;
-				$query['attrs'] = array('dn');
-
-                foreach($this->getBaseDN() as $base_dn) {
-					$query['base'] = $base_dn;
-
-                    $results = $this->query($query,null);
-
-                    if (DEBUG_ENABLED)
-                        debug_log('Search, Filter [%s], BaseDN [%s] Results [%s]',16,0,__FILE__,__LINE__,__METHOD__,
-                            $query['filter'],$query['base'],$results);
-
-                    if ($results) {
-                    	$dn_array = array();
-
-                        foreach ($results as $result)
-                            array_push($dn_array,$result['dn']);
-
-                        $dn_array = array_unique($dn_array);
-
-                        if (count($dn_array))
-                            foreach ($dn_array as $result_dn) {
-                                if (DEBUG_ENABLED)
-                                    debug_log('Comparing with [%s]',80,0,__FILE__,__LINE__,__METHOD__,$result_dn);
-
-                                # Check if $result_dn is a user DN
-                                if (strcasecmp($dn,trim(strtolower($result_dn))) == 0)
-                                    return true;
-
-                                # Check if $result_dn is a group DN
-                                if ($this->userIsMember($dn,$result_dn))
-                                    return true;
-                        }
-                    }
-                }
-            }
-
-            # Check if $login_allowed_dn is a user DN
-            if (strcasecmp($dn,trim(strtolower($login_allowed_dn))) == 0)
-                return true;
-
-            # Check if $login_allowed_dn is a group DN
-            if ($this->userIsMember($dn,$login_allowed_dn))
-                return true;
-        }
-
-        return false;
-	}
-}
-?>
diff --git a/lib/ds_ldap_pla.php b/lib/ds_ldap_pla.php
deleted file mode 100644
index 7631643d..00000000
--- a/lib/ds_ldap_pla.php
+++ /dev/null
@@ -1,677 +0,0 @@
-default->appearance['pla_password_hash'] = array(
-			'desc'=>'Default HASH to use for passwords',
-			'default'=>'md5');
-
-		$this->default->appearance['show_create'] = array(
-			'desc'=>'Whether to show the "Create new Entry here" in the tree browser',
-			'default'=>true);
-
-		$this->default->appearance['open_tree'] = array(
-			'desc'=>'Whether to initially open each tree',
-			'default'=>false);
-
-		$this->default->appearance['show_authz'] = array(
-			'desc'=>'Enable display of authorization ID as login',
-			'default'=>false);
-
-		$this->default->login['fallback_dn'] = array(
-			'desc'=>'If the attribute base login fails, see if a DN was entered',
-			'default'=>false);
-
-		$this->default->query['disable_default'] = array(
-			'desc'=>'Configuration to disable the default query template',
-			'default'=>false);
-
-		$this->default->query['custom_only'] = array(
-			'desc'=>'Configuration to force the usage of custom query templates',
-			'default'=>false);
-
-		$this->default->server['branch_rename'] = array(
-			'desc'=>'Enable renaming of branches',
-			'default'=>false);
-
-		$this->default->server['custom_attrs'] = array(
-			'desc'=>'Custom operational attributes to be treated as regular attributes',
-			'default'=>array(''));
-
-		$this->default->server['custom_sys_attrs'] = array(
-			'desc'=>'Custom operational attributes to be treated as internal attributes',
-			'default'=>array('+'));
-
-		# This was added in case the LDAP server doesnt provide them with a base +,* query.
-		$this->default->server['root_dse_attributes'] = array(
-			'desc'=>'RootDSE attributes for use when displaying server info',
-			'default'=>array(
-				'namingContexts',
-				'subschemaSubentry',
-				'altServer',
-				'supportedExtension',
-				'supportedControl',
-				'supportedSASLMechanisms',
-				'supportedLDAPVersion',
-				'currentTime',
-				'dsServiceName',
-				'defaultNamingContext',
-				'schemaNamingContext',
-				'configurationNamingContext',
-				'rootDomainNamingContext',
-				'supportedLDAPPolicies',
-				'highestCommittedUSN',
-				'dnsHostName',
-				'ldapServiceName',
-				'serverName',
-				'supportedCapabilities',
-				'changeLog',
-				'tlsAvailableCipherSuites',
-				'tlsImplementationVersion',
-				'supportedSASLMechanisms',
-				'dsaVersion',
-				'myAccessPoint',
-				'dseType',
-				'+',
-				'*'
-			));
-
-		$this->default->server['force_may'] = array(
-			'desc'=>'Force server MUST attributes as MAY attributes',
-			'default'=>array(
-			));
-
-		# Settings for auto_number
-		$this->default->auto_number['enable'] = array(
-			'desc'=>'Enable the AUTO UID feature',
-			'default'=>true);
-
-		$this->default->auto_number['mechanism'] = array(
-			'desc'=>'Mechanism to use to search for automatic numbers',
-			'default'=>'search');
-
-		$this->default->auto_number['search_base'] = array(
-			'desc'=>'Base DN to use for search mechanisms',
-			'default'=>null);
-
-		$this->default->auto_number['min'] = array(
-			'desc'=>'Minimum number to start with',
-			'default'=>array('uidNumber'=>1000,'gidNumber'=>500));
-
-		$this->default->auto_number['dn'] = array(
-			'desc'=>'DN to use when evaluating numbers',
-			'default'=>null);
-
-		$this->default->auto_number['pass'] = array(
-			'desc'=>'Password for DN to use when evaluating numbers',
-			'default'=>null);
-
-		$this->default->unique['attrs'] = array(
-			'desc'=>'Attributes to check for uniqueness before allowing updates',
-			'default'=>array('mail','uid','uidNumber'));
-
-		$this->default->unique['dn'] = array(
-			'desc'=>'DN to use when evaluating attribute uniqueness',
-			'default'=>null);
-
-		$this->default->unique['pass'] = array(
-			'desc'=>'Password for DN to use when evaluating attribute uniqueness',
-			'default'=>null);
-	}
-
-	public function __get($key) {
-		switch ($key) {
-			case 'name':
-				return $this->getValue('server','name');
-
-			default:
-				system_message(array(
-					'title'=>_('Unknown request for Object value.'),
-					'body'=>sprintf(_('Attempt to obtain value %s from %s'),$key,get_class($this)),
-					'type'=>'error'));
-		}
-	}
-
-	/**
-	 * Gets whether the admin has configured phpLDAPadmin to show the "Create New" link in the tree viewer.
-	 * 
-	 *	$servers->setValue('appearance','show_create',true|false);
-	 * 
-	 * If NOT set, then default to show the Create New item.
-	 * If IS set, then return the value (it should be true or false).
-	 *
-	 * The entry creation command must be available.
-	 * 
-	 *	$config->custom->commands['script'] = array('create' => true);
-	 * 
-	 *
-	 * @return boolean true if the feature is enabled and false otherwise.
-	 */
-	function isShowCreateEnabled() {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		if (! $_SESSION[APPCONFIG]->isCommandAvailable('script','create'))
-			return false;
-		else
-			return $this->getValue('appearance','show_create');
-	}
-
-	/**
-	 * Fetch whether the user has configured a certain server login to be non anonymous
-	 *
-	 * 
-	 *	$servers->setValue('login','anon_bind',true|false);
-	 * 
-	 *
-	 * @return boolean
-	 */
-	public function isAnonBindAllowed() {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		# If only_login_allowed_dns is set, then we cant have anonymous.
-		if (count($this->getValue('login','allowed_dns')) > 0)
-			$return = false;
-		else
-			$return = $this->getValue('login','anon_bind');
-
-		if (DEBUG_ENABLED)
-			debug_log('Returning (%s)',17,0,__FILE__,__LINE__,__METHOD__,$return);
-
-		return $return;
-	}
-
-	/**
-	 * Returns true if the user has configured the specified server to enable branch (non-leaf) renames.
-	 *
-	 * This is configured in config.php thus:
-	 * 
-	 *	$servers->setValue('server','branch_rename',true|false);
-	 * 
-	 *
-	 * @return boolean
-	 */
-	function isBranchRenameEnabled() {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
- 		return $this->getValue('server','branch_rename');
-	}
-
-	/**
-	 * Determines if an attribute's value can contain multiple lines. Attributes that fall
-	 * in this multi-line category may be configured in config.php. Hence, this function
-	 * accesses the global variable $_SESSION[APPCONFIG]->custom->appearance['multi_line_attributes'];
-	 *
-	 * Usage example:
-	 * 
-	 *	if ($ldapserver->isMultiLineAttr('postalAddress'))
-	 *		echo '';
-	 *	else
-	 *		echo '';
-	 * 
-	 *
-	 * @param string The name of the attribute of interested (case insensivite)
-	 * @param string (optional) The current value of the attribute (speeds up the process by searching for carriage returns already in the attribute value)
-	 * @return boolean
-	 */
-	function isMultiLineAttr($attr_name,$val=null) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		# Set default return
-		$return = false;
-
-		# First, check the optional val param for a \n or a \r
-		if (! is_null($val) && (strpos($val,"\n") || strpos($val,"\r")))
-			$return = true;
-
-		# Next, compare strictly by name first
-		else
-			foreach ($_SESSION[APPCONFIG]->getValue('appearance','multi_line_attributes') as $multi_line_attr_name)
-				if (strcasecmp($multi_line_attr_name,$attr_name) == 0) {
-					$return = true;
-					break;
-				}
-
-		# If unfound, compare by syntax OID
-		if (! $return) {
-			$sattr = $this->getSchemaAttribute($attr_name);
-
-			if ($sattr) {
-				$syntax_oid = $sattr->getSyntaxOID();
-
-				if ($syntax_oid)
-					foreach ($_SESSION[APPCONFIG]->getValue('appearance','multi_line_syntax_oids') as $multi_line_syntax_oid)
-						if ($multi_line_syntax_oid == $syntax_oid) {
-							$return = true;
-							break;
-						}
-			}
-		}
-
-		if (DEBUG_ENABLED)
-			debug_log('Returning (%s)',17,0,__FILE__,__LINE__,__METHOD__,$return);
-
-		return $return;
-	}
-
-	/**
-	 * Returns true if the specified attribute is configured according to
-	 * the test enabled in config.php
-	 *
-	 * @param string The name of the attribute to test.
-	 * @param array The attributes to test against.
-	 * @param dn A DN that is exempt from these tests.
-	 * @return boolean
-	 */
-	private function isAttrTest($attr,$attrs,$except_dn) {
-		$attr = trim($attr);
-		if (! trim($attr) || ! count($attrs))
-			return false;
-
-		# Is the user excluded?
-		if ($except_dn && $this->userIsMember($this->getLogin(),$except_dn))
-			return false;
-
-		foreach ($attrs as $attr_name)
-			if (strcasecmp($attr,trim($attr_name)) == 0)
-				return true;
-
-		return false;
-	}
-
-	/**
-	 * Returns true if the specified attribute is configured as read only
-	 * in config.php.
-	 * Attributes are configured as read-only in config.php thus:
-	 * 
-	 *	$config->custom->appearance['readonly_attrs'] = array('objectClass');
-	 * 
-	 *
-	 * @param string The name of the attribute to test.
-	 * @return boolean
-	 */
-	public function isAttrReadOnly($attr) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		$attrs = $_SESSION[APPCONFIG]->getValue('appearance','readonly_attrs');
-		$except_dn = $_SESSION[APPCONFIG]->getValue('appearance','readonly_attrs_exempt');
-
-		return $this->isAttrTest($attr,$attrs,$except_dn);
-	}
-
-	/**
-	 * Returns true if the specified attribute is configured as hidden
-	 * in config.php.
-	 * Attributes are configured as hidden in config.php thus:
-	 * 
-	 *	$config->custom->appearance['hide_attrs'] = array('objectClass');
-	 * 
-	 *
-	 * @param string The name of the attribute to test.
-	 * @return boolean
-	 */
-	public function isAttrHidden($attr) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		$attrs = $_SESSION[APPCONFIG]->getValue('appearance','hide_attrs');
-		$except_dn = $_SESSION[APPCONFIG]->getValue('appearance','hide_attrs_exempt');
-
-		return $this->isAttrTest($attr,$attrs,$except_dn);
-	}
-
-	/**
-	 * Add objects
-	 */
-	public function add($dn,$entry_array,$method=null) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		foreach ($entry_array as $attr => $val)
-			$entry_array[$attr] = dn_unescape($val);
-
-		$result = false;
-
-		# Check our unique attributes.
-		if (! $this->checkUniqueAttrs($dn,$entry_array))
-			return false;
-
-		if (run_hook('pre_entry_create',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attrs'=>$entry_array))) {
-			$result = @ldap_add($this->connect($method),dn_escape($dn),$entry_array);
-
-			if ($result) {
-				# Update the tree
-				$tree = get_cached_item($this->index,'tree');
-
-				# If we created the base, delete it, then add it back
-				if (get_request('create_base'))
-					$tree->delEntry($dn);
-
-				$tree->addEntry($dn);
-
-				set_cached_item($this->index,'tree','null',$tree);
-
-				run_hook('post_entry_create',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attrs'=>$entry_array));
-
-			} else {
-				system_message(array(
-					'title'=>_('Could not add the object to the LDAP server.'),
-					'body'=>ldap_error_msg($this->getErrorMessage(null),$this->getErrorNum(null)),
-					'type'=>'error'));
-			}
-		}
-
-		return $result;
-	}
-
-	/**
-	 * Delete objects
-	 */
-	public function delete($dn,$method=null) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		$result = false;
-
-		if (run_hook('pre_entry_delete',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn))) {
-			$result = @ldap_delete($this->connect($method),dn_escape($dn));
-
-			if ($result) {
-				# Update the tree
-				$tree = get_cached_item($this->index,'tree');
-				$tree->delEntry($dn);
-
-				set_cached_item($this->index,'tree','null',$tree);
-
-				run_hook('post_entry_delete',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn));
-			}
-		}
-
-		return $result;
-	}
-
-	/**
-	 * Rename objects
-	 */
-	public function rename($dn,$new_rdn,$container,$deleteoldrdn,$method=null) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		$result = false;
-
-		if (run_hook('pre_entry_rename',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'rdn'=>$new_rdn,'container'=>$container))) {
-			$result = @ldap_rename($this->connect($method),$dn,$new_rdn,$container,$deleteoldrdn);
-
-			if ($result) {
-				# Update the tree
-				$tree = get_cached_item($this->index,'tree');
-				$newdn = sprintf('%s,%s',$new_rdn,$container);
-				$tree->renameEntry($dn,$newdn);
-
-				set_cached_item($this->index,'tree','null',$tree);
-
-				run_hook('post_entry_rename',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'rdn'=>$new_rdn,'container'=>$container));
-			}
-		}
-
-		return $result;
-	}
-
-	/**
-	 * Modify objects
-	 */
-	public function modify($dn,$attrs,$method=null) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		# Check our unique attributes.
-		if (! $this->checkUniqueAttrs($dn,$attrs))
-			return false;
-
-		$result = false;
-		$summary = array();
-		$current_attrs = $this->getDNAttrValues($dn,$method,LDAP_DEREF_NEVER,array('*'));
-
-		# Go through our attributes and call our hooks for each attribute changing its value
-		foreach ($attrs as $attr => $values) {
-			# For new attributes
-			if (count($values) && ! isset($current_attrs[$attr])) {
-				if (! run_hook('pre_attr_add',
-					array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attr'=>$attr,'newvalue'=>$values))) {
-
-					unset($attrs[$attr]);
-					system_message(array(
-						'title'=>_('Attribute not added'),
-						'body'=>sprintf('%s (%s)',_('Hook pre_attr_add prevented attribute from being added'),$attr),
-						'type'=>'warn'));
-
-				} else
-					$summary['add'][$attr]['new'] = $values;
-
-			# For modify attributes
-			} elseif (count($values)) {
-				if (! run_hook('pre_attr_modify',
-					array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attr'=>$attr,'oldvalue'=>$current_attrs[$attr],'newvalue'=>$values))) {
-
-					unset($attrs[$attr]);
-					system_message(array(
-						'title'=>_('Attribute not modified'),
-						'body'=>sprintf('%s (%s)',_('Hook pre_attr_modify prevented attribute from being modified'),$attr),
-						'type'=>'warn'));
-
-				} else {
-					$summary['modify'][$attr]['new'] = $values;
-					$summary['modify'][$attr]['old'] = $current_attrs[$attr];
-				}
-
-			# For delete attributes
-			} else {
-				if (! run_hook('pre_attr_delete',
-					array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attr'=>$attr,'oldvalue'=>$current_attrs[$attr]))) {
-
-					unset($attrs[$attr]);
-					system_message(array(
-						'title'=>_('Attribute not deleted'),
-						'body'=>sprintf('%s (%s)',_('Hook pre_attr_delete prevented attribute from being deleted'),$attr),
-						'type'=>'warn'));
-
-				} else
-					$summary['delete'][$attr]['old'] = $current_attrs[$attr];
-			}
-		}
-
-		if (! count($attrs))
-			return false;
-
-		if (run_hook('pre_entry_modify',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attrs'=>$attrs))) {
-			$result = @ldap_modify($this->connect($method),$dn,$attrs);
-
-			if ($result) {
-				run_hook('post_entry_modify',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attrs'=>$attrs));
-
-				foreach (array('add','modify','delete') as $mode)
-					if (isset($summary[$mode]))
-						foreach ($summary[$mode] as $attr => $values)
-							switch ($mode) {
-								case 'add':
-									run_hook(sprintf('post_attr_%s',$mode),
-										array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attr'=>$attr,'newvalue'=>$values['new']));
-									break;
-
-								case 'modify':
-									run_hook(sprintf('post_attr_%s',$mode),
-										array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attr'=>$attr,'oldvalue'=>$values['old'],'newvalue'=>$values['new']));
-									break;
-
-								case 'delete':
-									run_hook(sprintf('post_attr_%s',$mode),
-										array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attr'=>$attr,'oldvalue'=>$values['old']));
-									break;
-
-								default:
-									debug_dump_backtrace(sprintf('Unkown mode %s',$mode),1);
-							}
-			} else {
-				system_message(array(
-					'title'=>_('Could not perform ldap_modify operation.'),
-					'body'=>ldap_error_msg($this->getErrorMessage($method),$this->getErrorNum($method)),
-					'type'=>'error'));
-			}
-		}
-
-		return $result;
-	}
-
-	/**
-	 * Returns true if the specified attribute is configured as unique
-	 * in config.php.
-	 * Attributes are configured as hidden in config.php thus:
-	 * 
-	 *	$servers->setValue('unique','attrs',array('mail','uid','uidNumber'));
-	 * 
-	 *
-	 * @param string $attr The name of the attribute to test.
-	 * @return boolean
-	 */
-	public function isAttrUnique($attr) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		# Should this attribute value be unique
-		if (in_array_ignore_case($attr,$this->getValue('unique','attrs')))
-			return true;
-		else
-			return false;
-	}
-
-	/**
-	 * This function will check whether the value for an attribute being changed
-	 * is already assigned to another DN.
-	 *
-	 * Returns the bad value, or null if all values are OK
-	 *
-	 * @param dn DN that is being changed
-	 * @param string Attribute being changed
-	 * @param string|array New values for the attribute
-	 */
-	public function checkUniqueAttrs($dn,$attrs) {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		# If none of the attributes are defined unique, we'll return immediately;
-		if (! $checkattrs = array_intersect(arrayLower($this->getValue('unique','attrs')),array_keys(array_change_key_case($attrs))))
-			return true;
-
-		# Check see and use our alternate uid_dn and password if we have it.
-		if (! $this->login($this->getValue('unique','dn'),$this->getValue('unique','pass'),'unique')) {
-			system_message(array(
-				'title'=>_('UNIQUE invalid login/password'),
-				'body'=>sprintf('%s (%s)',_('Unable to connect to LDAP server with the unique login/password, please check your configuration.'),
-					$this->getName()),
-				'type'=>'warn'));
-
-			return false;
-		}
-
-		$query = array();
-
-		# Build our search filter to double check each attribute.
-		$query['filter'] = '(|';
-		foreach ($checkattrs as $attr)
-			foreach ($attrs[$attr] as $val)
-				if ($val)
-					$query['filter'] .= sprintf('(%s=%s)',$attr,$val);
-		$query['filter'] .= ')';
-
-		$query['attrs'] = $checkattrs;
-
-		# Search through our bases and see if we have match
-		foreach ($this->getBaseDN() as $base) {
-			$query['base'] = $base;
-
-			# Do the search
-			$results = $this->query($query,'unique');
-
-			# If we have a match.
-			if (count($results))
-				foreach ($results as $values)
-					# If one of the attributes is owned to somebody else, then we may as well die here.
-					if ($values['dn'] != $dn) {
-						$href = sprintf('cmd.php?cmd=query_engine&server_id=%s&filter=%s&scope=sub&query=none&format=list&search=true',$this->index,$query['filter']);
-
-						system_message(array(
-							'title'=>_('Attribute value would not be unique'),
-							'body'=>sprintf('%s (%s)',
-								_('This update has been or will be cancelled, it would result in an attribute value not being unique. You might like to search the LDAP server for the offending entry.'),
-								htmlspecialchars($href),
-								_('Search')),
-							'type'=>'warn'));
-
-						return false;
-					}
-		}
-
-		# If we get here, then it must be OK?
-		return true;
-	}
-
-	/**
-	 * Check if the session timeout has occured for this LDAP server.
-	 */
-	public function isSessionValid() {
-		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-		# If inactiveTime() returns a value, we need to check that it has not expired.
-		if (is_null($this->inactivityTime()) || ! $this->isLoggedIn())
-			return true;
-
-		# If session has expired
-		if ((isset($_SESSION['ACTIVITY'][$this->getIndex()])) && ($_SESSION['ACTIVITY'][$this->getIndex()] < time())) {
-			$this->logout();
-			unset($_SESSION['ACTIVITY'][$this->getIndex()]);
-
-			return false;
-		}
-
-		$_SESSION['ACTIVITY'][$this->getIndex()] = $this->inactivityTime();
-		return true;
-	}
-
-	/**
-	 * Return login, or authorization ID if show_authz enabled
-	 */
-	public function displayLogin($method=null) {
-		// check for whoami function, added in 7.2
-		if ($this->getValue('appearance', 'show_authz') && function_exists('ldap_exop_whoami')) {
-			$result = @ldap_exop_whoami($this->connect($method));
-			if ($result) // strip any dn: or u: prefix
-				$result = preg_replace('/^(u|dn):/i', '', $result);
-			else // fall back to login on error
-				$result = $this->getLogin($method);
-			return $result;
-		}
-		else {
-			return $this->getLogin($method);
-		}
-	}
-}
-?>
diff --git a/lib/functions.php b/lib/functions.php
deleted file mode 100644
index 78492284..00000000
--- a/lib/functions.php
+++ /dev/null
@@ -1,2520 +0,0 @@
-_('Generic Error'),
-			'body'=>sprintf('%s: %s [%s]',
-				__METHOD__,_('Called to load a class that cant be found'),$className),
-			'type'=>'error'));
-}
-
-if (version_compare(phpversion(), '7.0', '>=')) {
-	spl_autoload_register('pla_autoload');
-} else {
-	eval('function __autoload($className) {pla_autoload($className);}');
-}
-
-/**
- * Strips all slashes from the specified array in place (pass by ref).
- * @param Array The array to strip slashes from, typically one of
- *        $_GET, $_POST, or $_COOKIE.
- */
-function array_stripslashes(&$array) {
-	if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-		debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-	if (is_array($array))
-		while (list($key) = each($array))
-			if (is_array($array[$key]) && $key != $array)
-				array_stripslashes($array[$key]);
-			else
-				$array[$key] = stripslashes($array[$key]);
-}
-
-/**
- * Compatibility Functions
- * These functions exist, so that a standard function can be used in new applications, and they
- * map to already defined functions in older applications.
- */
-
-/**
- * If gettext is not available in PHP, then this will provide compatibility for it.
- */
-if (! function_exists('_')) {
-	function _($msg) {
-		return $msg;
-	}
-}
-
-/**
- * Generic Utility Functions
- */
-
-/**
- * Custom error handling function.
- * When a PHP error occurs, PHP will call this function rather than printing
- * the typical PHP error string. This provides the application the ability to
- * format an error message so that it looks better.
- * Optionally, it can present a link so that a user can search/submit bugs.
- * This function is not to be called directly. It is exclusively for the use of
- * PHP internally. If this function is called by PHP from within a context
- * where error handling has been disabled (ie, from within a function called
- * with "@" prepended), then this function does nothing.
- *
- * @param int The PHP error number that occurred (ie, E_ERROR, E_WARNING, E_PARSE, etc).
- * @param string The PHP error string provided (ie, "Warning index "foo" is undefined)
- * @param string The file in which the PHP error ocurred.
- * @param int The line number on which the PHP error ocurred
- * @see set_error_handler
- */
-function app_error_handler($errno,$errstr,$file,$lineno) {
-	if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
-		debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs);
-
-	/**
-	 * error_reporting will be 0 if the error context occurred
-	 * within a function call with '@' preprended (ie, @ldap_bind() );
-	 * So, don't report errors if the caller has specifically
-	 * disabled them with '@'
-	 */
-	if (ini_get('error_reporting') == 0 || error_reporting() == 0)
-		return;
-
-	$file = basename($file);
-	$caller = basename($_SERVER['PHP_SELF']);
-	$errtype = '';
-
-	switch ($errno) {
-		case E_STRICT: $errtype = 'E_STRICT'; break;
-		case E_ERROR: $errtype = 'E_ERROR'; break;
-		case E_WARNING: $errtype = 'E_WARNING'; break;
-		case E_PARSE: $errtype = 'E_PARSE'; break;
-		case E_NOTICE: $errtype = 'E_NOTICE'; break;
-		case E_CORE_ERROR: $errtype = 'E_CORE_ERROR'; break;
-		case E_CORE_WARNING: $errtype = 'E_CORE_WARNING'; break;
-		case E_COMPILE_ERROR: $errtype = 'E_COMPILE_ERROR'; break;
-		case E_COMPILE_WARNING: $errtype = 'E_COMPILE_WARNING'; break;
-		case E_USER_ERROR: $errtype = 'E_USER_ERROR'; break;
-		case E_USER_WARNING: $errtype = 'E_USER_WARNING'; break;
-		case E_USER_NOTICE: $errtype = 'E_USER_NOTICE'; break;
-		case E_ALL: $errtype = 'E_ALL'; break;
-
-		default: $errtype = sprintf('%s: %s',_('Unrecognized error number'),$errno);
-	}
-
-	# Take out extra spaces in error strings.
-	$errstr = preg_replace('/\s+/',' ',$errstr);
-
-	if ($errno == E_NOTICE) {
-		$body = '';
-		$body .= sprintf('',_('Error'),$errstr,$errtype);
-		$body .= sprintf('',
-			_('File'),$file,_('line'),$lineno,_('caller'),$caller);
-		$body .= sprintf('',
-			app_version(),phpversion(),php_sapi_name());
-		$body .= sprintf('',isset($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : 'SCRIPT');
-
-		if (function_exists('get_href'))
-			$body .= sprintf('',
-				get_href('search_bug',"&summary_keyword=".rawurlencode($errstr)),
-				_('Please check and see if this bug has been reported'));
-		$body .= '
%s:%s (%s)
%s:%s %s %s, %s %s
Versions:PLA: %s, PHP: %s, SAPI: %s
Web server:%s
%s.
'; - - system_message(array( - 'title'=>_('You found a non-fatal phpLDAPadmin bug!'), - 'body'=>$body, - 'type'=>'error')); - - return; - } - - # If this is a more serious error, call the error call. - error(sprintf('%s: %s',$errtype,$errstr),'error',null,true,true); -} - -/** - * Returns the application name. - */ -function app_name() { - return 'phpLDAPadmin'; -} - -/** - * Returns the application version currently running. The version - * is read from the file named VERSION. - * - * @return string The current version as read from the VERSION file. - */ -function app_version() { - static $CACHE = null; - - if ($CACHE) - return $CACHE; - - $version_file = realpath(LIBDIR.'../VERSION'); - if (! file_exists($version_file)) - $CACHE = 'UNKNOWN'; - - else { - $version = rtrim(file_get_contents($version_file)); - - $CACHE = preg_replace('/^RELEASE-([0-9\.]+(-.*)*)$/','$1',$version); - - # Check if we are a CVS copy. - if (preg_match('/^(DEVEL)?$/',$CACHE)) - $CACHE = 'DEVEL'; - - # Check if we are special DEVEL version - elseif (preg_match('/^DEVEL-([0-9\.]+)+$/',$CACHE)) {} - - # If return is still the same as version, then the tag is not one we expect. - elseif ($CACHE == $version) - $CACHE = 'UNKNOWN'; - } - - return $CACHE; -} - -/** - * This function will convert the browser two character language into the - * default 5 character language, where the country portion should NOT be - * assumed to be upper case characters of the first two characters. - */ -function auto_lang($lang) { - switch ($lang) { - case 'ja': return 'ja_JP'; - case 'cs': return 'cs_CZ'; - default: return sprintf('%s_%s',$lang,strtoupper($lang)); - } -} - -/** - * Makes sure that the config file is properly setup. - */ -function check_config($config_file) { - # Read in config_default.php - require_once LIBDIR.'config_default.php'; - - # Make sure their PHP version is current enough - if (strcmp(phpversion(),REQUIRED_PHP_VERSION) < 0) - system_message(array( - 'title'=>_('Incorrect version of PHP'), - 'body'=>sprintf('phpLDAPadmin requires PHP version %s or greater.
(You are using %s)', - REQUIRED_PHP_VERSION,phpversion()), - 'type'=>'error')); - - $config = new Config; - - if (file_exists(LIBDIR.'config_custom.php') && is_readable(LIBDIR.'config_custom.php')) - include LIBDIR.'config_custom.php'; - - ob_start(); - require $config_file; - $str = ''; - if (ob_get_level()) { - $str = ob_get_contents(); - ob_end_clean(); - } - - if ($str) { - $str = strip_tags($str); - $matches = array(); - preg_match('/(.*):\s+(.*):.*\s+on line (\d+)/',$str,$matches); - - if (isset($matches[1]) && isset($matches[2]) && isset($matches[3])) { - $error_type = $matches[1]; - $error = $matches[2]; - $line_num = $matches[3]; - - $file = file($config_file); - - $body = '

Config file ERROR

'; - $body .= sprintf('

%s (%s) on line %s

',$error_type,$error,$line_num); - - $body .= '
'; - $body .= sprintf('Looks like your config file has an ERROR on line %s.
',$line_num); - $body .= 'Here is a snippet around that line
'; - $body .= '
'."\n"; - - $body .= '
'; - - for ($i = $line_num-9; $i<$line_num+5; $i++) { - if ($i+1 == $line_num) - $body .= '
'; - - if ($i < 0) - continue; - - $body .= sprintf('%s: %s
',$i+1,$file[$i]); - - if ($i+1 == $line_num) - $body .= '
'; - } - - $body .= '
'; - $body .= '
'; - $body .= 'Hint: Sometimes these errors are caused by lines preceding the line reported.'; - $body .= '
'; - - $block = new block(); - $block->SetBody($body); - $www['page'] = new page(); - $www['page']->block_add('body',$block); - $www['page']->display(); - - die(); - } - } - - # Check for server definitions. - if (! isset($servers) || count($servers->GetServerList()) == 0) - error(_('Your config.php is missing Server Definitions. Please see the sample file config/config.php.example.'),'error','index.php',true); - - $config->setServers($servers); - - # Check the memory limit parameter. - if ((ini_get('memory_limit') > -1) && ini_get('memory_limit') < $config->getValue('session','memorylimit')) - system_message(array( - 'title'=>_('Memory Limit low.'), - 'body'=>sprintf('Your php memory limit is low - currently %s, you should increase it to atleast %s. This is normally controlled in /etc/php.ini.', - ini_get('memory_limit'),$config->getValue('session','memorylimit')), - 'type'=>'error')); - - return $config; -} - -/** - * Commands available in the control_panel of the page - * - * @return array - */ -function cmd_control_pane($type) { - if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - switch ($type) { - case 'main' : - return array( - 'home'=>array( - 'title'=>_('Home'), - 'enable'=>true, - 'link'=>sprintf('href="index.php" title="%s"',_('Home')), - 'image'=>sprintf('%s',IMGDIR,_('Home'))), - - 'purge'=>array( - 'title'=>_('Purge caches'), - 'enable'=>isset($_SESSION[APPCONFIG]) ? $_SESSION[APPCONFIG]->isCommandAvailable('script','purge_cache') : false, - 'link'=>sprintf('href="cmd.php?cmd=purge_cache" onclick="return ajDISPLAY(\'BODY\',\'cmd=purge_cache\',\'%s\');" title="%s"', - _('Clearing cache'),_('Purge caches')), - 'image'=>sprintf('%s',IMGDIR,_('Purge caches'))), - - 'hide_debug_info'=>array( - 'title'=>_('Show Cache'), - 'enable'=>isset($_SESSION[APPCONFIG]) ? ($_SESSION[APPCONFIG]->isCommandAvailable('script','show_cache')) && (! $_SESSION[APPCONFIG]->getValue('appearance','hide_debug_info')) : false, - 'link'=>sprintf('href="cmd.php?cmd=show_cache" onclick="return ajDISPLAY(\'BODY\',\'cmd=show_cache\',\'%s\');" title="%s"', - _('Loading'),_('Show Cache'),_('Show Cache')), - 'image'=>sprintf('%s',IMGDIR,_('Show Cache'))), - ); - - break; - - case 'top' : - return array( - 'forum'=>array( - 'title'=>_('Forum'), - 'enable'=>isset($_SESSION[APPCONFIG]) ? $_SESSION[APPCONFIG]->isCommandAvailable('cmd','oslinks') : true, - 'link'=>sprintf('href="%s" title="%s" onclick="target=\'_blank\';"',get_href('forum'),_('Forum')), - 'image'=>sprintf('%s',IMGDIR,_('Forum'))), - - 'feature'=>array( - 'title'=>_('Request feature'), - 'enable'=>isset($_SESSION[APPCONFIG]) ? $_SESSION[APPCONFIG]->isCommandAvailable('cmd','oslinks') : true, - 'link'=>sprintf('href="%s" title="%s" onclick="target=\'_blank\';"',get_href('add_rfe'),_('Request feature')), - 'image'=>sprintf('%s',IMGDIR,_('Request feature'))), - - 'bug'=>array( - 'title'=>_('Report a bug'), - 'enable'=>isset($_SESSION[APPCONFIG]) ? $_SESSION[APPCONFIG]->isCommandAvailable('cmd','oslinks') : true, - 'link'=>sprintf('href="%s" title="%s" onclick="target=\'_blank\';"',get_href('add_bug'),_('Report a bug')), - 'image'=>sprintf('%s',IMGDIR,_('Report a bug'))), - - 'donation'=>array( - 'title'=>_('Donate'), - 'enable'=>isset($_SESSION[APPCONFIG]) ? $_SESSION[APPCONFIG]->isCommandAvailable('cmd','oslinks') : true, - 'link'=>sprintf('href="%s" title="%s" onclick="target=\'_blank\';"',get_href('donate'),_('Donate')), - 'image'=>sprintf('%s',IMGDIR,_('Donate'))), - - 'help'=>array( - 'title'=>_('Help'), - 'enable'=>isset($_SESSION[APPCONFIG]) ? $_SESSION[APPCONFIG]->isCommandAvailable('cmd','oslinks') : true, - 'link'=>sprintf('href="%s" title="%s" onclick="target=\'_blank\';"',get_href('documentation'),_('Help')), - 'image'=>sprintf('%s',IMGDIR,_('Help'))) - ); - - break; - } -} - -/** - * This function dumps the $variable for debugging purposes - * - * @param string|array Variable to dump - * @param boolean Whether to stop execution or not. - */ -function debug_dump($variable,$die=false,$onlydebugaddr=false) { - if ($onlydebugaddr && - isset($_SESSION[APPCONFIG]) && $_SESSION[APPCONFIG]->getValue('debug','addr') && - $_SERVER['HTTP_X_FORWARDED_FOR'] != $_SESSION[APPCONFIG]->getValue('debug','addr') && - $_SERVER['REMOTE_ADDR'] != $_SESSION[APPCONFIG]->getValue('debug','addr')) - return; - - $backtrace = debug_backtrace(); - $caller['class'] = isset($backtrace[0]['class']) ? $backtrace[0]['class'] : 'N/A'; - $caller['function'] = isset($backtrace[0]['function']) ? $backtrace[0]['function'] : 'N/A'; - $caller['file'] = isset($backtrace[0]['file']) ? $backtrace[0]['file'] : 'N/A'; - $caller['line'] = isset($backtrace[0]['line']) ? $backtrace[0]['line'] : 'N/A'; - $caller['debug'] = $variable; - - print '
';
-	print_r($caller);
-	print '
'; - - if ($die) - die(); -} - -/** - * This function generates a backtrace - * - * @param boolean Whether to stop execution or not. - */ -function debug_dump_backtrace($msg='Calling BackTrace',$die=false) { - error($msg,'note',null,$die,true); -} - -/** - * Send a debug as a sys message - */ -function debug_sysmsg($msg) { - system_message(array('title'=>_('Debug'),'body'=>$msg,'type'=>'debug')); -} - -/** - * Debug Logging - * - * The global debug level is turned on in your configuration file by setting: - * - * $config->custom->debug['level'] = 255; - * - * together with atleast one output direction (currently file and syslog are supported). - * - * $config->custom->debug['file'] = '/tmp/app_debug.log'; - * $config->custom->debug['syslog'] = true; - * - * - * The debug level is turned into binary, then if the message levels bit is on - * the message will be sent to the debug log. (Thus setting your debug level to 255, - * all bits on, will results in all messages being printed.) - * - * The message level bits are defined here. - * 0( 1) = Entry/Return results from function calls. - * 1( 2) = Configuration Processing - * 2( 4) = Template Processing - * 3( 8) = Schema Processing - * 4( 16) = LDAP Server Communication - * 5( 32) = Tree Processing - * 7( 64) = Other non generic messages - * 8(128) = Page Processing - * 9(256) = Hooks Processing - * @param string Message to send to syslog - * @param int Log bit number for this message. - * @see syslog.php - */ -function debug_log($msg,$level,$indent) { - static $debug_file; - - # In case we are called before we are fully initialised or if debugging is not set. - if (! isset($_SESSION[APPCONFIG]) - || ! ($_SESSION[APPCONFIG]->getValue('debug','file') || $_SESSION[APPCONFIG]->getValue('debug','syslog'))) - return; - - $debug_level = $_SESSION[APPCONFIG]->getValue('debug','level'); - if (! $debug_level || (! ($level & $debug_level))) - return; - - if ($_SESSION[APPCONFIG]->getValue('debug','addr')) - if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR'] == $_SESSION[APPCONFIG]->getValue('debug','addr')) - $debugaddr = true; - elseif ($_SERVER['REMOTE_ADDR'] == $_SESSION[APPCONFIG]->getValue('debug','addr')) - $debugaddr = true; - else - $debugaddr = false; - - else - $debugaddr = true; - - if (! $debugaddr) - return; - - # If we are limiting debug to a browser, then check that - $caller = basename($_SERVER['PHP_SELF']); - - $args = func_get_args(); - # Discard our first three arguments. - array_shift($args); - array_shift($args); - array_shift($args); - - # Pull the file/line/method - if (is_string($args[0]) && preg_match('/.php$/',$args[0])) { - $file = preg_replace('/.php$/','',array_shift($args)); - $line = array_shift($args); - $method = array_shift($args); - - } else { - $file = 'UNKNOWN'; - $line = 'UNKNOWN'; - $method = 'UNKNOWN'; - } - - # TEMP: New debuglog format - if (preg_match('/%%/',$msg) && $args[0] != 'NOARGS') - $args = array_shift($args); - - $fargs = array(); - foreach ($args as $key) { - if (is_array($key)) - array_push($fargs,serialize($key)); - elseif (is_object($key)) - array_push($fargs,sprintf('OBJECT:%s',get_class($key))); - else - array_push($fargs,$key); - } - - if (preg_match('/%%/',$msg)) - $msg = preg_replace('/%%/',join('|',$fargs),$msg); - else - $msg = vsprintf($msg,array_values($fargs)); - - if (function_exists('stopwatch')) - $timer = stopwatch(); - else - $timer = null; - - $debug_message = sprintf('[%2.3f] %15s(%04s-%03s): %s%s: %s',$timer,basename($file),$line,$level,str_repeat('.',$indent),$method,substr($msg,0,200)); - - if ($debug_file || $_SESSION[APPCONFIG]->getValue('debug','file')) { - if (! $debug_file) - $debug_file = fopen($_SESSION[APPCONFIG]->getValue('debug','file'), - $_SESSION[APPCONFIG]->getValue('debug','append') ? 'a' : 'w'); - - fwrite($debug_file,$debug_message."\n"); - } - - if ($_SESSION[APPCONFIG]->getValue('debug','syslog') && function_exists('syslog_notice')) - syslog_notice($debug_message); -} - -/** - * Display an error message in the system message panel of the page. - */ -function error($msg,$type='note',$redirect=null,$fatal=false,$backtrace=false) { - global $www; - static $counter; - - # Just a check to see that we are called right. - if (! isset($www['page']) && ! $fatal) - die("Function error called incorrectly [$msg]"); - - # If the error is fatal, we'll need to stop here. - if (! isset($www['page'])) - $www['page'] = new page(); - - if ($fatal) - $www['page']->setsysmsg(array('title'=>_('Error'),'body'=>$msg,'type'=>$type)); - else - system_message(array('title'=>_('Error'),'body'=>$msg,'type'=>$type),$redirect); - - # Spin loop detection - if ($counter++ > 20) { - debug_dump('Spin loop detection.'); - debug_dump(array('msg'=>$msg,'session'=>$_SESSION['sysmsg'],'www'=>$www),1); - } - - # Do we have a backtrace to display? - if ($backtrace) { - $backtraceblock = new block(); - $backtraceblock->SetTitle('PHP Debug Backtrace'); - - $body = ''; - $body .= "\n"; - - foreach (debug_backtrace() as $error => $line) { - $_SESSION['backtrace'][$error]['file'] = isset($line['file']) ? $line['file'] : 'unknown'; - $_SESSION['backtrace'][$error]['line'] = isset($line['line']) ? $line['line'] : 'unknown'; - $body .= sprintf('', - _('File'),isset($line['file']) ? $line['file'] : $last['file'],isset($line['line']) ? $line['line'] : ''); - - $_SESSION['backtrace'][$error]['function'] = $line['function']; - $body .= sprintf(''; - $body .= "\n"; - - if (isset($line['file'])) - $last['file'] = $line['file']; - } - - $body .= '
%s%s (%s)
 %s%s', - _('Function'),$line['function']); - - if (isset($line['args'])) { - $display = strlen(serialize($line['args'])) < 50 ? htmlspecialchars(serialize($line['args'])) : htmlspecialchars(substr(serialize($line['args']),0,50)).'...'; - $_SESSION['backtrace'][$error]['args'] = $line['args']; - if (file_exists(LIBDIR.'../tools/unserialize.php')) - $body .= sprintf(' (%s)', - '../tools/unserialize.php',$error,$display); - else - $body .= sprintf(' (%s)',$display); - } - $body .= '
'; - $body .= "\n"; - $backtraceblock->SetBody($body); - - $www['page']->block_add('body',$backtraceblock); - } - - if ($fatal) { - $www['page']->display(array('tree'=>false)); - die(); - } -} - -/** - * Return the result of a form variable, with optional default - * - * @return The form GET/REQUEST/SESSION/POST variable value or its default - */ -function get_request($attr,$type='POST',$die=false,$default=null,$preventXSS=true) { - switch($type) { - case 'GET': - $value = isset($_GET[$attr]) ? (is_array($_GET[$attr]) ? $_GET[$attr] : (empty($_GET['nodecode'][$attr]) ? rawurldecode($_GET[$attr]) : $_GET[$attr])) : $default; - break; - - case 'REQUEST': - $value = isset($_REQUEST[$attr]) ? (is_array($_REQUEST[$attr]) ? $_REQUEST[$attr] : (empty($_REQUEST['nodecode'][$attr]) ? rawurldecode($_REQUEST[$attr]) : $_REQUEST[$attr])) : $default; - break; - - case 'SESSION': - $value = isset($_SESSION[$attr]) ? (is_array($_SESSION[$attr]) ? $_SESSION[$attr] : (empty($_SESSION['nodecode'][$attr]) ? rawurldecode($_SESSION[$attr]) : $_SESSION[$attr])) : $default; - break; - - case 'POST': - default: - $value = isset($_POST[$attr]) ? (is_array($_POST[$attr]) ? $_POST[$attr] : (empty($_POST['nodecode'][$attr]) ? rawurldecode($_POST[$attr]) : $_POST[$attr])) : $default; - break; - } - - if ($die && is_null($value)) - system_message(array( - 'title'=>_('Generic Error'), - 'body'=>sprintf('%s: Called "%s" without "%s" using "%s"', - basename($_SERVER['PHP_SELF']),get_request('cmd','REQUEST'),preventXSS($attr),preventXSS($type)), - 'type'=>'error'), - 'index.php'); - if($preventXSS && !is_null($value)) - $value = preventXSS($value); - return $value; -} -/** -* Prevent XSS function. This function can usage has preventXSS(get_request('cmd','REQUEST')) -* Return valor escape XSS. -*/ - function preventXSS($data){ - if (gettype($data) == 'array') { - foreach ($data as $key => $value) { - if (gettype($value) == 'array') - $data[$key] = preventXSS($value); - else - $data[$key] = htmlspecialchars($value); - } - return $data; - } - return htmlspecialchars($data, ENT_QUOTES, 'UTF-8'); -} - -/* - * Record a system message. - * This function can be used as an alternative to generate a system message, if page hasnt yet been defined. - */ -function system_message($msg,$redirect=null) { - if (! is_array($msg)) - return null; - - if (! isset($msg['title']) && ! isset($msg['body'])) - return null; - - if (! isset($msg['type'])) - $msg['type'] = 'info'; - - if (! isset($_SESSION['sysmsg']) || ! is_array($_SESSION['sysmsg'])) - $_SESSION['sysmsg'] = array(); - - # Try and detect if we are in a redirect loop - if (get_request('redirect','GET') && $msg['type'] != 'debug') { - foreach ($_SESSION['sysmsg'] as $detail) { - if ($msg == $detail && ! isset($detail['special'])) { - debug_dump(array('Incoming MSG'=>$msg,'existing'=>$_SESSION['sysmsg'])); - debug_dump_backtrace('Redirect Loop Detected',true); - } - } - } - - array_push($_SESSION['sysmsg'],$msg); - - if ($redirect) { - if (preg_match('/\?/',$redirect)) - $redirect .= '&'; - else - $redirect .= '?'; - $redirect .= 'redirect=true'; - - # Check if we were an ajax request, and only render the ajax message - if (get_request('meth','REQUEST') == 'ajax') - $redirect .= '&meth=ajax'; - - header("Location: $redirect"); - die(); - } -} - -/** - * Other Functions - */ - -/** - * String padding - * - * @param string Input string - * @param integer Length of the result - * @param string The filling string - * @param integer Padding mode - * @return string The padded string - */ -function full_str_pad($input,$pad_length,$pad_string='',$pad_type=0) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $str = ''; - $length = $pad_length - strlen($input); - - if ($length > 0) { // str_repeat doesn't like negatives - if ($pad_type == STR_PAD_RIGHT) { // STR_PAD_RIGHT == 1 - $str = $input.str_repeat($pad_string, $length); - } elseif ($pad_type == STR_PAD_BOTH) { // STR_PAD_BOTH == 2 - $str = str_repeat($pad_string, floor($length/2)); - $str .= $input; - $str .= str_repeat($pad_string, ceil($length/2)); - } else { // defaults to STR_PAD_LEFT == 0 - $str = str_repeat($pad_string, $length).$input; - } - - } else { // if $length is negative or zero we don't need to do anything - $str = $input; - } - return $str; -} - -/** - * Returns the cached array of LDAP resources. - * - * Note that internally, this function utilizes a two-layer cache, - * one in memory using a static variable for multiple calls within - * the same page load, and one in a session for multiple calls within - * the same user session (spanning multiple page loads). - * - * @return Returns the cached attributed requested, - * or null if there is nothing cached.. - */ -function get_cached_item($index,$item,$subitem='null') { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - # Set default return - $return = null; - - # Check config to make sure session-based caching is enabled. - if ($_SESSION[APPCONFIG]->getValue('cache',$item) && isset($_SESSION['cache'][$index][$item][$subitem])) - $return = $_SESSION['cache'][$index][$item][$subitem]; - - if (DEBUG_ENABLED) - debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$return); - - return $return; -} - -/** - * Caches the specified $item for the specified $index. - * - * Returns true on success of false on failure. - */ -function set_cached_item($index,$item,$subitem='null',$data) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - # Check config to make sure session-based caching is enabled. - if ($_SESSION[APPCONFIG]->getValue('cache',$item)) { - global $CACHE; - - $CACHE[$index][$item][$subitem] = $data; - $_SESSION['cache'][$index][$item][$subitem] = $data; - - return true; - - } else - return false; -} - -/** - * Deletes the cache for a specified $item for the specified $index - */ -function del_cached_item($index,$item,$subitem='null') { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - global $CACHE; - - # Check config to make sure session-based caching is enabled. - if (isset($_SESSION['cache'][$index][$item][$subitem])) - unset($_SESSION['cache'][$index][$item][$subitem]); - - if (isset($CACHE[$index][$item][$subitem])) - unset($CACHE[$index][$item][$subitem]); -} - -/** - * Utility wrapper for setting cookies, which takes into consideration - * application configuration values. On success, true is returned. On - * failure, false is returned. - * - * @param string The name of the cookie to set. - * @param string The value of the cookie to set. - * @param int (optional) The duration in seconds of this cookie. If unspecified, $cookie_time is used from config.php - * @param string (optional) The directory value of this cookie (see php.net/setcookie) - * @return boolean - */ -function set_cookie($name,$val,$expire=null,$dir=null) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - # Set default return - $return = false; - - if ($expire == null) { - $cookie_time = $_SESSION[APPCONFIG]->getValue('session','cookie_time'); - $expire = $cookie_time == 0 ? null : time() + $cookie_time; - } - - if ($dir == null) - $dir = dirname($_SERVER['PHP_SELF']); - - if (@setcookie($name,$val,$expire,$dir)) { - $_COOKIE[$name] = $val; - $return = true; - } - - if (DEBUG_ENABLED) - debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$return); - - return $return; -} - -/** - * Get a customized file for a server - * We don't need any caching, because it's done by PHP - * - * @param int The ID of the server - * @param string The requested filename - * - * @return string The customized filename, if exists, or the standard one - */ -function get_custom_file($index,$filename,$path) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - # Set default return - $return = $path.$filename; - $server = $_SESSION[APPCONFIG]->getServer($index); - - $custom = $server->getValue('custom','pages_prefix'); - if (! is_null($custom) && is_file(realpath($path.$custom.$filename))) - $return = $path.$custom.$filename; - - if (DEBUG_ENABLED) - debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$return); - - return $return; -} - -/** - * Replacement for create_function() which is deprecated as of php 7.2 - * - * @param string The function arguments - * @param string The function code - */ -function pla_create_function($args, $code) { - if (version_compare(phpversion(),'7.0','>=')) { - # anonymous functions were introduced in PHP 5.3.0 - return eval("return function(".$args."){".$code."};"); - - } else { - # create_function is deprecated in php 7.2 - return create_function($args, $code); - } -} - -/** - * Sort a multi dimensional array. - * - * @param array Multi demension array passed by reference - * @param string Comma delimited string of sort keys. - * @param boolean Whether to reverse sort. - * @return array Sorted multi demension array. - */ -function masort(&$data,$sortby,$rev=0) { - if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - # if the array to sort is null or empty, or if we have some nasty chars - if (! preg_match('/^[a-zA-Z0-9_]+(\([a-zA-Z0-9_,]*\))?$/',$sortby) || ! $data) - return; - - static $CACHE = array(); - - if (empty($CACHE[$sortby])) { - $code = "\$c=0;\n"; - - foreach (explode(',',$sortby) as $key) { - $code .= "if (is_object(\$a) || is_object(\$b)) {\n"; - - $code .= " if (is_array(\$a->$key)) {\n"; - $code .= " asort(\$a->$key);\n"; - $code .= " \$aa = array_shift(\$a->$key);\n"; - $code .= " } else\n"; - $code .= " \$aa = \$a->$key;\n"; - - $code .= " if (is_array(\$b->$key)) {\n"; - $code .= " asort(\$b->$key);\n"; - $code .= " \$bb = array_shift(\$b->$key);\n"; - $code .= " } else\n"; - $code .= " \$bb = \$b->$key;\n"; - - $code .= " if (\$aa != \$bb)"; - if ($rev) - $code .= " return (\$aa < \$bb ? 1 : -1);\n"; - else - $code .= " return (\$aa > \$bb ? 1 : -1);\n"; - - $code .= "} else {\n"; - - $code .= " \$a = array_change_key_case(\$a);\n"; - $code .= " \$b = array_change_key_case(\$b);\n"; - - $key = strtolower($key); - - $code .= " if ((! isset(\$a['$key'])) && isset(\$b['$key'])) return 1;\n"; - $code .= " if (isset(\$a['$key']) && (! isset(\$b['$key']))) return -1;\n"; - - $code .= " if ((isset(\$a['$key'])) && (isset(\$b['$key']))) {\n"; - $code .= " if (is_array(\$a['$key'])) {\n"; - $code .= " asort(\$a['$key']);\n"; - $code .= " \$aa = array_shift(\$a['$key']);\n"; - $code .= " } else\n"; - $code .= " \$aa = \$a['$key'];\n"; - - $code .= " if (is_array(\$b['$key'])) {\n"; - $code .= " asort(\$b['$key']);\n"; - $code .= " \$bb = array_shift(\$b['$key']);\n"; - $code .= " } else\n"; - $code .= " \$bb = \$b['$key'];\n"; - - $code .= " if (\$aa != \$bb)\n"; - $code .= " if (is_numeric(\$aa) && is_numeric(\$bb)) {\n"; - - if ($rev) - $code .= " return (\$aa < \$bb ? 1 : -1);\n"; - else - $code .= " return (\$aa > \$bb ? 1 : -1);\n"; - - $code .= " } else {\n"; - - if ($rev) - $code .= " if ( (\$c = strcasecmp(\$bb,\$aa)) != 0 ) return \$c;\n"; - else - $code .= " if ( (\$c = strcasecmp(\$aa,\$bb)) != 0 ) return \$c;\n"; - - $code .= " }\n"; - $code .= " }\n"; - $code .= "}\n"; - } - - $code .= 'return $c;'; - - $CACHE[$sortby] = pla_create_function('$a, $b',$code); - } - - uasort($data,$CACHE[$sortby]); -} - -/** - * Is compression enabled for output - */ -function isCompress() { - return (isset($_SESSION[APPCONFIG]) && $_SESSION[APPCONFIG]->getValue('appearance','compress') - && ! ini_get('zlib.output_compression') - && preg_match('/gzip/',$_SERVER['HTTP_ACCEPT_ENCODING'])); -} - -/** - * PLA specific Functions - */ - -/** - * Returns an HTML-beautified version of a DN. - * Internally, this function makes use of pla_explode_dn() to break the - * the DN into its components. It then glues them back together with - * "pretty" HTML. The returned HTML is NOT to be used as a real DN, but - * simply displayed. - * - * @param string The DN to pretty-print. - * @return string - */ -function pretty_print_dn($dn) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $dn_save = $dn; - $dn = pla_explode_dn($dn); - - if (! $dn) - return $dn_save; - - foreach ($dn as $i => $element) { - $element = htmlspecialchars($element); - $element = explode('=',$element,2); - $element = implode('=',$element); - $dn[$i] = $element; - } - - $dn = implode(',',$dn); - - return $dn; -} - -/** - * Given a string, this function returns true if the string has the format - * of a DN (ie, looks like "cn=Foo,dc=example,dc=com"). Returns false otherwise. - * The purpose of this function is so that developers can examine a string and - * know if it looks like a DN, and draw a hyperlink as needed. - * - * (See unit_test.php for test cases) - * - * @param string The attribute to examine for "DNness" - * @return boolean - */ -function is_dn_string($str) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - /* Try to break the string into its component parts if it can be done - ie, "uid=Manager" "dc=example" and "dc=com" */ - $parts = pla_explode_dn($str); - if (! is_array($parts) || ! count($parts)) - return false; - - /* Foreach of the "parts", look for an "=" character, - and make sure neither the left nor the right is empty */ - foreach ($parts as $part) { - if (! strpos($part,"=")) - return false; - - $sub_parts = explode('=',$part,2); - $left = $sub_parts[0]; - $right = $sub_parts[1]; - - if ( ! strlen(trim($left)) || ! strlen(trim($right))) - return false; - - if (strpos($left,'#') !== false) - return false; - } - - # We survived the above rigor. This is a bonified DN string. - return true; -} - -/** - * Get whether a string looks like an email address (user@example.com). - * - * @param string The string to analyze. - * @return boolean Returns true if the specified string looks like an email address or false otherwise. - */ -function is_mail_string($str) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $mail_regex = "/^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*$/"; - - if (preg_match($mail_regex,$str)) - return true; - else - return false; -} - -/** - * Get whether a string looks like a web URL (http://www.example.com/) - * - * @param string The string to analyze. - * @return boolean Returns true if the specified string looks like a web URL or false otherwise. - */ -function is_url_string($str) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $url_regex = '/^(ftp|https?):\/\/+[\w\.\-\/\?\=\&]*\w+/'; - - if (preg_match($url_regex,$str)) - return true; - else - return false; -} - -/** - * Compares 2 DNs. If they are equivelant, returns 0, otherwise, - * returns their sorting order (similar to strcmp()): - * Returns < 0 if dn1 is less than dn2. - * Returns > 0 if dn1 is greater than dn2. - * - * The comparison is performed starting with the top-most element - * of the DN. Thus, the following list: - * - * ou=people,dc=example,dc=com - * cn=Admin,ou=People,dc=example,dc=com - * cn=Joe,ou=people,dc=example,dc=com - * dc=example,dc=com - * cn=Fred,ou=people,dc=example,dc=org - * cn=Dave,ou=people,dc=example,dc=org - * - * Will be sorted thus using usort( $list, "pla_compare_dns" ): - * - * dc=com - * dc=example,dc=com - * ou=people,dc=example,dc=com - * cn=Admin,ou=People,dc=example,dc=com - * cn=Joe,ou=people,dc=example,dc=com - * cn=Dave,ou=people,dc=example,dc=org - * cn=Fred,ou=people,dc=example,dc=org - * - * - * @param string The first of two DNs to compare - * @param string The second of two DNs to compare - * @return int - */ -function pla_compare_dns($dn1,$dn2) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - # If pla_compare_dns is passed via a tree, then we'll just get the DN part. - if (is_array($dn1)) - if (isset($dn1['dn'])) - $dn1 = $dn1['dn']; - else - $dn1 = implode('+',$dn1); - if (is_array($dn2)) - if (isset($dn2['dn'])) - $dn2 = $dn2['dn']; - else - $dn2 = implode('+',$dn2); - - # If they are obviously the same, return immediately - if (! strcasecmp($dn1,$dn2)) - return 0; - - $dn1_parts = pla_explode_dn(pla_reverse_dn($dn1)); - $dn2_parts = pla_explode_dn(pla_reverse_dn($dn2)); - assert(is_array($dn1_parts)); - assert(is_array($dn2_parts)); - - # Foreach of the "parts" of the smaller DN - for ($i=0; $i < count($dn1_parts) && $i < count($dn2_parts); $i++) { - /* dnX_part is of the form: "cn=joe" or "cn = joe" or "dc=example" - ie, one part of a multi-part DN. */ - $dn1_part = $dn1_parts[$i]; - $dn2_part = $dn2_parts[$i]; - - /* Each "part" consists of two sub-parts: - 1. the attribute (ie, "cn" or "o") - 2. the value (ie, "joe" or "example") */ - $dn1_sub_parts = explode('=',$dn1_part,2); - $dn2_sub_parts = explode('=',$dn2_part,2); - - $dn1_sub_part_attr = trim($dn1_sub_parts[0]); - $dn2_sub_part_attr = trim($dn2_sub_parts[0]); - - if (0 != ($cmp = strcasecmp($dn1_sub_part_attr,$dn2_sub_part_attr))) - return $cmp; - - $dn1_sub_part_val = trim($dn1_sub_parts[1]); - $dn2_sub_part_val = trim($dn2_sub_parts[1]); - if (0 != ($cmp = strcasecmp($dn1_sub_part_val,$dn2_sub_part_val))) - return $cmp; - } - - /* If we iterated through all entries in the smaller of the two DNs - (ie, the one with fewer parts), and the entries are different sized, - then, the smaller of the two must be "less than" than the larger. */ - if (count($dn1_parts) > count($dn2_parts)) { - return 1; - - } elseif (count($dn2_parts) > count($dn1_parts)) { - return -1; - - } else { - return 0; - } -} - -/** - * For LDAP servers with auto_number enabled, this function will get the next - * available number using the host's preferred mechanism (pool or search). - * - * This is configured in config.php by server: - * - * - * $servers->setValue('auto_number','enable',true|false); - * - * - * The available mechanisms are: - * pool: - * The pool mechanism uses a user-configured entry in the LDAP server to - * store the last used "number". This mechanism simply fetches and increments - * and returns that value. - * - * search: - * The search mechanism will search the LDAP server that has the attribute - * set. It will then find the smallest value and "fills in the gaps" by - * incrementing the smallest attribute until an unused value is found. - * - * NOTE: Both mechanisms do NOT prevent race conditions or toe-stomping, so - * care must be taken when actually creating the entry to check that the number - * returned here has not been used in the mean time. Note that the two different - * mechanisms may (will!) return different values as they use different algorithms - * to arrive at their result. Do not be alarmed if (when!) this is the case. - * - * See config.php.example for more notes on the two mechanisms. - * - * @param string Base to start the search from - * @param string Attribute to query - * @param boolean Increment the result (for pool searches) - * @param string LDAP filter to use (for pool searches) - * @return int - */ -function get_next_number($base,$attr,$increment=false,$filter=false,$startmin=null) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $server = $_SESSION[APPCONFIG]->getServer(get_request('server_id','REQUEST')); - $attr = strtolower($attr); - $query = array(); - - if (! $server->getValue('auto_number','enable')) { - system_message(array( - 'title'=>_('AUTO_NUMBER is disabled for this server'), - 'body'=>sprintf('%s (%s)',_('A call was made to get_next_number(), however, it is disabled for this server'),$attr), - 'type'=>'warn')); - - return false; - } - - # Check see and use our alternate uid_dn and password if we have it. - if (! $server->login($server->getValue('auto_number','dn'),$server->getValue('auto_number','pass'),'auto_number')) { - system_message(array( - 'title'=>_('AUTO_NUMBER invalid login/password'), - 'body'=>sprintf('%s (%s)',_('Unable to connect to LDAP server with the auto_number login/password, please check your configuration.'), - $server->getName()), - 'type'=>'warn')); - - return false; - } - - # Some error checking - if (! $base) { - $query['base'] = $server->getValue('auto_number','search_base'); - - if (! trim($query['base'])) { - system_message(array( - 'title'=>_('No AUTO_NUMBER search_base configured for this server'), - 'body'=>_('A call was made to get_next_number(), however, the base to search is empty.'), - 'type'=>'warn')); - - return false; - } - - } else - $query['base'] = $base; - - if (! $server->dnExists($query['base'])) { - system_message(array( - 'title'=>_('No AUTO_NUMBER search_base exists for this server'), - 'body'=>sprintf('%s (%s)',_('A call was made to get_next_number(), however, the base to search does not exist for this server.'),$query['base']), - 'type'=>'warn')); - - return false; - } - - if (! is_string($attr) || ! $server->getSchemaAttribute($attr)) { - system_message(array( - 'title'=>_('AUTO_NUMBER search attribute invalid'), - 'body'=>sprintf('%s (%s)',_('The search attribute for AUTO_NUMBER is invalid, expecting a single valid attribute.'),$attr), - 'type'=>'warn')); - - return false; - } - - $query['attrs'] = array($attr); - - # Based on the configured mechanism, go get the next available uidNumber! - switch ($server->getValue('auto_number','mechanism')) { - case 'search': - $query['filter'] = sprintf('(%s=*)',$attr); - $search = $server->query($query,'auto_number'); - - # Construct a list of used numbers - $autonum = array(0); - - foreach ($search as $dn => $values) { - $values = array_change_key_case($values); - foreach ($values[$attr] as $value) - array_push($autonum,$value); - } - - $autonum = array_unique($autonum); - sort($autonum); - - # Start with the least existing autoNumber and add 1 - $minNumber = is_null($startmin) ? intval($autonum[0])+1 : $startmin; - - # Override our minNumber by the configuration if it exists. - if (count($server->getValue('auto_number','min'))) { - $min = array_change_key_case($server->getValue('auto_number','min')); - - if (isset($min[$attr])) - $minNumber = $min[$attr] > $minNumber ? $min[$attr] : $minNumber; - } - - for ($i=0;$i $num+1) - return $autonum[$i] >= $num ? $num+1 : $num; - } - - # If we didnt find a suitable gap and are all above the minNumber, we'll just return the $minNumber - return $minNumber; - - break; - - case 'pool': - switch ($attr) { - case 'gidnumber': - $query['filter'] = '(objectClass=gidPool)'; - - break; - - case 'uidnumber': - $query['filter'] = '(objectClass=uidPool)'; - - break; - } - - # If we are called with a filter, we'll use the one from the configuration. - if (! empty($filter)) - $query['filter'] = $filter; - - $search = $server->query($query,'auto_number'); - - switch (count($search)) { - case '1': - break; - - case '0': - system_message(array( - 'title'=>_('AUTO_NUMBER pool filter didnt return any DNs'), - 'body'=>sprintf('%s (%s)',_('Please change your filter parameter, or check your auto_number,search_base configuration'),$query['filter']), - 'type'=>'warn')); - - return false; - - default: - system_message(array( - 'title'=>_('AUTO_NUMBER pool filter returned too many DNs'), - 'body'=>sprintf('%s (%s)',_('Please change your filter parameter, or check your auto_number,search_base configuration'),$query['filter']), - 'type'=>'warn')); - - return false; - } - - # This should only iterate once. - foreach ($search as $dn => $values) { - $values = array_change_key_case($values); - - $autonum = $values[$attr][0]; - $poolDN = $values['dn']; - } - - if ($increment) { - $updatedattr = array($attr=>$autonum+1); - $server->modify($poolDN,$updatedattr); - } - - return $autonum; - - # No other cases allowed. The user has an error in the configuration - default: - system_message(array( - 'title'=>_('Invalid AUTO_NUMBER mechanism'), - 'body'=>sprintf('%s (%s)',_('Your config file specifies an unknown AUTO_NUMBER search mechanism.'),$server->getValue('auto_number','mechanism')), - 'type'=>'warn')); - - return false; - } -} - -/** - * Given a DN and server ID, this function reads the DN's objectClasses and - * determines which icon best represents the entry. The results of this query - * are cached in a session variable so it is not run every time the tree - * browser changes, just when exposing new DNs that were not displayed - * previously. That means we can afford a little bit of inefficiency here - * in favor of coolness. :) - * - * This function returns a string like "country.png". All icon files are assumed - * to be contained in the /images/ directory of phpLDAPadmin. - * - * Developers are encouraged to add new icons to the images directory and modify - * this function as needed to suit their types of LDAP entries. If the modifications - * are general to an LDAP audience, the phpLDAPadmin team will gladly accept them - * as a patch. - * - * @param string The DN of the entry whose icon you wish to fetch. - * @return string - */ -function get_icon($server_id,$dn,$object_classes=array()) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $server = $_SESSION[APPCONFIG]->getServer($server_id); - - # Fetch and lowercase all the objectClasses in an array - if (! count($object_classes)) - $object_classes = $server->getDNAttrValue($dn,'objectClass'); - - foreach ($object_classes as $index => $value) - $object_classes[$index] = strtolower($value); - - $rdn = get_rdn($dn); - $rdn_parts = explode('=',$rdn,2); - $rdn_value = isset($rdn_parts[0]) ? $rdn_parts[0] : null; - $rdn_attr = isset($rdn_parts[1]) ? $rdn_parts[1] : null; - unset($rdn_parts); - - # Return icon filename based upon objectClass value - if (in_array('sambaaccount',$object_classes) && - '$' == $rdn[ strlen($rdn) - 1 ]) - return 'nt_machine.png'; - - if (in_array('sambaaccount',$object_classes)) - return 'nt_user.png'; - - elseif (in_array('organizationalrole',$object_classes)) - return 'ldap-uid.png'; - - elseif (in_array('jammvirtualdomain',$object_classes)) - return 'mail.png'; - - elseif (in_array('locality',$object_classes)) - return 'locality.png'; - - elseif (in_array('applicationprocess',$object_classes)) - return 'process.png'; - - elseif (in_array('groupofuniquenames',$object_classes)) - return 'ldap-uniquegroup.png'; - - elseif (in_array('nlsproductcontainer',$object_classes)) - return 'n.png'; - - elseif (in_array('ndspkikeymaterial',$object_classes)) - return 'lock.png'; - - elseif (in_array('volume',$object_classes)) - return 'hard-drive.png'; - - elseif (in_array('ndscatcatalog',$object_classes)) - return 'catalog.png'; - - elseif (in_array('resource',$object_classes)) - return 'n.png'; - - elseif (in_array('ldapgroup',$object_classes)) - return 'ldap-server.png'; - - elseif (in_array('ldapserver',$object_classes)) - return 'ldap-server.png'; - - elseif (in_array('nisserver',$object_classes)) - return 'ldap-server.png'; - - elseif (in_array('rbscollection',$object_classes)) - return 'ldap-ou.png'; - - elseif (in_array('dfsconfiguration',$object_classes)) - return 'nt_machine.png'; - - elseif (in_array('applicationsettings',$object_classes)) - return 'server-settings.png'; - - elseif (in_array('aspenalias',$object_classes)) - return 'mail.png'; - - elseif (in_array('container',$object_classes)) - return 'folder.png'; - - elseif (in_array('ipnetwork',$object_classes)) - return 'network.png'; - - elseif (in_array('samserver',$object_classes)) - return 'server-small.png'; - - elseif (in_array('lostandfound',$object_classes)) - return 'find.png'; - - elseif (in_array('infrastructureupdate',$object_classes)) - return 'server-small.png'; - - elseif (in_array('filelinktracking',$object_classes)) - return 'files.png'; - - elseif (in_array('automountmap',$object_classes) || - in_array('automount',$object_classes)) - - return 'hard-drive.png'; - - elseif (strpos($rdn_value,'ipsec') === 0 || - strcasecmp($rdn_value,'IP Security') == 0|| - strcasecmp($rdn_value,'MSRADIUSPRIVKEY Secret') == 0 || - strpos($rdn_value,'BCKUPKEY_') === 0) - - return 'lock.png'; - - elseif (strcasecmp($rdn_value,'MicrosoftDNS') == 0) - return 'ldap-dc.png'; - - # Oh well, I don't know what it is. Use a generic icon. - else - return 'ldap-default.png'; -} - -/** - * Appends a servers base to a "sub" dn or returns the base. - * - * @param string The baseDN to be added if the DN is relative - * @param string The DN to be made absolute - * @return string|null Returns null if both base is null and sub_dn is null or empty - */ -function expand_dn_with_base($base,$sub_dn) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $empty_str = (is_null($sub_dn) || (($len=strlen(trim($sub_dn))) == 0)); - - if ($empty_str) - return $base; - - # If we have a string which doesn't need a base - elseif ($sub_dn[$len-1] != ',') - return $sub_dn; - - else - return sprintf('%s%s',$sub_dn,$base); -} - -/** - * Split an RDN into its attributes - */ -function rdn_explode($rdn) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - # Setup to work out our RDN. - $rdnarray = explode('\+',$rdn); - - # Capture items that have +, but are not an attribute - foreach ($rdnarray as $index => $val) { - if (preg_match('/=/',$val)) - $validindex = $index; - - if (! preg_match('/=/',$val)) { - $rdnarray[$validindex] .= '+'.$val; - unset($rdnarray[$index]); - } - } - - return $rdnarray; -} - -/** - * Given an LDAP error number, returns a verbose description of the error. - * This function parses ldap_error_codes.txt and looks up the specified - * ldap error number, and returns the verbose message defined in that file. - * - * - * Array ( - * [title] => "Invalid Credentials" - * [description] => "An invalid username and/or password was supplied to the LDAP server." - * ) - * - * - * @param string The hex error number (ie, "0x42") of the LDAP error of interest. - * @return array An associative array contianing the error title and description like so: - */ -function pla_verbose_error($key) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - static $CACHE = array(); - - if (! count($CACHE)) { - $source_file = LIBDIR.'ldap_error_codes.txt'; - - if (! file_exists($source_file) || ! is_readable($source_file) || ! ($f = fopen($source_file,'r'))) - return false; - - $contents = fread($f,filesize($source_file)); - fclose($f); - $entries = array(); - preg_match_all("/0x[A-Fa-f0-9][A-Za-z0-9]\s+[0-9A-Za-z_]+\s+\"[^\"]*\"\n/", - $contents,$entries); - - foreach ($entries[0] as $values) { - $entry = array(); - preg_match("/(0x[A-Za-z0-9][A-Za-z0-9])\s+([0-9A-Za-z_]+)\s+\"([^\"]*)\"/",$values,$entry); - - $hex_code = isset($entry[1]) ? $entry[1] : null; - $title = isset($entry[2]) ? $entry[2] : null; - $desc = isset($entry[3]) ? $entry[3] : null; - $desc = preg_replace('/\s+/',' ',$desc); - $CACHE[$hex_code] = array('title'=>$title,'desc'=>$desc); - } - } - - if (isset($CACHE[$key])) - return $CACHE[$key]; - else - return array('title' => null,'desc' => null); -} - -/** - * Print an LDAP error message - */ -function ldap_error_msg($msg,$errnum) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $body = ''; - - $errnum = ('0x'.str_pad(dechex($errnum),2,0,STR_PAD_LEFT)); - $verbose_error = pla_verbose_error($errnum); - - $body .= sprintf('',_('LDAP said'),$msg); - - if ($verbose_error) { - $body .= sprintf('',_('Error number'),$errnum,$verbose_error['title']); - $body .= sprintf('',_('Description'),$verbose_error['desc']); - - } else { - $body .= sprintf('',_('Error number'),$errnum); - $body .= sprintf('',_('Description'),_('no description available')); - } - - $body .= '
%s:%s
%s:%s (%s)
%s:%s
%s:%s
%s:(%s)
'; - - return $body; -} - -/** - * Draw the jpegPhoto image(s) for an entry wrapped in HTML. Many options are available to - * specify how the images are to be displayed. - * - * Usage Examples: - * - * draw_jpeg_photo(0,'cn=Bob,ou=People,dc=example,dc=com',"jpegPhoto",0,true,array('img_opts'=>"border: 1px; width: 150px")); - * draw_jpeg_photo(1,'cn=Fred,ou=People,dc=example,dc=com',null,1); - * - * - * @param object The Server to get the image from. - * @param string The DN of the entry that contains the jpeg attribute you want to draw. - * @param string The name of the attribute containing the jpeg data (usually 'jpegPhoto'). - * @param int Index of the attribute to draw - * @param boolean If true, draws a button beneath the image titled 'Delete' allowing the user - * to delete the jpeg attribute by calling JavaScript function deleteAttribute() provided - * in the default modification template. - * @param array Specifies optional image and CSS style attributes for the table tag. Supported keys are - * fixed_width, fixed_height, img_opts. - */ -function draw_jpeg_photo($server,$dn,$attr_name='jpegphoto',$index,$draw_delete_buttons=false,$options=array()) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $fixed = array(); - $fixed['width'] = isset($options['fixed_width']) ? $options['fixed_width'] : false; - $fixed['height'] = isset($options['fixed_height']) ? $options['fixed_height'] : false; - - if (is_null($server)) - $jpeg_data = $_SESSION['tmp']; - else - $jpeg_data = $server->getDNAttrValues($dn,null,LDAP_DEREF_NEVER,array($attr_name)); - - if (! isset($jpeg_data[$attr_name][$index]) || ! $jpeg_data[$attr_name][$index]) { - system_message(array( - 'title'=>_('Unable to retrieve image'), - 'body'=>sprintf('%s %s', - _('Could not fetch jpeg data for attribute'),$attr_name), - 'type'=>'warn')); - - # This should atleast generate some text that says "Image not available" - printf('Photo',$attr_name); - - return; - } - - $width = 0; - $height = 0; - - if (function_exists('getimagesize')) { - $jpeg_temp_dir = realpath($_SESSION[APPCONFIG]->getValue('jpeg','tmpdir').'/'); - if (! is_writable($jpeg_temp_dir)) - system_message(array( - 'title'=>_('Unable to write to jpeg tmp directory'), - 'body'=>_('Please set jpeg,tmpdir to a writable directory in the phpLDAPadmin config.php'), - 'type'=>'warn')); - - else { - # We have an image to display - $jpeg_filename = tempnam($jpeg_temp_dir.'/','pla'); - $outjpeg = @file_put_contents($jpeg_filename,$jpeg_data[$attr_name][$index]); - - if (! $outjpeg) { - system_message(array( - 'title'=>_('Error writing to jpeg tmp directory'), - 'body'=>sprintf(_('Please check jpeg,tmpdir is a writable directory in the phpLDAPadmin config.php'),$jpeg_temp_dir), - 'type'=>'warn')); - - } elseif ($outjpeg < 6) { - system_message(array( - 'title'=>sprintf('%s %s',$attr_name,_('contains errors')), - 'body'=>_('It appears that the jpeg image may not be a jpeg image'), - 'type'=>'warn')); - - } else { - $jpeg_dimensions = getimagesize($jpeg_filename); - $width = $jpeg_dimensions[0]; - $height = $jpeg_dimensions[1]; - } - - unlink($jpeg_filename); - } - } - - if ($width > 300) { - $scale_factor = 300 / $width; - $img_width = 300; - $img_height = intval($height * $scale_factor); - - } else { - $img_width = $width; - $img_height = $height; - } - - $href = sprintf('view_jpeg_photo.php?dn=%s&index=%s&attr=%s',rawurlencode($dn),$index,$attr_name); - - printf('',number_format($outjpeg),_('bytes'),$width,$height,_('pixels')); - - printf('Photo', - htmlspecialchars($href), - is_null($server) ? 'location=session' : sprintf('server_id=%s',$server->getIndex()), - (! $img_width || $fixed['width'] ? '' : sprintf('width="%s"',$img_width)), - (! $img_height || $fixed['height'] ? '' : sprintf('height="%s"',$img_height)), - (isset($options['img_opts']) ? $options['img_opts'] : '')); - - echo ''; - - if ($draw_delete_buttons) - # - printf('
%s', - $attr_name,_('Delete photo')); -} - -/** - * Draws an HTML browse button which, when clicked, pops up a DN chooser dialog. - * @param string The name of the form element to which this chooser - * dialog will publish the user's choice. The form element must be a member - * of a form with the "name" or "id" attribute set in the form tag, and the element - * must also define "name" or "id" for JavaScript to uniquely identify it. - * Example $form_element values may include "creation_form.container" or - * "edit_form.member_uid". See /templates/modification/default.php for example usage. - * @param boolean (optional) If true, the function draws the localized text "choose" to the right of the button. - */ -function draw_chooser_link($form,$element,$include_choose_text=true,$rdn='none') { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $href = sprintf("javascript:dnChooserPopup('%s','%s','%s');",$form,$element,$rdn == 'none' ? '' : rawurlencode($rdn)); - $title = _('Click to popup a dialog to select an entry (DN) graphically'); - - printf('Find',$href,$title,IMGDIR); - - if ($include_choose_text) - printf('%s',$href,$title,_('browse')); -} - -/** - * http://php.net/manual/en/function.ldap-explode-dn.php#34724 - * fixed for: - * Keep attention on UTF8 encoded DNs. Since openLDAP >=2.1.2 - * ldap_explode_dn turns unprintable chars (in the ASCII sense, UTF8 - * encoded) into \. - */ -function ldap_explode_dn_patch($dn,$with_attrib) { - $result = ldap_explode_dn($dn,$with_attrib); - if (! $result) - return null; - - # translate hex code into ascii again - foreach ($result as $key => $value) { - $result[$key] = preg_replace_callback( - "/\\\([0-9A-Fa-f]{2})/", - function ($matches) { - return chr(hexdec($matches[1])); - }, - $value - ); - } - - return $result; -} - -/** - * Explode a DN into an array of its RDN parts. - * - * NOTE: When a multivalue RDN is passed to ldap_explode_dn, the results returns with 'value + value'; - * - * - * Array ( - * [0] => uid=ppratt - * [1] => ou=People - * [2] => dc=example - * [3] => dc=com - * ) - * - * - * @param string The DN to explode. - * @param int (optional) Whether to include attribute names (see http://php.net/ldap_explode_dn for details) - * @return array An array of RDN parts of this format: - */ -function pla_explode_dn($dn,$with_attributes=0) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - global $CACHE; - - if (isset($CACHE['explode'][$dn][$with_attributes])) { - if (DEBUG_ENABLED) - debug_log('Return CACHED result (%s) for (%s)',1,0,__FILE__,__LINE__,__METHOD__, - $CACHE['explode'][$dn][$with_attributes],$dn); - - return $CACHE['explode'][$dn][$with_attributes]; - } - - $dn = addcslashes($dn,'<>+";'); - - # split the dn - $result[0] = ldap_explode_dn_patch(dn_escape($dn),0); - $result[1] = ldap_explode_dn_patch(dn_escape($dn),1); - if (! $result[$with_attributes]) { - if (DEBUG_ENABLED) - debug_log('Returning NULL - NO result.',1,0,__FILE__,__LINE__,__METHOD__); - - return array(); - } - - # Remove our count value that ldap_explode_dn returns us. - unset($result[0]['count']); - unset($result[1]['count']); - - # Record the forward and reverse entries in the cache. - foreach ($result as $key => $value) { - # translate hex code into ascii for display - $result[$key] = dn_unescape($value); - - $CACHE['explode'][implode(',',$result[0])][$key] = $result[$key]; - $CACHE['explode'][implode(',',array_reverse($result[0]))][$key] = array_reverse($result[$key]); - } - - if (DEBUG_ENABLED) - debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$result[$with_attributes]); - - return $result[$with_attributes]; -} - -/** - * Parse a DN and escape any special characters - */ -function dn_escape($dn) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $olddn = $dn; - - # Check if the RDN has a comma and escape it. - while (preg_match('/([^\\\\]),(\s*[^=]*\s*),/',$dn)) - $dn = preg_replace('/([^\\\\]),(\s*[^=]*\s*),/','$1\\\\2C$2,',$dn); - - $dn = preg_replace('/([^\\\\]),(\s*[^=]*\s*)([^,])$/','$1\\\\2C$2$3',$dn); - - if (DEBUG_ENABLED) - debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$dn); - - return $dn; -} - -/** - * Parse a DN and unescape any special characters - */ -function dn_unescape($dn) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - if (is_array($dn)) { - $a = array(); - - foreach ($dn as $key => $rdn) - $a[$key] = preg_replace_callback('/\\\([0-9A-Fa-f]{2})/', - function ($r) { - return chr(hexdec($r[1])); - }, - $rdn - ); - - return $a; - - } else { - return preg_replace_callback('/\\\([0-9A-Fa-f]{2})/', - function ($r) { - return chr(hexdec($r[1])); - }, - $dn - ); - } -} - -/** - * Fetches the URL for the specified item. This is a convenience function for - * fetching project HREFs (like bugs) - * - * @param string One of "open_bugs", "add_bug", "donate", or "add_rfe" - * (rfe = request for enhancement) - * @return string The URL to the requested item. - */ -function get_href($type,$extra_info='') { - $pla = 'http://phpldapadmin.sourceforge.net'; - - switch($type) { - case 'add_bug': - return 'https://github.com/leenooks/phpLDAPadmin/issues'; - case 'add_rfe': - return 'https://github.com/leenooks/phpLDAPadmin/issues'; - case 'credits': - return sprintf('%s/Credits',$pla); - case 'documentation': - return sprintf('%s/Documentation',$pla); - case 'donate': - return 'https://sourceforge.net/donate/index.php?group_id=61828'; - case 'forum': - return 'https://stackoverflow.com/questions/tagged/phpldapadmin'; - case 'web': - return sprintf('%s',$pla); - default: - return null; - } -} - -/** - * Returns the current time as a double (including micro-seconds). - * - * @return double The current time in seconds since the beginning of the UNIX epoch (Midnight Jan. 1, 1970) - */ -function utime() { - $time = explode(' ',microtime()); - $usec = (double)$time[0]; - $sec = (double)$time[1]; - return $sec + $usec; -} - -/** - * Converts an array to a query-string with the option to exclude certain variables - * from the returned query string. This is convenient if callers want to convert the - * current GET query string or POST array into a string and replace certain - * variables with their own. - * - * @param array The associate array to convert whose form is such that the keys are the - * names of the variables and the values are said variables' values like this: - * - * Array ( - * [server_id] = 0, - * [dn] = "dc=example,dc=com", - * [attr] = "sn" - * ) - * - * This will produce a string like this: "server_id=0&dn=dc=example,dc=com&attr=sn" - * @param array (optional) An array of variables to exclude in the resulting string - * @return string The string created from the array. - */ -function array_to_query_string($array,$exclude_vars=array()) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - if (! is_array($array) || ! count($array)) - return ''; - - $str = ''; - $i = 0; - foreach ($array as $name => $val) - if (! in_array($name,$exclude_vars)) - if (is_array($val)) - foreach ($val as $v) { - if ($i++ > 0) - $str .= '&'; - - $str .= sprintf('%s[]=%s',rawurlencode($name),rawurlencode($v)); - } - - else { - if ($i++ > 0) - $str .= '&'; - - $str .= sprintf('%s=%s',rawurlencode($name),rawurlencode($val)); - } - - return $str; -} - -/** - * Reverses a DN such that the top-level RDN is first and the bottom-level RDN is last - * For example: - * - * cn=Brigham,ou=People,dc=example,dc=com - * - * Becomes: - * - * dc=com,dc=example,ou=People,cn=Brigham - * - * This makes it possible to sort lists of DNs such that they are grouped by container. - * - * @param string The DN to reverse - * @return string The reversed DN - * - * @see pla_compare_dns - * @see pla_explode_dns - */ -function pla_reverse_dn($dn) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - return (implode(',',array_reverse(pla_explode_dn($dn)))); -} - -/** - * Reads an array and returns the array values back in lower case - * - * @param array $array The array to convert the values to lowercase. - * @returns array Array with values converted to lowercase. - */ -function arrayLower($array) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - if (! is_array($array)) - return $array; - - $newarray = array(); - foreach ($array as $key => $value) - $newarray[$key] = strtolower($value); - - return $newarray; -} - -/** - * Checks if a string exists in an array, ignoring case. - * - * @param string What you are looking for - * @param array The array that you think it is in. - * @return boolean True if its there, false if its not. - */ -function in_array_ignore_case($needle,$haystack) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - if (! is_array($haystack)) - return false; - - if (! is_string($needle)) - return false; - - $return = false; - - foreach ($haystack as $element) { - if (is_string($element) && (strcasecmp($needle,$element) == 0)) { - $return = true; - break; - } - } - - if (DEBUG_ENABLED) - debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$return); - - return $return; -} - -/** - * Gets a DN string using the user-configured tree_display_format string to format it. - */ -function draw_formatted_dn($server,$entry) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $dn = $entry->getDn(); - - $formats = $_SESSION[APPCONFIG]->getValue('appearance','tree_display_format'); - - foreach ($formats as $format) { - $has_none = false; - preg_match_all('/%[a-zA-Z_0-9]+/',$format,$tokens); - $tokens = $tokens[0]; - - if (DEBUG_ENABLED) - debug_log('The tokens are (%s)',1,0,__FILE__,__LINE__,__METHOD__,$tokens); - - foreach ($tokens as $token) { - if (strcasecmp($token,'%dn') == 0) - $format = str_replace($token,pretty_print_dn($dn),$format); - - elseif (strcasecmp($token,'%rdn') == 0) - $format = str_replace($token,pretty_print_dn($entry->getRDN()),$format); - - elseif (strcasecmp($token,'%rdnvalue') == 0) { - $rdn = get_rdn($dn,0,true); - $rdn_value = explode('=',$rdn,2); - $rdn_value = $rdn_value[1]; - $format = str_replace($token,$rdn_value,$format); - - } else { - $attr_name = str_replace('%','',$token); - $attr_values = $server->getDNAttrValue($dn,$attr_name); - - if (is_null($attr_values) || (count($attr_values) <= 0)) { - $display = '<'._('none').'>'; - $has_none = true; - - } elseif (is_array($attr_values)) - $display = implode(', ',$attr_values); - - else - $display = $attr_values; - - $format = str_replace($token,$display,$format); - } - } - - # If this format has all values available, use it. Otherwise, try the next one - if (!$has_none) - return $format; - } - - return $format; -} - -/** - * Server html select list - */ -function server_select_list($selected=null,$logged_on=false,$name='index',$isVisible=true,$js=null) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $count = 0; - $server_menu_html = sprintf(''; - - if ($count > 1) - return $server_menu_html; - - elseif ($count) - return sprintf('%s ', - $selected_server->getName(),$name,$selected_server->getIndex()); - - else - return ''; -} - -/** - * Converts a little-endian hex-number to one, that 'hexdec' can convert - */ -function littleEndian($hex) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $result = ''; - - for ($x=strlen($hex)-2;$x>= 0;$x=$x-2) - $result .= substr($hex,$x,2); - - return $result; -} - -function binSIDtoText($binsid) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $hex_sid = bin2hex($binsid); - $rev = hexdec(substr($hex_sid,0,2)); // Get revision-part of SID - $subcount = hexdec(substr($hex_sid,2,2)); // Get count of sub-auth entries - $auth = hexdec(substr($hex_sid,4,12)); // SECURITY_NT_AUTHORITY - - $result = "$rev-$auth"; - - for ($x=0;$x<$subcount;$x++) { - $subauth[$x] = hexdec(littleEndian(substr($hex_sid,16+($x*8),8))); // get all SECURITY_NT_AUTHORITY - $result .= sprintf('-%s',$subauth[$x]); - } - - return $result; -} - -/** - * Query LDAP and return a hash. - * - * @param string The base DN to use. - * @param string LDAP Query filter. - * @param string LDAP attribute to use as key. - * @param array Attributes to use as values. - * @param boolean Specify false to not sort results by DN - * or true to have the returned array sorted by DN (uses ksort) - * or an array of attribute names to sort by attribute values - * @return array Array of values keyed by $key. - */ -function return_ldap_hash($base,$filter,$key,$attrs,$sort=true) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $server = $_SESSION[APPCONFIG]->getServer(get_request('server_id','REQUEST')); - $key = strtolower($key); - - $query = array(); - $query['base'] = $base; - $query['filter'] = $filter; - $query['attrs'] = $attrs; - $search = $server->query($query,null); - - $results = array(); - - foreach ($search as $dn => $values) - if (isset($values[$key])) - if (is_array($values[$key])) - foreach ($values[$key] as $i => $k) - foreach ($attrs as $attr) { - $lattr = strtolower($attr); - if (isset($values[$lattr])) { - $v = ''; - - if (is_array($values[$lattr]) && isset($values[$lattr][$i])) - $v = $values[$lattr][$i]; - - if (is_string($v) && (strlen($v) > 0)) - $results[$k][$attr] = $v; - } - } - - else - foreach ($attrs as $attr) { - $lattr = strtolower($attr); - if (isset($values[$lattr])) - $results[$values[$key]][$attr] = $values[$lattr]; - } - - if ($sort) - masort($results,is_array($sort) ? implode(',',$sort) : 'dn'); - - return $results; -} - -/** - * This function returns a string automatically generated - * based on the criteria defined in the array $criteria in config.php - */ -function password_generate() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - $no_use_similiar = ! $_SESSION[APPCONFIG]->getValue('password','use_similar'); - $lowercase = $_SESSION[APPCONFIG]->getValue('password','lowercase'); - $uppercase = $_SESSION[APPCONFIG]->getValue('password','uppercase'); - $digits = $_SESSION[APPCONFIG]->getValue('password','numbers'); - $punctuation = $_SESSION[APPCONFIG]->getValue('password','punctuation'); - $length = $_SESSION[APPCONFIG]->getValue('password','length'); - - $outarray = array(); - - if ($no_use_similiar) { - $raw_lower = 'a b c d e f g h k m n p q r s t u v w x y z'; - $raw_numbers = '2 3 4 5 6 7 8 9'; - $raw_punc = '# $ % ^ & * ( ) _ - + = . , [ ] { } :'; - - } else { - $raw_lower = 'a b c d e f g h i j k l m n o p q r s t u v w x y z'; - $raw_numbers = '1 2 3 4 5 6 7 8 9 0'; - $raw_punc = '# $ % ^ & * ( ) _ - + = . , [ ] { } : |'; - } - - $llower = explode(' ',$raw_lower); - shuffle($llower); - $lupper = explode(' ',strtoupper($raw_lower)); - shuffle($lupper); - $numbers = explode(' ',$raw_numbers); - shuffle($numbers); - $punc = explode(' ',$raw_punc); - shuffle($punc); - - if ($lowercase > 0) - $outarray = array_merge($outarray,a_array_rand($llower,$lowercase)); - - if ($uppercase > 0) - $outarray = array_merge($outarray,a_array_rand($lupper,$uppercase)); - - if ($digits > 0) - $outarray = array_merge($outarray,a_array_rand($numbers,$digits)); - - if ($punctuation > 0) - $outarray = array_merge($outarray,a_array_rand($punc,$punctuation)); - - $num_spec = $lowercase + $uppercase + $digits + $punctuation; - - if ($num_spec < $length) { - $leftover = array(); - if ($lowercase > 0) - $leftover = array_merge($leftover,$llower); - if ($uppercase > 0) - $leftover = array_merge($leftover,$lupper); - if ($digits > 0) - $leftover = array_merge($leftover,$numbers); - if ($punctuation > 0) - $leftover = array_merge($leftover,$punc); - - if (count($leftover) == 0) - $leftover = array_merge($leftover,$llower,$lupper,$numbers,$punc); - - shuffle($leftover); - $outarray = array_merge($outarray,a_array_rand($leftover,$length-$num_spec)); - } - - shuffle($outarray); - $return = implode('',$outarray); - - if (DEBUG_ENABLED) - debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$return); - - return $return; -} - -/** - * This function returns an array of $num_req values - * randomly picked from the $input array - * - * @param array Array of values - * @param integer Number of values in returned array - * @return string The padded string - */ -function a_array_rand($input,$num_req) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - if (count($input) == 0) - return array(); - - if ($num_req < 1) - return array(); - - $return = array(); - if ($num_req > count($input)) { - for($i = 0; $i < $num_req; $i++) { - $idx = array_rand($input,1); - $return[] = $input[$idx]; - } - - } else { - $idxlist = array_rand($input,$num_req); - if ($num_req == 1) - $idxlist = array($idxlist); - - for($i = 0; $i < count($idxlist); $i++) - $return[] = $input[$idxlist[$i]]; - } - - if (DEBUG_ENABLED) - debug_log('Returning (%s)',1,0,__FILE__,__LINE__,__METHOD__,$return); - - return $return; -} - -/** - * This is for Opera. By putting "random junk" in the query string, it thinks - * that it does not have a cached version of the page, and will thus - * fetch the page rather than display the cached version - */ -function random_junk() { - $time = gettimeofday(); - return md5(strtotime('now').$time['usec']); -} - -/** - * Returns a HTML id that can be used in the URL after the #. - * - * @param string The DN to pretty-print. - * @return string - */ -function htmlid($sid,$dn) { - return sprintf('SID%s:%s',$sid,preg_replace('/[\ =,]/','_',$dn)); -} - -/** - * Is PLA configured for AJAX display - */ -function isAjaxEnabled() { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - if (isset($_SESSION[APPCONFIG])) - return ($_SESSION[APPCONFIG]->getValue('appearance','tree') == 'AJAXTree'); - else - return false; -} -/** -* Check if user is a robot with reCAPTCHA -**/ -function IsRobot($gResponse){ - $isRobot = true; - $url = 'https://www.google.com/recaptcha/api/siteverify'; - $data = array( - 'secret' => $_SESSION[APPCONFIG]->getValue('session','reCAPTCHA-key-server'), - 'response' => $gResponse - ); - $options = array( - 'http' => array ( - 'method' => 'POST','header' => - 'Content-Type: application/x-www-form-urlencoded', - 'content' => http_build_query($data) - ) - ); - $context = stream_context_create($options); - $verify = file_get_contents($url, false, $context); - $captcha_success = json_decode($verify); - if ($captcha_success->success) { - $isRobot = false; - } - return $isRobot; - -} -?>