対uchome 2.0のfunction_common.phpの研究
12429 ワード
1、shtmlspecialchars
// HTML
function shtmlspecialchars($string) {
if(is_array($string)) {
foreach($string as $key => $val) {
$string[$key] = shtmlspecialchars($val);
}
} else {
$string = preg_replace('/&((#(\d{3,5}|x[a-fA-F0-9]{4})|[a-zA-Z][a-z0-9]{2,5});)/', '&\\1',
str_replace(array('&', '"', '<', '>'), array('&', '"', '<', '>'), $string));
}
return $string;
}
以上のコードの意味はhtmlの中の敏感な文字を例えば、<>&"はすべて<のようなものに転義します.この関数は1つの再帰的な思想を利用して、個人も理解することができます.
$string = preg_replace('/&((#(\d{3,5}|x[a-fA-F0-9]{4})|[a-zA-Z][a-z0-9]{2,5});)/', '&\\1',
str_replace(array('&', '"', '<', '>'), array('&', '"', '<', '>'), $string));
後ろのstr_replaceはarray('&',',','<','>')とarray('&',','<',','>')を対応するマッチング代替としています.しかし、これだけでは問題があります.例えば、私が前に「127;表示」を持っていたら、置き換えてになります.これは明らかに正しくありません.この場合は元の文字列を残してほしいです.だから'/&(#(d{3,5}|x[a-fA-F0-9]{4})|[a-zA-Z][a-z0-9]{2,5});)/'像をマッチングという置換された文字列は、の形に復元される.後の"\1"は#127に一致します.
しかし、私には質問があります.なぜ「&」を先に置き換えるのでしょうか.
2、saddslashes
//SQL ADDSLASHES
function saddslashes($string) {
if(is_array($string)) {
foreach($string as $key => $val) {
$string[$key] = saddslashes($val);
}
} else {
$string = addslashes($string);
}
return $string;
}
ここでは実はsqlの安全を考慮して、sql注入を防止するためです.引用符と二重引用符を「と」に変換します.ここでは他の文字も変換します.私はあまり話しません.
3、ssetcookie
//cookie
function ssetcookie($var, $value, $life=0) {
global $_SGLOBAL, $_SC, $_SERVER;
setcookie($_SC['cookiepre'].$var, $value, $life?($_SGLOBAL['timestamp']+$life):0, $_SC['cookiepath'], $_SC['cookiedomain'], $_SERVER['SERVER_PORT']==443?1:0);
}
ここで%SC['cookiepre']デフォルトはuchome_です.この接頭辞は、このクッキーがuchomeに関連していることを示しています.そのlifeは実はunixタイムスタンプで、$SGLOBAL['timestamp']はこのプログラムが実行された時間を表すので、$lifeを加えると期限切れの日を表し、ここでは秒記に従います.0の場合、クッキーのデフォルトは現在のブラウザで、閉じるとクリアされます.$SC['cookiepath']は有効なcookieのパスを指し、もしあなたが設定した「/」であれば、それからlocalhostアクセスであれば、localhostでアクセスしたページにこのcookieがあることがわかります.やはりあなたのプロジェクトパスを「/play」のように設定したほうがいいです.ここではディレクトリを示していますが、そのサブディレクトリにも有効です.後の$SC['cookiedomain']は有効なドメイン名を表し、ここでwww.exampleに設定すると.comはwww.example.comは有効です.もしあなたがそうすれば.example.comはサブドメイン名で有効であることを示します.
4、dbconnect()
//
function dbconnect() {
global $_SGLOBAL, $_SC;
include_once(S_ROOT.'./source/class_mysql.php');
if(empty($_SGLOBAL['db'])) {
$_SGLOBAL['db'] = new dbstuff;
$_SGLOBAL['db']->charset = $_SC['dbcharset'];
$_SGLOBAL['db']->connect($_SC['dbhost'], $_SC['dbuser'], $_SC['dbpw'], $_SC['dbname'], $_SC['pconnect']);
}
}
この変数はuchomeのconfigですphp構成では、アクセスページごとにcommonを実行する.phpの場合はこの関数が実行され、後でデータベース呼び出しを実行するたびに$SGLOBAL['db']でいいです.これはデータベース操作をカプセル化するクラスで、多くの有用な方法があります.
その中のpcconnect(persistent connect)は実はデータでプールを接続するかどうかの意味(デフォルトは0で、つまりプールを接続しない)で、connect関数はその1段があります
if($pconnect) {
if(!$this->link = @mysql_pconnect($dbhost, $dbuser, $dbpw)) {
$halt && $this->halt('Can not connect to MySQL server');
}
} else {
if(!$this->link = @mysql_connect($dbhost, $dbuser, $dbpw, 1)) {
$halt && $this->halt('Can not connect to MySQL server');
}
}
デフォルトではelseの句が実行されますが、ここの1はnew_です.linkの意味.つまり、同じパラメータでデータベースに接続すると、常に新しい接続が作成されます.上のmysql_pconnectは接続プールのリソースを利用するべきで、$pconnectに対応して1です.
5、showmessage
function showmessage($msgkey, $url_forward='', $second=1, $values=array()) {
global $_SGLOBAL, $_SC, $_SCONFIG, $_TPL, $space, $_SN;
obclean();
//
$_SGLOBAL['ad'] = array();
//
include_once(S_ROOT.'./language/lang_showmessage.php');
if(isset($_SGLOBAL['msglang'][$msgkey])) {
$message = lang_replace($_SGLOBAL['msglang'][$msgkey], $values);
} else {
$message = $msgkey;
}
//
if($_SGLOBAL['mobile']) {
include template('showmessage');
exit();
}
//
if(empty($_SGLOBAL['inajax']) && $url_forward && empty($second)) {
header("HTTP/1.1 301 Moved Permanently");
header("Location: $url_forward");
} else {
if($_SGLOBAL['inajax']) {
if($url_forward) {
$message = "<a href=\"$url_forward\">$message</a><ajaxok>";
}
//$message = "<h1>".$_SGLOBAL['msglang']['box_title']."</h1><a href=\"javascript:;\" onclick=\"hideMenu();\" class=\"float_del\">X</a><div class=\"popupmenu_inner\">$message</div>";
echo $message;
ob_out();
} else {
if($url_forward) {
$message = "<a href=\"$url_forward\">$message</a><script>setTimeout(\"window.location.href ='$url_forward';\", ".($second*1000).");</script>";
}
include template('showmessage');
}
}
exit();
}
obclean()は、以前の出力echo printをすべて明らかにすることです.ここはページがジャンプするに違いありませんので、前の論理は考慮する必要はありません.リダイレクトするだけです.
にある
showmessage.phpには
'no_privilege_friendnum' => ' \\1 , ,<a href="cp.php?ac=friend&op=find"> </a>',
'no_privilege_email' => ' ,<a href="cp.php?ac=password"> </a>',
ここには実はローカライズされた考えがあります.私はいくつかのshowmessageを書くことができます.php、前のキーは変わらないで、それは論理部分なので、後で私はフランス語やマレーシア語に書くことができて、私は異なる場所に掛けて異なるphpファイルを使うだけでいいです.
ここの
if(isset($_SGLOBAL['msglang'][$msgkey])) {
$message = lang_replace($_SGLOBAL['msglang'][$msgkey], $values);
} else {
$message = $msgkey;
}
たとえばshowmessage(「no_prililege_friendnum」,'club.php',2,array(8))を呼び出しました.
まずno_があるかどうかを確認しますprililege_friendnumのようなkeyは、あることを発見して、再び呼び出します
lang_replace($_SGLOBAL['msglang'][$msgkey], $values)
つかむ
「この操作を行うには\1人の友達を追加する必要があります...」の\1は私たちが伝えた8になって、ここでlangを使いました_replaceという関数は具体的には
//
function lang_replace
($text, $vars) {
if($vars) {
foreach ($vars as $k => $v) {
$rk = $k + 1;
$text = str_replace('\\'.$rk, $v, $text);
}
}
return $text;
}
携帯電話がこのページにアクセスして直接そのshowmesageのhtmlに戻ると、ジャンプしません.通常のウェブページ動作(ajaxリクエスト以外)であり、ユーザが$secondを0に設定した場合、直接301ジャンプします.ajaxモードであり、ユーザがジャンプを指定したurlは戻ります.
"<a href=\"$url_forward\">$message</a><ajaxok>"
urlを指定せずにそのローカライズされた情報メッセージを返します.
最後の判断はurlが指定されてsecondが0ではない場合で、これも最も一般的な場合で、showmessageというページをレンダリングしてから時間ジャンプを設定します.
6、formhash
この関数によりフォーム検証を検討しloginの例を挙げる
// form
function formhash() {
global $_SGLOBAL, $_SCONFIG;
if(empty($_SGLOBAL['formhash'])) {
$hashadd = defined('IN_ADMINCP') ? 'Only For UCenter Home AdminCP' : '';
$_SGLOBAL['formhash'] = substr(md5(substr($_SGLOBAL['timestamp'], 0, -7).'|'.$_SGLOBAL['supe_uid'].'|'.md5($_SCONFIG['sitekey']).'|'.$hashadd), 8, 8);
}
return $_SGLOBAL['formhash'];
}
ここのformhashはリクエストするたびに違うと思っていましたが、ここでは$SGLOBAL['timestamp']現在時刻の.しかし、私が実験をするたびに同じです.なぜですか.ここは$SGLOBAL['timestamp']はタイムスタンプです.ここで切り取ったのは0から-7です.つまり、10の7回の秒で計算できるのは同じです.もちろん、私のところは厳密ではありません.formhashはかなり長い間変わらないという意味です(同じsupeidなら)、どうしてですか.どうしてですか.
それからhtmlフォームの上でいつも1つのステルスinputがあって、中はformhashを記入して、もう1つのsubmit inputはsubmitのタイプを記入しました
<input type="hidden" name="formhash" value="<!--{eval echo formhash();}-->" /></form>
<input
type
="submit"
id
="loginsubmit"
name
="loginsubmit"
value
=" "
class
="submit"
/
>
submitcheck(「loginsubmit」)を使うと
function submitcheck($var) {
if(!empty($_POST[$var]) && $_SERVER['REQUEST_METHOD'] == 'POST') {
if((empty($_SERVER['HTTP_REFERER']) || preg_replace("/https?:\/\/([^\:\/]+).*/i", "\\1", $_SERVER['HTTP_REFERER']) == preg_replace("/([^\:]+).*/", "\\1", $_SERVER['HTTP_HOST'])) && $_POST['formhash'] == formhash()) {
return true;
} else {
showmessage('submit_invalid');
}
} else {
return false;
}
}
まず、コミットのタイプが予想されているかどうか、つまりloginsubmitであるかどうかを判断し、postコミットであるかどうかを判断します.ここでは少しわけがわかりませんが、あなたは$_からPOSTでデータを取ったのに、まだpostじゃないの?次に複雑なif文があります.現在のドメイン名とユーザーがフォームに記入したときのページのurlが同じドメイン名であるかどうかを判断し、私の本体ではlocalhostであり、そのformhashなどが現在に等しくないと判断します.なんてことだ!面倒くさい!どうしてこんなことをしたのですか.
7、updatetable
//
function updatetable($tablename, $setsqlarr, $wheresqlarr, $silent=0) {
global $_SGLOBAL;
$setsql = $comma = '';
foreach ($setsqlarr as $set_key => $set_value) {//fix
$setsql .= $comma.'`'.$set_key.'`'.'=\''.$set_value.'\'';
$comma = ', ';
}
$where = $comma = '';
if(empty($wheresqlarr)) {
$where = '1';
} elseif(is_array($wheresqlarr)) {
foreach ($wheresqlarr as $key => $value) {
$where .= $comma.'`'.$key.'`'.'=\''.$value.'\'';
$comma = ' AND ';
}
} else {
$where = $wheresqlarr;
}
$_SGLOBAL['db']->query('UPDATE '.tname($tablename).' SET '.$setsql.' WHERE '.$where, $silent?'SILENT':'');
}
このupdatetable以外にもiinserttableがありますが、ここにはupdatetableが1つしか置いていません.ここは実はDAOに似ています.すべてのCRUDを1つの関数にカプセル化し、どのエンティティのCRUDもこの関数を呼び出すだけで、操作があまり悪くないからです.ここ$commaの妙用に注意してください.
ここのqueryのパラメータsoelntもありますが、ここでsilentに設定するとmysqlでエラーが発生したロシアでMySQL Query Errorなどのエラーがページに表示されず、そのままそのエラーを無視してしまいます.