{
    # vim: ft=perl ts=4 sw=4 et:
    package esmith;
    use strict;
    use Errno;
    use esmith::util;
    # ADDs by PS :
    use esmith::ConfigDB ;
    use esmith::AccountsDB ;

    use constant FS => "," ;
    use constant RS => ";" ;
    $OUT ='';

    # Access to databases 'New Look' ! (PS)
    my $db = esmith::ConfigDB->open
        or die "Can't open the Config database : $!\n" ;
    my $accountdb = esmith::AccountsDB->open
        or die "Can't open the Account database : $!\n" ;

    my @users = $accountdb->get('admin');
    push @users, $accountdb->users();
    unless (scalar @users)
    {
        $OUT .="#\n#\n";
    }
    else
    {
        # In some cases, it's not adviseable to have the
        # local SMTP server set as mail.$domain
        # my $dom = "mail.".$db->get_value('DomainName') ;
        my $dom = $db->get_value('DomainName') ;
        #
        # convert the old configuration with this
        #
        # here, we need maybe to do a doble conversion :
        # old form to 1.0.2 form
        # 1.0.2 to 1.3 form
        my $maxmbox=20;
        my $mdrop=$db->get_value('MDrop');
        my $FM=$db->get('FetchMails');
        if ( not defined $FM ) { 
            $FM = $db->new_record('FetchMails', { type => '' } ) ;
        }
        my $UsersDatasToConvert = 0 ;
    
        if( not defined $mdrop)
        # form is not 'before 1.0.2' like
        {
	    my $type=$FM->prop('type') ;
	    if( (not defined $type) || ($type eq '') )
            # FetchMails record is not defined at all
	        {
                $FM->set_prop( 'type',    'service'  ) ;
                $FM->set_prop( 'status',  'disabled' ) ;
                $FM->set_prop( 'Routing', 'YES'      ) ;
	        } elsif ( $type eq 'custom_service' ) { # 1.0.2 like database
                $UsersDatasToConvert = 1 ;
                $FM->set_prop( 'type',    'service'  ) ;
                $FM->set_prop( 'status',  'enabled' ) ;
                $FM->delete_prop('Lang') ;
        	    $FM->delete_prop('MDrop');
        	    $FM->delete_prop('MDropServ');
        	    $FM->delete_prop('MDropName');
        	    $FM->delete_prop('MDropPass');
        	    $FM->delete_prop('MDropEnv');
        	    $FM->delete_prop('MDropDebug');
        	    $FM->delete_prop('MDropDomain1');
        	    $FM->delete_prop('MDropDomain2');
        	    $FM->delete_prop('MDropDomain3');
        	    $FM->delete_prop('MaxMailBox');
        	    $FM->delete_prop('OrigMDrop');
            }                
        }
        else
        {
            # Data base is in 'before 1.0.2' format
            $UsersDatasToConvert = 1 ;
            $FM->set_prop( 'type',    'service'  ) ;
            $FM->set_prop( 'status',  'enabled' ) ;
	        $db->delete('MDropServ');
    	    $db->delete('MDropName');
    	    $db->delete('MDropPass');
        	$db->delete('MDropEnv');
	        $db->delete('MDrop');
        	$db->delete('MDropDebug');
        }

        # starting with version 1.3.4, there is a 'version' field in the
        # configuration database. 
        # so, if the version in database is below the version of
        # smeserver-fetchmail, User accounts need to be converted.
        my $version = $FM->prop('version') || 0 ;
        $version =~s/[-\.]/0/g ;

        my $packversion = 0 ;
        if ( open VER, "/etc/e-smith/db/configuration/defaults/FetchMails/version" ) {
        $packversion = <VER> ;
            chomp $packversion ;
        }
        close VER ;
        my $packver = $packversion ; 
        $packversion =~s/[-\.]/0/g ;
        if ( $packversion gt $version ) {
            $UsersDatasToConvert = 1 ;
            $FM->set_prop('version', $packver ) ;
        }
        
        # Do we need to convert account Datas in user DataBases ?
        if ( $UsersDatasToConvert ) {
            my %ToConvert=( 'NumBox'            => 'FM-NumBox',
                            'FetchMailAccounts' => 'FM-Accounts',
                            'MailCopyTo'        => 'FM-MailCopyTo',
                            'ghost'             => 'FM-Ghost',
                            'DebugOption'       => 'FM-DebugOption',
                            'KeepOption'        => 'FM-KeepOption',
                            'TransName'         => 'FM-TransName' ) ;
 
            foreach my $u ( @users ) {
                # starting with version 1.3.1 : var names change in
                # users database
                foreach my $convert ( keys %ToConvert ) {
                    if ( defined ( $u->prop($convert) ) ) {
                        $u->set_prop($ToConvert{$convert}, $u->prop($convert) ) ;
                        $u->delete_prop($convert) ;
                    }
                }
                # special case : SpyOption is converted to MailCopyTo admin
                if ( defined ( $u->prop( 'SpyOption' ) ) ) { 
                    if ( $u->prop( 'SpyOption' ) eq 'YES' ) {
                        my $MailCopyTo = ( $u->prop( 'FM-MailCopyTo') || '' ) ;
                        if ( $MailCopyTo eq '' ) { $MailCopyTo = 'admin' }
                        else                     { $MailCopyTo = 'admin,' . $MailCopyTo }
                        $u->set_prop( 'FM-MailCopyTo', $MailCopyTo );
                    }
                    $u->delete_prop( 'SpyOption' ) ;
                }
                # starting with version 1.3.3, TransOption (who can conflict with
                # Ghost is removed. If a transName is set, we use it. If not, we don't ;-)
                # but, before removing, there a try to find a good mode for 'FM-Ghost'
                # that is :
                # if TransOption != 'FORWARD' no change to 'FM-Ghost'
                #    if 'FM-Ghost' == 'YES', no change
                #       if there no 'mail-copy-to' --> 'FM-Ghost' set to 'YES'
                if ( defined $u->prop( 'TransOption' ) ) {
                    if ( $u->prop( 'TransOption' ) eq 'FORWARD' ) {
                         my $ghost = $u->prop( 'FM-Ghost' ) || 'NO' ;
                         if ( $ghost eq 'NO' ) {
                            my $mailCopyTo = $u->prop( 'FM-MAilCopyTo' ) || '' ;
                            if ( $mailCopyTo eq '' ) {
                                $u->set_prop( 'FM-Ghost', 'YES' ) ;
                            }
                        }
                    }
                    $u->delete_prop( 'TransOption' ) ;
                }

                my @MailData ; my @MailRemove ;
                my $i = 0 ;
                for ( $i = 1 ; $i <= 20 ; $i++ ) {
                    my $MS='MailServ' . $i ;
                    my $MT='MailType' . $i ;
                    my $MN='MailName' . $i ;
                    my $MP='MailPass' . $i ;
                    if ( defined ( $u->prop($MS) ) && defined ( $u->prop($MT) ) &&
                         defined ( $u->prop($MN) ) && defined ( $u->prop($MP) ) ) {
                        push @MailRemove, $i ;
                        my $Rec = $u->prop($MS) . FS . $u->prop($MT) . FS ;
                        $Rec   .= unpack( "H*", $u->prop($MN) ) . FS ;
                        $Rec   .= unpack( "H*", $u->prop($MP) ) ;
                        push @MailData, $Rec ;
                        }
                    }
                $u->set_prop('FM-Accounts', join( RS, @MailData ) ) if scalar ( @MailData ) ;
                # Old data are removed only after writing the new look datas.
                foreach my $remove ( @MailRemove ) {
                    my $MS='MailServ' . $remove ;
                    my $MT='MailType' . $remove ;
                    my $MN='MailName' . $remove ;
                    my $MP='MailPass' . $remove ;
                    $u->delete_prop($MS) ;
                    $u->delete_prop($MT) ;
                    $u->delete_prop($MN) ;
                    $u->delete_prop($MP) ;
                }

                # Specials tests. Only needed for sanity check in case of 
                # some versions between 1.0.2 and 1.3.4 are in the wild 
                # should normaly not be the case...
                if (defined $u->prop('FM-Accounts') ) {
                    my $FMAccounts = $u->prop('FM-Accounts') ;
                    # News fields and records separators
                    $FMAccounts =~ s/\037/;/g ;
                    $FMAccounts =~ s/\036/,/g ;
                    # shall we convert to hex ???
                    my @Recs = split ( RS, $FMAccounts ) ;
                    my $toconv = 0 ;
                    foreach my $rec ( @Recs ) {
                        my @R = split( FS, $rec ) ;
                        if ( "$R[2]$R[3]" =~ /[A-Zg-z\W]/ ) {
                            $toconv = 1 ;
                        }
                    }
                    if ( $toconv ) {
                        my @Recs2 ;
                        foreach my $rec ( @Recs ) {
                            my @R = split ( FS, $rec ) ;
                            $R[2] = unpack( "H*", $R[2] ) ;
                            $R[3] = unpack( "H*", $R[3] ) ;
                            push @Recs2, join( FS, @R ) ;
                        }
                        $FMAccounts = join( RS, @Recs2) ;
                    }
                    $u->set_prop('FM-Accounts', $FMAccounts) ;
                }
            }
            # Here, the mails groups need to be generated...
            # But we don't need to put that in this file :
            # in a normal way, the database conversion is done at install time
            # and at install time, the group are build after the conversion
        }
    
        #
        # End of Data conversion...
        #
        
        # New test : if FetchMails status is 'disabled', we don't want that
        # this part of /etc/fetchmail be generated.

        if ( $FM->prop('status') eq 'enabled' ) {
            foreach my $account ( @users ) {
                my $FetchN=0;
            	my $Debug     = $account->prop( 'FM-DebugOption' ) || '' ;
            	my $spy       = $account->prop( 'FM-SpyOption' )   || '' ;
            	my $keepopt   = $account->prop( 'FM-KeepOption' )  || '' ;
            	my $transname = $account->prop( 'FM-TransName')    || '' ;
            	my $usergt    = $account->prop( 'FM-MailCopyTo')   || '' ;
            	my $ghost     = $account->prop( 'FM-Ghost')        || 'NO' ;
    
    	        my $name  = $account->key ;
                my $comment = $name ;
            	my $maxcpy = 0;
    
                if ( $transname ne '' ) {
                    $transname =~ s/:/,/g ;
                    if ( $usergt eq '' ) { $usergt = $transname }
                    else                 { $usergt = $usergt . "," . $transname }
                }
    
            	if($usergt ne '') { 
                    $name = "fm_fm-" . $name ;
                    my $comment2 = '' ;
                    $comment2 = $comment . "," if ( $ghost ne 'YES' ) ;
                    $comment = "$comment  delivered to :  $name = $comment2 $usergt";
                }
    
                # PS 2005/08/02 -> 1.3.4-05
                # tristate combination for the delivering host :
                # 1) if 'FetchMails->fetchhost' is set then this is the delivery host
                #    This should normally never be the case...
                # 2) If the (systemWide) 'SMTPSmartHost is set, then this is the delivey host for fetchmail
                # 3) If none of these are set, then the delivery host is set to the domain name of the computer
                # BTW, correcting a bug preventing previous version to use the SMTPSmartHost value...
                # PS 2005/08/19 ->1.3.4-06
                # considerable mistake ! I had an automagical configuration whistle, but not the good one.
                # I Said that if a smartHost is set, fetchmail must send incoming mails to the SmartHost.
                # But SmartHosts are for Outgoing mails !
                # Now, fetchmail automagically send mail to a DelegateMailServer, if set-up.
            	my $DestSMTPServer = $FM->prop( 'fetchhost' ) || '' ;
                # my $SMTPSmartHost  = $db->get( 'SMTPSmartHost' );
                # $smarthost = $SMTPSmartHost->value || '' if ( $smarthost eq '' ) ;
                # DelegateMailServer not ever exists...
                if ( my $DelegateMailServer = $db->get( 'DelegateMailServer' ) ) { 
                    $DestSMTPServer = $DelegateMailServer->value || '' if ( $DestSMTPServer eq '' ) ;
                }
    	
    	        if( $DestSMTPServer ne '')
    	            { $DestSMTPServer = "smtpaddress $DestSMTPServer" ; }
    	        else
    	            { $DestSMTPServer = "smtpaddress $dom" ; }
    
            	my $keep='fetchall';
    
            	if($keepopt eq "YES") { $keep='keep'; }
            	elsif($keepopt eq "NEW") { $keep='no fetchall'; }
    
            	# Change by PS
                my $FetchMailsAcc = '' ;
                if ( defined $account->prop( 'FM-Accounts' ) ) {
                    $FetchMailsAcc = $account->prop( 'FM-Accounts' ) ;
                }
                my @FetchMailAccounts = split RS, $FetchMailsAcc ;
    
                foreach my $FetchMailAcount ( @FetchMailAccounts ) {
                    $FetchN++ ; 
                    my ( $mserv, $mtype, $mname, $mpass, $moptions ) = split FS, $FetchMailAcount ;
            	    if(not defined $mserv ) { $mserv='';}
    	            if(not defined $mname ) { $mname='';}
            	    if(not defined $mpass ) { $mpass='';}
    	            if(not defined $mtype ) { $mtype='';}
    	            if(not defined $moptions ) { $moptions='';}
    
                    # we need to convert the name, the password and the options from HEX to text
                    $mname = pack( "H*", $mname );
                    $mpass = pack( "H*", $mpass );
                    $moptions = pack( "H*", $moptions );

    	            if ($mserv ne '') {
            	        my $ServOpt = ' and options uidl no dns';

                		if($mtype =~ /IMAP/ ) { $ServOpt = ' and options no dns'; }
    
                        # ver 1.3.5-01 : add a timeout option
                        # this option is equal to the value timeout in the 
                        # FetchMails service configuration
                        $ServOpt = ' timeout ' . ( $FM->prop('timeout') || 60 ) . $ServOpt;

                        if ( $mtype =~ s/^S// ) { $moptions = "ssl $moptions" }

                       #We retrieve the $qmail{MaxMessageSize} to fix 
                       #the max limit where emails won't be downloaded 
                       my $size = $db->get_prop('qmail','MaxMessageSize') || '0';
                       my $mdbg='-l' . $size . ' -d0 --silent --syslog'; 
                       if($Debug eq "YES") { $mdbg='-l' . $size . ' -d0 --verbose --syslog'; }

                		my $staticvalue  = "/usr/bin/fetchmail $mdbg --fetchmailrc - <<EOF\n" ;
                        $staticvalue .= "set postmaster \"postmaster\@$dom\"\n" ;
                        $staticvalue .= "set bouncemail\nset no softbounce\nset properties \"\"\n" ;

                        # special case : the \ must be changed to \x5c !
                        $mname =~ s/[\\]/\\x5c/g ;
                        $mpass =~ s/[\\]/\\x5c/g ;
                        # escape some odd characters by \ (just add them between the [] if needed 
                        $mname =~ s/([\^\$\@\'\"\`])/\\$1/g ;
                        $mpass =~ s/([\^\$\@\'\"\`])/\\$1/g ;
                        # special case : the ' must be quoted another way
                        $mname =~ s/[\']/\\x27/g ;
                        $mpass =~ s/[\']/\\x27/g ;

                        #find the tcp port of smtpd
                        my $tcpport = $db->get_prop('smtpd','TCPPort')||'25';

            		    $OUT .= "#\n";
                        $OUT .= "#   Mail N$FetchN Account for : $comment\n";
                        $OUT .= $staticvalue;
                        $OUT .= "poll $mserv with proto $mtype$ServOpt\n";
                        $OUT .= "  user '$mname' $DestSMTPServer with password '";
                        $OUT .= "$mpass' is $name here $keep\n";
                        if ( $moptions ne '' ) {
                            $OUT .= "  options $moptions\n";
                        }
                        $OUT .= "  smtphost 127.0.0.200/$tcpport" . "\n";
                        $OUT .= "  antispam 550\n";
                    	$OUT .="EOF\n";
            	    }
            	}
            }
        }
        $OUT .="#\n#\n";
    }
}

