设为首页 收藏本站
查看: 1108|回复: 0

[经验分享] 对uchome2.0 的function_common.php的研究

[复制链接]

尚未签到

发表于 2017-4-9 12:23:46 | 显示全部楼层 |阅读模式
  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里的敏感字符比如,<>&"都转义成类似于&lt;这样的东西的。这个函数利用了一个递归的思想,是个人也能看懂。这里着重讲一下那个

$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('&amp;', '&quot;', '&lt;', '&gt;')进行相对应的匹配替代。但是如果仅仅这样做是有问题的,比如我之前有一个&#127;表示"---",那么替换后就变成&amp;#127这个显然是不正确的,我们希望这种情况下保留原字符串。所以需要用'/&amp;((#(\d{3,5}|x[a-fA-F0-9]{4})|[a-zA-Z][a-z0-9]{2,5});)/'去匹配像&amp;#127这样的被替换过的字符串,将其还原成&#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_,这个前缀表示这个cookie是和uchome相关的。那个life其实是一个unix时间戳,由于$_SGLOBAL['timestamp']是表示这段程序执行的时间,所以加上一个$life就表示过期的日子,这里是按照秒记的;如果是0的话,cookie的默认日期是当前浏览器,关闭就清除了。$_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函数其有一段

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就返回那个本地化的信息message。
  最后一个判断肯定是当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表单上总有一个隐形input,里面填的就是formhash,还有一个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。这里其实有点类似于DAO。把所有的CRUD都封装为一个函数,任何实体的CRUD都只要调用这个函数,因为操作都是差不多的。注意这里 $comma的妙用。
  还有这里的query里的参数soelnt,这里如果设置成了silent则在mysql出错的俄时候不会在页面上显示MySQL Query Error等等的错误而是直接把那个错误忽略了。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-362406-1-1.html 上篇帖子: Web2.0动态网站开发-PHP技术与应用(PDF电子书) 下篇帖子: 使用PHP开发qmail邮件服务器管理系统
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表