PX : code

VDaemon - Form Validation by Alexander Orlov
Download this code


<?PHP
///////////////////////////////////////////////////////////////////////////////
// VDaemon Freeware version 1.0
//
// Copyright (C) 2002-2003 Alexander Orlov and Andrei Stepanuga
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or any later version.
//
// All copyright notices regarding VDaemon Software
// must remain intact in the scripts
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//
// Support can be obtained from the product page at:
// http://www.x-code.com/vdaemon.php
//
// Correspondence and Marketing Questions can be sent to:
// vdaemon@x-code.com
//
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
//                 Public Data & Code
//

//-----------------------------------------------------------------------------
//                 Global Variables
//-----------------------------------------------------------------------------
$goVLCurrentValidators null;

//-----------------------------------------------------------------------------
//                 Library Code
//-----------------------------------------------------------------------------
if (ob_get_length() === false)
{
    
ob_start();
}

//=============================================================================
//
//                 Global Functions
//
//=============================================================================
//-----------------------------------------------------------------------------
//                 VLRequest
//-----------------------------------------------------------------------------
/**
 * @return mixed
 * @param sName string
 * @param bQuotes bool
 * @param bFlat bool
 * @desc Return formated GET or POST variable
 */
function VLRequest($sName$bQuotes false$bFlat true)
{
    if (
strcmp(substr($sNamestrlen($sName) - 22), '[]') == 0)
    {
        
$sName substr($sName0strlen($sName) - 2);
    }
    
    
$sValue $_REQUEST[$sName];

    if (isset(
$_REQUEST[$sName]))
    {
        if (
is_array($sValue))
        {
            for (
$nIdx 0$nIdx sizeof($sValue); $nIdx++)
            {
                
$sValue[$nIdx] = VLFormat($sValue[$nIdx], $bQuotes);
            }

            if (
$bFlat)
            {
                
$sValue join($sValue',');
            }
        }
        else
        {
            
$sValue VLFormat($sValue$bQuotes);
        }
    }

    return 
$sValue;
}

//-----------------------------------------------------------------------------
//                 VLValidate
//-----------------------------------------------------------------------------
function VLValidate()
{
    global 
$goVLCurrentValidators;

    if (isset(
$_REQUEST['validators']))
    {
        
$oValidators unserialize(VLRequest('validators'));
        if (
$oValidators !== false)
        {
            
$bState $oValidators->ValidateAll();

            if (
$bState && $oValidators->bSessionSave)
            {
                
session_start();

                
$aVars $_REQUEST;
                unset(
$aVars['validators']);
                unset(
$aVars['PHPSESSID']);
                
$aVarNames array_keys($aVars);

                foreach (
$aVarNames as $sName)
                {
                    
$_SESSION[$sName] = VLRequest($sNamefalsefalse);
                }
            }

            
$sFunc $oValidators->sFunction;
            
$sFunc($bState);
        }
        
$goVLCurrentValidators $oValidators;
    }
    else
    {
        
$goVLCurrentValidators false;
    }
}

//-----------------------------------------------------------------------------
//                 VLBeginParse
//-----------------------------------------------------------------------------
function VLBeginParse()
{
    
ob_start();
}

//-----------------------------------------------------------------------------
//                 VLEndParse
//-----------------------------------------------------------------------------
function VLEndParse()
{
//    $sDispErrOld = ini_set('display_errors', false);
//    $sLogErrOld  = ini_set('log_errors', true);
//    $sLogFileOld = ini_set('error_log', 'error.log');

    
$sBuffer ob_get_contents();
    
ob_end_clean();

    
$oVLPage = new CVLPage($sBuffer);
    echo 
$oVLPage->PrintPage();

//    ini_set('display_errors', $sDispErrOld);
//    ini_set('log_errors', $sLogErrOld);
//    ini_set('error_log', $sLogFileOld);
}

///////////////////////////////////////////////////////////////////////////////
//                 Private Data & Code
//

//=============================================================================
//
//                 Constants
//
//=============================================================================
//-----------------------------------------------------------------------------
//                 Errors
//-----------------------------------------------------------------------------
define('VL_E_FORM_NOT_FOUND',           'Can not found FORM!');
define('VL_E_UNNAMED_FORM',             'FORM must have a NAME!');
define('VL_E_FORM_NAME',                'FORM NAME must be alphanumeric!');
define('VL_E_UNACTION_FORM',            'FORM must have a VLACTION parameter!');
define('VL_E_ACTION_NAME',              'FORM VLACTION function not found');
define('VL_E_UNNAMED_INPUT',            'INPUT tag must have a NAME!');
define('VL_E_INPUT_NAME',               'INPUT NAME must be alphanumeric!');
define('VL_E_UNTYPED_INPUT',            'INPUT tag must have a TYPE!');
define('VL_E_INVALID_VALIDATOR_SOURCE''Invalid Validator Source String');
define('VL_E_UNKNOWN_VALIDATOR',        'Unknown VALIDATOR type');
define('VL_E_UNNAMED_VALIDATOR',        'VALIDATOR tag must have a NAME!');
define('VL_E_VALIDATOR_NAME',           'VALIDATOR NAME must be alphanumeric!');
define('VL_E_UNTYPED_VALIDATOR',        'VALIDATOR tag must have a TYPE!');
define('VL_E_VALIDATOR_NOT_FOUND',      'Validator not found');
define('VL_E_CONTROL_NOT_FOUND',        'Required Control to Validate');
define('VL_E_VALIDTYPE_NOT_FOUND',      'VALIDTYPE property must be set');
define('VL_E_VALIDTYPE_INVALID',        'Invalid VALIDTYPE property');
define('VL_E_INVALID_LABEL_SOURCE',     'Invalid VLLABEL Source String');
define('VL_E_MINVALUE_TYPE',            'Invalid MINVALUE type');
define('VL_E_MAXVALUE_TYPE',            'Invalid MAXVALUE type');
define('VL_E_COMPAREVALUE_TYPE',        'Invalid COMPAREVALUE type');
define('VL_E_COMPAREVALUE_NOT_FOUND',   'COMPAREVALUE not found');
define('VL_E_INVALID_OPERATOR',         'Invalid OPERATOR property');
define('VL_E_OPERATOR_NOT_FOUND',       'OPERATOR property not found');
define('VL_E_COMPARECONTROL_NOT_FOUND''Required Control to Compare');
define('VL_E_REGEXP_NOT_FOUND',         'REGEXP property not found');
define('VL_E_FUNCTION_NOT_FOUND',       'FUNCTION property not found');
define('VL_E_INVALID_HTML',             'Invalid HTML syntax');
define('VL_E_SUMMARY_TAG',              'Summary Tag must be alphanumeric');

//-----------------------------------------------------------------------------
//                 Warnings
//-----------------------------------------------------------------------------
define('VL_W_MULTIPLE_SELECT',          'Missed [] in Combobox with multiple selection');
define('VL_W_MULTIPLE_CHECKBOX',        'Missed [] in Checkboxes with same names');

//-----------------------------------------------------------------------------
//                 Form States
//-----------------------------------------------------------------------------
define('VL_FS_UNKNOWN',         0);
define('VL_FS_FIRSTTIME',       1);
define('VL_FS_ERRORS',          2);
define('VL_FS_PROCESS',         4);
define('VL_FS_NOTVLIB',         15);

//=============================================================================
//
//                 Global Functions
//
//=============================================================================
//-----------------------------------------------------------------------------
//                 VLAlphaNumeric
//-----------------------------------------------------------------------------
/**
 * @return bool
 * @param sStr string
 * @desc Check is sStr alphanumeric
 */
function VLAlphaNumeric($sStr)
{
    return 
strspn($sStr'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789') == strlen($sStr);
}

//-----------------------------------------------------------------------------
//                 VLCompressSpaces
//-----------------------------------------------------------------------------
/**
 * @return string
 * @param sStr string
 * @desc Remove all but one spaces from sStr
 */
function VLCompressSpaces($sStr)
{
    
$sSpaces "\n\r\t\v\0 ";
    
$sOutput '';

    while (
strlen($sStr))
    {
        if (
$nLen strcspn($sStr$sSpaces))
        {
            
$sOutput .= substr($sStr0$nLen);
            
$sStr substr($sStr$nLen);
        }

        if (
$nLen strspn($sStr$sSpaces))
        {
            
$sOutput .= ' ';
            
$sStr substr($sStr$nLen);
        }
    }

    return 
$sOutput;
}

//-----------------------------------------------------------------------------
//                 VLFormat
//-----------------------------------------------------------------------------
/**
 * @return string
 * @param sValue string
 * @param bQuotes bool
 * @desc Format variable (VLib internal use only)
 */
function VLFormat($sValue$bQuotes false)
{
    
$sValue trim($sValue);
    if (
$bQuotes xor get_magic_quotes_gpc())
    {
        if (
$bQuotes)
        {
            
$sValue addslashes($sValue);
        }
        else
        {
            
$sValue stripslashes($sValue);
        }
    }

    return 
$sValue;
}

//-----------------------------------------------------------------------------
//                 VLParseLabels
//-----------------------------------------------------------------------------
function VLParseLabels(&$oForm$sSource, &$aLabels)
{
    
// Find <VLLABEL ... > ... </VLLABEL>
    
while ($oForm->GetTag($sSource'VLLABEL'false$aMatches))
    {
        
$sHeader $aMatches['HEADER'];
        
$sLabel  $aMatches['BODY'];
        
$sFooter $aMatches['FOOTER'];

        
$nIdx sizeof($aLabels);
        
$aLabels[$nIdx] = new CVLLabel($oForm$sLabel);

        
$sSource "$sHeader%%LABEL::$nIdx%%$sFooter";
    }

    return 
$sSource;
}

//-----------------------------------------------------------------------------
//                 VLParseInputs
//-----------------------------------------------------------------------------
/**
 * @return string
 * @param &$oForm object
 * @param sSource string
 * @param &$aInputs array
 * @desc Parse input tags
 */
function VLParseInputs(&$oForm$sSource, &$aInputs)
{
    
$nUnnamedIdx 0;

    
// Find <INPUT TYPE="..." ... >
    
while($oForm->GetTag($sSource'INPUT'true$aMatches))
    {
        
$sHeader    $aMatches['HEADER'];
        
$sInput     $aMatches['BODY'];
        
$sFooter    $aMatches['FOOTER'];

        if (!
$oForm->GetAttribute($sInput'TYPE'$sType))
        {
            
trigger_error(VL_E_UNTYPED_INPUTE_USER_ERROR);
        }

        if (
$oForm->GetAttribute($sInput'NAME'$sName))
        {
            if (!
VLAlphaNumeric($sName))
            {
                if (
strcasecmp($sType'CHECKBOX') != ||
                    
strcmp(substr($sNamestrlen($sName) - 22), '[]') != 0)
                {
                    
trigger_error(VL_E_INPUT_NAMEE_USER_ERROR);
                }
            }
        }
        else
        {
            
$sName "UNNAMED_INPUT_$nUnnamedIdx";
            
$nUnnamedIdx++;
        }

        
$bInput true;
        switch (
strtoupper($sType))
        {
            case 
'TEXT':
                
$aInputs[$sName] = new CVLText($oForm$sName$sInput);
                break;

            case 
'PASSWORD':
            case 
'FILE':
                
$aInputs[$sName] = new CVLPassword($oForm$sName$sInput);
                break;

            case 
'CHECKBOX':
                if (!isset(
$aInputs[$sName]))
                {
                    
$aInputs[$sName] = new CVLChechbox($oForm$sName);
                }
                
$sValue $aInputs[$sName]->AddCheck($sInput);
                
$bInput false;
                break;

            case 
'RADIO':
                if (!isset(
$aInputs[$sName]))
                {
                    
$aInputs[$sName] = new CVLRadio($oForm$sName);
                }
                
$sValue $aInputs[$sName]->AddCheck($sInput);
                
$bInput false;
                break;

            default:
                
$aInputs[$sName] = new CVLInputUnknown($oForm$sName$sInput);
                break;
        }

        if (
$bInput)
        {
            
$sSource "$sHeader%%INPUT::$sName%%$sFooter";
        }
        else
        {
            
$sSource "$sHeader%%VALINPUT::$sName::$sValue%%$sFooter";
        }
    }

    while (
$oForm->GetTag($sSource'TEXTAREA'false$aMatches))
    {
        
$sHeader    $aMatches['HEADER'];
        
$sInput     $aMatches['BODY'];
        
$sOpenTag   $aMatches['OPENTAG'];
        
$sFooter    $aMatches['FOOTER'];

        if (
$oForm->GetAttribute($sOpenTag'NAME'$sName))
        {
            if (!
VLAlphaNumeric($sName))
            {
                
trigger_error(VL_E_INPUT_NAMEE_USER_ERROR);
            }
        }
        else
        {
            
$sName "UNNAMED_INPUT_$nUnnamedIdx";
            
$nUnnamedIdx++;
        }

        
$aInputs[$sName] = new CVLTextArea($oForm$sName$sInput);
        
$sSource "$sHeader%%INPUT::$sName%%$sFooter";
    }

    while (
$oForm->GetTag($sSource'SELECT'false$aMatches))
    {
        
$sHeader    $aMatches['HEADER'];
        
$sInput     $aMatches['BODY'];
        
$sOpenTag   $aMatches['OPENTAG'];
        
$sFooter    $aMatches['FOOTER'];

        if (
$oForm->GetAttribute($sOpenTag'NAME'$sName))
        {
            if (!
VLAlphaNumeric($sName))
            {
                if (
strcmp(substr($sNamestrlen($sName) - 22), '[]') != 0)
                {
                    
trigger_error(VL_E_INPUT_NAMEE_USER_ERROR);
                }
            }
        }
        else
        {
            
$sName "UNNAMED_INPUT_$nUnnamedIdx";
            
$nUnnamedIdx++;
        }

        
$aInputs[$sName] = new CVLSelect($oForm$sName$sInput);
        
$sSource "$sHeader%%INPUT::$sName%%$sFooter";
    }

    return 
$sSource;
}

//=============================================================================
//
//                 Classes
//
//=============================================================================

//-----------------------------------------------------------------------------
//                 CVLPage
//-----------------------------------------------------------------------------
class CVLPage
{
    var 
$sTemplate;     // HTML Template Text
    
var $aStrings;
    var 
$aComments;
    var 
$aForms;        // Array of Forms

    
function CVLPage($sSource)
    {
        
$this->aStrings = array();
        
$this->aForms = array();
        
$this->aComments = array();
        
$this->sTemplate $this->ParsePage($sSource);
    }

    function 
ParsePage($sSource)
    {
        
$sSource $this->ParseStrings($sSource);
        
$sSource $this->ParseForms($sSource);
        return 
$sSource;
    }

    function 
ParseStrings($sSource)
    {
        
$sHeader '';
        
$sFooter $sSource;

        while ((
$nPos strpos($sFooter'<')) !== false)
        {
            
$sHeader .= substr($sFooter0$nPos);
            
$sFooter  substr($sFooter$nPos);

            if (
strncmp($sFooter'<!--'4) == 0)
            {
                if ((
$nPos strpos($sFooter'-->')) !== false)
                {
                    
$sStr substr($sFooter0$nPos 3);
                    
$nIdx sizeof($this->aComments);
                    
$this->aComments[$nIdx] = $sStr;

                    
$sHeader .= "%%COMMENT::$nIdx%%";
                    
$sFooter substr($sFooter$nPos 3);
                }
                else
                {
                    
trigger_error(VL_E_INVALID_HTMLE_USER_ERROR);
                }
            }
            elseif (
strspn(substr($sFooter1), '!/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz') > 0)
            {
                do
                {
                    if ((
$nPos strcspn($sFooter'>"\'')) < strlen($sFooter))
                    {
                        
$sHeader .= substr($sFooter0$nPos 1);
                        
$sChar    substr($sFooter$nPos1);
                        
$sFooter  substr($sFooter$nPos 1);

                        if (
$sChar != '>')
                        {
                            if ((
$nPos strcspn($sFooter$sChar)) < strlen($sFooter))
                            {
                                
$sStr substr($sFooter0$nPos);
                                if (
strcspn($sStr"\n") == $nPos)
                                {
                                    
$nIdx sizeof($this->aStrings);
                                    
$this->aStrings[$nIdx] = $sStr;
                                    
$sHeader .= "%%STR::$nIdx%%$sChar";
                                    
$sFooter substr($sFooter$nPos 1);
                                }
                                else
                                {
                                    
trigger_error(VL_E_INVALID_HTMLE_USER_ERROR);
                                }
                            }
                            else
                            {
                                
trigger_error(VL_E_INVALID_HTMLE_USER_ERROR);
                            }
                        }
                    }
                    else
                    {
                        
trigger_error(VL_E_INVALID_HTMLE_USER_ERROR);
                    }
                }
                while (
$sChar != '>');
            }
            else
            {
                
$sHeader .= substr($sFooter01);
                
$sFooter  substr($sFooter1);
            }
        }

        
$sSource $sHeader $sFooter;
        return 
$sSource;
    }

    function 
ParseForms($sSource)
    {
        while (
preg_match("|\A(.*)(<FORM[^>]+>.*</FORM[^>]*>)(.*)\z|Uis"$sSource$aMatches))
        {
            
$sHeader    $aMatches[1];
            
$sBody      $aMatches[2];
            
$sFooter    $aMatches[3];

            
$nIdx sizeof($this->aForms);
            
$this->aForms[$nIdx] = new CVLForm($sBody$this->aStrings);
            
$sSource "$sHeader%%FORM::$nIdx%%$sFooter";
        }

        return 
$sSource;
    }

    function 
PrintPage()
    {
        
$sSource $this->sTemplate;

        for (
$nIdx 0$nIdx sizeof($this->aForms); $nIdx++)
        {
            
$sSource str_replace("%%FORM::$nIdx%%"$this->aForms[$nIdx]->PrintForm(), $sSource);
        }

        for (
$nIdx 0$nIdx sizeof($this->aStrings); $nIdx++)
        {
            
$sSource str_replace("%%STR::$nIdx%%"$this->aStrings[$nIdx], $sSource);
        }

        for (
$nIdx 0$nIdx sizeof($this->aComments); $nIdx++)
        {
            
$sSource str_replace("%%COMMENT::$nIdx%%"$this->aComments[$nIdx], $sSource);
        }

        return 
$sSource;
    }
}

//-----------------------------------------------------------------------------
//                 CVLForm
//-----------------------------------------------------------------------------
class CVLForm
{
    var 
$sName;         // Form Name
    
var $sAction;       // Action after validation
    
var $aInputs;       // Array of Input Controlls
    
var $aLabels;       // Array of Labels
    
var $oValidators;   // Validators collection
    
var $aStrings;
    var 
$sTemplate;     // Form Template
    
var $nState;        // Form State
    
var $bSessionFill;
    var 
$bSessionSave;
    var 
$oSummary;

    function 
CVLForm($sTemplate, &$aStrings)
    {
        global 
$goVLCurrentValidators;

        
$this->aInputs = array();
        
$this->aLabels = array();
        
$this->bSessionFill false;
        
$this->bSessionSave false;
        
$this->aStrings = &$aStrings;
        
$this->nState VL_FS_UNKNOWN;
        
$this->oSummary null;
        
$this->oValidators null;

        
$this->ParseForm($sTemplate);

        if (
$this->nState != VL_FS_NOTVLIB)
        {
            if (isset(
$_REQUEST[$this->sName]))
            {
                
$this->FillValueAll();
                if (
$goVLCurrentValidators === null)
                {
                    
VLValidate();
                }
                if (
$goVLCurrentValidators)
                {
                    
$this->oValidators $goVLCurrentValidators;
                }
                else
                {
                    
$bState $this->oValidators->ValidateAll();
                    if (
$bState && $this->$oValidators->bSessionSave)
                    {
                        
session_start();

                        
$aVars $_REQUEST;
                        unset(
$aVars['validators']);
                        unset(
$aVars['PHPSESSID']);
                        
$aVarNames array_keys($aVars);

                        foreach (
$aVarNames as $sName)
                        {
                            
$_SESSION[$sName] = VLRequest($sNamefalsefalse);
                        }
                    }

                    
$sFunc $this->$oValidators->sFunction;
                    
$sFunc($bState);
                }

                if (
$this->oValidators->bState)
                {
                    
$this->nState VL_FS_PROCESS;

                }
                else
                {
                    
$this->nState VL_FS_ERRORS;
                }
            }
            else
            {
                
$this->nState VL_FS_FIRSTTIME;

                if (
$this->bSessionFill)
                {
                    
session_start();
                    if (isset(
$_SESSION[$this->sName]))
                    {
                        
$this->FillSessionAll();
                    }
                }
                if (isset(
$_REQUEST['vlfill']))
                {
                    
$this->FillValueAll();
                }
            }
        }
    }

    
/**
     * @return void
     * @param sSource string
     * @desc Form Source Parsing
     */
    
function ParseForm($sSource)
    {
        if (
$this->GetTag($sSource'FORM'false$aMatches))
        {
            
$sFormTag   $aMatches['OPENTAG'];
            
$sBody      $aMatches['INNER'];
            
$sFormClose $aMatches['CLOSETAG'];

            
$sRunAt '';
            if (
$this->GetAttribute($sFormTag'RUNAT'$sRunAt) && strcasecmp($sRunAt'VDAEMON') == 0)
            {
                
$this->GetAttribute($sFormTag'RUNAT'$sRunAt'');

                
// Find form name. Form must have name.
                
$sStr '';
                if (
$this->GetAttribute($sFormTag'NAME'$sStr))
                {
                    if (
VLAlphaNumeric($sStr))
                    {
                        
$this->sName $sStr;
                    }
                    else
                    {
                        
trigger_error(VL_E_FORM_NAMEE_USER_ERROR);
                    }
                }
                else
                {
                    
trigger_error(VL_E_UNNAMED_FORME_USER_ERROR);
                }

                
// Find form vlaction. Form must have vlaction (php script for result processing).
                
if ($this->GetAttribute($sFormTag'VLACTION'$sStr'%%ACTION%%'))
                {
                    if (
function_exists($sStr))
                    {
                        
$this->sAction $sStr;
                    }
                    else
                    {
                        
trigger_error(VL_E_ACTION_NAMEE_USER_ERROR);
                    }
                }
                else
                {
                    
trigger_error(VL_E_UNACTION_FORME_USER_ERROR);
                }

                
$this->GetAttribute($sFormTag'ACTION'$sStr'');

                if (
$this->GetAttribute($sFormTag'FILLFROM'$sStr''))
                {
                    if (!
strcasecmp($sStr'SESSION'))
                    {
                        
$this->bSessionFill true;
                    }
                }

                if (
$this->GetAttribute($sFormTag'SAVETO'$sStr''))
                {
                    if (!
strcasecmp($sStr'SESSION'))
                    {
                        
$this->bSessionSave true;
                    }
                }

                
// Parse summary
                
if ($this->GetTag($sBody'VLSUMMARY'true$aMatches'%%SUMMARY%%'))
                {
                    
$sSummary $aMatches['OPENTAG'];
                    
$this->oSummary = new CVLSummary($this$sSummary);
                }

                
// Parse inputs
                
$sBody VLParseInputs($this$sBody$this->aInputs);
                
// Parse validators
                
$this->oValidators = new CVLValidatorsCollection($this->sAction$this->bSessionSave);
                
$sBody $this->oValidators->ParseValidators($this$sBody);
                
// Parse labels
                
$sBody VLParseLabels($this$sBody$this->aLabels);

                
// Make form template
                
$this->sTemplate "$sFormTag%%HIDDEN%%$sBody$sFormClose";
            }
            else
            {
                
$this->sTemplate $sSource;
                
$this->nState VL_FS_NOTVLIB;
            }
        }
        else
        {
            
trigger_error(VL_E_FORM_NOT_FOUNDE_USER_ERROR);
        }
    }

    function 
FillValueAll()
    {
        
reset($this->aInputs);
        while (list(
$sName$oInput) = each($this->aInputs))
        {
            
$this->aInputs[$sName]->FillValue();
        }
    }

    function 
FillSessionAll()
    {
        
reset($this->aInputs);
        while (list(
$sName$oInput) = each($this->aInputs))
        {
            
$this->aInputs[$sName]->FillSession();
        }
    }

    function 
GetStr($nIdx)
    {
        
$sStr '';
        if (
$nIdx sizeof($this->aStrings))
        {
            
$sStr $this->aStrings[$nIdx];
        }

        return 
$sStr;
    }

    function 
GetTag(&$sSource$sName$bEmptyTag, &$aMatches$sReplace null)
    {
        
$bFind false;
        
$sBuffer $sSource;

        if (
$sBuffer stristr($sBuffer"<$sName"))
        {
            
$sHeader substr($sSource0strpos($sSource$sBuffer));

            if ((
$nIdx strpos($sBuffer">")) !== false)
            {
                
$sOpenTag substr($sBuffer0$nIdx 1);
                
$sBuffer substr($sBuffer$nIdx 1);

                if (
$bEmptyTag)
                {
                    
$bFind true;
                    
$sFooter $sBuffer;

                    
$aMatches = array();
                    
$aMatches['HEADER']  = $sHeader;
                    
$aMatches['OPENTAG'] = $sOpenTag;
                    
$aMatches['BODY']    = $sOpenTag;
                    
$aMatches['FOOTER']  = $sFooter;
                }
                else
                {
                    
$sBufferCopy $sBuffer;
                    if (
$sBuffer stristr($sBuffer"</$sName"))
                    {
                        
$sBody substr($sBufferCopy0strpos($sBufferCopy$sBuffer));

                        if ((
$nIdx strpos($sBuffer">")) !== false)
                        {
                            
$sCloseTag substr($sBuffer0$nIdx 1);
                            
$sFooter substr($sBuffer$nIdx 1);

                            
$bFind true;
                            
$aMatches = array();
                            
$aMatches['HEADER']   = $sHeader;
                            
$aMatches['OPENTAG']  = $sOpenTag;
                            
$aMatches['INNER']    = $sBody;
                            
$aMatches['BODY']     = $sOpenTag $sBody $sCloseTag;
                            
$aMatches['CLOSETAG'] = $sCloseTag;
                            
$aMatches['FOOTER']   = $sFooter;
                        }
                    }
                }

                if (
$bFind && $sReplace !== null)
                {
                    
$sSource $sHeader $sReplace $sFooter;
                }
            }
        }

        return 
$bFind;
    }

    function 
GetAttStrIdx(&$sSource$sName)
    {
        
$nRetIdx false;
        
$sBuffer $sSource;

        while (
$nRetIdx === false && $sBuffer stristr($sBuffer$sName))
        {
            
$sHeader substr($sSource0strpos($sSource$sBuffer));
            
$sBuffer substr($sBufferstrlen($sName));
            if (
strcmp($sHeaderrtrim($sHeader)) != 0)
            {
                
$sBuffer ltrim($sBuffer);
                if (
$sBuffer[0] == '=')
                {
                    
$sBuffer substr($sBuffer1);
                    
$sBuffer ltrim($sBuffer);

                    if (
$sBuffer[0] == '"' || $sBuffer[0] == "'")
                    {
                        
$sComma  $sBuffer[0];
                        
$sBuffer substr($sBuffer1);

                        if (
strcmp(substr($sBuffer07), '%%STR::') == 0)
                        {
                            
$sBuffer substr($sBuffer7);
                            
$nLen strspn($sBuffer'0123456789');
                            
$nIdx = (int)substr($sBuffer0$nLen);
                            
$sBuffer substr($sBuffer$nLen);

                            if (
strcmp(substr($sBuffer03), "%%$sComma") == 0)
                            {
                                
$sBuffer substr($sBuffer3);
                                if (
$nIdx sizeof($this->aStrings))
                                {
                                    
$nRetIdx $nIdx;
                                }
                            }
                        }
                    }
                }
            }
        }

        return 
$nRetIdx;
    }

    function 
GetAttribute(&$sSource$sName, &$sValue$sReplace null)
    {
        
$bFind false;
        
$sBuffer $sSource;

        while (!
$bFind && $sBuffer stristr($sBuffer$sName))
        {
            
$sHeader substr($sSource0strpos($sSource$sBuffer));
            
$sBuffer substr($sBufferstrlen($sName));
            if (
strcmp($sHeaderrtrim($sHeader)) != 0)
            {
                
$sBuffer ltrim($sBuffer);
                if (
$sBuffer[0] == '=')
                {
                    
$sBuffer substr($sBuffer1);
                    
$sBuffer ltrim($sBuffer);

                    if (
$sBuffer[0] == '"' || $sBuffer[0] == "'")
                    {
                        
$sComma  $sBuffer[0];
                        
$sBuffer substr($sBuffer1);

                        if (
strcmp(substr($sBuffer07), '%%STR::') == 0)
                        {
                            
$sBuffer substr($sBuffer7);
                            
$nLen strspn($sBuffer'0123456789');
                            
$nIdx = (int)substr($sBuffer0$nLen);
                            
$sBuffer substr($sBuffer$nLen);

                            if (
strcmp(substr($sBuffer03), "%%$sComma") == 0)
                            {
                                
$sBuffer substr($sBuffer3);
                                if (
$nIdx sizeof($this->aStrings))
                                {
                                    
$bFind true;
                                    
$sValue $this->aStrings[$nIdx];
                                    if (
$sReplace !== null)
                                    {
                                        
$sSource $sHeader $sReplace $sBuffer;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        return 
$bFind;
    }

    function 
PrintForm()
    {
        
$sOutput $this->sTemplate;

        if (
$this->nState != VL_FS_NOTVLIB)
        {
            
$sFormAction $_SERVER['SCRIPT_NAME'];
            
$sFormAction "ACTION=\"$sFormAction\"";
            
$sOutput preg_replace("|%%ACTION%%|U"$sFormAction$sOutput);

            
$sValidators serialize($this->oValidators);
            
$sValidators htmlspecialchars($sValidators);
            
$sHidden "\n<INPUT TYPE=\"HIDDEN\" NAME=\"$this->sName\" VALUE=\"form\">" .
                       
"\n<INPUT TYPE=\"HIDDEN\" NAME=\"validators\" VALUE=\"$sValidators\">";
            
$sOutput str_replace("%%HIDDEN%%"$sHidden$sOutput);

            if (
$this->oSummary)
            {
                
$sOutput str_replace("%%SUMMARY%%"$this->oSummary->Out(), $sOutput);
            }

            
reset($this->aInputs);
            while (list(
$sName$oInput) = each($this->aInputs))
            {
                if (
strstr($sOutput"%%INPUT::$sName%%"))
                {
                    
$sOutput str_replace("%%INPUT::$sName%%"$this->aInputs[$sName]->Out(), $sOutput);
                }
                else
                {
                    
$sQuoteName quotemeta($sName);
                    while (
preg_match("|%%VALINPUT::$sQuoteName::(.+)%%|Us"$sOutput$aMatches))
                    {
                        
$sValue $aMatches[1];
                        
$sOutput str_replace("%%VALINPUT::$sName::$sValue%%"$this->aInputs[$sName]->Out($sValue), $sOutput);
                    }
                }
            }

            for (
$nIdx 0$nIdx sizeof($this->aLabels); $nIdx++)
            {
                
$sOutput str_replace("%%LABEL::$nIdx%%"$this->aLabels[$nIdx]->Out(), $sOutput);
            }
        }

        return 
$sOutput;
    }
}

//-----------------------------------------------------------------------------
//                 CVLSummary
//-----------------------------------------------------------------------------
class CVLSummary
{
    var 
$oForm;
    var 
$sHeaderText;
    var 
$sClass;
    var 
$sTag;

    function 
CVLSummary(&$oForm$sSource)
    {
        
$this->oForm = &$oForm;

        if (
$oForm->GetAttribute($sSource'HEADERTEXT'$sStr))
        {
            
$this->sHeaderText $sStr;
        }

        if (
$oForm->GetAttribute($sSource'CLASS'$sStr))
        {
            
$this->sClass $sStr;
        }

        if (
$oForm->GetAttribute($sSource'TAG'$sStr))
        {
            if (
VLAlphaNumeric($sStr))
            {
                
$this->sTag $sStr;
            }
            else
            {
                
trigger_error(VL_E_SUMMARY_TAGE_USER_ERROR);
            }
        }
    }

    function 
Out()
    {
        
$sOutput '';
        if (
$this->oForm->nState == VL_FS_ERRORS)
        {
            if (isset(
$this->sTag))
            {
                
$sOutput .= "<$this->sTag";
                if (isset(
$this->sClass))
                {
                    
$sOutput .= " CLASS=\"$this->sClass\"";
                }
                
$sOutput .= '>';
            }

            if (isset(
$this->sHeaderText))
            {
                
$aErrors[] = $this->sHeaderText;
            }

            
$aNames $this->oForm->oValidators->GetNames();
            foreach (
$aNames as $sName)
            {
                if (!
$this->oForm->oValidators->GetState($sName))
                {
                    
$sErrMsg $this->oForm->oValidators->GetErrMsg($sName);
                    if (
$sErrMsg)
                    {
                        
$aErrors[] = $sErrMsg;
                    }
                }
            }

            if (
sizeof($aErrors))
            {
                
$sOutput .= join("<BR>\n"$aErrors);
            }

            if (isset(
$this->sTag))
            {
                
$sOutput .= "</$this->sTag>";
            }
        }

        return 
$sOutput;
    }
}

class 
CVLLabel
{
    var 
$sOKText;
    var 
$sOKClass;
    var 
$sErrText;
    var 
$sErrClass;
    var 
$oForm;         // Parent form
    
var $aValidators;   // Making state of Label
    
    
function CVLLabel(&$oForm$sSource)
    {
        
$this->aValidators = array();
        
$this->oForm = &$oForm;
        
        if (
$oForm->GetTag($sSource'VLLABEL'false$aMatches))
        {
            
$this->sOKText $aMatches['INNER'];
            
$sOpenTag $aMatches['OPENTAG'];
        }
        else
        {
            
trigger_error(VL_E_INVALID_LABEL_SOURCEE_USER_ERROR);
        }
        
        if (
$oForm->GetAttribute($sOpenTag'CLASS'$sStr))
        {
            
$this->sOKClass $sStr;
        }

        if (
$oForm->GetAttribute($sOpenTag'ERRTEXT'$sStr))
        {
            
$this->sErrText $sStr;
        }

        if (
$oForm->GetAttribute($sOpenTag'ERRCLASS'$sStr))
        {
            
$this->sErrClass $sStr;
        }

        if (
$oForm->GetAttribute($sOpenTag'VALIDATORS'$sStr))
        {
            
$this->aValidators explode(','$sStr);
            for (
$nIdx 0$nIdx sizeof($this->aValidators); $nIdx++)
            {
                
$this->aValidators[$nIdx] = trim($this->aValidators[$nIdx]);
                if (!
$oForm->oValidators->IsExist($this->aValidators[$nIdx]))
                {
                    
trigger_error(VL_E_VALIDATOR_NOT_FOUNDE_USER_ERROR);
                }
            }
        }
    }
    
    function 
GetState()
    {
        
$bState true;
        
reset($this->aValidators);
        for (
$nIdx 0$bState and $nIdx sizeof($this->aValidators); $nIdx++)
        {
            
$bState $bState && $this->oForm->oValidators->GetState($this->aValidators[$nIdx]);
        }
        
        return 
$bState;
    }
    
    function 
Out()
    {
        
$sOutput '';
        if (
$this->GetState())
        {
            if (!empty(
$this->sOKText))
            {
                if (!empty(
$this->sOKClass))
                {
                    
$sOutput "<SPAN CLASS=\"$this->sOKClass\">$this->sOKText</SPAN>";
                }
                else
                {
                    
$sOutput $this->sOKText;
                }
            }
        }
        else
        {
            if (!empty(
$this->sErrText))
            {
                if (!empty(
$this->sErrClass))
                {
                    
$sOutput "<SPAN CLASS=\"$this->sErrClass\">$this->sErrText</SPAN>";
                }
                else
                {
                    
$sOutput $this->sErrText;
                }
            }
            elseif (!empty(
$this->sOKText))
            {
                if (!empty(
$this->sErrClass))
                {
                    
$sOutput "<SPAN CLASS=\"$this->sErrClass\">$this->sOKText</SPAN>";
                }
                else
                {
                    
$sOutput $this->sOKText;
                }
            }
        }
        return 
$sOutput;
    }
}

class 
CVLInput
{
    var 
$oForm;
    var 
$sName;
    var 
$sValue;
    var 
$sTemplate;

    function 
CVLInput(&$oForm$sName$sSource)
    {
        
$this->oForm = &$oForm;
        
$this->sName $sName;
        
$this->sTemplate $sSource;
    }

    function 
GetValue()
    {
        if (isset(
$this->sValue))
        {
            return 
$this->sValue;
        }
        else
        {
            return 
'';
        }
    }
    
    function 
FillValue()
    {
        if (isset(
$_REQUEST[$this->sName]))
        {
            
$this->sValue VLRequest($this->sName);
        }
    }
    
    function 
FillSession()
    {
        if (isset(
$_SESSION[$this->sName]))
        {
            
$this->sValue $_SESSION[$this->sName];
        }
    }
    
    function 
GetStr($nIdx)
    {
        return 
$this->oForm->GetStr($nIdx);
    }
}

class 
CVLInputUnknown extends CVLInput
{
    function 
CVLInputUnknown(&$oForm$sName$sSource)
    {
        
$this->CVLInput($oForm$sName$sSource);
    }
    
    function 
Out()
    {
        return 
$this->sTemplate;
    }
}

class 
CVLText extends CVLInput
{
    
/**
     * @return CVLText
     * @param oForm object
     * @param sName string
     * @param sSource string
     * @desc Constructor
     */
    
function CVLText(&$oForm$sName$sSource)
    {
        
$this->CVLInput($oForm$sName$sSource);
        
        if (
$oForm->GetAttribute($sSource'VALUE'$sStr'%%VALUE%%'))
        {
            
$this->sValue $sStr;
            
$this->sTemplate $sSource;
        }
        else
        {
            
$nIdx strpos($sSource'>');
            
preg_match("|\A([^>]*)\s*?(>.*)\z|Uis"$sSource$aMatches);
            
$sHeader rtrim(substr($sSource0$nIdx));
            
$sFooter substr($sSource$nIdx);
            
$this->sTemplate "$sHeader %%VALUE%%$sFooter";
        }
    }

    
/**
     * @return string
     * @desc Print self as HTML tag
     */
    
function Out()
    {
        
$sIns '';
        if (!empty(
$this->sValue))
        {
            
$sIns 'VALUE="' htmlentities($this->sValueENT_QUOTES) . '"';
        }

        return 
str_replace("%%VALUE%%"$sIns$this->sTemplate);
    }
}

class 
CVLPassword extends CVLText
{
    
/**
     * @return CVLPassword
     * @param oForm object
     * @param sName string
     * @param aParam array
     * @desc Constructor
     */
    
function CVLPassword(&$oForm$sName$aParam)
    {
        
$this->CVLText($oForm$sName$aParam);
    }

    
/**
     * @return string
     * @desc Print self as HTML tag
     */
    
function Out()
    {
        return 
str_replace("%%VALUE%%"''$this->sTemplate);
    }
}

class 
CVLTextArea extends CVLInput
{
    
/**
     * @return CVLTextArea
     * @param oForm object
     * @param sName string
     * @param sSource string
     * @desc Constructor
     */
    
function CVLTextArea(&$oForm$sName$sSource)
    {
        
$this->CVLInput($oForm$sName$sSource);
        
        if (
$oForm->GetTag($sSource'TEXTAREA'false$aMatches))
        {
            
$this->sValue $aMatches['INNER'];
            
$sHeader $aMatches['OPENTAG'];
            
$sFooter $aMatches['CLOSETAG'];
            
$this->sTemplate "$sHeader%%VALUE%%$sFooter";
        }
    }

    
/**
     * @return string
     * @desc Print self as HTML tag
     */
    
function Out()
    {
        
$sIns '';
        if (!empty(
$this->sValue))
        {
            
$sIns htmlentities($this->sValueENT_QUOTES);
        }

        return 
str_replace("%%VALUE%%"$sIns$this->sTemplate);
    }
}

class 
CVLOption
{
    var 
$oForm;
    var 
$sValue;        // Option value
    
var $bSelected;
    var 
$sText;         // Option text
    
    
function CVLOption(&$oForm$sSource)
    {
        
$this->oForm = &$oForm;
        
        if (
$oForm->GetTag($sSource'OPTION'true$aMatches))
        {
            
$sHeader  $aMatches['HEADER'];
            
$sOpenTag $aMatches['OPENTAG'];
            
$sFooter  $aMatches['FOOTER'];
            
            if (
$sStr stristr($sOpenTag'SELECTED'))
            {
                
$sHeader .= rtrim(substr($sOpenTag0strpos($sOpenTag$sStr)));
                
$sFooter substr($sStrstrlen('SELECTED')) . $sFooter;

                
$this->bSelected true;
                
$this->sText $sHeader $sFooter;
            }
            else
            {
                
$this->bSelected false;
                
$this->sText $sSource;
            }
            
            if (
$oForm->GetAttribute($sOpenTag'VALUE'$sStr))
            {
                
$this->sValue $sStr;
            }
            elseif (
$oForm->GetTag($sSource'OPTION'false$aMatches))
            {
                
$sValue $aMatches['INNER'];
                
$this->sValue trim(VLCompressSpaces($sValue));
            }
            elseif (
$oForm->GetTag($sSource'OPTION'true$aMatches))
            {
                
$sValue $aMatches['FOOTER'];
                
$this->sValue trim(VLCompressSpaces($sValue));
            }
        }
        else
        {
            
$this->sValue '';
        }
    }
    
    function 
Out()
    {
        
$sOutput $this->sText;
        
        if (
$this->bSelected)
        {
            
$sFooter strstr($sOutput'>');
            
$sHeader rtrim(substr($sOutput0strpos($sOutput$sFooter)));
            
$sOutput "$sHeader selected$sFooter";
        }
        
        return 
$sOutput;
    }
}

class 
CVLSelect extends CVLInput
{
    var 
$bMultiple;
    var 
$aOptions;
    var 
$aValues;
    
    function 
CVLSelect(&$oForm$sName$sSource)
    {
        
$this->CVLInput($oForm$sName$sSource);
        
        
$this->bMultiple false;
        
$this->aOptions = array();
        
$this->aValues  = array();
        
        if (
$oForm->GetTag($sSource'SELECT'false$aMatches))
        {
            
$sOpenTag $aMatches['OPENTAG'];
            
            if (
strcmp(substr($sNamestrlen($sName) - 22), '[]') == 0)
            {
                
$this->bMultiple true;
                
$this->sName substr($sName0strlen($sName) - 2);
            }
            
            if (
stristr($sOpenTag'multiple') && !$this->bMultiple)
            {
               
trigger_error(VL_W_MULTIPLE_SELECTE_USER_WARNING);
            }
        }

        
$this->sTemplate $this->ParseOptions($sSource);
        
$this->ValueFromOptions();
    }
    
    function 
ParseOptions($sSource)
    {
        while (
$this->oForm->GetTag($sSource'OPTION'true$aMatches))
        {
            
$sHeader $aMatches['HEADER'];
            
$sBody   $aMatches['BODY'];
            
$sFooter $aMatches['FOOTER'];
            
            
$nIdx 0;
            do
            {
                if ((
$nIdx strpos($sFooter'<'$nIdx 1)) !== false)
                {
                    
$nIdx;
                    
$sStr substr($sFooter$nIdx 1);
                }
                else
                {
                    
$nIdx strlen($sFooter);
                    break;
                }
            }
            while (
strcspn($sStr'/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'));
            
            if (
stristr(substr($sFooter$nIdx), '</OPTION') === 0)
            {
                
$this->oForm->GetTag($sSource'OPTION'false$aMatches);
                
                
$sHeader $aMatches['HEADER'];
                
$sBody   $aMatches['BODY'];
                
$sFooter $aMatches['FOOTER'];
            }
            else
            {
                
$sBody  .= substr($sFooter0$nIdx);
                
$sFooter substr($sFooter$nIdx);
            }
            
            
$nIdx sizeof($this->aOptions);
            
$this->aOptions[$nIdx] = new CVLOption($this->oForm$sBody);
            
$sSource "$sHeader%%OPT::$nIdx%%$sFooter";
        }
        
        return 
$sSource;
    }
    
    function 
ValueFromOptions()
    {
        
$nJdx 0;
        for (
$nIdx 0$nIdx sizeof($this->aOptions); $nIdx++)
        {
            if (
$this->aOptions[$nIdx]->bSelected)
            {
                
$this->aValues[$nJdx++] = $this->aOptions[$nIdx]->sValue;
            }
        }
        
$this->sValue join(','$this->aValues);
    }
    
    function 
DeselectAll()
    {
        for (
$nJdx 0$nJdx sizeof($this->aOptions); $nJdx++)
        {
            
$this->aOptions[$nJdx]->bSelected false;
        }
    }
    
    function 
OptionsFromValue()
    {
        
$this->aValues explode(','$this->sValue);
    
        
$this->DeselectAll();
        for (
$nIdx 0$nIdx sizeof($this->aValues); $nIdx++)
        {
            for (
$nJdx 0$nJdx sizeof($this->aOptions); $nJdx++)
            {
                if (!
strcmp($this->aValues[$nIdx], $this->aOptions[$nJdx]->sValue))
                {
                    
$this->aOptions[$nJdx]->bSelected true;
                }
            }
        }
    }
    
    function 
FillValue()
    {
        if (isset(
$_REQUEST[$this->sName]))
        {
            
$this->sValue VLRequest($this->sName);
            
$this->OptionsFromValue();
        }
        else
        {
            
$this->DeselectAll();
            
$this->aValues = array();
            
$this->sValue '';
        }
    }
    
    function 
FillSession()
    {
        if (isset(
$_SESSION[$this->sName]))
        {
            if (
$this->bMultiple)
            {
                
$this->aValues $_SESSION[$this->sName];
                
$this->sValue join(','$this->aValues);
            }
            else
            {
                
$this->sValue $_SESSION[$this->sName];
            }
            
            
$this->OptionsFromValue();
        }
        else
        {
            
$this->DeselectAll();
            
$this->aValues = array();
            
$this->sValue '';
        }
    }
    
    function 
Out()
    {
        
$sOutput $this->sTemplate;
        
        for (
$nIdx 0$nIdx sizeof($this->aOptions); $nIdx++)
        {
            
$sOutput str_replace("%%OPT::$nIdx%%"$this->aOptions[$nIdx]->Out(), $sOutput);
        }
        
        return 
$sOutput;
    }
}

class 
CVLCheck
{
    var 
$bChecked;
    var 
$sText;
    
    function 
CVLCheck($sSource)
    {
        if (
$sStr stristr($sSource'CHECKED'))
        {
            
$sHeader rtrim(substr($sSource0strpos($sSource$sStr)));
            
$sFooter substr($sStrstrlen('CHECKED'));

            
$this->bChecked true;
            
$this->sText $sHeader $sFooter;
        }
        else
        {
            
$this->bChecked false;
            
$this->sText $sSource;
        }
    }
    
    function 
Out()
    {
        
$sOutput $this->sText;
        
        if (
$this->bChecked)
        {
            
$sFooter strstr($sOutput'>');
            
$sHeader rtrim(substr($sOutput0strpos($sOutput$sFooter)));
            
$sOutput "$sHeader checked$sFooter";
        }
        
        return 
$sOutput;
    }
}

class 
CVLChechbox extends CVLInput
{
    var 
$bMultiple;
    var 
$aChecks;
    var 
$aValues;
    
    function 
CVLChechbox(&$oForm$sName)
    {
        if (
strcmp(substr($sNamestrlen($sName) - 22), '[]') == 0)
        {
            
$this->bMultiple true;
            
$sName substr($sName0strlen($sName) - 2);
        }
        else
        {
            
$this->bMultiple false;
        }
        
        
$this->CVLInput($oForm$sName'');
        
        
$this->aChecks = array();
        
$this->aValues  = array();
    }
    
    function 
AddCheck($sSource)
    {
        if (!
$this->oForm->GetAttribute($sSource'VALUE'$sValue))
        {
            
$sValue 'on';
        }
        
        
$this->aChecks[$sValue] = new CVLCheck($sSource);
        
$this->ValueFromChecks();
        
        if (
sizeof($this->aChecks) > && !$this->bMultiple)
        {
           
trigger_error(VL_W_MULTIPLE_CHECKBOXE_USER_WARNING);
        }
            
        return 
$sValue;
    }
    
    function 
ValueFromChecks()
    {
        
$nIdx 0;
        
reset($this->aChecks);
        while (list(
$sValue$oCheck) = each($this->aChecks))
        {
            if (
$this->aChecks[$sValue]->bChecked)
            {
                
$this->aValues[$nIdx++] = $sValue;
            }
        }
        
$this->sValue join(','$this->aValues);
    }
    
    function 
DeselectAll()
    {
        
reset($this->aChecks);
        while (list(
$sValue$oCheck) = each($this->aChecks))
        {
            
$this->aChecks[$sValue]->bChecked false;
        }
    }
    
    function 
ChecksFromValue()
    {
        
$this->aValues explode(','$this->sValue);
    
        
$this->DeselectAll();
        for (
$nIdx 0$nIdx sizeof($this->aValues); $nIdx++)
        {
            
reset($this->aChecks);
            while (list(
$sValue$oCheck) = each($this->aChecks))
            {
                if (!
strcmp($this->aValues[$nIdx], $sValue))
                {
                    
$this->aChecks[$sValue]->bChecked true;
                }
            }
        }
    }
    
    function 
FillValue()
    {
        if (isset(
$_REQUEST[$this->sName]))
        {
            
$this->sValue VLRequest($this->sName);
            
$this->ChecksFromValue();
        }
        else
        {
            
$this->DeselectAll();
            
$this->aValues = array();
            
$this->sValue '';
        }
    }
    
    function 
FillSession()
    {
        if (isset(
$_SESSION[$this->sName]))
        {
            if (
$this->bMultiple)
            {
                
$this->aValues $_SESSION[$this->sName];
                
$this->sValue join(','$this->aValues);
            }
            else
            {
                
$this->sValue $_SESSION[$this->sName];
            }
            
            
$this->ChecksFromValue();
        }
        else
        {
            
$this->DeselectAll();
            
$this->aValues = array();
            
$this->sValue '';
        }
    }
    
    function 
Out($sValue)
    {
        
$sOutput '';
        if (isset(
$this->aChecks[$sValue]))
        {
            
$sOutput $this->aChecks[$sValue]->Out();
        }
        
        return 
$sOutput;
    }
}

class 
CVLRadio extends CVLInput
{
    var 
$aChecks;
    
    function 
CVLRadio(&$oForm$sName)
    {
        
$this->CVLInput($oForm$sName'');
        
        
$this->aChecks = array();
    }
    
    function 
AddCheck($sSource)
    {
        if (!
$this->oForm->GetAttribute($sSource'VALUE'$sValue))
        {
            
$sValue 'on';
        }
        
        
$this->aChecks[$sValue] = new CVLCheck($sSource);
        
$this->ValueFromChecks();
        
        return 
$sValue;
    }
    
    function 
ValueFromChecks()
    {
        
reset($this->aChecks);
        while (list(
$sValue$oCheck) = each($this->aChecks))
        {
            if (
$this->aChecks[$sValue]->bChecked)
            {
                
$this->sValue $sValue;
            }
        }
    }
    
    function 
DeselectAll()
    {
        
reset($this->aChecks);
        while (list(
$sValue$oCheck) = each($this->aChecks))
        {
            
$this->aChecks[$sValue]->bChecked false;
        }
    }
    
    function 
ChecksFromValue()
    {
        
$this->DeselectAll();
        
        
reset($this->aChecks);
        while (list(
$sValue$oCheck) = each($this->aChecks))
        {
            if (!
strcmp($this->sValue$sValue))
            {
                
$this->aChecks[$sValue]->bChecked true;
            }
        }
    }
    
    function 
FillValue()
    {
        if (isset(
$_REQUEST[$this->sName]))
        {
            
$this->sValue VLRequest($this->sName);
            
$this->ChecksFromValue();
        }
        else
        {
            
$this->DeselectAll();
        }
    }
    
    function 
FillSession()
    {
        if (isset(
$_SESSION[$this->sName]))
        {
            
$this->sValue $_SESSION[$this->sName];
            
$this->ChecksFromValue();
        }
        else
        {
            
$this->DeselectAll();
        }
    }
    
    function 
Out($sValue)
    {
        
$sOutput '';
        if (isset(
$this->aChecks[$sValue]))
        {
            
$sOutput $this->aChecks[$sValue]->Out();
        }
        
        return 
$sOutput;
    }
}

class 
CVLValidatorsCollection
{
    var 
$aValidators;
    var 
$sFunction;
    var 
$bSessionSave;
    var 
$bState;
    
    function 
CVLValidatorsCollection($sFunction ''$bSessionSave false)
    {
        
$this->aValidators = array();
        
$this->sFunction $sFunction;
        
$this->bSessionSave $bSessionSave;
        
$this->bState true;
    }
    
    function 
ParseValidators(&$oForm$sSource)
    {
        
// Find <VLVALIDATOR ... >
        
while ($oForm->GetTag($sSource'VLVALIDATOR'true$aMatches))
        {
            
$sHeader    $aMatches['HEADER'];
            
$sValidator $aMatches['BODY'];
            
$sFooter    $aMatches['FOOTER'];
            
            if (
$oForm->GetAttribute($sValidator'NAME'$sName))
            {
                if (!
VLAlphaNumeric($sName))
                {
                    
trigger_error(VL_E_VALIDATOR_NAMEE_USER_ERROR);
                }
            }
            else
            {
                
trigger_error(VL_E_UNNAMED_VALIDATORE_USER_ERROR);
            }
            
            if (!
$oForm->GetAttribute($sValidator'TYPE'$sType))
            {
                
trigger_error(VL_E_UNTYPED_VALIDATORE_USER_ERROR);
            }
            
            
$this->Add($oForm$sName$sType$sValidator);
            
$sSource "$sHeader$sFooter";
        }
        
        return 
$sSource;
    }

    function 
Add(&$oForm$sName$sType$sValidatorTag)
    {
        switch (
strtoupper($sType))
        {
            case 
'REQUIRED':
                
$this->aValidators[$sName] = new CVLReqValidator($oForm$sValidatorTag);
                break;
                
            case 
'CHECKTYPE':
                
$this->aValidators[$sName] = new CVLTypeValidator($oForm$sValidatorTag);
                break;
                
            case 
'RANGE':
                
$this->aValidators[$sName] = new CVLRangeValidator($oForm$sValidatorTag);
                break;
                
            case 
'COMPARE':
                
$this->aValidators[$sName] = new CVLCompareValidator($oForm$sValidatorTag);
                break;
                
            case 
'REGEXP':
                
$this->aValidators[$sName] = new CVLRegExpValidator($oForm$sValidatorTag);
                break;
                
            case 
'EMAIL':
                
$this->aValidators[$sName] = new CVLEmailValidator($oForm$sValidatorTag);
                break;
                
            case 
'CUSTOM':
                
$this->aValidators[$sName] = new CVLCustomValidator($oForm$sValidatorTag);
                break;
                
            default:
                
trigger_error(VL_E_UNKNOWN_VALIDATORE_USER_ERROR);
                break;
        }

    }
    
    function 
IsExist($sName)
    {
        return isset(
$this->aValidators[$sName]);   
    }
    
    function 
GetNames()
    {
        return 
array_keys($this->aValidators);
    }
    
    function 
GetState($sName)
    {
        
$bState true;
        if (isset(
$this->aValidators[$sName]))
        {
            
$bState $this->aValidators[$sName]->bState;
        }
        
        return 
$bState;
    }
    
    function 
GetErrMsg($sName)
    {
        
$sErrMsg '';
        if (isset(
$this->aValidators[$sName]))
        {
            
$sErrMsg $this->aValidators[$sName]->GetErrMsg();
        }
        
        return 
$sErrMsg;
    }

    function 
ValidateAll()
    {
        
$bState true;
        
reset($this->aValidators);
        while (list(
$sName$oValidator) = each($this->aValidators))
        {
            
$bState $this->aValidators[$sName]->Validate() && $bState;
        }
        
$this->bState $bState;
        
        return 
$bState;
    }
}

class 
CVLValidator
{
    var 
$sControl;      // Control to validate
    
var $bState;        // Is control valid?
    
var $sErrMsg;       // Text for page error message
    
    
function CVLValidator(&$oForm$sSource)
    {
        
$this->bState true;

        if (
$oForm->GetAttribute($sSource'CONTROL'$sStr))
        {
            
$this->sControl $sStr;
            if (!isset(
$oForm->aInputs[$this->sControl]))
            {
                
trigger_error(VL_E_CONTROL_NOT_FOUNDE_USER_ERROR);
            }
        }
        else
        {
            
trigger_error(VL_E_CONTROL_NOT_FOUNDE_USER_ERROR);
        }
        
        if (
$oForm->GetAttribute($sSource'ERRMSG'$sStr))
        {
            
$this->sErrMsg $sStr;
        }
    }
    
    function 
GetErrMsg()
    {
        if (
$this->bState)
        {
            return 
'';
        }
        elseif (empty(
$this->sErrMsg))
        {
            return 
'';
        }
        else
        {
            return 
$this->sErrMsg;
        }
    }
}

class 
CVLReqValidator extends CVLValidator
{
    var 
$sInitialValue// Empty Value
    
var $bCase;         // Is validation case sensitive
    
    
function CVLReqValidator(&$oForm$sSource)
    {
        
$this->CVLValidator($oForm$sSource);
        
        if (
$oForm->GetAttribute($sSource'INITIALVALUE'$sStr))
        {
            
$this->sInitialValue $sStr;
        }
        else
        {
            
$this->sInitialValue '';
        }
        
        if (
stristr($sSource'CASESENSITIVE'))
        {
            
$this->bCase true;
        }
        else
        {
            
$this->bCase false;
        }
    }
    
    function 
Validate()
    {
        if (
$this->bCase)
        {
            
$this->bState strcmp(VLRequest($this->sControl), $this->sInitialValue);
        }
        else
        {
            
$this->bState strcasecmp(VLRequest($this->sControl), $this->sInitialValue);
        }
        
        return 
$this->bState;
    }
}

class 
CVLTypeValidator extends CVLValidator
{
    var 
$sValidType;
    var 
$bCase;
    
    function 
CVLTypeValidator(&$oForm$sSource)
    {
        
$this->CVLValidator($oForm$sSource);
        
        if (
$oForm->GetAttribute($sSource'VALIDTYPE'$sStr))
        {
            switch (
strtoupper($sStr))
            {
                case 
'STRING':
                case 
'INTEGER':
                case 
'FLOAT':
                case 
'DATE':
                case 
'CURRENCY':
                    
$this->sValidType strtoupper($sStr);
                    break;
                    
                default:
                    
trigger_error(VL_E_VALIDTYPE_INVALIDE_USER_ERROR);
                    break;
            }
        }
        else
        {
            
trigger_error(VL_E_VALIDTYPE_NOT_FOUNDE_USER_ERROR);
        }
        
        if (
stristr($sSource'CASESENSITIVE'))
        {
            
$this->bCase true;
        }
        else
        {
            
$this->bCase false;
        }
    }
    
    function 
Value2Num($sValue)
    {
        switch (
$this->sValidType)
        {
            case 
'DATE':
                if (
preg_match("|\A(\d{1,2})([-\./])(\d{1,2})\\2(\d{2}(\d{2})?)\z|"$sValue$aMatches))
                {
                    
$nYear = (int)$aMatches[4];
                    if (
strlen($aMatches[4]) == 2)
                    {
                        if (
$nYear 30)
                        {
                            
$nYear += 2000;
                        }
                        else
                        {
                            
$nYear += 1900;
                        }
                    }
                    
$sValue mktime(000$aMatches[1], $aMatches[3], $nYear);
                }
                break;
                
            case 
'INTEGER':
                
$sValue intval($sValue);
                break;
                
            case 
'FLOAT':
            case 
'CURRENCY':
                
$sValue doubleval($sValue);
                break;
        }
        return 
$sValue;
    }
    
    function 
TypeValidate($sValue)
    {
        switch (
$this->sValidType)
        {
            case 
'STRING':
                
$bResult true;
                break;
                
            case 
'INTEGER':
                
$bResult preg_match("/\A[+-]?\d+\z/"$sValue);
                break;
                
            case 
'FLOAT':
                
$bResult preg_match("/\A[+-]?\d*\.?\d+(E[+-]?\d+)?\z/i"$sValue);
                break;
                
            case 
'CURRENCY':
                
$bResult preg_match("/\A\d+(\.\d\d)?\z/"$sValue);
                break;
                
            case 
'DATE':
                if (
preg_match("|\A(\d{1,2})([-\./])(\d{1,2})\\2(\d{2}(\d{2})?)\z|"$sValue$aMatches))
                {
                    
$nYear = (int)$aMatches[4];
                    if (
strlen($aMatches[4]) == 2)
                    {
                        if (
$nYear 30)
                        {
                            
$nYear += 2000;
                        }
                        else
                        {
                            
$nYear += 1900;
                        }
                    }
                    
$bResult checkdate($aMatches[1], $aMatches[3], $nYear);
                }
                else
                {
                    
$bResult false;
                }
                break;
        }
        return 
$bResult;
    }
    
    function 
Validate()
    {
        
$sValue VLRequest($this->sControl);
        if (!
$sValue)
        {
            
$this->bState true;
        }
        else
        {
            
$this->bState $this->TypeValidate($sValue);
        }
       
        return 
$this->bState;
    }
}

class 
CVLRangeValidator extends CVLTypeValidator
{
    var 
$sMinValue;
    var 
$sMaxValue;
    
    function 
CVLRangeValidator(&$oForm$sSource)
    {
        
$this->CVLTypeValidator($oForm$sSource);
        
        if (
$oForm->GetAttribute($sSource'MINVALUE'$sStr))
        {
            
$this->sMinValue $sStr;
            if (!
$this->TypeValidate($this->sMinValue))
            {
                
trigger_error(VL_E_MINVALUE_TYPEE_USER_ERROR);
            }
        }
        
        if (
$oForm->GetAttribute($sSource'MAXVALUE'$sStr))
        {
            
$this->sMaxValue $sStr;
            if (!
$this->TypeValidate($this->sMaxValue))
            {
                
trigger_error(VL_E_MAXVALUE_TYPEE_USER_ERROR);
            }
        }
    }
    
    function 
RangeValidate($sValue)
    {
        if (!
$sValue)
        {
            return 
true;
        }
        elseif (
$this->TypeValidate($sValue) == false)
        {
            return 
false;
        }
        
        
$bMin = isset($this->sMinValue);
        
$bMax = isset($this->sMaxValue);
        
$bResult true;
        
        if (
$this->sValidType == 'STRING')
        {
            if (
$bMin)
            {
                if (
$this->bCase)
                {
                    
$bResult $bResult && strcasecmp($sValue$this->sMinValue) >= 0;
                }
                else
                {
                    
$bResult $bResult && strcmp($sValue$this->sMinValue) >= 0;
                }
            }
            if (
$bMax)
            {
                if (
$this->bCase)
                {
                    
$bResult $bResult && strcasecmp($sValue$this->sMaxValue) <= 0;
                }
                else
                {
                    
$bResult $bResult && strcmp($sValue$this->sMaxValue) <= 0;
                }
            }
        }
        else
        {
            
$nValue $this->Value2Num($sValue);
            
$nMin   $this->Value2Num($this->sMinValue);
            
$nMax   $this->Value2Num($this->sMaxValue);

            if (
$bMin)
            {
                
$bResult $bResult && ($nValue >= $nMin);
            }
            if (
$bMax)
            {
                
$bResult $bResult && ($nValue <= $nMax);
            }
        }
        
        return 
$bResult;
    }
    
    function 
Validate()
    {
        
$sValue VLRequest($this->sControl);
        
$this->bState $this->RangeValidate($sValue);
       
        return 
$this->bState;
    }
}

class 
CVLCompareValidator extends CVLTypeValidator
{
    var 
$sCompareValue;
    var 
$sCompareControl;
    var 
$sOperator;
    
    function 
CVLCompareValidator(&$oForm$sSource)
    {
        
$this->CVLTypeValidator($oForm$sSource);
        
        if (
$oForm->GetAttribute($sSource'COMPAREVALUE'$sStr))
        {
            
$this->sCompareValue $sStr;
            if (!
$this->TypeValidate($this->sCompareValue))
            {
                
trigger_error(VL_E_COMPAREVALUE_TYPEE_USER_ERROR);
            }
        }
        elseif (
$oForm->GetAttribute($sSource'COMPARECONTROL'$sStr))
        {
            
$this->sCompareControl $sStr;
            if (!isset(
$oForm->aInputs[$this->sCompareControl]))
            {
                
trigger_error(VL_E_COMPARECONTROL_NOT_FOUNDE_USER_ERROR);
            }
        }
        else
        {
            
trigger_error(VL_E_COMPAREVALUE_NOT_FOUNDE_USER_ERROR);
        }
        
        if (
$oForm->GetAttribute($sSource'OPERATOR'$sStr))
        {
            
$this->sOperator $sStr;
            
            switch (
strtoupper($this->sOperator))
            {
                case 
'E':
                case 
'NE':
                case 
'G':
                case 
'GE':
                case 
'L':
                case 
'LE':
                    
$this->sOperator strtoupper($this->sOperator);
                    break;
                    
                default:
                    
trigger_error(VL_E_INVALID_OPERATORE_USER_ERROR);
                    break;
            }
        }
        else
        {
            
trigger_error(VL_E_OPERATOR_NOT_FOUNDE_USER_ERROR);
        }
    }
    
    function 
CompareValidate($sValue)
    {
        if (!
$sValue)
        {
            return 
true;
        }
        elseif (!
$this->TypeValidate($sValue))
        {
            return 
false;
        }
        
        if (!isset(
$this->sCompareValue))
        {
            
$sCompareValue VLRequest($this->sCompareControl);
            if (!
$this->TypeValidate($sCompareValue))
            {
                return 
true;
            }
        }
        else
        {
            
$sCompareValue $this->sCompareValue;
        }
        
        if (
$this->sValidType == 'STRING')
        {
            if (
$this->bCase)
            {
                
$nRes strcasecmp($sValue$sCompareValue);
            }
            else
            {
                
$nRes strcmp($sValue$sCompareValue);
            }
            
            switch (
$this->sOperator)
            {
                case 
'E':
                    
$bResult $nRes == 0;
                    break;
                    
                case 
'NE':
                    
$bResult $nRes != 0;
                    break;
                    
                case 
'G':
                    
$bResult $nRes 0;
                    break;
                    
                case 
'GE':
                    
$bResult $nRes >= 0;
                    break;
                    
                case 
'L':
                    
$bResult $nRes 0;
                    break;
                    
                case 
'LE':
                    
$bResult $nRes <= 0;
                    break;
            }
        }
        else
        {
            
$nValue   $this->Value2Num($sValue);
            
$nCompare $this->Value2Num($sCompareValue);

            switch (
$this->sOperator)
            {
                case 
'E':
                    
$bResult $nValue == $nCompare;
                    break;
                    
                case 
'NE':
                    
$bResult $nValue != $nCompare;
                    break;
                    
                case 
'G':
                    
$bResult $nValue $nCompare;
                    break;
                    
                case 
'GE':
                    
$bResult $nValue >= $nCompare;
                    break;
                    
                case 
'L':
                    
$bResult $nValue $nCompare;
                    break;
                    
                case 
'LE':
                    
$bResult $nValue <= $nCompare;
                    break;
            }
        }
        
        return 
$bResult;
    }
    
    function 
Validate()
    {
        
$sValue VLRequest($this->sControl);
        
$this->bState $this->CompareValidate($sValue);
       
        return 
$this->bState;
    }
}

class 
CVLRegExpValidator extends CVLValidator
{
    var 
$sRegExp;
    
    function 
CVLRegExpValidator(&$oForm$sSource)
    {
        
$this->CVLValidator($oForm$sSource);
        
        if (
$oForm->GetAttribute($sSource'REGEXP'$sStr))
        {
            
$this->sRegExp $sStr;
            
            
$aTrans get_html_translation_table(HTML_SPECIALCHARS);
            
$aTrans array_flip($aTrans);
            
$this->sRegExp strtr($this->sRegExp$aTrans);
        }
        else
        {
            
trigger_error(VL_E_REGEXP_NOT_FOUNDE_USER_ERROR);
        }
    }
    
    function 
RegExpValidate($sValue)
    {
        if (!
$sValue)
        {
            return 
true;
        }
        else
        {
            return 
preg_match($this->sRegExp$sValue);
        }
    }
    
    function 
Validate()
    {
        
$sValue VLRequest($this->sControl);
        
$this->bState $this->RegExpValidate($sValue);
       
        return 
$this->bState;
    }
}

class 
CVLEmailValidator extends CVLValidator
{
    function 
CVLEmailValidator(&$oForm$sSource)
    {
        
$this->CVLValidator($oForm$sSource);
    }

    function 
EmailValidate($sValue)
    {
        if (!
$sValue)
        {
            return 
true;
        }
        
        if (
preg_match("/(@.*@)|(\.\.)|(@\.)|(\.@)|(^\.)/"$sValue) ||
           !
preg_match("/^.+\@[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,3}|[0-9]{1,3})$/"$sValue))
        {
            return 
false;
        }
        else
        {
            return 
true;
        }
    }
    
    function 
Validate()
    {
        
$sValue VLRequest($this->sControl);
        
$this->bState $this->EmailValidate($sValue);
       
        return 
$this->bState;
    }
}

class 
CVLCustomValidator extends CVLValidator
{
    var 
$sFunction;
    
    function 
CVLCustomValidator(&$oForm$sSource)
    {
        
$this->CVLValidator($oForm$sSource);
        
        if (
$oForm->GetAttribute($sSource'FUNCTION'$sStr))
        {
            
$this->sFunction $sStr;
            
            if (!
function_exists($this->sFunction))
            {
                
trigger_error(VL_E_FUNCTION_NOT_FOUNDE_USER_ERROR);
            }
        }
        else
        {
            
trigger_error(VL_E_FUNCTION_NOT_FOUNDE_USER_ERROR);
        }
    }
    
    function 
Validate()
    {
        
$sValue VLRequest($this->sControl);
        
$sFunc $this->sFunction;
        
        
$this->bState $sFunc($sValue);
       
        return 
$this->bState;
    }
}

?> 

Comments or questions?
PX is running PHP 5.2.17
Thanks to Miranda Productions for hosting and bandwidth.
Use of any code from PX is at your own risk.