# Copyright 1999-2016. Parallels IP Holdings GmbH. All Rights Reserved.
package SendmailAgent;

use MailAccount;
use Logging;
use Mbox2Mdir;


use constant SENDMAIL_PATH => "/etc/mail/";

sub new {
  my $self = { };
  bless($self);

  return $self;
}


sub get_installed {
  return 1 if -e SendmailAgent::SENDMAIL_PATH . "local-host-names" and -e SendmailAgent::SENDMAIL_PATH . 'virtusertable';
  return 0;
}


sub get_id_string{
  return 'sendmail';
}

sub get_display_name{
  return 'sendmail';
}


sub can_backup_accounts{
 return 1;
}

sub can_check_account{
 return 0;
}

sub has_account{
  my ($self, $name) = @_;
  return 0;
}


sub backup_accounts{
 my ( $self, $accounts ) = @_;

 my @domains = $self->getLocalDomains();

 foreach my $domain(@domains){
    my $mailusers = $self->getDomainMails( $domain );
    my $mailInfo = $self->collectMailInfo( $mailusers );
    foreach my $key( keys %{$mailInfo} ){
       my $accountname = "$key@$domain";
      if( $accounts->add_account( $domain, $accountname, $mailInfo->{$key}->{'password'} || '' ) ) {
        $accounts->set_account_maildir( $accountname, $mailInfo->{$key}->{'directory'} ) if exists $mailInfo->{$key}->{'directory'};
        $accounts->set_account_redirect( $accountname, $mailInfo->{$key}->{'redirect'} ) if exists $mailInfo->{$key}->{'redirect'};
        if( exists $mailInfo->{$key}->{'mailgroup'} ){
           foreach my $mgmember( @{$mailInfo->{$key}->{'mailgroup'}} ){
              $accounts->set_account_redirect( $accountname, $mgmember );
           }
        }
      }
    }
 }
}


sub getLocalDomains {
  my ($self, $config) = @_;
  $config ||= SendmailAgent::SENDMAIL_PATH . 'local-host-names';
  Logging::debug( "Open send mail config file '$config'" );
  open (LOCAL, "< $config") or return;

  my @results;
  while (<LOCAL>) {
    chomp;
    push (@results, $_);
    Logging::debug( "Found send mail domain '$_'" );
  }
  close (LOCAL);
  return @results;
}

sub getDomainMails {
  my ($self, $domain, $virt_user_table) = @_;
  $virt_user_table ||= SendmailAgent::SENDMAIL_PATH .  'virtusertable';
  Logging::debug( "Open send mail user config file '$virt_user_table'" );

  my %mailnames;

  open (VIRT, " < $virt_user_table");

  while (<VIRT>) {
    if ($_=~/(.*)\@$domain\s+(.*)/){
      $mailnames{$1} = $2;
    }
  }
  close (VIRT);

  return \%mailnames;

}

sub collectMailInfo {
  my ($self, $mailnames) = @_;
  my $mail_info;
  foreach my $mail_unit (keys %{$mailnames}) {
    my $dest_mail = $mailnames->{$mail_unit};
    my $mailPtr = $self->parsePasswdShadow($dest_mail);
    if (defined $mailPtr->{$dest_mail}){
      $mail_info->{$mail_unit}->{'directory'} = $mailPtr->{$dest_mail}->{'directory'};
      $mail_info->{$mail_unit}->{'password'} = $mailPtr->{$dest_mail}->{'password'};
    }

    if ($dest_mail=~/[.*]\@[.*]/){
      $mail_info->{$mail_unit} = {'redirect' => $dest_mail};
    }

    my $aliasPtr = $self->parseAliases($dest_mail);
    if (defined $aliasPtr->{$dest_mail}) {
      foreach my $alias (@{$aliasPtr->{$dest_mail}}) {
        if (defined $self->parsePasswdShadow($alias)) {
          push @{$mail_info->{$mail_unit}->{'mailgroup'}}, $self->getMailByDest($alias);
        }
      }
    }
  }
  return $mail_info;
}

sub getMailByDest {
  my ($self, $mail) = @_;
  my $virt_user_table ||= SendmailAgent::SENDMAIL_PATH .  'virtusertable';

  my $result;
  open (VIRT, " < $virt_user_table");
  while (<VIRT>) {
    if($_=~/(.*)\@\w+\s+$mail/){
      $result = $1;
    }
  }
  close(VIRT);
  return $result;
}

sub parseAliases {
  my ($self, $mail) = @_;
  my $aliases_file = SendmailAgent::SENDMAIL_PATH . 'aliases';

  my %params;

  open (ALIASES, "< $aliases_file");
  while (<ALIASES>) {
    chomp;
    if ($_=~/$mail\:\s+(.*)/) {
      @{$params{$mail}} = split(/,/, $1);
    }
  }
  close(ALIASES);

  return \%params;
}

sub parsePasswdShadow {
  my ($self, $uid) = @_;

  my $shadow_file = '/etc/shadow';
  my $passwd_file = '/etc/passwd';

  my (%shadow,%passwd, %user_params, @params, $user, $password, @shadowParams);
  open (SHADOW, "< $shadow_file");
  while (<SHADOW>) {
    chomp;
    my @data1 = split(/:/, $_);
    #FIXME - remove @_->[0] at the begining of hash value
    push @{$shadow{$data1[0]}}, @data1;
  }
  close (SHADOW);

  open (PASSWD, "< $passwd_file");
  while (<PASSWD>) {
    chomp;
    my @data2 = split(/:/, $_);
    #FIXME - go to previous fix me
    push @{$passwd{$data2[0]}}, @data2;
  }
  close (PASSWD);

  while (($user, @params) = each %passwd) {
    if ($user eq $uid) {
      if (%shadow and defined($shadow{$user})) {
        @shadowParams = @{$shadow{$user}};
        $password = $shadowParams[1];
      }
      $user_params{$user} = {'shell' => $params[0]->[6], 'password' => $password, 'directory' => $params[0]->[5]};
    }
  }

  return \%user_params;
}

1;