Compare commits
5 Commits
3aa5e05947
...
098b75085e
Author | SHA1 | Date | |
---|---|---|---|
098b75085e | |||
4ef6cbc00e | |||
8e66b2adbc | |||
dfc76ef789 | |||
f08fdb1bcd |
@ -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
|
||||
|
@ -145,9 +145,9 @@ class Attribute implements \Countable, \ArrayAccess, \Iterator
|
||||
// Attribute values
|
||||
'values' => $this->values,
|
||||
// Required by Object Classes
|
||||
'required_by' => $this->schema->required_by_object_classes,
|
||||
'required_by' => $this->schema?->required_by_object_classes ?: collect(),
|
||||
// Used in Object Classes
|
||||
'used_in' => $this->schema->used_in_object_classes,
|
||||
'used_in' => $this->schema?->used_in_object_classes ?: collect(),
|
||||
|
||||
default => throw new \Exception('Unknown key:' . $key),
|
||||
};
|
||||
@ -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 <post> attribute.
|
||||
case 'helper':
|
||||
if (! isset($values['post']) && ! $_SESSION[APPCONFIG]->getValue('appearance','hide_template_warning'))
|
||||
system_message(array(
|
||||
'title'=>sprintf('%s [<i>%s</i>]',_('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 [<i>%s</i>]',_('Unknown XML setting'),$i),
|
||||
'body'=>sprintf('%s <small>[%s]</small>',_('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 [<i>%s</i>]',_('Unknown XML setting'),$index),
|
||||
'body'=>sprintf('%s <small>[%s]</small>',_('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 [<i>%s</i>]',_('Unknown XML setting'),$index),
|
||||
'body'=>sprintf('%s <small>[%s]</small>',_('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 <small>[%s]</small>',_('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 [<i>%s</i>]',_('Unknown XML setting'),$index),
|
||||
'body'=>sprintf('%s <small>[%s]</small>',_('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);
|
||||
}
|
||||
*/
|
||||
}
|
49
app/Classes/LDAP/Attribute/RDN.php
Normal file
49
app/Classes/LDAP/Attribute/RDN.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Attribute;
|
||||
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
use App\Classes\LDAP\Attribute;
|
||||
|
||||
/**
|
||||
* Represents the RDN for an Entry
|
||||
*/
|
||||
final class RDN extends Attribute
|
||||
{
|
||||
private string $base;
|
||||
private Collection $attrs;
|
||||
|
||||
public function __get(string $key): mixed
|
||||
{
|
||||
return match ($key) {
|
||||
'base' => $this->base,
|
||||
'attrs' => $this->attrs->pluck('name'),
|
||||
default => parent::__get($key),
|
||||
};
|
||||
}
|
||||
|
||||
public function hints(): array
|
||||
{
|
||||
return [
|
||||
'required' => __('RDN is required')
|
||||
];
|
||||
}
|
||||
|
||||
public function render(bool $edit=FALSE,bool $old=FALSE,bool $new=FALSE): View
|
||||
{
|
||||
return view('components.attribute.rdn')
|
||||
->with('o',$this);
|
||||
}
|
||||
|
||||
public function setAttributes(Collection $attrs): void
|
||||
{
|
||||
$this->attrs = $attrs;
|
||||
}
|
||||
|
||||
public function setBase(string $base): void
|
||||
{
|
||||
$this->base = $base;
|
||||
}
|
||||
}
|
@ -289,7 +289,6 @@ final class AttributeType extends Base {
|
||||
case 'type': return $this->type;
|
||||
case 'usage': return $this->usage;
|
||||
case 'used_in_object_classes': return $this->used_in_object_classes;
|
||||
case 'validation': return Arr::get(config('ldap.validation'),$this->name_lc);
|
||||
|
||||
default: return parent::__get($key);
|
||||
}
|
||||
@ -419,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
|
||||
*
|
||||
@ -466,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
|
||||
*
|
||||
@ -512,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
|
||||
@ -564,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;
|
||||
}
|
||||
|
||||
@ -591,14 +535,32 @@ final class AttributeType extends Base {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this attribute's type.
|
||||
* Return Request validation array
|
||||
*
|
||||
* @param string $type The new type.
|
||||
* This will merge configured validation with schema required attributes
|
||||
*
|
||||
* @param array $array
|
||||
* @return array|null
|
||||
*/
|
||||
public function setType($type) {
|
||||
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
|
||||
debug_log('Entered (%%)',9,1,__FILE__,__LINE__,__METHOD__,$fargs);
|
||||
public function validation(array $array): ?array
|
||||
{
|
||||
// For each item in array, we need to get the OC heirachy
|
||||
$heirachy = collect($array)
|
||||
->filter()
|
||||
->map(fn($item)=>config('server')
|
||||
->schema('objectclasses',$item)
|
||||
->getSupClasses()
|
||||
->push($item))
|
||||
->flatten()
|
||||
->unique();
|
||||
|
||||
$this->type = $type;
|
||||
$validation = collect(Arr::get(config('ldap.validation'),$this->name_lc,[]));
|
||||
if (($heirachy->intersect($this->required_by_object_classes)->count() > 0)
|
||||
&& (! collect($validation->get($this->name_lc))->contains('required'))) {
|
||||
$validation->put($this->name_lc,array_merge(['required','min:1'],$validation->get($this->name_lc,[])))
|
||||
->put($this->name_lc.'.*',array_merge(['required','min:1'],$validation->get($this->name_lc.'.*',[])));
|
||||
}
|
||||
|
||||
return $validation->toArray();
|
||||
}
|
||||
}
|
@ -208,7 +208,7 @@ final class ObjectClass extends Base
|
||||
public function __get(string $key): mixed
|
||||
{
|
||||
return match ($key) {
|
||||
'attributes' => $this->getAllAttrs(),
|
||||
'attributes' => $this->getAllAttrs(TRUE),
|
||||
'sup' => $this->sup_classes,
|
||||
'type_name' => match ($this->type) {
|
||||
Server::OC_STRUCTURAL => 'Structural',
|
||||
@ -223,13 +223,18 @@ final class ObjectClass extends Base
|
||||
/**
|
||||
* Return a list of attributes that this objectClass provides
|
||||
*
|
||||
* @param bool $parents
|
||||
* @return Collection
|
||||
* @throws InvalidUsage
|
||||
*/
|
||||
public function getAllAttrs(): Collection
|
||||
public function getAllAttrs(bool $parents=FALSE): Collection
|
||||
{
|
||||
return $this->getMustAttrs()
|
||||
->merge($this->getMayAttrs());
|
||||
return $this->getMustAttrs($parents)
|
||||
->transform(function($item) {
|
||||
$item->required = true;
|
||||
return $item;
|
||||
})
|
||||
->merge($this->getMayAttrs($parents));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,6 +16,7 @@ namespace App\Classes\LDAP\Schema;
|
||||
final class ObjectClassAttribute extends Base {
|
||||
// This Attribute's root.
|
||||
private string $source;
|
||||
public bool $required = FALSE;
|
||||
|
||||
/**
|
||||
* Creates a new ObjectClassAttribute with specified name and source objectClass.
|
||||
@ -31,11 +32,9 @@ final class ObjectClassAttribute extends Base {
|
||||
|
||||
public function __get(string $key): mixed
|
||||
{
|
||||
switch ($key) {
|
||||
case 'source':
|
||||
return $this->source;
|
||||
|
||||
default: return parent::__get($key);
|
||||
}
|
||||
return match ($key) {
|
||||
'source' => $this->source,
|
||||
default => parent::__get($key),
|
||||
};
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -16,21 +16,21 @@ class APIController extends Controller
|
||||
* Get the LDAP server BASE DNs
|
||||
*
|
||||
* @return Collection
|
||||
* @throws LdapRecord\Query\ObjectNotFoundException
|
||||
* @throws \LdapRecord\Query\ObjectNotFoundException
|
||||
*/
|
||||
public function bases(): Collection
|
||||
{
|
||||
$base = Server::baseDNs() ?: collect();
|
||||
|
||||
return $base->transform(function($item) {
|
||||
return [
|
||||
'title'=>$item->getRdn(),
|
||||
'item'=>$item->getDNSecure(),
|
||||
'lazy'=>TRUE,
|
||||
'icon'=>'fa-fw fas fa-sitemap',
|
||||
'tooltip'=>$item->getDn(),
|
||||
];
|
||||
});
|
||||
return $base
|
||||
->transform(fn($item)=>
|
||||
[
|
||||
'title'=>$item->getRdn(),
|
||||
'item'=>$item->getDNSecure(),
|
||||
'lazy'=>TRUE,
|
||||
'icon'=>'fa-fw fas fa-sitemap',
|
||||
'tooltip'=>$item->getDn(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -41,19 +41,31 @@ class APIController extends Controller
|
||||
{
|
||||
$levels = $request->query('depth',1);
|
||||
$dn = Crypt::decryptString($request->query('key'));
|
||||
|
||||
// Sometimes our key has a command, so we'll ignore it
|
||||
if (str_starts_with($dn,'*') && ($x=strpos($dn,'|')))
|
||||
$dn = substr($dn,$x+1);
|
||||
|
||||
Log::debug(sprintf('%s: Query [%s] - Levels [%d]',__METHOD__,$dn,$levels));
|
||||
|
||||
return (config('server'))
|
||||
->children($dn)
|
||||
->transform(function($item) {
|
||||
return [
|
||||
->transform(fn($item)=>
|
||||
[
|
||||
'title'=>$item->getRdn(),
|
||||
'item'=>$item->getDNSecure(),
|
||||
'icon'=>$item->icon(),
|
||||
'lazy'=>Arr::get($item->getAttribute('hassubordinates'),0) == 'TRUE',
|
||||
'tooltip'=>$item->getDn(),
|
||||
];
|
||||
});
|
||||
])
|
||||
->prepend(
|
||||
[
|
||||
'title'=>sprintf('[%s]',__('Create Entry')),
|
||||
'item'=>Crypt::encryptString(sprintf('*%s|%s','create',$dn)),
|
||||
'lazy'=>FALSE,
|
||||
'icon'=>'fas fa-fw fa-square-plus text-warning',
|
||||
'tooltip'=>__('Create new LDAP item here'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function schema_view(Request $request)
|
||||
@ -63,20 +75,20 @@ class APIController extends Controller
|
||||
switch($request->type) {
|
||||
case 'objectclasses':
|
||||
return view('fragment.schema.objectclasses')
|
||||
->with('objectclasses',$server->schema('objectclasses')->sortBy(function($item) { return strtolower($item->name); }));
|
||||
->with('objectclasses',$server->schema('objectclasses')->sortBy(fn($item)=>strtolower($item->name)));
|
||||
|
||||
case 'attributetypes':
|
||||
return view('fragment.schema.attributetypes')
|
||||
->with('server',$server)
|
||||
->with('attributetypes',$server->schema('attributetypes')->sortBy(function($item) { return strtolower($item->name); }));
|
||||
->with('attributetypes',$server->schema('attributetypes')->sortBy(fn($item)=>strtolower($item->name)));
|
||||
|
||||
case 'ldapsyntaxes':
|
||||
return view('fragment.schema.ldapsyntaxes')
|
||||
->with('ldapsyntaxes',$server->schema('ldapsyntaxes')->sortBy(function($item) { return strtolower($item->description); }));
|
||||
->with('ldapsyntaxes',$server->schema('ldapsyntaxes')->sortBy(fn($item)=>strtolower($item->description)));
|
||||
|
||||
case 'matchingrules':
|
||||
return view('fragment.schema.matchingrules')
|
||||
->with('matchingrules',$server->schema('matchingrules')->sortBy(function($item) { return strtolower($item->name); }));
|
||||
->with('matchingrules',$server->schema('matchingrules')->sortBy(fn($item)=>strtolower($item->name)));
|
||||
|
||||
default:
|
||||
abort(404);
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
@ -12,20 +13,21 @@ use Illuminate\Support\Facades\Redirect;
|
||||
use LdapRecord\Exceptions\InsufficientAccessException;
|
||||
use LdapRecord\LdapRecordException;
|
||||
use LdapRecord\Query\ObjectNotFoundException;
|
||||
use Nette\NotImplementedException;
|
||||
|
||||
use App\Classes\LDAP\Attribute\Factory;
|
||||
use App\Classes\LDAP\{Attribute,Server};
|
||||
use App\Classes\LDAP\Import\LDIF as LDIFImport;
|
||||
use App\Classes\LDAP\Export\LDIF as LDIFExport;
|
||||
use App\Exceptions\Import\{GeneralException,VersionException};
|
||||
use App\Exceptions\InvalidUsage;
|
||||
use App\Http\Requests\{EntryRequest,ImportRequest};
|
||||
use App\Http\Requests\{EntryRequest,EntryAddRequest,ImportRequest};
|
||||
use App\Ldap\Entry;
|
||||
use App\View\Components\AttributeType;
|
||||
use Nette\NotImplementedException;
|
||||
|
||||
class HomeController extends Controller
|
||||
{
|
||||
private function bases()
|
||||
private function bases(): Collection
|
||||
{
|
||||
$base = Server::baseDNs() ?: collect();
|
||||
|
||||
@ -51,21 +53,38 @@ class HomeController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a specific DN
|
||||
* Create a new object in the LDAP server
|
||||
*
|
||||
* @param Request $request
|
||||
* @param EntryAddRequest $request
|
||||
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
|
||||
* @throws InvalidUsage
|
||||
*/
|
||||
public function dn_frame(Request $request)
|
||||
public function entry_add(EntryAddRequest $request)
|
||||
{
|
||||
$dn = Crypt::decryptString($request->post('key'));
|
||||
if (! old('step',$request->validated('step')))
|
||||
abort(404);
|
||||
|
||||
$page_actions = collect(['edit'=>TRUE,'copy'=>TRUE]);
|
||||
$key = $this->request_key($request,collect(old()));
|
||||
|
||||
return view('frames.dn')
|
||||
->with('o',config('server')->fetch($dn))
|
||||
->with('dn',$dn)
|
||||
->with('page_actions',$page_actions);
|
||||
$o = new Entry;
|
||||
|
||||
if (count(array_filter($x=old('objectclass',$request->objectclass)))) {
|
||||
$o->objectclass = $x;
|
||||
|
||||
foreach($o->getAvailableAttributes()->filter(fn($item)=>$item->required) as $ao)
|
||||
$o->addAttribute($ao,'');
|
||||
|
||||
$o->setRDNBase($key['dn']);
|
||||
}
|
||||
|
||||
$step = $request->step ? $request->step+1 : old('step');
|
||||
|
||||
return view('frame')
|
||||
->with('subframe','create')
|
||||
->with('bases',$this->bases())
|
||||
->with('o',$o)
|
||||
->with('step',$step)
|
||||
->with('container',old('container',$key['dn']));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -75,7 +94,7 @@ class HomeController extends Controller
|
||||
* @param string $id
|
||||
* @return \Closure|\Illuminate\Contracts\View\View|string
|
||||
*/
|
||||
public function entry_attr_add(Request $request,string $id)
|
||||
public function entry_attr_add(Request $request,string $id): string
|
||||
{
|
||||
$xx = new \stdClass();
|
||||
$xx->index = 0;
|
||||
@ -90,6 +109,54 @@ class HomeController extends Controller
|
||||
return $x;
|
||||
}
|
||||
|
||||
public function entry_create(EntryAddRequest $request)
|
||||
{
|
||||
$key = $this->request_key($request,collect(old()));
|
||||
|
||||
$dn = sprintf('%s=%s,%s',$request->rdn,$request->rdn_value,$key['dn']);
|
||||
|
||||
$o = new Entry;
|
||||
$o->setDn($dn);
|
||||
|
||||
foreach ($request->except(['_token','key','rdn','rdn_value']) as $key => $value)
|
||||
$o->{$key} = array_filter($value);
|
||||
|
||||
try {
|
||||
$o->save();
|
||||
|
||||
// @todo To test and valide this Exception is caught
|
||||
} catch (InsufficientAccessException $e) {
|
||||
$request->flash();
|
||||
|
||||
switch ($x=$e->getDetailedError()->getErrorCode()) {
|
||||
case 50:
|
||||
return Redirect::to('/')
|
||||
->withInput()
|
||||
->withErrors(sprintf('%s: %s (%s)',__('LDAP Server Error Code'),$x,__($e->getDetailedError()->getErrorMessage())));
|
||||
|
||||
default:
|
||||
abort(599,$e->getDetailedError()->getErrorMessage());
|
||||
}
|
||||
|
||||
// @todo To test and valide this Exception is caught
|
||||
} catch (LdapRecordException $e) {
|
||||
$request->flash();
|
||||
|
||||
switch ($x=$e->getDetailedError()->getErrorCode()) {
|
||||
case 8:
|
||||
return Redirect::to('/')
|
||||
->withInput()
|
||||
->withErrors(sprintf('%s: %s (%s)',__('LDAP Server Error Code'),$x,__($e->getDetailedError()->getErrorMessage())));
|
||||
|
||||
default:
|
||||
abort(599,$e->getDetailedError()->getErrorMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return Redirect::to('/')
|
||||
->withFragment($o->getDNSecure());
|
||||
}
|
||||
|
||||
public function entry_export(Request $request,string $id)
|
||||
{
|
||||
$dn = Crypt::decryptString($id);
|
||||
@ -112,11 +179,9 @@ class HomeController extends Controller
|
||||
* @param string $id
|
||||
* @return mixed
|
||||
*/
|
||||
public function entry_objectclass_add(string $id)
|
||||
public function entry_objectclass_add(Request $request)
|
||||
{
|
||||
$dn = Crypt::decryptString($id);
|
||||
$o = config('server')->fetch($dn);
|
||||
$oc = $o->getObject('objectclass');
|
||||
$oc = Factory::create('objectclass',$request->oc);
|
||||
|
||||
$ocs = $oc
|
||||
->structural
|
||||
@ -259,26 +324,51 @@ class HomeController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Application home page
|
||||
* Render a frame, normally as a result of an AJAX call
|
||||
* This will render the right frame.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Collection|null $old
|
||||
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|View
|
||||
*/
|
||||
public function home()
|
||||
public function frame(Request $request,?Collection $old=NULL): View
|
||||
{
|
||||
if (old('dn'))
|
||||
return view('frame')
|
||||
->with('subframe','dn')
|
||||
->with('bases',$this->bases())
|
||||
->with('o',config('server')->fetch($dn=Crypt::decryptString(old('dn'))))
|
||||
->with('dn',$dn);
|
||||
// If our index was not render from a root url, then redirect to it
|
||||
if (($request->root().'/' !== url()->previous()) && $request->method() === 'POST')
|
||||
abort(409);
|
||||
|
||||
elseif (old('frame'))
|
||||
return view('frame')
|
||||
->with('subframe',old('frame'))
|
||||
$key = $this->request_key($request,$old);
|
||||
|
||||
$view = ($old
|
||||
? view('frame')->with('subframe',$key['cmd'])
|
||||
: view('frames.'.$key['cmd']))
|
||||
->with('bases',$this->bases());
|
||||
|
||||
return match ($key['cmd']) {
|
||||
'create' => $view
|
||||
->with('container',old('container',$key['dn']))
|
||||
->with('step',1),
|
||||
|
||||
'dn' => $view
|
||||
->with('dn',$key['dn'])
|
||||
->with('page_actions',collect(['edit'=>TRUE,'copy'=>TRUE])),
|
||||
|
||||
'import' => $view,
|
||||
|
||||
default => abort(404),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the main page render function
|
||||
*/
|
||||
public function home(Request $request)
|
||||
{
|
||||
// Did we come here as a result of a redirect
|
||||
return count(old())
|
||||
? $this->frame($request,collect(old()))
|
||||
: view('home')
|
||||
->with('bases',$this->bases());
|
||||
|
||||
else
|
||||
return view('home')
|
||||
->with('bases',$this->bases())
|
||||
->with('server',config('ldap.connections.default.name'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -334,6 +424,39 @@ class HomeController extends Controller
|
||||
->with('s',config('server'));
|
||||
}
|
||||
|
||||
/**
|
||||
* For any incoming request, work out the command and DN involved
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Collection|null $old
|
||||
* @return array
|
||||
*/
|
||||
private function request_key(Request $request,?Collection $old=NULL): array
|
||||
{
|
||||
// Setup
|
||||
$cmd = NULL;
|
||||
$dn = NULL;
|
||||
$key = $request->get('key',old('key'))
|
||||
? Crypt::decryptString($request->get('key',old('key')))
|
||||
: NULL;
|
||||
|
||||
// Determine if our key has a command
|
||||
if (str_contains($key,'|')) {
|
||||
$m = [];
|
||||
|
||||
if (preg_match('/\*([a-z_]+)\|(.+)$/',$key,$m)) {
|
||||
$cmd = $m[1];
|
||||
$dn = ($m[2] !== '_NOP') ? $m[2] : NULL;
|
||||
}
|
||||
|
||||
} elseif (old('dn',$request->get('key'))) {
|
||||
$cmd = 'dn';
|
||||
$dn = Crypt::decryptString(old('dn',$request->get('key')));
|
||||
}
|
||||
|
||||
return ['cmd'=>$cmd,'dn'=>$dn];
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the Schema Viewer
|
||||
*
|
||||
|
71
app/Http/Requests/EntryAddRequest.php
Normal file
71
app/Http/Requests/EntryAddRequest.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
|
||||
use App\Rules\{DNExists,HasStructuralObjectClass};
|
||||
|
||||
class EntryAddRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Get the error messages for the defined validation rules.
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function messages(): array
|
||||
{
|
||||
return [
|
||||
'rdn' => __('RDN is required.'),
|
||||
'rdn_value' => __('RDN value is required.'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
* @throws \Psr\Container\ContainerExceptionInterface
|
||||
* @throws \Psr\Container\NotFoundExceptionInterface
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
if (request()->method() === 'GET')
|
||||
return [];
|
||||
|
||||
return config('server')
|
||||
->schema('attributetypes')
|
||||
->intersectByKeys($this->request)
|
||||
->map(fn($item)=>$item->validation(request()->get('objectclass')))
|
||||
->filter()
|
||||
->flatMap(fn($item)=>$item)
|
||||
->merge([
|
||||
'key' => [
|
||||
'required',
|
||||
new DNExists,
|
||||
function (string $attribute,mixed $value,\Closure $fail) {
|
||||
$cmd = Crypt::decryptString($value);
|
||||
|
||||
// Sometimes our key has a command, so we'll ignore it
|
||||
if (str_starts_with($cmd,'*') && ($x=strpos($cmd,'|')))
|
||||
$cmd = substr($cmd,1,$x-1);
|
||||
|
||||
if ($cmd !== 'create') {
|
||||
$fail(sprintf('Invalid command: %s',$cmd));
|
||||
}
|
||||
},
|
||||
],
|
||||
'rdn' => 'required_if:step,2|string|min:1',
|
||||
'rdn_value' => 'required_if:step,2|string|min:1',
|
||||
'step' => 'int|min:1|max:2',
|
||||
'objectclass'=>[
|
||||
'required',
|
||||
'array',
|
||||
'min:1',
|
||||
new HasStructuralObjectClass,
|
||||
]
|
||||
])
|
||||
->toArray();
|
||||
}
|
||||
}
|
@ -6,29 +6,19 @@ use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class EntryRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function rules()
|
||||
public function rules(): array
|
||||
{
|
||||
return config('server')
|
||||
->schema('attributetypes')
|
||||
->intersectByKeys($this->request)
|
||||
->transform(function($item) { return $item->validation; })
|
||||
->map(fn($item)=>$item->validation(request()?->get('objectclass') ?: []))
|
||||
->filter()
|
||||
->flatMap(function($item) { return $item; })
|
||||
->flatMap(fn($item)=>$item)
|
||||
->toArray();
|
||||
}
|
||||
}
|
@ -6,15 +6,9 @@ use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class ImportRequest extends FormRequest
|
||||
{
|
||||
public function authorize()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
public function rules()
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'frame' => 'required|string|in:import',
|
||||
'file' => 'nullable|extensions:ldif|required_without:text',
|
||||
'text'=> 'nullable|prohibits:file|string|min:16',
|
||||
];
|
||||
|
@ -12,11 +12,14 @@ use App\Classes\LDAP\Attribute;
|
||||
use App\Classes\LDAP\Attribute\Factory;
|
||||
use App\Classes\LDAP\Export\LDIF;
|
||||
use App\Exceptions\Import\AttributeException;
|
||||
use App\Exceptions\InvalidUsage;
|
||||
|
||||
class Entry extends Model
|
||||
{
|
||||
private Collection $objects;
|
||||
private bool $noObjectAttributes = FALSE;
|
||||
// For new entries, this is the container that this entry will be stored in
|
||||
private string $rdnbase;
|
||||
|
||||
/* OVERRIDES */
|
||||
|
||||
@ -46,7 +49,7 @@ class Entry extends Model
|
||||
public function getAttributes(): array
|
||||
{
|
||||
return $this->objects
|
||||
->map(fn($item)=>$item->values->toArray())
|
||||
->map(fn($item)=>$item->values)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
@ -92,10 +95,7 @@ class Entry extends Model
|
||||
$key = $this->normalizeAttributeKey($key);
|
||||
|
||||
if ((! $this->objects->get($key)) && $value) {
|
||||
$o = new Attribute($key,[]);
|
||||
$o->value = $value;
|
||||
|
||||
$this->objects->put($key,$o);
|
||||
$this->objects->put($key,Factory::create($key,$value));
|
||||
|
||||
} elseif ($this->objects->get($key)) {
|
||||
$this->objects->get($key)->value = $this->attributes[$key];
|
||||
@ -144,6 +144,10 @@ class Entry extends Model
|
||||
|
||||
public function addAttribute(string $key,mixed $value): void
|
||||
{
|
||||
// While $value is mixed, it can only be a string
|
||||
if (! is_string($value))
|
||||
throw new \Exception('value should be a string');
|
||||
|
||||
$key = $this->normalizeAttributeKey($key);
|
||||
|
||||
if (! config('server')->schema('attributetypes')->has($key))
|
||||
@ -239,11 +243,12 @@ class Entry extends Model
|
||||
|
||||
/**
|
||||
* Return a secure version of the DN
|
||||
* @param string $cmd
|
||||
* @return string
|
||||
*/
|
||||
public function getDNSecure(): string
|
||||
public function getDNSecure(string $cmd=''): string
|
||||
{
|
||||
return Crypt::encryptString($this->getDn());
|
||||
return Crypt::encryptString(($cmd ? sprintf('*%s|',$cmd) : '').$this->getDn());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -265,8 +270,12 @@ class Entry extends Model
|
||||
*/
|
||||
public function getObject(string $key): Attribute|null
|
||||
{
|
||||
return $this->objects
|
||||
->get($this->normalizeAttributeKey($key));
|
||||
return match ($key) {
|
||||
'rdn' => $this->getRDNObject(),
|
||||
|
||||
default => $this->objects
|
||||
->get($this->normalizeAttributeKey($key))
|
||||
};
|
||||
}
|
||||
|
||||
public function getObjects(): Collection
|
||||
@ -289,6 +298,16 @@ class Entry extends Model
|
||||
->filter(fn($a)=>(! $this->getVisibleAttributes()->contains(fn($b)=>($a->name === $b->name))));
|
||||
}
|
||||
|
||||
private function getRDNObject(): Attribute\RDN
|
||||
{
|
||||
$o = new Attribute\RDN('dn',['']);
|
||||
// @todo for an existing object, return the base.
|
||||
$o->setBase($this->rdnbase);
|
||||
$o->setAttributes($this->getAvailableAttributes()->filter(fn($item)=>$item->required));
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return this list of user attributes
|
||||
*
|
||||
@ -413,4 +432,12 @@ class Entry extends Model
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setRDNBase(string $bdn): void
|
||||
{
|
||||
if ($this->exists)
|
||||
throw new InvalidUsage('Cannot set RDN base on existing entries');
|
||||
|
||||
$this->rdnbase = $bdn;
|
||||
}
|
||||
}
|
27
app/Rules/DNExists.php
Normal file
27
app/Rules/DNExists.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Rules;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
|
||||
class DNExists implements ValidationRule
|
||||
{
|
||||
/**
|
||||
* Run the validation rule.
|
||||
*
|
||||
* @param \Closure(string, ?string=): \Illuminate\Translation\PotentiallyTranslatedString $fail
|
||||
*/
|
||||
public function validate(string $attribute,mixed $value,Closure $fail): void
|
||||
{
|
||||
$dn = Crypt::decryptString($value);
|
||||
|
||||
// Sometimes our key has a command, so we'll ignore it
|
||||
if (str_starts_with($dn,'*') && ($x=strpos($dn,'|')))
|
||||
$dn = substr($dn,$x+1);
|
||||
|
||||
if (! config('server')->fetch($dn))
|
||||
$fail(sprintf('The DN %s doesnt exist.',$dn));
|
||||
}
|
||||
}
|
23
app/Rules/HasStructuralObjectClass.php
Normal file
23
app/Rules/HasStructuralObjectClass.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Rules;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
|
||||
class HasStructuralObjectClass implements ValidationRule
|
||||
{
|
||||
/**
|
||||
* Run the validation rule.
|
||||
*
|
||||
* @param \Closure(string, ?string=): \Illuminate\Translation\PotentiallyTranslatedString $fail
|
||||
*/
|
||||
public function validate(string $attribute,mixed $value,Closure $fail): void
|
||||
{
|
||||
foreach ($value as $item)
|
||||
if ($item && config('server')->schema('objectclasses',$item)->isStructural())
|
||||
return;
|
||||
|
||||
$fail('There isnt a Structural Objectclass.');
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
use App\Rules\HasStructuralObjectClass;
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
@ -119,8 +121,10 @@ return [
|
||||
'validation' => [
|
||||
'objectclass' => [
|
||||
'objectclass'=>[
|
||||
'required',
|
||||
'array',
|
||||
'min:1'
|
||||
'min:1',
|
||||
new HasStructuralObjectClass,
|
||||
]
|
||||
],
|
||||
'gidnumber' => [
|
||||
@ -170,4 +174,4 @@ return [
|
||||
]
|
||||
],
|
||||
],
|
||||
];
|
||||
];
|
@ -1,14 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* This script provides a convienent method to call the proper common.php
|
||||
*
|
||||
* @package phpLDAPadmin
|
||||
*/
|
||||
|
||||
/**
|
||||
*/
|
||||
|
||||
if (! defined('LIBDIR'))
|
||||
define('LIBDIR',sprintf('%s/',realpath('../lib/')));
|
||||
require_once LIBDIR.'common.php';
|
||||
?>
|
@ -1,103 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Creates a new object in LDAP.
|
||||
*
|
||||
* @package phpLDAPadmin
|
||||
* @subpackage Page
|
||||
*/
|
||||
|
||||
/**
|
||||
*/
|
||||
|
||||
require './common.php';
|
||||
|
||||
# If cancel was selected, we'll redirect
|
||||
if (get_request('cancel','REQUEST')) {
|
||||
header('Location: index.php');
|
||||
die();
|
||||
}
|
||||
|
||||
$request = array();
|
||||
$request['redirect'] = get_request('redirect','POST',false,false);
|
||||
|
||||
$request['page'] = new PageRender($app['server']->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('<meta http-equiv="refresh" content="0; url=%s" />',$redirect_url);
|
||||
|
||||
if ($action_number == 1 || $action_number == 2) {
|
||||
$create_message = sprintf('%s %s: <b>%s</b> %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: <b>%s</b> %s: <b>%s</b>',
|
||||
_('Server'),$app['server']->getName(),_('Distinguished Name'),$request['template']->getDN()));
|
||||
|
||||
echo '<br />';
|
||||
echo '<center>';
|
||||
printf('<a href="cmd.php?%s&dn=%s">%s</a>.',
|
||||
htmlspecialchars($href),rawurlencode($request['template']->getDN()),_('Display the new created entry'));
|
||||
echo '<br />';
|
||||
printf('<a href="cmd.php?%s&container=%s">%s</a>.',
|
||||
htmlspecialchars($href),rawurlencode($request['template']->getContainer()),_('Create another entry'));
|
||||
echo '</center>';
|
||||
}
|
||||
}
|
||||
?>
|
@ -1,142 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Creates a new object in LDAP.
|
||||
*
|
||||
* @package phpLDAPadmin
|
||||
* @subpackage Page
|
||||
*/
|
||||
|
||||
/**
|
||||
*/
|
||||
|
||||
require './common.php';
|
||||
|
||||
$request = array();
|
||||
$request['redirect'] = get_request('redirect','POST',false,false);
|
||||
|
||||
$request['page'] = new PageRender($app['server']->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: <b>%s</b> %s: <b>%s</b>',
|
||||
_('Server'),$app['server']->getName(),_('Container'),$request['template']->getContainer()));
|
||||
|
||||
# Confirm the creation
|
||||
if (count($request['template']->getLDAPadd(true))) {
|
||||
echo '<div style="text-align: center;">';
|
||||
echo _('Do you want to create this entry?');
|
||||
echo '<br /><br />';
|
||||
echo '</div>';
|
||||
|
||||
echo "\n\n";
|
||||
echo '<form action="cmd.php" method="post" id="create_form">';
|
||||
echo '<div>';
|
||||
echo '<input type="hidden" name="cmd" value="create" />';
|
||||
printf('<input type="hidden" name="server_id" value="%s" />',$app['server']->getIndex());
|
||||
printf('<input type="hidden" name="container" value="%s" />',$request['template']->getContainerEncode(false));
|
||||
printf('<input type="hidden" name="template" value="%s" />',$request['template']->getID());
|
||||
foreach ($request['template']->getRDNAttrs() as $rdn)
|
||||
printf('<input type="hidden" name="rdn_attribute[]" value="%s" />',htmlspecialchars($rdn));
|
||||
echo "\n";
|
||||
|
||||
$request['page']->drawHiddenAttributes();
|
||||
echo '</div>';
|
||||
|
||||
echo '<table class="result_table" style="margin-left: auto; margin-right: auto;">';
|
||||
echo "\n";
|
||||
|
||||
printf('<tr class="heading"><td>%s</td><td>%s</td><td>%s</td></tr>',
|
||||
_('Attribute'),_('New Value'),_('Skip'));
|
||||
echo "\n\n";
|
||||
|
||||
$counter = 0;
|
||||
printf('<tr class="%s"><td colspan="3" style="text-align: center;"><b>%s</b></td></tr>',$counter%2 ? 'even' : 'odd',htmlspecialchars($request['template']->getDN()));
|
||||
|
||||
foreach ($request['template']->getLDAPadd(true) as $attribute) {
|
||||
$counter++;
|
||||
|
||||
printf('<tr class="%s">',$counter%2 ? 'even' : 'odd');
|
||||
printf('<td><b>%s</b></td>',$attribute->getFriendlyName());
|
||||
|
||||
# Show NEW Values
|
||||
echo '<td><span style="white-space: nowrap;">';
|
||||
$request['page']->draw('CurrentValues',$attribute);
|
||||
echo '</span></td>';
|
||||
|
||||
# Show SKIP Option
|
||||
$input_disabled = '';
|
||||
$input_onclick = '';
|
||||
|
||||
if ($attribute->isRequired())
|
||||
$input_disabled = 'disabled="disabled"';
|
||||
|
||||
printf('<td><input name="skip_array[%s]" id="skip_array_%s" type="checkbox" %s %s/></td>',
|
||||
htmlspecialchars($attribute->getName()),htmlspecialchars($attribute->getName()),$input_disabled,$input_onclick);
|
||||
echo '</tr>';
|
||||
echo "\n\n";
|
||||
}
|
||||
|
||||
echo '</table>';
|
||||
|
||||
echo '<div style="text-align: center;">';
|
||||
echo '<br />';
|
||||
|
||||
printf('<input type="submit" value="%s" %s/>',
|
||||
_('Commit'),
|
||||
(isAjaxEnabled() ? sprintf('onclick="return ajSUBMIT(\'BODY\',document.getElementById(\'create_form\'),\'%s\');"',_('Updating Object')) : ''));
|
||||
|
||||
printf('<input type="submit" name="cancel" value="%s" %s/>',
|
||||
_('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 '</div>';
|
||||
echo '</form>';
|
||||
echo '<br />';
|
||||
|
||||
} else {
|
||||
$href = sprintf('cmd=template_engine&server_id=%s&dn=%s',
|
||||
$app['server']->getIndex(),$request['template']->getDNEncode());
|
||||
|
||||
echo '<div style="text-align: center;">';
|
||||
echo _('You made no changes');
|
||||
|
||||
if (isAjaxEnabled())
|
||||
printf(' <a href="cmd.php?%s" onclick="return ajDISPLAY(\'BODY\',\'%s\',\'%s\');">%s</a>.',
|
||||
htmlspecialchars($href),htmlspecialchars($href),_('Retrieving DN'),_('Go back'));
|
||||
else
|
||||
printf(' <a href="cmd.php?%s">%s</a>.',htmlspecialchars($href),_('Go back'));
|
||||
|
||||
echo '</div>';
|
||||
}
|
||||
?>
|
@ -1,88 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Check the password used by an entry.
|
||||
*
|
||||
* @package phpLDAPadmin
|
||||
* @subpackage Page
|
||||
*/
|
||||
|
||||
/**
|
||||
*/
|
||||
|
||||
require './common.php';
|
||||
|
||||
$www['page'] = new page();
|
||||
|
||||
$request = array();
|
||||
$request['componentid'] = get_request('componentid','REQUEST');
|
||||
$request['hash'] = get_request('hash','REQUEST');
|
||||
$request['password'] = get_request('check_password','REQUEST');
|
||||
$request['action'] = get_request('action','REQUEST');
|
||||
$request['attribute'] = get_request('attr','REQUEST');
|
||||
|
||||
if (get_request('base64','REQUEST')) {
|
||||
$request['hash'] = base64_decode($request['hash']);
|
||||
$request['password'] = base64_decode($request['password']);
|
||||
}
|
||||
|
||||
$request['enc_type'] = get_enc_type($request['hash']);
|
||||
|
||||
printf('<h3 class="subtitle">%s</h3>',_('Password Checker Tool'));
|
||||
|
||||
echo '<form action="password_checker.php" method="post">';
|
||||
echo '<input type="hidden" name="action" value="compare" />';
|
||||
printf('<input type="hidden" name="attr" value="%s" />',$request['attribute']);
|
||||
|
||||
echo '<table class="forminput" width="100%" border="0">';
|
||||
|
||||
echo '<tr>';
|
||||
printf('<td class="heading">%s</td>',_('Compare'));
|
||||
printf('<td><input type="%s" name="hash" id="hash" value="%s" /></td>',
|
||||
(obfuscate_password_display($request['enc_type']) ? 'password' : 'text'),htmlspecialchars($request['hash']));
|
||||
echo '</tr>';
|
||||
|
||||
echo '<tr>';
|
||||
printf('<td class="heading">%s</td>',_('To'));
|
||||
printf('<td><input type="password" name="check_password" value="%s" /></td>',
|
||||
htmlspecialchars($request['password']));
|
||||
echo '</tr>';
|
||||
|
||||
echo '<tr>';
|
||||
echo '<td> </td>';
|
||||
|
||||
echo '<td><input type="submit" value="Compare" />';
|
||||
|
||||
if ($request['action'] == 'compare') {
|
||||
echo ' <b>';
|
||||
|
||||
if (password_check($request['hash'],$request['password'],$request['attribute']))
|
||||
printf('<span class="good">%s</span>',_('Passwords match!'));
|
||||
else
|
||||
printf('<span class="bad">%s</span>',_('Passwords do not match!'));
|
||||
|
||||
echo '</b>';
|
||||
}
|
||||
|
||||
echo '</td>';
|
||||
echo '</tr>';
|
||||
echo '</table>';
|
||||
echo '</form>';
|
||||
|
||||
# Pull our password from the form that opened this window.
|
||||
if ($request['componentid']) {
|
||||
echo '<script type="text/javascript">';
|
||||
printf('var c = window.opener.document.getElementById("%s");',$request['componentid']);
|
||||
printf('var h = document.getElementById("%s");','hash');
|
||||
echo 'if (c && h) { h.value = c.value; }';
|
||||
echo '</script>';
|
||||
}
|
||||
|
||||
# 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));
|
||||
?>
|
735
lib/ds.php
735
lib/ds.php
@ -1,735 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Classes and functions for communication of Data Stores
|
||||
*
|
||||
* @author The phpLDAPadmin development team
|
||||
* @package phpLDAPadmin
|
||||
*/
|
||||
|
||||
/**
|
||||
* This abstract class provides the basic variables and methods.
|
||||
*
|
||||
* @package phpLDAPadmin
|
||||
* @subpackage DataStore
|
||||
*/
|
||||
abstract class DS {
|
||||
# ID of this db.
|
||||
protected $index;
|
||||
|
||||
# Configuration paramters.
|
||||
protected $default;
|
||||
protected $custom;
|
||||
protected $type;
|
||||
|
||||
abstract function __construct($index);
|
||||
|
||||
/**
|
||||
* This will make the connection to the datasource
|
||||
*/
|
||||
abstract protected function connect($method,$debug=false);
|
||||
|
||||
/**
|
||||
* Login to the datastore
|
||||
* method: default = anon, connect to ds using bind_id not auth_id.
|
||||
* method: 'user', connect with auth_id
|
||||
* method: '<freetext>', 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: <b>%s</b> hasnt been configured for auth_type <b>%s</b>',__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 "<PRE>";
|
||||
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;
|
||||
}
|
||||
}
|
||||
?>
|
1581
lib/ds_ldap.php
1581
lib/ds_ldap.php
File diff suppressed because it is too large
Load Diff
@ -1,677 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Classes and functions for communication of Data Stores
|
||||
*
|
||||
* @author The phpLDAPadmin development team
|
||||
* @package phpLDAPadmin
|
||||
*/
|
||||
|
||||
/**
|
||||
* This abstract class provides variables and methods for LDAP datastores for use by PLA.
|
||||
*
|
||||
* @package phpLDAPadmin
|
||||
* @subpackage DataStore
|
||||
*/
|
||||
class ldap_pla extends ldap {
|
||||
function __construct($index) {
|
||||
parent::__construct($index);
|
||||
|
||||
$this->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.
|
||||
* <code>
|
||||
* $servers->setValue('appearance','show_create',true|false);
|
||||
* </code>
|
||||
* 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.
|
||||
* <code>
|
||||
* $config->custom->commands['script'] = array('create' => true);
|
||||
* </code>
|
||||
*
|
||||
* @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
|
||||
*
|
||||
* <code>
|
||||
* $servers->setValue('login','anon_bind',true|false);
|
||||
* </code>
|
||||
*
|
||||
* @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:
|
||||
* <code>
|
||||
* $servers->setValue('server','branch_rename',true|false);
|
||||
* </code>
|
||||
*
|
||||
* @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:
|
||||
* <code>
|
||||
* if ($ldapserver->isMultiLineAttr('postalAddress'))
|
||||
* echo '<textarea name="postalAddress"></textarea>';
|
||||
* else
|
||||
* echo '<input name="postalAddress" type="text">';
|
||||
* </code>
|
||||
*
|
||||
* @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:
|
||||
* <code>
|
||||
* $config->custom->appearance['readonly_attrs'] = array('objectClass');
|
||||
* </code>
|
||||
*
|
||||
* @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:
|
||||
* <code>
|
||||
* $config->custom->appearance['hide_attrs'] = array('objectClass');
|
||||
* </code>
|
||||
*
|
||||
* @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 (<b>%s</b>)',_('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 (<b>%s</b>)',_('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 (<b>%s</b>)',_('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:
|
||||
* <code>
|
||||
* $servers->setValue('unique','attrs',array('mail','uid','uidNumber'));
|
||||
* </code>
|
||||
*
|
||||
* @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 (<b>%s</b>)',_('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 (<b><a href="%s">%s</a></b>)',
|
||||
_('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);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
2520
lib/functions.php
2520
lib/functions.php
File diff suppressed because it is too large
Load Diff
7
public/css/custom.css
vendored
7
public/css/custom.css
vendored
@ -7,9 +7,12 @@ img.jpegphoto {
|
||||
/** ensure our userpassword has select is next to the password input */
|
||||
div#userPassword .select2-container--bootstrap-5 .select2-selection {
|
||||
font-size: inherit;
|
||||
border-bottom-right-radius: unset;
|
||||
border-top-right-radius: unset;
|
||||
width: 9em;
|
||||
border: #444054 1px solid;
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.input-group:first-child .select2-container--bootstrap-5 .select2-selection {
|
||||
border-bottom-right-radius: unset;
|
||||
border-top-right-radius: unset;
|
||||
}
|
4
public/css/fixes.css
vendored
4
public/css/fixes.css
vendored
@ -303,4 +303,8 @@ div#objectClass .input-group-delete {
|
||||
bottom: 30px;
|
||||
right: 10px;
|
||||
height: 5px;
|
||||
}
|
||||
|
||||
.input-group-text {
|
||||
background-color: #fafafa;
|
||||
}
|
27
public/js/custom.js
vendored
27
public/js/custom.js
vendored
@ -13,32 +13,41 @@ function expandChildren(node) {
|
||||
|
||||
function getNode(item) {
|
||||
$.ajax({
|
||||
url: '/dn',
|
||||
url: '/frame',
|
||||
method: 'POST',
|
||||
data: { key: item },
|
||||
dataType: 'html',
|
||||
beforeSend: function() {
|
||||
content = $('.main-content').contents();
|
||||
$('.main-content').empty().append('<div class="fa-3x"><i class="fas fa-spinner fa-pulse"></i></div>');
|
||||
content = $('.main-content')
|
||||
.contents();
|
||||
|
||||
$('.main-content')
|
||||
.empty()
|
||||
.append('<div class="fa-3x"><i class="fas fa-spinner fa-pulse"></i></div>');
|
||||
}
|
||||
|
||||
}).done(function(html) {
|
||||
$('.main-content').empty().append(html);
|
||||
$('.main-content')
|
||||
.empty()
|
||||
.append(html);
|
||||
|
||||
}).fail(function(item) {
|
||||
switch(item.status) {
|
||||
}).fail(function(e) {
|
||||
switch(e.status) {
|
||||
case 404:
|
||||
$('.main-content').empty().append(item.responseText);
|
||||
$('.main-content').empty().append(e.responseText);
|
||||
break;
|
||||
case 409:
|
||||
location.replace('/#'+item);
|
||||
break;
|
||||
case 419:
|
||||
alert('Session has expired, reloading the page and try again...');
|
||||
location.reload();
|
||||
break;
|
||||
case 500:
|
||||
$('.main-content').empty().append(item.responseText);
|
||||
$('.main-content').empty().append(e.responseText);
|
||||
break;
|
||||
default:
|
||||
alert(item.status+': Well that didnt work?');
|
||||
alert('Well that didnt work? Code ['+e.status+']');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<html translate="no">
|
||||
@section('htmlheader')
|
||||
@include('architect::layouts.partials.htmlheader')
|
||||
@show
|
||||
|
64
resources/views/components/attribute/rdn.blade.php
Normal file
64
resources/views/components/attribute/rdn.blade.php
Normal file
@ -0,0 +1,64 @@
|
||||
<!-- $o=RDN::class -->
|
||||
<x-attribute.layout :edit="$edit ?? FALSE" :new="$new ?? FALSE" :o="$o">
|
||||
@foreach($o->values as $value)
|
||||
@if($edit)
|
||||
<div class="input-group has-validation mb-3">
|
||||
<select class="form-select @error('rdn')is-invalid @enderror" id="rdn" name="rdn">
|
||||
<option value=""></option>
|
||||
|
||||
@foreach($o->attrs->map(fn($item)=>['id'=>$item,'value'=>$item]) as $option)
|
||||
@continue(! Arr::get($option,'value'))
|
||||
<option value="{{ Arr::get($option,'id') }}" @selected(Arr::get($option,'id') == old('rdn',$value ?? ''))>{{ Arr::get($option,'value') }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
<span class="input-group-text">=</span>
|
||||
<input type="text" @class(['form-control','is-invalid'=>$errors->get('rdn_value')]) id="rdn_value" name="rdn_value" value="{{ old('rdn_value') }}" placeholder="rdn">
|
||||
<label class="input-group-text" for="inputGroupSelect02">,{{ $o->base }}</label>
|
||||
|
||||
<div class="invalid-feedback pb-2">
|
||||
@error('rdn')
|
||||
{{ $message }}
|
||||
@enderror
|
||||
@error('rdn_value')
|
||||
{{ $message }}
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
{{ $value }}
|
||||
@endif
|
||||
@endforeach
|
||||
</x-attribute.layout>
|
||||
|
||||
@section('page-scripts')
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
var rdn_value_set = null;
|
||||
var rdn_attr = null;
|
||||
|
||||
function set_rdn_value() {
|
||||
if (rdn_attr && rdn_value_set)
|
||||
$('#'+rdn_attr).find('input').val($('input#rdn_value').val());
|
||||
}
|
||||
|
||||
$('select#rdn').on('change',function() {
|
||||
// if rdn_attr is already set (and its now different), remove read only and clear value
|
||||
if (rdn_attr)
|
||||
$('#'+rdn_attr).find('input').attr('readonly',false).val('');
|
||||
|
||||
// set RDN attribute read-only
|
||||
if (rdn_attr = $(this).val())
|
||||
$('#'+rdn_attr).find('input').attr('readonly',true).val('');
|
||||
|
||||
set_rdn_value();
|
||||
})
|
||||
|
||||
$('input#rdn_value').on('change',function() {
|
||||
rdn_value_set = $(this).val();
|
||||
|
||||
set_rdn_value();
|
||||
})
|
||||
});
|
||||
</script>
|
||||
@endsection
|
@ -46,12 +46,15 @@
|
||||
if (! rendered)
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
// @todo When this is opened a second time, the data is appended.
|
||||
cache: false,
|
||||
url: '{{ url('entry/objectclass/add') }}',
|
||||
data: {
|
||||
oc: oc,
|
||||
},
|
||||
success: function(data) {
|
||||
$('select#newoc').select2({
|
||||
dropdownParent: $('#new_objectclass-modal'),
|
||||
theme: 'bootstrap-5',
|
||||
allowClear: true,
|
||||
multiple: true,
|
||||
data: data,
|
||||
});
|
||||
@ -60,8 +63,6 @@
|
||||
if (e.status != 412)
|
||||
alert('That didnt work? Please try again....');
|
||||
},
|
||||
url: '{{ url('entry/objectclass/add') }}/'+dn,
|
||||
cache: false
|
||||
});
|
||||
|
||||
rendered = true;
|
||||
|
@ -15,7 +15,7 @@
|
||||
{{ $slot }}
|
||||
@isset($name)
|
||||
<span class="invalid-feedback">
|
||||
@error((! empty($old)) ? $old : $name)
|
||||
@error((! empty($old)) ? $old : ($id ?? $name))
|
||||
{{ $message }}
|
||||
@elseif(isset($feedback))
|
||||
{{ $feedback }}
|
||||
|
@ -2,7 +2,7 @@
|
||||
@isset($name)
|
||||
<input type="hidden" id="{{ $id ?? $name }}_disabled" name="{{ $name }}" value="" disabled>
|
||||
@endisset
|
||||
<select class="form-select @isset($name)@error((! empty($old)) ? $old : $name) is-invalid @enderror @endisset" id="{{ $id ?? $name }}" @isset($name)name="{{ $name }}"@endisset @required(isset($required) && $required) @disabled(isset($disabled) && $disabled)>
|
||||
<select class="form-select @isset($name)@error((! empty($old)) ? $old : ($id ?? $name)) is-invalid @enderror @endisset" id="{{ $id ?? $name }}" @isset($name)name="{{ $name }}"@endisset @required(isset($required) && $required) @disabled(isset($disabled) && $disabled)>
|
||||
@if((empty($value) && ! empty($options)) || isset($addnew) || isset($choose))
|
||||
<option value=""></option>
|
||||
@isset($addnew)
|
||||
@ -54,10 +54,24 @@
|
||||
width: 'style',
|
||||
allowClear: {{ $allowclear ?? 'false' }},
|
||||
placeholder: '{{ $placeholder ?? '' }}',
|
||||
multiple: {{ $multiple ?? 'false' }},
|
||||
@isset($addvalues)
|
||||
tags: true,
|
||||
@endisset
|
||||
});
|
||||
|
||||
@if(isset($multiple) && (! $multiple))
|
||||
$('#{{ $id ?? $name }}').val(' ');
|
||||
$('#{{ $id ?? $name }}').trigger('change');
|
||||
@endif
|
||||
|
||||
@isset($options)
|
||||
@if($options->count() === 1)
|
||||
$('#{{ $id ?? $name }}')
|
||||
.val('{{ $options->first()['id'] }}')
|
||||
.trigger("change")
|
||||
@endif
|
||||
@endisset
|
||||
});
|
||||
</script>
|
||||
@append
|
22
resources/views/fragment/dn/add_attr.blade.php
Normal file
22
resources/views/fragment/dn/add_attr.blade.php
Normal file
@ -0,0 +1,22 @@
|
||||
<div id="newattrs"></div>
|
||||
|
||||
<!-- Add new attributes -->
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-1 col-md-2"></div>
|
||||
<div class="col-12 col-sm-10 col-md-8">
|
||||
<div class="d-none" id="newattr-select">
|
||||
<div class="row">
|
||||
<div class="col-12 bg-dark text-light p-2">
|
||||
<i class="fas fa-plus-circle"></i> Add New Attribute
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 pt-2">
|
||||
<x-form.select id="newattr" label="Select from..." :options="$o->getMissingAttributes()->sortBy('name')->map(fn($item)=>['id'=>$item->name,'value'=>$item->name_lc])"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2"></div>
|
||||
</div>
|
@ -3,7 +3,7 @@
|
||||
<td class="{{ ($x=$o->getObject('jpegphoto')) ? 'border' : '' }}" rowspan="2">
|
||||
{!! $x ? $x->render(FALSE,TRUE) : sprintf('<div class="page-title-icon f32"><i class="%s"></i></div>',$o->icon() ?? "fas fa-info") !!}
|
||||
</td>
|
||||
<td class="text-end align-text-top p-0 {{ $x ? 'ps-5' : 'pt-2' }}"><strong>{{ $dn }}</strong></td>
|
||||
<td class="text-end align-text-top p-0 {{ $x ? 'ps-5' : 'pt-2' }}"><strong>{{ $o->getDn() }}</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="line-height-1" style="font-size: 55%;vertical-align: bottom;" colspan="2">
|
||||
|
128
resources/views/frames/create.blade.php
Normal file
128
resources/views/frames/create.blade.php
Normal file
@ -0,0 +1,128 @@
|
||||
@extends('layouts.dn')
|
||||
|
||||
@section('page_title')
|
||||
@include('fragment.dn.header',['o'=>($oo=config('server')->fetch(old('container',$container)))])
|
||||
@endsection
|
||||
|
||||
@section('main-content')
|
||||
<div class="row">
|
||||
<p class="alert alert-danger text-center">
|
||||
This is a tech preview of what is to come, and it is by no means complete.
|
||||
</p>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="offset-1 col-10">
|
||||
<div class="main-card mb-3 card">
|
||||
|
||||
<div class="card-header">
|
||||
@lang('Create New Entry') - @lang('Step') {{ $step }}
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<form id="dn-create" method="POST" class="needs-validation" action="{{ url((int)$step === 2 ? 'entry/create' : 'entry/add') }}" enctype="multipart/form-data" novalidate>
|
||||
@csrf
|
||||
|
||||
<input type="hidden" name="key" value="{{ Crypt::encryptString('*create|'.$container) }}">
|
||||
@if($step < 2)
|
||||
<input type="hidden" name="step" value="{{ $step }}">
|
||||
@endif
|
||||
|
||||
@switch($step)
|
||||
@case(1)
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-6">
|
||||
<x-form.select
|
||||
id="objectclass"
|
||||
name="objectclass[]"
|
||||
:label="__('Select a Structural ObjectClass...')"
|
||||
:options="($oc=config('server')->schema('objectclasses'))
|
||||
->filter(fn($item)=>$item->isStructural())
|
||||
->sortBy(fn($item)=>$item->name_lc)
|
||||
->map(fn($item)=>['id'=>$item->name,'value'=>$item->name])"
|
||||
multiple="false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@break
|
||||
|
||||
@case(2)
|
||||
<x-attribute-type :edit="true" :o="$o->getObject('rdn')"/>
|
||||
|
||||
@foreach ($o->getVisibleAttributes() as $ao)
|
||||
<x-attribute-type :edit="true" :o="$ao"/>
|
||||
@endforeach
|
||||
|
||||
@include('fragment.dn.add_attr')
|
||||
|
||||
@break;
|
||||
@endswitch
|
||||
</form>
|
||||
|
||||
<div class="row d-none pt-3">
|
||||
<div class="col-12 {{ $step > 1 ? 'offset-sm-2' : '' }} col-sm-4 col-lg-2">
|
||||
<x-form.reset form="dn-create"/>
|
||||
<x-form.submit action="Next" form="dn-create"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('page-scripts')
|
||||
<script type="text/javascript">
|
||||
var oc = {!! $oo->getObject('objectclass')->values !!};
|
||||
|
||||
function editmode() {
|
||||
// Find all input items and turn off readonly
|
||||
$('input.form-control').each(function() {
|
||||
// Except for objectClass - @todo show an "X" instead
|
||||
if ($(this)[0].name.match(/^objectclass/))
|
||||
return;
|
||||
|
||||
$(this).attr('readonly',false);
|
||||
});
|
||||
|
||||
// Our password type
|
||||
$('div#userPassword .form-select').each(function() {
|
||||
$(this).prop('disabled',false);
|
||||
})
|
||||
|
||||
$('.row.d-none').removeClass('d-none');
|
||||
$('.addable.d-none').removeClass('d-none');
|
||||
$('.deletable.d-none').removeClass('d-none');
|
||||
$('#newattr-select.d-none').removeClass('d-none');
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$('#newattr').on('change',function(item) {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
beforeSend: function() {},
|
||||
success: function(data) {
|
||||
$('#newattrs').append(data);
|
||||
},
|
||||
error: function(e) {
|
||||
if (e.status != 412)
|
||||
alert('That didnt work? Please try again....');
|
||||
},
|
||||
url: '{{ url('entry/attr/add') }}/'+item.target.value,
|
||||
data: {
|
||||
objectclasses: oc,
|
||||
},
|
||||
cache: false
|
||||
});
|
||||
|
||||
// Remove the option from the list
|
||||
$(this).find('[value="'+item.target.value+'"]').remove()
|
||||
|
||||
// If there are no more options
|
||||
if ($(this).find("option").length === 1)
|
||||
$('#newattr-select').remove();
|
||||
});
|
||||
|
||||
editmode();
|
||||
});
|
||||
</script>
|
||||
@append
|
@ -1,7 +1,7 @@
|
||||
@extends('layouts.dn')
|
||||
|
||||
@section('page_title')
|
||||
@include('fragment.dn.header')
|
||||
@include('fragment.dn.header',['o'=>($o=config('server')->fetch($dn))])
|
||||
@endsection
|
||||
|
||||
@section('main-content')
|
||||
@ -9,8 +9,6 @@
|
||||
<x-updated/>
|
||||
<x-error/>
|
||||
|
||||
<!-- @todo If we are redirected here, check old() and add back any attributes that were in the original submission -->
|
||||
|
||||
<div class="main-card mb-3 card">
|
||||
<div class="card-body">
|
||||
<div class="card-header-tabs">
|
||||
@ -34,31 +32,7 @@
|
||||
<x-attribute-type :edit="true" :o="$ao"/>
|
||||
@endforeach
|
||||
|
||||
<div id="newattrs"></div>
|
||||
|
||||
<!-- Add new attributes -->
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-1 col-md-2"></div>
|
||||
<div class="col-12 col-sm-10 col-md-8">
|
||||
<div class="d-none" id="newattr-select">
|
||||
|
||||
@if($o->getMissingAttributes()->count())
|
||||
<div class="row">
|
||||
<div class="col-12 bg-dark text-light p-2">
|
||||
<i class="fas fa-plus-circle"></i> Add New Attribute
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 pt-2">
|
||||
<x-form.select id="newattr" label="Select from..." :options="$o->getMissingAttributes()->sortBy('name')->map(fn($item)=>['id'=>$item->name,'value'=>$item->name_lc])"/>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2"></div>
|
||||
</div>
|
||||
@include('fragment.dn.add_attr')
|
||||
</form>
|
||||
|
||||
<div class="row d-none pt-3">
|
||||
|
@ -15,7 +15,7 @@
|
||||
<div class="main-card mb-3 card">
|
||||
<form id="import-form" action="{{ url('import/process/ldif') }}" method="POST" enctype="multipart/form-data">
|
||||
@csrf
|
||||
<input type="hidden" name="frame" value="import">
|
||||
<input type="hidden" name="key" value="{{ Crypt::encryptString('*import|_NOP') }}">
|
||||
|
||||
<div class="card-header">
|
||||
@lang('LDIF Import')
|
||||
|
@ -1,10 +1,11 @@
|
||||
@use(App\Classes\LDAP\Server)
|
||||
@extends('layouts.dn')
|
||||
|
||||
@section('page_title')
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td style="border-radius: 5px;"><div class="page-title-icon f32"><i class="fas fa-fingerprint"></i></div></td>
|
||||
<td class="top text-end align-text-top p-0 pt-2"><strong>{{ \App\Classes\LDAP\Server::schemaDN() }}</strong></td>
|
||||
<td class="top text-end align-text-top p-0 pt-2"><strong>{{ Server::schemaDN() }}</strong></td>
|
||||
</tr>
|
||||
</table>
|
||||
@endsection
|
||||
|
@ -17,7 +17,7 @@
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-4">
|
||||
<h3 class="d-inline-block d-sm-none">phpLDAPadmin</h3>
|
||||
<img src="{{ url('/images/logo.png') }}" class="logo-image col-12" alt="PLA Logo">
|
||||
<img src="{{ url('images/logo.png') }}" class="logo-image col-12" alt="PLA Logo">
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-sm-8">
|
||||
@ -48,14 +48,23 @@
|
||||
var subpage = window.location.hash;
|
||||
|
||||
$(document).ready(function() {
|
||||
// Enable navigating to a page via a URL fragment, and that fragment is defined with a server-icon
|
||||
var valid = Object.values($('.server-icon > a').map(function(item) {
|
||||
return $(this).attr('id');
|
||||
})).indexOf(subpage.substring(1));
|
||||
if (subpage) {
|
||||
// Enable navigating to a page via a URL fragment, and that fragment is defined with a server-icon
|
||||
var valid = Object.values($('.server-icon > a').map(function() {
|
||||
return $(this).attr('id');
|
||||
})).indexOf(subpage.substring(1));
|
||||
|
||||
if (valid !== -1 && subpage) {
|
||||
// The click() event wont have been registered yet, so we need to delay us clicking it
|
||||
setTimeout(function() { $(subpage).click(); },250);
|
||||
if (valid !== -1) {
|
||||
// @todo this condition can probably be removed
|
||||
console.log('teleporting...:'+subpage.substring(1));
|
||||
// The click() event wont have been registered yet, so we need to delay us clicking it
|
||||
setTimeout(function() { $(subpage).click(); },250);
|
||||
|
||||
} else if (valid === -1) {
|
||||
// Clear the hash
|
||||
history.replaceState(null,null,' ');
|
||||
getNode(subpage.substring(1));
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
@ -32,8 +32,8 @@ Route::controller(HomeController::class)->group(function() {
|
||||
Route::middleware(AllowAnonymous::class)->group(function() {
|
||||
Route::get('/','home');
|
||||
Route::get('info','info');
|
||||
Route::post('dn','dn_frame');
|
||||
Route::get('debug','debug');
|
||||
Route::post('frame','frame');
|
||||
Route::get('import','import_frame');
|
||||
Route::get('schema','schema_frame');
|
||||
|
||||
@ -41,10 +41,12 @@ Route::controller(HomeController::class)->group(function() {
|
||||
Route::get('image','user_image');
|
||||
});
|
||||
|
||||
Route::match(['get','post'],'entry/add','entry_add');
|
||||
Route::post('entry/create','entry_create');
|
||||
Route::get('entry/export/{id}','entry_export');
|
||||
Route::post('entry/password/check/','entry_password_check');
|
||||
Route::post('entry/attr/add/{id}','entry_attr_add');
|
||||
Route::post('entry/objectclass/add/{id}','entry_objectclass_add');
|
||||
Route::post('entry/objectclass/add','entry_objectclass_add');
|
||||
Route::post('entry/update/commit','entry_update');
|
||||
Route::post('entry/update/pending','entry_pending_update');
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user