#!/usr/local/bin/perl
# make diary's index files
# $Id: mkdiary.pl,v 1.30 2002/01/23 14:35:46 yuuji Exp $

sub usage {
    print<<_EOU_;
年/月/日 というディレクトリ構成で日記をつける場合の、
「月」に相当するディレクトリのindex.htmlを生成します。
生成するindex.htmlは、たとえば以下のような見出しになります。
  12月
	1日 - 師走の風景
	25日 - 今日はクリスマス
それぞれのタイトルは、12/01/index.html, 12/25/index.html の中に最初に
現れるH1タグの中身となります。

起動方法: mkdiary.pl 「月」ディレクトリ…
以下のオプションが使用できます。
	-bg			index.htmlの背景色
	-f フッタファイル	body末尾に挿入するファイル
	-c confファイル		動作設定ファイル(~/.${myname}rc)
	-date 西暦年/月/日	その日のテンプレートHTMLを吐き出す
	-s			Stream(メイルで自動登録)モード

詳しくは http://www.gentei.org/~yuuji/diary/mkdiary/manual.html みてちょ。
_EOU_
    exit 0;
}

##
# Global variables
##
$mydir=''; $myname=''; $wday=''; $date=''; $youbi='';

($mydir, $myname) = ($0 =~ m,(.*)/(.*),);

$mybase = ($myname =~ m,([^.]*)(\.pl)?,)[0];
{
    local($cwd) = (`pwd`);
    chop $cwd;
    chdir $mydir;
    chop($mydir=`pwd`);
    chdir $cwd;
}


# ↓これらの変数の値を変えるときは ~/.mkdiraryrc に書いておく。
#   たとえば、背景色を白にしたいときは bg=white のように書く。
%opt =
 (
  'bg',		"lightseagreen",		# 背景色
  'fg',		"",				# 前景(文字)色
  'tojis',	"/usr/local/bin/nkf",		# 任意→jis
  'toeuc',	"/usr/local/bin/nkf -e",	# 任意→euc
  'euctojis',	"/usr/local/bin/nkf -Ej",	# euc→jis
  'outcode',	"jis",				# 生成ファイルコード(eucかjis)
  'decode64',	 "/usr/local/bin/mewdecode",	# base64デコードプログラム
  'titleleft',	"【",				# 表題の左側につける 【 とか
  'titleright',	"】",				# 表題の右側につける 】 とか
  'm',		"見出し",			# デフォルトの見出し
  'header',	"$mydir/header",		# htmlの先頭につけるやつ
  'footer',	"$mydir/footer",		# htmlの末尾につけるやつ
  'day_ascend',	1,				# 日付を昇順にソート
  'need_wday',	1,				# 曜日表示を付ける
  'body_opt',	"",				# bodyに付ける他のオプション
  'word_DIARY',	"Diary",			# タイトルに使うDiaryという単語
  'yearformat',	"%d年の日記",			# 年INDEXのタイトル書式
  'css_yearly',	"",				# 年INDEXcssファイル(必要なら)
  'yearleading',"",				# 年INDEXのタイトル直後の文句
  'monthheading',1,				# 「X月」標示をする
  'conf',	"$ENV{HOME}/.${mybase}rc",
  'debugfile',	"$mydir/debug",			# debugメッセージファイル
  'mail',	"/usr/bin/mail",		# mailコマンドのパス
  'notify',	0,				# mail更新通知するかどうか
  'ownotify',	1,				# mail更新時の上書き通知
  'gnutar',	"gtar",				# GNU tar コマンド
  'unzip',	"unzip",			# zipファイル展開用コマンド
  'lha',	"lha",				# lzhファイル展開用コマンド
  'bodyfilter',	"",				# 本文を食わすフィルタコマンド
  'bmp2jpg',	0,				# BMPをJPEGにするか
  'bmp2png',	0,				# BMPをPNGにするか
  'convert',	"convert",			# convertコマンド
  # 'bodyfilter',	"./body2html.rb",
  );


%readonlyopts=();
sub setoptreadonly {
    for (@_) {
	$readonlyopts{$_} = 1;
    }
}
sub isoptreadonly {
    return $readonlyopts{$_[0]};
}

&setoptreadonly('allow', 'owner');

(eval 'require "timelocal.pl"', $@ eq '')
  || (eval 'use "timelocal"', $@ eq '')
  || die "Cannot find timelocal library.\n";

sub day_week {
    local($y, $m, $d) = @_;
    $_ = &timelocal(0, 0, 0, $d, $m-1, $y-1900);
    "(" . ("日", "月", "火", "水", "木", "金", "土")[(localtime($_))[6]]
      . ")";
}

sub setdatevars {
    local($y, $m, $d) =  ($date =~ m,(\d\d\d\d+)/([01]?\d)/([0-3]?\d),);
    $_ = &timelocal(0, 0, 0, $d, $m-1, $y-1900);
    $wday = (localtime($_))[6];
    $youbi = ("日", "月", "火", "水", "木", "金", "土")[$wday];
    $wday = ("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat")[$wday];
}

sub daytitle {
    # 引数ディレクトリのタイトルを返す
    local($dir) = @_;
    local($index, @title) = ("$dir/index.html", ());
    local($bs) = (-s $index);
    open(DAYINDEX, $index)
	|| return undef; # die "$index がないみたいっす";
    select((select(DAYINDEX), $/="")[$[]);
    $_='';
    read(DAYINDEX, $_, $bs);
    close(DAYINDEX);
    s/\n//g;				  # 一気に読んで改行を削る
    @title = split(/<H1>/i, $_);	  # <h1>で分離
    @title = grep(/H1/i, split(/<H1>/i, $_));
    grep(s|</[Hh]1>.*$||g, @title);	  # </h1>以降切り落とす
    grep(s/^\s+//, @title);		  # 行頭行末スペース切除
    grep(s/\s+$//, @title);
    grep(s/^/$opt{"titleleft"}/, @title);
    grep(s/$/$opt{"titleright"}/, @title);
    # print "titles=", join(", ", @title), "\n";
    join(", ", @title);
}

sub monthlist {
    local($monthdir) = @_;
    opendir(MONTH, $monthdir);
    local(@months) = readdir(MONTH);
    closedir(MONTH);
    @months = grep(-d "$monthdir/$_", grep(/\d\d?/, @months));
    local($d, %list);
    %list = ();

    for $d (@months) {
	# push(@list, &daytitle("$monthdir/$d"));
	$list{$d} = &daytitle("$monthdir/$d")
	  if (-s "$monthdir/$d/index.html");
	# print "list{$d} =", &daytitle("$monthdir/$d"), "\n";
    }
    %list;
}

sub mkmonthindex {
    1;
}

sub mydirname {
    local($dir, $d) = @_;
    local($myino) = (stat($dir))[1];
    die "ルートディレクトリでやるこたないっしょ\n"
	if ($myino == (stat("$dir/.."))[1]);

    opendir(PARENT, "$dir/..")
	|| die "親ディレクトリの読み取り権限下さい";
    local(@p) = readdir(PARENT);
    closedir(PARENT);
    for $d (@p) {
	next if (! -d "$dir/../$d");
	if ((stat("$dir/../$d"))[1] == $myino) {
	    print "hogehoge\n" if $debug;
	}
	print "ここは $d\n" if $debug;
	return $d if ((stat("$dir/../$d"))[1] == $myino);
	$d = '';			  # for success flag
    }
    die "カレントディレクトリ名がどうも読めないん酢...";
}

sub mkyearindex {
    local($yeardir) = @_;
    die "$yeardir って無いんですけど…\n" unless (-d $yeardir);
    local($y, $m, $day, %title, @dir) = (&mydirname($yeardir));
    local($text) = ($opt{'fg'} || "black");
    die "$yeardir じゃなくて西暦年のディレクトリを指定してね\n"
	unless ($y =~ /\d\d\d\d+/);

    # まずヘッダ
    open(INDEX, "| $outfilter > $yeardir/index.html")
	|| die "$yeardir/index.html に書けないよ。なじぇ?\n";
    select INDEX;
    printf "<html>
<head><title>$opt{'word_DIARY'} of $y</title>
$opt{'yearstyle'}%s</head>
<body text=\"$text\" bgcolor=\"$opt{'bg'}\"$opt{'body_opt'}>
", $opt{'css_yearly'}
  ? "<link rel=\"stylesheet\" type=\"text/css\" href=\"$opt{'css_yearly'}\">"
    : "";
    printf "<h1>$opt{'yearformat'}</h1>\n", $y;
    print "$opt{'yearleading'}\n" if $opt{'yearleading'};
    print "<dl>\n";
    opendir(DIR, $yeardir) || die "$yeardir が読めるようにして下さいな\n";
    @dir = readdir(DIR);
    closedir(DIR);
    @dir = grep(/^\d+$/, @dir);
    for $m (sort {$b <=> $a} @dir) {	  # これは新しい順
	next unless ($m =~ /\d\d?/);
	printf " <hr>\n <dt> %d月\n", $m if $opt{'monthheading'};
	%title = &monthlist("$yeardir/$m");
	for $day ($opt{'day_ascend'} ? sort {$a <=> $b} keys(%title) : sort {$b <=> $a} keys(%title)) { # これはオプション day_ascend に従う
	    printf(" <dd> <a href=\"$m/$day/\">%s${day}%s</a>%s - %s\n",
		   $opt{'monthheading'} ? "" : "$m/",
		   $opt{'monthheading'} ? "日" : "",
		   $opt{'need_wday'} ? &day_week($y, $m, $day) : "",
		   $title{$day});
	}
    }
    print "</dl>\n";
    if (-f $opt{"footer"}) {
	open(FOOTER, "$opt{footer}");
	print while (<FOOTER>);
	close(FOOTER);
    }
    close(INDEX);
    select STDOUT;
}

sub _ascending {$a <=> $b}
sub _decsending {$b <=> $a}

sub mkdir_p {	# mkdir -p と同じ事をする。ああperlってディレクトリ処理弱い
    local(@component) = split(m,/,, $_[0]);
    local($path, $x) = ("");
    for $x (@component) {
	$path .= "$x";
	mkdir($path, 0755) unless (-d $path);
	$path .= "/";
    }
}

sub header {
    local($file) = @_;
    $file = $opt{'header'} unless ($file);
    local($str) = ('');
    if (-r $file && open(CREATEH, $file)) {
	while (<CREATEH>) {
	    s/%TITLE%/$opt{'word_DIARY'} of $date/g;
	    s/%BG%/$opt{'bg'}/g;
	    s/%DATE%/$date/g;
	    s/%HEADING%/$opt{'m'}/g;
	    s/%WDAY%/$wday/g;
	    s/%YOUBI%/$youbi/g;
	    $str .= $_;
	}
	close(CREATEH);
	return $str;
    } else {
	die "$file ってファイルが開けないっす\n";
    }
}

sub footer {
    &header($opt{'footer'});
}

sub create {		# 指定した日付のテンプレートを吐き出す
    $date = $_[0];
    chdir $mydir;
    die "$mydir に書き込みできましぇん.\n"
	. "$myname は日記基準ディレクトリに置いてね\n"
	    unless (-w $mydir);
    die "日付は $date じゃなくて 1999/10/10 のように指定して下さい.\n"
	unless ($date =~ m,\d\d\d\d+/\d\d?/\d\d?,);
    &setdatevars;
    &mkdir_p($date);

    if (! -r "$opt{header}") {
	die "$opt{header} というファイルにhtmlの先頭の見本を入れておいて下さい\n";
    }
    if (! -f "$opt{footer}") {
	die "$opt{footer} というファイルにhtmlの末尾の見本を入れておいて下さい\n";
    }
    local($header, $footer) = (&header(), &footer);
    if (! -f "$date/index.html") {
	print "$date の日記ファイルを準備します\n" unless $quiet;
	open(CREATEI, "| $outfilter > $date/index.html");
	print CREATEI $header, $footer;
	close(CREATEI);
	unless ($quiet) {
	    open(CREATEI, "$date/index.html");
	    print while (<CREATEI>);
	    close(CREATEI);
	}
    } else {
	print "既に $date/index.html あるのでなんもしません.\n" unless $quiet;
    }
}

sub today {
    # どうせ日付変わってから書くこと多いと思うので、
    # GMTで8時間前の日付で作ったほうがええっしょ:-)
    local($y, $m, $d) = (gmtime)[5,4,3];
    sprintf("%d/%02d/%02d", 1900+$y, 1+$m, $d);
}

sub readconf {
    local($conf) = ($opt{'conf'});
    $conf = "$mydir/.${mybase}rc" if (-f "$mydir/.${mybase}rc");
    return unless (-s $conf);
    if (open(READCONF, "$conf")) {
	local($var, $val, $continue);
	while (<READCONF>) {
	    if (/^$/) {
		$var = $continue = '';
	    } elsif (/^\s*\#/) {
		next;
	    } elsif ($continue && $var) { # preceding line ends with \
		# add this line literally to last set variable
		if (/\\$/) {
		    $continue = 1;
		    $opt{$var} .= $`;
		} else {
		    $opt{$var} .= $_;
		    $continue = 0;
		}
	    } elsif (/^\s(\s*\S.*)$/ && $var) { # continue line with \n
		# add \n and this line with one preceding white space stripped
		# to last set variable
		$_ = $1;
		if (/\\$/) {
		    $continue = 1;
		    $opt{$var} .= "\n$`";
		} else {
		    $opt{$var} .= "\n$_";
		    $continue = 0;
		}
	    } else {
		($var, $val) = m,([^= \t]+)\s*=\s*(.*)$,;
		if ($var) {
		    $val =~ s/^([\"\'])(.*)\1/$2/; #"
		    if ($val =~ /\\$/) {
			$val = $`;
			$continue = 1;
		    } else {
			$continue = 0;
		    }
		    $opt{$var} = $val;
		    print "$var set to $val\n" if ($debug);
		}
	    }
	}
	close(READCONF);
    }
}

#############################################
# Streamモード - メイルで受け取って自動処理
# メイル本体の構文
#	Subject: 日付
#	m=見出し
sub getheader {
    local($last, %headerinfo);
    while (<>) {
	chop;
	last if (/^$/);
	if (/^\s/ && $last) {
	    s/^\s+//;
	    $headerinfo{$last} .= "\n $_";
	} elsif (/^([A-z][^:]+):\s+(.*)/) {
	    $headerinfo{$1} = "$2";
	    $last = $1;
	} else {  ; }			  # just skip other lines
    }
    return %headerinfo;
}

sub extract_archive {
    # in:	"directory/archivefile.ext"
    # job:	extract "archivefile.ext" in "directory"
    local($dir, $archive) = ($_[0] =~ m,(.*)/(.*),);
    local($extcmd, $pid, $pid2);
    $_ = $archive;
    if (/tar$/i) {
	$extcmd = "$opt{gnutar} xpf";
    } elsif (/tar.(gz|Z)$/i) {
	$extcmd = "$opt{gnutar} zxpf";
    } elsif (/zip$/i) {
	$extcmd = "$opt{unzip}";
    } elsif (/lzh|lha$/i) {
	$extcmd = "$opt{lha} x";
    } else {
	&notifyto($opt{'owner'}, 'mkdiary-extract-unknown',
		  "添付した $dir/$fn の展開方法わかりませぬ.\n"
		  . "lha, tar(+gzip), zip のどれかにしてね.");
    }
    $extcmd .= " $archive";
    unless ($pid = open(CMD, "-|")) {
	# if child
	$ENV{"PATH"} = "/bin:/usr/bin:/usr/local/bin:$ENV{PATH}";
	chdir($dir);
	$| = 1;
	close(STDIN); close(STDOUT);
	exec split(' ', $extcmd);
    }
    if (!defined($pid)) {
	&notifyto($opt{'owner'}, 'mkdiary-extract-exec-error',
		  "添付した $dir/$fn の展開時に $extcmd が起動できんかった\n");
    }
    # 時間制限
    $file_to_remove = "$dir/$archive";
    alarm(10);				  # 10秒で十分じゃろ?
    $SIG{"ALRM"} = "kill_me";
    close(CMD);
    unlink("$dir/$archive");
}
$file_to_remove='';
sub kill_me { unlink($file_to_remove); kill 3, $$; }

sub extract_multipart {
    # in:	(multipart boundary string), (output dir)
    # job:	extract all attached binary files
    # out:	text/plain lines as array
    local($boundary, $dir) = @_;
    local(%h, $fn, @text);
    while ($_=<> ne "--$boundary\n") {};  # Skip to the first boundary
    while (%h=&getheader) {
	local($ct) = ($h{'Content-Type'});
	$ct =~ s/\n/ /g;		  # for latter regexp matching
	if ($ct =~ m,text/plain,i) {
	    while (<>) {
		last if ($_ eq "--$boundary\n");
		push(@text, $_);
	    }
	} elsif ($ct =~ m,image|audio|video|application/octet-stream,i
		 && $h{'Content-Transfer-Encoding'} =~ m,^base64,i) {
	    $fn = ($h{'Content-Disposition'}
		   =~ m,filename=(['"]?)([^'"]+)\1,)[1];
	    unless ($fn) {
	        $fn = ($h{'Content-Type'}
		    =~ m,name=(['"]?)([^'"]+)\1,i)[1];
	    }
	    unless ($fn) {
	    	$fn = "dummy.output";
	    }
	    if (open(DECODE64, "| $opt{'decode64'} >$dir/$fn")) {
		while (<>) {
		    last if ($_ eq "--$boundary\n" 
			     || $_ eq "--$boundary--\n");
		    print DECODE64;
		}
		close(DECODE64);
		if (-s "$dir/$fn") {
		    if ($ct =~ /octet-stream/i) {
			if ($fn =~ /lzh|tar(\.(gz|Z))?|tgz|zip/) {
			    &extract_archive("$dir/$fn");
			} elsif ($fn =~ /\.(bmp|tiff?)$/i) {
			    local ($fmt, $target, $pid);
			    if ($opt{"bmp2jpg"}) {
				$fmt = "jpg";
			    } elsif ($opt{"bmp2png"}) {
				$fmt = "png";
			    }
			    if ($fmt) {
				($target = $fn) =~ s/\.(bmp|tiff?)$/.$fmt/i;
				if (fork()) { #parent
				    wait;
				} else {
				    exec $opt{"convert"},
				      "-format", $fmt, "$dir/$fn",
					"$dir/$target", ();
				}
				if (-s "$dir/$target") {
				    unlink("$dir/$fn");
				} else {
				    &notifyto($opt{'owner'},
					      'mkdiary-extract-error',
					      "添付画像 $fmt 化に失敗
convert(ImageMagickに付属)をインストールしましょう。");
				}
			    }
			}
		    }
		} else {		  # 0 byte output, maybe failure
		    unlink("$dir/$fn");
		    &notifyto($opt{'owner'}, 'mkdiary-extract-error',
			      "添付した $fn の展開に失敗");
		}
	    } else {
		while (<>) {last if ($_ eq "--$boundary\n");}
	    }
	} elsif ($ct =~ /^multipart.*boundary=([\'\"]?)([^'"]+)\1/i) {
	    # $2 is new boundary ## print "newb=[$2]\n";
	    @_ = &extract_multipart($2, $dir);
	    # push(@text, @_);
	} elsif ($ct =~ m,Message/Rfc822,) {
	    &doStream;			  # ネストは一回に限る(手抜き)
	} else {
	    # 知らないのでスキップ
	    while (<>) {
		last if ($_ eq "--$boundary\n"
			|| $_ eq "--$boundary--\n");
	    }
	}
	last if ($_ eq "--$boundary--\n"); # current multipart ends
    }
    return @text;
}
sub debugout {
    local($mes) = @_;
    open(DEBUG, ">> $opt{'debugfile'}")
	|| die "Some error occurs, but couldn't open debug log file\n";
    print DEBUG "$mes\n";
    close(DEBUG);
}

sub notifyto {				  # ownerにメッセージ送信
    local($to, $subj, @mes) = @_;
    open(MAIL, "| $opt{'tojis'} | $opt{mail} -s '$subj' $to")
	|| &debugout("Cannot start $opt{mail} command");
    print MAIL @mes;
    close(MAIL);
}

sub bodyfilter {
    # Convert plain text to (maybe) HTML, if the filter is specified.
    local ($dir, @contents) = (@_);
    return @contents unless $opt{'bodyfilter'};
    return @contents if $opt{'bodyfilter'} =~ /^(none|no|nil|null|off)\b/i;
    # return @contents unless (-x $opt{'bodyfilter'});
    local @newcontents, $filter;
    if (!open(CHILD, "-|")) {
	# child
	select CHILD; $|=1;
	if (!open(ENC, "|-")) {
	    # child of child
	    $filter =  $opt{'bodyfilter'};
	    $filter = "$mydir/$filter" if (-x "$mydir/$filter");
	    chdir($dir);
	    $ENV{'PATH'} .= ":$mydir";
	    exec "/bin/sh", "-c", $filter, ();
	    print "<!-- Filter execution of $opt{'bodyfilter'} failed -->\n";
	    print @contents;
	} else {
	    # parent of child
	    select ENC;
	    $| = 1;
	    print ENC @contents;
	    close(ENC);
	    exit 0;
	}
    } else {
	# parent
	while (<CHILD>) {
	    push(@newcontents, $_);
	}
    }
    wait;
    if (@newcontents && $? == 0) {
	return @newcontents;
    } else {
	return @contents;
    }
}

sub confcheck {
    unless (defined $opt{"allow"}) {print "[allow] not defined\n";}
    unless (defined $opt{"owner"}) {print "[owner] not defined\n";}
    if ($opt{"owner"} eq '' || $opt{"allow"} eq '') {
	print STDERR ".mkdiary ファイルには最低限 owner, allow は" .
	  "設定しておいて下さい\n";
	exit 1;
    }
}

sub doStream {
    &confcheck;
    local(%h) = &getheader;
    $date = $h{"Subject"};
    local($today, $y, $m, $d, $sender) = (&today);
    # Dirty workaround for gentei.org
    $ENV{"PATH"} .= ":/usr/local/bin:/usr/local/bin/ImageMagick";

    # set default y/m/d
    ($y, $m, $d) = ($today =~ m,(\d\d\d\d+)/([01]?[0-9])/([0-3]?[0-9]),);

    # today's directory assumption
    if ($date =~ m,(\d\d\d\d+)/([01]?[0-9])/([0-3]?[0-9]),) {
	($y, $m, $d) = ($1, $2, $3);
    } elsif ($date =~ m,([01]?[0-9])/([0-3]?[0-9]),) {
	($m, $d) = ($1, $2);
    } elsif ($date =~ /yesterday/i) {
	($y, $m, $d) = (localtime(time-60*60*24))[5,4,3];
	$y += 1900; $m++;
    } elsif ($date =~ /(\d+)\s*days?.*ago/i) {
	($y, $m, $d) = (localtime(time-60*60*24*$1))[5,4,3];
	$y += 1900; $m++;
    } elsif ($date =~ m,([0-3]?[0-9]),) {
	$d = $1;
    }
    # Regulate date values
    if ($d > 31 || $d < 1 || $m > 12 || $m < 1 || $y < 1999) {
	($y, $m, $d) = (gmtime)[5,4,3];
	$y+=1900; $m++;
	&notifyto($opt{'owner'}, 'mkdiary-warning',
		  "日付指定がおかしい ($date) ので\n今日の日付" .
		  "($y/$m/$d)に強制的に設定しました\n");
    }

    $date = sprintf("%d/%02d/%02d", $y, $m, $d);
    &setdatevars;

    # configuration check (who is the owner)
    unless ($opt{'owner'}) {
	&debugout("$opt{'conf'}に owner=メイルアドレス って書いといてね");
	exit(0);
    }
    unless ($opt{'allow'}) {
	&notifyto($opt{'owner'}, 'mkdiary-error',
		  "$opt{'conf'}に allow=メイルアドレス って書いといてね");
	exit(0);
    }
    # authentication
    $sender = $ENV{'SENDER'} || $ENV{'UFLINE'} ||
	$h{'Sender'} || $h{'Return-Path'};
    $sender =~ s/^<(.*)>$/$1/;
    # matching done here
    unless ($sender =~ m,$opt{'allow'},) {
	&notifyto($opt{'owner'}, 'mkdiary-illegal-access',
		  "$sender さんから $mybase 更新依頼が来たけど\n" .
		  "その人は更新許可与えられてないんです.\n" .
		  "もし本人なら $opt{conf} ファイルの allow= 行に\n" .
		  "足しましょう。複数のアドレスを登録したいときは\n" .
		  'allow=yuuji@gentei.org|yuuji@hoge.hero.boo' .
		  "\nのように | で区切って書きます.");
	exit(0);
    }

    local($targetdir, $eod) = ("$mydir/$date", "<!-- end of diary -->\n");
    local($html) = ("$targetdir/index.html");
    umask(022);
    &mkdir_p($targetdir);
    # auth OK, now begin to generate
    local($title, @header, @contents) = ($date);
    # parse stdin
    if ($h{'Content-Type'} =~ m,multipart/mixed,i) {
	# decompose multipart and push all text part into @contents
	local($ct, $boundary) = ($h{'Content-Type'});
	$boundary = ($ct =~ m,boundary=(['"]?)([^'\"]+)\1,i)[1]; #"
	push(@contents, &extract_multipart($boundary, $targetdir));
    } else {
	# conventional mail. simply put text into @contents
	while (<>) {
	    push(@contents, $_);
	}
    }
    # parse embeded option
    while ($contents[0] =~ /(^[a-z]+)=(.*)\n/) {
	if (&isoptreadonly($1)) {
	    &notifyto($opt{'owner'}, "mkdiry-illegal-access",
		      "$sender からのアクセスで、勝手にownerを" .
		      "変えようとしましたが、\nそゆことはできねす.\n");
	    exit 0;
	}
	$opt{$1} = $2;
	# printf "opt$1 set to $2\n";
	shift @contents;
    }
    if (-d "$targetdir" && -s "$html") {
	if ($opt{'append'} || $opt{'tasu'} || $opt{'tsuika'}) {
	    # append=yes なら追加処理. そうでなければ上書き
	    if (open(HTML, "$html")) {
		while (<HTML>) {
		    last if ($_ eq $eod);
		    last if (m,</body>,);
		    push(@header, $_);
		}
		close(HTML);
	    } else {
		&notifyto($opt{'owner'}, 'mkdiary-error',
			  "appendモード指定しましたが元ファイルが開けなかったの.");
		exit 0;
	    }
	} else {
	    # 上書き
	    if ($opt{'ownotify'}) {	  # 上書き通知あり
		if (open(HTML, $html)) {
		    @_ = <HTML>;
		    &notifyto($opt{'owner'}, "mkdiary-overwrite-backup",
			      "既に↓こゆ日記があったのでバックアップと" .
			      "してとっといてちょ.\n\n", @_);
		    close(HTML);
		} else {
		    &notifyto($opt{'owner'}, "mkdiary-overwrite-backup-failed",
			      "日記上書き前のバックアップ失敗\n", @_);
		}
	    } else {
		# なんもせんでええ
	    }
	    unlink($html);
	    @header = &header();
	}
    } else {
	# 初期のときはデフォルトのヘッダ
	@header = &header();
    }
    open(HTML, "| $outfilter > $html");
    select((select(HTML), $|=1)[$[]);	  # avoid dups with forked process.
    print HTML @header;
    print HTML &bodyfilter($targetdir, @contents);
    print HTML $eod;
    print HTML &footer;
    close(HTML);
    if ($opt{'notify'} && open(HTML, "$html")) {
	@_ = <HTML>;
	&notifyto($opt{'owner'}, 'mkdiary-update-report',
		  "↓こんなんなりましたけどー\n\n", @_);
	close(HTML);
    }

    &mkyearindex("$mydir/$y");
    # exit 0;
}

sub timeout {
    die "alarm clock restart";
}
sub lock {
    eval {
	local $SIG{'ALRM'} = 'timeout';
	alarm 10;
	flock("$mydir/lockfile", $LOCK_EX);
	alarm 0;
    };
    if ($@ and $@ !~ /alarm clock restart/) {die;}
}
sub unlock {
    flock("$mydir/lockfile", $LOCK_UN);
}

while ($_=$ARGV[0], /^-.+/ && shift) {
    last if /^--$/;
    while (/^-[A-z]/) {
	if (/^-bg/) {
	    $opt{'bg'} = shift; last;
	} elsif (/^-f$/) {
	    $opt{'footer'} = shift; last;
	} elsif (/^-date$/) {
	    # &create(shift);
	    $today = shift;
	} elsif (/^-today$/) {
	    # &create_today(shift);
	    $today = &today;
	} elsif (/^-c$/) {
	    $opt{'conf'} = shift; last;
	} elsif (/^-D$/) {
	    $debug++;
	} elsif (/^-s$/) {
	    $doStream=1;
	    last;
	} 
        s/^-.(.*)/-$1/;
    }
}

&readconf;
$outfilter = $opt{'tojis'};
$outfilter = $opt{'toeuc'} if ($opt{'outcode'} =~ /euc/i);

if ($today) {
    &create($today);
} elsif ($doStream) {
    &lock();
    &doStream;
    &unlock();
    exit 0;
} elsif(-d $ARGV[0]) {
    &mkyearindex($ARGV[0]);
} else {
    &usage;
}

# $Log: mkdiary.pl,v $
# Revision 1.30  2002/01/23 14:35:46  yuuji
# Fix
#
# Revision 1.29  2002/01/23 09:55:37  yuuji
# Call bodyfilter process from today's directory.
#
# Revision 1.28  2002/01/22 13:40:22  yuuji
# Match with "boundary=..." case insensitive
#
# Revision 1.27  2001/08/30 05:45:38  yuuji
# $opt{"convert"}
#
# Revision 1.26  2001/08/30 04:57:35  yuuji
# Convert bmp/tiff to jpg/png
#
# Revision 1.25  2001/08/29 14:39:32  yuuji
# Support H"-s odd style of multipart.
#
# Revision 1.24  2001/01/27 15:09:14  yuuji
# Misplaced lines for debug removed.
#
# Revision 1.23  2001/01/26 17:05:55  yuuji
# Use flock();
#
# Revision 1.22  2001/01/26 06:43:16  yuuji
# Add $mydir to $PATH at invoking bodyfilter.
# Include new bodyfilter `./href' which converts http://xxx/yyy/(comment) to
# <a href="/http://xxx/yyy/">comment</a>.
#
# Revision 1.21  2001/01/26 04:45:28  yuuji
# New options;
#  - outcode	File code of generated HTML files (`euc' or `jis')
#  - css_yearly	CSS definition file name of yearly index
#  - monthheading	Need the name of each month in yearly index (1)
# Supplying `nil' or `none' (or so) to the option `bodyfilter'
# inhibits the use of bodyfilter.  So a line of;
# bodyfilter=none
# at the beginning of diary-mail writes following body directly to
# the diary file of the day.
#
# Revision 1.20  2001/01/24 15:57:33  yuuji
# -D option for $debug
# Daily title uses $opt{'word_DIARY'}
#
# Revision 1.19  2001/01/24 11:01:13  yuuji
# Fix: chdir to $mydir at calling bodyfilter
#
# Revision 1.18  2001/01/24 06:58:50  yuuji
# bodyfilter support
#
# Revision 1.17  2001/01/24 03:16:27  yuuji
# *** empty log message ***
#
# Revision 1.16  2001/01/24 03:15:52  yuuji
# New option day_ascend, need_wday, body_opt, word_DIARY
