1<?php
2/**
3 * @author The phpLDAPadmin development team
4 * @package phpLDAPadmin
5 */
6
7/**
8 * PageRender class
9 *
10 * @package phpLDAPadmin
11 * @subpackage Templates
12 */
13class PageRender extends Visitor {
14	# Template ID
15	protected $template_id;
16	protected $template = null;
17	# Object Variables
18	protected $dn;
19	protected $container;
20	# Page number
21	protected $page;
22
23	public function __construct($server_id,$template_id) {
24		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
25			debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs);
26
27		$this->server_id = $server_id;
28		$this->template_id = $template_id;
29	}
30
31	/**
32	 * Dummy method...
33	 */
34	protected function visitAttribute() {}
35
36	/**
37	 * Get our templates applicable for this object
38	 */
39	protected function getTemplates() {
40		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
41			debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs);
42
43		return new Templates($this->server_id);
44	}
45
46	public function getTemplate() {
47		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
48			debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs);
49
50		return $this->template;
51	}
52
53	public function getTemplateID() {
54		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
55			debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs);
56
57		return $this->template->getID();
58	}
59
60	/**
61	 * Initialise the PageRender
62	 */
63	public function accept() {
64		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
65			debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs);
66
67		if (DEBUGTMP) printf('<font size=-2>%s:%s</font><br />',time(),__METHOD__);
68
69		if ($this->template_id) {
70			$templates = $this->getTemplates();
71			$this->template = $templates->getTemplate($this->template_id);
72
73			if ($this->dn)
74				$this->template->setDN($this->dn);
75			elseif ($this->container)
76				$this->template->setContainer($this->container);
77
78			$this->template->accept();
79
80			# Process our <post> actions
81			if (get_request('post_value','REQUEST'))
82				foreach (get_request('post_value','REQUEST') as $attr => $values) {
83					$attribute = $this->template->getAttribute($attr);
84
85					if (! $attribute)
86						debug_dump_backtrace(sprintf('There was a post_value for an attribute [%s], but it doesnt exist?',$attr),1);
87
88					foreach ($values as $index)
89						if ($attribute->getPostValue())
90							$this->get('Post',$attribute,$index);
91						else
92							$this->get('AutoPost',$attribute,$index);
93				}
94
95			foreach ($this->template->getAttributes(true) as $attribute) {
96				if (DEBUGTMP||DEBUGTMPSUB) printf('<font size=-2>* %s [Accept:%s]</font><br />',__METHOD__,get_class($attribute));
97
98				$this->visit('',$attribute);
99			}
100
101			// Sort our attribute values for display, if we are the custom template.
102			if ($this->template->getID() == 'none')
103				$this->template->sort();
104		}
105	}
106
107	public function drawTitle($title='Title') {
108		printf('<h3 class="title">%s</h3>',$title);
109	}
110
111	public function drawSubTitle($subtitle=null) {
112		if (is_null($subtitle))
113			$subtitle = sprintf('%s: <b>%s</b>&nbsp;&nbsp;&nbsp;%s: <b>%s</b>',
114				_('Server'),$this->getServer()->getName(),_('Distinguished Name'),$this->dn);
115
116		printf('<h3 class="subtitle">%s</h3>',$subtitle);
117	}
118
119	public function setDN($dn) {
120		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
121			debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs);
122
123		if ($this->container)
124			system_message(array(
125				'title'=>__METHOD__,
126				'body'=>'CONTAINER set while setting DN',
127				'type'=>'info'));
128
129		$this->dn = $dn;
130	}
131
132	public function setContainer($dn) {
133		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
134			debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs);
135
136		if ($this->dn)
137			system_message(array(
138				'title'=>__METHOD__,
139				'body'=>'DN set while setting CONTAINER',
140				'type'=>'info'));
141
142		$this->container = $dn;
143	}
144
145	/**
146	 * May be overloaded in other classes
147	 */
148	protected function getMode() {}
149	protected function getModeContainer() {}
150
151	/**
152	 * Process our <post> arguments from the templates
153	 */
154	protected function getPostAttribute($attribute,$i) {
155		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
156			debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs);
157
158		$autovalue = $attribute->getPostValue();
159		$args = explode(';',$autovalue['args']);
160		$server = $this->getServer();
161		$vals = $attribute->getValues();
162
163		switch ($autovalue['function']) {
164			/**
165			 * Join will concatenate values with a string, similiar to explode()
166			 * eg: =php.Join(-;%sambaSID%,%sidsuffix%)
167			 *
168			 * * arg 0
169			 *   - character to use when joining the attributes
170			 *
171			 * * arg 1
172			 *   - values to concatenate together. we'll explode %attr% values.
173			 */
174			case 'Join':
175				preg_match_all('/%(\w+)(\|.+)?(\/[lU])?%/U',$args[1],$matchall);
176				$matchattrs = $matchall[1];
177				$char = $args[0];
178
179				$values = array();
180				$blank = 0;
181				foreach ($matchattrs as $joinattr) {
182						$attribute2 = $this->template->getAttribute($joinattr);
183
184						if (! $attribute2) {
185							if (($pv = get_request(strtolower($joinattr),'REQUEST')) && isset($pv[$attribute->getName()][$i])) {
186								array_push($values,$pv[$attribute->getName()][$i]);
187
188								if (! $pv[$attribute->getName()][$i])
189									$blank++;
190
191							} else {
192								array_push($values,'');
193								$blank++;
194							}
195
196						} elseif (count($attribute2->getValues()) == 0) {
197							return;
198
199						} elseif (count($attribute2->getValues()) != 1) {
200							array_push($values,'');
201							$blank++;
202
203							system_message(array(
204								'title'=>_('Invalid value count for [post] processing'),
205								'body'=>sprintf('%s (<b>%s [%s]</b>)',_('Function() variable expansion can only handle 1 value'),
206									$attribute->getName(false),count($attribute->getValues())),
207								'type'=>'warn'));
208
209						} else
210							array_push($values,$attribute2->getValue(0));
211				}
212
213				# If all our value expansion results in blanks, we'll return no value
214				if (count($matchattrs) == $blank)
215					if (count($vals) > 1)
216						$vals[$i] = null;
217					else
218						$vals = null;
219
220				else
221					$vals[$i] = implode($char,$values);
222
223				break;
224
225			/**
226			 * PasswordEncrypt will encrypt a password
227			 * eg: =php.PasswordEncrypt(%enc%;%userPassword%)
228			 *
229			 * This function will encrypt the users password "userPassword" using the "enc" method.
230			 */
231			case 'PasswordEncrypt':
232				if (count($args) != 2) {
233					system_message(array(
234						'title'=>_('Invalid argument count for PasswordEncrypt'),
235						'body'=>sprintf('%s (<b>%s</b>)',_('PasswordEncrypt() only accepts two arguments'),$autovalue['args']),
236						'type'=>'warn'));
237
238					return;
239				}
240
241				if (! $attribute->hasBeenModified())
242					return;
243
244				# Get the attribute.
245				if (preg_match_all('/%(\w+)(\|.+)?(\/[lU])?%/U',strtolower($args[1]),$matchall)) {
246					if (count($matchall[1]) != 1)
247						system_message(array(
248							'title'=>_('Invalid value count for PasswordEncrypt'),
249							'body'=>sprintf('%s (<b>%s</b>)',_('Unable to get the attribute value for PasswordEncrypt()'),count($matchall[1])),
250							'type'=>'warn'));
251
252					$passwordattr = $matchall[1][0];
253					$passwordvalue = $_REQUEST['new_values'][$passwordattr][$i];
254
255				} else
256					$passwordvalue = $args[1];
257
258				if (! trim($passwordvalue) || in_array($passwordvalue,$attribute->getOldValues()))
259					return;
260
261				# Get the encoding
262				if ($passwordattr && preg_match_all('/%(\w+)(\|.+)?(\/[lU])?%/U',strtolower($args[0]),$matchall)) {
263					if (count($matchall[1]) != 1)
264						system_message(array(
265							'title'=>_('Invalid value count for PasswordEncrypt'),
266							'body'=>sprintf('%s (<b>%s</b>)',_('Unable to get the attribute value for PasswordEncrypt()'),count($matchall[1])),
267							'type'=>'warn'));
268
269					$enc = $_REQUEST[$matchall[1][0]][$passwordattr][$i];
270
271				} else
272					$enc = $args[0];
273
274				$enc = strtolower($enc);
275
276				switch ($enc) {
277					case 'lm':
278						$sambapassword = new smbHash;
279						$vals[$i] = $sambapassword->lmhash($passwordvalue);
280
281						break;
282
283					case 'nt':
284						$sambapassword = new smbHash;
285						$vals[$i] = $sambapassword->nthash($passwordvalue);
286
287						break;
288
289					default:
290						$vals[$i] = pla_password_hash($passwordvalue,$enc);
291				}
292
293				$vals = array_unique($vals);
294
295				break;
296
297			default:
298				$vals = $this->get('AutoPost',$attribute,$i);
299		}
300
301		if (! $vals || $vals == $attribute->getValues())
302			return;
303
304		$attribute->clearValue();
305
306		if (! is_array($vals))
307			$attribute->setValue(array($vals));
308		else
309			$attribute->setValue($vals);
310	}
311
312	/**
313	 * This function is invoked if we dont know which template we should be using.
314	 *
315	 * @return string Template ID to be used or null if the user was presented with a list.
316	 */
317	protected function getTemplateChoice() {
318		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
319			debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs);
320
321		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
322
323		# First work out our template
324		$templates = $this->getTemplates();
325		$template = $templates->getTemplate($this->template_id);
326
327		# If the template we asked for is available
328		if ($this->template_id === $template->getID()) {
329			if (DEBUGTMP) printf('<font size=-2>%s:<u>%s</u></font><br />',__METHOD__,'Choosing the SELECTED template');
330
331			return $this->template_id;
332
333		# If there are no defined templates
334		} elseif (count($templates->getTemplates($this->getMode(),$this->getModeContainer(),false)) <= 0) {
335			if (DEBUGTMP) printf('<font size=-2>%s:<u>%s</u></font><br />',__METHOD__,'Choosing the DEFAULT template, no other template applicable');
336
337			# Since getTemplate() returns a default template if the one we want doesnt exist, we can return $templates->getID(), it should be the default.
338			if ($_SESSION[APPCONFIG]->getValue('appearance','disable_default_template') AND $this->getMode() == 'creation') {
339
340				system_message(array(
341					'title'=>_('No available templates'),
342					'body'=>_('There are no available active templates for this container.'),
343					'type'=>'warn'));
344
345				return 'invalid';
346
347			} else
348				return $template->getID();
349
350		# If there is only 1 defined template, and no default available, then that is our template.
351		} elseif ((count($templates->getTemplates($this->getMode(),$this->getModeContainer(),true)) == 1) && ! $this->haveDefaultTemplate()) {
352			if (DEBUGTMP) printf('<font size=-2>%s:<u>%s</u></font><br />',__METHOD__,'AUTOMATIC choosing a template, only 1 template applicable');
353
354			$template = $templates->getTemplates($this->getMode(),$this->getModeContainer(),true);
355			$template = array_shift($template);
356
357			# Dont render the only available template if it is invalid.
358			if (! $template->isInvalid())
359				return $template->getID();
360			else
361				$this->drawTemplateChoice();
362
363		} else {
364			if (DEBUGTMP) printf('<font size=-2>%s:<u>%s</u></font><br />',__METHOD__,'SELECT a template to use.');
365
366			# Propose the template choice
367			$this->drawTemplateChoice();
368		}
369
370		# If we got here, then there wasnt a template.
371		return null;
372	}
373
374	/** DRAW ATTRIBUTE NAME **/
375
376	final protected function drawNameAttribute($attribute) {
377		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
378
379		$href = sprintf('cmd.php?cmd=schema&server_id=%s&view=attributes&viewvalue=%s',
380			$this->getServerID(),$attribute->getName());
381
382		if (! $_SESSION[APPCONFIG]->getValue('appearance','show_schema_link') || !$_SESSION[APPCONFIG]->isCommandAvailable('script','schema'))
383			printf('%s',_($attribute->getFriendlyName()));
384
385		elseif ($attribute->getLDAPtype())
386			printf('<a href="%s" title="%s: %s">%s</a>',
387				htmlspecialchars($href),
388				_('Click to view the schema definition for attribute type'),$attribute->getName(false),_($attribute->getFriendlyName()));
389		else
390			printf('<acronym title="%s">%s</acronym>',_('This attribute is not defined in the LDAP schema'),_($attribute->getFriendlyName()));
391
392		if (DEBUGTMPSUB) printf(' <small>[%s]</small>',get_class($attribute));
393	}
394
395	/** ATTRIBUTE NOTES */
396
397	protected function drawNotesAttribute($attribute) {
398		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
399
400		$attr_note = '';
401
402		foreach (array('NoteAlias','NoteRequired','NoteRDN','NoteHint','NoteRO') as $note) {
403			$alias_note = $this->get($note,$attribute);
404
405			if ($alias_note) {
406				if (trim($attr_note))
407					$attr_note .= ', ';
408
409				$attr_note .= $alias_note;
410			}
411		}
412
413		if ($attr_note)
414			printf('<sup><small>%s</small></sup>',$attr_note);
415	}
416
417	protected function getNoteAliasAttribute($attribute) {
418		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
419			debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs);
420
421		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
422
423		# Is there a user-friendly translation available for this attribute?
424		$friendly_name = $attribute->getFriendlyName();
425
426		if (strtolower($friendly_name) != $attribute->getName())
427			return sprintf('<acronym title="%s: \'%s\' %s \'%s\'">%s</acronym>',
428				_('Note'),$friendly_name,_('is an alias for'),$attribute->getName(false),_('alias'));
429		else
430			return '';
431	}
432
433	#@todo this function shouldnt re-calculate requiredness, it should be known in the template already - need to set the ldaptype when initiating the attribute.
434	protected function getNoteRequiredAttribute($attribute) {
435		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
436			debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs);
437
438		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
439
440		$required_by = '';
441		$sattr_required = '';
442
443		# Is this attribute required by an objectClass ?
444		$sattr = $this->getServer()->getSchemaAttribute($attribute->getName());
445		if ($sattr)
446			$sattr_required = $sattr->getRequiredByObjectClasses();
447
448		if ($sattr_required) {
449			$oc = $this->template->getAttribute('objectclass');
450
451			if ($oc)
452				foreach ($oc->getValues() as $objectclass) {
453					# If this objectclass is in our required list
454					if (in_array_ignore_case($objectclass,$sattr_required)) {
455						$required_by .= sprintf('%s ',$objectclass);
456						continue;
457					}
458
459					# If not, see if it is in our parent.
460					$sattr = $this->getServer()->getSchemaObjectClass($objectclass);
461
462					if (array_intersect($sattr->getParents(),$sattr_required))
463						$required_by .= sprintf('%s ',$objectclass);
464				}
465
466			else
467				debug_dump_backtrace('How can there be no objectclasses?',1);
468		}
469
470		if ($required_by)
471			return sprintf('<acronym title="%s %s">%s</acronym>',_('Required attribute for objectClass(es)'),$required_by,_('required'));
472		else
473			return '';
474	}
475
476	protected function getNoteRDNAttribute($attribute) {
477		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
478			debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs);
479
480		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
481
482		# Is this attribute required because its the RDN
483		if ($attribute->isRDN())
484			return sprintf('<acronym title="%s">rdn</acronym>',_('This attribute is required for the RDN.'));
485		else
486			return '';
487	}
488
489	protected function getNoteHintAttribute($attribute) {
490		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
491			debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs);
492
493		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
494
495		# Is there a hint for this attribute
496		if ($attribute->getHint())
497			return sprintf('<acronym title="%s">%s</acronym>',_($attribute->getHint()),_('hint'));
498		else
499			return '';
500	}
501
502	protected function getNoteROAttribute($attribute) {
503		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
504			debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs);
505
506		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
507
508		# Is this attribute is readonly
509		if ($attribute->isReadOnly())
510			return sprintf('<acronym title="%s">ro</acronym>',_('This attribute has been marked as Read Only.'));
511		else
512			return '';
513	}
514	/** DRAW HIDDEN VALUES **/
515
516	/**
517	 * Draw all hidden attributes
518	 */
519	final public function drawHiddenAttributes() {
520		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
521			debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs);
522
523		foreach ($this->template->getAttributes(true) as $attribute)
524			if ($attribute->hasbeenModified()) {
525				if ($attribute->getValues())
526					foreach ($attribute->getValues() as $index => $details)
527						$this->draw('HiddenValue',$attribute,$index);
528
529				# We are deleting this attribute, so we need to display an empty value
530				else
531					$this->draw('HiddenValue',$attribute,0);
532			}
533	}
534
535	/**
536	 * Draw specific hidden attribute
537	 */
538	final protected function drawHiddenValueAttribute($attribute,$i) {
539		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
540
541		$val = $attribute->getValue($i);
542
543		printf('<input type="hidden" name="new_values[%s][%s]" id="new_values_%s_%s" value="%s" />',
544			htmlspecialchars($attribute->getName()),$i,htmlspecialchars($attribute->getName()),$i,
545			htmlspecialchars($val));
546	}
547
548	/** DRAW DISPLAYED OLD VALUES **/
549	protected function drawOldValuesAttribute($attribute) {
550		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
551
552		foreach ($attribute->getValues() as $index => $details)
553			$this->draw('OldValue',$attribute,$index);
554	}
555
556	final protected function drawOldValueAttribute($attribute,$i) {
557		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
558
559		echo $attribute->getOldValue($i);
560	}
561
562	/** DRAW DISPLAYED CURRENT VALUES **/
563
564	protected function drawCurrentValuesAttribute($attribute) {
565		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
566
567		for ($i=0;$i<$attribute->getValueCount();$i++) {
568			if ($i > 0)
569				echo '<br/>';
570
571			$this->draw('CurrentValue',$attribute,$i);
572		}
573	}
574
575	/**
576	 * Draw the current specific value of an attribute
577	 */
578	final protected function drawCurrentValueAttribute($attribute,$i) {
579		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
580		if (DEBUGTMPSUB) printf(' <small>[%s]</small>',__METHOD__);
581
582		echo htmlspecialchars($attribute->getValue($i));
583	}
584
585	/**
586	 * Draw a input value for an attribute - used in a form.
587	 */
588	protected function drawFormValueAttribute($attribute,$i) {
589		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
590		if (DEBUGTMPSUB) printf(' <small>[%s]</small>',__METHOD__);
591
592		if ($this->getServer()->isReadOnly() || $attribute->isReadOnly()
593			|| ($attribute->isRDN() && $this->template->getType() != 'creation' && $i < count($attribute->getValues())))
594
595			$this->draw('FormReadOnlyValue',$attribute,$i);
596		else
597			$this->draw('FormReadWriteValue',$attribute,$i);
598
599		# Show the ADDVALUE DIV if the attribute can have more values, and we have rendered the last value
600		if ($attribute->haveMoreValues() && $attribute->getValueCount() == $i+1)
601			printf('<div id="ajADDVALUE%s"></div>',$attribute->getName());
602
603		if ($attribute->getPostValue())
604			printf('<input type="hidden" name="post_value[%s][]" value="%s"/>',$attribute->getName(),$i);
605	}
606
607	protected function drawFormReadOnlyValueAttribute($attribute,$i) {
608		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
609
610		$val = $attribute->getValue($i);
611
612		printf('<input type="text" class="roval" name="new_values[%s][%s]" id="new_values_%s_%s" value="%s" readonly="readonly" />',
613			htmlspecialchars($attribute->getName()),$i,htmlspecialchars($attribute->getName()),$i,htmlspecialchars($val));
614	}
615
616	protected function drawFormReadWriteValueAttribute($attribute,$i) {
617		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
618
619		$val = $attribute->getValue($i);
620
621		if ($attribute->getHelper() || $attribute->getVerify())
622			echo '<table cellspacing="0" cellpadding="0" border="0"><tr><td valign="top">';
623
624		printf('<input type="text" class="value" name="new_values[%s][%s]" id="new_values_%s_%s" value="%s" %s%s %s %s/>',
625			htmlspecialchars($attribute->getName()),$i,
626			htmlspecialchars($attribute->getName()),$i,
627			htmlspecialchars($val),
628			$attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '',
629			$attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '',
630			($attribute->getSize() > 0) ? sprintf('size="%s"',$attribute->getSize()) : '',
631			($attribute->getMaxLength() > 0) ? sprintf('maxlength="%s"',$attribute->getMaxLength()) : '');
632
633		if ($attribute->getHelper()) {
634			echo '</td><td valign="top">';
635			$this->draw('AttributeHelper',$attribute,$i);
636			echo '</td></tr>';
637
638		} elseif ($attribute->getVerify())
639			echo '</td></tr>';
640
641		if ($attribute->getVerify()) {
642			printf('<tr><td><input type="text" class="value" name="new_values_verify[%s][%s]" id="new_values_verify_%s_%s" value="" %s %s/>',
643				htmlspecialchars($attribute->getName()),$i,
644				htmlspecialchars($attribute->getName()),$i,
645				($attribute->getSize() > 0) ? sprintf('size="%s"',$attribute->getSize()) : '',
646				($attribute->getMaxLength() > 0) ? sprintf('maxlength="%s"',$attribute->getMaxLength()) : '');
647
648			echo '</td><td valign="top">';
649			printf('(%s)',_('confirm'));
650			echo '</td></tr>';
651		}
652
653		if ($attribute->getHelper() || $attribute->getVerify())
654			echo '</table>';
655	}
656
657	/**
658	 * Draw specific hidden binary attribute
659	 */
660	final protected function drawHiddenValueBinaryAttribute($attribute,$i) {
661		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
662
663		$val = $attribute->getValue($i);
664
665		printf('<input type="hidden" name="new_values[%s][%s]" value="%s" />',
666			htmlspecialchars($attribute->getName()),$i,base64_encode($val));
667	}
668
669	final protected function drawOldValueBinaryAttribute($attribute,$i) {
670		# If we dont have a value, we'll just return;
671		if (! $attribute->getOldValue($i))
672			return;
673
674		printf('<small>[%s]</small>',_('Binary Value'));
675	}
676
677	final protected function drawCurrentValueBinaryAttribute($attribute,$i) {
678		printf('<small>[%s]</small>',_('Binary Value'));
679
680		if (in_array($attribute->getName(),array('objectsid')))
681			printf('<small> (%s)</small>', binSIDtoText($attribute->getValue(0)));
682	}
683
684	protected function drawFormReadOnlyValueBinaryAttribute($attribute,$i) {
685		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
686
687		$this->draw('CurrentValue',$attribute,$i);
688		echo '<br/><br/>';
689
690		$href = sprintf('download_binary_attr.php?server_id=%s&dn=%s&attr=%s&index=%s',
691		$this->getServerID(),rawurlencode($this->template->getDN()),$attribute->getName(),$i);
692
693		printf('<a href="%s"><img src="%s/save.png" alt="Save" /> %s</a>',
694			htmlspecialchars($href),IMGDIR,_('download value'));
695
696		echo '<br/>';
697	}
698
699	protected function drawFormReadWriteValueBinaryAttribute($attribute,$i) {
700		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
701
702		if ($attribute->getValue($i)) {
703			$this->draw('FormReadOnlyValue',$attribute,$i);
704
705			if (! $attribute->isReadOnly() && $_SESSION[APPCONFIG]->isCommandAvailable('script','delete_attr'))
706				printf('<a href="javascript:deleteAttribute(\'%s\',\'%s\',\'%s\');" style="color:red;"><img src="%s/trash.png" alt="Trash" /> %s</a>',
707					$attribute->getName(),$attribute->getFriendlyName(),$i,IMGDIR,_('delete attribute'));
708
709		} else {
710			printf('<input type="file" class="value" name="new_values[%s][%s]" id="new_values_%s_%s" value="" %s%s %s %s/><br />',
711				htmlspecialchars($attribute->getName()),$i,
712				htmlspecialchars($attribute->getName()),$i,
713				$attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '',
714				$attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '',
715				($attribute->getSize() > 0) ? 'size="'.$attribute->getSize().'"' : '',
716				($attribute->getMaxLength() > 0) ? 'maxlength="'.$attribute->getMaxLength().'"' : '');
717		}
718	}
719
720	protected function drawFormReadWriteValueDateAttribute($attribute,$i) {
721		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
722
723		$val = $attribute->getValue($i);
724
725		echo '<span style="white-space: nowrap;">';
726		printf('<input type="text" class="value" id="new_values_%s_%s" name="new_values[%s][%s]" value="%s" %s%s %s %s/>&nbsp;',
727			$attribute->getName(),$i,
728			htmlspecialchars($attribute->getName()),$i,htmlspecialchars($val),
729			$attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '',
730			$attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '',
731			($attribute->getSize() > 0) ? sprintf('size="%s"',$attribute->getSize()) : '',
732			($attribute->getMaxLength() > 0) ? sprintf('maxlength="%s"',$attribute->getMaxLength()) : '');
733
734		$this->draw('SelectorPopup',$attribute,$i);
735		echo '</span>'."\n";
736	}
737
738	protected function drawFormReadWriteValueDnAttribute($attribute,$i) {
739		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
740
741		$val = $attribute->getValue($i);
742
743		if ($attribute->getHelper())
744			echo '<table cellspacing="0" cellpadding="0"><tr><td valign="top">';
745
746		$input_name = sprintf('new_values[%s][%s]',htmlspecialchars($attribute->getName()),$i);
747		$id = sprintf('new_values_%s_%s',htmlspecialchars($attribute->getName()),$i);
748
749		printf('<span style="white-space: nowrap;"><input type="text" class="value" name="%s" id="%s" value="%s" %s%s %s %s/>&nbsp;',
750			$input_name,$id,htmlspecialchars($val),
751			$attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '',
752			$attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '',
753			($attribute->getSize() > 0) ? 'size="'.$attribute->getSize().'"' : '',
754			($attribute->getMaxLength() > 0) ? 'maxlength="'.$attribute->getMaxLength().'"' : '');
755
756		# Draw a link for popping up the entry browser if this is the type of attribute that houses DNs.
757		draw_chooser_link('entry_form',$id,false);
758		echo '</span>';
759
760		if ($attribute->getHelper()) {
761			echo '</td><td valign="top">';
762			$this->draw('Helper',$attribute,$i);
763			echo '</td></tr></table>';
764		}
765
766		echo "\n";
767	}
768
769	protected function drawFormReadWriteValueGidAttribute($attribute,$i) {
770		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
771
772		$this->drawFormReadWriteValueAttribute($attribute,$i);
773
774		$server = $this->getServer();
775		$val = $attribute->getValue($i);
776
777		# If this is a gidNumber on a non-PosixGroup entry, lookup its name and description for convenience
778		if ($this->template->getDN() && ! in_array_ignore_case('posixGroup',$this->getServer()->getDNAttrValue($this->template->getDN(),'objectclass'))) {
779			$query['filter'] = sprintf('(&(objectClass=posixGroup)(gidNumber=%s))',$val);
780			$query['attrs'] = array('dn','description');
781
782			# Reorganise our base, so that our base is first
783			$bases = array_unique(array_merge(array($server->getContainerTop($this->template->getDN())),$server->getBaseDN()));
784
785			# Search our bases, until we find a match.
786			foreach ($bases as $base) {
787				$query['base'] = $base;
788				$group = $this->getServer()->query($query,null);
789
790				if (count($group) > 0) {
791					echo '<br />';
792
793					$group = array_pop($group);
794					$group_dn = $group['dn'];
795					$group_name = explode('=',get_rdn($group_dn));
796					$group_name = $group_name[1];
797					$href = sprintf('cmd.php?cmd=template_engine&server_id=%s&dn=%s',
798						$this->getServerID(),rawurlencode($group_dn));
799
800					echo '<small>';
801					printf('<a href="%s">%s</a>',htmlspecialchars($href),$group_name);
802
803					$description = isset($group['description']) ? $group['description'] : null;
804
805					if (is_array($description))
806						foreach ($description as $item)
807							printf(' (%s)',$item);
808					else
809						printf(' (%s)',$description);
810
811					echo '</small>';
812
813					break;
814				}
815			}
816		}
817	}
818
819	/**
820	 * Draw a Jpeg Attribute
821	 */
822	final protected function drawOldValueJpegAttribute($attribute,$i) {
823		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
824		if (DEBUGTMPSUB) printf(' <small>[%s]</small>',__METHOD__);
825
826		# If we dont have a value, we'll just return;
827		if (! $attribute->getOldValue($i))
828			return;
829
830		draw_jpeg_photo($this->getServer(),$this->template->getDN(),$attribute->getName(),$i,false,false);
831	}
832
833	/**
834	 * Draw a Jpeg Attribute
835	 */
836	final protected function drawCurrentValueJpegAttribute($attribute,$i) {
837		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
838		if (DEBUGTMPSUB) printf(' <small>[%s]</small>',__METHOD__);
839
840		# If we dont have a value, we'll just return;
841		if (! $attribute->getValue($i))
842			return;
843
844		# If the attribute is modified, the new value needs to be stored in a session variable for the draw_jpeg_photo callback.
845		if ($attribute->hasBeenModified()) {
846			$_SESSION['tmp'][$attribute->getName()][$i] = $attribute->getValue($i);
847			draw_jpeg_photo(null,$this->template->getDN(),$attribute->getName(),$i,false,false);
848		} else
849			draw_jpeg_photo($this->getServer(),$this->template->getDN(),$attribute->getName(),$i,false,false);
850	}
851
852	protected function drawFormReadOnlyValueJpegAttribute($attribute,$i) {
853		$this->draw('HiddenValue',$attribute,$i);
854		$_SESSION['tmp'][$attribute->getName()][$i] = $attribute->getValue($i);
855
856		draw_jpeg_photo(null,$this->template->getDN(),$attribute->getName(),$i,false,false);
857	}
858
859	protected function drawFormReadOnlyValueMultiLineAttribute($attribute,$i) {
860		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
861
862		$val = $attribute->getValue($i);
863
864		printf('<textarea class="roval" rows="%s" cols="%s" name="new_values[%s][%s]" id="new_values_%s_%s" readonly="readonly">%s</textarea>',
865			($attribute->getRows() > 0) ? $attribute->getRows() : 5,
866			($attribute->getCols() > 0) ? $attribute->getCols() : 100,
867			htmlspecialchars($attribute->getName()),$i,
868			htmlspecialchars($attribute->getName()),$i,
869			$val);
870	}
871
872	protected function drawFormReadWriteValueMultiLineAttribute($attribute,$i) {
873		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
874
875		$val = $attribute->getValue($i);
876
877		printf('<textarea class="value" rows="%s" cols="%s" name="new_values[%s][%s]" id="new_values_%s_%s" %s%s>%s</textarea>',
878			($attribute->getRows() > 0) ? $attribute->getRows() : 5,
879			($attribute->getCols() > 0) ? $attribute->getCols() : 100,
880			htmlspecialchars($attribute->getName()),$i,
881			htmlspecialchars($attribute->getName()),$i,
882			$attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '',
883			$attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '',
884			$val);
885	}
886
887	protected function drawFormValueObjectClassAttribute($attribute,$i) {
888		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
889
890		$val = $attribute->getValue($i);
891
892		/* It seems that openLDAP allows us to remove additional structural objectclasses
893		   however other LDAP servers, dont remove them (even if we ask them to). */
894		# Do we have our internal attributes.
895		$internal = $this->template->getAttribute('structuralobjectclass');
896
897		if ($internal) {
898			$structural = in_array_ignore_case($val,$internal->getValues());
899
900		# We'll work it out the traditional way.
901		} else {
902			# If this schema structural?
903			$schema_object = ($val) ? $this->getServer()->getSchemaObjectClass($val) : false;
904			$structural = (is_object($schema_object) && $schema_object->getType() == 'structural');
905		}
906
907		if ($structural) {
908			$this->draw('FormReadOnlyValue',$attribute,$i);
909
910			printf(' <small>(<acronym title="%s">%s</acronym>)</small>',
911				_('This is a structural ObjectClass and cannot be removed.'),
912				_('structural'));
913
914		} else
915			$this->draw('FormReadWriteValue',$attribute,$i);
916	}
917
918	protected function getAutoPostPasswordAttribute($attribute,$i) {
919		# If the password is already encoded, then we'll return
920		if (preg_match('/^\{.+\}.+/',$attribute->getValue($i)))
921			return;
922
923		$attribute->setPostValue(array('function'=>'PasswordEncrypt','args'=>sprintf('%%enc%%;%%%s%%',$attribute->getName())));
924		$this->get('Post',$attribute,$i);
925	}
926
927	protected function drawOldValuePasswordAttribute($attribute,$i) {
928		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
929		if (DEBUGTMPSUB) printf(' <small>[%s]</small>',__METHOD__);
930
931		$val = $attribute->getOldValue($i);
932
933		if (obfuscate_password_display(get_enc_type($val)))
934			echo str_repeat('*',16);
935		else
936			echo nl2br(htmlspecialchars($attribute->getOldValue($i)));
937	}
938
939	final protected function drawCurrentValuePasswordAttribute($attribute,$i) {
940		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
941		if (DEBUGTMPSUB) printf(' <small>[%s]</small>',__METHOD__);
942
943		$val = $attribute->getValue($i);
944
945		if (obfuscate_password_display(get_enc_type($val)))
946			echo str_repeat('*',16);
947		else
948			echo nl2br(htmlspecialchars($attribute->getValue($i)));
949	}
950
951	protected function drawFormReadOnlyValuePasswordAttribute($attribute,$i) {
952		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
953
954		$server = $this->getServer();
955		$val = $attribute->getValue($i);
956
957		if (trim($val))
958			$enc_type = get_enc_type($val);
959		else
960			$enc_type = $server->getValue('appearance','pla_password_hash');
961
962		$obfuscate_password = obfuscate_password_display($enc_type);
963
964		printf('<input type="%s" class="roval" name="new_values[%s][%s]" id="new_values_%s_%s" value="%s" %s readonly="readonly" /><br />',
965			($obfuscate_password ? 'password' : 'text'),
966			htmlspecialchars($attribute->getName()),$i,htmlspecialchars($attribute->getName()),
967			$i,htmlspecialchars($val),($attribute->getSize() > 0) ? 'size="'.$attribute->getSize().'"' : '');
968
969		if (trim($val))
970			$this->draw('CheckLink',$attribute,'new_values_'.htmlspecialchars($attribute->getName()).'_'.$i);
971	}
972
973	protected function drawFormReadWriteValuePasswordAttribute($attribute,$i) {
974		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
975
976		$server = $this->getServer();
977		$val = $attribute->getValue($i);
978
979		$enc_type = get_enc_type($val);
980
981		# Set the default hashing type if the password is blank (must be newly created)
982		if (trim($val))
983			$enc_type = get_enc_type($val);
984		else
985			$enc_type = $server->getValue('appearance','pla_password_hash');
986
987		echo '<table cellspacing="0" cellpadding="0"><tr><td valign="top">';
988
989		$obfuscate_password = obfuscate_password_display($enc_type);
990		$id = sprintf('new_values_%s_%s',htmlspecialchars($attribute->getName()),$i);
991
992		printf('<input type="%s" class="value" name="new_values[%s][%s]" id="%s" value="%s" %s%s %s %s/>',
993			($obfuscate_password ? 'password' : 'text'),
994			htmlspecialchars($attribute->getName()),$i,$id,
995			htmlspecialchars($val),
996			$attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '',
997			$attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '',
998			($attribute->getSize() > 0) ? sprintf('size="%s"',$attribute->getSize()) : '',
999			($attribute->getMaxLength() > 0) ? sprintf('maxlength="%s"',$attribute->getMaxLength()) : '');
1000
1001		echo '</td><td valign="top">';
1002
1003		if ($attribute->getHelper())
1004			$this->draw('Helper',$attribute,$i);
1005		else
1006			$this->draw('DefaultHelper',$attribute,$i);
1007
1008		echo '</td></tr><tr><td valign="top">';
1009
1010		if ($attribute->getVerify() && $obfuscate_password) {
1011			printf('<input type="password" class="value" name="new_values_verify[%s][%s]" id="new_values_verify_%s_%s" value="" %s %s/>',
1012				htmlspecialchars($attribute->getName()),$i,
1013				htmlspecialchars($attribute->getName()),$i,
1014				($attribute->getSize() > 0) ? sprintf('size="%s"',$attribute->getSize()) : '',
1015				($attribute->getMaxLength() > 0) ? sprintf('maxlength="%s"',$attribute->getMaxLength()) : '');
1016
1017			echo '</td><td valign="top">';
1018			printf('(%s)',_('confirm'));
1019			echo '</td></tr><tr><td valign="top">';
1020		}
1021
1022		$this->draw('CheckLink',$attribute,$id);
1023		echo '</td></tr></table>';
1024	}
1025
1026	protected function drawFormReadWriteValueSelectionAttribute($attribute,$i) {
1027		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
1028
1029		if ($attribute->isMultiple()) {
1030			# For multiple selection, we draw the component only one time
1031			if ($i > 0)
1032				return;
1033
1034			$selected = array();
1035			$vals = $attribute->getValues();
1036			$j = 0;
1037
1038			if (! $vals && ! is_null($attribute->getDefault()) && ! is_array($vals = $attribute->getDefault()))
1039				$vals = array($attribute->getDefault());
1040
1041			if (($attribute->getSize() > 0) && ($attribute->getSize() < $attribute->getOptionCount())) {
1042
1043				printf('<select name="new_values[%s][]" size="%s" multiple="multiple">',
1044					htmlspecialchars($attribute->getName()),$attribute->getSize());
1045
1046				foreach ($attribute->getSelection() as $value => $description) {
1047					if (in_array($value,$vals))
1048						$selected[$value] = true;
1049
1050					printf('<option id="new_values_%s_%s" value="%s" onmouseDown="focus_%s(this);" onclick="blur_%s(this);" %s>%s</option>',
1051						htmlspecialchars($attribute->getName()),$j++,
1052						$value,htmlspecialchars($attribute->getName()),htmlspecialchars($attribute->getName()),
1053						isset($selected[$value]) ? 'selected="selected"' : '',$description);
1054
1055					echo "\n";
1056				}
1057
1058				foreach ($vals as $val) {
1059					if (! isset($selected[$val]))
1060						printf('<option id="new_values_%s_%s" value="%s" onmousedown="focus_%s(this);" onclick="blur_%s(this);" selected="selected">%s</option>',
1061							htmlspecialchars($attribute->getName()),$j++,
1062							$val,htmlspecialchars($attribute->getName()),
1063							htmlspecialchars($attribute->getName()),$val);
1064
1065					echo "\n";
1066				}
1067
1068				echo '</select>';
1069
1070			} else {
1071				echo '<table cellspacing="0" cellpadding="0" border="0">';
1072
1073				// For checkbox items, we need to render a blank entry, so that we detect an all-unselect situation
1074				printf('<tr><td colspan="2"><input type="hidden" id="new_values_%s_%s" name="new_values[%s][]" value="%s"/></td></tr>',
1075					htmlspecialchars($attribute->getName()),$j++,
1076					htmlspecialchars($attribute->getName()),'');
1077
1078				foreach ($attribute->getSelection() as $value => $description) {
1079					if (in_array($value,$vals))
1080						$selected[$value] = true;
1081
1082					printf('<tr><td><input type="checkbox" id="new_values_%s_%s" name="new_values[%s][]" value="%s" %s%s %s/></td><td><span style="white-space: nowrap;">&nbsp;%s</span></td></tr>',
1083						htmlspecialchars($attribute->getName()),$j++,
1084						htmlspecialchars($attribute->getName()),$value,
1085						$attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '',
1086						$attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '',
1087						isset($selected[$value]) ? 'checked="checked"' : '',
1088						$description);
1089				}
1090
1091				foreach ($vals as $val)
1092					if (! isset($selected[$val]))
1093						printf('<tr><td><input type="checkbox" id="new_values_%s_%s" name="new_values[%s][]" value="%s" %s%s checked="checked"/></td><td><span style="white-space: nowrap;">&nbsp;%s</span></td></tr>',
1094							htmlspecialchars($attribute->getName()),$j++,
1095							htmlspecialchars($attribute->getName()),$val,
1096							$attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '',
1097							$attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '',
1098							$val);
1099
1100				echo '</table>';
1101			}
1102
1103		# This is a single value attribute
1104		} else {
1105			$val = $attribute->getValue($i) ? $attribute->getValue($i) : $attribute->getDefault();
1106
1107			if ($attribute->getHelper())
1108				echo '<table cellspacing="0" cellpadding="0"><tr><td valign="top">';
1109
1110			$found = false;
1111			$empty_value = false;
1112
1113			# If we are a required attribute, and the selection is blank, then the user cannot submit this form.
1114			if ($attribute->isRequired() && ! count($attribute->getSelection()))
1115				system_message(array(
1116					'title'=>_('Template Value Error'),
1117					'body'=>sprintf('This template uses a selection list for attribute [<b>%s</b>], however the selection list is empty.<br />You may need to create some dependancy entries in your LDAP server so that this attribute renders with values. Alternatively, you may be able to define the appropriate selection values in the template file.',$attribute->getName(false)),
1118					'type'=>'warn'));
1119
1120			printf('<select name="new_values[%s][]" id="new_values_%s_%s" %s%s>',
1121				htmlspecialchars($attribute->getName()),
1122				htmlspecialchars($attribute->getName()),$i,
1123				$attribute->needJS('focus') ? sprintf('onfocus="focus_%s(this);" ',$attribute->getName()) : '',
1124				$attribute->needJS('blur') ? sprintf('onblur="blur_%s(this);" ',$attribute->getName()) : '');
1125
1126			foreach ($attribute->getSelection() as $value => $description) {
1127				printf('<option value="%s" %s>%s</option>',$value,
1128					((strcasecmp($value,$val) == 0) && $found = true) ? 'selected="selected"' : '',$description);
1129
1130				if ($value == '')
1131					$empty_value = true;
1132
1133				echo "\n";
1134			}
1135
1136			if (!$found) {
1137				printf('<option value="%s" selected="selected">%s</option>',$val,$val == '' ? '&nbsp;' : $val);
1138				if ($val == '')
1139					$empty_value = true;
1140				echo "\n";
1141			}
1142
1143			if ((strlen($val) > 0) && ! $empty_value && $this->template->getDN()) {
1144				printf('<option value="">(%s)</option>',_('none, remove value'));
1145				echo "\n";
1146			}
1147			echo '</select>';
1148
1149			if ($attribute->getHelper()) {
1150				echo '</td><td valign="top">';
1151				$this->draw('Helper',$attribute,$i);
1152				echo '</td></tr></table>';
1153			}
1154		}
1155	}
1156
1157	/**
1158	 * Takes a shadow* attribute and returns the date as an integer.
1159	 *
1160	 * @param array Attribute objects
1161	 * @param string A shadow attribute name
1162	 */
1163	private function shadow_date($attribute) {
1164		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
1165			debug_log('Entered (%%)',129,0,__FILE__,__LINE__,__METHOD__,$fargs);
1166
1167		$shadowattr = array();
1168		$shadowattr['lastchange'] = $this->template->getAttribute('shadowlastchange');
1169		$shadowattr['max'] = $this->template->getAttribute('shadowmax');
1170
1171		$shadow = array();
1172		$shadow['lastchange'] = $shadowattr['lastchange'] ? $shadowattr['lastchange']->getValue(0) : null;
1173		$shadow['max'] = $shadowattr['max'] ? $shadowattr['max']->getValue(0) : null;
1174
1175		if (($attribute->getName() == 'shadowlastchange') && $shadow['lastchange'])
1176			$shadow_date = $shadow['lastchange'];
1177
1178		elseif (($attribute->getName() == 'shadowmax') && ($shadow['max'] > 0) && $shadow['lastchange'])
1179			$shadow_date = $shadow['lastchange']+$shadow['max'];
1180
1181		elseif (($attribute->getName() == 'shadowwarning') && ($attribute->getValue(0) > 0)
1182			&& $shadow['lastchange'] && $shadow['max'] && $shadow['max'] > 0)
1183			$shadow_date = $shadow['lastchange']+$shadow['max']-$attribute->getValue(0);
1184
1185		elseif (($attribute->getName() == 'shadowinactive') && ($attribute->getValue(0) > 0)
1186			&& $shadow['lastchange'] && $shadow['max'] && $shadow['max'] > 0)
1187			$shadow_date = $shadow['lastchange']+$shadow['max']+$attribute->getValue(0);
1188
1189		elseif (($attribute->getName() == 'shadowmin') && ($attribute->getValue(0) > 0) && $shadow['lastchange'])
1190			$shadow_date = $shadow['lastchange']+$attribute->getValue(0);
1191
1192		elseif (($attribute->getName() == 'shadowexpire') && ($attribute->getValue(0) > 0))
1193			$shadow_date = $shadowattr->getValue(0);
1194
1195		# Couldn't interpret the shadow date (could be 0 or -1 or something)
1196		else
1197			return false;
1198
1199		return $shadow_date*24*3600;
1200	}
1201
1202	protected function drawShadowDateShadowAttribute($attribute) {
1203		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
1204
1205		$shadow_before_today_attrs = arrayLower($attribute->shadow_before_today_attrs);
1206		$shadow_after_today_attrs = arrayLower($attribute->shadow_after_today_attrs);
1207		$shadow_date = $this->shadow_date($attribute);
1208
1209		if (! $shadow_date)
1210			return;
1211
1212		$today = date('U');
1213
1214		echo '<br/><small>';
1215		if (($today < $shadow_date) && in_array(strtolower($attribute->getName()),$shadow_before_today_attrs))
1216			printf('<span style="color:red">(%s)</span>',
1217				strftime($_SESSION[APPCONFIG]->getValue('appearance','date'),$shadow_date));
1218
1219		elseif (($today > $shadow_date) && in_array(strtolower($attribute->getName()),$shadow_after_today_attrs))
1220			printf('<span style="color:red">(%s)</span>',
1221				strftime($_SESSION[APPCONFIG]->getValue('appearance','date'),$shadow_date));
1222
1223		else
1224			printf('(%s)',
1225				strftime($_SESSION[APPCONFIG]->getValue('appearance','date'),$shadow_date));
1226
1227		echo '</small><br />';
1228	}
1229
1230	protected function drawFormReadOnlyValueShadowAttribute($attribute,$i) {
1231		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
1232
1233		$this->drawFormReadOnlyValueAttribute($attribute,$i);
1234		$this->draw('ShadowDate',$attribute);
1235	}
1236
1237	protected function drawFormReadWriteValueShadowAttribute($attribute,$i) {
1238		if (DEBUGTMP) printf('<font size=-2>%s</font><br />',__METHOD__);
1239
1240		$this->drawFormReadWriteValueAttribute($attribute,$i);
1241		$this->draw('ShadowDate',$attribute);
1242	}
1243}
1244?>
1245