#!/usr/bin/perl -wT

#----------------------------------------------------------------------
# heading     : Your Settings
# description : Domain pseudonyms
# longdesc    : Manage domain specific pseudonyms
# navigation  : 100 453
#
# Author Stephen Noble dungog.net
#
#----------------------------------------------------------------------

package esmith;

use strict;
use CGI ':all';
use CGI::Carp qw(fatalsToBrowser);

use esmith::cgi;
use esmith::config;
use esmith::util;
use esmith::db;

sub showInitial ($$$);                   #main form
sub performSave ($);

sub editEmail ($$);
sub performModifyEmail ($);
sub removeEmail ($);

sub performSelect ($);

BEGIN
{
    # Clear PATH and related environment variables so that calls to
    # external programs do not cause results to be tainted. See
    # "perlsec" manual page for details.

    $ENV {'PATH'} = '/usr/sbin:/usr/bin:/usr/local/bin';
    $ENV {'SHELL'} = '/bin/bash';
    delete $ENV {'ENV'};
}

esmith::util::setRealToEffective ();

$CGI::POST_MAX=1024 * 100;  # max 100K posts
$CGI::DISABLE_UPLOADS = 1;  # no uploads

my %conf;
tie %conf, 'esmith::config';

my %accounts;
tie %accounts, 'esmith::config', '/home/e-smith/db/accounts';

my %domains;
tie %domains, 'esmith::config', '/home/e-smith/db/domains';

my %dungog;
tie %dungog, 'esmith::config', '/home/e-smith/db/dungog';


#------------------------------------------------------------
# examine state parameter and display the appropriate form
#------------------------------------------------------------

my $q = new CGI;

if (! grep (/^state$/, $q->param))
{
    showInitial ($q, '', '');
}
elsif ($q->param ('state') eq "save")
{
    performSave ($q);
}
elsif ($q->param ('state') eq "edit")
{
    editEmail ($q, '');
}
elsif ($q->param ('state') eq "performEmail")
{
    performModifyEmail ($q);
}
elsif ($q->param ('state') eq "remove")
{
    removeEmail ($q);
}
elsif ($q->param ('state') eq "select")
{
    performSelect ($q);
}
else
{
    esmith::cgi::genStateError ($q, \%conf);
}

exit (0);

#------------------------------------------------------------

sub showInitial ($$$)
{
    my ($q, $msg, $passdomain) = @_;
    my $acct = $ENV{'REMOTE_USER'};
    my @domains = ();
    my $domain = '';
    my $userlist =  '';
    my @selected1 = ();

    # find domains for this owner
    foreach my $dom (keys %dungog)
    {
        if (db_get_type(\%dungog, $dom) eq 'domain')
        {
            my $owner = db_get_prop(\%dungog, $dom, "owner") || '';

            if  ($owner eq $acct || $owner eq 'everyone')
            {
                push (@domains, $dom);
                $domain = $dom;
            }

            #or a member of a group
            $userlist = db_get_prop(\%accounts, $owner, 'Members') || '';
            @selected1 = split (/,/, $userlist);
            foreach my $user (@selected1)
            {
                if  ($user eq $acct)
                {
                  push (@domains, $dom);
                  $domain = $dom;
                }
            }
        }
    }

    #change to a passed value
    if ($passdomain ne '')
    {
        $domain = $passdomain;
    }

    # find system users in group
    my $group = db_get_prop(\%accounts, $domain, "group") || 'everyone';
    my $userlist2 = db_get_prop(\%accounts, $group, 'Members') || '';
    my @selected2 ;

    if ($group eq 'everyone')
    {
      foreach (keys %accounts)
      {
         push (@selected2, $_)
             if (db_get_type(\%accounts, $_) eq 'user');
      }
    }
    elsif ($group eq 'Administrator')
    {
      @selected2 = ($acct);
    }
    else
    {
      @selected2 = split (/,/, $userlist2);
    }

    if ($msg eq '')
    {
          esmith::cgi::genHeaderNonCacheable
            ($q, \%conf, "Domain pseudonyms. ");
    }
    else
    {
        esmith::cgi::genHeaderNonCacheable
            ($q, \%conf, "Domain pseudonyms. ");

        print $q->h4 ('Operation status report');
        print $q->p ($msg);
        print $q->hr;
    }

    print $q->start_form (-method => 'POST', -action => $q->url (-absolute => 1));

    #are there any ?
    my $domains = @domains;
    if ($domains == 0)
    {
        print $q->p ($q->b ("There are no Domains allocated to user $acct"));
    }
    else
    {
        print $q->p ("Pseudonyms for the Domain <b>$domain</b> managed by <b>$acct</b> (" .
	        db_get_prop(\%accounts, $acct, 'FirstName') . ' ' . db_get_prop(\%accounts, $acct, 'LastName') . ").");

        if ($domains > 1)
        {
            print $q->p ($q->td ("You have multiple domains, you can change below..."));
            foreach (@domains)
            {
              print $q->Tr ($q->td ($q->a ({href => $q->url (-absolute => 1) . "?state=select&swap=$_"},
                      "$_"), " ; "));
            }           
        }

    #commom with userpanel

    print $q->p ($q->b ("Delegate the domain \"$domain\""));

    print $q->Tr (esmith::cgi::genTextRow ($q, 'Forward all email for this domain to a remote mailserver,
                  either use a FQDN mail.domain.net or an IP address.
                  Or leave blank and forward domain specific pseudonyms below '));

    print '<p>';
    print $q->Tr (esmith::cgi::genNameValueRow ($q,"Server Name or IP",
                                                     "MailServer",
                             db_get_prop(\%domains, $domain, "MailServer") || '',));

    # get all pseudonyms
    my @vdemail = ();
    foreach (keys %accounts)
    {
        push (@vdemail, $_)
            if (db_get_type(\%accounts, $_) eq 'pseudonym');
    }

    # find email for this domain
    my @vdemail2 = ();
    foreach (@vdemail)
    {
        (my $u, my $d) = split (/@/, $_);

        push (@vdemail2, $u)  if (defined $d and $d eq $domain);
    }

    #are there any ?
    my $vdemail = @vdemail2;
    if ($vdemail == 0)
    {
        print $q->p ($q->b ("There are no pseudonyms for the domain \"$domain\""));

        print $q->p ($q->a ({href => $q->url (-absolute => 1) . "?state=edit&domain=$domain&pseu=new2user"},
                      'Click here'),
                      'to add your first pseudonym.');
    }
    else
    {
        print $q->p ($q->b ("Current List of pseudonyms for the domain \"$domain\""));

        print $q->p ($q->a ({href => $q->url (-absolute => 1) . "?state=edit&domain=$domain&pseu=new2user"},
                      'Click here'),
                      "to add another pseudonym.");

        print "<table border=1 cellspacing=1 cellpadding=4>";

        print $q->Tr (esmith::cgi::genSmallCell ($q, $q->b ('Pseudonyms')),
                      esmith::cgi::genSmallCell ($q, $q->b ('Local user')),
                      $q->td ('&nbsp;'),
                      $q->td ('&nbsp;'));

        foreach my $pseu (sort @vdemail2)
        {
            my $acct  = db_get_prop(\%accounts, "$pseu\@$domain", "Account") || '';

            print $q->Tr (esmith::cgi::genSmallCell ($q, $pseu),
                          esmith::cgi::genSmallCell ($q, $acct),
                          esmith::cgi::genSmallCell ($q,
                                  $q->a ({href => $q->url (-absolute => 1)
                                  . "?state=edit&domain=$domain&acct=$acct&pseu=$pseu"}, 'Modify...')),
                          esmith::cgi::genSmallCell ($q,
                                  $q->a ({href => $q->url (-absolute => 1)
                                  . "?state=remove&domain=$domain&pseu=$pseu"}, 'Remove...')));
        }

        print '</table>';

        print $q->p ($q->b ("Save Settings"));

        print $q->p ("Pseudonym settings are not activated until you save them here");

        print $q->Tr (esmith::cgi::genButtonRow ($q,
                                               $q->submit (-name => 'action',
                                                           -value => 'Save')));

        print $q->hidden (-name => 'state', -override => 1, -default => 'save');
        print $q->hidden (-name => 'domain', -override => 1, -default => $domain);

        #end common
        }
    }
}

sub editEmail ($$)
{
    my ($q, $msg) = @_;
    my $domain  = $q->param ('domain');
    my $acct    = $q->param ('acct') || '';
    my $pseu    = $q->param ('pseu') || '';
    my $user1   = $q->param ('pseu');
    my $newuser = '';
    
    if ($pseu eq 'new2user')
    {
      $newuser = 'new';
      $pseu    = '';
    }

    # find system users in group
    my $owner  =    $ENV{'REMOTE_USER'};   #userpanel
    # my $owner = db_get_prop(\%dungog, $domain, "owner") || '';
    my $group = db_get_prop(\%dungog, $domain, "group") || 'everyone';
    my @selected ;
    my $userlist = db_get_prop(\%accounts, $group, 'Members') || '';

    if ($group eq 'everyone')
    {
      foreach (keys %accounts)
      {
         push (@selected, $_)
             if (db_get_type(\%accounts, $_) eq 'user');
      }
    }
    elsif ($group eq 'Administrator')
    {
      @selected = ($owner);
    }
    else
    {
      @selected = split (/,/, $userlist);
    }

    if ($msg eq '')
    {
          esmith::cgi::genHeaderNonCacheable
            ($q, \%conf, 'Modify Email Address.');
    }
    else
    {
        esmith::cgi::genHeaderNonCacheable
            ($q, \%conf, 'Modify Email Address.');

        print $q->h4 ('Operation status report');
        print $q->p ($msg);
        print $q->hr;
    }

    my @sorted = sort @selected;

    print $q->start_form (-method => 'POST', -action => $q->url (-absolute => 1));

    print $q->table ({border => 0, cellspacing => 0, cellpadding => 4},

          $q->Tr (esmith::cgi::genCell ($q, "Domain name:"),
                               esmith::cgi::genCell ($q, $domain)),

           esmith::cgi::genTextRow ($q, "Enter a pseudonym. <br>".
                                        "NOTE. The domain name is added for you."),

           esmith::cgi::genNameValueRow ($q, "Pseudonym",
                                           "pseu",
                                           $pseu ,),

           esmith::cgi::genWidgetRow ($q, "Local Account",
                               $q->popup_menu (-name    => "acct",
                                               -values  => [ '', @sorted ],
                                               -default => $acct )),


           esmith::cgi::genButtonRow ($q,  $q->submit (-name => 'action',
                                                       -value => 'Save')));

    print $q->hidden (-name => 'domain', -override => 1, -default => $domain);
    print $q->hidden (-name => 'user1',  -override => 1, -default => $user1);
    print $q->hidden (-name => 'newuser', -override => 1, -default => $newuser);
    print $q->hidden (-name => 'state',   -override => 1, -default => 'performEmail');

    print $q->end_form;
    print $q->p ($q->hr, $q->font ({size => "-1"}, "Copyright dungog.net"));

    print '</FONT>';
    print '</DIV>';
    print $q->end_html;
}

sub performModifyEmail ($)
{
    my ($q) = @_;

    my $domain   = $q->param ('domain');
    my $MailServer  = $q->param ('MailServer ') || '';
    my $acct     = $q->param ('acct');
    my $pseu     = $q->param ('pseu');
    my $Pseudonym = "$pseu\@$domain";
    my $user1    = $q->param ('user1');
    my $newuser  = $q->param ('newuser');

    # get all pseudonyms
    my @vdemail = ();
    foreach (keys %accounts)
    {
        push (@vdemail, $_)
            if (db_get_type(\%accounts, $_) eq 'pseudonym');
    }
    
    #don't overwite existing users
    if ($newuser eq 'new2user')
    {
      foreach (@vdemail)
      {
          if ($_ eq $Pseudonym)
          {
               editEmail ($q, "Error: Pseudonym already exists.");
               return;
          } 
       }    
    }

    if ($pseu =~ /^([a-zA-Z0-9][\-\_\.a-zA-Z0-9]*)$/)
    {
        $pseu = $1;
    }
    else
    {
        editEmail ($q, "Error: unexpected characters in Pseudonym, \"$pseu\".");
        return;
    }

    if ($acct eq '')
    {
        editEmail ($q, "Error: please select a local account.");
        return;
    }

    unless (exists $accounts {$Pseudonym})
    {
      db_set(\%accounts, $Pseudonym, 'pseudonym');
    }
    db_set_prop(\%accounts, $Pseudonym, 'Account', $acct);

    #we changed the Pseudonym, so delete the old
    if ($user1 ne $pseu)
    {
	   db_delete(\%accounts, "$user1\@$domain");
    }

    showInitial ($q, "Successfully modified Pseudonym for $domain." ,"$domain");
    return;
}

sub removeEmail ($)
{
    my ($q)  = @_;
    my $pseu = $q->param ('pseu');
    my $domain   = $q->param ('domain');
    my $Pseudonym = "$pseu\@$domain";

    db_delete(\%accounts,  $Pseudonym);

    showInitial ($q, "Successfully removed Pseudonym for $domain." ,"$domain");
}

sub performSave ($)
{
    my ($q)  = @_;
    my $domain   = $q->param ('domain');
    my $MailServer  = $q->param ('MailServer') || '';

    if ($MailServer eq '')
    {
       db_delete_prop(\%domains, $domain, 'MailServer');
    }
    else
    {
       db_set_prop(\%domains, $domain, 'MailServer', $MailServer);
    }

    system ("/sbin/e-smith/signal-event", "email-update") == 0
            or die ("Error occurred while restarting email.\n");

    showInitial ($q, "Settings saved and email restarted." ,"$domain");
}

sub performSelect ($)
{
    my ($q) = @_;
    my $swap = $q->param ('swap');

    showInitial ($q, "Domain switched to $swap" ,"$swap");
}