#!/usr/bin/perl

# $Id: servimapsync,v 1.17 2024/11/20 22:22:01 gilles Exp gilles $
package Imapsync;

use base qw(Net::Server::HTTP);
use strict ;
use warnings ;
use Cwd ;
use Data::Dumper ;
use English qw( -no_match_vars ) ;


local $Data::Dumper::Sortkeys  = 1 ;

http_server(  ) ;

sub http_server
{
        print "Net::Server::VERSION $Net::Server::VERSION\n" ;
        my $server = Imapsync->new(
        'port'  => [
                {
                'ipv'  => '4', # Because 6 or * does not work in Docker context
                'port' => 8080,
                },
                {
                'ipv'  => '4', # Because 6 or * does not work in Docker context                
                'port' => 8443,
                'proto'     => 'ssl',
                'SSL_key_file'  => 'privkey.pem',
                'SSL_cert_file' => 'fullchain.pem',
                },
        ],
        'access_log_file' => 'STDERR',
        'log_level'       =>    4,
        'default_content_type' => 'text/html',
        'timeout_header'  =>   60,
        'timeout_idle'    => 3600,
        ) ;

        $server->log( 2, "Current directory is " . cwd() ) ;
        $server->run() ;
}


sub default_server_type { 'Fork' }

sub post_configure_hook
{
        my $self = shift ;
        $self->log( 2, Data::Dumper->Dump( [ $self ], ['self'] ) ) ;
}

sub output_file
{
        my ( $self, $file, $type ) = @_ ;
        
        $type ||= 'text/plain' ;
        
        my $string = file_to_string( $file ) ;
        
        my $output ;
        my( $status, $msg, $body ) ;
        if ( defined $string )
        {
                # I can not believe I have to write this condition.
                if ( $self->can( 'default_content_type' ) )
                {
                        $self->{'server'}->{'default_content_type'} = $type ;
                }
                else
                {
                        $output  = "Content-type: $type\r\n\r\n" ;                        
                }
                $output .= $string ;
                # body can not be sent by send_status() because then it
                # sets Content-type to text/html
                
                $self->send_status( '200', 'OK' ) ;
                print $output ;
        }
        else
        {
                $self->send_status( '404', 'Not found', "File not found: $file " ) ;
        }

        return ;
}


sub process_path_info
{
        my $self      = shift ;
        my $path_info = shift ;
        
        my $sitemap = 
        {
                '/imapsync_form_extra.html' => sub { 
                        output_file( $self, './imapsync_form_extra.html', 'text/html' )
                },
                '/imapsync_form.html'       => sub { 
                        output_file( $self, './imapsync_form.html', 'text/html' )
                },
                '/imapsync_form.css'        => sub {
                        output_file( $self, './imapsync_form.css', 'text/css' )
                },
                '/imapsync_form.js'         => sub {
                        output_file( $self, './imapsync_form.js', 'text/javascript' )
                },
                '/imapsync_form_new.js'     => sub {
                        output_file( $self, './imapsync_form_new.js', 'text/javascript' )
                },
                '/' => sub {
                        output_file( $self, './imapsync_form_extra.html', 'text/html' )
                },
                '/vnstat/vnstati.html' => sub {
                        output_file( $self, './vnstati.html', 'text/html' )
                },
        } ;
        
        if ( defined $sitemap->{ $path_info } )
        {
                #$self->log( 2, Data::Dumper->Dump( [ $self ], ['self'] ) ) ;
                $sitemap->{ $path_info }->() ;
        }
        else
        {
                $self->send_status( '404', 'Not found', "Error: $path_info not found!\n" ) ;
        }
        return ;
}

sub process_http_request
{
        my $self = shift ;
        
        $self->log( 2, "In process_http_request PID $$\n" ) ;

        #$self->log( 2, Data::Dumper->Dump( [ $self ], ['self'] ) ) ;

        $ENV{'SERVER_SOFTWARE'} = $PROGRAM_NAME ;

        if ( '/cgi-bin/imapsync' eq $ENV{'PATH_INFO'} )
        {
                #$self->exec_trusted_perl( './imapsync' ) ;
                #$self->log( 2, "In process_http_request PID $$ after exec_trusted_perl\n" ) ;
                
                $self->exec_cgi( './imapsync' ) ;
                $self->log( 2, "In process_http_request PID $$ after exec_cgi( './imapsync' )\n" ) ;
        }
        else
        {
                process_path_info( $self, $ENV{'PATH_INFO'} ) ;
        }
        #$self->log( 2, Data::Dumper->Dump( [ $self ], ['self'] ) ) ;
        $self->log( 2, "End of process_http_request PID $$\n" ) ;
}

sub file_to_string
{
        my $file  = shift ;
        if ( ! $file ) { warn "Error, no file given\n" ; return ; }
        if ( ! -e $file ) { warn "Error, $file does not exist\n" ; return ; }
        if ( ! -f $file ) { warn "Error, $file is not a file\n" ; return ; }
        if ( ! -r $file ) { warn "Error, $file is not readable\n" ; return ; }
        my @string ;
        if ( open my $FILE, '<', $file ) {
                @string = <$FILE> ;
                close $FILE ;
                my $string = join q{}, @string ;
                return $string ;
        }else{
                warn "Error reading file $file : $OS_ERROR\n" ;
                return ;
        }
}


