PHPCMS整站代碼分析講解_第1頁
PHPCMS整站代碼分析講解_第2頁
PHPCMS整站代碼分析講解_第3頁
PHPCMS整站代碼分析講解_第4頁
PHPCMS整站代碼分析講解_第5頁
已閱讀5頁,還剩32頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論