プロが教える店舗&オフィスのセキュリティ対策術

一行掲示板に投稿者のみが行える投稿削除機能(パスワード付き)を出力させたいのですが、プログラミング初心者なので、下記のテキストに何を入力すればいいのかわからないので教えてください。
お願いします。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>一行掲示板</title>
</head>
<body>
<form id="x1" name="x1" method="post" action="">
<input type="text" id="naiyou" name="naiyou" size="20">
<input type="submit" value="書き込む">
</form>
<hr>
<?php
//データファイルのファイル名
$filename='data.txt';

if(!empty($_POST['naiyou'])){
$data=file_get_contents($filename);
$body=$_POST['naiyou'];
$date=date('Y/m/d H:i:s');

$body="$body ($date)\n".$data;

$fp=@fopen($filename,'w');
flock($fp,LOCK_EX);
fputs($fp,$body);
fclose($fp);
}

$data=file($filename);
$line=count($data);
for($i=0; $i<$line; $i++){
$no=$line-$i-1;
echo "$no. $data[$i]<hr>\n";
}
?>
</body>
</html>

A 回答 (9件)

>data.txtのファイルの中身を確認しましたが、何も記述されておりませんでした。



そうなると、こちらで確認したものと全然違う動作ですね(こちらでは確実に追加されていきましたので)。

というか「何も記述されていない」のに「1行だけ表示される」という時点で滅茶苦茶です。スクリプト内のファイル名とチェックしているファイル名が違っているとしか思えません。




>尚、data.txtは.txtの拡張子で保存しています。

その表現だと、data.txt.txt みたいに思えます。ファイル名「data.txt」だけでいいです。WinPCで「登録されている拡張子を非表示」の環境なら、「data」としか表示されていないかもしれませんが・・・

#プログラミングするなら「拡張子非表示」はやめるべき。間違いの元です。

この回答への補足

無事出力することができました。
ただ、内容のの部分を新しく入力すると過去の掲示板から内容だけ削除されます。

01:テスト(2014/08/04 15:28:26)
02:(2014/08/04 15:26:32)

このような場合はどうしたらよいでしょうか?

補足日時:2014/08/04 15:32
    • good
    • 0
この回答へのお礼

ご返答ありがとうございます。

新しくdata.txtファイルを作成し、行ってみたのですが
01:こんばんは(2014/08/04 13:15:51)
新しく書き込んでも02、03とはいかずに01だけが上書きされる形になります。
data.txtファイルを開いて確認しても書き込んだ内容が記述されていませんでした。
何か仕様が違うという事なのでしょうか?

お礼日時:2014/08/04 13:25

>一行だけしか表示されないのですが、何行も続けて表示させるにはどうしたらいいでしょうか?



fgetcsvでファイルを最後まで読み込んでforeachで全行処理するように書いています。少なくともこちらの環境ではそういう動作をします。

何行も書き込んでみて

・データファイルに追加されていない
・データファイルには追加されているが表示されない

のどちらになっているかを確認してください(こちらでは再現できないので調べられない)。

なお、data.txtはテキストモードで落としてから確認してください。LF改行なので「そのまま」をメモ帳で開いて改行されていないなどと勘違いされても困りますので(普通は大丈夫だろうと思うのですが、今までのやりとりからデバッグのための基本的なスキルが期待できそうにないので)。
    • good
    • 0
この回答へのお礼

ご返答ありがとうございます。

data.txtのファイルの中身を確認しましたが、何も記述されておりませんでした。
尚、data.txtは.txtの拡張子で保存しています。

お礼日時:2014/08/04 11:37

>PHPのバージョンはPHP 5.1.6になっていました。



ずいぶん古いバージョンぽいですね
さすがに使えない機能が増えてきているので
どこかでアップグレードを検討した方がいいかもしれません

とりあえずforeach構文のところは一度変数に受ければいけるはず

#3さんのコードでいう

>foreach ($arr as list($naiyou, $time, $pass)) { printf('%02d:%s(%s)<br>', $no++, htmlspecialchars($naiyou, ENT_QUOTES), date('Y/m/d H:i:s', $time)); }

のところを

foreach ($arr as $arr2) {
list($naiyou, $time, $pass)=$arr2;
printf('%02d:%s(%s)<br>', $no++, htmlspecialchars($naiyou, ENT_QUOTES), date('Y/m/d H:i:s', $time));
}

的な対処でどうでしょう?
    • good
    • 0
この回答へのお礼

ご返答ありがとうございます。

出力することができました。
ありがとうございます。
ただ、一行だけしか表示されないのですが、何行も続けて表示させるにはどうしたらいいでしょうか?
ご教授頂ければ幸いです。

お礼日時:2014/08/01 23:49

横やりで申し訳ない



foreachでas listを指定できるのはPHP5.5以降だったはずなので
バージョンに依存しているのでは?
    • good
    • 0
この回答へのお礼

ご返答ありがとうございます。

PHPのバージョンはPHP 5.1.6になっていました。

お礼日時:2014/08/01 22:34

>コピーではなく新しく書き直したほうがいいという事でしょうか?



私の環境ではコピペしたものが問題なく動きます。コピペするときに何か間違っていませんかね・・・

#なので「どういうエラーになっているか」が大事なんですが(汗

phpのバージョンがわかりませんがバージョンに依存する関数は使っていません(fputcsvも5.1.0以降なら使える)し、データファイルを自動生成するように書き替えたソースならデータファイルの状態にも左右されません(前のデータが残っているなんて馬鹿げたミスはないですよね)。
    • good
    • 0
この回答へのお礼

ご返答ありがとうございます。

夜分遅くにすみません。
php.iniを編集してdisplay_errors = Onにした後、アパッチの再起動をしたのですが、真っ白のままです。
どうしたらいいでしょうか?

お礼日時:2014/08/01 22:28

>真っ白で何も映りませんでした。



単純なtypoの可能性もありますが、「エラーメッセージを表示する」設定になっていますか(error_reportingとかdisplay_errorsとか)。デバッグ時には必ずエラーを表示するようにしてください。
    • good
    • 0
この回答へのお礼

ご返答ありがとうございます。

設定はした覚えがないので、設定してみます。
コピーではなく新しく書き直したほうがいいという事でしょうか?

お礼日時:2014/08/01 19:05

>何度も質問して申し訳ないのですが、r+の拡張子は何にすればよろしいでしょか?



r+ はfopenの第二引数です。拡張子なんかありません。

http://www.php.net/manual/ja/function.fopen.php

質問者さんのソースでも、$fp=@fopen($filename,'w'); となっていますよね。





以下は蛇足ですが、

・最初にデータファイルを(存在しなかったら)作成する
・追加データを先頭に挿入
・内容/日時/パスワードのmd5値のフォーマットで保存

にしたものです。


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>一行掲示板</title>
</head>
<body>
<?php
//データファイルのファイル名
$filename='data.txt';
// なかったら作成
if (!is_file($filename)) { touch($filename); }
// データ読込み
$fp = fopen($filename, 'r+');
flock($fp, LOCK_EX);
$arr = array();
while ($buf = fgetcsv($fp)) { $arr[] = $buf; }

$upd = false;
// 削除
if (isset($_POST['no'])) {
$no = intval($_POST['no']) - 1;
list($naiyou, $time, $pass) = $arr[$no];
if ($pass === md5($_POST['pass'])) {
unset($arr[$no]);
$upd = true;
} else {
print '<div style="color:red">password error</div>';
}
}
// 追記
if(isset($_POST['naiyou'])) {
array_unshift($arr, array($_POST['naiyou'], time(), md5($_POST['pass'])));
$upd = true;
}
// 削除or追記があったらファイルを更新
if ($upd) {
ftruncate($fp, 0);
rewind($fp);
foreach ($arr as $dat) { fputcsv($fp, $dat); }
}
fclose($fp);
?>
<form method="post" action="">
内容:<input type="text" name="naiyou" size="20"> pass:<input type="password" name="pass">
<input type="submit" value="書き込む">
</form>
<hr>
<?php
// データを表示
$no = 1;
foreach ($arr as list($naiyou, $time, $pass)) { printf('%02d:%s(%s)<br>', $no++, htmlspecialchars($naiyou, ENT_QUOTES), date('Y/m/d H:i:s', $time)); }
?>
<hr>
削除用
<form method="post" action="">
No<input type="text" name="no"> pass:<input type="password" name="pass">
<input type="submit" value="削除">
</form>
</body>
</html>
    • good
    • 0
この回答へのお礼

ご返答ありがとうございます。

詳しく書いて頂きありがとうございます。
先程、data.txtを別で作成し、agunuzさんが作成して頂いたテキストをphpの拡張子に保存し、アップしてみたのですが真っ白で何も映りませんでした。
何か原因があれば、ご教授お願いします。

お礼日時:2014/08/01 13:39

> このサンプルをそのままエディタで写せば出力されるのでしょうか?



動作確認済みです。データファイルは(r+ で開いているので)サイズ 0 でもいいので存在する必要がありますがそれ以外は動かしてみればわかると思いますが・・・

新しい書き込みを最後に追加するようにしていますが、先頭に入れたければarray_unshiftで先頭に挿入してから書き込めばいいです。また日時の記録も端折っています。



なお、問題は動く・動かないではなく、質問者さんの最初のソースと「どう違うのか」を追ってください。最初のソースではロックが不適切なため破綻する怖れがあります。書き込む直前にロックしたって、その前に読込んでいた内容を書き込むんだからその間に他から書き込まれていても「なかったこと」になってしまいます。

また「内容+パスワード」を保存するのでfputcsvで書き込んでいます。当然削除のときはパスワードの一致チェックがあります。

この回答への補足

ご返答りがとうございます。

何度も質問して申し訳ないのですが、r+の拡張子は何にすればよろしいでしょか?

補足日時:2014/08/01 12:55
    • good
    • 0

いろいろ問題も多いのですが、全部指摘して説明する余裕がないのでサンプルだけ書いておきます。



(例)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>一行掲示板</title>
</head>
<body>
<?php
//データファイルのファイル名
$filename='data.txt';

$fp = fopen($filename, 'r+');
flock($fp, LOCK_EX);
$arr = array();
while ($buf = fgetcsv($fp)) { $arr[] = $buf; }
// 削除
if (isset($_POST['no'])) {
$no = intval($_POST['no']) - 1;
list($naiyou, $pass) = $arr[$no];
if ($pass === $_POST['pass']) {
unset($arr[$no]);
ftruncate($fp, 0);
rewind($fp);
foreach ($arr as $dat) { fputcsv($fp, $dat); }
fclose($fp);
} else {
print '<div style="color:red">password error</div>';
}
}
// 追記
if(isset($_POST['naiyou'])) {
ftruncate($fp, 0);
rewind($fp);
$arr[] = array($_POST['naiyou'], $_POST['pass']);
foreach ($arr as $dat) { fputcsv($fp, $dat); }
fclose($fp);
}
?>
<form method="post" action="">
内容:<input type="text" name="naiyou" size="20"> pass:<input type="password" name="pass">
<input type="submit" value="書き込む">
</form>
<hr>
<?php
$no = 1;
foreach ($arr as list($naiyou, $pass)) { printf('%02d:%s<br>', $no++, htmlspecialchars($naiyou, ENT_QUOTES)); }
?>
<hr>
削除用
<form method="post" action="">
No<input type="text" name="no"> pass:<input type="password" name="pass">
<input type="submit" value="削除">
</form>
</body>
</html>
    • good
    • 0
この回答へのお礼

ご返答ありがとうございます。

このサンプルをそのままエディタで写せば出力されるのでしょうか?

お礼日時:2014/08/01 11:23

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!