Sanitize::cleanした改行を元に戻す
以前の改修で、全データはDB登録前にヌルバイトなどの不正コードとSQL特殊文字のエスケープを処理する(($opsion['encode']=falseでSanitize::clean()))仕様にしていましたが、
その場合、TEXTAREAで改行を入れて登録した場合、\\\nを\nに戻す、という一手間が追加必要でした。
TEXTAREAから改行を入れて保存した場合、DB上では以下のように、改行は
\n
で登録されています。
mysql> SELECT * FROM systems ORDER BY id DESC LIMIT 1\G *************************** 1. row *************************** id: 2 name: ダブルクロス3rd detail: DX3rd\n\nF.E.A.Rの現代アクション物TRPG sort_order: 15 1 row in set (0.00 sec)
これをそのまま読み込んで表示すると、\n のまま表示されますから、<br>にでも変更して・・・と思いきや。
nl2br()が効きません。
また編集画面でも、 \n のまま表示されてしまいます。
うっかり勘違いしてたのですが、
ブラウザやMySQLコンソールでみえる\nは、改行コードそのものではなく、
\\\n*1なのです。。
そして、\\\n は、nl2br()にはヒットしないというわけで・・・。
理由がわかったので修正
編集画面は preg_replace、
表示側は、CakePlusさんの Cakeplus.HtmlEscape に処理を真似して、
- \\\nを\nに戻すメソッド(一覧など、nl2brにしない場合)
- \\\nを\nに変更した後nl2br()するメソッド
の2種類を作りました。
以下、差分
diff --git a/app/plugins/cakeplus/controllers/components/html_escape.php b/app/plugins/cakeplus/controllers/components/html_ index a7919a3..b740cc4 100644 --- a/app/plugins/cakeplus/controllers/components/html_escape.php +++ b/app/plugins/cakeplus/controllers/components/html_escape.php @@ -68,6 +68,55 @@ class HtmlEscapeComponent extends Object { } } + function _unsecape_recursive($value, $funcname, $noescape_list = null ,$parent_key = null) { + if (is_array($value)) { + foreach ($value as $key => $val) { + $parent_key_arr = ( isset($parent_key) ) ? $parent_key . '.' . $key : $key ; + + + $value[$key] = self::_unsecape_recursive($val, $funcname, $noescape_list, $parent_key_arr); + } + return $value; + } else { + if( is_array($noescape_list) ){ + foreach( $noescape_list as $noescape_value ){ + $noescape_value = str_replace( ".", '\.' , $noescape_value ); + + if( preg_match( "/^(.+\.|)$noescape_value(\..+|)$/", $parent_key ) ){ + return $value; + } + } + } + $value = call_user_func(array('HtmlEscapeComponent', $funcname), $value); + + return $value; + } + } + + /** + * Execute nl2br() to escaped Array Data + * + * @param string or array $value + * @param array $noescape_list + * @param string $parent_key + * @return string or array + */ + function nl2br_escaped( $value, $noescape_list = null ,$parent_key = null ) { + return $this->_unsecape_recursive($value, "_nl2br_escaped", $noescape_list, $parent_key); + } + + /** + * Execute unescape Array Data + * + * @param string or array $value + * @param array $noescape_list + * @param string $parent_key + * @return string or array + */ + function nl_unescape($value, $noescape_list = null ,$parent_key = null ) { + return $this->_unsecape_recursive($value, "_nl_unescape", $noescape_list, $parent_key); + } + /** * Execute nl2br() and h() to String Data @@ -78,5 +127,24 @@ class HtmlEscapeComponent extends Object { return nl2br( h( $value, $charset ) ); } + /** + * Execute nl2br() to escaped String Data + * @param string $value + * @return string + */ + function _nl2br_escaped(&$value) { + $value = $this->nl_unescape($value); + return nl2br($value); + } + + /** + * Execute unescape String Data + * @param string $value + * @return string + */ + function _nl_unescape($value) { + return preg_replace('/\\\n/', "\n", $value); + } + }
- 編集画面用、\\\nを\nに戻す
--- a/app/models/behaviors/sanitize_plus.php +++ b/app/models/behaviors/sanitize_plus.php @@ -53,6 +53,7 @@ class SanitizePlusBehavior extends ModelBehavior { function restore_html(&$model, $string, $strip_all = false, $strip_scripts = true, $strip_images = true, $strip_whitespace = false) { (中略) + $string = preg_replace('/\\\n/', "\n", $string); if ($strip_all) { $string = Sanitize::stripAll($string);
* Sanitize導入した際の記事
データのサニタイジング(2-1) 編集画面で逆Sanitize - 趣味の延長線
データのサニタイジング(1) save - 趣味の延長線
*1:\\\nで良さそうな気がするのですが、これではpreg_replaceでヒットせず