• R/O
  • SSH
  • HTTPS

momoutils: Commit


Commit MetaInfo

Revision20 (tree)
Time2007-02-11 13:57:05
Authorhisame

Log Message

  • 投稿内容に対する字数制限・行数制限機能を追加。
  • エラー表示を強化。
  • ソースコードの整理(一部クラス化)

データクラス、エラークラス、validatorクラスを新規作成。
これに併せて各所変更。

Change Summary

Incremental Difference

--- momosimplebbs/trunk/README.ja.txt (revision 19)
+++ momosimplebbs/trunk/README.ja.txt (revision 20)
@@ -12,7 +12,7 @@
1212
1313
1414 3.使い方
15- 1. srcディレクトリの名前を変更し、そのディレクトリ毎PHPが使用できるサーバにアップロードします。
15+ 1. srcディレクトリの名前を変更し、そのディレクトリごとPHPが使用できるサーバにアップロードします。
1616 2. logディレクトリと_lockディレクトリのパーミッションを777にして下さい。
1717
1818 なお、「config.php」を編集することで以下の設定できます。
@@ -20,6 +20,8 @@
2020 * 一度に表示する件数
2121 * 投稿者のIPの表示・非表示の設定
2222 * この掲示板のバージョンと配布サイトへのリンク表示有無の設定
23+ * 投稿時の名前・タイトル・メッセージの最大文字数
24+ * 投稿時のメッセージの最大行数
2325
2426
2527 4.連絡先について
@@ -29,6 +31,11 @@
2931
3032
3133 5.変更履歴
34+0.1.4 2007/02/11
35+ * 投稿内容に対する字数制限・行数制限機能を追加。
36+ * エラー表示を強化。
37+ * ソースコードの整理(一部クラス化)
38+
3239 0.1.3 2007/02/08
3340 * ディレクトリを用いたファイルロック機能を実装。
3441
--- momosimplebbs/trunk/doc/dev_note.txt (revision 19)
+++ momosimplebbs/trunk/doc/dev_note.txt (revision 20)
@@ -32,9 +32,12 @@
3232 index.php
3333 メッセージの表示、メッセージの入力欄
3434
35-func_momosimplebbs.php
35+momosimplebbs.inc.php
3636 このPHPプログラムで使用される関数郡
3737
38+data.class.php
39+ このプログラムで使用されるクラス群
40+
3841 postresult.php
3942 index.phpからのメッセージ投稿の可否を表示する
4043
--- momosimplebbs/trunk/src/data.class.php (nonexistent)
+++ momosimplebbs/trunk/src/data.class.php (revision 20)
@@ -0,0 +1,279 @@
1+<?
2+/**
3+ * @author S.Isogai
4+ * @copyright 2007 momoutils project
5+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
6+ * @link http://momoutils.sourceforge.jp/
7+ */
8+require_once("common.php");
9+
10+/**
11+ *
12+ */
13+class MessageData {
14+ var $_name;
15+ var $_title;
16+ var $_ip;
17+ var $_date;
18+ var $_message;
19+
20+ var $validator;
21+
22+ /**
23+ * Constructor
24+ */
25+ function MessageData($name="", $title="", $ip="", $date="", $message="") {
26+ $this->__construct($name, $title, $ip, $date, $message);
27+ }
28+
29+ /**
30+ * PHP5 Constructor
31+ */
32+ function __construct($name="", $title="", $ip="", $date="", $message="") {
33+ $this->_name = $name;
34+ $this->_title = $title;
35+ $this->_ip = $ip;
36+ $this->_date = $date;
37+ $this->_message = $message;
38+
39+ $this->validator = new Validator();
40+ }
41+
42+ function sanitizingHtmlTagAll() {
43+ $this->_name = htmlspecialchars($this->_name, ENT_QUOTES);
44+ $this->_title = htmlspecialchars($this->_title, ENT_QUOTES);
45+ $this->_ip = htmlspecialchars($this->_ip, ENT_QUOTES);
46+ $this->_date = htmlspecialchars($this->_date, ENT_QUOTES);
47+ $this->_message = htmlspecialchars($this->_message, ENT_QUOTES);
48+ }
49+
50+ function replaceLineFeedAll($flag_xhtml = false) {
51+ $this->_name = eregi_replace("\r|\n", "", $this->_name);
52+ $this->_title = eregi_replace("\r|\n", "", $this->_title);
53+ $this->_ip = eregi_replace("\r|\n", "", $this->_ip);
54+ $this->_date = eregi_replace("\r|\n", "", $this->_date);
55+
56+ // 改行文字を<br>に変換
57+ $this->_message = eregi_replace("\r\n", "\n", $this->_message);
58+ $this->_message = eregi_replace("\r", "\n", $this->_message);
59+ if ($flag_xhtml){
60+ $this->_message = eregi_replace("\n", "<br />", $this->_message);
61+ }
62+ else {
63+ $this->_message = eregi_replace("\n", "<br>", $this->_message);
64+ }
65+ }
66+
67+ function toLogString() {
68+ $strLog = "";
69+ $strLog .= $this->_date . "<>" . $this->_ip . "<>";
70+ $strLog .= $this->_title . "<>" . $this->_name . "<>";
71+ $strLog .= $this->_message ."\n";
72+ return $strLog;
73+ }
74+
75+ function setValidateRule($namelen=0, $titlelen=0, $messagelen=0, $messagelinelen=0) {
76+ $this->validator->addRule($this->_name, "名前は必須項目です。", "required");
77+ $this->validator->addRule($this->_name, "名前は".$namelen."文字以内です。", "maxlen", $namelen);
78+ $this->validator->addRule($this->_title, "タイトルは必須項目です。", "required");
79+ $this->validator->addRule($this->_title, "タイトルは".$titlelen."文字以内です。", "maxlen", $titlelen);
80+ $this->validator->addRule($this->_message, "内容は必須項目です。", "required");
81+ $this->validator->addRule($this->_message, "内容は".$messagelen."文字以内です。", "maxlen", $messagelen);
82+ $this->validator->addRule($this->_message, "内容の行数は".$messagelinelen."個以内です。", "maxline", $messagelinelen);
83+ }
84+
85+ function validate() {
86+ return $this->validator->validate();
87+ }
88+
89+ function getError() {
90+ return $this->validator->err;
91+ }
92+}
93+
94+
95+class Validator {
96+ /** error */
97+ var $err;
98+ var $_rule;
99+
100+ /**
101+ * Constructor
102+ */
103+ function Validator() {
104+ $this->__construct();
105+ }
106+
107+ /**
108+ * PHP5 Constructor
109+ */
110+ function __construct() {
111+ $this->err = new Error();
112+ $this->_rule = array();
113+ }
114+
115+ function validate() {
116+ for ($ii = 0; $ii < count($this->_rule); $ii++) {
117+ switch ($this->_rule[$ii]->type) {
118+ case "maxlen":
119+ if (!$this->_checkMaxLength($this->_rule[$ii]->content, $this->_rule[$ii]->prop1)) {
120+ $this->err->add($this->_rule[$ii]->message);
121+ }
122+ break;
123+ case "minlen":
124+ if (!$this->_checkMinLength($this->_rule[$ii]->content, $this->_rule[$ii]->prop1)) {
125+ $this->err->add($this->_rule[$ii]->message);
126+ }
127+ break;
128+ case "required":
129+ if (!$this->_checkRequired($this->_rule[$ii]->content)) {
130+ $this->err->add($this->_rule[$ii]->message);
131+ }
132+ break;
133+ case "maxline":
134+ if (!$this->_checkMaxLineLength($this->_rule[$ii]->content, $this->_rule[$ii]->prop1)) {
135+ $this->err->add($this->_rule[$ii]->message);
136+ }
137+ }
138+ }
139+
140+ return !$this->err->hasError();
141+ }
142+
143+ function addRule($content, $message, $type, $prop1=0) {
144+ $this->_rule[] = new ValidateRule($content, $message, $type, $prop1);
145+ }
146+
147+ function _checkMaxLength($data, $max) {
148+ if (mb_strlen($data) > $max) {
149+ return false;
150+ }
151+ return true;
152+ }
153+
154+ function _checkMinLength($data, $min) {
155+ if (mb_strlen($data) < $min) {
156+ return false;
157+ }
158+ return true;
159+ }
160+
161+ function _checkRequired($data) {
162+ if (is_null($data) || $data == "") {
163+ return false;
164+ }
165+ return true;
166+ }
167+
168+ function _checkMaxLineLength($data, $max) {
169+ $data = eregi_replace("\r\n", "\n", $data);
170+ $data = eregi_replace("\r", "\n", $data);
171+ $count = substr_count($data, "\n");
172+
173+ if ($count > $max) {
174+ return false;
175+ }
176+ return true;
177+ }
178+
179+}
180+
181+class ValidateRule {
182+ /** validateする内容 */
183+ var $content;
184+ /** エラー時のメッセージ */
185+ var $message;
186+ /** チェックタイプ */
187+ var $type;
188+ /** チェックに使用する引数 */
189+ var $prop1;
190+
191+ function ValidateRule($ruleContent, $ruleMessage, $ruleType, $ruleProp1=0) {
192+ $this->__construct($ruleContent, $ruleMessage, $ruleType, $ruleProp1);
193+ }
194+
195+ function __construct($ruleContent, $ruleMessage, $ruleType, $ruleProp1=0) {
196+ $this->content = $ruleContent;
197+ $this->message = $ruleMessage;
198+ $this->type = $ruleType;
199+ $this->prop1 = $ruleProp1;
200+ }
201+}
202+
203+class Error {
204+ var $_error;
205+
206+ /** エラー毎の区切り文字を指定 */
207+ var $separator;
208+ /** エラーの前に表示するヘッダー */
209+ var $header;
210+ /** エラーの後に表示するフッター */
211+ var $footer;
212+
213+ /**
214+ * コンストラクタ
215+ */
216+ function Error() {
217+ $this->__construct();
218+ }
219+
220+ /**
221+ * PHP5 コンストラクタ
222+ */
223+ function __construct() {
224+ $this->_error = array();
225+ $this->separator = $this->header = $this->footer = "";
226+ }
227+
228+ /**
229+ * エラーの数を数える。
230+ * @return エラーの数
231+ */
232+ function count() {
233+ return count($this->_error);
234+ }
235+
236+ /**
237+ * エラーを追加する。
238+ * @param $message エラーメッセージ
239+ */
240+ function add($message) {
241+ $this->_error[] = $message;
242+ }
243+
244+ /**
245+ * 全てのエラーメッセージを表示する。<br>
246+ * $separatorを区切り文字として出力する。<br>
247+ * エラーがなければ何もしない。
248+ */
249+ function showAllMessages() {
250+ $count = $this->count();
251+ if ($this->hasError) {
252+ return;
253+ }
254+
255+ print $this->header;
256+ for ($ii = 0; $ii < $count; $ii++) {
257+ print $this->_error[$ii];
258+ if ($ii < ($count - 1)) {
259+ print $this->separator;
260+ }
261+ }
262+ print $this->footer;
263+ }
264+
265+ /**
266+ * エラーが存在すればtrue、エラーがなければfalseを返す。
267+ * @retrun エラーが存在すればtrue、エラーがなければfalseを返す。
268+ */
269+ function hasError() {
270+ if ($this->count() < 1) {
271+ return false;
272+ }
273+ else {
274+ return true;
275+ }
276+ }
277+}
278+
279+?>
--- momosimplebbs/trunk/src/momosimplebbs.inc.php (revision 19)
+++ momosimplebbs/trunk/src/momosimplebbs.inc.php (revision 20)
@@ -1,4 +1,10 @@
11 <?php
2+/**
3+ * @author S.Isogai
4+ * @copyright 2007 momoutils project
5+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
6+ * @link http://momoutils.sourceforge.jp/
7+ */
28 require_once("common.php");
39
410 /**
@@ -102,37 +108,37 @@
102108 /**
103109 * メッセージをファイルに書き込む
104110 *
105- * @return 成功時は1を返す。書き込めなかった場合はfalseを返す。
111+ * @return 成功時はtrueを返す。書き込めなかった場合はクラスErrorを返す。
106112 */
107-function writeMessage($title, $name, $date, $ip, $message)
113+function writeMessage($messageData)
108114 {
109115 global $logDirName, $logFileName;
110116
111- $title = eregi_replace("\r\n", "", htmlspecialchars($title, ENT_QUOTES));
112- $title = eregi_replace("\n", "", $title);
113- $name = eregi_replace("\r\n", "", htmlspecialchars($name, ENT_QUOTES));
114- $name = eregi_replace("\n", "", $name);
115- $date = eregi_replace("\r\n", "", htmlspecialchars($date, ENT_QUOTES));
116- $date = eregi_replace("\n", "", $date);
117- $ip = eregi_replace("\r\n", "", htmlspecialchars($ip, ENT_QUOTES));
118- $ip = eregi_replace("\n", "", $ip);
119- $message = eregi_replace("\r\n", "<br>", htmlspecialchars($message, ENT_QUOTES));
120- $message = eregi_replace("\n", "<br>", $message);
117+ $err = new Error();
118+
119+ $messageData->sanitizingHtmlTagAll();
120+ $messageData->replaceLineFeedAll();
121121
122- $input = "$date<>$ip<>$title<>$name<>$message\n";
122+ $input = $messageData->toLogString();
123+
124+ if (!file_exists($logDirName) && !is_dir($logDirName)) {
125+ $err->add("ログディレクトリ".$logDirName."が存在しません");
126+ return $err;
127+ }
128+
123129 if (!$fp = fopen($logDirName . "/" . $logFileName, 'a')) {
124- echo "$logDirName/$logFileNameが開けません。";
125- return false;
130+ $err->add("$logDirName/$logFileNameが開けません。");
131+ return $err;
126132 }
127133
128134 if (!lockDir($logFileName)) {
129- echo "混雑しています。\n";
130- return false;
135+ $err->add("ただ今混雑していますので、暫くしてからまた投稿して下さい。");
136+ return $err;
131137 }
132138
133139 if (fwrite($fp, $input) == false) {
134- echo "$logDirName/$logFileNameに書き込めません。";
135- return false;
140+ $err->add("$logDirName/$logFileNameに書き込めません。");
141+ return $err;
136142 }
137143
138144 unlockDir($logFileName);
@@ -139,9 +145,17 @@
139145
140146 fclose($fp);
141147
142- return 1;
148+ return true;
143149 }
144150
151+function validateMessage(&$messageData) {
152+ global $maxTitleLength, $maxNameLength, $maxMessageLength, $maxMessageLine;
153+
154+ $messageData->setValidateRule($maxNameLength, $maxTitleLength, $maxMessageLength, $maxMessageLine);
155+ return $messageData->validate();
156+}
157+
158+
145159 /**
146160 * ディレクトリを用いたロックを行う。<br>
147161 * ロックの解除にはunlockDir関数を使うこと。
@@ -190,6 +204,18 @@
190204 }
191205
192206 /**
207+ * クラスErrorのエラーメッセージを表示する。
208+ */
209+function viewError($err) {
210+ $err->header = '<font color="red">';
211+ $err->footer = '</font>' . "\n";
212+ $err->separator = '<br>' . "\n";
213+
214+ $err->showAllMessages();
215+}
216+
217+
218+/**
193219 * ブラウザにキャッシュさせないためのHTTPヘッダーを設定。
194220 * この関数はHTMLタグを記述する前に実行する必要がある。
195221 *
--- momosimplebbs/trunk/src/postresult.php (revision 19)
+++ momosimplebbs/trunk/src/postresult.php (revision 20)
@@ -1,4 +1,11 @@
11 <?php
2+/**
3+ * @author S.Isogai
4+ * @copyright 2007 momoutils project
5+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
6+ * @link http://momoutils.sourceforge.jp/
7+ */
8+
29 header("Content-Type: text/html; charset=EUC-JP");
310 header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
411 header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
@@ -8,25 +15,32 @@
815
916 require_once("common.php");
1017
11-
12-$name = $_POST['name'];
13-$title = $_POST['title'];
14-$message = $_POST['message'];
18+$messageData = new MessageData();
19+$messageData->_name = $_POST['name'];
20+$messageData->_title = $_POST['title'];
21+$messageData->_message = $_POST['message'];
1522 // 海外のサーバでも日本時間で動く
16-$date = gmdate("Y/m/d H:i:s", time() + 9 * 3600);
17-$ip = $_SERVER['REMOTE_ADDR'];
23+$messageData->_date = gmdate("Y/m/d H:i:s", time() + 9 * 3600);
24+$messageData->_ip = $_SERVER['REMOTE_ADDR'];
1825
19-if (empty($name) || empty($title) || empty($message)) {
26+if (!validateMessage($messageData)) {
2027 $postResultFlag = false;
28+ $err = $messageData->getError();
2129 }
2230 else {
23- if (writeMessage($title, $name, $date, $ip, $message) == false) {
24- $postResultFlag = false;
31+ $result = writeMessage($messageData);
32+ if (is_object($result) && strcasecmp(get_class($result), 'Error') == 0) {
33+ $postResultFlag = false;
34+ $err = $result;
2535 }
2636 else {
27- $postResultFlag = true;
37+ $postResultFlag = true;
2838 }
2939 }
40+
41+$messageData->sanitizingHtmlTagAll();
42+$messageData->replaceLineFeedAll();
43+
3044 ?>
3145 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
3246 <html>
@@ -42,6 +56,7 @@
4256 }
4357 else {
4458 print "<p>投稿に失敗しました。</p>";
59+ viewError($err);
4560 }
4661 ?>
4762 <h2>投稿内容</h2>
@@ -49,23 +64,23 @@
4964 <table class="postmessage">
5065 <tr>
5166 <td class="postmessage">名前</td>
52- <td class="postmessage"><?php print $name; ?></td>
67+ <td class="postmessage"><?php print $messageData->_name; ?></td>
5368 </tr>
5469 <tr>
5570 <td class="postmessage">タイトル</td>
56- <td class="postmessage"><?php print $title; ?></td>
71+ <td class="postmessage"><?php print $messageData->_title; ?></td>
5772 </tr>
5873 <tr>
5974 <td class="postmessage">投稿時間</td>
60- <td class="postmessage"><?php print $date; ?></td>
75+ <td class="postmessage"><?php print $messageData->_date; ?></td>
6176 </tr>
6277 <tr>
6378 <td class="postmessage">IP</td>
64- <td class="postmessage"><?php print $ip; ?></td>
79+ <td class="postmessage"><?php print $messageData->_ip; ?></td>
6580 </tr>
6681 <tr>
6782 <td class="postmessage">内容</td>
68- <td class="postmessage"><?php print eregi_replace("\n", "<br>" ,$message); ?></td>
83+ <td class="postmessage"><?php print $messageData->_message ?></td>
6984 </tr>
7085 </table>
7186 </div>
--- momosimplebbs/trunk/src/config.php (revision 19)
+++ momosimplebbs/trunk/src/config.php (revision 20)
@@ -2,10 +2,20 @@
22 // BBSの名前を設定してください。
33 $bbsName = "momo Simple BBS";
44 // 一度に表示する件数を設定してください。
5-$maxKensu = 5;
5+$maxKensu = 15;
66 // 投稿者のIPを表示する場合はtrue,表示しない場合はfalseにしてください。
77 $isViewIP = false;
88 // この掲示板のバージョンとスクリプト配布サイトへのリンクを表示する場合はtrue,
99 // 表示しない場合はfalseに設定してください。
1010 $isViewBBSVer = true;
11+
12+// メッセージタイトルの最大文字数
13+$maxTitleLength = 100;
14+// 投稿者名の最大文字数
15+$maxNameLength = 40;
16+// メッセージの最大文字数
17+$maxMessageLength = 3000;
18+// メッセージの最大行数
19+$maxMessageLine = 25;
20+
1121 ?>
--- momosimplebbs/trunk/src/common.php (revision 19)
+++ momosimplebbs/trunk/src/common.php (revision 20)
@@ -1,15 +1,17 @@
11 <?php
2+/**
3+ * @author S.Isogai
4+ * @copyright 2007 momoutils project
5+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
6+ * @link http://momoutils.sourceforge.jp/
7+ */
8+
29 require_once("config.php");
310 require_once("momosimplebbs.inc.php");
11+require_once("data.class.php");
412
513 // このBBSのバージョン
6-$bbsVer = "0.1.3";
7-// メッセージタイトルの最大文字数
8-$maxTitleLength = 100;
9-// 投稿者名の最大文字数
10-$maxNameLength = 40;
11-// 内容の最大文字数
12-$maxNaiyouLength = 3000;
14+$bbsVer = "0.1.4";
1315
1416 // ログファイル名
1517 $logFileName = "message.log";
Show on old repository browser