/**
  * validates a value and returns error string, or false if field is valid.
  *
  * @param string $value
  * @param string $datatype
  * @param int $min
  * @param int $max
  */
 static function validateValue($value, $datatype, $min, $max)
 {
     $invert_match = true;
     $invalidated = false;
     switch ($datatype) {
         case "num":
             $pattern = "/[^\\d]/";
             break;
         case "float":
             $pattern = "/[^\\d\\.]/";
             break;
         case "date":
             // two types: ymd, dmy
             $pattern = "/([\\d]{4}-[\\d]{1,2}-[\\d]{1,2}|[\\d]{1,2}-[\\d]{1,2}-[\\d]{4})/";
             $invert_match = false;
             /* dates only HAVE certain ranges */
             $max = 10;
             if ($min > 0) {
                 $min = 8;
             } else {
                 if (empty($value)) {
                     return true;
                 }
             }
             $a = explode("-", $value);
             if (count($a) != 3) {
                 $invalidated = true;
                 break;
             }
             list($d1, $d2, $d3) = $a;
             if (empty($d1) || empty($d2) || empty($d3)) {
                 $invalidated = true;
                 break;
             }
             if (strlen($d1) == 4) {
                 $y = $d1;
                 $m = $d2;
                 $d = $d3;
             } else {
                 if (strlen($d3) == 4) {
                     if ($d2 < 12) {
                         $d = $d1;
                         $m = $d2;
                         $y = $d3;
                     } else {
                         $m = $d1;
                         $d = $d2;
                         $y = $d3;
                     }
                 } else {
                     $invalidated = true;
                     break;
                 }
             }
             if (!checkdate($m, $d, $y)) {
                 $invalidated = "Impossible date";
                 break;
             }
             break;
         case "string":
             $pattern = "/[^\\w\\s\\.\\/\\&\\+\\(\\)\\:,-@\\.]/";
             break;
         case "allstring":
             $pattern = "/[^\\w\\s\\.\\/\\&\\+\\(\\)\\:\\!,-@\\.]/";
             break;
         case "email":
             $pattern = '/^([.0-9a-z_-]+)@(([0-9a-z-]+\\.)+[0-9a-z]{2,4})$/i';
             $invert_match = false;
             break;
         case "url":
             $pattern = "/[^\\w\\.\\(\\)-]/";
             break;
         case "phone":
             $pattern = "/[^\\d\\(\\)\\s\\+-]/";
             break;
         default:
             $pattern = "/[^\\w\\s\\.,-]/";
     }
     /* validate field */
     if (strlen($value) < $min) {
         if ($min == 1) {
             $invalidated = "Required field.";
         } else {
             $invalidated = "Needs to be at least {$min} characters, is " . strlen($value) . ".";
         }
     } else {
         if (strlen($value) > $max) {
             $invalidated = "May not exceed {$max} characters, is " . strlen($value) . ".";
         } else {
             if (preg_match($pattern, $value)) {
                 if ($invert_match) {
                     $invalidated = cForm::valexpl($datatype);
                 }
             } else {
                 if (!$invert_match && strlen($value) > 0) {
                     $invalidated = cForm::valexpl($datatype);
                 }
             }
         }
     }
     if ($invalidated === true) {
         $invalidated = "Invalid value.";
     }
     return $invalidated;
 }