<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>Craftworks Tech Blog</title>
	<atom:link href="http://www.craft-works.co.jp/blog/feed" rel="self" type="application/rss+xml" />
	<link>http://www.craft-works.co.jp/blog</link>
	<description>━ 【名】 職人芸｛しょくにんげい｝</description>
	<pubDate>Mon, 02 Mar 2009 04:49:53 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.5</generator>
	<language>ja</language>
			<item>
		<title>Catalyst でかんたんログインを実装する</title>
		<link>http://www.craft-works.co.jp/blog/archives/259</link>
		<comments>http://www.craft-works.co.jp/blog/archives/259#comments</comments>
		<pubDate>Fri, 27 Feb 2009 12:13:07 +0000</pubDate>
		<dc:creator>isam</dc:creator>
		
		<category><![CDATA[howto]]></category>

		<category><![CDATA[Catalyst]]></category>

		<category><![CDATA[Mobile]]></category>

		<guid isPermaLink="false">http://www.craft-works.co.jp/blog/?p=259</guid>
		<description><![CDATA[前回の、Catalyst でオートログインとブラウザを閉じるまで有効な Cookie を共存の続きです。
mixi などで実装されている、携帯端末固有情報や契約者識別情報を利用した、「かんたんログイン」を実装する方法を紹介します。

まずは、ユーザー情報のテーブルに uid を格納するカラムを用意します。Schema も変更するのを忘れずに。
ユーザーがログインした後のページで、かんたんログインの設定をするページを作ります。


package MyApp::Controller::User;

sub uid_update : Path(&#039;uid/update&#039;) {
    my ( $self, $c ) = @_;
    $c-&#62;user-&#62;mobile_uid($c-&#62;req-&#62;mobile_agent-&#62;user_id());
    $c-&#62;user-&#62;mobile_agent($c-&#62;req-&#62;user_agent());
    $c-&#62;user-&#62;update();
}

sub uid_delete : Path(&#039;uid/delete&#039;) {
    my ( $self, $c ) = @_;
    $c-&#62;user-&#62;mobile_uid(undef);
   [...]]]></description>
			<content:encoded><![CDATA[<p>前回の、<a href="http://www.craft-works.co.jp/blog/archives/233">Catalyst でオートログインとブラウザを閉じるまで有効な Cookie を共存</a>の続きです。</p>
<p>mixi などで実装されている、携帯端末固有情報や契約者識別情報を利用した、「かんたんログイン」を実装する方法を紹介します。</p>
<p><span id="more-259"></span></p>
<p>まずは、ユーザー情報のテーブルに uid を格納するカラムを用意します。Schema も変更するのを忘れずに。</p>
<p>ユーザーがログインした後のページで、かんたんログインの設定をするページを作ります。</p>
<pre name="code" class="perl">

package MyApp::Controller::User;

sub uid_update : Path(&#039;uid/update&#039;) {
    my ( $self, $c ) = @_;
    $c-&gt;user-&gt;mobile_uid($c-&gt;req-&gt;mobile_agent-&gt;user_id());
    $c-&gt;user-&gt;mobile_agent($c-&gt;req-&gt;user_agent());
    $c-&gt;user-&gt;update();
}

sub uid_delete : Path(&#039;uid/delete&#039;) {
    my ( $self, $c ) = @_;
    $c-&gt;user-&gt;mobile_uid(undef);
    $c-&gt;user-&gt;mobile_agent(undef);
    $c-&gt;user-&gt;update();
}
</pre>
<p>$c->authenticate() に渡す認証情報の振り分けを追加します。</p>
<pre name="code" class="perl">

sub auth_info {
    my ( $self, $c ) = @_;
    my (%userinfo, $realms);
    # かんたんログイン
    if ($c-&gt;req-&gt;param(&#039;easylogin&#039;) &amp;&amp; !$c-&gt;req-&gt;mobile_agent-&gt;is_non_mobile) {
        %userinfo = (
            &#039;mobile_uid&#039;   =&gt; $c-&gt;req-&gt;mobile_agent-&gt;user_id(),
            &#039;mobile_agent&#039; =&gt; $c-&gt;req-&gt;user_agent()
        );
        $realms = &#039;users_mobile&#039;;
    }
    # パスワードログイン
    else {
        $c-&gt;form(
            user =&gt; [ qw/NOT_BLANK/ ],
            pass =&gt; [ qw/NOT_BLANK ASCII/, [qw/LENGTH 4 32/] ],
        );
        %userinfo = (
            user =&gt; $c-&gt;req-&gt;param(&#039;user&#039;),
            pass =&gt; $c-&gt;req-&gt;param(&#039;pass&#039;),
        );
        $realms = &#039;users&#039;;
    }
    return (\%userinfo, $realms);
}
</pre>
<p>実際の認証するところはこんな感じです。</p>
<pre name="code" class="perl">

    my @auth_info = $self-&gt;auth_info($c);
    return if $c-&gt;form-&gt;has_error();

    if (!$c-&gt;authenticate(@auth_info)) {
        $c-&gt;set_invalid_form(&#039;login&#039; =&gt; &#039;LOGIN&#039;);
        return;
    }
</pre>
<p><a href="http://search.cpan.org/~bobtfish/Catalyst-Plugin-Authentication-0.10010/lib/Catalyst/Authentication/Credential/Password.pm">Catalyst::Authentication::Credential::Password</a> は、デフォルトだと当たり前ですがパスワード認証しようとするので、password_field で指定したデータを渡さないと check_password() に怒られます。</p>
<pre><code>password_type
    This sets the password type.  Often passwords are stored in crypted or hashed formats.
    In order for the password module to verify the plaintext password passed in, it must
    be told what format the password will be in when it is retreived from the user object.
    The supported options are:

    none    No password check is done. An attempt is made to retrieve the user based on
            the information provided in the $c->authenticate() call. If a user is found,
            authentication is considered to be successful.</code></pre>
<p>ですので、以下のように password_type を none にして回避します。</p>
<pre name="code" class="perl">

authentication:
    default_realm: &#039;users&#039;
    realms:
        users:
            credential:
                class: &#039;Password&#039;
                password_field: &#039;passwd&#039;
                password_type: &#039;hashed&#039;
                password_hash_type: &#039;MD5&#039;
            store:
                class: &#039;DBIx::Class&#039;
                user_class: &#039;DBIC::User&#039;
                id_field: &#039;user&#039;
        users_mobile:
            credential:
                class: &#039;Password&#039;
                password_type: &#039;none&#039;
            store:
                class: &#039;DBIx::Class&#039;
                user_class: &#039;DBIC::User&#039;
                id_field: &#039;user&#039;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.craft-works.co.jp/blog/archives/259/feed</wfw:commentRss>
		</item>
		<item>
		<title>Catalyst でオートログインとブラウザを閉じるまで有効な Cookie を共存させる</title>
		<link>http://www.craft-works.co.jp/blog/archives/233</link>
		<comments>http://www.craft-works.co.jp/blog/archives/233#comments</comments>
		<pubDate>Tue, 24 Feb 2009 07:51:40 +0000</pubDate>
		<dc:creator>isam</dc:creator>
		
		<category><![CDATA[howto]]></category>

		<category><![CDATA[Catalyst]]></category>

		<category><![CDATA[cookie]]></category>

		<category><![CDATA[session]]></category>

		<guid isPermaLink="false">http://www.craft-works.co.jp/blog/?p=233</guid>
		<description><![CDATA[Catalyst::Plugin::Session では、デフォルトではセッションの有効期限は $c-&#62;config-&#62;{&#8217;session&#8217;}{&#8217;expires&#8217 [...]]]></description>
			<content:encoded><![CDATA[<p>Catalyst::Plugin::Session では、デフォルトではセッションの有効期限は $c-&gt;config-&gt;{&#8217;session&#8217;}{&#8217;expires&#8217;} の値に固定です。</p>
<p>ですので、「次回からログインを省略する」のようなオートログイン機能を実装するには、セッションの expires を動的に変更する必要があります。</p>
<p><span id="more-233"></span></p>
<p>これは、<a href="http://blog.hide-k.net/archives/2006/08/cpsessiondynami.php">C::P::Session::DynamicExpiryを使ってremember me</a>に紹介されている、<a href="http://search.cpan.org/%7Enuffin/Catalyst-Plugin-Session-DynamicExpiry/">Catalyst::Plugin::Session::DynamicExpiry</a> を使えば可能で、セッションと Cookie と両方の有効期限を変更してくれるので、</p>
<ol>
<li>オートログイン無効の場合、ログイン状態は一定時間、ブラウザを閉じてもログイン維持</li>
<li>オートログイン有効の場合、ログイン状態は半永久的、ブラウザを閉じてもログイン維持</li>
</ol>
<p>という仕様が実現できます。しかし、大抵のサイトでは、ログインセッションの要求仕様は以下になると思います。</p>
<ol>
<li>オートログインを無効の場合、ログイン状態はブラウザを閉じない限り継続</li>
<li>オートログインを有効の場合、ログイン状態は永久的、ブラウザを閉じてもログイン維持</li>
</ol>
<p>この要求を実現するには、セッションの有効期限の変更だけでなく、Cookie の有効期限の動的変更も必要になってきます。</p>
<p>これを、以下のように実装しました。</p>
<p>まずは、Catalyst::Plugin::Session::State::Cookie を継承して calculate_session_cookie_expires() をオーバーライドします。</p>
<p>lib/MyApp/WUI/Plugin/Session/State/Cookie.pm</p>
<pre name="code" class="perl">

package MyApp::WUI::Plugin::Session::State::Cookie;

use strict;
use warnings;
use parent &#039;Catalyst::Plugin::Session::State::Cookie&#039;;

sub calculate_session_cookie_expires {
    my $c = shift;
    if (defined(my $ttl = $c-&gt;session_time_to_live)) {
        $c-&gt;log-&gt;debug(&quot;Overridden session cookie time to live: $ttl&quot;);
        return time + $ttl;
    }
    return $c-&gt;config-&gt;{&#039;session&#039;}{&#039;cookie_expres&#039;};
}

1;
</pre>
<p>これを、プラグインとして読み込みます。</p>
<p>lib/MyApp/WUI.pm</p>
<pre name="code" class="perl">

use Catalyst qw/
    Session::DynamicExpiry
    Session
    Session::Store::DBIC
    +MyApp::WUI::Plugin::Session::State::Cookie
    Session::State::URI
/;
</pre>
<p>あとは、オートログインのパラメーターに応じて、Catalyst::Plugin::Session::DynamicExpiry の session_time_to_live() を呼んであげます。</p>
<p>lib/MyApp/WUI/Controller/Login.pm</p>
<pre name="code" class="perl">

if ($c-&gt;req-&gt;param(&#039;autologin&#039;)) {
    $c-&gt;session-&gt;{&#039;autologin&#039;} = 1;
    $c-&gt;session_time_to_live(2_592_000);
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.craft-works.co.jp/blog/archives/233/feed</wfw:commentRss>
		</item>
		<item>
		<title>ming で生成した swf で TextField の文字列が表示されない</title>
		<link>http://www.craft-works.co.jp/blog/archives/230</link>
		<comments>http://www.craft-works.co.jp/blog/archives/230#comments</comments>
		<pubDate>Mon, 23 Feb 2009 06:31:56 +0000</pubDate>
		<dc:creator>isam</dc:creator>
		
		<category><![CDATA[tips]]></category>

		<category><![CDATA[flash lite]]></category>

		<category><![CDATA[ming]]></category>

		<category><![CDATA[swf]]></category>

		<guid isPermaLink="false">http://www.craft-works.co.jp/blog/?p=230</guid>
		<description><![CDATA[ming で生成した Flash Lite 1.1 の swf である条件下で TextField に addString() した文字列が、DoCoMo の端末で表示できない場合があります。
画面サイズが、240px  [...]]]></description>
			<content:encoded><![CDATA[<p>ming で生成した Flash Lite 1.1 の swf である条件下で TextField に addString() した文字列が、DoCoMo の端末で表示できない場合があります。</p>
<p>画面サイズが、240px * 240px の端末に、</p>
<pre><code>$movie->setDimension(240, 240);</code></pre>
<p>とすると、上記の問題が発生します。</p>
<p>これを回避するには、</p>
<pre><code>$movie->setDimension(240 - 1, 240 - 1);</code></pre>
<p>とすると、表示されるようになります。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.craft-works.co.jp/blog/archives/230/feed</wfw:commentRss>
		</item>
		<item>
		<title>C::P::Session::State::URI で HTML::Entities に日本語をエスケープさせない方法</title>
		<link>http://www.craft-works.co.jp/blog/archives/226</link>
		<comments>http://www.craft-works.co.jp/blog/archives/226#comments</comments>
		<pubDate>Sun, 22 Feb 2009 10:12:16 +0000</pubDate>
		<dc:creator>isam</dc:creator>
		
		<category><![CDATA[tips]]></category>

		<category><![CDATA[Catalyst]]></category>

		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://www.craft-works.co.jp/blog/?p=226</guid>
		<description><![CDATA[Catalyst - Session管理とHTMLエンティティコード（数値文字実体参照） でも言及されているように、Catalyst::Plugin::Session::State::URI を使っていると、
&#60;i [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://lab.z-nix.jp/mt/archives/2006/10/catalyst_sessio_1.html">Catalyst - Session管理とHTMLエンティティコード（数値文字実体参照）</a> でも言及されているように、<a href="http://search.cpan.org/~bobtfish/Catalyst-Plugin-Session-State-URI-0.08/lib/Catalyst/Plugin/Session/State/URI.pm">Catalyst::Plugin::Session::State::URI</a> を使っていると、</p>
<pre><code>&lt;img alt="日本語" /&gt;</code></pre>
<p>などが、エスケープされてしまい、表示がおかしくなったりします。</p>
<p><span id="more-226"></span></p>
<p>これは、<a href="http://search.cpan.org/~ovid/HTML-TokeParser-Simple-3.15/lib/HTML/TokeParser/Simple/Token/Tag/Start.pm">HTML::TokeParser::Simple::Token::Tag::Start</a> が悪さをしているのですが、 HTML::TokeParse::Simple::Token::Tag::Start が呼んでいる HTML::Entities::encode_entities() の第二引数を設定できれば、この問題は回避できるのですが、HTML::TokeParser::Simple::Token::Tag::Start::rewrite_tag() を redefine しないとそれはできません。</p>
<p>しかし、それもコードが冗長になるので、以下の方法で対応しました。</p>
<p>MyApp.pm</p>
<pre><code>%HTML::Entities::char2entity = (
    '&amp;' =&gt; '&amp;amp;' ,  # ampersand
    '&gt;' =&gt; '&amp;gt;'  ,  # greater than
    '&lt;' =&gt; '&amp;lt;'  ,  # less than
    '"' =&gt; '&amp;quot;',  # double quote
);</code></pre>
<p>他にも、<a href="http://blog.nyarla.net/2007/07/13/1">HTML::Entitesで非ASCII文字を数字文字参照にしない方法</a> のように、HTML::Entities::num_entity() を redifine するという方法もあります。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.craft-works.co.jp/blog/archives/226/feed</wfw:commentRss>
		</item>
		<item>
		<title>for で変換 vs ダンプした文字列を変換して eval</title>
		<link>http://www.craft-works.co.jp/blog/archives/220</link>
		<comments>http://www.craft-works.co.jp/blog/archives/220#comments</comments>
		<pubDate>Mon, 16 Feb 2009 04:57:04 +0000</pubDate>
		<dc:creator>isam</dc:creator>
		
		<category><![CDATA[info]]></category>

		<category><![CDATA[Perl]]></category>

		<category><![CDATA[benchmark]]></category>

		<guid isPermaLink="false">http://www.craft-works.co.jp/blog/?p=220</guid>
		<description><![CDATA[ふと、for で回してパラメーターの個数分変換するのと、Data::Dumper でダンプして1回だけ変換して eval するのとどっちが速いのか気になってベンチマーク取ってみました。
コードと結果は以下。

#!/usr/bin/perl
use strict;
use warnings;
use Benchmark ':all';
use Encode qw(encode decode);
use Data::Dumper;

$Data::Dumper::Terse = 1;

our $params = {
    user => 'ユーザー',
    pass => 'password',
    text => 'フォームパラメーターの変換テストです
             for でひとつずつ処理する方法と
      [...]]]></description>
			<content:encoded><![CDATA[<p>ふと、for で回してパラメーターの個数分変換するのと、Data::Dumper でダンプして1回だけ変換して eval するのとどっちが速いのか気になってベンチマーク取ってみました。</p>
<p>コードと結果は以下。</p>
<p><span id="more-220"></span></p>
<pre><code>#!/usr/bin/perl
use strict;
use warnings;
use Benchmark ':all';
use Encode qw(encode decode);
use Data::Dumper;

$Data::Dumper::Terse = 1;

our $params = {
    user => 'ユーザー',
    pass => 'password',
    text => 'フォームパラメーターの変換テストです
             for でひとつずつ処理する方法と
             Data::Dumper と eval で一度に処理する方法と
             どちらが速いかテストします',
    jobs => [ qw(foo bar baz) ],
};

cmpthese(timethese(1_000_000, {
    'loop' => sub {
        my $params = $params;
        for my $value (values %$params) {
            next if (ref $value &#038;&#038; ref $value ne 'ARRAY');
            for my $v (ref($value) ? @$value : $value) {
                $v = encode('euc-jp', decode('utf8', $v));
            }
        }
    },
    'dumper' => sub {
        my $params = $params;
        $params = eval encode('euc-jp', decode('utf8', Dumper $params));
    },
}));</code></pre>
<p>結果はこちら。eval 入るからかやはり for の方が速かったです。YAML の loader() &#038; dumper() も試しましたが、そっちはこの二つと比べ物にならない遅さでした。</p>
<pre><code>Benchmark: timing 1000000 iterations of dumper, loop...
    dumper: 235 wallclock secs (233.67 usr +  0.18 sys = 233.85 CPU) @ 4276.25/s (n=1000000)
      loop: 154 wallclock secs (153.00 usr +  0.03 sys = 153.03 CPU) @ 6534.67/s (n=1000000)
         Rate dumper   loop
dumper 4276/s     --   -35%
loop   6535/s    53%     --
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.craft-works.co.jp/blog/archives/220/feed</wfw:commentRss>
		</item>
		<item>
		<title>Catalyst::Plugin::FillInForm::ForceUTF8 で fill_password などのオプションが渡せない</title>
		<link>http://www.craft-works.co.jp/blog/archives/216</link>
		<comments>http://www.craft-works.co.jp/blog/archives/216#comments</comments>
		<pubDate>Sun, 08 Feb 2009 06:01:07 +0000</pubDate>
		<dc:creator>isam</dc:creator>
		
		<category><![CDATA[review]]></category>

		<category><![CDATA[Catalyst]]></category>

		<category><![CDATA[Perl]]></category>

		<category><![CDATA[cpan]]></category>

		<category><![CDATA[patch]]></category>

		<guid isPermaLink="false">http://www.craft-works.co.jp/blog/?p=216</guid>
		<description><![CDATA[Catalyst::Plugin::FillInForm::ForceUTF8 に抜けがあったのでパッチ書きました。
--- lib/Catalyst/Plugin/FillInForm/ForceUTF8.pm.orig    2009-02-08 14:39:24.000000000 +0900
+++ lib/Catalyst/Plugin/FillInForm/ForceUTF8.pm 2009-02-08 14:40:02.000000000 +0900
@@ -115,11 +115,13 @@
 sub fillform {
     my $c = shift;
     my $fdat = shift &#124;&#124; $c->request->parameters;
+    my $additional_params = shift;

     $c->response->output(
       [...]]]></description>
			<content:encoded><![CDATA[<p>Catalyst::Plugin::FillInForm::ForceUTF8 に抜けがあったのでパッチ書きました。</p>
<pre><code>--- lib/Catalyst/Plugin/FillInForm/ForceUTF8.pm.orig    2009-02-08 14:39:24.000000000 +0900
+++ lib/Catalyst/Plugin/FillInForm/ForceUTF8.pm 2009-02-08 14:40:02.000000000 +0900
@@ -115,11 +115,13 @@
 sub fillform {
     my $c = shift;
     my $fdat = shift || $c->request->parameters;
+    my $additional_params = shift;

     $c->response->output(
         HTML::FillInForm::ForceUTF8->new->fill(
             scalarref => \$c->response->{body},
-            fdat      => $fdat
+            fdat      => $fdat,
+            %$additional_params,
         )
     );
 }</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.craft-works.co.jp/blog/archives/216/feed</wfw:commentRss>
		</item>
		<item>
		<title>greylist のブラックリストの IP アドレスを CIDR で記述できるパッチ</title>
		<link>http://www.craft-works.co.jp/blog/archives/207</link>
		<comments>http://www.craft-works.co.jp/blog/archives/207#comments</comments>
		<pubDate>Thu, 05 Feb 2009 14:00:15 +0000</pubDate>
		<dc:creator>isam</dc:creator>
		
		<category><![CDATA[release]]></category>

		<category><![CDATA[qmail]]></category>

		<category><![CDATA[spam]]></category>

		<guid isPermaLink="false">http://www.craft-works.co.jp/blog/?p=207</guid>
		<description><![CDATA[最近また SPAM が増加傾向にあるので、ブラックリストをもっと細かく指定できるようにパッチを書きました。
Jon Atkins 氏の qgreylist に、S25R と tarpit 機能を付け、ブラックリスト、ホワ [...]]]></description>
			<content:encoded><![CDATA[<p>最近また SPAM が増加傾向にあるので、ブラックリストをもっと細かく指定できるようにパッチを書きました。</p>
<p>Jon Atkins 氏の <a href="http://www.jonatkins.com/page/software/qgreylist">qgreylist</a> に、S25R と tarpit 機能を付け、ブラックリスト、ホワイトリストに指定するホスト名を正規表現で指定できるようにした、ちっち氏の <a href="http://chiji.atnifty.com/tools/s25rtarpit_before_qgreylist/s25rtarpit_before_qgreylist.html">S25R + tarpit before qgreylist パッチ</a> に、さらに CIDR 表記で指定できるようにしたパッチです。</p>
<p>greylist のデフォルトの blacklist の指定の仕方ですと、192.168.0.80 ～ 192.168.0.96 を拒否したかったら、192.168.0 と、256 アドレス巻き込んで拒否するか、16 ファイル個別に羅列して拒否するしかなかったので、アドレス範囲で拒否できれば便利だなと思い作成しました。</p>
<p><a href="http://www.craft-works.co.jp/pub/patch/qgreylist-0.3_cidrsyntax-0.1.patch">qgreylist-0.3_cidrsyntax-0.1.patch</a><br />
<span id="more-207"></span></p>
<h3>導入方法</h3>
<per><code>cd /tmp/<br />
wget http://www.jonatkins.com/qgreylist/qgreylist-0.3.tar.gz<br />
wget http://chiji.atnifty.com/tools/s25rtarpit_before_qgreylist/s25rtarpit_before_qgreylist0.3-0.3.tar.gz<br />
wget http://www.craft-works.co.jp/pub/patch/qgreylist-0.3_cidrsyntax-0.1.patch<br />
cd /usr/local/src<br />
tar xvfz /tmp/qgreylist-0.3.tar.gz<br />
tar xvfz /tmp/s25rtarpit_before_qgreylist0.3-0.3.tar.gz<br />
cd s25rtarpit_before_qgreylist0.3-0.3<br />
./setup.sh<br />
cd ../qgreylist<br />
patch < ../s25rtarpit_before_qgreylist0.3-0.3/qgreylist-0.3_s25rtarpitbefore-0.3.patch<br />
patch -p1 < /tmp/qgreylist-0.3_cidrsyntax-0.1.patch<br />
chown root.qmail greylist<br />
cp -a greylist /var/qmail/bin/<br />
touch /var/qmail/blacklist_cidr<br />
touch /var/qmail/whitelist_cidr<br />
</code></pre>
<h3>使用方法</h3>
<per><code>$ cat /var/qmail/blacklist_cidr<br />
# foo<br />
192.168.0.0/24<br />
192.168.32.0/23    # comment<br />
192.168.32.128/25</code></pre>
<p>CIDR 表記で拒否したいアドレスを1行ずつ書いてください。192.168/24 など、省略はできません。空行は無視されます。# 以降はコメントとみなされます。</p>
<p>qgreylist をくぐり抜けてきた SPAM の配信元のアドレス範囲の割り出しには ipcount が便利です。</p>
<p>ipcount は CPAN モジュールの Net::IP をインストールすると、一緒にインストールされます。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.craft-works.co.jp/blog/archives/207/feed</wfw:commentRss>
		</item>
		<item>
		<title>HTML-lint に User-Agent 切り替え機能を追加</title>
		<link>http://www.craft-works.co.jp/blog/archives/202</link>
		<comments>http://www.craft-works.co.jp/blog/archives/202#comments</comments>
		<pubDate>Tue, 03 Feb 2009 19:41:32 +0000</pubDate>
		<dc:creator>isam</dc:creator>
		
		<category><![CDATA[release]]></category>

		<category><![CDATA[html]]></category>

		<category><![CDATA[htmllint]]></category>

		<category><![CDATA[lint]]></category>

		<category><![CDATA[patch]]></category>

		<category><![CDATA[xhtml]]></category>

		<guid isPermaLink="false">http://www.craft-works.co.jp/blog/?p=202</guid>
		<description><![CDATA[HTML-lint は便利ですが、デフォルトでは ”Another_HTML-lint/1.22 +libwww-perl/5.820” という User-Agent を固定で吐いているので、モバイル対応サイトなど、Us [...]]]></description>
			<content:encoded><![CDATA[<p>HTML-lint は便利ですが、デフォルトでは ”Another_HTML-lint/1.22 +libwww-perl/5.820” という User-Agent を固定で吐いているので、モバイル対応サイトなど、User-Agent によって表示を切り替えているサイトでは、URL によるチェックができず、Data エリアに HTML ソースをコピペしてチェックするしか方法がありません。</p>
<p>そこで、いちいちそれをしていては面倒臭いので User-Agent を任意に切り替える機能を付けました。</p>
<p><a href="http://www.craft-works.co.jp/pub/patch/htmllint-user_agent_switch.patch">HTML-lint User-Agent 切り替えパッチ</a></p>
<p><span id="more-202"></span></p>
<pre><code>cd htmllint/
patch -p1 < htmllint-user_agent_switch.patch</code></pre>
<p>パッチを適用すると、このようなインターフェイスになります。<br />
<div id="attachment_203" class="wp-caption alignnone" style="width: 310px"><a href="http://www.craft-works.co.jp/blog/wp-content/uploads/2009/02/lint.png"><img src="http://www.craft-works.co.jp/blog/wp-content/uploads/2009/02/lint-300x168.png" alt="HTML-lint User-Agent Switch Patch" title="HTML-lint User-Agent Switch Patch" width="300" height="168" class="size-medium wp-image-203" /></a><p class="wp-caption-text">HTML-lint User-Agent Switch Patch</p></div></p>
]]></content:encoded>
			<wfw:commentRss>http://www.craft-works.co.jp/blog/archives/202/feed</wfw:commentRss>
		</item>
		<item>
		<title>HTML::MobileJpCSS レビュー</title>
		<link>http://www.craft-works.co.jp/blog/archives/184</link>
		<comments>http://www.craft-works.co.jp/blog/archives/184#comments</comments>
		<pubDate>Mon, 02 Feb 2009 04:02:26 +0000</pubDate>
		<dc:creator>isam</dc:creator>
		
		<category><![CDATA[review]]></category>

		<category><![CDATA[Mobile]]></category>

		<category><![CDATA[Perl]]></category>

		<category><![CDATA[cpan]]></category>

		<category><![CDATA[css]]></category>

		<guid isPermaLink="false">http://www.craft-works.co.jp/blog/?p=184</guid>
		<description><![CDATA[携帯サイトの CSS 対応は、今まで HTML::DoCoMoCSS を使用していましたが、01/15 に HTML::MobileJpCSS がリリースされていたので試してみました。
どういうことをしてくれるモジュール [...]]]></description>
			<content:encoded><![CDATA[<p class="title">携帯サイトの CSS 対応は、今まで <a href="http://search.cpan.org/~tokuhirom/HTML-DoCoMoCSS-0.01/lib/HTML/DoCoMoCSS.pm" target="_blank">HTML::DoCoMoCSS</a> を使用していましたが、01/15 に <a href="http://search.cpan.org/~komoriya/HTML-MobileJpCSS-0.01/lib/HTML/MobileJpCSS.pm" target="_blank">HTML::MobileJpCSS </a>がリリースされていたので試してみました。</p>
<p class="title">どういうことをしてくれるモジュールかと言うと、例えば hr タグは色を付けたいときに、キャリアによって下記のようにスタイルの指定が違います。</p>
<pre><code>DoCoMo   &lt;hr style="border-color:#FF0000;" /&gt;
au       &lt;hr style="color:#FF0000;" /&gt;
SoftBank &lt;hr style="border-color:#FF0000;" /&gt;</code></pre>
<p>これを、ひとつの指定でモジュール側で 3 キャリア分の指定方法の振り分けを自動でやってくれるというものです。</p>
<p class="title"><a name="1232011108" href="http://d.hatena.ne.jp/komoriya/20090115/1232011108">3キャリア対応のCSS変換モジュール<span class="highlight">HTML::MobileJpCSS</span></a><span class="hatena-star-comment-container"><img class="hatena-star-comment-button" style="border: medium none ; margin: 0pt; padding: 0pt; cursor: pointer; vertical-align: middle; display: none;" title="Comments" src="http://s.hatena.ne.jp/images/comment_dg.gif" alt="Comments" /></span></p>
<p><span id="more-184"></span></p>
<p>こんな感じで CSS を指定して、</p>
<pre><code>hr {
    margin: 2px 0;
    padding: 0;
    border: 0 solid #FFF;
    width: 100%;
    height: 1px;
}

*.red    { color: #FF0000; }
*.green  { color: #00FF00; }
*.blue   { color: #0000FF; }
</code></pre>
<p>テンプレート側でこんな感じにして hr 毎に色を変えられることができます。</p>
<pre><code>&lt;hr class="green" /&gt;</code></pre>
<p>早速使ってみたのですが、hr の色指定は border-color じゃなくて、background-color でやりたかったので、new() のオプションで変換ルールのマッピングを上書きできると pod に書いてありましたが、バージョン 0.01 の現時点では実装がありませんでしたので以下のように修正しました。pod の style_map のコード例も誤字でキーが style になっていますので注意。</p>
<pre><code>--- lib/HTML/MobileJpCSS.pm     2009-01-15 14:50:46.000000000 +0900
+++ /usr/lib/perl5/site_perl/5.8.8/HTML/MobileJpCSS.pm  2009-02-02 09:47:49.000000000 +0900
@@ -137,4 +137,7 @@
         $self-&gt;{agent} = HTTP::MobileAgent-&gt;new();
     }
+    if ($self-&gt;{style_map}) {
+        $StyleMap = { %$StyleMap, %{$self-&gt;{style_map}} };
+    }
 }</code></pre>
<p>また、CSS で全てのタグに適用されるクラス指定をするときにいつも下記のように書いているのですが、</p>
<pre><code>*.red { color: #FF0000; }</code></pre>
<p>変換が行われませんでしたので、下記のように修正しました。</p>
<pre><code>--- lib/HTML/MobileJpCSS.pm     2009-01-15 14:50:46.000000000 +0900
+++ /usr/lib/perl5/site_perl/5.8.8/HTML/MobileJpCSS.pm  2009-02-02 10:17:53.000000000 +0900
@@ -76,5 +76,5 @@
                 $style-&gt;{id}-&gt;{$2}    = $css-&gt;{$1};
             }
-            elsif (/^(\.(.+))/) {
+            elsif (/^(\*?\.(.+))/) {
                 $style-&gt;{class}-&gt;{$2} = $css-&gt;{$1};
             }

</code></pre>
<p>あと、問題点としましては、下記のような複数 class 指定に対応していないのと、</p>
<pre><code>&lt;hr class="green fs10" /&gt;</code></pre>
<p>下記の形式でしか CSS ファイルに記述できず、</p>
<pre><code>hr { ... }
#id { ... }
.class { ... }</code></pre>
<p>下記のような形式が使えないと言ったところでしょうか。</p>
<pre><code>hr.class { ... }
div.foo a.bar { ... }
</code></pre>
<p>この HTML::MobileJpCSS で不可能なことは、HTML::DoCoMoCSS で可能なので、当面は 3 キャリア共通の CSS に共通設定を記述して、それを DoCoMo のみ、HTML::DoCoMoCSS でインライン展開し、au と SoftBank は端末判別して外部 CSS を読み込ませて、記述方法の差異を吸収するというのがベストプラクティスな気がします。</p>
<p>HTML::MobileJpCSS には、今後のバージョンアップでの対応に期待です。</p>
<p>正規表現でのパースだけでなく、オプションで HTML::DoCoMoCSS と同様に XML::LibXML を使用できるようになってくれれば言うことなしですね。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.craft-works.co.jp/blog/archives/184/feed</wfw:commentRss>
		</item>
		<item>
		<title>Linux に ming ライブラリ + Perl SWF モジュールのインストール</title>
		<link>http://www.craft-works.co.jp/blog/archives/175</link>
		<comments>http://www.craft-works.co.jp/blog/archives/175#comments</comments>
		<pubDate>Mon, 26 Jan 2009 04:53:02 +0000</pubDate>
		<dc:creator>isam</dc:creator>
		
		<category><![CDATA[install]]></category>

		<category><![CDATA[Linux]]></category>

		<category><![CDATA[Perl]]></category>

		<category><![CDATA[flash]]></category>

		<category><![CDATA[ming]]></category>

		<guid isPermaLink="false">http://www.craft-works.co.jp/blog/?p=175</guid>
		<description><![CDATA[Fedra Core 5 に libming をインストールする方法です。
現時点での最新版、ming 0.4.0-rc2 をダウンロードします。

pushd ~/archive/
wget -nv -nc http: [...]]]></description>
			<content:encoded><![CDATA[<p>Fedra Core 5 に <a href="http://www.libming.org/">libming</a> をインストールする方法です。</p>
<p>現時点での最新版、<a href="http://sourceforge.net/project/showfiles.php?group_id=18365&#038;package_id=187304&#038;release_id=627077">ming 0.4.0-rc2</a> をダウンロードします。<br />
<span id="more-175"></span></p>
<pre><code>pushd ~/archive/
wget -nv -nc http://jaist.dl.sourceforge.net/sourceforge/ming/ming-0.4.2.tar.bz2
cd /usr/local/src/
tar xfj ~/archive/ming-0.4.2.tar.bz2
cd ming-0.4.2/
./configure --enable-perl
make
make install</code></pre>
<p>以上です。</p>
<p>perl の SWF モジュールは上記で一緒にインストールされます。</p>
<p>もし、configure 中に、</p>
<pre><code>To compile ming please install bison:
 as .deb user: sudo apt-get install bison
configure: error: Could not detect yacc/bison!</code></pre>
<p>と言われたら、yum install bison で bison をインストールします。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.craft-works.co.jp/blog/archives/175/feed</wfw:commentRss>
		</item>
	</channel>
</rss>
