#!/usr/bin/perl

#=============================================================================
# clippic_list.cgi: listing CGI program of clippic (ver.20030331)
#
# Copyright (C) 2003 OHKUBO Masahiko <mah@pobox.ne.jp>
# The latest version is available here: http://mah.pobox.ne.jp/clippic.shtml
#=============================================================================

use strict;
use vars '%setting';

BEGIN {
	my($path, $tmp);

	# プログラムがあるディレクトリを調べる
	$path = $0;
	if (index($path, '\\') > -1) {
		# 区切りに \ を使う環境?
		$path =~ s/\\/\//g;
	}
	if (index($path, '/') > -1) {
		# 区切りに / を使う環境?
		$path =~ /(.*)\/(.*)$/;
		$setting{'file_program'} = $2;
		if ($1 ne '') {
			$setting{'dir_program'} = $1 . '/';
		} else {
			$setting{'dir_program'} = './';
		}
	} else {
		# 判別ができない環境
		$setting{'file_program'} = $path;
		$setting{'dir_program'} = './';
	}
	require $setting{'dir_program'} . 'clippic_common.pl';
	require $setting{'dir_program'} . 'jcode.pl';
	require 5.004;
}

&MAIN();
exit;



# メインルーチン
sub MAIN {
	my($ref_setting_list, $ref_form, $ref_file, $ref_counter_month);
	my($ref_header_table_number2before, $ref_header_table_before2number, $ref_header_table_before2after);

	# 各種値の設定
	&SECTION_SET_SETTING();
	# 設定ファイルの読み込み
	($ref_setting_list, $ref_header_table_number2before, $ref_header_table_before2number, $ref_header_table_before2after) = &SECTION_READ_CONFIGFILE_LIST($setting{'dir_data'} . $setting{'file_data'});
	# フォーム入力を受け取って整形
	$ref_form = &SECTION_DECODE_CGI($ref_setting_list, $ref_header_table_number2before);
	if ($$ref_form{'mode'} eq 'popup') {
		# 画像ポップアップページの HTML 表示
		&SECTION_OUTPUT_POPUP($ref_setting_list, $ref_form, $ref_header_table_before2number, $ref_header_table_before2after);
	} else {
		# ファイルを検索する
		($ref_file, $ref_form, $ref_counter_month) = &SECTION_SEARCH_FILE($ref_setting_list, $ref_form);
		# 画像一覧ページの HTML 表示
		&SECTION_OUTPUT_LIST($ref_setting_list, $ref_form, $ref_file, $ref_counter_month, $ref_header_table_before2number, $ref_header_table_before2after);
	}
	return;
}



# セクション: 各種設定を決定する
sub SECTION_SET_SETTING {
	my(%setting_default);
	my($key);

	# デフォルト値の読み込み
	%setting_default = %{&SET_SETTING_DEFAULT('list')};
	$setting{'dir_data'} = $setting{'dir_program'};
	# %setting にコピー (優先順位: %setting_default, %setting)
	while (($key, undef) = each(%setting_default)) {
		if (exists($setting{$key})) {
			# プログラムによる指定
		} else {
			# デフォルト値による指定
			$setting{$key} = $setting_default{$key};
		}
	}
	return;
}



# セクション: 設定ファイルの読み込み
sub SECTION_READ_CONFIGFILE_LIST {
	my($file_list) = @_;
	my(%setting_list);
	my(@header) = ('from', 'to', 'cc', 'subject');
	my($header, $counter, $tmp, $replace_before, $replace_after, $key);
	my(%header_table_number2before, %header_table_before2number, %header_table_before2after);
	my($counter_max) = 99;

	# 設定ファイルを読み込む
	if (-e ($file_list)) {
		%setting_list = %{&LOAD_CONFIGFILE($file_list)};
	} else {
		&VERBOSE('error', 'error', 'ERROR: file not found. / file = ' . $file_list);
	}
	if (substr($setting_list{'directory_image:input'}, -1, 1) ne '/') {
		$setting_list{'directory_image:input'} = $setting_list{'directory_image:input'} . '/';
	}
	if (substr($setting_list{'directory_text:input'}, -1, 1) ne '/') {
		$setting_list{'directory_text:input'} = $setting_list{'directory_text:input'} . '/';
	}
	if ($setting_list{'alias_header:output'} eq 'yes') {
		# エイリアス機能を使用するなら，変換テーブルを用意
		while(@header) {
			$header = shift(@header);
			for ($counter = 1; $counter < $counter_max + 1; $counter ++) {
				$tmp = 'alias_' . $header . '_' . ($counter) . ':output';
				if ($setting_list{$tmp} ne '') {
					($replace_before, $replace_after) = split(',', $setting_list{$tmp}, 2);
					$replace_before = ${&CUT_SPACE_TERMINAL(\$replace_before)};
					$replace_after = ${&CUT_SPACE_TERMINAL(\$replace_after)};
					$header_table_number2before{$header . "\t" . '{' . ($counter) . '}'} = $replace_before;
					$header_table_before2number{$header . "\t" . $replace_before} = '{' . ($counter) . '}';
					$header_table_before2after{$header . "\t" . $replace_before} = $replace_after;
				}
			}
		}
	}
	return(\%setting_list, \%header_table_number2before, \%header_table_before2number, \%header_table_before2after);
}



# セクション: フォーム入力を受け取って整形
sub SECTION_DECODE_CGI {
	my($ref_setting_list, $ref_header_table_number2before) = @_;
	my($ref_form);

	$ref_form = &DECODE_CGI();
	if (!($$ref_form{'date_yyyymm'} =~ /^(\d{6})$/)) {
		$$ref_form{'date_yyyymm'} = '';
	}
	if ($$ref_form{'mode'} eq 'popup') {
		# 画像ポップアップページ
		$$ref_form{'file'} =~ s/[^\w\-\.\%]//g;	# clippic_mail.pl の &CONVERT_FILE + 「%」の処理
		$$ref_form{'no'} =~ s/\D//g;
		if (!($$ref_form{'scale'} =~ /^\d(\.\d)?$/)) {
			$$ref_form{'scale'} = $$ref_setting_list{'scale_default_popup:output'};
		}
	} else {
		# 画像一覧ページ
		if ($$ref_form{'date_dd'} =~ /^(\d{1})$/) {
			$$ref_form{'date_dd'} = '0' . $$ref_form{'date_dd'};
		} elsif (!($$ref_form{'date_dd'} =~ /^(\d{2})$/)) {
			$$ref_form{'date_dd'} = '';
		}
		if (!($$ref_form{'scale'} =~ /^(1|2)$/)) {
			$$ref_form{'scale'} = $$ref_setting_list{'scale_default:output'};
		}
		if (!($$ref_form{'order'} =~ /^(new|old)$/)) {
			$$ref_form{'order'} = $$ref_setting_list{'order_default:output'};
		}
		if ($$ref_setting_list{'alias_header:output'} eq 'yes') {
			# エイリアス機能を使うなら，{数値} を文字列に戻す
			if ($$ref_header_table_number2before{'from' . "\t" . $$ref_form{'from'}} ne '') {
				$$ref_form{'from_original'} = $$ref_form{'from'};
				$$ref_form{'from'} = $$ref_header_table_number2before{'from' . "\t" . $$ref_form{'from'}};
			}
			if ($$ref_header_table_number2before{'to' . "\t" . $$ref_form{'to'}} ne '') {
				$$ref_form{'to_original'} = $$ref_form{'to'};
				$$ref_form{'to'} = $$ref_header_table_number2before{'to' . "\t" . $$ref_form{'to'}};
			}
			if ($$ref_header_table_number2before{'cc' . "\t" . $$ref_form{'cc'}} ne '') {
				$$ref_form{'cc_original'} = $$ref_form{'cc'};
				$$ref_form{'cc'} = $$ref_header_table_number2before{'cc' . "\t" . $$ref_form{'cc'}};
			}
			if ($$ref_header_table_number2before{'subject' . "\t" . $$ref_form{'subject'}} ne '') {
				$$ref_form{'subject_original'} = $$ref_form{'subject'};
				$$ref_form{'subject'} = $$ref_header_table_number2before{'subject' . "\t" . $$ref_form{'subject'}};
			}
		}
	}
	return($ref_form);
}



# セクション: ファイルを検索する
sub SECTION_SEARCH_FILE {
	my($ref_setting_list, $ref_form) = @_;
	my($dir, $ref_file_text, $file_text);
	my($key, $value, $flag_exist, $flag_hit, $file_image, $tmp);
	my(%file, $image_format, $image_width, $image_height, $text_body);
	my($ref_header, $ref_text);
	my(%counter_month, $dir_last, $counter_file);
	my($string_subject_empty);

	# テキストファイルの一覧を得る
	$dir = $$ref_setting_list{'directory_text:input'};
	$string_subject_empty = '{empty}';
	($ref_file_text, $dir_last) = &GREP_FILE($dir, $$ref_setting_list{'filename_text_extension:input'});
	# Date での絞り込みが指定されていなければ，最終月のみにする。
	if ($$ref_form{'date_yyyymm'} eq '') {
		$$ref_form{'date_yyyymm'} = $dir_last;
	}
	# 検索候補のファイルをとりあえず取得
	$counter_file = 0;
	while(@$ref_file_text) {
		$file_text = shift(@$ref_file_text);
		$flag_exist = 'no';
		$tmp = $file_text;
		$tmp =~ s/^$$ref_setting_list{'directory_text:input'}//;
		$tmp =~ /(.*)\.$$ref_setting_list{'filename_text_extension:input'}$/;
		$tmp = $1;
		if (-f ($$ref_setting_list{'directory_image:input'} . $tmp . '.jpg')) { # 将来は 'jpg', 'jpeg', 'png', 'gif'
			$flag_exist = 'yes';
			$file_image = $$ref_setting_list{'directory_image:input'} . $tmp . '.jpg';
		} elsif (-f ($$ref_setting_list{'directory_image:input'} . $tmp . '.jpeg')) {
			$flag_exist = 'yes';
			$file_image = $$ref_setting_list{'directory_image:input'} . $tmp . '.jpeg';
		}
		if ($flag_exist eq 'yes') {
			# 画像ファイルが存在する
			$counter_file ++;
			$flag_hit = 'yes';
			# 月別のファイル数だけは絞り込まずに数えておく
			$file_text =~ /(\d+)\/[^\/]+$/;
			$tmp = $1;
			$counter_month{$tmp} ++;
			if (($$ref_form{'date_yyyymm'} ne '000000') && (($$ref_form{'date_yyyymm'} ne '') && ($tmp ne $$ref_form{'date_yyyymm'}))) {
				$flag_hit = 'no';
			}
			$$ref_header{'FROM'} = "\x00";
			$$ref_header{'TO'} = "\x00";
			$$ref_header{'CC'} = "\x00";
			$$ref_header{'SUBJECT'} = "\x00";
			$$ref_header{'DATE'} = "\x00";
			if ($flag_hit ne 'no') {
				# メールテキストを読み込む
				($ref_header, $ref_text) = &EXTRACT_HEADER_FAST((&LOAD_FILE($file_text, 'direct'))[0]);
				$text_body = join('<br>', @$ref_text);
				# 条件で検索
				if ($$ref_form{'date_dd'} ne '') {
					$tmp = substr($$ref_header{'DATE'}, 8, 2);
					if ($tmp ne $$ref_form{'date_dd'}) {
						$flag_hit = 'no';
					}
				}
				if ($$ref_form{'from'} ne '') {
					if ($$ref_header{'FROM'} ne $$ref_form{'from'}) {
						$flag_hit = 'no';
					}
				}
				if ($$ref_form{'to'} ne '') {
					if ($$ref_header{'TO'} ne $$ref_form{'to'}) {
						$flag_hit = 'no';
					}
				}
				if ($$ref_form{'cc'} ne '') {
					if ($$ref_header{'CC'} ne $$ref_form{'cc'}) {
						$flag_hit = 'no';
					}
				}
				if ($$ref_form{'subject'} ne '') {
					if ($$ref_form{'subject'} eq $string_subject_empty) {
						if ($$ref_header{'SUBJECT'} ne '') {
							$flag_hit = 'no';
						}
					} else {
						if ($$ref_header{'SUBJECT'} ne $$ref_form{'subject'}) {
							$flag_hit = 'no';
						}
					}
				}
				if ($$ref_form{'subject_body'} ne '') {
					$tmp = $$ref_header{'SUBJECT'} . $text_body;
					if (!($tmp =~ /$$ref_form{'subject_body'}/i)) {
						$flag_hit = 'no';
					}
				}
			}
			if ($flag_hit eq 'yes') {
				($image_format, $image_width, $image_height) = &ANALYZE_IMAGE($file_image);
				$file_image =~ s/^$$ref_setting_list{'directory_image:input'}//;
			}
			$file{$file_text} = join("\t", $flag_hit, $file_image, $image_format, $image_width, $image_height, $$ref_header{'FROM'}, $$ref_header{'TO'}, $$ref_header{'CC'}, $$ref_header{'SUBJECT'}, $$ref_header{'DATE'}, $counter_file, $text_body);
		}
	}
	return(\%file, $ref_form, \%counter_month);
}



# セクション: 画像一覧ページの HTML 出力
sub SECTION_OUTPUT_LIST {
	my($ref_setting_list, $ref_form, $ref_file, $ref_counter_month, $ref_header_table_before2number, $ref_header_table_before2after) = @_;
	my($key, $value, %replace, $tmp, $flag, @tmp, $date);
	my($flag_hit, $file_image, $image_format, $image_width, $image_height, $text_from, $text_to, $text_cc, $text_subject, $text_date, $text_body, $image_size);
	my(%buffer_from, %buffer_to, %buffer_cc, %buffer_subject);
	my($counter, $counter_hit, @header_display, $counter_file);
	my($string_select_all, $string_select_empty, $string_unit_picture, $string_subject_empty);

	# イロイロ準備
	$string_select_all = $$ref_setting_list{'string_select_all:output'};
	$string_select_empty = $$ref_setting_list{'string_select_empty:output'};
	$string_unit_picture = $$ref_setting_list{'string_unit_picture:output'};
	$string_subject_empty = '{empty}';
	$tmp = $$ref_setting_list{'header_display:output'};
	$tmp =~ s/\s+//g;
	$tmp =~ tr/a-z/A-Z/;
	@header_display = split(',', $tmp);

	# 絞り込まれたファイルの情報を読み込む
	$counter_hit = 0;
	if ($$ref_form{'order'} eq 'old') {
		@tmp = sort(keys(%$ref_file));
	} else {
		@tmp = reverse(sort(keys(%$ref_file)));
	}
	while (@tmp) {
		$key = shift(@tmp);
		($flag_hit, $file_image, $image_format, $image_width, $image_height, $text_from, $text_to, $text_cc, $text_subject, $text_date, $counter_file, $text_body) = split("\t", $$ref_file{$key}, 12);
		$buffer_from{$text_from} ++;
		$buffer_to{$text_to} ++;
		$buffer_cc{$text_cc} ++;
		if ($text_subject eq '') {
			$buffer_subject{$string_subject_empty} ++;
		} else {
			$buffer_subject{$text_subject} ++;
		}
		if ($flag_hit eq 'yes') {
			$counter_hit ++;
			$image_size = -s ($$ref_setting_list{'directory_image:input'} . $file_image);
			$file_image =~ s/\%/\%25/g;	# ファイル名に含まれる % を，HTTP リクエスト後にも % と扱うため
			$tmp = $file_image;
			$tmp =~ s/^([^\/]+)\///;
			$date = $1;
			$tmp =~ s/\.[^\.]+$//;
			$file_image = $$ref_setting_list{'url_image_base:output'} . $file_image;
			# 一覧のテーブル
			$replace{'TABLE_LIST'} .= '<table class="mail" summary="(No.' . $counter_file . ')">' . "\n";
			$replace{'TABLE_LIST'} .= "\t" . '<tr>' . "\n";
			if ($$ref_setting_list{'use_popup:output'} eq 'no') {
				# 画像ポップアップページを使用しない
				$replace{'TABLE_LIST'} .= "\t\t" . '<th class="mail_image" rowspan="2"><img src="' . $file_image . '" class="mail" width="' . ($image_width * $$ref_form{'scale'}) . '" height="' . ($image_height * $$ref_form{'scale'}) . '" alt="(' . $image_size . 'bytes)"></th>' . "\n";
			} else {
				# 画像ポップアップページを使用する
				$replace{'TABLE_LIST'} .= "\t\t" . '<th class="mail_image" rowspan="2"><a href="' . $setting{'file_program'} . '?mode=popup&date_yyyymm=' . $date . '&file=' . $tmp . '&no=' . $counter_file . '" target="_blank"><img src="' . $file_image . '" class="mail" width="' . ($image_width * $$ref_form{'scale'}) . '" height="' . ($image_height * $$ref_form{'scale'}) . '" alt="(' . $image_size . 'bytes)"></a></th>' . "\n";
			}
			$replace{'TABLE_LIST'} .= "\t\t" . '<td class="mail_header">' . "\n";
			$replace{'TABLE_LIST'} .= "\t\t\t" . '<span class="mail_header_key">No.' . $counter_file . '</span><br>' . "\n";
			for ($counter = 0; $counter < scalar(@header_display); $counter ++) {
				$tmp = $header_display[$counter];
				if ($tmp eq 'FROM') {
					$replace{'TABLE_LIST'} .= "\t\t\t" . '<span class="mail_header_key">From:</span><br>' . &REMAKE_HEADER_BEFORE2AFTER('from', $text_from, $ref_header_table_before2after) . '<br>' . "\n";
				} elsif ($tmp eq 'TO') {
					$replace{'TABLE_LIST'} .= "\t\t\t" . '<span class="mail_header_key">To:</span><br>' . &REMAKE_HEADER_BEFORE2AFTER('to', $text_to, $ref_header_table_before2after) . '<br>' . "\n";
				} elsif ($tmp eq 'CC') {
					$replace{'TABLE_LIST'} .= "\t\t\t" . '<span class="mail_header_key">Cc:</span><br>' . &REMAKE_HEADER_BEFORE2AFTER('cc', $text_cc, $ref_header_table_before2after) . '<br>' . "\n";
				} elsif ($tmp eq 'SUBJECT') {
					if ($$ref_setting_list{'link_map:output'} eq 'yes') {
						$replace{'TABLE_LIST'} .= "\t\t\t" . '<span class="mail_header_key">Subject:</span><br>' . &LINK_GEOGRAPHIC_NAME(&REMAKE_HEADER_BEFORE2AFTER('subject', $text_subject, $ref_header_table_before2after), $ref_setting_list, '_blank') . &LINK_URL(&REMAKE_HEADER_BEFORE2AFTER('subject', $text_subject, $ref_header_table_before2after)) . '<br>' . "\n";
					} else {
						$replace{'TABLE_LIST'} .= "\t\t\t" . '<span class="mail_header_key">Subject:</span><br>' . &REMAKE_HEADER_BEFORE2AFTER('subject', $text_subject, $ref_header_table_before2after) . '<br>' . "\n";
					}
				} elsif ($tmp eq 'DATE') {
					# Date の短縮
					$text_date = substr($text_date, 0, 16);
					$replace{'TABLE_LIST'} .= "\t\t\t" . '<span class="mail_header_key">Date:</span><br>' . $text_date . '<br>' . "\n";
				}
			}
			$replace{'TABLE_LIST'} .= "\t\t" . '</td>' . "\n";
			$replace{'TABLE_LIST'} .= "\t" . '</tr>' . "\n";
			if ($text_body ne '') {
				$replace{'TABLE_LIST'} .= "\t" . '<tr>' . "\n";
				$replace{'TABLE_LIST'} .= "\t\t" . '<td class="mail_body">' . "\n";
				$replace{'TABLE_LIST'} .= "\t\t\t" . &LINK_URL($text_body) . "\n";
				$replace{'TABLE_LIST'} .= "\t\t" . '</td>' . "\n";
				$replace{'TABLE_LIST'} .= "\t" . '</tr>' . "\n";
			}
			$replace{'TABLE_LIST'} .= '</table>' . "\n";
		}
	}
	if ($counter_hit == 0) {
		# エラー表示
		$replace{'TABLE_LIST'} .= '<p><span class="error">ERROR: File not found in this condition.</span></p>' . "\n";
		if (($$ref_form{'from'} . $$ref_form{'to'} . $$ref_form{'cc'} . $$ref_form{'subject'} eq '') && (($$ref_form{'date_yyyymm'} eq '' ) || ($$ref_form{'date_yyyymm'} eq '00000000'))) {
			# デフォルト起動だったら情報を表示
			$replace{'TABLE_LIST'} .= &MAKE_MESSAGE_CHECK($ref_setting_list);
		}
	}
	# From
	$replace{'OPTION_FROM'} .= '<option value="">' . $string_select_all . "\n";
	if ($$ref_form{'from'} eq '') {
		$replace{'SHORTCUT_FROM'} .= '[<span class="selected">' . $string_select_all . '</span>] ' . "\n";
	} else {
		$tmp = '<a href="' . $setting{'file_program'} . '?' . &REMAKE_URL($ref_form, $ref_header_table_before2number, 'scale', 'order', 'to', 'cc', 'date_yyyymm', 'subject') . '">' . $string_select_all . '</a>';
		$replace{'SHORTCUT_FROM'} .= '[' . $tmp . '] ' . "\n";
	}
	if ($counter_hit == 0) {
		$replace{'SHORTCUT_FROM'} .= '[<span class="selected"><del class="error">' . &REMAKE_HEADER_BEFORE2AFTER('from', $$ref_form{'from'}, $ref_header_table_before2after) . '</del></span>] ' . "\n";
	}
	foreach $key (sort(keys(%buffer_from))) {
		if ($key ne "\x00") {
			$value = $buffer_from{$key};
			if ($key eq $$ref_form{'from'}) {
				$flag = ' selected';
				if ($counter_hit != 0) {
					$replace{'SHORTCUT_FROM'} .= '[<span class="selected">' . &REMAKE_HEADER_BEFORE2AFTER('from', $key, $ref_header_table_before2after) . '</span>] ' . "\n";
				}
			} else {
				$flag = '';
				$tmp = '<a href="' . $setting{'file_program'} . '?' . &REMAKE_URL($ref_form, $ref_header_table_before2number, 'scale', 'order', 'to', 'cc', 'date_yyyymm', 'subject') . '&' . 'from=' . &ESCAPE_URI(&REMAKE_HEADER_BEFORE2NUMBER('from', $key, $ref_header_table_before2number)) . '">' . &REMAKE_HEADER_BEFORE2AFTER('from', $key, $ref_header_table_before2after) . '</a>';
				$replace{'SHORTCUT_FROM'} .= '[' . $tmp . '] ' . "\n";
			}
			$replace{'OPTION_FROM'} .= '<option value="' . &ESCAPE_QUOTATION(&REMAKE_HEADER_BEFORE2NUMBER('from', $key, $ref_header_table_before2number)) . '"' . $flag . '>' . &REMAKE_HEADER_BEFORE2AFTER('from', $key, $ref_header_table_before2after) . ' (' . ($value) . $string_unit_picture . ')' . "\n";
		}
	}
	# To
	$replace{'OPTION_TO'} .= '<option value="">' . $string_select_all . "\n";
	if ($$ref_form{'to'} eq '') {
		$replace{'SHORTCUT_TO'} .= '[<span class="selected">' . $string_select_all . '</span>] ' . "\n";
	} else {
		$tmp = '<a href="' . $setting{'file_program'} . '?' . &REMAKE_URL($ref_form, $ref_header_table_before2number, 'scale', 'order', 'from', 'cc', 'date_yyyymm', 'subject') . '">' . $string_select_all . '</a>';
		$replace{'SHORTCUT_TO'} .= '[' . $tmp . '] ' . "\n";
	}
	if ($counter_hit == 0) {
		$replace{'SHORTCUT_TO'} .= '[<span class="selected"><del class="error">' . &REMAKE_HEADER_BEFORE2AFTER('to', $$ref_form{'to'}, $ref_header_table_before2after) . '</del></span>] ' . "\n";
	}
	foreach $key (sort(keys(%buffer_to))) {
		if ($key ne "\x00") {
			$value = $buffer_to{$key};
			if ($key eq $$ref_form{'to'}) {
				$flag = ' selected';
				if ($counter_hit != 0) {
					$replace{'SHORTCUT_TO'} .= '[<span class="selected">' . &REMAKE_HEADER_BEFORE2AFTER('to', $key, $ref_header_table_before2after) . '</span>] ' . "\n";
				}
			} else {
				$flag = '';
				$tmp = '<a href="' . $setting{'file_program'} . '?' . &REMAKE_URL($ref_form, $ref_header_table_before2number, 'scale', 'order', 'from', 'cc', 'date_yyyymm', 'subject') . '&' . 'to=' . &ESCAPE_URI(&REMAKE_HEADER_BEFORE2NUMBER('to', $key, $ref_header_table_before2number)) . '">' . &REMAKE_HEADER_BEFORE2AFTER('to', $key, $ref_header_table_before2after) . '</a>';
				$replace{'SHORTCUT_TO'} .= '[' . $tmp . '] ' . "\n";
			}
			$replace{'OPTION_TO'} .= '<option value="' . &ESCAPE_QUOTATION(&REMAKE_HEADER_BEFORE2NUMBER('to', $key, $ref_header_table_before2number)) . '"' . $flag . '>' . &REMAKE_HEADER_BEFORE2AFTER('to', $key, $ref_header_table_before2after) . ' (' . ($value) . $string_unit_picture . ')' . "\n";
		}
	}
	# Cc
	$replace{'OPTION_CC'} .= '<option value="">' . $string_select_all . "\n";
	if ($$ref_form{'cc'} eq '') {
		$replace{'SHORTCUT_CC'} .= '[<span class="selected">' . $string_select_all . '</span>] ' . "\n";
	} else {
		$tmp = '<a href="' . $setting{'file_program'} . '?' . &REMAKE_URL($ref_form, $ref_header_table_before2number, 'scale', 'order', 'from', 'to', 'date_yyyymm', 'subject') . '">' . $string_select_all . '</a>';
		$replace{'SHORTCUT_CC'} .= '[' . $tmp . '] ' . "\n";
	}
	if ($counter_hit == 0) {
		$replace{'SHORTCUT_CC'} .= '[<span class="selected"><del class="error">' . &REMAKE_HEADER_BEFORE2AFTER('cc', $$ref_form{'cc'}, $ref_header_table_before2after) . '</del></span>] ' . "\n";
	}
	foreach $key (sort(keys(%buffer_cc))) {
		if ($key ne "\x00") {
			$value = $buffer_cc{$key};
			if ($key eq $$ref_form{'cc'}) {
				$flag = ' selected';
				if ($counter_hit != 0) {
					$replace{'SHORTCUT_CC'} .= '[<span class="selected">' . &REMAKE_HEADER_BEFORE2AFTER('cc', $key, $ref_header_table_before2after) . '</span>] ' . "\n";
				}
			} else {
				$flag = '';
				$tmp = '<a href="' . $setting{'file_program'} . '?' . &REMAKE_URL($ref_form, $ref_header_table_before2number, 'scale', 'order', 'from', 'to', 'date_yyyymm', 'subject') . '&' . 'cc=' . &ESCAPE_URI(&REMAKE_HEADER_BEFORE2NUMBER('cc', $key, $ref_header_table_before2number)) . '">' . &REMAKE_HEADER_BEFORE2AFTER('to', $key, $ref_header_table_before2after) . '</a>';
				$replace{'SHORTCUT_CC'} .= '[' . $tmp . '] ' . "\n";
			}
			$replace{'OPTION_CC'} .= '<option value="' . &ESCAPE_QUOTATION(&REMAKE_HEADER_BEFORE2NUMBER('cc', $key, $ref_header_table_before2number)) . '"' . $flag . '>' . &REMAKE_HEADER_BEFORE2AFTER('cc', $key, $ref_header_table_before2after) . ' (' . ($value) . $string_unit_picture . ')' . "\n";
		}
	}
	# Subject
	foreach $key (sort(keys(%buffer_subject))) {
		if ($key ne "\x00") {
			if ($key eq $string_subject_empty) {
				# 空欄のとき
				$value = $buffer_subject{$key};
				if ($key eq $$ref_form{'subject'}) {
					$flag = ' selected';
					if ($counter_hit != 0) {
						$replace{'SHORTCUT_SUBJECT'} = '[<span class="selected">' . $string_select_empty . '</span>] ' . "\n" . $replace{'SHORTCUT_SUBJECT'};
					}
				} else {
					$flag = '';
					$tmp = '<a href="' . $setting{'file_program'} . '?' . &REMAKE_URL($ref_form, $ref_header_table_before2number, 'scale', 'order', 'from', 'to', 'cc', 'date_yyyymm') . '&' . 'subject=' . &ESCAPE_URI($key) . '">' . $string_select_empty . '</a>';
					$replace{'SHORTCUT_SUBJECT'} = '[' . $tmp . '] ' . "\n" . $replace{'SHORTCUT_SUBJECT'};
				}
				$replace{'OPTION_SUBJECT'} = '<option value="' . &ESCAPE_QUOTATION($string_subject_empty) . '"' . $flag . '>' . $string_select_empty . ' (' . ($value) . $string_unit_picture . ')' . "\n" . $replace{'OPTION_SUBJECT'};
			} else {
				# その他 (通常)
				$value = $buffer_subject{$key};
				if ($key eq $$ref_form{'subject'}) {
					$flag = ' selected';
					if ($counter_hit != 0) {
						$replace{'SHORTCUT_SUBJECT'} .= '[<span class="selected">' . &REMAKE_HEADER_BEFORE2AFTER('subject', $key, $ref_header_table_before2after) . '</span>] ' . "\n";
					}
				} else {
					$flag = '';
					$tmp = '<a href="' . $setting{'file_program'} . '?' . &REMAKE_URL($ref_form, $ref_header_table_before2number, 'scale', 'order', 'from', 'to', 'cc', 'date_yyyymm') . '&' . 'subject=' . &ESCAPE_URI(&REMAKE_HEADER_BEFORE2NUMBER('subject', $key, $ref_header_table_before2number)) . '">' . &REMAKE_HEADER_BEFORE2AFTER('subject', $key, $ref_header_table_before2after) . '</a>';
					$replace{'SHORTCUT_SUBJECT'} .= '[' . $tmp . '] ' . "\n";
				}
				$replace{'OPTION_SUBJECT'} .= '<option value="' . &ESCAPE_QUOTATION(&REMAKE_HEADER_BEFORE2NUMBER('subject', $key, $ref_header_table_before2number)) . '"' . $flag . '>' . &REMAKE_HEADER_BEFORE2AFTER('subject', $key, $ref_header_table_before2after) . ' (' . ($value) . $string_unit_picture . ')' . "\n";
			}
		}
	}
	$replace{'OPTION_SUBJECT'} = '<option value="">' . $string_select_all . "\n" . $replace{'OPTION_SUBJECT'};
	if ($$ref_form{'subject'} eq '') {
		$replace{'SHORTCUT_SUBJECT'} = '[<span class="selected">' . $string_select_all. '</span>] ' . "\n" . $replace{'SHORTCUT_SUBJECT'};
	} else {
		$tmp = '<a href="' . $setting{'file_program'} . '?' . &REMAKE_URL($ref_form, $ref_header_table_before2number, 'scale', 'order', 'from', 'to', 'cc', 'date_yyyymm') . '">' . $string_select_all . '</a>';
		$replace{'SHORTCUT_SUBJECT'} = '[' . $tmp . '] ' . "\n" . $replace{'SHORTCUT_SUBJECT'};
	}
	if ($counter_hit == 0) {
		if ($$ref_form{'subject'} eq $string_subject_empty) {
			$replace{'SHORTCUT_SUBJECT'} = '[<span class="selected"><del class="error">' . $string_select_empty . '</del></span>] ' . "\n" . $replace{'SHORTCUT_SUBJECT'};
		} else {
			$replace{'SHORTCUT_SUBJECT'} = '[<span class="selected"><del class="error">' . &REMAKE_HEADER_BEFORE2AFTER('subject', $$ref_form{'subject'}, $ref_header_table_before2after) . '</del></span>] ' . "\n" . $replace{'SHORTCUT_SUBJECT'};
		}
	}
	# Subject (value)
	$replace{'VALUE_SUBJECT'} = &ESCAPE_QUOTATION(&CUT_HTMLTAG(&REMAKE_HEADER_BEFORE2AFTER('subject', $$ref_form{'subject'}, $ref_header_table_before2after)));
	# Date (YYYYMM)
	$replace{'OPTION_DATE_YYYYMM'} .= '<option value="000000">' . $string_select_all . "\n";
	$tmp = '<a href="' . $setting{'file_program'} . '?' . &REMAKE_URL($ref_form, $ref_header_table_before2number, 'scale', 'order', 'from', 'to', 'cc', 'subject') . '&' . 'date_yyyymm=000000' . '">' . $string_select_all . '</a>';
	if ($$ref_form{'date_yyyymm'} eq '000000') {
		$replace{'SHORTCUT_DATE_YYYYMM'} .= '[<span class="selected">' . $string_select_all . '</span>] ' . "\n";
	} else {
		$replace{'SHORTCUT_DATE_YYYYMM'} .= '[' . $tmp . '] ' . "\n";
	}
#	if ($counter_hit == 0) {
#		$replace{'SHORTCUT_DATE_YYYYMM'} .= '[<span class="selected"><del class="error">' . $$ref_form{'date_yyyymm'} . '</del></span>] ' . "\n";
#	}
	foreach $key (reverse(sort(keys(%$ref_counter_month)))) {
		$value = $$ref_counter_month{$key};
		$date = substr($key, 0, 4) . '/' . substr($key, 4, 2);
		$tmp = '<a href="' . $setting{'file_program'} . '?' . &REMAKE_URL($ref_form, $ref_header_table_before2number, 'scale', 'order', 'from', 'to', 'cc', 'subject') . '&' . 'date_yyyymm=' . $key . '">' . $date . '</a>';
		if ($key eq $$ref_form{'date_yyyymm'}) {
			$flag = ' selected';
			$replace{'SHORTCUT_DATE_YYYYMM'} .= '[<span class="selected">' . $date . '</span>] ' . "\n";
		} else {
			$flag = '';
			$replace{'SHORTCUT_DATE_YYYYMM'} .= '[' . $tmp . '] ' . "\n";
		}
		$replace{'OPTION_DATE_YYYYMM'} .= '<option value="' . $key . '"' . $flag . '>' . $date . ' (' . ($value) . $string_unit_picture . ')' . "\n";
	}
	# Date (DD)
	$replace{'VALUE_DATE_DD'} = $$ref_form{'date_dd'};
	# subject_body
	$replace{'VALUE_SUBJECT_BODY'} = &ESCAPE_QUOTATION( $$ref_form{'subject_body'});
#	# subject_body_condition
#	if ($$ref_form{'subject_body_condition'} eq 'or') {
#		$replace{'CHECKED_SUBJECT_BODY_CONDITION_OR'} = 'checked';
#	} else {
#		$replace{'CHECKED_SUBJECT_BODY_CONDITION_AND'} = 'checked';
#	}
	# URL
	$replace{'URL_COPY'} = $setting{'file_program'} . '?' . &REMAKE_URL($ref_form, $ref_header_table_before2number, 'from', 'to', 'cc', 'subject', 'date_yyyymm', 'date_dd', 'subject_body');
	$replace{'URL_CLEAR'} = $setting{'file_program'} . '?' . '$$';
	# scale
	$replace{'VALUE_SCALE'} = $$ref_form{'scale'};
	if ($$ref_form{'scale'} eq '1') {
		$replace{'TAG_SCALE_1_OPEN'} = '<span class="location">';
		$replace{'TAG_SCALE_1_CLOSE'} = '</span>';
		$replace{'TAG_SCALE_2_OPEN'} = '<a href="' . $replace{'URL_COPY'} . '&order=' . $$ref_form{'order'} . '&scale=2">';
		$replace{'TAG_SCALE_2_CLOSE'} = '</a>';
	} else {
		$replace{'TAG_SCALE_1_OPEN'} = '<a href="' . $replace{'URL_COPY'} . '&order=' . $$ref_form{'order'} . '&scale=1">';
		$replace{'TAG_SCALE_1_CLOSE'} = '</a>';
		$replace{'TAG_SCALE_2_OPEN'} = '<span class="location">';
		$replace{'TAG_SCALE_2_CLOSE'} = '</span>';
	}
	# hit
	$replace{'VALUE_HIT'} = $counter_hit;
	# order
	if ($$ref_form{'order'} eq 'old') {
		$replace{'VALUE_ORDER'} = 'old';
		$replace{'SELECTED_ORDER_OLD'} = ' selected';
		$replace{'TAG_ORDER_OLD_OPEN'} = '<span class="location">';
		$replace{'TAG_ORDER_OLD_CLOSE'} = '</span>';
		$replace{'TAG_ORDER_NEW_OPEN'} = '<a href="' . $replace{'URL_COPY'} . '&scale=' . $$ref_form{'scale'} . '&order=new">';
		$replace{'TAG_ORDER_NEW_CLOSE'} = '</a>';
	} else {
		$replace{'VALUE_ORDER'} = 'new';
		$replace{'SELECTED_ORDER_NEW'} = ' selected';
		$replace{'TAG_ORDER_OLD_OPEN'} = '<a href="' . $replace{'URL_COPY'} . '&scale=' . $$ref_form{'scale'} . '&order=old">';
		$replace{'TAG_ORDER_OLD_CLOSE'} = '</a>';
		$replace{'TAG_ORDER_NEW_OPEN'} = '<span class="location">';
		$replace{'TAG_ORDER_NEW_CLOSE'} = '</span>';
	}
	# ユーザの値
	$replace{'SITE_TOP_NAME'} = $$ref_setting_list{'site_top_name:output'};
	$replace{'SITE_TOP_URL'} = $$ref_setting_list{'site_top_url:output'};
	$replace{'SITE_CLIPPIC_NAME'} = $$ref_setting_list{'site_clippic_name:output'};
	$replace{'STRING_UNIT_PICTURE'} = $string_unit_picture;
	if ($$ref_setting_list{'link_map:output'} eq 'yes') {
		# 地図リンク有効
		if ($$ref_setting_list{'link_map_2_length:output'} > 0) {
			if ($$ref_setting_list{'link_map_1_name:output'} eq $$ref_setting_list{'link_map_2_name:output'}) {
				if ($$ref_setting_list{'link_map_1_mark:output'} eq $$ref_setting_list{'link_map_2_mark:output'}) {
					$replace{'STRING_LINK_MAP'} = '[ ' . $$ref_setting_list{'link_map_1_mark:output'} . ' = ' . $$ref_setting_list{'link_map_1_name:output'} . ' ]';
				} else {
					$replace{'STRING_LINK_MAP'} = '[ ' . $$ref_setting_list{'link_map_1_mark:output'} . ',' . $$ref_setting_list{'link_map_2_mark:output'} . ' = ' . $$ref_setting_list{'link_map_1_name:output'} . ' ]';
				}
			} else {
				$replace{'STRING_LINK_MAP'} = '[ ' . $$ref_setting_list{'link_map_1_mark:output'} . ' = ' . $$ref_setting_list{'link_map_1_name:output'} . ', ' . $$ref_setting_list{'link_map_2_mark:output'} . ' = ' . $$ref_setting_list{'link_map_2_name:output'} . ' ]';
			}
		} else {
			$replace{'STRING_LINK_MAP'} = '[ ' . $$ref_setting_list{'link_map_1_mark:output'} . ' = ' . $$ref_setting_list{'link_map_1_name:output'} . ' ]';
		}
	}
	# テンプレートファイル内の特殊タグを置換して表示
	$tmp = &SELECT_TEMPLATE($setting{'dir_data'}, $$ref_setting_list{'file_template:output'}, $ref_setting_list, $ref_form);
	&OUTPUT_HTML(&REPLACE_STRING_HTML(&LOAD_TEMPLATE($tmp), \%replace), $$ref_setting_list{'html_jcode:output'});
	return;
}



# セクション: 画像ポップアップページの HTML 出力
sub SECTION_OUTPUT_POPUP {
	my($ref_setting_list, $ref_form, $ref_header_table_before2number, $ref_header_table_before2after) = @_;
	my($file_text, $file_image, $flag_exist, $tmp);
	my($ref_header, $ref_text, %replace);
	my($image_format, $image_width, $image_height);

	$tmp = $$ref_form{'date_yyyymm'} . '/' . $$ref_form{'file'};
	$file_text = $$ref_setting_list{'directory_text:input'} . $tmp . '.' . $$ref_setting_list{'filename_text_extension:input'};
	if (-f ($$ref_setting_list{'directory_image:input'} . $tmp . '.jpg')) { # 将来は 'jpg', 'jpeg', 'png', 'gif'
		$flag_exist = 'yes';
		$file_image = $$ref_setting_list{'directory_image:input'} . $tmp . '.jpg';
	} elsif (-f ($$ref_setting_list{'directory_image:input'} . $tmp . '.jpeg')) {
		$flag_exist = 'yes';
		$file_image = $$ref_setting_list{'directory_image:input'} . $tmp . '.jpeg';
	}
	if ($flag_exist eq 'yes') {
		# 画像ファイルが存在する
		($ref_header, $ref_text) = &EXTRACT_HEADER_FAST((&LOAD_FILE($file_text, 'direct'))[0]);
		($image_format, $image_width, $image_height) = &ANALYZE_IMAGE($file_image);
		# 置換用文字列を準備
		$replace{'FROM'} = &REMAKE_HEADER_BEFORE2AFTER('from', $$ref_header{'FROM'}, $ref_header_table_before2after);
		$replace{'TO'} = &REMAKE_HEADER_BEFORE2AFTER('to', $$ref_header{'TO'}, $ref_header_table_before2after);
		$replace{'CC'} = &REMAKE_HEADER_BEFORE2AFTER('cc', $$ref_header{'CC'}, $ref_header_table_before2after);
		$replace{'SUBJECT'} = &LINK_GEOGRAPHIC_NAME(&REMAKE_HEADER_BEFORE2AFTER('subject', $$ref_header{'SUBJECT'}, $ref_header_table_before2after), $ref_setting_list) . &LINK_URL(&REMAKE_HEADER_BEFORE2AFTER('subject', $$ref_header{'SUBJECT'}, $ref_header_table_before2after));
		$replace{'DATE'} = $$ref_header{'DATE'};
		$replace{'MAILBODY'} = &LINK_URL(join('<br>', @$ref_text));
		$replace{'VALUE_NO'} = $$ref_form{'no'};
		$replace{'IMAGE_WIDTH'} = ($image_width * $$ref_form{'scale'});
		$replace{'IMAGE_WIDTH_PLUS'} = ($image_width * $$ref_form{'scale'}) + 10;
		$replace{'IMAGE_HEIGHT'} = ($image_height * $$ref_form{'scale'});
		$replace{'IMAGE_SIZE'} = -s ($file_image);
		$file_image =~ s/^$$ref_setting_list{'directory_image:input'}//;
		$file_image =~ s/\%/\%25/g;	# ファイル名に含まれる % を，HTTP リクエスト後にも % と扱うため
		$replace{'VALUE_FILENAME'} = $$ref_setting_list{'url_image_base:output'} . $file_image;
		# scale
		$replace{'URL_COPY'} = $setting{'file_program'} . '?' . &REMAKE_URL($ref_form, undef, 'mode', 'date_yyyymm', 'file', 'no');
		$replace{'VALUE_SCALE'} = sprintf('%1.1f', $$ref_form{'scale'});
		$replace{'TAG_SCALE_SMALLER_OPEN'} = '<a href="' . $replace{'URL_COPY'} . '&scale=' . ($$ref_form{scale} - 0.5) . '">';
		$replace{'TAG_SCALE_SMALLER_CLOSE'} = '</a>';
		$replace{'TAG_SCALE_LARGER_OPEN'} = '<a href="' . $replace{'URL_COPY'} . '&scale=' . ($$ref_form{scale} + 0.5) . '">';
		$replace{'TAG_SCALE_LARGER_CLOSE'} = '</a>';
		if ($$ref_form{'scale'} == 1) {
			$replace{'TAG_SCALE_SMALLER_OPEN'} = '<del>';
			$replace{'TAG_SCALE_SMALLER_CLOSE'} = '</del>';
		} elsif ($$ref_form{'scale'} == 9) {
			$replace{'TAG_SCALE_LARGER_OPEN'} = '<del>';
			$replace{'TAG_SCALE_LARGER_CLOSE'} = '</del>';
		}
	}
	# ユーザの値
	$replace{'SITE_TOP_NAME'} = $$ref_setting_list{'site_top_name:output'};
	$replace{'SITE_TOP_URL'} = $$ref_setting_list{'site_top_url:output'};
	$replace{'SITE_CLIPPIC_NAME'} = $$ref_setting_list{'site_clippic_name:output'};
	# テンプレートファイル内の特殊タグを置換して表示
	&OUTPUT_HTML(&REPLACE_STRING_HTML(&LOAD_TEMPLATE($setting{'dir_data'} . $$ref_setting_list{'file_template_popup:output'}), \%replace), $$ref_setting_list{'html_jcode:output'});
	return;
}



#=============================================================================

# メールヘッダの抜き出し (高速版)
sub EXTRACT_HEADER_FAST {
	my($ref_text) = @_;
	my($counter, @text, %header, @body, $key, $value);
	my(@header);

	for ($counter = 0; $counter < scalar(@$ref_text); $counter ++) {
		if ($$ref_text[$counter] eq '') {
			last;
		}
	}
	@text = splice(@$ref_text, 0, $counter);
	@body = splice(@$ref_text, 1);
	while (@text) {
		($key, $value) = split(': ', shift(@text), 2);
		$key =~ tr/a-z/A-Z/;
		$header{$key} = $value;
	}
	return(\%header, \@body);
}



# ' と " をエスケープする
sub ESCAPE_QUOTATION {
	my($line) = @_;

	$line =~ s/"/&quot;/g;
	$line =~ s/'/&#39;/g;
	return($line);
}



# フォームデータのデコード
sub DECODE_CGI {
	my($method) = @_;
	my($line, $tmp, $code, @part, $variable, $value, %form, $i);

	if ($method eq '') {
		$method = $ENV{'REQUEST_METHOD'};
	}
	if ($method eq 'POST') {
		read(STDIN, $line, $ENV{'CONTENT_LENGTH'});
	} elsif ($method eq 'GET') {
		$line = $ENV{'QUERY_STRING'};
	}
	# 入力文字コードの検知を試みる
	$tmp = $line;
	$tmp =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack('C', hex($1))/eg;
	$code = jcode::getcode(\$tmp);
	# ハッシュに代入
	@part = split('&', $line);
	foreach $i (@part) {
		($variable, $value) = split('=', $i);
		$variable =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack('C', hex($1))/eg;
		$value =~ tr/+/ /;
		$value =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack('C', hex($1))/eg;
		jcode::convert(\$value, 'euc', $code, 'z');
		$value =~ s/\015\012/\012/g;
		$value =~ s/\015/\012/g;
		$value =~ s/\t/ /g;
		$value =~ s/^\s+//;
		$value =~ s/^　+//;
		$value =~ s/\s+$//;
		$value =~ s/　$//;
		$value =~ s/&/&amp;/g;
		$value =~ s/</&lt;/g;
		$value =~ s/>/&gt;/g;
		$form{$variable} = $value;
	}
	return(\%form);
}



# HTML 出力
sub OUTPUT_HTML {
	my($ref_text, $code) = @_;
	my($cr_http) = "\x0D\x0A";
	my(%charset) = ('sjis' => 'Shift_JIS', 'jis' => 'ISO-2022-JP', 'euc' => 'EUC-JP');

	$| = 1;
	print 'Content-Type: text/html; charset=' . $charset{$code} . $cr_http;
	$ref_text = &CONVERT_JCODE($ref_text, $code);
	print 'Content-Length: ' . length($$ref_text) . $cr_http . $cr_http;
	print $$ref_text;
	$| = 0;
	return;
}



# 指定ディレクトリ以下の，指定拡張子のファイル名を得る
sub GREP_FILE {
	my($dir, $extension) = @_;
	my(@file_root, $file_root, @file_sub, $file_sub);
	my(@file_list, $dir_last, $tmp);

	opendir(DIR, $dir);
	@file_root = sort(grep(/[^\.]/, readdir(DIR)));
	closedir(DIR);
	while (@file_root) {
		$tmp = shift(@file_root);
		$file_root = $dir . $tmp;
		if (-d $file_root) {
			opendir(DIR, $file_root);
			@file_sub = sort(grep(/[^\.]/, readdir(DIR)));
			closedir(DIR);
			while (@file_sub) {
				$file_sub = $file_root . '/' . shift(@file_sub);
				if (($file_sub =~ /\.$extension$/) && (-f $file_sub)) {
					push(@file_list, $file_sub);
					$dir_last = $tmp;
				}
			}
		} elsif (($file_root =~ /\.$extension$/) && (-f $file_root)) {
			push(@file_list, $file_root);
		}
	}
	return(\@file_list, $dir_last);
}



# 画像のフォーマット・縦横サイズを取得する (今のところ JPEG のみ)
sub ANALYZE_IMAGE {
	my($file) = @_;
	my($t, $mark, $c, $l);
	my($format, $width, $height);

	$format = 'JPEG';
	open(FILE, "$file");	# 参考: ClipBoard <http://www.kent-web.com/>
	binmode FILE;
	read(FILE, $t, 2);
	while (1) {
		read(FILE, $t, 4);
		($mark, $c, $l) = unpack("a a n", $t);
		if ($mark ne "\xFF") {
			($width, $height) = (0, 0);
			last;
		} elsif ((ord($c) >= 0xC0) && (ord($c) <= 0xC3)) {
			read(FILE, $t, 5);
			($height, $width) = unpack("xnn", $t);
			last;
		} else {
			read(FILE, $t, ($l - 2));
		}
	}
	close(FILE);
	return($format, $width, $height);
}



# HTML タグをカットする (↓非常に参考: <http://www.din.or.jp/~ohzaki/perl.htm#Tag_Remove>)
sub CUT_HTMLTAG {
	my($str) = @_;
	my($tag_regex_, $comment_tag_regex, $tag_regex, $text_regex, $result, $tag_tmp);

	$tag_regex_ = q{[^"'<>]*(?:"[^"]*"[^"'<>]*|'[^']*'[^"'<>]*)*(?:>|(?=<)|$(?!\n))};
	$comment_tag_regex = '<!(?:--[^-]*-(?:[^-]+-)*?-(?:[^>-]*(?:-[^>-]+)*?)??)*(?:>|$(?!\n)|--.*$)';
	$tag_regex = qq{$comment_tag_regex|<$tag_regex_};
	$text_regex = q{[^<]*};
	while ($str =~ /($text_regex)($tag_regex)?/gso) {
		last if $1 eq '' and $2 eq '';
		$result .= $1;
		$tag_tmp = $2;
		if ($tag_tmp =~ /^<(XMP|PLAINTEXT|SCRIPT)(?![0-9A-Za-z])/i) {
			$str =~ /(.*?)(?:<\/$1(?![0-9A-Za-z])$tag_regex_|$)/gsi;
			$result .= $1;
		}
	}
	return($result);
}



# 地名らしき文字列をリンク化する
sub LINK_GEOGRAPHIC_NAME {
	my($text, $ref_setting_list, $target) = @_;
	my($url_base_1, $url_base_2, $mark_1, $mark_2, $jcode_1, $jcode_2, $length_2);
	my($url, $mark);

	# 変数代入
	$url_base_1 = $$ref_setting_list{'link_map_1_url:output'};
	$url_base_2 = $$ref_setting_list{'link_map_2_url:output'};
	$mark_1 = $$ref_setting_list{'link_map_1_mark:output'};
	$mark_2 = $$ref_setting_list{'link_map_2_mark:output'};
	$jcode_1 = $$ref_setting_list{'link_map_1_jcode:output'};
	$jcode_2 = $$ref_setting_list{'link_map_2_jcode:output'};
	$length_2 = $$ref_setting_list{'link_map_2_length:output'};
	if ($target ne '') {
		$target = ' target="' . $target . '"';
	}
	# マーク生成
	if ($text =~ /^(.+)(都|道|府|県)(.+)(市|区|郡)/) {
		$url = $url_base_1 . &ESCAPE_URI(${&CONVERT_JCODE(\$text, $jcode_1)});
		$mark = '<a href="' . $url . '"' . $target . '>' . $mark_1 . '</a>';
	} elsif (($length_2 > 0) && ($text ne '') && (length($text) >= $length_2)) {
		if ($text =~ / /) {
			$url = $url_base_2 . &ESCAPE_URI('"' . ${&CONVERT_JCODE(\$text, $jcode_2)} . '"');
		} else {
			$url = $url_base_2 . &ESCAPE_URI(${&CONVERT_JCODE(\$text, $jcode_2)});
		}
		$mark = '<a href="' . $url . '"' . $target . '>' . $mark_2 . '</a>';
	}
	return($mark);
}



# GET メソッド用の URL を作る
sub REMAKE_URL {
	my($ref_form, $ref_header_table_before2number, @key) = @_;
	my($key, $value, $line);
	my($amp) = '&';

	while(@key) {
		$key = shift(@key);
		if (defined($ref_header_table_before2number)) {
			$value = &ESCAPE_URI(&REMAKE_HEADER_BEFORE2NUMBER($key, $$ref_form{$key}, $ref_header_table_before2number));
		} else {
			$value = &ESCAPE_URI($$ref_form{$key});
		}
		if ($value ne '') {
			$line .= $key . '=' . $value . $amp;
		}
	}
	$line = substr($line, 0, - length($amp));
	return($line);
}



# メールヘッダエイリアス機能: 内部表現 (非公開) を外部表現 (公開) に変換
sub REMAKE_HEADER_BEFORE2AFTER {
	my($key, $before, $ref_header_table_before2after) = @_;

	if ($$ref_header_table_before2after{$key . "\t" . $before} ne '') {
		return($$ref_header_table_before2after{$key . "\t" . $before});
	} else {
		return($before);
	}
}



# メールヘッダエイリアス機能: 内部表現 (非公開) を {数値} に変換
sub REMAKE_HEADER_BEFORE2NUMBER {
	my($key, $before, $ref_header_table_before2number) = @_;

	if ($$ref_header_table_before2number{$key . "\t" . $before} ne '') {
		return($$ref_header_table_before2number{$key . "\t" . $before});
	} else {
		return($before);
	}
}



# 文字列中に URL が含まれていたらリンクを張る
sub LINK_URL {
	my($text) = @_;
	my($regex) = $setting{'url_http_regex'};

	$text =~ s/($regex)/<a href="$1" target="_blank">$1<\/a>/ogi;
	return($text);
}



# テンプレートファイルを決定する
sub SELECT_TEMPLATE {
	my($dir, $file_default, $ref_setting_list, $ref_form) = @_;
	my($key, $value, $file);
	my(@header) = ('from', 'to', 'cc', 'subject');

	$file = $dir . $file_default;
	while(@header) {
		$key = shift(@header);
		if ($$ref_form{$key . '_original'} =~ /^\{(\d+)\}$/) {
			$value = $$ref_setting_list{'alias_' . $key . '_' . ($1) . '_file_template:output'};
			if (($value ne '') && (-e ($dir . $value))) {
				$file = $dir . $value;
				last;
			}
		}
	}
	return($file);
}



# 日本語コードを変換
sub CONVERT_JCODE {
	my($ref_text, $code) = @_;

	if (($code eq 'jis') || ($code eq 'sjis')) {
		jcode::convert($ref_text, $code, 'euc');
	}
	return($ref_text);
}



# URI エスケープする (<http://www.din.or.jp/~ohzaki/perl.htm#JP_Escape> を参考)
sub ESCAPE_URI {
	my($line) = @_;

	$line =~ s/([^\w ])/'%' . unpack('H2', $1)/eg;
	$line =~ tr/ /+/;
	return($line);
}



# 設定ファイルのキャッシュを読み込む
sub LOAD_FILE_CACHE {
	my($file) = @_;
	my($file_cache) = &CONVERT_FILENAME_CACHE($file);
	my($key, %output);
	my($line, $counter);

	if ((-e $file) && (-w $file_cache) && ((-M $file) > (-M $file_cache))) {
		# 自分で更新可能なキャッシュファイルがあり，それが元ファイルより新しい
		open(FILE_CACHE, $file_cache) || return('no');
		$counter = 0;
		while (defined($line = <FILE_CACHE>)) {
			chop($line);
			if (($counter % 2) == 0) {
				$key = $line;
			} else {
				$output{$key} = $line;
			}
			$counter ++;
		}
		close(FILE_CACHE);
		return('yes', \%output);
	} else {
		return('no');
	}
}



# 設定ファイルのキャッシュを保存する
sub SAVE_FILE_CACHE {
	my($file, $ref_output) = @_;
	my($file_cache) = &CONVERT_FILENAME_CACHE($file);
	my($key, $value, $file_rename);

	$file_rename = &LOCK_FILE($file_cache);
	open(FILE_CACHE, ">$file_rename");
	chmod((stat($file))[2], $file_rename);
	while (($key, $value) = each(%$ref_output)) {
		print FILE_CACHE $key . "\n";
		print FILE_CACHE $value . "\n";
	}
	close(FILE_CACHE);
	&UNLOCK_FILE($file_rename);
	return;
}



# 設定の再チェックを促すメッセージを表示する
sub MAKE_MESSAGE_CHECK {
	my($ref_setting_list) = @_;
	my($text);

	$text = <<_END_OF_TEXT_;
<p>
「画像は存在していて，設定も合っているはずなんだけど画像がまったく表示されない (いつも0枚)」<br>
という場合は，下記のことをチェックしてみてください。
</p>
<ol>
	<li>次の二つの値が一致するように設定されているかどうか。
	<ol type="a">
		<li>設定ファイル clippic_mail_user.cgi の directory_image = (ここには表示されません。設定ファイルから読みとってください)
		<li>設定ファイル $setting{'file_data'} の directory_image = $$ref_setting_list{'directory_image:input'}
	</ol>
	<li>次の二つの値が一致するように設定されているかどうか。
	<ol type="a">
		<li>設定ファイル clippic_mail_user.cgi の directory_text = (ここには表示されません。設定ファイルから読みとってください)
		<li>設定ファイル $setting{'file_data'} の directory_text = $$ref_setting_list{'directory_text:input'}
	</ol>
	<li>参考: 本プログラムの絶対パスは次のようになっています。あなたのウェブ公開ディレクトリの絶対パスが何か，正確に分かるはずです。
	<ul>
		<li>環境変数 SCRIPT_FILENAME = $ENV{'SCRIPT_FILENAME'}
	</ul>
</ol>
_END_OF_TEXT_
	return($text);
}



#
sub CALC_DISTANCE {
	# http://village.infoweb.ne.jp/~kubota01/newpage31.htm
	return;
}
