]> 4ch.mooo.com Git - test.git/commitdiff
new file: ChangeLog
authorsparky4 <sparky4@4ch.irc.su>
Tue, 15 Feb 2011 03:21:19 +0000 (21:21 -0600)
committersparky4 <sparky4@4ch.irc.su>
Tue, 15 Feb 2011 03:21:19 +0000 (21:21 -0600)
new file:   config.php
new file:   config.xxxx
new file:   data/css/burichan.css
new file:   data/css/futaba.css
new file:   data/css/gurochan.css
new file:   data/css/kusaba.css
new file:   data/css/lightbox.css
new file:   data/css/lightbox/blank.gif
new file:   data/css/lightbox/overlay.gif
new file:   data/css/lightbox/overlay.png
new file:   data/css/main/style.css
new file:   data/css/null.css
new file:   data/css/photon.css
new file:   data/css/yotsuba.css
new file:   data/css/yotsubablue.css
new file:   data/css/yotsubanome.css
new file:   data/icon/ba.gif
new file:   data/icon/boot.gif
new file:   data/icon/closed.gif
new file:   data/icon/fade-blue.png
new file:   data/icon/fade.png
new file:   data/icon/favicon.ico
new file:   data/icon/favicon.png
new file:   data/icon/filedeleted.gif
new file:   data/icon/futaba.gif
new file:   data/icon/gchan_banner.gif
new file:   data/icon/kagami.gif
new file:   data/icon/kent_banner.gif
new file:   data/icon/letsphp.gif
new file:   data/icon/moeren.jpg
new file:   data/icon/nothumb.gif
new file:   data/icon/shiokara.gif
new file:   data/icon/sticky.gif
new file:   data/icon/yotsubanome_banner.png
new file:   data/js/iedivfix.js
new file:   data/js/script.js
new file:   data/stylesheets.csv_daty
new file:   data/tplt/inc_yo-festival.tplt
new file:   data/tplt/inc_yo-uploader.tplt
new file:   data/tplt/inc_yo.tplt
new file:   futaba2pio.php
new file:   futaba2pio.phps
new file:   info
new file:   lib/fileio/fileio.ftp.php
new file:   lib/fileio/fileio.imageshack.php
new file:   lib/fileio/fileio.normal.php
new file:   lib/fileio/fileio.satellite.php
new file:   lib/fileio/ifs.php
new file:   lib/lang/de_DE.php
new file:   lib/lang/en_US.php
new file:   lib/lang/ja_JP.php
new file:   lib/lang/strings_en.phps
new file:   lib/lang/strings_jp.phps
new file:   lib/lang/zh_TW.php
new file:   lib/lib_common.php
new file:   lib/lib_fileio.php
new file:   lib/lib_language.php
new file:   lib/lib_pio.cond.php
new file:   lib/lib_pio.php
new file:   lib/lib_pms.php
new file:   lib/lib_pte.php
new file:   lib/pio/pio.log.php
new file:   lib/pio/pio.logflockp.php
new file:   lib/pio/pio.mysql.php
new file:   lib/pio/pio.pgsql.php
new file:   lib/pio/pio.sqlite.php
new file:   lib/pio/pio.sqlite3.php
new file:   lib/pms.php
new file:   license
new file:   logo.gif
new file:   temp/1297428544668.gif
new file:   temp/1297428605149.gif
new file:   temp/1297428743387.gif
new file:   temp/1297429327524.gif
new file:   x.php
new file:   x.phps
new file:   yotsubanome.php

80 files changed:
.gitignore [new file with mode: 0644]
ChangeLog [new file with mode: 0755]
config.php [new file with mode: 0755]
config.xxxx [new file with mode: 0755]
data/css/burichan.css [new file with mode: 0755]
data/css/futaba.css [new file with mode: 0755]
data/css/gurochan.css [new file with mode: 0755]
data/css/kusaba.css [new file with mode: 0755]
data/css/lightbox.css [new file with mode: 0755]
data/css/lightbox/blank.gif [new file with mode: 0755]
data/css/lightbox/overlay.gif [new file with mode: 0755]
data/css/lightbox/overlay.png [new file with mode: 0755]
data/css/main/mainstyle.css [new file with mode: 0755]
data/css/main/style.css [new file with mode: 0755]
data/css/null.css [new file with mode: 0644]
data/css/photon.css [new file with mode: 0755]
data/css/yotsuba.css [new file with mode: 0755]
data/css/yotsubablue.css [new file with mode: 0755]
data/css/yotsubanome.css [new file with mode: 0755]
data/icon/ba.gif [new file with mode: 0755]
data/icon/boot.gif [new file with mode: 0755]
data/icon/closed.gif [new file with mode: 0755]
data/icon/fade-blue.png [new file with mode: 0755]
data/icon/fade.png [new file with mode: 0755]
data/icon/favicon.ico [new file with mode: 0755]
data/icon/favicon.png [new file with mode: 0755]
data/icon/filedeleted.gif [new file with mode: 0755]
data/icon/futaba.gif [new file with mode: 0755]
data/icon/gchan_banner.gif [new file with mode: 0755]
data/icon/kagami.gif [new file with mode: 0644]
data/icon/kent_banner.gif [new file with mode: 0644]
data/icon/letsphp.gif [new file with mode: 0755]
data/icon/moeren.jpg [new file with mode: 0755]
data/icon/nothumb.gif [new file with mode: 0755]
data/icon/shiokara.gif [new file with mode: 0755]
data/icon/sticky.gif [new file with mode: 0755]
data/icon/yotsubanome_banner.png [new file with mode: 0755]
data/js/iedivfix.js [new file with mode: 0755]
data/js/script.js [new file with mode: 0755]
data/stylesheets.csv_daty [new file with mode: 0644]
data/tplt/inc_yo-festival.tplt [new file with mode: 0755]
data/tplt/inc_yo-uploader.tplt [new file with mode: 0755]
data/tplt/inc_yo.tplt [new file with mode: 0755]
futaba2pio.php [new file with mode: 0755]
futaba2pio.phps [new file with mode: 0644]
info [new file with mode: 0755]
lib/fileio/fileio.ftp.php [new file with mode: 0755]
lib/fileio/fileio.imageshack.php [new file with mode: 0755]
lib/fileio/fileio.normal.php [new file with mode: 0755]
lib/fileio/fileio.satellite.php [new file with mode: 0755]
lib/fileio/ifs.php [new file with mode: 0755]
lib/lang/de_DE.php [new file with mode: 0755]
lib/lang/en_US.php [new file with mode: 0755]
lib/lang/ja_JP.php [new file with mode: 0755]
lib/lang/strings_en.phps [new file with mode: 0755]
lib/lang/strings_jp.phps [new file with mode: 0755]
lib/lang/zh_TW.php [new file with mode: 0755]
lib/lib_common.php [new file with mode: 0755]
lib/lib_fileio.php [new file with mode: 0755]
lib/lib_language.php [new file with mode: 0755]
lib/lib_pio.cond.php [new file with mode: 0755]
lib/lib_pio.php [new file with mode: 0755]
lib/lib_pms.php [new file with mode: 0755]
lib/lib_pte.php [new file with mode: 0755]
lib/pio/pio.log.php [new file with mode: 0755]
lib/pio/pio.logflockp.php [new file with mode: 0755]
lib/pio/pio.mysql.php [new file with mode: 0755]
lib/pio/pio.pgsql.php [new file with mode: 0755]
lib/pio/pio.sqlite.php [new file with mode: 0755]
lib/pio/pio.sqlite3.php [new file with mode: 0755]
lib/pms.php [new file with mode: 0755]
license [new file with mode: 0755]
logo.gif [new file with mode: 0755]
temp/1297428544668.gif [new file with mode: 0644]
temp/1297428605149.gif [new file with mode: 0644]
temp/1297428743387.gif [new file with mode: 0644]
temp/1297429327524.gif [new file with mode: 0644]
x.php [new file with mode: 0644]
x.phps [new file with mode: 0644]
yotsubanome.php [new file with mode: 0755]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..7a29ba2
--- /dev/null
@@ -0,0 +1,47 @@
+# Lines starting with '#' are considered comments.
+# Ignore (generated) html files,
+*.html
+*.htm
+*.xsl
+1*.* # images uploaded
+*.*.save
+*.*~
+#security reasons
+.audit
+*salt*.*
+#
+*-*_files/
+1279257582007.jpg
+1279257582007s.jpg
+bg_thumb.png
+magmachan_bg.png
+index.php
+src/
+thumb/
+arch/
+old/
+#beicon_files/
+cache/
+module/*.*
+module/*/
+module/*
+*.css
+*.csv_daty_old
+*cache.daty
+*.csv_loog
+!yotsuba.css
+!yotsubablue.css
+!kusaba.css
+!yotsubanome.css
+!gurochan.css
+!futaba.css
+!photon.css
+!burichan.css
+!null.css
+!mainstyle.css
+!style.css
+!lightbox.css
+# except foo.html which is maintained by hand.
+#!foo.html
+# Ignore objects and archives.
+*.[oa]
diff --git a/ChangeLog b/ChangeLog
new file mode 100755 (executable)
index 0000000..aa293e2
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,467 @@
+Pixmicat!-PIO 修改紀錄\r
+----------------------\r
+2010/09/14\r
+-[PMS] 修正 AdminFunction 掛載點第二個參數 $param 沒有傳址發生錯誤的問題\r
+\r
+2010/08/17\r
+-[PMS] 修正 Bug\r
+-[PMS] onlyLoad 恢復單載入,直到呼叫 callCHP 才會載入全部模組\r
+\r
+2010/08/16\r
+-[PMS] 新增 addCHP, callCHP 以實現模組間互相呼叫的方法\r
+-[PMS] onlyLoad 會載入全部模組方便 ModulePage 其他模組的相互作用\r
+\r
+2010/05/21 : 5th.Release (v100521)\r
+-正式釋出版\r
+\r
+2010/04/03\r
+-[mainscript] 使用 Closure Complier 取代先前使用之 Packer\r
+\r
+2010/02/05\r
+-[pixmicat] 修正討論串分頁 ThreadOrder 不正常的問題\r
+\r
+2010/01/28\r
+-[PTE] 標籤內容中的標籤無效化 (01/26 的再修正)\r
+\r
+2010/01/26\r
+-[pixmicat] 刪除回應排版 $arrLabels 多餘的 {$QUOTEBTN}\r
+-[PTE] 修正內文輸入 PTE 取代標籤會誤變換的情況 (ex: {$NAME_TEXT} => 名稱:)\r
+\r
+2010/01/13\r
+-[pixmicat] 修正autoHookAdminFunction參數不是ref的問題 *PHP 5.3相容修正\r
+-[Templates] 修正 IE8 標準成像模式下無法複製回應文字的問題\r
+-更新版權日期\r
+\r
+2009/12/15\r
+-[PIO] fetchPosts 新增 $fields 參數以降低total_size()的記憶體使用量 (log/logflockp只修改prototype)\r
+\r
+2009/07/01\r
+-[PIO] 靜態呼叫方法定義為靜態 *PHP 5.3相容修正\r
+-[pixmicat.php] ereg 系列函式以 preg 系列替代 *PHP 5.3相容修正\r
+-[PIO.sqlite3] 修正 tim 圖片檔名欄位超過 int 整數最大上限造成檔名溢位儲存無法對應的問題\r
+\r
+//--yotsubanome started here anything above this line is not in yotsubanome yet--//\r
+\r
+2009/05/21 : 4th.Anniversary (v090521)\r
+-正式釋出版\r
+\r
+2009/05/16\r
+-[pixmicat] 新增依特定類別標籤篩選觀看文章時,能根據No.連結找到文章的完整討論串位置\r
+-[PMS] PostOnDeletion 掛載點新增 $cond 參數判斷被呼叫時機 (frontend, backend, recycle)\r
+\r
+2009/04/25\r
+-[pixmicat] 修正發文時重複引用同一文章多次後造成的HTML重複問題\r
+\r
+2009/04/02\r
+-[lib_common] 修改 getREMOTE_ADDR() 對 HTTP_X_FORWARDED_FOR 的使用問題\r
+\r
+2009/03/21\r
+-[inc_pixmicat] 因應 IE8 推出,修改針對舊版 IE 的 Bugfix 判斷條件\r
+\r
+2009/01/12\r
+-[pixmicat] 修改分頁運算方法\r
+-[inc_pixmicat] 支援 AutoPagerize 套件換頁定義 (http://userscripts.org/scripts/show/8551)\r
+\r
+2008/11/30\r
+-[pixmicat] 修改上傳圖檔判斷是否存在的方法 (增加 is_uploaded_file() 偵測法)\r
+\r
+2008/09/20\r
+-[pixmicat] 修正發文後判斷附加圖檔容量過大開始刪除的敘述 (>= 改成 >)\r
+-[pixmicat] 修改管理區上方的連結列 (LinksAboveBar) 是否登入的判斷參數\r
+-[PIO] 新增 remove 系方法的 $posts 參數為空之錯誤處理\r
+-[pixmicat] 修正後端登入之 Authenticate 掛載點\r
+-[lib_common] 修正發文框下方說明列,回應模式時附加圖檔尺寸限制沒有正確反映的問題\r
+\r
+2008/09/10 : 4th.Release.3 (v080910)\r
+-[PMS] 修正 PHP 4 的相容性問題\r
+\r
+2008/09/03 : 4th.Release.3 (v080903)\r
+-正式釋出版\r
+\r
+2008/08/07\r
+-[PIO] 修改 FlagHelper 物件,使其更為方便讓模組修改屬性\r
+\r
+2008/07/27\r
+-[pixmicat] 修正當附加圖檔總容量限制功能關閉時,系統資訊顯示的排版錯誤問題\r
+\r
+2008/07/03\r
+-[pixmicat] 修正回應文章使用連貼機能時之不當快取,讓後續的連貼機能勾選框保持為勾選狀態的問題\r
+-[PIO] 0.6 版定案 (SQL Only)\r
+\r
+2008/05/31\r
+-[pixmicat] 修正刪除文章時 $_POST['func'] 未定義的問題\r
+\r
+2008/05/19\r
+-[FileIO] FTP, Satellite 方式參數增加是否要將預覽圖放至遠端的功能\r
+\r
+2008/04/28\r
+-[pixmicat] 修正類別標籤受到 magic_quotes_gpc() 開啟的影響\r
+-[pixmicat] 修正 glob() 在找不到回應快取時,因 PHP 的版本別而產生結果差異的錯誤\r
+-[PIO.sqlite3] 修正類別標籤搜尋時列出的文章沒有按照編號遞減排序\r
+\r
+2008/04/17:\r
+-[PTE][pixmicat-festival] 排版跟預設主題一致化。\r
+\r
+2008/04/07\r
+-[PIO] PIO 0.6 alpha: 交易模式支援、SQL Injection 防護等\r
+\r
+2008/03/31\r
+-[pixmicat] 修正版面更新文章 (remake) 過程中頁面超過索引值造成的錯誤\r
+\r
+2008/03/26\r
+-[PMS] autoHookRegistBegin 增加 $isReply 參數\r
+\r
+2008/03/19\r
+-[pixmicat] 修正 res=XXX 接受非數字的格式造成的 XSS & SQL Injection 問題\r
+-[PIO.sqlite3] 預設取消交易模式\r
+\r
+2008/03/18\r
+-[pixmicat] 修正直接瀏覽 pixmicat.php 出現動態輸出頁面並提示 page_num 未定義錯誤\r
+-[pixmicat] 修正前台管理刪除文章時處理文章陣列混入 'func' 造成刪除錯誤\r
+-[pixmicat] 修正前台管理刪除文章後沒有跳回前台管理頁面的問題\r
+-[pixmicat] 修正 usrdel() 之 AdminFunction 掛載點時機,delete 也可正常抓取\r
+-[language] 修改 del_btn 文字\r
+\r
+2008/03/14\r
+-[pixmicat] 新增前端管理功能 (以 PHP 動態輸出),支援 AdminList 跟 AdminFunction 掛載點之管理功能\r
+-[language] 新增 admin_delete, admin_frontendmanage\r
+\r
+2008/03/09\r
+-[inc_pixmicat-uploader] 更改 uploader-liked theme <table>的擺放位置\r
+\r
+2008/03/06\r
+-[PIO.mysql] 修正 dbMaintanence()\r
+\r
+2008/03/04\r
+-[PMS][pixmicat] 試驗性新增 AdminFunction 掛載點\r
+-[PIO] 修正 dbMaintanence('export',true) 出錯問題\r
+-[pixmicat] valid() 加入其他 dbMaintanence 功能\r
+-[language] action_opt_* 廢止,改為 action_main_* 並加入其他 dbMaintanence 功能\r
+\r
+2008/02/28\r
+-[PMS] 新增取得模組實體函式 getModuleInstance($module)\r
+\r
+2008/02/22\r
+-[pixmicat][PMS] 新增掛載點 ThreadOrder\r
+-[thumb][GD] GD 支援 RLE4/8 判斷式稍作修改,如果沒壓縮就不必再判斷\r
+\r
+2008/02/20\r
+-[thumb][GD] _ImageCreateFromBMP 修正 RLE4/RLE8 可能誤判的問題\r
+-[pixmicat] 讓 updatelog() 支援單頁生成 .htm 快取\r
+-[PIO] dbOptimize($doit=false) 廢止,改為 dbMaintanence($action,$doit=false)\r
+\r
+2008/02/19\r
+-[PMS] 修改模組單載入後手動掛載 ModulePage 掛載點造成多載入啟動、重複載入模組並作用的問題\r
+\r
+2008/02/11\r
+-[pixmicat][PTE] 讓 PTE MAIN block 能存取 {$RESTO}\r
+-[inc_pixmicat-uploader] 新增 uploader-liked theme\r
+\r
+2008/02/06, 08\r
+-[pixmicat][PMS] 新增掛載點 PostOnDeletion, RegistAfterCommit,移除掛載點 UsageExceed\r
+\r
+2008/01/31\r
+-[thumb][GD] _ImageCreateFromBMP 支援 RLE4/RLE8, 副檔名支援 '.rle'\r
+\r
+2008/01/27\r
+-[pixmicat][Language] 修正{$FORM_NOTICE}未與ALLOW_UPLOAD_EXT同步問題\r
+\r
+2008/01/18, 20\r
+-[pixmicat] 修正當欄位只填 XHTML 非法字元時會被系統清除而沒有任何內容卻也沒填預設值的錯誤\r
+-[pixmicat] 修正類別標籤字元 htmlentities() 後變成亂碼的問題\r
+-[config] 部分伺服器不相容$_SERVER['SCRIPT_FILENAME'],修改為常數方式\r
+-[pixmicat] 部分程式碼位置更動、精簡\r
+\r
+2008/01/13\r
+-[pixmicat] 搜尋結果增加連結至原討論串連結\r
+-[pixmicat] 系統資訊可查看目前使用之文章自動刪除機制名稱\r
+-[pixmicat] 修正當 STORAGE_MAX 設為 0 之程式非預期錯誤情況 (一般情況此值請設定 > 0)\r
+-[pixmicat] 修正類別標籤可能發生 XSS 的情況\r
+\r
+2007/12/16\r
+-[PMS] 修正在未初始化前 hookModuleMethod 的話會造成 autoHookXXXX 沒動作\r
+-[pixmicat] 修正在不支援緩衝區的情況下修改 XHTML MIME 動作會發生錯誤\r
+-[PTE][inc_pixmicat-festival] festival theme的post form下需要clear:both\r
+\r
+2007/11/09,18: 4th.Release.2 (v071120)\r
+-[lib_common] 修改 CIDR Notation 分析函式\r
+-[lib_common] 修改 CleanStr() 刪除 XML 1.1 SE 規範之避免用字\r
+-[pixmicat] 更改回傳 XHTML 檔頭時機\r
+-[PIO] 修正 Log 後端 updatePost() 時未處理逗號造成資料移位兼毀損問題\r
+-[PMS] 修正當載入模組未有掛載 ModulePage 方法仍試圖執行模組頁面造成錯誤\r
+\r
+2007/10/27: 4th.Release.2 RC4 (b071027)\r
+-[pixmicat] 修正類別標籤顯示頁面呼叫 arrangeThread() 傳入參數不合問題\r
+-[lib_common][config][pixmicat] 新增 USE_XHTML 選項能夠指定是否回傳 XHTML 檔頭\r
+\r
+2007/10/19: 4th.Release.2 RC3 (b071019)\r
+-[pixmicat] 修正引用瀏覽系統不斷 array_flip 造成搜尋對應文章失敗的問題\r
+\r
+2007/10/13,14: 4th.Release.2 RC2 (b071014)\r
+-[PIO] PIO 0.5 正式版 (修正 updatePost() 掉引號造成失敗問題)\r
+-[lib_common] 封鎖設定黑名單支援 CIDR Notation 模式 (ex: 192.168.0.1/16)\r
+-[PMS][pixmicat] 模組單載入功能復活,使用動態偵測決定是否要載入其他模組\r
+\r
+2007/10/06: 4th.Release.2 RC1 (b071006)\r
+-[PMS] 模組單載入功能取消 (當其他套件未載入可能造成功能上的錯誤)\r
+-[pixmicat] 引用瀏覽系統捨棄array_search()、開放引用首篇,對應修正樣板\r
+-[pixmicat] 修改樣板 POSTFORM 部分,去除 Ugly hack fix 新增 {$MODE} 修改模式\r
+-[pixmicat] $mode 取值順序改為 GET, POST\r
+\r
+2007/09/29\r
+-[config] 去除使用 $_SERVER['PHP_SELF'] (有 XSS 潛在危機)\r
+-[lib_common][FileIO] 修正 fullURL() / _getAbsoluteURL() 使用 $_SERVER['PHP_SELF'] 之 XSS 潛在危機\r
+\r
+2007/09/21\r
+-[PIO] PIO 0.5beta: Log 增加要求編號文章是否存在判定\r
+-[lib_common][pixmicat] 暫實裝 getREMOTE_ADDR() 函式取得使用者 IP (待完成)\r
+-[pixmicat] 提前容量暫存刪除時機,避免因預覽圖生成失敗未運作造成暫時的容量計算錯誤\r
+\r
+2007/09/16\r
+-[pixmicat][lib_common] 實裝 Session 後端認證功能\r
+\r
+2007/08/29,30\r
+-[pixmicat] 新增支援瀏覽器強制 no-cache (Ctrl + F5) 更新快取功能\r
+-[pixmicat] 移除筆數限制及使用量顯示\r
+-[pixmicat] 新增快取隨文章刪除功能\r
+-[pixmicat] 修正 Gzip 壓縮功能關閉時 $Encoding 變數未定義錯誤\r
+-[PIO] 新增文章自動刪除機制,可用自行定義好的模式來進行自動刪除判斷\r
+-[PIO] 移除 delOldPostes() 方法 (被文章自動刪除機制替代)\r
+\r
+2007/08/17,18,20\r
+-[PIO] 修正 MySQL setPostStatus() 自動更新到 root 欄位的問題\r
+-[PIO] 新增 FlagHelper 類別,加回 getPostStatus() [會回傳 FlagHelper 物件]\r
+-[pixmicat] 新增回應頁面顯示快取功能降低系統負擔 (因應原按鈕式 POST 換頁無法快取改為連結式)\r
+-[PMS] 修正 autoHookThreadFront/Rear 掛載點生成靜態頁面會重複輸出的錯誤\r
+\r
+2007/08/07,08\r
+-[PIO] PIO Structure V3: 加大 status 儲存量\r
+-[pixmicat][PIO] PIO 0.5alpha: 取消 getPostStatus(),修改 setPostStatus()\r
+-[pixmicat][PIO] PIO 0.5alpha: addPost() 新增 $status 引入\r
+-[PMS] RegistBeforeCommit 掛載點新增 &$status 引入\r
+-[lib_common] 修正 GD ImageCreateFormBMP 對 16bit BMP 的支援\r
+\r
+2007/07/26\r
+-[pixmicat] $path 取消 global\r
+-[pixmicat] 新增預覽圖生成函式庫物件,可以支援其他圖像處理函式庫\r
+\r
+2007/07/13\r
+-[pixmicat] 偵測上傳中斷前先判斷是否有資料長度才作,避免作白工\r
+-[PMS] autoHookRegistBegin 修改 $upfileInfo 為傳址, 去除 $POST ($_POST 為 superglobal)\r
+\r
+2007/07/09:\r
+-[PMS] 自事前掛載改為動態掛載,並可於模組頁面時只讀取特定模組\r
+\r
+2007/06/17: 4th.Release (v070617)\r
+-正式釋出版\r
+\r
+2007/06/15: 4th.Release-dev RC2 (b070615)\r
+-[PMS] 新增 PostForm, UsageExceed 掛載點\r
+\r
+2007/06/07: 4th.Release-dev RC (b070607)\r
+-[PIO] PIO 0.4 穩定版\r
+\r
+2007/06/05\r
+-[config] 刪除 CAPTCHA 預留設定 (不考慮內建)\r
+\r
+2007/05/27\r
+-[pixmicat][PMS] 新增 RegistBegin, RegistBeforeCommit 掛載點\r
+-[pixmicat] 修正模組資訊頁面的排版問題\r
+-[PTE] 強化並取代原內建輸出\r
+\r
+2007/05/13\r
+-[mainscript] 改寫增加效率,以 /packer/ 壓縮得到更小檔案\r
+ - 新增 Preset() Hook 機能,能在頁面載入完執行特定掛載函式\r
+ - replace_sakura() 改寫,增加效率\r
+-[iedivfix] 改寫,使用 Hook 機能提前執行時機\r
+-[lib_common] 把 mainscript.js 和 iedivfix.js 順序對調,防止執行錯誤\r
+\r
+2007/05/04, 05, 06\r
+-[pixmicat] 修正名稱輸入特殊字元轉成 Unicode 參照碼後被視為 Trip 轉換留下 & 造成 XML 解析錯誤的問題 (儲存/顯示雙重檢查)\r
+-[pixmicat] 修正搜尋文章結果印出錯誤的問題 (Since rev.363)\r
+-[pixmicat] 修正週五 (Friday) 字串顯示錯誤的問題\r
+\r
+2007/04/30\r
+-[PMS] 新增 AdminList 掛載點功能\r
+\r
+2007/04/25\r
+-將函式庫搬移至 /lib 目錄\r
+\r
+2007/04/15\r
+-[PMS] PMS 更新 (與 Pixmicat!2 共用相同的函式庫),並廢止PMS::getModulePageURL()方法\r
+\r
+2007/03/31\r
+-[pixmicat] 修改 Trip, Cap 生成函式 (ereg 在 PHP6 即將廢止,以 PCRE 函式取代)\r
+-[pixmicat] 修正 "管理"、"刪除" 在使用 Admin Cap 後仍然不能作為名稱的問題\r
+-[PIO] PIO 0.4gamma (與 Pixmicat!2 共用相同的函式庫)\r
+-[FileIO] FileIO 更新 (與 Pixmicat!2 共用相同的函式庫)\r
+\r
+2007/03/12\r
+01.[pixmicat] 修正翻譯索引錯誤 useage => usage\r
+\r
+2007/02/24\r
+01.[pixmicat][lib_common] 修正部份變數未定義錯誤\r
+\r
+2007/02/21\r
+01.[PIO] 修正 SQLite3 isThread() 總是回傳 true 的錯誤\r
+\r
+2007/02/14\r
+01.[PIO] PIO 0.4 beta,修改 fetchThreadList 方法\r
+\r
+2007/02/10, 11\r
+01.[PIO] 有關時區部份改以 UTC 時間手動位移避免混亂\r
+\r
+2007/02/07\r
+01.[PTE] 預設樣板更新 (inc_pixmicat.tpl)\r
+\r
+2007/02/01,02\r
+01.[lib_common] str_cut() 補上來源\r
+02.[upgradePIO] mysql2pio.php 修正,新增欄位次序修正 (舊版無影響)\r
+03.[PIO] PIO 0.4 alpha,新增 dbImport / dbExport 方法\r
+\r
+2007/01/31\r
+01.[lib_common][config] 刪除 RE_COL,改以 CSS 樣式表設定\r
+\r
+2007/01/30\r
+01.[FileIO] ImageShack 後端因應 mod_archiver 修改 getImageURL 方法\r
+02.[PMS] 新增 PMS::getModulePageURL(),可讓模組取得獨立頁面網址\r
+03.[PIO] Log postCount() 修正為回傳本篇加回應的數目,非先前僅有回應數\r
+04.[pixmicat] 修正 MAX_RES 不推文判斷,回應超過這個數字才不推 (先前是等於就不推了)\r
+\r
+2007/01/28,29\r
+01.[PMS] ThreadPost, ThreadReply 掛載點新增是否位於回應模式的判斷參數\r
+02.[PMS][lib_common] 新增 PostInfo 掛載點\r
+\r
+2007/01/27\r
+01.[PIO] SQLite3 類別標籤搜尋 SQL 語法更正\r
+02.[pixmicat][PMS] 新增 Foot / ThreadPost, ThreadReply 掛載點,可搭配 PTE 動態新增插入標籤\r
+\r
+2007/01/26\r
+01.[PMS] 增設 Toplink Hook Point, 並完成 mod_catalog\r
+02.[config] 更改模組載入形式,較可以自由切換載入模組 (註解起來即可)\r
+\r
+2007/01/25\r
+01.[PMS][config] 試驗性模組系統雛型架上,並完成 mod_rss 改寫\r
+02.[pixmicat][lib_common] fullURL(), anti_sakura() 移至 lib_common.php\r
+\r
+2007/01/24\r
+01.[lib_common] 廢除 PROXY_CHECK 檢查功能\r
+02.[config][pixmicat] 強化 IP 封鎖為綜合性 IP/Hostname/DNSBL 封鎖機能,支援 RegExp/Wildcard 模式\r
+\r
+2007/01/05:3rd.Release (v070106)\r
+01.[lib_common] 減少 str_cut() 的 ord() 呼叫次數\r
+02.[lib_common] CheckSupportGZip() 判斷式修改\r
+03.[FileIO] 修改 ImageShack 後端當上傳圖檔小於 200x200 時無法顯示縮圖的問題\r
+\r
+2006/12/28\r
+01.[pixmicat] 新增回應模式分頁 [ALL] 全部顯示功能 (顯示條件:分頁數超過一頁)\r
+02.[lib_common] 修正 2006/10/27 01. 項失效的問題 (Cookie 無法正確填入欄位)\r
+03.[PIO] SQL 讀寫新增 _error_handler() 錯誤攔截機制\r
+\r
+2006/12/23\r
+01.[FileIO] 修改normal模式使用getImageURL()回傳相對位置造成mod_rss生成RSS不合語法的問題\r
+02.[FileIO] 減少getImageLocalURL()每次都要取目前伺服器絕對位置造成的CPU浪費\r
+\r
+2006/12/22\r
+01.[lib_common][pixmicat] Publicβ 開始\r
+02.[config] 修改部分預設設定\r
+\r
+2006/12/19\r
+01.[PIO] 修正 PIO PgSQL, SQLite 儲存密碼欄位時變數名稱打錯的問題\r
+\r
+2006/12/16\r
+01.[config] 新增 PIO 及 FileIO 參考設定,移除 *_URL_PREFIX 設定 (目前取消)\r
+02.[PIO] 新增 searchCategory() 輸出順序依編號由大排到小\r
+\r
+2006/12/12\r
+01.[pixmicat] 修改 Category 印出時使用 urlencode 以確保各瀏覽器相容性\r
+02.[FileIO] 修改 FileIO IndexFS 使其在需要時才讀取索引以節省 CPU\r
+\r
+2006/12/11\r
+01.[PIOlog] 修正當 LUT 快取不見時無法重新生成造成版面無法復原問題\r
+02.[PTE] 預設樣版新增類別標籤欄位 (供修改製作參考)\r
+\r
+2006/12/10\r
+01.[PTE][lib_common] 改回原本樣式,原獨立樣式表方式廢棄 (見2006/09/22,23)\r
+02.[pixmicat] 新增搜尋類別標籤的重新快取功能,以免 Session 快取過久無法顯示最新文章\r
+\r
+2006/12/09\r
+01.[FileIO] Satellite PHP & Perl CGI 完成\r
+02.[FileIO] FileIO Index File System 獨立,FileIO 完成\r
+\r
+2006/12/07\r
+01.[FileIO] FileIO Satellite 後端完成,衛星 PHP 亦完成\r
+02.[FileIO] FileIO ImageShack 大圖連結 URL 更改,預設連至顯示頁面\r
+\r
+2006/12/06\r
+01.[FileIO] FileIO ImageShack 實裝註冊金鑰認證、要求刪圖功能及取消預覽圖資訊列\r
+\r
+2006/12/05\r
+01.[FileIO] FileIO 改用建立物件式,為此所有操作到 FileIO 敘述全部更改\r
+02.[FileIO] FileIO FTP 後端重寫完成\r
+03.[config] FileIO 參數規格修改,改以傳入陣列方式供後端自行分析使用\r
+04.字詞修正 CATALOG -> CATEGORY\r
+05.[FileIO] FileIO ImageShack 後端完成\r
+\r
+2006/12/04\r
+01.[FileIO] FileIO 0.2 版,並完成 Normal 後端\r
+02.[PIO][pixmicat] PIO, pixmicat.php 與 FileIO 相關函式修改\r
+\r
+2006/12/03\r
+01.[pixmicat] 修正顯示附加圖檔檔案大小時多一個B變成KBB的問題\r
+02.[pixmicat] 類別標籤分頁功能\r
+03.[PIO] PIO 0.3 更新\r
+\r
+2006/11/13\r
+01.[pixmicat] 修正E-mail填入 ◆XXX 的Trip後會造成版面亂掉的問題\r
+02.[pixmicat][config] 新增強制砍名功能 (仿二次元壁紙@ふたば、攤開Customized)\r
+\r
+2006/10/27\r
+01.[mainscript][lib_common] 修正Firefox瀏覽器自動填入Cookies儲存密碼時底端欄位漏填的問題\r
+02.[pixmicat] 用語更改:防止Spam對策機制啟動! -> 防止 Spambot 機制啟動!\r
+03.[PIO] searchCatalog 完成\r
+\r
+2006/10/23\r
+01.[mainscript] 更新方法,並重新以JSLint, JSMin檢測壓縮\r
+02.[lib_common][config][pixmicat] 實裝Spambot欄位陷阱\r
+\r
+2006/09/22,23\r
+01.[pixmicat] searchCatalog()初步完成,分頁功能暫時未加入 (目前採Session儲存,有可能改變)\r
+02.[pixmicat][lib_common] 無貼圖勾選框加回來以防止Spam攻擊\r
+03.[PTE][mainstyle] 將StyleSheet部分獨立出新樣板區塊,將mainstyle的討論串樣式搬過來\r
+04.[PIOlog][PIOmysql] 完成searchCatalog(),SQL錯誤訊息預設不顯示避免被利用\r
+\r
+2006/09/20\r
+01.[pixmicat] 搜尋部分(searchCatalog)實作中\r
+\r
+2006/09/15\r
+01.[pixmicat] 新增類別標籤功能,目前可以儲存標籤、印出標籤,搜尋部分尚未完成\r
+\r
+2006/08/26\r
+01.[PIOlog] 修正索引鍵錯亂造成Log丟失問題及刪舊文不刪其圖問題\r
+02.[PIOlog] 取消array_search改用array_flip + array_key_exists\r
+03.[PIOlog] 修正porder[0]刪掉後造成編號歸零計算\r
+04.[PIOlog] 修正torder混亂的問題\r
+\r
+2006/08/25\r
+01.[PIO] 廢除PIO Class Wrapper,以PIO Kernel Switcher代替\r
+02.[PIOlog] 修改處理結構,增加LUT Cache (目前尚有Bug, 徵求除錯)\r
+03.[pixmicat] 不具合小修正\r
+04.[PIOlog] 修正資料筆數必須要到LOG_MAX+1才會開始刪除舊文的問題\r
+\r
+2006/08/24\r
+01.[PIO] 各資料來源的資料結構更新完成\r
+02.[PIOlog] 修正在管理模式時若改變文章狀態會在dbCommit()刪除resto鍵值造成後續的輸出發生錯誤\r
+03.[pixmicat] 修正發文後檢查是否討論串被設為禁止回應的tim鍵值使用錯誤的問題\r
+\r
+2006/08/23\r
+01.[PIO] 修改資料結構,增加catalog和imgw, imgh, imgsize等欄位\r
+02.[pixmicat] 去除extract POST, GET以增強安全性和效率,需要時再解析取得\r
+03.[pixmicat] 去除對URL「?mode=search」POST的不符標準\r
+\r
+2006/08/11\r
+01.[pixmicat] PIO版本決議將繼續開發直到成熟為止\r
+02.[PIO] PIOlog, mysql, sqlite, pgsql物件化\r
+03.[pixmicat] 加回Refresh標籤,發文完成即使關閉JavaScript也能跳轉頁面\r
+04.[pixmicat] 配合PIO物件化修改,連續投稿 / 相同附加圖檔檢查給PIO處理\r
+05.[PIO] 新增checkSuccessivePost及checkDuplicateAttechment函式\r
diff --git a/config.php b/config.php
new file mode 100755 (executable)
index 0000000..fa47930
--- /dev/null
@@ -0,0 +1,249 @@
+<?php
+/*
+Pixmicat! : 圖咪貓貼圖版程式
+http://pixmicat.openfoundry.org/
+版權所有 © 2005-2009 Pixmicat! Development Team
+
+版權聲明:
+此程式是基於レッツPHP!<http://php.s3.to/>的gazou.php、
+双葉ちゃん<http://www.2chan.net>的futaba.php所改寫之衍生著作程式,屬於自由軟體,
+以The Clarified Artistic License作為發佈授權條款。
+您可以遵照The Clarified Artistic License來自由使用、散播、修改或製成衍生著作。
+更詳細的條款及定義請參考隨附"LICENSE"條款副本。
+
+發佈這一程式的目的是希望它有用,但沒有任何擔保,甚至沒有適合特定目的而隱含的擔保。
+關於此程式相關的問題請不要詢問レッツPHP!及双葉ちゃん。
+
+如果您沒有隨著程式收到一份The Clarified Artistic License副本,
+請瀏覽http://pixmicat.openfoundry.org/license/以取得一份。
+*/
+
+/*
+yotsubanome development status
+α = core under development [Database management] [core html output]
+β = module system under development & αtesting
+γ = language documentation and comments & β testing
+δ = clean up and testing & γ testing and finishing
+
+><
+
+//comment guide
+//---- removed
+//==== ????
+//++++---- QUICK AND DIRTY
+//++++ planned to be added on
+
+sparky4 made alot of changes with out following the guide lines
+TODO:
+       1. when pixmicat release 6 comes out, upgrade the code with all fixes.... (this will be a long prossess)
+       2. import functions ported to yotsubanome's standards testing.
+       3. multiboard sstem more automatic.
+       4. core board execution option
+
+ChangeLog:
+----------------------
+2011/2/12
+-[x.php] Created
+
+2011/2/11
+-[futaba2pio.php] Added more functionality
+-[yotsubanome.php] Fixed comment too long click "here" bug
+
+
+*/
+//error_reporting(E_ALL);  //Show the cursed errors
+include_once('../../conk/.pass.php'); // The password file sparky4 uses this line until the stable release is released
+
+/*---- Part 1:程式基本設定 ----*/
+// 伺服器常態設定
+if(!defined("PHP_SELF"))define("PHP_SELF", 'yotsubanome.php'); // このスクリプト名 // 主程式名 (若是修改了主程式名,請配合修改)
+//----define("TIME_ZONE", '-6'); // 時區設定 (GMT時區,參照 http://wwp.greenwichmeantime.com/ )
+define("DATE_FORMAT", "Y/m/d"); // date format
+define("EN_SEC", 1); // 時間表示に「秒」を含める  含める:1 含めない:0
+define("PIXMICAT_LANGUAGE", 'en_US'); // 語系語定 // ja_JP en_US zh_TW
+define("HTTP_UPLOAD_DIFF", 50); // HTTP上傳所有位元組與實際位元組之允許誤差值
+ini_set("memory_limit", '24M'); // PHP運行的最大記憶體使用量 (php內定8M / 建議32M)
+
+// FileIO設定
+define("FILEIO_BACKEND", 'normal'); // FileIO後端指定
+define("FILEIO_INDEXLOG", 'fileioindex.daty'); // FileIO索引記錄檔 (儲存在本機端)
+define("FILEIO_PARAMETER", ''); // FileIO參數 (本機端儲存)
+//define("FILEIO_PARAMETER", serialize(array('ftp.example.com', 21, 'demo', 'demo', 'PASV', '/pwd/', 'http://www.example.com/~demo/pwd/', true))); // FileIO參數 (FTP)
+//define("FILEIO_PARAMETER", serialize(array('00000000000000000000000000000000'))); // FileIO參數 (ImageShack)
+//define("FILEIO_PARAMETER", serialize(array('http://www.example.com/~demo/satellite.cgi', true, '12345678', 'http://www.example.com/~demo/src/', true))); // FileIO參數 (Satellite)
+
+// PIO資料來源設定
+if(!defined("CONNECTION_STRING")){ // incase you use a different database in a different board
+define("CONNECTION_STRING", 'log://img.csv_loog:tree.csv_loog/'); // PIO 連線字串 (Log)
+//under development //define("CONNECTION_STRING", 'mysql://yotsubanome:pass@localhost/yotsubanome/img_loog/'); // PIO 連線字串 (MySQL)
+//define("CONNECTION_STRING", 'sqlite://yotsubanome.db/img_loog/'); // PIO 連線字串 (SQLite)
+//define("CONNECTION_STRING", 'pgsql://yotsubanome:pass@localhost/yotsubanome/img_loog/'); // PIO 連線字串 (PostgreSQL)
+}
+
+// CSV Data file names
+// daty = yotsubanome data file
+// loog = yotsubanome log file
+define("LUT_CACHE", 'lutcache.daty');
+define("SIZE_CACHE", 'sizecache.daty');
+define("CSVSS", '_css.csv_daty');
+define("CSV_SS", 'stylesheets.csv_daty');
+
+/*---- Part 2:板面各項細部功能設定 ----*/ 
+define("IMG_DIR", 'src/'); // 画像保存ディレクトリ。futaba.phpから見て // 圖片存放目錄
+define("THUMB_DIR", 'thumb/'); //サムネイル保存ディレクトリ // 預覽圖存放目錄
+define("PHP_SELF2", 'index.htm'); // 入り口ファイル名 // 入口檔名
+define("PHP_EXT", '.htm'); // 1ページ以降の拡張子 // 第一頁以後生成檔案之副檔名
+
+$config['TITLE'] = '画像掲示板';
+if(!defined("TITLE"))define("TITLE", $config['TITLE']); // タイトル // 網頁標題
+define("TITLECOM", ''); // <small>TITLECOM</small>
+define("SHOWTITLEIMG", 0); // Show the title image (rotating:2 yes:1 no:0)
+define("SHOWTITLETXT", 1); // Show the title text (yes:1 no:0)
+define("TITLEIMG", 'logo.gif'); // Title image (point to php file if rotating)
+define("HOME", '../'); // 「ホーム」へのリンク // 回首頁的連結
+define("TOP_LINKS", ''); // 頁面右上方的額外連結,請直接以[<a href="網址" rel="_blank">名稱</a>]格式鍵入,如果不需要開新視窗可刪除rel一段
+if(!defined("ADMIN_PASS"))define("ADMIN_PASS", 'yotsubanome'); // 管理者パス // 管理員密碼
+define("IDSEED", 'idの種'); // idの種 // 生成ID之隨機種子
+define("TRIP_KEY", '◆');
+define("TRIP_KEY_FAKE", '◇');
+
+// 管理員キャップ(Cap)設定 (啟用條件:開啟使用;名稱輸入識別名稱,E-mail輸入#啟動密碼)
+define("CAP_ENABLE", 1); // 是否使用管理員キャップ (使用:1 不使用:0)
+define("CAP_NAME", 'futaba'); // 管理員キャップ識別名稱
+define("CAP_PASS", 'futaba'); // 管理員キャップ啟動密碼 (在E-mail一欄輸入#啟動密碼)
+define("CAP_SUFFIX", ' ■'); // 管理員キャップ後綴字元 (請務必有★以便程式防止偽造,或可自行修改程式的防偽造部份)
+define("CAP_SUFFIX_FAKE", ' []');
+define("CAP_ISHTML", 1); // 管理員キャップ啟動後內文是否接受HTML標籤 (是:1 否:0)
+
+// ^^????^^
+
+// 功能切換
+define("USE_THUMB", 1); // サムネイルを作る  する:1 しない:0 // 使用預覽圖機能 (使用:1 不使用:0)
+define("STYLEBAR", 1); // location of style bar [CSS decoration style for the pages] (top & bottom:1 bottom:0)
+define("USE_FLOATFORM", 0); // 新增文章表單使用自動隱藏 (是:1 否:0)
+define("USE_SEARCH", 1); // 開放搜尋功能 (是:1 否:0)
+define("OPTION", 1); // allow options to show up (yes:1 no:0)
+define("USE_UPSERIES", 1); // 是否啟用連貼機能 [開主題後自動指向到主題下以方便連貼] (是:1 否:0)
+define("RESIMG", 1); // レスにも画像を添付できるようにする 添付可能:1 添付不可:0 // 回應附加圖檔機能 (開啟:1 關閉:0)
+//++++define("RES_MARK", '…'); // レスの頭に付ける文字列
+define("AUTO_LINK", 1); // URL自動リンクを行う  する:1 しない:0 // 討論串文字內的URL是否自動作成超連結 (是:1 否:0)
+define("KILL_INCOMPLETE_UPLOAD", 1); // 自動刪除上傳不完整附加圖檔 (是:1 否:0)
+define("ALLOW_NOPASS", 0); // 削除キーの入力をチェックする  する:1 しない:0
+define("ALLOW_NOSUB",  1); // 題名省略時拒絶する  する:1 しない:0
+define("ALLOW_NONAME", 1); // 名前省略時拒絶する  強制的に名前をハック:2 する:1 しない:0 // 是否接受匿名發送 (強制砍名:2 是:1 否:0)
+define("ALLOW_NOCOM",  1); // 本文省略時拒絶する  する:1 しない:0
+// もし、有効にした場合、注意書きを書くことをお勧めします。
+define("DISP_ID", 2); // IDを表示する  強制:2 する:1 しない:0 // 顯示ID (強制顯示:2 選擇性顯示:1 永遠不顯示:0)
+define("CLEAR_SAGE", 0); // 使用不推文模式時清除E-mail中的「sage」關鍵字 (是:1 否:0)
+define("USE_QUOTESYSTEM", 1); // 是否打開引用瀏覽系統 [自動轉換>>No.xxxx文字成連結並導引] (是:1 否:0)
+define("KB", 1); // Kilobytes or Bytes on the image file size display (Kilobytes:1 Bytes:0)
+define("SHOW_IMGWH", 1); // 是否顯示附加圖檔之原檔長寬尺寸 (是:1 否:0)
+define("SHOW_FILENAME", 1); // 是否顯示附加圖檔之原檔文件名 (是:1 否:0)
+define("USE_CATEGORY", 0); // 是否開啟使用類別標籤分類功能 (是:1 否:0)
+define("USE_RE_CACHE", 1); // 是否使用回應頁面顯示快取功能 (是:1 否:0)
+if(!defined("USE_XHTML"))define("USE_XHTML", 1); // 是否回傳 XHTML 檔頭讓瀏覽器以更嚴格的方式解析 [僅限瀏覽器支援者] (是:1 否:0)
+
+// 模組載入
+$ModuleList = array();
+//$ModuleList[] = 'mod_rss';
+
+$ModuleList[] = 'mod_adminenhance';//<- ? help me please
+$ModuleList[] = 'mod_archiver';
+$ModuleList[] = 'mod_audit';
+$ModuleList[] = 'mod_bbcode';
+
+//$ModuleList[] = 'mod_captcha';
+$ModuleList[] = 'mod_catalog';//<-sparky4 needs here .... HELP
+//$ModuleList[] = 'mod_code';//<- missing JS and CSS files
+$ModuleList[] = 'mod_code_prettify';//<-sparky4 is here
+
+//$ModuleList[] = 'mod_dummy';
+//$ModuleList[] = 'mod_edit';//<-important
+//$ModuleList[] = 'mod_eggpoll';
+//$ModuleList[] = 'mod_exif';
+//$ModuleList[] = 'mod_imgsizelimit';
+//$ModuleList[] = 'mod_mobile';
+//$ModuleList[] = 'mod_neta';
+//$ModuleList[] = 'mod_opentag';
+//$ModuleList[] = 'mod_paint';
+//$ModuleList[] = 'mod_pm';
+//$ModuleList[] = 'mod_pushpost';
+//$ModuleList[] = 'mod_readonly';
+//$ModuleList[] = 'mod_recaptcha';
+//$ModuleList[] = 'mod_robottrap';
+//$ModuleList[] = 'mod_rss';
+//$ModuleList[] = 'mod_sectrip';
+//$ModuleList[] = 'mod_shoutbox';
+//$ModuleList[] = 'mod_showhide';
+//$ModuleList[] = 'mod_showip';
+//$ModuleList[] = 'mod_siokara';
+//$ModuleList[] = 'mod_tag';
+//$ModuleList[] = 'mod_threadlist';
+//$ModuleList[] = 'mod_threadorder';
+//$ModuleList[] = 'mod_tripcheck';
+//$ModuleList[] = 'mod_typepad_antispam';
+//$ModuleList[] = 'mod_userrepair';
+//$ModuleList[] = 'mod_vipquality';
+
+// 封鎖設定
+define("BAN_CHECK", 0); // 綜合性封鎖檢查功能 (關閉:0, 開啟:1)
+$BANPATTERN = array(); // 拒絶するホスト // IP/Hostname封鎖黑名單
+$DNSBLservers = array(0, 'sbl-xbl.spamhaus.org', 'list.dsbl.org', 'bl.blbl.org', 'bl.spamcop.net'); // DNSBL伺服器列表 (首項:使用伺服器個數)
+$DNSBLWHlist = array(); // DNSBL白名單 (請輸入IP位置)
+$BAD_STRING = array("dummy_string","dummy_string2"); // 拒絶する文字列 // 限制出現之文字
+$BAD_FILEMD5 = array("dummy","dummy2"); // 拒絶するファイルのmd5 // 限制上傳附加圖檔之MD5檢查碼
+
+// 附加圖檔限制
+define("MAX_KB", 9000); // 投稿容量制限 KB(phpの設定により2Mまで // 投稿容量制限 KB(phpの設定により2Mまで // 附加圖檔上傳容量限制KB (php內定為最高2MB)
+define("STORAGE_LIMIT", 0); // 附加圖檔總容量限制功能 (啟動:1 關閉:0)
+define("STORAGE_MAX", 30000); // 附加圖檔總容量限制上限大小 (單位:KB)
+define("ALLOW_UPLOAD_EXT", 'GIF|JPG|PNG|BMP|SWF|TXT'); // 接受之附加圖檔副檔名 (送出前表單檢查用,用 | 分隔)
+
+// 連續投稿時間限制
+define("RENZOKU", 4); // 連続投稿秒数 // 連續投稿間隔秒數
+define("RENZOKU2", 13); // 画像連続投稿秒数 // 連續貼圖間隔秒數
+
+// 預覽圖片相關限制
+define("MAX_W", 240); // 投稿サイズ幅(これ以上はwidthを縮小 // 討論串本文預覽圖片寬度 (超過則自動縮小)
+define("MAX_H", 240); // 投稿サイズ高さ // 討論串本文預覽圖片高度
+define("MAX_RW", 240); // 投稿サイズ幅(これ以上はwidthを縮小 // 討論串回應預覽圖片寬度 (超過則自動縮小)
+define("MAX_RH", 240); // 投稿サイズ高さ // 討論串回應預覽圖片高度
+//++++define("MIN_W", 2); // minimal width size
+//++++define("MIN_H", 2); // minimal hieght size
+//++++define("MAX_DIMENSION", 9000); // maximum dimentions
+define("THUMB_Q", 84); // 預覽圖片之品質 (1-100, 建議預設75,越高品質越好但檔案也越大)
+
+// 外觀設定
+$ADDITION_INFO = ""; // 可在表單下顯示額外文字
+$LIMIT_SENSOR = array('ByPostCountCondition'=>9000); // 文章自動刪除機制設定
+define("TEMPLATE_FILE", TPLT_DIR.'inc_yo.tplt'); // 樣板位置
+define("CSSFILE", "yotsubanome.css"); // default CSS file name
+define("FAV_ICON", '<link rel="shortcut icon" href="'.ICON_DIR.'favicon.ico" />'); // favicon file name
+define("PAGE_DEF", 16); // 一ページに表示する記事 // 一頁顯示幾篇討論串
+define("ADMIN_PAGE_DEF", 20); // 管理模式下,一頁顯示幾筆資料
+define("RE_DEF", 4); // 「レス省略」を表示するレスの数 // 一篇討論串最多顯示之回應筆數 (超過則自動隱藏,全部隱藏:0)
+define("RE_PAGE_DEF", 40); // 回應模式一頁顯示幾筆回應內容 (分頁用,全部顯示:0)
+define("MAX_RES", 0); // 強制sageレス数 // 回應筆數超過多少則不自動推文 (關閉:0)
+define("MAX_AGE_TIME", 0); // 強制sageまでの時間   0で強制sageなし // 討論串可接受推文的時間範圍 (單位:小時,討論串存在超過此時間則回應皆不再自動推文 關閉:0)
+define("COMM_MAX", 9000); // 內文接受Bytes數 (注意:中文字為2Bytes)
+define("MAX_LINES", 16); // The number of lines in the comment feild that are displayed in the index (unlimited:0)
+define("NO_TEXTONLY", 0); // no text only? behavior with the no image switch (Ost [Eastern]:2 Futaba:1 Yotsubanome [OLD]:0)
+define("BR_CHECK", 0); // 改行を抑制する行数 しない:0 // 文字換行行數上限 (不限:0)
+define("STATIC_HTML_UNTIL", -1); // 更新文章時自動生成的靜態網頁至第幾頁止 (全部生成:-1 僅入口頁:0)
+define("GZIP_COMPRESS_LEVEL", 4); // PHP動態輸出頁面使用Gzip壓縮層級 (關閉:0 啟動:1~9,推薦值:3)
+define("DEFAULT_NOTITLE", "無題"); // 省略時の題名 // 預設文章標題
+define("DEFAULT_NONAME", "名無し"); // 省略時の名前 // 預設文章名稱
+define("DEFAULT_NOCOMMENT", "本文なし"); // 省略時の本文 // 預設文章內文
+
+/*---- Part 3:Anti-SPAM 防止垃圾訊息機器人發文 ----*/
+/* 欄位陷阱 (Field Trap)
+介紹:
+機器人會針對常見的欄位名稱送出垃圾資料,將這些常見的欄位製成陷阱,
+另設名稱怪異的欄位為正確欄位,以避免直接的攻擊。
+防止機器人學習的可能,請隔一段時間修改底下欄位值,建議英數大小寫隨機6~10個 (避免特殊符號、第一位不能為數字)。
+*/
+define("FT_NAME", 'bvUFbdrIC'); // 名稱欄位
+define("FT_EMAIL", 'ObHGyhdTR'); // E-mail欄位
+define("FT_SUBJECT", 'SJBgiFbhj'); // 標題欄位
+define("FT_COMMENT", 'pOBvrtyJK'); // 內文欄位
+?>
diff --git a/config.xxxx b/config.xxxx
new file mode 100755 (executable)
index 0000000..02d5d17
--- /dev/null
@@ -0,0 +1,563 @@
+<?php\r
+if(!defined("LOGFILE")) define("LOGFILE", 'img.cgi');  //\83\8d\83O\83t\83@\83C\83\8b\96¼\r
+if(!defined("TREEFILE")) define("TREEFILE", 'tree.cgi');  //\83\8d\83O\83t\83@\83C\83\8b\96¼\r
+if(!defined("IMG_DIR")) define("IMG_DIR", 'src/');  //\89æ\91\9c\95Û\91\83f\83B\83\8c\83N\83g\83\8a\81Bfutaba.php\82©\82ç\8c©\82Ä\r
+if(!defined("THUMB_DIR")) define("THUMB_DIR",'thumb/');  //\83T\83\80\83l\83C\83\8b\95Û\91\83f\83B\83\8c\83N\83g\83\8a\r
+if(!defined("ARCH_DIR")) define("ARCH_DIR",'../arch/');    // Archive direcory\r
+if(!defined("TEMP_DIR")) define("TEMP_DIR", '../temp/');  //tmp directory\r
+if(!defined("TITLE")) define("TITLE", '\81u\8bL\8e\96\82ð\8cã\82Å\95Ò\8fW\8b@\94\\81v\95t\82«\89æ\91\9c\81\95\93®\89æ\81^\95\8e\9a\81\95\93®\89æ\8cf\8e¦\94Â');  //\83^\83C\83g\83\8b\81i<title>'.TITLE.'</title>\82ÆTOP\81j\r
+if(!defined("TITLECOM")) define("TITLECOM", '');  // <small>TITLECOM</small>\r
+if(!defined("SHOWTITLEIMG")) define("SHOWTITLEIMG", 0);   //show the title image (0=no 1=yes 2=rotating)\r
+if(!defined("SHOWTITLETXT")) define("SHOWTITLETXT", 1);   //(leave at 0)\r
+if(!defined("TITLEIMG")) define("TITLEIMG", 'logo.jpg');                       //Title image (point to php file if rotating)\r
+if(!defined("CHANNERU")) define("CHANNERU", '\8el\97t\82Ì\89è\81\9e\82¿\82á\82ñ\82Ë\82é');    // channeru name\r
+if(!defined("HOME")) define("HOME",  '../');   //\81u\83z\81[\83\80\81v\82Ö\82Ì\83\8a\83\93\83N\r
+if(!defined("MAX_KB")) define("MAX_KB", '9000');   //\93\8a\8de\97e\97Ê\90§\8cÀ KB\81iphp\82Ì\90Ý\92è\82É\82æ\82è2M\82Ü\82Å\r
+if(!defined("MAX_W")) define("MAX_W",  '240');   //\93\8a\8de\83T\83C\83Y\95\9d\81i\82±\82ê\88È\8fã\82Íwidth\82ð\8fk\8f¬\r
+if(!defined("MAX_H")) define("MAX_H",  '240');   //\93\8a\8de\83T\83C\83Y\8d\82\82³\r
+if(!defined("MAXR_W")) define("MAXR_W",  '240');   //\93\8a\8de\83T\83C\83Y\95\9d\81i\82±\82ê\88È\8fã\82Íwidth\82ð\8fk\8f¬\r
+if(!defined("MAXR_H")) define("MAXR_H",  '240');   //\93\8a\8de\83T\83C\83Y\8d\82\82³\r
+if(!defined("MIN_W")) define("MIN_W", 2);    //minimal width size\r
+if(!defined("MIN_H")) define("MIN_H", 2);    //minimal hieght size\r
+if(!defined("MAX_DIMENSION")) define("MAX_DIMENSION", 9000);    //maximum dementions\r
+if(!defined("PAGE_DEF")) define("PAGE_DEF", '16');   //\88ê\83y\81[\83W\82É\95\\8e¦\82·\82é\8bL\8e\96\r
+if(!defined("LOG_MAX")) define("LOG_MAX",  '4004');  //\83\8d\83O\8dÅ\91å\8ds\90\94\r
+//----\r
+//\8aÇ\97\9d\83p\83X\83t\83H\81[\83\80\82ð \8fo\82·:0 \8fo\82³\82È\82¢:1\r
+if(!defined("PASS_FSP")) define("PASS_FSP", 0);\r
+//\8aÇ\97\9d\8eÒ\83l\81[\83\80\83p\83X\r
+if(!defined("PASS_FM_PS")) define("PASS_FM_PS", 'mod');    //\8dí\8f\9c\90l\82Ì\96¼\91O\r
+if(!defined("PASS_FA_PS")) define("PASS_FA_PS", 'admin');    //\8aÇ\97\9d\90l\82Ì\96¼\91O\r
+if(!defined("NUKEPASS1")) define("NUKEPASS1", 'BOMBEM');  //1st nuke panel password\r
+if(!defined("NUKEPASS2")) define("NUKEPASS2", 'BOMBIT');    //2nd nuke panel password\r
+if(!defined("ADMIN_PASS")) define("ADMIN_PASS", 'admin_pass');  //\8aÇ\97\9d\8eÒ\83p\83X\r
+if(!defined("MOD_PASS")) define("MOD_PASS", 'mod_pass');         //\8dí\8f\9c\8eÒ\83p\83X\r
+if(!defined("MCAPCODE")) define("MCAPCODE", '</b></font>&nbsp;<font class="mod" color="#680f08">'.CHANNERU.'&nbsp;<u>##&nbsp;'.S_MODERATOR.'&nbsp;##</u>');\r
+if(!defined("M4CAPCODE")) define("M4CAPCODE", '<font class="mod" color="#680f08">'.S_MODERATOR.'</font>');\r
+//mod capcode  '.CHANNERU.'&nbsp;<u>##&nbsp;'.S_MODERATOR.'&nbsp;##</u></font>\r
+if(!defined("ACAPCODE")) define("ACAPCODE", '</b></font>&nbsp;<font class="admin" color="#0080ff">'.CHANNERU.'&nbsp;<u>##&nbsp;'.S_ADMINISTRATOR.'&nbsp;##</u>');\r
+if(!defined("A4CAPCODE")) define("A4CAPCODE", '<font class="admin" color="#0080ff">'.S_ADMINISTRATOR.'</font>');\r
+//admin capcode  '.CHANNERU.'&nbsp;<u>##&nbsp;'.S_ADMINISTRATOR.'&nbsp;##</u></font>\r
+//----\r
+if(!defined("PHP_SELF")) define("PHP_SELF", 'yotsubanome.php'); //\82±\82Ì\83X\83N     \83\8a\83v\83g\96¼\r
+if(!defined("PHP_SELF2")) define("PHP_SELF2", 'yotsuba.htm'); //\93ü\82è\8cû\83t\83@\83C\83\8b\96¼\r
+if(!defined("PHP_SELF3")) define("PHP_SELF3", 'index.php'); //\93ü\82è\8cû\83t\83@\83C\83\8b\96¼2\r
+if(!defined("IIII")) define("IIII", "<META HTTP-EQUIV=\"refresh\" content=\"0;URL=".PHP_SELF."\">"); //0.htm contents\r
+if(!defined("ENCODE")) define("ENCODE", "Shift_JIS");    //encodeing of pages\r
+if(!defined("FAVICON")) define("FAVICON", ICON_DIR."4leaf.png");    //icon of pages\r
+if(!defined("PHP_EXT")) define("PHP_EXT", '.htm');  //1\83y\81[\83W\88È\8d~\82Ì\8ag\92£\8eq\r
+if(!defined("PHP_EXT2")) define("PHP_EXT2", '.html');  //$time\8ag\92£\8eq\r
+if(!defined("RENZOKU")) define("RENZOKU", '4');   //\98A\91±\93\8a\8de\95b\90\94\r
+if(!defined("RENZOKU2")) define("RENZOKU2", '13');  //\89æ\91\9c\98A\91±\93\8a\8de\95b\90\94\r
+if(!defined("MAX_RES")) define("MAX_RES", '9000');  //\8b­\90§sage\83\8c\83X\90\94\r
+if(!defined("ARCHIVE")) define("ARCHIVE", 1);        //archive old threads? no:0 yes:1\r
+if(!defined("ARCH_FILE")) define("ARCH_FILE", $_SERVER['PHP_SELF']);    //board directory defined\r
+$archny = ARCH_FILE;\r
+$archny = str_replace("/",  "+", $archny);  // / \81¨ + for file system compatibility\r
+$archny = str_replace(PHP_SELF,  "", $archny);  //remove php file name\r
+if(!defined("ARCHFILE")) define("ARCHFILE", ARCH_DIR.$archny.'arch.log');    //archive log of the board directory\r
+\r
+//---------------------------- text board switch!!!!\r
+if(!defined("TEMPLATE")) define("TEMPLATE", 0);  //0 =Gazou BBS template 1 =textboard template This is a very important switch\r
+if(!defined("UP_IMG")) define("UP_IMG", 1);  //Use images yes:1 no i want a text board:0 This is a very important switch\r
+//---------------------------- seriously\r
+\r
+if(!defined("USE_THUMB")) define("USE_THUMB", 1);  //\83T\83\80\83l\83C\83\8b\82ð\8dì\82é \82·\82é:1 \82µ\82È\82¢:0\r
+if(!defined("GIF_ONLY")) define("GIF_ONLY", 0);                   // 0:not just gif files are allowed 1:only *.gif files are allowed\r
+if(!defined("PROXY_CHECK")) define("PROXY_CHECK", 0);  //proxy\82Ì\8f\91\8d\9e\82Ý\82ð\90§\8cÀ\82·\82é y:1 n:0\r
+if(!defined("DISP_ID")) define("DISP_ID", 0);  //ID\82ð\95\\8e¦\82·\82é \8b­\90§:2 \82·\82é:1 \82µ\82È\82¢:0\r
+if(!defined("IDSEED")) define("IDSEED", 'id\82Ì\8eí');  //id\82Ì\8eí\r
+if(!defined("LINK")) define("LINK", 0);    //Futaba channeru like advertisement? "\83\8a\83\93\83N:::" 0:no 1:yes\r
+if(!defined("WW")) define("WW", 80);    //wordwarp2 charater line <br /> number\r
+if(!defined("NO_TEXTONLY")) define("NO_TEXTONLY", 0);    //no text only?\r
+if(!defined("BR_")) define("BR_", 1);    // \n \81¨ <br /> n=0 y=1\r
+\r
+if(!BR_){\r
+if(!defined("BR_CHECK")) define("BR_CHECK", 16); }  //\89ü\8ds\82ð\97}\90§\82·\82é\8ds\90\94 \82µ\82È\82¢:0\r
+if(!defined("TRIPKEY")) define("TRIPKEY", '\81\9f');                  //key before tripcode\r
+if(!defined("TRIP_KEY")) define("TRIP_KEY", '\81\9e');                  //copied key before tripcode\r
+if(!defined("CSSFILE")) define("CSSFILE", CSS_DIR."yotsubanome.css");    //location of the css file [make blank if you want futaba look]\r
+\r
+if(!defined("PASS_CHECK")) define("PASS_CHECK", 0);                            // \8dí\8f\9c\83L\81[\82Ì\93ü\97Í\82ð\83`\83F\83b\83N\82·\82é  \82·\82é:1 \82µ\82È\82¢:0\r
+if(!defined("SUB_CHECK")) define("SUB_CHECK",  0);                             // \91è\96¼\8fÈ\97ª\8e\9e\8b\91\90â\82·\82é  \82·\82é:1 \82µ\82È\82¢:0\r
+if(!defined("NAME_CHECK")) define("NAME_CHECK", 0);                    // \96¼\91O\8fÈ\97ª\8e\9e\8b\91\90â\82·\82é  \82·\82é:1 \82µ\82È\82¢:0\r
+if(!defined("COM_CHECK")) define("COM_CHECK",  0);                             // \96{\95\8fÈ\97ª\8e\9e\8b\91\90â\82·\82é  \82·\82é:1 \82µ\82È\82¢:0\r
+// \82à\82µ\81A\97L\8cø\82É\82µ\82½\8fê\8d\87\81A\92\8d\88Ó\8f\91\82«\82ð\8f\91\82­\82±\82Æ\82ð\82¨\8a©\82ß\82µ\82Ü\82·\81B\r
+\r
+if(!defined("EN_AUTOLINK")) define("EN_AUTOLINK", 1);          // URL\8e©\93®\83\8a\83\93\83N\82ð\8ds\82¤  \82·\82é:1 \82µ\82È\82¢:0\r
+if(!defined("EN_SEC")) define("EN_SEC", 1);                                    // \8e\9e\8aÔ\95\\8e¦\82É\81u\95b\81v\82ð\8aÜ\82ß\82é  \8aÜ\82ß\82é:1 \8aÜ\82ß\82È\82¢:0\r
+if(!defined("EN_SAGE_START")) define("EN_SAGE_START", 1);                              // \83X\83\8c\8eå\8b­\90§sage\8b@\94\\82ð\8eg\97p\82·\82é  \82·\82é:1 \82µ\82È\82¢:0\r
+if(!defined("MAX_PASSED_HOUR")) define("MAX_PASSED_HOUR", 0);                  // \8b­\90§sage\82Ü\82Å\82Ì\8e\9e\8aÔ   0\82Å\8b­\90§sage\82È\82µ\r
+if(!defined("ADMIN_SAGE")) define("ADMIN_SAGE", 1);                            // \8aÇ\97\9d\8eÒ\8b­\90§sage\8f\88\97\9d  \82·\82é:1 \82µ\82È\82¢:0\r
+if(!defined("NOTICE_SAGE")) define("NOTICE_SAGE", 1);                          // \8b­\90§sage\82ð\8d\90\92m\82·\82é  \82·\82é:1 \82µ\82È\82¢:0\r
+\r
+if(!defined("MAX_LINES_SHOWN")) define("MAX_LINES_SHOWN", 24);\r
+if(!defined("DESC")) define("DESC", '4 leaf sprout channel');  //description of the pages\r
+if(!defined("KEYW")) define("KEYW", '4,leaf,sprout,channel,');  //keywords \r
+if(!defined("BACKGROUND_IMG")) define("BACKGROUND_IMG", '');         //what will that back ground image be\r
+\r
+if(!defined("SPOILERS")) define("SPOILERS", 1);                    // Spoilers\r
+if(!defined("SECURE")) define("SECURE", 0);    //Secure the nuke panel y=1 n=0\r
+if(!defined("CHANBAN")) define("CHANBAN", 0);    // banned from viewing index:1 or allowed to view but cannot post:0\r
+if(!defined("USER_WAS_BANNED_FOR_THIS_POST")) define("USER_WAS_BANNED_FOR_THIS_POST", '<b><font color="#ff0000">(USER WAS BANNED FOR THIS POST)</b></font>');    // the infamous (USER WAS BANNED FOR THIS POST) is customizable\r
+\r
+if(!defined("NOTPLEA")) define("NOTPLEA", 1);              //this is only for the banpleaboard. [DON'T MESS WITH IT]\r
+if(!defined("NOTREPORT")) define("NOTREPORT", 1);              //this is only for the reportboard. [DON'T MESS WITH IT]\r
+//---------------------------------------------antispam measures\r
+if(!defined("SECURITY")) define("SECURITY", 0);                      // Use captcha yes:1 no:0\r
+// \82Ê\82±\r
+// \93\8a\8de\83t\83H\81[\83\80\82ð\8fÁ\82· y=1 n=0\r
+if(!defined("FORM_HIDDEN")) define("FORM_HIDDEN", 0);\r
+// \83X\83p\83\80\91Î\8dô\r
+//--------------------------------------------- \83X\83p\83\80\91Î\8dô\r
+\r
+if(!defined("RE_")) define("RE_",  'Re\81F');                            // \83\8c\83X\82Ì\93ª\82É\95t\82¯\82é\95\8e\9a\97ñ\r
+if(!defined("RES_MARK")) define("RES_MARK",  '\81c');                            // \83\8c\83X\82Ì\93ª\82É\95t\82¯\82é\95\8e\9a\97ñ\r
+if(!defined("OMIT_RES")) define("OMIT_RES", 8);                        // \81u\83\8c\83X\8fÈ\97ª\81v\82ð\95\\8e¦\82·\82é\83\8c\83X\82Ì\90\94\r
+if(!defined("OMIT_RES_IMG")) define("OMIT_RES_IMG", 0);                        // \81u\83\8c\83X\8fÈ\97ª\81v\82ð\95\\8e¦\82·\82é\83\8c\83X\82Ì\90\94\81i\89æ\91\9c\95t\83\8c\83X\82Ì\8fê\8d\87\81j\r
+\r
+//\83\8c\83X\89æ\91\9c\93Y\95t\8b@\94\-------------------------------------------------------------\r
+if(!defined("RESIMG")) define("RESIMG", 1);                            // \83\8c\83X\82É\82à\89æ\91\9c\82ð\93Y\95t\82Å\82«\82é\82æ\82¤\82É\82·\82é  \93Y\95t\89Â\94\:1 \93Y\95t\95s\89Â:0\r
+if(!defined("RES_IMG")) define("RES_IMG", RESIMG);\r
+if(!defined("RES_IMG_LIMIT")) define("RES_IMG_LIMIT", 0);              // \83\8c\83X\89æ\91\9c\8fã\8cÀ\96\87\90\94\r
+if(!defined("RES_IMG_LIMIT_NOTICE")) define("RES_IMG_LIMIT_NOTICE", 1);                // \83\8c\83X\89æ\91\9c\8ec\82è\8d\90\92m\82·\82é  \82·\82é:1  \82µ\82È\82¢:0\r
+\r
+if(!defined("BANFILE1")) define("BANFILE1", BANS_DIR.'ipbans.php');   //ip banish\r
+if(!defined("BANFILE2")) define("BANFILE2", BANS_DIR.'spam.php');    //spam decioso\r
+if(!defined("BANFILE3")) define("BANFILE3", BANS_DIR.'filebans.php'); //bad files\r
+if(!defined("BANFILE4")) define("BANFILE4", 'bans.php');              //ip banish\r
+if(NOTPLEA==0){\r
+$banfile4 = './'.BANFILE4;\r
+}\r
+if(NOTPLEA==1){\r
+if(file_exists(BANS_DIR)){\r
+$banfile4 = BANS_DIR.BANFILE4;\r
+  }else{\r
+$banfile4 = HOME.BANFILE4;\r
+    }\r
+}\r
+\r
+if(!defined("HEADERFILE")) define("HEADERFILE", HOME.'HEADER.php');      //This is where the header lives.\r
+if(!defined("RULESFILE")) define("RULESFILE", HOME.'RULE.php');          //Location of the rules of this board.\r
+if(!defined("NEWSFILE")) define("NEWSFILE", HOME.'NEWS.php');             //Location of the news of the board.\r
+if(!defined("FOOTERFILE")) define("FOOTERFILE", HOME.'footer.php');          //This is where the footer lives.\r
+\r
+if(!defined("CAPTCHAFILE")) define("CAPTCHAFILE", PHP_DIRECTORY.'captcha.php');    //Location of the captcha of the board.\r
+if(!defined("WFFILE")) define("WFFILE", 'wf.cgi');          //This is where the wordfilter log lives.\r
+if(!file_exists(FILTER_DIR)){\r
+$wfwf = HOME.WFFILE;\r
+  }else{\r
+$wfwf = FILTER_DIR.WFFILE;\r
+}\r
+\r
+//default board colors\r
+// \83J\83\89\81[\83\8a\83\93\83O by \96G\82¦\98A ------------------------------------------------------\r
+if(!defined("BG_COL")) define("BG_COL",   '#FFFFEE');  // \94w\8ci\90F\r
+if(!defined("TXT_COL")) define("TXT_COL",  '#800000');  // \95\8e\9a\90F\r
+if(!defined("LINK_COL")) define("LINK_COL", '#0000EE');  // \83\8a\83\93\83N\90F\r
+if(!defined("VLINK_COL")) define("VLINK_COL",'#0000EE');  // \96K\96â\8dÏ\82Ý\83\8a\83\93\83N\90F\r
+if(!defined("ALINK_COL")) define("ALINK_COL",'#00DC00');  // \91I\91ð\82µ\82½\8e\9e\82Ì\90F\r
+if(!defined("TIT_COL")) define("TIT_COL",  '#800000');  // \8cf\8e¦\94Â\83^\83C\83g\83\8b\83J\83\89\81[\r
+if(!defined("TIT_COL")) define("TIT_COL",  '#800000');  // \8cf\8e¦\94Â\83^\83C\83g\83\8b\83J\83\89\81[\r
+if(!defined("BASE_COL")) define("BASE_COL", '#eeaa88');  // \83x\81[\83X\83J\83\89\81[\r
+\r
+// ----- \83\8c\83X\8bL\8e\96\8aÖ\8cW ----- //\r
+if(!defined("RE_COL")) define("RE_COL",   '#789922');  //\81\84\82ª\95t\82¢\82½\8e\9e\82Ì\90F\r
+if(!defined("RE_COL2")) define("RE_COL2",   '#696969');  //#\82ª\95t\82¢\82½\8e\9e\82Ì\90F\r
+if(!defined("RE_BGCOL")) define("RE_BGCOL", '#f0e0d6');  // \94w\8ci\83J\83\89\81[\r
+if(!defined("SUB_COL")) define("SUB_COL",  '#cc1105');  // \83^\83C\83g\83\8b\83J\83\89\81[\r
+if(!defined("NAME_COL")) define("NAME_COL", '#117743');  // \96¼\91O\83J\83\89\81[\r
+if(!defined("LONG_COL")) define("LONG_COL", '#b4b4b0');  // too long colors\r
+\r
+// ---- text board colors ---- //\r
+if(!defined("OP_BGCOL")) define("OP_BGCOL", '#efefef');  //text board thread colors\r
+if(!defined("BOX_BGCOL")) define("BOX_BGCOL",'#ccffcc');  //textboard header and footer colors\r
+\r
+// ---- host exploit color ---- //\r
+if(!defined("HOST_COL")) define("HOST_COL",'#f60000');\r
+if(!defined("IP_COL")) define("IP_COL",'#f60000');\r
+\r
+// ---- other colors ----//\r
+if(!defined("ROW1_COL")) define("ROW1_COL", '#d6d6f6');  // row1 colors\r
+if(!defined("ROW2_COL")) define("ROW2_COL", '#f6f6f6');  //row2 colors\r
+if(!defined("TOMATO_COL")) define("TOMATO_COL", '#FF0000');  //tomato color\r
+if(!defined("TTOPBOX_COL")) define("TTOPBOX_COL", '#80B0F6');  //Thread list top color\r
+if(!defined("TROW1_COL")) define("TROW1_COL", '#D6D00F');  // row1 colors\r
+if(!defined("TROW2_COL")) define("TROW2_COL", '#F6F60F');  //row2 colors\r
+//--------------------------------------------------------------------------------------------\r
+if(!defined("TL")) define("TL", 1);    //Thread Lists? speed? n=0 y=1\r
+if(!defined("FUTABA_S")) define("FUTABA_S", 0);    //futaba speed? n=0 y=1 [this will disable alot of functions]\r
+if(!FUTABA_S){\r
+//\95\89\89×\8cy\8c¸html\8co\97R\8aÖ\8cW---------------------------------------------------------\r
+if(!defined("RES_FILE")) define("RES_FILE", 1);                        // \83\8c\83X\82ðhtml\8co\97R\82É\82·\82é  \82·\82é:1 \82µ\82È\82¢:0\r
+if(!defined("RES_DIR")) define("RES_DIR", './');                       // \83\8c\83Xhtml\8ai\94[\83f\83B\83\8c\83N\83g\83\8a\r
+//Do not change RES_DIR //major glitches will appear\r
+}else{\r
+if(!defined("RES_FILE")) define("RES_FILE", 0);\r
+if(!defined("RES_DIR")) define("RES_DIR", './');                       // \83\8c\83Xhtml\8ai\94[\83f\83B\83\8c\83N\83g\83\8a\r
+//Do not change RES_DIR //major glitches will appear\r
+}\r
+// \83c\81[\83\8b\94ð\82¯html\8co\97R\8aÖ\8cW-------------------------------------------------------\r
+if(!defined("IMG_REFER")) define("IMG_REFER", 1);                 // \83c\81[\83\8b\94ð\82¯\82É\89æ\91\9c\83\8a\83\93\83N\82ðhtml\8co\97R\82É\82·\82é  \82·\82é:1  \82µ\82È\82¢:0\r
+if(!defined("IMG_REF_DIR")) define("IMG_REF_DIR", 'ref/');                 // \8co\97R\90æhtml\8ai\94[\83f\83B\83\8c\83N\83g\83\8a\r
+\r
+if(!defined("LIGHTBOX")) define("LIGHTBOX", 1);    //lightbox?   n=0 y=1\r
+if(!LIGHTBOX){\r
+$bbte = "target=_blank";\r
+  }else{\r
+$bbte = "rel=lightbox";\r
+  }\r
+if(!defined("NOTJUST_IMG")) define("NOTJUST_IMG", 1);    //Upload besides image based files  n=0 y=1\r
+if(NOTJUST_IMG || !1){\r
+$allowext=array('acc','asf','avi','bmp','bz2','c','css','gif','gz','htm','html','flv','flac','ico','it','jpg','lzh','mid','mo3','mod','mov','mp1','mp2','mp3','mp4','mpc','mpg','nsf','ogg','pdf','phps','png','psd','ram','rar','rm','s3m','spc','sid','svg','swf','text','txt','TXT','tmp','temp','torrent','wav','wma','wm','xm','zip','7z');\r
+    }else{\r
+$allowext="";\r
+  }\r
+//**************************************************************************\r
+if(!defined("GCHAN_VIDEO")) define("GCHAN_VIDEO", 1);    //video url support  n=0 y=1*\r
+//**************************************************************************\r
+\r
+if(!defined("ENABLE_EXIF")) define("ENABLE_EXIF", 0);\r
+if(!defined("OPTION")) define("OPTION", 1);    //enable options on form()\r
+//--------------------------------------------------------------------------------------------\r
+\r
+//\83X\83\8c\88ê\97\97\95\\8e¦\90\94\81in=0 y=\83X\83\8c\83b\83h\96{\90\94\81j\r
+//LIMIT\82Ì\90\94\92l\82ª\89º\82Ì\8fê\8d\87\81ALIMIT\82Ì\90\94\92l\82Å\83J\83b\83g\82³\82ê\82Ü\82·\81B(LIMIT\97D\90æ)\r
+//LIMIT\82Ì\90\94\92l\82ª 0 \82Ì\8fê\8d\87\81ATHREAD_IHIRAN\82Ì\90\94\92l\82Å\83J\83b\83g\82³\82ê\82Ü\82·\81B\r
+if(!defined("THREAD_IHIRAN")) define("THREAD_IHIRAN", 40);\r
+\r
+//\83X\83\8c\88ê\97\97\95\\8e¦\8fð\8c\8f\r
+// 0: \91è\96¼\82ª\83f\83t\83H\83\8b\83g\82È\82ç\93à\97e\82ð\88ø\97p\81i\91S\83y\81[\83W\83A\83\93\83J\81[\83\8a\83\93\83N\82 \82è\81j\r
+// 1: 1\88È\8fã\82ÍTOP\83y\81[\83W\88È\8aO\83y\81[\83W\83A\83\93\83J\81[\83\8a\83\93\83N\96³\82µ\81i\83X\83\8c\82Ì\8f¸\8d~\82ª\8c\83\82µ\82¢\82Æ\96³\88Ó\96¡\82Ì\88×\81j\r
+// 2: \8b­\90§\93I\82É\93à\97e\82ð\88ø\97p / 3: \8b­\90§\93I\82É\91è\96¼\82ð\88ø\97p\r
+if(!defined("SUB_IHIRAN")) define("SUB_IHIRAN", 0);\r
+\r
+//\8fÈ\97ª\83y\81[\83W\90\94: 5\83X\83\8c10\83y\81[\83W\82È\82ç5x10=50\81B0\83y\81[\83W\95ª\82Ì5\83X\83\8c\82ð\91«\82µ55\82Æ\82·\82é\r
+//       \81¨         LIMIT(55) = (PAGE_DEF:5 * \83y\81[\83W\90\94:10) + PAGE_DEF:5\r
+//\91S\8c\8f\95\\8e¦\82Ì\8fê\8d\87\82ÍLOG_MAX\82Ì\90Ý\92è\82Æ\93¯\82\82É\82µ\82Ä\82¨\82¯\82Î\97Ç\82¢\r
+//0=\89º\82Ì\83y\81[\83W\8cJ\82è\89z\82µ\83e\81[\83u\83\8b\93P\8b\8e (MAX_THREAD\82ð\95K\82¸\8ew\92è\82µ\82Ä\89º\82³\82¢)\r
+if(!defined("LIMIT")) define("LIMIT", 9000);\r
+\r
+//\93\8a\8de\8f\87\82É\83\\81[\83g\8cÅ\92è \82·\82é:1 \82µ\82È\82¢:0\r
+if(!defined("NATURAL_SORT")) define("NATURAL_SORT", 0);\r
+//threads are displayed in numeracle order and not according to the tree line  n=0 y=1\r
+\r
+// \83A\83j\83\81\81[\83V\83\87\83\93\82f\82h\82e\90Ý\92è-----------------------------------------------------\r
+// \83T\83\80\83l\83C\83\8b\82ð\8eg\97p\82µ\82È\82¢\8fê\8d\87\81AGIF\82ð\82»\82Ì\82Ü\82Ü\95\\8e¦\82·\82é\82½\82ß\81A\83A\83j\83\81\81[\83V\83\87\83\93GIF\82ª\93®\82«\82Ü\82·\81B\r
+if(!defined("USE_GIF_THUMB")) define("USE_GIF_THUMB", 0);                              // GIF\95\\8e¦\82É\83T\83\80\83l\83C\83\8b\82ð\8eg\97p\82·\82é  \82·\82é:1 \82µ\82È\82¢:0\r
+if(!defined("CHECK_ANI")) define("CHECK_ANI", 1);                                      // \83A\83j\83\81\81[\83V\83\87\83\93GIF\82©\82Ç\82¤\82©\83`\83F\83b\83N\82·\82é  \82·\82é:1 \82µ\82È\82¢:0\r
+if(!defined("USE_PNG_THUMB")) define("USE_PNG_THUMB", 0);                              // PNG\95\\8e¦\82É\83T\83\80\83l\83C\83\8b\82ð\8eg\97p\82·\82é  \82·\82é:1 \82µ\82È\82¢:0\r
+// \8d\90\92m\82Í\82µ\82Ü\82¹\82ñ.\97 \82Å\83R\83\\81[\83\8a\82Æ\8eæ\93¾\82¾\82¯\82µ\82Ü\82·.\r
+\r
+// hiro \92Ç\89Á 2005.03.17\r
+// \83T\83\80\83l\83C\83\8b\8dì\90¬\8b@\94\\91I\91ð------------------------------------------------------\r
+if(!defined("QUALITY_THUMB")) define("QUALITY_THUMB", 100);                    // \83T\83\80\83l\83C\83\8b\82Ì\95i\8e¿ 0\81`100 \82Ü\82Å\90Ý\92è\89Â\94\  default:75\r
+if(!defined("SELECT_THUMB")) define("SELECT_THUMB", 0);                                // \83T\83\80\83l\83C\83\8b\8dì\90¬  GD\94Å:0 repng2jpeg\94Å:1\r
+// hiro \92Ç\89Á \82±\82±\82Ü\82Å\r
+\r
+// \83_\83E\83\93\83\8d\81[\83h\83J\83E\83\93\83^ (\83c\81[\83\8b\94ð\82¯\82É\8añ\90¶)--------------------------------------dlcount\r
+// \93\8a\95[\83t\83H\81[\83\80\82Í\83\81\81[\83\8b\97\93\82É vote \82Æ\8f\91\82­\82±\82Æ\82Å\8en\93®\82µ\82Ü\82·\81B\r
+// \90e\82É\98A\93®\82µ\82Ä\89æ\91\9c\83\8c\83X\82É\82à\93\8a\95[\83t\83H\81[\83\80\82ª\82Å\82Ü\82·\81B\r
+// \93\8a\95[\82Í\83\8d\81[\83J\83\8b\82Ì\95\89\92S\82ð\94z\97\82µPHP\82É\82Ä\8f\91\82«\8fo\82µ\82Æ\82È\82è\81A\8dX\90V\8cã\82É\94½\89f\82Æ\82È\82è\82Ü\82·\81B\r
+if(!defined("DC_REFER")) define("DC_REFER", 2);                                        // \83_\83E\83\93\83\8d\81[\83h\83J\83E\83\93\83^\82ð  \95t\82¯\82é:1 \95t\82¯\82È\82¢:0 \8dX\82É\93\8a\95[\82ð\95t\82¯\82é:2\r
+\r
+// \89º\8bL\83t\83H\83\8b\83_\96¼\82Í dlreg.php, dlvote.php, dljs.php \82Æ\93\9d\88ê\90Ý\92è\82Æ\82·\82é\81B\r
+if(!defined("DC_CUN")) define("DC_CUN", PHP_DIRECTORY.'count/');                                       // \83_\83E\83\93\83\8d\81[\83h\83J\83E\83\93\83^\8bL\98^\97p\83t\83H\83\8b\83_\96¼\r
+if(!defined("DC_CAC")) define("DC_CAC", PHP_DIRECTORY.'cache/');                                       // \83_\83E\83\93\83\8d\81[\83h\83J\83E\83\93\83^\88ê\8e\9e\83L\83\83\83b\83V\83\85\97p\83t\83H\83\8b\83_\96¼\r
+\r
+// \83T\83\80\83l\83C\83\8b\8aÇ\97\9d\8eÒ\8d·\8a·\82¦\8b@\94\--------------------------------------------------\r
+// \8d·\82µ\91Ö\82¦\83T\83\80\83l(1)[replace_n.jpg]\97L\82Å\8d·\8a·\82¦\97L\8cø\81A\96³\82µ\82Å\96³\8cø\r
+if(!defined("REPLACE_EXT")) define("REPLACE_EXT", '.replaced');                // \8d·\82µ\91Ö\82¦\82Ì\8dÛ\81A\8c³\81X\82Ì\83T\83\80\83l\83C\83\8b\83t\83@\83C\83\8b\82Ì\82¨\90K\82É\95t\82¯\82é\95\8e\9a\r
+if(!defined("NOTICE_THUMB")) define("NOTICE_THUMB", 1);                                // \83T\83\80\83l\8d·\82µ\91Ö\82¦\82ð\8d\90\92m\82·\82é  \82·\82é:1 \82µ\82È\82¢:0\r
+\r
+// \8d\80\96Ú\82ð\91\9d\82â\82·\8fê\8d\87\82Í\92è\90\94\90é\8c¾\82µ\82½\83t\83@\83C\83\8b\96¼\81A\83^\83C\83g\83\8b\82ð$rep_thumb\94z\97ñ\82É\92Ç\89Á\82µ\82Ü\82·\81B\r
+// \82à\82¿\82ë\82ñ\92è\90\94\90é\8c¾\82µ\82È\82¢\82Å\92¼\90Ú\94z\97ñ\82É\92Ç\89Á\82µ\82Ä\82àOK\r
+if(!defined("R_THUM1")) define("R_THUM1", ICON_DIR.'replace_n.jpg');           // \8d·\82µ\91Ö\82¦\83T\83\80\83l(1) \83t\83@\83C\83\8b\96¼\r
+if(!defined("R_TITL1")) define("R_TITL1", '\82Ó\82Â\82¤');                   // \8d·\82µ\91Ö\82¦\83T\83\80\83l(1) \83^\83C\83g\83\8b\r
+if(!defined("R_THUM2")) define("R_THUM2", ICON_DIR.'replace_g.jpg');           // \8d·\82µ\91Ö\82¦\83T\83\80\83l(2) \83t\83@\83C\83\8b\96¼\r
+if(!defined("R_TITL2")) define("R_TITL2", '\82®\82ë');                             // \8d·\82µ\91Ö\82¦\83T\83\80\83l(2) \83^\83C\83g\83\8b\r
+if(!defined("R_THUM3")) define("R_THUM3", ICON_DIR.'replace_l.jpg');           // \8d·\82µ\91Ö\82¦\83T\83\80\83l(3) \83t\83@\83C\83\8b\96¼\r
+if(!defined("R_TITL3")) define("R_TITL3", '\82ë\82è');                             // \8d·\82µ\91Ö\82¦\83T\83\80\83l(3) \83^\83C\83g\83\8b\r
+if(!defined("R_THUM4")) define("R_THUM4", ICON_DIR.'replace_3.jpg');           // \8d·\82µ\91Ö\82¦\83T\83\80\83l(4) \83t\83@\83C\83\8b\96¼\r
+if(!defined("R_TITL4")) define("R_TITL4", '\82³\82ñ\82¶');                   // \8d·\82µ\91Ö\82¦\83T\83\80\83l(4) \83^\83C\83g\83\8b\r
+\r
+$rep_thumb = array(R_TITL1=>R_THUM1,R_TITL2=>R_THUM2,R_TITL3=>R_THUM3,R_TITL4=>R_THUM4);\r
+$default_thumb = R_THUM1;                              // \83f\83t\83H\83\8b\83g\82Ì\83T\83\80\83l\83t\83@\83C\83\8b\96¼\r
+\r
+// hage \92Ç\89Á 2004.8.1\r
+// \90Ô\8e\9a\95\\8e¦\8b@\94\\92Ç\89Á-----------------------------------------------------------\r
+if(!file_exists(DATA_DIR)){$data_dir = HOME;}else{$data_dir = DATA_DIR;}\r
+if(!defined("HOSTFILE")) define("HOSTFILE", $data_dir.'host.lst');            // \8eN\82µ\83z\83X\83g\82Ì\8bL\98^\83t\83@\83C\83\8b\r
+if(!defined("IDHOSTFILE")) define("IDHOSTFILE", $data_dir.'idhost.lst');        // \8eN\82µID\82Ì\8bL\98^\83t\83@\83C\83\8b\r
+// hage \92Ç\89Á\82±\82±\82Ü\82Å\r
+\r
+// hiro \92Ç\89Á 2005.03.24\r
+// \83X\83\8c\83b\83h\83X\83g\83b\83p\81[\8b@\94\-----------------------------------------------------\r
+if(!defined("THREAD_STOP")) define("THREAD_STOP", 1);                          // \83X\83\8c\83b\83h\83X\83g\83b\83p\81[\8b@\94\\82ð\8eg\97p\82·\82é  \82·\82é:1 \82µ\82È\82¢:0\r
+if(!defined("NOTICE_STOP")) define("NOTICE_STOP", 1);                  // \83X\83\8c\83X\83g\82ð\8d\90\92m\82·\82é  \82·\82é:1 \82µ\82È\82¢:0\r
+// hiro \92Ç\89Á \82±\82±\82Ü\82Å\r
+\r
+// hiro \92Ç\89Á 2005.03.18\r
+// \82 \82©\81`\82­\82È\82é\82È\81`\82é\81B\83o\83\8c\82é\82Æ\83s\83\93\83`\81I\81I\81i\82Å\82à\82È\82©\82Á\82½\82è\81d\r
+// \81u'tomato' => '\8aÇ\97\9d\90l'\81v\82Æ\82È\82Á\82Ä\82¢\82é\82È\82ç\82Î\83\81\83\8b\97\93\82É\81utomato\81v\82Æ\8f\91\82­\82±\82Æ\82Å\90Ô\82­\82È\82è\82Ü\82·\r
+// \90³\8bK\95\\8c»\82Í\8eg\97p\82µ\82Ä\82¢\82È\82¢\82Ì\82Å\81A\8a®\91S\83}\83b\83`\82Å\82·\81B\82È\82Ì\82Å\81A\97]\8cv\82È\82à\82Ì\82Í\8f\91\82©\82È\82¢\82±\82Æ\81I\r
+// \95Ï\8dX\82Ì\97]\92n\82 \82è\82Ü\82­\82è\82È\8ed\97l\82Å\82·\81B\82½\82¾\82Ì\82¨\97V\82Ñ\82¾\82Æ\8ev\82¢\82Ë\82¥\81B\r
+// \82±\82Ì\8b@\94\\82É\8aÖ\82·\82é\82²\97v\96]\93\99\8cä\8dÀ\82¢\82Ü\82µ\82½\82ç\81A\8cf\8e¦\94Â\82É\82¨\8aè\82¢\82µ\82Ü\82·\81B\r
+if(!defined("JOY_TOMATO")) define("JOY_TOMATO", 1);                            // \90Ô\8e\9a\8b@\94\  \8eg\82í\82È\82¢:0 \8eg\82¤:1\r
+$tomato = array('tomato' => '\8aÇ\97\9d\90l', 'tomato2' => '\8dí\8f\9c\90l', 'tomato3' => '\92Ê\8ds\90l\81H', 'tomato4' => '\8el\97t\82Ì\89è\90l');\r
+// hiro \92Ç\89Á \82±\82±\82Ü\82Å\r
+\r
+if(!defined("FACE_TAG")) define("FACE_TAG", 1);    //\83t\83F\83C\83X\83^\83O\83V\83X\83e\83\80\82ð\8eg\82¤  Yes:1 No:0\r
+  if(FACE_TAG){\r
+//\83t\83F\83C\83X\83}\81[\83N---------------------------------------------------    --gchan\r
+if(!defined("FACE_1")) define("FACE_1", '\81y\83j\83R\81z');           //(^^)\r
+if(!defined("FACE_2")) define("FACE_2", '\81y\83j\83R\83j\83R\81z');       //(^_^)\r
+if(!defined("FACE_3")) define("FACE_3", '\81y\83V\83\87\83b\83N\81z');       //(*_*)\r
+if(!defined("FACE_4")) define("FACE_4", '\81y\83A\83n\83n\81z');         //(^o^)\r
+if(!defined("FACE_5")) define("FACE_5", '\81y\8a¾\81z');             //(^_^;)\r
+if(!defined("FACE_6")) define("FACE_6", '\81y\83E\83C\83\93\83N\81z');       //(^_-)\r
+if(!defined("FACE_7")) define("FACE_7", '\81y\8b\83\82«\81z');           //(/_;)\r
+if(!defined("FONT_0")) define("FONT_0", '\81y\90F\95Â\82\81z');         //\90F\95Â\82\83^\83O\r
+if(!defined("FONT_1")) define("FONT_1", '\81y\90Ô\81z');             //\90Ô\r
+if(!defined("FONT_2")) define("FONT_2", '\81y\90Â\81z');             //\90Â\r
+if(!defined("FONT_3")) define("FONT_3", '\81y\97Î\81z');             //\97Î\r
+if(!defined("FONT_4")) define("FONT_4", '\81y\89©\81z');             //\89©\r
+if(!defined("FONT_5")) define("FONT_5", '\81y\91¾\81z');             //\91¾\r
+if(!defined("FONT_6")) define("FONT_6", '\81y\91¾\95Â\82\81z');         //\91¾\95Â\82\83^\83O\r
+if(!defined("FONT_7")) define("FONT_7", '\81y\8f¬\81z');             //\8f¬\r
+if(!defined("FONT_8")) define("FONT_8", '\81y\8f¬\95Â\82\81z');         //\8f¬\95Â\82\83^\83O\r
+if(!defined("FONT_9")) define("FONT_9", '\81y\8fÁ\81z');             //\8fÁ\r
+if(!defined("FONT_10")) define("FONT_10", '\81y\8fÁ\95Â\82\81z');               //\8fÁ\95Â\82\83^\83O\r
+}\r
+// \8d\95\97³ \92Ç\89Á\r
+// \8bL\8e\96\95Ò\8fW\8b@\94\ -----------------------------------------------------\r
+if(!defined("CH_IMG_DEL")) define("CH_IMG_DEL", 1);   //\95Ò\8fW\82Å\82Ì\89æ\91\9c\8d·\82µ\91Ö\82¦\8e\9e\82É\8c³\82Ì\89æ\91\9c\82ð \8fÁ\82·:1 \8ec\82·:0\r
+if(!defined("LOG_DEF")) define("LOG_DEF", 400);         //\8aÇ\97\9d\89æ\96Ê\82Å\95\\8e¦\82·\82é\83\8d\83O\82Ì\90\94\81B\r
+// \93ú\8bL\95\97\90Ý\92è--------------------------------------------------------------------\r
+if(!defined("FORM_IND")) define("FORM_IND", '1');                                      // \83t\83H\81[\83\80\82Ì\95\\8e¦\90Ý\92è\81B0:\8aÇ\97\9d\83\82\81[\83h\82Ì\82Ý\95\\8e¦\81A1:\8fí\82É\95\\8e¦\81B\r
+if(!defined("FORM_PSTN")) define("FORM_PSTN", '0');                                    //\83t\83H\81[\83\80\82Ì\95\\8e¦\88Ê\92u\81B0:\8fã\95\94\81A1:\89º\95\94\81A2:\8fã\89º\97¼\95û\81B\r
+if(!defined("TITLE_LIST")) define("TITLE_LIST", '1');                                  //\8bL\8e\96\88ê\97\97\81B1:\95\\8e¦ 0:\94ñ\95\\8e¦\81B\r
+if(!defined("TOP_INFO")) define("TOP_INFO", '');                               // \83y\81[\83W\8fã\82Ì\82Ù\82¤\82Ö\91}\93ü\81B\r
+if(!defined("INFO")) define("INFO", 'yotsubanome.php '.$ver);                  // \83t\83H\81[\83\80\82Ì\8fã\82É\89½\82©\8f\91\82«\8d\9e\82Þ\81B\r
+//\8d\95\97³ \92Ç\89Á \82±\82±\82Ü\82Å\r
+\r
+  // Catalog/List mode\r
+//\8aî\96{\90Ý\92è\r
+if(!defined("CATLIMIT")) define("CATLIMIT", 80);               //\83X\83\8c\96{\90\94\r
+if(!defined("REGZCUN")) define("REGZCUN", 8);             //\83J\83^\83\8d\83O\83\82\81[\83h\8e\9e\82Ì\89æ\91\9c\8ds\90\94\r
+if(!defined("MESSAGE")) define("MESSAGE", 1);              //\96{\95\82ð\91}\93ü (n=0 y=1)\r
+if(!defined("SYNTHETIC_COUNT")) define("SYNTHETIC_COUNT", 1);      //\89º\95\94\82É\83J\83E\83\93\83g\82ð\8fo\82· (n=0 y=1)\r
+//\83T\83\80\83l\83C\83\8b\90Ý\92è\r
+if(!defined("THUMBDIR")) define("THUMBDIR", /*THUMB_DIR.*/'thumbs/');    //\83T\83\80\83l\83C\83\8b\82ð\95Û\91\82·\82é\83t\83H\83\8b\83_\r
+if(!defined("IMG_W")) define("IMG_W", 84);              //\8fo\97Í\82·\82é\89æ\91\9c\81i\83T\83\80\83l\83C\83\8b\81j\82Ì\95\9d\r
+if(!defined("IMG_H")) define("IMG_H", 84);              //\8fo\97Í\82·\82é\89æ\91\9c\81i\83T\83\80\83l\83C\83\8b\81j\82Ì\8d\82\82³\r
+if(!defined("S_IMG_JPG")) define("S_IMG_JPG" , 80);         //\83T\83\80\83l\83C\83\8bJPG\82Ì\88³\8fk\97¦\r
+\r
+//\8aî\96{\90Ý\92è\r
+//\96¼\96³\82µ\90Ý\92è\81i\83t\83H\83\8d\81[\97p\81j\r
+if(!defined("Z_NAME"))define("Z_NAME", "\96¼\96³\82µ");\r
+//\96³\91è\90Ý\92è\81i\83t\83H\83\8d\81[\97p\81j\r
+if(!defined("Z_SUB"))define("Z_SUB", "\96³\91è");\r
+\r
+//\83\8c\83X\82Ì\8c\8f\90\94\r
+if(!defined("RE_CR")) define("RE_CR", 8);\r
+//\83J\83^\83\8d\83O\83\82\81[\83h\82É 0:\82·\82é 1:\82µ\82È\82¢\r
+if(!defined("CATALOG")) define("CATALOG", 1);\r
+//\83J\83^\83\8d\83O\83\82\81[\83h\83\8c\83X\82Ì\83R\83\81\83\93\83g\r
+if(!defined("CATCOM")) define("CATCOM", 8);\r
+//\83\8c\83X\82É\89æ\91\9c\82ð 1:\95t\82¯\82é 0:\95t\82¯\82È\82¢ 2:\89æ\91\9c\82Ì\82Ý\r
+if(!defined("RES_GZO")) define("RES_GZO", 1);\r
+\r
+//\8bL\8e\96\88ê\97\97\96{\91Ì\95\\8e¦\83X\83\8c\96{\90\94\97p\r
+//\81«\8fÈ\97ª\83y\81[\83W\90\94:\95\\8e¦\82·\82é\83X\83\8c\96{\90\94(TR_LIMIT & OYA_TR_LIMIT)\r
+//5\83X\83\8c10\83y\81[\83W\95ª\82È\82ç5x10=50\81B0\83y\81[\83W\95ª\82Ì5\83X\83\8c\82ð\91«\82µ55\81B\r
+if(!defined("TR_LIMIT")) define("TR_LIMIT", 24);\r
+//\83X\83\8c\83b\83h\88ê\97\97\95\\8e¦\83X\83\8c\96{\90\94\97p\r
+if(!defined("IHI_TR_LIMIT")) define("IHI_TR_LIMIT", 40);\r
+//\83X\83\8c\83b\83h\88ê\97\97 1:\95\\8e¦\82·\82é 0:\95\\8e¦\82µ\82È\82¢\r
+if(!defined("TURE_IHI")) define("TURE_IHI", 1);\r
+//\96¼\91O\82Æ\83^\83C\83g\83\8b\82ð 1:\8fo\82· 0:\8fo\82³\82È\82¢\r
+if(!defined("TXT_NOT")) define("TXT_NOT", 1);\r
+\r
+//\90V\92\85\88ê\97\97\96{\91Ì\8bL\8e\96\82ÉNEW\83}\81[\83N\82ð\95t\82¯\82é\8e\9e\8aÔ\r
+if(!defined("NEW_TIME")) define("NEW_TIME", 48);\r
+//\90V\92\85\r
+if(!defined("NEWMARK")) define("NEWMARK", '<font color="#ff3300"><i>NEW!</i></font>');\r
+//\90V\92\85\8e\9e\8aÔ\82Ì\94¼\95ª\88È\8d~\r
+if(!defined("NEWMARK2")) define("NEWMARK2", '<font color="#ff8000"><i>new!</i></font>');\r
+//\90V\92\85\83X\83\8c\83b\83h\88ê\97\97\8bL\8e\96\82ÉNEW\83}\81[\83N\82ð\95t\82¯\82é\8e\9e\8aÔ\r
+if(!defined("IHI_NEW_TIME")) define("IHI_NEW_TIME", 24);\r
+//\90V\92\85\r
+if(!defined("IHI_NEWMARK")) define("IHI_NEWMARK", '<font color="#ff3300"><b>!</b></font>');\r
+//\90V\92\85\8e\9e\8aÔ\82Ì\94¼\95ª\88È\8d~\r
+if(!defined("IHI_NEWMARK2")) define("IHI_NEWMARK2", '<font color="#ff8000">!</font>');\r
+\r
+  /* \83J\83\89\81[\90Ý\92è */\r
+//\83{\83f\83B\83J\83\89\81[\r
+if(!defined("COL_BODY")) define("COL_BODY", '<body bgcolor="#FFFFEE" text="#800000" link="#0000EE" vlink="#0000EE" alink="#0000EE">');\r
+//\8bL\8e\96\83e\81[\83u\83\8b\90F\r
+if(!defined("COL100")) define("COL100", '#F0E0D6');\r
+//\90e\89æ\91\9c\83e\81[\83u\83\8b\90F\r
+if(!defined("COL101")) define("COL101", '#eeaa88');\r
+//\83L\83\83\83b\83`\83t\83H\83\93\83g\90F\r
+if(!defined("COL102")) define("COL102", '#000000');\r
+//\83X\83^\83C\83\8b\83V\81[\83g\83e\81[\83u\83\8b\98g\90F\r
+if(!defined("COL103")) define("COL103", '#000000');\r
+//\8bL\8e\96\88ê\97\97\83e\81[\83u\83\8b\90F\r
+if(!defined("COL104")) define("COL104", '#F0E0D6');\r
+//\96¼\91O\82Ì\90F\r
+if(!defined("COL105")) define("COL105", '#117743');\r
+//\91è\96¼\82Ì\90F\r
+if(!defined("COL106")) define("COL106", '#cc1105');\r
+//\90Ô\8e\9a\82Æ\93\8a\8de\8cã\90Ø\91Ö\82Ì\95\8e\9a\90F\r
+if(!defined("COL107")) define("COL107", '#dd0000');\r
+//\82»\82ë\82»\82ë\8fÁ\82¦\82é\95\8e\9a\90F\r
+if(!defined("COL108")) define("COL108", '#f00000');\r
+//\83X\83\8c\83b\83h\83X\83g\83b\83v\95\8e\9a\90F\r
+if(!defined("COL109")) define("COL109", '#0000dd');\r
+//\83X\83\8c\8fÈ\97ª\95\8e\9a\90F\r
+if(!defined("COL110")) define("COL110", '#707070');\r
+  /* \83X\83^\83C\83\8b\83V\81[\83g */\r
+$css_collis='<STYLE TYPE="text/css"><!--\r
+body,tr,td,th { font-size:12pt; }\r
+a:hover { color:#DD0000; }\r
+span { font-size:20pt; }\r
+small { font-size:10pt; }\r
+.waku { border:1px solid '.COL103.'; }\r
+--></STYLE>';\r
+\r
+//\90\9b\8f\88\82Ìrepng2jpeg\82Å\83T\83\80\83l\83C\83\8b\82ð\8dì\82é (n=0 y=1)\r
+//\90\9b\8f\88: http://sugachan.dip.jp/download/\r
+//1\82É\90Ý\92è\82³\82ê\82Ä\82à exec \83R\83}\83\93\83h\82ª\8eg\82¦\82È\82¢\83T\81[\83o\82Ì\8fê\8d\87\81A\8e©\93®\93I\82ÉGD\82Å\8f\88\97\9d\82³\82ê\82Ü\82·\81B\r
+//\8f®\81A\94»\95Ê\82Í\8am\8eÀ\90«\82Í\82 \82è\82Ü\82¹\82ñ\81B\83T\81[\83o\91¤\82Ì\95Ï\91¥\93I\82È\90Ý\92è\82Å\81A\r
+//  \89½\82©\82µ\82ç\82Ì\83G\83\89\81[\82â\83T\83\80\83l\83C\83\8b\94­\90\82µ\82È\82¢\8fê\8d\87\82Í0\82Æ\82µ\82Ä\89^\89c\82µ\82Ä\89º\82³\82¢\81B\r
+if(!defined("SUGA_DOCORO")) define("SUGA_DOCORO", 0);\r
+\r
+// \90Ý\92è\8d\80\96Ú -------------------------------------------------------------------\r
+if(!defined("HSIZE")) define("HSIZE", 280);                    // \83T\83\80\83l\95\\8e¦\82Ì\89¡\83T\83C\83Y\81i\83X\83\8c\97p\r
+if(!defined("VSIZE")) define("VSIZE", 280);                    // \83T\83\80\83l\95\\8e¦\82Ì\8fc\83T\83C\83Y\81i\83X\83\8c\97p\r
+if(!defined("HSIZE_RES")) define("HSIZE_RES", 280);            // \83T\83\80\83l\95\\8e¦\82Ì\89¡\83T\83C\83Y\81i\83\8c\83X\97p\r
+if(!defined("VSIZE_RES")) define("VSIZE_RES", 280);            // \83T\83\80\83l\95\\8e¦\82Ì\8fc\83T\83C\83Y\81i\83\8c\83X\97p\r
+if(!defined("NEW_LINES")) define("NEW_LINES", 40);             // \90V\92\85\8bL\8e\96\95\\8e¦\90\94\81i\81«\82ª\97L\8cø\82Ì\8fê\8d\87\83f\83t\83H\83\8b\83g\8c\8f\90\94\82Æ\82È\82è\82Ü\82·\r
+if(!defined("NEW_LINES_U")) define("NEW_LINES_U", 9000);               // \8dÅ\91å\8bL\8e\96\95\\8e¦\90\94\81i\83\86\81[\83U\81[\82ª\8ew\92è\82µ\82½\82à\82Ì\82Æ\82ð\94ä\82×\82Ü\82· '0'\82Å\96³\8cø\89»\r
+if(!defined("AUTO_LINK")) define("AUTO_LINK", 1);                      // \83I\81[\83g\83\8a\83\93\83N\82·\82é  \82·\82é:1 \82µ\82È\82¢:0\r
+\r
+// \83i\83\8d\83u\83\8d\8b@\94\ ---------------------------------------------------------------\r
+if(!defined("NARO_BURO")) define("NARO_BURO", 0);                      // \83i\83\8d\83u\83\8d\8b@\94\\82ð\8eg\97p\82µ\82Ä\82¢\82é  \82µ\82Ä\82¢\82é:1 \82µ\82Ä\82¢\82È\82¢:0\r
+if(!defined("PHP_EXT_NOANI")) define("PHP_EXT_NOANI", 'g.htm');        // \8ag\92£\8eq(GIF\92â\8e~\83y\81[\83W)\r
+\r
+// VIEW\90Ý\92è\8aî\96{\8d\80\96Ú -----------------------------------------------------------\r
+if(!defined("TITLE1")) define("TITLE1", '\82Ñ\82ã\82¤\82í\82Í\81[');       // \83^\83C\83g\83\8b\r
+if(!defined("PAGE_COLS")) define("PAGE_COLS", 4);                      // 1\8ds\82É\95\\8e¦\82·\82é\89æ\91\9c\90\94\r
+if(!defined("HVSIZE")) define("HVSIZE", 180);                  // \83T\83\80\83l\95\\8e¦\82Ì\89¡\83T\83C\83Y\r
+if(!defined("VVSIZE")) define("VVSIZE", 180);                  // \83T\83\80\83l\95\\8e¦\82Ì\8fc\83T\83C\83Y\r
+\r
+// VIEW\90Ý\92è\8ag\92£\8d\80\96Ú \81¦\8fd\97v\81¦ --------------------------------------------------\r
+// \88È\89º\82Ì\91S\8d\80\96Ú\82Í siokara.php \93Á\97L\82Ì\82à\82Ì\82Å\82·.\82Ù\82©\82Ì\83X\83N\83\8a\83v\83g\82É\82Í\8b°\82ç\82­\82 \82è\82Ü\82¹\82ñ.\r
+// \8e©\93®\83`\83F\83b\83N\82Æ\82Í siokara.php \82Ì\8f\88\97\9d\82É\82æ\82è\83\8d\83O\93à\82É\95t\82¯\82ç\82ê\82½\88ó\82ð\8e©\93®\83`\83F\83b\83N\82·\82é\8b@\94\\82Å\82·.\r
+if(!defined("SAGE_START")) define("SAGE_START", 1);            // \83X\83\8c\8eå\8b­\90§sage\8b@\94\\82ð\8eg\97p\82µ\82Ä\82¢\82é\r
+// \83X\83\8c\8eå\8b­\90§sage\8b@\94\\82ª\96³\82¢\81A\82à\82µ\82­\82Í\8eg\97p\82µ\82Ä\82¢\82È\82¢\8fê\8d\87\82Í\81A\95K\82¸ '0' \82É\90Ý\92è\82µ\82Ä\82­\82¾\82³\82¢\r
+\r
+if(!defined("SAGE_MOJI")) define("SAGE_MOJI", '(sage)');               // \83X\83\8c\8eå\8b­\90§sage\82ª\8cø\82¢\82Ä\82¢\82é\82±\82Æ\82ð\92m\82ç\82¹\82é\95\8e\9a\r
+if(!defined("UGO_MOJI")) define("UGO_MOJI", 'Animation!');     // \83A\83j\83\81\81[\83V\83\87\83\93GIF\8e\9e\82Ì\95\8e\9a\81i\8e©\93®\83`\83F\83b\83N:siokara.php\r
+if(!defined("RPL_MOJI")) define("RPL_MOJI", '  ');             // \89æ\91\9c\8d·\82µ\91Ö\82¦\8e\9e\82Ì\95\8e\9a\81i\8e©\93®\83`\83F\83b\83N:siokara.php\r
+\r
+// \83i\83\8d\83u\83\8d\8b@\94\ ---------------------------------------------------------------\r
+if(!defined("NOANI_OPTION")) define("NOANI_OPTION", 'noani=1');        // GIF\92â\8e~\83y\81[\83W\82©\82ç\82Ì\83y\81[\83W\82Ì\92Ç\89Á\88ø\90\94\r
+\r
+// LOGS SEARCH \90Ý\92è\8d\80\96Ú -------------------------------------------------------\r
+if(!defined("TITLE2")) define("TITLE2", '\83\8d\83O\8c\9f\8dõ\82í\82Í\81[');     // \83^\83C\83g\83\8b\r
+if(!defined("LINK_LIM")) define("LINK_LIM", 16);                       // [1] [2] [3]...\82Ì\95\\8e¦\90§\8cÀ  '0'\82Å\96³\8cø\89»\r
+\r
+    //filter switch\r
+if(!defined("FILTER")) define("FILTER", 1); //0 = off 1 = on\r
+\r
+  // Futare\r
+if(!defined("COPY_LOG")) define("COPY_LOG", 'copy_log.cgi'); //\83R\83s\81[\83\8d\83O\96¼\r
+\r
+\r
+if(!defined("PWFN")) define("PWFN", 'Please wait for your name.');\r
+if(!defined("PWFE")) define("PWFE", 'Please wait for your email address.');\r
+\r
+    //Language settings\r
+if(!defined("LANGUAGE")) define("LANGUAGE", 'jp');\r
+if(!defined("S_HOME")) include HOME."strings_".LANGUAGE.".php";\r
+\r
+    //Time/Date\r
+if(!defined("DATE_FORMAT")) define("DATE_FORMAT", "Y/m/d");  //date format\r
+$youbi = array(S_SUN, S_MON, S_TUE, S_WED, S_THU, S_FRI, S_SAT);\r
+\r
+// \8b\91\94Û\90Ý\92è--------------------------------------------------------------------\r
+if(file_exists(BANFILE1)) include "".BANFILE1.""; else\r
+$badip = array("addr.dummy.com","addr2.dummy.com");\r
+if(file_exists(BANFILE2)) include "".BANFILE2.""; else\r
+$badstring = array("dummy_string","dummy_string2","\.ws/","\96³\97¿\93®\89æ","\96³\97¿\89æ\91\9c","\97F\92B\95å\8fW","dummy_string3","<a href=","</a>"); // \8b\91\90â\82·\82é\95\8e\9a\97ñ\r
+if(file_exists(BANFILE3)) include "".BANFILE3.""; else\r
+$badfile = array("dummy","dummy2","dummy3");\r
+if(CHANBAN){\r
+$bann="";\r
+chkban($bann);\r
+}\r
+\r
+//$addinfo = '<script language="JavaScript" src="'.PHP_DIRECTORY.'reader.php?js"></script><noscript><img src="'.PHP_DIRECTORY.'reader.php?dmy" /></noscript>'; // \93\8a\8de\97\93\92\8d\88Ó\8f\91\82«\82Ì\92Ç\8bL\8e\96\8d\80\r
+$addinfo = '<script language="JavaScript" src="'.HOME.'menu.php?js"></script><noscript><img src="'.HOME.'menu.php?dmy" /></noscript><script language="JavaScript" src="..menu.php?js"></script><noscript><img src="'.PHP_DIRECTORY.'menu.php?dmy" /></noscript>'; // \93\8a\8de\97\93\92\8d\88Ó\8f\91\82«\82Ì\92Ç\8bL\8e\96\8d\80\r
+//<div align=center><iframe src="".PHP_DIRECTORY."bbscount/menu.php" WIDTH=530 HEIGHT=15 SCROLLING=NO FRAMEBORDER=0 MARGINWIDTH=0 MARGINHEIGHT=0 BORDER=0></iframe></div>\r
+\r
+// [dlcount] \81«\83I\83}\83P\95\\8bL\83\81\83\82 (\83I\83\93\83\89\83C\83\93\83J\83E\83\93\83^\81\95\8fæ\8eZ\83J\83E\83\93\83^)\r
+// <script language="JavaScript" src="reader.php?js"></script><noscript><img src="reader.php?dmy" /></noscript>\r
+//------------------------------------------------------------------------\r
+$path = realpath("./").'/'.IMG_DIR;\r
+$thumb_path = realpath("./").'/'.THUMB_DIR;\r
+$temppath = realpath("./").'/'.TEMP_DIR;\r
+$higiyo = DC_CUN; //dlcount\r
+// \81ª\81«\81i\94O\82Ì\82½\82ß\82É\8ec\82·\81j //dlcount\r
+// $higiyo = realpath("./").'/'.DC_CUN; //dlcount\r
+\r
+    //Gazou BBS template\r
+if(TEMPLATE === 0){\r
+//form\r
+    $template['form_box'] = '<table cellpadding="1" cellspacing="1"><col span="1" />'."\n";\r
+    $template['td1'] = '<td class="postblock" align="left" bgcolor="'.BASE_COL.'">';\r
+    $template['td2'] = '</td>';\r
+//updatelog\r
+    $template['surelist'] = '<a name="list"></a><table class="reply" width="99%" border="1" cellspacing="8" cellpadding="1" bgcolor="'.RE_BGCOL.'" align="center"><tr><td class="reply">';\r
+\r
+    $template['sub_size'] = '+1';\r
+    $template['surebox1'] = FALSE;\r
+    $template['surebox2'] = FALSE;\r
+    $template['disa'] = FALSE; \r
+    $template['brcl'] = FALSE;\r
+    $template['rbox'] = "<table><tr><td class=\"doubledash\" align=\"right\" nowrap=\"nowrap\" valign=\"top\">".RES_MARK."</td><td class=\"reply\" bgcolor=\"".RE_BGCOL."\" ";\r
+\r
+    $template['imgbox'] = "</td></tr></table>\n";\r
+    $template['sbox'] = "</td></tr></table>\n";\r
+    $template['ebox'] = FALSE;\r
+    $template['brclibox'] = "<br clear=\"left\" />";\r
+\r
+    $template['foot_box'] = FALSE;\r
+}\r
+//================\r
+    //\82Q\82¿\82á\82ñ\82Ë\82é template\r
+if(TEMPLATE === 1){\r
+//form\r
+    $template['form_box'] = '<table class="reply" border="1" cellspacing="8" cellpadding="1" bgcolor="'.BOX_BGCOL.'" align="center"><col span="1" />'."\n";\r
+    $template['td1'] = '<td>';\r
+    $template['td2'] = '</td>';\r
+//updatelog\r
+    $template['surelist'] = '<a name="list"></a><table class="postblock" width="98%" border="1" cellspacing="8" cellpadding="1" bgcolor="'.BOX_BGCOL.'" align="center"><tr><td class="reply">';//</td></tr></table>\r
+\r
+    $template['sub_size'] = '+6';\r
+    $template['surebox1'] = '<table class="reply" width="98%" border="1" cellspacing="8" cellpadding="4" bgcolor="'.OP_BGCOL.'" align="center">'."\n";\r
+    $template['surebox2'] = '<tr><td>';\r
+    $template['disa'] = "<br />";\r
+    $template['brcl'] = "<br clear=\"left\" />";\r
+    $template['rbox'] = "<div ";\r
+\r
+    $template['imgbox'] = FALSE;\r
+    $template['sbox'] = "</div>";\r
+    $template['ebox'] = "</td></tr></table>\n";\r
+    $template['brclibox'] = "</td></tr></table>\n";\r
+\r
+    $template['foot_box'] = '<table class="postblock" width="98%" border="1" cellspacing="8" cellpadding="4" bgcolor="'.BOX_BGCOL.'" align="center"><tr><td>'."\n";\r
+}\r
+?>\r
diff --git a/data/css/burichan.css b/data/css/burichan.css
new file mode 100755 (executable)
index 0000000..532e1d6
--- /dev/null
@@ -0,0 +1,168 @@
+html, body {
+         font-size:12pt;
+         background:#EEF2FF;
+         color:#000000;
+}
+a       {
+        background:inherit;
+        color:#34345C;
+        text-decoration:none;
+        font-family:sans-serif;
+}
+a:visited {
+        background:inherit;
+        color:#34345C;
+        text-decoration:none;
+        font-family:sans-serif;
+}
+a:hover {
+        color:#DD0000;
+        background:inherit;
+        text-decoration:underline;
+        font-family:sans-serif;
+}
+.adminbar {
+        text-align:right;
+        background:inherit;
+        clear:both;
+        float:right;
+}
+.logo {
+        clear:both;
+        text-align:center;
+        background:inherit;
+        font-size:24pt;
+        color:#AF0A0F;
+        width:100%;
+}
+.theader {
+        background:#0010E0;
+        color:#FFFFFF;
+        width:100%;
+}
+.postarea {
+        background:inherit;
+}
+.rules {
+        font-size:10px;
+        font-family:sans-serif;
+}
+.postblock {
+        background:#9988EE;
+        color:#000000;
+        font-weight:800;
+}
+.footer {
+        text-align:center;
+        font-size:10px;
+        font-family:sans-serif;
+}
+.passvalid {
+       background:#9988EE;
+       text-align:center;
+       width:100%;
+       color:#ffffff;
+}
+.dellist {
+       background:inherit;
+       text-align:center;
+}
+.delbuttons {
+       background:inherit;
+       text-align:center;
+       padding-bottom:4px;
+
+}
+.managehead {
+       background:#0F8FE1;
+       color:#000000;
+       font-family:sans-serif;
+       font-size:14px;
+       padding:0px;
+}
+.postlists {
+       background:#FFFFFF;
+       width:100%;
+       padding:0px;
+       color:#000000;
+}
+.row1 {
+       background:#9AD2F6;
+       font-family:sans-serif;
+       font-size:12px;
+       color:#000000;
+}
+.row2 {
+        background:#FFFFFF;
+        font-family:sans-serif;
+        font-size:12px;
+        color:#000000;
+}
+.unkfunc {
+       background:#C4C2EE;
+       color:#FFFFFF;
+}
+.filesize {
+       font-size:12px;
+       font-family:sans-serif;
+       text-decoration:underline;
+       padding-left:3em;
+}
+.filetitle {
+       background:inherit;
+       font-size:18px;
+       font-family:serif;
+       color:#0F0C5D;
+       font-weight:800;
+}
+.postername {
+       background:inherit;
+       font-size:12px;
+       font-family:serif;
+       color:#117743;
+       font-weight:800;
+}
+.oldpost {
+        background:inherit;
+        font-size:18px;
+        font-family:serif;
+        color:#0F0C5D;
+        font-weight:800;
+}
+.omittedposts {
+        background:inherit;
+        font-size:18px;
+        font-family:serif;
+        color:#070707;
+        font-weight:800;
+}
+.reply {
+       background:#D6DAF0;
+       color:#000000;
+       font-family:serif;
+}
+.doubledash {
+       vertical-align:top;
+       clear:both;
+       float:left;
+}
+.replytitle {
+        background:inherit;
+        font-size:18px;
+        font-family:serif;
+        color:#0F0C5D;
+        font-weight:800;
+}
+.commentpostername {
+        background:inherit;
+        font-size:12px;
+        font-family:serif;
+        color:#117743;
+        font-weight:800;
+}
+.thumbnailmsg {
+       background:inherit;
+       font-size:9px;
+       font-family:sans-serif;
+       color:#000000;
+}
diff --git a/data/css/futaba.css b/data/css/futaba.css
new file mode 100755 (executable)
index 0000000..b240e1d
--- /dev/null
@@ -0,0 +1,143 @@
+html, body {
+         background:#FFFFEE;
+         color:#800000;
+}
+a {
+        color:#0000EE;
+}
+a:hover {
+        color:#DD0000;
+}
+.adminbar {
+        text-align:right;
+        clear:both;
+        float:right;
+}
+.logo {
+        clear:both;
+        text-align:center;
+        font-size:2em;
+        color:#800000;
+        width:100%;
+}
+.theader {
+        background:#E04000;
+        text-align:center;
+        padding:2px;
+        color:#FFFFFF;
+        width:100%;
+}
+.catalogmode {
+        background:#0040E0;
+        text-align:center;
+        padding:2px;
+        color:#FFFFFF;
+        width:100%;
+}
+.postarea {
+}
+.rules {
+        font-size:0.7em;
+}
+.postblock {
+        background:#EEAA88;
+        color:#800000;
+        font-weight:800;
+}
+.footer {
+        text-align:center;
+        font-size:12px;
+        font-family:serif;
+}
+.passvalid {
+       background:#E08000;
+       text-align:center;
+       width:100%;
+       color:#FFFFFF;
+}
+.dellist {
+       font-weight: bold;
+       text-align:center;
+}
+.delbuttons {
+       text-align:center;
+       padding-bottom:4px;
+
+}
+.managehead {
+       background:#6080F6;
+       color:#800000;
+       padding:0px;
+}
+.postlists {
+       background:#FFFFFF;
+       width:100%;
+       padding:0px;
+       color:#800000;
+}
+.row1 {
+       background:#F6F6F6;
+       color:#800000;
+}
+.row2 {
+        background:#D6D6F6;
+        color:#800000;
+}
+.unkfunc {
+       background:inert;
+       color:#789922;
+}
+.filesize {
+       text-decoration:none;
+}
+.filetitle {
+       background:inherit;
+       font-size:1.2em;
+       color:#CC1105;
+       font-weight:800;
+}
+.postername {
+       color:#117743;
+       font-weight:bold;
+}
+.postertrip {
+       color:#228854;
+}
+.oldpost {
+        color:#CC1105;
+        font-weight:800;
+}
+.omittedposts {
+        color:#707070;
+}
+.reply {
+       background:#F0E0D6;
+       color:#800000;
+}
+.replyhl {
+       background:#F0E0D6;
+       color:#800000;
+       border: 2px dashed #EEAA88;
+}
+.doubledash {
+       vertical-align:top;
+       clear:both;
+       float:left;
+}
+.replytitle {
+       font-size: 1.2em;
+        color:#CC1105;
+        font-weight:800;
+}
+.commentpostername {
+        color:#117743;
+       font-weight:800;
+}
+.thumbnailmsg {
+       font-size: small;
+       color:#800000;
+}
+
+.abbrev {
+        color:#707070;
+}
diff --git a/data/css/gurochan.css b/data/css/gurochan.css
new file mode 100755 (executable)
index 0000000..48b76af
--- /dev/null
@@ -0,0 +1,119 @@
+html, body {
+  font-size:10pt;
+  background:#EDDAD2;
+  color:#000000;
+}
+* {
+  font-family: "Trebuchet MS", Tahoma, Verdana, Arial, sans-serif;
+  font-size: 10pt;
+}
+input, textarea {
+  background-color: #E6CBC0;
+  border: 1px solid #CA927B;
+}
+a {
+  background:inherit;
+  color:#34345C;
+}
+a:visited {
+  background:inherit;
+  color:#34345C;
+}
+a:hover {
+  color:#DD0000;
+  background:inherit;
+}
+a.quotelink {
+  background:inherit;
+  color:#DD0000;
+}
+.logo {
+  clear:both;
+  text-align:center;
+  background:inherit;
+  font-size:24pt;
+  color:#AF0A0F;
+  width:100%;
+}
+.postarea {
+  background:inherit;
+}
+.postblock {
+  background: #D9AF9E;
+  border: 1px solid #CA927B;
+  color: black;
+  font-weight: bold;
+  padding: 2px 5px 2px 5px;
+}
+.footer {
+  text-align:center;
+  font-size:12px;
+}
+.unkfunc {
+       background:inert;
+       color:#789922;
+}
+.filesize {
+       text-decoration:none;
+}
+.filetitle {
+       background:inherit;
+       color:#0F0C5D;
+       font-weight:800;
+}
+.postername {
+  background:inherit;
+  font-size:11pt;
+  color:#117743;
+  font-weight: bold;
+}
+.postertrip {
+       background:inherit;
+       color:#228854;
+}
+.oldpost {
+  background:inherit;
+  color:#0F0C5D;
+  font-weight:800;
+}
+.omittedposts {
+  background:inherit;
+  color:#070707;
+}
+.reply {
+       background:#D9AF9E;
+       color:#000000;
+       border:1px solid #CA927B;
+}
+.replyhl {
+       background:#D6BAD0;
+       color:#000000;
+}
+.doubledash {
+       vertical-align:top;
+       clear:both;
+       float:left;
+}
+.replytitle {
+       background:inherit;
+       font-size:18px;
+  color:#0F0C5D;
+  font-weight:800;
+}
+.commentpostername {
+  background:inherit;
+  font-size:11pt;
+  color:#117743;
+  font-weight: bold;
+}
+a.quotejs {
+  color:#000000;
+       text-decoration: none;
+}
+a.quotejs:hover {
+  font-weight:bold;
+}
+
+.adminbar {
+  text-align: center;
+}
\ No newline at end of file
diff --git a/data/css/kusaba.css b/data/css/kusaba.css
new file mode 100755 (executable)
index 0000000..8e3b373
--- /dev/null
@@ -0,0 +1,232 @@
+html, body {\r
+         font-size:12pt;\r
+         background:#EEFFEE;\r
+         color:#000000;\r
+}\r
+a       {\r
+        background:inherit;\r
+        color:#345C34;\r
+        text-decoration:none;\r
+        font-family:sans-serif;\r
+}\r
+a:visited {\r
+        background:inherit;\r
+        color:#345C34;\r
+        text-decoration:none;\r
+        font-family:sans-serif;\r
+}\r
+a:hover {\r
+        color:#117743;\r
+        background:inherit;\r
+        text-decoration:underline;\r
+        font-family:sans-serif;\r
+}\r
+.adminbar {\r
+        text-align:right;\r
+        background:inherit;\r
+        clear:both;\r
+        float:right;\r
+}\r
+.logo {\r
+        clear:both;\r
+        text-align:center;\r
+        background:inherit;\r
+        font-size:24pt;\r
+        color:#117743;\r
+        width:100%;\r
+}\r
+.theader {\r
+        background:#00E010;\r
+        color:#FFFFFF;\r
+        width:100%;\r
+}\r
+.postarea {\r
+        background:inherit;\r
+}\r
+.rules {\r
+        font-size:10px;\r
+        font-family:sans-serif;\r
+}\r
+.postblock {\r
+        background:#88DD88;\r
+        color:#000000;\r
+        font-weight:800;\r
+}\r
+.footer {\r
+        text-align:center;\r
+        font-size:10px;\r
+        font-family:sans-serif;\r
+}\r
+.passvalid {\r
+       background:#99EE88;\r
+       text-align:center;\r
+       width:100%;\r
+       color:#ffffff;\r
+}\r
+.dellist {\r
+       background:inherit;\r
+       text-align:center;\r
+}\r
+.delbuttons {\r
+       background:inherit;\r
+       text-align:center;\r
+       padding-bottom:4px;\r
+\r
+}\r
+.managehead {\r
+       background:#0FE18F;\r
+       color:#000000;\r
+       font-family:sans-serif;\r
+       font-size:14px;\r
+       padding:0px;\r
+}\r
+.postlists {\r
+       background:#FFFFFF;\r
+       width:100%;\r
+       padding:0px;\r
+       color:#000000;\r
+}\r
+.row1 {\r
+       background:#9AF6D2;\r
+       font-family:sans-serif;\r
+       font-size:12px;\r
+       color:#000000;\r
+}\r
+.row2 {\r
+        background:#FFFFFF;\r
+        font-family:sans-serif;\r
+        font-size:12px;\r
+        color:#000000;\r
+}\r
+.unkfunc {\r
+       color:#117743;\r
+}\r
+.filesize {\r
+       font-size:12px;\r
+       font-family:sans-serif;\r
+       text-decoration:underline;\r
+       padding-left:3em;\r
+}\r
+.filetitle {\r
+       background:inherit;\r
+       font-size:18px;\r
+       font-family:serif;\r
+       color:#0F5D0C;\r
+       font-weight:800;\r
+}\r
+.postername {\r
+       background:inherit;\r
+       font-family:serif;\r
+       color:#117743;\r
+       font-weight:bold;\r
+}\r
+.postername a {\r
+       font-family:inherit;\r
+}\r
+.oldpost {\r
+        background:inherit;\r
+        font-size:18px;\r
+        font-family:serif;\r
+        color:#0F5D0C;\r
+        font-weight:800;\r
+}\r
+.omittedposts {\r
+        background:inherit;\r
+        font-size:18px;\r
+        font-family:serif;\r
+        color:#070707;\r
+        font-weight:800;\r
+}\r
+.reply {\r
+       background:#DAF0D6;\r
+       color:#000000;\r
+       font-family:serif;\r
+}\r
+.doubledash {\r
+       vertical-align:top;\r
+       clear:both;\r
+       float:left;\r
+}\r
+.replytitle {\r
+        background:inherit;\r
+        font-size:18px;\r
+        font-family:serif;\r
+        color:#0F5D0C;\r
+        font-weight:800;\r
+}\r
+.commentpostername {\r
+        background:inherit;\r
+        font-size:12px;\r
+        font-family:serif;\r
+        color:#117743;\r
+        font-weight:800;\r
+}\r
+.thumbnailmsg {\r
+       background:inherit;\r
+       font-size:9px;\r
+       font-family:sans-serif;\r
+       color:#000000;\r
+}\r
+\r
+.replyhl {\r
+       background: #88DD88;\r
+       border: 2px dashed #117743;\r
+}\r
+\r
+#watchedthreads {\r
+       background-color: #DAF0D6 !important;\r
+       border: 1px solid #88DD88 !important;\r
+}\r
+\r
+.replymode {\r
+       background:#DAF0D6;\r
+       text-align:center;\r
+       padding:2px;\r
+       color:#000000;\r
+       width:100%;\r
+       font-weight: bold;\r
+}\r
+.catalogmode {\r
+       background:#88DD88;\r
+       text-align:center;\r
+       padding:2px;\r
+       color:#000000;\r
+       width:100%;\r
+       font-weight: bold;\r
+}\r
+\r
+.hidethread {\r
+       background: transparent url('./icons/green/icons.gif') -32px -16px no-repeat;\r
+}\r
+\r
+.unhidethread {\r
+       background: transparent url('./icons/green/icons.gif') -48px 0px no-repeat;\r
+}\r
+\r
+.watchthread {\r
+       background: transparent url('./icons/green/icons.gif') -32px 0px no-repeat;\r
+}\r
+\r
+.expandthread {\r
+       background: transparent url('./icons/green/icons.gif') 0px -16px no-repeat;\r
+}\r
+\r
+.quickreply {\r
+       background: transparent url('./icons/green/icons.gif') 0px 0px no-repeat;\r
+}\r
+\r
+.hidewatchedthreads {\r
+       background: transparent url('./icons/green/icons.gif') -48px -16px no-repeat;\r
+}\r
+\r
+.refreshwatchedthreads {\r
+       background: transparent url('./icons/green/icons.gif') -16px -16px no-repeat;\r
+}\r
+\r
+.restorewatchedthreads {\r
+       background: transparent url('./icons/green/icons.gif') -16px 0px no-repeat;\r
+}\r
+\r
+.reflinkpreview {\r
+       background-color: #DAF0D6 !important;\r
+}
\ No newline at end of file
diff --git a/data/css/lightbox.css b/data/css/lightbox.css
new file mode 100755 (executable)
index 0000000..daba330
--- /dev/null
@@ -0,0 +1,29 @@
+#lightbox {\r
+       background-color: #eee;\r
+       padding: 10px;\r
+       border-bottom: 1px solid #666;\r
+       border-right: 1px solid #666;\r
+}\r
+#overlay {\r
+       background-image: url(../css/lightbox/overlay.gif);\r
+}\r
+#lightboxCaption {\r
+       color: #333;\r
+       background-color: #eee;\r
+       font-size: 90%;\r
+       text-align: center;\r
+       border-bottom: 1px solid #666;\r
+       border-right: 1px solid #666;\r
+}\r
+#lightboxIndicator {\r
+       border: 1px solid #fff;\r
+}\r
+#lightboxOverallView {\r
+       background-image: url(../css/lightbox/overlay.png);\r
+}\r
+* html #lightboxOverallView,\r
+* html #overlay {\r
+       background-color: #000;\r
+       background-image: url(../css/lightbox/blank.gif);\r
+       filter: Alpha(opacity=50);\r
+}\r
diff --git a/data/css/lightbox/blank.gif b/data/css/lightbox/blank.gif
new file mode 100755 (executable)
index 0000000..07f3e45
Binary files /dev/null and b/data/css/lightbox/blank.gif differ
diff --git a/data/css/lightbox/overlay.gif b/data/css/lightbox/overlay.gif
new file mode 100755 (executable)
index 0000000..fcce60a
Binary files /dev/null and b/data/css/lightbox/overlay.gif differ
diff --git a/data/css/lightbox/overlay.png b/data/css/lightbox/overlay.png
new file mode 100755 (executable)
index 0000000..a344996
Binary files /dev/null and b/data/css/lightbox/overlay.png differ
diff --git a/data/css/main/mainstyle.css b/data/css/main/mainstyle.css
new file mode 100755 (executable)
index 0000000..388637d
--- /dev/null
@@ -0,0 +1,61 @@
+@media all{ /* 通用設定 */\r
+       html { background: #FFE; color: #800000; } /* 基本網頁背景樣式 */\r
+       a:link { color: #00E; } /* 正常連結樣式 */\r
+       a:hover { color: #D00; } /* hover時連結樣式 */\r
+       a:visited { color: #00E; } /* 已拜訪連結樣式 */\r
+       a.qlink { text-decoration: none; } /* 引用用連結樣式 */\r
+       small { font-size: 0.8em; } /* 小字樣式(eg.[以預覽圖顯示]) */\r
+       hr { clear: left; } /* 分隔線樣式 */\r
+       img { border: 0; } /* 圖片顯示樣式 */\r
+\r
+       #toplink { text-align: right; } /* 頁首連結條樣式 */\r
+       h1 { color: #800000; text-align: center; margin: 0 auto; } /* 網頁主標題樣式 */\r
+       hr.top { width: 90%; height: 1px; } /* 主標題下分隔線樣式 */\r
+\r
+       .Form_bg { background: #EA8; } /* 送出表單左方欄位之底色 */\r
+       .hide_btn { float: right; width: 4em; height: 1.25em; overflow: hidden; text-align: center; background: #F0E0D6; } /* 表單收縮按鈕樣式 */\r
+       .show { color: #00E; }\r
+       .hide { display: none; }\r
+       #postinfo { font-size: 0.8em; } /* 上傳說明樣式 */\r
+       form { padding: 0; margin: 0; } /* 修正表單標籤造成的排版問題 */\r
+\r
+       .threadpost {  } /* 討論串首篇樣式 */\r
+       .reply { display: table; margin: 0.5ex 1em 0 1em; background: #F0E0D6; } /* 討論串回應樣式 */\r
+       .reply_hl { background: #F0D5B7; }  /* 討論串回應背景標亮樣式 */\r
+       .name { color: #117743; font-weight: bold; } /* 文章張貼者名稱樣式 */\r
+       .admin_cap { color: #0000FF; } /* 管理員キャップ樣式設定 */\r
+       .img { float: left; margin: 1ex 2ex; } /* 討論串圖片顯示樣式 */\r
+       .title { color: #CC1105; font-size: 1.125em; font-weight: bold; } /* 討論串標題樣式 */\r
+       .nor { font-weight: normal; } /* Trip取消粗體用 */\r
+       .quote { margin: 1em 2em; } /* 討論串內文縮排樣式 */\r
+       .resquote { color: #789922; } /* 標註引用回文顏色 */\r
+       .category { font-size: 0.8em; color: gray; } /* 類別標籤顯示樣式 */\r
+\r
+       .warn_txt { color: #F00000; font-weight: bold; } /* 討論串狀態警告文字(eg.文章即將被刪除) */\r
+       .warn_txt2 { color: #707070; } /* 討論串狀態提示文字(eg.回應幾篇被隱藏) */\r
+       #footer { text-align: center; clear: both; } /* 頁尾樣式 */\r
+       .bar_reply { background: #E04000; color: #FFF; font-weight: bold; text-align: center; } /* 回應模式樣式標題列 */\r
+       .bar_admin { background: #E08000; color: #FFF; font-weight: bold; text-align: center; } /* 管理模式樣式標題列 */\r
+       .ListRow1_bg { background: #D6D6F6; } /* 管理模式欄位背景顏色1(輪替出現) */\r
+       .ListRow2_bg { background: #F6F6F6; } /* 管理模式欄位背景顏色2(輪替出現) */\r
+}\r
+\r
+@media screen{ /* 標準顯示(一般顯示器)模式附加規則 */\r
+\r
+}\r
+\r
+@media handheld{ /* 手持設備(手機,PDA等)附加規則 */\r
+       html { max-width: 320px; margin: auto; font-size: 9px; } /* 320px為多數PDA的顯示寬度 */\r
+       input { max-width: 200px; }\r
+       textarea { max-width: 200px; height: 40px; }\r
+\r
+       .img { margin: 0.5ex 0.5ex; max-width: 125px; } /* 討論串圖片顯示樣式 */\r
+       .reply { clear: left; margin: 0.5ex 0 0 0; } /* 討論串回應樣式 */\r
+       .quote { margin: 1ex 1ex; } /* 討論串內文縮排樣式 */\r
+       #page_switch { clear: right; } /* 避免頁尾表格交疊 */\r
+}\r
+\r
+@media print{ /* 列印,預覽列印附加規則 */\r
+       html { background: #FFF; color: #000; } /* 網頁改成白底黑字,節省彩色列印成本 */\r
+       #postform_main { display: none; } /* 貼文表單在列印模式沒有用處,故不顯示以節省空間 */\r
+}
\ No newline at end of file
diff --git a/data/css/main/style.css b/data/css/main/style.css
new file mode 100755 (executable)
index 0000000..06017e8
--- /dev/null
@@ -0,0 +1,57 @@
+@media all{ /* 通用設定 */
+       hr { clear: left; } /* 分隔線樣式 */\r
+       img { border: 0; } /* 圖片顯示樣式 */\r
+       #heading { text-align: center; } /* 頁首連結條樣式 */
+       .adminbar { text-align: right; margin-bottom: 16px; }
+       .logo { font-size: 20pt; font-weight: bold; margin: 1.2ex 0ex; margin-top: 16px; float: none; } /* 文章張貼者名稱樣式 */
+       .sublogo { font-size: 10pt; font-weight: none;  }\r
+       hr.top { width: 90%; height: 0px; border-top: 1; border-bottom: 0px; border-left: 0px; border-right: 0px; } /* 主標題下分隔線樣式 */\r
+       .hide_btn { float: right; width: 4em; height: 1.25em; overflow: hidden; text-align: center; background: #FF0; } /* 表單收縮按鈕樣式 */\r
+       .show { color: #00E; padding: 1px; }\r
+       .hide { display: none; }\r
+       #postinfo { font-size: 0.8em; } /* 上傳說明樣式 */\r
+       form { padding: 0; margin: 0; } /* 修正表單標籤造成的排版問題 */
+       #fname { background-color: #FFFFA0; }
+       #femail { background-color: #FFFFA0; }
+       /*#fcom { width: 31.85em; height: 7.1em; margin-bottom: 0px; }*/
+       #option { font-size: small; }\r
+       .threadpost {  } /* 討論串首篇樣式 */\r
+       .img { float: left; margin: 0px 20px; margin-bottom: 8px; } /* 討論串圖片顯示樣式 */\r  .blockquote { margin: 1em 2.5em; } /* 討論串內文縮排樣式 */
+       .postertrip { font-weight: normal; }
+       #footer { text-align: center; clear: both; } /* 頁尾樣式 */
+
+       /*#postform_tbl { width: 508px; }*/ /* testing purposes */
+       .unkfunc2 { color: #696969; }
+       .tn_reply { width: 86px; height: 86px; margin: 0px 20px 20px 20px; float: left; background: #000; border: #0D0 2px solid; text-align: center; }
+
+       /* banner link */
+       #bannerlink { margin-top: -1px; margin-bottom: -1px; } /* links above the banner */
+       /* color banners */
+       #banner { text-align: center; width: 100%; padding: 2.5px 1px; }
+
+       .passvalid { font-weight: bold; width: auto; margin: 1px; padding: 1px 2px; }
+       .theader { font-weight: bold; width: auto; margin: 1px; padding: 1px 2px; }
+       .catalogmode { font-weight: bold; width: auto; margin: 1px; padding: 1px 2px; }
+       .bar_managecss { color: #FFF; background-color: #6080F6; font-weight: bold; width: auto; margin: 1px; padding: 1px 2px; }
+       .bar_info { color: #000; background-color: #FF0; font-weight: bold; width: auto; margin: 1px; padding: 1px 2px; }
+       .bar_search { color: #000; background-color: #0FB; font-weight: bold; width: auto; margin: 1px; padding: 1px 2px; }
+       .bar_info_mod { color: #FF0; background-color: #000; font-weight: bold; width: auto; margin: 1px; padding: 1px 2px; }\r
+}\r
+\r
+@media screen{ /* 標準顯示(一般顯示器)模式附加規則 */\r
+\r
+}\r
+\r
+@media handheld{ /* 手持設備(手機,PDA等)附加規則 */\r
+       html { max-width: 320px; margin: auto; font-size: 9px; } /* 320px為多數PDA的顯示寬度 */\r
+       input { max-width: 200px; }\r
+       textarea { max-width: 200px; height: 40px; }\r
+\r
+       .quote { margin: 1ex 1ex; } /* 討論串內文縮排樣式 */\r
+       #page_switch { clear: right; } /* 避免頁尾表格交疊 */\r
+}\r
+\r
+@media print{ /* 列印,預覽列印附加規則 */\r
+       html { background: #FFF; color: #000; } /* 網頁改成白底黑字,節省彩色列印成本 */\r
+       #postform_main { display: none; } /* 貼文表單在列印模式沒有用處,故不顯示以節省空間 */\r
+}
diff --git a/data/css/null.css b/data/css/null.css
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/data/css/photon.css b/data/css/photon.css
new file mode 100755 (executable)
index 0000000..aabb2ae
--- /dev/null
@@ -0,0 +1,175 @@
+html, body {
+       background-color: #EEEEEE;
+       color: #333333;
+       font-family: "Trebuchet MS",Trebuchet,serif;
+}
+a {
+       color: #FF6600;
+}
+a:hover {
+       color: #0066FF;
+}
+.adminbar {
+        clear:both;
+        float:right;
+        font-size: .8em;
+}
+.adminbar a {
+       font-weight: bold;
+}
+.logo {
+        clear:both;
+        text-align:left;
+        font-size:2em;
+        font-weight: bold;
+        color:#FF6600;
+        /*width:100%;*/
+}
+.theader, .passvalid {
+        background:#DDDDDD;
+        text-align:center;
+        padding:2px;
+        color:#2266AA;
+        clear: both;
+        font-weight: bold;
+        margin-bottom: .5em;
+        border: solid 1px #CCCCCC;
+        -moz-border-radius: 5px;
+}
+.postarea {
+}
+.rules {
+        font-size:0.7em;
+}
+.postblock {
+        background:transparent;
+        color:#002244;
+        font-weight:bold;
+}
+.footer {
+        text-align:center;
+        font-size:12px;
+        font-family:serif;
+        margin: 2em 0 0 0;
+}
+.dellist {
+       font-weight: bold;
+       text-align:center;
+}
+.delbuttons {
+       text-align:center;
+       padding-bottom:4px;
+}
+.managehead {
+       background:#DDDDDD;
+       color:#002244;
+       padding:0px;
+}
+.postlists {
+       background:#FFFFFF;
+       width:100%;
+       padding:0px;
+       color:#800000;
+}
+.row1 {
+       background:#DDDDDD;
+       color:#002244;
+}
+.row2 {
+        background:#CCCCCC;
+        color:#002244;
+}
+.unkfunc {
+       background:inherit;
+       color:#789922;
+}
+.reflink {
+       font-size: .8em;
+       font-weight: bold;
+}
+.filesize {
+       text-decoration:none;
+       color: #666666;
+       font-size: .8em;
+}
+.filetitle {
+       background:inherit;
+       font-size:1.2em;
+       color:#002244;
+       font-weight:bold;
+}
+.postername {
+       color:#004A99;
+       font-weight:bold;
+}
+.postertrip {
+       color:#FF3300;
+}
+.oldpost {
+        color:#CC1105;
+        font-weight:bold;
+}
+.omittedposts {
+        color:#666666;
+}
+.reply {
+       background:#DDDDDD;
+       border: solid 1px #CCCCCC;
+       padding: 0;
+       margin: 0;
+       -moz-border-radius: 5px;
+}
+blockquote {
+       margin: .5em .5em .5em 1em;
+}
+blockquote p {
+       margin: 0;
+       padding: 0;
+}
+.reply blockquote {
+       margin: .5em;
+}
+.doubledash {
+       display: none;
+       vertical-align:top;
+       clear:both;
+       float:left;
+}
+.replytitle {
+       font-size: 1.2em;
+        color:#002244;
+        font-weight:bold;
+}
+.commentpostername {
+        color:#004A99;
+       font-weight:800;
+}
+.thumbnailmsg {
+       font-size: .8em;
+       color:#666666;
+}
+hr {
+       border-style: solid none none none;
+       border-width: 1px;
+       border-color: #BBBBBB;
+}
+table {
+       border-style: none;
+}
+table td {
+       border-style: none;
+}
+.nothumb {
+       background-color: #FFFFFF;
+       border-style: dotted;
+       margin: .3em .5em;
+}
+
+.abbrev {
+        color:#666666;
+}
+.highlight {
+       background:#EEDACB;
+       color:#333333;
+       border: 2px dashed #EE6600;
+}
diff --git a/data/css/yotsuba.css b/data/css/yotsuba.css
new file mode 100755 (executable)
index 0000000..bec597b
--- /dev/null
@@ -0,0 +1,324 @@
+body {\r
+       font-family: arial,helvetica,sans-serif;\r
+       font-size: 10pt;\r
+       background: #FFFFEE url(../icon/fade.png) top center repeat-x;\r
+       color: #800000;\r
+       padding-left: 5px;\r
+       padding-right: 5px;\r
+       margin-right: 0px;\r
+       margin-left: 0px;\r
+       margin-top: 5px;\r
+}\r
+\r
+td { font-size: 10pt; padding:0; margin:0; }\r
+td.reply { border: 1px solid #D9BFB7; border-left: none; border-top: none; padding: 2px; }\r
+\r
+blockquote { font-size: 10pt; }\r
+.doubledash { color: #D9BFB7; }\r
+.inputtext {\r
+       margin: 0;\r
+       margin-right: 2px; \r
+       padding: 1px 4px;\r
+       border: 1px solid #aaa;\r
+       outline: none;\r
+       font-family: arial,helvetica,sans-serif; \r
+       font-size: 10pt;\r
+}\r
+input.inputtext { height: 1.75em; }\r
+td > .inputtext { height: auto; padding-top: 2px; padding-bottom: 3px; }\r
+.inputtext:focus { border: 1px solid #ea8; }\r
+.logo img { border: 1px solid #800; }\r
+.logo b span { font-family: tahoma;  }\r
+.logo span { font-size: 28px; letter-spacing: -2px; }\r
+hr { border: none; border-top: 1px solid #D9BFB7; height: 0px; }\r
+.postblock { border: 1px solid #800; font-size: 10pt; padding: 0px 5px;  }\r
+.rules { font-size: 10pt; }\r
+.rules a { text-decoration: none; }\r
+\r
+form a img { margin-top: 3px; }\r
+\r
+iframe, .rotating { background: #F0E0D6; border-right: 1px solid #D9BFB7; border-bottom: 1px solid #D9BFB7; }\r
+\r
+.pages { border: none; background:#F0E0D6; border-right: 1px solid #D9BFB7; border-bottom: 1px solid #D9BFB7;  }\r
+.pages td { border: none; padding: 1px 5px; }\r
+.pages td { color: #b86; }\r
+.pages td b { color: #800; }\r
+\r
+.deletebuttons { text-align: right; }\r
+.deletebuttons br { display: none; }\r
+\r
+a, a:visited {\r
+       color: #0000EE;\r
+}\r
+\r
+a:hover {\r
+       color: #DD0000;\r
+}\r
+\r
+a.quotelink {\r
+       color: #000080;\r
+}\r
+\r
+.logo {\r
+       clear: both;\r
+       text-align: center;\r
+       font-size: 24pt;\r
+       color: #800000;\r
+       width: 100%;\r
+}\r
+\r
+form {\r
+       margin-top: 0px;\r
+}\r
+\r
+.rules {\r
+       width: 468px;\r
+       font-size: 10px;\r
+}\r
+\r
+.rules a, .rules a:visited, .rules a:link {\r
+}\r
+\r
+\r
+.rules > li {\r
+       list-style: none;\r
+}\r
+.rules > li:before { content: "\2022 \20"; }\r
+\r
+.postblock {\r
+       background: #EEAA88;\r
+       color: #800000;\r
+       font-weight: 800;\r
+}\r
+\r
+.footer {\r
+       text-align: center;\r
+       font-size: 12px;\r
+}\r
+\r
+.unkfunc {\r
+       color: #789922;\r
+}\r
+\r
+.filesize {\r
+       text-decoration: none;\r
+}\r
+td .filesize { display: inline; background: none; }\r
+\r
+.filesize span, span.postername, span.filetitle, span.commentpostername {\r
+       unicode-bidi: embed;\r
+}\r
+\r
+.filetitle, .replytitle {\r
+\r
+       color: #CC1105;\r
+       font-weight: 800;\r
+}\r
+\r
+.postername, .commentpostername {\r
+       color: #117743;\r
+       font-weight: 800;\r
+}\r
+\r
+.postertrip {\r
+       background: inherit;\r
+       color: #228854;\r
+}\r
+\r
+.oldpost {\r
+       background: inherit;\r
+       color: #f00000;\r
+       font-weight: 800;\r
+}\r
+\r
+.omittedposts, .abbr {\r
+       color: #707070;\r
+}\r
+\r
+.reply {\r
+       background: #F0E0D6;\r
+       color: #800000;\r
+}\r
+\r
+.replyhl {\r
+       background: #F0C0B0;\r
+       color: #800000;\r
+}\r
+\r
+.doubledash {\r
+       vertical-align: top;\r
+       clear: both;\r
+       float: left;\r
+}\r
+\r
+a.quotejs:active, a.quotejs:link, a.quotejs:visited {\r
+       color: #800000;\r
+       text-decoration: none;\r
+}\r
+\r
+a.quotejs:hover {\r
+       color: #d00;\r
+}\r
+\r
+.tn_thread {\r
+       width: 200px;\r
+       height: 100px;\r
+       margin: 0px 20px 20px 20px;\r
+       float: left;\r
+       background: #eed;\r
+       border: #ea8 1px solid;\r
+       text-align: center;\r
+}\r
+\r
+.tn_reply {\r
+       width: 100px;\r
+       height: 100px;\r
+       margin: 0px 20px 20px 20px;\r
+       float: left;\r
+       background: #eed;\r
+       border: #ea8 1px solid;\r
+       text-align: center;\r
+}\r
+\r
+#ad {\r
+       width: 300px;\r
+       margin: 0;\r
+       padding: 0;\r
+       position: absolute;\r
+       left: 50%;\r
+       margin-left:-394px; /* -300 - 10 - (468-300)/2 */\r
+       font-family: arial,helvetica, sans-serif;\r
+       font-size: 11px;\r
+}\r
+\r
+#ad div {\r
+       margin: 0;\r
+       padding: 0.4em;\r
+}\r
+\r
+#ad div.ad-title, #ad h3, #ad .jltp_foot {\r
+       text-align:center;\r
+       padding: 0;\r
+       margin: 0;\r
+       background: #EEAA88;\r
+       color: #800000;\r
+       font-size: 11px;\r
+}\r
+\r
+#ad div.ad-title a, .bottomAdFoot a, .bottomAdFoot a:hover, #ad .jltp_foot a, #ad h3 a {\r
+       font-family: arial,helvetica, sans-serif;\r
+       color: #800000;\r
+}\r
+\r
+#ad div.ad-text a, #ad div.jltp a {\r
+       font-family: arial,helvetica, sans-serif;\r
+}\r
+#ad .jltp .itm { padding: 0.2em; }\r
+#ad .jltp { \r
+       overflow:hidden; \r
+       width: 120px; \r
+       padding: 0; \r
+       height: 240px; \r
+}\r
+#ad .jltp_foot { \r
+       position:absolute; \r
+       bottom: 0; \r
+       height:16px; \r
+       width:100%; \r
+       text-align: center; \r
+}\r
+\r
+.adHeadline {\r
+       font-family: arial,helvetica, sans-serif;\r
+       font-size: 11px;\r
+       font-weight: normal;\r
+}\r
+\r
+.adText {\r
+       font-family: arial,helvetica, sans-serif;\r
+       font-size: 11px;\r
+       font-weight: normal;\r
+       text-decoration: none;\r
+       color: #800000;\r
+}\r
+\r
+.bottomAdTitle {\r
+       font-family: arial,helvetica, sans-serif;\r
+       background: #EEAA88;\r
+       color: #800000;\r
+}\r
+\r
+#bottomAd {\r
+       height: 52px;\r
+       font-size: 11px;\r
+}\r
+\r
+#bottomAdOuter {\r
+       width: 600px;\r
+       border: 1px solid #EEAA88;\r
+       font-size: 11px;\r
+}\r
+\r
+.spoiler a.quotelink, .spoiler .unkfunc {\r
+       color: inherit;\r
+}\r
+\r
+.exif {\r
+       display: none;\r
+       font-family: arial,helvetica, sans-serif;\r
+       font-size: xx-small;\r
+}\r
+\r
+.exif td {\r
+       font-family: arial,helvetica, sans-serif;\r
+       font-size: xx-small;\r
+}\r
+\r
+.exif td b {\r
+       font-weight: 800;\r
+       text-decoration: underline;\r
+       font-size: x-small;\r
+}\r
+\r
+#header {\r
+       position: absolute;\r
+       top: 2px;\r
+       left: 5px;\r
+       right: 5px;\r
+}\r
+\r
+* html #header {\r
+       width: 100%;\r
+}\r
+\r
+#navtop, #navbot {\r
+       left: 0px;\r
+       float: left;\r
+}\r
+\r
+#navtopr, #navbotr {\r
+       right: 0px;\r
+       display: block;\r
+       float: right;\r
+       text-align: right;\r
+}\r
+\r
+#header, #navbot, #navbotr { font-size: 9pt; color: #b86; }\r
+#header a, #navbot a, #navbotr a, .pages td a  { font-weight: normal; padding: 1px; text-decoration: none; color: #800; }\r
+#header a:hover, #navbot a:hover, #navbotr a:hover, .pages td a:hover { color: #d00; }\r
+#footer { clear: both; padding-top: 10px; }\r
+#footer center font { font-size: 7pt; }\r
+.pages td a { color: #00e; }\r
+\r
+td.replyhl { border: 1px solid #D99F91; border-left: none; border-top: none; padding: 2px; }\r
+td.deletebuttons input.checkbox { margin: 1px 2px 1px 2px; }\r
+div.logo img { margin: 5px 0px 5px 0px; }\r
+\r
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">\r
+</script>\r
+<script type="text/javascript">\r
+_uacct = "UA-1858022-1";\r
+urchinTracker();\r
+</script>\r
+\r
+\r
diff --git a/data/css/yotsubablue.css b/data/css/yotsubablue.css
new file mode 100755 (executable)
index 0000000..34c3eaa
--- /dev/null
@@ -0,0 +1,320 @@
+body {\r
+       font-family: arial,helvetica,sans-serif;\r
+       font-size: 10pt;\r
+       background: #EEF2FF url(../icon/fade-blue.png) top center repeat-x;\r
+       color: #000000;\r
+       padding-left: 5px;\r
+       padding-right: 5px;\r
+       margin-right: 0px;\r
+       margin-left: 0px;\r
+       margin-top: 5px;\r
+}\r
+\r
+td { font-size: 10pt; padding:0; margin:0; }\r
+td.reply { border: 1px solid #B7C5D9; border-left: none; border-top: none; padding: 2px; }\r
+\r
+blockquote { font-size: 10pt; }\r
+.doubledash { color: #B7C5D9; }\r
+.inputtext {\r
+       margin: 0;\r
+       margin-right: 2px; \r
+       padding: 1px 4px;\r
+       border: 1px solid #aaa;\r
+       outline: none;\r
+       font-family: arial,helvetica,sans-serif; \r
+       font-size: 10pt;\r
+}\r
+input.inputtext { height: 1.75em; }\r
+td > .inputtext { height: auto; padding-top: 2px; padding-bottom: 3px; }\r
+.inputtext:focus { border: 1px solid #9988EE; }\r
+.logo img { border: 1px solid #34345C; }\r
+.logo b span { font-family: tahoma;  }\r
+.logo span { font-size: 28px; letter-spacing: -2px; }\r
+hr { border: none; border-top: 1px solid #B7C5D9; height: 0px; }\r
+.postblock { border: 1px solid #000; font-size: 10pt; padding: 0px 5px;  }\r
+.rules { font-size: 10pt; }\r
+.rules a { text-decoration: none; }\r
+\r
+form a img { margin-top: 3px; }\r
+\r
+iframe, .rotating { background: #D6DAF0; border-right: 1px solid #B7C5D9; border-bottom: 1px solid #B7C5D9; }\r
+\r
+.pages { border: none; background:#D6DAF0; border-right: 1px solid #B7C5D9; border-bottom: 1px solid #B7C5D9;  }\r
+.pages td { border: none; padding: 1px 5px; }\r
+.pages td { color: #89a; }\r
+.pages td b { color: #000; }\r
+\r
+.deletebuttons { text-align: right; }\r
+.deletebuttons br { display: none; }\r
+\r
+a, a:visited {\r
+       color: #34345C;\r
+}\r
+\r
+a:hover {\r
+       color: #DD0000;\r
+}\r
+\r
+a.quotelink {\r
+       color: #DD0000;\r
+}\r
+\r
+.logo {\r
+       clear: both;\r
+       text-align: center;\r
+       font-size: 24pt;\r
+       color: #AF0A0F;\r
+       width: 100%;\r
+}\r
+\r
+form {\r
+       margin-top: 0px;\r
+}\r
+\r
+.rules {\r
+       width: 468px;\r
+       font-size: 10px;\r
+}\r
+\r
+.rules a, .rules a:visited, .rules a:link {\r
+}\r
+\r
+.rules > li {\r
+       list-style: none;\r
+}\r
+.rules > li:before { content: "\2022 \20"; }\r
+\r
+.postblock {\r
+       background: #9988EE;\r
+       color: #000000;\r
+       font-weight: 800;\r
+}\r
+\r
+.footer {\r
+       text-align: center;\r
+       font-size: 12px;\r
+}\r
+\r
+.unkfunc {\r
+       color: #789922;\r
+}\r
+\r
+.filesize {\r
+       text-decoration: none;\r
+}\r
+\r
+.filesize span, span.postername, span.filetitle, span.commentpostername {\r
+       unicode-bidi: embed;\r
+}\r
+\r
+.filetitle, .replytitle {\r
+       color: #0F0C5D;\r
+       font-weight: 800;\r
+}\r
+\r
+.postername, .commentpostername {\r
+       color: #117743;\r
+       font-weight: 800;\r
+}\r
+\r
+.postertrip {\r
+       background: inherit;\r
+       color: #228854;\r
+}\r
+\r
+.oldpost {\r
+       background: inherit;\r
+       color: #0F0C5D;\r
+       font-weight: 800;\r
+}\r
+\r
+.omittedposts, .abbr {\r
+       color: #070707;\r
+}\r
+\r
+.reply {\r
+       background: #D6DAF0;\r
+       color: #000000;\r
+}\r
+\r
+.replyhl {\r
+       background: #D6BAD0;\r
+       color: #000000;\r
+}\r
+\r
+.doubledash {\r
+       vertical-align: top;\r
+       clear: both;\r
+       float: left;\r
+}\r
+\r
+a.quotejs:active, a.quotejs:link, a.quotejs:visited {\r
+       color: #000000;\r
+       text-decoration: none;\r
+}\r
+\r
+a.quotejs:hover {\r
+       color: #d00;\r
+}\r
+\r
+.tn_thread {\r
+       width: 200px;\r
+       height: 100px;\r
+       margin: 0px 20px 20px 20px;\r
+       float: left;\r
+       background: #eef2ff;\r
+       border: #98e 1px solid;\r
+       text-align: center;\r
+}\r
+\r
+.tn_reply {\r
+       width: 100px;\r
+       height: 100px;\r
+       margin: 0px 20px 20px 20px;\r
+       float: left;\r
+       background: #eef2ff;\r
+       border: #98e 1px solid;\r
+       text-align: center;\r
+}\r
+\r
+#ad {\r
+       width: 300px;\r
+       margin: 0;\r
+       padding: 0;\r
+       position: absolute;\r
+       left: 50%;\r
+       margin-left: -394px;\r
+       font-family: arial,helvetica, sans-serif;\r
+       font-size: 11px;\r
+}\r
+\r
+#ad div {\r
+       margin: 0;\r
+       padding: 0.4em;\r
+}\r
+\r
+#ad div.ad-title, #ad h3, #ad .jltp_foot {\r
+       text-align: center;\r
+       padding: 0;\r
+       margin: 0;\r
+       background: #98E;\r
+       color: #000000;\r
+       font-size: 11px;\r
+}\r
+\r
+#ad div.ad-title a, .bottomAdFoot a, .bottomAdFoot a:hover, #ad .jltp_foot a, #ad h3 a {\r
+       font-family: arial,helvetica, sans-serif;\r
+       color: #000000;\r
+}\r
+\r
+#ad div.ad-text a, #ad div.jltp a {\r
+       font-family: arial,helvetica, sans-serif;\r
+}\r
+#ad .jltp .itm { padding: 0.2em; }\r
+#ad .jltp {\r
+        overflow:hidden;\r
+        width: 120px;\r
+        padding: 0;\r
+        height: 240px;\r
+}\r
+#ad .jltp_foot {\r
+        position:absolute;\r
+        bottom: 0;\r
+        height:16px;\r
+        width:100%;\r
+        text-align: center;\r
+}\r
+.adHeadline {\r
+       font-family: arial,helvetica, sans-serif;\r
+       font-size: 11px;\r
+       font-weight: normal;\r
+}\r
+\r
+.adText {\r
+       font-family: arial,helvetica, sans-serif;\r
+       font-size: 11px;\r
+       font-weight: normal;\r
+       text-decoration: none;\r
+       color: #000;\r
+}\r
+\r
+.bottomAdTitle {\r
+       font-family: arial,helvetica, sans-serif;\r
+       background: #98E;\r
+       color: #000000;\r
+}\r
+\r
+#bottomAd {\r
+       height: 52px;\r
+       font-size: 11px;\r
+}\r
+\r
+#bottomAdOuter {\r
+       width: 600px;\r
+       border: 1px solid #98E;\r
+       font-size: 11px;\r
+}\r
+\r
+.spoiler a.quotelink, .spoiler .unkfunc {\r
+       color: inherit;\r
+}\r
+\r
+.exif {\r
+       display: none;\r
+       font-family: arial,helvetica, sans-serif;\r
+       font-size: xx-small;\r
+}\r
+\r
+.exif td {\r
+       font-family: arial,helvetica, sans-serif;\r
+       font-size: xx-small;\r
+}\r
+\r
+.exif td b {\r
+       font-weight: 800;\r
+       text-decoration: underline;\r
+       font-size: x-small;\r
+}\r
+\r
+#header {\r
+       position: absolute;\r
+       top: 2px;\r
+       left: 5px;\r
+       right: 5px;\r
+}\r
+\r
+* html #header {\r
+       width: 100%;\r
+}\r
+\r
+#navtop, #navbot {\r
+       left: 0px;\r
+       float: left;\r
+}\r
+\r
+#navtopr, #navbotr {\r
+       right: 0px;\r
+       display: block;\r
+       float: right;\r
+       text-align: right;\r
+}\r
+\r
+#header, #navbot, #navbotr { font-size: 9pt; color: #89a; }\r
+#header a, #navbot a, #navbotr a, .pages td a  { font-weight: normal; padding: 1px; text-decoration: none; color: #34345C; }\r
+#header a:hover, #navbot a:hover, #navbotr a:hover, .pages td a:hover { color: #d00; }\r
+#footer { clear: both; padding-top: 10px; }\r
+#footer center font { font-size: 7pt; }\r
+.pages td a { color: #34345C; }\r
+\r
+td.replyhl { border: 1px solid #BA9DBF; border-left: none; border-top: none; padding: 2px; }\r
+td.deletebuttons input.checkbox { margin: 1px 2px 1px 2px; }\r
+div.logo img { margin: 5px 0px 5px 0px; }\r
+\r
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">\r
+</script>\r
+<script type="text/javascript">\r
+_uacct = "UA-1858022-1";\r
+urchinTracker();\r
+</script>\r
+\r
+\r
diff --git a/data/css/yotsubanome.css b/data/css/yotsubanome.css
new file mode 100755 (executable)
index 0000000..7fe711b
--- /dev/null
@@ -0,0 +1,43 @@
+/* Yotsubanome Channel Official CSS */
+/* palette1 #FFFF7A #FFFFAC #FFFFEE #808000 */
+/* palette2 [web safe] #FFFF66 #FFFF99 #FFFFCC #CCCC00 */
+html, body { background:#FFFFEE; color:#808000; font-size: 12pt; } /*~~~~*/\r
+/*small { font-size: 10pt; }*/
+a { color:#0000EE; }\r
+a:hover { text-decoration: none; background-color: #FFFF00; color: #000000; }
+.adminbar { text-align:right; clear:both; float:right; }
+.logo { clear:both; text-align:center; font-size:2em; color:#000000; width:100%; }
+.theader { background:#E04000; text-align:center; padding:2px; color:#FFFFFF; width:100%; }
+.catalogmode { background:#0040E0; text-align:center; padding:2px; color:#FFFFFF; width:100%; }
+.rules { font-size:0.7em; }
+.postblock { background:#FFFF7A; font-weight:800; } /*~~~~*/
+.footer { text-align:center; font-size:12px; font-family:serif; }
+.passvalid { background:#E08000; text-align:center; width:100%; color:#FFFFFF; }
+.dellist { font-weight: bold; text-align:center; }
+.delbuttons { text-align:center; padding-bottom:4px; }
+.managehead { background:#6080F6; color:#808000; padding:0px; }
+.postlists { background:#000000; width:100%; padding:0px; color:#808000; }
+.row1 { background:#F6F6F6; color:#808000; }
+.row2 { background:#D6D6F6; color:#808000; }
+.unkfunc { background:inert; color:#789922; }
+.unkfunc2 { background:inert; color:#696969; }
+.spoiler a.quotelink { color: inherit; }
+.filesize { text-decoration:none; }
+.filetitle { background:inherit; font-size:1.2em; color:#CCCC05; font-weight:800; }
+.postername { color:#117743; font-weight:bold; }
+.postertrip { color:#228854; }
+.oldpost { color:#CC1105; font-weight:800; }
+.omittedposts { color:#707070; }\r
+.reply { background:#FFFFAC; } /*~~~~*/\r
+.replyhl { background: #000000; color:#00FF00; border: 4px dashed #FFFF00; }
+.doubledash { vertical-align:top; clear:both; float:left; }
+.replytitle { background:inherit; font-size:1.2em; color:#CCCC05; font-weight:800; }
+.commentpostername { color:#117743; font-weight:800; }
+.thumbnailmsg { font-size: small; }
+.abbrev { color:#707070; }\r
+.highlight { background: #000000; color:#00FF00; }
+.inputtext { border: 2px solid #aaa; }\r
+td.inputtext { height: auto; }\r
+.inputtext:focus { border: 2px solid #8ae; }\r
+a.del { color:#000000; }
+.tn_reply { width: 86px; height: 86px; margin: 0px 20px 20px 20px; float: left; background: #000; border: #0D0 2px solid; text-align: center; }
diff --git a/data/icon/ba.gif b/data/icon/ba.gif
new file mode 100755 (executable)
index 0000000..fa1d375
Binary files /dev/null and b/data/icon/ba.gif differ
diff --git a/data/icon/boot.gif b/data/icon/boot.gif
new file mode 100755 (executable)
index 0000000..f04e528
Binary files /dev/null and b/data/icon/boot.gif differ
diff --git a/data/icon/closed.gif b/data/icon/closed.gif
new file mode 100755 (executable)
index 0000000..d178c7b
Binary files /dev/null and b/data/icon/closed.gif differ
diff --git a/data/icon/fade-blue.png b/data/icon/fade-blue.png
new file mode 100755 (executable)
index 0000000..dcc5159
Binary files /dev/null and b/data/icon/fade-blue.png differ
diff --git a/data/icon/fade.png b/data/icon/fade.png
new file mode 100755 (executable)
index 0000000..16d860b
Binary files /dev/null and b/data/icon/fade.png differ
diff --git a/data/icon/favicon.ico b/data/icon/favicon.ico
new file mode 100755 (executable)
index 0000000..d15ba90
Binary files /dev/null and b/data/icon/favicon.ico differ
diff --git a/data/icon/favicon.png b/data/icon/favicon.png
new file mode 100755 (executable)
index 0000000..44a2c1d
Binary files /dev/null and b/data/icon/favicon.png differ
diff --git a/data/icon/filedeleted.gif b/data/icon/filedeleted.gif
new file mode 100755 (executable)
index 0000000..0998f82
Binary files /dev/null and b/data/icon/filedeleted.gif differ
diff --git a/data/icon/futaba.gif b/data/icon/futaba.gif
new file mode 100755 (executable)
index 0000000..c859e5e
Binary files /dev/null and b/data/icon/futaba.gif differ
diff --git a/data/icon/gchan_banner.gif b/data/icon/gchan_banner.gif
new file mode 100755 (executable)
index 0000000..297ddf1
Binary files /dev/null and b/data/icon/gchan_banner.gif differ
diff --git a/data/icon/kagami.gif b/data/icon/kagami.gif
new file mode 100644 (file)
index 0000000..5baa182
Binary files /dev/null and b/data/icon/kagami.gif differ
diff --git a/data/icon/kent_banner.gif b/data/icon/kent_banner.gif
new file mode 100644 (file)
index 0000000..8e0436f
Binary files /dev/null and b/data/icon/kent_banner.gif differ
diff --git a/data/icon/letsphp.gif b/data/icon/letsphp.gif
new file mode 100755 (executable)
index 0000000..75aeb4f
Binary files /dev/null and b/data/icon/letsphp.gif differ
diff --git a/data/icon/moeren.jpg b/data/icon/moeren.jpg
new file mode 100755 (executable)
index 0000000..8575eaf
Binary files /dev/null and b/data/icon/moeren.jpg differ
diff --git a/data/icon/nothumb.gif b/data/icon/nothumb.gif
new file mode 100755 (executable)
index 0000000..e20b763
Binary files /dev/null and b/data/icon/nothumb.gif differ
diff --git a/data/icon/shiokara.gif b/data/icon/shiokara.gif
new file mode 100755 (executable)
index 0000000..5d74e24
Binary files /dev/null and b/data/icon/shiokara.gif differ
diff --git a/data/icon/sticky.gif b/data/icon/sticky.gif
new file mode 100755 (executable)
index 0000000..da4ec3a
Binary files /dev/null and b/data/icon/sticky.gif differ
diff --git a/data/icon/yotsubanome_banner.png b/data/icon/yotsubanome_banner.png
new file mode 100755 (executable)
index 0000000..f55d404
Binary files /dev/null and b/data/icon/yotsubanome_banner.png differ
diff --git a/data/js/iedivfix.js b/data/js/iedivfix.js
new file mode 100755 (executable)
index 0000000..7f7fe6c
--- /dev/null
@@ -0,0 +1,10 @@
+// IE不支援display: table,故用此方法\r
+document.write('<style type="text/css">.reply { display: inline ; zoom: 1; }</style>');\r
+\r
+// 解決IE顯示回應區塊時排在同一行的問題\r
+function IEdivfix(){\r
+       var divs=document.getElementsByTagName('div'),divs_cnt=divs.length;\r
+       for(i=0;i<divs_cnt;i++)\r
+               if(divs[i].className.substr(0,5)=='reply') divs[i].insertAdjacentHTML('afterEnd','<br />');\r
+}\r
+hookPresetFunction(IEdivfix); // Hook on
\ No newline at end of file
diff --git a/data/js/script.js b/data/js/script.js
new file mode 100755 (executable)
index 0000000..e2a1a3a
--- /dev/null
@@ -0,0 +1,292 @@
+eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('8 V=14;8 K=0;8 G=[];8 15=[[2h,24,20],[1R,1I,1F],[1A,2t,4]];8 11=[[29,23,22,1Z,1X,1Q],[1L,1H,1G,1E,1C,1z]];h $g(i){t o.2g(i)}h 2c(){8 N=I(\'1q\'),E=I(\'21\'),x;5((x=$g(\'H\'))){x.k=N}5((x=$g(\'1T\'))){x.k=E}}h 1P(){8 P=I(\'1K\'),d=o,1g=d.A.u;v(8 i=0;i<1g;i++){5(d.A[i].1a){d.A[i].1a.k=P}}}h I(a){8 b,z,w=0,y=0,F;b=\' \'+o.17+\';\';8 c=b.u;2q(w<c){y=b.Z(\';\',w);z=b.10(w+1,y);F=z.Z(\'=\');5(z.10(0,F)==a){t 2i(z.10(F+1,y-w-1))}w=y+1}t\'\'}h 1s(a,b){8 c=12 2f();c.2d(c.2b()+2a*7);o.17=a+\'=\'+1w(b)+\'; 26=\'+c.25()}h c(){8 a,j,J,Y;1p{5(!$g(\'1n\')){t R}a=$g(\'1n\').k;5(!a&&!$g(\'Q\').k){X(W[0]);t 14}5(a){J=0;Y=1m.u;v(j=0;j<Y;j++){5(a.1Y(a.u-3,3).1W()==1m[j]){J=1;1U}}5(!J){X(W[1]);t 14}}D(\'Q\');D(\'H\');D(\'1S\');5(1k.1O){o.A[0].1N.k=a}o.A[0].1M.1J=R}18(e){}5($g(\'H\').k){1s(\'1q\',$g(\'H\').k)}}h 1b(){5(!o.1f){t}8 a,U=o.1f(\'a\');8 b=U.u;v(8 i=0;i<b;i++){a=U[i];5(a.T(\'1e\')){5(a.T(\'1d\')==\'1i\'){a.1c=\'1i\'}5(a.T(\'1d\')==\'1h\'){a.1c=\'1h\'}}}}h 1D(){$g("1j").m=\'\';$g("19").m=\'\';$g("B").m=\'C\';$g("C").m=\'B\'}h 1B(){$g("1j").m=\'1V\';$g("19").m=\'B\';$g("B").m=\'B\';$g("C").m=\'C\'}h 1l(a){1p{$g(\'Q\').1y()}18(e){}$g(\'Q\').k+=\'>>1x.\'+a+"\\r\\n"}h S(a,b){8 c=$g(\'r\'+a);5(c){5(b){c.m=c.m.16(\' 1o\',\'\')}2s{5(K){S(K,R)}K=a;c.m+=\' 1o\'}}}h D(a){8 b=$g(a);8 c=1w(b.k).2r();8 d=/%2p(6[2n]|7[0-1v-f]|2l)[0-1v-f]/;5(c.13(d)!==2j){X(W[2]);1r(b)}}h 1r(a){8 b=a.k,i=0,p=0;8 c=15.u,s;v(i=0;i<c;i++){s=15[i];v(p=0;p<=s[2];p++){b=b.16(12 M(O.L(s[0]+p),\'g\'),O.L(s[1]+p))}}c=11[0].2e;v(i=0;i<c;i++){s=11;b=b.16(12 M(O.L(s[0][i]),\'g\'),O.L(s[1][i]))}a.k=b}h 2k(a){5(1u a==\'h\'){G.2m(a)}}h 1t(){5(V){t}8 i,l=G.u,f;V=R;1b();v(i=0;i<l;i++){f=G[i];5(1u f==\'h\'){f()}}8 a=2o.1e;5(a.Z(\'?28=\')){5(a.13(/#[27]([0-9]+)$/)){S(M.$1)}5(a.13(/#q([0-9]+)$/)){1l(M.$1)}}}1k.2u=1t;',62,155,'|||||if|||var|||||||||function|||value||className||document||||Tbl|return|length|for|xx1|obj|xx2|tmp2|forms|hide|show|check_sakura||xx3|arrPresetFunc|fname|getCookie|ext_allowed|previous_replyhlno|fromCharCode|RegExp||String||fcom|true|replyhl|getAttribute|anchors|preset_sensor|msgs|alert|ext_length|indexOf|substring|arrSakuraTblsp|new|match|false|arrSakuraTbl|replace|cookie|catch|postform_tbl|pwd|fixalllinks|target|rel|href|getElementsByTagName|forms_length|_blank|_top|postform|window|quote|ext|fupfile|replyhl|try|namec|replace_sakura|setCookie|preset|typeof|9a|escape|No|focus|14446|63486|hideform|12445|showform|12542|85|12541|12540|12449|disabled|pwdc|12293|sendbtn|upfile_path|clipboardData|l2|63213|63306|fsub|femail|break|hide_btn|toUpperCase|63212|substr|63211|82|emailc|63210|63219|12353|toGMTString|expires|rq|res|63216|86400000|getTime|l1|setTime|legnth|Date|getElementById|63223|unescape|null|hookPresetFunction|80|push|ef|location|uf|while|toLowerCase|else|12535|onload'.split('|'),0,{}))
+/* Pixmicat! functions ^ */
+
+/* Futaba / Wakaba / Yotsubanome Functions */
+/*\r
+// Hide postform in thread index\r
+set_cookie ('toggle_upform', 0, 365);\r
+\r
+// Hide Staff password field\r
+set_cookie ('toggle_spform', 0, 365);\r
+*/\r
+function toggle (button, area)\r
+{\r
+       if (get_cookie ('toggle_' + area) == 1)\r
+       { set_cookie ('toggle_' + area, 0, 365); }\r
+       else\r
+       { set_cookie ('toggle_' + area, 1, 365); }\r
+\r
+       showstate (button, area);\r
+\r
+       return;\r
+}\r
+\r
+//function showstate (button, area)\r
+function showstate (button)\r
+{\r
+       var tag = document.getElementById (button);\r
+//     var tags = document.getElementsByName ('toggle');\r
+\r
+//     for (go = 0; go < tags.length; go ++)\r
+//     {\r
+//             var tag = tags[go];\r
+\r
+               if (!tag) { return; }\r
+               if (!tag.getAttribute ('rel') ) { return; }\r
+\r
+               var rel = tag.getAttribute ('rel').split (',');\r
+\r
+               var relc        = rel.length;\r
+               var area        = rel[0];\r
+\r
+               if (relc > 1)\r
+               {\r
+                       var show        = rel[1];\r
+                       var hide        = rel[2];\r
+               }\r
+\r
+               tag.onclick = function () { toggle (button, area); }\r
+\r
+               var tog = document.getElementById (area);\r
+\r
+               if (get_cookie ('toggle_' + area) == 1)\r
+               {\r
+                       tog.style.display       = '';\r
+                       if (relc > 1) { tag.innerHTML   = hide; }\r
+               }\r
+               else\r
+               {\r
+                       tog.style.display       = 'none';\r
+                       if (relc > 1) { tag.innerHTML   = show; }\r
+               }\r
+//     }\r
+\r
+       return;\r
+}\r
+\r
+\r
+function replace_all (str, from, to)\r
+{\r
+       var idx = str.indexOf (from);\r
+\r
+       while (idx > -1 )\r
+       {\r
+               str = str.replace (from, to);\r
+               idx = str.indexOf (from);\r
+       }\r
+       return str;\r
+}\r
+\r
+function highlight (post)\r
+{\r
+       var cello       = document.getElementsByTagName ('blockquote');\r
+       var cells       = document.getElementsByTagName ('td');\r
+       var reply       = document.getElementById ('post' + post);\r
+\r
+       for (var i = 0; i < cello.length; i ++)\r
+       {\r
+               if (cello[i].className == 'replyhl')\r
+               { cello[i].className    = 'threadpost'; }\r
+       }\r
+\r
+       for (var i = 0; i < cells.length; i ++)\r
+       {\r
+               if (cells[i].className == 'replyhl')\r
+               { cells[i].className    = 'reply'; }\r
+       }\r
+\r
+       if (reply)\r
+       {\r
+               reply.className = 'replyhl';\r
+               var match       = /^([^#r]*)/.exec (document.location.toString () );\r
+               document.location       = match[1] + '#r' + post;\r
+       }\r
+}\r
+\r
+function size_textarea (id, rows) { document.getElementById(id).com.setAttribute('rows', rows); }\r
+\r
+function get_password (name)\r
+{\r
+       var pass        = get_cookie (name);\r
+       if (pass) { return pass; }\r
+\r
+       var chars       = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';\r
+       var pass        = '';\r
+\r
+       for (var i = 0; i < 8; i ++)\r
+       {\r
+               var rnd = Math.floor (Math.random () * chars.length);\r
+               pass    += chars.substring (rnd, rnd + 1);\r
+       }\r
+\r
+       return (pass);\r
+}\r
+\r
+function get_cookie (name)\r
+{\r
+       with (document.cookie)\r
+       {\r
+               var reg = new RegExp ('(^|;\\s+)' + name + '=(.*?)(;|$)');\r
+               var hit = reg.exec (document.cookie);\r
+\r
+               if (hit && hit.length > 2)\r
+               { return unescape (replace_all (hit[2], '+', '%20') ); }\r
+               else return '';\r
+       }\r
+}\r
+\r
+function set_cookie (name, value, days)\r
+{\r
+       if (days)\r
+       {\r
+               var date        = new Date ();\r
+               date.setTime (date.getTime () + (days * 24 * 60 * 60 * 1000) );\r
+               var expires     = '; expires=' + date.toGMTString ();\r
+       }\r
+       else expires    = '';\r
+\r
+       document.cookie = name + '=' + value + expires + '; path=/';\r
+}\r
+\r
+function set_stylesheet (styletitle, norefresh)\r
+{\r
+       set_cookie ('yo_style', styletitle, 365);\r
+\r
+       var links       = document.getElementsByTagName ('link');\r
+       var found       = false;\r
+\r
+       for (var i = 0; i < links.length; i ++)\r
+       {\r
+               var rel = links[i].getAttribute ('rel');\r
+               var ttl = links[i].getAttribute ('title');\r
+\r
+               if (rel.indexOf ('style') != -1 && ttl)\r
+               {\r
+                       links[i].disabled       = true; // IE needs this to work. IE needs to die.\r
+\r
+                       if (styletitle == ttl)\r
+                       {\r
+                               links[i].disabled       = false;\r
+                               found   = true;\r
+                       }\r
+               }\r
+       }\r
+\r
+       if (!found) set_preferred_stylesheet ();\r
+}\r
+\r
+function set_preferred_stylesheet ()\r
+{\r
+       var links       = document.getElementsByTagName ('link');\r
+\r
+       for (var i = 0; i < links.length; i ++)\r
+       {\r
+               var rel = links[i].getAttribute ('rel');\r
+               var ttl = links[i].getAttribute ('title');\r
+\r
+               if (rel.indexOf ('style') != -1 && ttl)\r
+               { links[i].disabled     = (rel.indexOf ('alt') != -1); }\r
+       }\r
+}\r
+\r
+function get_active_stylesheet ()\r
+{\r
+       var links       = document.getElementsByTagName ('link');\r
+\r
+       for (var i = 0; i < links.length; i ++)\r
+       {\r
+               var rel = links[i].getAttribute ('rel');\r
+               var ttl = links[i].getAttribute ('title');\r
+\r
+               if (rel.indexOf ('style') != -1 && ttl && !links[i].disabled)\r
+               { return ttl; }\r
+       }\r
+       return null;\r
+}\r
+\r
+function get_preferred_stylesheet ()\r
+{\r
+       var links       = document.getElementsByTagName ('link');\r
+\r
+       for (var i=0;i<links.length;i++)\r
+       {\r
+               var rel = links[i].getAttribute ('rel');\r
+               var ttl = links[i].getAttribute ('title');\r
+\r
+               if (rel.indexOf ('style') != -1 && rel.indexOf ('alt') == -1 && ttl)\r
+               { return ttl; }\r
+       }\r
+       return null;\r
+}\r
+\r
+\r
+// Fill postform / delform fields\r
+function set_inputs (id)\r
+{\r
+       if (document.getElementById (id) )\r
+       {\r
+               with (document.getElementById (id) )\r
+               {\r
+                       if (document.getElementById ('name') && !name.value)\r
+                       { name.value    = get_cookie ('namec'); }\r
+                       if (document.getElementById ('email') && !email.value)\r
+                       { link.value    = get_cookie ('emailc'); }\r
+                       if (document.getElementById ('pwd') && !pwd.value)\r
+                       { pwd.value     = get_password ('pwdc'); }\r
+                       if (document.getElementById ('noko') && get_cookie ('yo_noko') == 1)\r
+                       { noko.options[1].selected = true; }\r
+               }\r
+       }\r
+}\r
+\r
+function set_delpass (id)\r
+{\r
+       if (document.getElementById (id) )\r
+       {\r
+               with (document.getElementById (id) )\r
+               {\r
+                       if (document.getElementById ('pwd') )\r
+                       { pwd.value     = get_cookie ('pwdc'); }\r
+               }\r
+       }\r
+}\r
+\r
+\r
+window.onunload        = function (e)\r
+{\r
+       if (style_cookie)\r
+       {\r
+               var title       = get_active_stylesheet ();\r
+               set_cookie (style_cookie, title, 365);\r
+       }\r
+}\r
+\r
+window.onload  = function (e)\r
+{\r
+       var match;\r
+\r
+       if (match       = /#q([0-9]+)/.exec (document.location.toString () ) )\r
+       if (!document.forms.postform.com.value)\r
+       quote (match[1]);\r
+\r
+       if (match       = /#r([0-9]+)/.exec (document.location.toString () ) )\r
+       highlight (match[1]);\r
+\r
+       set_inputs ('postform');\r
+       set_delpass ('delform');\r
+}\r
+\r
+\r
+if (style_cookie)\r
+{\r
+       var cookie      = get_cookie (style_cookie);\r
+       var title       = cookie ? cookie : get_preferred_stylesheet ();\r
+       set_stylesheet (title);\r
+}\r
+\r
+function reppop(url) {\r
+day = new Date();\r
+id = day.getTime();\r
+window.open(url, id, 'toolbar=0,scrollbars=0,location=0,status=1,menubar=0,resizable=1,width=512,height=128');\r
+return false;  \r
+}
\ No newline at end of file
diff --git a/data/stylesheets.csv_daty b/data/stylesheets.csv_daty
new file mode 100644 (file)
index 0000000..7d6aed2
--- /dev/null
@@ -0,0 +1,9 @@
+yotsuba,四葉,yotsuba.css,,
+yotsubablue,四葉青,yotsubablue.css,,
+草葉,草葉,kusaba.css,,
+四葉の芽,四葉の芽,yotsubanome.css,default,
+burichan,ブリ,burichan.css,,
+futaba,双葉,futaba.css,,
+gurochan,guro,gurochan.css,,
+photon,pho,photon.css,,
+NULL,0,null.css,,
diff --git a/data/tplt/inc_yo-festival.tplt b/data/tplt/inc_yo-festival.tplt
new file mode 100755 (executable)
index 0000000..0db6b10
--- /dev/null
@@ -0,0 +1,199 @@
+<!-- Theme Description -->\r
+<!--&THEMENAME-->Yotsubanome-Festival Theme<!--/&THEMENAME-->\r
+<!--&THEMEVER-->v20100404<!--/&THEMEVER-->\r
+<!--&THEMEAUTHOR-->Pixmicat! Development Team and sparky4<!--/&THEMEAUTHOR-->\r
+\r
+<!-- Theme Settings -->\r
+\r
+<!-- Festival Theme Settings -->\r
+<!--&CLICKENTER-->1<!--/&CLICKENTER-->\r
+<!--&BLOCKWIDTH-->272px<!--/&BLOCKWIDTH-->\r
+<!--&BLOCKHEIGHT-->400px<!--/&BLOCKHEIGHT-->\r
+<!--&CENTERIMG-->1<!--/&CENTERIMG-->\r
+\r
+<!-- non-Festival Theme Settings (Replace "!--&" to "!---&" of above and replace "!---&" to "!--&" of below to activate ) -->\r
+<!---&CLICKENTER-->1<!--/&CLICKENTER-->\r
+<!---&BLOCKWIDTH-->99%<!--/&BLOCKWIDTH-->\r
+<!---&BLOCKHEIGHT-->auto<!--/&BLOCKHEIGHT-->\r
+<!---&CENTERIMG-->0<!--/&CENTERIMG-->\r
+\r
+<!-- Theme Blocks -->\r
+<!--&IMGSTYLE--><!--&IF(&CENTERIMG,'.img {margin:0;}','')--><!--/&IMGSTYLE-->\r
+<!--&HEADER--><?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-tw">\r
+<head>\r
+<meta http-equiv="Pragma" content="no-cache" />\r
+<meta http-equiv="Expires" content="Sat, 1 Jan 2000 00:00:00 GMT" />\r
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\r
+<meta http-equiv="Content-Language" content="{$LANGUAGE}" />\r
+<title>{$TITLE}</title>
+{$STYLE_LOAD}<link rel="stylesheet" type="text/css" href="{$CSS_DIR}main/style.css" />
+{$FAV_ICON}\r
+<style type="text/css"><!--/*--><![CDATA[/*><!--*/\r
+.grid {float: left; border: 2px #F0E0D6 solid; width: <!--&BLOCKWIDTH/-->;height: <!--&BLOCKHEIGHT/-->;<!--&IF(&CLICKENTER,'cursor: pointer; cursor: hand;','')--> overflow:auto; margin:2px; padding:0;}\r
+#page_switch table {border: 2px #F0E0D6 solid;}\r
+#page_switch table td {border:0}\r
+.reply { margin: 0.3ex 0.2ex 0.2ex 1em;}\r
+<!--&IF($RESTO,'','#postform {border: 2px #F0E0D6 solid;} #postform hr {display:none;}')-->\r
+<!--&IF($RESTO,'','<!--&IMGSTYLE/-->')-->\r
+/*]]>*/--></style><!--/&HEADER-->\r
+\r
+<!--&JSHEADER-->\r
+<script type="text/javascript"><!--//--><![CDATA[//><!--
+var msgs=['{$JS_REGIST_WITHOUTCOMMENT}','{$JS_REGIST_UPLOAD_NOTSUPPORT}','{$JS_CONVERT_SAKURA}'];\r
+var ext="{$ALLOW_UPLOAD_EXT}".toUpperCase().split("|");
+{$JSDONK}
+var boxclicked=0;\r
+//--><!]]></script>
+<script type="text/javascript" src="{$JS_DIR}script.js"></script>\r
+<!--[if lt IE 8]><script type="text/javascript" src="{$JS_DIR}iedivfix.js"></script><![endif]-->
+<!--/&JSHEADER-->\r
+\r
+<!--&TOPLINKS-->\r
+<div id="heading"><div class="adminbar" id="header">\r
+{$HOOKLINKS} {$TOP_LINKS} {$REFRESH} {$STATUS} {$SEARCH} {$HOME} {$ADMIN}
+</div>\r
+<!--/&TOPLINKS-->\r
+\r
+<!--&BODYHEAD-->\r
+<body class="mainpage">\r
+<!--&TOPLINKS/-->
+<div class="logo">\r
+<div style="font-size: 20pt; font-weight: bold;">{$TITLEHEAD}</div><!--&IF($TITLECOM,'<div class="sublogo">{$TITLECOM}</div>','')-->
+</div><hr class="top" size="1" /></div>\r
+<!--/&BODYHEAD-->\r
+\r
+<!--&POSTFORM-->\r
+<form action="{$SELF}" method="post" enctype="multipart/form-data" onsubmit="return c();" id="postform_main">\r
+<div class="postarea" id="postform">\r
+<!--&IF($FORMTOP,'{$FORMTOP}','')-->\r
+<input type="hidden" name="mode" value="{$MODE}" />\r
+<input type="hidden" name="MAX_FILE_SIZE" value="{$MAX_FILE_SIZE}" />\r
+<input type="hidden" name="upfile_path" value="" />\r
+<!--&IF($RESTO,'{$RESTO}','')-->\r
+<div style="text-align: center;">\r
+<table cellpadding="1" cellspacing="1" id="postform_tbl" style="margin: 0px auto; text-align: left;">\r
+<tr><td class="postblock"><b>{$FORM_NAME_TEXT}</b></td><td>{$FORM_NAME_FIELD}</td></tr>\r
+<tr><td class="postblock"><b>{$FORM_EMAIL_TEXT}</b></td><td>{$FORM_EMAIL_FIELD}</td></tr>\r
+<tr><td class="postblock"><b>{$FORM_TOPIC_TEXT}</b></td><td>{$FORM_TOPIC_FIELD}{$FORM_SUBMIT}</td></tr>\r
+<tr><td class="postblock"><b>{$FORM_COMMENT_TEXT}</b></td><td>{$FORM_COMMENT_FIELD}</td></tr>\r
+<!--&IF($FORM_ATTECHMENT_FIELD,'<tr><td class="postblock"><b>{$FORM_ATTECHMENT_TEXT}</b></td><td>{$FORM_ATTECHMENT_FIELD}','')--><!--&IF($FORM_NOATTECHMENT_FIELD,' [{$FORM_NOATTECHMENT_FIELD}<label for="noimg">{$FORM_NOATTECHMENT_TEXT}</label>]','')--><!--&IF($FORM_ATTECHMENT_FIELD,'</td></tr>','')-->
+<tr><td class="postblock"><b>{$FORM_DELETE_PASSWORD_TEXT}</b></td><td>{$FORM_DELETE_PASSWORD_FIELD}<small>{$FORM_DELETE_PASSWORD_NOTICE}</small></td></tr>\r
+<!--&IF($FORM_OPTION1_TEXT,'<tr><td class="postblock"><b>{$FORM_OPTION1_TEXT}</b></td>','')-->
+<!--&IF($FORM_CONTPOST_FIELD,'<td> [{$FORM_CONTPOST_FIELD}<label for="up_series">{$FORM_CONTPOST_TEXT}</label>]','')-->\r
+<!--&IF($FORM_OPTION1_TEXT,'</td></tr>','')-->
+{$FORM_EXTRA_COLUMN}\r
+<!--&IF($FORM_CATEGORY_FIELD,'<tr><td class="postblock"><b>{$FORM_CATEGORY_TEXT}</b></td><td>{$FORM_CATEGORY_FIELD}<small>{$FORM_CATEGORY_NOTICE}</small></td></tr>','')-->\r
+<tr><td colspan="2">\r
+<div class="rules" id="postinfo">\r
+<ul>{$FORM_NOTICE}\r
+<!--&IF($FORM_NOTICE_STORAGE_LIMIT,'{$FORM_NOTICE_STORAGE_LIMIT}','')-->\r
+{$HOOKPOSTINFO}\r
+{$ADDITION_INFO}\r
+</ul>\r
+<noscript><div>{$FORM_NOTICE_NOSCRIPT}</div></noscript>\r
+</div>\r
+</td></tr>\r
+</table>\r
+</div>\r
+<script type="text/javascript">l1();</script>\r
+<hr />\r
+</div>\r
+</form>\r
+<!--&IF($FORMBOTTOM,'{$FORMBOTTOM}','')-->\r
+<!--/&POSTFORM-->\r
+\r
+<!--&FOOTER-->\r
+<div class="footer" id="footer">\r
+{$FOOTER}\r
+<script type="text/javascript">preset();</script>\r
+</div>\r
+\r
+</body>\r
+</html>\r
+<!--/&FOOTER-->\r
+\r
+<!--&ERROR-->\r
+<div id="error">\r
+<div style="text-align: center; font-size: 1.5em; font-weight: bold;">\r
+<span style="color: red;">{$MESG}</span><p />\r
+<a href="{$SELF2}">{$RETURN_TEXT}</a> <a href="javascript:history.back();">{$BACK_TEXT}</a>\r
+</div>\r
+<hr />\r
+</div>\r
+<!--/&ERROR-->\r
+\r
+\r
+<!--&CLICKENTER_PROP--> onclick="if (!boxclicked) window.location='{$SELF}?res={$NO}';boxclicked=0;"<!--/&CLICKENTER_PROP-->\r
+<!--&THREAD_CLICKENTER--><div class="grid"<!--&IF(&CLICKENTER,'<!--&CLICKENTER_PROP/-->','')-->><!--/&THREAD_CLICKENTER-->\r
+<!--&IMGARRANGE--><!--&IF(&CENTERIMG,'<!--&IMG_CENTER/-->','<!--&IMG_LEFT/-->')--><!--/&IMGARRANGE-->\r
+<!--&IMG_CENTER--><!--&IF($IMG_BAR,'<table align="center"><tr><td>','')-->{$IMG_SRC}<!--&IF($IMG_BAR,'</td></tr></table>','')--><!--/&IMG_CENTER-->\r
+<!--&IMG_LEFT--><!--&IF($IMG_BAR,'<br />','')-->{$IMG_SRC}<!--/&IMG_LEFT-->\r
+\r
+<!--&THREAD-->\r
+<!--&IF($RESTO,'','<!--&THREAD_CLICKENTER/-->')-->
+<!--Thread No.{$NO}-->
+<div class="threadpost" id="r{$NO}"><input type="checkbox" name="{$NO}" value="delete" onclick="boxclicked=1;" /><span class="filetitle">{$SUB}</span>\r
+{$NAME_TEXT}<span class="postername">{$NAME}</span> {$NOW} {$QUOTEBTN}&nbsp;&nbsp;{$REPLYBTN}</div>\r
+{$IMG_BAR}<!--&IF($RESTO,'<!--&IMG_LEFT/-->','<!--&IMGARRANGE/-->')-->\r
+{$WARN_OLD}{$WARN_BEKILL}{$WARN_ENDREPLY}{$WARN_HIDEPOST}\r
+<div class="blockquote">{$COM}</div>\r
+<!--&IF($CATEGORY,'<div class="category">{$CATEGORY_TEXT}{$CATEGORY}</div>','')-->\r
+<!--/&THREAD-->\r
+\r
+<!--&REPLY-->
+                               <!--Reply No.{$NO}-->
+<table><tr><td class="doubledash">…</td><td class="reply" id="r{$NO}">\r
+<input type="checkbox" name="{$NO}" value="delete" onclick="boxclicked=1;" /><span class="replytitle">{$SUB}</span>&nbsp;
+{$NAME_TEXT}<span class="commentpostername">{$NAME}</span> [{$NOW}] {$QUOTEBTN}&nbsp;<!--&IF($IMG_BAR,'<br />','')-->{$IMG_BAR}<!--&IF($IMG_SRC,'<br />','')-->{$IMG_SRC}\r
+{$WARN_BEKILL}<div class="blockquote">{$COM}</div>\r
+<!--&IF($CATEGORY,'<div class="category">{$CATEGORY_TEXT}{$CATEGORY}</div>','')-->\r
+</td></tr></table>\r
+<!--/&REPLY-->\r
+\r
+<!--&SEARCHRESULT-->\r
+<div class="threadpost">\r
+<span class="title">{$SUB}</span>\r
+{$NAME_TEXT}<span class="name">{$NAME}</span> {$NOW} No.{$NO}\r
+<div class="blockquote">{$COM}</div>\r
+<!--&IF($CATEGORY,'<div class="category">{$CATEGORY_TEXT}{$CATEGORY}</div>','')-->\r
+</div>\r
+<!--&REALSEPARATE/-->\r
+<!--/&SEARCHRESULT-->\r
+\r
+<!--&THREADSEPARATE-->\r
+<!--&IF($RESTO,'<hr />','</div>')-->\r
+<!--/&THREADSEPARATE-->\r
+\r
+<!--&REALSEPARATE-->\r
+<hr />\r
+<!--/&REALSEPARATE-->\r
+\r
+<!--&DELFORM-->\r
+<div id="del">\r
+<table style="float: right;">\r
+<tr><td align="center" style="white-space: nowrap;">\r
+{$DEL_HEAD_TEXT}[{$DEL_IMG_ONLY_FIELD}<label for="onlyimgdel">{$DEL_IMG_ONLY_TEXT}</label>]<br />\r
+{$DEL_PASS_TEXT}{$DEL_PASS_FIELD}{$DEL_SUBMIT_BTN}
+{$STYLE_BAR}\r
+</td></tr>\r
+</table>\r
+</div>\r
+<!--/&DELFORM-->\r
+\r
+<!--&MAIN-->\r
+<div id="contents">\r
+{$THREADFRONT}\r
+<form action="{$SELF}" method="post">\r
+<div id="threads" style="clear:both;">\r
+{$THREADS}\r
+</div>\r
+{$THREADREAR}\r
+<div style="clear:both"></div>\r
+<!--&DELFORM/-->\r
+<script type="text/javascript">l2();</script>\r
+</form>\r
+{$PAGENAV}\r
+</div>\r
+<!--/&MAIN-->
\ No newline at end of file
diff --git a/data/tplt/inc_yo-uploader.tplt b/data/tplt/inc_yo-uploader.tplt
new file mode 100755 (executable)
index 0000000..77195cd
--- /dev/null
@@ -0,0 +1,190 @@
+<!-- Theme Description -->\r
+<!--&THEMENAME-->Yotsubanome Uploader-liked Theme<!--/&THEMENAME-->\r
+<!--&THEMEVER-->v20100404<!--/&THEMEVER-->\r
+<!--&THEMEAUTHOR-->Pixmicat! Development Team and sparky4<!--/&THEMEAUTHOR-->\r
+\r
+<!-- Theme Blocks -->\r
+<!--&HEADER--><?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{$LANGUAGE}">\r
+<head>\r
+<meta http-equiv="Pragma" content="no-cache" />\r
+<meta http-equiv="Expires" content="Sat, 1 Jan 2000 00:00:00 GMT" />\r
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\r
+<meta http-equiv="Content-Language" content="{$LANGUAGE}" />\r
+<title>{$TITLE}</title>
+{$STYLE_LOAD}<link rel="stylesheet" type="text/css" href="{$CSS_DIR}main/style.css" />
+{$FAV_ICON}\r
+<style type="text/css"><!--/*--><![CDATA[/*><!--*/\r
+.grid {float: left; width: 99%;height: 1.2em; overflow:auto; margin:2px; padding:0;}\r
+#page_switch table {border: 2px #F0E0D6 solid;}\r
+#page_switch table td {border:0}\r
+.reply { margin: 0.3ex 0.2ex 0.2ex 1em;}\r
+<!--&IF($RESTO,'','#postform {border: 2px #F0E0D6 solid;} #postform hr {display:none;}')-->\r
+/*]]>*/--></style><!--/&HEADER-->\r
+\r
+<!--&JSHEADER-->\r
+<script type="text/javascript"><!--//--><![CDATA[//><!--
+var msgs=['{$JS_REGIST_WITHOUTCOMMENT}','{$JS_REGIST_UPLOAD_NOTSUPPORT}','{$JS_CONVERT_SAKURA}'];\r
+var ext="{$ALLOW_UPLOAD_EXT}".toUpperCase().split("|");
+{$JSDONK}
+var boxclicked=0;\r
+//--><!]]></script>
+<script type="text/javascript" src="{$JS_DIR}script.js"></script>\r
+<!--[if lt IE 8]><script type="text/javascript" src="{$JS_DIR}iedivfix.js"></script><![endif]-->
+<!--/&JSHEADER-->\r
+\r
+<!--&TOPLINKS-->\r
+<div id="heading"><div class="adminbar" id="header">\r
+{$HOOKLINKS} {$TOP_LINKS} {$REFRESH} {$STATUS} {$SEARCH} {$HOME} {$ADMIN}
+</div>\r
+<!--/&TOPLINKS-->\r
+\r
+<!--&BODYHEAD-->\r
+<body class="mainpage">\r
+<!--&TOPLINKS/-->
+<div class="logo">\r
+<div style="font-size: 20pt; font-weight: bold;">{$TITLEHEAD}</div><!--&IF($TITLECOM,'<div class="sublogo">{$TITLECOM}</div>','')-->
+</div><hr class="top" size="1" /></div>
+<!--/&BODYHEAD-->\r
+\r
+<!--&POSTFORM-->\r
+<form action="{$SELF}" method="post" enctype="multipart/form-data" onsubmit="return c();" id="postform_main">\r
+<div class="postarea" id="postform">\r
+<!--&IF($FORMTOP,'{$FORMTOP}','')-->\r
+<input type="hidden" name="mode" value="{$MODE}" />\r
+<input type="hidden" name="MAX_FILE_SIZE" value="{$MAX_FILE_SIZE}" />\r
+<input type="hidden" name="upfile_path" value="" />\r
+<!--&IF($RESTO,'{$RESTO}','')-->\r
+<div style="text-align: center;">\r
+<table cellpadding="1" cellspacing="1" id="postform_tbl" style="margin: 0px auto; text-align: left;">\r
+<tr><td class="postblock"><b>{$FORM_NAME_TEXT}</b></td><td>{$FORM_NAME_FIELD}</td></tr>\r
+<tr><td class="postblock"><b>{$FORM_EMAIL_TEXT}</b></td><td>{$FORM_EMAIL_FIELD}</td></tr>\r
+<tr><td class="postblock"><b>{$FORM_TOPIC_TEXT}</b></td><td>{$FORM_TOPIC_FIELD}{$FORM_SUBMIT}</td></tr>\r
+<tr><td class="postblock"><b>{$FORM_COMMENT_TEXT}</b></td><td>{$FORM_COMMENT_FIELD}</td></tr>\r
+<!--&IF($FORM_ATTECHMENT_FIELD,'<tr><td class="postblock"><b>{$FORM_ATTECHMENT_TEXT}</b></td><td>{$FORM_ATTECHMENT_FIELD}','')--><!--&IF($FORM_NOATTECHMENT_FIELD,' [{$FORM_NOATTECHMENT_FIELD}<label for="noimg">{$FORM_NOATTECHMENT_TEXT}</label>]','')--><!--&IF($FORM_ATTECHMENT_FIELD,'</td></tr>','')-->
+<tr><td class="postblock"><b>{$FORM_DELETE_PASSWORD_TEXT}</b></td><td>{$FORM_DELETE_PASSWORD_FIELD}<small>{$FORM_DELETE_PASSWORD_NOTICE}</small></td></tr>\r
+<!--&IF($FORM_OPTION1_TEXT,'<tr><td class="postblock"><b>{$FORM_OPTION1_TEXT}</b></td>','')-->
+<!--&IF($FORM_CONTPOST_FIELD,'<td> [{$FORM_CONTPOST_FIELD}<label for="up_series">{$FORM_CONTPOST_TEXT}</label>]','')-->\r
+<!--&IF($FORM_OPTION1_TEXT,'</td></tr>','')-->
+{$FORM_EXTRA_COLUMN}\r
+<!--&IF($FORM_CATEGORY_FIELD,'<tr><td class="postblock"><b>{$FORM_CATEGORY_TEXT}</b></td><td>{$FORM_CATEGORY_FIELD}<small>{$FORM_CATEGORY_NOTICE}</small></td></tr>','')-->\r
+<tr><td colspan="2">\r
+<div class="rules" id="postinfo">\r
+<ul>{$FORM_NOTICE}\r
+<!--&IF($FORM_NOTICE_STORAGE_LIMIT,'{$FORM_NOTICE_STORAGE_LIMIT}','')-->\r
+{$HOOKPOSTINFO}\r
+{$ADDITION_INFO}\r
+</ul>\r
+<noscript><div>{$FORM_NOTICE_NOSCRIPT}</div></noscript>\r
+</div>\r
+</td></tr>\r
+</table>\r
+</div>\r
+<script type="text/javascript">l1();</script>\r
+<hr />\r
+</div>\r
+</form>\r
+<!--&IF($FORMBOTTOM,'{$FORMBOTTOM}','')-->\r
+<!--/&POSTFORM-->\r
+\r
+<!--&FOOTER-->\r
+<div class="footer" id="footer">\r
+{$FOOTER}\r
+<script type="text/javascript">preset();</script>\r
+</div>\r
+\r
+</body>\r
+</html>\r
+<!--/&FOOTER-->\r
+\r
+<!--&ERROR-->\r
+<div id="error">\r
+<div style="text-align: center; font-size: 1.5em; font-weight: bold;">\r
+<span style="color: red;">{$MESG}</span><p />\r
+<a href="{$SELF2}">{$RETURN_TEXT}</a> <a href="javascript:history.back();">{$BACK_TEXT}</a>\r
+</div>\r
+<hr />\r
+</div>\r
+<!--/&ERROR-->\r
+\r
+\r
+<!--&RES_THREAD-->\r
+<div class="threadpost" id="r{$NO}"><input type="checkbox" name="{$NO}" value="delete" onclick="boxclicked=1;" /><span class="filetitle">{$SUB}</span>\r
+{$NAME_TEXT}<span class="postername">{$NAME}</span> [{$NOW}] {$QUOTEBTN} {$REPLYBTN}</div>\r
+{$IMG_BAR}<!--&IF($IMG_BAR,'<br />','')-->{$IMG_SRC}\r
+{$WARN_OLD}{$WARN_BEKILL}{$WARN_ENDREPLY}{$WARN_HIDEPOST}\r
+<div class="blockquote">{$COM}</div>\r
+<!--&IF($CATEGORY,'<div class="category">{$CATEGORY_TEXT}{$CATEGORY}</div>','')-->\r
+<!--/&RES_THREAD-->\r
+\r
+<!--&MAIN_THREAD-->\r
+<tr>\r
+<td><input type="checkbox" name="{$NO}" value="delete" onclick="boxclicked=1;" /></td><td>{$QUOTEBTN}</td><td><span class="postername">{$NAME}</span></td>\r
+<td><span class="filetitle">{$SUB}</span></td><td>{$NOW}</td><td>{$IMG_BAR}</td>&nbsp;<td>{$REPLYBTN}</td></tr>\r
+<!--/&MAIN_THREAD-->\r
+\r
+\r
+<!--&THREAD-->
+<!--Thread No.{$NO}-->
+<!--&IF($RESTO,'<!--&RES_THREAD/-->','<!--&MAIN_THREAD/-->')-->\r
+<!--/&THREAD-->\r
+\r
+<!--&REPLY-->
+                               <!--Reply No.{$NO}-->
+<table><tr><td class="doubledash">…</td><td class="reply" id="r{$NO}">
+<div class="reply" id="r{$NO}">\r
+<input type="checkbox" name="{$NO}" value="delete" onclick="boxclicked=1;" /><span class="replytitle">{$SUB}</span>&nbsp;
+{$NAME_TEXT}<span class="commentpostername">{$NAME}</span> {$NOW} {$QUOTEBTN}&nbsp;<!--&IF($IMG_BAR,'<br />','')-->{$IMG_BAR}<!--&IF($IMG_SRC,'<br />','')-->{$IMG_SRC}\r
+{$WARN_BEKILL}<div class="blockquote">{$COM}</div>\r
+<!--&IF($CATEGORY,'<div class="category">{$CATEGORY_TEXT}{$CATEGORY}</div>','')-->\r
+</td></tr></table>\r
+<!--/&REPLY-->\r
+\r
+<!--&SEARCHRESULT-->\r
+<div class="threadpost">\r
+<span class="title">{$SUB}</span>\r
+{$NAME_TEXT}<span class="name">{$NAME}</span> {$NOW} No.{$NO}\r
+<div class="blockquote">{$COM}</div>\r
+<!--&IF($CATEGORY,'<div class="category">{$CATEGORY_TEXT}{$CATEGORY}</div>','')-->\r
+</div>\r
+<!--&REALSEPARATE/-->\r
+<!--/&SEARCHRESULT-->\r
+\r
+<!--&THREADSEPARATE-->\r
+<!--&IF($RESTO,'<hr />','</div>')-->\r
+<!--/&THREADSEPARATE-->\r
+\r
+<!--&REALSEPARATE-->\r
+<hr />\r
+<!--/&REALSEPARATE-->\r
+\r
+<!--&DELFORM-->\r
+<div id="del">\r
+<table style="float: right;">\r
+<tr><td align="center" style="white-space: nowrap;">\r
+{$DEL_HEAD_TEXT}[{$DEL_IMG_ONLY_FIELD}<label for="onlyimgdel">{$DEL_IMG_ONLY_TEXT}</label>]<br />\r
+{$DEL_PASS_TEXT}{$DEL_PASS_FIELD}{$DEL_SUBMIT_BTN}
+{$STYLE_BAR}\r
+</td></tr>\r
+</table>\r
+</div>\r
+<!--/&DELFORM-->\r
+\r
+<!--&MAIN-->\r
+<div id="contents">\r
+<form action="{$SELF}" method="POST">\r
+<div id="threads">\r
+{$THREADFRONT}\r
+<!--&IF($RESTO,'','<table width="100%" style="clear:both"><tr><th>Del</th><th>No.</th><th>Name</th><th>Title</th><th>Date/ID</th><th>File</th><th>Reply</th></tr>')-->\r
+{$THREADS}\r
+<!--&IF($RESTO,'','</table>')-->\r
+{$THREADREAR}\r
+</div>\r
+<div style="clear:both"></div>\r
+<!--&DELFORM/-->\r
+<script type="text/javascript">l2();</script>\r
+</form>\r
+{$PAGENAV}\r
+</div>\r
+<!--/&MAIN-->
\ No newline at end of file
diff --git a/data/tplt/inc_yo.tplt b/data/tplt/inc_yo.tplt
new file mode 100755 (executable)
index 0000000..f1baef1
--- /dev/null
@@ -0,0 +1,166 @@
+<!--&THEMENAME-->Yotsubanome Theme<!--/&THEMENAME-->\r
+<!--&THEMEVER-->v20100404<!--/&THEMEVER-->\r
+<!--&THEMEAUTHOR-->Pixmicat! Development Team and sparky4<!--/&THEMEAUTHOR-->\r
+\r
+<!--&HEADER--><?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{$LANGUAGE}">\r
+<head>\r
+<meta http-equiv="Pragma" content="no-cache" />\r
+<meta http-equiv="Expires" content="Sat, 1 Jan 2000 00:00:00 GMT" />\r
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\r
+<meta http-equiv="Content-Language" content="{$LANGUAGE}" />\r
+<title>{$TITLE}</title>
+{$STYLE_LOAD}<link rel="stylesheet" type="text/css" href="{$CSS_DIR}main/style.css" />
+{$FAV_ICON}<!--/&HEADER-->\r
+\r
+<!--&JSHEADER-->\r
+<script type="text/javascript">\r
+// <![CDATA[
+var msgs=['{$JS_REGIST_WITHOUTCOMMENT}','{$JS_REGIST_UPLOAD_NOTSUPPORT}','{$JS_CONVERT_SAKURA}'];\r
+var ext="{$ALLOW_UPLOAD_EXT}".toUpperCase().split("|");
+{$JSDONK}\r
+// ]]>
+</script>
+<script type="text/javascript" src="{$JS_DIR}script.js"></script>\r
+<!--[if lt IE 8]><script type="text/javascript" src="{$JS_DIR}iedivfix.js"></script><![endif]-->\r
+<!--/&JSHEADER-->\r
+\r
+<!--&TOPLINKS-->\r
+<div id="heading"><div class="adminbar" id="header">\r
+{$HOOKLINKS} {$TOP_LINKS} {$REFRESH} {$STATUS} {$SEARCH} {$HOME} {$ADMIN}
+</div>\r
+<!--/&TOPLINKS-->\r
+\r
+<!--&BODYHEAD-->\r
+<body>\r
+<!--&TOPLINKS/-->
+<div class="logo">\r
+<div style="font-size: 20pt; font-weight: bold;">{$TITLEHEAD}</div><!--&IF($TITLECOM,'<div class="sublogo">{$TITLECOM}</div>','')-->
+</div><hr class="top" /></div>\r
+<!--/&BODYHEAD-->\r
+\r
+<!--&POSTFORM-->\r
+<form action="{$SELF}" method="post" enctype="multipart/form-data" onsubmit="return c();" id="postform_main">\r
+<div class="postarea" id="postform">\r
+<!--&IF($FORMTOP,'{$FORMTOP}','')-->\r
+<input type="hidden" name="mode" value="{$MODE}" />\r
+<input type="hidden" name="MAX_FILE_SIZE" value="{$MAX_FILE_SIZE}" />\r
+<input type="hidden" name="upfile_path" value="" />\r
+<!--&IF($RESTO,'{$RESTO}','')-->\r
+<div style="text-align: center;">\r
+<table cellpadding="1" cellspacing="1" id="postform_tbl" style="margin: 0px auto; text-align: left;">\r
+<tr><td class="postblock"><b>{$FORM_NAME_TEXT}</b></td><td>{$FORM_NAME_FIELD}</td></tr>\r
+<tr><td class="postblock"><b>{$FORM_EMAIL_TEXT}</b></td><td>{$FORM_EMAIL_FIELD}</td></tr>\r
+<tr><td class="postblock"><b>{$FORM_TOPIC_TEXT}</b></td><td>{$FORM_TOPIC_FIELD}{$FORM_SUBMIT}</td></tr>\r
+<tr><td class="postblock"><b>{$FORM_COMMENT_TEXT}</b></td><td>{$FORM_COMMENT_FIELD}</td></tr>\r
+<!--&IF($FORM_ATTECHMENT_FIELD,'<tr><td class="postblock"><b>{$FORM_ATTECHMENT_TEXT}</b></td><td>{$FORM_ATTECHMENT_FIELD}','')--><!--&IF($FORM_NOATTECHMENT_FIELD,' [{$FORM_NOATTECHMENT_FIELD}<label for="noimg">{$FORM_NOATTECHMENT_TEXT}</label>]','')--><!--&IF($FORM_ATTECHMENT_FIELD,'</td></tr>','')-->
+<tr><td class="postblock"><b>{$FORM_DELETE_PASSWORD_TEXT}</b></td><td>{$FORM_DELETE_PASSWORD_FIELD}<small>{$FORM_DELETE_PASSWORD_NOTICE}</small></td></tr>\r
+<!--&IF($FORM_OPTION1_TEXT,'<tr><td class="postblock"><b>{$FORM_OPTION1_TEXT}</b></td>','')-->
+<!--&IF($FORM_CONTPOST_FIELD,'<td> [{$FORM_CONTPOST_FIELD}<label for="up_series">{$FORM_CONTPOST_TEXT}</label>]','')-->\r
+<!--&IF($FORM_OPTION1_TEXT,'</td></tr>','')-->
+{$FORM_EXTRA_COLUMN}\r
+<!--&IF($FORM_CATEGORY_FIELD,'<tr><td class="postblock"><b>{$FORM_CATEGORY_TEXT}</b></td><td>{$FORM_CATEGORY_FIELD}<small>{$FORM_CATEGORY_NOTICE}</small></td></tr>','')-->\r
+<tr><td colspan="2">\r
+<div class="rules" id="postinfo">\r
+<ul>{$FORM_NOTICE}\r
+<!--&IF($FORM_NOTICE_STORAGE_LIMIT,'{$FORM_NOTICE_STORAGE_LIMIT}','')-->\r
+{$HOOKPOSTINFO}\r
+{$ADDITION_INFO}\r
+</ul>\r
+<noscript><div>{$FORM_NOTICE_NOSCRIPT}</div></noscript>\r
+</div>\r
+</td></tr>\r
+</table>\r
+</div>\r
+<script type="text/javascript">l1();</script>\r
+<hr />\r
+</div>\r
+</form>\r
+<!--&IF($FORMBOTTOM,'{$FORMBOTTOM}','')-->\r
+<!--/&POSTFORM-->\r
+\r
+<!--&FOOTER-->\r
+<div class="footer" id="footer">\r
+{$FOOTER}\r
+<script type="text/javascript">preset();</script>\r
+</div>\r
+\r
+</body>\r
+</html>\r
+<!--/&FOOTER-->\r
+\r
+<!--&ERROR-->\r
+<div id="error">\r
+<div style="text-align: center; font-size: 1.5em; font-weight: bold;">\r
+<span style="color: red;">{$MESG}</span><p />\r
+<a href="{$SELF2}">{$RETURN_TEXT}</a> <a href="javascript:history.back();">{$BACK_TEXT}</a>\r
+</div>\r
+<hr />\r
+</div>\r
+<!--/&ERROR-->\r
+\r
+\r
+<!--&THREAD-->
+<!--Thread No.{$NO}-->\r
+<div class="threadpost" id="r{$NO}">\r
+{$IMG_BAR}<!--&IF($IMG_BAR,'<br />','')-->{$IMG_SRC}<input type="checkbox" name="{$NO}" value="delete" /><span class="filetitle">{$SUB}</span>\r
+{$NAME_TEXT}<span class="postername">{$NAME}</span> {$NOW} {$QUOTEBTN}&nbsp;&nbsp;{$REPLYBTN}\r
+<div class="blockquote">{$COM}</div>\r
+<!--&IF($CATEGORY,'<div class="category">{$CATEGORY_TEXT}{$CATEGORY}</div>','')-->\r
+{$WARN_OLD}{$WARN_BEKILL}{$WARN_ENDREPLY}{$WARN_HIDEPOST}</div>\r
+<!--/&THREAD-->\r
+\r
+<!--&REPLY-->
+                               <!--Reply No.{$NO}-->
+<table><tr><td class="doubledash">…</td><td class="reply" id="r{$NO}"><input type="checkbox" name="{$NO}" value="delete" /><span class="replytitle">{$SUB}</span>&nbsp;
+{$NAME_TEXT}<span class="commentpostername">{$NAME}</span> {$NOW} {$QUOTEBTN}&nbsp;&nbsp;<!--&IF($IMG_BAR,'<br />','')-->{$IMG_BAR}<!--&IF($IMG_SRC,'<br />','')-->{$IMG_SRC}\r
+<div class="blockquote">{$COM}</div>\r
+<!--&IF($CATEGORY,'<div class="category">{$CATEGORY_TEXT}{$CATEGORY}</div>','')-->\r
+{$WARN_BEKILL}</td></tr></table>\r
+<!--/&REPLY-->\r
+\r
+<!--&SEARCHRESULT-->\r
+<div class="threadpost">\r
+<span class="title">{$SUB}</span>\r
+{$NAME_TEXT}<span class="name">{$NAME}</span> {$NOW} No.{$NO}\r
+<div class="blockquote">{$COM}</div>\r
+<!--&IF($CATEGORY,'<div class="category">{$CATEGORY_TEXT}{$CATEGORY}</div>','')-->\r
+</div>\r
+<!--&REALSEPARATE/-->\r
+<!--/&SEARCHRESULT-->\r
+\r
+<!--&THREADSEPARATE-->\r
+<hr />\r
+<!--/&THREADSEPARATE-->\r
+\r
+<!--&REALSEPARATE-->\r
+<hr />\r
+<!--/&REALSEPARATE-->\r
+\r
+<!--&DELFORM-->\r
+<div id="del">\r
+<table style="float: right;">\r
+<tr><td align="right" style="white-space: nowrap;">\r
+{$DEL_HEAD_TEXT}[{$DEL_IMG_ONLY_FIELD}<label for="onlyimgdel">{$DEL_IMG_ONLY_TEXT}</label>]<br />\r
+{$DEL_PASS_TEXT}{$DEL_PASS_FIELD}{$DEL_SUBMIT_BTN}
+{$STYLE_BAR}\r
+</td></tr>\r
+</table>\r
+</div>\r
+<!--/&DELFORM-->\r
+\r
+<!--&MAIN-->\r
+<div id="contents">\r
+{$THREADFRONT}\r
+<form action="{$SELF}" method="post">\r
+<div id="threads" class="autopagerize_page_element">\r
+{$THREADS}\r
+</div>\r
+{$THREADREAR}\r
+<!--&DELFORM/-->\r
+<script type="text/javascript">l2();</script>\r
+</form>\r
+{$PAGENAV}\r
+</div>\r
+<!--/&MAIN-->
\ No newline at end of file
diff --git a/futaba2pio.php b/futaba2pio.php
new file mode 100755 (executable)
index 0000000..ee647d0
--- /dev/null
@@ -0,0 +1,123 @@
+<?php\r
+/**\r
+ * Pixmicat! PIO 公用程式 - Pixmicat!-Log -> Pixmciat-PIO (Log) 資料格式轉換器\r
+ *\r
+ * 本程式可以自 Log 版轉換格式自 PIO 版 Log 資料來源。\r
+ *\r
+ * 注意:本程式是給 Log 版舊程式使用以轉換,非直接用在 PIO 新版上面\r
+ *\r
+ * @package PMCUtility\r
+ * @version $Id$\r
+ * @date $Date$\r
+ */\r
+\r
+define("PHP_DIRECTORY", '../../core/'); // yotsubanome "C:\windows\system\"\r
+include_once(PHP_DIRECTORY.'config.php');\r
+define('DEL_ZOMBIE', true); // 如果有文章沒有出現在樹狀結構,是否不要轉換直接刪除?\r
+define('SAVE_LOG', true); // 是否儲存新結構 (舊結構將保留並更名)\r
+define('LOGFILE', "img.csv_loog");\r
+define('TREEFILE', "tree.csv_loog");\r
+\r
+// 各資料儲存檔位置\r
+$logimg = file(LOGFILE); $logimg_cnt = count($logimg);\r
+$trees = array(); // 文章回應對應編號陣列 (回應No. => 首篇No.)\r
+$logtree = array_map('rtrim', file(TREEFILE));\r
+foreach($logtree as $treeline){ // 解析樹狀結構製成對應索引\r
+       if($treeline=='') continue;\r
+       $tline = explode(',', $treeline); $tline_cnt = count($tline);\r
+       $trees[$tline[0]] = 0;\r
+       for($t = 1; $t < $tline_cnt; $t++){ $trees[$tline[$t]] = $tline[0]; }\r
+}\r
+unset($logtree);\r
+\r
+// 圖檔存放位置\r
+$dirimg = realpath('.').DIRECTORY_SEPARATOR.IMG_DIR;\r
+\r
+/* 取得圖檔的寬長以存入資料 */\r
+function getImageWH($imgname){\r
+       global $dirimg;\r
+\r
+       $imgpath = $dirimg.$imgname;\r
+       if(!file_exists($imgpath)) return array(0, 0);\r
+       list($width, $height,) = getimagesize($imgpath);\r
+       return array($width, $height); // 回傳寬高陣列\r
+}\r
+\r
+/* 取得圖檔的檔案大小字串 (單位 KB) */\r
+function getImageSizeText($imgname){\r
+       global $dirimg;\r
+\r
+       $imgpath = $dirimg.$imgname;\r
+       if(!file_exists($imgpath)) return false;\r
+       $imgsize = filesize($imgpath);\r
+       return $imgsize = ($imgsize>=1024) ? (int)($imgsize/1024).' KB' : $imgsize.' B'; // KB和B的判別 // 回傳檔案大小字串\r
+}\r
+\r
+/* 取得回應的對象編號 */\r
+function getReplyTargetNo($no){\r
+       global $trees;\r
+\r
+       if(isset($trees[$no])) return $trees[$no];\r
+       return false;\r
+}\r
+\r
+/* 更改 log 檔結構 */\r
+// OLD: 編號,時間 (ID),名稱,E-Mail,標題,內文,狀態旗標,主機位置,編碼後文章密碼,附加圖檔類型,預覽圖寬,預覽圖長,Unix時間撮記,附加圖檔MD5,\r
+\r
+// SUPER DUPER UBER OLD:\r
+// 0$no,1$now,2$name,3$email,4$sub,5$com,6$url,7$host,8$pwd,9$ext,10$w,11$h,12$time,13$chk\r
+// (futaba)\r
+\r
+// SUPER DUPER OLD:\r
+// 0$no,1$now,2$name,3$email,4$sub,5$com,6$url,7$host,8$pwd,9$ext,10$w,11$h,12$time,13$chk,14$ip\r
+// (early yotsubanome)\r
+\r
+// SUPER OLD:\r
+// 0$no,1$now,2$name,3$email,4$sub,5$com,6$url,7$host,8$pwd,9$ext,10$w,11$h,12$time,13$chk,14$ip,15$filename,16$mime\r
+// (old yotsubanome)\r
+\r
+// OLD:\r
+// 0$no,1$now,2$name,3$email,4$sub,5$com,6$url,7$host,8$pwd,9$ext,10$w,11$h,12$time,13$chk,14$imgsize,15$filename,16$imgW,17$imgH,18$category,19$resto\r
+// (older new yotsubanome)\r
+\r
+\r
+// NEW: 編號,回應目標編號,附加圖檔MD5,類別標籤,Unix時間撮記,附加圖檔類型,圖檔寬,圖檔長,圖檔大小,預覽圖寬,預覽圖長,編碼後文章密碼,時間 (ID),名稱,E-mail,標題,內文,主機位置,狀態旗標,\r
+// NEW:\r
+// 0$no,1$resto,2$chk,3$category,4$time,5$ext,6$imgw,7$imgh,8$imgsize,9$filename,10$w,11$h,12$pwd,13$now,14$name,15$email,16$sub,17$com,18$host,19$url\r
+// ↑ = ↓ the line above is equal to the line below (The line above is the old futaba variable names, and the line below is the new yotsubanome variable names.)\r
+// 0$no,1$resto,2$md5chksum,3$category,4$tim,5$ext,6$imgw,7$imgh,8$imgsize,9$filename,10$tw,11$th,12$pwd,13$now,14$name,15$email,16$sub,17$com,18$host,19$status\r
+// (new yotsubanome)\r
+\r
+header('Content-Type: text/plain; charset=utf-8');\r
+$newLine = array(); // 新資料格式\r
+$countda = count(explode(',', $logimg[0]));\r
+if(count(explode(',', $logimg[0])) != 15 && count(explode(',', $logimg[0])) != 17 && count(explode(',', $logimg[0])) != 19){\r
+       if($countda = 21) die('File structure error. It\'s already a PIO structure. ['.$countda.']'.var_dump($logimg));\r
+       else die('File structure error. ['.$countda.']'.var_dump($logimg));\r
+}\r
+for($i = 0; $i < $logimg_cnt; $i++){\r
+       $l = explode(',', $logimg[$i]); // 舊資料格式 (用逗號拆開)\r
+       $s = getImageWH($l[12].$l[9]); // 圖檔寬長 (寬, 長)\r
+       $l[6] = str_replace('_THREADSTOP_', '_TS_', $l[6]); // 討論串停止旗標自 _THREADSTOP_ 改為 _TS_\r
+       $l[2] = preg_replace('/<(.*?)>/', '', $l[2]); // name crap that breaks HTTP\r
+       $l[2] = preg_replace('/&nbsp;/', '', $l[2]); // name crap that breaks HTTP\r
+       $l[2] = preg_replace('/◆四葉(.*?)##(.*?)##/', '', $l[2]); // name crap that breaks HTTP\r
+       if(strstr($l[14], "\n")){ $l[15] = $l[16] = $l[17] = $l[18] = $l[19] = ''; } // from futaba\r
+       if(strstr($l[14], ".") && $l[15] = false || !strstr($l[14], "KB") && !strstr($l[14], "B")){ $l[15] = $l[16] = $l[17] = $l[18] = $l[19] = ''; } // from early yotsubanome\r
+       if(strstr($l[14], ".") && strstr($l[16], "/") || !strstr($l[14], "KB") && !strstr($l[14], "B")){ $l[14] = $l[16] = ''; } // from old yotsubanome\r
+       //++++!if(strstr($l[1], "1969"))\r
+       if(!DEL_ZOMBIE || getReplyTargetNo($l[0]) !== false && $l[1] !== false) $newLine[] = implode(',', array($l[0], getReplyTargetNo($l[0]), $l[13], '', $l[12], $l[9], $s[0], $s[1], getImageSizeText($l[12].$l[9]), $l[15], (int) $l[10], (int) $l[11], $l[8], $l[1], $l[2], $l[3], $l[4], $l[5], $l[7], $l[6], ''))."\r\n";\r
+}\r
+\r
+$writeContent = implode('', $newLine);\r
+\r
+if(SAVE_LOG){\r
+       rename(LOGFILE, LOGFILE.'.old');\r
+       $fs = fopen(LOGFILE, 'w');\r
+       fwrite($fs, $writeContent);\r
+       fclose($fs);\r
+       die('File save OK. The old file already renamed.');\r
+}else{\r
+       echo $writeContent;\r
+}\r
+?>\r
diff --git a/futaba2pio.phps b/futaba2pio.phps
new file mode 100644 (file)
index 0000000..ee647d0
--- /dev/null
@@ -0,0 +1,123 @@
+<?php\r
+/**\r
+ * Pixmicat! PIO 公用程式 - Pixmicat!-Log -> Pixmciat-PIO (Log) 資料格式轉換器\r
+ *\r
+ * 本程式可以自 Log 版轉換格式自 PIO 版 Log 資料來源。\r
+ *\r
+ * 注意:本程式是給 Log 版舊程式使用以轉換,非直接用在 PIO 新版上面\r
+ *\r
+ * @package PMCUtility\r
+ * @version $Id$\r
+ * @date $Date$\r
+ */\r
+\r
+define("PHP_DIRECTORY", '../../core/'); // yotsubanome "C:\windows\system\"\r
+include_once(PHP_DIRECTORY.'config.php');\r
+define('DEL_ZOMBIE', true); // 如果有文章沒有出現在樹狀結構,是否不要轉換直接刪除?\r
+define('SAVE_LOG', true); // 是否儲存新結構 (舊結構將保留並更名)\r
+define('LOGFILE', "img.csv_loog");\r
+define('TREEFILE', "tree.csv_loog");\r
+\r
+// 各資料儲存檔位置\r
+$logimg = file(LOGFILE); $logimg_cnt = count($logimg);\r
+$trees = array(); // 文章回應對應編號陣列 (回應No. => 首篇No.)\r
+$logtree = array_map('rtrim', file(TREEFILE));\r
+foreach($logtree as $treeline){ // 解析樹狀結構製成對應索引\r
+       if($treeline=='') continue;\r
+       $tline = explode(',', $treeline); $tline_cnt = count($tline);\r
+       $trees[$tline[0]] = 0;\r
+       for($t = 1; $t < $tline_cnt; $t++){ $trees[$tline[$t]] = $tline[0]; }\r
+}\r
+unset($logtree);\r
+\r
+// 圖檔存放位置\r
+$dirimg = realpath('.').DIRECTORY_SEPARATOR.IMG_DIR;\r
+\r
+/* 取得圖檔的寬長以存入資料 */\r
+function getImageWH($imgname){\r
+       global $dirimg;\r
+\r
+       $imgpath = $dirimg.$imgname;\r
+       if(!file_exists($imgpath)) return array(0, 0);\r
+       list($width, $height,) = getimagesize($imgpath);\r
+       return array($width, $height); // 回傳寬高陣列\r
+}\r
+\r
+/* 取得圖檔的檔案大小字串 (單位 KB) */\r
+function getImageSizeText($imgname){\r
+       global $dirimg;\r
+\r
+       $imgpath = $dirimg.$imgname;\r
+       if(!file_exists($imgpath)) return false;\r
+       $imgsize = filesize($imgpath);\r
+       return $imgsize = ($imgsize>=1024) ? (int)($imgsize/1024).' KB' : $imgsize.' B'; // KB和B的判別 // 回傳檔案大小字串\r
+}\r
+\r
+/* 取得回應的對象編號 */\r
+function getReplyTargetNo($no){\r
+       global $trees;\r
+\r
+       if(isset($trees[$no])) return $trees[$no];\r
+       return false;\r
+}\r
+\r
+/* 更改 log 檔結構 */\r
+// OLD: 編號,時間 (ID),名稱,E-Mail,標題,內文,狀態旗標,主機位置,編碼後文章密碼,附加圖檔類型,預覽圖寬,預覽圖長,Unix時間撮記,附加圖檔MD5,\r
+\r
+// SUPER DUPER UBER OLD:\r
+// 0$no,1$now,2$name,3$email,4$sub,5$com,6$url,7$host,8$pwd,9$ext,10$w,11$h,12$time,13$chk\r
+// (futaba)\r
+\r
+// SUPER DUPER OLD:\r
+// 0$no,1$now,2$name,3$email,4$sub,5$com,6$url,7$host,8$pwd,9$ext,10$w,11$h,12$time,13$chk,14$ip\r
+// (early yotsubanome)\r
+\r
+// SUPER OLD:\r
+// 0$no,1$now,2$name,3$email,4$sub,5$com,6$url,7$host,8$pwd,9$ext,10$w,11$h,12$time,13$chk,14$ip,15$filename,16$mime\r
+// (old yotsubanome)\r
+\r
+// OLD:\r
+// 0$no,1$now,2$name,3$email,4$sub,5$com,6$url,7$host,8$pwd,9$ext,10$w,11$h,12$time,13$chk,14$imgsize,15$filename,16$imgW,17$imgH,18$category,19$resto\r
+// (older new yotsubanome)\r
+\r
+\r
+// NEW: 編號,回應目標編號,附加圖檔MD5,類別標籤,Unix時間撮記,附加圖檔類型,圖檔寬,圖檔長,圖檔大小,預覽圖寬,預覽圖長,編碼後文章密碼,時間 (ID),名稱,E-mail,標題,內文,主機位置,狀態旗標,\r
+// NEW:\r
+// 0$no,1$resto,2$chk,3$category,4$time,5$ext,6$imgw,7$imgh,8$imgsize,9$filename,10$w,11$h,12$pwd,13$now,14$name,15$email,16$sub,17$com,18$host,19$url\r
+// ↑ = ↓ the line above is equal to the line below (The line above is the old futaba variable names, and the line below is the new yotsubanome variable names.)\r
+// 0$no,1$resto,2$md5chksum,3$category,4$tim,5$ext,6$imgw,7$imgh,8$imgsize,9$filename,10$tw,11$th,12$pwd,13$now,14$name,15$email,16$sub,17$com,18$host,19$status\r
+// (new yotsubanome)\r
+\r
+header('Content-Type: text/plain; charset=utf-8');\r
+$newLine = array(); // 新資料格式\r
+$countda = count(explode(',', $logimg[0]));\r
+if(count(explode(',', $logimg[0])) != 15 && count(explode(',', $logimg[0])) != 17 && count(explode(',', $logimg[0])) != 19){\r
+       if($countda = 21) die('File structure error. It\'s already a PIO structure. ['.$countda.']'.var_dump($logimg));\r
+       else die('File structure error. ['.$countda.']'.var_dump($logimg));\r
+}\r
+for($i = 0; $i < $logimg_cnt; $i++){\r
+       $l = explode(',', $logimg[$i]); // 舊資料格式 (用逗號拆開)\r
+       $s = getImageWH($l[12].$l[9]); // 圖檔寬長 (寬, 長)\r
+       $l[6] = str_replace('_THREADSTOP_', '_TS_', $l[6]); // 討論串停止旗標自 _THREADSTOP_ 改為 _TS_\r
+       $l[2] = preg_replace('/<(.*?)>/', '', $l[2]); // name crap that breaks HTTP\r
+       $l[2] = preg_replace('/&nbsp;/', '', $l[2]); // name crap that breaks HTTP\r
+       $l[2] = preg_replace('/◆四葉(.*?)##(.*?)##/', '', $l[2]); // name crap that breaks HTTP\r
+       if(strstr($l[14], "\n")){ $l[15] = $l[16] = $l[17] = $l[18] = $l[19] = ''; } // from futaba\r
+       if(strstr($l[14], ".") && $l[15] = false || !strstr($l[14], "KB") && !strstr($l[14], "B")){ $l[15] = $l[16] = $l[17] = $l[18] = $l[19] = ''; } // from early yotsubanome\r
+       if(strstr($l[14], ".") && strstr($l[16], "/") || !strstr($l[14], "KB") && !strstr($l[14], "B")){ $l[14] = $l[16] = ''; } // from old yotsubanome\r
+       //++++!if(strstr($l[1], "1969"))\r
+       if(!DEL_ZOMBIE || getReplyTargetNo($l[0]) !== false && $l[1] !== false) $newLine[] = implode(',', array($l[0], getReplyTargetNo($l[0]), $l[13], '', $l[12], $l[9], $s[0], $s[1], getImageSizeText($l[12].$l[9]), $l[15], (int) $l[10], (int) $l[11], $l[8], $l[1], $l[2], $l[3], $l[4], $l[5], $l[7], $l[6], ''))."\r\n";\r
+}\r
+\r
+$writeContent = implode('', $newLine);\r
+\r
+if(SAVE_LOG){\r
+       rename(LOGFILE, LOGFILE.'.old');\r
+       $fs = fopen(LOGFILE, 'w');\r
+       fwrite($fs, $writeContent);\r
+       fclose($fs);\r
+       die('File save OK. The old file already renamed.');\r
+}else{\r
+       echo $writeContent;\r
+}\r
+?>\r
diff --git a/info b/info
new file mode 100755 (executable)
index 0000000..ef6f0b6
--- /dev/null
+++ b/info
@@ -0,0 +1,26 @@
+This is the core of the software
+
+Please refrain from creating boards in this directory
+but create the board in 1 diectory up
+
+And use the databases in
+core/lib/pio/
+and NOT in
+core/lib/pio/old/
+
+because that is where the development is taking place
+
+
+/var/www/core/ can be ran as a board it self
+but you can make another board
+
+/var/www/<name of board directory>/
+/var/www/core/
+
+Do NOT import the databases
+
+dbImport( = not ready
+
+there could be bugs
+
+please let me know about them in http://4ch.irc.su/sparky4/+4/core/yotsubanome.php
diff --git a/lib/fileio/fileio.ftp.php b/lib/fileio/fileio.ftp.php
new file mode 100755 (executable)
index 0000000..62da926
--- /dev/null
@@ -0,0 +1,106 @@
+<?php\r
+/**\r
+ * FileIO FTP 遠端儲存 API\r
+ *\r
+ * 以遠端硬碟空間作為圖檔儲存的方式 (以 FTP 存取),並提供一套方法供程式管理圖片\r
+ *\r
+ * @package PMCLibrary\r
+ * @version $Id: fileio.ftp.php 636 2008-05-19 07:54:19Z scribe $\r
+ * @date $Date: 2008-05-19 15:54:19 +0800 (星期一, 19 五月 2008) $\r
+ */\r
+\r
+class FileIO{\r
+       var $conn, $parameter, $thumbLocalPath;\r
+       var $IFS;\r
+\r
+       /* private 登入 FTP */\r
+       function _ftp_login(){\r
+               if($this->conn) return true;\r
+               $this->conn = ftp_connect($this->parameter[0], $this->parameter[1]);\r
+               if($result = @ftp_login($this->conn, $this->parameter[2], $this->parameter[3])){\r
+                       if($this->parameter[4]=='PASV') ftp_pasv($this->conn, true); // 被動模式\r
+                       ftp_set_option($this->conn, FTP_TIMEOUT_SEC, 120); // 延長 Timeout 至 120 秒\r
+                       @ftp_chdir($this->conn, $this->parameter[5]);\r
+               }\r
+               return $result;\r
+       }\r
+\r
+       /* private 關閉 FTP 及儲存索引檔 */\r
+       function _ftp_close(){\r
+               if($this->conn) ftp_close($this->conn); // 有開啟 FTP 連線則關閉\r
+               $this->IFS->saveIndex(); // 索引表更新\r
+       }\r
+\r
+       function FileIO($parameter, $ENV){\r
+               require($ENV['IFS.PATH']);\r
+               $this->IFS = new IndexFS($ENV['IFS.LOG']); // IndexFS 物件\r
+               $this->IFS->openIndex();\r
+               register_shutdown_function(array($this, '_ftp_close')); // 設定解構元 (PHP 結束前執行)\r
+               set_time_limit(120); // 執行時間 120 秒 (FTP 傳輸過程可能很長)\r
+               $this->thumbLocalPath = $ENV['PATH'].$ENV['THUMB']; // 預覽圖本機位置\r
+               $this->parameter = $parameter;\r
+               /*\r
+                       [0] : FTP 伺服器位置\r
+                       [1] : FTP 伺服器埠號\r
+                       [2] : FTP 使用者帳號\r
+                       [3] : FTP 使用者密碼\r
+                       [4] : 是否使用被動模式? (PASV: 使用, NOPASV: 不使用)\r
+                       [5] : FTP 預設工作目錄\r
+                       [6] : 工作目錄對應 URL\r
+                       [7] : 預覽圖是否上傳至遠端 (true: 是, false: 否,使用本機檔案)\r
+               */\r
+       }\r
+\r
+       function init(){\r
+               return true;\r
+       }\r
+\r
+       function imageExists($imgname){\r
+               if(!$this->parameter[7] && substr($imgname, -5) == 's.jpg') return file_exists($this->thumbLocalPath.$imgname);\r
+               return $this->IFS->beRecord($imgname);\r
+       }\r
+\r
+       function deleteImage($imgname){\r
+               if(!$this->_ftp_login()) return false;\r
+               if(is_array($imgname)){\r
+                       foreach($imgname as $i){\r
+                               if(!$this->parameter[7] && substr($i, -5) == 's.jpg'){\r
+                                       @unlink($this->thumbLocalPath.$i);\r
+                               }else{\r
+                                       if(!ftp_delete($this->conn, $i)) return false;\r
+                                       $this->IFS->delRecord($i); // 自索引中刪除\r
+                               }\r
+                       }\r
+                       return true;\r
+               }\r
+               else{\r
+                       if(!$this->parameter[7] && substr($imgname, -5) == 's.jpg') return @unlink($this->thumbLocalPath.$imgname);\r
+                       if($result = ftp_delete($this->conn, $imgname)) $this->IFS->delRecord($imgname);\r
+                       return $result;\r
+               }\r
+       }\r
+\r
+       function uploadImage($imgname='', $imgpath='', $imgsize=0){\r
+               if($imgname=='') return true; // 支援上傳方法\r
+               if(!$this->parameter[7] && substr($imgname, -5) == 's.jpg') return false; // 不處理預覽圖\r
+               if(!$this->_ftp_login()) return false;\r
+               $result = ftp_put($this->conn, $imgname, $imgpath, FTP_BINARY);\r
+               if($result){\r
+                       $this->IFS->addRecord($imgname, $imgsize, ''); // 加入索引之中\r
+                       unlink($imgpath); // 確實上傳後刪除本機暫存\r
+               }\r
+               return $result;\r
+       }\r
+\r
+       function getImageFilesize($imgname){\r
+               if(!$this->parameter[7] && substr($imgname, -5) == 's.jpg') return @filesize($this->thumbLocalPath.$imgname);\r
+               if($rc = $this->IFS->getRecord($imgname)) return $rc['imgSize'];\r
+               return false;\r
+       }\r
+\r
+       function getImageURL($imgname){\r
+               if(!$this->parameter[7] && substr($imgname, -5) == 's.jpg') return $this->getImageLocalURL($imgname);\r
+               return $this->IFS->beRecord($imgname) ? $this->parameter[6].$imgname : false;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/lib/fileio/fileio.imageshack.php b/lib/fileio/fileio.imageshack.php
new file mode 100755 (executable)
index 0000000..af93415
--- /dev/null
@@ -0,0 +1,151 @@
+<?php\r
+/**\r
+ * FileIO ImageShack 遠端儲存 API\r
+ *\r
+ * 以 ImageShack 存圖網站作為圖檔儲存的方式,並提供一套方法供程式管理圖片\r
+ *\r
+ * 使用此功能請遵守 ImageShack 網站的 Terms of Service,並注意以下條約:\r
+ * Terms specific to the XML API:\r
+ *\r
+ *  - Website or software must already be developed or have a strategic plan to be developed in the near future.\r
+ *  - Website or software users must be informed that ImageShack is providing free image hosting.\r
+ *\r
+ * Free implimentation support is offered to websites that have at least 500 unique visitors per day (users)\r
+ * or expect to achieve 500 users in the near future. Otherwise, the XML API is offered as is.\r
+ *\r
+ * 使用時請自律將 ImageShack 網站連結置於明顯處,並說明正使用其提供之免費圖檔存放功能。\r
+ * (http://reg.imageshack.us/content.php?page=linkto 可選擇喜歡方式使用)\r
+ *\r
+ * @package PMCLibrary\r
+ * @version $Id: fileio.imageshack.php 393 2007-04-30 11:25:29Z scribe $\r
+ * @date $Date: 2007-04-30 19:25:29 +0800 (星期一, 30 四月 2007) $\r
+ */\r
+\r
+class FileIO{\r
+       var $userAgent, $parameter;\r
+       var $IFS;\r
+\r
+       /* private 傳檔案到 ImageShack 上面 (發送抓取請求) */\r
+       function _transloadImageShack($imgname){\r
+               if(!($fp = @fsockopen('www.imageshack.us', 80))) return false;\r
+\r
+               $argument = 'xml=yes&rembar=1&url='.$this->getImageLocalURL($imgname);\r
+               $out = "POST /transload.php HTTP/1.1\r\n";\r
+               $out .= 'Host: www.imageshack.us'."\r\n";\r
+               $out .= 'User-Agent: '.$this->userAgent."\r\n";\r
+               $out .= "Content-Type: application/x-www-form-urlencoded\r\n";\r
+               if($this->parameter[0]) $out .= 'Cookie: myimages='.$this->parameter[0]."\r\n"; // ImageShack Registration Key Cookie\r
+               $out .= 'Content-Length: '.strlen($argument)."\r\n\r\n";\r
+               $out .= $argument;\r
+               fwrite($fp, $out);\r
+\r
+               $result = '';\r
+               while(!feof($fp)){ $result .= fgets($fp, 128); }\r
+               fclose($fp);\r
+\r
+               if(strpos($result, '<'.'?xml version="1.0" encoding="iso-8859-1"?>')===false) return false;\r
+               else{\r
+                       $returnValue = array();\r
+                       $xmlData = explode("\n", $result);\r
+                       foreach($xmlData as $xmlDatum){\r
+                               $xmlDatum = trim($xmlDatum);\r
+                               if($xmlDatum != '' && !eregi('links', $xmlDatum) && !eregi('xml', $xmlDatum)){\r
+                                       $xmlDatum = str_replace('>', '<', $xmlDatum);\r
+                                       $xmlDatum = explode('<', $xmlDatum);\r
+                                       if(count($xmlDatum) >= 3) $returnValue[$xmlDatum[1]] = $xmlDatum[2];\r
+                               }\r
+                       }\r
+                       return $returnValue;\r
+               }\r
+       }\r
+\r
+       /* private 發出刪除圖片要求 (需填入 Registration Key) */\r
+       function _deleteImageShack($imgURL){\r
+               if(!$this->parameter[0]) return true; // 沒金鑰無法要求刪除故直接略過\r
+               $imgURL = parse_url($imgURL); // 分析 URL 結構準備重組\r
+               if(!($fp = @fsockopen($imgURL['host'], 80))) return false;\r
+\r
+               $out = 'GET /delete.php?l='.substr($imgURL['path'], 1).'&c='.$this->parameter[0].'&page=THIS_IS_A_FLAG HTTP/1.1'."\r\n";\r
+               $out .= 'Host: '.$imgURL['host']."\r\n";\r
+               $out .= 'User-Agent: '.$this->userAgent."\r\n\r\n";\r
+               fwrite($fp, $out);\r
+\r
+               $result = '';\r
+               while(!feof($fp)){ $result .= fgets($fp, 128); }\r
+               fclose($fp);\r
+\r
+               return (strpos($result, 'THIS_IS_A_FLAG')!==false ? true : false); // 偷吃步,偵測page是否為設定的特殊值\r
+       }\r
+\r
+       /* private 生成 ImageShack my.php 指向頁面位置 */\r
+       function _myphpImageShack($imgurl, $ishotlink){\r
+               if($ishotlink) return $imgurl; // 直連:直接傳回不需處理\r
+               $imgurl = parse_url($imgurl);\r
+               return 'http://'.$imgurl['host'].'/my.php?image='.basename($imgurl['path']);\r
+       }\r
+\r
+       /* private 儲存索引檔 */\r
+       function _setIndex(){\r
+               $this->IFS->saveIndex(); // 索引表更新\r
+       }\r
+\r
+       function FileIO($parameter, $ENV){\r
+               require($ENV['IFS.PATH']);\r
+               $this->IFS = new IndexFS($ENV['IFS.LOG']); // IndexFS 物件\r
+               $this->IFS->openIndex();\r
+               register_shutdown_function(array($this, '_setIndex')); // 設定解構元 (PHP 結束前執行)\r
+               set_time_limit(120); // 執行時間 120 秒 (傳輸過程可能很長)\r
+               $this->userAgent = 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)'; // Just for fun ;-)\r
+               $this->parameter = $parameter; // 將參數重新解析\r
+               /*\r
+                       [0] : ImageShack 註冊金鑰 (即登入頁面 setlogin.php 網址後面附帶一串編碼) * 可不填,但功能會少\r
+                       登入後亦可在 http://reg.imageshack.us/content.php?page=register 找到 Your Registration Code\r
+               */\r
+       }\r
+\r
+       function init(){\r
+               return true;\r
+       }\r
+\r
+       function imageExists($imgname){\r
+               return $this->IFS->beRecord($imgname);\r
+       }\r
+\r
+       function deleteImage($imgname){\r
+               if(is_array($imgname)){\r
+                       foreach($imgname as $i){\r
+                               if(($rc = $this->IFS->getRecord($i)) && $this->_deleteImageShack($rc['imgURL'])) $this->IFS->delRecord($i); // 自索引中刪除\r
+                               else return false; // 送出刪除要求失敗\r
+                       }\r
+                       return true;\r
+               }\r
+               else{\r
+                       if(($rc = $this->IFS->getRecord($imgname)) && $this->_deleteImageShack($rc['imgURL'])){ $this->IFS->delRecord($imgname); return true; }\r
+                       return false;\r
+               }\r
+       }\r
+\r
+       function uploadImage($imgname='', $imgpath='', $imgsize=0){\r
+               if($imgname=='') return true; // 支援上傳方法\r
+               if(substr($imgname, -5)=='s.jpg'){ unlink($imgpath); return true; } // 預覽圖不用上傳,直接刪除\r
+               $result = $this->_transloadImageShack($imgname);\r
+               if($result){\r
+                       $this->IFS->addRecord($imgname, $imgsize, $result['image_link']); // 加入索引之中\r
+                       list($w, $h) = explode('x', $result['resolution']); // 原圖解析度\r
+                       // 判斷是否自動生成預覽圖 (長寬任一大於200像素) 並儲存預覽圖位置\r
+                       $this->IFS->addRecord(substr($imgname, 0, 13).'s.jpg', ceil($imgsize / 4), (($w > 200 || $h > 200) ?  $result['thumb_link'] : $result['image_link']));\r
+                       unlink($imgpath); // 確實上傳後刪除本機暫存\r
+               }\r
+               return $result;\r
+       }\r
+\r
+       function getImageFilesize($imgname){\r
+               if($rc = $this->IFS->getRecord($imgname)) return $rc['imgSize'];\r
+               return false;\r
+       }\r
+\r
+       function getImageURL($imgname, $ishotlink = false){ // 是否使用熱連結直連圖檔位置 (極有可能被 Ban 網域!請慎用)\r
+               return ($rc = $this->IFS->getRecord($imgname)) ? (substr($imgname, -5)=='s.jpg' ? $rc['imgURL'] : $this->_myphpImageShack($rc['imgURL'], $ishotlink)) : false;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/lib/fileio/fileio.normal.php b/lib/fileio/fileio.normal.php
new file mode 100755 (executable)
index 0000000..12926ab
--- /dev/null
@@ -0,0 +1,51 @@
+<?php\r
+/**\r
+ * FileIO Normal 本機儲存 API\r
+ *\r
+ * 以本機硬碟空間作為圖檔儲存的方式,並提供一套方法供程式管理圖片\r
+ *\r
+ * @package PMCLibrary\r
+ * @version $Id: fileio.normal.php 393 2007-04-30 11:25:29Z scribe $\r
+ * @date $Date: 2007-04-30 19:25:29 +0800 (星期一, 30 四月 2007) $\r
+ */\r
+\r
+class FileIO{\r
+       var $path, $imgPath, $thumbPath;\r
+\r
+       /* private 藉由檔名分辨圖檔存放位置 */\r
+       function _getImagePhysicalPath($imgname){\r
+               return (substr($imgname, -5)=='s.jpg' ? $this->thumbPath : $this->imgPath).$imgname;\r
+       }\r
+\r
+       function FileIO($parameter='', $ENV){\r
+               $this->path = $ENV['PATH'];\r
+               $this->imgPath = $this->path.$ENV['IMG'];\r
+               $this->thumbPath = $this->path.$ENV['THUMB'];\r
+       }\r
+\r
+       function init(){\r
+               return true;\r
+       }\r
+\r
+       function imageExists($imgname){\r
+               return file_exists($this->_getImagePhysicalPath($imgname));\r
+       }\r
+\r
+       function deleteImage($imgname){\r
+               if(is_array($imgname)){ foreach($imgname as $i){ if(!@unlink($this->_getImagePhysicalPath($i))) return false; } return true; }\r
+               else{ return @unlink($this->_getImagePhysicalPath($imgname)); }\r
+       }\r
+\r
+       function uploadImage($imgname='', $imgpath='', $imgsize=0){\r
+               return false;\r
+       }\r
+\r
+       function getImageFilesize($imgname){\r
+               return @filesize($this->_getImagePhysicalPath($imgname));\r
+       }\r
+\r
+       function getImageURL($imgname){\r
+               return $this->getImageLocalURL($imgname);\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/lib/fileio/fileio.satellite.php b/lib/fileio/fileio.satellite.php
new file mode 100755 (executable)
index 0000000..f97deb7
--- /dev/null
@@ -0,0 +1,182 @@
+<?php\r
+/**\r
+ * FileIO Satellite 衛星計畫後端\r
+ *\r
+ * 搭配 satellite.php/pl 利用遠端空間管理圖檔\r
+ *\r
+ * @package PMCLibrary\r
+ * @version $Id: fileio.satellite.php 636 2008-05-19 07:54:19Z scribe $\r
+ * @date $Date: 2008-05-19 15:54:19 +0800 (星期一, 19 五月 2008) $\r
+ */\r
+\r
+class FileIO{\r
+       var $userAgent, $parameter, $thumbLocalPath;\r
+       var $IFS;\r
+\r
+       /* private 測試連線並且初始化遠端衛星主機 */\r
+       function _initSatellite(){\r
+               if(!($fp = @fsockopen($this->parameter[0]['host'], 80))) return false;\r
+\r
+               $argument = 'mode=init&key='.$this->parameter[2];\r
+               $out = 'POST '.$this->parameter[0]['path']." HTTP/1.1\r\n";\r
+               $out .= 'Host: '.$this->parameter[0]['host']."\r\n";\r
+               $out .= 'User-Agent: '.$this->userAgent."\r\n";\r
+               $out .= "Content-Type: application/x-www-form-urlencoded\r\n";\r
+               $out .= 'Content-Length: '.strlen($argument)."\r\n\r\n";\r
+               $out .= $argument;\r
+               fwrite($fp, $out);\r
+               $result = fgets($fp, 128); // 取一次足以取到檔頭\r
+               fclose($fp);\r
+\r
+               return (strpos($result, '202 Accepted')!==false ? true : false); // 檢查狀態值偵測是否傳輸成功\r
+       }\r
+\r
+       /* private 傳送抓取要求到遠端衛星主機上面 */\r
+       function _transloadSatellite($imgname){\r
+               if(!($fp = @fsockopen($this->parameter[0]['host'], 80))) return false;\r
+\r
+               $argument = 'mode=transload&key='.$this->parameter[2].'&imgurl='.$this->getImageLocalURL($imgname).'&imgname='.$imgname;\r
+               $out = 'POST '.$this->parameter[0]['path']." HTTP/1.1\r\n";\r
+               $out .= 'Host: '.$this->parameter[0]['host']."\r\n";\r
+               $out .= 'User-Agent: '.$this->userAgent."\r\n";\r
+               $out .= "Content-Type: application/x-www-form-urlencoded\r\n";\r
+               $out .= 'Content-Length: '.strlen($argument)."\r\n\r\n";\r
+               $out .= $argument;\r
+               fwrite($fp, $out);\r
+               $result = fgets($fp, 128); // 取一次足以取到檔頭\r
+               fclose($fp);\r
+\r
+               return (strpos($result, '202 Accepted')!==false ? true : false); // 檢查狀態值偵測是否傳輸成功\r
+       }\r
+\r
+       /* private 直接傳送檔案到遠端衛星主機上面 */\r
+       function _uploadSatellite($imgname, $imgpath){\r
+               srand((double) microtime()*1000000);\r
+               $boundary = '---------------------'.substr(md5(rand(0,32000)), 0, 10); // 生成分隔線\r
+\r
+               $argument = ''; // 資料暫存\r
+               // 一般欄位資料轉換\r
+               $formField = array('mode' => 'upload', 'key' => $this->parameter[2], 'imgname' => $imgname);\r
+               foreach($formField as $ikey => $ival){\r
+                       $argument .= "--$boundary\r\n";\r
+                       $argument .= "Content-Disposition: form-data; name=\"".$ikey."\"\r\n\r\n";\r
+                       $argument .= $ival."\r\n";\r
+                       $argument .= "--$boundary\r\n";\r
+               }\r
+               // 上傳檔案欄位資料轉換\r
+               $imginfo = getimagesize($imgpath); // 取得圖檔資訊\r
+               $argument .= "--$boundary\r\n";\r
+               $argument .= 'Content-Disposition: form-data; name="imgfile"; filename="'.$imgname.'"'."\r\n";\r
+               $argument .= 'Content-Type: '.$imginfo['mime']."\r\n\r\n";\r
+               $argument .= join('', file($imgpath))."\r\n";\r
+               $argument .= "--$boundary--\r\n";\r
+\r
+               $out = 'POST '.$this->parameter[0]['path']." HTTP/1.1\r\n";\r
+               $out .= 'Host: '.$this->parameter[0]['host']."\r\n";\r
+               $out .= 'User-Agent: '.$this->userAgent."\r\n";\r
+               $out .= "Content-Type: multipart/form-data, boundary=$boundary\r\n";\r
+               $out .= 'Content-Length: '.strlen($argument)."\r\n\r\n";\r
+               $out .= $argument;\r
+\r
+               if(!($fp = @fsockopen($this->parameter[0]['host'], 80))) return false;\r
+               fwrite($fp, $out);\r
+               $result = fgets($fp, 128);\r
+               fclose($fp);\r
+\r
+               return (strpos($result, '202 Accepted')!==false ? true : false);\r
+       }\r
+\r
+       /* private 發出刪除圖片要求 */\r
+       function _deleteSatellite($imgname){\r
+               if(!($fp = @fsockopen($this->parameter[0]['host'], 80))) return false;\r
+\r
+               $argument = 'mode=delete&key='.$this->parameter[2].'&imgname='.$imgname;\r
+               $out = 'POST '.$this->parameter[0]['path']." HTTP/1.1\r\n";\r
+               $out .= 'Host: '.$this->parameter[0]['host']."\r\n";\r
+               $out .= 'User-Agent: '.$this->userAgent."\r\n";\r
+               $out .= "Content-Type: application/x-www-form-urlencoded\r\n";\r
+               $out .= 'Content-Length: '.strlen($argument)."\r\n\r\n";\r
+               $out .= $argument;\r
+               fwrite($fp, $out);\r
+               $result = fgets($fp, 128);\r
+               fclose($fp);\r
+\r
+               return (strpos($result, '202 Accepted')!==false ? true : false);\r
+       }\r
+\r
+       /* private 儲存索引檔 */\r
+       function _setIndex(){\r
+               $this->IFS->saveIndex(); // 索引表更新\r
+       }\r
+\r
+       function FileIO($parameter, $ENV){\r
+               require($ENV['IFS.PATH']);\r
+               $this->IFS = new IndexFS($ENV['IFS.LOG']); // IndexFS 物件\r
+               $this->IFS->openIndex();\r
+               register_shutdown_function(array($this, '_setIndex')); // 設定解構元 (PHP 結束前執行)\r
+               set_time_limit(120); // 執行時間 120 秒 (傳輸過程可能很長)\r
+               $this->userAgent = 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)'; // Just for fun ;-)\r
+               $this->thumbLocalPath = $ENV['PATH'].$ENV['THUMB']; // 預覽圖本機位置\r
+               $this->parameter = $parameter; // 將參數重新解析\r
+               $this->parameter[0] = parse_url($this->parameter[0]); // URL 位置拆解\r
+               /*\r
+                       [0] : 衛星程式遠端 URL 位置\r
+                       [1] : 是否使用 Transload 方式要求衛星程式抓取圖檔 (true:是 false:否,使用傳統 HTTP 上傳)\r
+                       [2] : 傳輸認證金鑰\r
+                       [3] : 遠端目錄對應 URL\r
+                       [4] : 預覽圖是否上傳至遠端 (true: 是, false: 否,使用本機檔案)\r
+               */\r
+       }\r
+\r
+       function init(){\r
+               return $this->_initSatellite();\r
+       }\r
+\r
+       function imageExists($imgname){\r
+               if(!$this->parameter[4] && substr($imgname, -5) == 's.jpg') return file_exists($this->thumbLocalPath.$imgname);\r
+               return $this->IFS->beRecord($imgname);\r
+       }\r
+\r
+       function deleteImage($imgname){\r
+               if(is_array($imgname)){\r
+                       foreach($imgname as $i){\r
+                               if(!$this->parameter[4] && substr($i, -5) == 's.jpg'){\r
+                                       @unlink($this->thumbLocalPath.$i);\r
+                               }else{\r
+                                       if(!$this->_deleteSatellite($i)) return false;\r
+                                       $this->IFS->delRecord($i); // 自索引中刪除\r
+\r
+                               }\r
+                       }\r
+                       return true;\r
+               }\r
+               else{\r
+                       if(!$this->parameter[4] && substr($imgname, -5) == 's.jpg') return @unlink($this->thumbLocalPath.$imgname);\r
+                       if($result = $this->_deleteSatellite($imgname)) $this->IFS->delRecord($imgname);\r
+                       return $result;\r
+               }\r
+       }\r
+\r
+       function uploadImage($imgname='', $imgpath='', $imgsize=0){\r
+               if($imgname=='') return true; // 支援上傳方法\r
+               if(!$this->parameter[4] && substr($imgname, -5) == 's.jpg') return false; // 不處理預覽圖\r
+               $result = $this->parameter[1] ? $this->_transloadSatellite($imgname) : $this->_uploadSatellite($imgname, $imgpath); // 選擇傳輸方法\r
+               if($result){\r
+                       $this->IFS->addRecord($imgname, $imgsize, ''); // 加入索引之中\r
+                       unlink($imgpath); // 確實上傳後刪除本機暫存\r
+               }\r
+               return $result;\r
+       }\r
+\r
+       function getImageFilesize($imgname){\r
+               if(!$this->parameter[4] && substr($imgname, -5) == 's.jpg') return @filesize($this->thumbLocalPath.$imgname);\r
+               if($rc = $this->IFS->getRecord($imgname)) return $rc['imgSize'];\r
+               return false;\r
+       }\r
+\r
+       function getImageURL($imgname){\r
+               if(!$this->parameter[4] && substr($imgname, -5) == 's.jpg') return $this->getImageLocalURL($imgname);\r
+               return $this->IFS->beRecord($imgname) ? $this->parameter[3].$imgname : false;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/lib/fileio/ifs.php b/lib/fileio/ifs.php
new file mode 100755 (executable)
index 0000000..b442eeb
--- /dev/null
@@ -0,0 +1,117 @@
+<?php\r
+/**\r
+ * FileIO Index File System\r
+ *\r
+ * 把遠端圖檔的各種屬性作本機快取及記錄,方便程式取用\r
+ *\r
+ * @package PMCLibrary\r
+ * @version $Id: ifs.php 393 2007-04-30 11:25:29Z scribe $\r
+ * @date $Date: 2007-04-30 19:25:29 +0800 (星期一, 30 四月 2007) $\r
+ */\r
+\r
+class IndexFS{\r
+       var $logfile, $backend, $index, $modified;\r
+\r
+       /* 建構元 */\r
+       function IndexFS($logfile){\r
+               $this->logfile = $logfile; // 索引記錄檔位置\r
+       }\r
+\r
+       /* 初始化 */\r
+       function init(){\r
+               switch($this->backend){\r
+                       case 'log':\r
+                               touch($this->logfile); chmod($this->logfile, 0666); // 建立索引檔\r
+                               break;\r
+                       case 'sqlite2':\r
+                               $execText = 'CREATE TABLE IndexFS (\r
+                               "imgName" VARCHAR(20)  NOT NULL PRIMARY KEY,\r
+                               "imgSize" INTEGER  NOT NULL,\r
+                               "imgURL" VARCHAR(255)  NOT NULL\r
+                               ); CREATE INDEX IDX_IndexFS_imgName ON IndexFS(imgName);';\r
+                               sqlite_exec($this->index, $execText);\r
+                               break;\r
+               }\r
+       }\r
+\r
+       /* 開啟索引檔並讀入 */\r
+       function openIndex(){\r
+               if(extension_loaded('SQLite')){\r
+                       $this->backend = 'sqlite2';\r
+                       $this->index = sqlite_open($this->logfile, 0666);\r
+                       if(sqlite_num_rows(sqlite_query($this->index, "SELECT name FROM sqlite_master WHERE name LIKE 'IndexFS'"))===0) $this->init();\r
+               }else{\r
+                       $this->backend = 'log';\r
+                       $this->modified = false;\r
+                       if(!file_exists($this->logfile)){ $this->init(); return; }\r
+                       if(filesize($this->logfile)==0) return;\r
+                       $indexlog = file($this->logfile); $indexlog_count = count($indexlog); // 讀入索引檔並計算目前筆數\r
+                       $this->index = array();\r
+                       for($i = 0; $i < $indexlog_count; $i++){\r
+                               if(!($trimline = rtrim($indexlog[$i]))) continue; // 本行無意義\r
+                               $field = explode("\t\t", $trimline);\r
+                               $this->index[$field[0]] = array('imgSize' => $field[1], 'imgURL' => $field[2]);\r
+                               // 索引格式: 檔名 檔案大小    對應路徑\r
+                       }\r
+                       unset($indexlog);\r
+               }\r
+       }\r
+\r
+       /* 索引是否存在 */\r
+       function beRecord($id){\r
+               switch($this->backend){\r
+                       case 'log':\r
+                               return isset($this->index[$id]);\r
+                       case 'sqlite2':\r
+                               return (sqlite_fetch_array(sqlite_query($this->index, 'SELECT imgName FROM IndexFS WHERE imgName = "'.sqlite_escape_string($id).'"'), SQLITE_ASSOC) ? true : false);\r
+               }\r
+       }\r
+\r
+       /* 取得一筆索引 */\r
+       function getRecord($id){\r
+               switch($this->backend){\r
+                       case 'log':\r
+                               return isset($this->index[$id]) ? $this->index[$id] : false;\r
+                       case 'sqlite2':\r
+                               return sqlite_fetch_array(sqlite_query($this->index, 'SELECT * FROM IndexFS WHERE imgName = "'.sqlite_escape_string($id).'"'), SQLITE_ASSOC);\r
+               }\r
+       }\r
+\r
+       /* 新增一筆索引 */\r
+       function addRecord($id, $imgSize, $imgURL){\r
+               switch($this->backend){\r
+                       case 'log':\r
+                               $this->modified = true;\r
+                               $this->index[$id] = array('imgSize' => $imgSize, 'imgURL' => $imgURL); // 加入索引之中\r
+                               break;\r
+                       case 'sqlite2':\r
+                               sqlite_exec($this->index, 'INSERT INTO IndexFS (imgName, imgSize, imgURL) VALUES ("'.sqlite_escape_string($id).'", '.sqlite_escape_string($imgSize).', "'.sqlite_escape_string($imgURL).'");');\r
+                               break;\r
+               }\r
+       }\r
+\r
+       /* 刪除一筆索引 */\r
+       function delRecord($id){\r
+               switch($this->backend){\r
+                       case 'log':\r
+                               if(isset($this->index[$id])){ unset($this->index[$id]); $this->modified = true; return true; }\r
+                               return false;\r
+                       case 'sqlite2':\r
+                               return sqlite_exec($this->index, 'DELETE FROM IndexFS WHERE imgName = "'.sqlite_escape_string($id).'";');\r
+               }\r
+       }\r
+\r
+       /* 儲存索引變更 */\r
+       function saveIndex(){\r
+               if($this->backend=='log' && $this->modified){ // 如果有修改索引就回存\r
+                       $indexlog = '';\r
+                       if(count($this->index)) foreach($this->index as $ikey => $ival){ $indexlog .= $ikey."\t\t".$ival['imgSize']."\t\t".$ival['imgURL']."\n"; } // 有資料才跑迴圈\r
+                       $fp = fopen($this->logfile, 'w');\r
+                       fwrite($fp, $indexlog);\r
+                       fclose($fp);\r
+               }elseif($this->backend=='sqlite2'){\r
+                       sqlite_close($this->index);\r
+               }\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/lib/lang/de_DE.php b/lib/lang/de_DE.php
new file mode 100755 (executable)
index 0000000..87d3307
--- /dev/null
@@ -0,0 +1,240 @@
+<?php\r
+/*\r
+Pixmicat! & Yotsubanome language file - German [de_DE]\r
+*/\r
+if (!isset($language)) $language = Array();\r
+\r
+// yotsubanome.php\r
+$language['page_not_found']                            = 'Sorry, the page you requested is not found.';\r
+$language['thread_not_found']                  = 'The thread you want to reply does not exist!';\r
+$language['del_head']                                  = '[Delete Post]';\r
+$language['del_img_only']                              = 'Delete image only';\r
+$language['del_pass']                                  = 'Password: ';\r
+$language['del_btn']                                   = ' Submit ';\r
+$language['prev_page']                                 = 'Previous';\r
+$language['first_page']                                        = 'First';\r
+$language['all_pages']                                 = 'ALL';\r
+$language['next_page']                                 = 'Next';\r
+$language['last_page']                                 = 'Last';\r
+$language['img_sample']                                        = '[Thumbnail]';\r
+$language['img_filename']                              = 'Filename: ';\r
+$language['reply_btn']                                 = 'Reply';\r
+$language['warn_sizelimit']                            = 'Image will be deleted soon because of the storage limit of image.';\r
+$language['warn_oldthread']                            = 'Thread will be deleted soon because it is old.';\r
+$language['warn_locked']                               = 'Thread is locked by administrator.';\r
+$language['notice_omitted_posts']                              = '[#] post[s]';
+$language['notice_omitted_images']                             = ' and [#] image[s]';
+$language['notice_omitted_reply']                              = ' omitted. Click [Reply] to view.';\r
+$language['post_name']                                 = 'Name: ';\r
+$language['post_category']                             = 'Category: ';\r
+$language['regist_notpost']                            = 'Please use the form on the board to submit.';\r
+$language['regist_nospam']                             = 'Anti Spambot system activated.';\r
+$language['regist_ipfiltered']                 = 'Your connection is refused. Reason: %1$s';\r
+$language['regist_wordfiltered']               = 'Banned words is found, cannot submit.';\r
+$language['regist_upload_exceedphp']   = 'Upload failed.<br />File size exceeds server limitation.';\r
+$language['regist_upload_exceedcustom']        = 'Upload failed.<br />File size exceeds limitation.';\r
+$language['regist_upload_incompelete'] = 'Upload failed.<br />Incomplete upload. Please retry.';\r
+$language['regist_upload_direrror']            = 'Upload failed.<br />Wrong setting of upload temporary directory. Please contact the system administrator.';\r
+$language['regist_upload_noimg']               = 'Please check No Image check box if you post without uploading an image!';\r
+$language['regist_upload_filenotfound']        = 'Upload failed.<br />Server disabled file uploading, permission denied, or unsupported format.';\r
+$language['regist_upload_killincomp']  = '[Notice] Your sending was canceled because of the incorrect file size.';\r
+$language['regist_upload_notimage']            = 'Upload failed.<br />Files other than image is not accepted.';\r
+$language['regist_upload_notsupport']  = 'Unsupported image.';\r
+$language['regist_upload_blocked']             = 'Upload failed.<br />Uploading this image is blocked.';\r
+$language['regist_uploaded']                   = 'Image %1$s uploaded.<br />';\r
+$language['regist_sakuradetected']             = 'Big5 sakura Japanese characters detected.';
+$language['regist_withoutname']                        = 'Please fill your name.';
+$language['regist_withoutsubject']                     = 'Please fill the title.';\r
+$language['regist_withoutcomment']             = 'Please fill comment field if you don\'t upload an image.';
+$language['regist_withoutpassword']                    = 'Please fill your password.';\r
+$language['regist_nametoolong']                        = 'Name is too long.';\r
+$language['regist_emailtoolong']               = 'E-mail is too long.';\r
+$language['regist_topictoolong']               = 'Topic is too long.';\r
+$language['regist_longthreadnum']              = 'The thread you reply may be wrong.';\r
+$language['admin']                                             = 'Admin';\r
+$language['deletor']                                   = 'Deletor';\r
+$language['trip_pre']                                  = '◆';\r
+$language['trip_pre_fake']                             = '◇';\r
+$language['cap_char']                                  = '★';\r
+$language['cap_char_fake']                             = '☆';\r
+$language['regist_commenttoolong']             = 'Comment is too long.';\r
+$language['notice_incompletefile']             = 'Notice: Incomplete image.';\r
+$language['sun']                                               = 'Sun';\r
+$language['mon']                                               = 'Mon';\r
+$language['tue']                                               = 'Tue';\r
+$language['wed']                                               = 'Wed';\r
+$language['thu']                                               = 'Thu';\r
+$language['fri']                                               = 'Fri';\r
+$language['sat']                                               = 'Sat';\r
+$language['regist_successivepost']             = 'Please wait for a while for continuous posting.';\r
+$language['regist_duplicatefile']              = 'Upload failed.<br />Same file uploaded lately.';\r
+$language['regist_threaddeleted']              = 'This thread is too old that it is deleted!';\r
+$language['regist_threadlocked']               = 'Thread is locked by administrator!';\r
+$language['regist_redirect']                   = '%1$s Redirecting... <p>If your browser don\'t redirect for you, please click: <a href="%2$s">Return</a></p>';\r
+$language['del_notchecked']                            = 'Nothing selected for deletion. Please go back and select again.';\r
+$language['del_wrongpwornotfound']             = 'No such post or wrong password.';\r
+$language['admin_wrongpassword']               = 'Wrong password';\r
+$language['return']                                            = 'Return';\r
+$language['admin_remake']                              = 'Update';\r
+$language['admin_frontendmanage']              = 'Front-End Manage (Sign in needed)';\r
+$language['admin_delete']                              = 'Delete';\r
+$language['admin_top']                                 = 'Administrator mode';\r
+$language['admin_manageposts']                 = 'Manage posts';\r
+$language['admin_optimize']                            = 'Optimize';\r
+$language['admin_check']                               = 'Check data source';\r
+$language['admin_repair']                              = 'Repair data source';\r
+$language['admin_export']                              = 'Export data';\r
+$language['admin_logout']                              = 'Sign out';\r
+$language['admin_verify_btn']                  = ' Sign in ';\r
+$language['admin_archive']                             = '<th>Archive</th>';\r
+$language['admin_notices']                             = '<ul><li>If you want to delete a post, check the "delete" checkbox before that post and click Submit button.</li><li>If you want to delete image only, please check "Delete image only" checkbox and follow normal deletion procedures.</li><li>If you want to lock/unlock a thread, please check "Stop" checkbox of that thread and click "Submit" button.</li><li>Please press "Update" after managing posts.</li></ul>';\r
+$language['admin_submit_btn']                  = ' Submit ';\r
+$language['admin_reset_btn']                   = ' Reset ';\r
+$language['admin_list_header']                 = '<th>Func</th><th>Stop</th><th>Del</th><th>Date</th><th>Topic</th><th>Name</th><th>Comment</th><th>Host</th><th>Image (Bytes)<br />MD5 checksum</th>';\r
+$language['admin_archive_btn']                 = 'A';\r
+$language['admin_stop_btn']                            = 'Stop';\r
+$language['admin_totalsize']                   = '[Total size of images: <b>%1$s</b> KB ]';\r
+$language['search_disabled']                   = 'Search is disabled!';\r
+$language['search_top']                                        = 'Search';\r
+$language['search_notice']                             = '<li>Please enter keyword and set search target, then press "Search" button.</li><li>Searching with multiple keywords can be done by seperating keywords with space.</li><li>You can set Search method("and searching" and "or searching") for multiple keywords searching.<p />Keyword:';\r
+$language['search_target']                             = 'Target:';\r
+$language['search_target_comment']             = 'Comment';\r
+$language['search_target_name']                        = 'Name';\r
+$language['search_target_topic']               = 'Topic';\r
+$language['search_target_number']              = 'No.';\r
+$language['search_method']                             = 'Method:';\r
+$language['search_method_and']                 = 'AND';\r
+$language['search_method_or']                  = 'OR';\r
+$language['search_submit_btn']                 = ' Search ';\r
+$language['search_notfound']                   = 'no search result with specified keyword.';\r
+$language['search_back']                               = '[Back]';\r
+$language['category_nokeyword']                        = 'Please enter category for searching similar posts.';\r
+$language['category_notfound']                 = 'No matching posts for this category.';\r
+$language['category_recache']                  = 'Recache';\r
+$language['module_info_top']                   = 'Module Information';\r
+$language['module_loaded']                             = 'Module Loaded:';\r
+$language['module_info']                               = 'Module Infomation:';\r
+$language['info_top']                                  = 'System Information';\r
+$language['info_disabled']                             = 'Disabled';\r
+$language['info_enabled']                              = 'Enabled';\r
+$language['info_functional']                   = 'Functional';\r
+$language['info_nonfunctional']                        = 'Non functional';\r
+$language['info_basic']                                        = 'Basic Settings';\r
+$language['info_basic_ver']                            = 'Program version';\r
+$language['info_basic_pio']                            = 'PIO library backend and version';\r
+$language['info_basic_threadsperpage'] = 'Threads per page';\r
+$language['info_basic_threads']                        = '';\r
+$language['info_basic_postsperpage']   = 'Replies to show in index';\r
+$language['info_basic_posts']                  = '';\r
+$language['info_basic_postsinthread']  = 'Posts per page in Reply mode';\r
+$language['info_basic_posts_showall']  = '(Show all:0)';\r
+$language['info_basic_bumpposts']              = 'Do not bump post if reply is more than';\r
+$language['info_basic_bumphours']              = 'Thread bumping hours';\r
+$language['info_basic_hours']                  = 'hour(s)';\r
+$language['info_basic_0disable']               = '(Disable:0)';\r
+$language['info_basic_urllinking']             = 'URL Auto Linking';\r
+$language['info_0no1yes']                              = '(Yes:1 No:0)';\r
+$language['info_basic_com_limit']              = 'Maximum size of comments';\r
+$language['info_basic_com_after']              = ' Bytes';\r
+$language['info_basic_anonpost']               = 'Anonymous posting';\r
+$language['info_basic_anonpost_opt']   = '(Force anonymous:2 Yes:1 No:0)';\r
+$language['info_basic_del_incomplete'] = 'Delete incomplete images';\r
+$language['info_basic_use_sample']             = 'Use thumbnails (Quality: %1$s)';\r
+$language['info_0notuse1use']                  = '(Use:1 Not used:0)';\r
+$language['info_basic_use_sample_func']        = '+ Thumbnails generation';\r
+$language['info_basic_useblock']               = 'IP blocking';\r
+$language['info_0disable1enable']              = '(Enable:1 Disable:0)';\r
+$language['info_basic_showid']                 = 'Show ID';\r
+$language['info_basic_showid_after']   = '(force show:2 selective show:1 do not show:0)';\r
+$language['info_basic_cr_limit']               = 'Comment row limit';\r
+$language['info_basic_cr_after']               = ' Row(s) (unlimited:0)';\r
+//$language['info_basic_timezone']             = 'Time zone';
+$language['info_basic_max_lines_limit']                = 'Comment line limit';
+$language['info_basic_max_lines_after']                = ' Line(s) (unlimited:0)';\r
+$language['info_basic_threadcount']            = 'Total threads count';\r
+$language['info_basic_theme']                  = 'Theme';\r
+$language['info_dsusage_top']                  = 'Data source usage';\r
+$language['info_dsusage_max']                  = 'Maximum size';\r
+$language['info_dsusage_usage']                        = 'Usage';\r
+$language['info_dsusage_count']                        = 'Current usage';\r
+$language['info_fileusage_top']                        = 'Storage limit of images:';\r
+$language['info_fileusage_limit']              = 'Maximum size';\r
+$language['info_fileusage_count']              = 'Current usage';\r
+$language['info_fileusage_unlimited']  = 'Unlimited';\r
+$language['info_server_top']                   = 'Server infomation';\r
+$language['info_server_gd']                            = 'GD library ';\r
+$language['init_permerror']                            = 'No write permission in root directory. Please modify permission settings.<br />';\r
+$language['init_inited']                               = 'Environment initialized.<br />Please edit this file and remove init() statement.<br />';\r
+$language['action_main_notsupport']            = 'Backend does not support this operation.';\r
+$language['action_main_optimize']              = 'Optimization ';\r
+$language['action_main_check']                 = 'Check ';\r
+$language['action_main_repair']                        = 'Repair ';\r
+$language['action_main_export']                        = 'Export ';\r
+$language['action_main_success']               = 'success!';\r
+$language['action_main_failed']                        = 'failed!';\r
+\r
+// lib_common.php\r
+$language['head_home']                                 = 'Home';\r
+$language['head_search']                               = 'Search';\r
+$language['head_info']                                 = 'Info';\r
+$language['head_admin']                                        = 'Admin';\r
+$language['head_refresh']                              = 'Refresh';\r
+$language['form_top']                                  = 'Reply Mode';\r
+$language['form_showpostform']                 = 'Post';\r
+$language['form_hidepostform']                 = 'Hide form';\r
+$language['form_name']                                 = 'Name';\r
+$language['form_email']                                        = 'E-mail';\r
+$language['form_topic']                                        = 'Subject';\r
+$language['form_submit_btn']                   = 'Submit';\r
+$language['form_comment']                              = 'Comment';\r
+$language['form_attechment']                   = 'File';\r
+$language['form_noattechment']                 = 'No File';\r
+$language['form_contpost']                             = 'Noko';\r
+$language['form_category']                             = 'Category';\r
+$language['form_category_notice']              = '(Use , to seperate)';\r
+$language['form_delete_password']              = 'Password';\r
+$language['form_delete_password_notice']= '(Password used for post and file deletion, 8 chars max)';\r
+$language['form_notice']                               = '<li>Supported file types are: %1$s</li><li>Maximum file size allowed is %2$s KB. Fill E-mail with sage for not bumping post.</li><li>Images greater than %3$s * %4$s pixels will be thumbnailed.</li>';\r
+$language['form_notice_storage_limit'] = '<li>Current storage usage: %1$s KB / %2$s KB</li>';\r
+$language['form_notice_noscript']              = '*** You disabled JavaScript, but this won\'t affect you when browsing and posting.';\r
+$language['error_back']                                        = 'Back';\r
+$language['ip_banned']                                 = 'Listed in IP/Hostname Blacklist';\r
+$language['ip_dnsbl_banned']                   = 'Listed in DNSBL(%1$s) Blacklist';\r
+\r
+// mainscript.js // regist_withoutcomment,regist_upload_notsupport,js_convert_sakura\r
+$language['js_convert_sakura']                 = 'Big5 sakura Japanese characters detected, please try to convert to standard one.';\r
+\r\r
+$language['form_option1']                      = '<span id="option">Option1</span>';
+$language['form_newt']         = 'New Thread';
+
+$language['nothumb']           = 'Thumbnail unavailable';
+$language['long_comment']              = '「Comment too long. Click ';
+$language['long_here']         = 'here';
+$language['long_see']          = ' to view the full text.」';
+
+$language['def_sub']           = '無題';
+$language['def_name']          = '名無し';
+$language['def_com']           = '';
+
+// Style tooltip: stuff inside [square brackets] MUST be left as is!\r
+$language['style_tooltip']             = 'Switch to [what] style';
+// Title of stylesheet management page\r
+$language['admin_stylesheets']         = 'Manage Stylesheets';\r
+$language['admin_imported']            = 'Imported from <b>[file]</b>';\r
+$language['admin_editing']             = 'Editing <b>[file]</b>';\r
+$language['admin_created']             = '<b>[file]</b> created!';\r
+$language['admin_updated']             = '<b>[file]</b> updated!';\r
+$language['admin_deleted']             = '<b>[file]</b> deleted!';\r
+// Headings for fields\r
+$language['admin_is_default']          = 'Default?';\r
+$language['admin_style_default']               = 'Make this default';\r
+$language['admin_fullname']            = 'Full name';\r
+$language['admin_shortname']           = 'Short name';\r
+$language['admin_dispid']              = '<nobr>ID / Display order</nobr> <nobr>(0 to delete)</nobr>';\r
+$language['admin_addstyle']            = 'Add [or modify] stylesheet entry';\r
+// This goes in [or modify] above\r
+$language['admin_modstyle']            = 'or modify';\r
+$language['admin_new_file']            = 'File';\r
+$language['admin_new_id']              = '<nobr>Display order</nobr> <nobr>(Use existing ID to overwrite)</nobr>';
+if(!defined("PIXMICAT_LANGUAGE")) print_r($language);\r
+?>
\ No newline at end of file
diff --git a/lib/lang/en_US.php b/lib/lang/en_US.php
new file mode 100755 (executable)
index 0000000..1d7bfa6
--- /dev/null
@@ -0,0 +1,240 @@
+<?php\r
+/*\r
+Pixmicat! & Yotsubanome language file - English (U.S.) [en_US]\r
+*/\r
+if (!isset($language)) $language = Array();\r
+\r
+// yotsubanome.php\r
+$language['page_not_found']                            = 'Sorry, the page you requested is not found.';\r
+$language['thread_not_found']                  = 'The thread you want to reply does not exist!';\r
+$language['del_head']                                  = '[Delete Post]';\r
+$language['del_img_only']                              = 'Delete image only';\r
+$language['del_pass']                                  = 'Password: ';\r
+$language['del_btn']                                   = ' Submit ';\r
+$language['prev_page']                                 = 'Previous';\r
+$language['first_page']                                        = 'First';\r
+$language['all_pages']                                 = 'ALL';\r
+$language['next_page']                                 = 'Next';\r
+$language['last_page']                                 = 'Last';\r
+$language['img_sample']                                        = '[Thumbnail]';\r
+$language['img_filename']                              = 'Filename: ';\r
+$language['reply_btn']                                 = 'Reply';\r
+$language['warn_sizelimit']                            = 'Image will be deleted soon because of the storage limit of image.';\r
+$language['warn_oldthread']                            = 'Thread will be deleted soon because it is old.';\r
+$language['warn_locked']                               = 'Thread is locked by administrator.';\r
+$language['notice_omitted_posts']                              = '[#] post[s]';
+$language['notice_omitted_images']                             = ' and [#] image[s]';
+$language['notice_omitted_reply']                              = ' omitted. Click [Reply] to view.';\r
+$language['post_name']                                 = 'Name: ';\r
+$language['post_category']                             = 'Category: ';\r
+$language['regist_notpost']                            = 'Please use the form on the board to submit.';\r
+$language['regist_nospam']                             = 'Anti Spambot system activated.';\r
+$language['regist_ipfiltered']                 = 'Your connection is refused. Reason: %1$s';\r
+$language['regist_wordfiltered']               = 'Banned words is found, cannot submit.';\r
+$language['regist_upload_exceedphp']   = 'Upload failed.<br />File size exceeds server limitation.';\r
+$language['regist_upload_exceedcustom']        = 'Upload failed.<br />File size exceeds limitation.';\r
+$language['regist_upload_incompelete'] = 'Upload failed.<br />Incomplete upload. Please retry.';\r
+$language['regist_upload_direrror']            = 'Upload failed.<br />Wrong setting of upload temporary directory. Please contact the system administrator.';\r
+$language['regist_upload_noimg']               = 'Please check No Image check box if you post without uploading an image!';\r
+$language['regist_upload_filenotfound']        = 'Upload failed.<br />Server disabled file uploading, permission denied, or unsupported format.';\r
+$language['regist_upload_killincomp']  = '[Notice] Your sending was canceled because of the incorrect file size.';\r
+$language['regist_upload_notimage']            = 'Upload failed.<br />Files other than image is not accepted.';\r
+$language['regist_upload_notsupport']  = 'Unsupported image.';\r
+$language['regist_upload_blocked']             = 'Upload failed.<br />Uploading this image is blocked.';\r
+$language['regist_uploaded']                   = 'Image %1$s uploaded.<br />';\r
+$language['regist_sakuradetected']             = 'Big5 sakura Japanese characters detected.';
+$language['regist_withoutname']                        = 'Please fill your name.';
+$language['regist_withoutsubject']                     = 'Please fill the title.';\r
+$language['regist_withoutcomment']             = 'Please fill comment field if you don\'t upload an image.';
+$language['regist_withoutpassword']                    = 'Please fill your password.';\r
+$language['regist_nametoolong']                        = 'Name is too long.';\r
+$language['regist_emailtoolong']               = 'E-mail is too long.';\r
+$language['regist_topictoolong']               = 'Topic is too long.';\r
+$language['regist_longthreadnum']              = 'The thread you reply may be wrong.';\r
+$language['admin']                                             = 'Admin';\r
+$language['deletor']                                   = 'Deletor';\r
+$language['trip_pre']                                  = '◆';\r
+$language['trip_pre_fake']                             = '◇';\r
+$language['cap_char']                                  = '★';\r
+$language['cap_char_fake']                             = '☆';\r
+$language['regist_commenttoolong']             = 'Comment is too long.';\r
+$language['notice_incompletefile']             = 'Notice: Incomplete image.';\r
+$language['sun']                                               = 'Sun';\r
+$language['mon']                                               = 'Mon';\r
+$language['tue']                                               = 'Tue';\r
+$language['wed']                                               = 'Wed';\r
+$language['thu']                                               = 'Thu';\r
+$language['fri']                                               = 'Fri';\r
+$language['sat']                                               = 'Sat';\r
+$language['regist_successivepost']             = 'Please wait for a while for continuous posting.';\r
+$language['regist_duplicatefile']              = 'Upload failed.<br />Same file uploaded lately.';\r
+$language['regist_threaddeleted']              = 'This thread is too old that it is deleted!';\r
+$language['regist_threadlocked']               = 'Thread is locked by administrator!';\r
+$language['regist_redirect']                   = '%1$s Redirecting... <p>If your browser don\'t redirect for you, please click: <a href="%2$s">Return</a></p>';\r
+$language['del_notchecked']                            = 'Nothing selected for deletion. Please go back and select again.';\r
+$language['del_wrongpwornotfound']             = 'No such post or wrong password.';\r
+$language['admin_wrongpassword']               = 'Wrong password';\r
+$language['return']                                            = 'Return';\r
+$language['admin_remake']                              = 'Update';\r
+$language['admin_frontendmanage']              = 'Front-End Manage (Sign in needed)';\r
+$language['admin_delete']                              = 'Delete';\r
+$language['admin_top']                                 = 'Administrator mode';\r
+$language['admin_manageposts']                 = 'Manage posts';\r
+$language['admin_optimize']                            = 'Optimize';\r
+$language['admin_check']                               = 'Check data source';\r
+$language['admin_repair']                              = 'Repair data source';\r
+$language['admin_export']                              = 'Export data';\r
+$language['admin_logout']                              = 'Sign out';\r
+$language['admin_verify_btn']                  = ' Sign in ';\r
+$language['admin_archive']                             = '<th>Archive</th>';\r
+$language['admin_notices']                             = '<ul><li>If you want to delete a post, check the "delete" checkbox before that post and click Submit button.</li><li>If you want to delete image only, please check "Delete image only" checkbox and follow normal deletion procedures.</li><li>If you want to lock/unlock a thread, please check "Stop" checkbox of that thread and click "Submit" button.</li><li>Please press "Update" after managing posts.</li></ul>';\r
+$language['admin_submit_btn']                  = ' Submit ';\r
+$language['admin_reset_btn']                   = ' Reset ';\r
+$language['admin_list_header']                 = '<th>Func</th><th>Stop</th><th>Del</th><th>Date</th><th>Topic</th><th>Name</th><th>Comment</th><th>Host</th><th>Image (Bytes)<br />MD5 checksum</th>';\r
+$language['admin_archive_btn']                 = 'A';\r
+$language['admin_stop_btn']                            = 'Stop';\r
+$language['admin_totalsize']                   = '[Total size of images: <b>%1$s</b> KB ]';\r
+$language['search_disabled']                   = 'Search is disabled!';\r
+$language['search_top']                                        = 'Search';\r
+$language['search_notice']                             = '<li>Please enter keyword and set search target, then press "Search" button.</li><li>Searching with multiple keywords can be done by seperating keywords with space.</li><li>You can set Search method("and searching" and "or searching") for multiple keywords searching.<p />Keyword:';\r
+$language['search_target']                             = 'Target:';\r
+$language['search_target_comment']             = 'Comment';\r
+$language['search_target_name']                        = 'Name';\r
+$language['search_target_topic']               = 'Topic';\r
+$language['search_target_number']              = 'No.';\r
+$language['search_method']                             = 'Method:';\r
+$language['search_method_and']                 = 'AND';\r
+$language['search_method_or']                  = 'OR';\r
+$language['search_submit_btn']                 = ' Search ';\r
+$language['search_notfound']                   = 'no search result with specified keyword.';\r
+$language['search_back']                               = '[Back]';\r
+$language['category_nokeyword']                        = 'Please enter category for searching similar posts.';\r
+$language['category_notfound']                 = 'No matching posts for this category.';\r
+$language['category_recache']                  = 'Recache';\r
+$language['module_info_top']                   = 'Module Information';\r
+$language['module_loaded']                             = 'Module Loaded:';\r
+$language['module_info']                               = 'Module Infomation:';\r
+$language['info_top']                                  = 'System Information';\r
+$language['info_disabled']                             = 'Disabled';\r
+$language['info_enabled']                              = 'Enabled';\r
+$language['info_functional']                   = 'Functional';\r
+$language['info_nonfunctional']                        = 'Non functional';\r
+$language['info_basic']                                        = 'Basic Settings';\r
+$language['info_basic_ver']                            = 'Program version';\r
+$language['info_basic_pio']                            = 'PIO library backend and version';\r
+$language['info_basic_threadsperpage'] = 'Threads per page';\r
+$language['info_basic_threads']                        = '';\r
+$language['info_basic_postsperpage']   = 'Replies to show in index';\r
+$language['info_basic_posts']                  = '';\r
+$language['info_basic_postsinthread']  = 'Posts per page in Reply mode';\r
+$language['info_basic_posts_showall']  = '(Show all:0)';\r
+$language['info_basic_bumpposts']              = 'Do not bump post if reply is more than';\r
+$language['info_basic_bumphours']              = 'Thread bumping hours';\r
+$language['info_basic_hours']                  = 'hour(s)';\r
+$language['info_basic_0disable']               = '(Disable:0)';\r
+$language['info_basic_urllinking']             = 'URL Auto Linking';\r
+$language['info_0no1yes']                              = '(Yes:1 No:0)';\r
+$language['info_basic_com_limit']              = 'Maximum size of comments';\r
+$language['info_basic_com_after']              = ' Bytes';\r
+$language['info_basic_anonpost']               = 'Anonymous posting';\r
+$language['info_basic_anonpost_opt']   = '(Force anonymous:2 Yes:1 No:0)';\r
+$language['info_basic_del_incomplete'] = 'Delete incomplete images';\r
+$language['info_basic_use_sample']             = 'Use thumbnails (Quality: %1$s)';\r
+$language['info_0notuse1use']                  = '(Use:1 Not used:0)';\r
+$language['info_basic_use_sample_func']        = '+ Thumbnails generation';\r
+$language['info_basic_useblock']               = 'IP blocking';\r
+$language['info_0disable1enable']              = '(Enable:1 Disable:0)';\r
+$language['info_basic_showid']                 = 'Show ID';\r
+$language['info_basic_showid_after']   = '(force show:2 selective show:1 do not show:0)';\r
+$language['info_basic_cr_limit']               = 'Comment row limit';\r
+$language['info_basic_cr_after']               = ' Row(s) (unlimited:0)';\r
+//$language['info_basic_timezone']             = 'Time zone';
+$language['info_basic_max_lines_limit']                = 'Comment line limit';
+$language['info_basic_max_lines_after']                = ' Line(s) (unlimited:0)';\r
+$language['info_basic_threadcount']            = 'Total threads count';\r
+$language['info_basic_theme']                  = 'Theme';\r
+$language['info_dsusage_top']                  = 'Data source usage';\r
+$language['info_dsusage_max']                  = 'Maximum size';\r
+$language['info_dsusage_usage']                        = 'Usage';\r
+$language['info_dsusage_count']                        = 'Current usage';\r
+$language['info_fileusage_top']                        = 'Storage limit of images:';\r
+$language['info_fileusage_limit']              = 'Maximum size';\r
+$language['info_fileusage_count']              = 'Current usage';\r
+$language['info_fileusage_unlimited']  = 'Unlimited';\r
+$language['info_server_top']                   = 'Server infomation';\r
+$language['info_server_gd']                            = 'GD library ';\r
+$language['init_permerror']                            = 'No write permission in root directory. Please modify permission settings.<br />';\r
+$language['init_inited']                               = 'Environment initialized.<br />Please edit this file and remove init() statement.<br />';\r
+$language['action_main_notsupport']            = 'Backend does not support this operation.';\r
+$language['action_main_optimize']              = 'Optimization ';\r
+$language['action_main_check']                 = 'Check ';\r
+$language['action_main_repair']                        = 'Repair ';\r
+$language['action_main_export']                        = 'Export ';\r
+$language['action_main_success']               = 'success!';\r
+$language['action_main_failed']                        = 'failed!';\r
+\r
+// lib_common.php\r
+$language['head_home']                                 = 'Home';\r
+$language['head_search']                               = 'Search';\r
+$language['head_info']                                 = 'Info';\r
+$language['head_admin']                                        = 'Admin';\r
+$language['head_refresh']                              = 'Refresh';\r
+$language['form_top']                                  = 'Reply Mode';\r
+$language['form_showpostform']                 = 'Post';\r
+$language['form_hidepostform']                 = 'Hide form';\r
+$language['form_name']                                 = 'Name';\r
+$language['form_email']                                        = 'E-mail';\r
+$language['form_topic']                                        = 'Subject';\r
+$language['form_submit_btn']                   = 'Submit';\r
+$language['form_comment']                              = 'Comment';\r
+$language['form_attechment']                   = 'File';\r
+$language['form_noattechment']                 = 'No File';\r
+$language['form_contpost']                             = 'Noko';\r
+$language['form_category']                             = 'Category';\r
+$language['form_category_notice']              = '(Use , to seperate)';\r
+$language['form_delete_password']              = 'Password';\r
+$language['form_delete_password_notice']= '(Password used for post and file deletion, 8 chars max)';\r
+$language['form_notice']                               = '<li>Supported file types are: %1$s</li><li>Maximum file size allowed is %2$s KB. Fill E-mail with sage for not bumping post.</li><li>Images greater than %3$s * %4$s pixels will be thumbnailed.</li>';\r
+$language['form_notice_storage_limit'] = '<li>Current storage usage: %1$s KB / %2$s KB</li>';\r
+$language['form_notice_noscript']              = '*** You disabled JavaScript, but this won\'t affect you when browsing and posting.';\r
+$language['error_back']                                        = 'Back';\r
+$language['ip_banned']                                 = 'Listed in IP/Hostname Blacklist';\r
+$language['ip_dnsbl_banned']                   = 'Listed in DNSBL(%1$s) Blacklist';\r
+\r
+// mainscript.js // regist_withoutcomment,regist_upload_notsupport,js_convert_sakura\r
+$language['js_convert_sakura']                 = 'Big5 sakura Japanese characters detected, please try to convert to standard one.';\r
+\r\r
+$language['form_option1']                      = '<span id="option">Option1</span>';
+$language['form_newt']         = 'New Thread';
+
+$language['nothumb']           = 'Thumbnail unavailable';
+$language['long_comment']              = '「Comment too long. Click ';
+$language['long_here']         = 'here';
+$language['long_see']          = ' to view the full text.」';
+
+$language['def_sub']           = '無題';
+$language['def_name']          = '名無し';
+$language['def_com']           = '';
+
+// Style tooltip: stuff inside [square brackets] MUST be left as is!\r
+$language['style_tooltip']             = 'Switch to [what] style';
+// Title of stylesheet management page\r
+$language['admin_stylesheets']         = 'Manage Stylesheets';\r
+$language['admin_imported']            = 'Imported from <b>[file]</b>';\r
+$language['admin_editing']             = 'Editing <b>[file]</b>';\r
+$language['admin_created']             = '<b>[file]</b> created!';\r
+$language['admin_updated']             = '<b>[file]</b> updated!';\r
+$language['admin_deleted']             = '<b>[file]</b> deleted!';\r
+// Headings for fields\r
+$language['admin_is_default']          = 'Default?';\r
+$language['admin_style_default']               = 'Make this default';\r
+$language['admin_fullname']            = 'Full name';\r
+$language['admin_shortname']           = 'Short name';\r
+$language['admin_dispid']              = '<nobr>ID / Display order</nobr> <nobr>(0 to delete)</nobr>';\r
+$language['admin_addstyle']            = 'Add [or modify] stylesheet entry';\r
+// This goes in [or modify] above\r
+$language['admin_modstyle']            = 'or modify';\r
+$language['admin_new_file']            = 'File';\r
+$language['admin_new_id']              = '<nobr>Display order</nobr> <nobr>(Use existing ID to overwrite)</nobr>';
+if(!defined("PIXMICAT_LANGUAGE")) print_r($language);\r
+?>
\ No newline at end of file
diff --git a/lib/lang/ja_JP.php b/lib/lang/ja_JP.php
new file mode 100755 (executable)
index 0000000..f9dfa2d
--- /dev/null
@@ -0,0 +1,241 @@
+<?php\r
+/*\r
+Pixmicat! & Yotsubanome language file - Japanese [ja_JP]\r
+*/\r
+if (!isset($language)) $language = Array();\r
+\r
+// yotsubanome.php\r
+$language['page_not_found']                            = 'ページがありません';\r
+$language['thread_not_found']                  = '該当記事がみつかりません';\r
+$language['del_head']                                  = '【記事削除】';\r
+$language['del_img_only']                              = '画像だけ消す';\r
+$language['del_pass']                                  = '削除キー: ';\r
+$language['del_btn']                                   = ' 実行 ';\r
+$language['prev_page']                                 = '前のページ'; // 前のページ\r
+$language['first_page']                                        = '最初のページ'; // 最初のページ\r
+$language['all_pages']                                 = 'すべて';\r
+$language['next_page']                                 = '次のページ'; // 次のページ\r
+$language['last_page']                                 = '最後のページ'; // 最後のページ\r
+$language['img_sample']                                        = '[サムネ表示]';\r
+$language['img_filename']                              = '画像ファイル名:';\r
+$language['reply_btn']                                 = '返信';\r
+$language['warn_sizelimit']                            = 'この画像は容量リミットの原因なので、もうすぐ消えます。';\r
+$language['warn_oldthread']                            = 'このスレは古いので、もうすぐ消えます。';\r
+$language['warn_locked']                               = '管理者によるスレッドストップです。';\r
+$language['notice_omitted_posts']                              = 'レス [#] 投稿';\r
+$language['notice_omitted_images']                             = 'と [#] ファイル';\r
+$language['notice_omitted_reply']                              = '件省略。全て読むには[返信]ボタンを押してください。';\r
+$language['post_name']                                 = 'Name ';\r
+$language['post_category']                             = 'カテゴリ: ';\r
+$language['regist_notpost']                            = '不正な投稿をしないで下さい(post)';\r
+$language['regist_nospam']                             = '反 Spambot 機能スタート!';\r
+$language['regist_ipfiltered']                 = '拒絶されました(host) 原因:%1$s';\r
+$language['regist_wordfiltered']               = '拒絶されました(str)';\r
+$language['regist_upload_exceedphp']   = 'アップロードに失敗しました<br />PHPファイルサイズオーバー';\r
+$language['regist_upload_exceedcustom']        = 'アップロードに失敗しました<br />ファイルサイズオーバー';\r
+$language['regist_upload_incompelete'] = 'アップロードに失敗しました<br />ファイルが破損しています';\r
+$language['regist_upload_direrror']            = 'アップロードに失敗しました<br />パーミッションエラー';\r
+$language['regist_upload_noimg']               = '画像がありません';\r
+$language['regist_upload_filenotfound']        = 'アップロードに失敗しました<br />サーバがサポートしていない可能性があります';\r
+$language['regist_upload_killincomp']  = '[Notice] Your sending was canceled because of the incorrect file size.';\r
+$language['regist_upload_notimage']            = 'アップロードに失敗しました<br />画像ファイル以外は受け付けません';\r
+$language['regist_upload_notsupport']  = 'アップロードに失敗しました<br />GIF,JPG,PNG以外の画像ファイルは受け付けません';\r
+$language['regist_upload_blocked']             = 'アップロードに失敗しました<br />禁止画像です';\r
+$language['regist_uploaded']                   = '画像 %1$s のアップロードが成功しました<br />';\r
+$language['regist_sakuradetected']             = '櫻花仮名を検出した';\r
+$language['regist_withoutname']                        = '名前がありません';\r
+$language['regist_withoutsubject']                     = '題名がありません';\r
+$language['regist_withoutcomment']             = '何か書いて下さい';\r
+$language['regist_withoutpassword']                    = '削除キーが未入力です';\r
+$language['regist_nametoolong']                        = '名前が長すぎます';\r
+$language['regist_emailtoolong']               = 'メル欄が長すぎます';\r
+$language['regist_topictoolong']               = '題名が長すぎます';\r
+$language['regist_longthreadnum']              = '変なレス番号指定するんじゃないの';\r
+$language['admin']                                             = '管理';\r
+$language['deletor']                                   = '削除';\r
+$language['trip_pre']                                  = '◆';\r
+$language['trip_pre_fake']                             = '◇';\r
+$language['cap_char']                                  = '★';\r
+$language['cap_char_fake']                             = '☆';\r
+$language['regist_commenttoolong']             = 'コメントが長すぎます';\r
+$language['notice_incompletefile']             = '注意:ファイルが破損しています';\r
+$language['sun']                                               = '日';\r
+$language['mon']                                               = '月';\r
+$language['tue']                                               = '火';\r
+$language['wed']                                               = '水';\r
+$language['thu']                                               = '木';\r
+$language['fri']                                               = '金';\r
+$language['sat']                                               = '土';\r
+$language['regist_successivepost']             = '連続投稿はもうしばらく時間を置いてからお願い致します';\r
+$language['regist_duplicatefile']              = 'アップロードに失敗しました<br />同じ画像があります';\r
+$language['regist_threaddeleted']              = 'スレッドがありません';\r
+$language['regist_threadlocked']               = 'もう書けませんです';\r
+$language['regist_redirect']                   = '%1$s 画面を切り替えます。<p>しばらく待っても変わらない場合は、<a href="%2$s">こちら</a>をクリックしてください。</p>';\r
+$language['del_notchecked']                            = '何でもない削除のために選択されなかった。';\r
+$language['del_wrongpwornotfound']             = '該当記事が見つからないかパスワードが間違っています';\r
+$language['admin_wrongpassword']               = 'パスワードが違います';\r
+$language['return']                                            = '掲示板に戻る';\r
+$language['admin_remake']                              = 'ログを更新する';\r
+$language['admin_frontendmanage']              = 'フロントエンド管理 (認証が必要です)';\r
+$language['admin_delete']                              = '削除する';\r
+$language['admin_top']                                 = '管理モード';\r
+$language['admin_manageposts']                 = '記事管理';\r
+$language['admin_optimize']                            = 'テーブルを最適化する';\r
+$language['admin_check']                               = 'テーブルをチェックする';\r
+$language['admin_repair']                              = 'テーブルを修復する';\r
+$language['admin_export']                              = 'データをエクスポートする';\r
+$language['admin_logout']                              = 'ログアウト';\r
+$language['admin_verify_btn']                  = ' 認証 ';\r
+$language['admin_archive']                             = '<th>保管</th>';\r
+$language['admin_notices']                             = '<ul><li>削除したい記事の削除チェックボックスにチェックを入れ、実行ボタンを押して下さい。</li><li>終了/再開したいスレのストップチェックボックスにチェックを入れ、実行ボタンを押して下さい。</li><li>記事を管理した後に、[ログを更新する]を押してください。</li></ul>';\r
+$language['admin_submit_btn']                  = ' 実行する ';\r
+$language['admin_reset_btn']                   = ' リセット ';\r
+$language['admin_list_header']                 = '<th>機能</th><th>ストップ</th><th>削除</th><th>投稿日</th><th>題名</th><th>投稿者</th><th>コメント</th><th>ホスト名</th><th>添付(Bytes)<br />MD5</th>';\r
+$language['admin_archive_btn']                 = '保管';\r
+$language['admin_stop_btn']                            = 'ストップ';\r
+$language['admin_totalsize']                   = '【 画像データ合計 : <b>%1$s</b> KB 】';\r
+$language['search_disabled']                   = '検索は禁じられます。';\r
+$language['search_top']                                        = '検索';\r
+$language['search_notice']                             = '<li>お探しの記事に関連する言葉をキーワード入力欄に入力して検索ボタンを押してください。</li><li>複数のキーワードの間にスペースを入れて入力します。</li><li>複数キーワード間の検索条件を細かく指定する場合に利用します。<p />キーワード:';\r
+$language['search_target']                             = '検索対象:';\r
+$language['search_target_comment']             = 'コメント';\r
+$language['search_target_name']                        = 'お名前';\r
+$language['search_target_topic']               = '題名';\r
+$language['search_target_number']              = '記事No.';\r
+$language['search_method']                             = '検索条件:';\r
+$language['search_method_and']                 = 'AND';\r
+$language['search_method_or']                  = 'OR';\r
+$language['search_submit_btn']                 = ' 検索 ';\r
+$language['search_notfound']                   = 'キーワードにマッチする記事がありませんでした。';\r
+$language['search_back']                               = '[戻る]';\r
+$language['category_nokeyword']                        = '探すことの同様の記事のためにカテゴリに入ってください。'; /***/\r
+$language['category_notfound']                 = 'カテゴリにマッチする記事がありませんでした。';\r
+$language['category_recache']                  = 'キャッシュを更新する';\r
+$language['module_info_top']                   = 'モジュール情報';\r
+$language['module_loaded']                             = 'Module Loaded:';\r
+$language['module_info']                               = 'Module Infomation:';\r
+$language['info_top']                                  = 'システム情報';\r
+$language['info_disabled']                             = '無効';\r
+$language['info_enabled']                              = '有効';\r
+$language['info_functional']                   = '働ける';\r
+$language['info_nonfunctional']                        = '働けない';\r
+$language['info_basic']                                        = '基本設定';\r
+$language['info_basic_ver']                            = 'バージョン';\r
+$language['info_basic_pio']                            = 'PIO バックエンドとバージョン';\r
+$language['info_basic_threadsperpage'] = '1ページに表示する記事';\r
+$language['info_basic_threads']                        = '件';\r
+$language['info_basic_postsperpage']   = 'スレに表示するレス';\r
+$language['info_basic_posts']                  = '件';\r
+$language['info_basic_postsinthread']  = '1ページに表示するレス';\r
+$language['info_basic_posts_showall']  = '(すべて:0)';\r
+$language['info_basic_bumpposts']              = '強制sageレス数';\r
+$language['info_basic_bumphours']              = '強制sageまでの時間';\r
+$language['info_basic_hours']                  = '時間';\r
+$language['info_basic_0disable']               = '(無効:0)';\r
+$language['info_basic_urllinking']             = 'URLをリンク';\r
+$language['info_0no1yes']                              = '(する:1 しない:0)';\r
+$language['info_basic_com_limit']              = 'コメント欄最大文字数';\r
+$language['info_basic_com_after']              = '';\r
+$language['info_basic_anonpost']               = '名前を必須に';\r
+$language['info_basic_anonpost_opt']   = '(強制名無し化:2 いいえ:1 はい:0)';\r
+$language['info_basic_del_incomplete'] = '破損したファイルを消す';\r
+$language['info_basic_use_sample']             = 'サムネイルを作る (画質:%1$s)';\r
+$language['info_0notuse1use']                  = '(する:1 しない:0)';\r
+$language['info_basic_use_sample_func']        = '└ サムネイルを作り関数';\r
+$language['info_basic_useblock']               = '拒絶するホスト';\r
+$language['info_0disable1enable']              = '(有効:1 無効:0)';\r
+$language['info_basic_showid']                 = 'IDを表示する?';\r
+$language['info_basic_showid_after']   = '(強制:2 する:1 しない:0)';\r
+$language['info_basic_cr_limit']               = '改行を抑制する行数';\r
+$language['info_basic_cr_after']               = ' 行 (しない:0)';\r
+//$language['info_basic_timezone']             = '時間帯設定';\r
+$language['info_basic_max_lines_limit']                = '改行を抑制する行数';\r
+$language['info_basic_max_lines_after']                = ' 線 (しない:0)';\r
+$language['info_basic_threadcount']            = '現在のスレ数';\r
+$language['info_basic_theme']                  = 'テーマ';\r
+$language['info_dsusage_top']                  = 'データソース使用量';\r
+$language['info_dsusage_max']                  = '最大値';\r
+$language['info_dsusage_usage']                        = '使用率';\r
+$language['info_dsusage_count']                        = '現在の値';\r
+$language['info_fileusage_top']                        = '添付ファイル容量リミット:';\r
+$language['info_fileusage_limit']              = '大きさの上限';\r
+$language['info_fileusage_count']              = '現在の容量';\r
+$language['info_fileusage_unlimited']  = '限界なし';\r
+$language['info_server_top']                   = 'サーバー支援情報';\r
+$language['info_server_gd']                            = 'GD モジュール';\r
+$language['init_permerror']                            = 'カレントディレクトリに書けません<br />';\r
+$language['init_inited']                               = '環境初始化成功した!<br />このファイルを編集して、init()を削除してください。<br />';\r
+$language['action_main_notsupport']            = 'バックエンドには、この動作がありません。';\r
+$language['action_main_optimize']              = 'テーブル最適化';\r
+$language['action_main_check']                 = 'テーブルチェック';\r
+$language['action_main_repair']                        = 'テーブル修復';\r
+$language['action_main_export']                        = 'データエクスポート';\r
+$language['action_main_success']               = '成功した';\r
+$language['action_main_failed']                        = '失敗した';\r
+\r
+// lib_common.php\r
+$language['head_home']                                 = 'ホーム';\r
+$language['head_search']                               = '検索';\r
+$language['head_info']                                 = 'システム情報';\r
+$language['head_admin']                                        = '管理用';\r
+$language['head_refresh']                              = 'リロード';\r
+$language['form_top']                                  = 'レス送信モード';\r
+$language['form_showpostform']                 = '投稿';\r
+$language['form_hidepostform']                 = 'フォームを隠す';\r
+$language['form_name']                                 = 'おなまえ';\r
+$language['form_email']                                        = 'E-mail';\r
+$language['form_topic']                                        = '題  名';\r
+$language['form_submit_btn']                   = '送信する';\r
+$language['form_comment']                              = 'コメント';\r
+$language['form_attechment']                   = '添付File';\r
+$language['form_noattechment']                 = '画像なし';\r
+$language['form_contpost']                             = '連貼り';\r
+$language['form_category']                             = 'カテゴリ';\r
+$language['form_category_notice']              = '(複数のカテゴリの間に「,」を入れて入力します)';\r
+$language['form_delete_password']              = '投稿キー';\r
+$language['form_delete_password_notice']= '(記事の削除用。英数字で8文字以内)';\r
+$language['form_notice']                               = '<li>添付可能ファイル:%1$s<br />ブラウザによっては正常に添付できないことがあります。</li><li>最大投稿データ量は %2$s KBまで。sage機能付き。</li><li>画像は横 %3$s ピクセル、縦 %4$s ピクセルを超えると縮小表示されます。</li>';\r
+$language['form_notice_storage_limit'] = '<li>現在の添付ファイル使用量: %1$s KB / %2$s KB</li>';\r
+$language['form_notice_noscript']              = '*JavaScriptは無効にでもブラウジングと返信に影響しない。';\r
+$language['error_back']                                        = '戻る';\r
+$language['ip_banned']                                 = 'IP/ホスト名ブラックリストに記載されています。';\r
+$language['ip_dnsbl_banned']                   = 'DNSBL(%1$s) ブラックリストに記載されています。';\r
+\r
+// mainscript.js // regist_withoutcomment,regist_upload_notsupport,js_convert_sakura\r
+$language['js_convert_sakura']                 = '櫻花仮名を検出した。変換します。';\r
+\r
+\r
+$language['form_option1']                      = '<span id="option">オプション1</span>';\r
+$language['form_newt']         = '新スレッド';\r
+\r
+$language['nothumb']           = '入手できないサムネイル';\r
+$language['long_comment']              = '「省略されました・・全てを読むには';\r
+$language['long_here']         = 'ここ';\r
+$language['long_see']          = 'を押してください」';\r
+\r
+$language['def_sub']           = '無題';\r
+$language['def_name']          = '名無し';\r
+$language['def_com']           = '本文なし';\r
+\r
+// Style tooltip: stuff inside [square brackets] MUST be left as is!\r
+$language['style_tooltip']             = 'スイッチは[what]スタイル';\r
+// Title of stylesheet management page\r
+$language['admin_stylesheets']         = 'スタイルシートを管理して';\r
+$language['admin_imported']            = 'インポートから <b>[file]</b>';\r
+$language['admin_editing']             = '編集 <b>[file]</b>';\r
+$language['admin_created']             = '作成 <b>[file]</b>!';\r
+$language['admin_updated']             = 'を更新 <b>[file]</b>!';\r
+$language['admin_deleted']             = '削除 <b>[file]</b>!';\r
+// Headings for fields\r
+$language['admin_is_default']          = 'デフォルトのですか?';\r
+$language['admin_style_default']               = 'このデフォルトにする';\r
+$language['admin_fullname']            = '本当の名前';\r
+$language['admin_shortname']           = '表示名前';\r
+$language['admin_dispid']              = '<nobr>ID / 表示順</nobr> <nobr>(タイプ0この項目を削除する)</nobr>';\r
+$language['admin_addstyle']            = '追加 [or modify] スタイルシートのエントリ';\r
+// This goes in [or modify] above\r
+$language['admin_modstyle']            = 'または変更';\r
+$language['admin_new_file']            = 'ファイル';\r
+$language['admin_new_id']              = '<nobr>表示順</nobr> <nobr>(既存のID番号を使用して、アイテムを上書きする)</nobr>';\r
+if(!defined("PIXMICAT_LANGUAGE")) print_r($language);\r
+?>\r
diff --git a/lib/lang/strings_en.phps b/lib/lang/strings_en.phps
new file mode 100755 (executable)
index 0000000..f3c2f86
--- /dev/null
@@ -0,0 +1,359 @@
+<?php\r
+define("S_HOME", 'Home');           //Forwards to home page\r
+define("S_ADMIN", 'Manage');          //Forwards to Management Panel\r
+define("S_ARCHIVELOG", 'Archive');          //Forwards to Archive List\r
+define("S_ARTICLE", 'List');          //Forwards to Thread List\r
+define("S_RETURN", 'Return to '.TITLE);          //Returns to image board\r
+define("S_POSTING", 'Posting mode: Reply');        //Prints message in red bar atop the reply screen\r
+define("S_EDITING", 'Posting mode: Edit');        //Prints message in yellow bar atop the edit screen\r
+define("S_EDITED", 'Edited post');        //Prints message below yellow bar atop the edit screen\r
+define("S_NOTAGS", 'HTML tags are allowed.');        //Prints message on Management Board\r
+define("S_NEWT", 'New Thread');           //Describes New Thread\r
+define("S_NEWT_", 'New Thread');           //Describes New Thread in thread list box\r
+define("S_SPOILERS", 'Spoilers');        //Describes Spoilers\r
+define("S_NAME", 'Name');           //Describes name field\r
+define("S_EMAIL", 'E-mail');          //Describes e-mail field\r
+define("S_SUBJECT", 'Subject');          //Describes subject field\r
+define("S_SUBMIT", 'Submit');          //Describes submit button\r
+define("S_COMMENT", 'Comment');          //Describes comment field\r
+define("S_UPLOADFILE", 'File');          //Describes file field\r
+define("S_NOFILE", 'No File');          //Describes file/no file checkbox\r
+define("S_DELPASS", 'Password');          //Describes password field\r
+define("S_DELEXPL", '(Password used for post and file deletion and editing)');       //Prints explanation for password box (to the right)\r
+define("S_OPTION", 'Option');    // options\r
+define("S_OPTIONAL", 'optional');    // optional\r
+define("S_GIFPNGSTOP", '<font size="-1"> Animation stop</font>'); // gif/png stop text\r
+define("S_OR",'<font size="-1"> or </font>');    //the or in gif/png stop text\r
+define("S_REQUIRE", 'Required');\r
+define("S_NONAMEF", 'No Name field');\r
+define("S_IDDISP", 'ID Display');\r
+define("S_RETURNTO", 'Noko');\r
+define("S_SPAMTRAP", 'Leave these fields empty (spam trap):');\r
+\r
+define("S_FRULES", '<li />Supported file types are: BMP, GIF, JPG, PNG  [YES! BITMAP!] \r
+<li />Maximum file size allowed is '.MAX_KB.' KB.\r
+<li />'.MAX_W.'x'.MAX_H.' or larger will be thumbnailed.');\r
+/*<li />Images greater than '.MAX_W.'x'.MAX_H.'pixels will be thumbnailed.*/\r
+define("S_MINHWRULES1", '<li />Images smaller than ');\r
+define("S_MAXHWRULES1", '<li />Images greater than ');\r
+define("S_MINHWRULES2", ' pixels are not allowed.');\r
+define("S_MAXHWRULES2", ' pixels are not allowed.');\r
+    //Prints file rules under posting section\r
+define("S_FANIMERULES1", '<li />On the ');\r
+define("S_FANIMERULES2", ' Animation stop, check it for a thumbnail of ');\r
+define("S_FANIMERULES3", ' file.');\r
+define("S_FVOTERULES", '<li />The vote function to the image starts to write \81uvote\81v in the E-mail column.');\r
+define("S_EDIT_RULE", '<li />If fields are not edited, there will be an ERROR');\r
+\r
+/*if(!USE_IMG){\r
+define("S_FRULES_BOX", '</tr></td></table><table border=1 cellspacing=8 cellpadding=4 bgcolor="#ccffcc" align=center>');\r
+}else\r
+define("S_FRULES_BOX", '');*/\r
+\r
+define("S_REPORTERR", 'Cannot find reply.');       //Returns error when a reply (res) cannot be found\r
+define("S_TGIF", 'Animation GIF');\r
+define("S_TPNG", 'Animation PNG');\r
+define("S_THUMB", 'Thumbnail displayed, click image for full size.');     //Prints instructions for viewing real source\r
+define("S_NOTHUMB", 'Thumbnail unavailable');\r
+define("S_FILEDELETED", 'File Deleted');\r
+define("S_PICNAME", 'File : ');          //Prints text before upload name/link\r
+define("S_REPLY", 'Reply');          //Prints text for reply link\r
+define("S_NOREPLY", 'It is not possible to Reply');          //Prints text for no reply link\r
+define("S_OLD", 'Marked for deletion (old).');        //Prints text to be displayed before post is marked for deletion, see: retention\r
+define("S_ARCH", 'Marked for archive (old).');        //Prints text to be displayed before post is marked for archive, see: retention\r
+define("S_THUMBR1", 'The thumbnail is being replaced by the manager. Please guess the reason. w');\r
+define("S_THUMBR2", 'When the thumbnail is clicked, former image is displayed.');\r
+define("S_SAGE", 'Sage is being specified for this by the manager. Please guess the reason. w');\r
+define("S_ABBRP", '[#] post[s]'); // [n] post(s) found / hidden\r
+define("S_ABBRI", ' and [#] image[s]'); // [n] image(s) found / hidden\r
+define("S_ABBRC", ' omitted. Click [Reply] to view.');      //Prints text to be shown when replies are hidden\r
+define("S_ABBRT", ' in [#] thread[s]'); // [n] thread(s) found\r
+define("S_ABBRU", ', made by [#] user[s]');\r
+define("S_REPDEL", 'Delete Post');         //Prints text next to S_DELPICONLY (left)\r
+define("S_DELPICONLY", 'File Only Deletion');         //Prints text next to checkbox for file deletion (right)\r
+define("S_EDITKEY", 'Password ');          //Prints text next to password field for edit (left)\r
+define("S_DELETE", 'Delete');          //Defines deletion button's name\r
+define("S_REPORT", 'Report');          //Defines report button's name\r
+define("S_ARTICLE_FIX",'Post Correction');\r
+define("S_ARTICLE_EDIT",'Post Edit');\r
+define("S_PREV", 'Previous');          //Defines previous button\r
+define("S_FIRSTPG", 'Previous');          //Defines previous button\r
+define("S_NEXT", 'Next');           //Defines next button\r
+define("S_LASTPG", 'Next');          //Defines next button\r
+define("S_FOOT", '- <a href="http://php.s3.to" target="_blank">GazouBBS</a> + <a href="http://www.2chan.net/" target="_blank">futaba</a> + <a href="http://www.1chan.net/futallaby/" target="_blank">futallaby</a> -'); //Prints footer (leave these credits)\r
+define("S_RELOAD", 'Reload');          //Reloads the image board (refresh)\r
+define("S_UPFAIL", 'Upload failed.');        //Returns error for failed upload (reason: unknown?)\r
+define("S_NOREC", 'Cannot find record.');        //Returns error when record cannot be found\r
+define("S_SAMEPIC", 'Duplicate md5 checksum detected.');      //Returns error when a md5 checksum dupe is detected\r
+define("S_SAMEPICLOCA1", "<br />Already posted <a href=\"");\r
+define("S_SAMEPICLOCA2", "\">here</a>.");\r
+define("S_TOOBIG", 'This image is too large!  Upload something smaller!');\r
+define("S_TOOBIGORNONE", 'Either this image is too big or there is no image at all.  Yeah.');\r
+define("S_UPGOOD", 'File '.$upfile_name.' uploaded!<br /><br />');     //Defines message to be displayed when file is successfully uploaded\r
+define ('S_SCRTHREAD', "Redirecting to your new thread.");\r
+define ('S_SCRPOST', "Redirecting to your post.");\r
+define("S_STRREF", 'String refused.');        //Returns error when a string is refused\r
+define("S_UNJUST", 'Unjust POST.');        //Returns error on an unjust POST - prevents floodbots or ways not using POST method?\r
+define("S_NOPIC", 'No file selected.');        //Returns error for no file selected and override unchecked\r
+define("S_NOTEXT", 'No text entered.');        //Returns error for no text entered in to subject/comment\r
+define("S_MANAGEMENT", 'Manager : ');         //Defines prefix for Manager Post name\r
+define("S_DELETION", 'Deletion');          //Prints deletion message with quotes?\r
+define("S_TOOLONG", 'Field too long.');\r
+define("S_TOOLONGS", 'Subject too long.');\r
+define("S_TOOLONGC", 'Comment too long.'); \r
+define("S_TOOLONGN", 'Name too long.');\r
+define("S_TOOLONGE", 'Email too long.');        //Returns error for too many characters in a given field\r
+define("S_UNUSUAL", 'Abnormal reply.');        //Returns error for abnormal reply? (this is a mystery!)\r
+define("S_LONGCOMMENT", '\81uComment too long. Click ');\r
+define("S_LONGHERE", 'here');\r
+define("S_LONGSEE", ' to view the full text.\81v');\r
+define("S_BADHOST", 'Host is banned.<br /><a href="../banplea/">Plea</a>');        //Returns error for banned host ($badip string)\r
+define("S_BADIP", 'YOU ARE B&.<br /><a href="../banplea/">Plea</a>');        //Returns error for banned user ($badip string)\r
+define("S_PROXY80", 'Proxy detected on :80.');       //Returns error for proxy detection on port 80\r
+define("S_PROXY8080", 'Proxy detected on :8080.');       //Returns error for proxy detection on port 8080\r
+define("S_SPAMACTI", '<h1>Anti-spam filters triggered.</h1>');       //Returns error for spam detection\r
+define("S_SPAMMESS", '<p>If you are not a spammer, you probably did not leave the Anti-spam field blank. Try editing your post to remove it. Sorry for any inconvenience.</p><br />');       //Returns error message for spam detection\r
+define("S_SUN", 'Sun');           //Defines abbreviation used for "Sunday"\r
+define("S_MON", 'Mon');           //Defines abbreviation used for "Monday"\r
+define("S_TUE", 'Tue');           //Defines abbreviation used for "Tuesday"\r
+define("S_WED", 'Wed');           //Defines abbreviation used for "Wednesday"\r
+define("S_THU", 'Thu');           //Defines abbreviation used for "Thursday"\r
+define("S_FRI", 'Fri');           //Defines abbreviation used for "Friday"\r
+define("S_SAT", 'Sat');           //Defines abbreviation used for "Saturday"\r
+if(!defined("S_NNAME")) define("S_NNAME", 'Name : ');\r
+if(!defined("DEF_SUB")) define("DEF_SUB", '\96³\91è');         //Defines what to print if there is no text entered into subject field\r
+if(!defined("DEF_NAME")) define("DEF_NAME", '\96¼\96³\82µ');          //Defines what to print if there is no text entered in the name field\r
+if(!defined("DEF_COM")) define("DEF_COM", '\83L\83^\81[\81[\81[\81[(^\83\8e^)\81[\81[\81[\81[\81I\81I\81I\81I');          //Defines what to print if there is no text entered in the comment field\r
+define("S_NONAME", 'You are no allowed to be'.DEF_NAME);    //Returns error for no name\r
+define("S_NOSUB", 'There is no title.');    //Returns error for no text entered in to subject\r
+define("S_NOCOM", 'There is no text in comment.');    //Returns error for no text entered in to comment\r
+define("S_NOPASS", 'There is no imputed password.');    //Returns error for no password\r
+define("S_RENZOKU1", 'Flood detected, post discarded.');      //Returns error for $sec/post spam filter\r
+define("S_RENZOKU2", 'Flood detected, file discarded.');      //Returns error for $sec/upload spam filter\r
+define("S_RENZOKU3", 'Flood detected, post & file discarded.');        //Returns error for flood? (don't know the specifics)\r
+define("S_DUPE", 'Duplicate file entry detected.');      //Returns error for a duped file (same upload name or same tim/time)\r
+define("S_NOTHREADERR", 'Thread specified does not exist.');     //Returns error when a non-existant thread is accessed\r
+define("S_SCRCHANGE", 'Updating page.');         //Defines message to be displayed when post is successful         //\r
+define("S_BADDELPASS", 'Password incorrect.');       //Returns error for wrong password (when user tries to delete file)\r
+define("S_WRONGPASS", 'Management password incorrect.');      //Returns error for wrong password (when trying to access Manager modes)\r
+define("S_WRONGMANAME", 'Management name is not found.');      //Returns error for wrong name (when trying to access Manager modes)\r
+define("S_RETURNS", 'Return to '.TITLE.'');          //Returns to HTML file instead of PHP--thus no log/SQLDB update occurs\r
+define("S_LOGUPD", 'Update');          //Updates the log/SQLDB by accessing the PHP file\r
+define("S_BNOTBANIP", 'Unable to find record of your IP being banned.');\r
+define("S_BNOTBAN", 'You are not banned!');\r
+define("S_BBAN", 'You have been banned!');\r
+\r
+define("S_BBANMESS1", 'You have been permanently banned from ');\r
+define("S_BBANBOARD", '<b>all boards</b>.');\r
+define("S_BBANMESS2", '');\r
+define("S_BBANMESSREA", 'The moderation team supplied the following reason: ');\r
+\r
+define("S_BBANMESSB4FORM", "If you believe this is a mistake, you may dispute the matter by posting <a href='".HOME."banplea/post".PHP_EXT2."'>here</a> or the form provided below.");\r
+\r
+define("S_BBANMESSVIEWDENY", 'Your appeal was reviewed and denied. You may not appeal this ban again.');\r
+define("S_BBANMESSDENY", 'You may not appeal this ban.');\r
+\r
+define("S_MANAMODE", 'Manager Mode');         //Prints heading on top of Manager page\r
+define("S_MANAREPDEL", 'Management Panel');        //Defines Management Panel radio button--allows the user to view the management panel (overview of all posts)\r
+define("S_MANAPOST", 'Manager Post');         //Defines Manager Post radio button--allows the user to post using HTML code in the comment box\r
+define("S_MANASAGE", 'Perma-sage');\r
+define("S_MANATHUMB", 'Thumbnail replacement');\r
+define("S_MANASTOP", 'Thread stop');\r
+define("S_MANAHOST", 'Host/ID display list'); // registration and deletion\r
+define("S_MANAARCH", 'Archive Management');\r
+define("S_MANAREGBAN", 'Ban Management');\r
+define("S_MANADELBAN", 'Unban Management');\r
+define("S_MANAREGWORD", 'Word filter Registration');\r
+define("S_MANADELWORD", 'Word filter Deletion');\r
+define("S_MANALOG", 'Log management');\r
+define("S_FUTARE", 'Log cleaning');\r
+define("S_MANASUB", 'Submit');          //Defines name for submit button in Manager Mode\r
+define("S_MANAVER", 'Verify Management access');\r
+define("S_MANANAME", 'Mod/Admin name');\r
+define("S_MANAPASS", 'Pass');\r
+define("S_MANAREM", 'Remeber my login');\r
+define("S_DELLIST", 'Mark the check box of a post, and push the deletion button to delete it.');         //Prints sub-heading of Management Panel\r
+define("S_SAGELIST", 'Mark the check box of a post, and push the change button to Permasage it.<center>\81uSage\81vand\81uSage release\81vchange.<center>\81usage\81vby\81uSage start\81vand\81uNumber sage of loesses\81vcannot be released.');\r
+define("S_STOPLIST", 'Mark the check box of a post, and push the change button to lock/close it.<br />\81uSuresuto\81vand\81uSuresuto\81vrelease" change.<br />');\r
+define("S_THUMBLIST", 'Mark the check box of a post, and push the replacement button to replace the thumbnail.<center>\81uSelection\81vand\81uSelection Release\81v change.');\r
+define("S_HOSTREGLIST", "Mark the check in object host's post check box, and push the change button.<br />It is registered in the display host's list.<br />If the host name is not done when it is checked to display the host name, ID is displayed.<br />");\r
+define("S_HOSTDELLIST", "Mark the check box of the host who wants to delete it from the list, and push the change button.<br />It is deleted from the display host's list.");\r
+define("S_WORDFILTERLIST", 'Put the word you want to filter in the red box.<br />Put the filtered word in the blue box.');\r
+define("S_INTO", '->');\r
+define("S_ITDELETES", 'Delete');          //Defines for deletion button in Management Panel\r
+define("S_MDDELETION", 'Delete');\r
+define("S_MDRESET", 'Reset');          //Defines name for field reset button in Management Panel\r
+define("S_MDCHANGE", 'Change');\r
+define("S_MDREPLACE", 'Replace');\r
+define("S_HOSTDIS", 'The host name is displayed');\r
+define("S_HOSTDISLIST", 'Host display list');\r
+define("S_IDDISLIST", 'ID display list');\r
+define("S_SEL", 'Sel');\r
+define("S_HOSTNAME", 'Host name');\r
+define("S_STILLGIF", 'GIF is only made thumbnail');\r
+define("S_STILLPNG", 'PNG is only made thumbnail');\r
+define("S_MDONLYPIC", 'File Only');         //Sets whether or not to delete only file, or entire post/thread\r
+\r
+//bann\r
+define("S_PUBREA", 'Public reason : ');\r
+define("S_PRIREA", 'Private note : ');\r
+define("S_BANPLEABLE", 'The ban is cleanable : ');\r
+define("S_MODADMINNAME", 'Name of Mod/Admin : ');\r
+define("S_BANNOTPLEABLE", 'The ban is <b>NOT</b> cleanable : ');\r
+define("S_REQUIRETOBANUSER", 'Required to ban user');\r
+define("S_REQUIRETOBAN", 'Required to ban');\r
+define("S_REQUIRETOBANANY", 'Required to ban anything');\r
+\r
+define("S_MANABANISHUSER", 'User banishment?');\r
+define("S_DISPLAYTOMANA", 'This will only be visible to mods and admins');\r
+define("S_DISPLAYTOUSER", 'This will be displayed to banned user');\r
+define("S_MANABADFILE", 'Bad file');\r
+define("S_MANABADWORD", 'Bad word');\r
+\r
+define("S_MDTABLE1", '<tr bgcolor="#6080f6"><th>Del</th><th>Post No</th><th>Time</th><th>Subject</th>'); //Explains field names for Management Panel (Delete?->Subject)\r
+define("S_MDTABLE2", '<th>Name</th><th>Comment</th><th>Host / IP</th>'); //Explains names for Management Panel (Name->IP)\r
+define("S_MDTABLE3", '<th>Size<br />(Bytes)</th>'); //Explains names for Management Panel (Size)\r
+define("S_MDTABLE4", '<th>md5</th>'); //Explains names for Management Panel (md5)\r
+\r
+define("S_MTTABLE1", '<tr bgcolor="#6080f6"><th>Sel</th><th>Post No</th><th>\8fó\91Ô\r
+</th><th>Time</th><th>Subject</th>');\r
+\r
+define("S_RESET", 'Reset');          //Sets name for field reset button (global)\r
+define("S_IMGSPACEUSAGE", 'Space used : ');      //Prints space used KB by the board under Management Panel\r
+define("S_YOURIP", 'Your IP Address is : ');\r
+define("S_SUCCESS", 'Success');\r
+define("S_CANNOTWRITE", 'Cannot write to a current directory.<br />');      //Returns error when the script cannot write to the directory, this is used on initial setup--check your chmod (777)\r
+define("S_NOTWRITE", 'Cannot write to directory.<br />');      //Returns error when the script cannot write to the directory, the chmod (777) is wrong\r
+define("S_NOTREAD", 'Cannot read from directory.<br />');      //Returns error when the script cannot read from the directory, the chmod (777) is wrong\r
+define("S_NOTDIR", 'Directory does not exist.<br />');      //Returns error when the script cannot find/read from the directory (does not exist/isn't directory), the chmod (777) is wrong\r
+define("S_VERIFY", 'Verify');                                                         //verification of the capatcha.\r
+define("S_WRONGVERY", 'You entered the wrong verification code!');\r
+define("S_NOTITLE", 'Please enter a title or subject for your post.');\r
+define("S_ANOTFOUND", 'The article is not found or the password is wrong.');\r
+define("S_EDITSAME", 'The content is quite the same. Please change somewhere.');\r
+define("S_CANNOTCORRECT", 'It is not possible to correct this post.');\r
+\r
+define("S_TOOBIGRES", 'Picture dimensions is too large.');\r
+define("S_TOOSMALLRES", 'Picture dimensions is too small.');\r
+define("S_FILEEXNOTSUPPORTED", 'File extension not supported');\r
+define("S_FILETYPENOTSUPPORTED", 'File type not supported');\r
+\r
+define("S_THUMBV", 'Thumb');\r
+define("S_VIEWA", 'Image \91\9c\82Ñ\82ã\81`\82í\81`');\r
+define("S_NEWTHREAD", 'Make new thread');\r
+define("S_CAT", 'Catalog');\r
+define("S_CATALOGMODE", 'Catalog Mode');\r
+define("S_LIST", 'Thread List');\r
+define("S_NWAHA", '\90V\92\85\82í\82Í\81[');\r
+define("S_ABOUT", 'ABOUT');\r
+define("S_OGEGE", 'Ogege');\r
+define("S_ALBUM", 'Album');\r
+define("S_TLIST", 'The Thread List is here.');\r
+define("S_SUBLIST", 'Subject List');\r
+define("S_SOURCECODE", 'Source Code');\r
+define("S_ARCHIVEOF", 'Archive of '.TITLE);\r
+define("S_NOARCHIVE", 'There is no archived threads.');\r
+\r
+/*smaller files connection*/\r
+define("S_TOTAL_IMG", 'Total Images');\r
+define("S_TOTAL_SURE", 'Total Threads');\r
+define("S_TOTAL_POST", 'Total Posts');\r
+\r
+define("S_FUTAPASS", '\81¥Please input the password.');\r
+define("S_FUTABO1", 'Submit');\r
+define("S_FUTADEL", 'Delete it?');\r
+define("S_FUTA2YOTSU", 'Update it?');\r
+define("S_FUTAGARBAGE", 'The garbage of URL, MAIL, and TIME is removed.<br />\r
+Please execute the log after it backs up without fail.');\r
+define("S_FUTAPROSS", '<b>It was normally processed.</b>');\r
+$copy_log = COPY_LOG;\r
+define("S_FUTAPROSSCOPY", '<br />Please rename <b>'.$copy_log.'</b> after confirming the log as '.LOGFILE.' and replace it.');\r
+define("S_FUTACLEAN", 'Clean');\r
+\r
+    //img_view/search\r
+define("S_IMG_VIEW_INFO", 'It links with contribution Thread a check box of the display it on as for the file information. ');\r
+define("S_TEXT_ENGINE", 'Full-text search engine');\r
+define("S_TEXT_ENGINE_INSTALLED", ' installed');\r
+define("S_FILE_INFO_DISP", 'The file information is displayed.');\r
+define("S_FILE_INFO_DISP_BUTTON", '\83|\83`\83b\82Æ\82È');\r
+define("S_ALL_TOTAL_IMG", 'The number of all images');\r
+define("S_SURE_IMG", 'The number of op images');\r
+define("S_REPLY_IMG", 'The number of reply images');\r
+define("S_PAGE_DEF", 'Number of one page displays');\r
+define("S_IMG_DISPLAY_TO", 'to');\r
+define("S_IMG_DISPLAY", 'are the images displayed.');\r
+define("S_PIECE", '');\r
+\r
+define("S_SEARCH",'Search');\r
+define("S_DISPNO",'Display results\81F');\r
+define("S_SEARCH_RULE", '\81E Please delimit it in space when you specify two or more key words.<br />\r
+\81E It retrieves it to the search condition AND A B = It is (A and B. )<br />\r
+\81E The retrieval object is article No, a name, a title, a text, and eye column.<br />\r
+\81E Capital letters and small letters are distinguished. (A?a) (ABC?aBC)<br />\r
+\81E The retrieval word is used four colors repeatedly and displayed with the color. Google style?<br />\r
+\81E Please refrain from a strange search strategy as much as possible. The report if there is a bug.<br />\r
+\81E The base of this search engine is logoogle.php ver 0.1.1<br />');\r
+\r
+define("S_SEARCH_NOT_FOUND", 'did not match any text.');\r
+define("S_SEARCH_PROTIP", 'Search PRO TIP');\r
+define("S_SEARCH_LIST", '- Please confirm whether there are neither an erratum nor an omission of a word in the key word.<br />\r
+- Please use a different key word.<br />\r
+- Please use a more general word.<br />\r
+- Please reduce the number of key words.<br />\r
+- Please doubt my sense.<br />');\r
+define("S_POSTSCRIPT", 'PRO TIP:');\r
+define("S_SEARCH_FIX", 'When it is not good, even if the above-mentioned is tried, please give up bravely. [ENGRISH wwww]');\r
+define("S_KEYWORD_NO_MATCH", 'There was no article that matched to the key word.');\r
+\r
+define("S_INLOG", 'In log');\r
+define("S_SEARCH_RESULT", 'Search result |');\r
+define("S_SEARCH_HIT", 'Hits');\r
+define("S_SEARCH_RESULTS", 'Results');\r
+define("S_SEARCH_SUBJECT", 'Subject\81F');\r
+define("S_SEARCH_NAME", 'Name\81F');\r
+define("S_SEARCH_DATE", 'Date\81F');\r
+define("S_SEARCH_PREV", '&lt;&lt;Previous');\r
+define("S_SEARCH_NEXT", 'Next&gt;&gt;');\r
+define("S_IMGRET",'Image retrieval');\r
+define("S_SEARCH_TOOL",'Search tool');\r
+define("S_HELP",'Help');\r
+\r
+    //time\r
+define("S_SECONDS", 'seconds');\r
+    //image download counter\r
+define("S_THISIMG",'This image has been downloaded ');\r
+define("S_THISIMGDLTIMES",' time[s].');\r
+\r
+// Style tooltip: stuff inside [square brackets] MUST be left as is!\r
+       define ('S_STYLETOOLTIP', "Switch to [what] style");\r
+\r
+       // Title of stylesheet management page\r
+       define ('S_ADMIN_STYLESHEETS', "Manage Stylesheets");\r
+\r
+               define ('TH_ADMIN_IMPORTED', "Imported from <b>[file]</b>");\r
+               define ('TH_ADMIN_EDITING', "Editing <b>[file]</b>");\r
+               define ('TH_ADMIN_CREATED', "<b>[file]</b> created!");\r
+               define ('TH_ADMIN_UPDATED', "<b>[file]</b> updated!");\r
+               define ('TH_ADMIN_DELETED', "<b>[file]</b> deleted!");\r
+\r
+               // Headings for fields\r
+               define ('TH_ADMIN_IS_DEFAULT', "Default?");\r
+               define ('TH_ADMIN_STYLE_DEFAULT', "Make this default");\r
+               define ('TH_ADMIN_FULLNAME', "Full name");\r
+               define ('TH_ADMIN_SHORTNAME', "Short name");\r
+               define ('TH_ADMIN_DISP_ID', '<nobr>ID / Display order</nobr> <nobr>(0 to delete)</nobr>');\r
+               define ('TH_ADMIN_ADDSTYLE', "Add [or modify] stylesheet entry");\r
+                       // This goes in [or modify] above\r
+                       define ('TH_ADMIN_MODSTYLE', "or modify");\r
+               define ('TH_ADMIN_NEW_FILE', 'File');\r
+               define ('TH_ADMIN_NEW_ID', '<nobr>Display order</nobr> <nobr>(Use existing ID to overwrite)</nobr>');\r
+\r
+/*\r
+define("S_SQLCONF", 'MySQL connection failure');  //MySQL connection failure\r
+define("S_SQLDBSF", 'Database error, check SQL settings<br />'); //database select failure\r
+define("S_TCREATE", 'Creating table!<br />\n'); //creating table\r
+define("S_TCREATEF", 'Unable to create table!<br />');  //table creation failed\r
+define("S_SQLFAIL", 'Critical SQL problem!<br />');  //SQL Failure\r
+define("S_UNFILE", 'File type not suported.');\r
+*/\r
+?>\r
diff --git a/lib/lang/strings_jp.phps b/lib/lang/strings_jp.phps
new file mode 100755 (executable)
index 0000000..21c3398
--- /dev/null
@@ -0,0 +1,358 @@
+<?php\r
+define("S_HOME", '\83z\81[\83\80');\r
+define("S_ADMIN", '\8aÇ\97\9d\97p');\r
+define("S_ARCHIVELOG", '\89ß\8b\8e\83\8d\83O');\r
+define("S_ARTICLE", '\88ê\97\97');\r
+define("S_RETURN", TITLE.' - \8cf\8e¦\94Â\82É\96ß\82é');\r
+define("S_POSTING", '\83\8c\83X\91\97\90M\83\82\81[\83h');\r
+define("S_EDITING", '\95Ò\8fW\83\82\81[\83h');\r
+define("S_EDITED", '\95Ò\8fW\82·\82é\8bL\8e\96');\r
+define("S_NOTAGS", '\83^\83O\82ª\82Â\82©\82¦\82Ü\82·');\r
+define("S_NEWT", '\90V\83X\83\8c\83b\83h');\r
+define("S_NEWT_", '\90V\83X\83\8c\83b\83h');\r
+define("S_SPOILERS", '\83X\83|\83C\83\89\81[\83Y');\r
+define("S_NAME", '\82¨\82È\82Ü\82¦');\r
+define("S_EMAIL", 'E-mail');\r
+define("S_SUBJECT", '\91è\81@\81@\96¼');\r
+define("S_SUBMIT", '\91\97\90M\82·\82é');\r
+define("S_COMMENT", '\83R\83\81\83\93\83g');\r
+define("S_UPLOADFILE", '\93Y\95tFile');\r
+define("S_NOFILE", '\89æ\91\9c\82È\82µ');\r
+define("S_DELPASS", '\8dí\8f\9c\83L\81[');\r
+define("S_DELEXPL", '(\8bL\8e\96\8dí\8f\9c\82È\82Ç\82Ì\95Ò\8fW\97p\81B\89p\90\94\8e\9a\82Å8\95\8e\9a\88È\93à)');\r
+define("S_OPTION", '\83I\83v\83V\83\87\83\93');\r
+define("S_OPTIONAL", '\83I\83v\83V\83\87\83i\83\8b');\r
+define("S_GIFPNGSTOP", '<font size="-1">\83A\83j\83\81\92â\8e~</font>');\r
+define("S_OR", '<font size="-1">\96\94\82Í</font>');\r
+define("S_REQUIRE", '\95K\90{');\r
+define("S_NONAMEF", '\96¼\91O\97\93\82È\82µ');\r
+define("S_IDDISP", '\8b­\90§ID\95\\8e¦');\r
+define("S_RETURNTO", '\83X\83\8c\82É\96ß\82é');\r
+define("S_SPAMTRAP", '\82±\82ê\82ç\82Ì\97\93\82Í\8bó\94\92\82Ì\82Ü\82Ü\82Å(\83X\83p\83\80\83g\83\89\83b\83v)\81F');\r
+\r
+define("S_FRULES", '<li />\93Y\95t\89Â\94\\81FBMP, GIF, JPG, PNG\r
+<li />\8dÅ\91å\93\8a\8de\83f\81[\83^-\83n\82Í '.MAX_KB.' KB \82Ü\82Å\82Å\82·\81Bsage\8b@\94\\95t\82«\81B\r
+<li />'.MAX_W.'x'.MAX_H.'\88È\8fã\82Í\8fk\8f¬.');\r
+/*<li />\89æ\91\9c\82Í\89¡ '.MAX_W.'\83s\83N\83Z\83\8b\81A\8fc '.MAX_H.'\83s\83N\83Z\83\8b\82ð\92´\82¦\82é\82Æ\8fk\8f¬\95\\8e¦\82³\82ê\82Ü\82·\81B*/\r
+define("S_MINHWRULES1", '<li />');\r
+define("S_MAXHWRULES1", '<li />');\r
+define("S_MINHWRULES2", '\89æ\91f\82æ\82è\8f¬\82³\82¢\83C\83\81\81[\83W\83Y\82Í\8b\96\97e\82³\82ê\82Ä\82¢\82Ü\82¹\82ñ\81B');\r
+define("S_MAXHWRULES2", '\89æ\91f\82Ì\83C\83\81\81[\83W\83Y\82Í\8b\96\97e\82³\82ê\82Ä\82¢\82Ü\82¹\82ñ\81B');\r
+\r
+define("S_FANIMERULES1", '<li />');\r
+define("S_FANIMERULES2", '\82Í\93®\82«\82Ü\82·\81B\93®\82©\82µ\82½\82¢\8e\9e\82Í\93\8a\8de\8e\9e\82É[');\r
+define("S_FANIMERULES3", '\83A\83j\83\81\92â\8e~]\82Ì\83`\83F\83b\83N\82ð\89ð\8f\9c\81B');\r
+define("S_FVOTERULES", '<li />E-mail \97\93\82É\81uvote\81v\82Æ\8f\91\82­\82±\82Æ\82Å\89æ\91\9c\82É\91Î\82·\82é\93\8a\95[\8b@\94\\82ª\83X\83^\81[\83g\82µ\82Ü\82·\81B');\r
+define("S_EDIT_RULE", '<li />\82Ç\82±\82à\95Ò\8fW\82µ\82È\82¢\82Æ\83G\83\89\81[\82É\82È\82è\82Ü\82·\81B');\r
+\r
+/*if(!USE_IMG){\r
+define("S_FRULES_BOX", '</tr></td></table><table border=1 cellspacing=8 cellpadding=4 bgcolor="#ccffcc" align=center>');\r
+}else\r
+define("S_FRULES_BOX", '');*/\r
+\r
+define("S_REPORTERR", '\8aY\93\96\8bL\8e\96\82ª\82Ý\82Â\82©\82è\82Ü\82¹\82ñ');\r
+define("S_TGIF", '\83A\83j\83\81GIF.');\r
+define("S_TPNG", '\83A\83j\83\81PNG.');\r
+define("S_THUMB", '\83T\83\80\83l\83C\83\8b\82ð\95\\8e¦\82µ\82Ä\82¢\82Ü\82·.\83N\83\8a\83b\83N\82·\82é\82Æ\8c³\82Ì\83T\83C\83Y\82ð\95\\8e¦\82µ\82Ü\82·.');\r
+define("S_NOTHUMB", '\93ü\8eè\82Å\82«\82È\82¢\83T\83\80\83l\83C\83\8b');\r
+define("S_FILEDELETED", '\83t\83@\83C\83\8b\8dí\8f\9c\82É\82³\82ê\82é');\r
+define("S_PICNAME", '\89æ\91\9c\83^\83C\83g\83\8b\81F');\r
+define("S_REPLY", '\95Ô\90M');\r
+define("S_NOREPLY", '\95Ô\90M\95s\89Â');\r
+define("S_OLD", '\82±\82Ì\83X\83\8c\82Í\81i\8cÃ\82¢\81j\82Ì\82Å\81A\82à\82¤\82·\82®\8fÁ\82¦\82Ü\82·\81B');\r
+define("S_ARCH", '\82±\82Ì\83X\83\8c\82Í\81i\8cÃ\82¢\81j\82Ì\82Å\81A\82à\82¤\82·\82®\83A\81[\83J\83C\83u\81B');\r
+define("S_THUMBR1", '\82±\82Ì\83X\83\8c\82Í\8aÇ\97\9d\8eÒ\82É\82æ\82è\83T\83\80\83l\83C\83\8b\82ª\8d·\82µ\91Ö\82¦\82ç\82ê\82Ä\82¢\82Ü\82·\81B\97\9d\97R\82Í\82¨\8e@\82µ\82­\82¾\82³\82¢\81B');\r
+define("S_THUMBR2", '\83T\83\80\83l\83C\83\8b\82ð\83N\83\8a\83b\83N\82·\82é\82Æ\8c³\82Ì\89æ\91\9c\82ð\95\\8e¦\82µ\82Ü\82·\81B');\r
+define("S_SAGE", '\82±\82Ì\83X\83\8c\82Í\8aÇ\97\9d\8eÒ\82É\82æ\82èsage\8ew\92è\82³\82ê\82Ä\82¢\82Ü\82·\81B\97\9d\97R\82Í\82¨\8e@\82µ\82­\82¾\82³\82¢\81B');\r
+define("S_ABBRP", '\83\8c\83X[#]\93\8a\8de');\r
+define("S_ABBRI", ' \82Æ[#]\83t\83@\83C\83\8b');\r
+define("S_ABBRC", '\8c\8f\8fÈ\97ª\81B\91S\82Ä\93Ç\82Þ\82É\82Í[\95Ô\90M]\83{\83^\83\93\82ð\89\9f\82µ\82Ä\82­\82¾\82³\82¢\81B');\r
+define("S_ABBRT", '\82Å[#]\8e\85');\r
+define("S_ABBRU", '\81A\8dì\90¬\82³\82ê\82½[#]\90l');\r
+define("S_REPDEL", '\8bL\8e\96\8dí\8f\9c');\r
+define("S_DELPICONLY", '\8bL\8e\96\82ð\8ec\82µ\89æ\91\9c\82¾\82¯\8fÁ\82·');\r
+define("S_EDITKEY", '\95Ò\8fW\83L\81[');\r
+define("S_DELETE", '\8dí\8f\9c');\r
+define("S_REPORT", '\83\8c\83|\81[\83g');\r
+define("S_ARTICLE_FIX",'\8bL\8e\96\8fC\90³');\r
+define("S_ARTICLE_EDIT",'\8bL\8e\96\95Ò\8fW');\r
+define("S_PREV", '\91O\82Ì\83y\81[\83W');\r
+define("S_FIRSTPG", '\8dÅ\8f\89\82Ì\83y\81[\83W');\r
+define("S_NEXT", '\8e\9f\82Ì\83y\81[\83W');\r
+define("S_LASTPG", '\8dÅ\8cã\82Ì\83y\81[\83W');\r
+define("S_FOOT", '- <a href="http://php.s3.to" target=_blank>GazouBBS</a> + <a href="http://www.2chan.net/" target=_blank>futaba</a> + <a href="http://www.mapored.com/futallaby/" target=_blank>futallaby</a> -'); \r
+define("S_RELOAD", '\83\8a\83\8d\81[\83h');\r
+define("S_UPFAIL", '\83A\83b\83v\83\8d\81[\83h\82É\8e¸\94s\82µ\82Ü\82µ\82½<br />\83T\81[\83o\82ª\83T\83|\81[\83g\82µ\82Ä\82¢\82È\82¢\89Â\94\\90«\82ª\82 \82è\82Ü\82·');\r
+define("S_NOREC", '\83A\83b\83v\83\8d\81[\83h\82É\8e¸\94s\82µ\82Ü\82µ\82½<br />\89æ\91\9c\83t\83@\83C\83\8b\88È\8aO\82Í\8eó\82¯\95t\82¯\82Ü\82¹\82ñ');\r
+define("S_SAMEPIC", '\83A\83b\83v\83\8d\81[\83h\82É\8e¸\94s\82µ\82Ü\82µ\82½<br />\93¯\82\89æ\91\9c\82ª\82 \82è\82Ü\82µ\82½');\r
+define("S_SAMEPICLOCA1", "<br /><a href=\"");\r
+define("S_SAMEPICLOCA2", "\">\82±\82±</a>\82É\8aù\82É\8cf\8e¦\82³\82ê\82Ä\82¢\82Ü\82·");\r
+define("S_TOOBIG", '\83A\83b\83v\83\8d\81[\83h\82É\8e¸\94s\82µ\82Ü\82µ\82½<br />\83T\83C\83Y\82ª\91å\82«\82·\82¬\82Ü\82·<br />'.MAX_KB.'K\83o\83C\83g\82Ü\82Å');\r
+define("S_TOOBIGORNONE", '\83A\83b\83v\83\8d\81[\83h\82É\8e¸\94s\82µ\82Ü\82µ\82½<br />\89æ\91\9c\83T\83C\83Y\82ª\91å\82«\82·\82¬\82é\82©\81A<br />\82Ü\82½\82Í\89æ\91\9c\82ª\82 \82è\82Ü\82¹\82ñ\81B');\r
+define("S_UPGOOD", '\89æ\91\9c '.$upfile_name.' \82Ì\83A\83b\83v\83\8d\81[\83h\82ª\90¬\8c÷\82µ\82Ü\82µ\82½<br /><br />');\r
+define ('S_SCRTHREAD', "\90V\82µ\82¢\83X\83\8c\83b\83h\82É\83\8a\83_\83C\83\8c\83N\83g\82·\82é\81B");\r
+define ('S_SCRPOST', "\82 \82È\82½\82Ì\93\8a\8de\82·\82é\82É\83\8a\83_\83C\83\8c\83N\83g\82·\82é\81B");\r
+define("S_STRREF", '\8b\91\90â\82³\82ê\82Ü\82µ\82½(str)');\r
+define("S_UNJUST", '\95s\90³\82È\93\8a\8de\82ð\82µ\82È\82¢\82Å\89º\82³\82¢(post)');\r
+define("S_NOPIC", '\89æ\91\9c\82ª\82 \82è\82Ü\82¹\82ñ');\r
+define("S_NOTEXT", '\89½\82©\8f\91\82¢\82Ä\89º\82³\82¢');\r
+define("S_MANAGEMENT", '\8dí\8f\9c');\r
+define("S_DELETION", '\8dí\8f\9c');\r
+define("S_TOOLONG", ' \96{\95\82ª\92·\82·\82¬\82Ü\82·\82Á\81I');\r
+define("S_TOOLONGS", ' \91è\96¼\82ª\92·\82·\82¬\82Ü\82·\82Á\81I');\r
+define("S_TOOLONGC", ' \83R\83\81\83\93\83g\82ª\92·\82·\82¬\82Ü\82·\82Á\81I'); \r
+define("S_TOOLONGN", ' \96¼\91O\82ª\92·\82·\82¬\82Ü\82·\82Á\81I');\r
+define("S_TOOLONGE", ' Email \82ª\92·\82·\82¬\82Ü\82·\82Á\81I');\r
+define("S_UNUSUAL", '\88Ù\8fí\82Å\82·');\r
+define("S_LONGCOMMENT", '\81u\8fÈ\97ª\82³\82ê\82Ü\82µ\82½\81E\81E\91S\82Ä\82ð\93Ç\82Þ\82É\82Í');\r
+define("S_LONGHERE", '\82±\82±');\r
+define("S_LONGSEE", '\82ð\89\9f\82µ\82Ä\82­\82¾\82³\82¢\81v');\r
+define("S_BADHOST", '\8b\91\90â\82³\82ê\82Ü\82µ\82½(host)<br /><a href="../banplea/">Plea</a>');\r
+define("S_BADIP", '\8b\91\90â\82³\82ê\82Ü\82µ\82½(ip)<br /><a href="../banplea/">Plea</a>');\r
+define("S_PROXY80", '\82d\82q\82q\82n\82q\81I\81@\8cö\8aJ\82o\82q\82n\82w\82x\8bK\90§\92\86\81I\81I(80)');\r
+define("S_PROXY8080", '\82d\82q\82q\82n\82q\81I\81@\8cö\8aJ\82o\82q\82n\82w\82x\8bK\90§\92\86\81I\81I(8080)');\r
+define("S_SPAMACTI", '<h1>\83X\83p\83\80\83t\83B\83\8b\83^\81[\82ª\8dì\93®\82µ\82Ü\82µ\82½</h1>');\r
+define("S_SPAMMESS",  '<p>\82à\82µ\82 \82È\82½\82ª\8dr\82ç\82µ\82Å\82È\82¯\82ê\82Î\81A\83X\83p\83\80\94»\92è\97p\82Ì\8bó\97\93\82ð\95Ï\8dX\82µ\82Ä\82¢\82é\89Â\94\\90«\82ª\82 \82è\82Ü\82·\81B\93\8a\8de\82ð\8c©\92¼\82µ\82Ä\8b^\82í\82µ\82¢\89Ó\8f\8a\82ð\8dí\8f\9c\82µ\82Ä\82Ý\82Ä\82­\82¾\82³\82¢\81B\82²\96À\98f\82ð\82¨\82©\82¯\82µ\82Ü\82·\81B</p><br />');\r
+define("S_SUN", '\93ú');\r
+define("S_MON", '\8c\8e');\r
+define("S_TUE", '\89Î');\r
+define("S_WED", '\90\85');\r
+define("S_THU", '\96Ø');\r
+define("S_FRI", '\8bà');\r
+define("S_SAT", '\93y');\r
+if(!defined("S_NNAME")) define("S_NNAME", '');\r
+if(!defined("DEF_SUB")) define("DEF_SUB", '\96³\91è');                             // \8fÈ\97ª\8e\9e\82Ì\91è\96¼\r
+if(!defined("DEF_NAME")) define("DEF_NAME", '\96¼\96³\82µ');                 // \8fÈ\97ª\8e\9e\82Ì\96¼\91O\r
+if(!defined("DEF_COM")) define("DEF_COM", '\83L\83^\81[\81[\81[\81[(^\83\8e^)\81[\81[\81[\81[\81I\81I\81I\81I');                       // \8fÈ\97ª\8e\9e\82Ì\96{\95\r
+define("S_NONAME", '\96¼\91O\82ª\82 \82è\82Ü\82¹\82ñ');\r
+define("S_NOSUB", '\96{\95\82ª\82 \82è\82Ü\82¹\82ñ');\r
+define("S_NOCOM", '\91è\96¼\82ª\82 \82è\82Ü\82¹\82ñ');\r
+define("S_NOPASS", '\95Ò\8fW\83L\81[\82ª\96¢\93ü\97Í\82Å\82·');\r
+define("S_RENZOKU1", '\98A\91±\93\8a\8de\82Í\82à\82¤\82µ\82Î\82ç\82­\8e\9e\8aÔ\82ð\92u\82¢\82Ä\82©\82ç\82¨\8aè\82¢\92v\82µ\82Ü\82·');\r
+define("S_RENZOKU2", '\89æ\91\9c\98A\91±\93\8a\8de\82Í\82à\82¤\82µ\82Î\82ç\82­\8e\9e\8aÔ\82ð\92u\82¢\82Ä\82©\82ç\82¨\8aè\82¢\92v\82µ\82Ü\82·');\r
+define("S_RENZOKU3", '\98A\91±\93\8a\8de\82Í\82à\82¤\82µ\82Î\82ç\82­\8e\9e\8aÔ\82ð\92u\82¢\82Ä\82©\82ç\82¨\8aè\82¢\92v\82µ\82Ü\82·');\r
+define("S_DUPE", '\83A\83b\83v\83\8d\81[\83h\82É\8e¸\94s\82µ\82Ü\82µ\82½<br />\93¯\82\89æ\91\9c\82ª\82 \82è\82Ü\82·');\r
+define("S_NOTHREADERR", '\83X\83\8c\83b\83h\82ª\82 \82è\82Ü\82¹\82ñ');\r
+define("S_SCRCHANGE", '\89æ\96Ê\82ð\90Ø\82è\91Ö\82¦\82Ü\82·');\r
+define("S_BADDELPASS", '\8aY\93\96\8bL\8e\96\82ª\8c©\82Â\82©\82ç\82È\82¢\82©\83p\83X\83\8f\81[\83h\82ª\8aÔ\88á\82Á\82Ä\82¢\82Ü\82·');\r
+define("S_WRONGPASS", '\83p\83X\83\8f\81[\83h\82ª\88á\82¢\82Ü\82·');\r
+define("S_WRONGMANAME", '\83l\81[\83\80\83p\83X\82ª\88á\82¢\82Ü\82·');\r
+define("S_RETURNS", '\8cf\8e¦\94Â\82É\96ß\82é');\r
+define("S_LOGUPD", '\83\8d\83O\82ð\8dX\90V\82·\82é');\r
+define("S_BNOTBANIP", '\82 \82È\82½\82ª\8bÖ\8e~\82³\82ê\82Ä\82¢\82Ü\82¹\82ñ');\r
+define("S_BNOTBAN", '\82 \82È\82½\82ª\8bÖ\8e~\82³\82ê\82Ä\82¢\82Ü\82¹\82ñ\81I ');\r
+define("S_BBAN", '\82 \82È\82½\82ª\8bÖ\8e~\82³\82ê\82Ä\81I');\r
+\r
+define("S_BBANMESS1", '\82 \82È\82½\82Í\89i\8bv\82É\81A');\r
+define("S_BBANBOARD", '<b>\82·\82×\82Ä\82Ì\94Â</b>');\r
+define("S_BBANMESS2", '\82©\82ç\8bÖ\8e~\82³\82ê\82Ü\82µ\82½\81B');\r
+define("S_BBANMESSREA", '\8aÇ\97\9d\83`\81[\83\80\82Í\88È\89º\82Ì\97\9d\97R\82ð\92ñ\8b\9f\82µ\82Ü\82µ\82½\81F');\r
+\r
+define("S_BBANMESSB4FORM", "\82 \82È\82½\82ª\82±\82ê\82ª\8cë\82è\82Å\82 \82é\82Æ\90M\82\82Ä\82¢\82é\82È\82ç\82 \82È\82½\82ª<a href='".HOME."banplea/post".PHP_EXT2."'>\82±\82±</a>\82Å\83|\83X\83e\83B\83\93\83O\82Å\82»\82Ì\8c\8f\82É\82Â\82¢\82Ä\8bc\98_\82Å\82«\82Ü\82·\82©\81A\82Ü\82½\82Í\83t\83H\81[\83\80\82Í\88È\89º\82É\92ñ\8b\9f\82³\82ê\82Ü\82µ\82½\81B");\r
+\r
+define("S_BBANMESSVIEWDENY", '\82 \82È\82½\82Ì\8fã\8d\90\82Í\81A\8c©\92¼\82³\82ê\82Ä\81A\94Û\92è\82³\82ê\82Ü\82µ\82½\81B\82 \82È\82½\82Í\8dÄ\82Ñ\82±\82Ì\8bÖ\8e~\97ß\82É\8fã\8d\90\82Å\82«\82Ü\82¹\82ñ\81B');\r
+define("S_BBANMESSDENY", '\82 \82È\82½\82Í\82±\82Ì\8bÖ\8e~\97ß\82É\8fã\8d\90\82Å\82«\82Ü\82¹\82ñ\81B');\r
+\r
+define("S_MANAMODE", '\8aÇ\97\9d\83\82\81[\83h');\r
+define("S_MANAREPDEL", '\8bL\8e\96\8dí\8f\9c');\r
+define("S_MANAPOST", '\8aÇ\97\9d\90l\93\8a\8de');\r
+define("S_MANASAGE", '\8b­\90§sage\8f\88\97\9d');\r
+define("S_MANATHUMB", '\83T\83\80\83l\83C\83\8b\8d·\82µ\91Ö\82¦');\r
+define("S_MANASTOP", '\83X\83\8c\83X\83g\8f\88\97\9d');\r
+define("S_MANAHOST", '\83z\83X\83g/ID\95\\8e¦\83\8a\83X\83g\82É\93o\98^\81E\8dí\8f\9c');\r
+define("S_MANAARCH", '\89ß\8b\8e\83\8d\83O\8aÇ\97\9d');\r
+define("S_MANAREGBAN", '\8bÖ\8e~\97ß\8aÇ\97\9d');\r
+define("S_MANADELBAN", '\8dí\8f\9c\8bÖ\8e~\97ß\8aÇ\97\9d');\r
+define("S_MANAREGWORD", '\92P\8cê\83t\83B\83\8b\83^\93o\98^');\r
+define("S_MANADELWORD", '\92P\8cê\83t\83B\83\8b\83^\8dí\8f\9c');\r
+define("S_MANALOG", '\83\8d\83O\8aÇ\97\9d');\r
+define("S_FUTARE", '\83\8d\83O\91|\8f\9c');\r
+define("S_MANASUB", ' \94F\8fØ');\r
+define("S_MANAVER", '\82±\82Æ\82ð\8am\94F\82µ\82Ü\82·\8aÇ\97\9d\83A\83N\83Z\83X');\r
+define("S_MANANAME", '\8aÇ\97\9d\90l\82Ì\96¼\91O');\r
+define("S_MANAPASS", '\83L\81[');\r
+define("S_MANAREM", '\8e\9f\89ñ\82©\82ç\8e©\93®\83\8d\83O\83C\83\93');\r
+define("S_DELLIST", '\8dí\8f\9c\82µ\82½\82¢\8bL\8e\96\82Ì\83`\83F\83b\83N\83{\83b\83N\83X\82É\83`\83F\83b\83N\82ð\93ü\82ê\81A\8dí\8f\9c\83{\83^\83\93\82ð\89\9f\82µ\82Ä\89º\82³\82¢\81B');\r
+define("S_SAGELIST", 'sage\8fó\91Ô\82ð\95Ï\8dX\82µ\82½\82¢\8bL\8e\96\82Ì\83`\83F\83b\83N\83{\83b\83N\83X\82É\83`\83F\83b\83N\82ð\93ü\82ê\81A\95Ï\8dX\83{\83^\83\93\82ð\89\9f\82µ\82Ä\89º\82³\82¢\81B<center>\81usage\81v\82Æ\81usage\89ð\8f\9c\81v\82ª\90Ø\82è\91Ö\82í\82è\82Ü\82·\81B<center>\81usage\83X\83^\81[\83g\81v\82â\81u\83\8c\83X\90\94sage\81v\82É\82æ\82é\81usage\81v\82Í\89ð\8f\9c\82Å\82«\82Ü\82¹\82ñ\81B');\r
+define("S_STOPLIST", '\83X\83\8c\83X\83g\8fó\91Ô\82ð\95Ï\8dX\82µ\82½\82¢\8bL\8e\96\82Ì\83`\83F\83b\83N\83{\83b\83N\83X\82É\83`\83F\83b\83N\82ð\93ü\82ê\81A\95Ï\8dX\83{\83^\83\93\82ð\89\9f\82µ\82Ä\89º\82³\82¢\81B<br />\81u\83X\83\8c\83X\83g\81v\82Æ\81u\83X\83\8c\83X\83g\89ð\8f\9c\81v\82ª\90Ø\82è\91Ö\82í\82è\82Ü\82·\81B');\r
+define("S_THUMBLIST", '\83T\83\80\83l\83C\83\8b\82ð\8d·\82µ\91Ö\82¦\82½\82¢\8bL\8e\96\82Ì\83`\83F\83b\83N\83{\83b\83N\83X\82É\83`\83F\83b\83N\82ð\93ü\82ê\81A\8d·\82µ\91Ö\82¦\83{\83^\83\93\82ð\89\9f\82µ\82Ä\89º\82³\82¢\81B<center>\81u\8d·\91Ö\81v\82Æ\81u\8d·\91Ö\89ð\8f\9c\81v\82ª\90Ø\82è\91Ö\82í\82è\82Ü\82·\81B');\r
+define("S_HOSTREGLIST", '\91Î\8fÛ\83z\83X\83g\82Ì\8bL\8e\96\83`\83F\83b\83N\83{\83b\83N\83X\82É\83`\83F\83b\83N\82ð\93ü\82ê\81A\95Ï\8dX\83{\83^\83\93\82ð\89\9f\82µ\82Ä\89º\82³\82¢\81B<br />\95\\8e¦\83z\83X\83g\82Ì\83\8a\83X\83g\82É\93o\98^\82³\82ê\82Ü\82·\81B<br />[\83z\83X\83g\96¼\82ð\95\\8e¦\82³\82¹\82é]\82É\83`\83F\83b\83N\82·\82é\82Æ\83z\83X\83g\96¼\82ð\81A\82µ\82È\82¢\82ÆID\82ð\95\\8e¦\82µ\82Ü\82·\81B');\r
+define("S_HOSTDELLIST", '\83\8a\83X\83g\82©\82ç\8dí\8f\9c\82µ\82½\82¢\83z\83X\83g\82Ì\83`\83F\83b\83N\83{\83b\83N\83X\82É\83`\83F\83b\83N\82ð\93ü\82ê\81A\95Ï\8dX\83{\83^\83\93\82ð\89\9f\82µ\82Ä\89º\82³\82¢\81B<br />\95\\8e¦\83z\83X\83g\82Ì\83\8a\83X\83g\82©\82ç\8dí\8f\9c\82³\82ê\82Ü\82·\81B');\r
+define("S_WORDFILTERLIST", '\83t\83B\83\8b\83^\82ð\93K\97p\82·\82é\90Ô\82¢\83{\83b\83N\83X\82Å\92P\8cê\82ð\92u\82«\82Ü\82·\81B<br />\90Â\90F\82Ì\83{\83b\83N\83X\82É\83t\83B\83\8b\83^\8f\88\97\9d\82³\82ê\82½\92P\8cê\82ð\92u\82«\82Ü\82·\81B');\r
+define("S_INTO", '->');\r
+define("S_ITDELETES", '\8dí\8f\9c\82·\82é');\r
+define("S_MDDELETION", '\8dí\8f\9c');\r
+define("S_MDRESET", '\83\8a\83Z\83b\83g');\r
+define("S_MDCHANGE", '\95Ï\8dX');\r
+define("S_MDREPLACE", '\8d·\82µ\91Ö\82¦');\r
+define("S_HOSTDIS", '\83z\83X\83g\96¼\82ð\95\\8e¦\82³\82¹\82é');\r
+define("S_HOSTDISLIST", '\83z\83X\83g\95\\8e¦\83\8a\83X\83g');\r
+define("S_IDDISLIST", 'ID\95\\8e¦\83\8a\83X\83g');\r
+define("S_SEL", '\91I\91ð');\r
+define("S_HOSTNAME", '\83z\83X\83g\96¼');\r
+define("S_STILLGIF", 'GIF\82ð\83T\83\80\83l\83C\83\8b\89»\82·\82é\82¾\82¯');\r
+define("S_STILLPNG", 'PNG\82ð\83T\83\80\83l\83C\83\8b\89»\82·\82é\82¾\82¯');\r
+define("S_MDONLYPIC", '\89æ\91\9c\82¾\82¯\8fÁ\82·');\r
+\r
+//bann\r
+define("S_PUBREA", '\8cö\8b¤\82Ì\97\9d\97R\81F');\r
+define("S_PRIREA", '\83v\83\89\83C\83x\81[\83g\83\81\83\82\81F');\r
+define("S_BANPLEABLE", '\8bÖ\8e~\82ð\90ô\8fò\89Â\94\\82Å\82·\81F');\r
+define("S_MODADMINNAME", '\8aÇ\97\9d\90l\82Ì\96¼\91O\81F');\r
+define("S_BANNOTPLEABLE", '\8bÖ\8e~\82ð\90ô\8fò\89Â\94\\82Å<b>\82Í\82È\82¢</b>\81F');\r
+define("S_REQUIRETOBANUSER", '\95K\90{\83\86\81[\83U\81[\82ð\8bÖ\8e~\82·\82é');\r
+define("S_REQUIRETOBAN", '\95K\90{\82ð\8bÖ\8e~\82·\82é');\r
+define("S_REQUIRETOBANANY", '\95K\90{\89½\82©\82ð\8bÖ\8e~\82·\82é');\r
+\r
+define("S_MANABANISHUSER", '\83\86\81[\83U\81[\92Ç\95ú\81H');\r
+define("S_DISPLAYTOMANA", '\82±\82ê\82Í\81A\8aÇ\97\9d\83`\81[\83\80\82É\95\\8e¦\82³\82ê\82Ü\82·');\r
+define("S_DISPLAYTOUSER", '\82±\82Ì\8bÖ\8e~\83\86\81[\83U\81[\82É\95\\8e¦\82³\82ê\82Ü\82·');\r
+define("S_MANABADFILE", '\83t\83@\83C\83\8b\88«\82¢');\r
+define("S_MANABADWORD", '\83\8f\81[\83h\88«\82¢');\r
+\r
+define("S_MDTABLE1", '<tr bgcolor="#6080f6"><th>\8dí\8f\9c</th><th>\8bL\8e\96No</th><th>\93\8a\8de\93ú</th><th>\91è\96¼</th>');\r
+define("S_MDTABLE2", '<th>\93\8a\8de\8eÒ</th><th>\83R\83\81\83\93\83g</th><th>\83z\83X\83g\96¼ \81^ IP</th>');\r
+define("S_MDTABLE3", '<th>\93Y\95t<br />(Bytes)</th>');\r
+define("S_MDTABLE4", '<th>md5</th>');\r
+\r
+define("S_MTTABLE1", '<tr bgcolor="#6080f6"><th>\91I\91ð</th><th>\8bL\8e\96No</th><th>\8fó\91Ô</th><th>\93\8a\8de\93ú</th><th>\91è\96¼</th>');\r
+\r
+define("S_RESET", '\83\8a\83Z\83b\83g');\r
+define("S_IMGSPACEUSAGE", '\89æ\91\9c\83f\81[\83^\8d\87\8cv : ');\r
+define("S_YOURIP", '\82 \82È\82½\82ÌIP\82Í\88È\89º\82Ì\92Ê\82è\82Å\82·\81F');\r
+define("S_SUCCESS", '\90¬\8c÷');\r
+define("S_CANNOTWRITE", '\83J\83\8c\83\93\83g\83f\83B\83\8c\83N\83g\83\8a\82É\8f\91\82¯\82Ü\82¹\82ñ<br />');\r
+define("S_NOTWRITE", '\82ð\8f\91\82¯\82Ü\82¹\82ñ<br />');\r
+define("S_NOTREAD", '\82ð\93Ç\82ß\82Ü\82¹\82ñ<br />');\r
+define("S_NOTDIR", '\82ª\82 \82è\82Ü\82¹\82ñ<br />');\r
+define("S_VERIFY", '\8am\94F');\r
+define("S_WRONGVERY", '\82 \82È\82½\82Í\8aÔ\88á\82Á\82½\8am\94F\83R\81[\83h\82ð\93ü\82ê\82Ü\82µ\82½\81I');\r
+define("S_NOTITLE", '\83|\83X\83g\82Ì\82½\82ß\82É\83^\83C\83g\83\8b\82©\91Î\8fÛ\82ð\93ü\97Í\82µ\82Ä\82­\82¾\82³\82¢');\r
+define("S_ANOTFOUND", '\8aY\93\96\8bL\8e\96\82ª\8c©\82Â\82©\82ç\82È\82¢\82©\83p\83X\83\8f\81[\83h\82ª\8aÔ\88á\82Á\82Ä\82¢\82Ü\82·');\r
+define("S_EDITSAME", '\93à\97e\82ª\91S\82­\93¯\82\82Å\82·\81@\82Ç\82±\82©\95Ï\8dX\82µ\82Ä\82­\82¾\82³\82¢');\r
+define("S_CANNOTCORRECT", '\8fC\90³\95s\89Â');\r
+\r
+define("S_TOOBIGRES", '\89æ\8bK\96Í\82Í\91å\82«\89ß\82¬\82Ü\82·');\r
+define("S_TOOSMALLRES", '\89æ\8bK\96Í\82Í\8f¬\82«\89ß\82¬\82Ü\82·');\r
+define("S_FILEEXNOTSUPPORTED", '\83T\83|\81[\83g\82³\82ê\82È\82©\82Á\82½\83t\83@\83C\83\8b\8ag\92£\8eq');\r
+define("S_FILETYPENOTSUPPORTED", '\83T\83|\81[\83g\82³\82ê\82È\82©\82Á\82½\83t\83@\83C\83\8b\83^\83C\83v');\r
+\r
+define("S_THUMBV", '\83T\83\80\83l\83C\83\8b');\r
+define("S_VIEWA", '\89æ\91\9c\82Ñ\82ã\81`\82í\81`');\r
+define("S_NEWTHREAD", '\90V\8bK\83X\83\8c\83b\83h\8dì\90¬');\r
+define("S_CAT", '\83J\83^\83\8d\83O');\r
+define("S_CATALOGMODE", '\83J\83^\83\8d\83O\83\82\81[\83h');\r
+define("S_LIST", '\83X\83\8c\83b\83h\88ê\97\97');\r
+define("S_NWAHA", '\90V\92\85\82í\82Í\81[');\r
+define("S_ABOUT", 'ABOUT');\r
+define("S_OGEGE", '\82¨\82°\82°');\r
+define("S_ALBUM", '\83A\83\8b\83o\83\80\83\82\81[\83h');\r
+define("S_TLIST", '\83X\83\8c\83b\83h\88ê\97\97\82Í\82±\82¿\82ç');\r
+define("S_SUBLIST", '\91è\96¼\88ê\97\97');\r
+define("S_SOURCECODE", '\83\\81[\83X\83R\81[\83h');\r
+define("S_ARCHIVEOF", TITLE.'\82Ì\83A\81[\83J\83C\83u');\r
+define("S_NOARCHIVE", '\83X\83\8c\82Í\8ai\94[\82³\82ê\82Ü\82¹\82ñ');\r
+\r
+/*smaller files connection*/\r
+define("S_TOTAL_IMG", '\89æ\91\9c\91\8d\90\94');\r
+define("S_TOTAL_SURE", '\83X\83\8c\96{\90\94');\r
+define("S_TOTAL_POST", '\8bL\8e\96\8c\8f\90\94');\r
+\r
+define("S_FUTAPASS", '\81¥\83p\83X\83\8f\81[\83h\82ð\93ü\97Í\82µ\82Ä\82­\82¾\82³\82¢.');\r
+define("S_FUTABO1", '\94F\8fØ');\r
+define("S_FUTADEL", '\8dí\8f\9c\82µ\82Ü\82·\82©\81H');\r
+define("S_FUTA2YOTSU", '\8dX\90V\82µ\82Ü\82·\82©\81H');\r
+define("S_FUTAGARBAGE", '\82t\82q\82k\81A\82l\82`\82h\82k\81A\82s\82h\82l\82d\82Ì\83S\83~\82ð\8eæ\82è\8f\9c\82«\82Ü\82·\81B<br />\r
+\83\8d\83O\82Í\95K\82¸\83o\83b\83N\83A\83b\83v\82µ\82Ä\82©\82ç\8eÀ\8ds\82µ\82Ä\89º\82³\82¢\81B');\r
+define("S_FUTAPROSS", '<b>\90³\8fí\82É\8f\88\97\9d\82³\82ê\82Ü\82µ\82½\81B</b>');\r
+$copy_log = COPY_LOG;\r
+define("S_FUTAPROSSCOPY", '<br />\83\8d\83O\82ð\8am\94F\82Ì\8fã\81A<b>'.$copy_log.'</b>\82ð'.LOGFILE.'\82Æ\83\8a\83l\81[\83\80\82µ\82Ä\8d·\82µ\91Ö\82¦\82Ä\89º\82³\82¢\81B');\r
+define("S_FUTACLEAN", '\82¨\91|\8f\9c\82·\82é');\r
+\r
+    //img_view/search\r
+define("S_IMG_VIEW_INFO", '\83t\83@\83C\83\8b\8fî\95ñ\82ð\95\\8e¦\82Ì\83`\83F\83b\83N\83{\83b\83N\83X\83I\83\93\82Å\93\8a\8de\83X\83\8c\82É\83\8a\83\93\83N\82µ\82Ü\82·');\r
+define("S_TEXT_ENGINE", '\91S\95\8c\9f\8dõ\83G\83\93\83W\83\93');\r
+define("S_TEXT_ENGINE_INSTALLED", '\93\8b\8dÚ');\r
+define("S_FILE_INFO_DISP", '\83t\83@\83C\83\8b\8fî\95ñ\82ð\95\\8e¦');\r
+define("S_FILE_INFO_DISP_BUTTON", '\83|\83`\83b\82Æ\82È');\r
+define("S_ALL_TOTAL_IMG", '\91\8d\89æ\91\9c\96\87\90\94');\r
+define("S_SURE_IMG", '\83X\83\8c\89æ\91\9c\90\94');\r
+define("S_REPLY_IMG", '\83\8c\83X\89æ\91\9c\90\94');\r
+define("S_PAGE_DEF", '\88ë\83y\81[\83W\95\\8e¦\90\94');\r
+define("S_IMG_DISPLAY_TO", '\82©\82ç');\r
+define("S_IMG_DISPLAY", '\82Ü\82Å\82Ì\89æ\91\9c\82ð\95\\8e¦');\r
+define("S_PIECE", '\96\87');\r
+\r
+define("S_SEARCH",'\8c\9f \8dõ');\r
+define("S_DISPNO",'\95\\8e¦\8c\8f\90\94\81F');\r
+define("S_SEARCH_RULE", '\81\83L\81[\83\8f\81[\83h\82ð\95¡\90\94\8ew\92è\82·\82é\8fê\8d\87\82Í \83X\83y\81[\83\82Å\8bæ\90Ø\82Á\82Ä\82­\82¾\82³\82¢\81B<br />\r
+\81\8c\9f\8dõ\8fð\8c\8f\82Í\81AAND\8c\9f\8dõ [A B] = (A \82©\82 B) \82Æ\82È\82Á\82Ä\82¢\82Ü\82·\81B<br />\r
+\81\8c\9f\8dõ\91Î\8fÛ\82Í\81\8bL\8e\96No\81A\96¼\91O\81A\91è\96¼\81A\96{\95\81A\96Ú\97\93 \82Å\82·\81B<br />\r
+\81\91å\95\8e\9a\8f¬\95\8e\9a\82Í\8bæ\95Ê\82³\82ê\82Ü\82·\81B (A\81\82a) (ABC\81\82aBC)<br />\r
+\81\8c\9f\8dõ\92P\8cê\82Í\82S\90F\8cJ\82è\95Ô\82µ\8eg\97p\82µ\82Ä\90F\82Â\82«\82Å\95\\8e¦\82µ\82Ü\82·\81Bgoogle\95\97\81H<br />\r
+\81\95Ï\82È\8c\9f\8dõ\95û\96@\82Í\82È\82é\82×\82­\82¨\8dT\82¦\82­\82¾\82³\82¢\81B\83o\83O\82ª\82 \82ê\82Î\82²\95ñ\8d\90\82ð\81B<br />\r
+\81\82±\82Ì\8c\9f\8dõ\83G\83\93\83W\83\93\82Ì\83x\81[\83X\82Í logoogle.php ver 0.1.1 \82Å\82·\81B<br />');\r
+\r
+define("S_SEARCH_NOT_FOUND", '\82É\8aY\93\96\82·\82é\92P\8cê\82ª\8c©\82Â\82©\82è\82Ü\82¹\82ñ\82Å\82µ\82½\81B');\r
+define("S_SEARCH_PROTIP", '\8c\9f\8dõ\82Ì\83q\83\93\83g');\r
+define("S_SEARCH_LIST", '- \83L\81[\83\8f\81[\83h\82É\8cë\8e\9a\81E\92E\8e\9a\82ª\82È\82¢\82©\8am\82©\82ß\82Ä\82­\82¾\82³\82¢\81B<br />\r
+- \88á\82¤\83L\81[\83\8f\81[\83h\82ð\8eg\82Á\82Ä\82Ý\82Ä\82­\82¾\82³\82¢\81B<br />\r
+- \82æ\82è\88ê\94Ê\93I\82È\8c¾\97t\82ð\8eg\82Á\82Ä\82Ý\82Ä\82­\82¾\82³\82¢\81B<br />\r
+- \83L\81[\83\8f\81[\83h\82Ì\90\94\82ð\8f­\82È\82­\82µ\82Ä\82Ý\82Ä\82­\82¾\82³\82¢\81B<br />\r
+- \8e©\95ª\82Ì\83Z\83\93\83X\82ð\8b^\82Á\82Ä\82Ý\82Ä\82­\82¾\82³\82¢\81B<br />');\r
+define("S_POSTSCRIPT", '\92Ç\8bL:');\r
+define("S_SEARCH_FIX", '\8fã\8bL\82Ì\82±\82Æ\82ð\8e\8e\82µ\82Ä\82à\83_\83\81\82È\8fê\8d\87\82Í\81A\8b°\82ç\82­\82à\82¤\8eè\92x\82ê\82È\82Ì\82Å\82µ\82å\82¤\81B\8c\89\82­\82 \82«\82ç\82ß\82Ä\82­\82¾\82³\82¢\81B');\r
+define("S_KEYWORD_NO_MATCH", '\83L\81[\83\8f\81[\83h\82É\83}\83b\83`\82·\82é\8bL\8e\96\82ª\82 \82è\82Ü\82¹\82ñ\82Å\82µ\82½\81B');\r
+\r
+define("S_INLOG", '\83\8d\83O\93à');\r
+define("S_SEARCH_RESULT", '\82Ì\8c\9f\8dõ\8c\8b\89Ê');\r
+define("S_SEARCH_HIT", '\8c\8f\92\86');\r
+define("S_SEARCH_RESULTS", '\8c\8f\96Ú');\r
+define("S_SEARCH_SUBJECT", '\91è\96¼\81F');\r
+define("S_SEARCH_NAME", '\96¼\91O\81F');\r
+define("S_SEARCH_DATE", '\93ú\95t\81F');\r
+define("S_SEARCH_PREV", '&lt;&lt;\91O\82Ö');\r
+define("S_SEARCH_NEXT", '\8e\9f\82Ö&gt;&gt;');\r
+define("S_IMGRET",'\89æ\91\9c\8c\9f\8dõ');\r
+define("S_SEARCH_TOOL",'\8c\9f\8dõ\83c\81[\83\8b');\r
+define("S_HELP",'\83w\83\8b\83v');\r
+\r
+    //time\r
+define("S_SECONDS", '\95b');\r
+    //image download counter\r
+define("S_THISIMG",'\82±\82Ì\89æ\91\9c\82Í');\r
+define("S_THISIMGDLTIMES",'\89ñDownload\82³\82ê\82Ä\82¢\82Ü\82·.');\r
+\r
+// Style tooltip: stuff inside [square brackets] MUST be left as is!\r
+       define ('S_STYLETOOLTIP', "[what]\83X\83^\83C\83\8b\82Ö\82Ì\90Ø\82è\91Ö\82¦");\r
+\r
+       // Title of stylesheet management page\r
+       define ('S_ADMIN_STYLESHEETS', "\83X\83^\83C\83\8b\83V\81[\83g\82ð\8aÇ\97\9d\82µ\82Ä");\r
+\r
+               define ('TH_ADMIN_IMPORTED', "\83C\83\93\83|\81[\83g\82©\82ç <b>[file]</b>");\r
+               define ('TH_ADMIN_EDITING', "\95Ò\8fW <b>[file]</b>");\r
+               define ('TH_ADMIN_CREATED', "\8dì\90¬ <b>[file]</b>!");\r
+               define ('TH_ADMIN_UPDATED', "\82ð\8dX\90V <b>[file]</b>!");\r
+               define ('TH_ADMIN_DELETED', "\8dí\8f\9c <b>[file]</b>!");\r
+\r
+               // Headings for fields\r
+               define ('TH_ADMIN_IS_DEFAULT', "\83f\83t\83H\83\8b\83g\82Ì\82Å\82·\82©\81H");\r
+               define ('TH_ADMIN_STYLE_DEFAULT', "     \82±\82Ì\83f\83t\83H\83\8b\83g\82É\82·\82é");\r
+               define ('TH_ADMIN_FULLNAME', "\96{\93\96\82Ì\96¼\91O");\r
+               define ('TH_ADMIN_SHORTNAME', "\95\\8e¦\96¼");\r
+               define ('TH_ADMIN_DISP_ID', '<nobr>ID / \95\\8e¦\8f\87</nobr> <nobr>(\83^\83C\83v0\82±\82Ì\8d\80\96Ú\82ð\8dí\8f\9c\82·\82é)</nobr>');\r
+               define ('TH_ADMIN_ADDSTYLE', "\92Ç\89Á [or modify] \83X\83^\83C\83\8b\83V\81[\83g\82Ì\83G\83\93\83g\83\8a");\r
+                       // This goes in [or modify] above\r
+                       define ('TH_ADMIN_MODSTYLE', "\82Ü\82½\82Í\95Ï\8dX");\r
+               define ('TH_ADMIN_NEW_FILE', '\83t\83@\83C\83\8b');\r
+               define ('TH_ADMIN_NEW_ID', '<nobr>\95\\8e¦\8f\87</nobr> <nobr>(\8aù\91\82ÌID\94Ô\8d\86\82ð\8eg\97p\82µ\82Ä\81A\83A\83C\83e\83\80\82ð\8fã\8f\91\82«\82·\82é)</nobr>');\r
+\r
+/* begin MySQL specific section \r
+define("S_SQLCONF", '\90Ú\91±\8e¸\94s');  //MySQL connection failure\r
+define("S_SQLDBSF", 'mysql_select_db\8e¸\94s<br />'); //database select failure\r
+define("S_TCREATE", '\83e\81[\83u\83\8b\82ð\8dì\90¬\82µ\82Ü\82·<br />\n'); //creating table\r
+define("S_TCREATEF", '\83e\81[\83u\83\8b\8dì\90¬\8e¸\94s<br />');  //table creation failed\r
+define("S_SQLFAIL", 'sql\8e¸\94s<br />');  //SQL Failure\r
+define("S_UNFILE", '\91Î\89\9e\82µ\82È\82¢\83t\83H\81[\83}\83b\83g\82Å\82·\81B');\r
+*/\r
+?>\r
diff --git a/lib/lang/zh_TW.php b/lib/lang/zh_TW.php
new file mode 100755 (executable)
index 0000000..79d2f0d
--- /dev/null
@@ -0,0 +1,241 @@
+<?php\r
+/*\r
+Pixmicat! & Yotsubanome language file - Chinese Traditional [zh_TW]\r
+*/\r
+if (!isset($language)) $language = Array();\r
+\r
+// yotsubanome.php\r
+$language['page_not_found']                            = '對不起,您所要求的頁數並不存在';\r
+$language['thread_not_found']                  = '欲回應之文章並不存在!';\r
+$language['del_head']                                  = '【刪除文章】';\r
+$language['del_img_only']                              = '僅刪除附加圖檔';\r
+$language['del_pass']                                  = '刪除用密碼: ';\r
+$language['del_btn']                                   = ' 執行 ';\r
+$language['prev_page']                                 = '上一頁';\r
+$language['first_page']                                        = '第一頁';\r
+$language['all_pages']                                 = 'ALL';\r
+$language['next_page']                                 = '下一頁';\r
+$language['last_page']                                 = '最後一頁';\r
+$language['img_sample']                                        = '[以預覽圖顯示]';\r
+$language['img_filename']                              = '檔名:';\r
+$language['reply_btn']                                 = '回應';\r
+$language['warn_sizelimit']                            = '這篇因附加圖檔容量限制,附加圖檔不久後就會刪除。';\r
+$language['warn_oldthread']                            = '這篇已經很舊了,不久後就會刪除。';\r
+$language['warn_locked']                               = '這篇討論串已被管理員標記為禁止回應。';\r
+$language['notice_omitted_posts']                              = '有回應 [#] ';
+$language['notice_omitted_images']                             = '和 [#] 圖像';
+$language['notice_omitted_reply']                              = '篇被省略。要閱讀所有回應請按下回應連結。';\r
+$language['post_name']                                 = '名稱: ';\r
+$language['post_category']                             = '類別: ';\r
+$language['regist_notpost']                            = '請使用此版提供的表單來上傳';\r
+$language['regist_nospam']                             = '防止 Spambot 機制啟動!';\r
+$language['regist_ipfiltered']                 = '您所使用的連線已被拒絕。原因:%1$s';\r
+$language['regist_wordfiltered']               = '發出的文章中有被管理員列為限制的字句,送出失敗';\r
+$language['regist_upload_exceedphp']   = '上傳失敗<br />上傳的附加圖檔容量超過PHP內定值';\r
+$language['regist_upload_exceedcustom']        = '上傳失敗<br />上傳的附加圖檔容量超過上傳容量限制';\r
+$language['regist_upload_incompelete'] = '上傳失敗<br />上傳的附加圖檔不完整,請回版面再重試';\r
+$language['regist_upload_direrror']            = '上傳失敗<br />上傳的暫存資料夾設定錯誤,請通報系統管理員';\r
+$language['regist_upload_noimg']               = '因應防止Spam對策,發文無附加圖檔請勾選[無貼圖]核選框!';\r
+$language['regist_upload_filenotfound']        = '上傳失敗<br />伺服器有可能禁止上傳、沒有權限,或不支援此格式';\r
+$language['regist_upload_killincomp']  = '[Notice] Your sending was canceled because of the incorrect file size.';\r
+$language['regist_upload_notimage']            = '上傳失敗<br />不接受圖片以外的檔案';\r
+$language['regist_upload_notsupport']  = '附加圖檔為系統不支援的格式';\r
+$language['regist_upload_blocked']             = '上傳失敗<br />此附加圖檔被管理員列為禁止上傳';\r
+$language['regist_uploaded']                   = '附加圖檔 %1$s 上傳完畢<br />';\r
+$language['regist_sakuradetected']             = '偵測到您有輸入櫻花日文假名';\r
+$language['regist_withoutname']                        = '您沒有填寫名稱';
+$language['regist_withoutsubject']                     = '您沒有填寫題名';\r
+$language['regist_withoutcomment']             = '在沒有附加圖檔的情況下,請寫入內文';
+$language['regist_withoutpassword']                    = '您必須輸入一個刪除用密碼的';\r
+$language['regist_nametoolong']                        = '名稱過長';\r
+$language['regist_emailtoolong']               = 'E-mail過長';\r
+$language['regist_topictoolong']               = '標題過長';\r
+$language['regist_longthreadnum']              = '欲回應的文章編號可能有誤';\r
+$language['admin']                                             = '管理';\r
+$language['deletor']                                   = '刪除';\r
+$language['trip_pre']                                  = '◆';\r
+$language['trip_pre_fake']                             = '◇';\r
+$language['cap_char']                                  = '★';\r
+$language['cap_char_fake']                             = '☆';\r
+$language['regist_commenttoolong']             = '內文過長';\r
+$language['notice_incompletefile']             = '注意:附加圖檔上傳不完全';\r
+$language['sun']                                               = '日';\r
+$language['mon']                                               = '一';\r
+$language['tue']                                               = '二';\r
+$language['wed']                                               = '三';\r
+$language['thu']                                               = '四';\r
+$language['fri']                                               = '五';\r
+$language['sat']                                               = '六';\r
+$language['regist_successivepost']             = '連續投稿請稍候一段時間';\r
+$language['regist_duplicatefile']              = '上傳失敗<br />近期已經有相同的附加圖檔';\r
+$language['regist_threaddeleted']              = '此討論串因為過舊已被刪除!';\r
+$language['regist_threadlocked']               = '這篇討論串已被管理員標記為禁止回應!';\r
+$language['regist_redirect']                   = '%1$s 畫面正在切換 <p>如果瀏覽器沒有自動切換,請手動按連結前往:<a href="%2$s">回到版面</a></p>';\r
+$language['del_notchecked']                            = '你真的有要刪除嗎?請回頁面重勾選';\r
+$language['del_wrongpwornotfound']             = '無此文章或是密碼錯誤';\r
+$language['admin_wrongpassword']               = '密碼錯誤';\r
+$language['return']                                            = '回到版面';\r
+$language['admin_remake']                              = '更新文章';\r
+$language['admin_frontendmanage']              = '前台管理 (需先登入)';\r
+$language['admin_delete']                              = '刪除文章';\r
+$language['admin_top']                                 = '管理模式';\r
+$language['admin_manageposts']                 = '管理文章';\r
+$language['admin_optimize']                            = '資料表最佳化';\r
+$language['admin_check']                               = '檢查資料表';\r
+$language['admin_repair']                              = '修復資料表';\r
+$language['admin_export']                              = '匯出資料';\r
+$language['admin_logout']                              = '登出';\r
+$language['admin_verify_btn']                  = ' 認證 ';\r
+$language['admin_archive']                             = '<th>庫存</th>';\r
+$language['admin_notices']                             = '<ul><li>想刪除文章,請勾選該文章前之「刪除」核取框之後按下執行按鈕</li><li>只想刪除文章的附加圖檔,請先勾選「僅刪除附加圖檔」再按照一般刪文方式</li><li>想停止/繼續討論串,請勾選該文章前之「停止」核取框之後按下執行按鈕</li><li>管理文章完畢,記得順手按下「更新文章」以更新靜態快取</li></ul>';\r
+$language['admin_submit_btn']                  = ' 執行 ';\r
+$language['admin_reset_btn']                   = ' 重置 ';\r
+$language['admin_list_header']                 = '<th>功能</th><th>停止</th><th>刪除</th><th>投稿日</th><th>標題</th><th>名稱</th><th>內文</th><th>主機位置名稱</th><th>附加圖檔 (Bytes)<br />MD5 檢查碼</th>';\r
+$language['admin_archive_btn']                 = '存';\r
+$language['admin_stop_btn']                            = '停';\r
+$language['admin_totalsize']                   = '【 附加圖檔使用容量總計 : <b>%1$s</b> KB 】';\r
+$language['search_disabled']                   = '管理員選擇不開放搜尋功能!';\r
+$language['search_top']                                        = '搜尋';\r
+$language['search_notice']                             = '<li>請輸入要搜尋的關鍵字,設定好搜尋目標之後,按下「搜尋」按鈕。</li><li>關鍵字使用半形空白可以區隔多個搜尋關鍵字作搜尋。</li><li>如果有多個關鍵字,可以選擇搜尋方法,系統提供 AND(交集) 和 OR(聯集) 方式搜尋。<p />關鍵字:';\r
+$language['search_target']                             = '搜尋目標:';\r
+$language['search_target_comment']             = '內文';\r
+$language['search_target_name']                        = '名稱';\r
+$language['search_target_topic']               = '標題';\r
+$language['search_target_number']              = '編號';\r
+$language['search_method']                             = '搜尋方法:';\r
+$language['search_method_and']                 = 'AND';\r
+$language['search_method_or']                  = 'OR';\r
+$language['search_submit_btn']                 = ' 搜尋 ';\r
+$language['search_notfound']                   = '找不到符合的關鍵字。';\r
+$language['search_back']                               = '[回上一頁]';\r
+$language['category_nokeyword']                        = '請輸入類別標籤以搜尋類似文章。';\r
+$language['category_notfound']                 = '沒有符合此類別標籤的文章';\r
+$language['category_recache']                  = '重新快取';\r
+$language['module_info_top']                   = '模組資訊';\r
+$language['module_loaded']                             = 'Module Loaded:';\r
+$language['module_info']                               = 'Module Infomation:';\r
+$language['info_top']                                  = '系統資訊';\r
+$language['info_disabled']                             = '未開啟';\r
+$language['info_enabled']                              = '已開啟';\r
+$language['info_functional']                   = '功能正常';\r
+$language['info_nonfunctional']                        = '功能失常';\r
+$language['info_basic']                                        = '基本設定';\r
+$language['info_basic_ver']                            = '程式版本';\r
+$language['info_basic_pio']                            = 'PIO 函式庫後端及版本';\r
+$language['info_basic_threadsperpage'] = '一頁顯示幾篇討論串';\r
+$language['info_basic_threads']                        = '篇';\r
+$language['info_basic_postsperpage']   = '一篇討論串最多顯示之回應筆數';\r
+$language['info_basic_posts']                  = '筆';\r
+$language['info_basic_postsinthread']  = '回應模式一頁顯示幾筆回應內容';\r
+$language['info_basic_posts_showall']  = '(全部顯示:0)';\r
+$language['info_basic_bumpposts']              = '回應筆數超過多少則不自動推文';\r
+$language['info_basic_bumphours']              = '討論串可接受推文的時間範圍';\r
+$language['info_basic_hours']                  = '小時';\r
+$language['info_basic_0disable']               = '(關閉:0)';\r
+$language['info_basic_urllinking']             = 'URL文字自動作成超連結';\r
+$language['info_0no1yes']                              = '(是:1 否:0)';\r
+$language['info_basic_com_limit']              = '內文接受Bytes數';\r
+$language['info_basic_com_after']              = ' Bytes (中文字為2Bytes)';\r
+$language['info_basic_anonpost']               = '接受匿名發送';\r
+$language['info_basic_anonpost_opt']   = '(強制砍名:2 是:1 否:0)';\r
+$language['info_basic_del_incomplete'] = '自動刪除上傳不完整附加圖檔';\r
+$language['info_basic_use_sample']             = '使用預覽圖機能 (品質:%1$s)';\r
+$language['info_0notuse1use']                  = '(使用:1 不使用:0)';\r
+$language['info_basic_use_sample_func']        = '└ 預覽圖生成功能';\r
+$language['info_basic_useblock']               = '封鎖檢查功能';\r
+$language['info_0disable1enable']              = '(啟動:1 關閉:0)';\r
+$language['info_basic_showid']                 = '顯示ID';\r
+$language['info_basic_showid_after']   = '(強制顯示:2 選擇性顯示:1 永遠不顯示:0)';\r
+$language['info_basic_cr_limit']               = '文字換行行數上限';\r
+$language['info_basic_cr_after']               = ' 行 (不限:0)';\r
+//$language['info_basic_timezone']             = '時區設定';
+$language['info_basic_max_lines_limit']                = '文字換行行數上限';\r
+$language['info_basic_max_lines_after']                = ' 線 (不限:0)';\r
+$language['info_basic_threadcount']            = '目前總討論串篇數';\r
+$language['info_basic_theme']                  = '主題風格';\r
+$language['info_dsusage_top']                  = '記錄檔使用量';\r
+$language['info_dsusage_max']                  = '最大筆數';\r
+$language['info_dsusage_usage']                        = '使用率';\r
+$language['info_dsusage_count']                        = '目前筆數';\r
+$language['info_fileusage_top']                        = '附加圖檔總容量限制功能:';\r
+$language['info_fileusage_limit']              = '上限大小';\r
+$language['info_fileusage_count']              = '目前容量';\r
+$language['info_fileusage_unlimited']  = '無上限';\r
+$language['info_server_top']                   = '伺服器支援情報';\r
+$language['info_server_gd']                            = 'GD函式庫';\r
+$language['init_permerror']                            = '根目錄沒有寫入權限,請修改權限<br />';\r
+$language['init_inited']                               = '環境初始化成功!<br />請現在打開此程式刪除init()程式環境初始化區段<br />';\r
+$language['action_main_notsupport']            = '後端並不支援此動作';\r
+$language['action_main_optimize']              = '資料表最佳化';\r
+$language['action_main_check']                 = '資料表檢查';\r
+$language['action_main_repair']                        = '資料表修復';\r
+$language['action_main_export']                        = '資料匯出';\r
+$language['action_main_success']               = '成功!';\r
+$language['action_main_failed']                        = '失敗!';\r
+\r
+// lib_common.php\r
+$language['head_home']                                 = '回首頁';\r
+$language['head_search']                               = '搜尋';\r
+$language['head_info']                                 = '系統資訊';\r
+$language['head_admin']                                        = '管理區';\r
+$language['head_refresh']                              = '重新整理';\r
+$language['form_top']                                  = '回應模式';\r
+$language['form_showpostform']                 = '投稿';\r
+$language['form_hidepostform']                 = '隱藏表單';\r
+$language['form_name']                                 = '名 稱';\r
+$language['form_email']                                        = 'E-mail';\r
+$language['form_topic']                                        = '標 題';\r
+$language['form_submit_btn']                   = '送 出';\r
+$language['form_comment']                              = '內 文';\r
+$language['form_attechment']                   = '附加圖檔';\r
+$language['form_noattechment']                 = '無貼圖';\r
+$language['form_contpost']                             = '連貼機能';\r
+$language['form_category']                             = '類別標籤';\r
+$language['form_category_notice']              = '(請以 , 逗號分隔多個標籤)';\r
+$language['form_delete_password']              = '刪除用密碼';\r
+$language['form_delete_password_notice']= '(刪除文章用。英數字8字元以內)';\r
+$language['form_notice']                               = '<li>可附加圖檔類型:%1$s,瀏覽器才能正常附加圖檔</li><li>附加圖檔最大上傳資料量為 %2$s KB。當回文時E-mail填入sage為不推文功能</li><li>當檔案超過寬 %3$s 像素、高 %4$s 像素時會自動縮小尺寸顯示</li>';\r
+$language['form_notice_storage_limit'] = '<li>目前附加圖檔使用量大小: %1$s KB / %2$s KB</li>';\r
+$language['form_notice_noscript']              = '*您選擇關閉了JavaScript,但這對您的瀏覽及發文應無巨大影響';\r
+$language['error_back']                                        = '回上頁';\r
+$language['ip_banned']                                 = '被列在 IP/Hostname 封鎖名單之內';\r
+$language['ip_dnsbl_banned']                   = '被列在 DNSBL(%1$s) 封鎖名單之內';\r
+\r
+// mainscript.js // regist_withoutcomment,regist_upload_notsupport,js_convert_sakura\r
+$language['js_convert_sakura']                 = '偵測到您有輸入櫻花日文假名的可能性,將自動為您轉換';\r
+
+
+$language['form_option1']                      = '<span id="option">選項1</span>';
+$language['form_newt']                 = '新主題';
+
+$language['nothumb']           = '縮略圖無法使用';
+$language['long_comment']              = '「評論太長。點擊';
+$language['long_here']         = '這裡';
+$language['long_see']          = '看全文。」';
+
+$language['def_sub']           = '無標題';
+$language['def_name']          = '無名氏';
+$language['def_com']           = '無內文';
+
+// Style tooltip: stuff inside [square brackets] MUST be left as is!
+$language['style_tooltip']                     = '切換到[what]風格';
+// Title of stylesheet management page
+$language['admin_stylesheets']                 = '樣式表管理';
+$language['admin_imported']                    = '<b>[file]</b>進口';
+$language['admin_editing']                     = '<b>[file]</b> 編輯';
+$language['admin_created']                     = '<b>[file]</b> 創建!';
+$language['admin_updated']                     = '<b>[file]</b> 更新!';
+$language['admin_deleted']                     = '<b>[file]</b> 刪除!';
+// Headings for fields
+$language['admin_is_default']                  = '什麼是默認? ';
+$language['admin_style_default']                       = '默認為';
+$language['admin_fullname']                    = '真實姓名';
+$language['admin_shortname']                   = '顯示名稱';
+$language['admin_dispid']                      = '<nobr>ID / 排序</nobr> <nobr>(類型0刪除此項目)</nobr>';
+$language['admin_addstyle']                    = '添加[or modify]樣式表項';
+// This goes in [or modify] above
+$language['admin_modstyle']                    = '或改變';
+$language['admin_new_file']                    = '文件';
+$language['admin_new_id']                      = '<nobr>排序</nobr> <nobr>(使用現有的身份證號碼覆蓋項目)</nobr>';
+if(!defined("PIXMICAT_LANGUAGE")) print_r($language);\r
+?>
\ No newline at end of file
diff --git a/lib/lib_common.php b/lib/lib_common.php
new file mode 100755 (executable)
index 0000000..fc31795
--- /dev/null
@@ -0,0 +1,419 @@
+<?php
+/**
+ * Pixmicat! Common Library
+ *
+ * 存放常用函式供主程式引入
+ * 
+ * @package PMCLibrary
+ * @version $Id: lib_common.php 690 2009-04-06 01:30:13Z scribe $
+ * @date $Date: 2009-04-06 09:30:13 +0800 (星期一, 06 四月 2009) $
+ */
+
+/* css data */
+$style_load = false;
+$style_bar = false;
+
+if(file_exists(DATA_DIR.CSV_SS)){ // Load FuuR4 CSS data
+       $style_data = DATA_DIR.CSV_SS;
+       $style_bar .= '[';
+       $lines = explode("\n", file_get_contents($style_data));
+       foreach($lines as $null => $line){
+               if($line != ''){
+                       list($style_name, $style_short, $style_path, $style_rel) = explode (',', $line);
+                       $style_path = CSS_DIR.$style_path;
+                       if(file_exists($style_path)){
+                               if($style_rel) $style_rel = 'stylesheet';
+                               else $style_rel = 'alternate stylesheet';
+                               $style_load .= '<link rel="'.$style_rel.'" type="text/css" href="'.$style_path.'" title="'.$style_name.'" />'."\n";
+                               $style_js = format_js_var($style_name);
+                               $style_title = str_replace('[what]', $style_name, _T('style_tooltip'));
+                               $style_bar .= ' <a href="javascript:set_stylesheet('.$style_js.')" title="'.$style_title.'">'.$style_short.'</a> |';
+                       }
+               }
+       }
+
+       $style_bar .= ']';
+
+       // Tidy up trailing seperators and empty brackets
+       $style_bar = str_replace('|]', ']', $style_bar);
+       $style_bar = str_replace('[] ', '', $style_bar);
+       $style_bar = str_replace('[]', '', $style_bar);
+}
+
+// Load stylesheet setting from config.php
+// if either of the datafiles are missing or empty
+if(str_replace('[]', '', $style_bar) == '') $style_load .= '<link rel="stylesheet" type="text/css" href="'.CSS_DIR.CSSFILE.'" />';
+
+// style sheet js loader
+$jsdonk = 'var style_cookie = "';
+$jsdonk .= ($style_bar) ? 'yo_style' : '';
+$jsdonk .= '";';
+////++++
+
+/* 輸出表頭 */
+/* ヘッダ */
+function head(&$dat,$resno=0){
+       global $PTE, $PMS, $language, $style_load, $style_bar, $jsdonk;
+       $title = '';
+
+       // Title from old yotsubanome //++++----
+       if(SHOWTITLEIMG == 1){
+               $title = '<img src="'.TITLEIMG.'" alt="'.TITLE.'" />';
+               if(SHOWTITLETXT) $title .= '<br />';
+       }elseif(SHOWTITLEIMG == 2){
+               $title = '<img src="'.TITLEIMG.'" onclick="this.src=this.src;" alt="'.TITLE.'" />';
+               if(SHOWTITLETXT) $title .= '<br />';
+       }
+       if(SHOWTITLETXT) $title .= TITLE;
+
+       $pte_vals = array('{$TITLE}'=>TITLE,'{$TITLEHEAD}'=>$title,'{$TITLECOM}'=>strip_tags(TITLECOM),'{$RESTO}'=>$resno?$resno:'','{$STYLE_LOAD}'=>$style_load,'{$STYLE_BAR}'=>$style_bar,'{$JS_DIR}'=>JS_DIR,'{$CSS_DIR}'=>CSS_DIR,'{$JSDONK}'=>$jsdonk,'{$FAV_ICON}'=>FAV_ICON,'{$LANGUAGE}'=>PIXMICAT_LANGUAGE);
+       $dat .= $PTE->ParseBlock('HEADER',$pte_vals);
+       $PMS->useModuleMethods('Head', array(&$dat,$resno)); // "Head" Hook Point
+       $pte_vals+=array('{$ALLOW_UPLOAD_EXT}' => ALLOW_UPLOAD_EXT,
+               '{$JS_REGIST_WITHOUTCOMMENT}' => str_replace('\'', '\\\'', _T('regist_withoutcomment')),
+               '{$JS_REGIST_UPLOAD_NOTSUPPORT}' => str_replace('\'', '\\\'', _T('regist_upload_notsupport')),
+               '{$JS_CONVERT_SAKURA}' => str_replace('\'', '\\\'', _T('js_convert_sakura')));
+       $dat .= $PTE->ParseBlock('JSHEADER',$pte_vals);
+       $dat .= '</head>';
+       $pte_vals += array('{$TOP_LINKS}' => TOP_LINKS,
+               '{$HOME}' => '[<a href="'.HOME.'" rel="_top">'._T('head_home').'</a>]',
+               '{$STATUS}' => '[<a href="'.PHP_SELF.'?mode=status">'._T('head_info').'</a>]',
+               '{$ADMIN}' => '[<a href="'.PHP_SELF.'?mode=admin">'._T('head_admin').'</a>]',
+               '{$REFRESH}' => '[<a href="'.PHP_SELF2.'?">'._T('head_refresh').'</a>]',
+               '{$SEARCH}' => (USE_SEARCH) ? '[<a href="'.PHP_SELF.'?mode=search">'._T('head_search').'</a>]' : '');
+       if(STYLEBAR) $pte_vals += array('{$HOOKLINKS}' => '<small>'.$style_bar.'</small>');
+       else $pte_vals += array('{$HOOKLINKS}' => '');
+       $PMS->useModuleMethods('Toplink', array(&$pte_vals['{$HOOKLINKS}'],$resno)); // "Toplink" Hook Point
+       $dat .= $PTE->ParseBlock('BODYHEAD',$pte_vals);
+}
+
+/* 發表用表單輸出 */
+/* 投稿フォーム */
+function form(&$dat, $resno, $iscollapse=true, $retURL=PHP_SELF, $name='', $mail='', $sub='', $com='', $cat='', $mode='regist'){
+       global $PTE, $PMS, $ADDITION_INFO, $language;
+       $pte_vals = array('{$SELF}'=>$retURL, '{$FORMTOP}'=>'', '{$MODE}'=>$mode);
+       $isedit = ($mode == 'edit'); // 是否為編輯模式
+       if($resno && !$isedit){
+               $links = '[<a href="'.PHP_SELF2.'?'.time().'">'._T('return').'</a>]';
+               $PMS->useModuleMethods('LinksAboveBar', array(&$links,'reply',$resno)); // "LinksAboveBar" Hook Point
+               $pte_vals['{$FORMTOP}'] = '<div id="bannerlink">'.$links.'</div><div id="banner"><div class="theader">'._T('form_top').'</div></div>';
+       } //----class="bar_reply"
+       if(!$resno) $ntno = _T('form_newt');
+       else $ntno = _T('reply_btn').':'.$resno; // new thread & reply:$resno
+       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>]';
+       $pte_vals += array('{$MAX_FILE_SIZE}' => MAX_KB * 1024,
+               '{$RESTO}' => $resno ? '<input type="hidden" name="resto" value="'.$resno.'" />' : '',
+               '{$FORM_NAME_TEXT}' => _T('form_name'),
+               '{$FORM_NAME_FIELD}' => '<input class="hide" type="text" name="name" value="spammer" /><input class="inputtext" type="text" name="'.FT_NAME.'" id="fname" size="28" value="'.$name.'" />',
+               '{$FORM_EMAIL_TEXT}' => _T('form_email'),
+               '{$FORM_EMAIL_FIELD}' => '<input class="inputtext" type="text" name="'.FT_EMAIL.'" id="femail" size="28" value="'.$mail.'" /><input type="text" class="hide" name="email" value="foo@foo.bar" />',
+               '{$FORM_TOPIC_TEXT}' => _T('form_topic'),
+               '{$FORM_TOPIC_FIELD}' => '<input class="hide" value="DO NOT FIX THIS" type="text" name="sub" /><input class="inputtext" type="text" name="'.FT_SUBJECT.'" id="fsub" size="35" value="'.$sub.'" />',
+               '{$FORM_SUBMIT}' => ' <input type="submit" name="sendbtn" value="'._T('form_submit_btn').'" /><small>「'.$ntno.'」</small>',
+               '{$FORM_COMMENT_TEXT}' => _T('form_comment'),
+               '{$FORM_COMMENT_FIELD}' => '<textarea class="inputtext" name="'.FT_COMMENT.'" id="fcom" cols="48" rows="4">'.$com.'</textarea><textarea name="com" class="hide" cols="48" rows="4">EID OG SMAPS</textarea>',
+               '{$FORM_DELETE_PASSWORD_FIELD}' => '<input class="inputtext" type="password" name="pwd" size="8" maxlength="8" value="" />',
+               '{$FORM_DELETE_PASSWORD_TEXT}' => _T('form_delete_password'),
+               '{$FORM_DELETE_PASSWORD_NOTICE}' => _T('form_delete_password_notice'),
+               '{$FORM_EXTRA_COLUMN}' => '',
+               '{$FORM_NOTICE}' => _T('form_notice',str_replace('|',', ',ALLOW_UPLOAD_EXT),MAX_KB,($resno ? MAX_RW : MAX_W),($resno ? MAX_RH : MAX_H)),
+               '{$HOOKPOSTINFO}' => '',
+               '{$ADDITION_INFO}' => $ADDITION_INFO,
+               '{$FORM_NOTICE_NOSCRIPT}' => _T('form_notice_noscript'));
+       $PMS->useModuleMethods('PostForm', array(&$pte_vals['{$FORM_EXTRA_COLUMN}'])); // "PostForm" Hook Point
+       if(!$isedit && (RESIMG || !$resno)){
+               $pte_vals += array('{$FORM_ATTECHMENT_TEXT}' => _T('form_attechment'),
+                       '{$FORM_ATTECHMENT_FIELD}' => '<input class="inputtext" type="file" name="upfile" id="fupfile" size="35" /><input class="hide" type="checkbox" name="reply" value="yes" />');
+                       if(!NO_TEXTONLY || NO_TEXTONLY == 1){
+                               $pte_vals += array('{$FORM_NOATTECHMENT_TEXT}' => _T('form_noattechment'),
+                               '{$FORM_NOATTECHMENT_FIELD}' => '<input type="checkbox" name="noimg" id="noimg" value="on" />');
+                       }
+       }
+       if(OPTION || USE_UPSERIES){ //++++ more options will be added on later
+               $pte_vals['{$FORM_OPTION1_TEXT}'] = _T('form_option1');
+       }
+       if(USE_UPSERIES){ // 啟動連貼機能
+               $pte_vals['{$FORM_CONTPOST_FIELD}'] = '<input type="checkbox" name="up_series" id="up_series" value="on"'.((isset($_GET["upseries"]) && $resno)?' checked="checked"':'').' />';
+               $pte_vals['{$FORM_CONTPOST_TEXT}'] = _T('form_contpost');
+       }
+       if(OPTION){ //options hook
+               $pte_vals['{$FORM_OPTION_HOOK}'] = '';
+       }
+       if(USE_CATEGORY){
+               $pte_vals += array('{$FORM_CATEGORY_FIELD}' => '<input class="inputtext" type="text" name="category" size="28" value="'.$cat.'" />',
+                       '{$FORM_CATEGORY_TEXT}' => _T('form_category'),
+                       '{$FORM_CATEGORY_NOTICE}' => _T('form_category_notice'));
+       }
+       if(STORAGE_LIMIT) $pte_vals['{$FORM_NOTICE_STORAGE_LIMIT}'] = _T('form_notice_storage_limit',total_size(),STORAGE_MAX);
+       $PMS->useModuleMethods('PostInfo', array(&$pte_vals['{$HOOKPOSTINFO}'])); // "PostInfo" Hook Point
+
+       if(USE_FLOATFORM && !$resno && $iscollapse) $pte_vals['{$FORMBOTTOM}'] = '<script type="text/javascript">hideform();</script>';
+       $dat .= $PTE->ParseBlock('POSTFORM',$pte_vals);
+}
+
+/* 輸出頁尾文字 */
+/* フッタ */
+function foot(&$dat){
+       global $PTE, $PMS, $language;
+       $pte_vals = array('{$FOOTER}'=>'<!-- GazouBBS v3.0 --><!-- ふたば改0.8 --><!-- Pixmicat! --><!-- 四葉の芽改0.8 -->'."\n");
+       $PMS->useModuleMethods('Foot', array(&$pte_vals['{$FOOTER}'])); // "Foot" Hook Point
+       $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> + <a href="http://4ch.irc.su/" rel="_blank">yotsubanome</a> -</small>';
+       $pte_vals['{$FOOTER}'] .= '<p>
+       <a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-xhtml11" alt="Valid XHTML 1.1" height="31" width="88" /></a>
+       </p>';
+       $dat .= $PTE->ParseBlock('FOOTER',$pte_vals);
+}
+
+/* 網址自動連結 */
+/* オートリンク */
+function auto_link_callback($matches){ 
+       return (strtolower($matches[3]) == "</a>") ? $matches[0] : preg_replace('/(https?|ftp|news|gopher)(:\/\/[\w\+\$\;\?\.\{\}%,!#~*\/:@&=_-]+)/u', '<a href="$1$2" rel="_blank">$1$2</a>', $matches[0]);
+}
+function auto_link($proto){
+       $proto = preg_replace('|<br\s*/?>|',"\n",$proto);
+       $proto = preg_replace_callback('/(>|^)([^<]+?)(<.*?>|$)/m','auto_link_callback',$proto);
+       return str_replace("\n",'<br />',$proto);
+}
+
+/* 引用標註 */
+function quoteLight($comment){
+       return preg_replace('/(^|<br \/>)((?:&gt;|>).*?)(?=<br \/>|$)/u', '$1<span class="unkfunc">$2</span>', $comment);
+}
+function quoteLight2($comment){
+       return preg_replace('/(^|<br \/>)((?:#|#).*?)(?=<br \/>|$)/u', '$1<span class="unkfunc2">$2</span>', $comment);
+}
+
+/* 取得完整的網址 */
+function fullURL(){
+       return 'http://'.$_SERVER['HTTP_HOST'].substr($_SERVER['PHP_SELF'], 0, strpos($_SERVER['PHP_SELF'], PHP_SELF));
+}
+
+/* 反櫻花字 */
+function anti_sakura($str){
+       return preg_match('/[\x{E000}-\x{F848}]/u', $str);
+}
+
+/* 輸出錯誤畫面 */
+/* エラー画面 */
+function error($mes, $dest=''){
+       global $PTE;
+       if(is_file($dest)) unlink($dest);
+       $pte_vals = array('{$SELF2}'=>PHP_SELF2.'?'.time(), '{$MESG}'=>$mes, '{$RETURN_TEXT}'=>_T('return'), '{$BACK_TEXT}'=>_T('error_back'));
+       $dat = '';
+       head($dat);
+       $dat .= $PTE->ParseBlock('ERROR',$pte_vals);
+       foot($dat);
+       exit($dat);
+}
+
+/* 文字修整 */
+/* テキスト整形 */
+function CleanStr($str, $IsAdmin=false){
+       $str = trim($str); // 去除前後多餘空白
+       if(get_magic_quotes_gpc()) $str = stripslashes($str); // "\"斜線符號去除
+       // XML 1.1 Second Edition: 部分避免用字 (http://www.w3.org/TR/2006/REC-xml11-20060816/#charsets)
+       $str = preg_replace('/([\x1-\x8\xB-\xC\xE-\x1F\x7F-\x84\x86-\x9F\x{FDD0}-\x{FDDF}])/u', '', htmlspecialchars($str));
+
+       if($IsAdmin && CAP_ISHTML){ // 管理員開啟HTML
+               $str = preg_replace('/&lt;(.*?)&gt;/', '<$1>', $str); // 如果有&lt;...&gt;則轉回<...>成為正常標籤
+       }
+       return $str;
+}
+
+/* 適用UTF-8環境的擬substr,取出特定數目字元
+原出處:Sea Otter @ 2005.05.10
+http://www.meyu.net/star/viewthread.php?tid=267&fpage=10 */
+function str_cut($str, $maxlen=20){
+    $i = $l = 0; $len = strlen($str); $f = true; $return_str = $str;
+       while($i < $len){
+               $chars = ord($str{$i});
+               if($chars < 0x80){ $l++; $i++; }
+               elseif($chars < 0xe0){ $l++; $i += 2; }
+               elseif($chars < 0xf0){ $l += 2; $i += 3; }
+               elseif($chars < 0xf8){ $l++; $i += 4; }
+       elseif($chars < 0xfc){ $l++; $i += 5; }
+               elseif($chars < 0xfe){ $l++; $i += 6; }
+               if(($l >= $maxlen) && $f){
+                       $return_str = substr($str, 0, $i);
+                       $f = false;
+               }
+               if(($l > $maxlen) && ($i <= $len)){
+                       $return_str = $return_str.'…';
+                       break;
+               }
+    }
+       return $return_str;
+}
+
+/* 檢查瀏覽器和伺服器是否支援gzip壓縮方式 */
+function CheckSupportGZip(){
+       $HTTP_ACCEPT_ENCODING = isset($_SERVER['HTTP_ACCEPT_ENCODING']) ? $_SERVER['HTTP_ACCEPT_ENCODING'] : '';
+       if(headers_sent() || connection_aborted()) return 0; // 已送出資料,取消
+       if(!(function_exists('gzencode') && function_exists('ob_start') && function_exists('ob_get_clean'))) return 0; // 伺服器相關的套件或函式無法使用,取消
+       if(strpos($HTTP_ACCEPT_ENCODING, 'gzip')!==false) return 'gzip';
+       return 0;
+}
+
+/* 封鎖 IP / Hostname / DNSBL 綜合性檢查 */
+function BanIPHostDNSBLCheck($IP, $HOST, &$baninfo){
+       if(!BAN_CHECK) return false; // Disabled
+       global $BANPATTERN, $DNSBLservers, $DNSBLWHlist;
+
+       // IP/Hostname Check
+       $HOST = strtolower($HOST);
+       $checkTwice = ($IP != $HOST); // 是否需檢查第二次
+       $IsBanned = false;
+       foreach($BANPATTERN as $pattern){
+               $slash = substr_count($pattern, '/');
+               if($slash==2){ // RegExp
+                       $pattern .= 'i';
+               }elseif($slash==1){ // CIDR Notation
+                       if(matchCIDR($IP, $pattern)){ $IsBanned = true; break; }
+                       continue;
+               }elseif(strpos($pattern, '*')!==false || strpos($pattern, '?')!==false){ // Wildcard
+                       $pattern = '/^'.str_replace(array('.', '*', '?'), array('\.', '.*', '.?'), $pattern).'$/i';
+               }else{ // Full-text
+                       if($IP==$pattern || ($checkTwice && $HOST==strtolower($pattern))){ $IsBanned = true; break; }
+                       continue;
+               }
+               if(preg_match($pattern, $HOST) || ($checkTwice && preg_match($pattern, $IP))){ $IsBanned = true; break; }
+       }
+       if($IsBanned){ $baninfo = _T('ip_banned'); return true; }
+
+       // DNS-based Blackhole List(DNSBL) 黑名單
+       if(!$DNSBLservers[0]) return false; // Skip check
+       if(array_search($IP, $DNSBLWHlist)!==false) return false; // IP位置在白名單內
+       $rev = implode('.', array_reverse(explode('.', $IP)));
+       $lastPoint = count($DNSBLservers) - 1; if($DNSBLservers[0] < $lastPoint) $lastPoint = $DNSBLservers[0];
+       $isListed = false;
+       for($i = 1; $i <= $lastPoint; $i++){
+               $query = $rev.'.'.$DNSBLservers[$i].'.'; // FQDN
+               $result = gethostbyname($query);
+               if($result && ($result != $query)){ $isListed = $DNSBLservers[$i]; break; }
+       }
+       if($isListed){ $baninfo = _T('ip_dnsbl_banned',$isListed); return true; }
+       return false;
+}
+function matchCIDR($addr, $cidr) {
+       list($ip, $mask) = explode('/', $cidr);
+       return (ip2long($addr) >> (32 - $mask) == ip2long($ip.str_repeat('.0', 3 - substr_count($ip, '.'))) >> (32 - $mask));
+}
+
+/* 後端登入權限管理 */
+function adminAuthenticate($mode){
+       @session_start();
+       $loginkey = md5($_SERVER['HTTP_USER_AGENT'].ADMIN_PASS.$_SERVER['REMOTE_ADDR']);
+       switch($mode){
+               case 'logout':
+                       if(isset($_SESSION['pmcLogin'])) unset($_SESSION['pmcLogin']);
+                       return true; break;
+               case 'login':
+                       $_SESSION['pmcLogin'] = $loginkey;
+                       break;
+               case 'check':
+                       if(isset($_SESSION['pmcLogin']) && $_SESSION['pmcLogin']==$loginkey){
+                               session_regenerate_id(true); // 更換 Session id key 避免 Hijacking
+                               return true;
+                       }
+                       return false;
+                       break;
+       }
+}
+
+/* 取得 (Transparent) Proxy 提供之 IP 參數 */
+function getREMOTE_ADDR(){
+       // 同時有 VIA 和 FORWARDED_FOR 較可能為 Proxy
+       if(isset($_SERVER['HTTP_VIA']) && isset($_SERVER['HTTP_X_FORWARDED_FOR'])){
+               $tmp = preg_split('/[ ,]+/', $_SERVER['HTTP_X_FORWARDED_FOR']);
+               // 防止 Squid "unknown" 問題,此種情況直接使用 REMOTE_ADDR
+               return ($tmp[0] != 'unknown' ? $tmp[0] : $_SERVER['REMOTE_ADDR']);
+       }
+       return $_SERVER['REMOTE_ADDR'];
+}
+
+/*css style sheet */
+function format_js_var($var_name){
+       return("'".$var_name."'");
+}
+
+# Identifies APNGs
+# Written by Coda, functionified by Foone/Popcorn Mariachi#!9i78bPeIxI
+# This code is in the public domain
+# identify_apng returns:
+# true if the file is an APNG
+# false if it is any other sort of file (it is not checked for PNG validity)
+# takes on argument, a filename.
+/* APNG */
+function identify_apng($filename){
+       global $apng;
+       $img_bytes = file_get_contents($filename);
+       if($img_bytes){
+               if(strpos(substr($img_bytes, 0, strpos($img_bytes, 'IDAT')), 'acTL') !== false){
+                       return $apng = TRUE; // APNG
+               }
+       }
+       return $apng = FALSE; // not APNG
+}
+
+/* total amount of ommited posts/images */
+function _res($posts, $images=0){
+       $omitp = ($posts) ? sp(_T('notice_omitted_posts'), $posts) : false;
+       $omiti = ($images) ? sp(_T('notice_omitted_images'), $images) : false;
+       return($omitp.$omiti);
+}
+/* plural strings for ommited post messages */
+function sp($string, $value, $shownull = false){
+       // Determine whether to show string for zero values
+       if(!$value && $shownull || $value) $show = true;
+       elseif(!$value && !$shownull) $show = false;
+       else $show = $shownull;
+
+       if($show) $string = str_replace('[#]', number_format($value), $string);
+       else return(false);
+
+       // Separate words from plural forms
+       ereg('(.*)(\[)(.*)(\])(.*)', $string, $regs);
+       $plu_word_s = $regs[1];
+       $plu_bits = $regs[3];
+       $plu_word_e = $regs[5];
+
+       if(strstr($plu_bits, '|')){
+               // To the left of the | is the single form; to the right, the plural form
+               ereg('(.*)(\|)(.*)', $plu_bits, $regs);
+               $single = $regs[1];
+               $plural = $regs[3];
+       }else{
+               // [|s] will work for words that should end in "s", but this bit handles [s]
+               $single = '';
+               $plural = $plu_bits;
+       }
+
+       // Spit it out, Smith
+       $plu_bit_d = ($value == -1 || $value == 1)?$single:$plural;
+       $plu_word = $plu_word_s.$plu_bit_d.$plu_word_e;
+
+       if($plu_word) return($plu_word); else return($string);
+}
+
+/* comment too long function */
+// truncate $str to $max_lines lines and return $str and $abbr
+// where $abbr = whether or not $str was actually truncated
+function abbreviate($str, $max_lines){
+       if(!defined('MAX_LINES')){
+               if(defined('BR_CHECK')) define('MAX_LINES', BR_CHECK);
+               else define('MAX_LINES', 24);
+
+               $max_lines = MAX_LINES;
+       }
+       $lines = explode("<br />", $str);
+       if(count($lines) > $max_lines){
+               $abbr = 1;
+               $lines = array_slice($lines, 0, $max_lines);
+               $str = implode("<br />", $lines);
+       }else $abbr = 0;
+       //close spans after abbreviating
+       //XXX will not work with more html - use abbreviate_html from shiichan
+       $str .= str_repeat("</span>", substr_count($str, "<span") - substr_count($str, "</span"));
+       return array($str, $abbr);
+}
+?>
\ No newline at end of file
diff --git a/lib/lib_fileio.php b/lib/lib_fileio.php
new file mode 100755 (executable)
index 0000000..c402f2a
--- /dev/null
@@ -0,0 +1,33 @@
+<?php\r
+/*\r
+FileIO - Pixmicat! File I/O\r
+FileIO Kernel Switcher\r
+*/\r
+\r
+// 引入必要函式庫\r
+$fileio_file = PHP_DIRECTORY.'lib/fileio/fileio.'.FILEIO_BACKEND.'.php'; // FileIO Backend\r
+if(is_file($fileio_file)) include_once($fileio_file);\r
+\r
+// 擴充物件\r
+class FileIOWrapper extends FileIO{\r
+       var $absoluteURL; // 伺服器絕對位置\r
+       function _getAbsoluteURL(){\r
+               return 'http://'.$_SERVER['HTTP_HOST'].substr($_SERVER['PHP_SELF'], 0, strpos($_SERVER['PHP_SELF'], PHP_SELF));\r
+       }\r
+       function getImageLocalURL($imgname){\r
+               if(!isset($this->absoluteURL)) $this->absoluteURL = $this->_getAbsoluteURL();\r
+\r
+               return $this->absoluteURL.(substr($imgname, -5)=='s.jpg' ? THUMB_DIR : IMG_DIR).$imgname;\r
+       }\r
+}\r
+\r
+$FileIOEnv = array( // FileIO 環境常數\r
+       'IFS.PATH' => PHP_DIRECTORY.'lib/fileio/ifs.php',\r
+       'IFS.LOG' => FILEIO_INDEXLOG,\r
+       'PATH' => realpath('.').DIRECTORY_SEPARATOR,\r
+       'IMG' => IMG_DIR,\r
+       'THUMB' => THUMB_DIR\r
+);\r
+\r
+$FileIO = new FileIOWrapper(unserialize(FILEIO_PARAMETER), $FileIOEnv); // FileIO 物件\r
+?>
\ No newline at end of file
diff --git a/lib/lib_language.php b/lib/lib_language.php
new file mode 100755 (executable)
index 0000000..9c307ad
--- /dev/null
@@ -0,0 +1,35 @@
+<?php\r
+/*\r
+Pixmicat! Language module loader\r
+*/\r
+$langloaded = false; // Is language file loaded?\r
+\r
+function _T(/*$arg1, $arg2...$argN*/) {\r
+       global $language,$langloaded;\r
+       if (!$langloaded){ // language file is not loaded\r
+               LoadLanguage(PIXMICAT_LANGUAGE); $langloaded = true;\r
+       }\r
+       if (!func_num_args()) // called with no arg\r
+               return '';\r
+       $arg_list = func_get_args();\r
+       $arg_list[0] = isset($language[$arg_list[0]]) ? $language[$arg_list[0]] : $arg_list[0];\r
+       return call_user_func_array('sprintf',$arg_list);\r
+}\r
+\r
+function LoadLanguage($locale = 'en_US') {\r
+       global $language;\r
+       if(!defined('PIXMICAT_LANGUAGE') || defined('PIXMICAT_LANGUAGE_OVERLOADING')) // language overloading\r
+               include_once(PHP_DIRECTORY."lib/lang/en_US.php");\r
+       if (file_exists(PHP_DIRECTORY."lib/lang/$locale.php"))\r
+               include_once(PHP_DIRECTORY."lib/lang/$locale.php");\r
+       else\r
+               include_once(PHP_DIRECTORY."lib/lang/en_US.php");\r
+}\r
+function AttachLanguage($fcall){\r
+       global $language,$langloaded;\r
+       if (!$langloaded){ // language file is not loaded\r
+               LoadLanguage(PIXMICAT_LANGUAGE); $langloaded = true;\r
+       }\r
+       call_user_func($fcall);\r
+}\r
+?>
\ No newline at end of file
diff --git a/lib/lib_pio.cond.php b/lib/lib_pio.cond.php
new file mode 100755 (executable)
index 0000000..e836cd1
--- /dev/null
@@ -0,0 +1,75 @@
+<?php\r
+/**\r
+ * PIO Condition Object\r
+ *\r
+ * 判斷文章是否符合刪除條件並列出刪除編號\r
+ * \r
+ * @package PMCLibrary\r
+ * @version $Id: lib_pio.cond.php 578 2008-01-13 03:51:18Z roytam1 $\r
+ * @date $Date: 2008-01-13 11:51:18 +0800 (星期日, 13 一月 2008) $\r
+ */\r
+\r
+/* 以總文章篇數作為刪除判斷 */\r
+class ByPostCountCondition{\r
+       /*public static */function check($type, $limit){\r
+               global $PIO;\r
+               return $PIO->postCount() >= $limit * ($type=='predict' ? 0.95 : 1);\r
+       }\r
+\r
+       /*public static */function listee($type, $limit){\r
+               global $PIO;\r
+               return $PIO->fetchPostList(0, intval($limit * ($type=='predict' ? 0.95 : 1)) - 1, $limit);\r
+       }\r
+\r
+       /*public static */function info($limit){\r
+               global $PIO;\r
+               return "ByPostCountCondition: ".($pcnt=$PIO->postCount()).'/'.$limit.sprintf(' (%.2f%%)',($pcnt/$limit*100));\r
+       }\r
+}\r
+\r
+/* 以總討論串數作為刪除判斷 */\r
+class ByThreadCountCondition{\r
+       /*public static */function check($type, $limit){\r
+               global $PIO;\r
+               return $PIO->threadCount() >= ($type=='predict' ? $limit * 0.95 : 1);\r
+       }\r
+\r
+       /*public static */function listee($type, $limit){\r
+               global $PIO;\r
+               return $PIO->fetchThreadList(intval($limit * ($type=='predict' ? 0.95 : 1)), $limit);\r
+       }\r
+\r
+       /*public static */function info($limit){\r
+               global $PIO;\r
+               return "ByThreadCountCondition: ".($tcnt=$PIO->threadCount()).'/'.$limit.sprintf(' (%.2f%%)',($tcnt/$limit*100));\r
+       }\r
+}\r
+\r
+/* 以討論串生存時間作為刪除判斷 */\r
+class ByThreadAliveTimeCondition{\r
+       /*public static */function check($type, $limit){\r
+               global $PIO;\r
+               $oldestThreadNo = $PIO->fetchThreadList($PIO->threadCount() - 1, 1, true); // 最舊討論串編號\r
+               $oldestThread = $PIO->fetchPosts($oldestThreadNo);\r
+               return (time() - substr($oldestThread[0]['tim'], 0, 10) >= 86400 * $limit * ($type=='predict' ? 0.95 : 1));\r
+       }\r
+\r
+       /*public static */function listee($type, $limit){\r
+               global $PIO;\r
+               $ThreadNo = $PIO->fetchThreadList(0, 0, true); sort($ThreadNo); // 討論串編號陣列 (由舊到新)\r
+               $NowTime = time();\r
+               $i = 0;\r
+               foreach($ThreadNo as $t){\r
+                       $post = $PIO->fetchPosts($t);\r
+                       if($NowTime - substr($post[0]['tim'], 0, 10) < 86400 * $limit * ($type=='predict' ? 0.95 : 1)) break; // 時間不符合\r
+                       $i++;\r
+               }\r
+               if(count($ThreadNo)===$i){ $i--; } // 保留最新的一篇避免全部刪除\r
+               return array_slice($ThreadNo, 0, $i);\r
+       }\r
+\r
+       /*public static */function info($limit){\r
+               return "ByThreadAliveTimeCondition: ".$limit.' day(s)';\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/lib/lib_pio.php b/lib/lib_pio.php
new file mode 100755 (executable)
index 0000000..5ce78db
--- /dev/null
@@ -0,0 +1,140 @@
+<?php\r
+/*\r
+PIO - Pixmicat! data source I/O\r
+*/\r
+\r
+// 協助設定 status 旗標的類別\r
+class FlagHelper{\r
+       var $_status;\r
+\r
+       function FlagHelper($status=''){\r
+               $this->_write($status);\r
+       }\r
+\r
+       function _write($status=''){\r
+               $this->_status = $status;\r
+       }\r
+\r
+       function toString(){\r
+               return $this->_status;\r
+       }\r
+\r
+       function get($flag){\r
+               $result = preg_match('/_('.$flag.'(\:(.*))*)_/U', $this->toString(), $match);\r
+               return $result ? $match[1] : false;\r
+       }\r
+\r
+       function exists($flag){\r
+               return $this->get($flag) !== false;\r
+       }\r
+\r
+       function value($flag){\r
+               $wholeflag = $this->get($flag);\r
+               if($scount = substr_count($wholeflag, ':')){\r
+                       $wholeflag = preg_replace('/^'.$flag.'\:/', '', $wholeflag);\r
+                       return ($scount > 1 ? explode(':', $wholeflag) : $wholeflag);\r
+               }else return $wholeflag !== false;\r
+       }\r
+\r
+       function add($flag, $value=null){\r
+               return $this->update($flag, $value);\r
+       }\r
+\r
+       function update($flag, $value=null){\r
+               if($value===null){\r
+                       $ifexist = $this->get($flag);\r
+                       if($ifexist !== $flag) $this->_write($this->toString()."_${flag}_");\r
+               }else{\r
+                       if(is_array($value)) $value = $this->join($value); // Array Flatten\r
+                       $ifexist = $this->get($flag);\r
+                       if($ifexist !== $flag.':'.$value){\r
+                               if($ifexist) $this->_write($this->replace($ifexist, "$flag:$value")); // 已立flag,不同值\r
+                               else $this->_write($this->toString()."_$flag:${value}_"); // 無flag\r
+                       }\r
+               }\r
+               return $this;\r
+       }\r
+\r
+       function replace($from, $to){\r
+               return str_replace("_${from}_", "_${to}_", $this->toString());\r
+       }\r
+\r
+       function remove($flag){\r
+               $wholeflag = $this->get($flag);\r
+               $this->_write(str_replace("_${wholeflag}_", '', $this->toString()));\r
+               return $this;\r
+       }\r
+\r
+       function toggle($flag){\r
+               return ($this->get($flag) ? $this->remove($flag) : $this->add($flag));\r
+       }\r
+\r
+       function offsetValue($flag, $d=0){\r
+               $v = intval($this->value($flag));\r
+               return $this->update($flag, $v + $d);\r
+       }\r
+\r
+       function plus($flag){ return $this->offsetValue($flag, 1); }\r
+       function minus($flag){ return $this->offsetValue($flag, -1); }\r
+\r
+       function join(){\r
+               $arg = func_get_args();\r
+               $newval = array();\r
+               foreach($arg as $a){\r
+                       if(is_array($a)) array_push($newval, implode(':', $a));\r
+                       else array_push($newval, $a);\r
+               }\r
+               return implode(':', $newval);\r
+       }\r
+}\r
+\r
+// 文章自動刪除機制\r
+include(PHP_DIRECTORY.'lib/lib_pio.cond.php');\r
+class PIOSensor{\r
+       /*public static */function check($type, $condobj){\r
+               foreach($condobj as $i => $j){\r
+                       // 有其中一個需要處理\r
+                       if(call_user_func_array(array($i, 'check'), array($type, $j))===true) return true;\r
+               }\r
+               return false;\r
+       }\r
+\r
+       /*public static */function listee($type, $condobj){\r
+               $tmparray = array(); // 項目陣列\r
+               foreach($condobj as $i => $j){\r
+                       // 結果併進 $tmparray\r
+                       $tmparray = array_merge($tmparray, call_user_func_array(array($i, 'listee'), array($type, $j)));\r
+               }\r
+               sort($tmparray); // 由舊排到新 (小到大)\r
+               return array_unique($tmparray);\r
+       }\r
+\r
+       /*public static */function info($condobj){\r
+               $sensorinfo='';\r
+               foreach($condobj as $i => $j){\r
+                       $sensorinfo .= call_user_func_array(array($i, 'info'), array($j))."\n";\r
+               }\r
+               return $sensorinfo;\r
+       }\r
+}\r
+\r
+// 分析連線字串\r
+if(preg_match('/^(.*):\/\//i', CONNECTION_STRING, $backend)) define('PIXMICAT_BACKEND', $backend[1]);\r
+\r
+// 引入必要函式庫\r
+$pio_file = PHP_DIRECTORY.'lib/pio/pio.'.PIXMICAT_BACKEND.'.php';\r
+$PIOEnv = array( // PIO 環境常數\r
+       'BOARD' => '.',\r
+       'LUTCACHE' => './'.LUT_CACHE,\r
+       'NONAME' => DEFAULT_NONAME,\r
+       'NOTITLE' => DEFAULT_NOTITLE,\r
+       'NOCOMMENT' => DEFAULT_NOCOMMENT,\r
+       'PERIOD.POST' => RENZOKU,\r
+       'PERIOD.IMAGEPOST' => RENZOKU2\r
+);\r
+if(is_file($pio_file)) include_once($pio_file);\r
+\r
+// PIO Kernel Switcher\r
+$pioSwitch = 'PIO'.PIXMICAT_BACKEND;\r
+$PIO = new $pioSwitch(CONNECTION_STRING, $PIOEnv);\r
+?>
\ No newline at end of file
diff --git a/lib/lib_pms.php b/lib/lib_pms.php
new file mode 100755 (executable)
index 0000000..1dfa116
--- /dev/null
@@ -0,0 +1,19 @@
+<?php\r
+/**\r
+ * Pixmicat! Module System Dispatcher\r
+ *\r
+ * 設定環境變數並初始化物件以供使用\r
+ * \r
+ * @package PMCLibrary\r
+ * @version $Id: lib_pms.php 468 2007-07-09 09:07:39Z scribe $\r
+ * @date $Date: 2007-07-09 17:07:39 +0800 (星期一, 09 七月 2007) $\r
+ */\r
+\r
+$PMSEnv = array( // PMS 環境常數\r
+       'MODULE.PATH' => PHP_DIRECTORY.'module/',\r
+       'MODULE.PAGE' => PHP_SELF.'?mode=module&amp;load=',\r
+       'MODULE.LOADLIST' => $ModuleList\r
+);\r
+require(PHP_DIRECTORY.'lib/pms.php');\r
+$PMS = new PMS($PMSEnv);\r
+?>
\ No newline at end of file
diff --git a/lib/lib_pte.php b/lib/lib_pte.php
new file mode 100755 (executable)
index 0000000..f41ac32
--- /dev/null
@@ -0,0 +1,86 @@
+<?php\r
+/*\r
+Pixmicat! Template-Embedded Library v070618\r
+by: scribe & RT\r
+Copyright(C) 2005-2007 Pixmicat! Development Team\r
+\r
+Pixmicat! Template-Embedded Library (PTE) is released under The Clarified \r
+Artistic License.\r
+A more detailed definition of the terms please refer to the attached "LICENSE" \r
+file. If you do not receive the program with The Artistic License copy, please \r
+visit http://pixmicat.openfoundry.org/license/ to obtain a copy.\r
+\r
+$Id: lib_pte.php 438 2007-06-18 13:59:13Z roytam1 $\r
+*/\r
+\r
+class PTELibrary{\r
+       var $tpl_block, $tpl;\r
+\r
+       /* 開啟樣板檔案並取出區塊 */\r
+       function PTELibrary($tplname){\r
+               $this->tpl_block = array();\r
+               $this->tpl = file_get_contents($tplname);\r
+       }\r
+\r
+       /* 回傳區塊樣板碼並快取 */\r
+       function _readBlock($blockName){\r
+               if(!isset($this->tpl_block[$blockName])){ // 是否找過\r
+                       if(preg_match('/<!--&'.$blockName.'-->(.*)<!--\/&'.$blockName.'-->/smU', $this->tpl, $matches))\r
+                               $this->tpl_block[$blockName] = $matches[1]; // 找到了存入陣列快取\r
+                       else\r
+                               $this->tpl_block[$blockName] = false; // 找過但沒找到\r
+               }\r
+               return $this->tpl_block[$blockName];\r
+       }\r
+\r
+       /* 回傳去除前後空格的區塊樣板碼 */\r
+       function BlockValue($blockName){\r
+               return trim($this->_readBlock($blockName));\r
+       }\r
+\r
+       /* 將樣版的標籤取代為正確的字串並傳回 */\r
+       function ParseBlock($blockName, $ary_val){\r
+               if(($tmp_block = $this->_readBlock($blockName))===false) return ""; // 找無\r
+               $tmp_block = $this->EvalFOREACH($tmp_block, $ary_val); // 解析FOREACH敘述\r
+               $tmp_block = $this->EvalIF($tmp_block, $ary_val); // 解析IF敘述\r
+               $tmp_block = $this->EvalInclude($tmp_block, $ary_val); // 解析引用\r
+               return @str_replace(@array_keys($ary_val), @array_values($ary_val), $tmp_block);\r
+       }\r
+\r
+       /* 解析IF敘述 */\r
+       function EvalIF($tpl, $ary){\r
+               $tmp_tpl = $tpl;\r
+               if(preg_match_all('/<!--&IF\(([\$&].*),\'(.*)\',\'(.*)\'\)-->/smU', $tmp_tpl, $matches, PREG_SET_ORDER)){\r
+                       foreach($matches as $submatches){\r
+                               $isblock = substr($submatches[1],0,1) == "&"; $vari = substr($submatches[1],1); $iftrue = $submatches[2]; $iffalse = $submatches[3];\r
+                               $tmp_tpl = @str_replace($submatches[0], (($isblock ? $this->BlockValue($vari) : ($ary['{$'.$vari.'}'] !== '' && $ary['{$'.$vari.'}'] !== false && $ary['{$'.$vari.'}'] !== null)) ? $this->EvalInclude($iftrue, $ary) : $this->EvalInclude($iffalse, $ary)), $tmp_tpl);\r
+                       }\r
+               }\r
+               return $tmp_tpl;\r
+       }\r
+       /* 解析FOREACH敘述 */\r
+       function EvalFOREACH($tpl, $ary){\r
+               $tmp_tpl = $tpl;\r
+               if(preg_match_all('/<!--&FOREACH\((\$.*),\'(.*)\'\)-->/smU', $tmp_tpl, $matches, PREG_SET_ORDER)){\r
+                       foreach($matches as $submatches){\r
+                               $vari = $submatches[1]; $block = $submatches[2];\r
+                               \r
+                               $foreach_tmp = '';\r
+                               if(isset($ary['{'.$vari.'}']) && is_array($ary['{'.$vari.'}']))\r
+                                       foreach($ary['{'.$vari.'}'] as $eachvar)\r
+                                               $foreach_tmp .= $this->ParseBlock($block, $eachvar);\r
+                               $tmp_tpl = @str_replace($submatches[0], $foreach_tmp, $tmp_tpl);\r
+                       }\r
+               }\r
+               return $tmp_tpl;\r
+       }\r
+       /* 解析區塊引用 */\r
+       function EvalInclude($tpl, $ary){\r
+               $tmp_tpl = $tpl;\r
+               if(preg_match_all('/<!--&(.*)\/-->/smU', $tmp_tpl, $matches, PREG_SET_ORDER))\r
+                       foreach($matches as $submatches)\r
+                               $tmp_tpl = str_replace($submatches[0], $this->ParseBlock($submatches[1], $ary), $tmp_tpl);\r
+               return $tmp_tpl;\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/lib/pio/pio.log.php b/lib/pio/pio.log.php
new file mode 100755 (executable)
index 0000000..5945871
--- /dev/null
@@ -0,0 +1,539 @@
+<?php\r
+/**\r
+ * PIO Log API\r
+ *\r
+ * 提供存取以 Log 檔案構成的資料結構後端的物件\r
+ *
+ * @package PMCLibrary\r
+ * @version $Id: pio.log.php 671 2008-09-20 05:54:15Z scribe $\r
+ * @date $Date: 2008-09-20 13:54:15 +0800 (星期六, 20 九月 2008) $
+ *
+ * @package PMCLibrary\r
+ * @version $Id$\r
+ * @date $Date$\r
+ */\r
+\r
+class PIOlog{\r
+       var $ENV, $logfile, $treefile, $porderfile; // Local Constant\r
+       var $logs, $trees, $LUT, $porder, $torder, $prepared; // Local Global\r
+       //var $memcached, $mid;\r
+\r
+       /* private 設定 memcached 資料\r
+       function _memcacheSet($isAnalysis=true){\r
+               if(!$this->_memcachedEstablish()) return false;\r
+               $this->memcached->set('pmc'.$this->mid.'_isset', true);\r
+               // 是否需要將每行資料分析為陣列\r
+               $this->memcached->set('pmc'.$this->mid.'_logs', ($isAnalysis ? array_map(array($this, '_AnalysisLogs'), $this->logs) : $this->logs));\r
+               $this->memcached->set('pmc'.$this->mid.'_trees', $this->trees);\r
+               $this->memcached->set('pmc'.$this->mid.'_LUT', $this->LUT);\r
+               $this->memcached->set('pmc'.$this->mid.'_porder', $this->porder);\r
+               $this->memcached->set('pmc'.$this->mid.'_torder', $this->torder);\r
+       }\r
+\r
+       /* private 取得 memcached 資料\r
+       function _memcacheGet(){\r
+               if(!$this->_memcachedEstablish()) return false;\r
+               if($this->memcached->get('pmc'.$this->mid.'_isset')){ // 有資料\r
+                       $this->logs = $this->memcached->get('pmc'.$this->mid.'_logs');\r
+                       $this->trees = $this->memcached->get('pmc'.$this->mid.'_trees');\r
+                       $this->LUT = $this->memcached->get('pmc'.$this->mid.'_LUT');\r
+                       $this->porder = $this->memcached->get('pmc'.$this->mid.'_porder');\r
+                       $this->torder = $this->memcached->get('pmc'.$this->mid.'_torder');\r
+                       return true;\r
+               }else return false;\r
+       }\r
+\r
+       /* private 建立 memcached 實體\r
+       function _memcachedEstablish(){\r
+               if(!extension_loaded('memcache')) return ($this->memcached = false);\r
+               if(is_null($this->memcached)){\r
+                       $this->memcached = new Memcache;\r
+                       if(!$this->memcached->pconnect('localhost')) return ($this->memcached = false);\r
+                       return true;\r
+               }\r
+               return ($this->memcached===false) ? false : true;\r
+       }*/\r
+\r
+       function PIOlog($connstr='', $ENV){\r
+               $this->ENV = $ENV;\r
+               $this->logs = $this->trees = $this->LUT = $this->porder = $this->torder = array();\r
+               $this->prepared = 0;\r
+               //$this->mid = md5($_SERVER['SCRIPT_FILENAME']); // Unique ID\r
+               //$this->memcached = false; // memcached object (null: use, false: don't use)\r
+\r
+               if($connstr) $this->dbConnect($connstr);\r
+       }\r
+\r
+       /* private 把每一行 Log 解析轉換成陣列資料 */\r
+       function _AnalysisLogs($line){\r
+               $tline = array();\r
+               list($tline['no'], $tline['resto'], $tline['md5chksum'], $tline['category'], $tline['tim'], $tline['ext'], $tline['imgw'], $tline['imgh'], $tline['imgsize'], $tline['filename'], $tline['tw'], $tline['th'], $tline['pwd'], $tline['now'], $tline['name'], $tline['email'], $tline['sub'], $tline['com'], $tline['host'], $tline['status']) = explode(',', $line);\r
+               return array_reverse($tline); // list()是由右至左代入的\r
+       }\r
+\r
+       /* private 將回文放進陣列 */\r
+       function _includeReplies($posts){\r
+               $torder_flip = array_flip($this->torder);\r
+               foreach($posts as $post){\r
+                       if(array_key_exists($post, $torder_flip)){ // 討論串首篇\r
+                               $posts = array_merge($posts, $this->trees[$post]);\r
+                       }\r
+               }\r
+               return array_merge(array(), array_unique($posts)); // 去除重複值\r
+       }\r
+\r
+       /* private 取代 , 成為 &#44; 避免衝突 */\r
+       function _replaceComma($txt){\r
+               return str_replace(',', '&#44;', $txt);\r
+       }\r
+\r
+       /* private 由編號取出資料分析成陣列 */\r
+       function _ArrangeArrayStructure($line){\r
+               $line = (array)$line; // 全部視為Arrays\r
+               $posts = array();\r
+               foreach($line as $i){\r
+                       if(!isset($this->LUT[$i])) continue;\r
+                       if(!is_array($this->logs[$this->LUT[$i]])){ // 進行分析轉換\r
+                               $line = $this->logs[$this->LUT[$i]]; if($line=='') continue;\r
+                               $this->logs[$this->LUT[$i]] = $this->_AnalysisLogs($line);\r
+                       }\r
+                       $posts[] = $this->logs[$this->LUT[$i]];\r
+               }\r
+               return $posts;\r
+       }\r
+\r
+       /* PIO模組版本 */\r
+       function pioVersion(){\r
+               return '0.6 (v20100404)';\r
+       }\r
+\r
+       /* 處理連線字串/連接 */\r
+       function dbConnect($connStr){\r
+               if(preg_match('/^log:\/\/(.*)\:(.*)\/$/i', $connStr, $linkinfos)){\r
+                       $this->logfile = $this->ENV['BOARD'].'/'.$linkinfos[1]; // 投稿文字記錄檔檔名\r
+                       $this->treefile = $this->ENV['BOARD'].'/'.$linkinfos[2]; // 樹狀結構記錄檔檔名\r
+                       $this->porderfile = $this->ENV['LUTCACHE']; // LUT索引查找表暫存檔案\r
+               }\r
+       }\r
+\r
+       /* 初始化 */\r
+       function dbInit(){\r
+               $chkfile = array($this->logfile, $this->treefile, $this->porderfile);\r
+               // 自動建置\r
+               foreach($chkfile as $value){\r
+                       if(!is_file($value)){ // 檔案不存在\r
+                               $fp = fopen($value, 'w');\r
+                               stream_set_write_buffer($fp, 0);\r
+                               if($value==$this->logfile) fwrite($fp, '0,0,,,0,,0,0,,,0,0,,08/11/08(土) 10:24:04,【スパーキー(④ ^ヮ^)】,,'.$this->ENV['NOTITLE'].','.$this->ENV['NOCOMMENT'].',,,'); // PIO Structure V4\r
+                               if($value==$this->treefile) fwrite($fp, '0');\r
+                               if($value==$this->porderfile) fwrite($fp, '0');\r
+                               fclose($fp);\r
+                               unset($fp);\r
+                               @chmod($value, 0666);\r
+                       }\r
+               }\r
+               return true;\r
+       }\r
+\r
+       /* 準備/讀入 */\r
+       function dbPrepare($reload=false, $transaction=true){\r
+               if($this->prepared && !$reload) return true;\r
+               if($reload && $this->prepared) $this->porder = $this->torder = $this->LUT = $this->logs = $this->trees = array();\r
+               //if($this->_memcacheGet()){ $this->prepared = 1; return true; } // 如果 memcache 有快取則直接使用\r\r
+               $this->logs = file($this->logfile); // Log每行原始資料\r
+               if(!file_exists($this->porderfile)){ // LUT不在,重生成\r
+                       $lut = '';\r
+                       foreach($this->logs as $line){\r
+                               if(!isset($line)) continue;\r
+                               $tmp = explode(',', $line); $lut .= $tmp[0]."\r\n";\r
+                       }\r
+                       $fp = fopen($this->porderfile, 'w'); // LUT\r
+                       stream_set_write_buffer($fp, 0);\r
+                       flock($fp, LOCK_EX); // 鎖定檔案\r
+                       fwrite($fp, $lut);\r
+                       flock($fp, LOCK_UN); // 解鎖\r
+                       fclose($fp);\r
+               }\r
+               $this->porder = array_map('rtrim', file($this->porderfile)); // 文章編號陣列\r
+               $this->LUT = array_flip($this->porder); // LUT索引查找表\r
+\r
+               $tree = array_map('rtrim', file($this->treefile));\r
+               foreach($tree as $treeline){ // 解析樹狀結構製成索引\r
+                       if($treeline=='') continue;
+                       if($treeline==0) break;\r
+                       $tline = explode(',', $treeline);\r
+                       $this->torder[] = $tline[0]; // 討論串首篇編號陣列\r
+                       $this->trees[$tline[0]] = $tline; // 特定編號討論串完整結構陣列\r
+               }\r
+               //$this->_memcacheSet(); // 把目前資料設定到 memcached 內\r
+               $this->prepared = 1;\r
+       }\r
+\r
+       /* 提交/儲存 */\r
+       function dbCommit(){\r
+               if(!$this->prepared) return false;\r
+\r
+               $log = $tree = $lut = '';\r
+               $this->logs = array_merge(array(), $this->logs); // 更新logs鍵值\r
+               $this->torder = array_merge(array(), $this->torder); // 更新torder鍵值\r
+               $this->porder = $this->LUT = array(); // 重新生成索引\r
+\r
+               foreach($this->logs as $line){\r
+                       if(!isset($line)) continue;\r
+                       if(is_array($line)){ // 已被分析過\r
+                               $log .= implode(',', $line).",\r\n";\r
+                               $lut .= ($this->porder[] = $line['no'])."\r\n";\r
+                       }else{ // 尚未分析過\r
+                               $log .= $line;\r
+                               $tmp = explode(',', $line); $lut .= ($this->porder[] = $tmp[0])."\r\n";\r
+                       }\r
+               }\r
+               $this->LUT = array_flip($this->porder);\r
+               $tcount = count($this->trees);\r
+               for($tline = 0; $tline < $tcount; $tline++){\r
+                       $tree .= $this->isThread($this->torder[$tline]) ? implode(',', $this->trees[$this->torder[$tline]])."\r\n" : '';\r
+               }\r
+               //$this->_memcacheSet(false); // 更新快取 (不需要再分析)\r
+\r
+               $fp = fopen($this->logfile, 'w'); // Log\r
+               stream_set_write_buffer($fp, 0);\r
+               flock($fp, LOCK_EX); // 鎖定檔案\r
+               fwrite($fp, $log);\r
+               flock($fp, LOCK_UN); // 解鎖\r
+               fclose($fp);\r
+\r
+               $fp = fopen($this->treefile, 'w'); // tree\r
+               stream_set_write_buffer($fp, 0);\r
+               flock($fp, LOCK_EX); // 鎖定檔案\r
+               fwrite($fp, $tree);\r
+               flock($fp, LOCK_UN); // 解鎖\r
+               fclose($fp);\r
+\r
+               $fp = fopen($this->porderfile, 'w'); // LUT\r
+               stream_set_write_buffer($fp, 0);\r
+               flock($fp, LOCK_EX); // 鎖定檔案\r
+               fwrite($fp, $lut);\r
+               flock($fp, LOCK_UN); // 解鎖\r
+               fclose($fp);\r
+       }\r
+\r
+       /* 資料表維護 */\r
+       function dbMaintanence($action,$doit=false){\r
+               switch($action) {\r
+                       case 'export':\r
+                               if($doit){\r
+                                       $this->dbPrepare(false);\r
+                                       $gp = gzopen('piodata.log.gz', 'w9');\r
+                                       gzwrite($gp, $this->dbExport());\r
+                                       gzclose($gp);\r
+                                       return '<a href="piodata.log.gz">下載 piodata.log.gz 中介檔案</a>';\r
+                               }else return true; // 支援匯出資料\r
+                               break;\r
+                       case 'optimize':\r
+                       case 'check':\r
+                       case 'repair':\r
+                       default: return false; // 不支援\r
+               }\r
+       }\r
+\r
+       /* 匯入資料來源 */\r
+       function dbImport($data){\r
+               $arrData = explode("\r\n", $data);\r
+               $arrData_cnt = count($arrData) - 1; // 最後一個是空的\r
+               $arrTree = array();\r
+               $tree = $logs = $lut = '';\r
+               for($i = 0; $i < $arrData_cnt; $i++){\r
+                       $line = explode(',', $arrData[$i], 4); // 切成四段\r
+                       $logs .= $line[0].','.$line[1].','.$line[3]."\r\n"; // 重建討論結構\r
+                       $lut .= $line[0]."\r\n"; // 重建 LUT 查找表結構\r
+                       if($line[1]==0){ // 首篇\r
+                               if(!isset($arrTree[$line[0]])) $arrTree[$line[0]] = array($line[0]); // 僅自身一篇\r
+                               else array_unshift($arrTree[$line[0]], $line[0]);\r
+                               continue;\r
+                       }\r
+                       if(!isset($arrTree[$line[1]])) $arrTree[$line[1]] = array();\r
+                       array_unshift($arrTree[$line[1]], $line[0]);\r
+               }\r
+               foreach($arrTree as $t) $tree .= implode(',', $t)."\r\n"; // 重建樹狀結構\r
+               $chkfile = array($this->logfile, $this->treefile, $this->porderfile);\r
+               foreach($chkfile as $value){\r
+                       $fp = fopen($value, 'w');\r
+                       stream_set_write_buffer($fp, 0);\r
+                       if($value==$this->logfile) fwrite($fp, $logs);\r
+                       if($value==$this->treefile) fwrite($fp, $tree);\r
+                       if($value==$this->porderfile) fwrite($fp, $lut);\r
+                       fclose($fp);\r
+                       unset($fp);\r
+                       @chmod($value, 0666);\r
+               }\r
+               return true;\r
+       }\r
+\r
+       /* 匯出資料來源 */\r
+       function dbExport(){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+               $f = file($this->logfile);\r
+               $data = '';\r
+               foreach($f as $line){\r
+                       $line = explode(',', $line, 3); // 分成三段 (最後一段特別長)\r
+                       if($line[1]==0 && isset($this->trees[$line[0]])){\r
+                               $lastno = array_pop($this->trees[$line[0]]);\r
+                               $line2 = $this->fetchPosts($lastno);\r
+                               $root = gmdate('Y-m-d H:i:s', substr($line2[0]['tim'], 0, 10)); // UTC 時間\r
+                               unset($this->trees[$line[0]]); // 刪除表示已取過\r
+                       }else{\r
+                               $root = '0';\r
+                       }\r
+                       $data .= $line[0].','.$line[1].','.$root.','.$line[2];\r
+               }\r
+               return $data;\r
+       }\r
+\r
+       /* 文章數目 */\r
+       function postCount($resno=0){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               return $resno ? ($this->isThread($resno) ? count(@$this->trees[$resno]) : 0) : count($this->porder);\r
+       }\r
+\r
+       /* 討論串數目 */\r
+       function threadCount(){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               return count($this->torder);\r
+       }\r
+\r
+       /* 取得最後的文章編號 */\r
+       function getLastPostNo($state){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               switch($state){\r
+                       case 'beforeCommit':\r
+                       case 'afterCommit':\r
+                               return reset($this->porder);\r
+               }\r
+       }\r
+\r
+       /* 輸出文章清單 */\r
+       function fetchPostList($resno=0, $start=0, $amount=0){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $plist = array();\r
+               if($resno){\r
+                       if($this->isThread($resno)){\r
+                               if($start && $amount){\r
+                                       $plist = array_slice($this->trees[$resno], $start, $amount);\r
+                                       array_unshift($plist, $resno);\r
+                               }\r
+                               if(!$start && $amount) $plist = array_slice($this->trees[$resno], 0, $amount);\r
+                               if(!$start && !$amount) $plist = $this->trees[$resno];\r
+                       }\r
+               }else{\r
+                       $plist = $amount ? array_slice($this->porder, $start, $amount) : $this->porder;\r
+               }\r
+               return $plist;\r
+       }\r
+\r
+       /* 輸出討論串清單 */\r
+       function fetchThreadList($start=0, $amount=0, $isDESC=false){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+               $tmp_array = $this->torder;\r
+               if($isDESC) rsort($tmp_array); // 按編號遞減排序 (預設為按最後更新時間排序)\r
+               return $amount ? array_slice($tmp_array, $start, $amount) : $tmp_array;\r
+       }\r
+\r
+       /* 輸出文章 */\r
+       function fetchPosts($postlist){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               return $this->_ArrangeArrayStructure($postlist); // 輸出陣列結構\r
+       }\r
+\r
+       /* 刪除舊附件 (輸出附件清單) */\r
+       function delOldAttachments($total_size, $storage_max, $warnOnly=true){\r
+               global $FileIO;\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $rpord = $this->porder; sort($rpord); // 由舊排到新 (小->大)\r
+               $arr_warn = $arr_kill = array();\r
+               foreach($rpord as $post){\r
+                       $logsarray = $this->_ArrangeArrayStructure($post); // 分析資料為陣列\r
+                       if($FileIO->imageExists($logsarray[0]['tim'].$logsarray[0]['ext'])){ $total_size -= $FileIO->getImageFilesize($logsarray[0]['tim'].$logsarray[0]['ext']) / 1024; $arr_kill[] = $post; $arr_warn[$post] = 1; } // 標記刪除\r
+                       if($FileIO->imageExists($logsarray[0]['tim'].'s.jpg')) $total_size -= $FileIO->getImageFilesize($logsarray[0]['tim'].'s.jpg') / 1024;\r
+                       if($total_size < $storage_max) break;\r
+               }\r
+               return $warnOnly ? $arr_warn : $this->removeAttachments($arr_kill);\r
+       }\r
+\r
+       /* 刪除文章 */\r
+       function removePosts($posts){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+               if(count($posts)==0) return array();\r
+\r
+               $posts = $this->_includeReplies($posts); // 包含所有回文\r
+               $filelist = $this->removeAttachments($posts); // 欲刪除附件\r
+               $torder_flip = array_flip($this->torder);\r
+               $pcount = count($posts);\r
+               $logsarray = $this->_ArrangeArrayStructure($posts); // 分析資料為陣列\r
+               for($p = 0; $p < $pcount; $p++){\r
+                       if(!isset($logsarray[$p])) continue;\r
+                       if($logsarray[$p]['resto']==0){ // 討論串頭\r
+                               unset($this->trees[$logsarray[$p]['no']]); // 刪除樹狀記錄\r
+                               if(array_key_exists($logsarray[$p]['no'], $torder_flip)) unset($this->torder[$torder_flip[$logsarray[$p]['no']]]); // 從討論串首篇陣列中移除\r
+                       }else{\r
+                               // 從樹狀檔刪除\r
+                               if(array_key_exists($logsarray[$p]['resto'], $this->trees)){\r
+                                       $tr_flip = array_flip($this->trees[$logsarray[$p]['resto']]);\r
+                                       unset($this->trees[$logsarray[$p]['resto']][$tr_flip[$posts[$p]]]);\r
+                               }\r
+                       }\r
+                       unset($this->logs[$this->LUT[$logsarray[$p]['no']]]);\r
+                       if(array_key_exists($logsarray[$p]['no'], $this->LUT)) unset($this->porder[$this->LUT[$logsarray[$p]['no']]]); // 從討論串編號陣列中移除\r
+               }\r
+               $this->LUT = array_flip($this->porder);\r
+               return $filelist;\r
+       }\r
+\r
+       /* 刪除附件 (輸出附件清單) */\r
+       function removeAttachments($posts){\r
+               global $FileIO;\r
+               if(!$this->prepared) $this->dbPrepare();\r
+               if(count($posts)==0) return array();\r
+\r
+               $files = array();\r
+               $logsarray = $this->_ArrangeArrayStructure($posts); // 分析資料為陣列\r
+               $lcount = count($logsarray);\r
+               for($i = 0; $i < $lcount; $i++){\r
+                       if($logsarray[$i]['ext']){\r
+                               if($FileIO->imageExists($logsarray[$i]['tim'].$logsarray[$i]['ext'])) $files[] = $logsarray[$i]['tim'].$logsarray[$i]['ext'];\r
+                               if($FileIO->imageExists($logsarray[$i]['tim'].'s.jpg')) $files[] = $logsarray[$i]['tim'].'s.jpg';\r
+                       }\r
+               }\r
+               return $files;\r
+       }\r
+\r
+       /* 新增文章/討論串 */\r
+       function addPost($no, $resto, $md5chksum, $category, $tim, $ext, $imgw, $imgh, $imgsize, $filename, $tw, $th, $pwd, $now, $name, $email, $sub, $com, $host, $age=false, $status='') {\r
+               if(!$this->prepared) $this->dbPrepare();
+\r
+               $tline = array($no, $resto, $md5chksum, $category, $tim, $ext, $imgw, $imgh, $imgsize, $filename, $tw, $th, $pwd, $now, $name, $email, $sub, $com, $host, $status);\r
+               $tline = array_map(array($this, '_replaceComma'), $tline); // 將資料內的 , 轉換 (Only Log needed)\r
+               array_unshift($this->logs, implode(',', $tline).",\r\n"); // 更新logs\r
+               array_unshift($this->porder, $no); // 更新porder\r
+               $this->LUT = array_flip($this->porder); // 更新LUT\r
+\r
+               // 更新torder及trees\r
+               if($resto){\r
+                       $this->trees[$resto][] = $no;\r
+                       if($age){\r
+                               $torder_flip = array_flip($this->torder);\r
+                               unset($this->torder[$torder_flip[$resto]]); // 先刪除舊有位置\r
+                               array_unshift($this->torder, $resto); // 再移到頂端\r
+                       }\r
+               }else{\r
+                       $this->trees[$no][0] = $no;\r
+                       array_unshift($this->torder, $no);\r
+               }\r
+       }\r
+\r
+       /* 檢查是否連續投稿 */\r
+       function isSuccessivePost($lcount, $com, $timestamp, $pass, $passcookie, $host, $isupload){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $pcount = $this->postCount();\r
+               $lcount = ($pcount > $lcount) ? $lcount : $pcount;\r
+               for($i = 0; $i < $lcount; $i++){\r
+                       $logsarray = $this->_ArrangeArrayStructure($this->porder[$i]); // 分析資料為陣列\r
+                       list($lcom, $lhost, $lpwd, $ltime) = array($logsarray[0]['com'], $logsarray[0]['host'], $logsarray[0]['pwd'], substr($logsarray[0]['tim'],0,-3));\r
+                       if($host==$lhost || $pass==$lpwd || $passcookie==$lpwd) $pchk = 1;\r
+                       else $pchk = 0;\r
+                       if($this->ENV['PERIOD.POST'] && $pchk){ // 密碼比對符合且開啟連續投稿時間限制\r
+                               if($timestamp - $ltime < $this->ENV['PERIOD.POST']) return true; // 投稿時間相距太短\r
+                               if($timestamp - $ltime < $this->ENV['PERIOD.IMAGEPOST'] && $isupload) return true; // 附加圖檔的投稿時間相距太短\r
+                               if($com == $lcom && !$isupload) return true; // 內文一樣\r
+                       }\r
+               }\r
+               return false;\r
+       }\r
+\r
+       /* 檢查是否重複貼圖 */\r
+       function isDuplicateAttachment($lcount, $md5hash){\r
+               global $FileIO;\r
+\r
+               $pcount = $this->postCount();\r
+               $lcount = ($pcount > $lcount) ? $lcount : $pcount;\r
+               for($i = 0; $i < $lcount; $i++){\r
+                       $logsarray = $this->_ArrangeArrayStructure($this->porder[$i]); // 分析資料為陣列\r
+                       if(!$logsarray[0]['md5chksum']) continue; // 無附加圖檔\r
+                       if($logsarray[0]['md5chksum']==$md5hash){\r
+                               if($FileIO->imageExists($logsarray[0]['tim'].$logsarray[0]['ext'])) return true; // 存在MD5雜湊相同的檔案\r
+                       }\r
+               }\r
+               return false;\r
+       }\r
+\r
+       /* 有此討論串? */\r
+       function isThread($no){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               return isset($this->trees[$no]);\r
+       }\r
+\r
+       /* 搜尋文章 */\r
+       function searchPost($keyword,$field,$method){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $foundPosts = array();\r
+               $keyword_cnt = count($keyword);\r
+               $pcount = $this->postCount();\r
+               for($i = 0; $i < $pcount; $i++){\r
+                       $logsarray = $this->_ArrangeArrayStructure($this->porder[$i]); // 分析資料為陣列\r
+                       $found = 0;\r
+                       foreach($keyword as $k){\r
+                               if(strpos($logsarray[0][$field], $k)!==FALSE) $found++;\r
+                               if($method=="OR" && $found) break;\r
+                       }\r
+                       if($method=="AND" && $found==$keyword_cnt) array_push($foundPosts, $logsarray[0]); // 全部都有找到 (AND交集搜尋)\r
+                       elseif($method=="OR" && $found) array_push($foundPosts, $logsarray[0]); // 有找到 (OR聯集搜尋)\r
+               }\r
+               return $foundPosts;\r
+       }\r
+\r
+       /* 搜尋類別標籤 */\r
+       function searchCategory($category){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $category = strtolower($category);\r
+               $foundPosts = array();\r
+               $pcount = $this->postCount();\r
+               for($i = 0; $i < $pcount; $i++){\r
+                       $logsarray = $this->_ArrangeArrayStructure($this->porder[$i]); // 分析資料為陣列\r
+                       if(!($ary_category = $logsarray[0]['category'])) continue;\r
+                       if(strpos(strtolower($ary_category), '&#44;'.$category.'&#44;')!==false) array_push($foundPosts, $logsarray[0]['no']); // 找到標籤,加入名單\r
+               }\r
+               return $foundPosts;\r
+       }\r
+\r
+       /* 取得文章屬性 */\r
+       function getPostStatus($status){\r
+               return new FlagHelper($status); // 回傳 FlagHelper 物件\r
+       }\r
+\r
+       /* 更新文章 */\r
+       function updatePost($no, $newValues){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $chk = array('resto', 'md5chksum', 'category', 'tim', 'ext', 'imgw', 'imgh', 'imgsize', 'filename', 'tw', 'th', 'pwd', 'now', 'name', 'email', 'sub', 'com', 'host', 'status');\r
+\r
+               $this->_ArrangeArrayStructure($no); // 將資料變成陣列\r
+               foreach($chk as $c)\r
+                       if(isset($newValues[$c]))\r
+                               $this->logs[$this->LUT[$no]][$c] = $this->_replaceComma($newValues[$c]); // 修改數值\r
+       }\r
+\r
+       /* 設定文章屬性 */\r
+       function setPostStatus($no, $newStatus){\r
+               $this->updatePost($no, array('status' => $newStatus));\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/lib/pio/pio.logflockp.php b/lib/pio/pio.logflockp.php
new file mode 100755 (executable)
index 0000000..edceff5
--- /dev/null
@@ -0,0 +1,572 @@
+<?php\r
+/**\r
+ * PIO Log API (flock+)\r
+ *\r
+ * 提供存取以 Log 檔案構成的資料結構後端的物件\r
+ *\r
+ * @package PMCLibrary\r
+ * @version $Id: pio.logflockp.php 671 2008-09-20 05:54:15Z scribe $\r
+ * @date $Date: 2008-09-20 13:54:15 +0800 (星期六, 20 九月 2008) $
+ *
+ * @package PMCLibrary\r
+ * @version $Id$\r
+ * @date $Date$\r
+ */\r
+\r
+class PIOlogflockp{\r
+       var $ENV, $logfile, $treefile, $porderfile; // Local Constant\r
+       var $logs, $trees, $LUT, $porder, $torder, $prepared; // Local Global\r
+       //var $memcached, $mid;\r
+\r
+       /* private 設定 memcached 資料\r
+       function _memcacheSet($isAnalysis=true){\r
+               if(!$this->_memcachedEstablish()) return false;\r
+               $this->memcached->set('pmc'.$this->mid.'_isset', true);\r
+               // 是否需要將每行資料分析為陣列\r
+               $this->memcached->set('pmc'.$this->mid.'_logs', ($isAnalysis ? array_map(array($this, '_AnalysisLogs'), $this->logs) : $this->logs));\r
+               $this->memcached->set('pmc'.$this->mid.'_trees', $this->trees);\r
+               $this->memcached->set('pmc'.$this->mid.'_LUT', $this->LUT);\r
+               $this->memcached->set('pmc'.$this->mid.'_porder', $this->porder);\r
+               $this->memcached->set('pmc'.$this->mid.'_torder', $this->torder);\r
+       }\r
+\r
+       /* private 取得 memcached 資料\r
+       function _memcacheGet(){\r
+               if(!$this->_memcachedEstablish()) return false;\r
+               if($this->memcached->get('pmc'.$this->mid.'_isset')){ // 有資料\r
+                       $this->logs = $this->memcached->get('pmc'.$this->mid.'_logs');\r
+                       $this->trees = $this->memcached->get('pmc'.$this->mid.'_trees');\r
+                       $this->LUT = $this->memcached->get('pmc'.$this->mid.'_LUT');\r
+                       $this->porder = $this->memcached->get('pmc'.$this->mid.'_porder');\r
+                       $this->torder = $this->memcached->get('pmc'.$this->mid.'_torder');\r
+                       return true;\r
+               }else return false;\r
+       }\r
+\r
+       /* private 建立 memcached 實體\r
+       function _memcachedEstablish(){\r
+               if(!extension_loaded('memcache')) return ($this->memcached = false);\r
+               if(is_null($this->memcached)){\r
+                       $this->memcached = new Memcache;\r
+                       if(!$this->memcached->pconnect('localhost')) return ($this->memcached = false);\r
+                       return true;\r
+               }\r
+               return ($this->memcached===false) ? false : true;\r
+       }*/\r
+\r
+       function PIOlogflockp($connstr='', $ENV){\r
+               $this->ENV = $ENV;\r
+               $this->logs = $this->trees = $this->LUT = $this->porder = $this->torder = array();\r
+               $this->prepared = 0;\r
+               //$this->mid = md5($_SERVER['SCRIPT_FILENAME']); // Unique ID\r
+               //$this->memcached = false; // memcached object (null: use, false: don't use)\r
+\r
+               if($connstr) $this->dbConnect($connstr);\r
+       }\r
+\r
+       /* private 把每一行 Log 解析轉換成陣列資料 */\r
+       function _AnalysisLogs($line){\r
+               $tline = array();\r
+               list($tline['no'], $tline['resto'], $tline['md5chksum'], $tline['category'], $tline['tim'], $tline['ext'], $tline['imgw'], $tline['imgh'], $tline['imgsize'], $tline['filename'], $tline['tw'], $tline['th'], $tline['pwd'], $tline['now'], $tline['name'], $tline['email'], $tline['sub'], $tline['com'], $tline['host'], $tline['status']) = explode(',', $line);\r
+               return array_reverse($tline); // list()是由右至左代入的\r
+       }\r
+\r
+       /* private 將回文放進陣列 */\r
+       function _includeReplies($posts){\r
+               $torder_flip = array_flip($this->torder);\r
+               foreach($posts as $post){\r
+                       if(array_key_exists($post, $torder_flip)){ // 討論串首篇\r
+                               $posts = array_merge($posts, $this->trees[$post]);\r
+                       }\r
+               }\r
+               return array_merge(array(), array_unique($posts)); // 去除重複值\r
+       }\r
+\r
+       /* private 取代 , 成為 &#44; 避免衝突 */\r
+       function _replaceComma($txt){\r
+               return str_replace(',', '&#44;', $txt);\r
+       }\r
+\r
+       /* private 由編號取出資料分析成陣列 */\r
+       function _ArrangeArrayStructure($line){\r
+               $line = (array)$line; // 全部視為Arrays\r
+               $posts = array();\r
+               foreach($line as $i){\r
+                       if(!isset($this->LUT[$i])) continue;\r
+                       if(!is_array($this->logs[$this->LUT[$i]])){ // 進行分析轉換\r
+                               $line = $this->logs[$this->LUT[$i]]; if($line=='') continue;\r
+                               $this->logs[$this->LUT[$i]] = $this->_AnalysisLogs($line);\r
+                       }\r
+                       $posts[] = $this->logs[$this->LUT[$i]];\r
+               }\r
+               return $posts;\r
+       }\r
+\r
+       /* PIO模組版本 */\r
+       function pioVersion(){\r
+               return '0.6 (v20100404)';\r
+       }\r
+\r
+       /* 處理連線字串/連接 */\r
+       function dbConnect($connStr){\r
+               if(preg_match('/^logflockp:\/\/(.*)\:(.*)\/$/i', $connStr, $linkinfos)){\r
+                       $this->logfile = $this->ENV['BOARD'].'/'.$linkinfos[1]; // 投稿文字記錄檔檔名\r
+                       $this->treefile = $this->ENV['BOARD'].'/'.$linkinfos[2]; // 樹狀結構記錄檔檔名\r
+                       $this->porderfile = $this->ENV['LUTCACHE']; // LUT索引查找表暫存檔案\r
+               }\r
+       }\r
+\r
+       /* 初始化 */\r
+       function dbInit(){\r
+               $chkfile = array($this->logfile, $this->treefile, $this->porderfile);\r
+               // 自動建置\r
+               foreach($chkfile as $value){\r
+                       if(!is_file($value)){ // 檔案不存在\r
+                               $fp = fopen($value, 'w');\r
+                               stream_set_write_buffer($fp, 0);\r
+                               if($value==$this->logfile) fwrite($fp, '0,0,,,0,,0,0,,,0,0,,08/11/08(土) 10:24:04,【スパーキー(④ ^ヮ^)】,,'.$this->ENV['NOTITLE'].','.$this->ENV['NOCOMMENT'].',,,'); // PIO Structure V4\r
+                               if($value==$this->treefile) fwrite($fp, '1');\r
+                               if($value==$this->porderfile) fwrite($fp, '1');\r
+                               fclose($fp);\r
+                               unset($fp);\r
+                               @chmod($value, 0666);\r
+                       }\r
+               }\r
+               return true;\r
+       }\r
+\r
+       /* 準備/讀入 */\r
+       function dbPrepare($reload=false, $transaction=true){\r
+               if($this->prepared && !$reload) return true;\r
+               if($reload && $this->prepared) $this->porder = $this->torder = $this->LUT = $this->logs = $this->trees = array();\r
+               //if($this->_memcacheGet()){ $this->prepared = 1; return true; } // 如果 memcache 有快取則直接使用\r
+\r
+               $this->logs = file($this->logfile); // Log每行原始資料\r
+               if(!file_exists($this->porderfile)){ // LUT不在,重生成\r
+                       $lut = '';\r
+                       foreach($this->logs as $line){\r
+                               if(!isset($line)) continue;\r
+                               $tmp = explode(',', $line); $lut .= $tmp[0]."\r\n";\r
+                       }\r
+                       $this->_lock($this->porderfile);\r
+                       $fp = fopen($this->porderfile, 'w'); // LUT\r
+                       stream_set_write_buffer($fp, 0);\r
+//                     flock($fp, LOCK_EX); // 鎖定檔案\r
+                       fwrite($fp, $lut);\r
+//                     flock($fp, LOCK_UN); // 解鎖\r
+                       fclose($fp);\r
+                       $this->_unlock($this->porderfile);\r
+               }\r
+               $this->porder = array_map('rtrim', file($this->porderfile)); // 文章編號陣列\r
+               $this->LUT = array_flip($this->porder); // LUT索引查找表\r
+\r
+               $tree = array_map('rtrim', file($this->treefile));\r
+               foreach($tree as $treeline){ // 解析樹狀結構製成索引\r
+                       if($treeline=='') continue;\r
+                       $tline = explode(',', $treeline);\r
+                       $this->torder[] = $tline[0]; // 討論串首篇編號陣列\r
+                       $this->trees[$tline[0]] = $tline; // 特定編號討論串完整結構陣列\r
+               }\r
+               //$this->_memcacheSet(); // 把目前資料設定到 memcached 內\r
+               $this->prepared = 1;\r
+       }\r
+\r
+       /* 提交/儲存 */\r
+       function dbCommit(){\r
+               if(!$this->prepared) return false;\r
+\r
+               $log = $tree = $lut = '';\r
+               $this->logs = array_merge(array(), $this->logs); // 更新logs鍵值\r
+               $this->torder = array_merge(array(), $this->torder); // 更新torder鍵值\r
+               $this->porder = $this->LUT = array(); // 重新生成索引\r
+\r
+               foreach($this->logs as $line){\r
+                       if(!isset($line)) continue;\r
+                       if(is_array($line)){ // 已被分析過\r
+                               $log .= implode(',', $line).",\r\n";\r
+                               $lut .= ($this->porder[] = $line['no'])."\r\n";\r
+                       }else{ // 尚未分析過\r
+                               $log .= $line;\r
+                               $tmp = explode(',', $line); $lut .= ($this->porder[] = $tmp[0])."\r\n";\r
+                       }\r
+               }\r
+               $this->LUT = array_flip($this->porder);\r
+               $tcount = count($this->trees);\r
+               for($tline = 0; $tline < $tcount; $tline++){\r
+                       $tree .= $this->isThread($this->torder[$tline]) ? implode(',', $this->trees[$this->torder[$tline]])."\r\n" : '';\r
+               }\r
+               //$this->_memcacheSet(false); // 更新快取 (不需要再分析)\r
+\r
+               $this->_lock($this->logfile);\r
+               $fp = fopen($this->logfile, 'w'); // Log\r
+               stream_set_write_buffer($fp, 0);\r
+//             flock($fp, LOCK_EX); // 鎖定檔案\r
+               fwrite($fp, $log);\r
+//             flock($fp, LOCK_UN); // 解鎖\r
+               fclose($fp);\r
+               $this->_unlock($this->logfile);\r
+\r
+               $this->_lock($this->treefile);\r
+               $fp = fopen($this->treefile, 'w'); // tree\r
+               stream_set_write_buffer($fp, 0);\r
+//             flock($fp, LOCK_EX); // 鎖定檔案\r
+               fwrite($fp, $tree);\r
+//             flock($fp, LOCK_UN); // 解鎖\r
+               fclose($fp);\r
+               $this->_unlock($this->treefile);\r
+\r
+               $this->_lock($this->porderfile);\r
+               $fp = fopen($this->porderfile, 'w'); // LUT\r
+               stream_set_write_buffer($fp, 0);\r
+//             flock($fp, LOCK_EX); // 鎖定檔案\r
+               fwrite($fp, $lut);\r
+//             flock($fp, LOCK_UN); // 解鎖\r
+               fclose($fp);\r
+               $this->_unlock($this->porderfile);\r
+       }\r
+\r
+       /* 資料表維護 */\r
+       function dbMaintanence($action,$doit=false){\r
+               switch($action) {\r
+                       case 'export':\r
+                               if($doit){\r
+                                       $this->dbPrepare(false);\r
+                                       $gp = gzopen('piodata.log.gz', 'w9');\r
+                                       gzwrite($gp, $this->dbExport());\r
+                                       gzclose($gp);\r
+                                       return '<a href="piodata.log.gz">下載 piodata.log.gz 中介檔案</a>';\r
+                               }else return true; // 支援匯出資料\r
+                               break;\r
+                       case 'optimize':\r
+                       case 'check':\r
+                       case 'repair':\r
+                       default: return false; // 不支援\r
+               }\r
+       }\r
+\r
+       /* 匯入資料來源 */\r
+       function dbImport($data){\r
+               $arrData = explode("\r\n", $data);\r
+               $arrData_cnt = count($arrData) - 1; // 最後一個是空的\r
+               $arrTree = array();\r
+               $tree = $logs = $lut = '';\r
+               for($i = 0; $i < $arrData_cnt; $i++){\r
+                       $line = explode(',', $arrData[$i], 4); // 切成四段\r
+                       $logs .= $line[0].','.$line[1].','.$line[3]."\r\n"; // 重建討論結構\r
+                       $lut .= $line[0]."\r\n"; // 重建 LUT 查找表結構\r
+                       if($line[1]==0){ // 首篇\r
+                               if(!isset($arrTree[$line[0]])) $arrTree[$line[0]] = array($line[0]); // 僅自身一篇\r
+                               else array_unshift($arrTree[$line[0]], $line[0]);\r
+                               continue;\r
+                       }\r
+                       if(!isset($arrTree[$line[1]])) $arrTree[$line[1]] = array();\r
+                       array_unshift($arrTree[$line[1]], $line[0]);\r
+               }\r
+               foreach($arrTree as $t) $tree .= implode(',', $t)."\r\n"; // 重建樹狀結構\r
+               $chkfile = array($this->logfile, $this->treefile, $this->porderfile);\r
+               foreach($chkfile as $value){\r
+                       $fp = fopen($value, 'w');\r
+                       stream_set_write_buffer($fp, 0);\r
+                       if($value==$this->logfile) fwrite($fp, $logs);\r
+                       if($value==$this->treefile) fwrite($fp, $tree);\r
+                       if($value==$this->porderfile) fwrite($fp, $lut);\r
+                       fclose($fp);\r
+                       unset($fp);\r
+                       @chmod($value, 0666);\r
+               }\r
+               return true;\r
+       }\r
+\r
+       /* 匯出資料來源 */\r
+       function dbExport(){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+               $f = file($this->logfile);\r
+               $data = '';\r
+               foreach($f as $line){\r
+                       $line = explode(',', $line, 3); // 分成三段 (最後一段特別長)\r
+                       if($line[1]==0 && isset($this->trees[$line[0]])){\r
+                               $lastno = array_pop($this->trees[$line[0]]);\r
+                               $line2 = $this->fetchPosts($lastno);\r
+                               $root = gmdate('Y-m-d H:i:s', substr($line2[0]['tim'], 0, 10)); // UTC 時間\r
+                               unset($this->trees[$line[0]]); // 刪除表示已取過\r
+                       }else{\r
+                               $root = '0';\r
+                       }\r
+                       $data .= $line[0].','.$line[1].','.$root.','.$line[2];\r
+               }\r
+               return $data;\r
+       }\r
+\r
+       /* 文章數目 */\r
+       function postCount($resno=0){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               return $resno ? ($this->isThread($resno) ? count(@$this->trees[$resno]) : 0) : count($this->porder);\r
+       }\r
+\r
+       /* 討論串數目 */\r
+       function threadCount(){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               return count($this->torder);\r
+       }\r
+\r
+       /* 取得最後的文章編號 */\r
+       function getLastPostNo($state){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               switch($state){\r
+                       case 'beforeCommit':\r
+                       case 'afterCommit':\r
+                               return reset($this->porder);\r
+               }\r
+       }\r
+\r
+       /* 輸出文章清單 */\r
+       function fetchPostList($resno=0, $start=0, $amount=0){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $plist = array();\r
+               if($resno){\r
+                       if($this->isThread($resno)){\r
+                               if($start && $amount){\r
+                                       $plist = array_slice($this->trees[$resno], $start, $amount);\r
+                                       array_unshift($plist, $resno);\r
+                               }\r
+                               if(!$start && $amount) $plist = array_slice($this->trees[$resno], 0, $amount);\r
+                               if(!$start && !$amount) $plist = $this->trees[$resno];\r
+                       }\r
+               }else{\r
+                       $plist = $amount ? array_slice($this->porder, $start, $amount) : $this->porder;\r
+               }\r
+               return $plist;\r
+       }\r
+\r
+       /* 輸出討論串清單 */\r
+       function fetchThreadList($start=0, $amount=0, $isDESC=false){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+               $tmp_array = $this->torder;\r
+               if($isDESC) rsort($tmp_array); // 按編號遞減排序 (預設為按最後更新時間排序)\r
+               return $amount ? array_slice($tmp_array, $start, $amount) : $tmp_array;\r
+       }\r
+\r
+       /* 輸出文章 */\r
+       function fetchPosts($postlist){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               return $this->_ArrangeArrayStructure($postlist); // 輸出陣列結構\r
+       }\r
+\r
+       /* 刪除舊附件 (輸出附件清單) */\r
+       function delOldAttachments($total_size, $storage_max, $warnOnly=true){\r
+               global $FileIO;\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $rpord = $this->porder; sort($rpord); // 由舊排到新 (小->大)\r
+               $arr_warn = $arr_kill = array();\r
+               foreach($rpord as $post){\r
+                       $logsarray = $this->_ArrangeArrayStructure($post); // 分析資料為陣列\r
+                       if($FileIO->imageExists($logsarray[0]['tim'].$logsarray[0]['ext'])){ $total_size -= $FileIO->getImageFilesize($logsarray[0]['tim'].$logsarray[0]['ext']) / 1024; $arr_kill[] = $post; $arr_warn[$post] = 1; } // 標記刪除\r
+                       if($FileIO->imageExists($logsarray[0]['tim'].'s.jpg')) $total_size -= $FileIO->getImageFilesize($logsarray[0]['tim'].'s.jpg') / 1024;\r
+                       if($total_size < $storage_max) break;\r
+               }\r
+               return $warnOnly ? $arr_warn : $this->removeAttachments($arr_kill);\r
+       }\r
+\r
+       /* 刪除文章 */\r
+       function removePosts($posts){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+               if(count($posts)==0) return array();\r
+\r
+               $posts = $this->_includeReplies($posts); // 包含所有回文\r
+               $filelist = $this->removeAttachments($posts); // 欲刪除附件\r
+               $torder_flip = array_flip($this->torder);\r
+               $pcount = count($posts);\r
+               $logsarray = $this->_ArrangeArrayStructure($posts); // 分析資料為陣列\r
+               for($p = 0; $p < $pcount; $p++){\r
+                       if(!isset($logsarray[$p])) continue;\r
+                       if($logsarray[$p]['resto']==0){ // 討論串頭\r
+                               unset($this->trees[$logsarray[$p]['no']]); // 刪除樹狀記錄\r
+                               if(array_key_exists($logsarray[$p]['no'], $torder_flip)) unset($this->torder[$torder_flip[$logsarray[$p]['no']]]); // 從討論串首篇陣列中移除\r
+                       }else{\r
+                               // 從樹狀檔刪除\r
+                               if(array_key_exists($logsarray[$p]['resto'], $this->trees)){\r
+                                       $tr_flip = array_flip($this->trees[$logsarray[$p]['resto']]);\r
+                                       unset($this->trees[$logsarray[$p]['resto']][$tr_flip[$posts[$p]]]);\r
+                               }\r
+                       }\r
+                       unset($this->logs[$this->LUT[$logsarray[$p]['no']]]);\r
+                       if(array_key_exists($logsarray[$p]['no'], $this->LUT)) unset($this->porder[$this->LUT[$logsarray[$p]['no']]]); // 從討論串編號陣列中移除\r
+               }\r
+               $this->LUT = array_flip($this->porder);\r
+               return $filelist;\r
+       }\r
+\r
+       /* 刪除附件 (輸出附件清單) */\r
+       function removeAttachments($posts){\r
+               global $FileIO;\r
+               if(!$this->prepared) $this->dbPrepare();\r
+               if(count($posts)==0) return array();\r
+\r
+               $files = array();\r
+               $logsarray = $this->_ArrangeArrayStructure($posts); // 分析資料為陣列\r
+               $lcount = count($logsarray);\r
+               for($i = 0; $i < $lcount; $i++){\r
+                       if($logsarray[$i]['ext']){\r
+                               if($FileIO->imageExists($logsarray[$i]['tim'].$logsarray[$i]['ext'])) $files[] = $logsarray[$i]['tim'].$logsarray[$i]['ext'];\r
+                               if($FileIO->imageExists($logsarray[$i]['tim'].'s.jpg')) $files[] = $logsarray[$i]['tim'].'s.jpg';\r
+                       }\r
+               }\r
+               return $files;\r
+       }\r
+\r
+       /* 新增文章/討論串 */\r
+       function addPost($no, $resto, $md5chksum, $category, $tim, $ext, $imgw, $imgh, $imgsize, $filename, $tw, $th, $pwd, $now, $name, $email, $sub, $com, $host, $age=false, $status='') {\r
+               if(!$this->prepared) $this->dbPrepare();\r
+
+               $tline = array($no, $resto, $md5chksum, $category, $tim, $ext, $imgw, $imgh, $imgsize, $filename, $tw, $th, $pwd, $now, $name, $email, $sub, $com, $host, $status);\r
+               $tline = array_map(array($this, '_replaceComma'), $tline); // 將資料內的 , 轉換 (Only Log needed)\r
+               array_unshift($this->logs, implode(',', $tline).",\r\n"); // 更新logs\r
+               array_unshift($this->porder, $no); // 更新porder\r
+               $this->LUT = array_flip($this->porder); // 更新LUT\r
+\r
+               // 更新torder及trees\r
+               if($resto){\r
+                       $this->trees[$resto][] = $no;\r
+                       if($age){\r
+                               $torder_flip = array_flip($this->torder);\r
+                               unset($this->torder[$torder_flip[$resto]]); // 先刪除舊有位置\r
+                               array_unshift($this->torder, $resto); // 再移到頂端\r
+                       }\r
+               }else{\r
+                       $this->trees[$no][0] = $no;\r
+                       array_unshift($this->torder, $no);\r
+               }\r
+       }\r
+\r
+       /* 檢查是否連續投稿 */\r
+       function isSuccessivePost($lcount, $com, $timestamp, $pass, $passcookie, $host, $isupload){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $pcount = $this->postCount();\r
+               $lcount = ($pcount > $lcount) ? $lcount : $pcount;\r
+               for($i = 0; $i < $lcount; $i++){\r
+                       $logsarray = $this->_ArrangeArrayStructure($this->porder[$i]); // 分析資料為陣列\r
+                       list($lcom, $lhost, $lpwd, $ltime) = array($logsarray[0]['com'], $logsarray[0]['host'], $logsarray[0]['pwd'], substr($logsarray[0]['tim'],0,-3));\r
+                       if($host==$lhost || $pass==$lpwd || $passcookie==$lpwd) $pchk = 1;\r
+                       else $pchk = 0;\r
+                       if($this->ENV['PERIOD.POST'] && $pchk){ // 密碼比對符合且開啟連續投稿時間限制\r
+                               if($timestamp - $ltime < $this->ENV['PERIOD.POST']) return true; // 投稿時間相距太短\r
+                               if($timestamp - $ltime < $this->ENV['PERIOD.IMAGEPOST'] && $isupload) return true; // 附加圖檔的投稿時間相距太短\r
+                               if($com == $lcom && !$isupload) return true; // 內文一樣\r
+                       }\r
+               }\r
+               return false;\r
+       }\r
+\r
+       /* 檢查是否重複貼圖 */\r
+       function isDuplicateAttachment($lcount, $md5hash){\r
+               global $FileIO;\r
+\r
+               $pcount = $this->postCount();\r
+               $lcount = ($pcount > $lcount) ? $lcount : $pcount;\r
+               for($i = 0; $i < $lcount; $i++){\r
+                       $logsarray = $this->_ArrangeArrayStructure($this->porder[$i]); // 分析資料為陣列\r
+                       if(!$logsarray[0]['md5chksum']) continue; // 無附加圖檔\r
+                       if($logsarray[0]['md5chksum']==$md5hash){\r
+                               if($FileIO->imageExists($logsarray[0]['tim'].$logsarray[0]['ext'])) return true; // 存在MD5雜湊相同的檔案\r
+                       }\r
+               }\r
+               return false;\r
+       }\r
+\r
+       /* 有此討論串? */\r
+       function isThread($no){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               return isset($this->trees[$no]);\r
+       }\r
+\r
+       /* 搜尋文章 */\r
+       function searchPost($keyword,$field,$method){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $foundPosts = array();\r
+               $keyword_cnt = count($keyword);\r
+               $pcount = $this->postCount();\r
+               for($i = 0; $i < $pcount; $i++){\r
+                       $logsarray = $this->_ArrangeArrayStructure($this->porder[$i]); // 分析資料為陣列\r
+                       $found = 0;\r
+                       foreach($keyword as $k){\r
+                               if(strpos($logsarray[0][$field], $k)!==FALSE) $found++;\r
+                               if($method=="OR" && $found) break;\r
+                       }\r
+                       if($method=="AND" && $found==$keyword_cnt) array_push($foundPosts, $logsarray[0]); // 全部都有找到 (AND交集搜尋)\r
+                       elseif($method=="OR" && $found) array_push($foundPosts, $logsarray[0]); // 有找到 (OR聯集搜尋)\r
+               }\r
+               return $foundPosts;\r
+       }\r
+\r
+       /* 搜尋類別標籤 */\r
+       function searchCategory($category){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $category = strtolower($category);\r
+               $foundPosts = array();\r
+               $pcount = $this->postCount();\r
+               for($i = 0; $i < $pcount; $i++){\r
+                       $logsarray = $this->_ArrangeArrayStructure($this->porder[$i]); // 分析資料為陣列\r
+                       if(!($ary_category = $logsarray[0]['category'])) continue;\r
+                       if(strpos(strtolower($ary_category), '&#44;'.$category.'&#44;')!==false) array_push($foundPosts, $logsarray[0]['no']); // 找到標籤,加入名單\r
+               }\r
+               return $foundPosts;\r
+       }\r
+\r
+       /* 取得文章屬性 */\r
+       function getPostStatus($status){\r
+               return new FlagHelper($status); // 回傳 FlagHelper 物件\r
+       }\r
+\r
+       /* 更新文章 */\r
+       function updatePost($no, $newValues){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $chk = array('resto', 'md5chksum', 'category', 'tim', 'ext', 'imgw', 'imgh', 'imgsize', 'filename', 'tw', 'th', 'pwd', 'now', 'name', 'email', 'sub', 'com', 'host', 'status');\r
+\r
+               $this->_ArrangeArrayStructure($no); // 將資料變成陣列\r
+               foreach($chk as $c)\r
+                       if(isset($newValues[$c]))\r
+                               $this->logs[$this->LUT[$no]][$c] = $newValues[$c]; // 修改數值\r
+       }\r
+\r
+       /* 設定文章屬性 */\r
+       function setPostStatus($no, $newStatus){\r
+               $this->updatePost($no, array('status' => $newStatus));\r
+       }\r
+\r
+       /* 檔案鎖定/解鎖處理 */\r
+       function _lock($lock, $tries=10) {\r
+               ignore_user_abort(true);\r
+               $lock0 = ".{$lock}0";\r
+               $lock1 = ".{$lock}1";\r
+               for ($i=0; $i<$tries; $i++) {\r
+                       if (!is_file($lock0)) {\r
+                               touch($lock0);\r
+                               if (!is_file($lock1)) {\r
+                                  touch($lock1);\r
+                                  return TRUE;\r
+                               }\r
+                       }\r
+                       usleep(100);\r
+               }\r
+               return FALSE;\r
+       }\r
+\r
+       // Unlock a file.\r
+       function _unlock($lock) {\r
+               unlink(".{$lock}1");\r
+               unlink(".{$lock}0");\r
+               ignore_user_abort(false);\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/lib/pio/pio.mysql.php b/lib/pio/pio.mysql.php
new file mode 100755 (executable)
index 0000000..4b0243f
--- /dev/null
@@ -0,0 +1,494 @@
+<?php\r
+/**\r
+ * PIO MySQL API\r
+ *\r
+ * 提供存取以 MySQL 資料庫構成的資料結構後端的物件\r
+ *\r
+ * @package PMCLibrary\r
+ * @version $Id: pio.mysql.php 671 2008-09-20 05:54:15Z scribe $\r
+ * @date $Date: 2008-09-20 13:54:15 +0800 (星期六, 20 九月 2008) $\r
+ */\r
+\r
+class PIOmysql{\r
+       var $ENV, $username, $password, $server, $dbname, $tablename; // Local Constant\r
+       var $con, $prepared, $useTransaction; // Local Global\r
+\r
+       function PIOmysql($connstr='', $ENV){\r
+               $this->ENV = $ENV;\r
+               $this->prepared = 0;\r
+               if($connstr) $this->dbConnect($connstr);\r
+       }\r
+\r
+       /* private 攔截SQL錯誤 */\r
+       function _error_handler($errarray, $query=''){\r
+               $err = 'Pixmicat! SQL Error: '.$errarray[0].' on line '.$errarray[1];\r
+               error_log($err."\n".mysql_errno().': '.mysql_error()."\n".$query."\n\n", 3, 'error.log');\r
+               trigger_error($err, E_USER_ERROR);\r
+               exit();\r
+       }\r
+\r
+       /* private 使用SQL字串和MySQL伺服器要求 */\r
+       function _mysql_call($query, $errarray=false){\r
+               $resource = mysql_query($query);\r
+               if(is_array($errarray) && $resource===false) $this->_error_handler($errarray, $query);\r
+               else return $resource;\r
+       }\r
+\r
+       /* private 由資源輸出陣列 */\r
+       function _ArrangeArrayStructure($line){\r
+               $posts = array();\r
+               while($row = mysql_fetch_array($line, MYSQL_ASSOC)) $posts[] = $row;\r
+               mysql_free_result($line);\r
+               return $posts;\r
+       }\r
+\r
+       /* PIO模組版本 */\r
+       function pioVersion(){\r
+               return '0.6 (v20100404)';\r
+       }\r
+\r
+       /* 處理連線字串/連接 */\r
+       function dbConnect($connStr){\r
+               // 格式: mysql://帳號:密碼@伺服器位置:埠號(可省略)/資料庫/資料表/\r
+               // 示例: mysql://yotsubanome:pass@localhost/yotsubanome/img_loog/\r
+               if(preg_match('/^mysql:\/\/(.*)\:(.*)\@(.*(?:\:[0-9]+)?)\/(.*)\/(.*)\/$/i', $connStr, $linkinfos)){\r
+                       $this->username = $linkinfos[1]; // 登入帳號\r
+                       $this->password = $linkinfos[2]; // 登入密碼\r
+                       $this->server = $linkinfos[3]; // 登入伺服器 (含埠號)\r
+                       $this->dbname = $linkinfos[4]; // 資料庫名稱\r
+                       $this->tablename = $linkinfos[5]; // 資料表名稱\r
+               }\r
+       }\r
+
+       /* 初始化 */\r
+       function dbInit($isAddInitData=true){\r
+               $this->dbPrepare();\r
+               if(mysql_num_rows(mysql_query("SHOW TABLES LIKE '".$this->tablename."'"))!=1){ // 資料表不存在\r
+               $result = "CREATE TABLE ".$this->tablename." (primary key(no),\r
+       index (resto),index (root),index (time),\r
+       no int(1) not null auto_increment,\r
+       resto int(1) not null,\r
+       root timestamp(14) null DEFAULT 0,\r
+       time int(1) not null,\r
+       md5chksum varchar(32) not null,\r
+       category varchar(255) not null,\r
+       tim bigint(1) not null,\r
+       ext varchar(4) not null,\r
+       imgw smallint(1) not null,\r
+       imgh smallint(1) not null,\r
+       imgsize varchar(10) not null,
+       filename varchar(255) not null,\r
+       tw smallint(1) not null,\r
+       th smallint(1) not null,\r
+       pwd varchar(8) not null,\r
+       now varchar(255) not null,\r
+       name varchar(255) not null,\r
+       email varchar(255) not null,\r
+       sub varchar(255) not null,\r
+       com text not null,\r
+       host varchar(255) not null,\r
+       status varchar(255) not null)\r
+       TYPE = MYISAM\r
+       COMMENT = 'PIO Structure V4'";
+                       $result2 = @mysql_query("SHOW CHARACTER SET like 'utf8'"); // 是否支援UTF-8 (MySQL 4.1.1開始支援)\r
+                       if($result2 && mysql_num_rows($result2)){\r
+                               $result .= ' CHARACTER SET utf8 COLLATE utf8_general_ci'; // 資料表追加UTF-8編碼\r
+                               mysql_free_result($result2);\r
+                       }
+                       mysql_query($result); // 正式新增資料表
+                       // 追加一筆新資料
+                       if($isAddInitData) $this->addPost(0, 0, '', '', 0, '', 0, 0, '', '', 0, 0, '', '08/11/08(土) 10:24:04', '【スパーキー(④ ^ヮ^)】', '', $this->ENV['NOTITLE'], $this->ENV['NOCOMMENT'], ''); // 追加一筆新資料料\r
+                       $this->dbCommit();\r
+               }\r
+       }\r
+\r
+       /* 準備/讀入 */\r
+       function dbPrepare($transaction=false){\r
+               if($this->prepared) return true;\r
+\r
+               if(@!$this->con = mysql_pconnect($this->server, $this->username, $this->password)) $this->_error_handler(array('Open database failed', __LINE__));\r
+               @mysql_select_db($this->dbname, $this->con);\r
+               @mysql_query("SET NAMES 'utf8'"); // MySQL資料以UTF-8模式傳送\r
+               $this->useTransaction = $transaction;\r
+               if($transaction) @mysql_query('START TRANSACTION'); // 啟動交易性能模式\r
+\r
+               $this->prepared = 1;\r
+       }\r
+\r
+       /* 提交/儲存 */\r
+       function dbCommit(){\r
+               if(!$this->prepared) return false;\r
+               if($this->useTransaction) @mysql_query('COMMIT'); // 交易性能模式提交\r
+       }\r
+\r
+       /* 資料表維護 */\r
+       function dbMaintanence($action, $doit=false){\r
+               switch($action) {\r
+                       case 'optimize':\r
+                               if($doit){\r
+                                       $this->dbPrepare(false);\r
+                                       if($this->_mysql_call('OPTIMIZE TABLES '.$this->tablename)) return true;\r
+                                       else return false;\r
+                               }else return true; // 支援最佳化資料表\r
+                               break;\r
+                       case 'check':\r
+                               if($doit){\r
+                                       $this->dbPrepare(false);\r
+                                       if($rs=$this->_mysql_call('CHECK TABLE '.$this->tablename)){\r
+                                               mysql_data_seek($rs, mysql_num_rows($rs)-1);\r
+                                               $row = mysql_fetch_assoc($rs);\r
+                                               return 'Table '.$row['Table'].': '.$row['Msg_type'].' = '.$row['Msg_text'];\r
+                                       }\r
+                                       else return false;\r
+                               }else return true; // 支援檢查資料表\r
+                               break;\r
+                       case 'repair':\r
+                               if($doit){\r
+                                       $this->dbPrepare(false);\r
+                                       if($rs=$this->_mysql_call('REPAIR TABLE '.$this->tablename)){\r
+                                               mysql_data_seek($rs, mysql_num_rows($rs)-1);\r
+                                               $row = mysql_fetch_assoc($rs);\r
+                                               return 'Table '.$row['Table'].': '.$row['Msg_type'].' = '.$row['Msg_text'];\r
+                                       }\r
+                                       else return false;\r
+                               }else return true; // 支援修復資料表\r
+                               break;\r
+                       case 'export':\r
+                               if($doit){\r
+                                       $this->dbPrepare(false);\r
+                                       $gp = gzopen('piodata.log.gz', 'w9');\r
+                                       gzwrite($gp, $this->dbExport());\r
+                                       gzclose($gp);\r
+                                       return '<a href="piodata.log.gz">下載 piodata.log.gz 中介檔案</a>';\r
+                               }else return true; // 支援匯出資料\r
+                               break;\r
+                       default: return false; // 不支援\r
+               }\r
+       }\r
+\r
+       /* 匯入資料來源 */\r
+       function dbImport($data){\r
+               $this->dbInit(false); // 僅新增結構不新增資料\r
+               $data = explode("\r\n", $data);\r
+               $data_count = count($data) - 1;\r
+               $replaceComma = create_function('$txt', 'return str_replace("&#44;", ",", $txt);');\r
+               for($i = 0; $i < $data_count; $i++){\r
+                       $line = array_map($replaceComma, explode(',', $data[$i])); // 取代 &#44; 為 ,\r
+                       $SQL = 'INSERT INTO '.$this->tablename.' (no,resto,root,time,md5chksum,category,tim,ext,imgw,imgh,imgsize,filename,tw,th,pwd,now,name,email,sub,com,host,status) VALUES ('.\r
+       $line[0].','.\r
+       $line[1].',\''.\r
+       $line[2].'\','.\r
+       substr($line[5], 0, 10).',\''.\r
+       mysql_real_escape_string($line[3], $this->con).'\',\''.\r
+       mysql_real_escape_string($line[4], $this->con).'\','.\r
+       $line[5].',\''.mysql_real_escape_string($line[6], $this->con).'\','.\r
+       $line[7].','.$line[8].',\''.mysql_real_escape_string($line[9], $this->con).','.mysql_real_escape_string($line[10], $this->con).'\','.$line[11].','.$line[12].',\''.\r
+       mysql_real_escape_string($line[13], $this->con).'\',\''.\r
+       mysql_real_escape_string($line[14], $this->con).'\',\''.\r
+       mysql_real_escape_string($line[15], $this->con).'\',\''.\r
+       mysql_real_escape_string($line[16], $this->con).'\',\''.\r
+       mysql_real_escape_string($line[17], $this->con).'\',\''.\r
+       mysql_real_escape_string($line[18], $this->con).'\',\''.\r
+       mysql_real_escape_string($line[19], $this->con).'\',\''.\r
+       mysql_real_escape_string($line[20], $this->con).'\')';\r
+                       $this->_mysql_call($SQL, array('Import a new post failed', __LINE__));\r
+               }\r
+               $this->dbCommit(); // 送交\r
+               return true;\r
+       }\r
+\r
+       /* 匯出資料來源 */\r
+       function dbExport(){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+               $line = $this->_mysql_call('SELECT no,resto,root,md5chksum,category,tim,ext,imgw,imgh,imgsize,filename,tw,th,pwd,now,name,email,sub,com,host,status FROM '.$this->tablename.' ORDER BY no DESC',\r
+                       array('Export posts failed', __LINE__));\r
+               $data = '';\r
+               $replaceComma = create_function('$txt', 'return str_replace(",", "&#44;", $txt);');\r
+               while($row = mysql_fetch_array($line, MYSQL_ASSOC)){\r
+                       $row = array_map($replaceComma, $row); // 取代 , 為 &#44;\r
+                       if($row['root']=='0000-00-00 00:00:00') $row['root'] = '0'; // 初始值設為 0\r
+                       $data .= rtrim(implode(',', $row)).",\r\n";\r
+               }\r
+               mysql_free_result($line);\r
+               return $data;\r
+       }\r
+\r
+       /* 文章數目 */\r
+       function postCount($resno=0){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               if($resno){ // 回傳討論串總文章數目\r
+                       $line = $this->_mysql_call('SELECT COUNT(no) FROM '.$this->tablename.' WHERE resto = '.intval($resno),\r
+                               array('Fetch count in thread failed', __LINE__));\r
+                       $countline = mysql_result($line, 0) + 1;\r
+               }else{ // 回傳總文章數目\r
+                       $line = $this->_mysql_call('SELECT COUNT(no) FROM '.$this->tablename, array('Fetch count of posts failed', __LINE__));\r
+                       $countline = mysql_result($line, 0);\r
+               }\r
+               mysql_free_result($line);\r
+               return $countline;\r
+       }\r
+\r
+       /* 討論串數目 */\r
+       function threadCount(){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $tree = $this->_mysql_call('SELECT COUNT(no) FROM '.$this->tablename.' WHERE resto = 0',\r
+                       array('Fetch count of threads failed', __LINE__));\r
+               $counttree = mysql_result($tree, 0); mysql_free_result($tree); // 計算討論串目前資料筆數\r
+               return $counttree;\r
+       }\r
+\r
+       /* 取得最後文章編號 */\r
+       function getLastPostNo($state){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               if($state=='afterCommit'){ // 送出後的最後文章編號\r
+                       $tree = $this->_mysql_call('SELECT MAX(no) FROM '.$this->tablename, array('Get the last No. failed', __LINE__));\r
+                       $lastno = mysql_result($tree, 0); mysql_free_result($tree);\r
+                       return $lastno;\r
+               }else return 0; // 其他狀態沒用\r
+       }\r
+\r
+       /* 輸出文章清單 */\r
+       function fetchPostList($resno=0, $start=0, $amount=0){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $line = array();\r
+               $resno = intval($resno);\r
+               if($resno){ // 輸出討論串的結構 (含自己, EX : 1,2,3,4,5,6)\r
+                       $tmpSQL = 'SELECT no FROM '.$this->tablename.' WHERE no = '.$resno.' OR resto = '.$resno.' ORDER BY no';\r
+               }else{ // 輸出所有文章編號,新的在前\r
+                       $tmpSQL = 'SELECT no FROM '.$this->tablename.' ORDER BY no DESC';\r
+                       $start = intval($start); $amount = intval($amount);\r
+                       if($amount) $tmpSQL .= " LIMIT {$start}, {$amount}"; // 有指定數量才用 LIMIT\r
+               }\r
+               $tree = $this->_mysql_call($tmpSQL, array('Fetch post list failed', __LINE__));\r
+               while($rows = mysql_fetch_row($tree)) $line[] = $rows[0]; // 迴圈\r
+               mysql_free_result($tree);\r
+               return $line;\r
+       }\r
+\r
+       /* 輸出討論串清單 */\r
+       function fetchThreadList($start=0, $amount=0, $isDESC=false){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $start = intval($start); $amount = intval($amount);\r
+               $treeline = array();\r
+               $tmpSQL = 'SELECT no FROM '.$this->tablename.' WHERE resto = 0 ORDER BY '.($isDESC ? 'no' : 'root').' DESC';\r
+               if($amount) $tmpSQL .= " LIMIT {$start}, {$amount}"; // 有指定數量才用 LIMIT\r
+               $tree = $this->_mysql_call($tmpSQL, array('Fetch thread list failed', __LINE__));\r
+               while($rows = mysql_fetch_row($tree)) $treeline[] = $rows[0]; // 迴圈\r
+               mysql_free_result($tree);\r
+               return $treeline;\r
+       }\r
+\r
+       /* 輸出文章 */\r
+       function fetchPosts($postlist){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               if(is_array($postlist)){ // 取多串\r
+                       $pno = implode(', ', $postlist); // ID字串\r
+                       $tmpSQL = 'SELECT * FROM '.$this->tablename.' WHERE no IN ('.$pno.') ORDER BY no';\r
+                       if(count($postlist) > 1){ if($postlist[0] > $postlist[1]) $tmpSQL .= ' DESC'; } // 由大排到小\r
+               }else $tmpSQL = 'SELECT * FROM '.$this->tablename.' WHERE no = '.intval($postlist); // 取單串\r
+               $line = $this->_mysql_call($tmpSQL, array('Fetch the post content failed', __LINE__));\r
+               return $this->_ArrangeArrayStructure($line); // 輸出陣列結構\r
+       }\r
+\r
+       /* 刪除舊附件 (輸出附件清單) */\r
+       function delOldAttachments($total_size, $storage_max, $warnOnly=true){\r
+               global $FileIO;\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $arr_warn = $arr_kill = array(); // 警告 / 即將被刪除標記陣列\r
+               $result = $this->_mysql_call('SELECT no,ext,tim FROM '.$this->tablename.' WHERE ext <> \'\' ORDER BY no',\r
+                       array('Get old posts failed', __LINE__));\r
+               while(list($dno, $dext, $dtim) = mysql_fetch_row($result)){ // 個別跑舊文迴圈\r
+                       $dfile = $dtim.$dext; // 附加檔案名稱\r
+                       $dthumb = $dtim.'s.jpg'; // 預覽檔案名稱\r
+                       if($FileIO->imageExists($dfile)){ $total_size -= $FileIO->getImageFilesize($dfile) / 1024; $arr_kill[] = $dno; $arr_warn[$dno] = 1; } // 標記刪除\r
+                       if($FileIO->imageExists($dthumb)) $total_size -= $FileIO->getImageFilesize($dthumb) / 1024;\r
+                       if($total_size < $storage_max) break;\r
+               }\r
+               mysql_free_result($result);\r
+               return $warnOnly ? $arr_warn : $this->removeAttachments($arr_kill);\r
+       }\r
+\r
+       /* 刪除文章 */\r
+       function removePosts($posts){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+               if(count($posts)==0) return array();\r
+\r
+               $files = $this->removeAttachments($posts, true); // 先遞迴取得刪除文章及其回應附件清單\r
+               $pno = implode(', ', $posts); // ID字串\r
+               $this->_mysql_call('DELETE FROM '.$this->tablename.' WHERE no IN ('.$pno.') OR resto IN('.$pno.')',\r
+                       array('Delete old posts and replies failed', __LINE__)); // 刪掉文章\r
+               return $files;\r
+       }\r
+\r
+       /* 刪除附件 (輸出附件清單) */\r
+       function removeAttachments($posts, $recursion=false){\r
+               global $FileIO;\r
+               if(!$this->prepared) $this->dbPrepare();\r
+               if(count($posts)==0) return array();\r
+\r
+               $files = array();\r
+               $pno = implode(', ', $posts); // ID字串\r
+               if($recursion) $tmpSQL = 'SELECT ext,tim FROM '.$this->tablename.' WHERE (no IN ('.$pno.') OR resto IN('.$pno.")) AND ext <> ''"; // 遞迴取出 (含回應附件)\r
+               else $tmpSQL = 'SELECT ext,tim FROM '.$this->tablename.' WHERE no IN ('.$pno.") AND ext <> ''"; // 只有指定的編號\r
+\r
+               $result = $this->_mysql_call($tmpSQL, array('Get attachments of the post failed', __LINE__));\r
+               while(list($dext, $dtim) = mysql_fetch_row($result)){ // 個別跑迴圈\r
+                       $dfile = $dtim.$dext; // 附加檔案名稱\r
+                       $dthumb = $dtim.'s.jpg'; // 預覽檔案名稱\r
+                       if($FileIO->imageExists($dfile)) $files[] = $dfile;\r
+                       if($FileIO->imageExists($dthumb)) $files[] = $dthumb;\r
+               }\r
+               mysql_free_result($result);\r
+               return $files;\r
+       }\r
+
+       /* 新增文章/討論串 */\r
+       function addPost($no, $resto, $md5chksum, $category, $tim, $ext, $imgw, $imgh, $imgsize, $filename, $tw, $th, $pwd, $now, $name, $email, $sub, $com, $host, $age=false, $status='') {\r
+               if(!$this->prepared) $this->dbPrepare();\r\r
+               $time = (int)substr($tim, 0, -3); // 13位數的數字串是檔名,10位數的才是時間數值\r
+               $updatetime = gmdate('Y-m-d H:i:s'); // 更動時間 (UTC)\r
+               $resto = intval($resto);\r
+               if($resto){ // 新增回應\r
+                       $root = '0';\r
+                       if($age){ // 推文\r
+                               $this->_mysql_call('UPDATE '.$this->tablename.' SET root = "'.$updatetime.'" WHERE no = '.$resto,\r
+                                       array('Push the post failed', __LINE__)); // 將被回應的文章往上移動\r
+                       }\r              }else $root = $updatetime; // 新增討論串, 討論串最後被更新時間\r
+
+               if($no === 0){ // init post 0
+                       $query = 'INSERT INTO '.$this->tablename.' (no,resto,root,time,md5chksum,category,tim,ext,imgw,imgh,imgsize,tw,th,pwd,now,name,email,sub,com,host,status) VALUES ('.
+               -1,'. // 回應編號
+               $resto.','. // 回應編號
+               "'$root',". // 最後更新時間
+               $time.','. // 發文時間數值
+               "'$md5chksum',". // 附加檔案md5
+               "'".mysql_real_escape_string($category, $this->con)."',". // 分類標籤
+               "'$tim', '$ext',". // 附加檔名
+               (int)$imgw.','.(int)$imgh.",'".$imgsize."','".$filename."',".(int)$tw.','.(int)$th.','. // 圖檔長寬及檔案大小;預覽圖長寬
+               "'".mysql_real_escape_string($pwd, $this->con)."',".\r
+               "'$now',". // 時間(含ID)字串
+               "'".mysql_real_escape_string($name, $this->con)."',".\r
+               "'".mysql_real_escape_string($email, $this->con)."',".\r
+               "'".mysql_real_escape_string($sub, $this->con)."',".\r
+               "'".mysql_real_escape_string($com, $this->con)."',".\r
+               "'".mysql_real_escape_string($host, $this->con)."', '".mysql_real_escape_string($status, $this->con)."')";
+               }else{\r
+                       $query = 'INSERT INTO '.$this->tablename.' (resto,root,time,md5chksum,category,tim,ext,imgw,imgh,imgsize,tw,th,pwd,now,name,email,sub,com,host,status) VALUES ('.\r
+               $resto.','. // 回應編號
+               "'$root',". // 最後更新時間
+               $time.','. // 發文時間數值
+               "'$md5chksum',". // 附加檔案md5
+               "'".mysql_real_escape_string($category, $this->con)."',". // 分類標籤
+               "'$tim', '$ext',". // 附加檔名
+               (int)$imgw.','.(int)$imgh.",'".$imgsize."','".$filename."',".(int)$tw.','.(int)$th.','. // 圖檔長寬及檔案大小;預覽圖長寬
+               "'".mysql_real_escape_string($pwd, $this->con)."',".\r
+               "'$now',". // 時間(含ID)字串
+               "'".mysql_real_escape_string($name, $this->con)."',".\r
+               "'".mysql_real_escape_string($email, $this->con)."',".\r
+               "'".mysql_real_escape_string($sub, $this->con)."',".\r
+               "'".mysql_real_escape_string($com, $this->con)."',".\r
+               "'".mysql_real_escape_string($host, $this->con)."', '".mysql_real_escape_string($status, $this->con)."')";
+               }
+               $this->_mysql_call($query, array('Insert a new post failed', __LINE__));\r
+       }\r
+\r
+       /* 檢查是否連續投稿 */\r
+       function isSuccessivePost($lcount, $com, $timestamp, $pass, $passcookie, $host, $isupload){\r
+               global $FileIO;\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               if(!$this->ENV['PERIOD.POST']) return false; // 關閉連續投稿檢查\r
+               $timestamp = intval($timestamp);\r
+               $tmpSQL = 'SELECT pwd,host FROM '.$this->tablename.' WHERE time > '.($timestamp - (int)$this->ENV['PERIOD.POST']); // 一般投稿時間檢查\r
+               if($isupload) $tmpSQL .= ' OR time > '.($timestamp - (int)$this->ENV['PERIOD.IMAGEPOST']); // 附加圖檔的投稿時間檢查 (與下者兩者擇一)\r
+               else $tmpSQL .= ' OR md5(com) = "'.md5($com).'"'; // 內文一樣的檢查 (與上者兩者擇一)\r
+\r
+               $result = $this->_mysql_call($tmpSQL, array('Get the post to check the succession failed', __LINE__));\r
+               while(list($lpwd, $lhost) = mysql_fetch_row($result)){\r
+                       // 判斷為同一人發文且符合連續投稿條件\r
+                       if($host==$lhost || $pass==$lpwd || $passcookie==$lpwd) return true;\r
+               }\r
+               return false;\r
+       }\r
+\r
+       /* 檢查是否重複貼圖 */\r
+       function isDuplicateAttachment($lcount, $md5hash){\r
+               global $FileIO;\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $result = $this->_mysql_call('SELECT tim,ext FROM '.$this->tablename." WHERE ext <> '' AND md5chksum = '$md5hash' ORDER BY no DESC",\r
+                       array('Get the post to check the duplicate attachment failed', __LINE__));\r
+               while(list($ltim, $lext) = mysql_fetch_row($result)){\r
+                       if($FileIO->imageExists($ltim.$lext)) return true; // 有相同檔案\r
+               }\r
+               return false;\r
+       }\r
+\r
+       /* 有此討論串? */\r
+       function isThread($no){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $result = $this->_mysql_call('SELECT no FROM '.$this->tablename.' WHERE no = '.intval($no).' AND resto = 0');\r
+               return mysql_fetch_array($result) ? true : false;\r
+       }\r
+\r
+       /* 搜尋文章 */\r
+       function searchPost($keyword, $field, $method){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $keyword_cnt = count($keyword);\r
+               $SearchQuery = 'SELECT * FROM '.$this->tablename." WHERE {$field} LIKE '%".mysql_real_escape_string($keyword[0], $this->con)."%'";\r
+               if($keyword_cnt > 1){\r
+                       for($i = 1; $i < $keyword_cnt; $i++){\r
+                               $SearchQuery .= " {$method} {$field} LIKE '%".mysql_real_escape_string($keyword[$i], $this->con)."%'"; // 多重字串交集 / 聯集搜尋\r
+                       }\r
+               }\r
+               $SearchQuery .= ' ORDER BY no DESC'; // 按照號碼大小排序\r
+               $line = $this->_mysql_call($SearchQuery, array('Search the post failed', __LINE__));\r
+               return $this->_ArrangeArrayStructure($line); // 輸出陣列結構\r
+       }\r
+\r
+       /* 搜尋類別標籤 */\r
+       function searchCategory($category){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $foundPosts = array();\r
+               $SearchQuery = 'SELECT no FROM '.$this->tablename." WHERE lower(category) LIKE '%,".strtolower(mysql_real_escape_string($category, $this->con)).",%' ORDER BY no DESC";\r
+               $line = $this->_mysql_call($SearchQuery, array('Search the category failed', __LINE__));\r
+               while($rows = mysql_fetch_row($line)) $foundPosts[] = $rows[0];\r
+               mysql_free_result($line);\r
+               return $foundPosts;\r
+       }\r
+\r
+       /* 取得文章屬性 */\r
+       function getPostStatus($status){\r
+               return new FlagHelper($status); // 回傳 FlagHelper 物件\r
+       }\r
+\r
+       /* 更新文章 */\r
+       function updatePost($no, $newValues){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $no = intval($no);\r
+               $chk = array('resto', 'md5chksum', 'category', 'tim', 'ext', 'imgw', 'imgh', 'imgsize', 'filename', 'tw', 'th', 'pwd', 'now', 'name', 'email', 'sub', 'com', 'host', 'status');\r
+               foreach($chk as $c){\r
+                       if(isset($newValues[$c])){\r
+                               $this->_mysql_call('UPDATE '.$this->tablename." SET $c = '".mysql_real_escape_string($newValues[$c], $this->con)."', root = root WHERE no = ".$no,\r
+                                       array('Update the field of the post failed', __LINE__)); // 更新討論串屬性\r
+                       }\r
+               }\r
+       }\r
+\r
+       /* 設定文章屬性 */\r
+       function setPostStatus($no, $newStatus){\r
+               $this->updatePost($no, array('status' => $newStatus));\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/lib/pio/pio.pgsql.php b/lib/pio/pio.pgsql.php
new file mode 100755 (executable)
index 0000000..26aca8d
--- /dev/null
@@ -0,0 +1,475 @@
+<?php\r
+/**\r
+ * PIO PostgreSQL API\r
+ *\r
+ * 提供存取以 PostgreSQL 資料庫構成的資料結構後端的物件\r
+ *\r
+ * @package PMCLibrary\r
+ * @version $Id: pio.pgsql.php 671 2008-09-20 05:54:15Z scribe $\r
+ * @date $Date: 2008-09-20 13:54:15 +0800 (星期六, 20 九月 2008) $\r
+ */\r
+\r
+class PIOpgsql{\r
+       var $ENV, $username, $password, $server, $port, $dbname, $tablename; // Local Constant\r
+       var $con, $prepared, $useTransaction; // Local Global\r
+\r
+       function PIOpgsql($connstr='', $ENV){\r
+               $this->ENV = $ENV;\r
+               $this->prepared = 0;\r
+               if($connstr) $this->dbConnect($connstr);\r
+       }\r
+\r
+       /* private 攔截SQL錯誤 */\r
+       function _error_handler($errarray, $query=''){\r
+               $err = 'Pixmicat! SQL Error: '.$errarray[0].' on line '.$errarray[1];\r
+               //error_log($err."\n".pg_last_error($this->con)."\n".$query."\n\n", 3, 'error.log');\r
+               trigger_error($err, E_USER_ERROR);\r
+               exit();\r
+       }\r
+\r
+       /* private 使用SQL字串和PostgreSQL伺服器要求 */\r
+       function _pgsql_call($query, $errarray=false){\r
+               $resource = pg_query($this->con, $query);\r
+               if(is_array($errarray) && $resource===false) $this->_error_handler($errarray, $query);\r
+               else return $resource;\r
+       }\r
+\r
+       /* private 由資源輸出陣列 */\r
+       function _ArrangeArrayStructure($line){\r
+               $posts = array();\r
+               while($row = pg_fetch_array($line, null, PGSQL_ASSOC)) $posts[] = $row;\r
+               pg_free_result($line);\r
+               return $posts;\r
+       }\r
+\r
+       /* PIO模組版本 */\r
+       function pioVersion(){\r
+               return '0.6 (v20100404)';\r
+       }\r
+\r
+       /* 處理連線字串/連接 */\r
+       function dbConnect($connStr){\r
+               // 格式: pgsql://帳號:密碼@伺服器位置:埠號(可省略)/資料庫/資料表/\r
+               // 示例: pgsql://yotsubanome:pass@localhost/yotsubanome/img_loog/\r
+               if(preg_match('/^pgsql:\/\/(.*)\:(.*)\@([^\:]*)((\:)([0-9]+)){0,1}\/(.*)\/(.*)\/$/i', $connStr, $linkinfos)){\r
+                       $this->username = $linkinfos[1]; // 登入帳號\r
+                       $this->password = $linkinfos[2]; // 登入密碼\r
+                       $this->server = $linkinfos[3]; // 登入伺服器\r
+                       $this->port = ($linkinfos[6] ? $linkinfos[6] : '5432'); // 登入埠號\r
+                       $this->dbname = $linkinfos[7]; // 資料庫名稱\r
+                       $this->tablename = $linkinfos[8]; // 資料表名稱\r
+               }\r
+       }\r
+\r
+       /* 初始化 */\r
+       function dbInit($isAddInitData=true){\r
+               $this->dbPrepare();\r
+               if(pg_num_rows(pg_query($this->con, "SELECT relname FROM pg_class WHERE relname = '".$this->tablename."'"))!=1){ // 資料表不存在\r
+                       $result = "CREATE SEQUENCE ".$this->tablename."_no_seq;\r
+       CREATE TABLE ".$this->tablename." (
+       \"no\" int NOT NULL DEFAULT nextval('".$this->tablename."_no_seq'),\r
+       \"resto\" int NOT NULL,\r
+       \"root\" timestamp NULL DEFAULT '1980-01-01 00:00:00',\r
+       \"time\" int NOT NULL,\r
+       \"md5chksum\" varchar(32) NOT NULL,\r
+       \"category\" varchar(255) NOT NULL,\r
+       \"tim\" bigint NOT NULL,\r
+       \"ext\" varchar(4) NOT NULL,\r
+       \"imgw\" smallint NOT NULL,\r
+       \"imgh\" smallint NOT NULL,\r
+       \"imgsize\" varchar(10) NOT NULL,
+       \"filename\" varchar(255) NOT NULL,\r
+       \"tw\" smallint NOT NULL,\r
+       \"th\" smallint NOT NULL,\r
+       \"pwd\" varchar(8) NOT NULL,\r
+       \"now\" varchar(255) NOT NULL,\r
+       \"name\" varchar(255) NOT NULL,\r
+       \"email\" varchar(255) NOT NULL,\r
+       \"sub\" varchar(255) NOT NULL,\r
+       \"com\" text NOT NULL,\r
+       \"host\" varchar(255) NOT NULL,\r
+       \"status\" varchar(255) NOT NULL,\r
+       PRIMARY KEY (\"no\"));"; // PIO Structure V4\r
+                       $idxs = array('resto', 'root', 'time');\r
+                       foreach($idxs as $idx) $result .= 'CREATE INDEX '.$this->tablename.'_'.$idx.'_index ON '.$this->tablename.' ('.$idx.');';\r
+                       pg_query($this->con, $result); // 正式新增資料表\r
+                       if($isAddInitData) $this->addPost(0, 0, '', '', 0, '', 0, 0, '', '', 0, 0, '', '08/11/08(土) 10:24:04', '【スパーキー(④ ^ヮ^)】', '', $this->ENV['NOTITLE'], $this->ENV['NOCOMMENT'], ''); // 追加一筆新資料\r
+                       $this->dbCommit();\r
+               }\r
+       }\r
+\r
+       /* 準備/讀入 */\r
+       function dbPrepare($transaction=true){\r
+               if($this->prepared) return true;\r
+\r
+               $this->con = pg_pconnect("host='".$this->server."' port=".$this->port." dbname='".$this->dbname."' user='".$this->username."' password='".$this->password."'");\r
+               if(!$this->con) $this->_error_handler(array('Open database failed', __LINE__));\r
+               $this->useTransaction = $transaction;\r
+               if($transaction) @pg_query($this->con, 'START TRANSACTION;'); // 啟動交易性能模式\r
+\r
+               $this->prepared = 1;\r
+       }\r
+\r
+       /* 提交/儲存 */\r
+       function dbCommit(){\r
+               if(!$this->prepared) return false;\r
+\r
+               if($this->useTransaction) @pg_query($this->con, 'COMMIT;'); // 交易性能模式提交\r
+       }\r
+\r
+       /* 資料表維護 */\r
+       function dbMaintanence($action, $doit=false){\r
+               switch($action) {\r
+                       case 'optimize':\r
+                               if($doit){\r
+                                       $this->dbPrepare(false);\r
+                                       if($this->_pgsql_call('VACUUM '.$this->tablename)) return true;\r
+                                       else return false;\r
+                               }else return true; // 支援最佳化資料表\r
+                               break;\r
+                       case 'export':\r
+                               if($doit){\r
+                                       $this->dbPrepare(false);\r
+                                       $gp = gzopen('piodata.log.gz', 'w9');\r
+                                       gzwrite($gp, $this->dbExport());\r
+                                       gzclose($gp);\r
+                                       return '<a href="piodata.log.gz">下載 piodata.log.gz 中介檔案</a>';\r
+                               }else return true; // 支援匯出資料\r
+                               break;\r
+                       case 'check':\r
+                       case 'repair':\r
+                       default: return false; // 不支援\r
+               }\r
+       }\r
+\r
+       /* 匯入資料來源 */\r
+       function dbImport($data){\r
+               $this->dbInit(false); // 僅新增結構不新增資料\r
+               $data = explode("\r\n", $data);\r
+               $data_count = count($data) - 1;\r
+               $replaceComma = create_function('$txt', 'return str_replace("&#44;", ",", $txt);');\r
+               for($i = 0; $i < $data_count; $i++){\r
+                       $line = array_map($replaceComma, explode(',', $data[$i])); // 取代 &#44; 為 ,\r
+                       if($line[2]=='0') $line[2] = '1980-01-01 00:00:00'; // 零值\r
+                       $SQL = 'INSERT INTO '.$this->tablename.' (no,resto,root,time,md5chksum,category,tim,ext,imgw,imgh,imgsize,filename,tw,th,pwd,now,name,email,sub,com,host,status) VALUES ('.\r
+       $line[0].','.\r
+       $line[1].',\''.\r
+       $line[2].'\','.\r
+       substr($line[5], 0, 10).',\''.\r
+       pg_escape_string($line[3]).'\',\''.\r
+       pg_escape_string($line[4]).'\','.\r
+       $line[5].',\''.pg_escape_string($line[6]).'\','.\r
+       $line[7].','.$line[8].',\''.pg_escape_string($line[9]).','.pg_escape_string($line[10]).'\','.$line[11].','.$line[12].',\''.\r
+       pg_escape_string($line[13]).'\',\''.\r
+       pg_escape_string($line[14]).'\',\''.\r
+       pg_escape_string($line[15]).'\',\''.\r
+       pg_escape_string($line[16]).'\',\''.\r
+       pg_escape_string($line[17]).'\',\''.\r
+       pg_escape_string($line[18]).'\',\''.\r
+       pg_escape_string($line[19]).'\',\''.\r
+       pg_escape_string($line[20]).'\');';\r
+                       $this->_pgsql_call($SQL, array('Insert a new post failed', __LINE__));\r
+               }\r
+               $this->dbCommit(); // 送交\r
+               return true;\r
+       }\r
+\r
+       /* 匯出資料來源 */\r
+       function dbExport(){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+               $line = $this->_pgsql_call('SELECT no,resto,root,md5chksum,category,tim,ext,imgw,imgh,imgsize,filename,tw,th,pwd,now,name,email,sub,com,host,status FROM '.$this->tablename.' ORDER BY no DESC',\r
+                       array('Export posts failed', __LINE__));\r
+               $data = '';\r
+               $replaceComma = create_function('$txt', 'return str_replace(",", "&#44;", $txt);');\r
+               while($row = pg_fetch_array($line, null, PGSQL_ASSOC)){\r
+                       $row = array_map($replaceComma, $row); // 取代 , 為 &#44;\r
+                       if($row['root']=='1980-01-01 00:00:00') $row['root'] = '0'; // 初始值設為 0\r
+                       $data .= implode(',', $row).",\r\n";\r
+               }\r
+               pg_free_result($line);\r
+               return $data;\r
+       }\r
+\r
+       /* 文章數目 */\r
+       function postCount($resno=0){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               if($resno){ // 回傳討論串總文章數目\r
+                       $line = $this->_pgsql_call('SELECT COUNT(no) FROM '.$this->tablename.' WHERE resto = '.intval($resno),\r
+                               array('Fetch count in thread failed', __LINE__));\r
+                       $countline = pg_fetch_result($line, 0, 0) + 1;\r
+               }else{ // 回傳總文章數目\r
+                       $line = $this->_pgsql_call('SELECT COUNT(no) FROM '.$this->tablename, array('Fetch count of posts failed', __LINE__));\r
+                       $countline = pg_fetch_result($line, 0, 0);\r
+               }\r
+               pg_free_result($line);\r
+               return $countline;\r
+       }\r
+\r
+       /* 討論串數目 */\r
+       function threadCount(){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $tree = $this->_pgsql_call('SELECT COUNT(no) FROM '.$this->tablename.' WHERE resto = 0',\r
+                       array('Fetch count of threads failed', __LINE__));\r
+               $counttree = pg_fetch_result($tree, 0, 0); pg_free_result($tree); // 計算討論串目前資料筆數\r
+               return $counttree;\r
+       }\r
+\r
+       /* 取得最後文章編號 */\r
+       function getLastPostNo($state){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               if($state=='afterCommit'){ // 送出後的最後文章編號\r
+                       $tree = $this->_pgsql_call('SELECT MAX(no) FROM '.$this->tablename, array('Get the last No. failed', __LINE__));\r
+                       $lastno = pg_fetch_result($tree, 0, 0); pg_free_result($tree);\r
+                       return $lastno;\r
+               }else return 0; // 其他狀態沒用\r
+       }\r
+\r
+       /* 輸出文章清單 */\r
+       function fetchPostList($resno=0, $start=0, $amount=0){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $line = array();\r
+               $resno = intval($resno);\r
+               if($resno){ // 輸出討論串的結構 (含自己, EX : 1,2,3,4,5,6)\r
+                       $tmpSQL = 'SELECT no FROM '.$this->tablename.' WHERE no = '.$resno.' OR resto = '.$resno.' ORDER BY no';\r
+               }else{ // 輸出所有文章編號,新的在前\r
+                       $tmpSQL = 'SELECT no FROM '.$this->tablename.' ORDER BY no DESC';\r
+                       $start = intval($start); $amount = intval($amount);\r
+                       if($amount) $tmpSQL .= " LIMIT {$amount} OFFSET {$start}"; // 有指定數量才用 LIMIT\r
+               }\r
+               $tree = $this->_pgsql_call($tmpSQL, array('Fetch post list failed', __LINE__));\r
+               while($rows = pg_fetch_array($tree)) $line[] = $rows[0]; // 迴圈\r
+\r
+               pg_free_result($tree);\r
+               return $line;\r
+       }\r
+\r
+       /* 輸出討論串清單 */\r
+       function fetchThreadList($start=0, $amount=0, $isDESC=false){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $start = intval($start); $amount = intval($amount);\r
+               $treeline = array();\r
+               $tmpSQL = 'SELECT no FROM '.$this->tablename.' WHERE resto = 0 ORDER BY '.($isDESC ? 'no' : 'root').' DESC';\r
+               if($amount) $tmpSQL .= " LIMIT {$amount} OFFSET {$start}"; // 有指定數量才用 LIMIT\r
+               $tree = $this->_pgsql_call($tmpSQL, array('Fetch thread list failed', __LINE__));\r
+               while($rows = pg_fetch_array($tree)) $treeline[] = $rows[0]; // 迴圈\r
+\r
+               pg_free_result($tree);\r
+               return $treeline;\r
+       }\r
+\r
+       /* 輸出文章 */\r
+       function fetchPosts($postlist){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               if(is_array($postlist)){ // 取多串\r
+                       if(!count($postlist)) return array();\r
+                       $pno = implode(', ', $postlist); // ID字串\r
+                       $tmpSQL = 'SELECT * FROM '.$this->tablename.' WHERE no IN ('.$pno.') ORDER BY no';\r
+                       if(count($postlist) > 1){ if($postlist[0] > $postlist[1]) $tmpSQL .= ' DESC'; } // 由大排到小\r
+               }else $tmpSQL = 'SELECT * FROM '.$this->tablename.' WHERE no = '.intval($postlist); // 取單串\r
+               $line = $this->_pgsql_call($tmpSQL, array('Fetch the post content failed', __LINE__));\r
+\r
+               return $this->_ArrangeArrayStructure($line); // 輸出陣列結構\r
+       }\r
+\r
+       /* 刪除舊附件 (輸出附件清單) */\r
+       function delOldAttachments($total_size, $storage_max, $warnOnly=true){\r
+               global $FileIO;\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $arr_warn = $arr_kill = array(); // 警告 / 即將被刪除標記陣列\r
+               $result = $this->_pgsql_call('SELECT no,ext,tim FROM '.$this->tablename." WHERE ext <> '' ORDER BY no",\r
+                       array('Get the old post failed', __LINE__));\r
+               while(list($dno, $dext, $dtim) = pg_fetch_array($result)){ // 個別跑舊文迴圈\r
+                       $dfile = $dtim.$dext; // 附加檔案名稱\r
+                       $dthumb = $dtim.'s.jpg'; // 預覽檔案名稱\r
+                       if($FileIO->imageExists($dfile)){ $total_size -= $FileIO->getImageFilesize($dfile) / 1024; $arr_kill[] = $dno; $arr_warn[$dno] = 1; } // 標記刪除\r
+                       if($FileIO->imageExists($dthumb)) $total_size -= $FileIO->getImageFilesize($dthumb) / 1024;\r
+                       if($total_size < $storage_max) break;\r
+               }\r
+               pg_free_result($result);\r
+               return $warnOnly ? $arr_warn : $this->removeAttachments($arr_kill);\r
+       }\r
+\r
+       /* 刪除文章 */\r
+       function removePosts($posts){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+               if(count($posts)==0) return array();\r
+\r
+               $files = $this->removeAttachments($posts, true); // 先遞迴取得刪除文章及其回應附件清單\r
+               $pno = implode(', ', $posts); // ID字串\r
+               $this->_pgsql_call('DELETE FROM '.$this->tablename.' WHERE no IN ('.$pno.') OR resto IN('.$pno.')',\r
+                       array('Delete old posts and replies failed', __LINE__)); // 刪掉文章\r
+               return $files;\r
+       }\r
+\r
+       /* 刪除附件 (輸出附件清單) */\r
+       function removeAttachments($posts, $recursion=false){\r
+               global $FileIO;\r
+               if(!$this->prepared) $this->dbPrepare();\r
+               if(count($posts)==0) return array();\r
+\r
+               $files = array();\r
+               $pno = implode(', ', $posts); // ID字串\r
+               if($recursion) $tmpSQL = 'SELECT ext,tim FROM '.$this->tablename.' WHERE (no IN ('.$pno.') OR resto IN('.$pno.")) AND ext <> ''"; // 遞迴取出 (含回應附件)\r
+               else $tmpSQL = 'SELECT ext,tim FROM '.$this->tablename.' WHERE no IN ('.$pno.") AND ext <> ''"; // 只有指定的編號\r
+\r
+               $result = $this->_pgsql_call($tmpSQL, array('Get attachments of the post failed', __LINE__));\r
+               while(list($dext, $dtim) = pg_fetch_array($result)){ // 個別跑迴圈\r
+                       $dfile = $dtim.$dext; // 附加檔案名稱\r
+                       $dthumb = $dtim.'s.jpg'; // 預覽檔案名稱\r
+                       if($FileIO->imageExists($dfile)) $files[] = $dfile;\r
+                       if($FileIO->imageExists($dthumb)) $files[] = $dthumb;\r
+               }\r
+               pg_free_result($result);\r
+               return $files;\r
+       }\r
+
+       /* 新增文章/討論串 */\r
+       function addPost($no, $resto, $md5chksum, $category, $tim, $ext, $imgw, $imgh, $imgsize, $filename, $tw, $th, $pwd, $now, $name, $email, $sub, $com, $host, $age=false, $status='') {\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $time = (int)substr($tim, 0, -3); // 13位數的數字串是檔名,10位數的才是時間數值
+               $updatetime = gmdate('Y-m-d H:i:s'); // 更動時間 (UTC)
+               $resto = intval($resto);\r               if($resto){ // 新增回應
+                       $root = '1980-01-01 00:00:00';
+                       if($age){ // 推文
+                               $this->_pgsql_call('UPDATE '.$this->tablename.' SET root = \''.$updatetime.'\' WHERE no = '.$resto,\r                                    array('Push the post failed', __LINE__)); // 將被回應的文章往上移動
+                       }
+               }else $root = $updatetime; // 新增討論串, 討論串最後被更新時間
+
+               if($no === 0){ // init post 0\r
+                       $query = 'INSERT INTO '.$this->tablename.' (no,resto,root,time,md5chksum,category,tim,ext,imgw,imgh,imgsize,tw,th,pwd,now,name,email,sub,com,host,status) VALUES ('.
+               0,'. // 回應編號
+               $resto.",'". // 回應編號
+               $root."',". // 最後更新時間
+               $time.','. // 發文時間數值
+               "'$md5chksum',". // 附加檔案md5
+               "'".pg_escape_string($category)."',". // 分類標籤
+               "'$tim', '$ext',". // 附加檔名
+               (int)$imgw.','.(int)$imgh.",'".$imgsize."','".$filename."',".(int)$tw.','.(int)$th.','. // 圖檔長寬及檔案大小;預覽圖長寬
+               "'".pg_escape_string($pwd)."',".\r
+               "'$now',". // 時間(含ID)字串
+               "'".pg_escape_string($name)."',".\r
+               "'".pg_escape_string($email)."',".\r
+               "'".pg_escape_string($sub)."',".\r
+               "'".pg_escape_string($com)."',".\r
+               "'".pg_escape_string($host)."', '".pg_escape_string($status)."');";
+               }else{
+                       $query = 'INSERT INTO '.$this->tablename.' (resto,root,time,md5chksum,category,tim,ext,imgw,imgh,imgsize,tw,th,pwd,now,name,email,sub,com,host,status) VALUES ('.\r
+               $resto.",'". // 回應編號
+               $root."',". // 最後更新時間
+               $time.','. // 發文時間數值
+               "'$md5chksum',". // 附加檔案md5
+               "'".pg_escape_string($category)."',". // 分類標籤
+               "'$tim', '$ext',". // 附加檔名
+               (int)$imgw.','.(int)$imgh.",'".$imgsize."','".$filename."',".(int)$tw.','.(int)$th.','. // 圖檔長寬及檔案大小;預覽圖長寬
+               "'".pg_escape_string($pwd)."',".\r
+               "'$now',". // 時間(含ID)字串
+               "'".pg_escape_string($name)."',".\r
+               "'".pg_escape_string($email)."',".\r
+               "'".pg_escape_string($sub)."',".\r
+               "'".pg_escape_string($com)."',".\r
+               "'".pg_escape_string($host)."', '".pg_escape_string($status)."');";
+               }
+               $this->_pgsql_call($query, array('Insert a new post failed', __LINE__));\r
+       }\r
+\r
+       /* 檢查是否連續投稿 */\r
+       function isSuccessivePost($lcount, $com, $timestamp, $pass, $passcookie, $host, $isupload){\r
+               global $FileIO;\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               if(!$this->ENV['PERIOD.POST']) return false; // 關閉連續投稿檢查\r
+               $timestamp = intval($timestamp);\r
+               $tmpSQL = 'SELECT pwd,host FROM '.$this->tablename.' WHERE time > '.($timestamp - (int)$this->ENV['PERIOD.POST']); // 一般投稿時間檢查\r
+               if($isupload) $tmpSQL .= ' OR time > '.($timestamp - (int)$this->ENV['PERIOD.IMAGEPOST']); // 附加圖檔的投稿時間檢查 (與下者兩者擇一)\r
+               else $tmpSQL .= " OR md5(com) = '".md5($com)."'"; // 內文一樣的檢查 (與上者兩者擇一)\r
+\r
+               $result = $this->_pgsql_call($tmpSQL, array('Get the post to check the succession failed', __LINE__));\r
+               while(list($lpwd, $lhost) = pg_fetch_array($result)){\r
+                       // 判斷為同一人發文且符合連續投稿條件\r
+                       if($host==$lhost || $pass==$lpwd || $passcookie==$lpwd) return true;\r
+               }\r
+               return false;\r
+       }\r
+\r
+       /* 檢查是否重複貼圖 */\r
+       function isDuplicateAttachment($lcount, $md5hash){\r
+               global $FileIO;\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $result = $this->_pgsql_call('SELECT tim,ext FROM '.$this->tablename." WHERE ext <> '' AND md5chksum = '$md5hash' ORDER BY no DESC",\r
+                       array('Get the post to check the duplicate attachment failed', __LINE__));\r
+               while(list($ltim, $lext) = pg_fetch_array($result)){\r
+                       if($FileIO->imageExists($ltim.$lext)) return true; // 有相同檔案\r
+               }\r
+               return false;\r
+       }\r
+\r
+       /* 有此討論串? */\r
+       function isThread($no){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $result = $this->_pgsql_call('SELECT no FROM '.$this->tablename.' WHERE no = '.intval($no).' AND resto = 0');\r
+               return pg_fetch_array($result) ? true : false;\r
+       }\r
+\r
+       /* 搜尋文章 */\r
+       function searchPost($keyword, $field, $method){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $keyword_cnt = count($keyword);\r
+               $SearchQuery = 'SELECT * FROM '.$this->tablename." WHERE {$field} ILIKE '%".pg_escape_string($keyword[0])."%'";\r
+               if($keyword_cnt > 1){\r
+                       for($i = 1; $i < $keyword_cnt; $i++){\r
+                               $SearchQuery .= " {$method} {$field} ILIKE '%".pg_escape_string($keyword[$i])."%'"; // 多重字串交集 / 聯集搜尋\r
+                       }\r
+               }\r
+               $SearchQuery .= ' ORDER BY no DESC'; // 按照號碼大小排序\r
+               $line = $this->_pgsql_call($SearchQuery, array('Search the post failed', __LINE__));\r
+               return $this->_ArrangeArrayStructure($line); // 輸出陣列結構\r
+       }\r
+\r
+       /* 搜尋類別標籤 */\r
+       function searchCategory($category){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $foundPosts = array();\r
+               $SearchQuery = 'SELECT no FROM '.$this->tablename." WHERE category ~* ',".pg_escape_string($category).",' ORDER BY no DESC";\r
+               $line = $this->_pgsql_call($SearchQuery, array('Search the category failed', __LINE__));\r
+               while($rows = pg_fetch_array($line)) $foundPosts[] = $rows[0];\r
+               pg_free_result($line);\r
+               return $foundPosts;\r
+       }\r
+\r
+       /* 取得文章屬性 */\r
+       function getPostStatus($status){\r
+               return new FlagHelper($status); // 回傳 FlagHelper 物件\r
+       }\r
+\r
+       /* 更新文章 */\r
+       function updatePost($no, $newValues){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $no = intval($no);\r
+               $chk = array('resto', 'md5chksum', 'category', 'tim', 'ext', 'imgw', 'imgh', 'imgsize', 'filename', 'tw', 'th', 'pwd', 'now', 'name', 'email', 'sub', 'com', 'host', 'status');\r
+               foreach($chk as $c){\r
+                       if(isset($newValues[$c])){\r
+                               $this->_pgsql_call('UPDATE '.$this->tablename." SET $c = '".pg_escape_string($newValues[$c])."' WHERE no = ".$no,\r
+                                       array('Update the field of the post failed', __LINE__)); // 更新討論串屬性\r
+                       }\r
+               }\r
+       }\r
+\r
+       /* 設定文章屬性 */\r
+       function setPostStatus($no, $newStatus){\r
+               $this->updatePost($no, array('status' => $newStatus));\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/lib/pio/pio.sqlite.php b/lib/pio/pio.sqlite.php
new file mode 100755 (executable)
index 0000000..07a3baa
--- /dev/null
@@ -0,0 +1,440 @@
+<?php\r
+/**\r
+ * PIO SQLite API\r
+ *\r
+ * 提供存取以 SQLite 資料庫構成的資料結構後端的物件\r
+ *\r
+ * @package PMCLibrary\r
+ * @version $Id: pio.sqlite.php 671 2008-09-20 05:54:15Z scribe $\r
+ * @date $Date: 2008-09-20 13:54:15 +0800 (星期六, 20 九月 2008) $\r
+ */\r
+\r
+class PIOsqlite{\r
+       var $ENV, $dbname, $tablename; // Local Constant\r
+       var $con, $prepared, $useTransaction; // Local Global\r
+\r
+       function PIOsqlite($connstr='', $ENV){\r
+               $this->ENV = $ENV;\r
+               $this->prepared = 0;\r
+               if($connstr) $this->dbConnect($connstr);\r
+       }\r
+\r
+       /* private 攔截SQL錯誤 */\r
+       function _error_handler($errarray, $query=''){\r
+               $err = 'Pixmicat! SQL Error: '.$errarray[0].' on line '.$errarray[1];\r
+               //error_log($err."\n".sqlite_last_error($this->con).': '.sqlite_error_string(sqlite_last_error($this->con))."\n".$query."\n\n", 3, 'error.log');\r
+               trigger_error($err, E_USER_ERROR);\r
+               exit();\r
+       }\r
+\r
+       /* private 使用SQL字串和SQLite要求 */\r
+       function _sqlite_call($query, $errarray=false){\r
+               $resource = sqlite_query($this->con, $query);\r
+               if(is_array($errarray) && $resource===false) $this->_error_handler($errarray, $query);\r
+               else return $resource;\r
+       }\r
+\r
+       /* private SQLite的sqlite_result頂替函數 */\r
+       function _sqlite_result($rh, $row, $field){\r
+               $currrow = sqlite_fetch_all($rh, SQLITE_NUM);\r
+               return $currrow[$row][$field];\r
+       }\r
+\r
+       /* PIO模組版本 */\r
+       function pioVersion(){\r
+               return '0.6 (v20100404)';\r
+       }\r
+\r
+       /* 處理連線字串/連接 */\r
+       function dbConnect($connStr){\r
+               // 格式: sqlite://SQLite檔案之位置/資料表/\r
+               // 示例: sqlite://yotsubanome.db/img_loog/\r
+               if(preg_match('/^sqlite:\/\/(.*)\/(.*)\/$/i', $connStr, $linkinfos)){\r
+                       $this->dbname = $linkinfos[1]; // SQLite檔案之位置\r
+                       $this->tablename = $linkinfos[2]; // 資料表名稱\r
+               }\r
+       }\r
+\r
+       /* 初始化 */\r
+       function dbInit($isAddInitData=true){\r
+               $this->dbPrepare();\r
+               if(sqlite_num_rows(sqlite_query($this->con, "SELECT name FROM sqlite_master WHERE name LIKE '".$this->tablename."'"))===0){ // 資料表不存在\r
+                       $result = 'CREATE TABLE '.$this->tablename.' (\r
+       "no" INTEGER  NOT NULL PRIMARY KEY,\r
+       "resto" INTEGER  NOT NULL,\r
+       "root" TIMESTAMP DEFAULT \'0\' NOT NULL,\r
+       "time" INTEGER  NOT NULL,\r
+       "md5chksum" VARCHAR(32)  NOT NULL,\r
+       "category" VARCHAR(255)  NOT NULL,\r
+       "tim" INTEGER  NOT NULL,\r
+       "ext" VARCHAR(4)  NOT NULL,\r
+       "imgw" INTEGER  NOT NULL,\r
+       "imgh" INTEGER  NOT NULL,\r
+       "imgsize" VARCHAR(10)  NOT NULL,
+       "filename" VARCHAR(255)  NOT NULL,\r
+       "tw" INTEGER  NOT NULL,\r
+       "th" INTEGER  NOT NULL,\r
+       "pwd" VARCHAR(8)  NOT NULL,\r
+       "now" VARCHAR(255)  NOT NULL,\r
+       "name" VARCHAR(255)  NOT NULL,\r
+       "email" VARCHAR(255)  NOT NULL,\r
+       "sub" VARCHAR(255)  NOT NULL,\r
+       "com" TEXT  NOT NULL,\r
+       "host" VARCHAR(255)  NOT NULL,\r
+       "status" VARCHAR(255)  NOT NULL\r
+       );'; // PIO Structure V4
+                       $idx = array('resto', 'root', 'time');\r
+                       foreach($idx as $x){\r
+                               $result .= 'CREATE INDEX IDX_'.$this->tablename.'_'.$x.' ON '.$this->tablename.'('.$x.');';\r
+                       }
+                       $result .= 'CREATE INDEX IDX_'.$this->tablename.'_resto_no ON '.$this->tablename.'(resto,no);';\r
+                       if($isAddInitData)\r
+                               $result .= 'INSERT INTO '.$this->tablename.' (no,resto,root,time,md5chksum,category,tim,ext,imgw,imgh,imgsize,filename,tw,th,pwd,now,name,email,sub,com,host,status) VALUES (0, 0, datetime("now"), 1111111111, "", "", 1111111111111, "", 0, 0, "", "", 0, 0, "", "08/11/08(土)10:24:04", "【スパーキー(④ ^ヮ^)】", "", "'.$this->ENV['NOTITLE'].'", "'.$this->ENV['NOCOMMENT'].'", "", "");';
+                       sqlite_exec($this->con, $result); // 正式新增資料表\r
+                       $this->dbCommit();\r
+               }\r
+       }\r
+\r
+       /* 準備/讀入 */\r
+       function dbPrepare($transaction=true){\r
+               if($this->prepared) return true;\r
+\r
+               if(@!$this->con=sqlite_popen($this->dbname, 0666)) $this->_error_handler(array('Open database failed', __LINE__));\r
+               $this->useTransaction = $transaction;\r
+               if($transaction) @sqlite_exec($this->con, 'BEGIN;'); // 啟動交易性能模式\r
+\r
+               $this->prepared = 1;\r
+       }\r
+\r
+       /* 提交/儲存 */\r
+       function dbCommit(){\r
+               if(!$this->prepared) return false;\r
+               if($this->useTransaction) @sqlite_exec($this->con, 'COMMIT;'); // 交易性能模式提交\r
+       }\r
+\r
+       /* 資料表維護 */\r
+       function dbMaintanence($action, $doit=false){\r
+               switch($action) {\r
+                       case 'optimize':\r
+                               if($doit){\r
+                                       $this->dbPrepare(false);\r
+                                       if($this->_sqlite_call('VACUUM '.$this->tablename)) return true;\r
+                                       else return false;\r
+                               }else return true; // 支援最佳化資料表\r
+                               break;\r
+                       case 'export':\r
+                               if($doit){\r
+                                       $this->dbPrepare(false);\r
+                                       $gp = gzopen('piodata.log.gz', 'w9');\r
+                                       gzwrite($gp, $this->dbExport());\r
+                                       gzclose($gp);\r
+                                       return '<a href="piodata.log.gz">下載 piodata.log.gz 中介檔案</a>';\r
+                               }else return true; // 支援匯出資料\r
+                               break;\r
+                       case 'check':\r
+                       case 'repair':\r
+                       default: return false; // 不支援\r
+               }\r
+       }\r
+\r
+       /* 匯入資料來源 */\r
+       function dbImport($data){\r
+               $this->dbInit(false); // 僅新增結構不新增資料\r
+               $data = explode("\r\n", $data);\r
+               $data_count = count($data) - 1;\r
+               $replaceComma = create_function('$txt', 'return str_replace("&#44;", ",", $txt);');\r
+               for($i = 0; $i < $data_count; $i++){\r
+                       $line = array_map($replaceComma, explode(',', $data[$i])); // 取代 &#44; 為 ,\r
+                       $SQL = 'INSERT INTO '.$this->tablename.' (no,resto,root,time,md5chksum,category,tim,ext,imgw,imgh,imgsize,filename,tw,th,pwd,now,name,email,sub,com,host,status) VALUES ('.\r
+       $line[0].','.\r
+       $line[1].',\''.\r
+       $line[2].'\','.\r
+       substr($line[5], 0, 10).',\''.\r
+       sqlite_escape_string($line[3]).'\',\''.\r
+       sqlite_escape_string($line[4]).'\','.\r
+       $line[5].',\''.sqlite_escape_string($line[6]).'\','.\r
+       $line[7].','.$line[8].',\''.sqlite_escape_string($line[9]).','.sqlite_escape_string($line[10]).'\','.$line[11].','.$line[12].',\''.\r
+       sqlite_escape_string($line[13]).'\',\''.\r
+       sqlite_escape_string($line[14]).'\',\''.\r
+       sqlite_escape_string($line[15]).'\',\''.\r
+       sqlite_escape_string($line[16]).'\',\''.\r
+       sqlite_escape_string($line[17]).'\',\''.\r
+       sqlite_escape_string($line[18]).'\',\''.\r
+       sqlite_escape_string($line[19]).'\',\''.\r
+       sqlite_escape_string($line[20]).'\')';\r
+                       $this->_sqlite_call($SQL, array('Insert a new post failed', __LINE__));\r
+               }\r
+               $this->dbCommit(); // 送交\r
+               return true;\r
+       }\r
+\r
+       /* 匯出資料來源 */\r
+       function dbExport(){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+               $line = $this->_sqlite_call('SELECT no,resto,root,md5chksum,category,tim,ext,imgw,imgh,imgsize,filename,tw,th,pwd,now,name,email,sub,com,host,status FROM '.$this->tablename.' ORDER BY no DESC',\r
+                       array('Export posts failed', __LINE__));\r
+               $data = '';\r
+               $replaceComma = create_function('$txt', 'return str_replace(",", "&#44;", $txt);');\r
+               while($row = sqlite_fetch_array($line, SQLITE_ASSOC)){\r
+                       $row = array_map($replaceComma, $row); // 取代 , 為 &#44;\r
+                       $data .= implode(',', $row).",\r\n";\r
+               }\r
+               return $data;\r
+       }\r
+\r
+       /* 文章數目 */\r
+       function postCount($resno=0){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               if($resno){ // 回傳討論串總文章數目\r
+                       $line = $this->_sqlite_call('SELECT COUNT(no) FROM '.$this->tablename.' WHERE resto = '.intval($resno),\r
+                               array('Fetch count in thread failed', __LINE__));\r
+                       $countline = $this->_sqlite_result($line, 0, 0) + 1;\r
+               }else{ // 回傳總文章數目\r
+                       $line = $this->_sqlite_call('SELECT COUNT(no) FROM '.$this->tablename, array('Fetch count of posts failed', __LINE__));\r
+                       $countline = $this->_sqlite_result($line, 0, 0);\r
+               }\r
+               return $countline;\r
+       }\r
+\r
+       /* 討論串數目 */\r
+       function threadCount(){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $tree = $this->_sqlite_call('SELECT COUNT(no) FROM '.$this->tablename.' WHERE resto = 0',\r
+                       array('Fetch count of threads failed', __LINE__));\r
+               $counttree = $this->_sqlite_result($tree, 0, 0); // 計算討論串目前資料筆數\r
+               return $counttree;\r
+       }\r
+\r
+       /* 取得最後文章編號 */\r
+       function getLastPostNo($state){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               if($state=='afterCommit'){ // 送出後的最後文章編號\r
+                       $tree = $this->_sqlite_call('SELECT MAX(no) FROM '.$this->tablename, array('Get the last No. failed', __LINE__));\r
+                       $lastno = $this->_sqlite_result($tree, 0, 0);\r
+                       return $lastno;\r
+               }else return 0; // 其他狀態沒用\r
+       }\r
+\r
+       /* 輸出文章清單 */\r
+       function fetchPostList($resno=0, $start=0, $amount=0){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $line = array();\r
+               $resno = intval($resno);\r
+               if($resno){ // 輸出討論串的結構 (含自己, EX : 1,2,3,4,5,6)\r
+                       $tmpSQL = 'SELECT no FROM '.$this->tablename.' WHERE no = '.$resno.' OR resto = '.$resno.' ORDER BY no';\r
+               }else{ // 輸出所有文章編號,新的在前\r
+                       $tmpSQL = 'SELECT no FROM '.$this->tablename.' ORDER BY no DESC';\r
+                       $start = intval($start); $amount = intval($amount);\r
+                       if($amount) $tmpSQL .= " LIMIT {$start}, {$amount}"; // 有指定數量才用 LIMIT\r
+               }\r
+               $tree = $this->_sqlite_call($tmpSQL, array('Fetch post list failed', __LINE__));\r
+               while($rows = sqlite_fetch_array($tree)) $line[] = $rows[0]; // 迴圈\r
+               return $line;\r
+       }\r
+\r
+       /* 輸出討論串清單 */\r
+       function fetchThreadList($start=0, $amount=0, $isDESC=false) {\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $start = intval($start); $amount = intval($amount);\r
+               $treeline = array();\r
+               $tmpSQL = 'SELECT no FROM '.$this->tablename.' WHERE resto = 0 ORDER BY '.($isDESC ? 'no' : 'root').' DESC';\r
+               if($amount) $tmpSQL .= " LIMIT {$start}, {$amount}"; // 有指定數量才用 LIMIT\r
+               $tree = $this->_sqlite_call($tmpSQL, array('Fetch thread list failed', __LINE__));\r
+               while($rows = sqlite_fetch_array($tree)) $treeline[] = $rows[0]; // 迴圈\r
+               return $treeline;\r
+       }\r
+\r
+       /* 輸出文章 */\r
+       function fetchPosts($postlist){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               if(is_array($postlist)){ // 取多串\r
+                       $pno = implode(', ', $postlist); // ID字串\r
+                       $tmpSQL = 'SELECT * FROM '.$this->tablename.' WHERE no IN ('.$pno.') ORDER BY no';\r
+                       if(count($postlist) > 1){ if($postlist[0] > $postlist[1]) $tmpSQL .= ' DESC'; } // 由大排到小\r
+               }else $tmpSQL = 'SELECT * FROM '.$this->tablename.' WHERE no = '.intval($postlist); // 取單串\r
+               $line = $this->_sqlite_call($tmpSQL, array('Fetch the post content failed', __LINE__));\r
+               return sqlite_fetch_all($line, SQLITE_ASSOC);\r
+       }\r
+\r
+       /* 刪除舊附件 (輸出附件清單) */\r
+       function delOldAttachments($total_size, $storage_max, $warnOnly=true){\r
+               global $FileIO;\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $arr_warn = $arr_kill = array(); // 警告 / 即將被刪除標記陣列\r
+               $result = $this->_sqlite_call('SELECT no,ext,tim FROM '.$this->tablename.' WHERE ext <> \'\' ORDER BY no',\r
+                       array('Get the old post failed', __LINE__));\r
+               while(list($dno, $dext, $dtim) = sqlite_fetch_array($result)){ // 個別跑舊文迴圈\r
+                       $dfile = $dtim.$dext; // 附加檔案名稱\r
+                       $dthumb = $dtim.'s.jpg'; // 預覽檔案名稱\r
+                       if($FileIO->imageExists($dfile)){ $total_size -= $FileIO->getImageFilesize($dfile) / 1024; $arr_kill[] = $dno; $arr_warn[$dno] = 1; } // 標記刪除\r
+                       if($FileIO->imageExists($dthumb)) $total_size -= $FileIO->getImageFilesize($dthumb) / 1024;\r
+                       if($total_size < $storage_max) break;\r
+               }\r
+               return $warnOnly ? $arr_warn : $this->removeAttachments($arr_kill);\r
+       }\r
+\r
+       /* 刪除文章 */\r
+       function removePosts($posts){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+               if(count($posts)==0) return array();\r
+\r
+               $files = $this->removeAttachments($posts, true); // 先遞迴取得刪除文章及其回應附件清單\r
+               $pno = implode(', ', $posts); // ID字串\r
+               $this->_sqlite_call('DELETE FROM '.$this->tablename.' WHERE no IN ('.$pno.') OR resto IN('.$pno.')',\r
+                       array('Delete old posts and replies failed', __LINE__)); // 刪掉文章\r
+               return $files;\r
+       }\r
+\r
+       /* 刪除附件 (輸出附件清單) */\r
+       function removeAttachments($posts, $recursion=false){\r
+               global $FileIO;\r
+               if(!$this->prepared) $this->dbPrepare();\r
+               if(count($posts)==0) return array();\r
+\r
+               $files = array();\r
+               $pno = implode(', ', $posts); // ID字串\r
+               if($recursion) $tmpSQL = 'SELECT ext,tim FROM '.$this->tablename.' WHERE (no IN ('.$pno.') OR resto IN('.$pno.")) AND ext <> ''"; // 遞迴取出 (含回應附件)\r
+               else $tmpSQL = 'SELECT ext,tim FROM '.$this->tablename.' WHERE no IN ('.$pno.") AND ext <> ''"; // 只有指定的編號\r
+\r
+               $result = $this->_sqlite_call($tmpSQL, array('Get attachments of the post failed', __LINE__));\r
+               while(list($dext, $dtim) = sqlite_fetch_array($result)){ // 個別跑迴圈\r
+                       $dfile = $dtim.$dext; // 附加檔案名稱\r
+                       $dthumb = $dtim.'s.jpg'; // 預覽檔案名稱\r
+                       if($FileIO->imageExists($dfile)) $files[] = $dfile;\r
+                       if($FileIO->imageExists($dthumb)) $files[] = $dthumb;\r
+               }\r
+               return $files;\r
+       }\r
+\r
+       /* 新增文章/討論串 */\r
+       function addPost($no, $resto, $md5chksum, $category, $tim, $ext, $imgw, $imgh, $imgsize, $filename, $tw, $th, $pwd, $now, $name, $email, $sub, $com, $host, $age=false, $status='') {\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $time = (int)substr($tim, 0, -3); // 13位數的數字串是檔名,10位數的才是時間數值\r
+               $updatetime = gmdate('Y-m-d H:i:s'); // 更動時間 (UTC)\r
+               $resto = intval($resto);\r
+               if($resto){ // 新增回應\r
+                       $root = '0';\r
+                       if($age){ // 推文\r
+                               $this->_sqlite_call('UPDATE '.$this->tablename.' SET root = "'.$updatetime.'" WHERE no = '.$resto,\r
+                                       array('Push the post failed', __LINE__)); // 將被回應的文章往上移動\r
+                       }\r
+               }else $root = $updatetime; // 新增討論串, 討論串最後被更新時間\r
+\r
+               $query = 'INSERT INTO '.$this->tablename.' (resto,root,time,md5chksum,category,tim,ext,imgw,imgh,imgsize,filename,tw,th,pwd,now,name,email,sub,com,host,status) VALUES ('.\r
+       $resto.','. // 回應編號
+       "'$root',". // 最後更新時間
+       $time.','. // 發文時間數值
+       "'$md5chksum',". // 附加檔案md5
+       "'".sqlite_escape_string($category)."',". // 分類標籤
+       "$tim, '$ext',". // 附加檔名
+       (int)$imgw.','.(int)$imgh.",'".$imgsize."','".$filename."',".(int)$tw.','.(int)$th.','. // 圖檔長寬及檔案大小;預覽圖長寬
+       "'".sqlite_escape_string($pwd)."',".\r
+       "'$now',". // 時間(含ID)字串
+       "'".sqlite_escape_string($name)."',".\r
+       "'".sqlite_escape_string($email)."',".\r
+       "'".sqlite_escape_string($sub)."',".\r
+       "'".sqlite_escape_string($com)."',".\r
+       "'".sqlite_escape_string($host)."', '".sqlite_escape_string($status)."')";
+               $this->_sqlite_call($query, array('Insert a new post failed', __LINE__));\r
+       }\r
+\r
+       /* 檢查是否連續投稿 */\r
+       function isSuccessivePost($lcount, $com, $timestamp, $pass, $passcookie, $host, $isupload){\r
+               global $FileIO;\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               if(!$this->ENV['PERIOD.POST']) return false; // 關閉連續投稿檢查\r
+               $timestamp = intval($timestamp);\r
+               $tmpSQL = 'SELECT pwd,host FROM '.$this->tablename.' WHERE time > '.($timestamp - (int)$this->ENV['PERIOD.POST']); // 一般投稿時間檢查\r
+               if($isupload) $tmpSQL .= ' OR time > '.($timestamp - (int)$this->ENV['PERIOD.IMAGEPOST']); // 附加圖檔的投稿時間檢查 (與下者兩者擇一)\r
+               else $tmpSQL .= " OR php('md5', com) = '".md5($com)."'"; // 內文一樣的檢查 (與上者兩者擇一) * 此取巧採用了PHP登錄的函式php來叫用md5\r
+\r
+               $result = $this->_sqlite_call($tmpSQL, array('Get the post to check the succession failed', __LINE__));\r
+               while(list($lpwd, $lhost) = sqlite_fetch_array($result)){\r
+                       // 判斷為同一人發文且符合連續投稿條件\r
+                       if($host==$lhost || $pass==$lpwd || $passcookie==$lpwd) return true;\r
+               }\r
+               return false;\r
+       }\r
+\r
+       /* 檢查是否重複貼圖 */\r
+       function isDuplicateAttachment($lcount, $md5hash){\r
+               global $FileIO;\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $result = $this->_sqlite_call('SELECT tim,ext FROM '.$this->tablename." WHERE ext <> '' AND md5chksum = '$md5hash' ORDER BY no DESC",\r
+                       array('Get the post to check the duplicate attachment failed', __LINE__));\r
+               while(list($ltim, $lext) = sqlite_fetch_array($result)){\r
+                       if($FileIO->imageExists($ltim.$lext)) return true; // 有相同檔案\r
+               }\r
+               return false;\r
+       }\r
+\r
+       /* 有此討論串? */\r
+       function isThread($no){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $result = $this->_sqlite_call('SELECT no FROM '.$this->tablename.' WHERE no = '.intval($no).' AND resto = 0');\r
+               return sqlite_fetch_array($result) ? true : false;\r
+       }\r
+\r
+       /* 搜尋文章 */\r
+       function searchPost($keyword, $field, $method){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $keyword_cnt = count($keyword);\r
+               $SearchQuery = 'SELECT * FROM '.$this->tablename." WHERE {$field} LIKE '%".sqlite_escape_string($keyword[0])."%'";\r
+               if($keyword_cnt > 1){\r
+                       for($i = 1; $i < $keyword_cnt; $i++){\r
+                               $SearchQuery .= " {$method} {$field} LIKE '%".sqlite_escape_string($keyword[$i])."%'"; // 多重字串交集 / 聯集搜尋\r
+                       }\r
+               }\r
+               $SearchQuery .= ' ORDER BY no DESC'; // 按照號碼大小排序\r
+               $line = $this->_sqlite_call($SearchQuery, array('Search the post failed', __LINE__));\r
+               return sqlite_fetch_all($line, SQLITE_ASSOC);\r
+       }\r
+\r
+       /* 搜尋類別標籤 */\r
+       function searchCategory($category){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $foundPosts = array();\r
+               $SearchQuery = 'SELECT no FROM '.$this->tablename." WHERE lower(category) LIKE '%,".strtolower(sqlite_escape_string($category)).",%' ORDER BY no DESC";\r
+               $line = $this->_sqlite_call($SearchQuery, array('Search the category failed', __LINE__));\r
+               while($rows = sqlite_fetch_array($line)) $foundPosts[] = $rows[0];\r
+               return $foundPosts;\r
+       }\r
+\r
+       /* 取得文章屬性 */\r
+       function getPostStatus($status){\r
+               return new FlagHelper($status); // 回傳 FlagHelper 物件\r
+       }\r
+\r
+       /* 更新文章 */\r
+       function updatePost($no, $newValues){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $no = intval($no);\r
+               $chk = array('resto', 'md5chksum', 'category', 'tim', 'ext', 'imgw', 'imgh', 'imgsize', 'filename', 'tw', 'th', 'pwd', 'now', 'name', 'email', 'sub', 'com', 'host', 'status');\r
+               foreach($chk as $c){\r
+                       if(isset($newValues[$c])){\r
+                               $this->_sqlite_call('UPDATE '.$this->tablename." SET $c = '".sqlite_escape_string($newValues[$c])."' WHERE no = $no",\r
+                                       array('Update the field of the post failed', __LINE__)); // 更新討論串屬性\r
+                       }\r
+               }\r
+       }\r
+\r
+       /* 設定文章屬性 */\r
+       function setPostStatus($no, $newStatus){\r
+               $this->updatePost($no, array('status' => $newStatus));\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/lib/pio/pio.sqlite3.php b/lib/pio/pio.sqlite3.php
new file mode 100755 (executable)
index 0000000..510c451
--- /dev/null
@@ -0,0 +1,420 @@
+<?php\r
+/**\r
+ * PIO SQLite3 (PDO) API\r
+ *\r
+ * 提供存取以 SQLite3 資料庫構成的資料結構後端的物件 (需要 PHP 5.1.0 以上並開啟 PDO 功能)\r
+ *\r
+ * @package PMCLibrary\r
+ * @version $Id: pio.sqlite3.php 658 2008-08-06 15:59:17Z scribe $\r
+ * @date $Date: 2008-08-06 23:59:17 +0800 (星期三, 06 八月 2008) $\r
+ */\r
+\r
+class PIOsqlite3{\r
+       private $ENV, $DSN, $tablename; // Local Constant\r
+       private $con, $prepared, $useTransaction; // Local Global\r
+\r
+       public function __construct($connstr='', $ENV){\r
+               $this->ENV = $ENV;\r
+               $this->prepared = false;\r
+               if($connstr) $this->dbConnect($connstr);\r
+       }\r
+\r
+       /* private 攔截SQL錯誤 */\r
+       private function _error_handler($errtext, $errline){\r
+               $err = "Pixmicat! SQL Error: $errtext on line $errline";\r
+               //error_log($err."\n".print_r($this->con->errorInfo(),true)."\n", 3, 'error.log');\r
+               trigger_error($err, E_USER_ERROR);\r
+               exit();\r
+       }\r
+\r
+       /* PIO模組版本 */\r
+       function pioVersion(){\r
+               return '0.6 (v20100404)';\r
+       }\r
+\r
+       /* 處理連線字串/連接 */\r
+       public function dbConnect($connStr){\r
+               // 格式: sqlite3://資料庫檔案之位置/資料表/\r
+               // 示例: sqlite://yotsubanome.db/img_loog/\r
+               //     sqlite3://:memory:/img_loog/\r
+               if(preg_match('/^sqlite3:\/\/(.*)\/(.*)\/$/i', $connStr, $linkinfos)){\r
+                       $this->DSN = 'sqlite:'.$linkinfos[1];\r
+                       $this->tablename = $linkinfos[2];\r
+               }\r
+       }\r
+\r
+       /* 初始化 */\r
+       public function dbInit($isAddInitData=true){\r
+               $this->dbPrepare();\r
+               $nline = $this->con->query('SELECT COUNT(name) FROM sqlite_master WHERE name LIKE "'.$this->tablename.'"')->fetch();\r
+               if($nline[0]==='0'){ // 資料表不存在\r
+                       $result = 'CREATE TABLE '.$this->tablename.' (\r
+       "no" INTEGER  NOT NULL PRIMARY KEY,\r
+       "resto" INTEGER  NOT NULL,\r
+       "root" TIMESTAMP DEFAULT \'0\' NOT NULL,\r
+       "time" INTEGER  NOT NULL,\r
+       "md5chksum" VARCHAR(32)  NOT NULL,\r
+       "category" VARCHAR(255)  NOT NULL,\r
+       "tim" INTEGER  NOT NULL,\r
+       "ext" VARCHAR(4)  NOT NULL,\r
+       "imgw" INTEGER  NOT NULL,\r
+       "imgh" INTEGER  NOT NULL,\r
+       "imgsize" VARCHAR(10)  NOT NULL,
+       "filename" VARCHAR(255)  NOT NULL,\r
+       "tw" INTEGER  NOT NULL,\r
+       "th" INTEGER  NOT NULL,\r
+       "pwd" VARCHAR(8)  NOT NULL,\r
+       "now" VARCHAR(255)  NOT NULL,\r
+       "name" VARCHAR(255)  NOT NULL,\r
+       "email" VARCHAR(255)  NOT NULL,\r
+       "sub" VARCHAR(255)  NOT NULL,\r
+       "com" TEXT  NOT NULL,\r
+       "host" VARCHAR(255)  NOT NULL,\r
+       "status" VARCHAR(255)  NOT NULL\r
+       );'; // PIO Structure V4\r
+                       $idx = array('resto', 'root', 'time');\r
+                       foreach($idx as $x) $result .= 'CREATE INDEX IDX_'.$this->tablename.'_'.$x.' ON '.$this->tablename.'('.$x.');';\r
+                       $result .= 'CREATE INDEX IDX_'.$this->tablename.'_resto_no ON '.$this->tablename.'(resto,no);';\r
+                       if($isAddInitData) $result .= 'INSERT INTO '.$this->tablename.' (no,resto,root,time,md5chksum,category,tim,ext,imgw,imgh,imgsize,filename,tw,th,pwd,now,name,email,sub,com,host,status) VALUES (0, 0, datetime("now"), 1111111111, "", "", 1111111111111, "", 0, 0, "", "", 0, 0, "", "08/11/08(土)10:24:04", "【スパーキー(④ ^ヮ^)】", "", "'.$this->ENV['NOTITLE'].'", "'.$this->ENV['NOCOMMENT'].'", "", "");';\r
+                       $this->con->exec($result);\r
+                       $this->dbCommit();\r
+               }\r
+       }\r
+\r
+       /* 準備/讀入 */\r
+       public function dbPrepare($transaction=false){\r
+               if($this->prepared) return true;\r
+\r
+               ($this->con = new PDO($this->DSN, '', '', array(PDO::ATTR_PERSISTENT => true))) or $this->_error_handler('Open database failed', __LINE__);\r
+               $this->useTransaction = $transaction;\r
+               if($transaction) @$this->con->beginTransaction(); // 啟動交易性能模式\r
+\r
+               $this->prepared = true;\r
+       }\r
+\r
+       /* 提交/儲存 */\r
+       public function dbCommit(){\r
+               if(!$this->prepared) return false;\r
+               if($this->useTransaction) @$this->con->commit(); // 交易性能模式提交\r
+       }\r
+\r
+       /* 資料表維護 */\r
+       public function dbMaintanence($action, $doit=false){\r
+               switch($action) {\r
+                       case 'optimize':\r
+                               if($doit){\r
+                                       $this->dbPrepare(false);\r
+                                       if($this->con->exec('VACUUM '.$this->tablename)!==false) return true;\r
+                                       else return false;\r
+                               }else return true; // 支援最佳化資料表\r
+                               break;\r
+                       case 'export':\r
+                               if($doit){\r
+                                       $this->dbPrepare(false);\r
+                                       $gp = gzopen('piodata.log.gz', 'w9');\r
+                                       gzwrite($gp, $this->dbExport());\r
+                                       gzclose($gp);\r
+                                       return '<a href="piodata.log.gz">下載 piodata.log.gz 中介檔案</a>';\r
+                               }else return true; // 支援匯出資料\r
+                               break;\r
+                       case 'check':\r
+                       case 'repair':\r
+                       default: return false; // 不支援\r
+               }\r
+       }\r
+\r
+       /* 匯入資料來源 */\r
+       public function dbImport($data){\r
+               $this->dbInit(false); // 僅新增結構不新增資料\r
+               $data = explode("\r\n", $data);\r
+               $data_count = count($data) - 1;\r
+               $replaceComma = create_function('$txt', 'return str_replace("&#44;", ",", $txt);');\r
+               $SQL = 'INSERT INTO '.$this->tablename.' (no,resto,root,time,md5chksum,category,tim,ext,imgw,imgh,imgsize,filename,tw,th,pwd,now,name,email,sub,com,host,status) VALUES '\r
+                               .'(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';\r
+               $PDOStmt = $this->con->prepare($SQL);\r
+               for($i = 0; $i < $data_count; $i++){\r
+                       $line = array_map($replaceComma, explode(',', $data[$i])); // 取代 &#44; 為 ,
+                       $tim = substr($line[5], 0, 10);\r
+                       $PDOStmt->bindValue(1, $line[0], PDO::PARAM_INT);\r
+                       $PDOStmt->bindValue(2, $line[1], PDO::PARAM_INT);\r
+                       $PDOStmt->bindValue(3, $line[2], PDO::PARAM_STR);\r
+                       $PDOStmt->bindValue(4, $tim, PDO::PARAM_INT);\r
+                       $PDOStmt->bindValue(5, $line[3], PDO::PARAM_STR);\r
+                       $PDOStmt->bindValue(6, $line[4], PDO::PARAM_STR);\r
+                       $PDOStmt->bindValue(7, $line[5], PDO::PARAM_INT);\r
+                       $PDOStmt->bindValue(8, $line[6], PDO::PARAM_STR);\r
+                       $PDOStmt->bindValue(9, $line[7], PDO::PARAM_INT);\r
+                       $PDOStmt->bindValue(10, $line[8], PDO::PARAM_INT);\r
+                       $PDOStmt->bindValue(11, $line[9], PDO::PARAM_STR);
+                       $PDOStmt->bindValue(12, $line[10], PDO::PARAM_STR);\r
+                       $PDOStmt->bindValue(13, $line[11], PDO::PARAM_INT);\r
+                       $PDOStmt->bindValue(14, $line[12], PDO::PARAM_INT);\r
+                       $PDOStmt->bindValue(15, $line[13], PDO::PARAM_STR);\r
+                       $PDOStmt->bindValue(16, $line[14], PDO::PARAM_STR);\r
+                       $PDOStmt->bindValue(17, $line[15], PDO::PARAM_STR);\r
+                       $PDOStmt->bindValue(18, $line[16], PDO::PARAM_STR);\r
+                       $PDOStmt->bindValue(19, $line[17], PDO::PARAM_STR);\r
+                       $PDOStmt->bindValue(20, $line[18], PDO::PARAM_STR);\r
+                       $PDOStmt->bindValue(21, $line[19], PDO::PARAM_STR);\r
+                       $PDOStmt->bindValue(22, $line[20], PDO::PARAM_STR);\r
+                       $PDOStmt->execute() or $this->_error_handler('Insert a new post failed', __LINE__);\r
+               }\r
+               $this->dbCommit(); // 送交\r
+               return true;\r
+       }\r
+\r
+       /* 匯出資料來源 */\r
+       public function dbExport(){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+               $line = $this->con->query('SELECT no,resto,root,md5chksum,category,tim,ext,imgw,imgh,imgsize,filename,tw,th,pwd,now,name,email,sub,com,host,status FROM '.$this->tablename.' ORDER BY no DESC');\r
+               $data = '';\r
+               $replaceComma = create_function('$txt', 'return str_replace(",", "&#44;", $txt);');\r
+               while($row = $line->fetch(PDO::FETCH_ASSOC)){\r
+                       $row = array_map($replaceComma, $row); // 取代 , 為 &#44;\r
+                       $data .= implode(',', $row).",\r\n";\r
+               }\r
+               return $data;\r
+       }\r
+\r
+       /* 文章數目 */\r
+       public function postCount($resno=0){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               if($resno){ // 一討論串文章總數目\r
+                       $line = $this->con->query('SELECT COUNT(no) FROM '.$this->tablename.' WHERE resto = '.intval($resno))->fetch();\r
+                       $countline = $line[0] + 1;\r
+               }else{ // 文章總數目\r
+                       $line = $this->con->query('SELECT COUNT(no) FROM '.$this->tablename)->fetch();\r
+                       $countline = $line[0];\r
+               }\r
+               return $countline;\r
+       }\r
+\r
+       /* 討論串數目 */\r
+       public function threadCount(){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $tree = $this->con->query('SELECT COUNT(no) FROM '.$this->tablename.' WHERE resto = 0')->fetch();\r
+               return $tree[0]; // 討論串目前數目\r
+       }\r
+\r
+       /* 取得最後文章編號 */\r
+       public function getLastPostNo($state){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               if($state=='afterCommit'){ // 送出後的最後文章編號\r
+                       $lastno = $this->con->query('SELECT MAX(no) FROM '.$this->tablename)->fetch();\r
+                       return $lastno[0];\r
+               }else return 0; // 其他狀態沒用\r
+       }\r
+\r
+       /* 輸出文章清單 */\r
+       public function fetchPostList($resno=0, $start=0, $amount=0){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $resno = intval($resno);\r
+               if($resno){ // 輸出討論串的結構 (含自己, EX : 1,2,3,4,5,6)\r
+                       $tmpSQL = 'SELECT no FROM '.$this->tablename.' WHERE no = '.$resno.' OR resto = '.$resno.' ORDER BY no';\r
+               }else{ // 輸出所有文章編號,新的在前\r
+                       $tmpSQL = 'SELECT no FROM '.$this->tablename.' ORDER BY no DESC';\r
+                       $start = intval($start); $amount = intval($amount);\r
+                       if($amount) $tmpSQL .= " LIMIT {$start}, {$amount}"; // 指定數量\r
+               }\r
+               return $this->con->query($tmpSQL)->fetchAll(PDO::FETCH_COLUMN, 0);\r
+       }\r
+\r
+       /* 輸出討論串清單 */\r
+       public function fetchThreadList($start=0, $amount=0, $isDESC=false) {\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $tmpSQL = 'SELECT no FROM '.$this->tablename.' WHERE resto = 0 ORDER BY '.($isDESC ? 'no' : 'root').' DESC';\r
+               $start = intval($start); $amount = intval($amount);\r
+               if($amount) $tmpSQL .= " LIMIT {$start}, {$amount}"; // 指定數量\r
+               return $this->con->query($tmpSQL)->fetchAll(PDO::FETCH_COLUMN, 0);\r
+       }\r
+\r
+       /* 輸出文章 */\r
+       public function fetchPosts($postlist){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               if(is_array($postlist)){ // 取多串\r
+                       $pno = implode(', ', $postlist); // ID字串\r
+                       $tmpSQL = 'SELECT * FROM '.$this->tablename.' WHERE no IN ('.$pno.') ORDER BY no';\r
+                       if(count($postlist) > 1){ if($postlist[0] > $postlist[1]) $tmpSQL .= ' DESC'; } // 由大排到小\r
+               }else $tmpSQL = 'SELECT * FROM '.$this->tablename.' WHERE no = '.intval($postlist); // 取單串\r
+               $line = $this->con->query($tmpSQL)->fetchAll();\r
+               return $line;\r
+       }\r
+\r
+       /* 刪除舊附件 (輸出附件清單) */\r
+       public function delOldAttachments($total_size, $storage_max, $warnOnly=true){\r
+               global $FileIO;\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $arr_warn = $arr_kill = array(); // 警告 / 即將被刪除標記\r
+               ($result = $this->con->query('SELECT no,ext,tim FROM '.$this->tablename.' WHERE ext <> "" ORDER BY no')) or $this->_error_handler('Get the old post failed', __LINE__);\r
+               while(list($dno, $dext, $dtim) = $result->fetch(PDO::FETCH_NUM)){\r
+                       $dfile = $dtim.$dext; $dthumb = $dtim.'s.jpg';\r
+                       if($FileIO->imageExists($dfile)){ $total_size -= $FileIO->getImageFilesize($dfile) / 1024; $arr_kill[] = $dno; $arr_warn[$dno] = 1; } // 標記刪除\r
+                       if($FileIO->imageExists($dthumb)) $total_size -= $FileIO->getImageFilesize($dthumb) / 1024;\r
+                       if($total_size < $storage_max) break;\r
+               }\r
+               return $warnOnly ? $arr_warn : $this->removeAttachments($arr_kill);\r
+       }\r
+\r
+       /* 刪除文章 */\r
+       public function removePosts($posts){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $files = $this->removeAttachments($posts, true); // 先遞迴取得刪除文章及其回應附件清單\r
+               $pno = implode(', ', $posts); // ID字串\r
+               if(!$this->con->exec('DELETE FROM '.$this->tablename.' WHERE no IN ('.$pno.') OR resto IN('.$pno.')')) $this->_error_handler('Delete old posts and replies failed', __LINE__);\r
+               return $files;\r
+       }\r
+\r
+       /* 刪除附件 (輸出附件清單) */\r
+       public function removeAttachments($posts, $recursion=false){\r
+               global $FileIO;\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $files = array();\r
+               $pno = implode(', ', $posts); // ID字串\r
+               if($recursion) $tmpSQL = 'SELECT ext,tim FROM '.$this->tablename.' WHERE (no IN ('.$pno.') OR resto IN('.$pno.")) AND ext <> ''"; // 遞迴取出 (含回應附件)\r
+               else $tmpSQL = 'SELECT ext,tim FROM '.$this->tablename.' WHERE no IN ('.$pno.") AND ext <> ''"; // 只有指定的編號\r
+\r
+               ($result = $this->con->query($tmpSQL)) or $this->_error_handler('Get attachments of the post failed', __LINE__);\r
+               while(list($dext, $dtim) = $result->fetch(PDO::FETCH_NUM)){\r
+                       $dfile = $dtim.$dext; $dthumb = $dtim.'s.jpg';\r
+                       if($FileIO->imageExists($dfile)) $files[] = $dfile;\r
+                       if($FileIO->imageExists($dthumb)) $files[] = $dthumb;\r
+               }\r
+               return $files;\r
+       }\r
+\r
+       /* 新增文章/討論串 */\r
+       public function addPost($no, $resto, $md5chksum, $category, $tim, $ext, $imgw, $imgh, $imgsize, $filename, $tw, $th, $pwd, $now, $name, $email, $sub, $com, $host, $age=false, $status='') {\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $time = (int)substr($tim, 0, -3); // 13位數的數字串是檔名,10位數的才是時間數值\r
+               $updatetime = gmdate('Y-m-d H:i:s'); // 更動時間 (UTC)\r
+               if($resto){ // 新增回應\r
+                       $root = '0';\r
+                       if($age){ // 推文\r
+                               $result = $this->con->prepare('UPDATE '.$this->tablename.' SET root = :now WHERE no = :resto');\r
+                               $result->execute(array(':now' => $updatetime, ':resto' => $resto)) or $this->_error_handler('Push the post failed', __LINE__);\r
+                       }\r
+               }else $root = $updatetime; // 新增討論串, 討論串最後被更新時間\r
+\r
+               $SQL = 'INSERT INTO '.$this->tablename.' (resto,root,time,md5chksum,category,tim,ext,imgw,imgh,imgsize,filename,tw,th,pwd,now,name,email,sub,com,host,status) VALUES '\r
+                               .'(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';\r
+               $PDOStmt = $this->con->prepare($SQL);\r
+               $PDOStmt->bindValue(1, $resto, PDO::PARAM_INT);\r
+               $PDOStmt->bindValue(2, $root, PDO::PARAM_STR);\r
+               $PDOStmt->bindValue(3, $time, PDO::PARAM_INT);\r
+               $PDOStmt->bindValue(4, $md5chksum, PDO::PARAM_STR);\r
+               $PDOStmt->bindValue(5, $category, PDO::PARAM_STR);\r
+               $PDOStmt->bindValue(6, $tim, PDO::PARAM_INT);\r
+               $PDOStmt->bindValue(7, $ext, PDO::PARAM_STR);\r
+               $PDOStmt->bindValue(8, $imgw, PDO::PARAM_INT);\r
+               $PDOStmt->bindValue(9, $imgh, PDO::PARAM_INT);\r
+               $PDOStmt->bindValue(10, $imgsize, PDO::PARAM_STR);
+               $PDOStmt->bindValue(11, $filename, PDO::PARAM_STR);\r
+               $PDOStmt->bindValue(12, $tw, PDO::PARAM_INT);\r
+               $PDOStmt->bindValue(13, $th, PDO::PARAM_INT);\r
+               $PDOStmt->bindValue(14, $pwd, PDO::PARAM_STR);\r
+               $PDOStmt->bindValue(15, $now, PDO::PARAM_STR);\r
+               $PDOStmt->bindValue(16, $name, PDO::PARAM_STR);\r
+               $PDOStmt->bindValue(17, $email, PDO::PARAM_STR);\r
+               $PDOStmt->bindValue(18, $sub, PDO::PARAM_STR);\r
+               $PDOStmt->bindValue(19, $com, PDO::PARAM_STR);\r
+               $PDOStmt->bindValue(20, $host, PDO::PARAM_STR);\r
+               $PDOStmt->bindValue(21, $status, PDO::PARAM_STR);\r
+               $PDOStmt->execute() or $this->_error_handler('Insert a new post failed', __LINE__);\r
+       }\r
+\r
+       /* 檢查是否連續投稿 */\r
+       public function isSuccessivePost($lcount, $com, $timestamp, $pass, $passcookie, $host, $isupload){\r
+               global $FileIO;\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               if(!$this->ENV['PERIOD.POST']) return false; // 關閉連續投稿檢查\r
+               $timestamp = intval($timestamp);\r
+               $tmpSQL = 'SELECT pwd,host FROM '.$this->tablename.' WHERE time > '.($timestamp - (int)$this->ENV['PERIOD.POST']); // 一般投稿時間檢查\r
+               if($isupload) $tmpSQL .= ' OR time > '.($timestamp - (int)$this->ENV['PERIOD.IMAGEPOST']); // 附加圖檔的投稿時間檢查 (與下者兩者擇一)\r
+               else $tmpSQL .= " OR md5(com) = '".md5($com)."'"; // 內文一樣的檢查 (與上者兩者擇一)\r
+               $this->con->sqliteCreateFunction('md5', 'md5', 1); // Register MD5 function\r
+               ($result = $this->con->query($tmpSQL)) or $this->_error_handler('Get the post to check the succession failed', __LINE__);\r
+               while(list($lpwd, $lhost) = $result->fetch(PDO::FETCH_NUM)){\r
+                       // 判斷為同一人發文且符合連續投稿條件\r
+                       if($host==$lhost || $pass==$lpwd || $passcookie==$lpwd) return true;\r
+               }\r
+               return false;\r
+       }\r
+\r
+       /* 檢查是否重複貼圖 */\r
+       public function isDuplicateAttachment($lcount, $md5hash){\r
+               global $FileIO;\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               ($result = $this->con->query('SELECT tim,ext FROM '.$this->tablename.' WHERE ext <> "" AND md5chksum = "'.$md5hash.'" ORDER BY no DESC'))\r
+                       or $this->_error_handler('Get the post to check the duplicate attachment failed', __LINE__);\r
+               while(list($ltim, $lext) = $result->fetch(PDO::FETCH_NUM)){\r
+                       if($FileIO->imageExists($ltim.$lext)) return true; // 有相同檔案\r
+               }\r
+               return false;\r
+       }\r
+\r
+       /* 有此討論串? */\r
+       public function isThread($no){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $result = $this->con->query('SELECT no FROM '.$this->tablename.' WHERE no = '.intval($no).' AND resto = 0');\r
+               return $result->fetch() ? true : false;\r
+       }\r
+\r
+       /* 搜尋文章 */\r
+       public function searchPost($keyword, $field, $method){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $keyword_cnt = count($keyword);\r
+               $SearchQuery = 'SELECT * FROM '.$this->tablename." WHERE {$field} LIKE ".$this->con->quote('%'.$keyword[0].'%')."";\r
+               if($keyword_cnt > 1) for($i = 1; $i < $keyword_cnt; $i++) $SearchQuery .= " {$method} {$field} LIKE ".$this->con->quote('%'.$keyword[$i].'%'); // 多重字串交集 / 聯集搜尋\r
+               $SearchQuery .= ' ORDER BY no DESC'; // 按照號碼大小排序\r
+               ($line = $this->con->query($SearchQuery)) or $this->_error_handler('Search the post failed', __LINE__);\r
+               return $line->fetchAll();\r
+       }\r
+\r
+       /* 搜尋類別標籤 */\r
+       public function searchCategory($category){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $result = $this->con->prepare('SELECT no FROM '.$this->tablename.' WHERE lower(category) LIKE :category ORDER BY no DESC');\r
+               $result->execute(array(':category' => '%,'.strtolower($category).',%'));\r
+               return $result->fetchAll(PDO::FETCH_COLUMN, 0);\r
+       }\r
+\r
+       /* 取得文章屬性 */\r
+       public function getPostStatus($status){\r
+               return new FlagHelper($status); // 回傳 FlagHelper 物件\r
+       }\r
+\r
+       /* 更新文章 */\r
+       public function updatePost($no, $newValues){\r
+               if(!$this->prepared) $this->dbPrepare();\r
+\r
+               $no = intval($no);\r
+               $chk = array('resto', 'md5chksum', 'category', 'tim', 'ext', 'imgw', 'imgh', 'imgsize', 'filename', 'tw', 'th', 'pwd', 'now', 'name', 'email', 'sub', 'com', 'host', 'status');\r
+               foreach($chk as $c){\r
+                       if(isset($newValues[$c])){\r
+                               if(!$this->con->exec('UPDATE '.$this->tablename." SET $c = ".$this->con->quote($newValues[$c]).' WHERE no = '.$no))\r
+                                       $this->_error_handler('Update the field of the post failed', __LINE__); // 更新討論串屬性\r
+                       }\r
+               }\r
+       }\r
+\r
+       /* 設定文章屬性 */\r
+       public function setPostStatus($no, $newStatus){\r
+               $this->updatePost($no, array('status' => $newStatus));\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/lib/pms.php b/lib/pms.php
new file mode 100755 (executable)
index 0000000..ddd2244
--- /dev/null
@@ -0,0 +1,116 @@
+<?php\r
+/**\r
+ * Pixmicat! Module System\r
+ *\r
+ * 增加掛載點供函式掛上並在需要時依序呼叫以動態改變內容或達成各種效果\r
+ * \r
+ * @package PMCLibrary\r
+ * @version $Id: pms.php 608 2008-03-04 12:44:27Z scribe $\r
+ * @date $Date: 2008-03-04 20:44:27 +0800 (星期二, 04 三月 2008) $\r
+ */\r
+\r
+class PMS{\r
+       var $ENV;\r
+       var $moduleInstance, $moduleLists;\r
+       var $hookPoints;\r
+       var $loaded;\r
+\r
+       /* Constructor */\r
+       function PMS($ENV){\r
+               $this->loaded = false; // 是否載入完成 (模組及函式)\r
+               $this->ENV = $ENV; // 環境變數\r
+               $this->hooks = array_flip(array('Head', 'Toplink', 'LinksAboveBar', 'PostInfo', 'PostForm',\r
+                       'ThreadFront', 'ThreadRear', 'ThreadPost', 'ThreadReply',\r
+                       'Foot', 'ModulePage', 'RegistBegin', 'RegistBeforeCommit', 'RegistAfterCommit', 'PostOnDeletion',\r
+                       'AdminList', 'AdminFunction', 'Authenticate', 'ThreadOrder'\r
+               ));\r
+               $this->hookPoints = array(); // 掛載點\r
+               $this->moduleInstance = array(); // 存放各模組實體\r
+               $this->moduleLists = array(); // 存放各模組類別名稱\r
+       }\r
+\r
+       // 模組載入相關\r
+       /* 載入模組 */\r
+       function init(){\r
+               $this->loaded = true;\r
+               $this->loadModules();\r
+               return true;\r
+       }\r
+\r
+       /* 單載入模式 */\r
+       function onlyLoad($specificModule){\r
+               // 搜尋載入模組列表有沒有,沒有就直接取消程式\r
+               if(array_search($specificModule, $this->ENV['MODULE.LOADLIST'])===false) return false;\r
+               $this->loadModules($specificModule);\r
+               return isset($this->hookPoints['ModulePage']);\r
+       }\r
+\r
+       /* 載入擴充模組 */\r
+       function loadModules($specificModule=false){\r
+               $loadlist = $specificModule ? array($specificModule) : $this->ENV['MODULE.LOADLIST'];\r
+               foreach($loadlist as $f){\r
+                       $mpath = $this->ENV['MODULE.PATH'].$f.'.php';\r
+                       if(is_file($mpath) && array_search($f, $this->moduleLists)===false){\r
+                               include_once($mpath);\r
+                               $this->moduleLists[] = $f;\r
+                               $this->moduleInstance[$f] = new $f();\r
+                       }\r
+               }\r
+       }\r
+\r
+       /* 取得載入模組列表 */\r
+       function getLoadedModules(){\r
+               if(!$this->loaded) $this->init();\r
+               return $this->moduleLists;\r
+       }\r
+\r
+       /* 取得模組實體 */\r
+       function getModuleInstance($module){\r
+               return isset($this->moduleInstance[$module])?$this->moduleInstance[$module]:null;\r
+       }\r
+\r
+       /* 取得特定模組方法列表 */\r
+       function getModuleMethods($module){\r
+               if(!$this->loaded) $this->init();\r
+               return array_search($module, $this->moduleLists)!==false ? get_class_methods($module) : array();\r
+       }\r
+\r
+       // 提供給模組的取用資訊\r
+       /* 取得模組註冊獨立頁面之網址 */\r
+       function getModulePageURL($name){\r
+               return $this->ENV['MODULE.PAGE'].$name;\r
+       }\r
+\r
+       // 模組掛載與使用相關\r
+       /* 自動掛載相關模組方法於掛載點並回傳掛載點 (Return by Reference) */\r
+       function &__autoHookMethods($hookPoint){\r
+               if(isset($this->hooks[$hookPoint]) && !isset($this->hookPoints[$hookPoint])){ // 尚未掛載\r
+                       $this->hookPoints[$hookPoint] = array();\r
+                       foreach($this->moduleLists as $m){\r
+                               if(method_exists($this->moduleInstance[$m], 'autoHook'.$hookPoint)){\r
+                                       $this->hookModuleMethod($hookPoint, array(&$this->moduleInstance[$m], 'autoHook'.$hookPoint));\r
+                               }\r
+                       }\r
+               }\r
+               return $this->hookPoints[$hookPoint];\r
+       }\r
+\r
+       /* 將模組方法掛載於特定掛載點 */\r
+       function hookModuleMethod($hookPoint, $methodObject){\r
+               if(!isset($this->hooks[$hookPoint])) return false;\r
+               if(!isset($this->hookPoints[$hookPoint]) && $hookPoint != 'ModulePage'){\r
+                       if(!$this->loaded) $this->init();\r
+                       $this->__autoHookMethods($hookPoint);\r
+               }\r
+               $this->hookPoints[$hookPoint][] = $methodObject;\r
+       }\r
+\r
+       /* 使用模組方法 */\r
+       function useModuleMethods($hookPoint, $parameter){\r
+               if(!$this->loaded) $this->init();\r
+               $arrMethod =& $this->__autoHookMethods($hookPoint); // 取得掛載點模組方法\r
+               $imax = count($arrMethod);\r
+               for($i = 0; $i < $imax; $i++) call_user_func_array($arrMethod[$i], $parameter);\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/license b/license
new file mode 100755 (executable)
index 0000000..8224d07
--- /dev/null
+++ b/license
@@ -0,0 +1,147 @@
+This license is a free software license, compatible with the GNU General
+Public License (GPL).  It is the minimal set of changes needed to correct
+the vagueness of the Original Artistic License.
+
+Text'ified by Randy McDowell (stainless@users.sourceforge.net).
+
+
+                     - The Clarified Artistic License -
+
+i. Preamble
+
+    The intent of this document is to state the conditions under which a
+    Package may be copied, such that the Copyright Holder maintains some
+    semblance of artistic control over the development of the package, while
+    giving the users of the package the right to use and distribute the
+    Package in a more-or-less customary fashion, plus the right to make
+    reasonable modifications.
+
+ii. Definitions:
+
+    "Package" refers to the collection of files distributed by the Copyright
+    Holder, and derivatives of that collection of files created through
+    textual modification. 
+
+    "Standard Version" refers to such a Package if it has not been modified,
+    or has been modified in accordance with the wishes of the Copyright
+    Holder as specified below. 
+
+    "Copyright Holder" is whoever is named in the copyright or copyrights
+    for the package. 
+
+    "You" is you, if you're thinking about copying or distributing this
+    Package.
+
+    "Distribution fee" is a fee you charge for providing a copy of this
+    Package to another party. 
+
+    "Freely Available" means that no fee is charged for the right to use the
+    item, though there may be fees involved in handling the item.  It also
+    means that recipients of the item may redistribute it under the same
+    conditions they received it.
+
+iii. Context
+
+    1. You may make and give away verbatim copies of the source form of the
+       Standard Version of this Package without restriction, provided that
+       you duplicate all of the original copyright notices and associated
+       disclaimers.
+
+    2. You may apply bug fixes, portability fixes and other modifications
+       derived from the Public Domain, or those made Freely Available, or
+       from the Copyright Holder.  A Package modified in such a way shall
+       still be considered the Standard Version. 
+
+    3. You may otherwise modify your copy of this Package in any way,
+       provided that you insert a prominent notice in each changed file
+       stating how and when you changed that file, and provided that you do
+       at least ONE of the following:
+
+       a) place your modifications in the Public Domain or otherwise make
+          them Freely Available, such as by posting said modifications to
+          Usenet or an equivalent medium, or placing the modifications on a
+          major network archive site allowing unrestricted access to them,
+          or by allowing the Copyright Holder to include your modifications
+          in the Standard Version of the Package.
+
+       b) use the modified Package only within your corporation or
+          organization.
+
+       c) rename any non-standard executables so the names do not conflict
+          with standard executables, which must also be provided, and
+          provide a separate manual page for each non-standard executable
+          that clearly documents how it differs from the Standard Version. 
+
+       d) make other distribution arrangements with the Copyright Holder.
+
+       e) permit and encourge anyone who receives a copy of the modified
+          Package permission to make your modifications Freely Available in
+          some specific way.
+
+    4. You may distribute the programs of this Package in object code or
+       executable form, provided that you do at least ONE of the following: 
+
+       a) distribute a Standard Version of the executables and library
+          files, together with instructions (in the manual page or
+          equivalent) on where to get the Standard Version. 
+
+       b) accompany the distribution with the machine-readable source of the
+          Package with your modifications. 
+
+       c) give non-standard executables non-standard names, and clearly
+          document the differences in manual pages (or equivalent), together
+          with instructions on where to get the Standard Version. 
+
+       d) make other distribution arrangements with the Copyright Holder.
+
+       e) offer the machine-readable source of the Package, with your
+          modifications, by mail order. 
+
+    5. You may charge a distribution fee for any distribution of this
+       Package.  If you offer support for this Package, you may charge any
+       fee you choose for that support.  You may not charge a license fee
+       for the right to use this Package itself.  You may distribute this
+       Package in aggregate with other (possibly commercial and possibly
+       nonfree) programs as part of a larger (possibly commercial and
+       possibly nonfree) software distribution, and charge license fees for
+       other parts of that software distribution, provided that you do not
+       advertise this Package as a product of your own.  If the Package
+       includes an interpreter, You may embed this Package's interpreter
+       within an executable of yours (by linking); this shall be construed
+       as a mere form of aggregation, provided that the complete Standard
+       Version of the interpreter is so embedded.
+
+    6. The scripts and library files supplied as input to or produced as
+       output from the programs of this Package do not automatically fall
+       under the copyright of this Package, but belong to whoever generated
+       them, and may be sold commercially, and may be aggregated with this
+       Package.  If such scripts or library files are aggregated with this
+       Package via the so-called "undump" or "unexec" methods of producing a
+       binary executable image, then distribution of such an image shall
+       neither be construed as a distribution of this Package nor shall it
+       fall under the restrictions of Paragraphs 3 and 4, provided that you
+       do not represent such an executable image as a Standard Version of
+       this Package. 
+
+    7. C subroutines (or comparably compiled subroutines in other languages)
+       supplied by you and linked into this Package in order to emulate
+       subroutines and variables of the language defined by this Package
+       shall not be considered part of this Package, but are the equivalent
+       of input as in Paragraph 6, provided these subroutines do not change
+       the language in any way that would cause it to fail the regression
+       tests for the language.
+
+    8. Aggregation of the Standard Version of the Package with a commercial
+       distribution is always permitted provided that the use of this
+       Package is embedded; that is, when no overt attempt is made to make
+       this Package's interfaces visible to the end user of the commercial
+       distribution.  Such use shall not be construed as a distribution of
+       this Package.
+
+    9. The name of the Copyright Holder may not be used to endorse or
+       promote products derived from this software without specific prior
+       written permission.
+
+   10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED 
+       WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 
+       MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 
diff --git a/logo.gif b/logo.gif
new file mode 100755 (executable)
index 0000000..22cae27
Binary files /dev/null and b/logo.gif differ
diff --git a/temp/1297428544668.gif b/temp/1297428544668.gif
new file mode 100644 (file)
index 0000000..bd5103f
Binary files /dev/null and b/temp/1297428544668.gif differ
diff --git a/temp/1297428605149.gif b/temp/1297428605149.gif
new file mode 100644 (file)
index 0000000..bd5103f
Binary files /dev/null and b/temp/1297428605149.gif differ
diff --git a/temp/1297428743387.gif b/temp/1297428743387.gif
new file mode 100644 (file)
index 0000000..bd5103f
Binary files /dev/null and b/temp/1297428743387.gif differ
diff --git a/temp/1297429327524.gif b/temp/1297429327524.gif
new file mode 100644 (file)
index 0000000..bd5103f
Binary files /dev/null and b/temp/1297429327524.gif differ
diff --git a/x.php b/x.php
new file mode 100644 (file)
index 0000000..ff67f93
--- /dev/null
+++ b/x.php
@@ -0,0 +1,67 @@
+<?php
+/*yotsubanome multiBBS reader
+from 2ch PHP script 18c
+X v0.0.0.0
+*/
+
+error_reporting(E_ALL); // show all errors for debugging
+
+/* Enviorment Settings */
+// Do not change unless you renamed the directories
+define("PHP_DIRECTORY", '../core/'); // yotsubanome "C:\windows\system\"
+define("DATA_DIR", PHP_DIRECTORY.'data/'); // data directory
+define("CSS_DIR", DATA_DIR.'css/'); // CSS directory
+define("ICON_DIR", DATA_DIR.'icon/'); // icon directory [Graphics of the software go here]
+define("TEMP_DIR", PHP_DIRECTORY.'temp/'); // upload content temperary directory
+define("TPLT_DIR", DATA_DIR.'tplt/'); // template directory
+
+//include_once(PHP_DIRECTORY.'config.php'); // 引入設定檔
+
+if(!defined("PHP_SELF"))define("PHP_SELF", 'yotsubanome.php'); // このスクリプト名 // 主程式名 (若是修改了主程式名,請配合修改)
+if(!defined("BBSMENU")) define("BBSMENU", 0); // BBSmenu for the frame at BBS home page
+if(!defined("INDEXBBS")) define("INDEXBBS", 0); // home page BBS list
+if(!defined("BBSMENU") and !defined("INDEXBBS")) define("LISTBBS", 1); // misc. BBS list
+
+$board = array();
+$handle = opendir('../');
+while(false !== ($file = readdir($handle))){
+       if($file != 'core' and $file != 'script' and $file != '.' and $file != '..'){ // do not include system core directory or distribution directory
+               if(is_dir('../'.$file) and is_file('../'.$file.'/config.php') || is_file('../'.$file.'/'.PHP_SELF)) array_push($board, $file);
+       }
+}
+closedir($handle);
+
+// display the list
+$bbsi = 0;
+$bbsdat = '';
+if(BBSMENU && !INDEXBBS && !LISTBBS){
+       foreach($board as $dir){
+               include('../'.$dir.'/config.php');
+               $bbsdat .= '<a href="../'.$dir.'/" target="cont">'.$config['TITLE'].'</a><br>';
+//++++ <font color="#ff0099">new</font>
+//++++ <font color="#6f0069">old</font>
+               $bbsi++;
+       }
+}else if(!BBSMENU && INDEXBBS && !LISTBBS){
+       foreach($board as $dir){
+               include('../'.$dir.'/config.php');
+               $bbsdat .= '<a href="../'.$dir.'/">'.$config['TITLE'].'</a><br>';
+//++++ <font color="#ff0099">new</font>
+//++++ <font color="#6f0069">old</font>
+               $bbsi++;
+       }
+}else if(!BBSMENU && !INDEXBBS && LISTBBS){
+       foreach($board as $dir){
+               include('../'.$dir.'/config.php');
+               echo $config['TITLE'].'<br>';
+               $bbsdat .= '<a href="../'.$dir.'/">'.$config['TITLE'].'</a><br>';
+//++++ <font color="#ff0099">new</font>
+//++++ <font color="#6f0069">old</font>
+               $bbsi++;
+//             define("$config['TITLE']", '');
+       }
+}
+// print
+print_r($bbsdat);
+if(LISTBBS) print_r($board);
+?>
diff --git a/x.phps b/x.phps
new file mode 100644 (file)
index 0000000..66f4a8b
--- /dev/null
+++ b/x.phps
@@ -0,0 +1,67 @@
+<?php
+/*yotsubanome multiBBS reader
+from 2ch PHP script 18c
+X v0.0.0.0
+*/
+
+error_reporting(E_ALL); // show all errors for debugging
+
+/* Enviorment Settings */
+// Do not change unless you renamed the directories
+define("PHP_DIRECTORY", '../core/'); // yotsubanome "C:\windows\system\"
+define("DATA_DIR", PHP_DIRECTORY.'data/'); // data directory
+define("CSS_DIR", DATA_DIR.'css/'); // CSS directory
+define("ICON_DIR", DATA_DIR.'icon/'); // icon directory [Graphics of the software go here]
+define("TEMP_DIR", PHP_DIRECTORY.'temp/'); // upload content temperary directory
+define("TPLT_DIR", DATA_DIR.'tplt/'); // template directory
+
+//include_once(PHP_DIRECTORY.'config.php'); // 引入設定檔
+
+if(!defined("PHP_SELF"))define("PHP_SELF", 'yotsubanome.php'); // このスクリプト名 // 主程式名 (若是修改了主程式名,請配合修改)
+if(!defined("BBSMENU")) define("BBSMENU", 0); // BBSmenu for the frame at BBS home page
+if(!defined("INDEXBBS")) define("INDEXBBS", 0); // home page BBS list
+if(!defined("BBSMENU") and !defined("INDEXBBS")) define("LISTBBS", 1); // misc. BBS list
+
+$board = array();
+$handle = opendir('../');
+while(false !== ($file = readdir($handle))){
+       if($file != 'core' and $file != 'script' and $file != '.' and $file != '..'){ // do not include system core directory or distribution directory
+               if(is_dir('../'.$file) and is_file('../'.$file.'/config.php') || is_file('../'.$file.'/'.PHP_SELF)) array_push($board, $file);
+       }
+}
+closedir($handle);
+
+// display the list
+$bbsi = 0;
+$bbsdat = '';
+if(BBSMENU && !INDEXBBS && !LISTBBS){
+       foreach($board as $dir){
+               include('../'.$dir.'/config.php');
+               $bbsdat .= '<a href="../'.$dir.'/" target="cont">'.TITLE.'</a><br>';
+//++++ <font color="#ff0099">new</font>
+//++++ <font color="#6f0069">old</font>
+               $bbsi++;
+       }
+}else if(!BBSMENU && INDEXBBS && !LISTBBS){
+       foreach($board as $dir){
+               include('../'.$dir.'/config.php');
+               $bbsdat .= '<a href="../'.$dir.'/">'.TITLE.'</a><br>';
+//++++ <font color="#ff0099">new</font>
+//++++ <font color="#6f0069">old</font>
+               $bbsi++;
+       }
+}else if(!BBSMENU && !INDEXBBS && LISTBBS){
+       foreach($board as $dir){
+               include('../'.$dir.'/config.php');
+               echo TITLE.'<br>';
+               $bbsdat .= '<a href="../'.$dir.'/">'.TITLE.'</a><br>';
+//++++ <font color="#ff0099">new</font>
+//++++ <font color="#6f0069">old</font>
+               $bbsi++;
+               define("TITLE", '');
+       }
+}
+// print
+print_r($bbsdat);
+if(LISTBBS) print_r($board);
+?>
diff --git a/yotsubanome.php b/yotsubanome.php
new file mode 100755 (executable)
index 0000000..4b3fb48
--- /dev/null
@@ -0,0 +1,1630 @@
+<?php
+/********************************
+    四葉の芽画像掲示板
+
+yotsubanome.php*/$ver = "v0.7.8.1.0001 β lot.100404";/*
+
+これがコアシステムです。 四葉の芽スクリプト
+このスクリプトはレッツPHP!<http://php.s3.to/>のgazou.phpを改造したものです。
+配布条件はレッツPHP!に準じます。改造、再配布は自由にどうぞ。
+このスクリプトに関する質問はレッツPHP!にしないようにお願いします。
+最新版は<http://4ch.irc.su/+4/script/>で配布しています。
+ご質問は準備板@四葉の芽<http://4ch.irc.su/+4/core/>までどうぞ。
+
+--【スパーキー(④ ^ヮ^)】◆FCr.DTJy2k◆◆/ODv/gdbGrBJVTTiLB/IBFugUUM=◆四葉の芽◇ちゃんねる ## 管理者 ##
+********************************
+*/
+define("PIXMICAT_VER", 'yotsubanome '.$ver); // 版本資訊文字
+/*
+Pixmicat! : 圖咪貓貼圖版程式
+http://pixmicat.openfoundry.org/
+版權所有 © 2005-2009 Pixmicat! Development Team
+
+版權聲明:
+此程式是基於レッツPHP!<http://php.s3.to/>的gazou.php、
+双葉ちゃん<http://www.2chan.net>的futaba.php所改寫之衍生著作程式,屬於自由軟體,
+以The Clarified Artistic License作為發佈授權條款。
+您可以遵照The Clarified Artistic License來自由使用、散播、修改或製成衍生著作。
+更詳細的條款及定義請參考隨附"LICENSE"條款副本。
+
+發佈這一程式的目的是希望它有用,但沒有任何擔保,甚至沒有適合特定目的而隱含的擔保。
+關於此程式相關的問題請不要詢問レッツPHP!及双葉ちゃん。
+
+如果您沒有隨著程式收到一份The Clarified Artistic License副本,
+請瀏覽http://pixmicat.openfoundry.org/license/以取得一份。
+
+最低運行需求:
+PHP 4.3.0 / 27 December 2002
+GD Version 2.0.28 / 21 July 2004
+
+建議運行環境:
+PHP 4.4.9 或更高版本並開啟 GD 和 Zlib 支援,如支援 ImageMagick 建議使用
+安裝 PHP 編譯快取套件 (如eAccelerator, XCache, APC) 或其他快取套件 (如memcached) 更佳
+如伺服器支援 SQLite, MySQL, PostgreSQL 等請盡量使用
+
+設置方法:
+根目錄的權限請設為777,
+首先將pixmicat.php執行過一遍,必要的檔案和資料夾權限皆會自動設定,
+自動設定完成後請刪除或註解起來此檔案底部之init(); // ←■■!程式環境初始化(略)一行,
+然後再執行一遍pixmicat.php,即完成初始化程序,可以開始使用。
+
+細部的設定請打開config.php參考註解修改,另有 Wiki (http://pixmicat.wikidot.com/pmcuse:config)
+說明條目可資參考。
+*/
+
+error_reporting(E_ALL); // show all errors for debugging
+
+/* Enviorment Settings */
+// Do not change unless you renamed the directories
+define("PHP_DIRECTORY", '../core/'); // yotsubanome "C:\windows\system\"
+define("DATA_DIR", PHP_DIRECTORY.'data/'); // data directory
+define("CSS_DIR", DATA_DIR.'css/'); // CSS directory
+define("ICON_DIR", DATA_DIR.'icon/'); // icon directory [Graphics of the software go here]
+define("TEMP_DIR", PHP_DIRECTORY.'temp/'); // upload content temperary directory
+define("TPLT_DIR", DATA_DIR.'tplt/'); // template directory
+define("JS_DIR", DATA_DIR.'js/'); // javascript directory
+define("SALTFILE", DATA_DIR.'salt.php'); // saltfile for secure t. codes
+
+include_once(PHP_DIRECTORY.'config.php'); // 引入設定檔
+include_once(PHP_DIRECTORY.'lib/lib_language.php'); // 引入語系
+include_once(PHP_DIRECTORY.'lib/lib_common.php'); // 引入共通函式檔案
+include_once(PHP_DIRECTORY.'lib/lib_fileio.php'); // 引入FileIO
+include_once(PHP_DIRECTORY.'lib/lib_pio.php'); // 引入PIO
+include_once(PHP_DIRECTORY.'lib/lib_pms.php'); // 引入PMS
+include_once(PHP_DIRECTORY.'lib/lib_pte.php'); // 引入PTE外部函式庫
+
+$PTE = new PTELibrary(TEMPLATE_FILE); // PTE Library
+
+/* Lockdown [prevents posting] */
+if(file_exists(PHP_DIRECTORY.'lockdown')){
+       if($_POST['mode'] == 'usrdel' || $_GET['mode'] == 'latest' || $_GET['res']){
+               echo "";
+       }else{
+               die('Posting temporarily disabled. Come back later!<br/>&mdash;四葉の芽チーム');
+       }
+}
+
+/* 更新記錄檔檔案/輸出討論串 */
+/* ログの全体更新 */
+function updatelog($resno=0,$page_num=-1,$single_page=false){
+       global $PIO, $FileIO, $PTE, $PMS, $language, $LIMIT_SENSOR, $style_bar;
+
+       $adminMode = adminAuthenticate('check') && $page_num != -1 && !$single_page; // 前端管理模式
+       $adminFunc = ''; // 前端管理選擇
+       if($adminMode){
+               $adminFunc = '<select name="func"><option value="delete">'._T('admin_delete').'</option>';
+               $funclist = array();
+               $PMS->useModuleMethods('AdminFunction', array('add', &$funclist, null, null)); // "AdminFunction" Hook Point
+               foreach($funclist as $f) $adminFunc .= '<option value="'.$f[0].'">'.$f[1].'</option>'."\n";
+               $adminFunc .= '</select>';
+       }
+       $resno = intval($resno); // 編號數字化
+       $page_start = $page_end = 0; // 靜態頁面編號
+       $inner_for_count = 1; // 內部迴圈執行次數
+       $RES_start = $RES_amount = $hiddenReply = $tree_count = $hiddenImage = $hiddenImagP = 0;
+       $hiddenImagRP = 1; // o++
+       $kill_sensor = $old_sensor = false; // 預測系統啟動旗標
+       $arr_kill = $arr_old = array(); // 過舊編號陣列
+       $pte_vals = array('{$THREADFRONT}'=>'','{$THREADREAR}'=>'','{$SELF}'=>PHP_SELF,
+               '{$DEL_HEAD_TEXT}' => '<input type="hidden" name="mode" value="usrdel" />'._T('del_head'),
+               '{$DEL_IMG_ONLY_FIELD}' => '<input type="checkbox" name="onlyimgdel" id="onlyimgdel" value="on" />',
+               '{$DEL_IMG_ONLY_TEXT}' => _T('del_img_only'),
+               '{$DEL_PASS_TEXT}' => ($adminMode ? $adminFunc : '')._T('del_pass'),
+               '{$DEL_PASS_FIELD}' => '<input class="inputtext" type="password" name="pwd" size="8" value="" />',
+               '{$DEL_SUBMIT_BTN}' => '<input type="submit" value="'._T('del_btn').'" />');
+       if(is_file(DATA_DIR.CSV_SS)) $pte_vals += array('{$STYLE_BAR}' => '<br />Style '.$style_bar);
+
+       if($resno) $pte_vals['{$RESTO}'] = $resno;
+
+       if(!$resno){
+               if($page_num==-1){ // remake模式 (PHP動態輸出多頁份)
+                       $threads = $PIO->fetchThreadList(); // 取得全討論串列表
+                       $PMS->useModuleMethods('ThreadOrder', array($resno,$page_num,$single_page,&$threads)); // "ThreadOrder" Hook Point
+                       $threads_count = count($threads);
+                       $inner_for_count = $threads_count > PAGE_DEF ? PAGE_DEF : $threads_count;
+                       $page_end = ceil($threads_count / PAGE_DEF) - 1; // 頁面編號最後值
+               }else{ // 討論串分頁模式 (PHP動態輸出一頁份)
+                       $threads_count = $PIO->threadCount(); // 討論串個數
+                       if($page_num < 0 || ($page_num * PAGE_DEF) >= $threads_count) error(_T('page_not_found')); // $page_num超過範圍
+                       $page_start = $page_end = $page_num; // 設定靜態頁面編號
+                       $threads = $PIO->fetchThreadList($page_num * PAGE_DEF, PAGE_DEF); // 取出分頁後的討論串首篇列表
+                       $PMS->useModuleMethods('ThreadOrder', array($resno,$page_num,$single_page,&$threads)); // "ThreadOrder" Hook Point
+                       $inner_for_count = count($threads); // 討論串個數就是迴圈次數
+               }
+       }else{
+               if(!$PIO->isThread($resno)){ error(_T('thread_not_found')); }
+               $AllRes = isset($_GET['page_num']) && $_GET['page_num']=='all'; // 是否使用 ALL 全部輸出
+
+               // 計算回應分頁範圍
+               $tree_count = $PIO->postCount($resno) - 1; // 討論串回應個數
+               if($tree_count && RE_PAGE_DEF){ // 有回應且RE_PAGE_DEF > 0才做分頁動作
+                       if($page_num==='all'){ // show all
+                               $page_num = 0;
+                               $RES_start = 1;
+                               $RES_amount = $tree_count;
+                       }else{
+                               if($page_num==='RE_PAGE_MAX') $page_num = ceil($tree_count / RE_PAGE_DEF) - 1; // 特殊值:最末頁
+                               if($page_num < 0) $page_num = 0; // 負數
+                               if($page_num * RE_PAGE_DEF >= $tree_count) error(_T('page_not_found'));
+                               $RES_start = $page_num * RE_PAGE_DEF + 1; // 開始
+                               $RES_amount = RE_PAGE_DEF; // 取幾個
+                       }
+               }elseif($page_num > 0) error(_T('page_not_found')); // 沒有回應的情況只允許page_num = 0 或負數
+               else{ $RES_start = 1; $RES_amount = $tree_count; $page_num = 0; } // 輸出全部回應
+
+               if(USE_RE_CACHE && !$adminMode){ // 檢查快取是否仍可使用 / 頁面有無更動
+                       $cacheETag = md5(($AllRes ? 'all' : $page_num).'-'.$tree_count); // 最新狀態快取用 ETag
+                       $cacheFile = './cache/'.$resno.'-'.($AllRes ? 'all' : $page_num).'.'; // 暫存快取檔位置
+                       $cacheGzipPrefix = extension_loaded('zlib') ? 'compress.zlib://' : ''; // 支援 Zlib Compression Stream 就使用
+                       $cacheControl = isset($_SERVER['HTTP_CACHE_CONTROL']) ? $_SERVER['HTTP_CACHE_CONTROL'] : ''; // 瀏覽器快取控制
+                       if(isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == '"'.$cacheETag.'"'){ // 再度瀏覽而快取無更動
+                               header('HTTP/1.1 304 Not Modified');
+                               header('ETag: "'.$cacheETag.'"');
+                               return;
+                       }elseif(file_exists($cacheFile.$cacheETag) && $cacheControl != 'no-cache'){ // 有(更新的)暫存快取檔存在 (未強制no-cache)
+                               header('X-Cache: HIT from Pixmicat');
+                               header('ETag: "'.$cacheETag.'"');
+                               header('Connection: close');
+                               readfile($cacheGzipPrefix.$cacheFile.$cacheETag); return;
+                       }else{
+                               header('X-Cache: MISS from Pixmicat');
+                       }
+               }
+       }
+
+       // 預測過舊文章和將被刪除檔案
+       if(PIOSensor::check('predict', $LIMIT_SENSOR)){ // 是否需要預測
+               $old_sensor = true; // 標記打開
+               $arr_old = array_flip(PIOSensor::listee('predict', $LIMIT_SENSOR)); // 過舊文章陣列
+       }
+       $tmp_total_size = total_size(); // 目前附加圖檔使用量
+       $tmp_STORAGE_MAX = STORAGE_MAX * (($tmp_total_size >= STORAGE_MAX) ? 1 : 0.96); // 預估上限值
+       if(STORAGE_LIMIT && STORAGE_MAX > 0 && ($tmp_total_size >= $tmp_STORAGE_MAX)){
+               $kill_sensor = true; // 標記打開
+               $arr_kill = $PIO->delOldAttachments($tmp_total_size, $tmp_STORAGE_MAX); // 過舊附檔陣列
+       }
+
+       $PMS->useModuleMethods('ThreadFront', array(&$pte_vals['{$THREADFRONT}'], $resno)); // "ThreadFront" Hook Point
+       $PMS->useModuleMethods('ThreadRear', array(&$pte_vals['{$THREADREAR}'], $resno)); // "ThreadRear" Hook Point
+
+       // 生成靜態頁面一頁份內容
+       for($page = $page_start; $page <= $page_end; $page++){
+               $dat = ''; $pte_vals['{$THREADS}'] = '';
+               head($dat, $resno);
+               form($dat, $resno);
+               // 輸出討論串內容
+               for($i = 0; $i < $inner_for_count; $i++){
+                       // 取出討論串編號
+                       if($resno) $tID = $resno; // 單討論串輸出 (回應模式)
+                       else{
+                               if($page_num == -1 && ($page * PAGE_DEF + $i) >= $threads_count) break; // remake 超出索引代表已全部完成
+                               $tID = ($page_start==$page_end) ? $threads[$i] : $threads[$page * PAGE_DEF + $i]; // 一頁內容 (一般模式) / 多頁內容 (remake模式)
+                               $tree_count = $PIO->postCount($tID) - 1; // 討論串回應個數
+                               $RES_start = $tree_count - RE_DEF + 1; if($RES_start < 1) $RES_start = 1; // 開始
+                               $RES_amount = RE_DEF; // 取幾個
+                               $hiddenReply = $RES_start - 1; // 被隱藏回應數
+                       }
+
+                       // $RES_start, $RES_amount 拿去算新討論串結構 (分頁後, 部分回應隱藏)
+                       $tree = $PIO->fetchPostList($tID); // 整個討論串樹狀結構
+                       $tree_cut = array_slice($tree, $RES_start, $RES_amount); array_unshift($tree_cut, $tID); // 取出特定範圍回應
+                       $posts = $PIO->fetchPosts($tree_cut); // 取得文章架構內容
+                       $posts_img = $PIO->fetchPosts($tree); // o++
+                       $pte_vals['{$THREADS}'] .= arrangeThread($PTE, $tree, $tree_cut, $posts, $hiddenReply, $resno, $arr_kill, $arr_old, $kill_sensor, $old_sensor, true, $adminMode, $hiddenImage, $hiddenImagP, $hiddenImagRP, $posts_img); // 交給這個函式去搞討論串印出
+               }
+               $pte_vals['{$PAGENAV}'] = '<div id="page_switch">';
+
+               // 換頁判斷
+               $prev = ($resno ? $page_num : $page) - 1;
+               $next = ($resno ? $page_num : $page) + 1;
+               if($resno){ // 回應分頁
+                       if(RE_PAGE_DEF > 0){ // 回應分頁開啟
+                               $pte_vals['{$PAGENAV}'] .= '<table class="pages" border="1"><tr><td style="white-space: nowrap;">';
+                               $pte_vals['{$PAGENAV}'] .= ($prev >= 0) ? '<a href="'.PHP_SELF.'?res='.$resno.'&amp;page_num='.$prev.'">'._T('prev_page').'</a>' : _T('first_page');
+                               $pte_vals['{$PAGENAV}'] .= "</td><td>";
+                               if($tree_count==0) $pte_vals['{$PAGENAV}'] .= '[<b>0</b>] '; // 無回應
+                               else{
+                                       for($i = 0, $len = $tree_count / RE_PAGE_DEF; $i < $len; $i++){
+                                               if(!$AllRes && $page_num==$i) $pte_vals['{$PAGENAV}'] .= '[<b>'.$i.'</b>] ';
+                                               else $pte_vals['{$PAGENAV}'] .= '[<a href="'.PHP_SELF.'?res='.$resno.'&amp;page_num='.$i.'">'.$i.'</a>] ';
+                                       }
+                                       $pte_vals['{$PAGENAV}'] .= $AllRes ? '[<b>'._T('all_pages').'</b>] ' : ($tree_count > RE_PAGE_DEF ? '[<a href="'.PHP_SELF.'?res='.$resno.'&amp;page_num=all">'._T('all_pages').'</a>] ' : '');
+                               }
+                               $pte_vals['{$PAGENAV}'] .= '</td><td style="white-space: nowrap;">';
+                               $pte_vals['{$PAGENAV}'] .= (!$AllRes && $tree_count > $next * RE_PAGE_DEF) ? '<a href="'.PHP_SELF.'?res='.$resno.'&amp;page_num='.$next.'">'._T('next_page').'</a>' : _T('last_page');
+                               $pte_vals['{$PAGENAV}'] .= '</td></tr></table>'."\n";
+                       }
+               }else{ // 一般分頁
+                       $pte_vals['{$PAGENAV}'] .= '<table class="pages" border="1"><tr>';
+                       if($prev >= 0){
+                               if(!$adminMode && $prev==0) $pte_vals['{$PAGENAV}'] .= '<td><form action="'.PHP_SELF2.'" method="get">';
+                               else{
+                                       if($adminMode || (STATIC_HTML_UNTIL != -1) && ($prev > STATIC_HTML_UNTIL)) $pte_vals['{$PAGENAV}'] .= '<td><form action="'.PHP_SELF.'?page_num='.$prev.'" method="post">';
+                                       else $pte_vals['{$PAGENAV}'] .= '<td><form action="'.$prev.PHP_EXT.'" method="get">';
+                               }
+                               $pte_vals['{$PAGENAV}'] .= '<div><input type="submit" value="'._T('prev_page').'" /></div></form></td>';
+                       }else $pte_vals['{$PAGENAV}'] .= '<td style="white-space: nowrap;">'._T('first_page').'</td>';
+                       $pte_vals['{$PAGENAV}'] .= '<td>';
+                       for($i = 0, $len = $threads_count / PAGE_DEF; $i < $len; $i++){
+                               if($page==$i) $pte_vals['{$PAGENAV}'] .= "[<b>".$i."</b>] ";
+                               else{
+                                       $pageNext = ($i==$next) ? ' rel="next"' : '';
+                                       if(!$adminMode && $i==0) $pte_vals['{$PAGENAV}'] .= '[<a href="'.PHP_SELF2.'?">0</a>] ';
+                                       elseif($adminMode || (STATIC_HTML_UNTIL != -1 && $i > STATIC_HTML_UNTIL)) $pte_vals['{$PAGENAV}'] .= '[<a href="'.PHP_SELF.'?page_num='.$i.'"'.$pageNext.'>'.$i.'</a>] ';
+                                       else $pte_vals['{$PAGENAV}'] .= '[<a href="'.$i.PHP_EXT.'?"'.$pageNext.'>'.$i.'</a>] ';
+                               }
+                       }
+                       $pte_vals['{$PAGENAV}'] .= '</td>';
+                       if($threads_count > $next * PAGE_DEF){
+                               if($adminMode || (STATIC_HTML_UNTIL != -1) && ($next > STATIC_HTML_UNTIL)) $pte_vals['{$PAGENAV}'] .= '<td><form action="'.PHP_SELF.'?page_num='.$next.'" method="post">';
+                               else $pte_vals['{$PAGENAV}'] .= '<td><form action="'.$next.PHP_EXT.'" method="get">';
+                               $pte_vals['{$PAGENAV}'] .= '<div><input type="submit" value="'._T('next_page').'" /></div></form></td>';
+                       }else $pte_vals['{$PAGENAV}'] .= '<td style="white-space: nowrap;">'._T('last_page').'</td>';
+                       $pte_vals['{$PAGENAV}'] .= '</tr></table>'."\n";
+               }
+               $pte_vals['{$PAGENAV}'] .= '<br style="clear: left;" />
+</div>';
+               $dat .= $PTE->ParseBlock('MAIN', $pte_vals);
+               foot($dat);
+
+               // 存檔 / 輸出
+               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 $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 (回應) //++++----\r             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, '&amp;'.TRIP_KEY, $name); // 避免 &#xxxx; 後面被視為 Trip 留下 & 造成解析錯誤
+               if(CLEAR_SAGE) $email = preg_replace('/^sage( *)/i', '', trim($email)); // 清除E-mail中的「sage」關鍵字
+               //Tripcode indicator // t++ //++++----
+               $tripkeycount = substr_count($name, TRIP_KEY);
+               if(ALLOW_NONAME==2){ // 強制砍名
+                       if($tripkeycount==1) $name = preg_match('/(\\'.TRIP_KEY.'.{10})/', $name, $matches) ? '<span class="postertrip">'.$matches[1].'</span>' : '';
+                       if($tripkeycount==2) $name = preg_match('/(\\'.TRIP_KEY.TRIP_KEY.'.{16})/', $name, $matches) ? '<span class="postertrip">'.$matches[1].'</span>' : '';
+                       if($tripkeycount==3) $name = preg_match('/(\\'.TRIP_KEY.'.{32})/', $name, $matches) ? '<span class="postertrip">'.$matches[1].'</span>' : '';
+                       if($email) $now = "<a href=\"mailto:$email\" class=\"linkmail\">$now</a>";
+               }else{
+                       if($tripkeycount==1) $name = preg_replace('/(\\'.TRIP_KEY.'.{10})/', '<span class="postertrip">$1</span>', $name); // Trip取消粗體
+                       if($tripkeycount==2) $name = preg_replace('/(\\'.TRIP_KEY.TRIP_KEY.'.{16})/', '<span class="postertrip">$1</span>', $name); // Trip取消粗體
+                       if($tripkeycount==3) $name = preg_replace('/(\\'.TRIP_KEY.'.{32})/', '<span class="postertrip">$1</span>', $name); // Trip取消粗體
+                       if($email) $name = "<a href=\"mailto:$email\" class=\"linkmail\">$name</a>";
+               }
+
+               if(AUTO_LINK) $com = auto_link($com);
+               $com = quoteLight($com);
+               $com = quoteLight2($com);
+               if(!$resno && MAX_LINES) list($com, $abbreviated) = abbreviate($com, MAX_LINES);
+               if(isset($abbreviated) && $abbreviated && MAX_LINES) $com .= '<br /><span class="abbrev">'._T('long_comment').'<a href="'.PHP_SELF.'?res='.$tree[0].'#r'.$no.'">'._T('long_here').'</a>'._T('long_see').'</span>';
+
+               if(USE_QUOTESYSTEM && $i){ // 啟用引用瀏覽系統
+                       if(preg_match_all('/((?:&gt;|>)+)(?:No\.)?(\d+)/i', $com, $matches, PREG_SET_ORDER)){ // 找尋>>No.xxx
+                               $matches_unique = array();
+                               foreach($matches as $val){ if(!in_array($val, $matches_unique)) array_push($matches_unique, $val); }
+                               foreach($matches_unique as $val){
+                                       if(isset($tree_clone[$val[2]])){
+                                               $r_page = $tree_clone[$val[2]]; // 引用回應在整體討論串中的位置
+                                               // 在此頁顯示區間內,輸出錨點即可
+                                               if(isset($tree_cut[$val[2]])) $com = str_replace($val[0], '<span class="reflink"><a class="qlink" href="#r'.$val[2].'" onclick="replyhl('.$val[2].');">'.$val[0].'</a></span>', $com);
+                                               // 非此頁顯示區間,輸出完整頁面位置
+                                               else $com = str_replace($val[0], '<span class="reflink"><a class="qlink" href="'.PHP_SELF.'?res='.$tree[0].(RE_PAGE_DEF ? '&amp;page_num='.floor(($r_page - 1) / RE_PAGE_DEF) : '').'#r'.$val[2].'">'.$val[0].'</a></span>', $com);
+                                       }
+                               }
+                       }
+               }
+
+               // 設定附加圖檔顯示
+               if($ext && !$FileIO->imageExists($tim.$ext)){
+                       $imgsrc = '<img src="'.ICON_DIR.'filedeleted.gif" class="img" alt="'.$imgsize.'" title="'.$imgsize.'" />';
+               }elseif($ext && $FileIO->imageExists($tim.$ext)){
+                       $imageURL = $FileIO->getImageURL($tim.$ext); // image URL
+                       $thumbURL = $FileIO->getImageURL($tim.'s.jpg'); // thumb URL
+
+                       //----$imgsrc = '<a href="'.$imageURL.'" rel="_blank"><img src="'.ICON_DIR.'nothumb.gif" class="img" alt="'.$imgsize.'" title="'.$imgsize.'" /></a>'; // 預設顯示圖樣式 (無預覽圖時)
+                       $imgsrc = '<a href="'.$imageURL.'" rel="_blank"><span class="tn_reply" title="'.$imgsize.'">'._T('nothumb').'</span></a>'; // 預設顯示圖樣式 (無預覽圖時)
+                       if($tw && $th){
+                               if($FileIO->imageExists($tim.'s.jpg')){ // 有預覽圖
+                                       $img_thumb = '<br /><small><span class="thumbnailmsg">'._T('img_sample').'</span></small>';
+                                       $imgsrc = '<a href="'.$imageURL.'" rel="_blank"><img src="'.$thumbURL.'" style="width: '.$tw.'px; height: '.$th.'px;" class="img" alt="'.$imgsize.'" title="'.$imgsize.'" /></a>';
+                               }elseif($ext=='.swf') $imgsrc = ''; // swf檔案不需預覽圖
+                       }
+                       if(SHOW_IMGWH) $imgwh_bar = ', '.$imgw.'x'.$imgh; // 顯示附加圖檔之原檔長寬尺寸
+                       if(SHOW_FILENAME){
+                               $longname = $shortname = '';
+                               if($filename){
+                                       $longname = $filename.$ext;
+                                       if(strlen($filename) > 40) $shortname = substr($filename, 0, 40).'(....)'.$ext;
+                                       else $shortname = $longname;
+                               }
+                       }
+                       if($longname) $imgfn_bar = ', <span title="'.$longname.'">'.$shortname.'</span>';
+                       $IMG_BAR = '<span class="filesize">'._T('img_filename').'<a href="'.$imageURL.'" rel="_blank">'.$tim.$ext.'</a>-('.$imgsize.$imgwh_bar.$imgfn_bar.')</span>'.$img_thumb;
+               }
+
+               // 設定回應 / 引用連結
+               if($resno){ // 回應模式
+                       if($showquotelink) $QUOTEBTN = '<span class="reflink"><a href="'.PHP_SELF.'?res='.$tree[0].'#r'.$no.'" onclick="return replyhl('.$no.');">No.</a><a href="javascript:quote('.$no.');" class="qlink">'.$no.'</a></span>';
+                       else $QUOTEBTN = '<span class="reflink"><a href="'.PHP_SELF.'?res='.$tree[0].'#r'.$no.'" onclick="return replyhl('.$no.');">No.</a><a href="'.PHP_SELF.'?res='.$tree.'&amp;page_num=all#r'.$no.'" class="qlink">'.$no.'</a></span>';
+               }else{
+                       if(!$i) $REPLYBTN = '[<a href="'.PHP_SELF.'?res='.$no.'">'._T('reply_btn').'</a>]'; // 首篇
+                       $QUOTEBTN = '<span class="reflink"><a href="'.PHP_SELF.'?res='.$tree[0].'#r'.$no.'">No.</a><a href="'.PHP_SELF.'?res='.$tree[0].'#q'.$no.'" class="qlink">'.$no.'</a></span>';
+               }
+               if($adminMode){ // 前端管理模式
+                       $modFunc = '';
+                       $PMS->useModuleMethods('AdminList', array(&$modFunc, $posts[$i], $resto)); // "AdminList" Hook Point
+                       $QUOTEBTN .= $modFunc;
+               }
+
+               // 設定討論串屬性
+               if(STORAGE_LIMIT && $kill_sensor) if(isset($arr_kill[$no])) $WARN_BEKILL = '<span class="warn_txt">'._T('warn_sizelimit').'</span><br />'."\n"; // 預測刪除過大檔
+               if(!$i){ // 首篇 Only
+                       if($old_sensor) if(isset($arr_old[$no])) $WARN_OLD = '<span class="oldpost">'._T('warn_oldthread').'</span><br />'."\n"; // 快要被刪除的提示
+                       $flgh = $PIO->getPostStatus($status);
+                       if($flgh->exists('TS')) $WARN_ENDREPLY = '<span class="warn_txt">'._T('warn_locked').'</span><br />'."\n"; // 被標記為禁止回應
+                       if($hiddenReply) $WARN_HIDEPOST = '<span class="omittedposts">'._res($hiddenReply, $hiddenImgs)._T('notice_omitted_reply').'</span><br />'."\n"; // 有隱藏的回應
+               }
+               // 對類別標籤作自動連結
+               if(USE_CATEGORY){
+                       $ary_category = explode(',', str_replace('&#44;', ',', $category)); $ary_category = array_map('trim', $ary_category);
+                       $ary_category_count = count($ary_category);
+                       $ary_category2 = array();
+                       for($p = 0; $p < $ary_category_count; $p++){
+                               if($c = $ary_category[$p]) $ary_category2[] = '<a href="'.PHP_SELF.'?mode=category&amp;c='.urlencode($c).'">'.$c.'</a>';
+                       }
+                       $category = implode(', ', $ary_category2);
+               }else $category = '';
+
+               // 最終輸出處
+               if($i){ // 回應
+                       $arrLabels = array('{$NO}'=>$no, '{$SUB}'=>$sub, '{$NAME}'=>$name, '{$NOW}'=>$now, '{$COM}'=>$com, '{$CATEGORY}'=>$category, '{$QUOTEBTN}'=>$QUOTEBTN, '{$IMG_BAR}'=>$IMG_BAR, '{$IMG_SRC}'=>$imgsrc, '{$WARN_BEKILL}'=>$WARN_BEKILL, '{$QUOTEBTN}'=>$QUOTEBTN, '{$NAME_TEXT}'=>_T('post_name'), '{$CATEGORY_TEXT}'=>_T('post_category'), '{$SELF}'=>PHP_SELF);
+                       if($resno) $arrLabels['{$RESTO}']=$resno;
+                       $PMS->useModuleMethods('ThreadReply', array(&$arrLabels, $posts[$i], $resno)); // "ThreadReply" Hook Point
+                       $thdat .= $PTE->ParseBlock('REPLY',$arrLabels);
+               }else{ // 首篇
+                       $arrLabels = array('{$NO}'=>$no, '{$SUB}'=>$sub, '{$NAME}'=>$name, '{$NOW}'=>$now, '{$COM}'=>$com, '{$CATEGORY}'=>$category, '{$QUOTEBTN}'=>$QUOTEBTN, '{$REPLYBTN}'=>$REPLYBTN, '{$IMG_BAR}'=>$IMG_BAR, '{$IMG_SRC}'=>$imgsrc, '{$WARN_OLD}'=>$WARN_OLD, '{$WARN_BEKILL}'=>$WARN_BEKILL, '{$WARN_ENDREPLY}'=>$WARN_ENDREPLY, '{$WARN_HIDEPOST}'=>$WARN_HIDEPOST, '{$NAME_TEXT}'=>_T('post_name'), '{$CATEGORY_TEXT}'=>_T('post_category'), '{$SELF}'=>PHP_SELF);
+                       if($resno) $arrLabels['{$RESTO}']=$resno;
+                       $PMS->useModuleMethods('ThreadPost', array(&$arrLabels, $posts[$i], $resno)); // "ThreadPost" Hook Point
+                       $thdat .= $PTE->ParseBlock('THREAD',$arrLabels);
+               }
+       }
+       $thdat .= $PTE->ParseBlock('THREADSEPARATE',($resno)?array('{$RESTO}'=>$resno):array());
+       return $thdat;
+}
+
+/* 寫入記錄檔 */
+/* 記事書き込み */
+function regist(){
+       global $PIO, $FileIO, $PMS, $language, $BAD_STRING, $BAD_FILEMD5, $BAD_IPADDR, $LIMIT_SENSOR;
+       $dest = ''; $mes = ''; $up_incomplete = 0; $is_admin = false;
+       $path = realpath('.').DIRECTORY_SEPARATOR; // 此目錄的絕對位置
+
+       if($_SERVER['REQUEST_METHOD'] != 'POST') error(_T('regist_notpost')); // 非正規POST方式
+       // 欄位陷阱
+       $FTname = isset($_POST['name']) ? $_POST['name'] : '';
+       $FTemail = isset($_POST['email']) ? $_POST['email'] : '';
+       $FTsub = isset($_POST['sub']) ? $_POST['sub'] : '';
+       $FTcom = isset($_POST['com']) ? $_POST['com'] : '';
+       $FTreply = isset($_POST['reply']) ? $_POST['reply'] : '';
+       if($FTname != 'spammer' || $FTemail != 'foo@foo.bar' || $FTsub != 'DO NOT FIX THIS' || $FTcom != 'EID OG SMAPS' || $FTreply != '') error(_T('regist_nospam'));
+
+       $name = isset($_POST[FT_NAME]) ? CleanStr($_POST[FT_NAME]) : '';
+       $email = isset($_POST[FT_EMAIL]) ? CleanStr($_POST[FT_EMAIL]) : '';
+       $sub = isset($_POST[FT_SUBJECT]) ? CleanStr($_POST[FT_SUBJECT]) : '';
+       $com = isset($_POST[FT_COMMENT]) ? $_POST[FT_COMMENT] : '';
+       $pwd = isset($_POST['pwd']) ? $_POST['pwd'] : '';
+       $category = isset($_POST['category']) ? CleanStr($_POST['category']) : '';
+       $resto = isset($_POST['resto']) ? intval($_POST['resto']) : 0;
+       $upfile = isset($_FILES['upfile']['tmp_name']) ? $_FILES['upfile']['tmp_name'] : '';
+       $upfile_path = isset($_POST['upfile_path']) ? $_POST['upfile_path'] : '';
+       $upfile_name = isset($_FILES['upfile']['name']) ? $_FILES['upfile']['name'] : false;
+       $ext_ = ereg_replace("^.*\\.", ".", $upfile_name); // filename extention
+       $basename = basename($upfile_name, $ext_); // filename
+       $filename = isset($basename) ? CleanStr($basename) : ''; // cleaned filename
+       $upfile_status = isset($_FILES['upfile']['error']) ? $_FILES['upfile']['error'] : 4;
+       $pwdc = isset($_COOKIE['pwdc']) ? $_COOKIE['pwdc'] : '';
+       $ip = getREMOTE_ADDR(); $host = gethostbyaddr($ip);
+
+       $PMS->useModuleMethods('RegistBegin', array(&$name, &$email, &$sub, &$com, array('file'=>&$upfile, 'path'=>&$upfile_path, 'name'=>&$upfile_name, 'status'=>&$upfile_status), array('ip'=>$ip, 'host'=>$host), $resto)); // "RegistBegin" Hook Point
+       // 封鎖:IP/Hostname/DNSBL 檢查機能
+       $baninfo = '';
+       if(BanIPHostDNSBLCheck($ip, $host, $baninfo)) error(_T('regist_ipfiltered', $baninfo));
+       // 封鎖:限制出現之文字
+       foreach($BAD_STRING as $value){
+               if(strpos($com, $value)!==false || strpos($sub, $value)!==false || strpos($name, $value)!==false || strpos($email, $value)!==false){
+                       error(_T('regist_wordfiltered'));
+               }
+       }
+
+       // 檢查是否輸入櫻花日文假名
+       foreach(array($name, $email, $sub, $com) as $anti) if(anti_sakura($anti)) error(_T('regist_sakuradetected'));
+
+       // 時間
+       $time = time();
+       $tim = $time.substr(microtime(),2,3);
+       $tome = time()+0*60*60;
+
+       // 判斷上傳狀態
+       switch($upfile_status){
+               case 1:
+                       error(_T('regist_upload_exceedphp'));
+                       break;
+               case 2:
+                       error(_T('regist_upload_exceedcustom'));
+                       break;
+               case 3:
+                       error(_T('regist_upload_incompelete'));
+                       break;
+               case 6:
+                       error(_T('regist_upload_direrror'));
+                       break;
+               case 4: // 無上傳
+                       if(NO_TEXTONLY == 2){
+                               if(!$resto) error(_T('regist_upload_noimg'));
+                       }elseif(NO_TEXTONLY == 1){
+                               if(!$resto && !isset($_POST['noimg'])) error(_T('regist_upload_noimg'));
+                       }
+                       break;
+               case 0: // 上傳正常
+               default:
+       }
+
+       // 如果有上傳檔案則處理附加圖檔
+       if($upfile && (@is_uploaded_file($upfile) || @is_file($upfile))){
+               // 一‧先儲存檔案
+               $dest = $path.TEMP_DIR.$tim.'.temp';
+               @move_uploaded_file($upfile, $dest) or @copy($upfile, $dest);
+               @chmod($dest, 0666);
+               if(!is_file($dest)) error(_T('regist_upload_filenotfound'), $dest);
+
+               // 二‧判斷上傳附加圖檔途中是否有中斷
+               $upsizeTTL = $_SERVER['CONTENT_LENGTH'];
+               if(isset($_FILES['upfile'])){ // 有傳輸資料才需要計算,避免作白工
+                       $upsizeHDR = 0;
+                       // 檔案路徑:IE附完整路徑,故得從隱藏表單取得
+                       $tmp_upfile_path = $upfile_name;
+                       if($upfile_path) $tmp_upfile_path = get_magic_quotes_gpc() ? stripslashes($upfile_path) : $upfile_path;
+                       list(,$boundary) = explode('=', $_SERVER['CONTENT_TYPE']);
+                       foreach($_POST as $header => $value){ // 表單欄位傳送資料
+                               $upsizeHDR += strlen('--'.$boundary."\r\n");
+                               $upsizeHDR += strlen('Content-Disposition: form-data; name="'.$header.'"'."\r\n\r\n".(get_magic_quotes_gpc()?stripslashes($value):$value)."\r\n");
+                       }
+                       // 附加圖檔欄位傳送資料
+                       $upsizeHDR += strlen('--'.$boundary."\r\n");
+                       $upsizeHDR += strlen('Content-Disposition: form-data; name="upfile"; filename="'.$tmp_upfile_path."\"\r\n".'Content-Type: '.$_FILES['upfile']['type']."\r\n\r\n");
+                       $upsizeHDR += strlen("\r\n--".$boundary."--\r\n");
+                       $upsizeHDR += $_FILES['upfile']['size']; // 傳送附加圖檔資料量
+                       // 上傳位元組差值超過 HTTP_UPLOAD_DIFF:上傳附加圖檔不完全
+                       if(($upsizeTTL - $upsizeHDR) > HTTP_UPLOAD_DIFF){
+                               if(KILL_INCOMPLETE_UPLOAD){
+                                       unlink($dest);
+                                       die(_T('regist_upload_killincomp')); // 給瀏覽器的提示,假如使用者還看的到的話才不會納悶
+                               }else $up_incomplete = 1;
+                       }
+               }
+
+               // 三‧檢查是否為可接受的檔案
+               $size = @getimagesize($dest);
+               if(!is_array($size)) error(_T('regist_upload_notimage'), $dest); // $size不為陣列就不是圖檔
+               $imgsize = @filesize($dest); // 檔案大小
+               if(!KB) $imgsize .= ' B'; // B only
+               else $imgsize = ($imgsize>=1024) ? (int)($imgsize/1024).' KB' : $imgsize.' B'; // KB和B的判別
+               switch($size[2]){ // 判斷上傳附加圖檔之格式
+                       case 1 : $ext = ".gif"; break;
+                       case 2 : $ext = ".jpg"; break;
+                       case 3 : $ext = ".png"; break;
+                       case 4 : $ext = ".swf"; break;
+                       case 5 : $ext = ".psd"; break;
+                       case 6 : $ext = ".bmp"; break;
+                       case 7 : $ext = ".tiff"; break;
+                       case 8 : $ext = ".tiff"; break;
+                       case 9 : $ext = ".jpc"; break;
+                       case 10 : $ext = ".jp2"; break;
+                       case 11 : $ext = ".jpx"; break;
+                       case 12 : $ext = ".jb2"; break;
+                       case 13 : $ext = ".swf"; break;
+                       case 14 : $ext = ".aiff"; break;
+                       case 15 : $ext = ".wbmp"; break;
+                       case 16 : $ext = ".xbm"; break;
+                       default : $ext = ".xxxx"; error(_T('regist_upload_notsupport'), $dest);
+               }
+               $allow_exts = explode('|', strtolower(ALLOW_UPLOAD_EXT)); // 接受之附加圖檔副檔名
+               if(array_search(substr($ext, 1), $allow_exts)===false) error(_T('regist_upload_notsupport'), $dest); // 並無在接受副檔名之列
+               // 封鎖設定:限制上傳附加圖檔之MD5檢查碼
+               $md5chksum = md5_file($dest); // 檔案MD5
+               if(array_search($md5chksum, $BAD_FILEMD5)!==FALSE) error(_T('regist_upload_blocked'), $dest); // 在封鎖設定內則阻擋
+
+               // 四‧計算附加圖檔圖檔縮圖顯示尺寸
+               $W = $imgW = $size[0];
+               $H = $imgH = $size[1];
+               $MAXW = $resto ? MAX_RW : MAX_W;
+               $MAXH = $resto ? MAX_RH : MAX_H;
+               if($W > $MAXW || $H > $MAXH){
+                       $W2 = $MAXW / $W;
+                       $H2 = $MAXH / $H;
+                       $key = ($W2 < $H2) ? $W2 : $H2;
+                       $W = ceil($W * $key);
+                       $H = ceil($H * $key);
+               }
+               $mes = _T('regist_uploaded', CleanStr($upfile_name));
+       }
+
+       // 檢查表單欄位內容並修整
+       if(strlen($name) > 100) error(_T('regist_nametoolong'), $dest);
+       if(strlen($email) > 100) error(_T('regist_emailtoolong'), $dest);
+       if(strlen($sub) > 100) error(_T('regist_topictoolong'), $dest);
+       if(strlen($resto) > 10) error(_T('regist_longthreadnum'), $dest);
+
+       // E-mail / 標題修整
+       $email = str_replace("\r\n", '', $email); $sub = str_replace("\r\n", '', $sub);
+       // Tripcode area--------------------------------------------------------------------------------
+       if($name){
+               // 名稱修整
+               $name = str_replace(TRIP_KEY, TRIP_KEY_FAKE, $name); // 防止トリップ偽造
+               $name = str_replace(CAP_SUFFIX, CAP_SUFFIX_FAKE, $name); // 防止管理員キャップ偽造
+               $name = str_replace("\r\n", '', $name);
+               $nameOri = $name; // 名稱
+               // トリップ
+               //----if(preg_match('/(.*?)[##](.*)/u', $name, $regs)){ // トリップ(Trip)機能
+                       //----$name = $nameOri = $regs[1]; $cap = strtr($regs[2], array('&amp;'=>'&'));
+                       //----$salt = preg_replace('/[^\.-z]/', '.', substr($cap.'H.', 1, 2));
+                       //----$salt = strtr($salt, ':;<=>?@[\\]^_`', 'ABCDEFGabcdef');
+                       //----$name = $name.TRIP_KEY.substr(crypt($cap, $salt), -10);
+               if(preg_match('/(.*?)[##](.*)/u', $name, $regs)){ // トリップ(Trip)機能
+                       $name = str_replace("&#", "&%%%%%%", $name); # otherwise HTML numeric entities screw up explode()!
+                       list($name, $trip, $sectrip) = str_replace("&&", "&%%%%%%", explode("#", $name));
+
+                       if($trip != ''){
+                               if(function_exists("iconv")) $trip = iconv("UTF-8", "SHIFT_JIS//TRANSLIT", $trip); // convert to Windows Japanese #&#65355;&#65345;&#65357;&#65353;
+                               $salt = strtr(preg_replace('/[^\.-z]/', '.', substr($trip.'H.', 1, 2)), ':;<=>?@[\\]^_`', 'ABCDEFGabcdef');
+                               $metrip = TRIP_KEY.substr(crypt($trip, $salt), -10);
+                       }else $metrip = '';
+                       if($sectrip != ''){
+                               if(function_exists("iconv")) $sectrip = iconv("UTF-8", "SHIFT_JIS//TRANSLIT", $sectrip); // convert to Windows Japanese #&#65355;&#65345;&#65357;&#65353;
+                               $salt = "LOLLOLOLOLOLOLOLOLOLOLOLOLOLOLOLMEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"; # this is ONLY used if the host doesn't have openssl # I don't know a better way to get random data
+                               if(file_exists(SALTFILE)){ # already generated a key
+                                       $salt = file_get_contents(SALTFILE);
+                               }else{
+                                       system("openssl rand 448 > '".SALTFILE, $err);
+                                       if($err === 0){
+                                               if(chmod(SALTFILE,0400)){
+                                                       $salt = file_get_contents(SALTFILE);
+                                               }else{
+                                                       $donk = IDSEED;
+                                                       $fp = fopen(SALTFILE, "w");
+                                                       fputs($fp, $donk);
+                                                       fclose($fp);
+                                               }
+                                       }
+                               }
+                               $sha = base64_encode(pack("H*", sha1($sectrip.$salt)));
+                               $sha = substr($sha, 0, 16);
+                               $metrip .= TRIP_KEY.TRIP_KEY.$sha;
+                       }
+                       // Tripcode filter
+                       //++++if(file_exists(FILTER_DIR)){
+                               //++++include(FILTER_DIR.'trip.php');
+                       //++++}
+                       //----"</b></font><font class=\"postertrip\">".
+                       $name .= $metrip;
+               }
+               if(CAP_ENABLE && preg_match('/(.*?)[##](.*)/u', $email, $aregs)){ // 管理員キャップ(Cap)機能
+                       $acap_name = $nameOri; $acap_pwd = strtr($aregs[2], array('&amp;'=>'&'));
+                       if($acap_name==CAP_NAME && $acap_pwd==CAP_PASS){
+                               $name = '<span class="admin_cap">'.$name.CAP_SUFFIX.'</span>';
+                               $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, '&amp;'.TRIP_KEY, $name); // 避免 &#xxxx; 後面被視為 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); // 換行字元用<br />代替
+       $com = str_replace("\n", '', $com); // 若還有\n換行字元則取消換行
+       // 預設的內容
+       if(!$name || ereg("^[ | |]*$", $name)){
+               if(ALLOW_NONAME) $name = DEFAULT_NONAME;
+               else error(_T('regist_withoutname'), $dest);
+       }
+       if(!$sub || ereg("^[ | |]*$", $sub)){
+               if(ALLOW_NOSUB) $sub = DEFAULT_NOTITLE;
+               else error(_T('regist_withoutsubject'), $dest);
+       }
+       if(!$com || ereg("^[ | |\t]*$", $com)){
+               if(ALLOW_NOSUB) $com = 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 .= '<br /><br /><span class="warn_txt">'._T('notice_incompletefile').'</span>'; // 上傳附加圖檔不完全的提示
+
+       // 密碼和時間的樣式 
+       if($pwd=='') if(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);
+       if(!EN_SEC)
+               $now = date(DATE_FORMAT, $tome).'('.(string)$yd.')'.date('H:i', $tome);
+               else $now = date(DATE_FORMAT, $tome).'('.(string)$yd.')'.date('H:i:s', $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(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.'&amp;upseries=1'; // 回應後繼續轉回此主題下
+               else{
+                       $RedirURL = PHP_SELF.'?res='.$lastno.'&amp;upseries=1'; // 新增主題後繼續轉到此主題下
+               }
+       }
+       $RedirforJS = strtr($RedirURL, array("&amp;"=>"&")); // JavaScript用轉址目標
+
+       echo '<?xml version="1.0" encoding="UTF-8"?>'."\n";
+       echo <<< _REDIR_
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="'.PIXMICAT_LANGUAGE.'">
+<head>
+<title></title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<meta http-equiv="Refresh" content="1;URL=$RedirURL" />
+<script type="text/javascript">
+// Redirection (use JS)
+// <![CDATA[
+function redir(){
+       location.href = "$RedirforJS";
+}
+setTimeout("redir()", 1000);
+// ]]>
+</script>
+</head>
+<body>
+<div>
+_REDIR_;
+echo _T('regist_redirect',$mes,$RedirURL).'</div>
+</body>
+</html>';
+}
+
+/* 使用者刪除 */
+/* ユーザー削除 */
+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 = '[<a href="'.PHP_SELF2.'?'.time().'">'._T('return').'</a>] [<a href="'.PHP_SELF.'?mode=remake">'._T('admin_remake').'</a>] [<a href="'.PHP_SELF.'?page_num=0">'._T('admin_frontendmanage').'</a>]';
+       $PMS->useModuleMethods('LinksAboveBar', array(&$links,'admin',$isCheck)); // LinksAboveBar hook point
+       $dat .= '<div id="bannerlink">'.$links.'</div><div id="banner"><div class="passvalid">'._T('admin_top').'</div>
+</div>
+<form action="'.PHP_SELF.'" method="post" id="adminform">
+<div id="admin-check" style="text-align: center;">
+'; //----class="bar_admin"
+       echo $dat;
+       if(!$isCheck){
+               echo '<br />
+<input type="radio" name="admin" value="del" checked="checked" />'._T('admin_manageposts').'
+<input type="radio" name="admin" value="optimize" />'._T('admin_optimize').'
+<input type="radio" name="admin" value="check" />'._T('admin_check').'
+<input type="radio" name="admin" value="repair" />'._T('admin_repair').'
+<input type="radio" name="admin" value="export" />'._T('admin_export').'
+<input type="radio" name="admin" value="stylesheets" />'._T('admin_stylesheets').'<p />
+<input type="hidden" name="mode" value="admin" />
+<input class="inputtext" type="password" name="pass" size="8" />
+<input type="submit" value="'._T('admin_verify_btn').'" />
+</div>
+</form>';
+               die("\n</body>\n</html>");
+       }elseif(!isset($_REQUEST['admin'])){
+               echo '<br />
+<input type="radio" name="admin" value="del" checked="checked" />'._T('admin_manageposts').'
+<input type="radio" name="admin" value="optimize" />'._T('admin_optimize').'
+<input type="radio" name="admin" value="check" />'._T('admin_check').'
+<input type="radio" name="admin" value="repair" />'._T('admin_repair').'
+<input type="radio" name="admin" value="export" />'._T('admin_export').'
+<input type="radio" name="admin" value="stylesheets" />'._T('admin_stylesheets').'
+<input type="radio" name="admin" value="logout" />'._T('admin_logout').'<p />
+<input type="hidden" name="mode" value="admin" />
+<input type="submit" value="'._T('admin_submit_btn').'" />
+</div>
+</form>';
+               die("\n</body>\n</html>");
+       }
+}
+
+/* 管理文章模式 */
+/* 管理者削除 */
+function admindel(){
+       global $PIO, $FileIO, $PMS, $language;
+
+       $pass = isset($_POST['pass']) ? $_POST['pass'] : ''; // 管理者密碼
+       $page = isset($_REQUEST['page']) ? $_REQUEST['page'] : 0; // 切換頁數
+       $onlyimgdel = isset($_POST['onlyimgdel']) ? $_POST['onlyimgdel'] : ''; // 只刪圖
+       $modFunc = '';
+       $delno = $thsno = array();
+       $delflag = isset($_POST['func']) && ($_POST['func'] == 'delete') && isset($_POST['clist']); // 是否有「刪除」勾選
+       $thsflag = isset($_POST['stop']); // 是否有「停止」勾選
+       $is_modified = false; // 是否改寫檔案
+       $message = ''; // 操作後顯示訊息
+
+       if(isset($_POST['func']) && isset($_POST['clist']))
+               $PMS->useModuleMethods('AdminFunction', array('run', $_POST['clist'], $_POST['func'], &$message)); // "AdminFunction" Hook Point
+
+       // 刪除文章區塊
+       if($delflag){
+               //if(!adminAuthenticate('check')) error(_T('admin_wrongpassword'));
+
+               $delno = array_merge($delno, $_POST['clist']);
+               if($onlyimgdel != 'on') $PMS->useModuleMethods('PostOnDeletion', array($delno, 'backend')); // "PostOnDeletion" Hook Point
+               $files = ($onlyimgdel != 'on') ? $PIO->removePosts($delno) : $PIO->removeAttachments($delno);
+               $FileIO->deleteImage($files);
+               deleteCache($delno);
+               total_size(true); // 刪除容量快取
+               $is_modified = true;
+       }
+       // 討論串停止區塊
+       if($thsflag){
+               //if(!adminAuthenticate('check')) error(_T('admin_wrongpassword'));
+
+               $thsno = array_merge($thsno, $_POST['stop']);
+               $threads = $PIO->fetchPosts($thsno); // 取得文章
+               foreach($threads as $th){
+                       $flgh = $PIO->getPostStatus($th['status']);
+                       $flgh->toggle('TS');
+                       $PIO->setPostStatus($th['no'], $flgh->toString());
+               }
+               $is_modified = true;
+       }
+       if(($delflag || $thsflag) && $is_modified) $PIO->dbCommit(); // 無論如何都有檔案操作,回寫檔案
+
+       $line = $PIO->fetchPostList(0, $page * ADMIN_PAGE_DEF, ADMIN_PAGE_DEF); // 分頁過的文章列表
+       $posts_count = count($line); // 迴圈次數
+       $posts = $PIO->fetchPosts($line); // 文章內容陣列
+
+       echo '<input type="hidden" name="mode" value="admin" />
+<input type="hidden" name="admin" value="del" />
+<div style="text-align: left;">'._T('admin_notices').'</div>
+<div>'.$message.'</div>
+<table border="1" cellspacing="0" style="margin: 0px auto;">
+<tr class="managehead">'._T('admin_list_header').'</tr>
+';
+
+       for($j = 0; $j < $posts_count; $j++){
+               $bg = ($j % 2) ? 'row1' : 'row2'; // 背景顏色
+               extract($posts[$j]);
+
+               if($no == 0) break; // Do not display post 0
+
+               // 修改欄位樣式
+               $now = preg_replace('/.{2}\/(.{5})\(.+?\)(.{5}).*/', '$1 $2', $now);
+               $name = htmlspecialchars(str_cut(html_entity_decode(strip_tags($name)), 8));
+               $sub = htmlspecialchars(str_cut(html_entity_decode($sub), 8));
+               if($email) $name = "<a href=\"mailto:$email\">$name</a>";
+               $com = str_replace('<br />',' ',$com);
+               $com = htmlspecialchars(str_cut(html_entity_decode($com), 20));
+
+               // 討論串首篇停止勾選框 及 模組功能
+               $modFunc = $THstop = ' ';
+               $PMS->useModuleMethods('AdminList', array(&$modFunc, $posts[$j], $resto)); // "AdminList" Hook Point
+               if($resto==0){ // $resto = 0 (即討論串首篇)
+                       $flgh = $PIO->getPostStatus($status);
+                       $THstop = '<input type="checkbox" name="stop[]" value="'.$no.'" />'.($flgh->exists('TS') ? _T('admin_stop_btn') : '');
+               }
+
+               // 從記錄抽出附加圖檔使用量並生成連結
+               if($ext && $FileIO->imageExists($tim.$ext)){
+                       $clip = '<a href="'.$FileIO->getImageURL($tim.$ext).'" rel="_blank">'.$tim.$ext.'</a>';
+                       $size = $FileIO->getImageFilesize($tim.$ext);
+                       if($FileIO->imageExists($tim.'s.jpg')) $size += $FileIO->getImageFilesize($tim.'s.jpg');
+               }else{
+                       $clip = $md5chksum = '--';
+                       $size = 0;
+               }
+
+               // 印出介面
+               echo <<< _ADMINEOF_
+<tr class="$bg" align="left">
+<th align="center">$modFunc</th><th align="center">$THstop</th><th><input type="checkbox" name="clist[]" value="$no" />$no</th><td><small>$now</small></td><td>$sub</td><td><b>$name</b></td><td><small>$com</small></td><td>$host</td><td align="center">$clip ($size)<br />$md5chksum</td>
+</tr>
+
+_ADMINEOF_;
+       }
+       echo '</table>
+<p>
+<select name="func"><option value="delete">'._T('admin_delete').'</option>';
+       $funclist = array();
+       $PMS->useModuleMethods('AdminFunction', array('add', &$funclist, null, null)); // "AdminFunction" Hook Point
+       foreach($funclist as $f) echo '<option value="'.$f[0].'">'.$f[1].'</option>';
+       echo '</select>
+<input type="submit" value="'._T('admin_submit_btn').'" /> <input type="reset" value="'._T('admin_reset_btn').'" /> [<input type="checkbox" name="onlyimgdel" id="onlyimgdel" value="on" /><label for="onlyimgdel">'._T('del_img_only').'</label>]</p>
+<p>'._T('admin_totalsize',total_size()).'</p>
+</div>
+</form>
+<hr />
+';
+
+       $countline = $PIO->postCount(); // 總文章數
+       $page_max = ceil($countline / ADMIN_PAGE_DEF) - 1; // 總頁數
+       echo '<table class="pages" border="1" style="float: left;"><tr>';
+       if($page) echo '<td><a href="'.PHP_SELF.'?mode=admin&amp;admin=del&amp;page='.($page - 1).'">'._T('prev_page').'</a></td>';
+       else echo '<td style="white-space: nowrap;">'._T('first_page').'</td>';
+       echo '<td>';
+       for($i = 0; $i <= $page_max; $i++){
+               if($i==$page) echo '[<b>'.$i.'</b>] ';
+               else echo '[<a href="'.PHP_SELF.'?mode=admin&amp;admin=del&amp;page='.$i.'">'.$i.'</a>] ';
+       }
+       echo '</td>';
+       if($page < $page_max) echo '<td><a href="'.PHP_SELF.'?mode=admin&amp;admin=del&amp;page='.($page + 1).'">'._T('next_page').'</a></td>';
+       else echo '<td style="white-space: nowrap;">'._T('last_page').'</td>';
+       die('</tr></table><br/><br/>
+</body>
+</html>');
+}
+
+////////////////
+// manage_css //
+////////////////
+function manage_css(){
+       global $PMS, $language;
+       $order = array(); $line = '';
+
+       // Handle submission
+       if(isset($_POST['order']) || isset($_POST['new'])){
+               $default = $_POST['default'];
+
+               if(isset($_POST['order'])){
+                       $dupid = false;
+                       $order = $_POST['order'];
+                       $ids = array();
+                       $id = 0;
+                       $name = '';
+                       if(count($order) > 1){
+                               foreach($order as $name => $id) $ids[$id]++;
+                               foreach($ids as $idu => $count){
+                                       if($idu < 1 || $count == 1) continue;
+                                       foreach($order as $name => $id) if($id == $idu) $dupid = true;
+                               }
+                               if($dupid){
+                                       ksort($order); // Yes, we're going to wimp out and reset it alphabetically.
+                                       $go = 0;
+                                       foreach($order as $name => $id) $go++;
+                                       $order[$name] = $go;
+                               }
+                       }
+                       $order = array_flip($order);
+               }
+
+               // Find out if a new stylesheet entry has been added
+               if(is_array($_POST['new'])){
+                       $new_path = $_POST['new']['path'];
+                       $new_name = $_POST['new']['name'];
+                       $new_order = $_POST['new']['order'];
+                       if($new_path != '' && $new_name != '') $order[$new_order] = $new_name;
+                       if($default == 'new') $default = $new_name;
+               }
+
+               ksort($order);
+
+               // Get existing stylesheet entries
+               foreach($order as $id => $name){
+                       if(!$id) continue;
+                       if(!$_POST['path'][$name]) continue;
+                       $temp['path'][$name] = $_POST['path'][$name];
+                       $temp['names'][$name] = $name;
+                       $temp['short'][$name] = $_POST['short'][$name];
+                       $temp['order'][$name] = $id;
+               }
+
+               // Get newly added stylesheet entries
+               if(is_array($_POST['new'])){
+                       $temp['path'][$new_name] = $_POST['new']['path'];
+                       $temp['names'][$new_name] = $new_name;
+                       $temp['short'][$new_name] = $_POST['new']['short'];
+                       $temp['order'][$new_name] = $new_order;
+               }
+
+               // Build CSV lines
+               foreach($order as $id => $name){
+                       if(!$id) continue; // Ignore Display order 0
+                       $line   .= $name.','.$temp['short'][$name].','.$temp['path'][$name].',';
+                       $line   .= ($name == $default) ? 'default,' : ',';
+                       $line   .= "\n";
+               }
+
+               $style_dat = DATA_DIR.CSV_SS;
+
+               // Success messages
+               $action = (file_exists($style_dat)) ? _t('admin_updated') : _t('admin_created');
+               $delete = (@unlink(CSS_DIR.CSVSS)) ? ' - <span class="warning">'.str_replace('[file]', CSS_DIR.CSVSS, _t('admin_deleted')).'</span>' : false;
+               $fp = fopen($style_dat, 'w+');
+               set_file_buffer($fp, 0);
+               rewind($fp);
+               fputs($fp, $line);
+               fclose($fp);
+               @chmod($style_dat, 0666);
+               echo '<div class="bar_managecss">'.str_replace('[file]', $style_dat, _t('admin_updated')).$delete.'</div>';
+       }
+
+       // Editing messages
+       if(file_exists(DATA_DIR.CSV_SS)){
+               $style_data = DATA_DIR.CSV_SS;
+               $style_mode = _t('admin_editing');
+       }else{
+               $style_data = CSS_DIR.CSVSS;
+               $style_mode = _t('admin_imported');
+       }
+       echo '<div class="banner"><table width="100%"><tr><th class="bar_managecss">
+'.str_replace('[file]', $style_data, $style_mode).'
+</th></tr></table></div>';
+
+       echo '<div class="postlists">
+<input type="hidden" name="mode" value="admin" />
+<input type="hidden" name="admin" value="stylesheets" />
+<table width="100%" border="1" cellspacing="0">';
+
+       // Read data from R4+(CSV)
+       if(file_exists(DATA_DIR.CSV_SS)){
+               $style_data = DATA_DIR.CSV_SS;
+               $lines = explode("\n", file_get_contents($style_data));
+               $j = 0;
+               $lines = array_diff($lines, array(''));
+               if(count($lines)){
+                       echo '<tr class="managehead"><th colspan="2">'._t('admin_is_default').'</th><th>'._t('admin_fullname').'</th><th>'._t('admin_shortname').'</th><th>'._t('admin_dispid').'</th></tr>';
+               }
+               foreach($lines as $null => $line){
+                       if($line != ''){ // Line has data
+                               list($style_name, $style_short, $style_file, $style_rel) = explode(',', $line);
+                               $j++; // For alternating <tr> BG colour
+
+                               $style_path = CSS_DIR.$style_file;
+
+                               if(file_exists($style_path)){
+                                       if($style_rel) $style_rel = ' checked="checked"';
+                                       else $style_rel = false;
+                                       $class = ($j % 2) ? 'row1' : 'row2'; // BG colour
+                                       echo '<tr class="'.$class.'"><td align="left" colspan="2"><label><input name="default" type="radio"'.$style_rel.' value="'.$style_name.'" /> '.$style_path.'</label><input type="hidden" name="path['.$style_name.']" value="'.$style_file.'" /></td><td align="left">'.$style_name.'</td><td align="left"><input name="short['.$style_name.']" value="'.$style_short.'" size="5" /></td><td align="left"><label><input name="order['.$style_name.']" size="2" value="'.$j.'" /></label></td></tr>';
+                               }
+                       }
+               }
+       }
+
+       // Read data from R3 DAT
+       else if(file_exists(CSS_DIR.CSVSS)){
+               $style_data = CSS_DIR.CSVSS;
+               $lines = explode("\n", file_get_contents($style_data));
+               $j = 0;
+               foreach($lines as $null => $line){ // Line has data, or line is not commented out
+                       if(substr($line, 0, 2) != '//' && $line != ''){
+                               $bits = explode('[*]', $line);
+                               $j++;
+                               $style_name = $bits[0];
+                               $style_path = CSS_DIR.$bits[2];
+                               if(file_exists($style_path)){
+                                       $style_short = $bits[1];
+                                       if($bits[3]) $style_rel = ' checked="checked"';
+                                       else $style_rel = false;
+                                       $class = ($j % 2) ? 'row1' : 'row2'; // BG colour
+                                       echo '<tr class="'.$class.'"><td align="left" colspan="2"><label><input name="default" type="radio"'.$style_rel.' value="'.$style_name.'" /> '.$style_path.'</label><input type="hidden" name="path['.$style_name.']" value="'.$bits[2].'" /></td><td align="left"><input name="names['.$style_name.']" value="'.$style_name.'" size="25" /></td><td align="left"><input name="short['.$style_name.']" value="'.$style_short.'" size="5" /></td><td align="left"><input name="order['.$style_name.']" size="2" value="'.$j.'" /></td></tr>';
+                               }
+                       }
+               }
+       }
+
+       $j++; $class = ($j % 2) ? 'row1' : 'row2';
+
+       // Insert string for when there are stylesheet entries to modify
+       $action = ($j > 1) ? _t('admin_modstyle') : false;
+       // Check default radio button for new row when there are NO stylesheet entries
+       $style_rel = (!$action) ? ' checked="checked"' : false;
+
+       echo '<tr class="managehead"><th>'.str_replace('[or modify]', $action, _t('admin_addstyle')).'</th><th>'._t('admin_new_file').'</th><th>'._t('admin_fullname').'</th><th>'._t('admin_shortname').'</th><th>'._t('admin_new_id').'</th></tr>';
+
+       echo '<tr class="'.$class.'"><td align="left"><label><input name="default" type="radio"'.$style_rel.' value="new" /> '._t('admin_style_default').'</label></td><td align="left"><nobr>'.CSS_DIR.'<input name="new[path]" /></nobr></td><td align="left"><input name="new[name]" size="25" /></td><td align="left"><input name="new[short]" size="5" /></td><td align="left"><input name="new[order]" size="2" value="'.$j.'" /></td></tr></table></div>
+<center><p><div class="passvalid"><input type="submit" value="'._T('admin_submit_btn').'" /> <input type="reset" value="'._T('admin_reset_btn').'" /></div></p>';
+       die('</center></form></body></html>');
+}
+
+/* 計算目前附加圖檔使用容量 (單位:KB) */
+function total_size($isupdate=false){
+       global $PIO, $FileIO;
+
+       $size = 0; $all = 0;
+       $cache_file = "./".SIZE_CACHE; // 附加圖檔使用容量值快取檔案
+
+       if($isupdate){ // 刪除舊快取
+               if(is_file($cache_file)) unlink($cache_file);
+               return;
+       }
+       if(!is_file($cache_file)){ // 無快取,新增
+               $line = $PIO->fetchPostList(); // 取出所有文章編號
+               $posts = $PIO->fetchPosts($line);
+               $linecount = count($posts);
+               for($i = 0; $i < $linecount; $i++){
+                       extract($posts[$i]);
+                       // 從記錄檔抽出計算附加圖檔使用量
+                       if($ext && $FileIO->imageExists($tim.$ext)) $all += $FileIO->getImageFilesize($tim.$ext); // 附加圖檔合計計算
+                       if($FileIO->imageExists($tim.'s.jpg')) $all += $FileIO->getImageFilesize($tim.'s.jpg'); // 預覽圖合計計算
+               }
+               $sp = fopen($cache_file, 'w');
+               stream_set_write_buffer($sp, 0);
+               fwrite($sp, $all); // 寫入目前使用容量值
+               fclose($sp);
+               @chmod($cache_file, 0666);
+       }else{ // 使用快取
+               $sp = file($cache_file);
+               $all = $sp[0];
+               unset($sp);
+       }
+       return (int)($all / 1024);
+}
+
+/* 搜尋(全文檢索)功能 */
+function search(){
+       global $PTE, $PIO, $FileIO, $PMS, $language;
+
+       if(!USE_SEARCH) error(_T('search_disabled'));
+       $searchKeyword = isset($_POST['keyword']) ? trim($_POST['keyword']) : ''; // 欲搜尋的文字
+       $dat = '';
+       head($dat);
+       $links = '[<a href="'.PHP_SELF2.'?'.time().'">'._T('return').'</a>]';
+       $PMS->useModuleMethods('LinksAboveBar', array(&$links,'search'));
+       $dat .= '<div id="bannerlink">'.$links.'</div><div id="banner"><div class="bar_search">'._T('search_top').'</div>
+</div>
+';
+       echo $dat;
+       if($searchKeyword==''){
+               echo '<form action="'.PHP_SELF.'" method="post">
+<div id="search">
+<input type="hidden" name="mode" value="search" />
+';
+               echo '<ul>'._T('search_notice').'<input class="inputtext" type="text" name="keyword" size="30" />
+'._T('search_target').'<select name="field"><option value="com" selected="selected">'._T('search_target_comment').'</option><option value="name">'._T('search_target_name').'</option><option value="sub">'._T('search_target_topic').'</option><option value="no">'._T('search_target_number').'</option></select>
+'._T('search_method').'<select name="method"><option value="AND" selected="selected">'._T('search_method_and').'</option><option value="OR">'._T('search_method_or').'</option></select>
+<input type="submit" value="'._T('search_submit_btn').'" />
+</li>
+</ul>
+</div>
+</form>';
+       }else{
+               $searchField = $_POST['field']; // 搜尋目標 (no:編號, name:名稱, sub:標題, com:內文)
+               $searchMethod = $_POST['method']; // 搜尋方法
+               $searchKeyword = preg_split('/( | )+/', trim($searchKeyword)); // 搜尋文字用空格切割
+               $hitPosts = $PIO->searchPost($searchKeyword, $searchField, $searchMethod); // 直接傳回符合的文章內容陣列
+
+               echo '<div id="search_result">
+';
+               $resultlist = '';
+               foreach($hitPosts as $post){
+                       extract($post);
+                       if(USE_CATEGORY){
+                               $ary_category = explode(',', str_replace('&#44;', ',', $category)); $ary_category = array_map('trim', $ary_category);
+                               $ary_category_count = count($ary_category);
+                               $ary_category2 = array();
+                               for($p = 0; $p < $ary_category_count; $p++){
+                                       if($c = $ary_category[$p]) $ary_category2[] = '<a href="'.PHP_SELF.'?mode=category&amp;c='.urlencode($c).'">'.$c.'</a>';
+                               }
+                               $category = implode(', ', $ary_category2);
+                       }else $category = '';
+                       $arrLabels = array('{$NO}'=>'<a href="'.PHP_SELF.'?res='.($resto?$resto.'#r'.$no:$no).'">'.$no.'</a>', '{$SUB}'=>$sub, '{$NAME}'=>$name, '{$NOW}'=>$now, '{$COM}'=>$com, '{$CATEGORY}'=>$category, '{$NAME_TEXT}'=>_T('post_name'), '{$CATEGORY_TEXT}'=>_T('post_category'));
+                       $resultlist .= $PTE->ParseBlock('SEARCHRESULT',$arrLabels);
+               }
+               echo $resultlist ? $resultlist : '<div style="text-align: center">'._T('search_notfound').'<br/><a href="?mode=search">'._T('search_back').'</a></div>';
+               echo "</div>";
+       }
+       echo "</body>\n</html>";
+}
+
+/* 利用類別標籤搜尋符合的文章 */
+function searchCategory(){
+       global $PTE, $PIO, $PMS, $FileIO, $language;
+       $category = isset($_GET['c']) ? strtolower(strip_tags(trim($_GET['c']))) : ''; // 搜尋之類別標籤
+       if(!$category) error(_T('category_nokeyword'));
+       $category_enc = urlencode($category); $category_md5 = md5($category);
+       $page = isset($_GET['p']) ? @intval($_GET['p']) : 1; if($page < 1) $page = 1; // 目前瀏覽頁數
+       $isrecache = isset($_GET['recache']); // 是否強制重新生成快取
+
+       // 利用Session快取類別標籤出現篇別以減少負擔
+       session_start(); // 啟動Session
+       if(!isset($_SESSION['loglist_'.$category_md5]) || $isrecache){
+               $loglist = $PIO->searchCategory($category);
+               $_SESSION['loglist_'.$category_md5] = serialize($loglist);
+       }else $loglist = unserialize($_SESSION['loglist_'.$category_md5]);
+
+       $loglist_count = count($loglist);
+       if(!$loglist_count) error(_T('category_notfound'));
+       $page_max = ceil($loglist_count / PAGE_DEF); if($page > $page_max) $page = $page_max; // 總頁數
+
+       // 分割陣列取出適當範圍作分頁之用
+       $loglist_cut = array_slice($loglist, PAGE_DEF * ($page - 1), PAGE_DEF); // 取出特定範圍文章
+       $loglist_cut_count = count($loglist_cut);
+
+       $dat = '';
+       head($dat);
+       $links = '[<a href="'.PHP_SELF2.'?'.time().'">'._T('return').'</a>][<a href="'.PHP_SELF.'?mode=category&amp;c='.$category_enc.'&amp;recache=1">'._T('category_recache').'</a>]';
+       $PMS->useModuleMethods('LinksAboveBar', array(&$links,'category'));
+       $dat .= "<div>$links</div>\n";
+       for($i = 0; $i < $loglist_cut_count; $i++){
+               $posts = $PIO->fetchPosts($loglist_cut[$i]); // 取得文章內容
+               $dat .= arrangeThread($PTE, ($posts[0]['resto'] ? $posts[0]['resto'] : $posts[0]['no']), null, $posts, 0, $loglist_cut[$i], array(), array(), false, false, false); // 逐個輸出 (引用連結不顯示)
+       }
+
+       $dat .= '<table border="1"><tr>';
+       if($page > 1) $dat .= '<td><form action="'.PHP_SELF.'?mode=category&amp;c='.$category_enc.'&amp;p='.($page - 1).'" method="post"><div><input type="submit" value="'._T('prev_page').'" /></div></form></td>';
+       else $dat .= '<td style="white-space: nowrap;">'._T('first_page').'</td>';
+       $dat .= '<td>';
+       for($i = 1; $i <= $page_max ; $i++){
+               if($i==$page) $dat .= "[<b>".$i."</b>] ";
+               else $dat .= '[<a href="'.PHP_SELF.'?mode=category&amp;c='.$category_enc.'&amp;p='.$i.'">'.$i.'</a>] ';
+       }
+       $dat .= '</td>';
+       if($page < $page_max) $dat .= '<td><form action="'.PHP_SELF.'?mode=category&amp;c='.$category_enc.'&amp;p='.($page + 1).'" method="post"><div><input type="submit" value="'._T('next_page').'" /></div></form></td>';
+       else $dat .= '<td style="white-space: nowrap;">'._T('last_page').'</td>';
+       $dat .= '</tr></table>'."\n";
+
+       foot($dat);
+       echo $dat;
+}
+
+/* 顯示已載入模組資訊 */
+function listModules(){
+       global $PMS, $language;
+       $dat = '';
+       head($dat);
+       $links = '[<a href="'.PHP_SELF2.'?'.time().'">'._T('return').'</a>]';
+       $PMS->useModuleMethods('LinksAboveBar', array(&$links,'modules'));
+       $dat .= '<div id="bannerlink">'.$links.'</div><div id="banner"><div class="bar_info_mod">'._T('module_info_top').'</div>
+</div>
+
+<div id="modules">
+';
+       /* Module Loaded */
+       $dat .= _T('module_loaded').'<ul>'."\n";
+       foreach($PMS->getLoadedModules() as $m) $dat .= '<li>'.$m."</li>\n";
+       $dat .= "</ul><hr />\n";
+
+       /* Module Infomation */
+       $dat .= _T('module_info').'<ul>'."\n";
+       foreach($PMS->moduleInstance as $m) $dat .= '<li>'.$m->getModuleName().'<div style="padding-left:2em;">'.$m->getModuleVersionInfo()."</div></li>\n";
+       $dat .= '</ul><hr />
+</div>
+
+';
+       foot($dat);
+       echo $dat;
+}
+
+/* 刪除舊頁面快取檔 */
+function deleteCache($no){
+       foreach($no as $n){
+               if($oldCaches = glob('./cache/'.$n.'-*')){
+                       foreach($oldCaches as $o) @unlink($o);
+               }
+       }
+}
+
+/* 顯示系統各項資訊 */
+function showstatus(){
+       global $PTE, $PIO, $FileIO, $PMS, $language, $LIMIT_SENSOR;
+       $countline = $PIO->postCount(); // 計算投稿文字記錄檔目前資料筆數
+       $counttree = $PIO->threadCount(); // 計算樹狀結構記錄檔目前資料筆數
+       $tmp_total_size = total_size(); // 附加圖檔使用量總大小
+       $tmp_ts_ratio = STORAGE_MAX > 0 ? $tmp_total_size / STORAGE_MAX : 0; // 附加圖檔使用量
+
+       // 決定「附加圖檔使用量」提示文字顏色
+       if($tmp_ts_ratio < 0.3 ) $clrflag_sl = '235CFF';
+       elseif($tmp_ts_ratio < 0.5 ) $clrflag_sl = '0CCE0C';
+       elseif($tmp_ts_ratio < 0.7 ) $clrflag_sl = 'F28612';
+       elseif($tmp_ts_ratio < 0.9 ) $clrflag_sl = 'F200D3';
+       else $clrflag_sl = 'F2004A';
+
+       // 生成預覽圖物件資訊及功能是否正常
+       $func_thumbWork = '<span style="color: red;">'._T('info_nonfunctional').'</span>';
+       $func_thumbInfo = '(No thumbnail)';
+       if(USE_THUMB !== 0){
+               $thumbType = USE_THUMB; if(USE_THUMB==1){ $thumbType = 'gd'; }
+               require(PHP_DIRECTORY.'lib/thumb/thumb.'.$thumbType.'.php');
+               $thObj = new ThumbWrapper();
+               if($thObj->isWorking()) $func_thumbWork = '<span style="color: blue;">'._T('info_functional').'</span>';
+               $func_thumbInfo = $thObj->getClass();
+               unset($thObj);
+       }
+
+       // PIOSensor
+       if(count($LIMIT_SENSOR))
+               $piosensorInfo=nl2br(PIOSensor::info($LIMIT_SENSOR));
+
+       $dat = '';
+       head($dat);
+       $links = '[<a href="'.PHP_SELF2.'?'.time().'">'._T('return').'</a>] [<a href="'.PHP_SELF.'?mode=moduleloaded">'._T('module_info_top').'</a>]';
+       $PMS->useModuleMethods('LinksAboveBar', array(&$links,'status'));
+       $dat .= '<div id="bannerlink">'.$links.'</div><div id="banner"><div class="bar_info">'._T('info_top').'</div>
+</div>
+';
+
+       $dat .= '
+<div id="status-table" style="text-align: center;">
+<table border="1" style="margin: 0px auto; text-align: left;">
+<tr><td align="center" colspan="4">'._T('info_basic').'</td></tr>
+<tr><td style="width: 240px;">'._T('info_basic_ver').'</td><td colspan="3"> '.PIXMICAT_VER.' </td></tr>
+<tr><td>'._T('info_basic_pio').'</td><td colspan="3"> '.PIXMICAT_BACKEND.' : '.$PIO->pioVersion().'</td></tr>
+<tr><td>'._T('info_basic_threadsperpage').'</td><td colspan="3"> '.PAGE_DEF.' '._T('info_basic_threads').'</td></tr>
+<tr><td>'._T('info_basic_postsperpage').'</td><td colspan="3"> '.RE_DEF.' '._T('info_basic_posts').'</td></tr>
+<tr><td>'._T('info_basic_postsinthread').'</td><td colspan="3"> '.RE_PAGE_DEF.' '._T('info_basic_posts').' '._T('info_basic_posts_showall').'</td></tr>
+<tr><td>'._T('info_basic_bumpposts').'</td><td colspan="3"> '.MAX_RES.' '._T('info_basic_posts').' '._T('info_basic_0disable').'</td></tr>
+<tr><td>'._T('info_basic_bumphours').'</td><td colspan="3"> '.MAX_AGE_TIME.' '._T('info_basic_hours').' '._T('info_basic_0disable').'</td></tr>
+<tr><td>'._T('info_basic_urllinking').'</td><td colspan="3"> '.AUTO_LINK.' '._T('info_0no1yes').'</td></tr>
+<tr><td>'._T('info_basic_com_limit').'</td><td colspan="3"> '.COMM_MAX._T('info_basic_com_after').'</td></tr>
+<tr><td>'._T('info_basic_anonpost').'</td><td colspan="3"> '.ALLOW_NONAME.' '._T('info_basic_anonpost_opt').'</td></tr>
+<tr><td>'._T('info_basic_del_incomplete').'</td><td colspan="3"> '.KILL_INCOMPLETE_UPLOAD.' '._T('info_0no1yes').'</td></tr>
+<tr><td>'._T('info_basic_use_sample',THUMB_Q).'</td><td colspan="3"> '.USE_THUMB.' '._T('info_0notuse1use').'</td></tr>
+<tr><td>'._T('info_basic_useblock').'</td><td colspan="3"> '.BAN_CHECK.' '._T('info_0disable1enable').'</td></tr>
+<tr><td>'._T('info_basic_showid').'</td><td colspan="3"> '.DISP_ID.' '._T('info_basic_showid_after').'</td></tr>
+<tr><td>'._T('info_basic_cr_limit').'</td><td colspan="3"> '.BR_CHECK._T('info_basic_cr_after').'</td></tr>
+<!--<tr><td>'._T('info_basic_timezone').'</td><td colspan="3"> GMT </td></tr>-->
+<tr><td>'._T('info_basic_max_lines_limit').'</td><td colspan="3"> '.MAX_LINES._T('info_basic_max_lines_after').'</td></tr>
+<tr><td>'._T('info_basic_theme').'</td><td colspan="3"> '.$PTE->BlockValue('THEMENAME').' '.$PTE->BlockValue('THEMEVER').'<br/>by '.$PTE->BlockValue('THEMEAUTHOR').'</td></tr>
+<tr><td align="center" colspan="4">'._T('info_dsusage_top').'</td></tr>
+<tr align="center"><td>'._T('info_basic_threadcount').'</td><td colspan="'.(isset($piosensorInfo)?'2':'3').'"> '.$counttree.' '._T('info_basic_threads').'</td>'.(isset($piosensorInfo)?'<td rowspan="2">'.$piosensorInfo.'</td>':'').'</tr>
+<tr align="center"><td>'._T('info_dsusage_count').'</td><td colspan="'.(isset($piosensorInfo)?'2':'3').'">'.$countline.'</td></tr>
+<tr><td align="center" colspan="4">'._T('info_fileusage_top').STORAGE_LIMIT.' '._T('info_0disable1enable').'</td></tr>';
+
+       if(STORAGE_LIMIT){
+               $dat .= '
+<tr align="center"><td>'._T('info_fileusage_limit').'</td><td colspan="2">'.STORAGE_MAX.' KB</td><td rowspan="2">'._T('info_dsusage_usage').'<br /><span style="color: #'.$clrflag_sl.'">'.substr(($tmp_ts_ratio * 100), 0, 6).'</span> %</td></tr>
+<tr align="center"><td>'._T('info_fileusage_count').'</td><td colspan="2"><span style="color: #'.$clrflag_sl.'">'.$tmp_total_size.' KB</span></td></tr>';
+       }else{
+               $dat .= '
+<tr align="center"><td>'._T('info_fileusage_count').'</td><td>'.$tmp_total_size.' KB</td><td colspan="2">'._T('info_dsusage_usage').'<br /><span style="color: green;">'._T('info_fileusage_unlimited').'</span></td></tr>';
+       }
+
+       $dat .= '
+<tr><td align="center" colspan="4">'._T('info_server_top').'</td></tr>
+<tr align="center"><td colspan="3">PHP version</td><td>'.phpversion().'</td></tr>
+<tr align="center"><td colspan="3">'.$func_thumbInfo.'</td><td>'.$func_thumbWork.'</td></tr>
+</table>
+<hr />
+</div>'."\n";
+
+       foot($dat);
+       echo $dat;
+}
+
+/* 程式首次執行之初始化 */
+/* 初期設定 */
+function init(){
+       global $PIO, $FileIO, $language;
+       if(!is_writable(realpath('./'))) error(_T('init_permerror'));
+
+       $chkfolder = array(IMG_DIR, THUMB_DIR, 'cache/');
+       // 逐一自動建置資料夾
+       foreach($chkfolder as $value) if(!is_dir($value)){ mkdir($value); @chmod($value, 0777); }  // 沒有就建立
+
+       $PIO->dbInit(); // PIO Init
+       $FileIO->init(); // FileIO Init
+
+       error(_T('init_inited'));
+}
+
+/*-----------程式各項功能主要判斷-------------*/
+/*-----------Main-------------*/
+if(GZIP_COMPRESS_LEVEL && ($Encoding = CheckSupportGZip())){ ob_start(); ob_implicit_flush(0); } // 支援且開啟Gzip壓縮就設緩衝區
+$mode = isset($_GET['mode']) ? $_GET['mode'] : (isset($_POST['mode']) ? $_POST['mode'] : ''); // 目前執行模式 (GET, POST)
+
+//init(); // ←■■!程式環境初始化,跑過一次後請刪除此行!■■
+switch($mode){
+       case 'regist':
+               regist();
+               break;
+       case 'admin':
+               $admin = isset($_REQUEST['admin']) ? $_REQUEST['admin'] : ''; // 管理者執行模式
+               valid();
+               switch($admin){
+                       case 'del': admindel(); break;
+                       case 'logout':
+                               adminAuthenticate('logout');
+                               header('HTTP/1.1 302 Moved Temporarily');
+                               header('Location: '.fullURL().PHP_SELF2.'?'.time());
+                               break;
+                       case 'optimize':
+                       case 'check':
+                       case 'repair':
+                       case 'export':
+                               if(!$PIO->dbMaintanence($admin)) echo _T('action_main_notsupport');
+                               else echo _T('action_main_'.$admin).(($mret = $PIO->dbMaintanence($admin,true))?_T('action_main_success'):_T('action_main_failed')).(is_bool($mret)?'':'<br/>'.$mret);
+                               die("</div></form></body>\n</html>");
+                               break;
+                       case 'stylesheets': manage_css(); break;
+                       default:
+               }
+               break;
+       case 'search':
+               search();
+               break;
+       case 'status':
+               showstatus();
+               break;
+       case 'category':
+               searchCategory();
+               break;
+       case 'module':
+               $loadModule = isset($_GET['load']) ? $_GET['load'] : '';
+               if($PMS->onlyLoad($loadModule)) $PMS->moduleInstance[$loadModule]->ModulePage();
+               else echo '404 Not Found';
+               break;
+       case 'moduleloaded':
+               listModules();
+               break;
+       case 'init':
+               init(); // ←■■!程式環境初始化,跑過一次後請刪除此行!■■
+               break;
+       case 'usrdel':
+               usrdel();
+       case 'remake':
+               updatelog();
+               header('HTTP/1.1 302 Moved Temporarily');
+               header('Location: '.fullURL().PHP_SELF2.'?'.time());
+               break;
+       default:
+               // 如果瀏覽器支援XHTML標準MIME就輸出
+               header('Content-Type: '.((USE_XHTML && strpos($_SERVER['HTTP_ACCEPT'],'application/xhtml+xml')!==FALSE) ? 'application/xhtml+xml' : 'text/html').'; charset=utf-8');
+               $res = isset($_GET['res']) ? $_GET['res'] : 0; // 欲回應編號
+               if($res){ // 回應模式輸出
+                       $page = isset($_GET['page_num']) ? $_GET['page_num'] : 'RE_PAGE_MAX';
+                       if(!($page=='all' || $page=='RE_PAGE_MAX')) $page = intval($_GET['page_num']);
+                       updatelog($res, $page); // 實行分頁
+               }elseif(isset($_GET['page_num']) && intval($_GET['page_num']) > -1){ // PHP動態輸出一頁
+                       updatelog(0, intval($_GET['page_num']));
+               }else{ // 導至靜態庫存頁
+                       if(!is_file(PHP_SELF2)) updatelog();
+                       header('HTTP/1.1 302 Moved Temporarily');
+                       header('Location: '.fullURL().PHP_SELF2.'?'.time());
+               }
+}
+if(GZIP_COMPRESS_LEVEL && $Encoding){ // 有啟動Gzip
+       if(!ob_get_length()) exit; // 沒內容不必壓縮
+       header('Content-Encoding: '.$Encoding);
+       header('X-Content-Encoding-Level: '.GZIP_COMPRESS_LEVEL);
+       header('Vary: Accept-Encoding');
+       print gzencode(ob_get_clean(), GZIP_COMPRESS_LEVEL); // 壓縮內容
+}
+?>