対uchome 2.0のfunction_common.phpの研究



 
 
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('&amp;', '&quot;', '&lt;', '&gt;'), $string));
	}
	return $string;
}

以上のコードの意味はhtmlの中の敏感な文字を例えば、<>&"はすべて<のようなものに転義します.この関数は1つの再帰的な思想を利用して、個人も理解することができます.
$string = preg_replace('/&amp;((#(\d{3,5}|x[a-fA-F0-9]{4})|[a-zA-Z][a-z0-9]{2,5});)/', '&\\1',
			str_replace(array('&', '"', '<', '>'), array('&amp;', '&quot;', '&lt;', '&gt;'), $string));


後ろのstr_replaceはarray('&',',','<','>')とarray('&',','<',','>')を対応するマッチング代替としています.しかし、これだけでは問題があります.例えば、私が前に「127;表示」を持っていたら、置き換えて&#127になります.これは明らかに正しくありません.この場合は元の文字列を残してほしいです.だから'/&(#(d{3,5}|x[a-fA-F0-9]{4})|[a-zA-Z][a-z0-9]{2,5});)/'像をマッチング&#127という置換された文字列は、の形に復元される.後の"\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などのエラーがページに表示されず、そのままそのエラーを無視してしまいます.