掲示板を作成したのでぜひアドバイスをください! - PHPプロ!Q&A掲示板

3460

  • 0P

掲示板を作成したのでぜひアドバイスをください!

質問日時 / 2011年10月30日 02:51    回答数 / 6件

Questioner:  sryou1985  このエントリーをはてなブックマークに追加 

キーワード / 掲示板    アドバイス   

掲示板の登録フォームを趣味で作成しました。
なんせ初めて作成したものですから、「これで正しいのか?」「セキュリティー上の問題はないのか?」ととても不安です。
そこで、このコードをご覧になって「ここはこうしたほうがいい」「このあたりは関数で省略できる」等のアドバイスがございましたら、ぜひ下さい。
ダメ出しでもかまいませんので、どうかよろしくお願いいたします!

function.php
  1. <?php
  2. /***データベース接続関数***/
  3. function setuzoku() {
  4. //サーバー
  5. $sv="localhost";
  6. //データベース名
  7. $dbname="keijiban";
  8. //ユーザー名
  9. $user="root";
  10. //パスワード
  11. $pass="****";
  12. $connmysql_connect($sv,$user,$pass) or die(mysql_error());
  13. mysql_select_db($dbname) or die(mysql_error());
  14.  
  15. }
  16.  
  17. /***エラーッチェック関数***/
  18. function error_check($name,$title,$body) {
  19.     //エラーフラグ(0=エラーなし、1=エラーあり)とメッセージを保存
  20.     $err = array();
  21.     //エラーメッセージを代入
  22.     
  23. //名前のエラーチェック
  24.     if($name=="") {
  25.         $err["name"]="名前を入力してください<br>";
  26.     }elseif(mb_strlen($name)>10) {
  27.         $err["longname"]="名前は10文字以内で入力してください<br>";  
  28.     }
  29.          //名前の重複チェック
  30.          $sql = sprintf('select count(*) as cnt from keijiban where name="%s"',
  31.              mysql_real_escape_string($name)
  32.             );
  33.          $record = mysql_query($sql) or die(mysql_error());
  34.          $table = mysql_fetch_array($record,MYSQL_ASSOC);
  35.          if($table['cnt'] > 0){
  36.              $err["doublename"] = "既に登録されています";
  37.              }
  38.             
  39.     
  40.     //タイトルのエラーチェック 
  41.     if($title == "") {  
  42.         $err["title"]="タイトルを入力してください。<br>";
  43.         
  44.     } 
  45.  
  46.     //本文のエラーチェック 
  47.     if($body == "") {  
  48.         $err["body"]="本文を入力してください。<br>";
  49.     } 
  50.  
  51.     //上記の処理でエラーがなかったら 
  52.     if(empty($err)){ 
  53.         $_SESSION=$_POST;
  54.         header("Location:check.php");
  55.         //エラーがあれば
  56.     } else {
  57.         //エラー配列を返す
  58.         return $err;
  59.     }
  60. }
  61.  
  62. //文字列をエスケープする関数
  63. function check($string) {
  64.     if (get_magic_quotes_gpc()) {
  65.             $string = stripslashes($string);
  66.         }
  67.         $string = htmlspecialchars($string,ENT_QUOTES,'UTF-8');
  68.         return $string;
  69.     }   
  70.  
  71. //年齢のセレクトボックスを作成する関数
  72. function nenreilist($inputName,$sentaku,$i = "") {
  73.      $temphtml='<select name="'check($inputName)'">'"\n";
  74.     for ($i=18;$i<=100;$i++) {
  75.        if ($i == $sentaku) {
  76.             $selectedText = ' selected="selected"';
  77.         } else {
  78.             $selectedText = '';
  79.         }
  80.    $temphtml .= '<option value="'check($i)'歳"'$selectedText'>'check($i)'歳</option>' . $i . '</option>'"\n";
  81.     }
  82.     $temphtml .= '</select>'"\n";
  83.     return $temphtml;
  84. }
  85.  
  86. //データベースへ登録する関数
  87. function kakikomu($name,$nenrei,$title,$body) {
  88.   $sql = sprintf('select count(*) as cnt from keijiban where name="%s"',
  89.              mysql_real_escape_string($name)
  90.             );
  91.          $record = mysql_query($sql) or die(mysql_error());
  92.          $table = mysql_fetch_array($record,MYSQL_ASSOC);
  93.          if($table['cnt'] > 0){
  94.              $_SESSION["doublename"] = "既に登録されています";
  95.              header("Location:form.php");
  96.          } else {
  97.              $sql=sprintf('insert into keijiban set name="%s", nenrei="%s",
  98.              title="%s",body="%s",created=now()',
  99.   mysql_real_escape_string($name),
  100.   mysql_real_escape_string($nenrei),
  101.   mysql_real_escape_string($title),
  102.   mysql_real_escape_string($body)
  103.   );
  104.   mysql_query($sql) or die(mysql_error());
  105.  
  106. }
  107. }
  108. ?>
form.php
  1. <?php
  2. //関数ファイルを読み込む
  3. require_once("function.php");
  4. setuzoku();
  5. session_start();
  6. $name="";
  7. $nenrei="";
  8. $title="";
  9. $body="";
  10. $errmsg=array();
  11. $error_name="";
  12. $error_longname="";
  13. $error_doublename="";
  14. $error_title="";
  15. $error_body="";
  16.  
  17.  
  18. //ボタンが押されたら
  19. if(isset($_POST["submit"]) && !empty ($_POST["submit"])) {
  20.     //エラーチェック関数を呼び出す
  21.     $errmsg=error_check($_POST["name"],$_POST["title"],$_POST["body"]);   
  22.     $name=check($_POST["name"]);
  23.     $nenrei=check($_POST["nenrei"]);
  24.     $title = check($_POST["title"]);
  25.     $body = check($_POST["body"]);
  26.  
  27. }
  28.  
  29. //エラーがあれば表示する
  30. if(isset($errmsg["name"])) {
  31.     $error_name=$errmsg["name"];
  32. }
  33. //エラーがあれば表示する
  34. if(isset($errmsg["longname"])) {
  35.     $error_longname=$errmsg["longname"];
  36. } 
  37. //エラーがあれば表示する
  38. if(isset($errmsg["doublename"])) {
  39.     $error_doublename=$errmsg["doublename"];
  40. }
  41. //エラーがあれば表示する
  42. if(isset($errmsg["title"])) {
  43.     $error_title=$errmsg["title"];
  44. } 
  45. //エラーがあれば表示する
  46. //エラーがあれば表示する
  47. if(isset($errmsg["body"])) {
  48.     $error_body=$errmsg["body"];
  49. } 
  50.  
  51.  
  52. //確認画面からの書き直し
  53. if(isset($_POST["ng"])&& !empty ($_POST["ng"])) {
  54.     $name=check($_SESSION["name"]);
  55.     $nenrei=check($_SESSION["nenrei"]);
  56.     $title=check($_SESSION["title"]);
  57.     $body=check($_SESSION["body"]);
  58. }
  59.  
  60. //登録ボタンを押したときに名前が重複していたら
  61. if(isset ($_SESSION["doublename"])) {
  62.     $name=check($_SESSION["name"]);
  63.     $nenrei=check($_SESSION["nenrei"]);
  64.     $title=check($_SESSION["title"]);
  65.     $body=check($_SESSION["body"]);
  66.     $error_doublename=$_SESSION["doublename"];
  67. }
  68. ?>
  69. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  70. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
  71. <head>
  72. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  73. <meta http-equiv="Content-Script-Type" content="text/javascript" />
  74. <meta http-equiv="Content-Style-Type" content="text/css" />
  75. <meta name="description" content="" />
  76. <meta name="keywords" content="" />
  77. <title>掲示板書き込みフォーム</title>
  78.  
  79. </head>
  80. <body>
  81. <h1>掲示板</h1>
  82. <!--エラーがなかったら飛ばす-->
  83. <form method="post" action="<?php echo $_SERVER['SCRIPT_NAME']?>">
  84. <dl>
  85.     <!--エラーメッセージをあるだけ表示する-->
  86.     <dd><font color="#FF0000"></font></dd>
  87. </dl>
  88. <dl>
  89.     <dt><label for="name">名前</label></dt>
  90.     <?php echo $error_name ?>
  91.     <?php echo $error_longname ?>
  92.     <?php echo $error_doublename ?>
  93.  
  94.     
  95.     <dd><input type="text" id="name" name="name" value="<?php echo $name ?>" /></dd>
  96.     <dt><label for="name">年齢</label></dt>
  97.     <dd><?php echo nenreilist("nenrei",$nenrei)?></dd>
  98.     <dt><label for="title">タイトル</label></dt>
  99.     <?php echo $error_title ?>
  100.     <dd><input type="text" id="title" name="title"  value="<?php echo $title ?>" /></dd>
  101.     <dt><label for="body">本文</label></dt> 
  102.     <?php echo $error_body ?>
  103.     <dd><textarea id="body" name="body" cols="40" rows="10"><?php echo $body ?></textarea></dd>
  104. </dl>
  105. <input type="submit" id="submit" name="submit" value="確認" />
  106. </form>
  107. </body>
  108. </html>
check.php
  1. <?php
  2. //関数ファイルを読み込む
  3. require_once("function.php");
  4. setuzoku();
  5. session_start();
  6. $view_name="";
  7. $view_nenrei="";
  8. $view_title="";
  9. $view_body="";
  10.  
  11. //セッションが存在すれば
  12. if(isset($_SESSION)){
  13.     //セッションに値を保存する
  14.     $view_name = check($_SESSION["name"]);
  15.     $view_nenrei = check($_SESSION["nenrei"]);
  16.     $view_title = check($_SESSION["title"]);
  17.     $view_body = check($_SESSION["body"]);
  18.     $view_body=nl2br($view_body);
  19.   
  20.     }
  21. ?>
  22.  
  23. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  24. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
  25. <head>
  26. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  27. <meta http-equiv="Content-Script-Type" content="text/javascript" />
  28. <meta name="description" content="" />
  29. <meta name="keywords" content="" />
  30. <title>掲示板書き込み確認</title>
  31. </head>
  32. <body>
  33. <h1>掲示板投稿確認</h1>
  34.  
  35. <dl class="message">
  36.         <dt class="msg-label">名前</dt>
  37.         <dd class="msg-name"><?php echo check($view_name) ?></dd>
  38.         <dt class="msg-label">年齢</dt>
  39.         <dd class="msg-name"><?php echo check($view_nenrei) ?></dd>
  40.         <dt class="msg-label">タイトル</dt>
  41.         <dd class="msg-title"><?php echo check($view_title) ?></dd>
  42.         <dt class="msg-label">本文</dt>
  43.         <dd class="msg-body"><?php echo check($view_body) ?></dd>
  44. </dl>
  45. <p>登録する内容にお間違いはございませんか?</p>
  46. <div class="formButtons01 editEndBd">
  47.     <ul>
  48.         <li><form action="form.php" method="post">
  49.  
  50. <input type="submit" name="ng" value="書き直します" />
  51.  
  52. </form>
  53.         </li>
  54.         <li>
  55. <form action="thanks.php" method="post">
  56.  
  57. <input type="submit" name="ok" value="登録します" />
  58. </form>
  59.         </li>
  60. </ul>
  61. </div>
  62.     
  63. </body>
  64. </html>
thanks.php
  1. <?php 
  2. //関数ファイルを読み込む 
  3. require_once("function.php")
  4. setuzoku();
  5. session_start();
  6.     
  7. if(isset($_POST["ok"])&& !empty ($_POST["ok"])) {
  8.  
  9. //データベースへ登録する関数を呼び出す
  10. kakikomu($_SESSION["name"],$_SESSION["nenrei"],$_SESSION["title"],
  11.         $_SESSION["body"]);
  12. }
  13. ?>
  14.  
  15. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  16. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
  17. <head>
  18. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  19. <meta http-equiv="Content-Script-Type" content="text/javascript" />
  20. <meta http-equiv="Content-Style-Type" content="text/css" />
  21. <meta name="description" content="" />
  22. <meta name="keywords" content="" />
  23. <title>掲示板書き込み完了</title> 
  24. <style type="text/css"> 
  25.     * { margin: 0px; padding: 0px; } 
  26.     body { margin-left: 10%; margin-right: 10%;  
  27. padding-bottom: 1em; color: #333333; background-color: #E0E0E0;} 
  28.     h1 { padding: 10px; border: 1px solid #BDBDBD;  
  29. font-size: 1.2em; color: #545454; background-color: #FFFFFF; } 
  30.     hr { display: none; } 
  31.     table { margin-bottom: 1em;  } 
  32.     dt { clear: left; float: left; width: 5em;  
  33. margin-bottom: 5px; } 
  34.     dd { margin-bottom: 5px; } 
  35.     form {margin-bottom: 1em; padding: 10px;  
  36. border-left: 1px solid #BDBDBD; border-bottom: 1px solid #BDBDBD;  
  37. border-right: 1px solid #BDBDBD; color: #333333;  
  38. background-color: #EAEAEA; } 
  39.     #name, #title { width: 15em; } 
  40.     #submit { font-size: 1em; margin-left: 5em; } 
  41.     .message { padding: 10px; margin-bottom: 1em;  
  42. border: 1px solid #CBCBCB; color: #333333;  
  43. background-color: #F9F9F9;} 
  44.     .msg-label { color: #666666; background-color: transparent; } 
  45.     .msg-body {margin-left: 5em; } 
  46.     #navigation { text-align: right; } 
  47. </style> 
  48. </head> 
  49. <body> 
  50. <h1>掲示板書き込み完了</h1> 
  51. <dl class="message"> 
  52.         <dt class="msg-label"></dt> 
  53.         <dd class="msg-name">書き込みが完了しました。</dd> 
  54. </dl> 
  55.  
  56. <br /> 
  57. <a href="form.php">書き込みフォームへ戻る</a> 
  58. </body> 
  59. </html>

この質問への意見の募集は締め切られ、ポイントは既に配分されました。
意見を投稿することはできますが、ポイントを受け取ることはできません。



ツリー一覧

┣A01kendeソースを丸っと載せて「ご意見求む」は「チェックして
┃┗A01-1sryou1985かなり図々しい質問をしていたんだと反省しました。
┣A02NurseAngelせっかくなんでてろてろと ・初めてのわりにぱっと
┃┗A02-1sryou1985まさか、こんなド素人にたくさんのアドバイスをしてく
┗A03iroha_code[function.php] 54,95 header();の後にexit; (exit
 ┗A03-1sryou1985まさか、こんなド素人にたくさんのアドバイスをいただ

回答一覧

並び替え:

A01
answererkende [10月31日 10:07]

ソースを丸っと載せて「ご意見求む」は「チェックしてくれ」であって質問ではないです。
なので「有料です」といわれても仕方ありません。
実際にそういう業者さんは高額の費用でお仕事をなさっております。

期待する動作にもっていくには、「テストをして修正」を繰り返すしかないです。
自分で出来ることは自分でチェック!

Selenium, Nessus,  Paros この辺をググると答えに近いものを短時間で見つけることができるかも知れません。

この意見に回答する

ツリーへ TOPへ

A01-1
replyersryou1985 [10月31日 11:50]

かなり図々しい質問をしていたんだと反省しました。
的確なアドバイスありがとうございました。

この意見に回答する

ツリーへ TOPへ

A02 満足
answererNurseAngel [10月31日 21:06]

せっかくなんでてろてろと

・初めてのわりにぱっと見脆弱性的なものが見あたらないのは素晴らしいかなと。

・MVCが混在してるので分離する方向で。
 DB関連はクラスにしてひとつのモデルに切り出すとか。
 まあ、そこらへんはおいおいやっていけばいいです

・エスケープ関数の名前がcheck()みたいに、実体とかけ離れているとあとで見てわからなくなるのでわかりやすくした方がいい

・error_check()で入力値の検証をした後でif (get_magic_quotes_gpc()){stripslashes()}やってるが、これは逆
 stripslashes()→入力値検証→htmlspecialchars()→出力
 まあそれ以前にmagic_quotes_gpcオンのサーバとか今時無いんでスルーしていいと思うが

・エスケープは出力時に行うのがわかりやすくて安全(<?php echo htmlspecialchars($error_title) ?>とする)
 ていうかSmarty使おうぜSmarty

・select count(*) as cnt from keijibanが2箇所にあるのでどこか切り出す

・DBリソースは省略しない($connをmysql_query()とかの引数に渡すようにする)

・「エラーがあれば表示する」はforeachとか使えばもう少し楽になる

・確認画面で$bodyの改行がなくなる気がするのでnl2br()する

・最後の?>はいらない

この意見に回答する

ツリーへ TOPへ

A02-1
replyersryou1985 [11月7日 14:46]

まさか、こんなド素人にたくさんのアドバイスをしてくれまして、ほんとうにありがとうございます。
これを機に、よりいっそう精進してまいります。

この意見に回答する

ツリーへ TOPへ

A03 満足
answereriroha_code [10月31日 21:41] (最終編集:10月31日 22:28)

[function.php]
54,95 header();の後にexit;
exit;で止めないと、header()の後が実行される)

26 mb_strlenに文字コード指定(mb_**()には必須)
80 value値に[歳]を含めるとチェックしづらい
80 </option>が続けて2つある
80 nenreiのチェックがない
(このフォームから送信されるとは限らない)
88 COUNT(`name`)とカラムを限定する方が速い

[check.php]
37-43 セッションが存在する時、二重にcheck()してる

[form.php check.php thanks.php]
文字化け防止にDOCTYPEの上へ
header('Content-type: text/html; charset=UTF-8');
Firefoxのselectedキャシュ防止に
header('Cache-Control: no-store');

check.phpとthanks.phpは検索エンジンにアーカイブされてはいけない。
metaやrobots.txtで設定する。(sitemap.xmlにプライオリティを)

[database]
掲示板ID、日付カラムが欲しい。
(ソートの為や、古い投稿に返信したりしないように)

この意見に回答する

ツリーへ TOPへ

A03-1
replyersryou1985 [11月7日 14:47]

まさか、こんなド素人にたくさんのアドバイスをいただけるとは、ほんとうにありがとうございます。
これを機に、よりいっそう精進してまいります。

この意見に回答する

ツリーへ TOPへ

<<質問一覧へ



Pick Up Q&A

Q
正規表現について教えてください。
 このエントリーをはてなブックマークに追加 
A
>このようになります。htmlspecialcharsはない方が良いのでしょうか? ブラウザに表示すればたしかにそうなるでしょうけど、ブラウザ側で「ソース表示」で確認してみましたか? htmlspecialcharsはブラウザ...

>>続きを読む

外部から取得してきた値を解析などしたいときには、取得してきた値をそのまま利用するのがポイントですね。値をvar_dumpしてみるのも、解決につながるかもしれません。

▲解説者:岡本(アシアル株式会社 教育コーディネーター兼 システムエンジニア)