廣告廣告
  加入我的最愛 設為首頁 風格修改
首頁 首尾
 手機版   訂閱   地圖  簡體 
您是第 49899 個閱讀者
 
發表文章 發表投票 回覆文章
  可列印版   加為IE收藏   收藏主題   上一主題 | 下一主題   
月光 手機
個人頭像
個人文章 個人相簿 個人日記 個人地圖
社區建設獎
頭銜:看我代替月亮懲罰你!看我代替月亮懲罰你!
版主
級別: 版主 該用戶目前不上站
版區: Unix-like, 網站架設
推文 x42 鮮花 x565
分享: 轉寄此文章 Facebook Plurk Twitter 複製連結到剪貼簿 轉換為繁體 轉換為簡體 載入圖片
推文 x2
[<5.0][教學] PHPWind 源碼解析
1、本源碼分析針對PHPWind 4.3.2 060428更新版做出
2、除部分文件外,多數文件均可直接使用,不影響論壇的正常執行
3、本次僅對global.php相關的文件進行解析說明
4、下面只貼出其中幾個重要文件的源碼分析,其餘文件請自行下載附件檢視
基本上看懂這些文件,可以對phpwind論壇的執行機制有個大概的瞭解

下面對代碼中的顏色使用作個說明
保留關鍵字
函數
類型
字符串
註釋
括號    
數字
運算符
預定義變量
PHP開始結束標籤


global.php

<?php
/**
*
* Copyright (c) 2003-06 PHPWind.net. All rights reserved.
* Support : http://www.php...net/
* This software is the proprietary information of PHPWind.com.
*
*/
//此文件內容為全局變量和公用函數

//定義只有運行錯誤和語法編譯錯誤才會顯示錯誤信息
error_reporting(E_ERROR | E_PARSE);

//設置php.ini中 magic_quotes_runtime 選項值為0
//若 magic_quotes_runtime 打開時,所有外部引入的數據庫資料或者文件等等都會自動轉為含有反斜線溢出字符的資料。
//0表示關閉此功能

set_magic_quotes_runtime(0);

//microtime() 當前 Unix 時間戳以及微秒數。本函數僅在支持 gettimeofday() 系統調用的操作系統下可用。
//如果調用時不帶可選參數,本函數以 "msec sec" 的格式返回一個字符串,其中 sec 是自 Unix 紀元(0:00:00 January 1, 1970 GMT)起到現在的秒數,msec 是微秒部分。字符串的兩部分都是以秒為單位返回的。

//用$t_array變量記錄microtime()函數產生的msec和sec,此時$t_array代表數組

$t_array = explode(' ',microtime());
//$P_S_T記錄當前時間秒數
$P_S_T = $t_array[0] + $t_array[1];

//判斷__FILE__是否為空,返回路徑值,並定義為D_P和R_P
//其中__FILE__文件的完整絕對路徑和文件名
//D_P和R_P的區別在於,當論壇使用二級目錄設置時,D_P用於分論壇,R_P用於記錄總論壇目錄的絕對路徑
//具體參考PHPWind論壇關於二級目錄方面的說明
//在沒有使用這方面設置的時候這兩個值相等

define('D_P',__FILE__ ? getdirname(__FILE__).'/' : './');
define('R_P',D_P);

//銷毀以下變量
unset($_ENV,$HTTP_ENV_VARS,$_REQUEST,$HTTP_POST_VARS,$HTTP_GET_VARS,$HTTP_POST_FILES,$HTTP_COOKIE_VARS);

//get_magic_quotes_gpc函數取得 PHP 環境配置的變量 magic_quotes_gpc (GPC, Get/Post/Cookie) 值。返回 0 表示關閉本功能;返回 1 表示本功能打開。當 magic_quotes_gpc 打開時,所有的 ' (單引號), " (雙引號), \ (反斜線) and 空字符會自動轉為含有反斜線的溢出字符。
//在magic_quotes_gpc功能關閉的情況下,對$_POST、$_GET、$_COOKIE中的特殊字符轉義處理

if(!get_magic_quotes_gpc()){
//$_POST 經由 HTTP POST 方法提交至腳本的變量。
Add_S($_POST);
//$_GET 經由 URL 請求提交至腳本的變量。
Add_S($_GET);
//$_FILES 通過 HTTP POST 方法傳遞的已上傳文件項目組成的數組。
Add_S($_FILES);
//$_COOKIE 經由 HTTP Cookies 方法提交至腳本的變量。
Add_S($_COOKIE);
}

//$_SERVER 變量由 web 服務器設定或者直接與當前腳本的執行環境相關聯。
//如果服務器變量中存在HTTP_X_FORWARDED_FOR,則從中取得客戶端ip,如果沒有則到HTTP_CLIENT_IP中取,都沒有則到REMOTE_ADDR中取
//'HTTP_CLIENT_IP','HTTP_X_FORWARDED_FOR'是代理的IP
//這些IP頭消息未必能夠取得到(因為不同的瀏覽器不同的網絡設備,可能發不同的IP頭消息).所以PHP就嘗試把每個IP頭消息判斷一下,若有,則取其中的一個.
//$c_agentip記錄是否為代理ip

if($_SERVER['HTTP_X_FORWARDED_FOR']){
$onlineip = $_SERVER['HTTP_X_FORWARDED_FOR'];
$c_agentip=1;
}elseif($_SERVER['HTTP_CLIENT_IP']){
$onlineip = $_SERVER['HTTP_CLIENT_IP'];
$c_agentip=1;
}else{
$onlineip = $_SERVER['REMOTE_ADDR'];
$c_agentip=0;
}

//str_replace 用指定的字符串替換在被搜索的字符串中找到的字符串;
//第一個,要搜索的字符串,第二個為替換為的字符串,第三個被搜索的字符串
//取得客戶端ip值

$onlineip = substrs(str_replace("\n",'',$onlineip),16);
//返回自從 Unix 紀元(格林威治時間 1970 年 1 月 1 日 00:00:00)到當前時間的秒數。
$timestamp= time();
//require_once require_once() 語句在腳本執行期間包含並運行指定文件。此行為和 require() 語句類似,
//唯一區別是如果該文件中的代碼已經被包含了,則不會再次包含.應該用於在腳本執行期間同一個文件有可能被
//包含超過一次的情況下,想確保它只被包含一次以避免函數重定義,變量重新賦值等問題。
//包含require/defend.php文件,如果其中有重複包含,略過

require_once(R_P.'require/defend.php');

//根據時區設置$db_cvtime取得正確的時間$timestamp
$db_cvtime != 0 && $timestamp += $db_cvtime*60;

//如果論壇運行在DEBUG模式下
if($db_debug){
//定義顯示所有錯誤除了運行NOTICE錯誤
error_reporting(E_ALL ^ E_NOTICE);
}
//PHPWind論壇版本變量
$wind_version = "4.3.2";
//在線列表大小值
$db_olsize = 96;
//靜態htm緩存目錄名
$htm dir = 'htm_data';
//'PHP_SELF' 當前正在執行腳本的文件名,與 document root 相關
//'SCRIPT_NAME' 當前執行腳本的絕對路徑名,注: 如果腳本在 CLI 中被執行,作為相對路徑,例如
//file.php 或 ../file.php,$_SERVER['SCRIPT_FILENAME'] 將包含用戶指定的相對路徑。
//'QUERY_STRING' 查詢(query)的字符串(URL 中第一個問號 ? 之後的內容)。
//如果PHP_SELF(當前正在執行腳本的文件名)為空,則設置其為SCRIPT_NAME(包含當前腳本的路徑)
!$_SERVER['PHP_SELF'] && $_SERVER['PHP_SELF']=$_SERVER['SCRIPT_NAME'];
//取得請求url完整的路徑保存在$REQUEST_URI變量中
$REQUEST_URI = $_SERVER['PHP_SELF'].'?'.$_SERVER['QUERY_STRING'];
//判斷當前執行文件名中是否包含靜態目錄$db_dir,如果包含,則
if(strpos($_SERVER['PHP_SELF'],$db_dir)!==false){
//strpos 查找字符串第一次出現的位置,第一個為被查找的字符串,第二個為要查找的字符串。返回值為0,或
//者被查找的字符第一次出現的數字位置的值;
//取到靜態目錄前

$tmp=substr($_SERVER['PHP_SELF'],0,strpos($_SERVER['PHP_SELF'],$db_dir));
}else{
//取全部
$tmp=$_SERVER['PHP_SELF'];
}
//HTTP_HOST-當前請求的 Host: 頭信息的內容
//設置論壇地址

$db_bbsurl="http://$_s...er/[HTTP_HOST]"
.substr($tmp,0,strrpos($tmp,'/'));

//(int) 強制類型轉換為整型
//定義整型變量$fid用於記錄板塊id

$fid = (int)$fid;
//定義整型變量$tid用於記錄帖子id
$tid = (int)$tid;
//初始化附件保存目錄$attachname及js腳本路徑$js_path
$attachname = $js_path = '';
//包含data/bbscache/dbset.php文件,如果其中有重複包含,略過
require_once(D_P.'data/bbscache/dbset.php');

//ob_start("ob_gzhandler");是一種壓縮技術
//ob_start();僅僅啟動緩衝 並沒有壓縮輸出
//ob_start 用來 打開輸出緩衝區。 當緩衝區激活時,所有來自PHP程序的非文件頭信息均不會發送,而是保存在內部緩衝區。為了輸出緩衝區的內容,可以使用ob_end_flush()或者使用ob_end_clean()來輸出緩衝區的內容。
//是否允許GZIP 壓縮輸出,允許使用ob_gzhandler壓縮技術,否則只啟動緩衝

$db_obstart == 1 ? ob_start('ob_gzhandler') : ob_start();

//如果使用跨台固定圖片鏈,則圖片路徑為$db_http值,否則使用$picpath圖片保存目錄
$imgpath = $db_http != 'N' ? $db_http : $picpath;
//如果使用遠程附件連接設置,則附件路徑為$db_attachurl,否則使用$attachname附件保存目錄
$attachpath = $db_attachurl != 'N' ? $db_attachurl : $attachname;
//本地圖片路徑
$imgdir = R_P.$picpath;
//本地附件路徑
$attachdir = R_P.$attachname;

//如果D_P和R_P不相等並且使用了跨台固定圖片鏈,即使用了二級目錄功能
if(D_P != R_P && $db_http != 'N'){
//取總站論壇地址
$R_url=substr($db_http,-1)=='/' ? substr($db_http,0,-1) : $db_http;
$R_url=substr($R_url,0,strrpos($R_url,'/'));
}else{
//總站論壇地址即全局變量$db_bbsurl中的論壇地址值
$R_url=$db_bbsurl;
}

//如果cookie中上次訪問變量lastvisit值是否為空
if(GetCookie('lastvisit')){
//取cookie中的上次訪問變量lastvisit值,以"\t"分割並分別賦於$c_oltime,$lastvisit,$lastpath
//$c_oltime-用戶在線時間,$lastvisit-上次訪問時間,$lastpath-上次訪問路徑

list($c_oltime,$lastvisit,$lastpath) = explode("\t",GetCookie('lastvisit'));
//判斷現在和上次訪問之間的時間差是否小於論壇設定的在線用戶時限,如果小於,則用戶此次在線時間累加相應時間數值
($onbbstime=$timestamp-$lastvisit)<$db_onlinetime && $c_oltime+=$onbbstime;
}else{
$lastvisit=$lastpath='';
$c_oltime=0;
}
//取在線偏移cookie(在線列表文件中的偏移量)
$ol_offset = GetCookie('ol_offset');

//取風格cookie
$skinco = GetCookie('skinco');
//若刷新預防時間不等於0
if ($db_refreshtime!=0){
//$REQUEST_URI 訪問此頁面所需的 URI。
//如果$REQUEST_URI與上次最後訪問的路徑相同,且與上次訪問的時間差小於論壇設定的刷新預防時間

if($REQUEST_URI==$lastpath && $onbbstime<$db_refreshtime){
  //如果Cookie中沒有winduser即用戶的記錄,設置$groupid為guest即當前用戶歸於遊客組
  !GetCookie('winduser') && $groupid='guest';
  //創始人帳號設置為TRUE
  $manager=TRUE;
  //如果cookie中沒有風格變量,則風格設置為論壇的默認風格
  $skin = $skinco ? $skinco : $db_defaultstyle;
  //轉頁面顯示語言文件中refresh_limit對應鍵值的提示信息
  Showmsg("refresh_limit");
}
}

//引用 在 PHP 中引用意味著用不同的名字訪問同一個變量內容。這並不像 C 的指針,替代的是,引用是符號
//表別名。注意在
PHP 中,變量名和變量內容是不一樣的,因此同樣的內容可以有不同的名字。PHP 的引用允
//許用兩個變量來指向同一個內容。意思是,當這樣做時: $a =& $b;這意味著 $a 和 $b 指向了
//同一個變量。注: $a 和 $b 在這裡是完全相同的,這並不是 $a 指向了 $b 或者相反,而是 $a 和 $b 指向
//了同一個地方。注: 如果具有引用的數組被拷貝,其值不會解除引用。對於數組傳值給函數也是如此。
$H_url =& $db_wwwurl;
$B_url =& $db_bbsurl;

//包含data/sql_config.php文件,如果其中有重複包含,略過
require_once(D_P.'data/sql_config.php');

//如果論壇關閉
if ($db_bbsifopen==0){
//從cookie中取得AdminUser(管理人員)變量值,並對其進行解碼操作後,以"\t"分割存入數組$CK中
$CK = explode("\t",StrCode(GetCookie('AdminUser'),'DECODE'));
//如果上次訪問時間$CK[0]與現在相差超過1800s即30分鐘
//或者帳號$CK[1]不是創始人帳號$manager
//或者不符合安全檢測

if ($timestamp-$CK[0]>1800 || $CK[1]!=$manager || !SafeCheck($CK,PwdCode($manager_pwd))){
  //取得風格值
  $skin = $skinco ? $skinco : $db_defaultstyle;
  //設置用戶組為空
  $groupid = '';
  //轉頁面顯示$db_whybbsclose信息即論壇關閉的原因
  Showmsg($db_whybbsclose);
}
}


//gmdate -- 格式化一個 GMT/UTC 日期/時間
//date -- 格式化一個本地時間/日期,返回將整數 timestamp 按照給定的格式字串而產生的
//字符串。如果沒有給出時間戳則使用本地當前時間。換句話說,timestamp 是可選的,默認值為 time()。注:
//有效的時間戳典型範圍是格林威治時間 1901 年 12 月 13 日 20:45:54 到 2038 年 1 月 19 日
//03:14:07。(此範圍符合 32 位有符號整數的最小值和最大值)。不過在
PHP 5.1 之前此範圍在某些系統
//(如 Windows)中限制為從 1970 年 1 月 1 日到 2038 年 1 月 19 日。
//格式字串可以識別以下 format 參數的字符串 format 字符 說明 返回值例子
//日 --- ---
//d 月份中的第幾天,有前導零的 2 位數字 01 到 31
//D 星期中的第幾天,文本表示,3 個字母 Mon 到 Sun
//j 月份中的第幾天,沒有前導零 1 到 31
//l(「L」的小寫字母) 星期幾,完整的文本格式 Sunday 到 Saturday
//N ISO-8601 格式數字表示的星期中的第幾天(
PHP 5.1.0 新加) 1(表示星期一)到 7(表示星期天)
//S 每月天數後面的英文後綴,2 個字符 st,nd,rd 或者 th。可以和 j 一起用
//w 星期中的第幾天,數字表示 0(表示星期天)到 6(表示星期六)
//z 年份中的第幾天 0 到 366
//星期 --- ---
//W ISO-8601 格式年份中的第幾周,每週從星期一開始(
PHP 4.1.0 新加的)
//月 --- ---
//F 月份,完整的文本格式,例如 January 或者 March January 到 December
//m 數字表示的月份,有前導零 01 到 12
//M 三個字母縮寫表示的月份 Jan 到 Dec
//n 數字表示的月份,沒有前導零 1 到 12
//t 給定月份所應有的天數 28 到 31
//年 --- ---
//L 是否為閏年 如果是閏年為 1,否則為 0
//o ISO-8601 格式年份數字。這和 Y 的值相同,只除了如果 ISO 的星期數(W)屬於前一年或下一年,則用
//那一年。(
PHP 5.1.0 新加) Examples: 1999 or 2003
//Y 4 位數字完整表示的年份 例如:1999 或 2003
//y 2 位數字表示的年份 例如:99 或 03
//時間 --- ---
//a 小寫的上午和下午值 am 或 pm
//A 大寫的上午和下午值 AM 或 PM
//B Swatch Internet 標準時 000 到 999
//g 小時,12 小時格式,沒有前導零 1 到 12
//G 小時,24 小時格式,沒有前導零 0 到 23
//h 小時,12 小時格式,有前導零 01 到 12
//H 小時,24 小時格式,有前導零 00 到 23
//i 有前導零的分鐘數 00 到 59
//s 秒數,有前導零 00 到 59
//時區 --- ---
//e 時區標識(
PHP 5.1.0 新加) 例如:UTC,GMT,Atlantic/Azores
//I 是否為夏令時 如果是夏令時為 1,否則為 0
//O 與格林威治時間相差的小時數 例如:+0200
//T 本機所在的時區 例如:EST,MDT(在 Windows 下為完整文本格式,例如「Eastern
//Standard Time」,中文版會顯示「中國標準時間」)。
//Z 時差偏移量的秒數。UTC 西邊的時區偏移量總是負的,UTC 東邊的時區偏移量總是正的。 -43200 到 43200
//完整的日期/時間 --- ---
//c ISO 8601 格式的日期(
PHP 5 新加) 2004-02-12T15:19:21+00:00
//r RFC 822 格式的日期 例如:Thu, 21 Dec 2000 16:01:07 +0200
//U 從 Unix 紀元(January 1 1970 00:00:00 GMT)開始至今的秒數 參見 time()
//格式字串中不能被識別的字符將原樣顯示。Z 格式在使用 gmdate() 時總是返回 0。
//取當前默認時區時間的24小時時間值,賦於$t['hours']
$t = array('hours'=>gmdate('G',$timestamp+$db_timedf*3600));
//floor -- 捨去法取整
//今天的起始時間

$tdtime = (floor($timestamp/3600)-$t['hours'])*3600;
//是否需要更新在線情況標記
$runfc = 'N';
//如果上次訪問時間和當前時間的時間差大於論壇設置的在線用戶時限
//或者板塊$fid不為空且不等於cookie中的上次訪問板塊id
//或者上次訪問板塊id的cookie存在且$wind_in(論壇動作)為hm(論壇首頁)

if($timestamp-$lastvisit>$db_onlinetime || ($fid && $fid != GetCookie('lastfid')) || (GetCookie('lastfid') && $wind_in=='hm')){
//設置cookie中上次訪問板塊id
Cookie('lastfid',$fid);
//設置$runfc為Y
$runfc='Y';
//包含data/userglobal.php文件,如果其中有重複包含,略過
require_once(R_P.'require/userglobal.php');
}

//包含require/db_'.$database.'.php文件,如果其中有重複包含,略過(此處為db_mysql.php)
require_once(R_P.'require/db_'.$database.'.php');
//創建數據庫連接
$db = new DB($dbhost, $dbuser, $dbpw, $dbname, $pconnect);
//銷毀$dbhost,$dbuser,$dbpw,$dbname,$pconnect,$manager_pwd變量
unset($dbhost,$dbuser,$dbpw,$dbname,$pconnect,$manager_pwd);
//從cookie中取得winduser信息解碼用"\t"分割後存入$winduid,$windpwd
list($winduid,$windpwd)=explode("\t",StrCode(GetCookie('winduser'),'DECODE'));
//若用戶登陸id存在且密碼長度大等於16
if($winduid && strlen($windpwd)>=16){
//定義$winddb為用戶信息數組
$winddb = User_info();
//用戶id
$winduid = $winddb['uid'];
//用戶組id
$groupid = $winddb['groupid'];
//用戶實際威望為數據庫中威望值/10取整
$userrvrc = (int)($winddb['rvrc']/10);
//用戶名
$windid = $winddb['username'];
//用戶時間顯示格式
$_datefm = $winddb['datefm'];
//用戶時區設置
$_timedf = $winddb['timedf'];
//用戶皮膚
$skin = $winddb['style'] ? $winddb['style'] : $db_defaultstyle;
//用戶在線ip
$winddb['onlineip']=substr($winddb['onlineip'],0,strpos($winddb['onlineip'],'|'));
//如果用戶組id為-1則設置用戶組id為用戶的會員組id
$groupid=='-1' && $groupid=$winddb['memberid'];
//若用戶開啟簽名顯示功能 且
//((用戶開始使用簽名時間為空 且 簽名顯示一天需要交易幣個數不為空 且當前用戶組屬於需要購買簽名顯示的用戶組 且 用戶擁有的交易幣數大於簽名顯示一天需要交易幣個數) 或者
//(用戶開始使用簽名時間不為空 且 用戶開始使用簽名時間不等於今日開始時間))

if($winddb['showsign'] && (!$winddb['starttime'] && $db_signmoney && strpos($db_signgroup,",$groupid,") !== false && $winddb['currency'] > $db_signmoney || $winddb['starttime'] && $winddb['starttime'] != $tdtime)){
  //包含require/Signfunc.php文件,如果其中有重複包含,略過
  require_once(R_P.'require/Signfunc.php');
  //對用交易幣購買簽名做相應的操作
  Signfunc($winddb['showsign'],$winddb['starttime'],$winddb['currency']);
}
}
else{
//若登陸id不存在
//設置風格為論壇默認風格

$skin = $db_defaultstyle;
//用戶組為遊客組
$groupid = 'guest';
//銷毀$winddb
unset($winddb);
//設置用戶名,用戶id,用戶時間顯示方式,用戶時區設置
$windid=$winduid=$_datefm=$_timedf='';
}
//取最優先的風格
$_GET['skinco'] && $skinco=$_GET['skinco'];
$_POST['skinco'] && $skinco=$_POST['skinco'];
//如果風格存在,且D_P."data/style/$skinco.php"文件存在,風格變量中不包含".."
if($skinco && file_exists(D_P."data/style/$skinco.php") && strpos($skinco,'..')===false){
//設置風格變量
$skin=$skinco;
//設置風格cookie
Cookie('skinco',$skinco);
}
//對處在ip封禁列表中的ip禁止登陸
Ipban();
//設置上次訪問cookie,包括此次在線時間、當前時間、請求頁面
Cookie('lastvisit',$c_oltime."\t".$timestamp."\t".$REQUEST_URI);
//如果當前用戶組不是遊客
if($groupid!='guest'){
//且相應組別配置文件存在
if(file_exists(D_P."data/groupdb/group_$groupid.php")){
  //包含相應組別配置文件,如有重複,略過
  require_once(D_P."data/groupdb/group_$groupid.php");
}else{
  //否則載入默認組別配置文件
  require_once(D_P."data/groupdb/group_1.php");
}
}
else{
//載入遊客組配置文件
require_once(D_P."data/groupdb/group_2.php");
}

//HTTP_REFERER 鏈接到當前頁面的前一頁面的 URL 地址。不是所有的用戶代理(瀏覽器)都會設置這個變量,而且有的還可以手工修改 HTTP_REFERER。因此,這個變量不總是真實正確的。
//HTTP_HOST 當前請求的 Host: 頭信息的內容。
//如果允許用戶使用宣傳代碼且用戶名非空且傳入的參數$u為數字
//或者傳入的參數$a存在且長度不超過16且HTTP_REFERER中不含HTTP_HOST
if($db_ads && !$windid && (is_numeric($u) || ($a && strlen($a)<16)) && strpos($_SERVER['HTTP_REFERER'],$_SERVER['HTTP_HOST'])===false){
//設置用戶宣傳cookie userads
Cookie('userads',"$u\t$a");
}

//如果SCR常量沒有定義
if(!defined('SCR')){
//定義其為other
define('SCR','other');
}
//標記頁面類型
$SCR = SCR;
$header_ad=$footer_ad='';
//如果頁面類型不是帖子頁面
if(SCR != 'read'){
//取得廣告信息數組
$advertdb = AdvertInit(SCR,$fid);
//is_array -- 檢測變量是否是數組
if(is_array($advertdb['header'])){
  //array_rand -- 從數組中隨機取出一個或多個單元
  //取得頁首廣告

  $header_ad = $advertdb['header'][array_rand($advertdb['header'])]['code'];
}
if(is_array($advertdb['footer'])){
  //取得頁尾廣告
  $footer_ad = $advertdb['footer'][array_rand($advertdb['footer'])]['code'];
}
}

//返回頁首導航 類似 霏凡論壇 -> 口- 超級灌水
function headguide($guidename=array(),$guide=''){
global $fid,$jinhua;
if(is_array($guidename)){
  foreach($guidename as $key=>$value){
      if($key){
      $headguide.=$value ? " -> <a href='$value'>$key</a>" : " -> $key";
      }
  }
}
else{
  $headguide.=" -> ".$guidename;
}
//返回頁首導航字符串
return $headguide;
}

//頁面跳轉
function refreshto($URL,$content,$statime=1){
global $db_ifjump;
//替換url中的特殊字符=
$URL=str_replace('=','=',$URL);
//如果開啟自動跳轉且多少秒後抓向$statime大於0
if($db_ifjump && $statime>0){

//清空緩衝
  ob_end_clean();
  //是否允許GZIP 壓縮輸出,允許使用ob_gzhandler壓縮技術,否則只啟動緩衝
  global $tplpath,$fid,$imgpath,$db_obstart,$db_bbsname,$skin,$B_url;
  $index_name =& $db_bbsname;
  $index_url =& $B_url;
  $db_obstart==1 ? ob_start('ob_gzhandler') : ob_start();
  //確定引用風格
  if(file_exists(D_P."data/style/$skin.php") && strpos($skin,'..')===false){
      include_once(D_P."data/style/$skin.php");
  }else{
      include_once(D_P."data/style/wind.php");
  }
  //解出全局變量數組,如果有衝突不覆蓋
  @extract($GLOBALS, EXTR_SKIP);
  //包含對應風格目錄下的lang_refreshto.php語言文件,如果其中有重複包含,略過
  require_once GetLang('refreshto');
  $lang[$content] && $content=$lang[$content];
  //包含對應風格目錄下的refreshto.htm文件
  @require PrintEot('refreshto');
  //退出
  exit;
} else{
  ObHeader($URL);
}
}

//頁面直接轉向
function ObHeader($URL){
global $db_obstart,$db_bbsurl,$db_htmifopen;
//strtolower-小寫處理字符串
//如果開啟靜態目錄部署功能且url中不是http開頭

if($db_htmifopen && strtolower(substr($URL,0,4))!='http'){
  $URL="$db_bbsurl/$URL";
}
//頁面直接轉向
if($db_obstart){
  //header -- 發送一個原始 HTTP 標頭
  header("Location: $URL");exit;
}else{
  ob_start();
  echo "<meta http-equiv='refresh' content=Ɔurl=$URL'>";
  exit;
}
}


//轉向顯示提示信息的頁面顯示提示信息
function Showmsg($msg_info,$dejump=0){
//extract -- 從數組中將變量導入到當前的符號表
//extract() 檢查每個鍵名看是否可以作為一個合法的變量名,同時也檢查和符號表中已有的變量名的衝突。對待非法/數字和衝突的鍵名的方法將根據 extract_type 參數決定。可以是以下值之一:
//EXTR_OVERWRITE(如果有衝突,覆蓋已有的變量)
//EXTR_SKIP(如果有衝突,不覆蓋已有的變量)
//EXTR_PREFIX_SAME(如果有衝突,在變量名前加上前綴 prefix)
//EXTR_PREFIX_ALL(給所有變量名加上前綴 prefix)
//EXTR_PREFIX_INVALID(僅在非法/數字的變量名前加上前綴 prefix)
//EXTR_IF_EXISTS(僅在當前符號表中已有同名變量時,覆蓋它們的值。其它的都不處理。可以用在已經定義了一組合法的變量,然後要從一個數組例如 $_REQUEST 中提取值覆蓋這些變量的場合。)
//EXTR_PREFIX_IF_EXISTS(僅在當前符號表中已有同名變量時,建立附加了前綴的變量名,其它的都不處理)
//EXTR_REFS(將變量作為引用提取。這有力地表明了導入的變量仍然引用了 var_array 參數的值。可以單獨使用這個標誌或者在 extract_type 中用 OR 與其它任何標誌結合使用)
//如果沒有指定 extract_type,則被假定為 EXTR_OVERWRITE。
//extract() 返回成功導入到符號表中的變量數目。
//$GLOBALS由所有已定義全局變量組成的數組。變量名就是該數組的索引。
//將全局變量導入當前符號表

@extract($GLOBALS, EXTR_SKIP);
//在函數中聲明了全局變量,任何變量的所有引用變量都會指向到全局變量。包括修改
//聲明全局變量,風格圖片文件路徑$stylepath,表格寬度$tablewidth,小表格寬度$mtablewidth,風格模板路徑$tplpath,$runfc

global $stylepath,$tablewidth,$mtablewidth,$tplpath,$runfc;
$runfc='';
//檢查SIMPLE常量是否定義,如果定義過
if(defined('SIMPLE')){
  //<base>是一個鏈接基準標記,用以改變頁面中所有鏈接標記的參數默認值。
  echo "<base href=\"$db_bbsurl/\">";
}
//包含require/header.php文件,如果其中有重複包含,略過
require_once(R_P.'require/header.php');
//包含對應風格目錄下的lang_msg.php語言文件,如果其中有重複包含,略過
require_once GetLang('msg');
//如果相應的語言文件中對應鍵值存在,則設置$msg_info為對應值
$lang[$msg_info] && $msg_info=$lang[$msg_info];
//包含對應風格目錄下的showmsg.htm文件
require_once PrintEot('showmsg');
exit;
}

//返回參數指定的文件相應風格語言文件路徑
function GetLang($lang,$EXT="php"){
//聲明全局變量風格模板路徑
global $tplpath;
//路徑為……
$path=R_P."template/$tplpath/lang_$lang.$EXT";
//如果該風格下模板指定的文件不存在,則路徑為默認的wind風格下的對應文件
!file_exists($path) && $path=R_P."template/wind/lang_$lang.$EXT";
return $path;
}

//返回參數指定的文件相應風格模板路徑
function PrintEot($template,$EXT="htm"){
//Copyright (c) 2003-06 PHPWind
//聲明全局變量風格模板路徑

global $tplpath;
//如果參數為空,則設置參數值為N
if(!$template) $template=N;
//路徑為……
$path=R_P."template/$tplpath/$template.$EXT";
//如果該風格下模板指定的文件不存在,則路徑為默認的wind風格下的對應文件
!file_exists($path) && $path=R_P."template/wind/$template.$EXT";
return $path;
}

//設置相關cookie
function Cookie($ck_Var,$ck_Value,$ck_Time = 'F'){
//聲明全局變量COOKIE有效目錄$db_ckpath,COOKIE有效域名$db_ckdomain,$timestamp
global $db_ckpath,$db_ckdomain,$timestamp;
//如果設置有效的cookie時間參數為F則,cookie有效時間設置為31536000s即1年
//否則如果傳入的cookie參數值為空並且有效時間參數為0則設置cookie有效時間為31536000s即1年前,也就是無效
//如果都不是則設置時間為傳入的cookie有效時間參數值

$ck_Time = $ck_Time == 'F' ? $timestamp + 31536000 : ($ck_Value == '' && $ck_Time == 0 ? $timestamp - 31536000 : $ck_Time);
//SERVER_PORT-服務器所使用的端口。默認為「80」。如果使用 SSL 安全連接,則這個值為用戶設置的 HTTP 端口。
//判斷是否使用安全連接

$S = $_SERVER['SERVER_PORT'] == 験' ? 1:0;
//如果COOKIE有效目錄為空則設置其為根目錄
!$db_ckpath && $db_ckpath = '/';
//setcookie -- 發送一個 cookie 信息
//參數說明:Cookie 的名字,Cookie 的值,Cookie 過期的時間(這是個 Unix 時間戳,即從 Unix 紀元開始的秒數),Cookie 在服務器端的有效路徑,該 cookie 有效的域名,指明 cookie 是否僅通過安全的 HTTPS 連接傳送(當設成 TRUE 時,cookie 僅在安全的連接中被設置,默認值為 FALSE)

setCookie($ck_Var,$ck_Value,$ck_Time,$db_ckpath,$db_ckdomain,$S);
}
//取cookie中的某變量值
function GetCookie($Var){
//_COOKIE 通過 HTTP cookies 傳遞的變量組成的數組。是自動全局變量。
return $_COOKIE[$Var];
}

//對處在ip封禁列表中的ip禁止登陸
function Ipban(){
//聲明全局變量IP封禁列表$db_ipban,客戶端ip$onlineip,圖片目錄$imgpath,風格圖片文件路徑$stylepath
global $db_ipban,$onlineip,$imgpath,$stylepath;
//如果ip封禁列表不為空
if($db_ipban){
  //以","分割
  $baniparray=explode(",",$db_ipban);
  foreach($baniparray as $banip){
      //ip為空繼續下個循環
      if(!$banip)continue;
      //去掉變量中的空格
      $banip=trim($banip);
      //如果客戶端ip在被封禁列表中
      if(strpos(','.$onlineip.'.',','.$banip.'.')!==false){
      //轉頁面顯示語言文件中ip_ban對應鍵值的提示信息
      Showmsg('ip_ban');
      }
  }
}
}


//刪除文件
function P_unlink($filename){
//判斷是否$filename是否包含..,包含則退出顯示Forbidden
strpos($filename,'..')!==false && exit('Forbidden');
//unlink -- 刪除文件
@unlink($filename);
}

//讀取文件內容
function readover($filename,$method="rb"){
//由於strpos函數返回是整數值,所以使用!==(不全等)符號判斷是否$filename是否包含..,包含則退出顯示Forbidden
strpos($filename,'..')!==false && exit('Forbidden');
//fopen -- 打開文件或者 URL,
//mode 說明
//'r' 只讀方式打開,將文件指針指向文件頭。
//'r+' 讀寫方式打開,將文件指針指向文件頭。
//'w' 寫入方式打開,將文件指針指向文件頭並將文件大小截為零。如果文件不存在則嘗試創建之。
//'w+' 讀寫方式打開,將文件指針指向文件頭並將文件大小截為零。如果文件不存在則嘗試創建之。
//'a' 寫入方式打開,將文件指針指向文件末尾。如果文件不存在則嘗試創建之。
//'a+' 讀寫方式打開,將文件指針指向文件末尾。如果文件不存在則嘗試創建之。
//'x' 創建並以寫入方式打開,將文件指針指向文件頭。如果文件已存在,則 fopen() 調用失敗並返回 FALSE,
//並生成一條 E_WARNING 級別的錯誤信息。如果文件不存在則嘗試創建之。這和給 底層的 open(2) 系統調
//用指定 O_EXCL|O_CREAT 標記是等價的。此選項被
PHP 4.3.2 以及以後的版本所支持,僅能用於本地文
//件。
//'x+' 創建並以讀寫方式打開,將文件指針指向文件頭。如果文件已存在,則 fopen() 調用失敗並返回
//FALSE,並生成一條 E_WARNING 級別的錯誤信息。如果文件不存在則嘗試創建之。這和給 底層的 open
//(2) 系統調用指定 O_EXCL|O_CREAT 標記是等價的。此選項被
PHP 4.3.2 以及以後的版本所支持,僅能用
//於本地文件。
//@為錯誤運算符。當將其放置在一個 PHP 表達式之前,該表達式可能產生的任何錯誤信息都被忽略掉。
//以讀方式打開文件,並將返回的資源(resource)保存在$handle變量中

if($handle=@fopen($filename,$method)){
  //flock -- 輕便的咨詢文件鎖定
  //flock() 操作的 handle 必須是一個已經打開的文件指針。operation 可以是以下值之一:LOCK_SH取得共享鎖定、LOCK_EX取得獨佔鎖定、LOCK_UN釋放鎖定、LOCK_NB不希望 flock() 在鎖定時堵塞

  flock($handle,LOCK_SH);
  //filesize返回文件字節數
  //fread() 從文件指針 handle 讀取最多 length 個字節(這裡為全部),返回類型為string

  $filedata=@fread($handle,filesize($filename));
  //fclose -- 關閉一個已打開的文件指針
  fclose($handle);
}
//返回文件內容
return $filedata;
}

//寫入文件
function writeover($filename,$data,$method="rb+",$iflock=1,$check=1,$chmod=1){
//Copyright (c) 2003-06 PHPWind
//判斷是否$filename是否包含..,包含則退出顯示Forbidden

$check && strpos($filename,'..')!==false && exit('Forbidden');
//touch -- 設定文件的訪問和修改時間
touch($filename);
//以讀寫方式打開文件,並將返回的資源(resource)保存在$handle變量中
$handle=fopen($filename,$method);
if($iflock){
  flock($handle,LOCK_EX);
}
//fwrite -- 寫入文件(可安全用於二進制文件)
fwrite($handle,$data);
//ftruncate -- 將文件截斷到給定的長度
if($method=="rb+") ftruncate($handle,strlen($data));
fclose($handle);
//chmod -- 改變文件模式
//mode 參數包含三個八進制數按順序分別指定了所有者、所有者所在的組以及所有人的訪問限制。每一部分都可以通過加入所需的權限來計算出所要的權限。數字 1 表示使文件可執行,數字 2 表示使文件可寫,數字 4 表示使文件可讀。

$chmod && @chmod($filename,0777);
}
//打開文件,返回文件數組
function openfile($filename){
//讀取文件內容
$filedata=readover($filename);
//做相應替換
$filedata=str_replace("\n","\n<:wind:>",$filedata);
//以"<:wind:>"分割,相當於每行一個數組元素
$filedb=explode("<:wind:>",$filedata);
//count -- 計算數組中的單元數目或對像中的屬性個數,返回 var 中的單元數目,通常是一個 array,任何其它
//類型都只有一個單元。對於對象,如果安裝了 SPL,可以通過實現 Countable 接口來調用 count()。該接口
//只有一個方法 count(),此方法返回 count() 函數的返回值。如果 var 不是數組類型或者實現了Countable
//接口的對象,將返回 1,有一個例外,如果 var 是 NULL 則結果是 0。注: 可選的 mode 參數自 PHP
//4.2.0 起可用。如果可選的 mode 參數設為 COUNT_RECURSIVE(或 1),count() 將遞歸地對數組計
//數。對計算多維數組的所有單元尤其有用。mode 的默認值是 0。count() 識別不了無限遞歸。count() 對沒
//有初始化的變量返回 0,但對於空的數組也會返回 0。用 isset() 來測試變量是否已經初始化。

$count=count($filedb);
//如果數組最後一個元素為空或者為"\r",銷毀此元素
if($filedb[$count-1]==''||$filedb[$count-1]=="\r"){unset($filedb[$count-1]);}
//empty -- 檢查一個變量是否為空,如果 var 是非空或非零的值,則 empty() 返回 FALSE。換句話說,
//""、0、"0"、NULL、FALSE、array()、var $var; 以及沒有任何屬性的對象都將被認為是空的,如果 var
//為空,則返回 TRUE。除了當變量沒有置值時不產生警告之外,empty() 是 (boolean) var 的反義詞。

if(empty($filedb)){$filedb[0]="";}
//返回文件數組
return $filedb;
}

//更新在線信息
function Update_ol(){
global $runfc;
if($runfc == 'Y'){
  //聲明全局變量在在線文件中的偏移量$ol_offset,用戶id$winduid,是否開啟IP統計$db_ipstates,是否修改$isModify
  global $ol_offset,$winduid,$db_ipstates,$isModify;
  //如果用戶id存在
  if($winduid != ''){
      //更新在線會員文件
      list($alt_offset,$isModify) = addonlinefile($ol_offset,$winduid);
  }else{
      //更新在線遊客文件
      list($alt_offset,$isModify) = addguestfile($ol_offset);
  }
  //如果返回的文件中偏移量和當前cookie中的不同,更新該cookie
  if($alt_offset!=$ol_offset)Cookie('ol_offset',$alt_offset,0);
  //重置是否更新在線信息標記為空
  $runfc='';
  //如果開啟ip統計 且
  //(cookie中ipstate信息為空且修改標記為是 或
  //cookie中ipstate信息存在但其小於今日開始時間)

  if($db_ipstates && ((!GetCookie('ipstate') && $isModify===1) || (GetCookie('ipstate') && GetCookie('ipstate')<$GLOBALS['tdtime']))){
      //包含require/ipstates.php,若有重複,略過
      require_once(R_P.'require/ipstates.php');
  }
}
}


//頁腳處理顯示函數
function footer(){
//聲明全局變量數據庫訪問類$db,是否開啟GZIP 壓縮輸出$db_obstart,是否在頁腳顯示程序運行時間$db_footertime,是否開啟靜態目錄部署功能$db_htmifopen,當前時間秒數$P_S_T,頭部和尾部表格寬度$mtablewidth,聯繫我們URL$db_ceoconnect,PHPWind版本$wind_version,圖片目錄$imgpath,此風格在image目錄下的文件夾名稱$stylepath,頁腳廣告$footer_ad,論壇聯盟廣告$db_union,當前時間$timestamp
global $db,$db_obstart,$db_footertime,$db_htmifopen,$P_S_T,$mtablewidth,$db_ceoconnect,$wind_version,$imgpath,$stylepath,$footer_ad,$db_union,$timestamp;
//更新在線信息
Update_ol();
//如果訪問類不為空
if($db){
  //記錄查詢次數
  $qn=$db->query_num;
}
//顯示是否開始gzip壓縮
$ft_gzip=($db_obstart==1 ? "Gzip enabled" : "Gzip disabled").$db_union[3];
//如果設置了允許在頁腳顯示程序運行時間
if ($db_footertime == 1){
  $t_array = explode(' ',microtime());
  //number_format 按照千分制劃分數字,string number_format ( float number [, int decimals [,
  //string dec_point, string thousands_sep]] )它接受一個、兩個或四個參數,不接受三個;給
  //定一個將沒有十進制 . 點號,只有千分制 , 逗號;兩個,具有十進制的 . 點號和千進制的 , 句號;四個,十進
  //制、千進制全部用 , 都好劃分;註:僅千進制的第一個字符被使用;例如,你使用foo作為千進制的區分,那
  //麼1000就成為1f000;

  $totaltime = number_format(($t_array[0]+$t_array[1]-$P_S_T),6);
  $wind_spend = "Total $totaltime(s) query $qn,";
}
//按格式取當前時間
$ft_time=get_date($timestamp,'m-d H:i');
//包含對應風格目錄下的footer.htm文件
include PrintEot('footer');
//ob_get_contents 返回輸出緩存的內容,如輸出緩存未被激活,將返回緩存內容或Flase;
$output = str_replace(array('<!--<!---->','<!---->'),array('',''),ob_get_contents());
//如果開啟靜態目錄功能
if($db_htmifopen){
  //preg_replace -- 執行正則表達式的搜索和替換,mixed preg_replace ( mixed pattern, mixed
  //replacement, mixed subject [, int limit] )在 subject 中搜索 pattern 模式的匹配項並替換為
  //replacement。如果指定了 limit,則僅替換 limit 個匹配,如果省略 limit 或者其值為 -1,則所有的匹配項
  //都會被替換。replacement 可以包含 \\n 形式或(自 PHP 4.0.4 起)$n 形式的逆向引用,首選使用後者。
  //每個此種引用將被替換為與第 n 個被捕獲的括號內的子模式所匹配的文本。n 可以從 0 到 99,其中 \\0 或
  //$0 指的是被整個模式所匹配的文本。對左圓括號從左到右計數(從 1 開始)以取得子模式的數目。對替換模式
  //在一個逆向引用後面緊接著一個數字時(即:緊接在一個匹配的模式後面的數字),不能使用熟悉的 \\1 符號
  //來表示逆向引用。舉例說 \\11,將會使 preg_replace() 搞不清楚是想要一個 \\1 的逆向引用後面跟著一個
  //數字 1 還是一個 \\11 的逆向引用。本例中的解決方法是使用 \${1}1。這會形成一個隔離的 $1 逆向引用,
  //而使另一個 1 只是單純的文字。

  $output = preg_replace(
      "/\<a(\s*[^\>]+\s*)href\=([\"|\']?)([^\"\'>\s]+\.php\?[^\"\'>\s]+)([\"|\']?)/ies",
      "Htm_cv('\\3','<a\\1href=\"')",
      $output
  );
}
ob_end_clean();
$db_obstart == 1 ? ob_start('ob_gzhandler') : ob_start();
echo $output;
//flush -- 刷新輸出緩衝,刷新 PHP 程序的緩衝,而不論 PHP 執行在何種情況下(CGI ,web服務器等等)。該
//函數將當前為止程序的所有輸出發送到用戶的瀏覽器。flush() 函數不會對服務器或客戶端瀏覽器的緩存模式產
//生影響。因此,必須同時使用 ob_flush() 和flush() 函數來刷新輸出緩衝。個別web服務器程序,特別是
//Win32下的web服務器程序,在發送結果到瀏覽器之前,仍然會緩存腳本的輸出,直到程序結束為止。有些
//Apache的模塊,比如mod_gzip,可能自己進行輸出緩存,這將導致flush()函數產生的結果不會立即被發送
//到客戶端瀏覽器。甚至瀏覽器也會在顯示之前,緩存接收到的內容。例如 Netscape 瀏覽器會在接受到換行
//或 html 標記的開頭之前緩存內容,並且在接受到 </table> 標記之前,不會顯示出整個表格。一些版本的
//Microsoft Internet Explorer 只有當接受到的256個字節以後才開始顯示該頁面,所以必須發送一些額外的
//空格來讓這些瀏覽器顯示頁面內容。

flush;
exit;
}

//返回靜態目錄功能開始時頁面的訪問路徑
function Htm_cv($url,$tag){
//聲明全局變量靜態目錄$db_dir,靜態目錄擴展名設置$db_ext
global $db_dir,$db_ext;
//ereg -- 正則表達式匹配,注: 使用 Perl 兼容正則表達式語法的 preg_match() 函數通常是比 ereg() 更快
//的替代方案。以區分大小寫的方式在 string 中尋找與給定的正則表達式 pattern 所匹配的子串。如果找到與
//pattern 中圓括號內的子模式相匹配的子串並且函數調用給出了第三個參數 regs,則匹配項將被存入 regs
//數組中。$regs[1] 包含第一個左圓括號開始的子串,$regs[2] 包含第二個子串,以此類推。$regs[0] 包含
//整個匹配的字符串。注: 直到 PHP 4.1.0 為止,$regs 將被填充為正好十個單元,即使實際匹配的子串少於十
//個。這並不影響 ereg() 匹配更多子串的能力。如果沒有找到匹配,則 $regs 不會被 ereg() 更改。 如果在
//string 中找到 pattern 模式的匹配則返回 TRUE,如果沒有找到匹配或出錯則返回 FALSE。

if(ereg("^http|ftp|telnet|mms|rtsp|admin.php|rss.php",$url)===false){
  if(strpos($url,'#')!==false){
      $add = substr($url,strpos($url,'#'));
  }
  $url = str_replace(
      array('.php?','=','&',$add),
      array($db_dir,'-','-',''),
      $url
  ).$db_ext.$add;
}
return $tag.$url.'"';
}

//取得用戶信息數組
function User_info(){
//聲明全局變量數據庫訪問類$db,當前時間$timestamp,在線用戶時限$db_onlinetime,用戶id$winduid,用戶密碼$windpwd,是否記錄會員在線時間並在版塊內顯示$db_ifonlinetime,用戶此次在線時間$c_oltime,客戶端ip$onlineip,是否開啟IP驗證功能$db_ipcheck,今日開始時間$tdtime;
global $db,$timestamp,$db_onlinetime,$winduid,$windpwd,$db_ifonlinetime,$c_oltime,$onlineip,$db_ipcheck,$tdtime;
$ct='';
//取得數據表中的相應記錄
//相關字段名解釋如下:
//用戶id-m.uid,
//用戶名-m.username,
//用戶密碼-m.password,
//用戶郵箱-m.email,
//用戶qq號-oicq,
//用戶系統組id-m.groupid,
//用戶會員組id-m.memberid,
//用戶註冊時間-m.regdate,
//用戶時區設置-m.timedf,
//用戶風格設置-m.style,
//用戶時間顯示格式設置-m.datefm,
//主題列表每頁個數-m.t_num,
//文章列表每頁個數-m.p_num,
//是否已激活-m.yz,
//是否有新的短消息-m.newpm,
//是否開啟簽名展示功能-m.showsign,
//用戶交易帳號信息-m.payemail
//用戶發帖數-md.postnum,
//用戶威望數-md.rvrc,
//用戶金錢數-md.money,
//用戶自定義積分數-md.credit,
//用戶交易幣數-md.currency,
//用戶上次訪問時間-md.lastvisit,
//用戶這次訪問時間-md.thisvisit,
//用戶在線時間-md.onlinetime,
//用戶上次回復時間-md.lastpost,
//用戶今日發帖數-md.todaypost,
//用戶在線ip情況-md.onlineip,
//用戶上傳時間-md.uploadtime,
//用戶上傳數-md.uploadnum,
//使用所見即所得編輯器還是windcode編輯器-md.editor,
//簽名使用起始時間-md.starttime

$detail =$db->get_one("SELECT m.uid,m.username,m.password,m.email,oicq,m.groupid,m.memberid,m.regdate,m.timedf,m.style,m.datefm,m.t_num,m.p_num,m.yz,m.newpm,m.showsign,m.payemail,md.postnum,md.rvrc,md.money,md.credit,md.currency,md.lastvisit,md.thisvisit,md.onlinetime,md.lastpost,md.todaypost,md.onlineip,md.uploadtime,md.uploadnum,md.editor,md.starttime FROM pcr_members m LEFT JOIN pcr_memberdata md USING(uid) WHERE m.uid='$winduid'");
//如果用戶登陸ip字段中不存在當前客戶端ip信息
if(strpos($detail['onlineip'],$onlineip)===false){
  //以"."分割客戶端ip
  $iparray=explode(".",$onlineip);
  //如果用戶登陸ip字段中不存在當前客戶端ip的前2節則退出標記設為Y
  if(strpos($detail['onlineip'],$iparray[0].'.'.$iparray[1])===false) $loginout='Y';
}
//如果查詢不到該會員信息即$detail為空
//或者用戶密碼在編碼後和cookie中保存的值不相同
//或者退出標記為Y且論壇開啟了IP驗證功能

if(!$detail || PwdCode($detail['password']) != $windpwd || ($loginout=='Y' && $db_ipcheck==1)){
  //銷毀$detail
  unset($detail);
  //設置當前用戶組為遊客
  $GLOBALS['groupid']='guest';
  //包含require/checkpass.php文件,如果其中有重複包含,略過
  require_once(R_P.'require/checkpass.php');
  //退出並清空cookies
  Loginout();
  //轉頁面顯示語言文件中ip_change對應鍵值的提示信息
  Showmsg('ip_change');
}else{
  //銷毀用戶信息中的密碼變量
  unset($detail['password']);
  //如果當前時間和數據庫中用戶這次訪問時間差大於在線用戶時限
  if($timestamp-$detail['thisvisit']>$db_onlinetime){
//非隱身
      if(!GetCookie('hideid')){
      $ct="lastvisit=thisvisit,thisvisit='$timestamp'";
      //更新數組中上次訪問時間變量為這次訪問時間
      $detail['lastvisit'] = $detail['thisvisit'];
      //更新數組中這次訪問時間變量為當前時間
      $detail['thisvisit'] = $timestamp;
      }
      //如果設置了記錄會員在線時間並在版塊內顯示且ct變量不為空,且用戶此次在線時間大於0
      if($db_ifonlinetime == 1 && $ct && $c_oltime > 0){
      //如果用戶此次在線時間大於在線用戶時限的1.2倍
      if($c_oltime > $db_onlinetime*1.2){
        //更新用戶此次在線時間為在線用戶時限
        $c_oltime = $db_onlinetime;
      }
      $ct .= ",onlinetime=onlinetime+'$c_oltime'";
      $c_oltime = 0;
      }
      //若ct變量不為空,則更新數據庫中的上次訪問時間、這次訪問時間、在線時間
      $ct && $db->update("UPDATE pcr_memberdata SET $ct WHERE uid='$winduid' AND $timestamp-thisvisit>$db_onlinetime");
  }
}

//返回用戶信息數組
return $detail;
}

//返回pwd的編碼後值
function PwdCode($pwd){
//連接頭信息、$pwd參數(密碼)以及論壇安全驗證參數,md5加密後返回該值
return md5($_SERVER["HTTP_USER_AGENT"].$pwd.$GLOBALS['db_hash']);
}

//安全檢測,若不符合銷毀相應cookie,符合重新設置相應cookie
function SafeCheck($CK,$PwdCode,$var='AdminUser',$expire=1800){
//聲明全局變量$timestamp
global $timestamp;
//上次訪問時間和當前時間的時間差賦於變量$t
$t = $timestamp - $CK[0];
//如果其超過定義的過期時間或者$CK[2]中存儲的密碼(編碼後的密碼連接上次訪問時間再md5加密後得到的值)並不匹配
if($t > $expire || $CK[2] != md5($PwdCode.$CK[0])){
  //設置$var狀態為無效,即銷毀此cookie
  Cookie($var,'',0);
  return false;
}else{
  //設置上次訪問時間為當前時間
  $CK[0] = $timestamp;
  //設置存儲的密碼信息為編碼後的密碼連接當前時間再md5加密後得到的值
  $CK[2] = md5($PwdCode.$timestamp);
  //implode 聯結數組元素為一個字符串;string implode ( string glue, array pieces )第一個參數為分割符
  //第二個參數為要聯結的數組單元;
  //用"\t"連接數組$CK

  $Value = implode("\t",$CK);
  //設置變量$$var為$Value編碼後的值
  $$var = StrCode($Value);
  Cookie($var,StrCode($Value));
  return true;
}
}


//對字符串進行編碼或解碼處理,並返回編碼或解碼後得到的值
function StrCode($string,$action='ENCODE'){
//HTTP_USER_AGENT-當前請求的 User-Agent: 頭信息的內容。該字符串表明了訪問該頁面的用戶代理的信息。一個典型的例子是:Mozilla/4.5 [en] (X11; U; Linux 2.2.9 i586)。也可以使用 get_browser() 得到此信息。
//連接頭信息和論壇安全驗證參數,md5加密後,從第8位起取18個字符,作為變量key的值

$key = substr(md5($_SERVER["HTTP_USER_AGENT"].$GLOBALS['db_hash']),8,18);
//base64_decode -- 對使用 MIME base64 編碼的數據進行解碼
//如果選擇的操作是編碼操作,則string變量不變仍舊為自己本身參數的值,否則為base64解碼該參數後得到的值

$string = $action == 'ENCODE' ? $string : base64_decode($string);
//記錄key的長度,為18
$len = strlen($key);
$code = '';
//對string中的每個字符
for($i=0; $i<strlen($string); $i++){
  //k變量存儲$i % $len餘數
  $k = $i % $len;
  //位運算符允許對整型數中指定的位進行置位。如果左右參數都是字符串,則位運算符將操作字符的 ASCII 值。
  //$a ^ $b Xor(按位異或) 將把 $a 和 $b 中不同的位設為 1。
  //把$string[$i]和$key[$k]以ascii值方式進行異或運算後,值累加到code變量中

  $code .= $string[$i] ^ $key[$k];
}
//base64_encode -- 使用 MIME base64 對數據進行編碼
//設計此種編碼是為了使二進制數據可以通過非純 8-bit 的傳輸層傳輸,例如電子郵件的主體。
//Base64-encoded 數據要比原始數據多佔用 33% 左右的空間。
//如果選擇的操作是加碼操作,則code變量不變,否則為base64編碼code後得到的值

$code = $action == 'DECODE' ? $code : base64_encode($code);
return $code;
}

//返回$content字符串$length長度的值,超過$length顯示".."
//返回$content字符串$length長度的值,超過$length顯示".."
function substrs($content,$length){
//取字符集設置
global $db_charset;
if($length && strlen($content)>$length){
  if($db_charset!='utf-8'){
      $retstr='';
      for($i = 0; $i < $length - 2; $i++) {
      //ord 返回字符串的第一個字符的二進制值;string chr ( int ascii ) 返回相對應於 ascii 所指定的單個字符。
      $retstr .= ord($content[$i]) > 127 ? $content[$i].$content[++$i] : $content[$i];
      }
      return $retstr.' ..';
  }else{
      //trim 去除字符串裡的空格或其他字符,string trim ( string str [, string charlist] ),
      //" " (ASCII 32 (0x20)), 空格."\t" (ASCII 9 (0x09)),tab字符."\n" (ASCII 10 (0x0A)),換行符;
      //"\r" (ASCII 13 (0x0D)), 回車符."\0" (ASCII 0 (0x00)),空字符."\x0B" (ASCII 11 (0x0B)), 垂直tab.

      return utf8_trim(substr($content,0,$length)).' ..';
  }
}

return $content;
}

//將非utf8字符集字符串取整字符串避免亂碼
function utf8_trim($str) {
$len = strlen($str);
for($i=strlen($str)-1;$i>=0;$i-=1){
  $hex .= ' '.ord($str[$i]);
  $ch = ord($str[$i]);
  if(($ch & 128)==0) return substr($str,0,$i);
  if(($ch & 192)==192)return substr($str,0,$i);
}
return($str.$hex);
}

//按格式返回時間
function get_date($timestamp,$timeformat=''){
//聲明全局變量論壇默認時間顯示格式$db_datefm,默認時區設置$db_timedf,用戶時間顯示格式$_datefm,用戶時區設置$_timedf
global $db_datefm,$db_timedf,$_datefm,$_timedf;
//如果傳入參數設定了時間格式,則時間格式取參數中設定的值,否則看是否用戶設置了時間顯示格式,有則取用戶的時間顯示格式,否則取論壇默認時間顯示格式
$date_show=$timeformat ? $timeformat : ($_datefm ? $_datefm : $db_datefm);

//取得時區設置(用戶沒設置取論壇默認的)
if($_timedf){
  $offset = $_timedf==飇' ? 0 : $_timedf;
}else{
  $offset = $db_timedf==飇' ? 0 : $db_timedf;
}
//按格式返回真實的用戶顯示時間
return gmdate($date_show,$timestamp+$offset*3600);
}

//遞歸執行,使得每個數組中的字符串都是為了數據庫查詢語句等的需要在某些特殊字符前加上了反斜線的字符串
function Add_S(&$array){
foreach($array as $key=>$value){
  if(!is_array($value)){
      //addslashes -- 使用反斜線引用字符串,返回字符串,該字符串為了數據庫查詢語句等的需要在某些字符前加
      //上了反斜線。這些字符是單引號(')、雙引號(")、反斜線(\)與 NUL(NULL 字符)。 一個使用
      //addslashes() 的例子是當你要往數據庫中輸入數據時。例如,將名字 O'reilly 插入到數據庫中,這就需要對
      //其進行轉義。大多數據庫使用 \ 作為轉義符:O\'reilly。這樣可以將數據放入數據庫中,而不會插入額外的 \。
      //當 PHP 指令 magic_quotes_sybase 被設置成 on 時,意味著插入 ' 時將使用 ' 進行轉義。默認情況下,
      //PHP 指令 magic_quotes_gpc 為 on,它主要是對所有的 GET、POST 和 COOKIE 數據自動運行
      //addslashes()。不要對已經被 magic_quotes_gpc 轉義過的字符串使用 addslashes(),因為這樣會導致
      //雙層轉義。遇到這種情況時可以使用函數 get_magic_quotes_gpc() 進行檢測。

      $array[$key]=addslashes($value);
  }else{
      Add_S($array[$key]);
  }
}
}


//對字符中的特殊字符進行轉義,並返回轉換後的字符串
function Char_cv($msg){
$msg = str_replace('&','&',$msg);
$msg = str_replace(' ',' ',$msg);
$msg = str_replace('"','"',$msg);
$msg = str_replace("'",''',$msg);
$msg = str_replace("<","<",$msg);
$msg = str_replace(">",">",$msg);
$msg = str_replace("\t","   ",$msg);
$msg = str_replace("\r","",$msg);
$msg = str_replace(" ","   ",$msg);
return $msg;
}
//認證碼檢查函數
function GdConfirm($code){
//銷毀cookie中的cknum
Cookie('cknum','',0);
if(!$code || !SafeCheck(explode("\t",StrCode(GetCookie('cknum'),'DECODE')),$code,'cknum',1800)){
  //轉頁面顯示語言文件中check_error對應鍵值的提示信息
  Showmsg('check_error');
}
}


//廣告初始化函數
function AdvertInit($SCR,$fid){
//聲明全局變量當前時間$timestamp
global $timestamp;
//包含data/bbscache/advert_data.php
include(D_P.'data/bbscache/advert_data.php');
$newadvert = array();
foreach($advertdb as $key=>$val){
  foreach($val as $k=>$v){
      //strtotime -- 將任何英文文本的日期時間描述解析為 Unix 時間戳,本函數預期接受一個包含美國英語日期格
      //式的字符串並嘗試將其解析為 Unix 時間戳(自 January 1 1970 00:00:00 GMT 起的秒數),其值相對於
      //now 參數給出的時間,如果沒有提供此參數則用系統當前時間。本函數將使用 TZ 環境變量(如果有的話)來
      //計算時間戳。自 PHP 5.1.0 起有更容易的方法來定義時區用於所有的日期/時間函數。此過程在
      //date_default_timezone_get() 函數頁面中有說明。注: 如果給定的年份是兩位數字的格式,則其值 0-69
      //表示 2000-2069,70-100 表示 1970-2000。參數 time 被解析的字符串,格式根據 GNU Date
      //Input Formats 語法 now 用來計算返回值的時間戳 返回值 成功則返回時間戳,否則返回 FALSE。
      //在
PHP 5.1.0 之前本函數在失敗時返回 -1。 php5.1.0 失敗時返回 FALSE,不再是 -1。

      //如果是頭部橫幅廣告或者底部橫幅廣告且結束時間為空
      //或者結束時間小於當前時間

      if(($key=='header' || $key=='footer') && !$v['endtime'] || strtotime($v['endtime']) < $timestamp){
      //跳出執行下個循環
      continue;
      }
      //如果是首頁且投放範圍為首頁
      if($SCR == 'index' && strpos(",$v[fid],",",-1,")!==false){
      $newadvert[$key][]=$v;
      //如果是板塊且投放範圍為主題列表頁面
      }elseif($SCR == 'thread' && strpos(",$v[fid],",",-2,")!==false){
      $newadvert[$key][]=$v;
      //如果是帖子且投放範圍為帖子頁面
      }elseif($SCR == 'read' && strpos(",$v[fid],",",-3,")!==false){
      $newadvert[$key][]=$v;
      //如果投放範圍為所有頁面
      }elseif(strpos(",$v[fid],",",-4,")!==false){
      $newadvert[$key][]=$v;
      //如果板塊fid不為空投放範圍包含該板塊
      }elseif($fid && strpos(",$v[fid],",",$fid,")!==false){
      $newadvert[$key][]=$v;
      }
  }
}

//返回廣告數組
return $newadvert;
}

//取路徑,去除$path中的文件名
function getdirname($path){
if(strpos($path,'\\')!==false){
  //strrpos 查找匹配字符串出現的最後位置;沒找到,返回False
  return substr($path,0,strrpos($path,'\\'));
}elseif(strpos($path,'/')!==false){
  return substr($path,0,strrpos($path,'/'));
}else{
  return '/';
}
}

?>

data\sql_config.php



<?php
//此文件內容為論壇數據庫配置信息,以及插件創始人信息

/**
* 以下變量需根據您的服務器說明檔修改
*/

$dbhost = 'localhost'; // 數據庫服務器
$dbuser = 'root'; //數據庫用戶名
$dbpw = 'phpwind.net'; // 數據庫密碼
$dbname = 'phpwind'; // 數據庫名
$database = 'mysql'; //數據庫類型
$PW = 'pcr_'; //表區分符
$pconnect = 0; //是否持久連接

/*
MYSQL編碼設置
如果您的論壇出現亂碼現象,需要設置此項來修復
請不要隨意更改此項,否則將可能導致論壇出現亂碼現象
*/

$charset='big5';

/**
* 論壇創始人,擁有論壇所有權限
*/
//創始人帳號

$manager='admin';
//創始人md5加密密碼
$manager_pwd=?f297a57a5a743894a0e4a801fc3';

/**
* 鏡像站點設置
*/

$db_hostweb=1; //是否為主站點

/*
* 附件url地址 例如: http://www.phpwind....achment 最後為附件目錄
*/

$attach_url='';

/**
* 插件配置
*/

$db_hackdb=array(
//插件名稱 唯一標識符 前台文件名 後台文件名 是否啟用(0不顯示1下拉菜單顯示2直接顯示) 相關文件(前台程序文件,後台程序文件,前台模板文件,後台模板文件)
'bank'=>array('銀行','bank','bank.php','bankset.php',Ƈ','hack/bank.php,hack/bankset.php,template/wind/bank.htm,template/admin/bankset.htm'),
'colony'=>array('朋友圈','colony','colony.php','colonyset.php',Ƈ','hack/colony.php,hack/colonyset.php,template/admin/colonyset.htm,template/wind/colony.htm'),
'advert'=>array('廣告管理','advert','','advert.php',Ƈ','hack/advert.php'),
'new'=>array('首頁調用管理','new','','new.php',Ɔ','hack/new.php'),
'medal'=>array('勳章中心','medal','medal.php','medalset.php',Ɔ','hack/medal.php,hack/medalset.php,template/wind/medal.htm,template/admin/medalset.htm'),
'toolcenter'=>array('道具中心','toolcenter','toolcenter.php','toolsetting.php',Ɔ','hack/toolcenter.php,hack/toolsetting.php,template/wind/toolcenter.htm,template/admin/toolsetting.htm'),
'blog'=>array('博客','blog','blog.php','blogset.php',Ɔ','hack/blog.php,hack/blogset.php,template/wind/blog.htm,template/admin/blogset.htm'),
'live'=>array('網絡電視','live','live.php','',ƈ',''),
);
?>


[ 此文章被月光在2009-04-09 13:22重新編輯 ]



月光論壇
http://bbs.dj...com/


===================================
贊助本站 -- 刊登廣告 -- 物超所值虛擬主機租用
獻花 x1 回到頂端 [樓 主] From:臺灣中華電信HINET | Posted:2007-09-25 18:14 |
hsu71792
個人文章 個人相簿 個人日記 個人地圖
路人甲
級別: 路人甲 該用戶目前不上站
推文 x0 鮮花 x7
分享: 轉寄此文章 Facebook Plurk Twitter 複製連結到剪貼簿 轉換為繁體 轉換為簡體 載入圖片

表情 表情 表情 又增加寶貴的知識~~感謝月光大大不吝指導~~~感恩啊!!!!


獻花 x0 回到頂端 [1 樓] From:臺灣 | Posted:2008-10-03 21:45 |
liangjkds1
數位造型
個人文章 個人相簿 個人日記 個人地圖
路人甲
級別: 帳號封鎖 該用戶目前不上站
推文 x0 鮮花 x21
分享: 轉寄此文章 Facebook Plurk Twitter 複製連結到剪貼簿 轉換為繁體 轉換為簡體 載入圖片

回 覆 鎖 定 :

  此回覆已被鎖定,只有『管理員及回覆者』看的到 !!!




獻花 x0 回到頂端 [2 樓] From:歐洲 | Posted:2015-10-21 05:23 |

首頁  發表文章 發表投票 回覆文章
Powered by PHPWind v1.3.6
Copyright © 2003-04 PHPWind
Processed in 0.122484 second(s),query:16 Gzip disabled
本站由 瀛睿律師事務所 擔任常年法律顧問 | 免責聲明 | 本網站已依台灣網站內容分級規定處理 | 連絡我們 | 訪客留言