サポート » 使い方全般 » esc_html() の配列バージョンを作りたい

  • AJAXでデータを受け取る際の質問です。

    まず確認させてください。

    esc_html()を通せばそれ以降その値をどう扱おうと絶対安全だと考えて間違いないでしょうか?

    具体的には下記の$valはもう絶対に安全でしょうか?

    もし危険なケースがあればお伺いしたいです。

    
    // AJAX
    add_action( 'wp_ajax_get_data', 'get_data' );
    function get_data() {
    	$val = esc_html( $_POST['val'] );
    	// これ以降$valをどのように扱おうと絶対に安全…?
    	$post_type = get_post_type( $val );    // 安全…?
    	$post_meta = get_post_meta( $val, 'meta_key' ); // 安全…?
    }
    

    次に質問になります。

    受け取る値が配列の場合にまとめてesc_html()を通すべく、次のような関数esc_arr()を作ってみました。

    しかし、$val['a','b']のような場合はこれでいいとしても、[['a','b'],['c']]とか[['a'=>1,'b'=>2],['c'=>3]]とかに対応させる場合がわかりません。

    もしまとめてesc_html()を通す良い方法がございましたらご教授頂けませんでしょうか。

    
    // まとめてesc_html()を通す
    function esc_arr( $arr ) {
    	if( is_array($arr) ){
    		foreach ( $arr as $k=>$v ) {
    			$arr[$k] = esc_html($v);
    		}
    	}
    	else{
    		$arr = esc_html( $arr );
    	}
    	return $arr;
    }
    
    // AJAX
    add_action( 'wp_ajax_get_data', 'get_data' );
    function get_data() {
    	$arr = esc_arr( $_POST['arr'] ); // まとめてesc_html()を通す
    	extract($arr); // もう安全なのでextractをかけても大丈夫、としたい
    }
    
3件の返信を表示中 - 1 - 3件目 (全3件中)
  • こんにちは

    それ以降その値をどう扱おうと絶対安全だと考えて間違いないでしょうか?

    あらゆるケースを想定した絶対的な安全などはありません。

    リファレンス(esc_html)には

    HTML ブロックをエスケープします。

    とありますが、何かをセキュアにするとは書かれていません。
    エスケープされた結果としてセキュアな状態かどうかは使用する側がケースバイケースで判断するしかないでしょう。
    また、「HTML ブロックをエスケープ」と書かれているのであって、SQL インジェクションやディレクトリトラバーサルなどその他もろもろの脆弱性をターゲットにして何かの対応がされているわけでもありません。

    esc_html()を通せばそれ以降その値をどう扱おうと絶対安全だと考えて間違いないでしょうか?

    こちらは、@munyagu さんの書かれている通りです。esc_html() はあくまでも、HTML ブロックをエスケープするだけです。
    WordPress Codex 日本語版の「データ検証」ページが参考になると思います。

    もしまとめてesc_html()を通す良い方法がございましたらご教授頂けませんでしょうか。

    こちらは、下記のようなコードではどうでしょうか?

    function esc_arr( $arr ) {
    	return filter_var( $arr, FILTER_CALLBACK, ["options" => function( $v ) { return esc_html( $v ); }] );
    }
    トピック投稿者 notenotennoote

    (@notenotennoote)

    @munyagu様、@ishitaka様

    ご忠告くださったお二方にまずは感謝申し上げます。
    どうもありがとうございます。

    ユーザー投稿型サイトを作るにあたって、本文や検索バーでAJAXを使う予定です。
    たとえば下記コードは投稿のフローですが、不安点など見えますでしょうか?

    ※動くことは確認できているので「コードがあってるかどうか見てくれ」ではなくて、「こういうフローで注意すべきこと」や「esc_html()以外に通すべき関数」などをお伺いできましたら幸いです。

    
    // AJAX
    add_action( 'wp_ajax_get_data', 'get_data' );
    function get_data() {
    
    	// 入力値をエスケープ
    	$arr = esc_arr( $_POST['arr'] ); 
    
    	// $post_type, $post_title, $post_content, $term_name_arr が展開
    	extract( $arr ); 
    
    	// 投稿タイプはどちらかのみOK
    	if( $post_type != 'custom1' && $post_type != 'custom1' ) die();
    
    	// タイトルは必須で50文字以内OK
    	if( ! empty( $post_title ) ) {
    		$post_title_mblen = mb_strlen($post_title);
    		if( ! $post_title_mblen || $post_title_mblen > 50 ){
    			die();
    		}
    	}
    	else{
    		die();
    	}
    
    	// 本文はもしあれば1000文字以内OK
    	if( ! empty( $post_content ) ) {
    		$post_content_mblen = mb_strlen($post_content);
    		if( ! $post_content_mblen || $post_content_mblen > 1000 ){
    			die();
    		}
    	}
    
    	// 投稿
    	$my_post = array(
    		'post_title'    => $ttl',
    		'post_content'  => $content,
    		'post_type'     => $post_type',
    		'post_status'   => 'publish',
    		'post_author'   => get_current_user_id(),
    	);
    	$insert_id = wp_insert_post( $my_post ); 
    	
    	// タームを登録
    	if( ($insert_id) && !is_wp_error($insert_id) ) { 
    		// タームIDを取得
    		$book_id_arr = my_insert_terms( 'book', $term_name_arr );
    		// 登録		
    		wp_set_object_terms($insert_id, $book_id_arr, 'book' );
    	}
    }
    
    // タームIDを取得
    function my_insert_terms( $taxonomy, $term_name_arr ){
    /*
    タームがあればIDを返し、なければ登録して返す
    @param
    $taxonomy      : 'book'のみ
    $term_name_arr : ユーザーが投稿したターム名の配列
    @return
    $book_id_arr   : 'book'のタームIDの配列
    */	
    	if( $taxonomy=='book' ){
    		$parent_book = term_exists( 'en', 'book' );
    		
    		$book_id_arr = [];
    		foreach( $term_name_arr as $term_name ){
    			
    			// 既存ならそのままタームのデータを取得
    			$book_data = term_exists( $term_name, 'book', 'en' ); 
    			
    			// もしなければタームを登録
    			if( !$book_data ){ 
    				$book_data = wp_insert_term( $term_name, 'book', array( 'parent'=> $parent_book["term_id"] ) );
    			}
    			
    			// タームのlIDを取得
    			$book_id_arr[] = intval( $book_data['term_id'] ); 
    		}	
    		
    		return $book_id_arr;
    	}
    }
    
    // 入力値をエスケープ
    function esc_arr( $arr ) {
    	return filter_var( $arr, FILTER_CALLBACK, ["options" => function( $v ) { return esc_html( $v ); }] );
    }
    

    @ishitaka
    便利なfilter_varに感動しました。上記の通り使わせて頂きたいと思います。
    いつも便利な書き方をありがとうございます。

3件の返信を表示中 - 1 - 3件目 (全3件中)
  • トピック「esc_html() の配列バージョンを作りたい」には新たに返信することはできません。