#!/usr/bin/perl

#############################################################################
# This tool converts one or more MBOX files into MH files while keeping
# the directory structure. It also eventually filters some Mozilla or
# Netscape(c) chunk.
#
# Copyright (C) 2002 Valentin Koch
#
# 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.
#
# History:
# version 1.0.0  May  8, 2002 V.Koch
# version 1.0.1  May 14, 2002 V.Koch   bug fixes: substitution of .sbd
#                                                 some parse errors
#
#############################################################################

use Getopt::Long;

#################
# sub routines
#################

sub ascending {
  $b <=> $a;
}

sub getDirContent {
  local $dir = @_[0];
  local(*DIRHL);
  if(opendir(DIRHL, $dir)) {
    # filter mozilla/netscape chunk
    @content = grep(!/^\.|\.msf$|\.dat$/, readdir(DIRHL));
    closedir(DIRHL);
    return @content;
  } else {
    die "Can't open $dir: $!\n";
  }
}

sub getMailBoxes {
  local $mbox = @_[0];
  local $recursive = @_[1];
  local $interactive = @_[2];
  local @files = ();
  print "Read mails from: $mbox\n";
  if ($inclsub == 1) {
    print "Include subdirectories.\n"
  }

  if(-d $mbox) {
    local @dirs[++$#dirs] = $mbox;
    while(scalar(@dirs) >= 1) {
      local @subdirs = ();
      foreach $dir (@dirs) {
	foreach $node (getDirContent($dir)) {
	  $fullnode = $dir . "/" . $node;
	  if(-d $fullnode) {
	    if($recursive) {
	      @subdirs[++$#subdirs] = $fullnode;
	    }
	  } else {
	    if ($interactive) {
	      print "Import $fullnode ? [Y/n]: ";
	      $_ = <STDIN>;
	      if (s/y|Y|^\n$/$1/) {
		@files[++$#files] = $fullnode;
	      }
	    } else {
	      @files[++$#files] = $fullnode;
	    }
	  }
	}
      }
      @dirs = @subdirs;
    }
  } else {
    @files[++$#files] = $mbox;
  }
  return @files;
}

sub getLastMailOfDir {
  my $dir = @_[0];
  local(*DIRHL);
  if(opendir(DIRHL, $dir)) {
    @allmails = grep(!/^\./, readdir DSTDIR);
    closedir DSTDIR;
    @ascmails = sort ascending @allmails;
    return $ascmails[0];
  } else {
    die "Can't open $dir: $!\n";
  }
}

sub printHelp {
     print (
"Usage: mbox2mh [-h | --help] [-i | --interactive]
        [-r | --recursive] SOURCE DESTINATION

Imports MBOX mail files from SOURCE where SOURCE can
be a file or a directory and imports them as MH mails
and directories into the DESTINATION directory. If 
DESTINATION does not exist, mbox2mh tries to create it.
DESTINATION can also be an existing MH directory which
is already in use.

Options:

 -i,  --interactive ask for every MBOX file to import
 -r,  --recursive   include subdirectories in SOURCE
 -h,  --help        display this help and exit

Report bugs to vale\@canada.com");
}

#################
# main
#################

unless(@ARGV) {
  die"mbox2mh: missing operand\nmbox2mh: Try `mbox2mh --help' for more information.\n";
}

&GetOptions("help"|"h" => \$ShowHelp,
	    "interactive"|"i" => \$Interactive,
	    "recursive"|"r" => \$Recursive);

if($ShowHelp) {
  printHelp();
  exit 0;
}

if(scalar(@ARGV) < 2) {
  die"mbox2mh: missing operand\nmbox2mh: Try `mbox2mh --help' for more information.\n";
} elsif(scalar(@ARGV) > 2) {
    die"mbox2mh: extra operand\nmbox2mh: Try `mbox2mh --help' for more information.\n";
} else {
    $source = $ARGV[0];
    $dest = $ARGV[1];
}

@mboxes = getMailBoxes($source, $Recursive, $Interactive);

foreach $mbox (@mboxes) {
  # open source
  open(INFILE, $mbox) or die "Can't open $mbox:$!\n";
  # open/create destination
  $mbox =~ s/$source/$dest/;
  # get rid of ev. mozilla/netscape chunk
  $mbox =~ s/\.sbd//g;
  $path = "";
  @mdirs = split(/\//, $mbox);
  foreach $mdir (@mdirs) {
    $path = $path . $mdir . "/";
    if(! -e $path) {
      mkdir($path) or die "Can't create $path:$!\n";
    } elsif (! -d $path) {
      die "$path is not a directory.\n";
    }
  }

  $mailname = getLastMailOfDir($mbox);

  # do the job
  while(<INFILE>) {
    if (/^From /) {
      if(OUTFILE) {
	close OUTFILE;
      }
      $mailname++;
      $filename = $mbox . "/" . $mailname;
      print "Create mail: $filename\n";
      open OUTFILE, ">$filename" or die "Can't create file $filename\n";
    } else {
      print OUTFILE $_;
    }
  }
}
if(OUTFILE) { close OUTFILE };
print "completed.\n";
