<?php

// LET OP: Deze code kan verouderd zijn!
// Kijk voor de huidige versie op http://www.FormHandler.nl


/**
* class FormHandler
*
* Deze class genereerd automatisch een formulier en handeld de
* data ook direct af.
*
* Auteur: T. Heimans (teye@cyberpoint.nl)
*
* Kijk voor de huidige versie, uitleg en voorbeelden op http://www.FormHandler.nl
* 
*/

// deze twee vars zorgen ervoor dat bij twee formulieren tegelijk maar 1 <form> tag wordt geplaatst
$_COUNTER['FORM']  = 0;
$_COUNTER['FLUSH'] = 0;

class FormHandler {
    var $bFormType;                 // FALSE = toevoeging, TRUE = wijziging
    var $bUseDB;                    // of er een database gebruikt wordt
    var $sOutput;                   // hierin komt het formulier te staan
    var $iEditId;                   // Hierin komt het id van het record welke we wijzigen
    var $dbName;                    // Database naam
    var $dbTable; 	                // De tabel waarin de gegevens staan
    var $dbPrKey;                   // Hierin komt de primaire sleutel te staan
    var $dbFields       = array();  // array waar de veldnamen van de db in komen te staan
    var $bErrors        = FALSE;    // een boolean welke aangeeft of er een fout in het formulier zit
    var $rNames         = array();	// een array waarin de namen van de velden in komen te staan.
    var $rRecords       = FALSE;    // array waar de waarden van de record in komen. Standaard FALSE: records nog niet bekend
    var $rSetVals       = array();  // array waarin de standaard waarden van de velden in komen te staan
    var $rAddVals       = array();  // array, gegevens welke handmatig in de db worden gestopt
    var $rChkBox        = array();  // array waar de namen van de checkbox velden in komen te staan
    var $sOnCorrect     = FALSE;    // hierin komt de naam van de afhandel-functie te staan
    var $sOnSaved       = FALSE;    // hierin komt de afhandel functie VOORDAT er een database-wijziging is gedaan
    var $bUploadForm    = FALSE;    // of het een upload form is of niet...
    var $bSelectList    = FALSE;    // of er een dubbele selectielijst aanwezig is in het formulier
    var $FieldSet       = FALSE;    // of er een kader actief is
    var $iFieldSetCount = 1;        // teller voor de kaders...
    var $bPosted        = FALSE;    // of het formulier gepost is of niet
    var $sMask          = FALSE;    // masker wat gebruikt wordt voor het veld
    var $iMaskCounter   = 1;  		// counter welke gebruikt kan worden binnen de mask functie
    var $rCache         = array();  // chache waar de waarden in komen te staan...
    var $rReturnArray   = array();  // de velden in deze array moeten een array als waarde terug
    var $rSQL           = array();  // de veldnamen waarvan de waarden een SQL functie zijn
    var $classError     = FALSE;    // boolean/String welke aangeeft of er een error in de class is voorgekomen
    var $uploadFields   = array();  // array waar de namen van de uploadvelden in komen te staan
    var $dateFields     = array();  // array waar de datum velden in komen te staan zodat deze in het juiste formaat returned worden
	var $sFocusField    = NULL;
    
    var $_save          = "Opslaan";
    var $_reset         = "Reset";
    var $_cancel        = "Annuleren";
    var $_password      = "Alleen invullen als u uw wachtwoord wilt wijzigen";
    var $_error         = "U heeft geen juiste waarde voor dit veld opgegeven!";
    var $_date          = "De dag-maand-jaar combinatie is niet mogelijk!";
    var $_size          = "De grootte van het bestand overschrijd de maximale toegestane grootte!";
    var $_file          = "Alleen invullen als u de oude waarde wilt vervangen.";
    var $_notFound      = "De door u opgevraagde record is niet gevonden! Waarschijnlijk is deze record verwijderd.";
    var $_back          = "Klik hier om terug te gaan";
    var $_months        = array("Januari", "Februari", "Maart",
                                "April", "Mei", "Juni",
                                "Juli", "Augustus", "September",
                                "Oktober", "November", "December");
    
    /* Deze functie wordt direct aangeroepen wanneer
    de class wordt aangeroepen omdat ze hetzelfde heten. */
    function FormHandler($dbName = FALSE, $dbTable = FALSE, $dbPrKey = FALSE) {
        global $_COUNTER;
        
        // de formulier counter verhogen..
        $_COUNTER["FORM"]++;
        
        if($dbName && $dbTable && $dbPrKey) {
            // tabelgegevens vaststellen
            $this->bUseDB  = TRUE;
            $this->dbName  = $dbName;
            $this->dbTable = $dbTable;
            $this->dbPrKey = $dbPrKey;
        } else {
            $this->bUseDB = FALSE;
        }
        
        if (!defined("SQL") ) define("SQL", "TRUE", TRUE);
        if (!defined("MYSQL") ) define("MYSQL", "TRUE", TRUE);

        // kijken wat voor type formulier het moet worden
        $this->bFormType = !empty($_GET["id"]);
        
        // vertellen als het formulier gepost is
        $this->bPosted = ($_SERVER["REQUEST_METHOD"] == "POST") ? TRUE : FALSE;
        
	    // haal het record welke we wijzigen op. Wanneer dit niet van toepassing is, 0 instellen.
	    $this->iEditId = !empty($_GET["id"]) ? intval($_GET["id"]) : 0;
    }
    
    // functie om de query's uit te voeren
    function query($query, $file = "unknown", $line = 0) {
        $sql = mysql_query($query) or die("MySQL Error: ". mysql_error() ." in $file op regel $line<br />\n<br />\nQuery:".$query);

        return $sql;
    }
    
    // deze functie haalt de gewenste record op uit de database en stopt de resultaten
    // in een array
    function getRecord() {
        // query maken en uitvoeren
        $query = "SELECT * FROM $this->dbTable WHERE $this->dbPrKey = $this->iEditId LIMIT 1";
        $sql = $this->query($query, __FILE__, __LINE__);

        // kijken of er records gevonden zijn en zo ja, in array stoppen
        if(mysql_num_rows($sql) == 1) {
            $row = mysql_fetch_array($sql, MYSQL_ASSOC);

            // wanneer de runtime quotes aanstaan, eerst strippen
            if(get_magic_quotes_runtime()) {
                foreach($row as $fld => $val) {
                    $this->rRecords[$fld] = stripSlashes($row);
                }
            } else {
                $this->rRecords = $row;
            }

            // de veldnamen listen
            foreach($row as $field => $val) {
                $this->dbFields[] = $field;
            }

        } else {
            $this->classError = $this->_notFound .
            "\n<p><a href=\"javascript:history.back()\">".$this->_back."</a></p>";

            trigger_error("Record niet gevonden: ". $query);
        }
    }

    
    // functie welke de waarde van het veld retourneert
    // kan aangeroepen worden met het veldnaam
    function value($sFldName, $bMakeSave = FALSE) {
        // [] aan het einde weghalen
        $sFldName = eregi_replace('^(.*)\[\]$', "\\1", $sFldName);

        // kijken of we de waarde al in het chache hebben...
        if(array_key_exists($sFldName, $this->rCache)) {
            $return = $this->rCache[$sFldName];
            return ($bMakeSave) ? $this->makeSave($return) : $return;
        }
        
        // kijken of het formulier gepost is, zo ja, gegevens uit $_POST halen
        if($this->bPosted) {
            // kijken of het een upload-veld is
            if(array_key_exists($sFldName, $_FILES)) {
                $sValue = $_FILES[$sFldName];
            }
            // kijken of de waarde in $_POST staat
            elseif(array_key_exists($sFldName, $_POST)) {
                // de waarde veilig terug geven
                $sValue = $_POST[$sFldName];
            }
            // kijken of het misschien een datum veld is
            elseif( array_key_exists($sFldName ."_dag", $_POST) &&
                    array_key_exists($sFldName ."_maand", $_POST) &&
                    array_key_exists($sFldName ."_jaar", $_POST) &&
					array_key_exists($sFldName ."_format", $_POST)) {

				// datum-array maken
				$sValue = array("dag"   => $_POST[$sFldName ."_dag"],
								"maand" => $_POST[$sFldName ."_maand"],
								"jaar"  => $_POST[$sFldName ."_jaar"],
								"format"=> $_POST[$sFldName."_format"]);
								
            }
            // kijken of het misschien een time-veld is
            elseif( array_key_exists($sFldName ."_h1", $_POST) &&
                    array_key_exists($sFldName ."_m1", $_POST) &&
                    array_key_exists($sFldName ."_h2", $_POST) &&
                    array_key_exists($sFldName ."_m2", $_POST)) {

                $sValue = $_POST[$sFldName ."_h1"] .":".
                $_POST[$sFldName ."_m1"] ." tot ".
                $_POST[$sFldName ."_h2"] .":".
                $_POST[$sFldName ."_m2"];
            }
            
            // wanneer de waarde gevonden is in de POST array, maak eem escape-teken veilig..
            if(isset($sValue) && get_magic_quotes_gpc() && !array_key_exists($sFldName, $_FILES)) {
                $sValue = $this->makeSave($sValue, "stripslashes");
            }
        } else {
            // kijken wat voor formulier het is (FALSE = toevoeging)
            if(!$this->bFormType) {
                // toevoegingsformulier, lege waarde retourneren
                // wanneer niet bekend in standaard-waarde-array
                $sValue = array_key_exists($sFldName, $this->rSetVals) ? $this->rSetVals[$sFldName] : "";
                
            } elseif($this->bUseDB) {
                // kijken of we de record-gegevens al hebben. Zo niet, ophalen
                if($this->rRecords === FALSE) {
                    $this->getRecord();
                }

                // kijken of de waarde in de record-array staat
        	   if(is_array($this->rRecords) && array_key_exists($sFldName, $this->rRecords)) {
                    // de waarde veilig terug geven
                    $sValue = (in_array($sFldName, $this->rChkBox) && $this->rRecords[$sFldName] == "Ja") ? "on" : $this->rRecords[$sFldName];
                }
            }
        }

        // kijken of we een waarde hebben. Zo niet en hij staat
        // in de checkbox-array, dan is het een checkbox
        // welke niet aanstaat (dus geven we off mee)
        // en anders een lege waarde ("")
        if(!isset($sValue) && in_array($sFldName, $this->rChkBox)) {
            $return = "off";
        } elseif(!isset($sValue)) {
            $return = "";
        } elseif(isset($sValue) && in_array($sFldName, $this->rReturnArray)) {
            $return = !is_array($sValue) ? array($sValue) : $sValue;
        } else {
            $return = $sValue;
        }

        $this->rCache[$sFldName] = $return;
        return ($bMakeSave) ? $this->makeSave($return) : $return;
    }
    
    // functie welke de waarde veilig maakt... (HTMLSpecialChars())
    function makeSave($value, $function = "HTMLSpecialChars") {
        if(is_array($value)) {
            foreach($value as $key => $var) {
                $value[$key] = $function($var);
            }
        } else {
            $value = $function($value);
        }
        return $value;
    }
    
    // een soortgelijke $this->callUserFunction alleen deze accepteert ook
    // bestaande functies
    function callUserFunction($functie, $waarde, $secWaarde = NULL) {

        // omdat isset of empty een language contructor is
        // en deze niet werken met function_exists eerst checken of deze zijn meegegeven
        $reverse = (strPos($functie, "!") === FALSE) ? FALSE : TRUE;
        if($reverse)
            $functie = str_replace('!', '', $functie);
            
        switch (strToLower($functie)) {
            case 'empty':   $output = empty($waarde);   break;
            case 'isset':   $output = isset($waarde);   break;
        }
        
       
        
        // wanneer bekend (dus isset of empty)
        if(isset($output)) {
            return ($reverse) ? !$output : $output;
        } else {
        	$fe = get_defined_functions();
			
			if(in_array($functie, $fe['internal']) ) {
				if (function_exists($functie)) {
					return ($secWaarde == NULL) ? call_user_func($functie, $waarde) : call_user_func($functie, $waarde, $secWaarde);
				} else {
     				trigger_error("Kan geen interne PHP functie aanroepen met call_user_func: $functie");
     			}
            } elseif(in_array(strToLower($functie), $fe['user'])) {
			    return ($secWaarde == NULL) ? call_user_func($functie, $waarde) : call_user_func($functie, $waarde, $secWaarde);
            } else {
                trigger_error("Functie $functie is niet beschikbaar!", E_USER_ERROR);
            }
            
        }
    }
    
    // html toevoegen wanneer gewilt
    function AddHTML($html) {
        $this->sOutput .= $html;
    }

    // betere benaming voor kader
    function KaderStart($legend) {
        $this->FieldSet($legend);
    }
    
    // betere benaming voor kader
    function KaderStop() {
        $this->FieldSet();
    }
    
    // functie welke gebruikers kunnen aanroepen om de focus op een bepaald veld te zetten
    function Focus($sField) {
    	$this->sFocusField = $sField;
    }
    
    // functie om een masker te zetten
    function setMask($sMask = FALSE, $counter = 1) {
        $this->sMask = ($sMask == "") ? FALSE : $sMask;
        $this->iMaskCounter = $counter;
    }

    // de functie welke de kaders plaatst. De functies kaderStart en kaderStop zijn aliassen voor deze functie
    function FieldSet($legend = "") {
        // start kader
        if(!$this->FieldSet) {
            $this->sOutput .=
            " <tr>\n".
            "  <td valign=\"top\" colspan=\"3\">\n".
            "   <br />\n".
            "   <fieldset>\n".
            "    <legend><B><i>". $legend ."</i></B></legend>\n".
            "    <table cellspacing=\"0\" cellpadding=\"4\" id=\"kader".$this->iFieldSetCount++."\">\n";
            
            $this->FieldSet = TRUE;
        } else {
            $this->sOutput .=
            "     </table>\n".
            "    </fieldset>\n".
            "   </td>\n".
            " </tr>\n";
            $this->FieldSet = FALSE;
        }
    }
    
    // functie welke het HTML veld bij de output zet
    // en de error in de error-array zet 
    function generateField($sTitel, $sField, $sName, $sError = TRUE) {

        // kijken of de eventuele error een boolean is
        if(is_bool($sError)) {
            // Wanneer niet TRUE, standaard melding
            if($sError) {
                $sErrMsg = FALSE;
            } else {
                $sErrMsg = $this->_error;
                $this->bErrors = TRUE;
            }
        } else {
            // wanneer een string en niet leeg, dan deze als error beschouwen
            if($sError != "") {
                $sErrMsg = $sError;
                $this->bErrors = TRUE;
            } else {
                $sErrMsg = FALSE;
            }
        }

        // de naam van het veld bij de overige velden zetten
        $this->rNames[] = $sName;

        // veld, titel, teller en error klaarmaken
        $sTitel = str_replace("*", "<font color=\"red\" style=\"color:red\">*</font>", $sTitel);
        $sTitel = ($sErrMsg) ? "<a name=\"error\"></a>" . $sTitel : $sTitel;
        $sErrMsg = ($sErrMsg) ? "<div class=\"errormsg\">". HTMLSpecialChars($sErrMsg)."</div>" : "";

        // HTML rijtje genereren en bij de output stoppen (eventueel met masker)	
        if($this->sMask) {
        	$output = str_replace('%teller%', $this->iMaskCounter, $this->sMask);
            $output = str_replace('%error%', $sErrMsg, $output);
            $output = str_replace('%titel%', $sTitel, $output);
            $this->sOutput .= str_replace('%veld%',  $sField, $output);
        } else {
            $this->sOutput .=
            " <tr>\n".
            "  <td valign=\"top\" nowrap=\"nowrap\">". $sTitel ."</td>\n".
            "  <td valign=\"top\">". (!$sTitel ? "" :":")."</td>\n".
            "  <td valign=\"top\">". $sField . $sErrMsg ."</td>\n".
            " </tr>\n";
        }
        $this->iMaskCounter++;
    }

    // functie om een tekstveld bij de output te stoppen
    function TextField($sTitel, $sName, $sCallBack = FALSE, $iSize = 20, $iMaxLength = 0, $sAddOn = "") {

        // kijken of de waarde gecontroleerd moet worden door een functie en zo ja, doen	
        $sError = ($sCallBack && $this->bPosted) ? $this->callUserFunction($sCallBack, $this->value($sName)) : TRUE;
        
        // als er nul is ingevoerd, 20 pakken
        $iSize = ($iSize == 0) ? 20 : $iSize;

        // maximale veldlengte-regel maken wanneer meegegeven
        $sMaxLength = ($iMaxLength != 0) ? 'maxlength="'. intval($iMaxLength) .'"' : '';
	
        // maak het veld met alle 'instellingen'
        $sField = '<input type="text" name="'. $sName .'" value="'.$this->value($sName, TRUE).'" size="'. $iSize.'" '. $sMaxLength .' '. $sAddOn .' />';

        // het veld bij de HTML output zetten
        $this->generateField($sTitel, $sField, $sName, $sError);
    }

    // functie om een tekstveld bij de output te stoppen
    function PassField($sTitel, $sName, $sCallBack = FALSE, $iSize = 20, $iMaxLength = 0, $sAddOn = "", $bMsg = FALSE) {

        // kijken of de waarde gecontroleerd moet worden door een functie en zo ja, doen	
        $sError = ($sCallBack && $this->bPosted) ? $this->callUserFunction($sCallBack, $this->value($sName)) : TRUE;

        // als er nul is ingevoerd, 20 pakken
        $iSize = ($iSize == 0) ? 20 : $iSize;
        
        // maximale veldlengte-regel maken wanneer meegegeven
        $sMaxLength = ($iMaxLength != 0) ? 'maxlength="'. intval($iMaxLength) .'"' : '';
	
	    $this->sOutput .=($bMsg && !empty($_GET["id"])) ?
        " <tr>\n".
        "  <td valign=\"top\" colspan=\"3\"><font color=\"red\" style=\"font-size: 8pt;\">". $this->_password ."</font></td>\n".
        " </tr>\n":"";

        // maak het veld met alle 'instellingen'
        $sField = '<input type="password" name="'. $sName .'" size="'. $iSize."\" $sMaxLength $sAddOn />";

        // het veld bij de HTML output zetten
        $this->generateField($sTitel, $sField, $sName, $sError);
    }
    
    // functie om een dubbele selectielijst te genereren
    function ListField($sTitel, $sName, $Vls, $sCallBack = FALSE, $installed = "", $non_installed = "", $size = 4, $addOn="") {

        // vertellen dat er een dubbele selectielijst is
        $this->bSelectList = TRUE;

        // kijken of de waarde gecontroleerd moet worden door een functie en zo ja, doen	
        $sError = ($sCallBack && $this->bPosted) ? $this->callUserFunction($sCallBack, $this->value($sName)) : TRUE;

        // geinstalleerde waarden ophalen
        $values = explode(",", str_replace(" ", "", $this->value($sName, TRUE)));
        
        // veld genereren
        $sField =
        "\n".
        "   <input type=\"hidden\" name=\"$sName\" value=\"".$this->value($sName, TRUE)."\" />\n".
        "   <table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n".
        "    <tr>\n".
        "     <td align=\"center\"><b>".$installed."</b></td>\n".
        "     <td align=\"center\"><b> - </b></td>\n".
        "     <td align=\"center\"><b>".$non_installed."</b></td>\n".
        "    </tr>\n".
        "    <tr>\n".
        "     <td rowspan=\"2\" align=\"right\">\n".
        "      <select name=\"".$sName."_ListOn\" size=\"".$size."\" $addOn>\n";

        // geinstalleerde componenten weergeven
        $counter = 0;
        foreach($values as $val) {
        	if(!empty($val) && array_key_exists($val, $Vls)) {
        		$counter++;
        		$sField .=  "       <option value=\"". HTMLSpecialChars($val) ."\">". HTMLSpecialChars($Vls[$val]) ."</option>\n";
        		
        	}
    	}
    	if($counter == 0) {
    		$sField .= "       <option></option>\n";
        }

        $sField .=
        "      </select>\n".
        "     </td>\n".
        "     <td width=\"30\" align=\"center\" valign=\"middle\">\n".
        "      <input type=\"button\" value=\" &gt; \" onclick=\"changeValue('{$sName}', false)\" />\n".
        "     </td>\n".
        "     <td rowspan=\"2\">\n".
        "      <select name=\"".$sName."_ListOff\" size=\"".$size."\" $addOn>\n";

        // niet geinstallleerde componenten weergeven
        foreach($Vls as $key => $val) {
            if(!in_array($key, $values))
            $sField .=  "       <option value=\"". HTMLSpecialChars($key) ."\">". HTMLSpecialChars($val) ."</option>\n";
        }
        
        $sField .=
        "      </select>\n".
        "     </td>\n".
        "    </tr>\n".
        "    <tr>\n".
        "     <td align=\"center\" valign=\"middle\">\n".
        "      <input type=\"button\" value=\" &lt; \" onclick=\"changeValue('{$sName}', true)\" />\n".
        "     </td>\n".
        "    </tr>\n".
        "   </table>\n ";
        
        // het veld bij de HTML output zetten
        $this->generateField($sTitel, $sField, $sName, $sError);
    }
    
    // functie om een tekstveld bij de output te stoppen
    function TextArea($sTitel, $sName, $sCallBack = FALSE, $iCols = 40, $iRows = 7, $sAddOn = "") {

        // kijken of de waarde gecontroleerd moet worden door een functie en zo ja, doen	
        $sError = ($sCallBack && $this->bPosted) ? $this->callUserFunction($sCallBack, $this->value($sName)) : TRUE;

        // maak het veld met alle 'instellingen'
        $sField = "<textarea name=\"$sName\" cols=\"$iCols\" rows=\"$iRows\" $sAddOn>".$this->value($sName, TRUE)."</textarea>";

        // het veld bij de HTML output zetten
        $this->generateField($sTitel, $sField, $sName, $sError);
    }

    // functie om een checkbox te genereren
    function CheckBox($sTitel, $sName, $rValues = "on", $sCallBack = FALSE, $bUseKeyAsValue = TRUE, $sAddOn = "", $sGlue = "<br />\n") {
        static $counter = 1;
        
        // naam veilig maken
        $sName = eregi_replace('^(.*)\[\]$', "\\1", $sName);

        // vertellen dat dit een checkbox is
        $this->rChkBox[] = $sName;

        // waarde ophalen
        $val = $this->value($sName);
        
        // kijken of de waarde gecontroleerd moet worden door een functie en zo ja, doen	
        $sError = ($sCallBack && $this->bPosted) ? $this->callUserFunction($sCallBack, $val) : TRUE;

        // kijken of ze een array meegeven als waarden
        $sField = '';
        if(is_array($rValues)) {
            // wanneer de waarde uit de db komt, array van maken
            if(!is_array($val)) {
                if(@unSerialize($val)) {
                    $val = unSerialize($val);
                } else {
                    $val = explode(", ", $val);
                }
            }
            foreach($rValues as $key => $value) {
                $key = ($bUseKeyAsValue ? $key : $value);

                $sField .= "<input type=\"checkbox\" name=\"".$sName."[]\" id=\"checkbox".$counter."\" ".(in_array($key, $val)?'checked="checked"':"").
                " value=\"$key\" $sAddOn /> <label for=\"checkbox".$counter++."\">$value</label>". $sGlue;
            }
        } else {
            // wanneer de waarde een sting is, gewoon weergeven
            $key = ($rValues == $val) ? ' checked="checked"' : "";
            $sField .= "<input type=\"checkbox\" name=\"$sName\" id=\"checkbox".$counter."\" value=\"$rValues\" $sAddOn $key />".
            " <label for=\"checkbox".$counter++."\">".(($rValues == "on") ? "" : $rValues) ."</label>".str_replace('<br />', '', $sGlue);
        }

        // het veld bij de HTML output zetten
        $this->generateField($sTitel, $sField, $sName, $sError);
    }
    
    // functie om een checkbox te genereren
    function RadioButton($sTitel, $sName, $rValues = "on", $sCallBack = FALSE, $bUseKeyAsValue = TRUE, $sAddOn = "", $sGlue = "<br />\n") {
        static $counter = 1;

        // naam veilig maken
        $sName = eregi_replace('^(.*)\[\]$', "\\1", $sName);

        // vertellen dat dit een radio button is (en dus de waarde off moet krijgen als ie leeg is)
        $this->rChkBox[] = $sName;

        // waarde ophalen
        $val = $this->value($sName);

        // kijken of de waarde gecontroleerd moet worden door een functie en zo ja, doen	
        $sError = ($sCallBack && $this->bPosted) ? $this->callUserFunction($sCallBack, $val) : TRUE;

        // kijken of ze een array meegeven als waarden
        $sField = '';
        if(is_array($rValues)) {
            foreach($rValues as $key => $value) {
                $key = ($bUseKeyAsValue ? $key : $value);

                $sField .= "<input type=\"radio\" name=\"$sName\" id=\"radio".$counter."\" ".(($key == $val)?'checked="checked"':"").
                " value=\"$key\" $sAddOn /> <label for=\"radio".$counter++."\">$value</label>". $sGlue;
            }
        } else {
            // wanneer de waarde een sting is, gewoon weergeven
            $key = ($rValues == $val) ? ' checked="checked"' : "";
            $sField .= "<input type=\"radio\" name=\"$sName\" id=\"radio".$counter."\" value=\"$rValues\" $sAddOn $key />".
            " <label for=\"radio".$counter++."\">".(($rValues == "on") ? "" : $rValues) ."</label>".str_replace('<br />', '', $sGlue);
        }

        // het veld bij de HTML output zetten
        $this->generateField($sTitel, $sField, $sName, $sError);
    }
    
    // functie welke een radiobutton-lijst  genereerd (OUDE BENAMING)
    function RadioBtns($sTitel, $sName, $rValues = "on", $sCallBack = FALSE, $bUseKeyAsValue = TRUE, $sAddOn = "", $sGlue = "<br />\n") {
        $this->RadioButton($sTitel, $sName, $rValues, $sCallBack, $bUseKeyAsValue, $sAddOn, $sGlue);
    }
    
    // functie welke een selectielijst genereerd
    function SelectField ($sTitel, $sName, $rValues, $bUseKey = TRUE, $sCallBack = FALSE, $iSize = 1, $sAddOn = "") {
        // controle of $rValues wel een array is
        if(!is_array($rValues)) {
             trigger_error("U dient een array als waarden mee te geven!", E_USER_ERROR);
        }
        
        // waarde ophalen van het veld
        $val = $this->value($sName);

        // kijken of de waarde gecontroleerd moet worden door een functie en zo ja, doen	
        $sError = ($sCallBack && $this->bPosted) ? $this->callUserFunction($sCallBack, $val) : TRUE;

        // beginnen met veld genereren
        $sField = '<select name="'.$sName.'" '. $sAddOn .' size="'.$iSize.'">';
        
        // alle waarden langslopen en bij het veld stoppen
        $label = FALSE;
        foreach($rValues as $key => $value ) {

            // kijken of de waarde een label is
            if(ereg("LABEL", $key)) {
                $sField .= "\n\t<optgroup label=\"". HTMLSpecialChars($value)."\">";
            } else {
                // juiste 'value' pakken
                $key = HTMLSpecialChars($bUseKey ? $key : $value);
            
                // kijken welke geselecteerd is
                $selected = ($key == $val) ? " selected" : "";
            
                // waarde bij het veld stoppen
                $sField .=
                "\n\t<option value=\"".$key.'"'.$selected.'>'. HTMLSpecialChars($value) .'</option>';
            }
        }
        
        // veld afsluiten
        $sField .= "\n  </select>";
        
        // het veld bij de HTML output zetten
        $this->generateField($sTitel, $sField, $sName, $sError);
    }
    
    // veld om een bestand te uploaden
    function UploadField($sTitel, $sName, $sCallBack = FALSE, $maxFileSize = FALSE, $sAddOn = "", $bOverWrite = TRUE) {
        // zorgen dat het een upload form wordt
        $this->bUploadForm = TRUE;
        $this->uploadFields[] = $sName;
        
        // waarde ff in een veld stoppen zodat we deze niet vaker hoeven op te halen
        $FILE = $this->value($sName);

        // kijken of de waarde gecontroleerd moet worden door een functie en zo ja, doen	
        $sError = ($sCallBack && $this->bPosted) ? $this->callUserFunction($sCallBack, $FILE) : TRUE;

        // maximum upload groote vaststellen wanneer gewenst
        if($maxFileSize) {
            if(is_array($FILE) && array_key_exists("error", $FILE)) {
                if($FILE["error"] == 2 || $FILE["error"] == 3) {
                    $sError = $this->_size;
                }
            }
        }

        $msg = (!empty($_GET["id"]) && $bOverWrite && (is_string($FILE) && $FILE != "")) ?"<small style=\"color: red\">". $this->_file ."</small><br />\n\t" : "";
        $sField = $msg ."<input type=\"file\" name=\"".$sName."\" {$sAddOn} />";
        
        // het veld bij de HTML output zetten
        $this->generateField($sTitel, $sField, $sName, $sError);
    }
    
    // functie welke een datum veld voor ons genereerd
    function TimeField ($sTitel, $sName, $sCallBack = FALSE) {
        //waarden ophalen
        list($v, $t) = explode(" tot ", ($this->value($sName) == "") ? ("0:00 tot 0:00") : $this->value($sName));
        list($vHour, $vMinute) = explode(":", $v);
        list($tHour, $tMinute) = explode(":", $t);

        // kijken of de waarde gecontroleerd moet worden door een functie en zo ja, doen	
        $sError = ($sCallBack && $this->bPosted) ? $this->callUserFunction($sCallBack, $this->value($sName)) : TRUE;

        // uur-start-veld genereren
        $sField = '<select name="'. $sName.'_h1">';
        for($i = 0; $i <= 23; $i++) {
            $sField .= "\n\t<option value=\"$i\"".(($vHour == $i) ? " selected" : "").">". sprintf("%02d", $i) ."</option>";
        }
        $sField .=
        "\n    </select>\n".
        '    <select name="'.$sName.'_m1">';

        // minuut-start-veld genereren
        for($i = 0; $i <= 45; $i+=15) {
            $sField .= "\n\t<option value=\"".sprintf("%02d", $i)."\"".(($vMinute==$i) ? " selected" : "").">". sprintf("%02d", $i) ."</option>";
        }
        $sField .=
        "\n    </select> <b> tot </b> \n".
        '    <select name="'.$sName.'_h2">';

        // uur-tot-veld
        for($i = 0; $i <= 23; $i++) {
            $sField .= "\n\t<option value=\"$i\"".(($tHour == $i) ? " selected" : "").">". sprintf("%02d", $i) ."</option>";
        }
        $sField .=
        "\n    </select>\n".
        '    <select name="'.$sName.'_m2">';
        
        // minuut-tot-veld genereren
        for($i = 0; $i <= 45; $i+=15) {
            $sField .= "\n\t<option value=\"". sprintf("%02d", $i)."\"".(($tMinute==$i) ? " selected" : "").">". sprintf("%02d", $i) ."</option>";
        }
        $sField .= "\n    </select>\n";

        // het veld bij de HTML output zetten
        $this->generateField($sTitel, $sField, $sName, $sError);
    }
    
    // functie welke een datum veld voor ons genereerd
    function DateField ($sTitel, $sName, $sCallBack = FALSE, $format = "Y-m-d") {
        //waarden ophalen
        $value = $this->value($sName);
        
        $this->dateFields[] = $sName;

		// zijn de waarden gepost ?
		if(is_array($value)) {
			$dag    = $value["dag"];
			$maand  = $value["maand"];
			$jaar   = $value["jaar"];
			$format = $value["format"];
		} else {
			if(ereg("^([0-9]{4})[-]([0-9]{1,2})[-]([0-9]{1,2})$", $value)) {
				list($jaar, $maand, $dag) = explode("-", $value);
        	} else {
            	list($dag, $maand, $jaar) = explode("-", (($value == "") ? date("j-n-Y") : $value));
        	}
        }

        // kijken of de waarde gecontroleerd moet worden door een functie en zo ja, doen	
        $sError = ($sCallBack && $this->bPosted) ? $this->callUserFunction($sCallBack, $value) : TRUE;

        // maanden array voor mooie namen ipv nummers
        $maanden = $this->_months;
                         
        // dag-veld genereren
        $sField = '<select name="'. $sName.'_dag">';
        for($i = 1; $i <= 31; $i++) {
            $selected = ($dag == $i) ? ' selected="selected"' : "";
            $sField .= "\n\t<option value=\"". sprintf("%02d", $i) ."\"{$selected}>{$i}</option>";
        }
        $sField .=
        "\n    </select>\n".
        '    <select name="'.$sName.'_maand">';

        // Maand-veld genereren
        for($i = 0; $i < count($maanden); $i++) {
            $selected = ($maand==$i+1) ? ' selected="selected"' : "";
            $sField .= "\n\t<option value=\"". sprintf("%02d", $i+1) ."\"{$selected}>". $maanden[$i]."</option>";
        }
        $sField .=
        "\n    </select>\n".
        '    <select name="'.$sName.'_jaar">';

        // Jaar-veld genereren (nu tot 90 jaar geleden)
        for($i = date("Y")+10; $i >= date("Y")-90;  $i--) {
            $selected = ($i==$jaar) ? ' selected="selected"': "";
            $sField .= "\n\t<option value=\"".$i."\"".$selected.">".$i."</option>";
        }
        $sField .=
		"\n    </select>\n".
        "\n    <input type=\"hidden\" size=\"5\" value=\"$format\" name=\"".$sName."_format\" />\n";
        
        // tot slot een automatische datum-checker
        if($_SERVER['REQUEST_METHOD'] == 'POST' && !checkdate($maand, $dag, $jaar)) {
        	$sError = $this->_date;
        }
        
        // het veld bij de HTML output zetten
        $this->generateField($sTitel, $sField, $sName, $sError);
    }
    
    // functie welke een setje data-handeling knoppen bij de output zet
    function SubmitBtn($gotoUrl = FALSE) {
        // wanneer geen masker opgegeven door de gebruiker,
        // gebruik dan eigen masker...
        if($this->sMask === FALSE) {
            $setMask = TRUE;
            $this->setMask(
            " <tr>\n".
            "  <td colspan=\"3\">\n".
            "    %veld%\n".
            "   </td>\n".
            " </tr>\n");
        }

        $field =
        "   <input type=\"submit\" value=\"Opslaan\" />\n".
        "   <input type=\"reset\" value=\"Reset\" />\n".
        "   <input type=\"button\" onclick=\"". (!$gotoUrl ? "javascript:history.back(1)" : "location.href='".$gotoUrl."'") ."\" value=\"Annuleren\" />\n";

        // het veld bij de HTML output zetten
        $this->generateField('', $field, '');

        // masker afsluiten
        if(isset($setMaks)) {
            $this->setMask();
        }
    }
    
    // functie welke de waarde van een veld vult... (VOORDAT het veld gecreerd wordt, aanroepen!)
    function setValue($sField, $sValue, $bMakeSave = TRUE) {
        if(is_array($sValue) && $bMakeSave) {
            foreach($sValue as $key => $value) {
                $sValue[$key] = HTMLSpecialChars($value);
            }
        } elseif($bMakeSave) {
            $sValue = HTMLSpecialChars($sValue);
        }

        $this->rSetVals[$sField] = $sValue;
    }
    
    // functie welke de gebruiker kan aanroepen om handmatig een waarde in de db te stoppen
    function addValue ($sField, $sValue, $MYSQL = FALSE, $bMakeSave = TRUE) {
        if(!$this->bUseDB) {
            trigger_error("De functie addValue kan alleen worden gebruikt als u correcte database gegevens meegeeft!", E_USER_ERROR);
        } else {
            if($MYSQL) {
                $this->rSQL[] = $sField;
            } else {
                $key = array_search($sField, $this->rSQL);
                if($key) {
                    unset($this->rSQL[$key]);
                }
            }

		    $this->rAddVals[$sField] = (!$bMakeSave) ? $sValue : HTMLSpecialChars($sValue);
		}
    }
    
    // afhandelfunctie wanneer het formulier correct is maar nog niet opgeslagen
    function onCorrect($sCallBack) {
        $this->sOnCorrect = $sCallBack;
    }
    
    // afhandelfunctie wanneer het formulier is opgeslagen in de tabel
    function onSaved($sCallBack) {
        $this->sOnSaved = $sCallBack;
    }
    
    // OUDE AFHANDLEFUNCTIE VOOR OnSaved
	// NIET GEBRUIKEN!
    function whenFinished($sCallBack) {
        $this->sOnSaved = $sCallBack;
    }
    
    // OUDE AFHANDELFUNCTIE VOOR onCorrect
    // NIET GEBRUIKEN!
    function beforeFinished($sCallBack) {
        $this->sOnCorrect = $sCallBack;
    }
    
    // functie welke de output retourneert
    function flushForm($returnValue = FALSE) {
        global $_COUNTER;

        $_COUNTER["FLUSH"]++;

        // kijken of er een afhandelfunctie gesteld is
        if((!$this->sOnCorrect && !$this->sOnSaved) || (!$this->sOnCorrect && !$this->bUseDB)) {
            trigger_error("U heeft geen juiste afhandel-functie opgegeven!", E_USER_ERROR);
        }

        // kijken of er fouten in het formulier zitten en of het formulier wel gepost is
        if($this->classError !== FALSE) {
            $this->sOutput = "<h3>Error!</h3>\n". $this->classError;
        } else {
            if(!$this->bErrors && $this->bPosted) {
	            // we gaan kijken of de veldnamen wel bekend zijn.. zo niet, dan helen we deze nog ff op
	            if(sizeof($this->dbFields) == 0 && $this->bUseDB) {
	                // veldnamen ophalen
	                $fields = mysql_list_fields($this->dbName, $this->dbTable);

	                // veldnamen in array stoppen
	                if(!$fields) {
	                	trigger_error("Gebruik van de MySQL optie maar geen connectie beschikbaar!", E_USER_WARNING);
	                	$this->bUseDB = FALSE;
	                } else {
	                	for ($i = 0; $i < mysql_num_fields($fields); $i++) {
	                    	$this->dbFields[] =  mysql_field_name($fields, $i);
	                	}
	                }
	            }

	            $rFieldValues = array();
	            // voordat we de query gaan genereren, maken we een array met de velden en waarden
	            foreach( $this->rNames as $field ) {
	                if(!empty($field)) {
	                	// kijken of het een datum veld is
	                	// zo ja, dan juiste formaat retourneren
	                 	if(in_array($field, $this->dateFields)) {
	                 		$var = $this->value($field);
	                 		$rFieldValues[$field] = str_replace(array("y", "m", "d"),
							                                    array($var["jaar"], $var["maand"], $var["dag"]),
																strToLower($var["format"]));
	                 	} else {
	                 		$rFieldValues[$field] = $this->value($field);
	                 	}
	                }
	            }

	            // alle door de gebruiker toegevoegde waarden in de array stoppen
	            foreach($this->rAddVals as $field => $value) {
	            	$rFieldValues[$field] = $value;
	            }

	            // gebruikersfunctie aanroepen voor de db-wijziging
	            if($this->sOnCorrect != FALSE) {
	            	$sign= (ini_get('allow_call_time_pass_reference') ||  ini_set('allow_call_time_pass_reference', 'On'))  ? "&":"";
					eval("\$this->callUserFunction(\$this->sOnCorrect, $sign\$rFieldValues);");
	             }

	            // De waarden klaarstomen voor de query...
	            if(is_array($rFieldValues)) {
	                foreach($rFieldValues as $field => $value) {

						// ** nieuw
						// uploadveld ?
						if(!in_array($field, $this->uploadFields)) {

	                        $value = is_array($value) ? serialize($value) : $value;
	                        $queryValues[$field] = !in_array($field, $this->rSQL)? "'". mysql_escape_string($value) ."'": $value;
	                    }
	                }
	            }

	            // Query maken... wijzigen of toevoegen?? (en zijn er eigenlijk wel waarden?)
	            if($this->iEditId > 0 && isset($queryValues)) {
	                // Update query maken voor wijziginen opslaan
	                $query = "UPDATE ". $this->dbTable ." SET \n";

	                // gegevens in query stoppen
	                foreach($queryValues as $field => $value) {
	                    // kijken of het veld wel in de db staat
	                    if(in_array($field, $this->dbFields)) {
	                        $query .= $field ." = ". $value .", \n";
	                    }
	                }

	                // laatste komma weghalen en WHERE gedeelte achter plakken
	                $query = substr($query, 0, -3) . " WHERE ". $this->dbPrKey ." = ". $this->iEditId;

	            } elseif(isset($queryValues)) {
	                // temporary varabelen voor listen van velden en waarden
	                $fields = "";
	                $values = "";
	                foreach($queryValues as $field => $value) {
	                    // kijken of het veld wel in de db staat
	                    if(in_array($field, $this->dbFields)) {
	                        $fields .= $field .", \n";
	                        $values .= $value .", \n";
	                    }
	                }
	                if(!strlen($fields) && !strlen($values)) {
	                    $query = FALSE;
	                } else {
	                    // query maken
	                    $query = "INSERT INTO ". $this->dbTable ." (\n".
	                    substr($fields, 0, -3) .
	                    ") VALUES (\n".
	                    substr($values, 0, -3) . ")";
	                }
	            } else {
	                $query = FALSE;
	            }

	            // query uitvoeren
	            if($query)
	                $sql = $this->query($query, __FILE__, __LINE__);

	            // record-id pakken van de gewijzigde of toegevoegde
	            $RID = ($this->iEditId > 0) ? $this->iEditId : ((isset($query) && $this->bUseDB) ? mysql_insert_id() : "Database functions are not used...");

	            // de afhandel functie uitvoeren
	            if($this->sOnSaved != FALSE) {
	                if($query === FALSE || $this->bUseDB === FALSE) {
	                    trigger_error("U kunt geen gebruik maken van de 'onSaved' functie als u geen gebruik maakt van de MySQL databse opties. Maak gebruik van de 'onCorrect' functie.", E_USER_WARNING);
	                } else {
	                    $this->callUserFunction($this->sOnSaved, $RID, $rFieldValues);
	                }
	            }
            }

			// output pakken
            $this->sOutput =
            (($_COUNTER["FLUSH"] == 1) ?
            "<form name=\"AutoGeneratedForm\" action=\"".$_SERVER["PHP_SELF"].(!empty($_SERVER["QUERY_STRING"])?"?".$_SERVER["QUERY_STRING"]:"")."#error\" ".
			"method=\"post\" ". ($this->bUploadForm ? 'enctype="multipart/form-data"' : "") . ">\r\n".
            "<table>\r\n" : "") .
            $this->sOutput.
            (($_COUNTER["FLUSH"] == $_COUNTER["FORM"]) ? "</table>\r\n</form>\r\n" : "");

			// javascript welke voor het script gebruikt wordt
			$javascript =
			"\n".
            "<!-- Benodigde javascript voor de dubbele selectielijsten en het focus veld -->\n".
            "<script type=\"text/javascript\">\n".
            "<!-- // javascript verbergen voor oude browsers \n";
            
            // focus leggen
            if($this->sFocusField != NULL) {
            	$field = str_replace('[]', '', $this->sFocusField);
            	if(in_array($field, $this->rNames)) {
            		$this->sOutput .=
					"<script type=\"text/javascript\">\n".
            		"<!-- // javascript verbergen voor oude browsers \n".
					"document.forms['AutoGeneratedForm'].elements['".$field."'].focus();\n".
					" //-->\n".
            		"</script>\n";
            	} else {
            		trigger_error("Kan de focus niet legge op het veld $field omdat deze niet bekent is!");
            	}
            }

			// javascript voor de dubbele selectielijst
            if($this->bSelectList != FALSE) {
                $javascript .=
                "function changeValue(prefix, install) {\n".
                "    // velden vaststellen\n".
                "    var FromField = document.forms['AutoGeneratedForm'].elements[prefix+(install?\"_ListOff\":\"_ListOn\")];\n".
                "    var ToField   = document.forms['AutoGeneratedForm'].elements[prefix+(install?\"_ListOn\":\"_ListOff\")];\n\n".
                "    // kijken of er wel wat geselecteerd is\n".
                "    if(FromField.value != \"\") {\n".
                "        // het aantal opties uit de 'nieuwe' lijst halen\n".
                "        var len = ToField.options.length;\n\n".
                "        // de optie in de nieuwe lijst toevoegen\n".
                "        ToField.options[len] = new Option(FromField.options[FromField.selectedIndex].text);\n".
                "        ToField.options[len].value = FromField.options[FromField.selectedIndex].value;\n".
                "        ToField.options[len].selected = true;\n\n".
                "        // de optie verwijderen uit de 'oude' lijst\n".
                "        FromField.options[FromField.selectedIndex] = null;\n".
                "        FromField.focus();\n".
                "    }\n\n".
                "    // de geinstalleerde waarden in het text-veld stoppen\n".
                "    var InstalledVars = \" \";\n".
                "    var Installed = document.forms['AutoGeneratedForm'].elements[prefix+'_ListOn'];\n\n".
                "    for(i = 0; i < Installed.options.length; i++) {\n".
                "        InstalledVars += Installed.options[i].value + \", \";\n".
                "    }\n".
                "    document.forms['AutoGeneratedForm'].elements[prefix].value = InstalledVars;\n".
                "}\n";
                

            }
            
            $javascript .=
            " //-->\n".
            "</script>\n".
            "<!-- Einde javascript voor de dubbele selectielijsten -->\n\n";
        }

        // retourneren wanneer gewenst
        if($returnValue) {
            return $javascript . $this->sOutput;
        } else {
            echo $javascript . $this->sOutput;
        }
    }
}

?>