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 に処理を真似して、

  1. \\\nを\nに戻すメソッド(一覧など、nl2brにしない場合)
  2. \\\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);
+       }
+
 }
  1. 編集画面用、\\\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でヒットせず