#!/usr/bin/perl # ------------------------------------------------------------------------------ # CDB Viewer # ------------------------------------------------------------------------------ my $document_root = '..'; # Modules use strict; use Time::Local; # Common Lib use lib "../system/lib"; use common; # Debug use Data::Dumper; use CGI::Carp qw(fatalsToBrowser); # ドキュメント名 my $document_name = 'topics'; # DB設定ディレクトリ our $config_dir = 'conf'; #my $php_path = 'C:\php\php'; my $php_path = '/usr/bin/php'; # =============================================================================== # フレームワークの設定変更 # =============================================================================== $common::conf->{'sys_root'} = "$document_root/system"; $config_dir = "$document_root/system/$config_dir"; #================================================================================ # 設定読み込み #================================================================================ # ---- 表示設定 ---------------------------------------------------------------- require qq|${document_name}_config.pl|; my $view; { $view = $viewconf::view; } # ツール名 my $tool_name = 'contents'; # ---- DB全体設定 -------------------------------------------------------------- require qq|$config_dir/${tool_name}_conf.pl|; my $cnf; { my $config_package_name; ## 標準設定で取得 $config_package_name = '$'.qq|config::cnf|; $cnf = eval $config_package_name; ## 見つからない場合はツール名付きでトライ if(!$cnf){ $config_package_name = '$'.$tool_name.qq|::config::cnf|; $cnf = eval $config_package_name; } if(!$cnf){ error('設定ファイルが見つかりません。') } # スクリプト名補完 $cnf->{'script_name'} = $ENV{'SCRIPT_NAME'}; if(!$view->{'detail_script_name'}){ $cnf->{'detail_script_name'} = qq|${document_name}_detail.cgi|; }else{ $cnf->{'detail_script_name'} = $view->{'detail_script_name'}; } # ファイル名補完 $cnf->{'data_filename'} = qq|${tool_name}.dat| if($cnf->{'data_filename'} eq ''); $cnf->{'data_file'} = qq|$common::conf->{'sys_root'}/$cnf->{'data_dir'}/$cnf->{'data_filename'}|; $cnf->{'preview_data_file'} = qq|$common::conf->{'sys_root'}/$cnf->{'preview_root_dir'}/$cnf->{'data_filename'}|; $cnf->{'preview_root_dir'} = qq|$common::conf->{'sys_root'}/$cnf->{'preview_root_dir'}|; # ディレクトリ名補完 $cnf->{'img_path'} = qq|$cnf->{'img_dir'}/$tool_name|; $cnf->{'thumb_path'} = qq|$cnf->{'thumb_dir'}/$tool_name|; $cnf->{'file_path'} = qq|$cnf->{'file_dir'}/$tool_name|; } # ---- DBテーブル設定 ---------------------------------------------------------- require qq|$config_dir/${tool_name}_table.pl|; my $table; { my $table_package_name; ## 標準設定で取得 $table_package_name = '$'.qq|table::layout|; $table = eval $table_package_name; ## 見つからない場合はツール名付きでトライ if(!$table){ $table_package_name = '$'.$tool_name.qq|::table::layout|; $table = eval $table_package_name; } if(!$table){ error('テーブル設定ファイルが見つかりません。'); } } #================================================================================ # メインルーチン #================================================================================ # ----- データ収集 ------------------------------------------------------------- my %form = read_form(); my %cookie = get_cookie(); # ----- DB読み込み ------------------------------------------------------------- my @data; if($form{'preview'} eq 'on'){ @data = read_db($cnf->{'preview_data_file'}); }else{ # 該当するコーナーIDを抽出 if($form{'corner'} ne ''){ my $corner; $form{'corner'} = int($form{'corner'}); foreach my $target (@{$view->{'corner'}}){ if($form{'corner'} == $target){ $view->{'corner'} = [$target]; $corner = $target; last; } } if($corner eq ''){ $form{'corner'} = ''; } } @data = grep { { map { $_, 1 } (@{$view->{'corner'}}) }->{$_->{'corner'}} } read_db($cnf->{'data_file'}); # @data = read_db($cnf->{'data_file'}); # 公開期間設定がある場合 if($table->{'open'}->{'type'} != 0){ # 公開設定が非公開のものをマスク @data = grep { $_->{'hidden'} ne 'on' } @data; # 公開期間外をマスク my $nowtime = time(); if($table->{'open'}->{'type'} == 1 && $table->{'open'}->{'future_handling'} != 1){ @data = grep { (split(/,/,$_->{'dateset'}))[0] < $nowtime } @data; }elsif($table->{'open'}->{'type'} == 2 || $table->{'open'}->{'type'} == 3 ){ @data = grep { (split(/,/,$_->{'dateset'}))[1] > $nowtime } grep { (split(/,/,$_->{'dateset'}))[0] < $nowtime } @data; } # 並び順をソート @data = sort { (split(",",$b->{'dateset'}))[0] <=> (split(",",$a->{'dateset'}))[0] } reverse @data; } } # ----- テンプレート設定 ------------------------------------------------------- my $template; # ----- モード分岐 ------------------------------------------------------------- if($cnf->{'script_name'} =~ /top\.cgi$/){ top_list(); }elsif($cnf->{'script_name'} =~ /json\.cgi$/){ json_list(); }elsif($cnf->{'script_name'} =~ /detail\.cgi$/){ detail(); }else{ list(); } # # exit; #================================================================================ # list # 記事の一覧表示 # パラメタ : なし # 返り値 : なし # 出力 : 記事一覧ページ #================================================================================ sub list { my $html; my $array = @data; ### 表示記事決定 ########################################################### my $page = ''; # 表示ページ my $from = ''; # 表示開始位置 my $to = ''; # 表示終了位置 $form{'page'} =~ s/\W//g; $page = int($form{'page'}); $page = 1 if($page < 1); my $max_page = int(($array - 1) / $view->{"items_per_page"}) + 1; $page = $max_page if($page > $max_page); $from = ($page - 1) * $view->{"items_per_page"}; $to = $from + $view->{"items_per_page"} - 1; $to = $array - 1 if($to >= $array); ### 表示記事決定 ########################################################### my $navi; my $corner_param; if($form{'corner'} ne ''){ $corner_param = qq|&corner=$form{'corner'}|; } # 前後ボタン生成 my $prev = ''; my $next = ''; # 前ボタン if($page < 2){ $prev = $view->{'btn_prev'}; }else{ my $prev_page = $page - 1; $prev = qq|$view->{'btn_prev'}|; } # 後ボタン if($page >= $max_page ){ $next .= $view->{'btn_next'}; }else{ my $next_page = $page + 1; $next .= qq|$view->{'btn_next'}|; } # ダイレクトジャンプ生成 my $direct = ''; my $page_from = ''; my $page_to = ''; $page_from = int($page - ($view->{'direct_jump'} / 2)); $page_to = int($page + ($view->{'direct_jump'} / 2)); $page_from = 1 if($page_from < 1); $page_to = $max_page if($page_to > $max_page); for(my $i=$page_from;$i<=$page_to;$i++){ my $now = ''; if($i == $page){ $now =qq|class="now"|; } $direct .= qq||; $direct .= sprintf ($view->{'direct_jump_format'},$i); $direct .= qq| |; } # ナビ生成 $navi = $view->{'navi_style'}; $navi =~ s/\[PREV\]/$prev/ig; $navi =~ s/\[NEXT\]/$next/ig; $navi =~ s/\[DIRECT\]/$direct/ig; ## 記事一覧生成 ############################################################ $html .= $view->{'list_head'}; for(my $i=$from; $i<=$to; $i++){ my $item = $data[$i]; my $id = $item->{'id'}; my $date = get_date( $item ); my $icon = get_corner_icon( $item ); my $corner = get_item_format( $item, 'corner' )->{'html'}; my $title = get_item_format( $item, 'title' )->{'html'}; my $comment = get_item_format( $item, 'comment' )->{'html'}; my $link = get_item_format( $item, 'link' )->{'html'}; ## アイコンHTMLタグ my $corner_html; if($view->{'corner_icon'} == 1){ $corner_html = qq|$corner|; }else{ $corner_html = $corner; } ## リンク先調整 if($link ne ''){ $title = qq|$title|; }elsif($comment ne ''){ $title = qq|$title|; } ## HTML生成 my $tmphtml = $view->{'list_body'}; $tmphtml =~ s/\[CORNER\]/$corner_html/ig; $tmphtml =~ s/\[DATE\]/$date/ig; $tmphtml =~ s/\[TITLE\]/$title/ig; $html .= $tmphtml; } $html .= $view->{'list_foot'}; $html =~ s/\[NAVI\]/$navi/ig; $template->{'contents'} = $html; print_html_et($template, $view->{'list_template'}); } #================================================================================ # json_list # 記事の一覧表示 # パラメタ : なし # 返り値 : なし # 出力 : 記事一覧ページ #================================================================================ sub json_list { my $json; my $callback = $view->{'json_callback'}; my @json_list; my $array = @data; ### 表示記事決定 ########################################################### my $from = 0; # 表示開始位置 my $to = $view->{"top_items_per_page"} - 1; # 表示終了位置 if($to >= $array){ $to = $array - 1; } ## 記事一覧生成 ############################################################ for(my $i=$from; $i<=$to; $i++){ my $item = $data[$i]; my $id = $item->{'id'}; my $date = get_date( $item ); my $title = get_item_format( $item, 'title' )->{'html'}; my $comment = get_item_format( $item, 'comment' )->{'html'}; my $link = get_item_format( $item, 'link' )->{'html'}; my $corner = get_item_format( $item, 'corner' )->{'html'}; my $icon = get_corner_icon( $item ); ## リンク先調整 my $internal = 0; if($comment ne ''){ $internal = 1; $link = qq|$cnf->{'detail_script_name'}?id=$id|; } my $json_item =<<"__END__"; { id: "$id", date: "$date", title: "$title", link: "$link", internal: "$internal", corner: "$corner", icon: "$icon" } __END__ push @json_list, $json_item; } # JSONP $json .= qq|$callback ([|; $json .= join ',',@json_list; $json .= qq|]);|; print qq|Content-type: text/javascript; charset=utf-8\n\n|; print $json; } #================================================================================ # top_list # 記事の一覧表示 # パラメタ : なし # 返り値 : なし # 出力 : 記事一覧ページ #================================================================================ sub top_list { my $html; my $array = @data; ### 表示記事決定 ########################################################### my $from = 0; # 表示開始位置 my $to = $view->{"top_items_per_page"} - 1; # 表示終了位置 if($to >= $array){ $to = $array - 1; } ## 記事一覧生成 ############################################################ $html .= $view->{'top_list_head'}; for(my $i=$from; $i<=$to; $i++){ my $item = $data[$i]; my $id = $item->{'id'}; my $date = get_date( $item ); my $icon = get_corner_icon( $item ); my $corner = get_item_format( $item, 'corner' )->{'html'}; my $title = get_item_format( $item, 'title' )->{'html'}; my $comment = get_item_format( $item, 'comment' )->{'html'}; my $link = get_item_format( $item, 'link' )->{'html'}; ## アイコンHTMLタグ my $corner_html; if($view->{'corner_icon'} == 1){ $corner_html = qq|$corner|; }else{ $corner_html = $corner; } ## リンク先調整 if($link ne ''){ $title = qq|$title|; }elsif($comment ne ''){ $title = qq|$title|; } ## コメント装飾 $comment = alink ($comment,'_blank'); $comment = decoration ($comment); ## HTML生成 my $tmphtml = $view->{'top_list_body'}; $tmphtml =~ s/\[CORNER\]/$corner_html/ig; $tmphtml =~ s/\[COMMENT\]/$comment/ig; $tmphtml =~ s/\[DATE\]/$date/ig; $tmphtml =~ s/\[TITLE\]/$title/ig; $html .= $tmphtml; } $html .= $view->{'top_list_foot'}; $template->{'contents'} = $html; print_html_et($template, $view->{'top_list_template'}); } #================================================================================ # detail # 記事の一覧表示 # パラメタ : なし # 返り値 : なし # 出力 : 記事一覧ページ #================================================================================ sub detail { my $html; my $item; if($form{'preview'} ne 'on'){ my @entry = search_data('id',$form{'id'},@data); if(@entry != 1){ $item->{'empty'} = 1; }else{ $item = shift @entry; } }else{ $item = shift @data; } ## 詳細記事生成 ############################################################ my $format; foreach my $label (@{$table->{'table'}}){ $format->{$label->{'name'}} = get_item_format( $item, $label->{'name'} ); } ## 日付 $format->{'pubdate'} = get_date( $item ); ## アイコンHTMLタグ my $corner_html; { my $icon = get_corner_icon( $item ); my $corner = $format->{'corner'}->{'html'}; if($view->{'corner_icon'} == 1){ $corner_html = qq|$corner|; }else{ $corner_html = $corner; } $format->{'corner_html'} = $corner_html; } ## コメント装飾 $format->{'comment'}->{'html'} = alink ($format->{'comment'}->{'html'},'_blank'); $format->{'comment'}->{'html'} = decoration ($format->{'comment'}->{'html'}); ## 記事出力 $template->{'title'} = $format->{'title'}->{'html'}; $template->{'contents'} = viewconf::detail($format);; print_html_et($template, $view->{'detail_template'}); } #================================================================================ # get_item_format # パラメタ : 記事データ, 項目名 # 返り値 : HTML # 出力 : なし #================================================================================ sub get_item_format { my ($item, $name) = @_; my $output; my $label = (search_data('name',$name,@{$table->{'table'}}))[0]; #$output->{'label'} = $label; # 1: 文字型の場合 if($label->{'type'} == 1){ $output->{'html'} = $item->{$name}; } # 2/3: 選択肢の場合 elsif($label->{'type'} == 2 || $label->{'type'} == 3){ $output->{'html'} = (split ",",$label->{'options'})[$item->{$name}]; } # 4: 選択肢の場合 elsif($label->{'type'} == 4){ my @array; foreach my $tmp ( split /,/,$item->{$name} ){ @array = (split ",",$label->{'options'}) [$tmp]; } $output->{'html_array'} = \@array; } # 11: 画像の場合 elsif($label->{'type'} == 11){ $label->{'imagetype'} = $cnf->{'imagetype'} if($label->{'imagetype'} eq ''); my @imagetype = split ",",$label->{'imagetype'}; # 画像のパス取得 my $filename = ''; foreach my $ext (@imagetype){ my $tmp_fname = sprintf "%s/%s/%s_%s.%s",$document_root,$cnf->{'img_path'},$label->{'prefix'},$item->{'id'},$ext; if(-e $tmp_fname) { $filename = $tmp_fname; last; } } # サムネールのパス取得 my $thumb = ''; { my $tmp_fname = sprintf "%s/%s/%s_%s_thumb.jpg",$document_root,$cnf->{'thumb_path'},$label->{'prefix'},$item->{'id'}; if(-e $tmp_fname) { $thumb = $tmp_fname; last; } } # プレビューモードの場合 if($form{'preview'} eq 'on'){ # プレビュー画像のパス取得 foreach my $ext (@imagetype){ my $tmp_fname = sprintf "%s/%s/%s_%s.%s",$cnf->{'preview_root_dir'},$cnf->{'img_path'},$label->{'prefix'},$item->{'id'},$ext; if(-e $tmp_fname) { $filename = $tmp_fname; last; } } # プレビューサムネールのパス取得 { my $tmp_fname = sprintf "%s/%s/%s_%s_thumb.jpg",$cnf->{'preview_root_dir'},$cnf->{'thumb_path'},$label->{'prefix'},$item->{'id'}; if(-e $tmp_fname) { $thumb = $tmp_fname; last; } } } if($filename && $thumb){ $output->{'exist'} = 2; }elsif($filename){ $output->{'exist'} = 1; }else{ $output->{'exist'} = 0; } $output->{'filename'} = $filename; $output->{'thumb'} = $thumb; } # 12:添付ファイルの場合 elsif($label->{'type'} == 12){ $label->{'filetype'} = $cnf->{'filetype'} if($label->{'filetype'} eq ''); my @filetype = split ",",$label->{'filetype'}; my $filename = ''; $output->{'exist'} = 0; foreach my $ext (@filetype){ my $tmp_fname; if($form{'preview'} eq 'on'){ $tmp_fname = sprintf "%s/%s/%s_%s.%s",$cnf->{'preview_root_dir'},$cnf->{'file_path'},$label->{'prefix'},$item->{'id'},$ext; if(! -e $tmp_fname){ $tmp_fname = sprintf "%s/%s/%s_%s.%s",$document_root,$cnf->{'file_path'},$label->{'prefix'},$item->{'id'},$ext; } }else{ $tmp_fname = sprintf "%s/%s/%s_%s.%s",$document_root,$cnf->{'file_path'},$label->{'prefix'},$item->{'id'},$ext; } if(-e $tmp_fname) { $filename = $tmp_fname; $output->{'exist'} = 1; $output->{'ext'} = $ext; $output->{'size'} = -s $filename; last; } } $output->{'filename'} = $filename; } # 21:日付入力 elsif($label->{'type'} == 21){ $output->{'html'} = date_conv(10,$item->{$name}); } # 22:日付入力 elsif($label->{'type'} == 22){ my ($systime1,$systime2,$switch) = split /,/,$item->{$name}; $output->{'html'} = date_conv(10,$systime1).'~'.date_conv(10,$systime2); } return $output; } #================================================================================ # decoration # 文字装飾 # パラメタ : 記事データ # 返り値 : HTML # 出力 : なし #================================================================================ sub decoration{ my $html = shift; $html =~ s/\[RED\](.+?)\[\/RED\]/$1<\/strong>/ig; $html =~ s/\[GREEN\](.+?)\[\/GREEN\]/$1<\/strong>/ig; $html =~ s/\[BLUE\](.+?)\[\/BLUE\]/$1<\/strong>/ig; $html =~ s/\[B\](.+?)\[\/B\]/$1<\/strong>/ig; return $html; } #================================================================================ # get_corner_icon # リストアップモード:記事の一覧表示 # パラメタ : 記事データ # 返り値 : HTML # 出力 : なし #================================================================================ sub get_corner_icon { my $item = shift; my $iconfile = qq|$view->{'corner_icon_dir'}/$view->{'corner_iconfile'}->{$item->{'corner'}}|; return $iconfile } #================================================================================ # get_date # リストアップモード:記事の一覧表示 # パラメタ : 記事データ # 返り値 : HTML # 出力 : なし #================================================================================ sub get_date { my $item = shift; my $epoc = (split ',',$item->{'dateset'})[0]; return date_conv(2,$epoc); } #================================================================================ # get_date # リストアップモード:記事の一覧表示 # パラメタ : 記事データ # 返り値 : HTML # 出力 : なし #================================================================================ sub get_date { my $item = shift; my $epoc = (split ',',$item->{'dateset'})[0]; return date_conv(2,$epoc); } #================================================================================ # date_conv # 日付形式の生成 # パラメタ : $date_type(日付型の番号) # $era_mode = 0 (西暦表示)の場合 # [1]0000/ 0/ 0 [2]0000/00/00 [3]00/ 0/ 0 [4]00/00/00 # [5]0000. 0. 0 [6]0000.00.00 [7]00. 0. 0 [8]00.00.00 # [9]0000年0月0日 [10]0000年0月0日(曜) # $era_mode = 1 (年号表示)の場合 # [1]年号00年00月00日 [2]年号00年00月00日(曜) # 返り値 : $date_style(日付形式) # 出力 : なし #================================================================================ sub date_conv { my ($date_type, $time_value) = @_; my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = gmtime ($time_value + 32400); my @wdays = ("日","月","火","水","木","金","土"); $year += 1900; $mon += 1; my $syear = ($year + 1900) % 100; my $date_style = ''; # 西暦表示の場合 if($cnf->{'era_mode'} == 0){ if($date_type == 1) { $date_style = sprintf("%4d/%2d/%2d", $year, $mon, $mday); } elsif($date_type == 2) { $date_style = sprintf("%04d/%02d/%02d", $year, $mon, $mday); } elsif($date_type == 3) { $date_style = sprintf("%2d/%2d/%2d", $syear, $mon, $mday); } elsif($date_type == 4) { $date_style = sprintf("%02d/%02d/%02d", $syear, $mon, $mday); } elsif($date_type == 5) { $date_style = sprintf("%4d.%2d.%2d", $year, $mon, $mday); } elsif($date_type == 6) { $date_style = sprintf("%04d.%02d.%02d", $year, $mon, $mday); } elsif($date_type == 7) { $date_style = sprintf("%2d.%2d.%2d", $syear, $mon, $mday); } elsif($date_type == 8) { $date_style = sprintf("%02d.%02d.%02d", $syear, $mon, $mday); } elsif($date_type == 9) { $date_style = sprintf("%d年%d月%d日", $year, $mon, $mday); } elsif($date_type == 10) { $date_style = sprintf("%d年%d月%d日(%s)", $year, $mon, $mday, $wdays[$wday]); } else { $date_style = sprintf("%4d/%2d/%2d", $year, $mon, $mday); } } # 年号表示の場合 elsif($cnf->{'era_mode'} == 1){ my $year_count = $year + $cnf->{'era_offset'}; my $year_label = "$cnf->{'era_name'}${year_count}"; if($date_type == 1) { $date_style = sprintf("%s年%2d月%2d日",$year_label, $mon, $mday); } elsif($date_type == 2) { $date_style = sprintf("%s年%2d月%2d日(%s)",$year_label, $mon, $mday, $wdays[$wday]); } else { $date_style = sprintf("%s年%2d月%2d日",$year_label, $mon, $mday); } } return $date_style; } #================================================================================ # read_db # データベース読み込み # パラメタ : ファイルパス # 返り値 : 記事データ # 出力 : なし #================================================================================ sub read_db { my $filepath = shift; # 通常読込 if(-e "${filepath}.fmt" && -e $filepath){ return read_data($filepath); }else{ return -1; } } #================================================================================ # print_html_php (\%html, $template_file); # HTML出力 (簡易テンプレート) #================================================================================ sub print_html_php { my @gzip_str = ('[GZIP OFF]','[GZIP ON]'); my $html = shift; my $template_html_file = shift; $html->{'gzip_mode'} = $gzip_str[ http_header ]; map { $html->{$_} = outcode($html->{$_}) } keys(%{$html}); my $template_html = `$php_path $template_html_file`; my $template = join '',$template_html; foreach my $key (keys (%{$html})){ my $target = qq||; $template =~ s/($target)/$html->{$key}/igs; } print $template; }