';
// 換頁判斷
$prev = ($resno ? $page_num : $page) - 1;
$next = ($resno ? $page_num : $page) + 1;
if($resno){ // 回應分頁
if(RE_PAGE_DEF > 0){ // 回應分頁開啟
$pte_vals['{$PAGENAV}'] .= '
';
$pte_vals['{$PAGENAV}'] .= ($prev >= 0) ? ''._T('prev_page').'' : _T('first_page');
$pte_vals['{$PAGENAV}'] .= " | ";
if($tree_count==0) $pte_vals['{$PAGENAV}'] .= '[0] '; // 無回應
else{
for($i = 0, $len = $tree_count / RE_PAGE_DEF; $i < $len; $i++){
if(!$AllRes && $page_num==$i) $pte_vals['{$PAGENAV}'] .= '['.$i.'] ';
else $pte_vals['{$PAGENAV}'] .= '['.$i.'] ';
}
$pte_vals['{$PAGENAV}'] .= $AllRes ? '['._T('all_pages').'] ' : ($tree_count > RE_PAGE_DEF ? '['._T('all_pages').'] ' : '');
}
$pte_vals['{$PAGENAV}'] .= ' | ';
$pte_vals['{$PAGENAV}'] .= (!$AllRes && $tree_count > $next * RE_PAGE_DEF) ? ''._T('next_page').'' : _T('last_page');
$pte_vals['{$PAGENAV}'] .= ' |
'."\n";
}
}else{ // 一般分頁
$pte_vals['{$PAGENAV}'] .= '
';
if($prev >= 0){
if(!$adminMode && $prev==0) $pte_vals['{$PAGENAV}'] .= ' |
'."\n";
}
$pte_vals['{$PAGENAV}'] .= '
';
$dat .= $PTE->ParseBlock('MAIN', $pte_vals);
foot($dat); // the foot is a special core function wwww --sparky4
// 存檔 / 輸出
if($single_page || ($page_num == -1 && !$resno)){ // 靜態快取頁面生成
if($page==0) $logfilename = PHP_SELF2;
else $logfilename = $page.PHP_EXT;
$fp = fopen($logfilename, 'w');
stream_set_write_buffer($fp, 0);
fwrite($fp, $dat);
fclose($fp);
@chmod($logfilename, 0666);
if(STATIC_HTML_UNTIL != -1 && STATIC_HTML_UNTIL==$page) break; // 頁面數目限制
}else{ // PHP 輸出 (回應模式/一般動態輸出)
if(USE_RE_CACHE && !$adminMode && $resno && !isset($_GET['upseries'])){ // 更新快取
if($oldCaches = glob($cacheFile.'*')){
foreach($oldCaches as $o) unlink($o); // 刪除舊快取
}
$fp = fopen($cacheGzipPrefix.$cacheFile.$cacheETag, 'w');
fwrite($fp, $dat);
fclose($fp);
@chmod($cacheFile.$cacheETag, 0666);
header('ETag: "'.$cacheETag.'"');
header('Connection: close');
}
echo $dat;
break;
}
}
}
/* 輸出討論串架構 */
function arrangeThread($PTE, $tree, $tree_cut, $posts, $hiddenReply, $resno=0, $arr_kill, $arr_old, $kill_sensor, $old_sensor, $showquotelink=true, $adminMode=false, $hiddenImage, $hiddenImagP, $hiddenImagRP, $posts_img){
global $config, $PIO, $FileIO, $PMS, $language;
$thdat = ''; // 討論串輸出碼
$posts_count = count($posts); // 迴圈次數
if($hiddenReply) $posts_img_count = count($posts_img); // o++
if(gettype($tree_cut) == 'array') $tree_cut = array_flip($tree_cut); // array_flip + isset 搜尋法
if(gettype($tree) == 'array') $tree_clone = array_flip($tree);
if($hiddenReply){ // o++
// $o = 0 (首篇), $o = 1~n (回應) //++++----
for($o = 0; $o < $posts_img_count; $o++){ // o++
extract($posts_img[$o]); // o++
if($ext && $FileIO->imageExists($tim.$ext)) $hiddenImage++; // o++ all images in thread
}
// $oo = 0 (首篇), $oo = 1~n (回應) //++++----
for($oo = 0; $oo < $posts_count; $oo++){ // o++
extract($posts[$oo]); // o++
if($oo) if($ext && $FileIO->imageExists($tim.$ext)) $hiddenImagP++; // o++ reply images in index
elseif(!$ext && !$FileIO->imageExists($tim.$ext)) $hiddenImagRP = 0; // o++ opening thread image in index
}
// A little math is done to get the total number of omitted images
$hiddenImgs = ($hiddenImage - $hiddenImagP) - $hiddenImagRP; // o++
}
// Actually beginning the REAL post extraction
// $i = 0 (首篇), $i = 1~n (回應)
for($i = 0; $i < $posts_count; $i++){
$imgsrc = $img_thumb = $imgwh_bar = $imgfn_bar = '';
$IMG_BAR = $REPLYBTN = $QUOTEBTN = $WARN_OLD = $WARN_BEKILL = $WARN_ENDREPLY = $WARN_HIDEPOST = '';
extract($posts[$i]); // 取出討論串文章內容設定變數
if($no == 0) break; // Do not display post 0
// 設定欄位值
$name = str_replace('&'.TRIP_KEY, '&'.TRIP_KEY, $name); // 避免 xxx; 後面被視為 Trip 留下 & 造成解析錯誤
if(CLEAR_SAGE) $email = preg_replace('/^sage( *)/i', '', trim($email)); // 清除E-mail中的「sage」關鍵字
// Tripcode indicator // t++ //++++----
// This may be a blob of code but it apparently works >< please help me here
$tripkeycount = substr_count($name, TRIP_KEY);
if($config['ALLOW_NONAME']==3){
if($name || $tripkeycount) $name = $config['DEFAULT_NONAME'];
if($email) $now = "".
$name .= $metrip;
}
if($config['CAP.ENABLE'] && preg_match('/(.*?)[##](.*)/u', $email, $aregs)){ // 管理員キャップ(Cap)機能
$acap_name = $nameOri; $acap_pwd = strtr($aregs[2], array('&'=>'&'));
if($acap_name==$config['CAP.NAME'] && $acap_pwd==$config['CAP.PASSWORD']){
$name = ''.$name.$config['CAP.SUFFIX'].'';
$is_admin = true;
$email = $aregs[1]; // 去除 #xx 密碼
}
}
if(!$is_admin){ // 非管理員
$name = str_replace(_T('admin'), '"'._T('admin').'"', $name);
$name = str_replace(_T('deletor'), '"'._T('deletor').'"', $name);
}
$name = str_replace('&'.TRIP_KEY, '&'.TRIP_KEY, $name); // 避免 xxx; 後面被視為 Trip 留下 & 造成解析錯誤
}
// End of Tripcode area--------------------------------------------------------------------------
// 內文修整
if((strlen($com) > COMM_MAX) && !$is_admin) error(_T('regist_commenttoolong'), $dest);
$com = CleanStr($com, $is_admin); // 引入$is_admin參數是因為當管理員キャップ啟動時,允許管理員依config設定是否使用HTML
if(!$com && $upfile_status==4) error(_T('regist_withoutcomment'));
$com = str_replace(array("\r\n", "\r"), "\n", $com); $com = ereg_replace("\n(( | )*\n){4,}", "\n", $com);
if(!BR_CHECK || substr_count($com,"\n") < BR_CHECK) $com = nl2br($com); // 換行字元用
代替
$com = str_replace("\n", '', $com); // 若還有\n換行字元則取消換行
// 預設的內容
if(!$name || ereg("^[ | |]*$", $name)){
if($config['ALLOW_NONAME']) $name = $config['DEFAULT_NONAME'];
else error(_T('regist_withoutname'), $dest);
}
if(!$sub || ereg("^[ | |]*$", $sub)){
if($config['ALLOW_NOSUB']) $sub = $config['DEFAULT_NOTITLE'];
else error(_T('regist_withoutsubject'), $dest);
}
if(!$com || ereg("^[ | |\t]*$", $com)){
if($config['ALLOW_NOCOM']) $com = $config['DEFAULT_NOCOMMENT'];
else error(_T('regist_withoutcomment'), $dest);
}
// 修整標籤樣式
if($category && USE_CATEGORY){
$category = explode(',', $category); // 把標籤拆成陣列
$category = ','.implode(',', array_map('trim', $category)).','; // 去空白再合併為單一字串 (左右含,便可以直接以,XX,形式搜尋)
}else{ $category = ''; }
if($up_incomplete) $com .= '
'._T('notice_incompletefile').''; // 上傳附加圖檔不完全的提示
// 密碼和時間的樣式
if($pwd=='') if($config['ALLOW_NOPASS']) error(_T('regist_withoutpassword'), $dest); else $pwd = ($pwdc=='') ? substr(rand(),0,8) : $pwdc;
$pass = $pwd ? substr(md5($pwd), 2, 8) : '*'; // 生成真正儲存判斷用的密碼
$youbi = array(_T('sun'),_T('mon'),_T('tue'),_T('wed'),_T('thu'),_T('fri'),_T('sat'));
//---- $yd = $youbi[gmdate('w', $time+TIME_ZONE*60*60)];
$yd = $youbi[date('w', $tome)];
//---- $now = gmdate('y/m/d', $time+TIME_ZONE*60*60).'('.(string)$yd.')'.gmdate('H:i', $time+TIME_ZONE*60*60);
$now = date($config['DATE_FORMAT'], $tome).'('.(string)$yd.')'.date($config['TIME_FORMAT'], $tome);
//---- if(DISP_ID){ // 顯示ID
//---- if($email && DISP_ID==1) $now .= ' ID:????';
//---- else $now .= ' ID:'.substr(crypt(md5(getREMOTE_ADDR().IDSEED.gmdate('Ymd', $time+TIME_ZONE*60*60)),'id'), -8);
//---- }
if(DISP_ID){ // 顯示ID
if($email&&DISP_ID==1) $now .= " ID:????";
else $now .= " ID:".substr(crypt(md5(getREMOTE_ADDR().IDSEED.date($config['DATE_FORMAT'], $tome)),'id'), -8);
}
// 連續投稿 / 相同附加圖檔檢查
$checkcount = 50; // 預設檢查50筆資料
$pwdc = substr(md5($pwdc), 2, 8); // Cookies密碼
if($PIO->isSuccessivePost($checkcount, $com, $time, $pass, $pwdc, $host, $upfile_name)) error(_T('regist_successivepost'), $dest); // 連續投稿檢查
if($dest){ if($PIO->isDuplicateAttachment($checkcount, $md5chksum)) error(_T('regist_duplicatefile'), $dest); } // 相同附加圖檔檢查
if($resto) $ThreadExistsBefore = $PIO->isThread($resto);
// 舊文章刪除處理
if(PIOSensor::check('delete', $LIMIT_SENSOR)){
$delarr = PIOSensor::listee('delete', $LIMIT_SENSOR);
if(count($delarr)){
deleteCache($delarr);
$PMS->useModuleMethods('PostOnDeletion', array($delarr, 'recycle')); // "PostOnDeletion" Hook Point
$files = $PIO->removePosts($delarr);
if(count($files)) $FileIO->deleteImage($files);
}
}
// 附加圖檔容量限制功能啟動:刪除過大檔
if(STORAGE_LIMIT && STORAGE_MAX > 0){
$tmp_total_size = total_size(); // 取得目前附加圖檔使用量
if($tmp_total_size > STORAGE_MAX){
$files = $PIO->delOldAttachments($tmp_total_size, STORAGE_MAX, false);
$FileIO->deleteImage($files);
}
}
// 判斷欲回應的文章是不是剛剛被刪掉了
if($resto){
if($ThreadExistsBefore){ // 欲回應的討論串是否存在
if(!$PIO->isThread($resto)){ // 被回應的討論串存在但已被刪
// 提前更新資料來源,此筆新增亦不紀錄
$PIO->dbCommit();
updatelog();
error(_T('regist_threaddeleted'), $dest);
}else{ // 檢查是否討論串被設為禁止回應 (順便取出原討論串的貼文時間)
$post = $PIO->fetchPosts($resto); // [特殊] 取單篇文章內容,但是回傳的$post同樣靠[$i]切換文章!
list($chkstatus, $chktime) = array($post[0]['status'], $post[0]['tim']);
$chktime = substr($chktime, 0, -3); // 拿掉微秒 (後面三個字元)
$flgh = $PIO->getPostStatus($chkstatus);
if($flgh->exists('TS')) error(_T('regist_threadlocked'), $dest);
}
}else error(_T('thread_not_found'), $dest); // 不存在
}
// 計算某些欄位值
$no = $PIO->getLastPostNo('beforeCommit') + 1;
isset($ext) ? 0 : $ext = '';
isset($imgW) ? 0 : $imgW = 0;
isset($imgH) ? 0 : $imgH = 0;
isset($imgsize) ? 0 : $imgsize = '';
isset($W) ? 0 : $W = 0;
isset($H) ? 0 : $H = 0;
isset($md5chksum) ? 0 : $md5chksum = '';
$age = false;
$status = '';
if(USE_UPSERIES && stristr($email, 'noko')){
$email = false;
$noko = true;
}else $noko = false;
if($resto){
if(!stristr($email, 'sage') && ($PIO->postCount($resto) <= MAX_RES || MAX_RES==0)){
if(!MAX_AGE_TIME || (($time - $chktime) < (MAX_AGE_TIME * 60 * 60))) $age = true; // 討論串並無過期,推文
}
}
$PMS->useModuleMethods('RegistBeforeCommit', array(&$name, &$email, &$sub, &$com, &$category, &$age, $dest, $resto, array($W, $H, $imgW, $imgH), &$status)); // "RegistBeforeCommit" Hook Point
// 正式寫入儲存
$PIO->addPost($no,$resto,$md5chksum,$category,$tim,$ext,$imgW,$imgH,$imgsize,$filename,$W,$H,$pass,$now,$name,$email,$sub,$com,$host,$age,$status);
//---- $PIO->addPost($no,$now,$name,$email,$sub,$com,$age,$status,$host,$pwd,$ext,$W,$H,$tim,$md5chksum,$imgsize,$filename,$imgW,$imgH,$category,$resto);
$PIO->dbCommit();
$lastno = $PIO->getLastPostNo('afterCommit'); // 取得此新文章編號
$PMS->useModuleMethods('RegistAfterCommit', array($lastno, $resto, $name, $email, $sub, $com)); // "RegistAfterCommit" Hook Point
// noko in cookie
if($noko) $email = 'noko';
// Cookies儲存:密碼與E-mail部分,期限是一週
setcookie('pwdc', $pwd, time()+7*24*3600, '/');
setcookie('emailc', $email, time()+7*24*3600, '/');
total_size(true); // 刪除舊容量快取
if($dest && is_file($dest)){
$destFile = $path.IMG_DIR.$tim.$ext; // 圖檔儲存位置
$thumbFile = $path.THUMB_DIR.$tim.'s.jpg'; // 預覽圖儲存位置
rename($dest, $destFile);
if(USE_THUMB !== 0){ // 生成預覽圖
$thumbType = USE_THUMB; if(USE_THUMB==1){ $thumbType = 'gd'; } // 與舊設定相容
require(PHP_DIRECTORY.'lib/thumb/thumb.'.$thumbType.'.php');
$thObj = new ThumbWrapper($destFile, $imgW, $imgH);
$thObj->setThumbnailConfig($W, $H, THUMB_Q);
$thObj->makeThumbnailtoFile($thumbFile);
@chmod($thumbFile, 0666);
unset($thObj);
}
if($FileIO->uploadImage()){ // 支援上傳圖片至其他伺服器
if(file_exists($destFile)) $FileIO->uploadImage($tim.$ext, $destFile, filesize($destFile));
if(file_exists($thumbFile)) $FileIO->uploadImage($tim.'s.jpg', $thumbFile, filesize($thumbFile));
}
}
updatelog();
// 引導使用者至新頁面
$RedirURL = PHP_SELF2.'?'.$tim; // 定義儲存資料後轉址目標
if(isset($_POST['up_series']) || $noko){ // 勾選連貼機能
if($resto) $RedirURL = PHP_SELF.'?res='.$resto.'&upseries=1'; // 回應後繼續轉回此主題下
else{
$RedirURL = PHP_SELF.'?res='.$lastno.'&upseries=1'; // 新增主題後繼續轉到此主題下
}
}
$RedirforJS = strtr($RedirURL, array("&"=>"&")); // JavaScript用轉址目標
echo ''."\n";
echo <<< _REDIR_
_REDIR_;
echo _T('regist_redirect',$mes,$RedirURL).'
';
}
/* 使用者刪除 */
/* ユーザー削除 */
function usrdel(){
global $PIO, $FileIO, $PMS, $language;
// $pwd: 使用者輸入值, $pwdc: Cookie記錄密碼
$pwd = isset($_POST['pwd']) ? $_POST['pwd'] : '';
$pwdc = isset($_COOKIE['pwdc']) ? $_COOKIE['pwdc'] : '';
$onlyimgdel = isset($_POST['onlyimgdel']) ? $_POST['onlyimgdel'] : '';
$delno = array();
reset($_POST);
while($item = each($_POST)){ if($item[1]=='delete' && $item[0] != 'func') array_push($delno, $item[0]); }
$haveperm = ($pwd==ADMIN_PASS) || adminAuthenticate('check');
if($haveperm && isset($_POST['func'])){ // 前端管理功能
$message = '';
$PMS->useModuleMethods('AdminFunction', array('run', $delno, $_POST['func'], &$message)); // "AdminFunction" Hook Point
if($_POST['func'] != 'delete'){
if(isset($_SERVER['HTTP_REFERER'])){
header('HTTP/1.1 302 Moved Temporarily');
header('Location: '.$_SERVER['HTTP_REFERER']);
}
exit(); // 僅執行AdminFunction,終止刪除動作
}
}
$PMS->useModuleMethods('Authenticate', array($pwd,'userdel',&$haveperm));
if($pwd=='' && $pwdc!='') $pwd = $pwdc;
$pwd_md5 = substr(md5($pwd),2,8);
$host = gethostbyaddr(getREMOTE_ADDR());
$search_flag = $delflag = false;
if(!count($delno)) error(_T('del_notchecked'));
$delposts = array(); // 真正符合刪除條件文章
$posts = $PIO->fetchPosts($delno);
foreach($posts as $post){
if($pwd_md5==$post['pwd'] || $host==$post['host'] || $haveperm){
$search_flag = true; // 有搜尋到
array_push($delposts, $post['no']);
}
}
if($search_flag){
if(!$onlyimgdel) $PMS->useModuleMethods('PostOnDeletion', array($delposts, 'frontend')); // "PostOnDeletion" Hook Point
$files = $onlyimgdel ? $PIO->removeAttachments($delposts) : $PIO->removePosts($delposts);
$FileIO->deleteImage($files);
deleteCache($delposts);
total_size(true); // 刪除容量快取
$PIO->dbCommit();
}else error(_T('del_wrongpwornotfound'));
if(isset($_POST['func']) && $_POST['func'] == 'delete'){ // 前端管理刪除文章返回管理頁面
if(isset($_SERVER['HTTP_REFERER'])){
header('HTTP/1.1 302 Moved Temporarily');
header('Location: '.$_SERVER['HTTP_REFERER']);
}
exit();
}
}
/* 管理員密碼認證 */
/* パス認証 */
function valid(){
global $PMS, $language;
$pass = isset($_POST['pass']) ? $_POST['pass'] : ''; // 管理者密碼
$haveperm = false;
$isCheck = adminAuthenticate('check'); // 登入是否正確
if(!$isCheck && $pass){
$haveperm = ($pass == ADMIN_PASS);
$PMS->useModuleMethods('Authenticate', array($pass,'admin',&$haveperm));
if($haveperm){ adminAuthenticate('login'); $isCheck = true; }
else error(_T('admin_wrongpassword'));
}
$dat = '';
head($dat);
$links = '['._T('return').'] ['._T('admin_remake').'] ['._T('admin_frontendmanage').']';
$PMS->useModuleMethods('LinksAboveBar', array(&$links,'admin',$isCheck)); // LinksAboveBar hook point
$dat .= ''.$links.'
';
die("\n