セキュリティで ほんとは esc_html とかエスケープしなと xss とかのたいしょうとなるらしい

http://www.warna.info/archives/2476/

わんばんこ。2012 WordPress アドベントカレンダーの3日目をむゆうさん( @anticyborg )と共に担当させていただきます。本当は、アドベントよりおべんt(以下略

WordPress で実現系のコードを紹介する記事は、よく目にしますし、セキュリティに関する関心も高いようですが、意外に基本的な所が抜け落ちているケースが多いように感じたので、テーマやプラグイン開発時に憶えておいて欲しい WordPress 関数、esc_html、esc_attr、esc_url について、つらつらと書いてみたいと思います。


この esc_ なんちゃらは、WordPress 2.8 から導入された関数で、それ以前のバージョンでは、wp_specialchars、attribute_escape、clean_urlと様々な名称であったものが、(おそらくは憶えやすいように)統一的な関数名に改名されたものです。Webには、様々な脆弱性を狙った攻撃方法がありますが、これらのエスケープ処理は、XSS を防ぐためのものですね。

WordPress のテンプレートタグで、そのまま表示を行うものの場合、エスケープなども含めて適切な処理をしてくれますが、カスタムフィールドの入力やURL、フォームなどから受け取る値の出力に関しては、必ずこれらの関数を用いておく必要があります。
特定の人のみしか入力しないから大丈夫とかいうのではなく、普段から表示するものにはエスケープ処理を加えるようにしておき、

Webサイト管理者によって完全に管理された内容であること
タグを使う必要性があるもの
である場合でのみ、エスケープを解除するように癖をつけておいた方が、うっかり抜けの少ない安全なWebにできます。(この場合でもstrip_tagsを用いて、特定のタグだけ許可した方がいいですね。)

特に昨今は、カスタムフィールドを用いて、表示する項目が多くなってきていますので要注意ですよ。

esc_html

Webページ上で表示する文字列に対し、タグとして認識される < > のエスケープや、& などの特殊文字のエンティティを行います。

適用例 1

1
<?php echo esc_html( get_post_meta( $post->ID, 'meta_key', true ) );
適用例 2

1
<?php echo esc_html( $_GET['key'] ); ?>
esc_attr

attr の名前が示すとおり、タグの属性値にかけるエスケープ関数です。でも、ソースコード読むと、esc_html とまったく一緒。でも、将来的に変わる可能性もあるので、ちゃんと使い分けましょうね。

適用例 1

1
<img src="" alt="<?php echo esc_attr( get_post_meta( $post->ID, 'img-alt', true ) ); ?>" />
適用例 2

1
<input type="text" name="form-name" value="<?php echo esc_attr( get_option( 'form-name', '' ) ); ?>" />
esc_url

urlとして不適切な文字列の削除やエンティティ化を行います。

適用例 1

1
<a href="<?php echo esc_url( get_post_meta( $post->ID, 'user_website', true ) ); ?>">Webサイト</a>
この他にも、javascriptのサニタイズを行う esc_js や、テキストエリアに用いる esc_textarea (し、知らなかった。)なんていうものもあるようです。

テンプレートで ファンクションを整理して メタタグなどを ファンクションで管理する方法

[WordPress] functions.phpを編集、修正、管理しやすくする書き方
http://millkeyweb.com/wp-functions-management/

まずこちらを参考にファンクションを整理

require_once locate_template('func/init.php');        // 初期設定の関数
require_once locate_template('func/cleanup.php');     // 不要なモノを削除する関数
require_once locate_template('func/titles.php');      // タイトル出力の関数
require_once locate_template('func/breadcrumbs.php'); // パンくずリストの関数
require_once locate_template('func/scripts.php');     // CSSやJavascript関連の関数
require_once locate_template('func/ads.php');         // 広告関連の関数
require_once locate_template('func/widgets.php');     // サイドバー、ウィジェットの関数
require_once locate_template('func/custom.php');      // その他カスタマイズの関数

require_once locate_template('func/plugin.php');      // プラグインの関数


require_once locate_template('func/d_header/disp.php');      // プラグインの関数

こんな感じでなにも入れない ちょくは

フォルダfuncにそれそれ作って 入れる

メタをファンクションで
meta descriptionを設定(プラグインなし版)
http://easyramble.com/wordpress-meta-description.html 参考
ベース

// get meta description from the content
function get_meta_description() {
  global $post;
  $description = "";
  if ( is_home() ) {
    // ホームでは、ブログの説明文を取得
    $description = get_bloginfo( 'description' );
  }
  elseif ( is_category() ) {
    // カテゴリーページでは、カテゴリーの説明文を取得
    $description = category_description();
  }
  elseif ( is_single() ) {
    if ($post->post_excerpt) {
      // 記事ページでは、記事本文から抜粋を取得
      $description = $post->post_excerpt;
    } else {
      // post_excerpt で取れない時は、自力で記事の冒頭100文字を抜粋して取得
      $description = strip_tags($post->post_content);
      $description = str_replace("\n", "", $description);
      $description = str_replace("\r", "", $description);
      $description = mb_substr($description, 0, 100) . "...";
    }
  } else {
    ;
  }

  return $description;
}

// echo meta description tag
function echo_meta_description_tag() {
  if ( is_home() || is_category() || is_single() ) {
    echo '<meta name="description" content="' . get_meta_description() . '" />' . "\n";
  }
}

屁だー

<?php echo_meta_description_tag(); ?>

自己

まず覚え発見

$disp = single_term_title( '' , false );//falseで出力せん

ドルに収納するときは
. ピリオドで繋げれる事

$description =  $disp . $disp_base . $disp_page;
$description =  $disp .' | '. $disp_base . $disp_page;

ページ数は

get_query_var('paged')

でとれるから
1ページ目は0がかえるから
そいつを覗いてページをいれる

$disp_page_no = get_query_var('paged') ;
  if($disp_page_no !== 0)
  {
	  $disp_page = ' | '.$disp_page_no . 'ページ目';
	  }

あとこの違い

$disp = get_the_author_meta( nickname, $author );//the_author_meta() は出力

カスタムポストタイプの場合 ラベルの単数系を使うことでメニューと混合しん
get post typeは戻り値がスラッグだで
get post type objectの中に入れてやることで投稿タイプの情報がとれる

<?php get_post_type_object( $post_type ); ?>

つまりラベルをとるには

<?php echo esc_html( get_post_type_object( get_post_type() )->labels->singular_name ); ?>

https://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/get_post_type_object 参考

タームがかぶる件は カテゴリは:カテゴリ タグは:タグ タクソノミーは:

同じ記事タイトルの件
ブログシングルでよくあった件だが 今回の設定ではディスプはコンテンツが入っているので 必要ない
タイトル+ベース文の場合おこる重複
※タイトルでは使う

//タイトルが同じ記事の場合-2とかスラッグにつくが、the_title wp_titleにはつかないのでディスプリクション・タイトルが重複するのを防ぐ
if (is_single() || is_page()){//シングルなら
$dd_title = urldecode ($slug_name = $post->post_name);// スラッグをデコードして取得
//echo $dd_title;
$keywords = preg_split("/[-]+/", $dd_title);//phpスプリット - にて
//print_r($keywords);
$last = end($keywords); //配列の最後を取得する ほにゃらら-2 ▶ $keywords[0]がほにゃらら $keywords[1]が2
//echo $last;
if (ctype_digit($last)) {//ケツが数字ならの分岐 
}
}
 //カスタムポストでは常時カスタムする  ラベルの単数系を使うことでメニューと混合しん
 //サンプル 
  elseif ( is_singular('sample') ) {
	  if (ctype_digit($last)) {//ケツが数字なら つまりタイトルが重複しているなら 
	  $title_no = '-'.$last; }//-数字を装弾

	$disp = get_the_title() . $title_no;
	 $d_post_type_label = ' | '.get_post_type_object( get_post_type() )->labels->singular_name;//ラベルを取得
	   $description =  $disp . $d_post_type_label .' | '. $disp_base;

結果

<?

// get meta description from the content
function get_meta_description() {
  global $post;
  $description = "";	
  
  //タイトルが同じ記事の場合-2とかスラッグにつくが、the_title wp_titleにはつかないのでディスプリクション・タイトルが重複するのを防ぐ
if (is_single() || is_page()){//シングルなら
$dd_title = urldecode ($slug_name = $post->post_name);// スラッグをデコードして取得
//echo $dd_title;
$keywords = preg_split("/[-]+/", $dd_title);//phpスプリット - にて
//print_r($keywords);
$last = end($keywords); //配列の最後を取得する ほにゃらら-2 ▶ $keywords[0]がほにゃらら $keywords[1]が2
//echo $last;
if (ctype_digit($last)) {//ケツが数字ならの分岐 
}
}


  $disp_page_no = get_query_var('paged') ;//ページナンバーを取得
  if($disp_page_no !== 0)
 		 {	$disp_page = ' | '.$disp_page_no . 'ページ目';	}//2ページ目以降装弾
  
  $disp_base = '春日井市で外構エクステリア工事(カーポート、ウッドデッキ、テラス、サンルーム、玄関、駐車場の工事など)なら春日井市神屋町にあるクリエイト福海へ!地域密着店ですので、些細な事もお気軽にご相談ください。愛知県全域御対応!見積り無料!';

// ホームでは、基本文
  if ( is_home() ) {
	  
    $description =  $disp_base
	//get_bloginfo( 'description' )
	;}
	
	 ///////------------------------アーカイブ------------------------ ///////
	
//カテゴリではターム名  + 基本文
	elseif ( is_category() ) {
		
	$disp = single_cat_title( '' , false );//falseで出力せん //single_term_titleでも同じ
	   $description =  $disp .' | カテゴリー' . $disp_page .' | '. $disp_base;
    //$description = category_description();
  }
  
//タクソノミーではターム名 + 基本文  
   elseif ( is_tax() ) {	
   
       $my_tax   = get_taxonomy( get_query_var( 'taxonomy' ));//タクソノミー情報を取得して
	$my_tax_label =' | '. $my_tax->labels->singular_name; //わかりやすくシングルラベルを使う
	
$disp = single_term_title( '' , false );
	   $description =  $disp . $my_tax_label . $disp_page.' | '. $disp_base;

  }
//タグではタグ名 + 基本文 
	elseif ( is_tag() ) {
		
	$disp = single_term_title( '' , false );
	   $description =  $disp  .' | タグ' . $disp_page .' | '. $disp_base;

  }
  
//月アーカイブでは年月 + 基本文  
  elseif ( is_month() ) {
	  	
	$disp = get_query_var('year') . '年' . get_query_var('monthnum') . '月の記事';
	   $description =  $disp . $disp_page .' | '. $disp_base;
 
  }
  
 //オーサーアーカイブではオーサー名 + 基本文
    elseif ( is_author() ) {
		
	$disp = get_the_author_meta( nickname, $author );//the_author_meta() は出力
	   $description =  $disp . ' さんの投稿 |' . $disp_page . $disp_base;
 
  }
  
  //ポストタイプアーカイブ カスタムポストのアーカイブ
  elseif(is_post_type_archive( 'sample' )){
//あれば
  }
  //ただのアーカイブ カテゴリー、タグ、投稿者または日時のいずれかに基づいて投稿を集めたページ
  //elseif(is_archive()){
	  
 // }
 ///////------------------------ページ------------------------ ///////
  
 //個ページではページタイトル + 基本文
      elseif ( is_page() ) {
	
	$disp = get_the_title();//
	   $description =  $disp . $disp_page .' | '. $disp_base;
 
  }
  
 ///////------------------------シングル------------------------ ///////
 
  //ブログシングル  
  elseif ( is_single() ) {
	//記事本文から抜粋を取得  
    if ($post->post_excerpt) {
 $description = $post->post_excerpt;
	  
	  // post_excerpt で取れない時は、自力で記事の冒頭100文字を抜粋して取得
    } else {
      
      $description = strip_tags($post->post_content);
      $description = str_replace("\n", "", $description);
      $description = str_replace("\r", "", $description);
      $description = mb_substr($description, 0, 100) . "...";
    }
  }
 ///////////////////////////ここからカスタム投稿タイプ それぞれ違うから注意!///////////////////////////////
 
 //カスタムポストでは常時カスタムする  ラベルの単数系を使うことでメニューと混合しん
 //サンプル 
  elseif ( is_singular('sample') ) {
	  if (ctype_digit($last)) {//ケツが数字なら つまりタイトルが重複しているなら 
	  $title_no = '-'.$last; }//-数字を装弾

	$disp = get_the_title() . $title_no;
	 $d_post_type_label = ' | '.get_post_type_object( get_post_type() )->labels->singular_name;//ラベルを取得
	   $description =  $disp . $d_post_type_label .' | '. $disp_base;
 
  }
 ////////春日井ナビ  ショップ
 elseif ( is_singular('shop') ) {
		
		  
  if($post-> お店からメッセージ見出し): 
  			$disp = str_replace(array("\r\n","\r","\n"), '', mb_substr(get_post_meta($post->ID,"お店からメッセージ見出し",true), 0, 120)) . str_replace(array("\r\n","\r","\n"), '', mb_substr(get_post_meta($post->ID,"お店からメッセージ",true), 0, 120));
   else: 	if($post-> 店舗紹介文){$disp = mb_substr(post_custom('店舗紹介文'), 0, 120);} 
   endif;
	  //if (ctype_digit($last)) {//ケツが数字なら つまりタイトルが重複しているなら 
	  //$title_no = '-'.$last; }//-数字を装弾

$disp_t = get_the_title() . ' | ';
$disp_site = ' | 春日井ナビ';
	// $d_post_type_label = ' | '.get_post_type_object( get_post_type() )->labels->singular_name;//ラベルを取得
	   $description =  $disp_t . $disp . $disp_site;
 
  }

  
  
 else {
    ;
  }
  

 
  return $description;
}
 
// echo meta description tag
function echo_meta_description_tag() {
  //if ( is_home() || is_category() || is_single() ) {
    echo '<meta name="description" content="' . get_meta_description() . '" />' . "\n";
  //}
}
		


?>