%s:%s ', time(), __METHOD__);
}
if (DEBUGTMP||DEBUGTMPSUB)
{
printf('* %s [Visit-Start:%s] ', __METHOD__, get_class($this));
}
$tree = get_cached_item($this->server_id,'tree');
if (! $tree)
{
$tree = Tree::getInstance($this->server_id);
}
$treeitem = $tree->getEntry($this->dn);
# If we have a DN, and no template_id, see if the tree has one from last time
if ($this->dn && is_null($this->template_id) && $treeitem && $treeitem->getTemplate())
{
$this->template_id = $treeitem->getTemplate();
}
# Check that we have a valid template, or present a selection
# @todo change this so that the modification templates rendered are the ones for the objectclass of the dn.
if (! $this->template_id)
{
$this->template_id = $this->getTemplateChoice();
}
if ($treeitem)
{
$treeitem->setTemplate($this->template_id);
}
$this->page = get_request('page','REQUEST',false,1);
if ($this->template_id AND $this->template_id != 'invalid') {
if (! $this->template)
{
parent::accept();
}
$this->url_base = sprintf('server_id=%s&dn=%s',
$this->getServerID(),$this->template->getDNEncode());
$this->layout['hint'] = sprintf('
';
# If we dont want to render this template automatically, we'll return here.
if ($norender)
{
return;
}
$this->visitStart();
foreach ($this->template->getAttributes(true) as $attribute) {
# Evaluate our defaults
if ($attribute->getAutoValue())
{
$this->get('Default', $attribute,
$this->template->getContainer() ?: $this->getServer()->getContainerPath($this->template->getDN()),
'autovalue');
}
# If this is the default template, we should mark all our attributes to show().
if (($this->template->getID() == 'none') && (! $attribute->isInternal())
&& (($this->template->getContext() == 'edit' && $this->template->getID() == 'none')
|| ($this->template->getContext() == 'create' && $attribute->getName() != 'objectclass')))
{
$attribute->show();
}
}
if (DEBUGTMP||DEBUGTMPSUB)
{
printf('* %s [Visit-End:%s] ', __METHOD__, get_class($this));
}
$this->visitEnd();
}
}
protected function getDefaultAttribute($attribute,$container,$type) {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
{
debug_log('Entered (%%)', 129, 0, __FILE__, __LINE__, __METHOD__, $fargs);
}
switch ($type) {
case 'autovalue':
$autovalue = $attribute->getAutoValue();
break;
case 'helpervalue':
$autovalue = $attribute->getHelperValue();
break;
default:
system_message(array(
'title'=>_('Unknown Default Attribute context'),
'body'=>sprintf('%s (%s)',_('A call was made to getDefaultAttribute() with an unkown context'),$type),
'type'=>'warn'));
return;
}
$args = explode(';',$autovalue['args']);
$server = $this->getServer();
$vals = '';
switch ($autovalue['function']) {
/**
* Function enables normal PHP functions to be called to evaluate a value.
* eg: =php.Function(date;dmY)
*
* All arguments will be passed to the function, and its value returned.
* If this used used in a POST context, the attribute values can be used as arguments.
*
* Mandatory Arguments:
* * arg 0
* - php Function to call
*
* Additional arguments will be passed to the function.
*/
case 'Function':
$function = array_shift($args);
if (count($args) && count($args) > 1) {
system_message(array(
'title'=>_('Too many arguments'),
'body'=>sprintf('%s (%s)',_('Function() only takes two arguments and more than two were specified'),count($args)),
'type'=>'warn'));
return;
}
$function_args = explode(',',$args[0]);
if (function_exists($function))
{
$vals = call_user_func_array($function, $function_args);
}
else
{
system_message(array(
'title' => _('Function doesnt exist'),
'body' => sprintf('%s (%s)', _('An attempt was made to call a function that doesnt exist'), $function),
'type' => 'warn'));
}
break;
/**
* GetNextNumber will query the LDAP server and calculate the next number based on the query
* eg:
*
* Mandatory Arguments:
* * arg 0
* - "$" => 'auto_number','search_base' in config file
* - "/",".",".." => get container parent as usual
*
* * arg 1
* - attribute to query for
*
* Optional Arguments:
* * arg 2 (pool mechanism only)
* - "true" increments attribute by 1
* - "false" do nothing
*
* * arg 3 (pool mechanism only)
* - ldap filter (must match one entry only in container)
*
* * arg 4
* - calculus on number, eg:
* - *2,+1000 => number = (2*number) + 1000
*
* * arg 5
* - Min number
*/
case 'GetNextNumber':
# If the attribute already has values, we'll return
if ($type == 'autovalue' && $attribute->getValues())
{
return;
}
if ($args[0] == '$')
{
$args[0] = $server->getValue($this->server_id, 'auto_number', 'search_base');
}
$container = $server->getContainerPath($container,$args[0]);
$vals = get_next_number($container,$args[1],
(! empty($args[2]) && ($args[2] == 'false')) ? false : true,
(! empty($args[3])) ? $args[3] : false,
(! empty($args[5])) ? $args[5] : null);
# Operate calculus on next number.
if (! empty($args[4])) {
$mod = explode(',',$args[4]);
$next_number = $vals;
foreach ($mod as $calc) {
$operand = $calc{0};
$operator = substr ($calc,1);
switch ($operand) {
case '*':
$next_number *= $operator;
break;
case '+':
$next_number += $operator;
break;
case '-':
$next_number -= $operator;
break;
case '/':
$next_number /= $operator;
break;
}
}
$vals = $next_number;
}
break;
/**
* PickList will query the LDAP server and provide a select list of values
* MultiList will query the LDAP server and provide a multi select list of values
* eg:
*
* eg: cn=root,nobody => cn=nobody;gidNumber;10)]]>
*
* Mandatory Arguments:
* * arg 0
* - container, to query from current position
* - "/",".",".." => get container parent as usual
*
* * arg 1
* - LDAP filter. May include '%attr%', it will be expanded.
*
* * arg2
* - list attribute key
*
* Optional Arguments:
* * arg3
* - select display (plus modifier /C: Capitalize)
* - replaced by %arg 2% if not given
*
* * arg 4
* - the value furnished in output - must be attribute id. replaced by arg 2 if not given
*
* * arg 5
* - container override
*
* * arg 6
* - csv list (, separator) of added values. syntax: key => display_attribute=value, key...
*
* * arg 7
* - csv list (, separator) of sort attributes (less to more important)
*
* * arg 8 (for MultiList)
* - size of displayed list (default: 10 lines)
*/
case 'MultiList':
case 'PickList':
# arg5 overrides our container
if (empty($args[5]))
{
$container = $server->getContainerPath($container, $args[0]);
}
else
{
$container = $args[5];
}
# Process filter (arg 1), eventually replace %attr% by it's value set in a previous page.
preg_match_all('/%(\w+)(\|.+)?(\/[lUC])?%/U',$args[1],$filtermatchall);
//print_r($matchall); // -1 = highlevel match, 1 = attr, 2 = subst, 3 = mod
if (isset($_REQUEST['form'])) {
$formvalues = array_change_key_case($_REQUEST['form']);
foreach ($filtermatchall[1] as $arg) {
$value = $formvalues[strtolower($arg)];
$args[1] = preg_replace("/%($arg)(\|.+)?(\/[lU])?%/U",$value,$args[1]);
}
}
if (empty($args[3]))
{
$args[3] = "%{$args[2]}%";
}
preg_match_all('/%(\w+)(\|.+)?(\/[lUC])?%/U',$args[3],$matchall);
//print_r($matchall); // -1 = highlevel match, 1 = attr, 2 = subst, 3 = mod
$attrs = array_unique(array_merge($matchall[1],array($args[2])));
# arg7 is sort attributes
if (isset($args[7])) {
$sort_attrs = explode(',',$args[7]);
$attrs = array_unique(array_merge($attrs,$sort_attrs));
}
$picklistvalues = return_ldap_hash($container,$args[1],$args[2],$attrs,(isset($args[7]) && ($args[7])) ? $sort_attrs : false);
# arg6 is a set of fixed values to add to search result
if (isset($args[6])) {
$fixedvalues = explode(',',$args[6]);
foreach ($fixedvalues as $fixedvalue) {
if (empty($fixedvalue))
{
continue;
}
$fixedvalue = preg_split('/=\>/',$fixedvalue);
$displayvalue = explode('=',$fixedvalue[1]);
$newvalue[trim($fixedvalue[0])] = array($args[2]=>trim($fixedvalue[0]),trim($displayvalue[0])=>trim($displayvalue[1]));
$picklistvalues = array_merge($picklistvalues,$newvalue);
}
}
$vals = array();
foreach ($picklistvalues as $key => $values) {
$display = $args[3];
foreach ($matchall[1] as $key => $arg) {
if (isset($values[$arg]))
{
$disp_val = $values[$arg];
}
else
{
$disp_val = '';
}
if (is_array($disp_val))
{
$disp_val = $disp_val[0];
}
if ($matchall[3][$key])
{
switch ($matchall[3][$key])
{
case '/l':
# lowercase
if (function_exists('mb_convert_case'))
{
$disp_val = mb_convert_case($disp_val, MB_CASE_LOWER, 'utf-8');
} else
{
$disp_val = strtolower($disp_val);
}
break;
case '/U':
# uppercase
if (function_exists('mb_convert_case'))
{
$disp_val = mb_convert_case($disp_val, MB_CASE_UPPER, 'utf-8');
} else
{
$disp_val = strtoupper($disp_val);
}
break;
case '/C':
# capitalize
if (function_exists('mb_convert_case'))
{
$disp_val = mb_convert_case($disp_val, MB_CASE_TITLE, 'utf-8');
} else
{
$disp_val = ucfirst($disp_val);
}
break;
default:
break;
}
}
# make value a substring of
preg_match_all('/^\|([0-9]*)-([0-9]*)$/',trim($matchall[2][$key]),$substrarray);
if ((isset($substrarray[1][0]) && $substrarray[1][0]) || (isset($substrarray[2][0]) && $substrarray[2][0])) {
$begin = $substrarray[1][0] ? $substrarray[1][0] : '0';
$end = $substrarray[2][0] ? $substrarray[2][0] : strlen($disp_val);
if (function_exists('mb_substr'))
{
$disp_val = mb_substr($disp_val, $begin, $end, 'utf-8');
}
else
{
$disp_val = substr($disp_val, $begin, $end);
}
}
$display = preg_replace("/%($arg)(\|.+)?(\/[lUC])?%/U",$disp_val,$display);
}
if (! isset($picklist[$values[$args[2]]])) {
$vals[$values[$args[2]]] = $display;
$picklist[$values[$args[2]]] = true;
}
}
break;
/**
* PasswordEncryptionTypes will return a list of our support password encryption types
* eg: =php.PasswordEncryptionTypes()
*
* This function doesnt use any arguments
*/
case 'PasswordEncryptionTypes':
$vals = password_types();
break;
/**
* RandomPassword will create a random password for the value.
* eg: =php.RandomPassword()
*
* When calling the attribute Javascript it will generate a random password.
*
* This function doesnt use any arguments
*/
case 'RandomPassword':
break;
}
switch ($type) {
case 'autovalue':
if (! is_array($vals))
{
$attribute->autoValue(array($vals));
}
else
{
$attribute->autoValue($vals);
}
break;
case 'helpervalue':
return $vals;
}
}
/**
* Set the mode of the TemplateRender
* Applicable modes are "create" or "edit"
*/
protected function getMode() {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
{
debug_log('Entered (%%)', 129, 0, __FILE__, __LINE__, __METHOD__, $fargs);
}
if ($this->dn)
{
return 'modification';
}
elseif ($this->container)
{
return 'creation';
}
elseif (get_request('create_base'))
{
return 'creation';
}
else
{
debug_dump_backtrace(sprintf('Unknown mode for %s', __METHOD__), 1);
}
}
/**
* Return the container for this mode
*/
protected function getModeContainer() {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
{
debug_log('Entered (%%)', 129, 0, __FILE__, __LINE__, __METHOD__, $fargs);
}
switch ($this->getMode()) {
case 'creation':
return $this->container;
break;
case 'modification':
return $this->dn;
break;
default:
return null;
}
}
/**
* Is the default template enabled?
*/
protected function haveDefaultTemplate() {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
{
debug_log('Entered (%%)', 129, 0, __FILE__, __LINE__, __METHOD__, $fargs);
}
if ($_SESSION[APPCONFIG]->getValue('appearance','disable_default_template'))
{
return FALSE;
}
else
{
return TRUE;
}
}
/**
* Present a list of available templates for creating and editing LDAP entries
*/
protected function drawTemplateChoice() {
if (DEBUGTMP)
{
printf('%s ', __METHOD__);
}
$this->drawTitle();
$this->drawSubTitle();
echo "\n";
switch ($this->getMode()) {
case 'creation':
$msg = _('Select a template for the creation process');
break;
case 'modification':
$msg = _('Select a template to edit the entry');
break;
}
$avail_templates = $this->getTemplates();
$templates = $avail_templates->getTemplates($this->getMode(),$this->getModeContainer());
printf('
%s
',$msg);
$href_parms = array_to_query_string($_GET,array('meth'));
printf('';
}
/** VISIT METHODS **/
/**
* This function will setup our template object (read LDAP for current values, read $_REQUEST for new values, etc)
* so that it can be rendered.
*/
private function visitStart() {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
{
debug_log('Entered (%%)', 129, 0, __FILE__, __LINE__, __METHOD__, $fargs);
}
if (DEBUGTMP)
{
printf('%s ', __METHOD__);
}
# If we have a DN, then we are an editing template
if ($this->dn)
{
$this->template->setDN($this->dn);
}
# Else if we have a container, we are a creating template
elseif ($this->container || get_request('create_base'))
{
$this->template->setContainer($this->container);
}
else
{
debug_dump_backtrace('Dont know what type of template we are - no DN or CONTAINER?', 1);
}
# Header
$this->drawHeader();
}
private function visitEnd() {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
{
debug_log('Entered (%%)', 129, 0, __FILE__, __LINE__, __METHOD__, $fargs);
}
if (DEBUGTMP)
{
printf('%s ', __METHOD__);
}
foreach ($this->template->getAttributesShown() as $attribute)
{
if ($attribute->getPage() > $this->pagelast)
{
$this->pagelast = $attribute->getPage();
}
}
echo "\n\n";
if ($this->template->getContext() == 'create') {
$this->drawStepTitle($this->page);
$this->drawStepFormStart($this->page);
$this->drawStepForm($this->page);
$this->drawStepFormEnd();
} elseif ($this->template->getContext() == 'copyasnew') {
$this->drawStepFormStart($this->page);
printf('',$this->template->getContainer(false));
echo '
';
}
/**
* Object Class Chooser
*/
protected function drawObjectClassChooser() {
if (DEBUGTMP)
{
printf('%s ', __METHOD__);
}
$socs = $this->getServer()->SchemaObjectClasses();
if (! $socs)
{
$socs = array();
}
echo '
';
printf('
%s
',_('ObjectClasses'));
echo '
';
echo '
';
echo '
';
if ($_SESSION[APPCONFIG]->getValue('appearance','show_hints')) {
printf('
',IMGDIR);
echo _('Hint: You must choose exactly one structural objectClass (shown in bold above)');
echo '
';
}
}
/** INTERNAL ATTRIBUTES **/
protected function drawInternalAttributes() {
if ($this->template->getAttributesInternal())
{
foreach ($this->template->getAttributesInternal() as $attribute)
{
$this->draw('Internal', $attribute);
}
}
else
{
printf('
(%s)
', _('No internal attributes'));
}
echo "\n";
}
protected function drawInternalAttribute($attribute) {
if (DEBUGTMP)
{
printf('%s ', __METHOD__);
}
$this->draw('Template',$attribute);
}
/** FORM METHODS **/
public function drawFormStart() {
echo '';
# Javascript
$this->drawJavascript();
# For debugging, show the template object.
if (! $_SESSION[APPCONFIG]->getValue('appearance','hide_debug_info') && get_request('debug','GET')) {
echo "\n\n";
printf('',IMGDIR);
echo '
';
echo '';
echo '
';
}
}
public function drawFormSubmitButton() {
if (DEBUGTMP)
{
printf('%s ', __METHOD__);
}
if (! $this->template->isReadOnly())
// @todo cant use AJAX here, it affects file uploads.
{
printf('
',
_('Update Object'));
}
}
/** STEP FORM METHODS *
* @param $page
*/
private function drawStepTitle($page) {
if (DEBUGTMP)
{
printf('%s ', __METHOD__);
}
if (DEBUGTMP||DEBUGTMPSUB)
{
printf('* %s [templateNAME:%s] ', __METHOD__, $this->template->getName());
}
# The default template needs to ask the user for objectClasses.
if ($this->template->isType('default')) {
# The default template only uses 2 pages
$this->pagelast = 2;
echo '
';
printf('%s: ',sprintf(_('Step %s of %s'),$page,$this->pagelast));
if ($page == 1)
{
echo _('Container and ObjectClass(es)');
}
else
{
echo _('Specify attributes and values');
}
echo '