#!%PERL_PATH%
#注意 perl version 5 のあるディレクトリにして下さい。
## mail2nikki.pl (Project SHIMONODA)
## Version 0.74 (12/23/2000)

# Copyright (C) 1998-2000  Ken-ichi HASHIMOTO, HyperNikkiSystem Project

# Special Thanks:
#  Mori Kouji <moriko@hh.iij4u.or.jp>
#  Seiji Hamaguchi <makoto@zob.ne.jp> 
#  Masato Kawakami <masato@orange.co.jp>
#  TOKUMITSU Satoshi <tokumitsu@three-a.co.jp>

# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

# $Id: mail2nikki.pl.in,v 1.18 2000/12/23 10:17:58 kenji Exp $

require '%HTMLDIR%/lib/jcode.pl';

use MIME::Parser;
use MIME::Head;

# $diaryDir 日記のあるディレクトリ
$diaryDir    = "%DIARYDIR%";

# 報告を受け取るアドレス．
$mailAddress = '%FROMADDR%';
# 投稿を許すアドレス(From認証) -複数のアドレスが登録可能です-
@certiy_mailAddress = ('%FROMADDR%', 'second_address');
# 報告メールの From: アドレス
$recvMailAddress = '%FROMADDR%';
# GET の時に送るアドレス
$cmdGetAddress = '';	## 「hnf:GET」を送ったメールアドレスが入ります

# パスワードです。
$MASTERPASSWD = "%PASSWORD%";

# 日記ファイルディレクトリの対応
$hnfDir = 1;	# 1 分散管理(ex ~/diary/1998/19981201.hnf), 0 一括管理
# LOGMODE 全文ログを取得する時  0 エラー時のみ, 1 常に, 2 絶対しない
$LOGMODE = 0;
# status reporting mail
$MAILMODE = 0;  # 1 無条件で動作報告メール
# use nkf?
$NKF_USE = 1;	# 1 -> Use (default), 0 -> No Use
# auto signature cut
$SIG_CUT = 0;	# 1 Signatureを削除する
$SIG_PATTERN = '^-- $'; # Signatureの開始行の正規表現

# Update Namazu index? 
$NamazuExecFlag = 0;	# 0 -> no (default), 1 -> yes
# where is hns-index?
$MkNamazuPath = "$ENV{'HOME'}/diary/bin/hns-index";

# sendmail の場所 各サーバによって違うでしょう
$sendmail = "%SENDMAIL_PATH%";
# nkf の場所 確かめてね
$nkf      = "%NKF_PATH%";

# // 画像まわり
# 画像ファイルを置くディレクトリ(public_html以下)
$graphic_outputdir	= "%HTMLDIR%/img/";

# その画像ファイルの URL (ディレクトリまで)
$graphic_uri = "%MYDIARYURI%/img/";

# NEW 行が空だったら時刻を付加する(1)  しない(0)
$isaddtime = 1;

$mimetmp = "$diaryDir/bin/mimetmp.$$";



##  install 方法
## 1. $HOME/diary/bin/mail2nikki.pl に これを copy 
## 2. chmod 700 mail2nikki.pl
## 3. mail2nikki.pl の 設定
## 4. $HOME/diary/mail を作成 ( mkdir を使って )
## 5. .forward の設定
#例:
# inseki:~$ cat .forward 
#\ken,"|/home/ken/diary/bin/mail2nikki.pl "

## 日記の登録方法
## Subject: hnf:ADD
## 本文に
## PASSWORD: <password>
## [DATE: 19981109]   (省略可能,省略時 mail を処理した日付)
## (改行1つ)
## 日記本文
## END 文頭まで hnf に登録


############################
### You DON'T have to change 
###

# qmail だと 600 の permission だから
# Thanks. masakazu@yamada.gr.jp
umask(022);

# 一応バックアップするので そのファイル。
$backupFile  = "$diaryDir/mail/backup";

# 安全のために処理したメールは LOG に保存
$logFile        = "$diaryDir/mail/mail.log";
# 簡易ログ
$SimpleLogFile  = "$diaryDir/mail/simple.log";
# 作業ファイル
$mailTempFile   = "$diaryDir/mail/file.$$";


@hnfCommandHash = ('NO','DEL&ADD','ADD','DEL','GET');
@hnfObjectHash = ('NO','DIARY','PLAN','TODO','REPEAT');


# メール送信
# 例: Sendmail( "/usr/sbin/sendmail" , "aite@hoge.jp" , 
#	        "jibun@geho.jp" , "title" , \@body );
sub Sendmail {
    my ( $sendmail , $to , $from , $subject , $body ) = @_;

    open(MAIL,"|$sendmail -t");

    print MAIL "To: $to\n";
    print MAIL "From: <$from>\n";
    print MAIL "Subject: $subject\n\n";
    
    for( @$body )
    {
	print MAIL "$_\n";
    }

    close (MAIL);
}

sub OkMail {
    @mbody = ( 'This messege was written by mail2nikki.pl.' ,
	       'System transact your mail.');
    push( @mbody , $_[0] );
    if ($loopcheck == 0) {
      Sendmail( $sendmail , $mailAddress 
	     , "$recvMailAddress" , "[mail2nikki] transact complete" 
	     , \@mbody ); 
    }
}
sub NgMail {
    @mbody = ( 'This messege was written by mail2nikki.pl.' ,
	       'System DON\'T transact your mail.');
    push( @mbody , $_[0] );
    if ($loopcheck == 0) {
      Sendmail( $sendmail , $mailAddress 
	     , "$recvMailAddress" , "[mail2nikki] transact faled" 
	     , \@mbody ); 
    }
}
# 表示部分
sub HnsPrint {
    for( @body )
    {
	print OUT "$_";
    }
}


# log に保存
sub savelog {
    open( OUT , ">>$logFile" );    
    print OUT "---- START ----\n";
    print OUT "---- HEAD -----\n";
    for( @headers )
    {
	print OUT "$_";
    }
    print OUT "\n";
    print OUT "---- HNF HEAD -----\n";
    for( @hnfheaders )
    {
	if( /^(PASSWORD|PASSWD): /i )
	{   
	    print OUT "PASSWD: ****************\n"; 
	}
	else
	{
	    print OUT "$_";
	}
    }
    print OUT "---- HNF BODY -----\n";
    for( @body )
    {
	print OUT "$_";
    }
    print OUT "---- HNF FOOT -----\n";
    for( @foot )
    {
	print OUT "$_";
    }
    print OUT "---- STATE -----\n";
    print OUT "PASSWORD : $PASSWORD \n";
    print OUT "HNF MODE : $HnsMode \n";
    print OUT "HNF OBJ  : $HnsObj \n";
    print OUT "---- END ----\n";
    close(OUT);
}


sub copy {
  my ($from, $to) = @_;
  my @tmp;

  open (TEMP, $from) || die "can't open: $!";
  while (<TEMP>) {
    &jcode::convert(\$_, 'euc');
    push (@tmp, $_);
  }
  close(TEMP);
  open (FILE, ">$to") || die "can't open: $!";
  foreach (@tmp) {
    print FILE $_;
  }
  close(FILE);
}


sub copy_jis {
  my ($from, $to) = @_;
  my @tmp;

  open (TEMP, $from) || die "can't open: $!";
  while (<TEMP>) {
    &jcode::convert(\$_, 'jis');
    push (@tmp, $_);
  }
  close(TEMP);
  open (FILE, ">$to") || die "can't open: $!";
  foreach (@tmp) {
    print FILE $_;
  }
  close(FILE);
}


sub append {
  my ($from, $to) = @_;
  my @tmp;

  open (TEMP, $from) || die "can't open: $!";
  while (<TEMP>) {
    &jcode::convert(\$_, 'euc');
    push (@tmp, $_);
  }
  close(TEMP);
  open (FILE, ">>$to") || die "can't open: $!";
  foreach (@tmp) {
    print FILE $_;
  }
  close(FILE);
}


sub cvs_add_commit {
	my ($file) = @_;
	my ($filedir, $base);
	$base = (split('/', $file))[-1];
	$filedir = $file;
	$filedir =~ s!/[^\/]+$!!;
#	system("cd $filedir; cvs add $base; cvs commit -m 'Update by mail'");
}

sub
extractEntity($$)
{
	my $entity = shift;
	my $outputdir = shift;

	my @parts = $entity->parts;
	my @mailbody;

	if(! $entity->is_multipart){
		$mailbody[0] .= $entity->bodyhandle->as_string . "\n";
	}
	else{
	$mailbody[0] .= $entity->parts(0)->bodyhandle->as_string . "\n";

	for($i=1; $i<$entity->parts; $i++){
		my $mimetype = $entity->parts($i)->head->mime_type;
		if($mimetype =~ /^(text\/plain|message\/rfc822)$/){
			$mailbody[0] .= $entity->parts($i)->bodyhandle->as_string . "\n";
		}
		elsif($mimetype =~ /^image\//){
				$filename = $entity->parts($i)->head->recommended_filename;
				fileWrite($outputdir . "/" . $filename,
						$entity->parts($i)->bodyhandle->as_string
						 );
				push(@mailbody, $filename);
		}
	}
	}
	return @mailbody;
}

sub
fileWrite($$)
{
	if(!open(FH, ">".$_[0])){
		die $!;
	}
	print FH $_[1];
	close(FH);
}

sub
splitCR($)
{
	my @src = split(/\n/, $_[0]);
	my @array;

	foreach(@src){
		last if /^END/;
		last if /^!#EOF/;
		last if /$SIG_PATTERN/o && $SIG_CUT;
		s/[\r\n]//g;
		push(@array, $_ . "\n");
	}
	return @array;
}

sub
getTime()
{
	my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
	return sprintf("%02d:%02d:%02d", $hour, $min, $sec);
}



$loopcheck = 0;
# /* sendmail から渡されたヘッダを登録 */
while($_=<STDIN>)
{
    if (/^Subject: \[mail2nikki\]/) {
      $loopcheck = 1;
    }
    last if /^\r?\n$/;
    s/\r?\n$/\n/;
    if (/^\s/) {
       $_ = pop( @headers ) . $_;
    }
    push( @headers,$_ );
}

$HnsFlag = 0;
$Correct = "No";
$i = 0;
$imax = @certiy_mailAddress - 1;
$HnsMode = 0;
for( @headers )
{

#    /* 認証 メールアドレス だけしか見てないけどね(^^;) */
    if( /^From: / )
    {
#	$HnsFlag = 1 if( /$mailAddress/ );

	while( $Correct eq "No" ){
		if( /@certiy_mailAddress[$i]/ ){
			$HnsFlag = 1;
			$Correct = "Yes";
			$cmdGetAddress = @certiy_mailAddress[$i];  ##
		} elsif ($i < $imax){
			$i = $i + 1;
		} else {
			$HnsFlag = 0;
			$Correct = "Yes";
		}
	}
    }
#    /* ヘッダみて それぞれを 選択 (ごしごし、じゃぶじゃぶ 洗濯開始) */
    if(/^Subject: (hnf|hns):(ADD|DEL|DEL&ADD|GET) *(PLAN|TODO|REPEAT)?/)
    {
        $HnsMode = 2 if( /ADD/ );
        $HnsMode = 3 if( /DEL/ );
	$HnsMode = 1 if( /DEL&ADD/ );
	$HnsMode = 4 if( /GET/ );
	$HnsObj = 1;
        if( /PLAN/ )
	{
	    $HnsObj = 2;
	    $file = $pfile;
	}
        if( /TODO/ )
	{
	    $HnsObj = 3;
	    $file = "$diaryDir/todo";
	}
        if( /REPEAT/ )
	{
	    $HnsObj = 4;
	    $file = "$diaryDir/repeat";
	}
    }
}


# /* Subject 日記のだったらデコード */
if($HnsMode){
	my $parser = new MIME::Parser;
	$parser->output_to_core(1);
	$parser->tmp_recycling(1);
	$parser->tmp_to_core(0);
	$parser->use_inner_files(0);

#	seek(STDIN, 0, 0); /* パイプだと seek() できない*/
	open(MIMETMP, ">" . $mimetmp) or die $!;
	foreach(@headers){ print MIMETMP; }
	print MIMETMP "\r\n";
	while($_=<STDIN>){ print MIMETMP; }
	close(MIMETMP);

	open(MIMETMP, $mimetmp) or die $!;
	$entity = $parser->read(\*MIMETMP) or die("couldn't parse MIME stream");
	close(MIMETMP);
	unlink($mimetmp);

	@MailBody = extractEntity($entity, $graphic_outputdir);
}
else{
	exit;
}

@header_body = splitCR($MailBody[0]);

# hnf 用ヘッダと本体
$location=0;
foreach $string(@header_body)
{
	if ($string =~ /^Subject: \[mail2nikki\]/) {
	  $loopcheck = 1;
	}
	if(($string =~ /^\n$/) && ($location == 0)){
		$location = 1;
	}

	if($location==0){
		push(@hnfheaders, $string);
	}
	elsif($location==1){
		push(@body, $string);
		if($string =~ /^NEW/ && $HnsMode == 2){ # // ADD だったら NEW のあとに画像タグ

			if($string eq "NEW\n" && $isaddtime){
				pop(@body);
				push(@body, "NEW " . getTime() . "\n");
			}
			for(my $cnt=1; $cnt<=$#MailBody; $cnt++){
				push(@body, "IMG r " . $graphic_uri . $MailBody[$cnt] ."\n");
			}
		}
	}
}
# <br clear="all"> が入ってないせいで画像の後のレイアウトがずれる場合は
# テーマ修正でなんとかしてください。


# 処理時間取得
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
$year = $year + 1900;
$mon  = $mon + 1;
$mday = "0$mday" if $mday < 10;
$mon  = "0$mon"  if $mon  < 10;
$sec  = "0$sec"  if $sec  < 10;
$min  = "0$min"  if $min  < 10;
$hour = "0$hour" if $hour < 10;

if( $hnfDir == 1 )
{
    if ( !( -d $diaryDir . "/" . $year ) )
    {
	system("mkdir $diaryDir/$year;chmod 755 $diaryDir/$year");
    }
    $file = "$diaryDir/$year/d$year$mon$mday.hnf";
    $pfile = "$diaryDir/$year/y$year$mon";
}
else
{
    $file = "$diaryDir/d$year$mon$mday.hnf";
    $pfile = "$diaryDir/y$year$mon";
}

# /* header 解析は上に移動しました */

$PASSWORD = 0;
for( @hnfheaders )
{
    if( /^(PASSWORD|PASSWD)\s*:\s*$MASTERPASSWD/i )
    {

#    @list = split( /\s*:\s*/ , $_ );
#    $tmp = shift( @list );
#    $tmp = shift( @list );
#    $PASSWORD = 1 if ( $MASTERPASSWD =~ /$tmp/ ) ;

	$PASSWORD = 1;
	next;
    }
    if( /^DATE\s*:\s*/ && $HnsObj == 1 )
    {
	@list = split( /\s*:\s*/ , $_ );
	$tmp = shift( @list );
	$tmp = shift( @list );
	chop $tmp;
	if( $tmp =~ /([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9])/ )
	{
	    $year = $1;
	    if( $hnfDir == 1 )
	    {
		if ( ! (-d $diaryDir . "/" . $year) )
		{
		    system("mkdir $diaryDir/$year;chmod 755 $diaryDir/$year");
		}

		$file = "$diaryDir/$year/d$tmp.hnf";
	    }
	    else
	    {
		$file = "$diaryDir/d$tmp.hnf";
	    }
	}
	else
	{
	    $file = "$diaryDir/d$tmp.hnf";
	}
	next;
    }
    if( /^DATE\s*:\s*/ && $HnsObj == 2 )
    {
	@list = split( /\s*:\s*/ , $_ );
	$tmp = shift( @list );
	$tmp = shift( @list );
	chop $tmp;
	if( $tmp =~ /([0-9][0-9][0-9][0-9])([0-9][0-9])/ )
	{
	    $year = $1;
	    if( $hnfDir == 1 )
	    {
		if ( ! (-d $diaryDir . "/" . $year) )
		{
		    system("mkdir $diaryDir/$year;chmod 755 $diaryDir/$year");
		}

		$file = "$diaryDir/$year/y$tmp";
	    }
	    else
	    {
		$file = "$diaryDir/y$tmp";
	    }
	}
	else
	{
	    $file = "$diaryDir/y$tmp";
	}
	next;
    }

    push( @userVar , $_ );
}

open( SLOG , ">>$SimpleLogFile" );
$slogMsg = "[$year/$mon/$mday:$hour:$min:$sec]"
           . " COMMAND=$hnfCommandHash[$HnsMode]"
           . " OBJ=$hnfObjectHash[$HnsObj]"
           . " PASSWD=$PASSWORD"
	   . " LOOPCHK=$loopcheck";

print SLOG "$slogMsg";

if( $PASSWORD == 0)
{
    print SLOG " STATE=ERROR\n";
    close( SLOG );
    savelog() if( $LOGMODE != 2 ) ;
    NgMail( $slogMsg ) if( $MAILMODE == 1 );
    exit;
}

if( $LOGMODE == 1 )
{
    savelog();
}


#   /* CREATE なら 新しくファイルを開いて OK を書いてから、mailの本文 */
if( $HnsMode == 1 )
{
    if( $HnsFlag )
    {
	# 作業ファイルに一度いれる。
	open( OUT , ">$mailTempFile" );
	for( @userVar )
	{
	    print OUT "$_";
	}
	print OUT "OK\n\n" if ($HnsObj == 1);
	HnsPrint();
	close( OUT );

	# 作業ファイルからコピーする する。
	if ($NKF_USE) {
	  system( "$nkf -e < $mailTempFile > $file" );
	}
	else {
	  copy ($mailTempFile, $file);
	}
	unlink "$mailTempFile";
	print SLOG " STATE=DONE\n";
	close( SLOG );
	OkMail ($slogMsg . "\n-- body\n" . join('', @body)) if $MAILMODE == 1;

	# Update Namazu index
	system("$MkNamazuPath") if $NamazuExecFlag == 1;

	# cvs_add_commit ($file);
	exit;
    }
}

# /* APPEND で */
if( $HnsMode == 2 )
{
    if( $HnsFlag )
    {
	if(-f "$file")
	{
#	/* 既にファイルがあるなら そのまま */
	    if ($NKF_USE) {
	      system( "$nkf -e < $file > $mailTempFile");
	    }
	    else {
	      copy ($file, $mailTempFile);
	    }
	    system( "cp $mailTempFile $file" );

	    open( OUT , ">$mailTempFile" );
#    /* mail の本文 */
	    HnsPrint();
	    close( OUT );
	    # 作業ファイルからコピーする する。
	    if ($NKF_USE) {
	      system( "$nkf -e < $mailTempFile >> $file" );
	    }
	    else {
	      append ($mailTempFile, $file);
	    }
	    unlink "$mailTempFile";

	}
	else
	{
#	/* なかったら 作って OK をだして */
	    # 作業ファイルに一度いれる。
	    open( OUT , ">$mailTempFile" );
	    for( @userVar )
	    {
		print OUT "$_";
	    }
	    print OUT "OK\n\n" if ($HnsObj == 1);
#    /* mail の本文 */
	    HnsPrint();
	    close( OUT );
	    # 作業ファイルからコピーする する。
	    if ($NKF_USE) {
	      system( "$nkf -e < $mailTempFile > $file" );
	    }
	    else {
	      copy ($mailTempFile, $file);
	    }
	    unlink "$mailTempFile";

	}

	print SLOG " STATE=DONE\n";
	close( SLOG );

        OkMail ($slogMsg . "\n-- body\n" . join('', @body)) if $MAILMODE == 1;

        # Update Namazu index
        system("$MkNamazuPath") if $NamazuExecFlag == 1;

        # cvs_add_commit ($file);
	exit;
    }

}

# /* DELETE なら、消しちゃえ */
if( $HnsMode == 3 )
{
    if( $HnsFlag )
    {
# /* でも恐いから 元は のこしておこう */       
	system( "cat $file >>$backupFile" );
	unlink "$file";
	print SLOG " STATE=DONE\n";
	close( SLOG );
	OkMail( $slogMsg ) if( $MAILMODE == 1 );
	exit;
    }
}
# /* GET なら mail を送る */
if( $HnsMode == 4 )
{
    if( $HnsFlag )
    {

	# まず、作業ファイルに nkf -j する。
	if ($NKF_USE) {
	  system( "$nkf -j < $file > $mailTempFile" );
	}
	else {
	  copy_jis ($file, $mailTempFile);
	}
	# そのファイルを今度は sendmail する。

	@mbody = ( 'This message was written by mail2nikki',
		   'System accsept GET command',
		  '');

	open( IN , "$mailTempFile");
	while( $_=<IN>)
	{
	    chomp;
	    s/^\./\.\./;
	    push( @mbody , $_ );
	}
	close( IN );

##	Sendmail($sendmail , $mailAddress , $recvMailAddress ,
	Sendmail($sendmail , $cmdGetAddress , $recvMailAddress ,
		 "[mail2nikki] GET $file", \@mbody);
	unlink "$mailTempFile";
	print SLOG " STATE=DONE\n";
	close( SLOG );
	OkMail( $slogMsg ) if( $MAILMODE == 1 );
	exit;
    }
}


print SLOG " STATE=NO TRANSACT\n";
close( SLOG );
NgMail( $slogMsg ) if( $MAILMODE == 1 );
exit;
