downsample for mp3s

06 March 2007


mm, we use lame to resample/downsample mp3 under linux. (like convert 256 kbps to 128 kbps )
first use MP3::Info to get $bitrate = $info->{BITRATE}.
then use $s = "lame -b 128 $orig_file $tmp_file && mv -f $tmp_file $orig_file && chmod 0777 $orig_file"; for $bitrate > 128
then system($s);

pretty simple but useful.

Catalyst::Plugin::Session::Store::Memcached hack

27 February 2007


Catalyst::Plugin::Session::Store::Memcached is much faster than DBIC. but that's not so fit our demand.
we have one function called "Ban a user", we remove the session of that user when he is banned. but Memcached Store don't have user_id field as key.

Cache::Memcached::Managed has one function named "group". so I hack that pm to support delete_session_data_by_user_id.

first when new Cache::Memcached::Managed we add:
        my $storage = $cfg->{memcached_obj} || Cache::Memcached::Managed->new(
data => "localhost:11211",
namespace => "catalyst_session",
group_names => [qw(user_id)],
%{ $cfg->{memcached_new_args} || {} },
),
so that we can set user_id when set a memcache key.
    $c->_session_memcached_storage->set(
@{ $c->_session_memcached_arg_fudge },
(
$key =~ /^(?:expires|session|flash)/
? ( expiration => $c->session_expires )
: ()
),
id => $key,
value => $data,
user_id => $user_id,
)
at end, delete_session_data_by_user_id is pretty simple.
sub delete_session_data_by_user_id {
my ( $c, $user_id ) = @_;

return unless ($user_id > 0);
$c->_session_memcached_storage->delete_group( user_id => $user_id );
}

have fun!

Cache::Memcached::Managed

27 February 2007


Cache::Memcached::Managed supports ->delete_group. so if u are not satisfied with Cache::Memcached, u may want to have a look at that. :)

Married

26 February 2007


I'm married from now on. :)

my first Catalyst Action

17 December 2006


Catalyst::Action 是 Catalyst 里的另一种代码复用技术。

我写的一个功能是记录一些 path 信息:比如 get, post, 还有页面载入的时长。
这个页面载入的时长是在 begin 时用 Time::HiRes 记录一个 gettimeofday, 然
后在 end 结束后再用 tv_interval 来获取时长。
“记录 path 信息”要写的地方在 return 之前。比如有 $c->res->body 或
$c->res->location 的时候直接返回了,否则在 $c->view 后返回。这是常见的一
个 sub end 的写法。
如果不用 Catalyst::Action 的话,可以有一些弊端如,sub end 里要写两次(两
个 return 之前),还有如果有很多个 end 代码就可能会写到很多地方。
第二个好处是 Catalyst::Action 所谓的真正的复用。只要是 sub end 在后面加
上 :ActionClass 就会复用之个 Action 的代码。
第一个好处只是 NEXT 所带来的。

可能的代码:
Before:
# Root.pm
sub begin : Private { my ($self, $c) = @_; $c->stash->{start_t0} =
[gettimeofday]; }
sub end : Private { my ($self, $c) = @_;
if ($c->res->body || $c->res->location) {
$c->model('Log')->log_path($c, tv_interval(
$c->stash->{start_t0}, [gettimeofday] ) ); # log path
return;
}
# code here
$c->forward($c->view('TT'));
$c->model('Log')->log_path($c, tv_interval( $c->stash->{start_t0},
[gettimeofday] ) ); # log path
}
如果有其他 pm 的 sub end 覆盖了 Root.pm 的 end 的话,那还要在那个
sub end 里加上 log_path.

而 Catalyst::Action 的复用会很方便:
After:
package Catalyst::Action::PathLogger;

use strict;use warnings;
use base 'Catalyst::Action';
use Time::HiRes qw( gettimeofday tv_interval );

sub execute {
my $self = shift;
my ( $controller, $c ) = @_;

$self->NEXT::execute( @_ );

$c->model('Log')->log_path($c, tv_interval( $c->stash->{start_t0},
[gettimeofday] ) );
}
而 Root.pm 的 sub end 将不在用 :Private 而是 sub end :
ActionClass('PathLogger') 其他 pm 如果有 sub end 也可以这么写。

quite easy and reusable. have fun! :)

easy example for Catalyst::Plugin::Captcha

16 December 2006


Catalyst::Plugin::Captcha 在 CPAN 的文档不是很明了。我在 Foorum 中用了一下。把经过简单的写一下。

功能要求是“密码错误”的登录次数超过三次以后就显示出验证码。这样可以防止 script 暴力破解 user 密码。把登录错误次数可以放到 session 里,但是 script 可以通过删除 cookie 来伪造 sessionid, 所以我就把登录错误次数放到了 memcached 里。

首先当然是 cpan 安装模块,然后在 yml 中配置:
captcha:
session_name: captcha_string
new:
width: 80
height: 30
lines: 1
gd_font: giant
create:
- normal
- rect
particle:
- 100
out:
force: jpeg
然后弄一个 captcha 的 Global 函数。
sub captcha : Global {
my ($self, $c) = @_;
$c->create_captcha();
}
create_captcha 返回的是一个 img 的 source, 也就是验证码那个图片的内容。
所以如果你要显示出验证码来的话,代码大致上是这样的:
<input type='text' name='captcha' size='12' /><img src='/captcha' />
img 的地址就是刚才的 Global 所弄的函数。插件将这个图片实际上的字符串内容放到了当前的 session 里。
$c->session->{ $c->config->{captcha}->{session_name} } = $random_string;
然后它提供的 validate_captcha method 就是比较 user 输入的东西跟这个 session 的内容。看看源代码就觉得非常清晰。
我最后的 Logon.pm
还是自己点过去看看吧。:)

Autocompleter.Local

14 December 2006


I'm pretty happy with scriptaculous. Ajax.Autocompleter works fine expect a bit slow than I thought.
so sometimes u may want that acts much faster. In that situation, I bet u can have a try of Autocompleter.Local

Autocompleter.Local is somehow the same as Ajax.Autocompleter but the third param is an array ref instead of a remote url.

for more details, please check:
http://wiki.script.aculo.us/scriptaculous/show/Autocompleter.Local

memcached in Win32

08 December 2006


http://jehiah.cz/projects/memcached-win32/

works fine in my WinXP, and with great Cache::Memcached in CPAN.


Perl Advent

01 December 2006



learning non-stop

17 November 2006


mm, busy with my work. but I still need to learn a lot.
scheduler:
Haskell and Perl 6
Catalyst Chained, Action, COMPONENT
DBIx-Class Relationship and other stuff.
Locale::Maketext for multi-language

somehow I want to write a Plugin for Catalyst to set priority for Regex. u know I hate the url mapping of Regex these days.

bye