中里情報ソースに困る
巨人に移籍してしまったため現在まったく情報源がなくこまっている。巨人のサイトとかチェックしてねー。
たこthon
というのに参加してきた。
tomyhero さんの家なのでどんだけ奇天烈な家なんだろうと思ってワクワクして言ったら予想に反してまともな家でした。でもものすごく遠い。
たこ焼き食べたり鯛焼き食べたりタコライスたべたりしてあとはハックしたりゲームしたり漫画読んだりする会らしい。
予想に反して集中できたので
- オレオレlighttpdモジュールを本番投入したり
- 前から作ろうと思ってたiPhoneアプリをガリガリ実装したり
した。iPhoneアプリはほしい機能全部はつけてないけどとりあえずそれ削れば公開はできそうだったので公開してから帰るかとおもってリリース作業してたら最後の最後で謎エラーで手間取りだめだった。今日の夜にでもアップしよう。
たこ焼き器とPS3欲しくなった。
Kindleもちょっとだけ欲しくなった。
mod_accessvalve
lighttpd で一定時間におけるアクセス数をもとにアクセスを制限したいという用件があったのですが、それにマッチする良いモジュールがなかったので試しに書いてみた。
設定項目は
accessvalve.bucket-size
:reset-interval
の時間内に許可するリクエスト数accessvalve.reset-interval
: リクエスト数カウントをリセットする時間(秒) (デフォルト 60)accessvalve.ban-duration
: リクエスト数がbucket-size
を超えた場合にアクセスを拒否する時間(秒)(デフォルト 900)
という感じで。また bucket-size
を指定しない、もしくは 0
に設定するとそのブロックではこの機能は無効になる。
このようなアクセス制限をあえて HTTPD でやる利点としては、Virtual Hostごとに設定を変えたり、特定のパスだけ制限したりと言うことができると言うことかなぁ。あとは 503 エラーとかかえせたりとかか。その分無駄なループが発生するのでオーバーヘッドになる。
最初 lighttpd のサイトを検索すると mod_throttle
というのを誰かが書いているのが見つかってそれを使おうとしたのだけど、設定ファイルの patch 処理がされてなく、上記のような設定ファイルの場所によって設定を変えるということができなかったので採用を見送った。
また、単純なコネクションごとの帯域制限やコネクション数制限は lighttpd に付属の mod_evasive でできる。
なぜか X 関係でビルドできないとき
lighttpd 1.4.24 以降や現在の SVN head で autogen.sh
を走らせてからビルドしようとするとなぜか X 関係のエラーが出て make
が失敗するということがありますがそういうときは、
cp `which libtool` .
とかすると make
とおるようになります。それ以上追ってないけど。なんでだろ?
リニューアル
clmemo を開始してから4年ほど、ずっと変えていなかったサイトをサーバーが死亡したのを機にリニューアル。
今年初めに作った nim をつかって全部静的ファイルな構成にしてみる。制限のきついレンタルサーバーならともかく、僕の環境ではまったく意味がない。最初は typester.github.com
とかでやろうとおもったけど、その後移転したくなったときリダイレクトとかできないのはいやなのでやめた。
でも自鯖はめんどくさいので prgmr.com 借りた。なかなか良い。
nim なら clmemo 以外にもコンテンツを扱えるのでぼちぼち増やしていく予定。とりあえずブログかなぁ。
しかしやっぱりサイトをいじるのは楽しい。最近はブログサービスなどが普及してきてこういうことをやる人が少なくなってしまったけどもったいないなーとおもう。
AnyEventでirssiプラグインを書く
AnyEvent はその名の通りさまざまなイベントインタフェースに対応していて、その中に irssi が使用している Glib も含まれているため、irssiのプラグインの中で普通に AnyEvent を使用することができます。
キーワード反応を im.kayac.com で自分の IM に通知する higlith2im.pl プラグインを AnyEvent を使用するように書き換えたのが以下です。
use strict;
use warnings;
use Glib;
use Irssi;
use AnyEvent::HTTP;
use HTTP::Request::Common;
our $VERSION = '0.1';
our %IRSSI = (
name => 'hilight2im',
description => 'notify hilight message to IM via im.kayac.com api',
authors => 'Daisuke Murase',
);
sub sig_printtext {
my ($dest, $text, $stripped) = @_;
if ( $dest->{level} & MSGLEVEL_HILIGHT ) {
my $user = Irssi::settings_get_str('im_kayac_com_username') or return;
my $msg = sprintf('[irssi] %s', $stripped);
my $req = POST "http://im.kayac.com/api/post/$user", [ message => $msg ];
my %headers = map { $_ => $req->header($_), } $req->headers->header_field_names;
my $r;
$r = http_post $req->uri, $req->content, headers => \%headers, sub { undef $r };
}
}
Irssi::signal_add('print text' => \&sig_printtext);
Irssi::settings_add_str('im_kayac_com', 'im_kayac_com_username', '');
fork する必要がなくなってシンプルですね!
...とおもいきや現状の AnyEvent::HTTP はなんと HTTP::Request オブジェクトからのリクエスト送信に対応していないため、自分ですべてのリクエストを組み立てる必要があるようです。これは不便。。
ですが、irssi の中で普通に AnyEvent を使うことができるのはなかなか便利です。お試しあれ!
AnyEvent 版は github にあげた。
AnyEventの良いところを3行で
教えて!と言われたのでそのとき答えた物をここにも記す。
- POE みたいにきもくない
- Danga::Socket とかだと自分で実装しないといけないread queueとかそういうのも面倒見てくれる便利モジュールがある>AnyEvent::Handle
- ドキュメントがアツイ
最後のは主に AnyEvent::Intro のことを言ってますが、これ一通り読めばとりあえず AnyEvent 使えるようになるっていうくらい完璧な内容となっています。
AnyEventとは何かからはじまり、非同期プログラミングの説明からAnyEventを使用したシンプルな例が続き、AnyEvent::Socket や AnyEvent::Handle を使用するのを順々に詳しく説明してくれています。 どうして AnyEvent::Handle みたいな物を使うといいのかというところまで書かれているので、非同期プログラミングやネットワークプログラミングにあまり詳しくない人でも読めるのではないでしょうか。
AnyEvent で $poe_kernel->alias_set 的なことをする方法
最近 AnyEvent にはまっています。おもしろい!
AnyEvent と同じ非同期プログラミングフレームワークであるところの POE では
$kernel->alias_set('hoge');
などとしておくと
$kernel->post( hoge => 'state' );
みたいな感じでどこからでもそのコンポーネントを呼び出すことができました。 しかし AnyEvent ではそう言った機能がないため以下のように Object::Container を使って解決することにしました。
呼び出される側:
use AnyEvent;
use Object::Container 'event';
my $cv = AnyEvent->condvar;
$cv->cb(sub {
my (@args) = $cv->recv;
# ここになんか処理
});
event->register( foo => sub { $cv } );
呼び出す側:
use AnyEvent;
use Object::Container 'event';
event('foo')->send(@args);
Condvarをグローバルなシングルトンコンテナに入れ、それを使って相互にやりとりをするという感じですね。
Object::Container は export する機能がなかったのですが、毎回 Object::Container->get(...)
などとかくのがだるかったので import に引数渡すとその名前でコンテナを export する機能をつけました。(0.2以降)
同等のことはいろいろな方法があると思いますが、これが一応今の所の僕の解となってます。参考までに!
さっきのパッチ取り込んでもらった
なんと jesse のプロジェクトだったらしい。パッケージ名でなんか見たことあるなーって思ってたんだけど、気がつかなかったなぁ。世間せまい!
コミット権もらったのでこれからもなんかあったら貢献しよう。
k9mailを日本語環境でただしく使えるようにした
GDP1 で android のメールアプリが Connection error
と言うエラーで新しいメールをまったく受信してくれない状態になってしまった。GDDフォンだとこの問題はいまのところ出たことはない。
昔、 brad のブログで k9mail というのを見たのを思い出したのでそれを入れてみたのだが、ヘッダーのエンコード処理がされておらず日本語の件名などをつかうと化け化けになってしまう。
機能的には k9mail のほうが優れていて、このエンコード問題さえ解決できれば使えそうだなーと思ったのでいっちょパッチを書いてみた。
diff --git a/src/com/android/email/mail/internet/MimeHeader.java b/src/com/android/email/mail/internet/MimeHeader.java
index 24aad4d..a117e08 100644
--- a/src/com/android/email/mail/internet/MimeHeader.java
+++ b/src/com/android/email/mail/internet/MimeHeader.java
@@ -11,6 +11,7 @@ import java.util.List;
import com.android.email.Email;
import com.android.email.Utility;
import com.android.email.mail.MessagingException;
+import org.apache.james.mime4j.codec.EncoderUtil;
public class MimeHeader {
/**
@@ -97,12 +98,35 @@ public class MimeHeader {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out), 1024);
for (Field field : mFields) {
if (!Utility.arrayContains(writeOmitFields, field.name)) {
- writer.write(field.name + ": " + field.value + "\r\n");
+ String v = field.value;
+
+ if (hasToBeEncoded(v)) {
+ v = EncoderUtil.encodeEncodedWord(
+ field.value,
+ EncoderUtil.Usage.WORD_ENTITY
+ );
+ }
+
+ writer.write(field.name + ": " + v + "\r\n");
}
}
writer.flush();
}
+ // encode non printable characters except LF/CR codes.
+ public boolean hasToBeEncoded(String text) {
+ for (int i = 0; i < text.length(); i++) {
+ char c = text.charAt(i);
+ if (c < 0x20 || 0x7e < c) { // non printable
+ if (c != 0x0a && c != 0x0d) { // non LF/CR
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
class Field {
String name;
github にもあげた。
この実装がただしいかどうかはわからないけど、これで一応ちゃんとエンコードされるようになる。
ところで、おもしろいのがこのパッチは com.android. なパッケージを編集してしまっていると言うこと。 なんと k9mail は com.android.* のパッケージも含んでいるのである。android のメール機能を持ってきて再利用している。 これはアプリごとにVMが別れてるandroidだからできることなのかなぁとか思ったりした。
エンコードされないとかどう見てもバグなので issue 登録しておいた。パッチは採用されないと思うけどw android のメールではこの問題はおこらないということは com.android.* なところはいじらなくても実現可能ということなので。