htmlとして出力するデータのサニタイズ

head line

オプション値

<?php sanitize_option( $option, $value ); ?>

整数値

  • intval($int)
  • absint($int)

HTML XML

  • ent2ncr( $text )
    • HTML実体参照を数値参照(10進数)に置換 してreturn

エレメントの許諾

  • wp_kses( (string) $fragment, (array) $allowed_html, (array) $protocols= null )

用例

 if ( preg_match( ' |Author:(.*)$ |mi', $theme_data, $author_name ) ) {
 if ( empty( $author_uri ) ) {
$author= wp_kses( _cleanup_header_comment($author_name[1]), $themes_allowed_tags );
 } else {
$author= sprintf( '%3$s', $author_uri, __( 'Visit author homepage' ), wp_kses( _cleanup_header_comment($author_name[1]), $themes_allowed_tags ) );
 }
 } else {
 $author= __('Anonymous');
 }

たとえば、strip_tags()なら

wp_kses

$stripped_element= wp_kses( $html, array() );

テキストノードのサニタイズ

  • esc textarea
    • $safe_text= htmlspecialchars( $text, ENT_QUOTES );を返す
  • esc_html( $text ) (since 2.8)
    • UTF8のチェックをして、_wp_specialchars ENT_QUOTES シングルクウォートを’&#039;’へ
    • less than, greater than, ampersand, double quote, single quote
  • esc_html__ (since 2.8)
    • 国際化
  • esc_html_e (since 2.8)
    • 国際化
  • function wp_specialchars_decode( $string, $quote_style= ENT_NOQUOTES )
    • 戻す
  • shortcode_unautop($pee)
  • function wpautop($pee, $br= 1)
    • Replaces double line-breaks with paragraph elements.
  • function wptexturize($text)
    • no_texturize_tags hook
    • no_texturize_shortcodes hook

style アトリビュートのサニタイズ

以下のような、スタイル属性に記述されたスタイルのバリデート


$css= 'background:red;margin:0 5px;';

    • safecss_filter_attr($css);

以下のプロパティが、デフォルトで許可されているので、CSS3な場合は、適宜追加の事

$allowed_attr= apply_filters( 'safe_style_css', array( 'text-align', 'margin', 'color', 'float',
	'border', 'background', 'background-color', 'border-bottom', 'border-bottom-color',
	'border-bottom-style', 'border-bottom-width', 'border-collapse', 'border-color', 'border-left',
	'border-left-color', 'border-left-style', 'border-left-width', 'border-right', 'border-right-color',
	'border-right-style', 'border-right-width', 'border-spacing', 'border-style', 'border-top',
	'border-top-color', 'border-top-style', 'border-top-width', 'border-width', 'caption-side',
	'clear', 'cursor', 'direction', 'font', 'font-family', 'font-size', 'font-style',
	'font-variant', 'font-weight', 'height', 'letter-spacing', 'line-height', 'margin-bottom',
	'margin-left', 'margin-right', 'margin-top', 'overflow', 'padding', 'padding-bottom',
	'padding-left', 'padding-right', 'padding-top', 'text-decoration', 'text-indent', 'vertical-align',
	'width' ) );

html アトリビュートのサニタイズ

  • esc_attr( $text )
    • UTF8のチェックをして、_wp_specialchars ENT_QUOTES シングルクウォート→’&#039;’
  • esc_attr__
  • esc_attr_e

ヌル文字

  • wp_kses_no_null()

javascript

  • esc_js( $text )

用例

URL

wp_http_validate_url() (since 3.5.2)

wp_http_validate_url() に localhost を許可しない(since4.9.5)

  • esc_url( $url, (array) $protocols= null ) (since 2.8)
  • esc_url_raw( $url, (array) $protocols= null ) (since 2.8)

esc_url()とesc_url_rawの違いは、

esc_url()は、第三引数を使用しない場合、

wp_kses_normalize_entities()で、& を &amp;に置換

&amp;を&#38;に ’ を&#039;に置換する。

esc_url_raw()は、この置換の工程が省かれる データベースにURLを保存するような場合に使う。
URLに?や#、/が含まれる場合は、http://プロトコルが追加されるが、
//から始まるプロトコルレスURLは、サポートされている

  • urlencode_deep( $array )

  • function utf8_uri_encode( $utf8_string, $length= 0 ) {

  • wp_sanitize_redirect()
    • エスケープ処理されたNULL文字や改行コード除去

MySQL

$wpdb->insert( $table, (array) $data )

$wpdb->update(
 'my_table',
 array( 'status'=> $untrusted_status, 'title'=> $untrusted_title ),
 array( 'id'=> 123 )
);

$wpdb->get_var( $wpdb->prepare(
 "SELECT something FROM table WHERE foo= %s and status= %d",
 $name, // an unescaped string (function will do the sanitation for you)
 $status // an untrusted integer (function will do the sanitation for you)
) );

esc_sql( $sql ) (since 2.8)

$wpdb->escape_by_ref( &$text )

like_escape( $string )

LIKE演算子で使われるワイルドカード% and _をエスケープする

  • function sanitize_sql_orderby( $orderby )

Filesystem

  • validate_file( (string) $filename, (array) $allowed_files= “” )

ファイル名

sanitize_file_name( $name )

HTTP Headers

wp_redirect($location, $status= 302)

wp_safe_redirect($location, $status= 302)

  • wp_sanitize_redirect( string $locaution )

Slug

  • function sanitize_title($title, $fallback_title= ”)
    • strip_tagsして、タイトルがなければ、fallback_title を return
    • 日本語文字列は、urlencodeされます

user name

sanitize_user( $username, $strict= false )

    • バイナリ値、数値文字実体参照、連続スペースの除去、return

バランスタグ

balanceTags( $html ) or force_balance_tags( $html )

タグエスケープ

  • tag_escape( $html_tag_name )
    • a-z _ : 以外を削除して小文字化して return

#ありhex colorの妥当性検証、失敗の場合 空文字または何も返さない

#なしhex colorの妥当性検証、失敗の場合 null

#なし、hex colorに、#をつける それ以外は、そのままの値を返す

チェックボックスのサニタイズ

オプションフィールドの、サニタイズフィルタ

pre_update_option_$option

theme_mod用のサニタイズフィルタ

sanitize_option_theme_mods_$theme

メールアドレス

  • is_email( $email_address )

パス

  • wp_normalize_path( string $path )

http://codex.wordpress.org/Data_Validation

  • wp_make_link_relative()
    • http://www.example.com/hogeを、/hogeに置換 return
  • wp_parse_str() [クエリ形式の文字列を、$arrayに変換]
  • wp_sprintf(sprintfの hook付き)
  • wp_html_excerpt()
  • wp_strip_all_tags()
  • wp_filter_nohtml_kses( $data )
    • CSS等の処理
  • links_add_base_url [wp_make_link_relative()をabsolute URLに]
  • function links_add_target( $content, $target= ‘_blank’, $tags= array(‘a’) )[Adds a Target attribute to all links in passed content.]
  • function wp_strip_all_tags($string, $remove_breaks= false)
    • style scriptタグも除去します。
  • function sanitize_text_field($str)
    • Sanitize a string from user input or from the db
  • capital_P_dangit( $text )
    • WordPressをWordPressに置換するだけ
  • make_clickable($ret) [Convert plaintext URI to HTML links.]
function mmc_make_twitter_clickable($text) {
 $reply_url = '@\\1';
 $hastag_url= '#\\1';
 
 $reply_url = '';
 $hastag_url= '';
 
 $text= preg_replace("/@(\w+)/", $reply_url, $text);
 $text= preg_replace("/#(\w+)/", $hastag_url, $text);
 $text= make_clickable($text);
 
 return $text;

}

http://code.google.com/p/macmediacenter-dot-info/source/browse/theme/trunk/wp-theme/functions.php?spec=svn119&r=119

余談

WordPressは、ユーザー権限によって、利用できるタグやアトリビュートが異なりますが、その仕組みは、以下を参考に

wp_includes/kses.php

/**
 * Sets up most of the Kses filters for input form content.
 *
 * If you remove the kses_init() function from 'init' hook and
 * 'set_current_user' (priority is default), then none of the Kses filter hooks
 * will be added.
 *
 * First removes all of the Kses filters in case the current user does not need
 * to have Kses filter the content. If the user does not have unfiltered_html
 * capability, then Kses filters are added.
 *
 * @uses kses_remove_filters() Removes the Kses filters
 * @uses kses_init_filters() Adds the Kses filters back if the user
 *		does not have unfiltered HTML capability.
 * @since 2.0.0
 */
function kses_init() {
	kses_remove_filters();

	if (current_user_can('unfiltered_html')== false)
		kses_init_filters();
}

add_action('init', 'kses_init');
add_action('set_current_user', 'kses_init');

翻訳 国際化 gettext

翻訳ファイルの、ja.moはテキストファイルではないため、不正なコードなどが混入していても、発見が遅れやすい。
したがって、翻訳テキストはエスケープしたほうが、安全ですが、長ったらしいコードになりがちなので、ワードプレスは、エスケープを含んだ関数を準備している


	/**
	 * Retrieves the translation of $text and escapes it for safe use in HTML output.
	 * If there is no translation, or the domain isn't loaded, the original text is returned.
	 *
	 * @see translate() An alias of translate()
	 * @see esc_html()
	 * @since 2.8.0
	 *
	 * @param string $text Text to translate
	 * @param string $domain Optional. Domain to retrieve the translated text
	 * @return string Translated text
	 */
	function esc_html__( $text, $domain= 'default' ) {
		return esc_html( translate( $text, $domain ) );
	}

	/**
	 * Displays the returned translated text from translate().
	 *
	 * @see translate() Echoes returned translate() string
	 * @since 1.2.0
	 *
	 * @param string $text Text to translate
	 * @param string $domain Optional. Domain to retrieve the translated text
	 */
	function _e( $text, $domain= 'default' ) {
		echo translate( $text, $domain );
	}
	/**
	 * Displays translated text that has been escaped for safe use in an attribute.
	 *
	 * @see translate() Echoes returned translate() string
	 * @see esc_attr()
	 * @since 2.8.0
	 *
	 * @param string $text Text to translate
	 * @param string $domain Optional. Domain to retrieve the translated text
	 */
	function esc_attr_e( $text, $domain= 'default' ) {
		echo esc_attr( translate( $text, $domain ) );
	}

	/**
	 * Displays translated string with gettext context
	 *
	 * @see _x
	 * @since 3.0.0
	 *
	 * @param string $text Text to translate
	 * @param string $context Context information for the translators
	 * @param string $domain Optional. Domain to retrieve the translated text
	 * @return string Translated context string without pipe
	 */
	function _ex( $text, $context, $domain= 'default' ) {
		echo _x( $text, $context, $domain );
	}

	function esc_attr_x( $single, $context, $domain= 'default' ) {
		return esc_attr( translate_with_gettext_context( $single, $context, $domain ) );
	}

	function esc_html_x( $single, $context, $domain= 'default' ) {
		return esc_html( translate_with_gettext_context( $single, $context, $domain ) );
	}

/**
 * Retrieves the translation of $text and escapes it for safe use in an attribute.
 * If there is no translation, or the domain isn't loaded, the original text is returned.
 *
 * @see translate() An alias of translate()
 * @see esc_attr()
 * @since 2.8.0
 *
 * @param string $text Text to translate
 * @param string $domain Optional. Domain to retrieve the translated text
 * @return string Translated text
 */
function esc_attr__( $text, $domain= 'default' ) {
	return esc_attr( translate( $text, $domain ) );
}

/**
 * Retrieves the translation of $text. If there is no translation, or
 * the domain isn't loaded, the original text is returned.
 *
 * @see translate() An alias of translate()
 * @since 2.1.0
 *
 * @param string $text Text to translate
 * @param string $domain Optional. Domain to retrieve the translated text
 * @return string Translated text
 */
function __( $text, $domain= 'default' ) {
	return translate( $text, $domain );
}

/**
 * Retrieves the translation of $text and escapes it for safe use in HTML output.
 * If there is no translation, or the domain isn't loaded, the original text is returned.
 *
 * @see translate() An alias of translate()
 * @see esc_html()
 * @since 2.8.0
 *
 * @param string $text Text to translate
 * @param string $domain Optional. Domain to retrieve the translated text
 * @return string Translated text
 */
function esc_html__( $text, $domain= 'default' ) {
	return esc_html( translate( $text, $domain ) );
}