2008年5月9日 星期五

[PHP]最強表單驗證

這幾天一直在處理表單驗證的方法,在因緣際會下發現了個強大的表單驗證程式Validator。

這表單驗證的方式是使用物件的方式,只要將需驗證的item標上dataType,便可根據此dataType做出各種規則的驗證方式。


表單驗證 Validator v1.05 作者:我佛山人 <原文連結>

Validator目前可實現的驗證類型有:
1.是否為空;
2.中文字符;
3.雙字節字符
4.英文;
5.數字;
6.整數;
7.實數;
8.Email地址;
9.使用HTTP協議的網址;
10.電話號碼;
11.貨幣;
12.手機號碼;
13.郵政編碼;
14.身份證號碼(1.05增強);
15.QQ號碼;
16.日期;
17.符合安全規則的密碼;
18.某項的重複值;
19.兩數的關係比較;
20.判斷輸入值是否在(n, m)區間;
21.輸入字符長度限制(可按字節比較);
22.對於具有相同名稱的單選按鈕的選中判斷;
23.限制具有相同名稱的多選按鈕的選中數目;
24.自定義的正則表達式驗證;
25.文件上傳格式過濾(1.04)

##CONTINUE##

更新歷史:

1.01
修正對12月份的日期驗證(感謝flylg999)

1.03
修正Range驗證類型時將數字當字符串比較的bug(感謝cncom和xtlhnhbb)
修正日期驗證(感謝Papsam)
增加Username驗證類型
增加對Phone驗證類型時支持分機號

1.04
增加文件格式的過濾,用於上傳時限制上傳的文件格式

1.05
增強對身份證號碼的驗證


JavaScript版

<title>表單驗證類 Validator v1.05</title>
<style>
body,td{font:normal 12px Verdana;color:#333333}
input,textarea,select,td{font:normal 12px Verdana;color:#333333;border:1px solid #999999;background:#ffffff}
table{border-collapse:collapse;}
td{padding:3px}
input{height:20;}
textarea{width:80%;height:50px;overflow:auto;}
form{display:inline}
</style>
<table align="center">
<form name="theForm" id="demo" method="get" onSubmit="return Validator.Validate(this,2)">
<tr>
<td>身份證號:</td><td><input name="Card" dataType="IdCard" msg="身份證號錯誤"></td>
</tr>
<tr>
<td>真實姓名:</td><td><input name="Name" dataType="Chinese" msg="真實姓名只允許中文"></td>
</tr>
<tr>
<td>ID:</td><td><input name="username" dataType="Username" msg="ID名不符合規定"></td>
</tr>
<tr>
<td>英文名:</td><td><input name="Nick" dataType="English" require="false" msg="英文名只允許英文字母"></td>
</tr>
<tr>
<td>主頁:</td><td><input name="Homepage" require="false" dataType="Url" msg="非法的Url"></td>
</tr>
<tr>
<td>密碼:</td><td><input name="Password" dataType="SafeString" msg="密碼不符合安全規則" type="password"></td>
</tr>
<tr>
<td>重複:</td><td><input name="Repeat" dataType="Repeat" to="Password" msg="兩次輸入的密碼不一致" type="password"></td>
</tr>
<tr>
<td>信箱:</td><td><input name="Email" dataType="Email" msg="信箱格式不正確"></td>
</tr>
<tr>
<td>信箱:</td><td><input name="Email" dataType="Repeat" to="Email" msg="兩次輸入的信箱不一致"></td>
</tr>
<tr>
<td>QQ:</td><td><input name="QQ" require="false" dataType="QQ" msg="QQ號碼不存在"></td>
</tr>
<tr>
<td>身份證:</td><td><input name="Card" dataType="IdCard" msg="身份證號碼不正確"></td>
</tr>
<tr>
<td>年齡:</td><td><input name="Year" dataType="Range" msg="年齡必須在18~28之間" min="18" max="28"></td>
</tr>
<tr>
<td>年齡1:</td><td><input name="Year1" require="false" dataType="Compare" msg="年齡必須在18以上" to="18" operator="GreaterThanEqual"></td>
</tr>
<tr>
<td>電話:</td><td><input name="Phone" require="false" dataType="Phone" msg="電話號碼不正確"></td>
</tr>
<tr>
<td>手機:</td><td><input name="Mobile" require="false" dataType="Mobile" msg="手機號碼不正確"></td>
</tr>
<tr>
<td>生日:</td><td><input name="Birthday" dataType="Date" format="ymd" msg="生日日期不存在"></td>
</tr>
<tr>
<td>郵政編碼:</td><td><input name="Zip" dataType="Custom" regexp="^[1-9]\d{5}$" msg="郵政編碼不存在"></td>
</tr>
<tr>
<td>郵政編碼:</td><td><input name="Zip1" dataType="Zip" msg="郵政編碼不存在"></td>
</tr>
<tr>
<td>操作系統:</td><td><select name="Operation" dataType="Require" msg="未選擇所用操作系統" ><option value="">選擇您所用的操作系統</option><option value="Win98">Win98</option><option value="Win2k">Win2k</option><option value="WinXP">WinXP</option></select></td>
</tr>
<tr>
<td>所在省份:</td><td>廣東<input name="Province" value="1" type="radio">陝西<input name="Province" value="2" type="radio">浙江<input name="Province" value="3" type="radio">江西<input name="Province" value="4" type="radio" dataType="Group" msg="必須選定一個省份" ></td>
</tr>
<tr>
<td>愛好:</td><td>運動<input name="Favorite" value="1" type="checkbox">上網<input name="Favorite" value="2" type="checkbox">聽音樂<input name="Favorite" value="3" type="checkbox">看書<input name="Favorite" value="4" type="checkbox"" dataType="Group" min="2" max="3" msg="必須選擇2~3種愛好"></td>
</tr>
<td>自我介紹:</td><td><textarea name="Description" dataType="Limit" max="10" msg="自我介紹內容必須在10個字之內">中文是一個字</textarea></td>
</tr>
<td>自傳:</td><td><textarea name="History" dataType="LimitB" min="3" max="10" msg="自傳內容必須在[3,10]個字節之內">中文是兩個字節t</textarea></td>
</tr>
<tr>
<td>相片上傳:</td><td><input name="up" dataType="Filter" msg="非法的文件格式" type="file" accept="jpg, gif, png"></td>
</tr>
<tr>
<td colspan="2"><input name="Submit" type="submit" value="確定提交"><input onClick="Validator.Validate(document.getElementById('demo'))" value="檢驗模式1" type="button"><input onClick="Validator.Validate(document.getElementById('demo'),2)" value="檢驗模式2" type="button"><input onClick="Validator.Validate(document.getElementById('demo'),3)" value="檢驗模式3" type="button"></td>
</tr>
</form>
</table>
<script>
/*************************************************
Validator v1.05
code by 我佛山人
wfsr@msn.com
*************************************************/
Validator = {
Require : /.+/,
Email : /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/,
Phone : /^((\(\d{2,3}\))|(\d{3}\-))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9]\d{6,7}(\-\d{1,4})?$/,
Mobile : /^((\(\d{2,3}\))|(\d{3}\-))?13\d{9}$/,
Url : /^http:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>\"\"])*$/,
IdCard : "this.IsIdCard(value)",
Currency : /^\d+(\.\d+)?$/,
Number : /^\d+$/,
Zip : /^[1-9]\d{5}$/,
QQ : /^[1-9]\d{4,8}$/,
Integer : /^[-\+]?\d+$/,
Double : /^[-\+]?\d+(\.\d+)?$/,
English : /^[A-Za-z]+$/,
Chinese : /^[\u0391-\uFFE5]+$/,
Username : /^[a-z]\w{3,}$/i,
UnSafe : /^(([A-Z]*|[a-z]*|\d*|[-_\~!@#\$%\^&\*\.\(\)\[\]\{\}<>\?\\\/\'\"]*)|.{0,5})$|\s/,
IsSafe : function(str){return !this.UnSafe.test(str);},
SafeString : "this.IsSafe(value)",
Filter : "this.DoFilter(value, getAttribute('accept'))",
Limit : "this.limit(value.length,getAttribute('min'), getAttribute('max'))",
LimitB : "this.limit(this.LenB(value), getAttribute('min'), getAttribute('max'))",
Date : "this.IsDate(value, getAttribute('min'), getAttribute('format'))",
Repeat : "value == document.getElementsByName(getAttribute('to'))[0].value",
Range : "getAttribute('min') < (value|0) && (value|0) < getAttribute('max')",
Compare : "this.compare(value,getAttribute('operator'),getAttribute('to'))",
Custom : "this.Exec(value, getAttribute('regexp'))",
Group : "this.MustChecked(getAttribute('name'), getAttribute('min'), getAttribute('max'))",
ErrorItem : [document.forms[0]],
ErrorMessage : ["以下原因導致提交失敗:\t\t\t\t"],
Validate : function(theForm, mode){
var obj = theForm || event.srcElement;
var count = obj.elements.length;
this.ErrorMessage.length = 1;
this.ErrorItem.length = 1;
this.ErrorItem[0] = obj;
for(var i=0;i<count;i++){
with(obj.elements[i]){
var _dataType = getAttribute("dataType");
if(typeof(_dataType) == "object" || typeof(this[_dataType]) == "undefined") continue;
this.ClearState(obj.elements[i]);
if(getAttribute("require") == "false" && value == "") continue;
switch(_dataType){
case "IdCard" :
case "Date" :
case "Repeat" :
case "Range" :
case "Compare" :
case "Custom" :
case "Group" :
case "Limit" :
case "LimitB" :
case "SafeString" :
case "Filter" :
if(!eval(this[_dataType])) {
this.AddError(i, getAttribute("msg"));
}
break;
default :
if(!this[_dataType].test(value)){
this.AddError(i, getAttribute("msg"));
}
break;
}
}
}
if(this.ErrorMessage.length > 1){
mode = mode || 1;
var errCount = this.ErrorItem.length;
switch(mode){
case 2 :
for(var i=1;i<errCount;i++)
this.ErrorItem[i].style.color = "red";
case 1 :
alert(this.ErrorMessage.join("\n"));
this.ErrorItem[1].focus();
break;
case 3 :
for(var i=1;i<errCount;i++){
try{
var span = document.createElement("SPAN");
span.id = "__ErrorMessagePanel";
span.style.color = "red";
this.ErrorItem[i].parentNode.appendChild(span);
span.innerHTML = this.ErrorMessage[i].replace(/\d+:/,"*");
}
catch(e){alert(e.description);}
}
this.ErrorItem[1].focus();
break;
default :
alert(this.ErrorMessage.join("\n"));
break;
}
return false;
}
return true;
},
limit : function(len,min, max){
min = min || 0;
max = max || Number.MAX_VALUE;
return min <= len && len <= max;
},
LenB : function(str){
return str.replace(/[^\x00-\xff]/g,"**").length;
},
ClearState : function(elem){
with(elem){
if(style.color == "red")
style.color = "";
var lastNode = parentNode.childNodes[parentNode.childNodes.length-1];
if(lastNode.id == "__ErrorMessagePanel")
parentNode.removeChild(lastNode);
}
},
AddError : function(index, str){
this.ErrorItem[this.ErrorItem.length] = this.ErrorItem[0].elements[index];
this.ErrorMessage[this.ErrorMessage.length] = this.ErrorMessage.length + ":" + str;
},
Exec : function(op, reg){
return new RegExp(reg,"g").test(op);
},
compare : function(op1,operator,op2){
switch (operator) {
case "NotEqual":
return (op1 != op2);
case "GreaterThan":
return (op1 > op2);
case "GreaterThanEqual":
return (op1 >= op2);
case "LessThan":
return (op1 < op2);
case "LessThanEqual":
return (op1 <= op2);
default:
return (op1 == op2);
}
},
MustChecked : function(name, min, max){
var groups = document.getElementsByName(name);
var hasChecked = 0;
min = min || 1;
max = max || groups.length;
for(var i=groups.length-1;i>=0;i--)
if(groups[i].checked) hasChecked++;
return min <= hasChecked && hasChecked <= max;
},
DoFilter : function(input, filter){
return new RegExp("^.+\.(?=EXT)(EXT)$".replace(/EXT/g, filter.split(/\s*,\s*/).join("|")), "gi").test(input);
},
IsIdCard : function(number){
var date, Ai;
var verify = "10x98765432";
var Wi = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
var area = ['','','','','','','','','','','','北京','天津','河北','山西','內蒙古','','','','','','遼寧','吉林','黑龍江','','','','','','','','上海','江蘇','浙江','安微','福建','江西','山東','','','','河南','湖北','湖南','廣東','廣西','海南','','','','重慶','四川','貴州','雲南','西藏','','','','','','','陝西','甘肅','青海','寧夏','新疆','','','','','','台灣','','','','','','','','','','香港','澳門','','','','','','','','','國外'];
var re = number.match(/^(\d{2})\d{4}(((\d{2})(\d{2})(\d{2})(\d{3}))|((\d{4})(\d{2})(\d{2})(\d{3}[x\d])))$/i);
if(re == null) return false;
if(re[1] >= area.length || area[re[1]] == "") return false;
if(re[2].length == 12){
Ai = number.substr(0, 17);
date = [re[9], re[10], re[11]].join("-");
}
else{
Ai = number.substr(0, 6) + "19" + number.substr(6);
date = ["19" + re[4], re[5], re[6]].join("-");
}
if(!this.IsDate(date, "ymd")) return false;
var sum = 0;
for(var i = 0;i<=16;i++){
sum += Ai.charAt(i) * Wi[i];
}
Ai += verify.charAt(sum%11);
return (number.length ==15 || number.length == 18 && number == Ai);
},
IsDate : function(op, formatString){
formatString = formatString || "ymd";
var m, year, month, day;
switch(formatString){
case "ymd" :
m = op.match(new RegExp("^((\\d{4})|(\\d{2}))([-./])(\\d{1,2})\\4(\\d{1,2})$"));
if(m == null ) return false;
day = m[6];
month = m[5]*1;
year = (m[2].length == 4) ? m[2] : GetFullYear(parseInt(m[3], 10));
break;
case "dmy" :
m = op.match(new RegExp("^(\\d{1,2})([-./])(\\d{1,2})\\2((\\d{4})|(\\d{2}))$"));
if(m == null ) return false;
day = m[1];
month = m[3]*1;
year = (m[5].length == 4) ? m[5] : GetFullYear(parseInt(m[6], 10));
break;
default :
break;
}
if(!parseInt(month)) return false;
month = month==0 ?12:month;
var date = new Date(year, month-1, day);
return (typeof(date) == "object" && year == date.getFullYear() && month == (date.getMonth()+1) && day == date.getDate());
function GetFullYear(y){return ((y<30 ? "20" : "19") + y)|0;}
}
}
</script>


PHP版程式碼

<title>表單驗證類 Validator for PHP β</title>
<style>
body,td{font:normal 12px Verdana;color:#333333}
input,textarea,select,td{font:normal 12px Verdana;color:#333333;border:1px solid #999999;background:#ffffff}
table{border-collapse:collapse;}
td{padding:3px}
input{height:20;}
textarea{width:80%;height:50px;overfmin:auto;}
form{display:inline}
</style>
<table align="center">
<form action="Validator.php" method="post">
<tr>
<td>提示模式:</td><td>
<select name="emode">
<option value="1">警告提示框(客戶端)</option>
<option value="2">提示框加紅色文字提示</option>
<option value="3">附加紅色提示</option>
<option value="4">警告提示框(服務器端)</option>
<option value="5">文字提示(服務器端)</option>
</select></td>
</tr>
<tr>
<td>真實姓名:</td><td><input name="Name"></td>
</tr>
<tr>
<td>英文名:</td><td><input name="Nick"></td>
</tr>
<tr>
<td>主頁:</td><td><input name="Homepage"></td>
</tr>
<tr>
<td>密碼:</td><td><input name="Password"></td>
</tr>
<tr>
<td>重複:</td><td><input name="Repeat"></td>
</tr>
<tr>
<td>信箱:</td><td><input name="Email"></td>
</tr>
<tr>
<td>信箱:</td><td><input name="Email1"></td>
</tr>
<tr>
<td>QQ:</td><td><input name="QQ"></td>
</tr>
<tr>
<td>身份證:</td><td><input name="Card"></td>
</tr>
<tr>
<td>年齡:</td><td><input name="Year"></td>
</tr>
<tr>
<td>年齡1:</td><td><input name="Year1"></td>
</tr>
<tr>
<td>電話:</td><td><input name="Phone"></td>
</tr>
<tr>
<td>手機:</td><td><input name="Mobile"></td>
</tr>
<tr>
<td>生日:</td><td><input name="Birthday"></td>
</tr>
<tr>
<td>郵政編碼:</td><td><input name="Zip"></td>
</tr>
<tr>
<td>郵政編碼:</td><td><input name="Zip1"></td>
</tr>
<tr>
<td>操作系統:</td><td><select name="OS"><option value="">選擇您所用的操作系統</option><option value="Win98">Win98</option><option value="Win2k">Win2k</option><option value="WinXP">WinXP</option></select></td>
</tr>
<tr>
<td>所在省份:</td><td>廣東<input name="Province" value="1" type="radio">陝西<input name="Province" value="2" type="radio">浙江<input name="Province" value="3" type="radio">江西<input name="Province" value="4" type="radio"></td>
</tr>
<tr>
<td>愛好:</td><td>運動<input name="Favorite" value="1" type="checkbox">上網<input name="Favorite" value="2" type="checkbox">聽音樂<input name="Favorite" value="3" type="checkbox">看書<input name="Favorite" value="4" type="checkbox"></td>
</tr>
<td>自我介紹:</td><td><textarea name="Description">中文是一個字</textarea></td>
</tr>
<td>自傳:</td><td><textarea name="History">中文是兩個字節t</textarea></td>
</tr>
<tr>
<td colspan="2"><input name="Submit" type="submit" value="確定提交"></td>
</tr>
</form>
</table>
<script defer>
/*************************************************
Validator for PHP β 客戶端腳本
code by 我佛山人
wfsr@cunite.com
http://www.cunite.com
*************************************************/
function dispError(items, messages, mode, separator){
var iArray = items.split(separator);
for(var i=iArray.length-1;i>=0;i--)
iArray[i] = getObj(iArray[i]);
messages = ("以下原因導致提交失敗:\t\t\t\t" + separator + messages).split(separator);
switch(mode){
case 2 :
for(i=iArray.length-1;i>=0;i--)
iArray[i].style.color = "red";
case 1 :
alert(messages.join("\n"));
iArray[0].focus();
break;
case 3 :
for(i=iArray.length-1;i>=0;i--){
try{
var span = document.createElement("SPAN");
span.id = "__ErrorMessagePanel";
span.style.color = "red";
iArray[i].parentNode.appendChild(span);
span.innerHTML = messages[i+1].replace(/\d+:/,"*");
}
catch(e){alert(e.description);}
}
iArray[0].focus();
break;
}
}

function getObj(name){
var objs = document.getElementsByName(name);
return objs[objs.length -1];
}
</script>
<?php
class Validator{
/*************************************************
Validator for PHP β 服務器端腳本
code by 我佛山人
wfsr@cunite.com
http://www.cunite.com
*************************************************/
var $submit;
var $error_item, $error_message, $error_mode, $error_no;
function Validator($submit_name = "Submit", $mode = 5){
$this->submit = $submit_name;
$this->error_mode = $mode;
$this->error_no = 1;
}

function Validate($arr){
if(! isset($_POST[$this->submit])) return false;
$this->error_mode = $_POST["emode"];
echo "<script defer>document.getElementsByName(\"emode\")[0].selectedIndex =" . ($this->error_mode - 1) . "</script>";
if(is_array($arr)){
$len = count($arr);
for($i = 0; $i < $len; $i++){
$this->is_valid($arr[$i]);
}
}

if($this->error_no > 1)
$this->display_error();
}

function is_valid($str){
$str = split(",", $str);
if(count($str) < 3) return false;
$name = trim($str[0]);
$message = trim($str[1]);
$data_type = trim($str[2]);
$value = trim($_POST[$name]);

switch($data_type){
case "compare" :
break;
case "range" :
break;
case "repeat" :
break;
default :
$method = "is_".$data_type;
if(!$this->$method($value))
$this->add_error($name, $message);
break;
}
}

function add_error($name, $message){
$this->error_item .= "," . $name;
$this->error_message .= "," . $this->error_no . ":" . $message;
$this->error_no ++;
}

function display_error(){
$this->error_item = ereg_replace("^,+", "", $this->error_item);
$this->error_message = ereg_replace("^,+", "", $this->error_message);

switch($this->error_mode){
case 4 :
$info = "以下原因導致提交失敗:\t\t\t\t,";
echo "<script>alert(\"".join("\\n", split(",", $info . $this->error_message))."\")</script>";
//print >>>end;
break;
case 5 :
echo "輸入有錯誤:<br /><ul><li>" . ereg_replace( "\b\d+:", "",join("</li><li>", split(",", $this->error_message))) . "</li></ul>";
echo "<br /><a href='javascript:history.back()'>返回</a>";
exit;
break;
default :
echo "<script defer>dispError(\"" . $this->error_item . "\", \"" . $this->error_message . "\", " . $this->error_mode . ", \",\")</script>";
break;
}
}

function is_email($str){
return preg_match("/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/", $str);
}

function is_url($str){
return preg_match("/^http:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>\"])*$/", $str);
}

function is_qq($str){
return preg_match("/^[1-9]\d{4,8}$/", $str);
}

function is_zip($str){
return preg_match("/^[1-9]\d{5}$/", $str);
}

function is_idcard($str){
return preg_match("/^\d{15}(\d{2}[A-Za-z0-9])?$/", $str);
}

function is_chinese($str){
return ereg("^[".chr(0xa1)."-".chr(0xff)."]+$",$str);
}

function is_english($str){
return preg_match("/^[A-Za-z]+$/", $str);
}

function is_mobile($str){
return preg_match("/^((\(\d{3}\))|(\d{3}\-))?13\d{9}$/", $str);
}

function is_phone($str){
return preg_match("/^((\(\d{3}\))|(\d{3}\-))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9]\d{6,7}$/", $str);
}

function is_safe($str){
return (preg_match("/^(([A-Z]*|[a-z]*|\d*|[-_\~!@#\$%\^&\*\.\(\)\[\]\{\}<>\?\\\/\'\"]*)|.{0,5})$|\s/", $str) != 0);
}
}
$v = new Validator();
$v->Validate(array("Name,名字只允許中文,chinese", "Nick, 只允許英文暱稱, english", "Homepage, 主頁Url格式不正確, url", "Password, 密碼不符合安全規則, safe","Email,信箱格式錯誤,email", "QQ, QQ號碼不存在, qq","Card, 身份證號碼不正確, idcard","Phone, 電話號碼不存在, phone","Mobile, 手機號碼不存在, mobile","Zip, 郵政編碼不存在, zip"));
?>


ASP版程式碼

<%
Class Validator
'*************************************************
' Validator for ASP beta 2 服務器端腳本
' code by 我佛山人
' wfsr@cunite.com
' http://www.cunite.com
'*************************************************
Private Re, Dic
Private Separator
Private ErrorItem, ErrorMessage, ErrorMode, ErrorNo
Private FormName, FormIndex, FilePath, GetMethod

Private Sub Class_Initialize()
Set Re = New RegExp
Re.IgnoreCase = True
Re.Global = True
Set Dic = CreateObject("Scripting.Dictionary")
Separator = ","
ErrorItem = ""
ErrorMessage = ""
ErrorMode = 5
ErrorNo = 1
FilePath = Server.MapPath(Request.ServerVariables("Script_Name"))
GetMethod = "FSO"
End Sub

Private Sub Class_Terminate()
Set Re = Nothing
Dic.RemoveAll()
Set Dic = Nothing
End Sub

Public Sub Validate()
IF Request("Submit")="" Then Exit Sub
IF Not IsValidPost() Then Exit Sub

With Dic
.Add "Compare", "Compare( PostValue, operator, toObj)"
.Add "Custom", "Custom( PostValue,regexp )"
.Add "Date", "IsDateFormat( PostValue,format )"
.Add "Limit", "Limit( PostValue,min, max )"
.Add "LimitB", "LimitB( PostValue,min, max )"
.Add "Range", "Range( PostValue,min, max )"
.Add "Repeat", "IsEqual( PostValue, Request(toObj) )"
.Add "Group", "Group( PostValue,min, max )"

.Add "NotEqual", "Op1 <> Op2"
.Add "GreaterThan", "Op1 > Op2"
.Add "GreaterThanEqual", "Op1 >= Op2"
.Add "LessThan", "Op1 < Op2"
.Add "LessThanEqual", "Op1 <= Op2"
.Add "Equal", "Op1 = Op2"
End With

Call MatchCode()

IF ErrorMessage <> "" Then DisplayError
End Sub

Private Sub MatchCode()
Dim bI, bG, bM
Dim Str

Select Case GetMethod
Case "FSO" :
Dim FSO : Set FSO = Server.CreateObject("Scripting.FileSystemObject")
Set TS = FSO.OpenTextFile(FilePath, 1, false)
Str = TS.ReadAll()
TS.Close
Set TS = Nothing
Set FSO = Nothing
Case "XMLHTTP" :
Dim XHttp : Set XHttp = Server.CreateObject("MSXML2.XMLHTTP")
With XHttp
Call .Open("Get", "http://"&Request.ServerVariables("Server_Name")&Request.ServerVariables("Script_Name"), False)
Call .Send()
Str =B2S(.responseBody)
End With
Set XHttp = Nothing
End Select
Dim itemString
With Re
bI = .IgnoreCase
bG = .Global
bM = .MultiLine
.IgnoreCase = True
.Global = True
.Pattern = "[\s\S]*<form [^>]+>([\s\S]+)<\/form>[\s\S]*"
Str = .Replace(Str, "$1")

.Global = True
.MultiLine = True
.Pattern = "<\/?(?!input|textarea|select)[^>]*>"
Str = .Replace(Str, "")

.Pattern = "^.*(<(?=input|textarea|select)[^>]*>).*$"
Str = .Replace(Str, "$1")

.Pattern = "([\r\n]+|^\s*)(?=<)"
Str = .Replace(Str, "")
While Test("dataType=([""\'])([^""\'>]+)\1", Str)
.MultiLine = False
.Pattern = "^([^\n]+)\n([\s\S]*)$"
itemString = .Replace(Str, "$1")
Str = .Replace(Str, "$2")
.Pattern = "(name|dataType|to1|min|max|msg|require|regexp|format)=([""\'])([^""\'>]+)\2"

Dim Matches : Set Matches = .Execute(itemString)
Dim Match, RetStr : RetStr = ""
For Each Match in Matches
RetStr = RetStr & Match.Value & " : "
Next
Call IsValid(Replace(Replace(Replace(RetStr, " : $", ""), "to=", "toObj="), """Require""", """NotEmpty"""))
Wend
.IgnoreCase = bI
.Global = bG
.MultiLine = bM

End With
End Sub

Private Sub IsValid(ByVal Str)
Dim name, msg, dataType, toObj, min, max, require, regexp, format
min = 1 : max = 100 : require = "true" : format = "YMD"
Execute Str
Dim PostValue : PostValue = Request(name)
Dim Fun

IF require = "false" AND PostValue = "" Then Exit Sub

IF Dic.Exists(dataType) Then
Fun = Dic.Item(dataType)
Else Fun = "Is" & dataType &"( PostValue )"
End IF

IF Not Eval(Fun) Then Call AddError(name,msg)
End Sub

Private Sub DisplayError()
ErrorItem = Replace(ErrorItem, "^(" & Separator & ")", "")
ErrorMessage = Replace(ErrorMessage, "^(" & Separator & ")", "")
Select Case ErrorMode
Case 4
ErrorMessage = Join(Split(ErrorMessage, Separator), "</li><li>")
Response.Clear
Response.Write "<div style=""padding-left:100px;font:bold 12px Tahoma"">輸入有錯誤:<br><ul><li>" & Replace(ErrorMessage, "\b\d+:", "") & "</li></ul>"
Response.Write "<br><a href='javascript:history.back()'>返回重填</a></div>"
Response.End
Case Else
Response.Write("<script defer>dispError(""" & ErrorItem & """, """ & ErrorMessage & """, " & ErrorMode & ", """ & Separator & """)</script>")
End Select
End Sub

Public Function IsEmail(ByVal Str)
IsEmail = Test("^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$", Str)
End Function

Public Function IsUrl(ByVal Str)
IsUrl = Test("^http:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>""])*$", Str)
End Function

Public Function IsNum(ByVal Str)
IsNum= Test("^\d+$", Str)
End Function

Public Function IsQQ(ByVal Str)
IsQQ = Test("^[1-9]\d{4,8}$", Str)
End Function

Public Function IsZip(ByVal Str)
IsZip = Test("^[1-9]\d{5}$", Str)
End Function

Public Function IsIdCard(ByVal Str)
IsIdCard = Test("^\d{15}(\d{2}[A-Za-z0-9])?$", Str)
End Function

Public Function IsChinese(ByVal Str)
IsChinese = Test("^[\u0391-\uFFE5]+$", Str)
End Function

Public Function IsEnglish(ByVal Str)
IsEnglish = Test("^[A-Za-z]+$", Str)
End Function

Public Function IsMobile(ByVal Str)
IsMobile = Test("^((\(\d{3}\))|(\d{3}\-))?13\d{9}$", Str)
End Function

Public Function IsPhone(ByVal Str)
IsPhone = Test("^((\(\d{3}\))|(\d{3}\-))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9]\d{6,7}$", Str)
End Function

Public Function IsSafe(ByVal Str)
IsSafe = (Test("^(([A-Z]*|[a-z]*|\d*|[-_\~!@#\$%\^&\*\.\(\)\[\]\{\}<>\?\\\/\'\""]*)|.{0,5})$|\s", Str) = False)
End Function

Public Function IsNotEmpty(ByVal Str)
IsNotEmpty = LenB(Str) > 0
End Function

Public Function IsDateFormat(ByVal Str, ByVal Format)
IF Not IsDate(Str) Then
IsDateFormat = False
Exit Function
End IF

IF Format = "YMD" Then
IsDateFormat = Test("^((\d{4})|(\d{2}))([-./])(\d{1,2})\4(\d{1,2})$", Str)
Else
IsDateFormat = Test("^(\d{1,2})([-./])(\d{1,2})\\2((\d{4})|(\d{2}))$", Str)
End IF
End Function

Public Function IsEqual(ByVal Src, ByVal Tar)
IsEqual = (Src = Tar)
End Function

Public Function Compare(ByVal Op1, ByVal Operator, ByVal Op2)
Compare = False
IF Dic.Exists(Operator) Then
Compare = Eval(Dic.Item(Operator))
Elseif IsNotEmpty(Op1) Then
Compare = Eval(Op1 & Operator & Op2 )
End IF
End Function

Public Function Range(ByVal Src, ByVal Min, ByVal Max)
Min = CInt(Min) : Max = CInt(Max)
Range = (Min < Src And Src < Max)
End Function

Public Function Group(ByVal Src, ByVal Min, ByVal Max)
Min = CInt(Min) : Max = CInt(Max)
Dim Num : Num = UBound(Split(Src, ",")) + 1
Group = Range(Num, Min - 1, Max + 1)
End Function

Public Function Custom(ByVal Str, ByVal Reg)
Custom = Test(Reg, Str)
End Function

Public Function Limit(ByVal Str, ByVal Min, ByVal Max)
Min = CInt(Min) : Max = CInt(Max)
Dim L : L = Len(Str)
Limit = (Min <= L And L <= Max)
End Function

Public Function LimitB(ByVal Str, ByVal Min, ByVal Max)
Min = CInt(Min) : Max = CInt(Max)
Dim L : L =bLen(Str)
LimitB = (Min <= L And L <= Max)
End Function

Private Function Test(ByVal Pattern, ByVal Str)
Re.Pattern = Pattern
Test = Re.Test(Str)
End Function

Public Function bLen(ByVal Str)
bLen = Len(Replace(Str, "[^\x00-\xFF]", ".."))
End Function

Private Function Replace(ByVal Str, ByVal Pattern, ByVal ReStr)
Re.Pattern = Pattern
Replace = Re.Replace(Str, ReStr)
End Function

Private Function B2S(ByVal iStr)
Dim reVal : reVal= ""
Dim i, Code, nCode
For i = 1 to LenB(iStr)
Code = AscB(MidB(iStr, i, 1))
IF Code < &h80 Then
reVal = reVal & Chr(Code)
Else
nCode = AscB(MidB(iStr, i+1, 1))
reVal = reVal & Chr(CLng(Code) * &h100 + CInt(nCode))
i = i + 1
End IF
Next
B2S = reVal
End Function

Private Sub AddError(ByVal Name, ByVal Message)
ErrorItem = ErrorItem & Separator & Name
ErrorMessage = ErrorMessage & Separator & ErrorNo & ":" & Message
ErrorNo = ErrorNo + 1
End Sub

Public Function IsValidPost()
Dim Url1 : Url1 = Cstr(Request.ServerVariables("HTTP_REFERER"))
Dim Url2 : Url2 = Cstr(Request.ServerVariables("SERVER_NAME"))
IsValidPost = (Mid(Url1, 8, Len(Url2)) = Url2)
End Function

Public Property Let Mode(ByVal Val)
ErrorMode = CInt(Val)
End Property

Public Property Let Form(ByVal Val)
IF IsNumeric(Val) Then
FormIndex = Val
Else
FormName = Val
End IF
End Property

Public Property Let Path(ByVal Val)
IF Test("^[A-Za-z]:\\\w+$", Val) Then
FilePath = Val
Else
FilePath = Server.MapPath(Val)
End IF
End Property

Public Property Let Method(ByVal Val)
GetMethod = Val
End Property
End Class
%>
<title>表單驗證類 Validator v1.0</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<style>
body,td{font:normal 12px Verdana;color:#333333}
input,textarea,select,td{font:normal 12px Verdana;color:#333333;border:1px solid #999999;background:#ffffff}
table{border-collapse:collapse;}
td{padding:3px}
input{height:20;}
textarea{width:80%;height:50px;overfmin:auto;}
form{display:inline}
</style>
<script>
/*************************************************
Validator for ASP beta 2 客戶端腳本
code by 我佛山人
wfsr@cunite.com
http://www.cunite.com
*************************************************/
function dispError(items, messages, mode, separator){
var iArray = items.split(separator);
for(var i=iArray.length-1;i>=0;i--)
iArray[i] = getObj(iArray[i]);
messages = ("以下原因導致提交失敗:\t\t\t\t" + separator + messages).split(separator);
switch(mode){
case 2 :
for(i=iArray.length-1;i>=0;i--)
iArray[i].style.color = "red";
case 1 :
alert(messages.join("\n"));
iArray[0].focus();
break;
case 3 :
for(i=iArray.length-1;i>=0;i--){
try{
var span = document.createElement("SPAN");
span.id = "__ErrorMessagePanel";
span.style.color = "red";
iArray[i].parentNode.appendChild(span);
span.innerHTML = messages[i+1].replace(/\d+:/,"*");
}
catch(e){alert(e.description);}
}
iArray[0].focus();
break;
}
}

function getObj(name){
var objs = document.getElementsByName(name);
return objs[objs.length -1];
}
</script>
<form name="theForm" id="demo" action="" method="post" onSubmit="return true">
<table align="center">
<tr>
<td>真實姓名:</td><td><input name="Name" dataType="Chinese" msg="真實姓名只允許中文"></td>
</tr>
<tr>
<td>英文名:</td><td><input name="Nick" dataType="English" require="false" msg="英文名只允許英文字母"></td>
</tr>
<tr>
<td>主頁:</td><td><input name="Homepage" require="false" dataType="Url" msg="非法的Url"></td>
</tr>
<tr>
<td>密碼:</td><td><input name="Password" dataType="Safe" msg="密碼不符合安全規則" type="password"></td>
</tr>
<tr>
<td>重複:</td><td><input name="Repeat" dataType="Repeat" to="Password" msg="兩次輸入的密碼不一致" type="password"></td>
</tr>
<tr>
<td>信箱:</td><td><input name="Email" dataType="Email" msg="信箱格式不正確"></td>
</tr>
<tr>
<td>信箱:</td><td><input name="Email1" dataType="Repeat" to="Email" msg="兩次輸入的信箱不一致"></td>
</tr>
<tr>
<td>QQ:</td><td><input name="QQ" require="false" dataType="QQ" msg="QQ號碼不存在"></td>
</tr>
<tr>
<td>身份證:</td><td><input name="Card" dataType="IdCard" msg="身份證號碼不正確"></td>
</tr>
<tr>
<td>年齡:</td><td><input name="Year" dataType="Range" msg="年齡必須在18~28之間" min="18" max="28"></td>
</tr>
<tr>
<td>年齡1:</td><td><input name="Year1" require="false" dataType="Compare" msg="年齡必須在18以上" to1="18" operator="GreaterThanEqual"></td>
</tr>
<tr>
<td>電話:</td><td><input name="Phone" require="false" dataType="Phone" msg="電話號碼不正確"></td>
</tr>
<tr>
<td>手機:</td><td><input name="Mobile" require="false" dataType="Mobile" msg="手機號碼不正確"></td>
</tr>
<tr>
<td>生日:</td><td><input name="Birthday" dataType="Date" format="YMD" msg="生日日期不存在"></td>
</tr>
<tr>
<td>郵政編碼:</td><td><input name="Zip" dataType="Custom" regexp="^[1-9]\d{5}$" msg="郵政編碼不存在"></td>
</tr>
<tr>
<td>郵政編碼:</td><td><input name="Zip1" dataType="Zip" msg="郵政編碼不存在"></td>
</tr>
<tr>
<td>操作系統:</td><td><select name="OS" dataType="Require" msg="未選擇所用操作系統" ><option value="">選擇您所用的操作系統</option><option value="Win98">Win98</option><option value="Win2k">Win2k</option><option value="WinXP">WinXP</option></select></td>
</tr>
<tr>
<td>所在省份:</td><td>廣東<input name="Province" value="1" type="radio">陝西<input name="Province" value="2" type="radio">浙江<input name="Province" value="3" type="radio">江西<input name="Province" value="4" type="radio" dataType="Group" msg="必須選定一個省份"></td>
</tr>
<tr>
<td>愛好:</td><td>運動<input name="Favorite" value="1" type="checkbox">上網<input name="Favorite" value="2" type="checkbox">聽音樂<input name="Favorite" value="3" type="checkbox">看書<input name="Favorite" value="4" type="checkbox" dataType="Group" min="2" max="3" msg="必須選擇2~3種愛好"></td>
</tr>
<tr>
<td>自我介紹:</td><td><textarea name="Description" dataType="Limit" max="10" msg="自我介紹內容必須在10個字之內">中文是一個字</textarea></td>
</tr>
<tr>
<td>自傳:</td><td><textarea name="History" dataType="LimitB" min="3" max="10" msg="自傳內容必須在[3~10]個字節之內">中文是兩個字節t</textarea></td>
</tr>
<tr>
<td colspan="2"><input name="Submit" type="submit" value="確定提交"></td>
</tr>
</table>
</form>
<%
Dim V : Set V = New Validator
V.Mode = 3
V.Method = "XMLHTTP"
V.Validate()
Set V = Nothing
%>
</body>
</html>




檔案備份 Validator.chm

2008年5月8日 星期四

[PHP]表單驗證

引用自[PHP 5討論區]bahammm、總理大臣、linsr

。表單驗證

<script type="text/javascript">
function chkjoin(){
if(document.form.username.value.length<5){
alert('帳號錯誤!! 請輸入5個以上的英文或數字');
}
if(document.form.password.value.length<5){
alert('密碼錯誤!! 請輸入5個以上的英文或數字');
}
if(document.form.password.value!= ocument.form.chkpass.value){
alert('密碼錯誤!!請確認你輸入的密碼是否一致');
}
if(document.form.name.value.length<2){
alert('暱稱錯誤!!請輸入2個字以上的中英文數字');
}
var count = 0;
for(i=0;i<form.sex.length;i++){
if(form.sex.checked){
count++;
}
}
if(count==0){
alert('性別錯誤!!請選擇你的性別');
}
var rege = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\- ])+\.) +([a-zA-Z0-9])+$/;
if (rege.exec(document.form.email.value) == null){
alert('信箱錯誤!!請詳細填寫你的信箱');
}
}
</script>



。將頁面跳回錯誤選項

document.form.username.focus()


。集合錯誤訊息

<script type="text/javascript">
function chkjoin(){
var errtxt="";
if(document.form.username.value.length<5){
errtxt ="帳號錯誤!! 請輸入5個以上的英文或數字 \n";
}
if(document.form.password.value.length<5){
errtxt ="密碼錯誤!! 請輸入5個以上的英文或數字 \n";
}

if(errtxt ==") return true;

else{
alert(errtxt);
return false;}

}
</script>



引用自[說走就走]

。Radio Bottom驗證

<script>
function chk(){
var items = document.getElementsByName('product');
for(var i=0;i<items.length;i++){
if(items[i].checked == true){
return true
}
}
alert(' 請 選 擇 款 式 ');
return false;
}
</script>
<form action="re_mimi.php" method="post" name=f9 onsubmit="return chk();">
<input type="radio" name="product" value="1">
<input type="radio" name="product" value="2">
<input type="radio" name="product" value="其它">
<input type="submit" value="寫 好 送 出">



原CODE

我來解釋一下為什麼會錯誤好了
//當選擇2或其他時條件成立
if( f9.product[0].checked == false )
{
alert(" 請 選 擇 款 式 ");
//到此行時因為product他是一個html的集合體,可以說把1,2,其他放在一個陣列所以沒有所謂的focus();函式,如果要使用的話必須改為f9.product[0].focus();也因為在這兒錯誤所以不會執行到return false,所以表單也就會執行submit的動作了!
f9.product.focus();
return false;
}


引用自[NTHU 7-4 簡易表單資料驗證]


<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=big5">
</head>

<body>
<h2 align=center>表單資料驗證:驗證各類控制項的資料</h2>
<hr>

<script>
function checkName(control) {
if (control.value == "") {
validatePrompt(control, "請輸入大名!");
return (false);
}
return (true);
}

function checkPassword(control) {
if (control.value.length != 5) {
validatePrompt(control, "請輸入長度為 5 的密碼!");
return (false);
}
return (true);
}

function checkGender(control) {
for (i=0; i<control.length; i++)
if (control[i].status)
return(true);
alert ("請輸入性別!");
return (false);
}

function checkNationality(control) {
for (i=1; i<control.length; i++)
if (control[i].selected)
return(true);
alert ("請輸入國籍!");
return (false);
}

function checkHobbies(control) {
var count=0;
for (i=1; i<control.length; i++)
if (control[i].selected)
count++;
if (count>=2)
return(true);
alert ("請輸入至少兩樣興趣!");
return (false);
}

function checkComment(control) {
if (control.value == "") {
validatePrompt(control, "請輸入您的寶貴意見!");
return (false);
}
return (true);
}

function validateForm(form) {
if (!checkName(form.realname)) return;
if (!checkPassword(form.password)) return;
if (!checkGender(form.gender)) return;
if (!checkNationality(form.nationality)) return;
if (!checkHobbies(form.hobbies)) return;
if (!checkComment(form.comments)) return;
alert ("你終於聽我的話了!\n全部資料通過驗證!\n表單即將送出!!!");
document.testform.submit(); // Submit form
}

function validatePrompt(control, promptStr) {
alert(promptStr);
control.focus();
return;
}
</script>

<form name=testform>
<P>貴性大名:<input type="text" name="realname" value="xxx">
<P>個人密碼:<input type="password" name="password">
<P>您的性別:<input type="radio" name="gender" value="male"> male
<input type="radio" name="gender" value="female"> female
<P>您的國籍:<select name="nationality">
<option>----<option>台灣<option>日本<option>韓國
</select>
<P>您的興趣:<select multiple name="hobbies">
<option>打球<option>下棋<option selected>聽音樂<option>閱讀<option>上網
</select>
<p>寶貴意見:<textarea name=comments cols=40 rows=3></textarea>
<P><input type="button" value="送出" onClick="validateForm(this.form)"><input type="reset">
</form>

<hr>
</body>
</html>



。大絕招 XD 各種語法集合體

<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=big5">
</head>

<body>
<h2 align=center>表單資料驗證:驗證各類控制項的資料</h2>
<hr>

<script>
function checkName(control) {
if (control.value == "") {
validatePrompt(control, "請輸入大名!");
return (false);
}
return (true);
}

function checkPassword(control) {
if (control.value.length != 5) {
validatePrompt(control, "請輸入長度為 5 的密碼!");
return (false);
}
return (true);
}

function checkGender(control) {
for (i=0; i<control.length; i++)
if (control[i].status)
return(true);
alert ("請輸入性別!");
return (false);
}

function checkNationality(control) {
for (i=1; i<control.length; i++)
if (control[i].selected)
return(true);
alert ("請輸入國籍!");
return (false);
}

function checkHobbies(control) {
var count=0;
for (i=1; i<control.length; i++)
if (control[i].selected)
count++;
if (count>=2)
return(true);
alert ("請輸入至少兩樣興趣!");
return (false);
}

function checkComment(control) {
if (control.value == "") {
validatePrompt(control, "請輸入您的寶貴意見!");
return (false);
}
return (true);
}

function validateForm(form) {
if (!checkName(form.realname)) return;
if (!checkPassword(form.password)) return;
if (!checkGender(form.gender)) return;
if (!checkNationality(form.nationality)) return;
if (!checkHobbies(form.hobbies)) return;
if (!checkComment(form.comments)) return;
alert ("你終於聽我的話了!\n全部資料通過驗證!\n表單即將送出!!!");
document.testform.submit(); // Submit form
}

function validatePrompt(control, promptStr) {
alert(promptStr);
control.focus();
return;
}
</script>

<form name=testform>
<P>貴性大名:<input type="text" name="realname" value="xxx">
<P>個人密碼:<input type="password" name="password">
<P>您的性別:<input type="radio" name="gender" value="male"> male
<input type="radio" name="gender" value="female"> female
<P>您的國籍:<select name="nationality">
<option>----<option>台灣<option>日本<option>韓國
</select>
<P>您的興趣:<select multiple name="hobbies">
<option>打球<option>下棋<option selected>聽音樂<option>閱讀<option>上網
</select>
<p>寶貴意見:<textarea name=comments cols=40 rows=3></textarea>
<P><input type="button" value="送出" onClick="validateForm(this.form)"><input type="reset">
</form>

<hr>
</body>
</html>

2008年5月7日 星期三

已故恐怖份子 Achmed

這是 Jeff Dunham 的超爆笑腹語術表演
title 是 "Achmed the dead terrorist" (已故恐怖份子 Achmed)

在批踢踢因緣際會下看到翻譯作者(柯小毛koshiyen)分享

##CONTINUE##
↓ Achmed the dead terrorist (已故恐怖分子 Achmed) ↓











↓ Achmed's "Jingle Bomb" (Achmed 的叮叮炸彈) ↓

Blog Spot張貼程式語法

引用自「Warrick DoDo

第一種:Code Block
將語法貼在[修改HTML]→[修改範本]

CODE {
display: block; /* fixes a strange ie margin bug */
font-family: Courier New;
font-size: 8pt;
overflow:auto;
background: #f0f0f0 url(http://klcintw.images.googlepages.com/Code_BG.gif) left top repeat-y;
border: 1px solid #ccc;
padding: 10px 10px 10px 21px;
max-height:200px;
line-height: 1.2em;
}


只要把要張貼的語法放在
<code>程式碼</code>

引用自「Mark Chiang

第二種:語法轉換(一般)
到此「http://www.opinionatedgeek.com/DotNet/Tools/HTMLEncode/Encode.aspx
」複製貼上搞定。


第三種:語法轉換(標示行數+語法顏色)
到此「http://code.google.com/p/syntaxhighlighter/」複製貼上
要下載檔案@@;
[檔案備份]