最近 search.cpan.org で POD 中のコードに syntax highlight できるようになりました。

使い方
ページ最下部右側にこのようなcolor schemeを選ぶオプションがあるので、リストの中から自分好みのものを選ぶと良いでしょう。
おすすめは "cpan" らしいです。

参考
http://blogs.perl.org/users/mark_a_stratman/2011/03/syntax-highlighting-for-searchcpanorg.html
最近 search.cpan.org で POD 中のコードに syntax highlight できるようになりました。

ページ最下部右側にこのようなcolor schemeを選ぶオプションがあるので、リストの中から自分好みのものを選ぶと良いでしょう。
おすすめは "cpan" らしいです。

http://blogs.perl.org/users/mark_a_stratman/2011/03/syntax-highlighting-for-searchcpanorg.html
I'm using weechat on remote server's screen.
The big problem is I can't perceive chatting on IRC without "polling" terminal by myself. Because I have no way to get alert over screen and ssh.
I was thinking to solve this problem and just found the solution.
The flow is:
tail -f $HOME/.weechat/logs/*/*/*.weechatlog
You may have to rewrite ssh options and path to the log. Be careful with `'` (single quotation mark) to guaranteeing the home dir path is interpolated with remote's.
ssh example.com tail -n 1 -f '$HOME/.weechat/logs/*/*/*.weechatlog' | perl irc_growl.pl &
You can rewrite system()'s args as you want. `man growlnotify` will help you.
while (<STDIN>) {
chomp;
next unless $_;
next if /^==>/; # ignore tail's output
my $attr = parse($_);
if ($attr->{type} =~ /(:?NOTICE|PRIVMSG)/) {
system("growlnotify", "-m", $attr->{content}, "-t", $attr->{user}, "--appIcon", "LimeChat");
}
}
sub parse {
my ($line) = @_;
my ($time, $cmd, @contents) = split /\t/, $line;
my $content = join "\t", @contents;
my $user;
if (not $cmd) { # critical error
$cmd = 'ERROR';
} elsif ($cmd eq '-->') { # join
$cmd = 'JOIN';
} elsif ($cmd eq '<--') { # part
$cmd = 'PART';
} elsif ($cmd eq '--') { # messages from server
$cmd = 'SERVER';
} elsif ($cmd eq '*') { # notice
$user = $cmd;
$cmd = 'NOTICE';
} else { # privmsg
$user = $cmd;
$cmd = 'PRIVMSG';
}
return +{
type => $cmd,
time => $time,
content => $content,
user => $user,
};
}
./irc_growl.sh
Mac に戻ってくるのはもう6~7年ぶりなのか、当時は Intel Mac なんて無くて PowerPC でした。全体的な UI は昔からさほど変わった感じはしないですね。
さっそく環境を整えていたら github から持ってきたモジュールのテストがコケる。
こんな感じのテストを使っていたんですが、 spell は OSX には無いらしく、今まで Linux でしか作業してなかったのでだいぶ嵌りました。
use Test::More;
eval q{ use Test::Spelling };
plan skip_all => "Test::Spelling is not installed." if $@;
add_stopwords(map { split /[\s\:\-]/ } <DATA>);
$ENV{LANG} = 'C';
all_pod_files_spelling_ok('lib');
__DATA__
spell がないと怒られます。
sh: spell: command not found
はてどうしたものかと CPAN モジュールを漁って見ると、各々思い思いの方法で podspell.t を書いているようでした。
そこで参考にしたのは、いろいろな環境の開発者がいて xt/ が多く走っていそうな Plack のテストを参考にしてみました。aspell が存在する場合には aspell を使い、ない場合には spell を使う方法が良さそうです。
use Test::More;
eval q{ use Test::Spelling };
plan skip_all => "Test::Spelling is not installed." if $@;
add_stopwords(map { split /[\s\:\-]+/ } <DATA>);
$ENV{LANG} = 'C';
set_spell_cmd("aspell -l en list") if `which aspell`;
all_pod_files_spelling_ok('lib');
__DATA__
// ==UserScript==
// @name Google Reader with InstaReader
// @namespace http://linknode.net
// @description Open feed item with InstaReader in background by pressing 'v'
// @include http*://www.google.com/reader/view/*
// ==/UserScript==
document.addEventListener('keypress', function(event) {
if(event.which == 118) { // 118 is 'v'
if (document.getElementById('current-entry') == null) return; // no current entry
var link = document.getElementById('current-entry').getElementsByTagName('a').item(0).getAttribute('href');
var url = 'http://www.instapaper.com/text?u=' + encodeURIComponent(link);
event.stopPropagation();
event.preventDefault();
GM_openInTab(url);
}
}, true);
ヘルプフォーラムから2chまで探してようやく解決したので2011年1月14日現在のメモ
http://help.ocn.ne.jp/ols/mail/10002_m_infochk.html の表記通りに従っても、smtp.vc*.ocn.ne.jp はTLS対応してないようなので延々と下のエラーメッセージが表示される。
Remote server does not support TLS code(500)
この項目は一見すると昔からのユーザは使えない様に見えるが、この通り設定することで受信できる。なんだそれ。
| 送信メールサーバ(SMTP) | smtp.ocn.ne.jp |
| ポート番号 | 465 |
| SSL | 利用する |
| 認証 | 使用する |
| アカウント名(ユーザ名) | メールアドレスをすべて入力 |
| パスワード | メールパスワードを入力 |
Twitter のアイコンには主に gif / jpeg / png が使われており、 png を表示できないガラケーがある。
Cache::Memcached::Fast でキャッシュしつつ、 Imager では一時ファイルを作らず。思っていたよりも楽にかけた
use LWP::UserAgent;
use Imager;
use Cache::Memcached::Fast;
use Plack::Request;
use Plack::Builder;
my $memd = Cache::Memcached::Fast->new({
...
});
builder {
mount '/tw_thumbnail' => sub {
my $env = shift;
my $req = Plack::Request->new($env);
if ($req->param("url") =~ m{^(http://a\d\.twimg\.com/.+)}) {
my $url = $1;
if (my $result = $memd->get($url)) {
return [200, ['Content-Type' => 'image/jpeg'], [$result]];
} else {
my $img = LWP::UserAgent->new->get($url)->decoded_content;
my $image = Imager->new;
$image->read(data => $img)
or return [500, [], [$image->errstr]];
$image->write(data => \my $out, jpegquality => 30, type => 'jpeg')
or return [500, [], [$image->errstr]];
$memd->set($url, $out, 1 * 60 * 60 * 24);
return [200, ['Content-Type' => 'image/jpeg'], [$out]];
}
} else {
return [404, [], ['Not Found']];
}
};
};
XSS や事前に取得したセッションを利用者に送り込んで権限を昇格させる類の攻撃で、セッションIDをクエリに含ませたり、シーケンシャルなセッションIDを用いるような愚かなことをしなければ基本的に問題はないものの、 Session Fixation への根本的な対策として、ログイン成功後にこれまでのセッションを破棄し、新しいセッションを発行することが望ましい。
Session Fixation について詳しいことは IPA の出している『安全なウェブサイトの作り方(pdf)』改定第4版 p.15 から p.20 に説明があります。
今まで P::M::Session ではログイン成功後に新しくセッションを開始するのにちょっとした細工が必要でしたが、 0.13 からは古いセッションの破棄とあたらしいセッションの発行を、
$request->env->{'psgix.session.options'}->{change_id}++;
することで容易に行えるようになりました
@punytan you can use $req->session_options
Tatsuhiko Miyagawa (@miyagawa) December 22, 2010
$request->session_options->{change_id}++;
こちらの方がいいですね!
ログイン時にあたらしいセッションが発行されるかをチェックするために簡略化した検証用のコードを書いてみました。
/ -> /login -> / と遷移したときに、セッションが変わっていることがわかりますね!
use strict;
use warnings;
use Plack::Builder;
use Plack::Session 0.13;
use Plack::Session::Store::File;
use Plack::Session::State::Cookie;
my $app = sub {
my $env = shift;
my $request = Plack::Request->new($env);
my $body = q{
<html><head><title></title>
<script>document.write(document.cookie);</script>
</head><body></body></html>
};
if ($request->path_info eq '/') {
my $session = Plack::Session->new($request->env);
if ($session->get('verified')) {
my $res = $request->new_response(200);
$res->content_type('text/html');
$res->body($body, ' verified session');
$res->finalize;
} else {
my $res = $request->new_response(200);
$res->content_type('text/html');
$res->body($body, ' session is not verified');
$res->finalize;
}
} elsif ($request->path_info eq '/login') {
my $session = Plack::Session->new($request->env);
if ($request->param("password") eq 'foo') {
$request->session_options->{change_id}++;
# is equals to $request->env->{'psgix.session.options'}->{change_id}++;
$session->set('verified', 1);
my $res = $request->new_response(200);
$res->content_type('text/html');
$res->body($body, ' correct password');
$res->finalize;
} else {
my $res = $request->new_response(200);
$res->content_type('text/html');
$res->body($body, ' incorrect password');
$res->finalize;
}
} elsif ($request->path_info eq '/logout') {
my $session = Plack::Session->new($request->env);
$session->expire;
my $res = $request->new_response(200);
$res->content_type('text/html');
$res->body($body, ' logout');
$res->finalize;
} else {
my $res = $request->new_response(404);
$res->body("Not Found");
$res->finalize;
}
};
builder {
enable 'Session',
store => Plack::Session::Store::File->new(
dir => './sessions'
),
state => Plack::Session::State::Cookie->new(
session_key => 'sid'
);
$app;
};
とある環境で latin1 - latin1 の憎き動作をしていたので今後のために最小限のコードと設定をメモしておく
これ重要
[mysqld] character_set_server = utf8
mysql クライアントで status と SHOW VARIABLES LIKE 'char%'; を発行し、 mysqld_safe で指定した my.cnf の内容が適用されているか、次のような結果を得られるかを確認する。
Server characterset: utf8 Db characterset: utf8 Client characterset: utf8 Conn. characterset: utf8
+--------------------------+------------------------------------------------------------+ | Variable_name | Value | +--------------------------+------------------------------------------------------------+ | character_set_client | utf8 | | character_set_connection | utf8 | | character_set_database | utf8 | | character_set_filesystem | binary | | character_set_results | utf8 | | character_set_server | utf8 | | character_set_system | utf8 | | character_sets_dir | /usr/local/mysql-5.1.50-linux-i686-glibc23/share/charsets/ | +--------------------------+------------------------------------------------------------+
CREATE DATABASE enctest;
CREATE TABLE `utf8table` ( `title_utf8` VARCHAR(20) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8
DEFAULT CHARSET が utf8 になってるかを確認
SHOW CREATE TABLE utf8table;
テスト用なので最低限必要なオプションを DBI->connect() の \%attr にふたつ。
use strict;
use warnings;
use utf8;
use Encode;
use Data::Dumper;
use DBI;
my $dbh = DBI->connect('DBI:mysql:database=enctest;host=localhost', 'foo', 'bar',
{
mysql_enable_utf8 => 1,
on_connect_do => ['SET NAMES utf8'],
}
);
my $sth = $dbh->prepare(q{
INSERT INTO utf8table (title_utf8)
VALUES (?)
});
$sth->execute('いろは' . rand); # string
my $sth2 = $dbh->prepare(q{
SELECT * FROM utf8table
});
$sth2->execute;
my $rv = $sth2->fetchall_arrayref;
print Dumper $rv;
for (@$rv) {
print encode_utf8($_->[0]), $/;
}
$dbh->disconnect;
exit;
__END__
$VAR1 = [
[
"\x{3044}\x{308d}\x{306f}0.052142747285874"
],
[
"\x{3044}\x{308d}\x{306f}0.87866795396349"
],
[
"\x{3044}\x{308d}\x{306f}0.85588866665876"
],
[
"\x{3044}\x{308d}\x{306f}0.473092086686851"
]
];
いろは0.052142747285874
いろは0.87866795396349
いろは0.85588866665876
いろは0.473092086686851
めでたしめでたし。
http://search.cpan.org/~punytan/AnyEvent-Twitter-0.52/lib/AnyEvent/Twitter.pm を出しました。
AnyEvent::Twitter::Stream と同等の OAuth 引数を使えるようになりました
つまり、access_token と access_token_secret が token と token_secret として使えます。これに伴って、eg/gen_token.pl でも出力形式を選べるようになりました。
これまでは
my $ua = AnyEvent::Twitter->new(
consumer_key => 'consumer_key',
consumer_secret => 'consumer_secret',
access_token => 'access_token',
access_token_secret => 'access_token_secret',
);
のように書いていたものを
my $ua = AnyEvent::Twitter->new(
consumer_key => 'consumer_key',
consumer_secret => 'consumer_secret',
token => 'access_token',
token_secret => 'access_token_secret',
);
のようにかけるようになりました
これまでは request() メソッドのみ対応していましたが、今回の変更で get() と post() を追加しました。
$cv->begin;
$ua->request(
method => 'GET',
api => 'account/verify_credentials',
sub {
my ($hdr, $res, $reason) = @_;
say $res->{screen_name};
$cv->end;
}
);
のように書いていたものは、 0.52 からは
$cv->begin;
$ua->get('account/verify_credentials', sub {
my ($hdr, $res, $reason) = @_;
say $res->{screen_name};
$cv->end;
});
のようにかけるようになりました。
get() ではパラメータは省略可能です。
post() ではパラメータは省略不可です。パラメータ不要の場合は空の hashref を渡してください。
つぶやく場合は
$cv->begin;
$ua->post('statuses/update', {status => 'いろはにほへと ちりぬるを'}, sub {
my ($hdr, $res, $reason) = @_;
say $res->{user}{screen_name};
$cv->end;
});
のように、より短くかけるようになりました。
メソッド追加に伴ってテストを増やした(xt/05_get.t と xt/06_post.t あたり)
http://twitter.com/cpan_new ドキュメントへのリンクは FrePAN へ。
http://friendfeed.com/cpan からリアルタイムでデータを取ってくる。使ったモジュールはこれだけで、全体で60行弱。機能のわりに短くかけた。
use common::sense; use Data::Dumper; use AnyEvent::Twitter; use AnyEvent::FriendFeed::Realtime;
https://github.com/punytan/cpan_new