2007年11月20日

CodeIgniter:日本語URIでThe URI you submitted has disallowed characters.

前回はソート機能を作ってみましたが、今回は検索支援UI?として五十音パッド(なんじゃそりゃ?)を作ってみようとおもいました。んでいろいろいじっていたら、日本語(もちろんURLエンコード済み)が含まれているURLで"The URI you submitted has disallowed characters."というエラーが発生しました。

ただこの件に関しては予め?というか前に散々ネットを検索してCodeIgniterの情報を集めていた際に、
Code Igniter - goungoun技術系雑記帳」様
とか
price-change:blog CodeIgniter | URIで日本語を使うのだ」様
などで語られていたため、その当時は「まあ自分で必要になった時に(上記サイトの説明にあるように)設定すればいいや」などと簡単に考えていました。

で、その設定にしてもできない(--;。最終的に自分で使う分には問題ない程度までは解決しましたが、果たしてその解決方法が正しいのかどうかはわかりません(毎度のことながら)。そんなわけでここに書いてある方法はあてにはなりませんが、一応メモっておきます。

まず何をしていたかというと、上に書いたように五十音パッド?なるものを作成していました。要するに「あいうえお〜」を並べておいて、例えば「あ」をクリックしたら、「あ」で始まる旧市町村を検索する〜みたいな感じです。(参項↓こんなやつ)
Wikipedia - Category:鎌倉時代の武士

でformは使わずanchorにしたかったので当然URIは
http://localhost/class/method/parameter

みたいになるわけですが、どういうロジックにせよparameterの部分にはどうしたって、[あ-わ]の平仮名五十音が入りそうな予感だったので、まずは適当なメソッドをでっちあげて
http://localhost/gappei/tekitou/あ(※実際は"%E3%81%82")

のように送信?してみました。

すると案の定
The URI you submitted has disallowed characters.

となり正常に動作しません。

ただここまでは上述の通り想定の範囲内だったので、まずはgoungoun技術系雑記帳様で解説されていたようにconfigの$config['uri_protocol']をAUTOからREQUEST_URIに変更してみました。

すると送信とか以前にメインページ自体が表示できなくなってしまいました。おそらくは自分のところの環境がcodeigniterをサブディレクトリ(アパッチのDocumentRootより深い場所)に置いていたりとかなんとか…そんなのが影響してるっぽかったので、この方法は却下しました。
(※誤解を招く恐れがあるので明言しておきますが、決して上記サイト様の情報が誤っているとか、上記サイト様に文句を言っているとかいうわけではありません。あくまでもウチの環境ではできなかったという話です。)

で、仕方がないので次にprice-change:blog CodeIgniter | URIで日本語を使うのだで解説されていた方法を試してみました。

$config['permitted_uri_chars'] の正規表現?みたいな部分に日本語を付け足す?という感じの方法なのですが、自分の場合は漢字は必要なく今回は平仮名だけが通ればいいので、「ぁ-ん」だけを付け足してみました。

すると
preg_match() [function.preg-match]: Compilation failed: range out of order in character class at offset 5

というエラーがでました。

そこでよくよく考えて…というかフト思ったのが、実はうちの環境は文字コードは全てUTF-8に統一する方向でApacheもPHPもMySQLも設定していたのですが、codeigniterのファイルの文字コードってなんだったっけかな?と。それでconfig.phpの文字コードを見てみたらSJISになっていました!まあ元ファイルには日本語は一切含まれていないので何でもよかった?んでしょうが、どうやら「ぁ-ん」←コレを記述したことでアレな感じだったので、UTF-8で保存し直しました。

すると今度はすんなり通りました!よしよしと思いつつ「あ」から始まってランダムに「き」とか「せ」「ぬ」「ほ」…とクリックして、ほぼOKだろなどと考えつつ「む」をクリックした瞬間…
The URI you submitted has disallowed characters.

(TT(TT(TT(TT(TT

わけがわからず、とりあえず気を取り直してもう一度、今度はちゃんと「あ」から一文字づつ順番にクリック。でも「み」までは大丈夫なのに「む」は相変わらずダメ。その後に続く「め」から「わ」はOK。

さっぱりわからないので、まずは手がかりとして文字コードと思い、「む」のURLエンコードを見てみると「%E3%82%80」。むむむむ、なんか臭い。特に末尾の%80ってのが気になる、非常に気になる。なんで気になったかというと、その昔SJISのダメ文字が確か80がどーのこーの…。

後で調べてみるとダメ文字は0x5Cが含まれている文字で、80は関係ありませんでしたが、それでもこの%80が怪しいと睨んだのは、あながち的外れなことでもなく、「あ」から「わ」の文字の中に%80という部分を含む文字は「む」だけだったわけです。

で、試しに
「%E3%83%80」=「ダ」カタカナのダ
「%E3%80%82」=「。」句読点
「%E3%80%83」=「〃」繰返しの記号?
の三文字についても同じように調べてみたところ、全部同一のエラーがでました。隣の「ヂ」とか「、」などはOKでした。

そこで今度は$config['permitted_uri_chars'] の「ぁ-ん」の隣に「む」と記述してみました。「ぁ-んむa-z 0-9~%.:_-」

すると今度は「む」もすんなりと通りました。不思議なことに「ダ」「。」「〃」も通ってしまいました。

う〜む、謎は深まるばかり…。なんとなく%80がダメっぽい気もしないでもないですが、どうも100%そうとも言い切れないような、なんかモヤモヤした気分。そこでUTF-8についてもう少し調べていると、なんかpreg_matchに関して書いてあって、preg系の関数にUTF-8を通すには/uオプションをつけることとかなんとかなってる。

なんだ「/u」って、とおもいPHPのマニュアルを読む。
パターン修飾子 -- 正規表現パターンに使用可能な修飾子
u (PCRE_UTF8)
この修正子は、Perl 非互換な PCRE の機能を有効にします。パターン 文字列は、UTF-8 エンコードされた文字列として処理されます。 この修正子は、UNIX では PHP 4.1.0 以降、Win32 では PHP 4.2.3 以降で 使用可能です。 また、PHP 4.3.5 以降では、パターンの UTF-8 としての妥当性も確認されます。

ふむふむ…ってこんなのプロプログラマじゃなきゃ知らんがな(--;。ってか自分preg_matchとか使ってないし、使ったのはcodeigniter書いた人じゃん。などとぶつぶつ言いながら、↑の方でpreg_matchのエラーが出ていたファイル=/system/libraries/Router.phpの408行目付近を見てみる。

するとなにやらpermitted_uri_charsをごにょごにょしてるっぽいところでpreg_matchがあった。んですでにi修飾子が書かれてる。なのでおもむろにその隣にuって書いて保存。
if ( ! preg_match("|^[".preg_quote($this->config->item('permitted_uri_chars'))."]+$|i", $str))
     ↓
if ( ! preg_match("|^[".preg_quote($this->config->item('permitted_uri_chars'))."]+$|iu", $str))

こんなことしていいのかどうかは全く定かではない。でもとりあえず上で「ぁ-んむ」としていた個所を「ぁ-ん」に戻して再度テスト。

「あ」:もちろんOK
「む」:なんとOK!
「ダ」:エラー
「。」:エラー
「〃」:エラー

というわけで、一応「ぁ-ん」と指定していて、その文字は通ってそれ以外はエラーになったので、一応期待された動作ってことで終了!UTF-8で運用?している人には参考になるかもしれない。漢字も通したい場合は上記のサイト様のところの書式が参考になるとおもいます。但しおそらくその場合もpreg_matchには/u修飾子は必要そうな気がする(漢字は試してないっす)。だけどコアファイル?をいじってるのでくれぐれも自己責任で〜。
タグ:codeigniter
posted by ciallost at 22:54| Comment(1) | TrackBack(0) | 日記 | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
ひらがな は、あと2文字あります。
http://pentan.info/php/reg/is_hira.html

またリンク先のページの漢字検出も完全ではありません。
http://pentan.info/php/reg/is_kanji.html
Posted by at 2009年01月12日 07:31
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
この記事へのトラックバックURL
http://blog.seesaa.jp/tb/67901022

この記事へのトラックバック
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。