Wonderful! WordPress

続、コメントの編集機能session版

この記事は公開または最後に更新されてから3224日が経過しています。情報が古くなっている可能性があるのでご注意下さい。

コメントの編集機能の続編です。
wordpressのコメントに関する関数、編集の wp_update_comment()、削除の wp_delete_comment() についてはコメントの編集機能に記載してあります。

上記ページで作ったコメント編集、削除機能は、良く知っている方だけが見る、非公開サイト用なのでほとんどセキュリティの事など考えもしないで作ったもの。
金銭のやりとりのある商品販売のためのフォームでもないから、ユーザーに迷惑がかかることもないだろうし、何かおこるとすればメールアドレスを盗み見られるぐらいでしょうか。

少し関心があって不正アクセス対策等のセキュリティに関する本を何冊か読んでみましたが、一般に公開しているサイトにおいては何がおこるかわからないということもあります。
それにここのところ外国からの(特に中国だと思えます)スパムコメントがやたらと多くなって、ログを見ていると何やら気味の悪い事をしていそうなのです。
と、いうことで備えあれば憂いなしですし、少しでも手を打っておこうとsession機能を使って造り直してみました。
ただ、session機能はcookieを受け入れるようにしていないと使えないことになるのでその辺は不便になりますが。
urlでsessionIDをやり取りできるようにすればcookieは必要ありませんが、それだとsessionを使うメリットも無くなってしまうように思います。

2015年12月17日追記:nonce で新しく作り直しています。【コメントの編集機能、nonceで作り直してプラグイン】

前回作ったものは、ユーザーから入力された検証用のメールアドレスとコメントIDはフォームhiddenに入れてページのリロード時にPOSTで送信してデータを持ち回りさせていました。
その辺を改良して、それらのデータをsessionで扱って、どうせsessionを使用するならフォームの偽造を防ぐワンタイムチケットの機能も付けようという目論見です。

<?php
/*
Template Name: books
 */
				//各変数の初期化
	$myticket = '';//ワンタイムチケット
	$idcom = 0;//コメントIDを入れる変数
	$strmail = '';//メアドを入れる変数
	$opeflg = '';//処理を続けるか否かのフラグ
	$opestr = '';//何の処理を行うかのフラグ
	$upansstr = '';//処理が成功したか否かの文字列

	session_start();

	//フォームのキャンセルボタンを押された時にセッションデータを破棄する処理
	if ( isset( $_POST['cancel'] ) ) {
		$_SESSION = array();
		if ( isset( $_COOKIE[ session_name() ] ) ) {
			setcookie( session_name(), '', time() - 42000, '/' );
		}
		$sesdest = session_destroy();
	}

	/*セッションデータのワンタイムチケットが既にセットされている時はデータを編集、削除する最終段階の検証を行う時で、 メアドもコメントIDもセッション変数にセットされているはず。*/
	if ( isset( $_SESSION['myticket'] ) ) {
		$myticket = $_SESSION['myticket'];
		$idcom = $_SESSION['comid'];
		$strmail = $_SESSION['mailstr'];
		
		//セッションとPOSTで送信されるチケットの照合
		if ( $_POST['ticket'] === $myticket ) {
			$opeflg = 'a';// 正しい時
		} else {
			$opeflg = 't';// 不正な時
		}
	}

	/*初めて編集、削除用のフォームが呼び出されるときはコメントIDと照合用のメアドはPOSTで送信されてくる。この時に各セッション変数を代入*/
	if ( isset( $_POST['comid'] ) and isset( $_POST['mailstr'] ) ) {
		$myticket = md5( uniqid( mt_rand(), TRUE ) );
		$_SESSION['myticket'] = $myticket;// ワンタイムチケット
		$_SESSION['comid'] = $_POST['comid'];// コメントID
		$_SESSION['mailstr'] = $_POST['mailstr'];// メールアドレス
		$idcom = $_POST['comid'];
		$strmail = $_POST['mailstr'];
		if ( isset( $_POST['delcom'] ) ) {
			$opeflg = 'a';
			$opestr = 'd';
		} elseif ( isset( $_POST['editcom'] ) ) {
			$opeflg = 'a';
			$opestr = 'e';
		}

	}
	
	if ( $idcom !== 0 and $strmail !== '' ) {
		// コメントIDのチェック
		if ( ! ctype_digit( $idcom ) or $idcom <= 0 ) {
			$opeflg = 'i';
		}
		
		// メールアドレスのチェック
		$pattern = '/^([a-z0-9\+_\-\.]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/iD';
		if ( ! preg_match( $pattern, $strmail ) ) {
			$opeflg = 'm';
		}
	}
	
	if ( $opeflg === 'a' ) {// $opeflgが'a'の時だけ処理を進める
		// フォームのボタンが何を押されたかを得る
		if ( $opestr !== 'd' and $opestr !== 'e' ) {
			if ( isset( $_POST['editlast'] ) ) {
				$opestr = 'l';
			} elseif ( isset( $_POST['dellast'] ) ) {
				$opestr = 'k';
			}
		}

		// コメントIDからコメントの情報を取得
		$comrow = get_comment( $idcom );
		
		// 該当するコメントがなければ'null'が返ってくる
		if ( ! is_null( $comrow ) ) {
			$comemail = $comrow->comment_author_email;
			if ( $comemail === $strmail ) {// メールアドレスが同じか検証
				$comauth = $comrow->comment_author;
				$oribun = $comrow->comment_content;
				// ブラウザ出力用にエスケイプ
				$comauth = htmlspecialchars( $comauth, ENT_QUOTES );
				$oribun = htmlspecialchars( $oribun, ENT_QUOTES );
			} else {
				// 検証が不正な時は処理が進まないように各フラグを変更
				$opeflg = 'm';
				$opestr = 'n';
			}
		} else {
			$opeflg = 'c';
			$opestr = 'n';
		}

		$today = date( 'Y/m/d H:i:s' );
		if ( $opestr === 'l' ) {// 編集するときのデータのデータベースへのアップデート処理
			if ( $_POST['lasthon'] != '' ) {
			
				$combun = '';
				$combun = $wpdb->escape( $_POST['lasthon'] );
				$idcom = $wpdb->escape( $idcom );
					
				$comarr = array(
				    'comment_ID' => $idcom,
				    'comment_content' => $combun,
                );

				$comans = wp_update_comment( $comarr );
			
				if ( $comans === 1 ) {
					$upansstr = ':success';
				} elseif ( $comans === 0 ) {
					$upansstr = ':lost';
				}
			
				$mailstr = '日付:' . $today . 'に' . $comauth . 'さんがコメントID:' . $idcom . 'のコメントを編集し' . $upansstr . ':しました。\n\n元:\n' . $oribun . '\n\n後:\n' . $combun;
				wp_mail( '通知したいメールアドレス', 'コメントが編集されました', $mailstr );
				
				// 処理が終了したらセッションデータの破棄
				$_SESSION = array();
				if ( isset( $_COOKIE[ session_name() ] ) ) {
					setcookie( session_name(), '', time() - 42000, '/' );
				}
				session_destroy();
			
			} else {
				$opeflg = 'h';
				$opestr = 'n';
			}
		} elseif ( $opestr === 'k' ) {// 削除するときのデータベースへのアップデート処理
			$idcom = $wpdb->escape( $idcom );
		
			$comans = wp_delete_comment( $idcom );
		
			if ( $comans === true ) {
				$upansstr = ':success';
			} elseif ( $comans === false ) {
				$upansstr = ':lost';
			}
		
			$mailstr = '日付:' . $today . 'に' . $comauth . 'さんがコメントID:' . $idcom . 'のコメントを削除し' . $upansstr . ':しました。\n\n内容:\n' . $oribun;
			wp_mail( '通知したいメールアドレス', 'コメントが削除されました', $mailstr );
			
			$_SESSION = array();
			if ( isset( $_COOKIE[ session_name() ] ) ) {
				setcookie( session_name(), '', time() - 42000, '/' );
			}
			session_destroy();
		}
	}
	
?>
// 通常のヘッダーの記載部分
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>
<html xmlns='https://www.w3.org/1999/xhtml'>

<head>
<?php
	//検証でエラーがあって途中で強制終了した時に別ファイルへリダイレクトしてセッションデータを破棄する時の処理
	if ( $opeflg !== 'n' and $opeflg !== 'a' ) {
		$_SESSION['errcord'] = $opeflg;
		$_SESSION['myurl'] = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
		echo '<meta HTTP-EQUIV=\'REFRESH\' CONTENT=\'0;URL= https://strix.main.jp/?page_id=*****\' />';
	}
?>
<meta http-equiv='Content-Type' content='<?php bloginfo( 'html_type' ); ?>;charset=<?php bloginfo( 'charset' ); ?>' />
<title>My favorite books|Photographs of Japanese Birds</title>
			・
			・
			・
<?php wp_head(); ?>

</head>

<body>	
	<div id='header'>
		
		<h1><a href='<?php echo home_url(); ?>'>気に入っている鳥の本。</a></h1>
	</div>	
<div id='mainframe'>
	
<div id='container'>

	<div id='content'>

		<?php
			//編集、削除のボタンを押されて初めて呼ばれた時はそれ用のフォームを表示する
			if ( $opestr === 'e' or $opestr === 'd' ) {
		?>
				<div class='post' name='comments'>
					<form name='dircomfrm' action='' method='POST'>
						<div class='lascomfrm'>
						<p id='lastcomfrmp'>コメントID : <?php echo $idcom; ?><br />
							送信者 : <?php echo $comauth; ?></p>
						<input type='hidden' name='ticket' value='<?php echo $myticket; ?>' /><br />
						<textarea name='lasthon' rows='20' cols='80'><?php echo $oribun; ?></textarea><br />
						<?php if($opestr==='e'): ?>
							<p>編集ボタンで編集した結果を保存します。</p>
							<input type='submit' name='editlast' value='編集' />
						<?php elseif($opestr==='d'): ?>
							<p>このコメントを削除します。戻すことは出来ませんのでご注意ください。</p>
							<input type='submit' name='dellast' value='削除' />
						<?php endif; ?>
						<input type='submit' name='cancel' value='キャンセル' />
						</div>
					</form>
				</div>
		<?php
			} else {
		?>

		// 編集、削除を指示されていない時の通常の投稿の表示
		<?php if ( have_posts()):while( have_posts() ):the_post(); ?>

		<div class='post'>

			<?php the_content(); ?>

		</div>

		<?php endwhile;endif; ?>

		<?php
			comments_template();//通常のコメント入力フォームの表示
		
			}
		?>
		
	</div>
	
<!-- サイドバー -->
	<div id='sidebar'>
		//通常のサイドバー表示部分
	</div>
	
<?php

/*検証でエラーがあって途中で強制終了した場合のメッセージを表示させ
 セッションデータを破棄する処理。
 セッションデータ破棄用のファイルへリダイレクトする場合は
  そちらで処理させるので両方とも必要なし*/
if ( $opeflg !== 'n' and $opeflg !== 'a' ) {
	echo '<script type=\'text/javascript\'>';
	echo 'alert(\'コメント処理に失敗しました。\');';
	echo '</script>';
}

// Firefox Safariは正常に動作しなくなるので除く
global $is_gecko, $is_safari;
if ( ! $is_gecko and ! $is_safari ) {
	if ( $opeflg !== 'n' and $opeflg !== 'a' ) {
		$_SESSION = array();
		if ( isset( $_COOKIE[ session_name() ] ) ) {
			setcookie( session_name(), '', time() - 42000, '/' );
		}
		$sesdest = session_destroy();
	}
}
?>

		<div id='footer'>
			//通常のフッターの表示部分
			<?php //wp_footer(); ?>
		</div>
	</div>
</div>
	<script type='text/javascript' src='<?php bloginfo( 'template_url' ); ?>/bookstmp.js'></script>
</body>
</html>
PHP
CopyExpand

186~210行目は編集、削除のボタンを押されてリロードされた時に表示する編集用のフォーム部分。

ヘッダー部分の158~165行目部分と末尾の236~259行目部分に関して。
検証で何らかのエラーがあって途中で処理が終了してしまった場合に236~259行目部分で失敗したことの表示とセッションデータの破棄を行っています。
セッションデータの破棄を処理しているのは249~259行目ですが、実はこれがあるとFirefoxSafariにおいて正常に動作しなくなります。

Firefoxでいろいろ様子を見たところ、コメントを見るときに直接このページのコメント表示部分に対してのリンク(たとえば https://strix.main.jp/?page_id=26870#comments というような)で開いた時に正常に動かなくなります。
コメントを表示する<div id="comments">に対してのジャンパーというのかなんというのかurl#commentsがついている時におかしくなります。

セッションデータやPOSTで送信されるデータを見ているとどうもPOSTのデータが無くなったりしているようなのでセッション変数にカウンターを設けてみるとやはりurl#commentsがある時は2度リロードし異常で、ない時は1度のみで正常に作動します。
2度再読み込みするためにPOSTで送信されるデータが無くなってしまい、検証が不正になり、セッションデータも破棄されてしまうようです。
それにしても不思議ですねぇ、面白いです。これにたどり着くのに随分時間と手間を要しました。
データの処理の仕方に問題があるのか、フォームの表示の仕方に問題があるのかよくわからないところです。
Safariに関しては、詳しく検証しませんでしたが、ジャンパーの有無にかかわらずこのセッションデータ破棄の処理があると正常に動作しませんでした。
ちなみにFirefoxSafariとも、2012年11月6日現在においての最新バージョンです。

まぁこの249~259行目部分は検証でエラーがあった場合のセッションデータを破棄する処理なので、そんなに頻繁に発生することもないだろうし、特にFirefoxSafariにおいてだけの問題のようなので、それ以外の時にだけ処理させればいいかという気もします。そんなにセッションデータのゴミもたまらないだろうしガベッジコレクタにお任せしてもいいのではと。
で、この2つのブラウザにこの処理を無視させれば期待した通りの動作をしてくれます。

とは言うもののなんだかすっきりしませんね。
特にFirefoxはメインに使用しているブラウザなのでなんとかしたくなります。
いろいろ考えあぐねたすえに、エラーがあった場合の処理を別ファイルを呼び出して処理させることにしました。
それが158~165行目部分です。

検証で得たエラーフラグと自らのurlをセッション変数に作って、目的のファイルへリダイレクトさせています。
リダイレクトされるファイルはセッションデータからどのファイルから呼び出されたかを検証し、セッションデータの破棄を行い、再び元のページへリダイレクトするだけのページです。一応、固定ページにて作成しました。
当然のことですが、このリダイレクトさせる処理をするのであれば、236~259行目は不必要です。
ここまでやる必要もなさそうですけどね。

尚、コメントの編集機能の最後にも掲載してあるcomments.phpのフォーム部分の追加はこちらでも必要です。

Talking

  • ドラえもん より:

    本当に勉強になります。

    応援しています!!

    • admin より:

      ドラえもんさん。
      コメントありがとうございます。
      いやぁ、ほんとにうれしいなぁ!
      とても励みになります。

Leave a Reply!

JavaScript is necessary to send a comment.
You can edit and delete your comment if you input a edit key.
Edit key is necessary for attesting you when you edit and delete it.
The tag of HTML cannot be used in comment.
When you comment for the first time, it is displayed after the approval of the administrator.
Because I cannot speak English so much, it takes time to answer.
Required fields are marked *.

※Please enter more than 5 characters only alphabets.
※Edit or delete are possible for 2000 days after approval.

*

♠Simplistic Comment User Editable v4.0

♠When visitors leave comments on the site this site collect the data shown in the comments form, and also the visitor’s IP address and browser user agent string to help spam detection.
♠This site does not use cookie when visitors leave comments and commenter edit comment.
♠This site uses Akismet to reduce spam. Learn how your comment data is processed.

Comments feed

Trackback URL : https://strix.main.jp/wp-trackback.php?p=27500

Sanbanse Funabashi

Top

スクロールさせるか画像をクリックすると元に戻ります。