インラインJavaScriptをWordPressページのフッターに wp_add_inline_script()
で追加すると、エンコードの問題が発生しました。
以下の説明は、デモンストレーションを目的とした問題の詳細版です。
だから、私は次のJavaScriptを含むポストエディタ上のメタボックス内のテキストエリアを持っています:
var test3 = '3';
var test4 = "4";
テストには一重AND二重引用符を使用してください。次のものを含むJavaScriptファイルもエンキューしています。
console.log("test.js loaded");
TextareaからのJavaScriptは、wp_add_inline_script()を介してtest.js
の直後にページに追加されます。
問題は、ソースコードを調べると一重引用符と二重引用符がエンコードされていることです。
var test3 = '3';
var test4 = "4";
これがなぜなのかわからなかったので、同様のテストをしましたが、プラグイン設定ページのtextarea内にJavaScriptを格納しました。
ここでは、textareaが含まれています:
var test1 = '1';
var test2 = "2";
フロントエンドページに追加すると、このJavaScriptは完全に出力されます。これがスクリーンショットです。
まるでpost metaからのデータはエンコードされていますが、pluginオプションからのデータはエンコードされていないようです。
これが完全なプラグインコードです。
ファイル:inline-js-test.js
<?php
/*
Plugin Name: Inline JS Test
Version: 0.1
Author: David Gwyer
*/
// ijst_ prefix is derived from [i]nline [js] [t]est
// Enqueue scripts
function ijst_enqueue_scripts() {
$options = get_option( 'ijst_options' );
$js = get_post_meta( '5943', '_ijst-js', true );
wp_enqueue_script( 'ijst-test', plugins_url('test.js', __FILE__), array(), '', true );
$inline_js1 = $options['textarea'];
$inline_js2 = $js;
wp_add_inline_script( 'ijst-test', $inline_js1 );
wp_add_inline_script( 'ijst-test', $inline_js2 );
}
add_action( 'wp_enqueue_scripts', 'ijst_enqueue_scripts' );
// Plugin options page
function ijst_init() {
register_setting( 'ijst_plugin_options', 'ijst_options' );
}
add_action( 'admin_init', 'ijst_init' );
function ijst_add_options_page() {
$page = add_options_page( 'Inline JS Test', 'Inline JS Test', 'manage_options', __FILE__, 'ijst_render_form' );
}
add_action( 'admin_menu', 'ijst_add_options_page' );
function ijst_render_form() {
?>
<div class="wrap">
<h2 style="font-size: 23px;">Inline JS Test</h2>
<form method="post" action="options.php">
<?php
settings_fields( 'ijst_plugin_options' );
$options = get_option( 'ijst_options' );
?>
<table>
<tr>
<td><textarea name="ijst_options[textarea]" rows="7" cols="50" type='textarea'><?php echo $options['textarea']; ?></textarea></td>
</tr>
</table>
<p class="submit"><input type="submit" class="button-primary" value="<?php _e( 'Save Changes' ) ?>"></p>
</form>
</div>
<?php
}
// Post meta box
function ijst_meta_box_init() {
add_meta_box( 'inline-js-test', 'Inline JS Test', 'ijst_render_meta_box', 'post', 'normal', 'high' );
add_action( 'save_post', 'ijst_save_meta_box_data' );
}
add_action( 'admin_init', 'ijst_meta_box_init' );
function ijst_save_meta_box_data( $post_id ) {
if ( isset( $_POST['ijst-js'] ) ) { update_post_meta( $post_id, '_ijst-js', esc_attr( $_POST['ijst-js'] ) ); }
}
function ijst_render_meta_box( $post, $args ) {
$js = get_post_meta( $post->ID, '_ijst-js', true );
?><table><tr><td><textarea id="ijst-js" name="ijst-js"><?php echo esc_attr( $js ); ?></textarea></td></tr></table><?php
}
ファイル:test.js
console.log("test.js loaded");
プラグイン全体のコードもこの要旨にあります。 https://Gist.github.com/dgwyer/0bb2022be0d733cf3bfc4e094ea815f7
主な問題とは別に、私はそれをWebページに追加する前にJavaScriptのエスケープ/サニタイズの正しい手順を理解する必要がありますか
生データを出力することは素晴らしい考えではないと思いますが、明らかにコードを壊すようなものを使用したくありません。
1)textareaの内容をエスケープするためには、esc_textarea
ではなくesc_attr
を使うべきです。
2)それらをDBに格納するときにはエスケープしないでください。エスケープは出力時にのみ行うべきです。 (私はあなたがそれが必要とされるかもしれないEdgeケースを見つけることができると思います、しかし一般的な原則として、それをしないでください)。
3)JSコードを挿入するようにユーザーに要求することは非常にユーザー敵対的です。一般的な種類の破損を引き起こす可能性がある明白なセキュリティ問題に加えて、ほとんど避けられません...誰かが$ = 'dollar';
をやっていると思います。そのようにしても、何かをサニタイズする方法がなく、それを生のまま提供しなければならないというのは役に立ちません。