| Tripletail documentation | Contained in the Tripletail distribution. |
Tripletail::Filter::HTML - 通常 HTML 用出力フィルタ
$TL->setContentFilter('Tripletail::Filter::HTML', charset => 'UTF-8');
$TL->print($TL->readTextFile('foo.html'));
HTML に対して以下の処理を行う。
セッションを利用している場合、 http 領域用のセッション情報は "SID + セッショングループ名"、
https 領域用のセッション情報は "SIDS + セッショングループ名" という名称のクッキーに保存する。
$TL->setContentFilter('Tripletail::Filter::HTML', charset => 'Shift_JIS');
出力文字コードを指定する。省略可能。
使用可能なコードは次の通り。 UTF-8,Shift_JIS,EUC-JP,ISO-2022-JP
デフォルトはShift_JIS。
$TL->setContentFilter('Tripletail::Filter::HTML', contenttype => 'text/html; charset=sjis');
Content-Type を指定する。省略可能。
デフォルトは text/html; charset=(charasetで指定された文字コード)。
$TL->setContentFilter('Tripletail::Filter::HTML', type => 'xhtml');
'html' もしくは 'xhtml' を利用可能。省略可能。
フィルタが HTML を書換える際の動作を調整する為のオプション。 XHTML を出力する際に、このパラメータを html のままにした場合、 不正な XHTML が出力される事がある。
デフォルトは 'html'。
my $SAVE = $TL->getContentFilter->getSaveForm;
出力フィルタが所持している保存すべきデータが入った、 Form オブジェクトを返す。
$TL->getContentFilter->setHeader($key => $value)
他の出力の前に実行する必要がある。
同じヘッダを既に出力しようとしていれば、そのヘッダの代わりに指定したヘッダを出力する。(上書きされる)
$TL->getContentFilter->addHeader($key => $value)
他の出力の前に実行する必要がある。
同じヘッダを既に出力しようとしていれば、そのヘッダに加えて指定したヘッダを出力する。(追加される)
Copyright 2006 YMIRLINK Inc.
This framework is free software; you can redistribute it and/or modify it under the same terms as Perl itself
このフレームワークはフリーソフトウェアです。あなたは Perl と同じライセンスの 元で再配布及び変更を行うことが出来ます。
Address bug reports and comments to: tl@tripletail.jp
HP : http://tripletail.jp/
| Tripletail documentation | Contained in the Tripletail distribution. |
# ----------------------------------------------------------------------------- # Tripletail::Filter::HTML - é常HTMLç¨åºåãã£ã«ã¿ # ----------------------------------------------------------------------------- package Tripletail::Filter::HTML; use strict; use warnings; use Tripletail; require Tripletail::Filter; our @ISA = qw(Tripletail::Filter); # Tripletail::Filter::HTMLã¯ã # * æåã³ã¼ãã®å¤æããã # * ãã©ã¼ã ã¸"CCC=æ"ã追å ãã # * å¤é¨ãªã³ã¯ã®æ¸æãã *ããªã* # * ã»ãã·ã§ã³ãã¼ã¿ããªã³ã¯ã»ãã©ã¼ã ã«è¿½å *ããªã* # * Content-Dispositionãåºåããªã # ãªãã·ã§ã³ä¸è¦§: # * charset => åºåã®æåã³ã¼ãã(UTF-8ãã夿ããã) # Encode.pmãå©ç¨å¯è½ãªãå©ç¨ããã(UniJPä¸é¨äºæã¨ã³ã³ã¼ãåãsjisçµµæå使ç¨ä¸å¯) # ããã©ã«ã: Shift_JIS # * contenttype => ããã©ã«ã: text/html; charset=(CHARSET) # * type => 'html'ã¾ãã¯'xhtml'ãããã©ã«ã: html # HTMLæ¸æãæã®åä½ãå¤åããã # 注æ: # * Tripletail::Filter::HTMLã¯ãããã¡ãªã³ã°ãè¡ããªãçºãåºåãããhtmlã® # <meta>è¦ç´ ãè¦ã¦æåã³ã¼ããèªåå¤å¥ããäºã¯åºæ¥ãªãã # * ãããã®åºåã¯ãæåã«ãã£ã«ã¿ã®print()ã¡ã½ããã使ãããæã # ããªãã¡æåã«$TL->printãå¼ã°ããæã«è¡ãããã # åºåãã¹ãã¯ããã¼ã®è¨å®/夿´(ã»ãã·ã§ã³å«ã)ã¯ã # $TL->printãå¼ã³åºãåã«è¡ããªããã°ãªããªãã 1; sub _new { my $class = shift; my $this = $class->SUPER::_new(@_); # ããã©ã«ãå¤ãåããã my $defaults = [ [charset => 'Shift_JIS'], [contenttype => sub { # åçã«æ±ºã¾ãã®ã§CODE Refãæ¸¡ãã弿°ã¯åããªãã require Tripletail::CharConv; sprintf 'text/html; charset=%s', $this->{option}{charset}; }], [type => 'html'], ]; $this->_fill_option_defaults($defaults); # ãªãã·ã§ã³ã®ãã§ã㯠my $check = { charset => [qw(defined no_empty scalar)], contenttype => [qw(defined no_empty scalar)], type => [qw(no_empty scalar)], }; $this->_check_options($check); if($this->{option}{type} ne 'html' && $this->{option}{type} ne 'xhtml') { die "TL#setContentFilter: option [type] for [Tripletail::Filter::HTML] ". "must be 'html' or 'xhtml', not [$this->{option}{type}].". " (typeãªãã·ã§ã³ã¯html/xhtmlã®ãããããæå®ãã¦ãã ãã)\n"; } # ç¶æ ã®åæåã $this->reset; $this; } sub getSaveForm { my $this = shift; $this->{save}; } sub print { my $this = shift; my $data = shift; return '' if($data eq '' and $this->{buffer} eq ''); if(ref($data)) { die __PACKAGE__."#print: arg[1] is a reference. [$data] (第1弿°ããªãã¡ã¬ã³ã¹ã§ã)\n"; } if(defined $this->{locationurl}) { die __PACKAGE__."#print: \$TL->print() must not be called after calling \$TL->location(). (locationå¾ã«printãããã¨ã¯åºæ¥ã¾ãã)\n"; } $data = $this->{buffer} . $data; $this->{buffer} = ''; if($data =~ s/(<[^>]+)$//) { $this->{buffer} = $1; } $data = $this->_relink_html(html => $data); if(length($data)) { $this->{content_printed} = 1; } my $output = $this->_flush_header; $output .= $TL->charconv($data, 'UTF-8' => $this->{option}{charset}); $output; } sub flush { my $this = shift; my $output; if(defined $this->{locationurl}) { my $data = $this->_flush_header; if($TL->getDebug->{location_debug}) { my $link = $this->_relink(url => $this->{locationurl}); $data .= q{<html><head><title>redirect</title></head><body><a href="} . $TL->escapeTag($link) . q{">} . $TL->escapeTag($link) . q{</a></body></html>}; } $output = $data; } else { # ä¸åº¦ä»¥ä¸ print ãéãã®ã§, _flush_header ã¯å¼ã³åºãæ¸ã¿. my $data = $this->{buffer}; $this->{buffer} = ''; $data = $this->_relink_html(html => $data); if(length($data)) { $this->{content_printed} = 1; } $output = $TL->charconv($data, 'UTF-8' => $this->{option}{charset}); if(!$this->{content_printed}) { die __PACKAGE__."#flush: no contents has been printed during this request. (ãªã¯ã¨ã¹ãå¦çã§ä½ãprintããã¦ãã¾ãã)\n"; } } $output; } sub _location { my $this = shift; my $url = shift; $this->{locationurl} = $url; $this; } sub _make_header { my $this = shift; if(defined(&Tripletail::Session::_getInstance)){ # Tripletail::Sessionãæå¹ã«ãªã£ã¦ããã®ã§ããã¼ã¿ãæãã°ããããã¯ããã¼ã«å ããã foreach my $group (Tripletail::Session->_getInstanceGroups) { Tripletail::Session->_getInstance($group)->_setSessionDataToCookies; } } require Tripletail::RawCookie; require Tripletail::Cookie; my %opts = (); if(defined $this->{locationurl}) { if(!$TL->getDebug->{location_debug}) { # relinkããä¸ã§Locationãçæã %opts = (Location => $this->_relink(url => $this->{locationurl})); } } return { %opts, 'Set-Cookie' => [ Tripletail::Cookie->_makeSetCookies, Tripletail::RawCookie->_makeSetCookies, ], }; } sub _relink_html { # $this->{save}ã®å 容ã§htmlãæ¸æããã # æ¸æãå 容: # * form.action : 空ãªãREQUEST_URIã«ãããç¸å¯¾ãªã³ã¯ãªãhiddenã§$saveã®å 容ã追å ããã my $this = shift; my $opts = { @_ }; my $html = $opts->{html}; # æ¸æããHTML if(!defined($this->{save})) { # sanity check die __PACKAGE__."#_relink_form: internal error: \$this->{save} is undefined. (å é¨ã¨ã©ã¼:\$this->{save}ãæªå®ç¾©ã§ã)\n"; } # _relinkç¨ã®ãã£ãã·ã¥(é å) my $relink_cache = []; my $is_xhtml = $this->{option}{type} eq 'xhtml' || 0; my @intr = qw(form a); $is_xhtml and push(@intr, qw(input br option)); my $filter = $TL->newHtmlFilter( interest => \@intr, ); $filter->set($html); while(my ($context, $elem) = $filter->next) { my $elem_name_lc = lc($elem->name); if($elem_name_lc eq 'form') { my $link_unescaped = do { my $action = $elem->attr('action'); if (!defined($action) || !length($action)) { # actionã空ã my $uri = $ENV{REQUEST_URI} || ''; # ãã¡ã¤ã«å以å¤ãæ¶ã $uri =~ s/\?.*$//; $uri =~ s|.*/([^/]+)$|$1|; #$TL->log( # __PACKAGE__, # sprintf( # 'Set action of form [%s] to [%s]', # $elem->toStr, $TL->escapeTag($uri)) #); # ã¿ã°ãã¨ã¹ã±ã¼ããã¦è¨å® $elem->attr(action => $TL->escapeTag($uri)); $uri; } else { # 空ã§ãªãã $TL->unescapeTag($action); } }; # ãã®ãªã³ã¯ãå é¨ãªã³ã¯ãªã$saveã®å 容ã追å if(!$elem->attr('EXT')) { if( $is_xhtml ) { $context->add($context->newElement('div')); } foreach my $key ($this->{save}->getKeys) { foreach my $value ($this->{save}->getValues($key)) { my $e = $context->newElement('input'); $e->attr(type => 'hidden'); $e->attr(name => $TL->escapeTag($key)); $e->attr(value => $TL->escapeTag($value)); if( $is_xhtml ) { $e->end('/'); } #$TL->log( # __PACKAGE__, # sprintf( # 'Inserted hidden input in the form [%s]: [%s]', # $elem->toStr, $e->toStr) #); $context->add($e); } } if( $is_xhtml ) { $context->add($context->newElement('/div')); } } else { $elem->attr(EXT => undef); } } elsif($elem_name_lc eq 'a' && $elem->attr('href')) { # hrefããããªãããªã³ã¯ãæ¸æããã my $newurl = $TL->escapeTag( $this->_relink( url => $TL->unescapeTag($elem->attr('href')), cache => $relink_cache, ) ); if($newurl ne $elem->attr('href')) { #$TL->log( # __PACKAGE__, # sprintf('Relinked: [%s] => [%s]', $elem->attr('href'), $newurl) #); } $elem->attr(href => $newurl); } elsif($elem_name_lc =~ /^(input|br)$/ ) { # ããã«æ¥ãã®ã¯ $is_xhtml ã®æã ã. my $end = $elem->end || ''; if( $end =~ s/checked// && !$elem->attr('checked') ) { $elem->attr('checked' => 'checked'); } $elem->end('/'); } elsif($elem_name_lc eq 'option' ) { # ããã«æ¥ãã®ã¯ $is_xhtml ã®æã ã. my $end = $elem->end || ''; if( $end =~ s/selected// && !$elem->attr('selected') ) { $elem->attr('selected' => 'selected'); } $elem->end($end =~ /\S/ ? $end : ''); } } $filter->toStr; } sub _relink { my $this = shift; my $opts = { @_ }; my $url = $opts->{url}; my $cache = $opts->{cache} || []; if(!@$cache) { # ãã£ãã·ã¥ãã¾ã ä½ããã¦ããªãã # $cache->[0] : CCCã常ã«ä»ãã¦ãã$saveæåå # $cache->[1] : $saveå ã«asciiæåããå ¥ã£ã¦ããªããªãCCCãä»ããªã$saveæåå # ã©ã¡ããå é ã«'&'ãä»ãã¦ããäºã«æ³¨æã @$cache = ('') x 2; my $onlyascii = 1; my $CCC; foreach my $key ($this->{save}->getKeys) { foreach my $value ($this->{save}->getValues($key)) { if($key ne 'CCC' && $value =~ m/[\x80-\xff]/) { $onlyascii = 0; } my $add .= sprintf '&%s=%s', $TL->encodeURL($TL->charconv($key, 'UTF-8' => $this->{option}{charset})), $TL->encodeURL($TL->charconv($value, 'UTF-8' => $this->{option}{charset})); $cache->[0] .= $add; if($key eq 'CCC') { $CCC = $add; # ã¾ã 追å ããªãã } else { $cache->[1] .= $add; } } } if(!$onlyascii) { $cache->[1] .= $CCC; } } my $fragment = ($url =~ s/(#.+)$// ? $1 : ''); my $type = 0; if($url =~ m,INT=1,) { # å度æ£ç¢ºã«ãã§ãã¯ãã my $int = $TL->newForm($url)->get('INT'); if($int) { $type = 1; } } if($type == 1) { # å é¨ãªã³ã¯ # URLã®æåã³ã¼ãã夿ãã my ($file, $delim, $param) = split(/(\?)/, $url); if($delim) { my @pairs; my $url2 = $file . $delim; foreach my $pair (split(/\&/, $param)) { my ($key, $value) = split(/\=/, $pair); next if($key eq 'INT'); $key = $TL->encodeURL($TL->charconv($TL->decodeURL($key), 'UTF-8' => $this->{option}{charset})); $value = $TL->encodeURL($TL->charconv($TL->decodeURL($value), 'UTF-8' => $this->{option}{charset})); $url2 .= $key . '=' . $value . '&'; } chop $url2; $url = $url2; } my $onlyascii = ($url !~ m/[\x80-\xff]|\%[8-9a-fA-F][0-9a-fA-F]/ ? 1 : 0); if($url =~ m/\?/) { $url .= $cache->[$onlyascii]; } else { # å ã®URLã«ã¯ã¨ãªãä»ãã¦ããªããªããããã§ä»ããã (my $add = $cache->[$onlyascii]) =~ s/\&//; $url .= '?' . $add; } } elsif($type == 0) { # å¼ã£ã¦ã¯ãªããªããªã³ã¯ } $url . $fragment; } sub reset { my $this = shift; $this->SUPER::reset; # Contentã1ãã¤ãã§ãåºåããããã©ãã $this->{content_printed} = undef; # ä¿åãããã©ã¼ã ãªãã¸ã§ã¯ã $this->{save} = $TL->newForm->set( CCC => 'æ', ); $this->setHeader('Content-Type' => $this->{option}{contenttype}); $this->{buffer} = ''; $this->{locationurl} = undef; $this; } __END__