<?
########## Confixx(R) 3.0 Professional ############
####### Copyright SWsoft, Inc. 2004-2005 ##########
#### http://www.sw-soft.com - info@sw-soft.com ####

define ('CRONTAB_MINUTE_FIRST', 0);
define ('CRONTAB_MINUTE_LAST', 59);
define ('CRONTAB_MINUTE_COUNT', CRONTAB_MINUTE_LAST - CRONTAB_MINUTE_FIRST + 1);
define ('CRONTAB_HOUR_FIRST', 0);
define ('CRONTAB_HOUR_LAST', 23);
define ('CRONTAB_HOUR_COUNT', CRONTAB_HOUR_LAST - CRONTAB_HOUR_FIRST + 1);
define ('CRONTAB_DOM_FIRST', 1);
define ('CRONTAB_DOM_LAST', 31);
define ('CRONTAB_DOM_COUNT', CRONTAB_DOM_LAST - CRONTAB_DOM_FIRST + 1);
define ('CRONTAB_MONTH_FIRST', 1);
define ('CRONTAB_MONTH_LAST', 12);
define ('CRONTAB_MONTH_COUNT', CRONTAB_MONTH_LAST - CRONTAB_MONTH_FIRST + 1);
define ('CRONTAB_DOW_FIRST', 1);
define ('CRONTAB_DOW_LAST', 7);
define ('CRONTAB_DOW_COUNT', CRONTAB_DOW_LAST - CRONTAB_DOW_FIRST + 1);

define ('CTE_TYPE_X',	0); // not set type
define ('CTE_TYPE_P',	1); // Param type
define ('CTE_TYPE_S',	2); // ParamStr type
define ('CTE_TYPE_LL',	3); // Load limited type
define ('CTE_TYPE_V',	4); // variable type
define ('CTE_TYPE_C',	5); // comment type
/****************************
* Crontab entry storage/parse class
*/


class CrontabEntry 
{
	var $_vars = array();
	var $_vars_err = array();
	var $_is_changed = false;
	var $_error = false;
		
	/***********************
	* CrontabEntry - constructor
	* 
	* @param $str - string of crontab record
	*
	* @return - true if ok
	*/
	function CrontabEntry($str='')
	{
		$this->resetError_();
		$this->_vars = $this->resetVars();
		if ($str==''){
			$this->_vars['is_new'] = true;
			$this->_is_changed = true;
			return true;
		}
		
		$vars = $this->parseString_($str);
		if (!$vars)
		{
			$this->setError_(lmsg($this->error()));
			return false;
		}
		
		$this->_vars = $vars;
		return true;
	}
	
	/**********************
	* parseString_($string) - this function parse a crontab config string
	*
	* @param $str  - crontab string
	* 
	* @return array() of crontab config of false if parse failed
	*/
	function parseString_($string)
	{
		$vars = $this->resetVars();

		// store source string
		$vars['src'] = trim($string);
		
		$string1 = trim($string);	// Work string
		$string2 = '';				// No comment String
		$sub = array();				// parse values array
		$ret = true;				// parse result 
		
		$re = '^[\s\t ]{0,}##!PSA!##(.{0,})$';
		if (ereg($re,$string1, $sub)) // disabled string or comment
		{
			$string1 = trim($sub[1]);	// store uncomennted string in work string 
			$string2 = $string1;		// store No comment string
			$vars['psaenabled'] = false;	// mark comment
		} else {
			$vars['psaenabled'] = true;	// unmark comment
		}

		$re = '^[\s\t ]{0,}#{1,}[\s\t ]{0,}(.{0,})$';
		if (ereg($re,$string1, $sub)) // disabled string or comment
		{
			$string1 = trim($sub[1]);	// store uncomennted string in work string 
			$string2 = $string1;		// store No comment string
			$vars['enabled'] = false;	// mark comment
		} else {
			$vars['enabled'] = true;	// unmark comment
		}

		// check @ load-limited
		if ($this->parseLoadLimited($vars, $string1)) { // parse as load-limited format
		} elseif ($this->parseParams($vars, $string1)){	// parse as param string
		} elseif ($this->parseVar($vars, $string1)){
		} else {
			if ($vars['enabled'] && $vars['psaenabled']){ // parse error
				$this->setError_('parse error');
				return false;
			}
			$vars['type'] = CTE_TYPE_C;
			$vars['comment'] = $string2;			//set command as no commant string
		}
		
		$vars['cmd'] = trim($string1);		//set command as work string
		
		return $vars;
	}
	
	function identifyStr($string)
	{
		$this->resetError_();
		if ( !in_array($this->_vars['type'], array(CTE_TYPE_P, CTE_TYPE_S, CTE_TYPE_LL, CTE_TYPE_V, CTE_TYPE_C, ) ) ){		// bad entry
			$this->setError_(lmsg('__invalid_type'));
			return false;
		}
		return (strcmp($this->_vars['src'], trim($string))==0);
	}

	function identifyBit($string)
	{
		$this->resetError_();
		if (!in_array($this->_vars['type'], array(CTE_TYPE_P, CTE_TYPE_S, CTE_TYPE_LL, CTE_TYPE_V, CTE_TYPE_C, ) ) ){		// bad entry
			$this->setError_(lmsg('__invalid_type'));
			return false;
		}
		$vars = $this->parseString_(trim($string));
		if (!$vars || !is_array($vars))
			return false;
		foreach (array('minute', 'hour', 'dom', 'month', 'dow') AS $key)
			foreach ($vars[$key.'_bit'] AS $n => $b)
				if ($b != $this->_vars[$key.'_bit'][$n]){
					return false;
				}
		return (strcmp(trim($this->_vars['cmd']), trim($vars['cmd']))==0);
	}
	
	/********************
	* Compare two arrays
	*/
	function identifyBitArr(&$arr1, &$arr2)
	{
		if (sizeof($arr1)!=sizeof($arr2))
			return false;
		foreach ($arr1 AS $n => $b)
			if ($b != $arr2[$n])
				return false;
				
		return true;
	}
	
	function isEmptyBitArr(&$arr)
	{
		if (!is_array($arr))
			return true;
		foreach ($arr AS $b)
			if ($b)
				return false;
		return true;
	}
	
	/*************************
	* parseLoadLimited - parse LoadLimited crontab string
	* 
	* @param &$vars  - crontab entry link
	* @param &$string - parse string link
	*
	* @return - true if ok
	*/
	function parseLoadLimited(&$vars, &$string)
	{
		$string1 = trim($string);					// workstring copy
		$vars1 = $vars;								// work vars copy
		$sub = array();								// parse values array
		
		$re = '^[\s\t ]{0,}\@{1}([a-zA-Z]{1,})[\s\t ]{0,}(.{0,})$';	// ll expression
		if (!ereg($re, $string1, $sub))				// parse
			return false;
			
		switch (strtolower(trim($sub[1])))
		{
			case 'reboot':
				$vars1['when_reboot'] = true;
				break;
			case 'yearly':
				$this->bit_set_($vars1['minute_bit'], 0);
				$this->bit_set_($vars1['hour_bit'], 0);
				$this->bit_set_($vars1['dom_bit'], 0);
				$this->bit_set_($vars1['month_bit'], 0);
				$this->bit_nset_($vars1['dow_bit'], 0, CRONTAB_DOW_LAST-CRONTAB_DOW_FIRST+1);
				break;
			case 'annually':
				$this->bit_set_($vars1['minute_bit'], 0);
				$this->bit_set_($vars1['hour_bit'], 0);
				$this->bit_set_($vars1['dom_bit'], 0);
				$this->bit_set_($vars1['month_bit'], 0);
				$this->bit_set_($vars1['dow_bit'], 0, CRONTAB_DOW_LAST-CRONTAB_DOW_FIRST+1);
				break;
			case 'monthly':
				$this->bit_set_($vars1['minute_bit'], 0);
				$this->bit_set_($vars1['hour_bit'], 0);
				$this->bit_nset_($vars1['dom_bit'], 0, CRONTAB_DOM_LAST-CRONTAB_DOM_FIRST+1);
				$this->bit_nset_($vars1['month_bit'], 0, CRONTAB_MONTH_LAST-CRONTAB_MONTH_FIRST+1);
				$this->bit_set_($vars1['dow_bit'], 0);
				break;
			case 'midnight':
				$this->bit_set_($vars1['minute_bit'], 0);
				$this->bit_set_($vars1['hour_bit'], 0);
				$this->bit_set_($vars1['dom_bit'], 0);
				$this->bit_nset_($vars1['month_bit'], 0, CRONTAB_MONTH_LAST-CRONTAB_MONTH_FIRST+1);
				$this->bit_nset_($vars1['dow_bit'], 0, CRONTAB_DOW_LAST-CRONTAB_DOW_FIRST+1);
				break;
			case 'daily':
				$this->bit_set_($vars1['minute_bit'], 0);
				$this->bit_set_($vars1['hour_bit'], 0);
				$this->bit_set_($vars1['dom_bit'], 0);
				$this->bit_nset_($vars1['month_bit'], 0, CRONTAB_MONTH_LAST-CRONTAB_MONTH_FIRST+1);
				$this->bit_nset_($vars1['dow_bit'], 0, CRONTAB_DOW_LAST-CRONTAB_DOW_FIRST+1);
				break;
			case 'hourly':
				$this->bit_set_($vars1['minute_bit'], 0);
				$this->bit_nset_($vars1['hour_bit'], 0, CRONTAB_HOUR_LAST-CRONTAB_HOUR_FIRST+1);
				$this->bit_nset_($vars1['dom_bit'], 0, CRONTAB_DOM_LAST-CRONTAB_DOM_FIRST+1);
				$this->bit_nset_($vars1['month_bit'], 0, CRONTAB_MONTH_LAST-CRONTAB_MONTH_FIRST+1);
				$this->bit_nset_($vars1['dow_bit'], 0, CRONTAB_DOW_LAST-CRONTAB_DOW_FIRST+1);
				break;
			default:
				return false;
		}
		
		$vars1['ll'] = strtolower(trim($sub[1]));
		$vars1['type'] = CTE_TYPE_LL;	// set type as ll
		
		$string = trim($sub[2]);		// return work string
		$vars = $vars1;					// return work vars
		return true;
	}
	
	/*************************
	* parseParams - parse param crontab string
	* 
	* @param &$vars   - crontab vars link
	* @param &$string - parse string link
	*
	* @return - true if ok
	*/
	function parseParams(&$vars, &$string)
	{
		$string1 = trim($string);		// copy work string
		$vars1 = $vars;					//copy work vars
		
		$vars1['minute'] =  $this->getInterval($vars1['minute_bit'], $string1, CRONTAB_MINUTE_FIRST, CRONTAB_MINUTE_LAST);
		if (!is_string($vars1['minute']))
			return false;
		$vars1['hour'] =  $this->getInterval($vars1['hour_bit'], $string1, CRONTAB_HOUR_FIRST, CRONTAB_HOUR_LAST);
		if (!is_string($vars1['hour']))
			return false;
		$vars1['dom'] = $this->getInterval($vars1['dom_bit'], $string1, CRONTAB_DOM_FIRST, CRONTAB_DOM_LAST);
		if (!is_string($vars1['dom']))
			return false;
		$vars1['month'] = $this->getInterval($vars1['month_bit'], $string1, CRONTAB_MONTH_FIRST, CRONTAB_MONTH_LAST);
		if (!is_string($vars1['month']))
			return false;
		$vars1['dow'] = $this->getInterval($vars1['dow_bit'], $string1, CRONTAB_DOW_FIRST, CRONTAB_DOW_LAST);
		if (!is_string($vars1['dow']))
			return false;

			
		$vars1['type'] = CTE_TYPE_P;			// set type as param
		
		$string = $string1;				// return work string
		$vars = $vars1;					// return work vars
		
		return true;
	}
	
	/*************************
	* parseVar - parse vars crontab string
	* 
	* @param &$vars   - crontab vars link
	* @param &$string - parse string link
	*
	* @return - true if ok
	*/
	function parseVar(&$vars, &$string)
	{
		$string1 = trim($string);		// copy work string
		$vars1 = $vars;					//copy work vars
		
		$re = '^(.{1,})=(.{0,})$';
		
		if (!ereg($re, $string1, $sub))				// parse
			return false;
			
		$vars1['name'] = trim($sub[1]);
		$vars1['value'] = trim($sub[2]);
		
		$vars1['type'] = CTE_TYPE_V;			// set type as var
		
		$string = $string1;				// return work string
		$vars = $vars1;					// return work vars
		
		return true;
	}
	
	
	/*************************
	* getInterval - parse interval 
	* 
	* @param &$arr    - bit array
	* @param &$string - parse string link
	* @param $first   - lowest value of interval
	* @param $last    - highst value of interval
	*
	* @return - intervalStr if ok else false;
	*/
	function getInterval(&$arr, &$string, $first, $last)
	{
		$string1 = trim($string);
		$intervalStr = '';
		$arr1 = $arr;
		$sub = array();
		
		$re0 = '^[\s\t ]{0,}\*{1}[\s\t ]{0,}(.{0,})$';									// all 
		$re1 = '^[\s\t ]{0,}([0-9]{1,})[\s\t ]{0,}\-{1}[\s\t ]{0,}([0-9]{1,})[\s\t ]{0,}(.{0,})$';	//interval
		$re2 = '^[\s\t ]{0,}([0-9]{1,})[\s\t ]{0,}(.{0,})$';								// single 
		$re3 = '^[\s\t ]{0,}\/{1}[\s\t ]{0,}([0-9]+)[\s\t ]{0,}(.{0,})$';						//each 
		$re4 = '^[\s\t ]{0,}\,{1}(.{0,})$'; 									//continue
		
		$done = false;
		
		while (!$done)
		{
			$arr2 = array_pad(array(), sizeof($arr1), false);
			if (ereg($re0, $string1, $sub)){
				$string1 = trim($sub[1]);
				$start = $first;
				$end = $last;
				if ($start<$first || $end>$last || $end<$start )
					return false;
				$intervalStr .= '*';
				$this->bit_nset_($arr2, $start-$first, $last-$first+1);
			} elseif (ereg($re1, $string1, $sub)) {
				$start = trim($sub[1])+0;
				$end = trim($sub[2])+0;
				$string1 = trim($sub[3]);
				if ($start<$first || $end>$last || $end<$start )
					return false;
				$intervalStr .= strval($start).'-'.strval($end);
				$this->bit_nset_($arr2, $start-$first, $end-$start+1);
			} elseif (ereg($re2, $string1, $sub)){
				$string1 = trim($sub[2]);
				$start = trim($sub[1])+0;
				$end = trim($sub[1])+0;
				if ($start<$first || $end>$last || $end<$start )
					return false;
				$intervalStr .= strval($start);
				$this->bit_set_($arr2, $start-$first);
			} else {
				return false;
			}
			
			if (ereg($re3, $string1, $sub)){
				$curr = 1;
				$each = trim($sub[1])+0;
				$string1 = trim($sub[2]);
				for ($i = $start-$first; $i < $end-$first+1; $i++)
				{
					if ($curr != $each)
					{
						$this->bit_clean_($arr2, $i);
					} else {
						$curr=0;
					}
					$curr++;
				}
				$intervalStr .= '/'.$each;
			}
			
			for ($i=0; $i<$last-$first+1;$i++)
			{
				if ($arr2[$i]==true)
				{
					$arr1[$i] = true;
				}
			}
			
			if (ereg($re4, $string1, $sub))
			{
				$string1 = trim($sub[1]);
				$intervalStr .= ',';
			} else {
				$done=true;
			}
			
		}
	
		for ($i=0; $i<$last-$first+1;$i++)
			if ($arr1[$i]==true)
				$arr[$i] = true;
			
		$string = trim($string1);
		
		return $intervalStr.' ';
	}
	
	
	
	/*************************
	* resetVars - create emty CrontabEntry struct 
	* 
	* @return - crontab entry struct
	*/
	function resetVars()
	{
		$this->resetError_();
		return array(
			'type'			=> CTE_TYPE_X,
			'is_new'		=> false,
			'is_removed'	=> false,
			'name'			=> '',
			'value'			=> '',
			'll'			=> '',
			'minute_bit'	=> array_pad(array(), CRONTAB_MINUTE_COUNT, false),
			'minute'		=> '',
			'hour_bit'		=> array_pad(array(), CRONTAB_HOUR_COUNT, false),
			'hour'			=> '',
			'dom_bit'		=> array_pad(array(), CRONTAB_DOM_COUNT, false),
			'dom'			=> '',
			'month_bit'		=> array_pad(array(), CRONTAB_MONTH_COUNT, false),
			'month'			=> '',
			'dow_bit'		=> array_pad(array(), CRONTAB_DOW_COUNT, false),
			'dow'			=> '',
			'dow_error'	=> array(),
			'when_reboot'	=> false,
			'cmd'			=> '',
			'psaenabled'	=> true,
			'enabled'		=> true,
			'comment'		=> '',
			'src'			=> '',
		);
	}
	
	/*****************
	*  bit_set_ - set bit $start in array $array
	*/
	function bit_set_(&$array, $start)
	{
		$this->resetError_();
		if (!is_array($array)){
			$this->setError_('first argument not array');
			return false;
		}
		$array[$start] = true;
		return true;
	}

	/*****************
	*  bit_nset_ - set $count bits from $start in array $array
	*/
	function bit_nset_(&$array, $start, $count)
	{
		if (!is_array($array))
			return false;
		for ($i=0; $i<$count; $i++)
			$array[$start+$i] = true;
		return true;
	}

	/*****************
	*  bit_clean_ - clean bit $start in array $array
	*/
	function bit_clean_(&$array, $start)
	{
		$this->resetError_();
		if (!is_array($array)){
			$this->setError_('first argument not array');
			return false;
		}
		$array[$start] = false;
		return true;
	}

	/*****************
	*  bit_nclean_ - clean $count bits from $start in array $array
	*/
	function bit_nclean_(&$array, $start, $count)
	{
		$this->resetError_();
		if (!is_array($array)){
			$this->setError_('first argument not array');
			return false;
		}
		for ($i=0; $i<$count; $i++)
			$array[$start+$i] = false;
		return true;
	}
	
	/*************************
	* getValue - return alue of crontab entry
	* 
	* @parm $key  - param name
	*
	* @return - string
	*/
	function getValue($key='')
	{
		$this->resetError_();
		
		switch ($key){
			case 'src':
			case 'enabled':
			case 'psaenabled':
			case 'name':
			case 'value':
			case 'll':
			case 'comment':
				return $this->_vars[$key];
			case 'minute':
			case 'hour':
			case 'dom':
			case 'month':
			case 'dow':
			case 'cmd':
				return trim($this->_vars[$key]);
			default:
				$this->setError_(lmsg('__invalid_key'));				
		}
		return false;
	}
	
	/*************************
	* getString - return crontab string
	* 
	* @return - string
	*/
	function getString()
	{
		$this->resetError_();

		switch ($this->_vars['type']){		// check type
		
			case CTE_TYPE_V:
				$str='';
				if (!$this->getValue('psaenabled'))
					$str.= '##!PSA!##';
				if (!$this->getValue('enabled') || trim($this->getValue('value'))=='')
					$str.= '##';
				$str.=$this->getValue('name').'='.$this->getValue('value');
				return $str;
				break;
			
			case CTE_TYPE_C:						// comment string
				return '##'.$this->getValue('comment');
				break;
				
			case CTE_TYPE_P:						// param string
				$str='';
				if (!$this->getValue('psaenabled'))
					$str.= '##!PSA!##';
				if (!$this->getValue('enabled'))
					$str.= '##';
				$str.= "\t".$this->getValue('minute');
				$str.= "\t".$this->getValue('hour');
				$str.= "\t".$this->getValue('dom');
				$str.= "\t".$this->getValue('month');
				$str.= "\t".$this->getValue('dow');
				$str.= "\t".$this->getValue('cmd');
				return $str;
				break;
				
			case CTE_TYPE_LL:						// load limited string
				$str='';
				if (!$this->getValue('psaenabled'))
					$str.= '##!PSA!##';
				if (!$this->getValue('enabled'))
					$str.= '##';
				$str.= "\t".'@'.$this->getValue('ll');
				return $str;
				break;

			case CTE_TYPE_S:						// string param
				$str='';
				return $str;
				break;

			default:
				$this->setError_(lmsg('__invalid_entry'));
		}
		
		return false;
	}
	
	/****************
	* getIntervalStr - make crontab String from array
	* 
	* @param $arr	- sourse array
	* @param $first	- first value of interval
	* @param $last	- last value of interval
	*
	* @return crontab crontab string if Ok else False
	*/
	function getIntervalStr($arr, $first, $last)
	{
		$str = '';
		$p = -1;
		for ($i=0; $i<$last-$first+1; $i++){
			if ($arr[$i])
			{
				if ($p<0)
				{
					$p = $i;
				}
			} else {
				if ($p>=0)
				{
					if ($i-1==$p)
					{
						$str.=','.($i+$first-1);
					} else {
						$str.=','.($p+$first).'-'.($i+$first-1);
					}
					$p = -1;
				}
			}	
		}
		
		// close interval if is open
		if ($p>=0)
		{
			if ($p==0){
				$str.=',*';
			} elseif ($p==$last-$first)
			{
				$str.=','.($p+$first);
			} else {
				$str.=','.($p+$first).'-'.($last);
			}
		}
		return substr($str,2);
	}
	
	function getType()
	{
		$this->resetError_();
		if (!in_array($this->_vars['type'], array(CTE_TYPE_P, CTE_TYPE_S, CTE_TYPE_LL, CTE_TYPE_V, CTE_TYPE_C, ) ) ){
			$this->setError_(lmsg('__invalid_type'));
			return false;
		}
		return $this->_vars['type'];
	}
	
	function setType($type)
	{
		$this->resetError_();
		if (!in_array($type, array(CTE_TYPE_P, CTE_TYPE_S, CTE_TYPE_LL, CTE_TYPE_V, CTE_TYPE_C, ) ) ){
			$this->setError_(lmsg('__invalid_type'));
			return false;
		}
		
		if ($this->_vars['type'] != $type) {
			$this->_vars['type'] = $type;
			$this->_is_changed = true;
		}
		
		return true;
	}
	
	function Remove()
	{
		$this->_vars['is_removed'] = true;
		$this->_is_changed = true;
		return true;
	}
	
	function isRemoved()
	{
		return $this->_vars['is_removed'];
	}
	
	function isChanged(){
		return $this->_is_changed;
	}
	
	function setValue($key, $value, $forse=false)
	{
		$this->resetError_();
		switch ($key)
		{
			case 'cmd':
			case 'src':
			case 'name':
				if (!is_string($value) || !($value = str_replace("\r", ' ', $value)) || !($value = str_replace("\n", ' ', $value)) || trim($value) == ''){
					$this->addValueError($key, lmsg('__empty_or_not_string'));
					$this->_vars[$key] = $value;
					return false;
				}
				$this->_vars[$key] = $value;
				break;
			case 'value':
			case 'comment':
				if (!is_string($value)){
					$this->addValueError($key, lmsg('__not_string'));
					$this->_vars[$key] = $value;
					return false;
				}
				$this->_vars[$key] = $value;
				break;
				
			case 'psaenabled':
			case 'enabled':
				if (is_bool($value)){
				} elseif (is_string($value)) {
					$value = ($value == 'true');
				} else {
					$this->addValueError($key, lmsg('__not_true_false'));
					$this->_vars[$key] = $value;
					return false;
				}
				$this->_vars[$key] = $value;
				break;
				
			case 'll':
				switch ($value){
					default:
						return false;
				}
				break;

			// ------------------------------------------- minute
			case 'minute':
			case 'hour':
			case 'dom':
			case 'month':
			case 'dow':
				eval ('$i_count = CRONTAB_'.strtoupper($key).'_COUNT;');
				eval ('$i_first = CRONTAB_'.strtoupper($key).'_FIRST;');
				eval ('$i_last = CRONTAB_'.strtoupper($key).'_LAST;');
				if (!is_string($value)){
					$this->addValueError($key, lmsg('__not_string'));
					$this->_vars[$key] = $value;
					return false;
				}
				$arr = array_pad(array(), $i_count, false);
				$i_value = $this->getInterval($arr, $value, $i_first, $i_last);				
				if (!$i_value){
					$this->addValueError($key, lmsg('__invalid_interval'));
					$this->_vars[$key] = $value;
					return false;
				} else {
					$this->_vars[$key] = $i_value;
				}
				if (CrontabEntry::isEmptyBitArr($arr)){
					$this->addValueError($key, lmsg('__invalid_interval'));
					$this->_vars[$key] = $value;
					return false;
				} else {
					$this->_vars[$key.'_bit'] = $arr;
				}
				break;

			default:
				$this->setError_(lmsg('__invalid_key'));
				return false;
		}
		
		$this->_is_changed = true;
		return true;
	}
	
	function resetBadValue(){
		$this->_vars_err = array();
	}
	
	function addValueError($key, $error){
		$this->_vars_err[$key][] = $error;
	}
	
	/***************
	* getBadValues - return array of bad values
	*/
	function getBadValues(){
		return $this->_vars_err;
	}
	
	function getValueErr($key){
		if (isset($this->_vars_err[$key]))
			return $this->_vars_err[$key];
		return array();
	}
	function resetError_()
	{
		$this->_error = false;
	}

	function error()
	{
		return $this->_error;
	}
	
	function setError_($e)
	{
		$this->_error = $e;
	}
}
?>
