質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.12%

PHP データベースエラーが出る! ( mysql_result() )

受付中

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,875
退会済みユーザー

退会済みユーザー

/* (^_^)  ERRORS  (>_<) */
Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead in bbs.php on line 7
Warning: mysql_result() expects parameter 1 to be resource, boolean given in bbs.php on line 36 // これ
Warning: Cannot modify header information - headers already sent by (output started at bbs.php:7) in bbs.php on line 48
Warning: Cannot modify header information - headers already sent by (output started at bbs.php:7) in bbs.php on line 49
Warning: Cannot modify header information - headers already sent by (output started at bbs.php:7) in bbs.php on line 52
<?php
/* version 5.6.10*/
    // MySQL接続部分
    $conn = mysql_connect('localhost:8888', 'example', 'example');
    mysql_select_db('example', $conn);
    mysql_query('SET NAMES ujis', $conn);

    // 投稿処理
    if ( !empty($_POST["dopost"]) && !empty($_POST["name"]) ) {
        // クエリがエラーになったら、テーブルが存在しないと見て新規作成
        if ( !mysql_query( "SELECT cout(*) FROM bbs ", $conn) ) {
            mysql_query( "CREATE TABLE bbs 
                          (
                              id INT UNSIGNED NOT NULL AUTO_INCREMENT,
                              name VARCHAR(255) NOT NULL default '',
                              title VARCHAR(255) NOT NULL default '',
                              body TEXT,
                              pass VARCHAR(255) NOT NULL default '',
                              postdate DATETIME NOT NULL,
                              PRIMARY KEY (id) 
                          ) TYPE=MyISAM" , $conn);
        }

    // パスワードが指定されていなければ、クッキーのパスワードで上書きする
    if ( empty($_POST["pass"]) && !empty($_COOKIE["pass"]) ) {
        $_POST["pass"] = $_COOKIE["pass"];
    }

    // 名前とパスワードの一致を確認
    $sql = "SELECT COUNT(*) FROM bbs WHERE name = '" . $_POST["name"] . "' AND pass<>'" . $_POST["pass"] . "'";
    $rs = mysql_query($sql, $conn);

    if ( mysql_result($rs, 0, 0) ) {
        // 同じ名前で、パスワードの異なるレコードがあれば受付拒否
        header( "Location: http://" . $_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'] . '?message=' . urlencode('その名前は既に使われています') );
        exit;
    }

    // 投稿内容をデータベースへ書き込む
    $sql = "INSERT INTO bbs SET name='" . $_POST["name"] . "', title='" . $_POST["title"] . "', body='" . $_POST["body"] .
           "', pass='" . $_POST["pass"] . "', postdate=NOW()";
    mysql_query($sql, $conn);

    // 次回の投稿・管理用に、クッキーに名前とパスワードを保存する
    setcookie( 'name', $_POST["name"], time()+60*60*24*30 );
    setcookie( 'pass', $_POST["pass"], time()+60*60*24+30 );

    // 投稿したらリダイレクト
    header( "Location: http//" . $_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'] . '?message=' . urlencode('登録しました') );
    exit;
}

// メッセージ削除処理
if ( !empty($_POST['delete']) ) {
    // パスワードが指定されていなければ、クッキーのパスワードで上書きする
    if ( empty($_POST["pass"]) && !empty($_COOKIE["pass"]) ) {
        $_POST["pass"] = $_COOKIE["pass"];
    }

    // idとパスワードが一致したら、削除
    $sql = "DELETENFROM bbs WHERE id=" . $_POST["id"] . "AND pass='" . $_POST["pass"] . "'LIMIT 1";
    mysql_query($sql, $conn);
    $message = mysql_affected_rows ? "削除しました" : "パスワードが違います";

    // 削除したらリダイレクト
    header( "Location: http://" . $_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'] . "?message=" . urlencode($message) );
    exit;
}

// キャラクーセットの指定
header( "Content-Type: text/html; charset=EUC-JP" );

// HTML開始部
echo '<!DOCTYPE html><html lang="ja"><head><meta http-equiv="Content-Type: text/html; charset=EUC-JP" /><title>脆弱性だらけの掲示板</title></head><body>';

// メッセージがあれば表示
if ( !empty($_GET['message']) ) {
    echo '<p style="color:red;">' . $_GET['message'] . '</p>';
}

// フォーム描画処理
echo '<form action="' . $_SERVER['PHP_SELF'] . '" method="post">';

echo '名前 : <input type="text" name="name" value="' . @$_COOKIE['name'] . '" /><br />';
echo '題名 : <input type="text" name="title" /><br />';
echo '内容 : <br /> <textarea name="body" rows="4" cols="40"></textarea><br />';
echo 'パスワード : <input type="password" name="pass" size="8" value="" /><br /><br />';
echo '<input type="submit" name="dopost" value="投稿" />';
echo '<input type="reset" value="リセット" />';
echo '</form>';
echo '<hr />';

// 過去の投稿表示部分 (最新順に10件のみ表示)
$sql = "SELECT * FROM bbs ORDER BY postdate DESC LIMIT 10";
$result = mysql_query($sql, $conn);
if ( $result ) {
    while ( $row = mysql_fetch_array($result, MYSQL_ASSOC) ) {
        echo '<p>';
        echo 'No.' . $row['id'] . '<br />';
        echo '題名 : ' . $row['title'] . '<br />';
        echo '名前 : ' . $row['name'] . '<br />';
        echo '日時 : ' . $row['postdate'] . '<br />';
        echo '<blockquote>' . n12br($row['body']) . '</blockquote>';
        echo 'パスワード : ' . $row['pass'] . '<br />';
        echo '</p><hr />';
    }
}

// 削除よう
echo '<form action"' . $_SERVER['PHP_SELF'] . '" method="post">';
echo '記事No.<input type="text" name="id" size="4" />';
echo 'パスワード<input type="password name="pass" size="8" value="" />';
echo '<input type="submit" name="delete" value="記事削除" />';
echo '</form>';

// HTML終了部
echo '</body></html>';


PHPサイバーテロの技法という本でwebアプリのセキュリティ対策について学んでいるのですが、その本のPHPはバージョンが古く、データベースへの接続はmysql_connectを使用しています。
私には現代風のPDOに書き換えることができないのでMAMPでPHPのバージョン設定を5.6.10にし、PHPMyAdminを用いてユーザーを作成し、プログラムを実行し、投稿ボタンより投稿したのですが、エラーとなります。

いろいろ調べてみると、真偽値がどうこうとのことですが、全くわかりません。
また、サンプルコードでも同じエラーが出ます。

どうしたら、上記のプログラムを実行できますか?

Warning: mysql_result() expects parameter 1 to be resource, boolean given in bbs.php on line 36


このエラー(↑)はどう対応したらいいのですか?

ちなみに本書での実行環境であるXAMPPで実行したら、サンプルコードでは登録しましたの文字のみが表示されました。
私のプログラムは相変わらずエラーです。

※ 先述した通り、私にはmysql_connectをPDOのプログラムに書き換える能力がないのでPDOを使いなさいとの回答はお控えください...
書き換えたコードをくれるのであれば別ですが...!

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+2

mysql_result() <http://php.net/manual/ja/function.mysql-result.php> の引数として与えているものが想定するresource型じゃない→FALSEでも入っているんでしょう。

// 名前とパスワードの一致を確認
    $sql = "SELECT COUNT(*) FROM bbs WHERE name = '" . $_POST["name"] . "' AND pass<>'" . $_POST["pass"] . "'";
    $rs = mysql_query($sql, $conn);


ここ、失敗しているんでしょうね。

遡ると、allowsさんの指摘どおり

mysql_query( "CREATE TABLE bbs 
                          (
                              id INT UNSIGNED NOT NULL AUTO_INCREMENT,
                              name VARCHAR(255) NOT NULL default '',
                              title VARCHAR(255) NOT NULL default '',
                              body TEXT,
                              pass VARCHAR(255) NOT NULL deafult '',
                              postdate DATETIME NOT NULL,
                              PRIMARY KEY (id) 
                          ) TYPE=MyISAM" , $conn);


なのですが、
そもそもmysql_query()の返り値を一切点検せず次々と処理を進めていくやり方が危険極まりないです。
せめて結果を変数に受け取ってFALSEを返していないかチェックしましょうよ。
サンプルコードがそう書いてあっても、エラーチェックを適宜加えていくのもセンスです。
SQL(やMySQL)への理解が乏しければ、
転記ミスを発見するためにもmysql_query()がFALSEを返していないかだけでもチェックしてください。

でも、もっと言いたいことがあるんだ、
動作に必要なテーブルが存在しないからといって即席でテーブルを作っちゃうのって、実務でやる?
データベース接続先が間違っていて、想定外のところにテーブルを作っちゃう可能性とか、
そもそもphp側からテーブル作成できちゃう実行権限をもたせるのって別の危険性を孕むよね。
php側からアクセスする際のユーザーはSELECT, INSERT, UPDATE, DELETEくらいしかさせない権限に絞るとか余計な情報にアクセスさせないとかいうのもセキュリティ対策です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/09/07 14:55

    ありがとうございます!
    参考になりました!

    キャンセル

+1

PHPサイバーテロの技法 正誤表

何ページのものなのかとか私は知らないので、こちらに該当の箇所があるのかどうかも知りませんが…

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/09/07 14:48

    ありがとうございます。
    私の本ではその誤植等は修正されています。

    キャンセル

+1

とりあえず PRIMARY LEY (id) →  PRIMARY KEY (id) かな

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/09/07 14:52

    ありがとうございます!
    気づきませんでした!

    直しましたが同じエラーが出ます...><

    キャンセル

+1

たとえば

$_PSOT["pass"] = $_COOKIE["pass"];

のtypoとかいろいろ怪しいところはあります。
それとmysql_関数を使い続けるのであれば必ず外から来たデータには
mysql_escape_stringをかましてください

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/09/07 10:49

    文字セットを考慮する mysql_real_escape_string のほうが使用が推奨されます.(とはいえども,mysql関数自体を早急に書き換えるべきに1票,ですが…)

    キャンセル

  • 2016/09/07 10:52

    (↑これは脆弱性を学ぶ本のようなので,そういう回答も相応しくない気がしてきました.しかし実用的なアプリケーションを作る場合には絶対に避けたいところですね.)

    キャンセル

  • 2016/09/07 10:55

    ありがとうござます
    mysql_real_escape_string・・・ああそういえばそんな関数もありましたね
    そもそも最近ではmysql_関数が使える環境を作ること自体が難しいですから
    せめてmysqli_関数の手続き型にすれば似たような処理でできるので
    こだわりがある方にはそちらを選択してもらうくらいでしょうか

    キャンセル

  • 2016/09/07 14:53

    お恥ずかしい!!
    気づきませんでした!
    ありがとうございます!!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.12%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る