DOMDocument->loadHTML()でパースすると文字化けする
大体HTMLに原因があるのでそこを見ればよい。
- 原因1: CP932なのにmeta charset=Shift_JISになっている
- 原因2: meta charsetは正しいが、それより前にマルチバイト文字がある
- 原因3: そもそもmeta charsetがない
ブラウザが「いい感じ」に処理してくれるのもダメHTMLがいまだに駆逐されない原因の一つじゃないだろうか。
正しく処理するには、HTMLの頭に正しいmeta charset指定を補うのが一番速いだろうと思う。
ただ(3)のmeta charsetがない場合、mb_detect_encoding()
で見当をつけるにも言語を絞り込まないと限界があるので、結構難しい。
ちなみにコンストラクタで文字コードを指定できるが、HTML処理では全く使われない。
$doc = new DOMDocument(null, 'UTF-8');
$doc->loadHTMLFile()
の場合PHPはlibxmlの htmlCreateFileParserCtxt()
にエンコーディングを渡しておらず、$doc->loadHTML()
の場合 htmlCreateMemoryParserCtxt()
にはエンコーディングを指定できないようになっている。
$doc->saveHTML() で出力する
パースしたHTMLを変形して出力することもあると思うが、libxml2 2.9.8 時点では <meta charset="...">
で指定していると保存するべきエンコーディングを発見できず、出力がHTMLエンティティだらけになる。
そのため<meta http-equiv="Content-Type" content="text/html; charset=...">
で指定する必要がある。
そもそもHTML4のパースと言っているので、HTML5の記法には対応していないということだろうか。読み込みでは認識しているようにも見えるが深く追っていない。
RawGitからjsDelivrに移行した
今月末以後にサービス終了とのことなのでjsDelivrに移行した。
アナウンスから終了まで割と短いが、jsDelivrに専用のガイドページが用意されている。jsDelivrはRawGitのようにGitHubの参照もできるが、npmパッケージがある場合はそちらの方が利用率は高くなる傾向があるとか。
Subversion 1.10で認可され(authorize)ない
1.9から1.10にサーバをバージョンアップしたら問題が発生した。
svn up なり svn list なりを行うと、
svn: E175013: Access to '/path/to/hoge/trunk' forbidden
と出てアクセスできない。HTTP(S)経由なので、LogLevel debug
としてログを追ってみると最後に
Access denied: 'admin' OPTIONS hoge:/trunk
となっていて、認証(authentication)まではうまくいっている。
認可用ファイルは以下の通り
[/] admin = rw [hoge:/] user = rw
こうしておくと、今までは admin ユーザは全リポジトリにアクセスできていた。
どうも1.10から一番詳しく一致するレコードのみ見るようになった風に思える。確かにその方がより細かくアクセス制御はできるのだろうが、リリースノートには認可周りの修正と強化をしたとあるだけで、そのような非互換の変更があったとは書いていない(か、気付かなかった)。
対策1 新機能の :glob:を使う
[/]
を [:glob:/*]
としたらアクセスできるようになった。
より深いパスの指定が他にある場合は、それより優先させるために [:glob:/**]
とする必要があるはず。
一番単純で admin としての意図に近いのでこの方法にした。大量にファイルを舐める時にパフォーマンス的には悪いかもしれない。
CentOS 7でgeoipupdateが動かなくなった
GeoIP-update-1.5.0-11.el7 が4月からエラーを吐くようになった。
/etc/cron.weekly/geoipupdate: Received Error -21 (Sanity check database_info string failed) when attempting to update GeoIP Database Received Error -21 (Sanity check database_info string failed) when attempting to update GeoIP Database
サイトを確認してみると、ライセンス購入をしていないとLegacy Databaseは更新できなくなり、ダウンロードできるのも3月版のみ、しかも2019年1月2日からはウェブからも削除されるらしい。
GeoLite2は使える風なので、別途GeoIP2をインストールしてみる。
データベースのダウンロード
本来であればデータベースをダウンロードするのだが、後述の通り2019年12月下旬より直接のデータのダウンロードはできなくなった。geoipupdateというアップデータで全データをダウンロードすることになる。バージョン2系のアップデータは全データのダウンロードがとても遅かったが、現在のバージョンでは解消されている。
geoipupdate のインストール
更新のためgeoipupdateを入れる。
リリースページにバイナリリリースのtarballがあるのでこれを使用した。
rpmもあるが、これを入れるにはGeoIP1系を消しておく必要がある。
curl -O https://github.com/maxmind/geoipupdate/releases/download/v4.1.5/geoipupdate_4.1.5_linux_386.tar.gz tar xaf geoipupdate_4.1.5_linux_386.tar.gz cd geoipupdate_4.1.5_linux_386 mkdir -p /opt/geoip/{bin,etc} mv geoipupdate /opt/geoip/bin/ mv GeoIP.conf /opt/geoip/etc/
GeoIP.conf の DatabaseDirectory も設定する。
# The directory to store the database files. Defaults to /usr/local/share/GeoIP DatabaseDirectory /opt/geoip/share/GeoIP
geoipupdate をソースからビルドする場合
以下はソースからビルドする場合だが、バージョン2.5の時の例なので現在(4.1)とは手順が異なる可能性が高い。
sudo yum install libcurl-devel git clone --depth=1 https://github.com/maxmind/geoipupdate cd geoipupdate ./bootstrap ./configure --prefix=/opt/geoip make sudo make install
ASN databaseも更新するならばGeoIP.confのEditionIDsにGeoLite2-ASNを追加する必要がある。
ライセンスキーを取得する
2019年12月下旬より、カリフォルニアのプライバシー法(CCPA)準拠のために無料利用でもアカウントが必要になったらしい。
GeoIPの利用者もCCPAに準拠する必要があるが、その辺りはここでは割愛する。
更新をテストする
/opt/geoip/bin/geoipupdate -f /opt/geoip/etc/GeoIP.conf -v | less
rpmインストールや自前でビルドした場合など、デフォルトのパスを使っている場合は-fでconfファイルの場所を指定する必要はない。
ASN databaseは毎週火曜、他は毎月最初の火曜に更新されるらしい。
タイムゾーンが不明なので木曜頃に更新するようにcrontabに書いた。
23 9 1-8 * Thu /opt/geoip/bin/geoipupdate -f /opt/geoip/etc/GeoIP.conf
以上だが…
あとは各アプリケーションでGeoIPではなくGeoIP2を使うようにする必要があり、これが多いと面倒かもしれない。
またDBパスがデフォルトではないので /opt/geoip/share/GeoIP 以下をクライアントでも指定する必要がある。