#osc16ep (20161005) | 2016-10-05 11:46 |
piwik-fluentd (2.0.3) | 2015-11-12 15:22 |
Piwik patches for Japanese (20160813) | 2016-08-13 15:23 |
Piwik はなるべく新しいバージョンを使ってください。 今までずっと引き継いできた問題でも発見したバージョン以降で修正しています。遡っての修正はしていません。 例えば Piwik >= 2.14.3 で解決できる問題があります。
文字化けは UTF-8 のカラムで、UTF-8 ではない文字列を INSERT することにより起こりますが、MySQL のデフォルトの仕様でカラムに入るように自動変換され、文字化けはするもののエラーは起きません。
しかし、my.cnf の設定で
[mysql] sql_mode = "STRICT_ALL_TABLES"
または
[mysql] sql_mode = "TRADITIONAL"
として自動変換をお断りするすると、General error: 1366 で MySQL がクラッシュします。Tracker で追跡しているときは、一アクセスだけ犠牲になりますが import_logs.py でログを取り込んでいるときは処理が止まるので、--skip を指定して、問題の起きているログを飛ばして再取り込みを行う必要があります。
まず検索エンジンの定義ですが、
piwik/core/DataFiles/SearchEngines.php (もしくは piwik をインストールしたディレクトリ/core/DataFiles/SearchEngines.php 、以下同じ)にあります。ここの array 第 4 引数でキーワードの文字コードが複数指定できるよう考慮されており、UTF-8 以外では各国文字コードを指定しなければならないのですが、日本語検索エンジンで文字コードの指定があるのは
'www.excite.co.jp' => array('Excite', 'search', 'search.gw?search={k}', 'SHIFT_JIS'),
だけで(しかもこの設定だと UTF-8、EUC-JP の検索キーワードは文字化けとなります。指定文字コードが mb_detect_encoding で検出できない場合、キーワードは最初に指定する文字コード -- つまり上の例では SHIFT_JIS -- とみなされるからです)、そのほか肝心の yahoo などには設定がありません。
キーワード抽出は piwik/core/UrlHelper.php 中の extractSearchEngineInformationFromUrl で行っているのですが、文字コードの指定がないと、何も処理しません。この場合、MySQL の検索キーワード格納カラムが UTF-8 なので、結果的に UTF-8 として扱われます。
参考 SearchEngines.php について:
検索エンジンは、ウェブサイトのリファラーとしてカウントされます。 Piwik に検索エンジンを追加する方法は?
A search engine is counted as a website referer. How can I add the search engine to Piwik?
まず検索エンジンの定義ですが、従来と違い
piwik/vendor/piwik/searchengine-and-social-list/SearchEngines.yml で yml ファイル管理に大きく変更されています。文字コードは、yml ファイルの charsets 以下で複数定義可能で、並び順に文字コードを推測しますが、Piwik 2.16.2 では、Shift_JIS と EUC-JP も受け付ける検索エンジンにおいても何も定義がされていないので piwik-japan-2.16.2.patch で charsets を追加しています(Piwik > 2.16.2 で本家にマージされることが決まっています)。 以下は search.yahoo.co.jp の例です。また日本以外の例えばロシアの検索エンジンなどは、 charsets を追加していませんが、文字コードの指定がない場合は search.yahoo.co.jp の定義で、検索文字コードを推測します。判定できなければ最初に定義されている UTF-8 を採用します。
Yahoo! Japan: - urls: - search.yahoo.co.jp params: - p - vp backlink: 'search?p={k}' charsets: - utf-8 - euc-jp - ms932
キーワード抽出は piwik/plugins/Referrers/SearchEngine.php 中の extractInformationFromUrl で行っているのですが、文字コードの指定がないと、何も処理しません。この場合、MySQL の検索キーワード格納カラムが UTF-8 なので、結果的に UTF-8 として扱われます。
サイト内検索設定は、システムの構成→ウェブサイト→Tracking Internal Site Search です。さらに各サイトごとに、 "サイト内検索" の項目で設定できます。これで自サイトの検索エンジンの検索キーワードを抽出でき、 "サイト検索ウィジット" で結果を見ることができます。
しかしながら、サイト内検索は、 SearchEngines.php のように文字コードの指定がなく、MySQL のサイト内検索キーワード格納カラムが UTF-8 なので、結果的に UTF-8 として扱われます。 最近は UTF-8 でサイト作るので問題ないのねと思われるかもしれませんが、CMS によっては裏でスマホページを UTF-8 出力、携帯ページを Shift_JIS 出力なんてこともできるので、そうとも限りません。
2.10.0 でさすがに、自サイトの検索で UTF-8 以外の文字列がきた場合に上記の TRADITIONAL 時にデータベースエラー回避の手段が何もないのはまずいとと思ったのか、自サイト検索 文字列全体 が UTF-8 か否かを判定し、UTF-8 以外だと空白文字列にしてしまうというなんともやっつけな変更が加えられています。iconv で ignore 設定をかけて、なるべく拾ってみるという丁寧さもございません。
このような仕様は 邪魔なだけ です。 piwik-japan-2.10.0.patch 以降では以前と同様、 UTF-8、EUC-JP、MS932 の順(ただし、指定がないとき)で文字コードを特定させます。
サイト内検索は、 SearchEngines.php のように文字コードの指定がなく、Controller::sanitizeString で UTF-8 でハードコーディングされています。 外部検索とは違い柔軟性はありません。
関数は次の順序でよばれます: ActionSiteSearch::shouldHandle $request->getParam('url') -> detectSiteSearch -> detectSiteSearchFromUrl
また、$request->getParam('url') は次の順序でよばれます: Controller::getParam -> Common::getRequestVar -> sanitizeInputValues -> sanitizeString
sanitizeString にはこのようなコメントがあるが、urldecode されてない前提でこのあと urldecodeValidUtf8 を使って urldecode される場合がある。
private static function sanitizeString($value) { // $_GET and $_REQUEST already urldecode()'d
getParam は UTF-8 前提で作っているんだけれども、 ActionSiteSearch::detectSiteSearchFromUrl 中に
// decode values if they were sent from a client using another charset $pageEncoding = $this->request->getParam('cs'); PageUrl::reencodeParameters($parameters, $pageEncoding);
としてある箇所がある。 parameter を全部 cs の文字コードから utf8 にエンコードしなおす関数になっているが getParam が UTF-8 ハードコーディングなので cs が必要になる前に文字化け。
Piwik 2.16.0 で本家にマージされました。 キーワードは、MySQL で varchar(255) として扱われています。MySQL の自動変換をにお断りしてもクラッシュしないように制限を加えているのでしょうが、 MySQL はバイトではなくて文字数です。つまり、255 文字までです。
tracker から送られてくる title 文字列は Web サイトがどんな文字コードであろうと UTF-8 で送られてくるように実装されているようです。しかし中国経由でこられたときに、title 文字列が UTF-8 ... なのですが、さまざまな Proxy を介するうちに UTF-8 → Big5 → UTF-8 と変換され UTF-8 の 4 バイト(U+10000)に文字化けすることがあるようです、確認できた事象では途中から文字化けしていました。 MySQL の UTF-8 は 4 バイト以上の UTF-8 を受け付けないらしく、そのような UTF-8 文字列が来ると、上記に記述した通り MySQL のデフォルトの仕様ではカラムに入るように自動変換されますが、文字化けはします(まあこの場合はどのみち最初から文字化けですけど)。また、これも上記のとおり、MySQL にこのような文字列をエラーとして受け付けない設定としている場合は、Internal Server Error として終了します。
Piwik 2.16.0 で本家にマージされました。 該当カラムは piwik_log_visit の referer_name で varchar(70) として扱われています。MySQL の自動変換をにお断りしてもクラッシュしないように制限を加えているのでしょうが、 MySQL はバイトではなくて文字数です。つまり、70 文字までです。