版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
PHPCMS整站代碼分析講解(一)
首先我對PHPCMS的頭程序文件開始講解:include/common.inc.php這個文件是程序啟動的核心文
件.
<?php
/**
代碼講解分析:逆雪寒.2007-12-20
*/
=explode,microtime());
$phpcms_starttime=$mtime[l]+$mtime[0];
/**
計算腳本開始運行的時間。很常見的寫法。最后結(jié)算還在程序運行的終點位置。講到了在給各位說。
*/
unset($LANG,$_REQUESTZ$HTTP_ENV_VARS,$HTTP_POST_VARSZ$HTTP_GET_VARS/
$HTTP_POST_FILES,$HTTP_COOKIE_VARS);
/**
把$HTTP_ENV_VARS$HTTP_POST_VARS全局變量設(shè)置.為NULL因為php4.1.0以上默認(rèn)以$_POST
來替代。unset后防止程序運行在低版本會出現(xiàn)安全等問題。比如變量注入
*/
set_magic_quotes_runtime(0);
〃地球人都知道。關(guān)了字符竄入庫自動轉(zhuǎn)意比如mynameison'x轉(zhuǎn)成mynameison\'x為了最大
的程序性能所以我們關(guān)掉吧~哈哈
defineCIN.PHPCMS;TRUE);
/**
程序入口標(biāo)記。為什么需要這個東西呢。就好比你進(jìn)一個小區(qū),保安大哥哥肯定要你簽字或是掛個用牌證
明你是從正門進(jìn)來的。
防止你翻墻進(jìn)入去偷東西搞破壞。這個入口標(biāo)記也有這個功能。在這里定義了一個常量IN_PHPCMS為
TRUE,然后我在其他程序文件里面檢查這個標(biāo)記。如果不存在或不為真,
那么就基本可以肯定你這個家伙是個小偷來的。人可能牖墻進(jìn)入。但程序怎么翻堵呢。只要在php.ini文
件里面激活allow_url_fopen近項,include()就可以包含URL地址了。你想下如果你有個放密碼的PHP
文件。如果給人家include了以后。你怕不怕。
*/
defineCPHPCMS_ROOT',str_replace("\\';7\substr(dirname(_FILE_),0,-8)));
/**
為了程序產(chǎn)品的跨平臺。自動獲取程序的安裝目錄路徑,定義為PHPCMS_ROOT常量。方便以后程序使
用。建議大家都這樣做哦
*/
requirePHPCMS_ROOT.7include/global.func.php';
/**
包含全局函數(shù)global.func.php文件。里面放了些程序全局都有需要用的函數(shù).大家看到了吧。常量
PHPCMS_ROOT己經(jīng)發(fā)揮作用。這樣程序給人家發(fā)布到了二級目錄下。也不需要人家手動改整站根目錄
路徑了。
自己好燈理解下。。。。。
*/
$search_arr=array(7union/i",7select/i";7update/i";'/outfile/i","/or/『);
C7union/i")這個是正則的寫法?不懂正則的自己百度找教程來學(xué)。這里不詳細(xì)說了
*/
$replace_arr=array。union'/select'/update'/outfileor');
/**
看這個意思很明了。union:連接兩條SQL語句。outfile:主要用來導(dǎo)出數(shù)據(jù)庫資料到其他介質(zhì)上。
干啥字要定義這兩個變量呢?在global.func.php文件(前面已經(jīng)加載)里面有個函數(shù)strip_sql()各位可
以看下。
functionstrip_sql($string)
{
global$search_arrz$replace_arr;
returnis_array($string)?array_map('strip_sqr,$string):preg_replace($search_arr,$replace_arr,
$string);
}
函數(shù)里面定義了這兩個變量為global全局變量。那么函數(shù)里就可以直接使用了。先講解F這個函數(shù)吧。
顧名思義這個函數(shù)是過謔字符牢里面的SQL語句使得關(guān)鍵的SQL語句單詞失效。
主要過濾那些SQL語句呢。主要是這幾個關(guān)鍵字:unionselectupdateoutfileor等。因為這幾個SQL
字是極度容易在$_6日傳輸中給截注.
這個函數(shù)寫得實在精妙。is_array來判斷$string是否為數(shù)組。如果是就array_m叩。函數(shù)來遞歸過
濾$string數(shù)組里面的每一個單元.每個單元是一個字符竄吧?
當(dāng)遞歸調(diào)用strip_sql()以后is_array()判斷$string肯定為假「,因為$string已經(jīng)不是數(shù)組而是字符第。
所以執(zhí)行preg」eplace()函數(shù)。這個函數(shù)很好理解了。就是替換了。
7
$_POST=strip_sql($_POST);
$,GET=strip_sql($_GET);
$_COOKIE=strip_sql($_COOKIE);
/**
使用strip_sql()函數(shù)來過濾$_POST$_GET$_COOKIE;
一般不是開源的站。很少過SQL關(guān)鍵字過濾。不過這個也是冒很大風(fēng)險的。
7
unset($search_arrz$replace_arr);
/**
unset使用過但以后不需要的變量。這個是很好的習(xí)慣。第一不會浪費內(nèi)存。如果變量存了大量的數(shù)據(jù)字
節(jié),而后你的程序是一直不需要用的。那么
就會很浪費內(nèi)存。拉底程序性能.哈哈。真很書面。反正是好習(xí)慣我們都要學(xué)習(xí)的拉。
*/
$magic_quotes_gpc=get_magic_quotes_gpc();//get_magic_quotes_gpc()檢測gpc是否系統(tǒng)自動轉(zhuǎn)意。
gpc是什么呢?GETPOSTCOOKIE來來去去就這幾個東西羅。會返回其或假
if(!$magic_quotes_gpc)
{
$_POST=new_addslashes($_POST);
$_GET=new_addslashes($_GET);
)
/**
判斷一下系統(tǒng)是否打開了自動對gpc進(jìn)行轉(zhuǎn)意這個選擇。如果是的話,就不需要我們自動轉(zhuǎn)意了。如果不
是那么還是要老百姓的手段。自己動手豐衣足食。
來看下也是在global.func.php文件里面定義的這個函數(shù):其實走一個封裝好的php的addslashesi)函
數(shù)的函數(shù)。PHP都自己有.了為什么還要自己封裝成函數(shù)呢?
理由很簡單。為了以后的擴(kuò)展更改容易羅。如果我們?開始就全部用addslashes()這個函數(shù)來對‘進(jìn)行
轉(zhuǎn)意的話。那么以后隨著程序的發(fā)展。我可能想多過濾個人*(〕之類的
那如何是好呢?所以為了以后孩子的成K:.我們還是最好封起來吧.記住:以后有?可能會邊的東西.最好
都封裝成模塊。函數(shù)。類。這樣程序的靈活度就上去了。
functionnew_addslashes($string)
{
if(!is_array($string))returnaddslashes($string);
foreach($stringas$key=>$val)$string[$key]=new_addslashes($val);
return$string;
}
這個函數(shù)也是寫得賊好。也是同時考慮過濾字符竄或數(shù)組,也是使用了傳歸??聪戮蛻?yīng)該明白了吧。這
個不用說了。我們要學(xué)下這個思路這個方法方式哦。這樣才能進(jìn)步。
哈哈。我們要懂模仿。
*/
@extract($_POST,EXTR_OVERWRITE);
@extract($_GET,EXTR_OVERWRITE);
/**
嘿。extract前面加個@雞蛋做什么呢??抑制錯誤的。還不懂的話。自己百度了。
為什么用extract。函數(shù)呢.平時我們程序是不是要常使用$_POST$_GET來獲取傳遞的變量呀。是不是
感覺賊麻煩呀。
比如$_POST['xx']這樣接受是挺好。但寫多了很麻煩是吧。我是感覺麻煩。我現(xiàn)在想直接就$xx就可以
獲取傳遞過來的東西。那怎么辦呢。
就用了extract。函數(shù)來實現(xiàn)這么一個技巧。這個技巧在discuz論壇上也有應(yīng)用。
*/
unset($_POSTz$_GET);
/**
unset()好處不用說了吧。釋放$_POST$_GET數(shù)組,因為己經(jīng)不需要他們了。
*/
?>
明天放假「今天在寫點羅.放假沒空寫了.要陪老婆,大家看r有什么不明白的.可以跟帖問.我懂的
我會回答.謝謝
PHPCMS整站代碼分析講解(二)
[Copytoclipboard][-]
CODE:
/**
代碼講解分析:逆雪寒.2007-12-21
*/
requirePHPCMS_ROOT.7config.inc.php";
/**
加栽整站的配置參數(shù)文件。i股的程序都會有這個文件。做什么的呢?比如一些數(shù)據(jù)庫連接地址。用戶名,
密碼等。需要用到的參數(shù)都定義在這個文件里面。這樣以后配置變了。我們只要改動下這個文件里面的
變量值就好。是不是很方便呢。呵呵.在這里說下require()這個加載函數(shù)。require和include都是用
來加載其他PHP文件用的。但他們是有區(qū)別的。require函數(shù):是"預(yù)解辭"函數(shù)。就是程序一加載,就執(zhí)
行了require函數(shù)。而include呢。是個過程加載函數(shù)。我們可以在邏輯里比如:if里面使用include來
動態(tài)的加載其他程序片段。而require就不行。*/
requirePHPCMS_ROOT.7languages/'.$CONFIG['language'].7phpcms.lang.php,;
/**
顧名思義:這個就是加載語宮包了。PHP的國際化目前做得最多的。就是直接用PHP文件來實現(xiàn).
在phpcms.lang.php文件里面定義程序中要用到的中文信息。然后在程序一開始就加載。那里程序里面
就可以使用這個文件里面的變量和一切。那么就簡單了。模板上就不需要直接寫中文信息了。直接用這個
文件里面定義的變量等來替換。從而實現(xiàn)國際化。over!!!最好自己打開這個語言文件再加上自己思考下。
就知道。原來如此簡單。
*/
defineCPHPCMS-PATH',$COrJFIGr'rootpath'l);
defineCPHPCMS.CACHEDIR',$CONFIG['cachedir']);
/**
$CONFIG['rootpath']這個就是全局配置文件config.inc.php文件里面數(shù)據(jù)庫信息。等全部配宜信息。在
這里把他們定義為常量。為什么需要定義為常量呢。因為作者感覺這樣寫爽羅。呵呵。其實因為后面
用到這兩個變量多。所以干脆定義為常量。方便使用。再多說一個技巧:$CONFIG['rootpath']其實也
可以寫成$CONFIG[rootpath]但是最好不要這樣。為什么呢。因為PHP引擎會先判斷rootpath是不
是常量。如果不是才會認(rèn)定$CONFIG[rootpath]是數(shù)組。這樣性能上就差了一點點了。再多
說一個技巧:為什么程序多數(shù)都用"單引號呢而不用""雙引號呢。因為這樣效率好,”"雙引號。
php引擎還會先檢查里面是否有變量.如果有就解釋.而"單引號不會做這一步的檢查.而直接就當(dāng)成字
符竄了。所以效率上也會有一點點影響哦。
*/
$CONFIG['enablephplog']?set_error_handler('phpcms_error'):error_reporting(E_ERROR|E_WARNING
IE_PARSE);
/**
$CONFIG['enablephplog']是否開啟錯誤日志設(shè)置這個設(shè)置在全局配置文件里面.config.inc.php。這
里使用了三目運算符偶最喜歡用了。一些簡短的邏輯判斷??梢允褂??::來實現(xiàn)比較簡潔
set_error_handler()這個函數(shù)就大有來頭了。php4里面的典型自定義程序出錯后行為的一個函數(shù)。十分好
用。怎么用呢?set_error_handler(函數(shù))的參數(shù)也是一個函數(shù),這個函數(shù)。反映了程序出錯后行為的。
phpcms_error函數(shù)存在global.func.php全局函數(shù)里面。
functionphpcms_error($errnoz$errmsg,$filenamez$linenumz$vars)
$filename=str_replace(PHPCMS_ROOTz$filename);
$帆加(^=str.replaceCW",7'z$filename);//把win平臺的\\換成/兼容常見系統(tǒng)的路徑
if(!defined('E_STRICT'))define('E_STRICT'z2048);
$dt=date('Y-m-dH:i:s');
$errortype=array(
E_ERROR=>Error,,
E_WARNING=>'Warning',
E_PARSE=>'ParsingError',
E.NOTICE=>'Notice',
E_CORE_ERROR=>'CoreError',
E_CORE_WARNING=>'CoreWarning',
E_COMPILE_ERROR=>'CompileError;
E_COMPILE_WARNING=>'CompileWarning;
E_USER_CRROR=>'UserError',
E_USER_WARNING=>'UserWarning;
E_USER_NOTICE=>'UserNotice;
E_STRICT=>'RuntimeNotice'
);
$user_errors=array(E_USER_ERRORzE_USER_WARNING,E_USER_NOTICE);
$err="<errorentry>\n";
$err.="\t<datetime>".$dt."</datetime>\n";
$err.="\t<errornum>".$erno."</errornum>\n";
$err.="\t<errortype>".$errortype[$errno]."</errortype>\n";
$err.="\t<errormsg>".$errmsg."</errormsg>\n";
$err.="\t<scriptname>".$filename."</scriptname>\n";
$err.="\t<scriptlinenum>".$linenum."</scriptlinenum>\n";
if(in_array($errno,$user_errors))
{
$err.="\t<vartrace>".v/ddx_serialize_value($vars,"Variables")."</vartrace>\n";
)
$err.="</errorentry>\n\n";
echo$err;
,
error_log($errz3,PHPCMS_ROOT.7data/php_error_log.xml);
chmod(PHPCMS_ROOT.7data/php_error_log.xmrz0777);
}
就是這個鳥蛋。現(xiàn)在我們慢慢來干掉他。呵呵這個自定義出錯信息函數(shù)默認(rèn)帶有四個參數(shù)。第一個
參數(shù)$errno是程序出錯的等級。第二參數(shù)是程序出錯的界面信息。第三是出現(xiàn)錯誤的程序文件名。
第四是第幾行出現(xiàn)錯誤。第五個參數(shù)。要不要都行是當(dāng)前變量狀態(tài)的快照.看吧。我們有這些信息后。想
定義怎么樣的錯誤信息給客戶看都很容易了是吧?但現(xiàn)在我們是要生成錯誤日志呢?這里phpcms作者是
動態(tài)生成?個XML文件來做錯誤日志的。不錯不錯.他使用了in_array()函數(shù)來實現(xiàn)(因為比較簡單,
自己理解下)只記錄E_USER_ERRORZE_USER_WARNINGZE_USER_NOTICE這三個級別的錯誤日志
信息。\n是文本換行符\t是制表符.這里他使用了一個比較漂亮而不常用的函數(shù)
wddx_serialize_value()wddx其實也是一種xmlowddx_serialize_value()這個函數(shù)就是把一般變量
以XML格式輸出。這樣我們就不用自己模擬寫xml了。方便吧。呵呵第一個參數(shù)就是:要格式輸出的
變量,第二個參數(shù)處輸出的xml的介紹信息.下面就是errorJog()函數(shù)。這個函數(shù)十分有用了。就是生
成錯誤日志XML文件。不需要我們fopen了。方便吧。它還有很多功能。詳細(xì)的看手冊。chmod設(shè)置
日志文件的權(quán)限是可讀可寫可執(zhí)行。在php5中。我習(xí)慣僅用extendsException來定義It己的
出錯信息。所以很少用set_e-ror_handle().如果沒開啟日志功能。那么error_reporting(E_ERROR|
E_WARNING|E_PARSE)就運行了.把一般出錯信息先出過來.
*/
if($CONFIG['sessionsavepath'])session_save_path($CONFIG['sessionsavepath']);
/**
定義session的存儲路徑,session其實也是cookie不過session是實現(xiàn)在服務(wù)器端的。安全但負(fù)載重
點。這樣做的好處?效率很好。如果你在虛擬主機(jī)的話。大家的sessioncookie都放在了php.ini里而設(shè)置
的默認(rèn)地方。文件夾臃腫就會慢羅。是吧。第二就是安全羅。記得一定要定義在session_start()函數(shù)之
前
*/
session_start();
if(function_exists('date_default_timezone_set'))date_default_timezone_set($CONFIG['timezone']);
/**
php5開始有時區(qū)的概念了。記得就行
*/
header('Content-type:text/html;charset='.$CONFIG['charset']);
/**
設(shè)置頁面編碼.php編碼有:頁面編碼。數(shù)據(jù)庫編碼。文件內(nèi)碼。如果三碼相同就一般不會出現(xiàn)亂碼.
文件內(nèi)碼是什么呢?每個文件都有自己的內(nèi)部編碼。一般都用UTF8比較爽。怎么改變文件內(nèi)碼?你用
DW也行UE也行。隨便。數(shù)據(jù)庫編碼那肯定是要指定的了。mysql5開始也行字符集模式這個最
好也設(shè)置這樣可以兼容更多平臺。
頁面編碼:<metahttp-equiv="Content-Type"c/>這句就是。一般的HTML頭文件都有。那還需
header('Content-type:text/html;charset='.$CONFIG['charsef]);嗎?其實需要的。因為有些自己
寫的提示層呀?;蚴俏募餂]指定頁面編碼的。就很容易出現(xiàn)亂嗎那么我們就防范于未然。header一個
編碼過去。那就0K了。多好。
*/
if(getenvCHTTP_CLIENT_IP')&&strcasecmp(getenv('HTTP_CLIENT_IP')z'unknown'))
(
$PHP_IP=getenvCHTTP_CLIENTJP');
)
elseif(getenv('HTTP_X_FOR\A/ARDED_FOR')&&strcasecmp(getenv('HTTP_X_FORWARDED_FOR')z
'unknown'))
(
$PHP_IP=getenvCHTTP_X_FORWARDED_FOR');
)
elseif(getenv('REMOTE_ADDR')&&strcasecmp(getenv('REMOTE_ADDR')/'unknown'))
$PHP」P=getenv('REMOTE_ADDR');
)
elseif(iSSet($_SERVER['REMOTE_ADDR,])&&$_SERVER['REMOTE_ADDR']&&
strcasecmp($_SERVER['REMOTE_ADDR'],'unknown'))
(
$PHP_IP=$_SERVER['REMOTE_ADDR'];
)
preg_match(7[\d\.]{7,15}/",$PHP」P,$ipmatches);
$PHP_IP=$ipmatches[O]?$ipmatches[O]:'unknown';
PHPCMS整站代碼分析講解(二)續(xù)
QUOTE:
原帖由peixin2292008-1-1909:46AM發(fā)衣C1
/**
代碼講解分析:逆雪寒.2007-12-21
*/
requirePHPCMS_ROOT.7config.inc.php,;
/**
加栽整站的配置參數(shù)文件。-般的程序都會有這個文件。做什么的呢?比如一些數(shù)據(jù)庫連接地址。用戶名,
密碼等…
由于論壇字符限制,所以分兩次發(fā),接上面一部分。
[Copytoclipboard][-]
CODE:
/**
函數(shù)getenv()是獲取環(huán)境變量。環(huán)境變量:HTTP_CLIENTJP是獲取客戶端的IP。但有可能
人家是通過代理來訪問你的程序的呢。那么這時候就要用環(huán)境變量:
HTTP_X_FORWARDED_FOR了。包括getenv('REMOTE_ADDR')$_SERVER['REMOTE_ADDR']
都是獲取人家IP的。反正碰羅。碰到那個能獲取就大工告成。
*/
$PHP_TIME=time();
$PHP_SELF=isset($_SERVER['PHP_SELF,])?$_SERVER['PHP_SELF']:
(isset($_SERVER['SCRIPT_NAME'])?$_SERVER['SCRIPT_NAME']:$_SERVER['ORIG_PATH_INFO']);
/**
獲取當(dāng)前運行的惻本名:剛開始看是不是有點亂呢。咋沒用ifelse呢??催@樣的東西。我們最好從
右看到左。這樣比較好明白點。$_SERVER['SCRIPT_NAMF]
$_SERVER['PHP_SELF']$_SERVER['ORIG_PATH_INFO']這三個服務(wù)器全局變量都是獲取當(dāng)前腳本名
的。主要看服務(wù)器當(dāng)前環(huán)境了。那個存在的就獲取那個。
isset()函數(shù)十分有用。測試一個變量是否已經(jīng)定義。注:$a=NULL;isset($a)這樣會返叵false
的哦。注意isset和empty兩個函數(shù)的用法。用得不好會出大問題的。自己看手冊。
*/
$PHP_QUERYSTRING=$_SERVER['QUERY_STRING'];
$PHP_DOMAIN=$_SERVER['SERVER_NAME'];
$PHP_REFERER=isset($_SERVER['HTTP_REFERER'])?$_SERVER['HTTP_REFERER']:
$PHP_SCHEME=$_SERVER['SERVER_PORT]=='443'?'https://':'http://';〃測試服務(wù)器是否啟動了
ssl連接如果是的話。就用https:〃安全連接來進(jìn)行通行
$PHP_PORT=$_SERVER[SERVER_PORT]=='80'?":T.$_SERVER[SERVER_PORT];
$PHP_SITEURL=$PHP_SCHEME.$PHP_DOMAIN.$PHP_PORT.PHPCMS_PATH;
$PHP_URL=$PHP_SCHEME.$PHP_DOMAIN.$PHP_PORT.$PHP_SELF.($PHP_QUERYSTRING?
?.$PHP_QUERYSTRING:");
/**
獲取當(dāng)前腳本的URL
*/
$db_file=$db_class='dbJ.^CONFIGC'database'];
if(!defined('IN_ADMIN'))〃如果不是在后臺。常量IN_ADMIN是后臺標(biāo)志
(
if($CONFIG['dbiscache'])$db_file.='.cache';
if($CONFIG['phpcache']=='2')//如果在config.inc.php里面開啟了緩存
(
$cachefileid=md5($PHP_SELF.?.$PHP_QUERYSTRING);〃把腳本名和后面的get信息md5加密,
以此來生成卜面的緩存目錄和緩存文件
$cachefiledir=PHPCMS_RCOT.7data/phpcache/'.substr($cachefileid/0,2).7,;〃緩存目錄
$cachefile=$cachefiledir.$cachefileid.'.htmr;〃緩存文件:xxx.html格式
if(file_exists($cachefile)&&($PHP_TIME<@filemtime($cachefile)+$CONFIG['phpcacheexpires']))
{〃如果緩存文件存在和緩存沒有過期效,那么就返回緩存文件名
require$cachefile;
exit;
)
)
A
if($PHP_QUERYSTRING&&preg_match("/(.*)\,(htm|html|shtm|shtml)$/",$PHP_QUERYSTRING/
$urlvar))〃獲取傳遞過來的變量。有什么用的呢?請看下面解釋
{
,,
parse_str(str_replace(array(7'zarray(&z"),$urlvar[l]));
}
)
/**
上面這部分相對復(fù)雜了點。但沒關(guān)系。慢慢講解.首先緩存只針對前臺.所以我們一開始就判斷.這個
腳本是運行在前臺的而不是在后臺!defined('IN_ADMIN')來判斷.
然后呢.再看客戶配置config.inc.php文件是否開啟/緩存.==2就是開啟.接著開始用?系列
的規(guī)則來找出緩寸的文件名和目錄:以腳本名:xx.php和后續(xù)傳遞的參數(shù)?xx=ee&bb=jj他兩的N符竄
的MD5.以這個md5竄來定義出了緩存目錄.和緩存文件.接著再判斷這個緩存文件是否存在和是否
沒過緩存有效期.如果沒有就返回這個緩存文件的名字.
然后到主菜了.最后一個if邏輯是做什么的呢?不知道大家有沒見過這樣的網(wǎng)址:
[url=/dd.php/xx]/dd.php/xx[/url]—23Zcc-22.html他們
其實都算是偽靜態(tài).優(yōu)化URL用的.咋看起來還很象靜態(tài).爽.但你可能想.這樣的地址.我們寫PII
P程序的.怎么獲取get變量呢?最后if就是解答這個問題的.先剝離url來獲取傳遞的字符竄.
然后str_replace來把替換成標(biāo)準(zhǔn)的&'='好象:
[url=/dd.php&xx=23&cc=22]http://\A//dd.php&xx=23&cc=22[/url]
看這樣你應(yīng)該看明白了吧.然后用parse_str()函數(shù)來把xx變$xx=23cc變$cc=22php真是
什么都給你想到了.強(qiáng).看明白了吧.0K.過了.
*/
PHPCMS整站代碼分析講解(二)
[Copytoclipboard][-]
CODE:
requirePHPCMS-ROOT.'/indude/'.Sdb.file.'.class.php,;//包含數(shù)據(jù)庫操作類,下章詳說
requirePHPCMS_ROOT.7include/tag.func.php';〃遇到再說
requirePHPCMS_ROOT.7indude/extension.inc.php';〃遇到再說
$db=new$db_class;;/實例化數(shù)據(jù)庫類
$db->connect($CONFIG['dbhDSt']z$CONFIG['dbuser']/$CONFIG['dbpw'],$CONFIG['dbname']z
$CONFIG「pconnect]);〃連接數(shù)據(jù)庫@_@
$db->iscache=$CONFIG['dtiscache'];〃是否開啟SQL緩存
$db->expires=$CONFIG['dbexpires'];〃緩存時間
if(!cache_read('table.php'))
(
require_oncePHPCMS_ROOT.7include/cache.func.php';
cache_all();〃生成所有緩存
}
/**
cache_read()函數(shù)讀緩存文件函數(shù)存在global.func.php里面.上菜先:
functioncache_read($file,$mode=T)
(
$cachefile=PHPCMS_CACHEDIR.$file;
if(!file_exists($cachefile))returnarray();
return$mode==T?include$cachefile:file_get_contents($cachefile);
)
就這么簡單.文本緩存,在一些大的開源的PHP項目中經(jīng)常見到.主要是為了減輕數(shù)據(jù)庫的負(fù)荷的.比
如在程序啟動文件里面,就把一些后臺配置的常用信息緩存到php文件里面.然后在以后的程序就可以直
接使用而不用每次都訪問數(shù)據(jù)庫了.但對經(jīng)常要更新的信息.最好不要用文本緩存這形式,因為PHP文
件內(nèi)置的文件鎖flock。不是很好用.大系統(tǒng)中多用戶同時寫訪問的時候有可能會把緩存文件破壞.大系統(tǒng)
建議使用memcachedmysql5.1分區(qū)mysql主從來實現(xiàn)負(fù)載均衡@=@廢話太多了.這個
函數(shù)很簡單.自己看下就明白了.如果緩存和模式變量$mode是否為i是就include不是就把文件以
字符竄形式讀到內(nèi)存中.
如果cache_read()找不到緩存文件'table.php'就會返回false.那么就加栽cache.func.php文件.它
里面是些創(chuàng)建緩存的一些函數(shù),然后呢執(zhí)行cache_all()函數(shù)生成所有的常用信息緩存.
關(guān)于phpcms的緩存更詳細(xì)包括生成原理.打算在弄完啟動文件8mmon.inc.php后再開篇寫個詳紐的.
*/
$CACHE=cache_read('common.php');
/**
加載common.php緩存文;牛里面的變量(數(shù)據(jù))這樣我們不用從數(shù)據(jù)庫讀了每次.是吧
common.php文件里面是什么來的呢?上菜:
<?php
returnarray(
'module'=>
array(
'phpcms'=>
array(
'module'=>'phpcms',
'name'=>'phpcms',
'iscore'=>T,
'iscopy'=>'O',
'isshare'=>'0;
'moduledir'=>",
,linkurl'=>",
),
'member'=>
array(
'module'=>'member',
'name'=>'會員
'iscore'=>T,
'iscopy'=>'O',
'isshare'=>'O',
'moduledir'=>'member1,
'linkurl'=>'/phpcms/member/',
),
'article'=>
array(
'module'=>'article',
'name'=>'文章
'iscore'=>'O;
'iscopy'=>'1。
'isshare'=>'0;
'moduledir'=>'article',
'linkurl'=>,
)
?>
看到了吧.這個就是全部從數(shù)據(jù)庫里面生成的文本緩存信息.我們不用每次都連接數(shù)據(jù)庫讀數(shù)據(jù)庫.而只
要訪問里面的數(shù)組就可以得到一些配置信息.
這個就是文本緩存的作用了,至于怎么會生成這個文本緩存文件的.我會另外開一篇來介紹。
*/
$MODULE=$CACHE['module'];〃緩存中的數(shù)據(jù)
$CHANNEL=$CACHE['channel'];
$PHPCMS=$CACHE['phpcms'];
$FIEI_D=$CACHE['field'];
unset($CACHEz$ipmatches,$CONFIG['timezone']z$CONFIG['cachedir']/$CONFIG['dbhost']/
$CONFIG['dbuser']z$CONFIG['dbpw'],$CONFIG['pconnect']z$CONFIG['dbiscache']z
$CONFIG['dbexpires']);
/**
unset掉不需要用的變量.
*/
if($PHPCMS['enablebanip']&&ip_banned($PHP_IP))
showmessage($LANG['administrator_banned_this_IP']);
/**
SPHRCMSfenablebanip']是什么.不用說應(yīng)該知道「吧.這個就是后臺里面設(shè)置是否開啟過濾IP訪問
的功能.(因為我沒用過phpons,我是按照代碼猜的,不對的請指出)從這里就看出了文本緩存也有他的作
用的。ip_banned()函數(shù)是什么呢.上菜再說:
functionip_banned($ip)
(
global$PHP_TIME;〃前面定義過的.當(dāng)前的時間
$ipbanneds=cache_read('bcnip.php');
if(!is_array($ipbanneds))returnFALSE;
foreach($ipbannedsas$v)
{
if($v['overtime']<$PHP_TIME)returnFALSE;
An
if($ip==$v['ip']||preg_match(7.str_replaceC.',$v['ip'])."$/"z$ip))returnTRUE;
)
)
里面也用到了cache_read()這個函數(shù),還是讀banip.php這個文件.banip.php這個文件里面存著你在
后臺甚至的要過濾的IP列表.
里面的邏輯比較簡單.自己消化下了.不明白跟帖問
showmessage()函數(shù)是提示出錯信息封裝好的一個函數(shù).國家化的
$LANG['administrator_banned_this」P']這個看至ij了吧.這個就是讀語言包里面的.這樣我們就可以tl好多
個語言版本的程序拉.
*/
$TEMP=$MOD=$CHA=$CATEGORY=$CAT=array();
$ftp=$enableftp=$tags=$html=0;
/**
初始化變量.這個是好習(xí)慣我們要模仿.
*/
if(!isset($mod))
{
$mod='phpcms';//phpcms是默認(rèn)加載的模塊
)
elseif($mod1='phpcms')
(
isset($MODULE[$mod])orexjt($LANG['module_not_exists']);〃從緩存中讀加載的模塊是否開啟
/**
這個寫法,我十分喜歡,平時也用.XX&ⅆXXanddd;與運算要同時兩邊都為真整個公式才為真,
就是利用這個原理.:xx|dd;xxordd或運算只要一個條件滿足就不會執(zhí)行下一個條件而繼續(xù)執(zhí)行
下去.這樣寫是不是很酷.
*/
$MOD=cache_read($mod.'_setting.php');〃開始加載這個模塊的一些常用配置數(shù)值。phpcms對應(yīng)的每
個模塊都有一個緩存配置文件。@@怪不得速度那么快
?includePHPCMS_ROOT.'/languages/'.(definedCIN_ADMIN')?
$CONFIG['adminlanguage'].7.$mod.'_admin.lang.php':SCONFIGt'language'J.'/'4mod.'.lang.php');
/**
加載想對應(yīng)的模塊語言包.
*/
)
if(!isset($forward))$forward=$PHP_REFERER;〃記錄前一個URL地址。估計以后下面程序有需要月這個
變量
$dosubmit=isset($dosubmit)?1:0;〃記錄是否有表單提交過也是以后有用
$channelid=isset($channelid)?intval($channelid):0;〃記錄當(dāng)前頻道的id如果$channelid沒有isset
那么就為0.intval()十分有用。數(shù)字和數(shù)字的比較加減速度會快很多。記得哦
$skindir=PHPCMS_PATH.'tempEes/'.$CONFIGrde侑ulttemplate'].'/skins/1.$CONFIG「de啟ultskin?!?/p>
載默認(rèn)phpcms皮膚
if($PHPCMS['enablegzip']&&function_exists('ob_gzhandler'))
(
($CONFIG['phpcache']11defined('SHOWJS'))?ob_start():ob_start('ob_gzhandler');
)
else
{
$PHRCMS['enablegzip']=0;
ob_start();
)
/**
$PHPCMS['enablegzip']這個變量就是存在于phpcms_setting.php文件里。上面已經(jīng)說過了。每人模塊
都有相對應(yīng)的模塊配置緩存文件(是從數(shù)據(jù)庫copy過來的信息)這個變量標(biāo)致是否開啟壓縮傳輸。
壓縮傳輸,聽名字就知道。就是把數(shù)據(jù)按照?定的算法壓縮小羅,然后再傳送到客戶端。這樣就可以在有
限的帶寬中傳輸更大的數(shù)據(jù)拉。當(dāng)然速度快了不少。壓縮的數(shù)據(jù)到了你的瀏覽器,它就自動解壓縮,老版
本的?些瀏覽器不支持解壓縮哦。不過現(xiàn)在還有誰用很久的瀏覽器呢。用法很簡單的:看卜.面就知道:
首先判斷"看客戶老大們是否在后臺選擇了這個模塊的壓縮傳輸(如果是的話。自然的已經(jīng)加載到7相對
應(yīng)的文本緩存文件里面拉)標(biāo)致:$PHPCMS['enablegzip]和判斷回調(diào)函數(shù)ob_gzhandler是否開
啟,ob_gzhandler其實不算是個函數(shù)??词謨哉f明。就這么簡單。它只是一個專門給ob_start()做回調(diào)
使用的一個參數(shù)函數(shù)。詳細(xì)請看下手冊。別偷懶哦,在程序開頭ob_start('ob_gzhandler')就算是開始壓縮傳
輸了;判斷完了如果為真。就繼續(xù)下面的代碼:
($CONFIG['phpcache']11defined('SHOWJS'))?ob_start():ob_start('ob_gzhandler');
看代碼phpcms是這樣的:如果用戶在后臺開啟了壓縮傳輸。而用戶又開啟了頁面緩存。那么就默認(rèn)不
使用壓縮傳輸廣。我也不知道為什么這樣設(shè)計。我測試了下。后臺開啟壓縮傳輸。又同時又使用頁面緩存。
沒發(fā)現(xiàn)有什么問題。@@
如果沒開啟壓縮傳輸,那么我們就ob_start();使用session之前必須要ob_start();而且在ob_star:()之
前不能有任何的頭文件發(fā)送和輸出。比如:echoheader等要不會出錯的哦。
*/
PHPCMS整站代碼分析講解(三)續(xù)
QUOTE:
原帖由peixin2292008-1-1909:51AM發(fā)表G
requirePHPCMS.ROOT.'/include/'^db.file.'.class.php,;//包含數(shù)據(jù)庫操作類,下章詳說
requirePHPCMS_ROOT.7include/tag.func.php';〃遇到再說
requirePHPCMS_ROOT.'/include/extension.inc.php';...
[Copytoclipboard][-]
CODE:
$_userid=0;
$_username=
$_groupid=3;
$_arrgroupid=array();
$phpcms_auth=getcookie('auth');
/**
$_userid,$_username,$_grouDid這幾個記錄用戶信息的變量初始化,不初始化危險就太大了。@@如果
給人家$_GET一個“serid變量過來。那么就會把我們這個變量澄蠱。但是我們?nèi)绻o這幾個變量一個值,
那么按照就近原則。就算你GET個變量過來。你也一?樣改不/我原來的變量值。大家好好臼己想下。就會
明白了。
getcookieO這個自定義函數(shù)在global.func.php文件里定義的。上菜:
functiongetcookie($var)
global$CONFIG;
$var=$CONFIG['cookiepre'].$var;
returnisset($_COOKIE[$var])?$_COOKIE[$var]:FALSE;
}
這個函數(shù)用來提取我們設(shè)置的cookie(t.$CONFIG['cookiepre']在config.inc.php文件里面設(shè)置,cookie
名的前綴.函數(shù)很簡單。一看就明白不說了。
*/
if($phpcms_auth)
{
$phpcms_auth_key=md5($PHPCMS[,authkey,].$_SERVER[,HTTP_USER_AGENT,]);
list($_userid,$_password,$_answer)=$phpcms_auth?explode("\t",phpcms_auth($phpcms_auth,
'DECODE')):array",“,");
/**
list。=array。;用戶大家自己試下。意會下
phpcms_auth()是加密和解密函數(shù),因為cookie是存在于客戶端。卜分危險呀。你看連用戶的密碼也
存在cookie不加密能行嗎。但是呢加密后又要能解密。因為用廣名和用戶密碼我們往下操作要
獲取的。這個函數(shù)存在于global.func.php文件里面。大家想了解這個算法的自一去看卜吧。挺簡單的。
其實就是圍繞著$phpcms_auth_key這個變量來加密解密和discuz的cookie機(jī)制差不。
$phpcms_auth_key=md5($PHPCMS[,authkey'].$_SERVER[,HTTP_USER_AGENT']);看
$PHPCMS['authkeyl估計后臺有個cookie加密值讓你填,然后以這個值和
$_SERVER「HTTP_USER_AGENr](系統(tǒng)信息)
*/
$_userid=intval($_userid);
if($_userid<0)$_userid=0;〃讀出的cookie的用戶id如果是小于0
lf($_userid)〃如果cookie保存的這個uid在在,那么開始按照這個ID來查數(shù)據(jù)庫用戶表米取出用戶信
息
(
$memberinfo=$db->get_one("SELECT
username,password,groupid,arrgroupid,email,chargetype,begindate,enddate,money,point,credit,newme
ssagesFROM".TABLE_MEMBER."WHEREuserid=$_useridLIMIT0,1");
phpcms封裝好的數(shù)據(jù)庫類,下篇開講這個大家就大概看行了。大家看下selectsql語句。也可以學(xué)
習(xí)下。首先最好不要使用select*fromxx的*形式,除非你想獲取所有字段的記錄。只羅列你要的字
段。這樣在數(shù)據(jù)量大的杳詢中。速度明顯上去。常量:TABLE.MEMBER定義了表名。這樣做有什么
好處呢?想都知道了,為了以后變更表名方便而定義為常量。這個東西那里來的。估計在一個文件里面定
義好的。遇到了再講吧懶得找了。
*/
if($memberinfo&&$memberinfo['password']==$_password)〃用查詢出來的密碼和cookie中存在
的密碼想對比,為了在效率:在比較前先判斷查詢是否成功先。很多phper往往忽略。
{
if($memberinfo['groupid,]==2)〃如果用戶屬于的組的ID為2那么這個用戶是被管理員禁止訪問
的了。
mkcookieCauth',");//清除cookie
showmessage($LANG['userid_banned_by_administrator']);//提示出錯菜單
}
@extract($memberinfo,EXTR_PREFIX_ALL,");〃又來這招,應(yīng)該明白了吧各位老大:把字段變成我
們能直接使用的變量
unset($memberinfo,$_passwordz$_answer);
$_arrgroupid=$_arrgroupid?array_filter(explode(7,$_arrgroupid)):array();〃才巴字段為
arrgroupid值為FALSE過濾抻.array_filter()不帶回調(diào)參數(shù)的比法,請看手冊.
)
else
{
mkcookie('auth',");
)
/**
經(jīng)過上面的讀cookie和查數(shù)據(jù)庫用戶信息后。當(dāng)確定這個用戶信息是合法以后。就會自動登陸了。比如
phpchina論壇。當(dāng)你登陸后沒注銷。下次訪問的時候還是登陸狀態(tài)。就是這個原理。記得模仿哦
這里詳細(xì)解釋下mkcookie()函數(shù)上菜:
functionmkcookie($var,$vclue="z$time=0)
{
global$CONFIG,$PHP_TIME;
$time=$time>0?$time:(empty($value)?$PHP_TIME-3600:0);
$S=$_SERVER['SERVER_PORT]=='443'?1:0;
$var=$CONFIG['cookiepre'].$var;
returnsetcookie($var,$value/$time,$CONFIG['cookiepath']z$CONFIG['cookiedomain']/$s);
)
$time為cookie的存活時間:如果為0就是關(guān)閉瀏覽器cookie就自動失效,$PHP_TIME在前面定
義了:當(dāng)前時間。$PHP_TIME-3600減去3600秒。就是一個小時前的意思,那肯定是設(shè)置cookie失
效的意思了。
$s變量是獲取是否開啟SSL安全傳輸?shù)臉?biāo)致。cookie有?個參數(shù)是ssl傳輸?shù)摹H绻?wù)器已經(jīng)
opensll了那么我們肯定不能浪費這么好的安全資源了。
$varcookie名的前綴,主要防止混淆。
$CONFIG['cookiedomain']這個家伙在config.inc.php里面已經(jīng)配置的了。定義為:/意思就是說在當(dāng)
前域的所有目錄的PHP程序都能訪問這個COOKIE,還有限制孑錄訪問COOKIE的弄法。具體請看
setcookie()函數(shù)手冊上說明,
*/
)
}
unset($db_class,$db_filez$phpcms_auth,$phpcms_auth_key,Smemberinfo);
PHPCMS整站代碼分析講解(四)
這個講phpcms的數(shù)據(jù)庫類和phpcms的文本緩存的實現(xiàn).看了看
都是很簡單的東西.大家看著我注釋慢慢看吧.慢慢理解,最好能裝了PHPCMS在來看.因為這樣可以看下它
的數(shù)據(jù)庫結(jié)構(gòu)信息.可以幫助理解.
不明白的繼續(xù)問吧.
首先是數(shù)據(jù)庫類,phpcms的數(shù)據(jù)庫分mysql和mssql版本.MSSQL版本的我就不說了.他們主要的sql
語句不同點就在于我們分頁常用到的limit語句.所以.在mssql數(shù)據(jù)庫類驅(qū)動里.他做了個挺好的封裝.讓
MYSQL和MSSQL在SQL語句方面的差異性就很小了.可以說PHPCMS你可以隨便轉(zhuǎn)換數(shù)據(jù)庫只要在代碼
中換下數(shù)據(jù)庫類驅(qū)動就行.
[Copytoclipboard][-]
CODE:
<?php
/**
mysql數(shù)據(jù)庫類。寫得比較簡單。也沒什么好說的。大家自己看下理解下。
然后就可以跳過了。
*/
defined('IN_PHPCMS')orexiti'AccessDenied');
/**
這個東西是不是很熟呀。對了。在上?章已經(jīng)講過了。也已經(jīng)在上一章的common.inc.php啟動文件里面
定義了IN.PHPCMS所以在以下的PHP文件里都檢測下是否是人為"跳墻''進(jìn)來的。是就中斷
*/
*Mysql數(shù)據(jù)庫類,支持Cache功能
*/
classdb_mysql
(
/**
*MySQL連接標(biāo)識
*@varresource
*/
var$connid;
/**
*整型變量用來計算被執(zhí)行的sql語句數(shù)量
*@varint
*/
var$querynum=0;
/**
*數(shù)據(jù)庫連接,返回數(shù)據(jù)庫連接標(biāo)識符
*@paramstring數(shù)據(jù)庫服務(wù)需主機(jī)
*@paramstring數(shù)據(jù)庫服務(wù)器帳號
*@paramstring數(shù)據(jù)庫服務(wù)器密碼
*@paramstring數(shù)據(jù)庫名
*@parambool是否保持持續(xù)連接,1為持續(xù)連接,0為非持續(xù)連接
*@returnlinkjdentifier
*/
functionconnect($dbhostz$dbuser,$dbpw,$dbnamez$pconnect=0)
(
global$CONFIG;
$func=$pconnect==1?'nysqLpconnect':'mysql_connect';
/**
mysql_pconnect()為常連接。它和mysql_connect的區(qū)別是前者在多進(jìn)程的WEB服務(wù)器上效率比較
好。但也有瑕疵就是在有關(guān)事務(wù)和數(shù)據(jù)表鎖方面。詳情請查看自己的手冊。
7
if(!$this->connid=@$func($dbhost,$dbuser,$dbpw))
{
$this->halt('CannotconnecttoMySQLserver');
}
〃當(dāng)mysql版本為4.1以上時,啟用數(shù)據(jù)庫字符集設(shè)置
if($this->version()>'4.1'&&$CONFIG[,dbcharset1])
{
mysql_query("SETNAMES"'^CONFIGfdbcharset'].,$this->connid);
)
//當(dāng)mysql版本為5.0以上時,設(shè)置sqlmode,mysql5數(shù)據(jù)庫帶了字符集模式。設(shè)置卜.就好
if($this->version()>'5.0')
(
mysql_query("SETsql_mode="",$this->connid);
)
if($dbname)
{
if([email=!@mysql_select_db($dbname]!@mysql_select_db($dbname[/email],$this->connid))
{
$this->halt('Cannotusedatabase'.$dbname);
)
)
return$this->connid;
)
/**
*選擇數(shù)據(jù)庫
*@paramstring數(shù)據(jù)庫名
*/
functionselect_db($dbname)
returnmysql_select_db($dbname,$this->connid);
}
/**
*執(zhí)行sql語句
*@paramstringsql語句
*@paramstring默認(rèn)為空,可選值為CACHEUNBUFFERED
*@paramintCache以秒為隼位的生命周期
*@returnresource
*/
functionquery($sql,$type=",$expires=3600,$dbname=")
{
$func=$type=='UNBUFFERED'?'mysql_unbuffered_query':'mysql_query';
/**
mysql_unbuffered_query效率更好。節(jié)省內(nèi)存看手冊
*/
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 銀行風(fēng)險控制崗位面試題及答案
- 特殊血型(如Rh陰性)患者的輸血策略
- 專用儀器儀表項目可行性分析報告范文
- 網(wǎng)絡(luò)工程師崗位面試題及答案詳解
- 財務(wù)報表的異常數(shù)據(jù)識別與處理考試題
- 切魚機(jī)建設(shè)項目可行性分析報告(總投資14000萬元)
- 深度解析(2026)《GBT 18589-2001焦化產(chǎn)品蒸餾試驗的氣壓補(bǔ)正方法》(2026年)深度解析
- 特殊凝血功能異?;颊邇?nèi)鏡知情同意策略
- 醫(yī)藥行業(yè)財務(wù)分析面試題及答案詳解
- 物聯(lián)網(wǎng)遠(yuǎn)程監(jiān)護(hù):基層重癥資源下沉方案
- 珠海市紀(jì)委監(jiān)委公開招聘所屬事業(yè)單位工作人員12人考試題庫附答案
- 2025內(nèi)蒙古鄂爾多斯東勝區(qū)消防救援大隊招聘鄉(xiāng)鎮(zhèn)(街道)消防安全服務(wù)中心專職工作人員招聘3人考試筆試模擬試題及答案解析
- 2025濟(jì)寧市檢察機(jī)關(guān)招聘聘用制書記員(31人)筆試考試參考試題及答案解析
- 2025年安全總監(jiān)年終總結(jié)報告
- 安順市人民醫(yī)院招聘聘用專業(yè)技術(shù)人員筆試真題2024
- 廚師專業(yè)職業(yè)生涯規(guī)劃與管理
- 2025年10月自考00688設(shè)計概論試題及答案
- 六西格瑪設(shè)計實例
- 海南檳榔承包協(xié)議書
- 工業(yè)交換機(jī)產(chǎn)品培訓(xùn)
- 2025浙江溫州市龍港市國有企業(yè)招聘產(chǎn)業(yè)基金人員3人筆試歷年備考題庫附帶答案詳解試卷3套
評論
0/150
提交評論