Changeset 24901 for lang

Show
Ignore:
Timestamp:
11/26/08 11:23:30 (4 years ago)
Author:
mattn
Message:

big merge from MENTA. X-(

Location:
lang/perl/MENTOS/trunk
Files:
2 added
12 modified

Legend:

Unmodified
Added
Removed
  • lang/perl/MENTOS/trunk/app/controller/edit.mt

    r24806 r24901  
    11? my ($entry, $message) = @_ 
    2 ?= render_partial('header.mt', config()->{application}->{title}) 
     2?= render('header.mt', config()->{application}->{title}) 
    33                        <div class="entry"> 
    44                                <span class="error"><?= $message ?></span> 
     
    2121                                </form> 
    2222                        </div> 
    23 ?= render_partial('footer.mt') 
     23?= render('footer.mt') 
  • lang/perl/MENTOS/trunk/app/controller/edit.pl

    r24303 r24901  
    11use MENTA; 
    2  
    3 load_plugin('blog'); 
    42 
    53sub do_edit { 
    64    my $id = param('id') || ''; 
    75    my $data_dir = data_dir; 
    8     my $static_dir = static_dir; 
     6    my $static_dir = docroot . '/static/'; 
    97    my $msg = ''; 
    108    my $entry = {}; 
     
    2624            } 
    2725            if ($entry->{description}) { 
    28                 write_file("${data_dir}/${id}.txt", $entry->{title}."\n".$entry->{description}); 
     26                blog_file_write("${data_dir}/${id}.txt", $entry->{title}."\n".$entry->{description}); 
    2927            } else { 
    3028                unlink("${data_dir}/${id}.txt"); 
     
    4038    } 
    4139 
    42     render('edit.mt', $entry, $msg); 
     40    render_and_print('edit.mt', $entry, $msg); 
    4341} 
  • lang/perl/MENTOS/trunk/app/controller/entries.mt

    r24806 r24901  
    11? my $entries = shift 
    2 ?= render_partial('header.mt', config()->{application}->{title}) 
     2?= render('header.mt', config()->{application}->{title}) 
    33                <div class="entries hfeed"> 
    44? for my $entry (@{$entries}) { 
     
    2626                <p align="right"><a href="edit">新規編集</a></p> 
    2727                <br /> 
    28 ?= render_partial('footer.mt') 
     28?= render('footer.mt') 
  • lang/perl/MENTOS/trunk/app/controller/entry.mt

    r24806 r24901  
    11? my $entry = shift 
    2 ?= render_partial('header.mt', config()->{application}->{title}) 
     2?= render('header.mt', config()->{application}->{title}) 
    33                        <div class="entry hentry"> 
    44                                <a class="entry-title" href="<?= docroot ?>?id=<?= $entry->{id} ?>"><?=r $entry->{title} ?></a><br /> 
     
    2020                        </div> 
    2121                        <p align="right"><a href="edit?id=<?= $entry->{id} ?>">編集</a></p> 
    22 ?= render_partial('footer.mt') 
     22?= render('footer.mt') 
  • lang/perl/MENTOS/trunk/app/controller/index.pl

    r24303 r24901  
    11use MENTA; 
    2  
    3 load_plugin('blog'); 
    42 
    53sub do_index { 
     
    86 
    97    if ($id =~ /^\d+$/) { 
    10         render('entry.mt', blog_read_entry("${data_dir}/${id}.txt")); 
     8        render_and_print('entry.mt', blog_read_entry("${data_dir}/${id}.txt")); 
    119    } else { 
    12         my @entries = sort {$b->{mtime} <=> $a->{mtime}} 
    13             map { blog_read_entry($_) } glob("${data_dir}/*.txt"); 
    14         render('entries.mt', \@entries); 
     10                my @entries = sort {$b->{mtime} <=> $a->{mtime}} 
     11                    map { blog_read_entry("$_") } glob("${data_dir}/*.txt"); 
     12        render_and_print('entries.mt', \@entries); 
    1513    } 
    1614} 
  • lang/perl/MENTOS/trunk/lib/MENTA.pm

    r24806 r24901  
    55use CGI::ExceptionManager; 
    66use MENTA::Dispatch (); 
     7use MENTA::Context; 
     8use CGI::Simple; 
     9use Class::Trigger qw/BEFORE_OUTPUT/; 
    710require Encode; # use Encode するとふるい Encode でエラーになるときがあるらしい。2.15 で確認。200810-11-20 
    811 
    9 our $VERSION = '0.06'; 
     12our $VERSION = '0.07'; 
    1013our $REQ; 
    1114our $CONFIG; 
    12 our $REQUIRED; 
    1315our $STASH; 
    14 our $PLUGIN_LOADED; 
    15 BEGIN { 
    16     $REQUIRED = {}; 
    17 } 
    1816 
    1917sub import { 
     
    2321} 
    2422 
     23{ 
     24    our $context; 
     25    sub context { $context } 
     26    sub run_context { 
     27        my ($class, $config, $code) = @_; 
     28        local $context = MENTA::Context->new( 
     29            config => $config, 
     30        ); 
     31        $code->(); 
     32    } 
     33} 
     34 
    2535package main; # ここ以下の関数はすべてコントローラで呼ぶことができます 
    2636 
    27 sub AUTOLOAD { 
    28     my $method = our $AUTOLOAD; 
    29     $method =~ s/.*:://o; 
    30     (my $prefix = $method) =~ s/_.+//; 
    31     load_plugin($prefix); 
    32     return main->can($method)->(@_); 
    33 } 
    34  
    35 sub config () { $MENTA::CONFIG } 
     37 
     38sub config () { MENTA->context->config } 
    3639 
    3740sub run_menta { 
    3841    my $config = shift @_; 
    3942 
    40     local $MENTA::CONFIG = $config; 
    41     local $MENTA::REQ; 
    42     local $MENTA::STASH; 
    43  
    4443    CGI::ExceptionManager->run( 
    4544        callback => sub { 
    46             MENTA::Dispatch->dispatch() 
     45            MENTA->run_context( 
     46                $config => sub { 
     47                    MENTA::Dispatch->dispatch() 
     48                } 
     49            ); 
    4750        }, 
    4851        powered_by => '<strong>MENTA</strong>, Web Application Framework.', 
    49         (config->{menta}->{fatals_to_browser} ? () : (renderer => sub { "INTERNAL SERVER ERROR!" x 100 })) 
     52        ($config->{menta}->{fatals_to_browser} ? () : (renderer => sub { "INTERNAL SERVER ERROR!" x 100 })) 
    5053    ); 
    5154} 
     
    8689} 
    8790 
    88 sub static_dir { 
    89     config->{menta}->{static_dir} || 'app/static/' 
    90 } 
    91  
    9291sub __render_partial { 
    9392    my ($tmpl, $tmpldir, @params) = @_; 
    94     require_once('MENTA/TemplateLoader.pm'); 
    9593    MENTA::TemplateLoader::__load("$tmpldir/$tmpl", @params); 
    9694} 
    97 sub render_partial { 
    98     my ($tmpl, @params) = @_; 
    99     bless \__render_partial($tmpl, controller_dir(), @params), 'MENTA::Template::RawString'; 
    100 } 
    101  
    102 sub detach() { CGI::ExceptionManager::detach(@_) } 
    103  
     95 
     96# テンプレートの一部を描画する 
    10497sub render { 
    10598    my ($tmpl, @params) = @_; 
    106     my $out = render_partial($tmpl, @params); 
    107     $out = $$out; 
    108     $out = encode_output($out); 
    109     print "Content-Type: text/html; charset=" . charset() . "\r\n"; 
    110     print "\r\n"; 
    111     print $out; 
    112  
    113     detach; 
     99    my $out = MENTA::TemplateLoader::__load("@{[ controller_dir() ]}/$tmpl", @params); 
     100    bless \$out, 'MENTA::Template::RawString'; 
     101} 
     102 
     103sub _finish { 
     104    MENTA->call_trigger('BEFORE_OUTPUT'); 
     105    use bytes; 
     106    my $res = MENTA->context->res; 
     107    $res->headers->content_length(bytes::length($res->content)); 
     108    print $res->as_string; 
     109    CGI::ExceptionManager::detach(); 
     110} 
     111 
     112sub render_and_print { 
     113    my ($tmpl, @params) = @_; 
     114    MENTA::Util::require_once('MENTA/TemplateLoader.pm'); 
     115    my $out = MENTA::TemplateLoader::__load("@{[ controller_dir() ]}/$tmpl", @params); 
     116    $out = MENTA::Util::encode_output($out); 
     117 
     118    my $res = MENTA->context->res; 
     119    $res->headers->content_type("text/html; charset=" . MENTA::Util::_charset()); 
     120    $res->content($out); 
     121 
     122    _finish(); 
    114123} 
    115124 
    116125sub redirect { 
    117126    my ($location, ) = @_; 
    118     print "Status: 302\r\n"; 
    119     print "Location: $location\r\n"; 
    120     print "\r\n"; 
    121  
    122     detach; 
     127 
     128    my $res = MENTA->context->res; 
     129    $res->header('Status' => 302); 
     130    $res->header('Location' => $location); 
     131 
     132    _finish(); 
    123133} 
    124134 
    125135sub finalize { 
    126136    my $str = shift; 
    127     my $content_type = shift || ('text/html; charset=' . charset()); 
    128  
    129     print "Content-Type: $content_type\r\n"; 
    130     print "\r\n"; 
    131     print $str; 
    132  
    133     detach; 
    134 } 
    135  
    136 sub read_file { 
    137     my $fname = shift; 
    138     open my $fh, '<:utf8', $fname or die "${fname} を読み込み用に開けません: $!"; 
    139     my $s = do { local $/; join '', <$fh> }; 
    140     close $fh; 
    141     $s; 
    142 } 
    143  
    144 sub write_file { 
    145     my ($fname, $stuff) = @_; 
    146     open my $fh, '>:utf8', $fname or die "${fname} を書き込み用に開けません: $!"; 
    147     print $fh $stuff; 
    148     close $fh; 
    149 } 
    150  
    151 sub param { 
    152     my $key = shift; 
    153  
    154     unless (defined $MENTA::REQ) { 
    155         require_once('MENTA/CGI.pm'); 
    156         $MENTA::REQ = CGI::Simple->new(); 
    157     } 
    158  
    159     $MENTA::REQ->param($key); 
    160 } 
    161  
    162 sub upload { 
    163     unless (defined $MENTA::REQ) { 
    164         require_once('MENTA/CGI.pm'); 
    165         $MENTA::REQ = CGI::Simple->new(); 
    166     } 
    167     $MENTA::REQ->upload(@_); 
    168 } 
    169  
    170 sub require_once { 
    171     my $path = shift; 
    172     return if $MENTA::REQUIRED->{$path}; 
    173     require $path; 
    174     $MENTA::REQUIRED->{$path} = 1; 
    175 } 
    176  
    177 sub load_plugin { 
    178     my $plugin = shift; 
    179     return if $MENTA::PLUGIN_LOADED->{$plugin}; 
    180     my $path = "plugins/${plugin}.pl"; 
    181     require $path; 
    182     $MENTA::PLUGIN_LOADED->{$plugin}++; 
    183     my $package = __menta_extract_package($path) || ''; 
    184     no strict 'refs'; 
    185     for ( 
    186         grep { /$plugin/o } 
    187         grep { defined &{"${package}::$_"} } 
    188         keys %{"${package}::"} 
    189     ) { 
    190         *{"main::$_"} = *{"${package}::$_"} 
    191     } 
    192 } 
    193  
    194 sub __menta_extract_package { 
    195     my $modulefile = shift; 
    196     open my $fh, '<', $modulefile or die "$modulefile を開けません: $!"; 
    197     my $in_pod = 0; 
    198     while (<$fh>) { 
    199         $in_pod = 1 if m/^=\w/; 
    200         $in_pod = 0 if /^=cut/; 
    201         next if ( $in_pod || /^=cut/ );    # skip pod text 
    202         next if /^\s*\#/; 
    203  
    204         /^\s*package\s+(.*?)\s*;/ and return $1; 
    205     } 
    206     return; 
     137    my $content_type = shift || ('text/html; charset=' . MENTA::Util::_charset()); 
     138 
     139    my $res = MENTA->context->res; 
     140    $res->headers->content_type($content_type); 
     141    $res->content($str); 
     142 
     143    _finish(); 
     144} 
     145 
     146sub param        { MENTA->context->request->param(@_) } 
     147sub upload       { MENTA->context->request->upload(@_) } 
     148sub mobile_agent { MENTA->context->mobile_agent() } 
     149 
     150 
     151{ 
     152    # プラグインのロード機構 
     153 
     154    my $plugin_loaded; 
     155    my $__menta_extract_package = sub { 
     156        my $modulefile = shift; 
     157        open my $fh, '<', $modulefile or die "$modulefile を開けません: $!"; 
     158        my $in_pod = 0; 
     159        while (<$fh>) { 
     160            $in_pod = 1 if m/^=\w/; 
     161            $in_pod = 0 if /^=cut/; 
     162            next if ( $in_pod || /^=cut/ );    # skip pod text 
     163            next if /^\s*\#/; 
     164 
     165            /^\s*package\s+(.*?)\s*;/ and return $1; 
     166        } 
     167        return; 
     168    }; 
     169    my $_load_plugin = sub { 
     170        my $plugin = shift; 
     171        return if $plugin_loaded->{$plugin}; 
     172        my $path = "plugins/${plugin}.pl"; 
     173        require $path; 
     174        $plugin_loaded->{$plugin}++; 
     175        my $package = $__menta_extract_package->($path) || ''; 
     176        no strict 'refs'; 
     177        for ( 
     178            grep { /$plugin/ } 
     179            grep { defined &{"${package}::$_"} } 
     180            keys %{"${package}::"} 
     181        ) { 
     182            *{"main::$_"} = *{"${package}::$_"} 
     183        } 
     184    }; 
     185 
     186    sub AUTOLOAD { 
     187        my $method = our $AUTOLOAD; 
     188        $method =~ s/.*:://o; 
     189        (my $prefix = $method) =~ s/_.+//; 
     190        die "変な関数よびだしてませんか?: $method" unless $prefix; 
     191        $_load_plugin->($prefix); 
     192        return main->can($method)->(@_); 
     193    } 
    207194} 
    208195 
     
    212199} 
    213200 
    214 # TODO: CGI にはこのための環境変数ってなかったっけ? 
    215201sub docroot () { $ENV{SCRIPT_NAME} || '' } 
    216202 
     
    230216} 
    231217 
    232 sub mobile_agent { 
    233     require_once('HTTP/MobileAgent.pm'); 
    234     $STASH->{'HTTP::MobileAgent'} ||= HTTP::MobileAgent->new(); 
    235 } 
    236  
    237 # HTTP::MobileAgent::Plugin::Charset よりポート。 
    238 # cp932 の方が実績があるので優先させる方針。 
    239 # Shift_JIS とかじゃなくて cp932 にしとかないと、諸問題にひっかかりがちなので注意 
    240 sub _mobile_encoding { 
    241     my $ma = mobile_agent(); 
    242     return 'utf-8' if $ma->is_non_mobile; 
    243     return 'utf-8' if $ma->is_docomo && $ma->xhtml_compliant; # docomo の 3G 端末では UTF-8 の表示が保障されている 
    244     return 'utf-8' if $ma->is_softbank && $ma->is_type_3gc;   # SoftBank 3G の一部端末は CP932 だと絵文字を送ってこない不具合がある 
    245     return 'cp932';                                           # au は HTTPS のときに UTF-8 だと文字化ける場合がある 
    246 } 
    247  
    248 # charset に設定する文字列を生成 
    249 sub charset { 
    250     +{ 'utf-8' => 'UTF-8', cp932 => 'Shift_JIS' }->{_mobile_encoding()}; 
    251 } 
    252  
    253 # HTTP の入り口んとこで decode させる用 
    254 sub decode_input { 
    255     my ($txt, $fb) = @_; 
    256     Encode::decode(_mobile_encoding(), $txt, $fb); 
    257 } 
    258  
    259 # 出力直前んとこで encode させる用 
    260 sub encode_output { 
    261     my ($txt, $fb) = @_; 
    262     Encode::encode(_mobile_encoding(), $txt, $fb); 
     218{ 
     219    package MENTA::Util; 
     220    # ユーティリティメソッドたち。 
     221    # これらのメソッドは一般ユーザーはよぶべきではない。 
     222 
     223    # HTTP::MobileAgent::Plugin::Charset よりポート。 
     224    # cp932 の方が実績があるので優先させる方針。 
     225    # Shift_JIS とかじゃなくて cp932 にしとかないと、諸問題にひっかかりがちなので注意 
     226    sub _mobile_encoding { 
     227        my $ma = MENTA->context->mobile_agent(); 
     228        return 'utf-8' if $ma->is_non_mobile; 
     229        return 'utf-8' if $ma->is_docomo && $ma->xhtml_compliant; # docomo の 3G 端末では UTF-8 の表示が保障されている 
     230        return 'utf-8' if $ma->is_softbank && $ma->is_type_3gc;   # SoftBank 3G の一部端末は CP932 だと絵文字を送ってこない不具合がある 
     231        return 'cp932';                                           # au は HTTPS のときに UTF-8 だと文字化ける場合がある 
     232    } 
     233 
     234    # HTTP の入り口んとこで decode させる用 
     235    sub decode_input { 
     236        my ($txt, $fb) = @_; 
     237        Encode::decode(_mobile_encoding(), $txt, $fb); 
     238    } 
     239 
     240    # 出力直前んとこで encode させる用 
     241    sub encode_output { 
     242        my ($txt, $fb) = @_; 
     243        Encode::encode(_mobile_encoding(), $txt, $fb); 
     244    } 
     245 
     246    # charset に設定する文字列を生成 
     247    sub _charset { 
     248        +{ 'utf-8' => 'UTF-8', cp932 => 'Shift_JIS' }->{_mobile_encoding()}; 
     249    } 
     250 
     251    # 一回ロードしたクラスは二度ロードしないための仕組み。 
     252    { 
     253        my $required = {}; 
     254        sub require_once { 
     255            my $path = shift; 
     256            return if $required->{$path}; 
     257            require $path; 
     258            $required->{$path} = 1; 
     259        } 
     260    } 
    263261} 
    264262 
  • lang/perl/MENTOS/trunk/lib/MENTA/CGI.pm

    r24488 r24901  
    1717              and $self->{'.globals'}->{'NO_UNDEF_PARAMS'}; 
    1818        $value =~ tr/\000//d if $self->{'.globals'}->{'NO_NULL'}; 
    19         $value = main::decode_input( $value ); # XXX この行だけ変えてる 
     19        $value = MENTA::Util::decode_input( $value ); # XXX この行だけ変えてる 
    2020        push @{ $self->{$param} }, $value; 
    2121        unless ( $self->{'.fieldnames'}->{$param} ) { 
  • lang/perl/MENTOS/trunk/lib/MENTA/Dispatch.pm

    r24488 r24901  
    3131            } 
    3232        } elsif (-f $controller_mt) { 
    33             my $out = main::__render_partial("${path}.mt", main::controller_dir()); 
    34             $out = main::encode_output($out); 
     33            MENTA::Util::require_once('MENTA/TemplateLoader.pm'); 
     34            my $tmpldir = main::controller_dir(); 
     35            my $out = MENTA::TemplateLoader::__load("${tmpldir}/${path}.mt", main::controller_dir()); 
     36            $out = MENTA::Util::encode_output($out); 
    3537            main::finalize($out); 
    3638        } else { 
     
    4850sub show_static { 
    4951    my $path = shift; 
     52    MENTA::Util::require_once('Cwd.pm'); 
     53    MENTA::Util::require_once('File/Spec.pm'); 
     54    $path = Cwd::realpath($path); 
     55    my $appdir = Cwd::realpath(File::Spec->catfile(Cwd::cwd(), 'app', 'static')); 
     56    if (index($path, $appdir) != 0) { 
     57        die "どうやら攻撃されているようだ: $path"; 
     58    } 
    5059    open my $fh, '<', $path or die "ファイルを開けません: ${path}: $!"; 
    5160    binmode $fh; 
  • lang/perl/MENTOS/trunk/lib/MENTA/Plugin.pm

    r24111 r24901  
    11package MENTA::Plugin; 
     2use strict; 
     3use warnings; 
     4use utf8; 
    25 
    36sub import { 
     
    710    utf8->import; 
    811 
     12    no strict 'refs'; 
    913    for (qw/config data_dir/) { 
    1014        *{"${pkg}::$_"} = *{"main::$_"} 
  • lang/perl/MENTOS/trunk/lib/MENTA/TemplateLoader.pm

    r24488 r24901  
    2121        my $tmplcode = eval $code; 
    2222        die $@ if $@; 
    23         $out = $tmplcode->(); 
     23        $out = $tmplcode->(@params); 
    2424        __update_cache($path, $code); 
    2525    } 
     
    2929sub __compile { 
    3030    my ($path) = @_; 
    31     main::require_once('MENTA/Template.pm'); 
     31    MENTA::Util::require_once('MENTA/Template.pm'); 
     32    my $src = do { 
     33        open my $fh, '<:utf8', $path or die "${path} を読み込み用に開けません: $!"; 
     34        my $s = do { local $/; join '', <$fh> }; 
     35        close $fh; 
     36        $s; 
     37    }; 
    3238    my $t = MENTA::Template->new; 
    33     $t->parse(main::read_file($path)); 
     39    $t->parse($src); 
    3440    $t->build(); 
    3541    my $code = $t->code(); 
  • lang/perl/MENTOS/trunk/menta.cgi

    r24806 r24901  
    11#!perl 
    2 use lib 'lib', 'extlib'; 
     2BEGIN { 
     3    unshift @INC, 'lib', 'extlib'; 
     4}; 
    35use MENTA; 
    46# -- ここまではおまじない -- 
     
    1315        # キャッシュディレクトリ 
    1416        cache_dir => 'cache', 
     17        # ブラウザにエラーを表示するかどうか 
     18        fatals_to_browser => 1, 
    1519    }, 
    1620    # あなたのアプリの設定 
     
    2226    }, 
    2327}); 
     28 
     29# 以下、あなたのプログラム 
     30 
  • lang/perl/MENTOS/trunk/plugins/blog.pl

    r24410 r24901  
    33use POSIX qw(strftime); 
    44 
     5sub blog_file_write { 
     6    my ( $fname, $stuff ) = @_; 
     7    open my $fh, '>:utf8', $fname 
     8      or die "${fname} を書き込み用に開けません: $!"; 
     9    print $fh $stuff; 
     10    close $fh; 
     11} 
     12 
    513sub blog_top_url { 
    6     my $url = $ENV{SCRIPT_NAME}; 
     14    my $url = ::docroot; 
    715    $url =~ s!menta\.cgi!!g; 
    816    $url || '/'; 
     
    1018 
    1119sub blog_read_entry { 
    12     my ($file, $mode) = @_; 
    13     my $mtime = (stat $file)[9]; 
    14     my $content = ::read_file($file); 
    15     my $data_dir = ::data_dir; 
    16     my $static_dir = ::static_dir; 
    17     $file =~ s!.*?([^/]+)\.txt$!$1!; 
    18     my $photo = "${file}.jpg"; 
     20    my ($fname, $mode) = @_; 
     21    my $mtime = (stat $fname)[9]; 
     22    open my $fh, '<:utf8', $fname 
     23      or die "${fname} を読み込み用に開けません: $!"; 
     24    my $content = do { local $/; join '', <$fh> }; 
     25    close $fh; 
     26    my $data_dir = data_dir; 
     27    my $static_dir = ::docroot . '/static/'; 
     28    $fname =~ s!.*?([^/]+)\.txt$!$1!; 
     29    my $photo = "${fname}.jpg"; 
    1930    $photo = '' unless -f "${static_dir}/${photo}"; 
    2031    my $entry = { 
    21         id => $file, 
     32        id => $fname, 
    2233        title => '', 
    2334        description => '',