まだ重たいCMSをお使いですか?
毎秒1000リクエスト を捌く超高速CMS「adiary

2010/08/18(水)Pure PerlでのOAuth実装メモ

adiaryに、twitter投稿のためのOAuthを実装したときのメモです。PurePerl動作。

OAuthモジュール(OAuth::Lite::Consumer)を使わずに実装したので、同じことをやりたい人には参考になるかと思います。*1

続きを読む

2010/08/12(木)Digest::SHA を使って HMAC-SHA1 を生成するPerlのコード

Digest::SHA ないしは Digest::SHA::PurePerl を使います。よって PurePerl でも動作します。

HMAC署名についてはwikipediaを参照

sub hmac_sha1 {
	# my $self = shift;
	my ($key, $msg) = @_;
	my $sha1;

	if ($Digest::SHA::PurePerl::VERSION) {
		$sha1 = Digest::SHA::PurePerl->new(1);
	} else {
		eval {
			require Digest::SHA;
			$sha1 = Digest::SHA->new;
		};
		if ($@) {
			require Digest::SHA::PurePerl;
			$sha1 = Digest::SHA::PurePerl->new(1);
		}
	}

	my $bs = 64;
	if (length($key) > $bs) {
		$key = $sha1->add($key)->digest;
		$sha1->reset;
	}
	my $k_opad = $key ^ ("\x5c" x $bs);
	my $k_ipad = $key ^ ("\x36" x $bs);
	$sha1->add($k_ipad);
	$sha1->add($msg);
	my $hk_ipad = $sha1->digest;
	$sha1->reset;
	$sha1->add($k_opad, $hk_ipad);

	my $b64d = $sha1->b64digest;
	$b64d = substr($b64d.'====', 0, ((length($b64d)+3)>>2)<<2);
	return $b64d;
}

最後に「====」を付けてやるのがポイントで、これがないとOAuthで盛大にコケます。

なおこのソースコードはPDS扱いとします。

2010/02/22(月)SpeedyCGI で ImageMagick が動かない

Webアプリ開発中に ImageMagick(perlmagick)が SpeedyCGI 環境でまともに動かない不具合に当たりました。

問題の詳細

  • Image::Magick をロードして何かしら処理を行うルーチンを SpeedyCGI で実行する時、2回目以降のキャッシュされた状態で不具合が起こる*1
  • 問題確認環境
    • Perl 5.8.8 + SpeedyCGI 2.22
    • ImageMagick 6.3.7 および 6.5.9

この問題は FastCGI や mod_perl2 では起きません。

*1 : スクリプトの処理が停止してしまう。もしくは処理中のまま返ってこなくなる

問題の症状

スクリプト

#!/usr/bin/speedy

use Image::Magick();

print "Content-Type: text/plain\n\n";
print "Image::Magick Version $Image::Magick::VERSION \n";
my $image = Image::Magick->new;
$image->Read( 'x.png' );

実行結果。

~$ test.pl
Image::Magick Version 6.3.7
~$ test.pl
Segmentation fault
~$ test.pl
Image::Magick Version 6.5.9
~$ test.pl
Segmentation fault

問題の原因

不明。

問題の解決法 2014/08/18

#!/usr/bin/speedy

delete $INC{'Image/Magick.pm'};
require Image::Magick;

print "Content-Type: text/plain\n\n";
print "Image::Magick Version $Image::Magick::VERSION \n";
my $image = Image::Magick->new;
$image->Read( 'x.png' );

requireで毎回確実にロードさせる細工をすることで問題は起こらなくなりました。Image::Magickモジュールがキャッシュされませんが、evalを飛び越えてSpeedyCGIごと落ちるよりはマシということで……。

まとめ

gccの(ライブラリlibgomp )バグのようです。gcc 4.3より前のVersion(4.2以下)で、amd64環境の時起こる模様。

gcc 4.4でも起きたので関係ないようです。4年経っても解決されてないとは思わなかった(汗)

メモ

256色png(8bitカラーパレット)で保存する方法。

$image->Read( 'x.png' );
$image->Resize(width=>133, height=>100);
$image->Quantize(colorspace=>'RGB',colors=>256);
$image->Set(depth => 8); 
$image->Write( 'y.png' );

2010/01/09(土)Perl/UTF8, 日本語「全角」→「半角」変換ルーチン

よくネットショップ等で買い物をすると

郵便番号は半角で入力してください。

とか言われてウザくないですか? こういうのを解消するためのルーチンです。

条件

  • Perl 5.8以降
  • 利用可能文字列はutf-8のみ(そうでない場合はutf8に変換して渡してください)
  • WTFPL(PDS扱いでも可)。

ソースは必ずutf-8で保存してください。

日本語に混ざる全角英数等を半角にする

use utf8;
use Encode ();
sub utf8_zen2han {
	my $str = shift;
	my $flag = utf8::is_utf8($str);
	Encode::_utf8_on($str);

	$str =~ tr/ !”#$%&’()*+,-./0-9:;<=>?@A-Z[¥]^_`a-z{|}/ -}/;

	if (!$flag) { Encode::_utf8_off($str); }
	return $str;
}

実行例。

(変換前)abcdefgさささ110-2244あいう##$”
(変換後)abcdefgさささ110-2244あいう##$"

半角カタカナを全角カタカナにする

use utf8;
use Encode ();

my %hankana_map = (
'ガ'=>'ガ','ギ'=>'ギ','グ'=>'グ','ゲ'=>'ゲ','ゴ'=>'ゴ',
'ザ'=>'ザ','ジ'=>'ジ','ズ'=>'ズ','ゼ'=>'ゼ','ゾ'=>'ゾ',
'ダ'=>'ダ','ヂ'=>'ヂ','ヅ'=>'ヅ','デ'=>'デ','ド'=>'ド',
'バ'=>'バ','ビ'=>'ビ','ブ'=>'ブ','ベ'=>'ベ','ボ'=>'ボ',
'パ'=>'パ','ピ'=>'ピ','プ'=>'プ','ペ'=>'ペ','ポ'=>'ポ',
'ヴ'=>'ヴ');

sub utf8_hankana2zen {
	my $str = shift;

	my $flag = utf8::is_utf8($$str);
	Encode::_utf8_on($$str);

	$str =~ s/(ガ|ギ|グ|ゲ|ゴ|ザ|ジ|ズ|ゼ|ゾ|ダ|ヂ|ヅ|デ|ド|バ|ビ|ブ|ベ|ボ|パ|ピ|プ|ペ|ポ|ヴ)/$hankana_map{$1}/g;
	$str =~ tr/。-゚/。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゛゜/;

	if (!$flag) { Encode::_utf8_off($str); }
	return $str;
}

Encode::JP::H2Z

今更使いませんが、EUC-JPの場合は標準モジュールでもできます。逆変換は Encode::JP::H2Z::z2h()。

use Encode ();
use Encode::JP::H2Z ();

sub eucjp_hankana2zen {
	my $str = shift;
	Encode::JP::H2Z::h2z(\$str);
	return $str;
}

その他

バグ等あったらコメントください。