[groonga-dev,02205] Re: PHPなどによる検索文字列エスケープの基準

Back to archive index

Kimura A a.kim****@live*****
2014年 3月 31日 (月) 20:45:29 JST


木村です。林さんご回答ありがとうございます。

教えていただいた

> * mroongaEscapeでは +-<>~*()をエスケープ
> * ' "などについてはreal_escape_stringにまかせる

を基準に考えてみると、こんな感じになりそうです。

public function mroongaEscape($str) {
    return preg_replace('/([\+\-<>~\*\(\)])/', '\\\\$1', $str);
}

この時点では二重エスケープになりませんが、続けて以下のようにmysqli_real_escape_string()なりを適用すれば、「\」自体がエスケープされることで二重エスケープになるわけですね。
$escapedStr = mysqli_real_escape_string($link, mroongaEscape($str));


ただ、検索文字列が「"」を含んでいる場合にはどうすべきでしょう?
$escapedStr = mysqli_real_escape_string($link, mroongaEscape('test_"_withQuote'));

この場合、「"」部分にはmysqli_real_escape_string()だけが適用され、$valueは'test_\"_withQuote'となりますよね。
するとMySQLからMroongaに渡るときには'test_"_withQuote'に戻ってしまって、特殊記号扱いになってしまうと思います。

かといって、mroongaEscape()の処理対象に「"」を加えたとしても、後続のmysqli_real_escape_string()で「\」
と「"」の双方がエスケープされてしまい、いわば三重エスケープの状態になってしまうのでダメかと思います(「"」→「\"」→「\\\"」)。


自分では今のところ、単純に文字列置換で「"」に対するエスケープを追加する方向で考えています。
$value = str_replace('\\"', '\\\\"', mysqli_real_escape_string($link, mroongaEscape($str)));
mysqli_real_escape_string()より後に文字列をいじるのはちょっと引っかかりますが、これだけなら大きな危険はないんじゃないか…と。

この形なら、たとえば「He said "I'm sad."」という文でフレーズ検索する場合なども、
$value = '"' . $this->mroongaValue('He said "I\'m sad."') . '"';
という要領でクエリに組み込めるのではないかと思っているんですが。


思い当たることなどあれば、引き続きアドバイスをどうぞよろしくお願いします。
ひとまずはありがとうございましたm(_ _)m 		 	   		  



groonga-dev メーリングリストの案内
Back to archive index