diff --git a/livesupport/modules/storageServer/var/Validator.php b/livesupport/modules/storageServer/var/Validator.php index a0d1f59b3..a0ffdf8de 100644 --- a/livesupport/modules/storageServer/var/Validator.php +++ b/livesupport/modules/storageServer/var/Validator.php @@ -23,119 +23,242 @@ Author : $Author: tomas $ - Version : $Revision: 1.2 $ + Version : $Revision: 1.3 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storageServer/var/Validator.php,v $ ------------------------------------------------------------------------------*/ define('VAL_ROOT', 110); -define('VAL_NOREQ', 111); +define('VAL_NOREQE', 111); define('VAL_NOONEOF', 112); define('VAL_UNKNOWNE', 113); define('VAL_UNKNOWNA', 114); define('VAL_NOTDEF', 115); +define('VAL_UNEXPONEOF', 116); +define('VAL_FORMAT', 117); +define('VAL_CONTENT', 118); +define('VAL_NOREQA', 119); +define('VAL_ATTRIB', 120); #require_once ""; /** * Simple XML validator against structure stored in PHP hash-array hierarchy. * - * It should be replaced by XML schema validation in the future. + * Basic format files: + * + * It probably should be replaced by XML schema validation in the future. */ class Validator{ /** - * + * string - format type of validated document */ - var $format = ''; + var $formatType = NULL; /** - * + * */ - var $data = ''; + var $format = NULL; /** - * + * string - gunid of validated file for identification in mass input */ - var $anode = ''; + var $gunid = NULL; /** + * Constructor * + * @param formatType string - format type of validated document + * @param gunid string - gunid of validated file for identification + * in mass input */ - function Validator($format) + function Validator($formatType, $gunid) { - $this->format = $format; + $this->formatType = $formatType; + $this->gunid = $gunid; + $formats = array( + 'audioclip' => "audioClipFormat", + 'playlist' => "playlistFormat", + 'webstream' => "webstreamFormat", + ); + if(!isset($formats[$formatType])) return $this->_err(VAL_FORMAT); + $format = $formats[$formatType]; + $formatFile = dirname(__FILE__)."/$format.php"; + if(!file_exists($formatFile)) return $this->_err(VAL_FORMAT); + require $formatFile; + $this->format = $$format; } /** + * Validate document - only wrapper for validateNode method * + * @param data object, validated object tree + * @return TRUE or PEAR::error */ function validate(&$data) { - $this->data =& $data; $r = $this->validateNode($data, $this->format['_root']); return $r; } /** + * Validation of one element node from object tree * + * @param node object - validated node + * @param fname string - aktual name in format structur + * @return TRUE or PEAR::error */ function validateNode(&$node, $fname) { $dname = strtolower(($node->ns? $node->ns.":" : '').$node->name); $format =& $this->format; if(DEBUG) echo"\nVAL::validateNode: 1 $dname/$fname\n"; - if($dname != $fname) return $this->_err(VAL_ROOT); + // check root node name: + if($dname != $fname) return $this->_err(VAL_ROOT, $fname); + // check if this element is defined in format: if(!isset($format[$fname])) return $this->_err(VAL_NOTDEF, $fname); - $attrs = array(); - foreach($node->attrs as $i=>$attr){ - $attrs[$attr->name] =& $node->attrs[$i]; - $listr = $this->isListedAs($fname, $attr->name, 'attrs', 'required'); - $listi = $this->isListedAs($fname, $attr->name, 'attrs', 'implied'); - $listn = $this->isListedAs($fname, $attr->name, 'attrs', 'normal'); - if($listr===FALSE && $listi===FALSE && $listn===FALSE) - return $this->_err(VAL_UNKNOWNA, $attr->name); + // check element content + if(isset($format[$fname]['regexp'])){ + // echo "XXX {$format[$fname]['regexp']} / ".$node->content."\n"; + if(!preg_match("|{$format[$fname]['regexp']}|", $node->content)) + return $this->_err(VAL_CONTENT, $fname); } + // validate attributes: + $ra = $this->validateAttributes($node, $fname); + if(PEAR::isError($ra)) return $ra; + // validate children: + $r = $this->validateChildren($node, $fname); + if(PEAR::isError($r)) return $r; + return TRUE; + } + + /** + * Validation of attributes + * + * @param node object - validated node + * @param fname string - aktual name in format structure + * @return TRUE or PEAR::error + */ + function validateAttributes(&$node, $fname) + { + $format =& $this->format; + $attrs = array(); + // check if all attrs are permitted here: + foreach($node->attrs as $i=>$attr){ + $aname = strtolower(($attr->ns? $attr->ns.":" : '').$attr->name); + $attrs[$aname] =& $node->attrs[$i]; + if(!$this->isAttrInFormat($fname, $aname)) + return $this->_err(VAL_UNKNOWNA, $aname); + // check attribute format + // echo "XXA $aname\n"; + if(isset($format[$aname]['regexp'])){ + // echo "XAR {$format[$fname]['regexp']} / ".$node->content."\n"; + if(!preg_match("|{$format[$aname]['regexp']}|", $attr->val)) + return $this->_err(VAL_ATTRIB, $aname); + } + } + // check if all required attrs are here: if(isset($format[$fname]['attrs'])){ $fattrs =& $format[$fname]['attrs']; if(isset($fattrs['required'])){ foreach($fattrs['required'] as $i=>$attr){ - if(!isset($childs[$attr])) return $this->_err(VAL_NOREQ, $attr); + if(!isset($attrs[$attr])) + return $this->_err(VAL_NOREQA, $attr); } } } - $childs = array(); - foreach($node->children as $i=>$ch){ - $chname = strtolower(($ch->ns? $ch->ns.":" : '').$ch->name); - $childs[$chname] =& $node->children[$i]; - $listo = $this->isListedAs($fname, $chname, 'childs', 'optional'); - $listr = $this->isListedAs($fname, $chname, 'childs', 'required'); - $list1 = $this->isListedAs($fname, $chname, 'childs', 'oneof'); - if($listo===FALSE && $listr===FALSE && $list1===FALSE) - return $this->_err(VAL_UNKNOWNE, $chname); - } - //var_dump($childs); - if(isset($format[$fname]['childs'])){ - $fchilds =& $format[$fname]['childs']; - if(isset($fchilds['required'])){ - foreach($fchilds['required'] as $i=>$ch){ - if(!isset($childs[$ch])) return $this->_err(VAL_NOREQ, $ch); - } - } - if(isset($fchilds['oneof'])){ - $one = FALSE; - foreach($fchilds['oneof'] as $i=>$ch){ - if(isset($childs[$ch])) $one = TRUE; - } - if(!$one) return $this->_err(VAL_NOONEOF); - } - } - foreach($childs as $chname=>$ch){ - $r = $this->validateNode($childs[$chname], $chname); - if(PEAR::isError($r)) return $r; - } return TRUE; } /** + * Validation children nodes * + * @param node object - validated node + * @param fname string - aktual name in format structure + * @return TRUE or PEAR::error */ - function isListedAs($fname, $chname, $nType='childs', $reqType='required') + function validateChildren(&$node, $fname) + { + $format =& $this->format; + $childs = array(); + // check if all children are permitted here: + foreach($node->children as $i=>$ch){ + $chname = strtolower(($ch->ns? $ch->ns.":" : '').$ch->name); + // echo "XXE $chname\n"; + if(!$this->isChildInFormat($fname, $chname)) + return $this->_err(VAL_UNKNOWNE, $chname); + // call children recursive: + $r = $this->validateNode($node->children[$i], $chname); + if(PEAR::isError($r)) return $r; + $childs[$chname] = TRUE; + } + // check if all required children are here: + if(isset($format[$fname]['childs'])){ + $fchilds =& $format[$fname]['childs']; + if(isset($fchilds['required'])){ + foreach($fchilds['required'] as $i=>$ch){ + if(!isset($childs[$ch])) return $this->_err(VAL_NOREQE, $ch); + } + } + // required one from set + if(isset($fchilds['oneof'])){ + $one = FALSE; + foreach($fchilds['oneof'] as $i=>$ch){ + if(isset($childs[$ch])){ + if($one) return $this->_err( + VAL_UNEXPONEOF, "$ch in $fname"); + $one = TRUE; + } + } + if(!$one) return $this->_err(VAL_NOONEOF); + } + } + return TRUE; + } + + /** + * Test if child is presented in format structure + * + * @param fname string - node name in format structure + * @param chname string - child node name + * @return boolean + */ + function isChildInFormat($fname, $chname) + { + $listo = $this->isInFormatAs($fname, $chname, 'childs', 'optional'); + $listr = $this->isInFormatAs($fname, $chname, 'childs', 'required'); + $list1 = $this->isInFormatAs($fname, $chname, 'childs', 'oneof'); + return ($listo!==FALSE || $listr!==FALSE || $list1!==FALSE); + } + + /** + * Test if attribute is presented in format structure + * + * @param fname string - node name in format structure + * @param aname string - attribute name + * @return boolean + */ + function isAttrInFormat($fname, $aname) + { + $listr = $this->isInFormatAs($fname, $aname, 'attrs', 'required'); + $listi = $this->isInFormatAs($fname, $aname, 'attrs', 'implied'); + $listn = $this->isInFormatAs($fname, $aname, 'attrs', 'normal'); + return ($listr!==FALSE || $listi!==FALSE || $listn!==FALSE); + } + + /** + * Check if node/attribute is presented in format structure + * + * @param fname string - node name in format structure + * @param chname string - node/attribute name + * @param nType string - 'childs' | 'attrs' + * @param reqType string - + * @return boolean/int (index int format array returned if found) + */ + function isInFormatAs($fname, $chname, $nType='childs', $reqType='required') { $format =& $this->format; $listed = ( @@ -147,25 +270,38 @@ class Validator{ } /** + * Error exception generator * + * @param errno int - erron code + * @param par string - optional string for more descriptive error messages + * @return PEAR::error */ function _err($errno, $par='') { $msg = array( 110=>'Wrong root element', - 111=>'Required object missing', - 112=>'One-of object missing', + 111=>'Required element missing', + 112=>'One-of element missing', 113=>'Unknown element', 114=>'Unknown attribute', 115=>'Not defined', + 116=>'Unexpected second object from one-of set', + 117=>'Unknown format', + 118=>'Invalid content', + 119=>'Required attribute missing', + 120=>'Invalid attribute format', ); return PEAR::raiseError( - "Validator: {$msg[$errno]} #$errno ($par)" + "Validator: {$msg[$errno]} #$errno ($par, gunid={$this->gunid})", + $errno ); } /** * + * + * @param + * @return * / function () {