pixmicat - Blame information for rev 854

Subversion Repositories:
Rev:
Rev Author Line No. Line
393 scribe 1 <?php
432 scribe 2 /**
3  * Pixmicat! Common Library
4  *
5  * 存放常用函式供主程式引入
833 scribe 6  *
432 scribe 7  * @package PMCLibrary
8  * @version $Id: lib_common.php 854 2013-01-13 06:14:09Z scribe $
9  * @date $Date: 2013-01-13 14:14:09 +0800 (Sun, 13 Jan 2013) $
10  */
393 scribe 11  
12 /* 輸出表頭 */
447 roytam1 13 function head(&$dat,$resno=0){
833 scribe 14         $PTE = PMCLibrary::getPTEInstance();
15         $PMS = PMCLibrary::getPMSInstance();
16  
447 roytam1 17         $pte_vals = array('{$TITLE}'=>TITLE,'{$RESTO}'=>$resno?$resno:'');
427 roytam1 18         $dat .= $PTE->ParseBlock('HEADER',$pte_vals);
447 roytam1 19         $PMS->useModuleMethods('Head', array(&$dat,$resno)); // "Head" Hook Point
20         $pte_vals+=array('{$ALLOW_UPLOAD_EXT}' => ALLOW_UPLOAD_EXT,
21                 '{$JS_REGIST_WITHOUTCOMMENT}' => str_replace('\'', '\\\'', _T('regist_withoutcomment')),
22                 '{$JS_REGIST_UPLOAD_NOTSUPPORT}' => str_replace('\'', '\\\'', _T('regist_upload_notsupport')),
23                 '{$JS_CONVERT_SAKURA}' => str_replace('\'', '\\\'', _T('js_convert_sakura')));
24         $dat .= $PTE->ParseBlock('JSHEADER',$pte_vals);
409 roytam1 25         $dat .= '</head>';
26         $pte_vals += array('{$TOP_LINKS}' => TOP_LINKS,
27                 '{$HOME}' => '[<a href="'.HOME.'" rel="_top">'._T('head_home').'</a>]',
28                 '{$STATUS}' => '[<a href="'.PHP_SELF.'?mode=status">'._T('head_info').'</a>]',
29                 '{$ADMIN}' => '[<a href="'.PHP_SELF.'?mode=admin">'._T('head_admin').'</a>]',
30                 '{$REFRESH}' => '[<a href="'.PHP_SELF2.'?">'._T('head_refresh').'</a>]',
31                 '{$SEARCH}' => (USE_SEARCH) ? '[<a href="'.PHP_SELF.'?mode=search">'._T('head_search').'</a>]' : '',
32                 '{$HOOKLINKS}' => '');
447 roytam1 33         $PMS->useModuleMethods('Toplink', array(&$pte_vals['{$HOOKLINKS}'],$resno)); // "Toplink" Hook Point
409 roytam1 34         $dat .= $PTE->ParseBlock('BODYHEAD',$pte_vals);
393 scribe 35 }
36  
37 /* 發表用表單輸出 */
545 scribe 38 function form(&$dat, $resno, $iscollapse=true, $retURL=PHP_SELF, $name='', $mail='', $sub='', $com='', $cat='', $mode='regist'){
833 scribe 39         global $ADDITION_INFO;
40         $PTE = PMCLibrary::getPTEInstance();
41         $PMS = PMCLibrary::getPMSInstance();
42  
545 scribe 43         $pte_vals = array('{$SELF}'=>$retURL, '{$FORMTOP}'=>'', '{$MODE}'=>$mode);
44         $isedit = ($mode == 'edit'); // 是否為編輯模式
45         if($resno && !$isedit){
483 roytam1 46                 $links = '[<a href="'.PHP_SELF2.'?'.time().'">'._T('return').'</a>]';
47                 $PMS->useModuleMethods('LinksAboveBar', array(&$links,'reply',$resno)); // "LinksAboveBar" Hook Point
482 roytam1 48                 $pte_vals['{$FORMTOP}'] = $links.'<div class="bar_reply">'._T('form_top').'</div>';
393 scribe 49         }
545 scribe 50         if(USE_FLOATFORM && !$resno && $iscollapse) $pte_vals['{$FORMTOP}'] .= "\n".'[<span id="show" class="hide" onmouseover="showform();" onclick="showform();">'._T('form_showpostform').'</span><span id="hide" class="show" onmouseover="hideform();" onclick="hideform();">'._T('form_hidepostform').'</span>]';
409 roytam1 51         $pte_vals += array('{$MAX_FILE_SIZE}' => MAX_KB * 1024,
52                 '{$RESTO}' => $resno ? '<input type="hidden" name="resto" value="'.$resno.'" />' : '',
53                 '{$FORM_NAME_TEXT}' => _T('form_name'),
538 roytam1 54                 '{$FORM_NAME_FIELD}' => '<input class="hide" type="text" name="name" value="spammer" /><input type="text" name="'.FT_NAME.'" id="fname" size="28" value="'.$name.'" />',
409 roytam1 55                 '{$FORM_EMAIL_TEXT}' => _T('form_email'),
538 roytam1 56                 '{$FORM_EMAIL_FIELD}' => '<input type="text" name="'.FT_EMAIL.'" id="femail" size="28" value="'.$mail.'" /><input type="text" class="hide" name="email" value="foo@foo.bar" />',
409 roytam1 57                 '{$FORM_TOPIC_TEXT}' => _T('form_topic'),
538 roytam1 58                 '{$FORM_TOPIC_FIELD}' => '<input class="hide" value="DO NOT FIX THIS" type="text" name="sub" /><input type="text" name="'.FT_SUBJECT.'" id="fsub" size="28" value="'.$sub.'" />',
409 roytam1 59                 '{$FORM_SUBMIT}' => '<input type="submit" name="sendbtn" value="'._T('form_submit_btn').'" />',
60                 '{$FORM_COMMENT_TEXT}' => _T('form_comment'),
538 roytam1 61                 '{$FORM_COMMENT_FIELD}' => '<textarea name="'.FT_COMMENT.'" id="fcom" cols="48" rows="4" style="width: 400px; height: 80px;">'.$com.'</textarea><textarea name="com" class="hide" cols="48" rows="4">EID OG SMAPS</textarea>',
409 roytam1 62                 '{$FORM_DELETE_PASSWORD_FIELD}' => '<input type="password" name="pwd" size="8" maxlength="8" value="" />',
63                 '{$FORM_DELETE_PASSWORD_TEXT}' => _T('form_delete_password'),
64                 '{$FORM_DELETE_PASSWORD_NOTICE}' => _T('form_delete_password_notice'),
432 scribe 65                 '{$FORM_EXTRA_COLUMN}' => '',
672 scribe 66                 '{$FORM_NOTICE}' => _T('form_notice',str_replace('|',', ',ALLOW_UPLOAD_EXT),MAX_KB,($resno ? MAX_RW : MAX_W),($resno ? MAX_RH : MAX_H)),
409 roytam1 67                 '{$HOOKPOSTINFO}' => '',
68                 '{$ADDITION_INFO}' => $ADDITION_INFO,
69                 '{$FORM_NOTICE_NOSCRIPT}' => _T('form_notice_noscript'));
432 scribe 70         $PMS->useModuleMethods('PostForm', array(&$pte_vals['{$FORM_EXTRA_COLUMN}'])); // "PostForm" Hook Point
545 scribe 71         if(!$isedit && (RESIMG || !$resno)){
409 roytam1 72                 $pte_vals += array('{$FORM_ATTECHMENT_TEXT}' => _T('form_attechment'),
73                         '{$FORM_ATTECHMENT_FIELD}' => '<input type="file" name="upfile" id="fupfile" size="25" /><input class="hide" type="checkbox" name="reply" value="yes" />',
74                         '{$FORM_NOATTECHMENT_TEXT}' => _T('form_noattechment'),
75                         '{$FORM_NOATTECHMENT_FIELD}' => '<input type="checkbox" name="noimg" id="noimg" value="on" />');
76                 if(USE_UPSERIES) { // 啟動連貼機能
77                         $pte_vals['{$FORM_CONTPOST_FIELD}'] = '<input type="checkbox" name="up_series" id="up_series" value="on"'.((isset($_GET["upseries"]) && $resno)?' checked="checked"':'').' />';
78                         $pte_vals['{$FORM_CONTPOST_TEXT}'] = _T('form_contpost');
79                 }
393 scribe 80         }
409 roytam1 81         if(USE_CATEGORY) {
538 roytam1 82                 $pte_vals += array('{$FORM_CATEGORY_FIELD}' => '<input type="text" name="category" size="28" value="'.$cat.'" />',
409 roytam1 83                         '{$FORM_CATEGORY_TEXT}' => _T('form_category'),
84                         '{$FORM_CATEGORY_NOTICE}' => _T('form_category_notice'));
85         }
86         if(STORAGE_LIMIT) $pte_vals['{$FORM_NOTICE_STORAGE_LIMIT}'] = _T('form_notice_storage_limit',total_size(),STORAGE_MAX);
87         $PMS->useModuleMethods('PostInfo', array(&$pte_vals['{$HOOKPOSTINFO}'])); // "PostInfo" Hook Point
88  
545 scribe 89         if(USE_FLOATFORM && !$resno && $iscollapse) $pte_vals['{$FORMBOTTOM}'] = '<script type="text/javascript">hideform();</script>';
409 roytam1 90         $dat .= $PTE->ParseBlock('POSTFORM',$pte_vals);
393 scribe 91 }
92  
93 /* 輸出頁尾文字 */
94 function foot(&$dat){
833 scribe 95         $PTE = PMCLibrary::getPTEInstance();
96         $PMS = PMCLibrary::getPMSInstance();
97  
409 roytam1 98         $pte_vals = array('{$FOOTER}'=>'<!-- GazouBBS v3.0 --><!-- ふたば改0.8 --><!-- Pixmicat! -->');
99         $PMS->useModuleMethods('Foot', array(&$pte_vals['{$FOOTER}'])); // "Foot" Hook Point
100         $pte_vals['{$FOOTER}'] .= '<small>- <a href="http://php.s3.to" rel="_top">GazouBBS</a> + <a href="http://www.2chan.net/" rel="_top">futaba</a> + <a href="http://pixmicat.openfoundry.org/" rel="_blank">Pixmicat!</a> -</small>';
101         $dat .= $PTE->ParseBlock('FOOTER',$pte_vals);
393 scribe 102 }
103  
104 /* 網址自動連結 */
833 scribe 105 function auto_link_callback($matches){
466 roytam1 106         return (strtolower($matches[3]) == "</a>") ? $matches[0] : preg_replace('/(https?|ftp|news)(:\/\/[\w\+\$\;\?\.\{\}%,!#~*\/:@&=_-]+)/u', '<a href="$1$2" rel="_blank">$1$2</a>', $matches[0]);
107 }
393 scribe 108 function auto_link($proto){
500 roytam1 109         $proto = preg_replace('|<br\s*/?>|',"\n",$proto);
110         $proto = preg_replace_callback('/(>|^)([^<]+?)(<.*?>|$)/m','auto_link_callback',$proto);
508 roytam1 111         return str_replace("\n",'<br />',$proto);
393 scribe 112 }
113  
114 /* 引用標註 */
115 function quoteLight($comment){
508 roytam1 116         return preg_replace('/(^|<br \/>)((?:&gt;|>).*?)(?=<br \/>|$)/u', '$1<span class="resquote">$2</span>', $comment);
393 scribe 117 }
118  
119 /* 取得完整的網址 */
120 function fullURL(){
543 scribe 121         return 'http://'.$_SERVER['HTTP_HOST'].substr($_SERVER['PHP_SELF'], 0, strpos($_SERVER['PHP_SELF'], PHP_SELF));
393 scribe 122 }
123  
124 /* 反櫻花字 */
125 function anti_sakura($str){
126         return preg_match('/[\x{E000}-\x{F848}]/u', $str);
127 }
128  
129 /* 輸出錯誤畫面 */
130 function error($mes, $dest=''){
833 scribe 131         $PTE = PMCLibrary::getPTEInstance();
132  
393 scribe 133         if(is_file($dest)) unlink($dest);
409 roytam1 134         $pte_vals = array('{$SELF2}'=>PHP_SELF2.'?'.time(), '{$MESG}'=>$mes, '{$RETURN_TEXT}'=>_T('return'), '{$BACK_TEXT}'=>_T('error_back'));
393 scribe 135         $dat = '';
136         head($dat);
409 roytam1 137         $dat .= $PTE->ParseBlock('ERROR',$pte_vals);
138         foot($dat);
414 scribe 139         exit($dat);
393 scribe 140 }
141  
142 /* 文字修整 */
143 function CleanStr($str, $IsAdmin=false){
144         $str = trim($str); // 去除前後多餘空白
145         if(get_magic_quotes_gpc()) $str = stripslashes($str); // "\"斜線符號去除
560 scribe 146         // XML 1.1 Second Edition: 部分避免用字 (http://www.w3.org/TR/2006/REC-xml11-20060816/#charsets)
147         $str = preg_replace('/([\x1-\x8\xB-\xC\xE-\x1F\x7F-\x84\x86-\x9F\x{FDD0}-\x{FDDF}])/u', '', htmlspecialchars($str));
148  
149         if($IsAdmin && CAP_ISHTML){ // 管理員開啟HTML
150                 $str = preg_replace('/&lt;(.*?)&gt;/', '<$1>', $str); // 如果有&lt;...&gt;則轉回<...>成為正常標籤
393 scribe 151         }
152         return $str;
153 }
154  
155 /* 適用UTF-8環境的擬substr,取出特定數目字元
156 原出處:Sea Otter @ 2005.05.10
157 http://www.meyu.net/star/viewthread.php?tid=267&fpage=10 */
158 function str_cut($str, $maxlen=20){
159     $i = $l = 0; $len = strlen($str); $f = true; $return_str = $str;
160         while($i < $len){
161                 $chars = ord($str{$i});
162                 if($chars < 0x80){ $l++; $i++; }
163                 elseif($chars < 0xe0){ $l++; $i += 2; }
164                 elseif($chars < 0xf0){ $l += 2; $i += 3; }
165                 elseif($chars < 0xf8){ $l++; $i += 4; }
166         elseif($chars < 0xfc){ $l++; $i += 5; }
167                 elseif($chars < 0xfe){ $l++; $i += 6; }
168                 if(($l >= $maxlen) && $f){
169                         $return_str = substr($str, 0, $i);
170                         $f = false;
171                 }
172                 if(($l > $maxlen) && ($i <= $len)){
173                         $return_str = $return_str.'…';
174                         break;
175                 }
176     }
177         return $return_str;
178 }
179  
180 /* 檢查瀏覽器和伺服器是否支援gzip壓縮方式 */
181 function CheckSupportGZip(){
182         $HTTP_ACCEPT_ENCODING = isset($_SERVER['HTTP_ACCEPT_ENCODING']) ? $_SERVER['HTTP_ACCEPT_ENCODING'] : '';
183         if(headers_sent() || connection_aborted()) return 0; // 已送出資料,取消
184         if(!(function_exists('gzencode') && function_exists('ob_start') && function_exists('ob_get_clean'))) return 0; // 伺服器相關的套件或函式無法使用,取消
185         if(strpos($HTTP_ACCEPT_ENCODING, 'gzip')!==false) return 'gzip';
186         return 0;
187 }
188  
189 /* 封鎖 IP / Hostname / DNSBL 綜合性檢查 */
190 function BanIPHostDNSBLCheck($IP, $HOST, &$baninfo){
191         if(!BAN_CHECK) return false; // Disabled
192         global $BANPATTERN, $DNSBLservers, $DNSBLWHlist;
193  
194         // IP/Hostname Check
559 roytam1 195         $HOST = strtolower($HOST);
393 scribe 196         $checkTwice = ($IP != $HOST); // 是否需檢查第二次
197         $IsBanned = false;
198         foreach($BANPATTERN as $pattern){
548 scribe 199                 $slash = substr_count($pattern, '/');
200                 if($slash==2){ // RegExp
393 scribe 201                         $pattern .= 'i';
548 scribe 202                 }elseif($slash==1){ // CIDR Notation
559 roytam1 203                         if(matchCIDR($IP, $pattern)){ $IsBanned = true; break; }
548 scribe 204                         continue;
393 scribe 205                 }elseif(strpos($pattern, '*')!==false || strpos($pattern, '?')!==false){ // Wildcard
206                         $pattern = '/^'.str_replace(array('.', '*', '?'), array('\.', '.*', '.?'), $pattern).'$/i';
207                 }else{ // Full-text
208                         if($IP==$pattern || ($checkTwice && $HOST==strtolower($pattern))){ $IsBanned = true; break; }
209                         continue;
210                 }
211                 if(preg_match($pattern, $HOST) || ($checkTwice && preg_match($pattern, $IP))){ $IsBanned = true; break; }
212         }
213         if($IsBanned){ $baninfo = _T('ip_banned'); return true; }
214  
215         // DNS-based Blackhole List(DNSBL) 黑名單
216         if(!$DNSBLservers[0]) return false; // Skip check
217         if(array_search($IP, $DNSBLWHlist)!==false) return false; // IP位置在白名單內
218         $rev = implode('.', array_reverse(explode('.', $IP)));
219         $lastPoint = count($DNSBLservers) - 1; if($DNSBLservers[0] < $lastPoint) $lastPoint = $DNSBLservers[0];
220         $isListed = false;
221         for($i = 1; $i <= $lastPoint; $i++){
222                 $query = $rev.'.'.$DNSBLservers[$i].'.'; // FQDN
223                 $result = gethostbyname($query);
224                 if($result && ($result != $query)){ $isListed = $DNSBLservers[$i]; break; }
225         }
226         if($isListed){ $baninfo = _T('ip_dnsbl_banned',$isListed); return true; }
227         return false;
228 }
559 roytam1 229 function matchCIDR($addr, $cidr) {
230         list($ip, $mask) = explode('/', $cidr);
560 scribe 231         return (ip2long($addr) >> (32 - $mask) == ip2long($ip.str_repeat('.0', 3 - substr_count($ip, '.'))) >> (32 - $mask));
548 scribe 232 }
530 scribe 233  
234 /* 後端登入權限管理 */
235 function adminAuthenticate($mode){
236         @session_start();
237         $loginkey = md5($_SERVER['HTTP_USER_AGENT'].ADMIN_PASS.$_SERVER['REMOTE_ADDR']);
238         switch($mode){
239                 case 'logout':
240                         if(isset($_SESSION['pmcLogin'])) unset($_SESSION['pmcLogin']);
241                         return true; break;
242                 case 'login':
243                         $_SESSION['pmcLogin'] = $loginkey;
244                         break;
245                 case 'check':
246                         if(isset($_SESSION['pmcLogin']) && $_SESSION['pmcLogin']==$loginkey){
247                                 session_regenerate_id(true); // 更換 Session id key 避免 Hijacking
248                                 return true;
249                         }
250                         return false;
251                         break;
252         }
253 }
535 scribe 254  
255 /* 取得 (Transparent) Proxy 提供之 IP 參數 */
256 function getREMOTE_ADDR(){
854 scribe 257         // 確定有需要才使用 HTTP_X_FORWARDED_FOR
258         if(defined('TRUST_HTTP_X_FORWARDED_FOR') && TRUST_HTTP_X_FORWARDED_FOR) {
259                 // 同時有 VIA 和 FORWARDED_FOR 較可能為 Proxy
260                 if(isset($_SERVER['HTTP_VIA']) && isset($_SERVER['HTTP_X_FORWARDED_FOR'])){
261                         $tmp = preg_split('/[ ,]+/', $_SERVER['HTTP_X_FORWARDED_FOR']);
262                         // 防止 Squid "unknown" 問題,此種情況直接使用 REMOTE_ADDR
263                         // 如果結果為 Private IP 或 Reserved IP,捨棄改用 REMOTE_ADDR
264                         if(filter_var($tmp[0], FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)){
265                                 return $tmp[0];
266                         }
812 scribe 267                 }
540 scribe 268         }
535 scribe 269         return $_SERVER['REMOTE_ADDR'];
270 }
393 scribe 271 ?>