# -------------------------------------------------------------------------------------
# flo::plugin::Static
# -------------------------------------------------------------------------------------
#
#       Author : Jean-Michel Hiver (jhiver@cisedi.com).
#    Copyright : (c) MKDoc Holdings Ltd, 2001
# 
#      Unauthorized modification, use, reuse, distribution or redistribution
#      of this module is stricly forbidden
#
#    Description:
#
#      A plugin that is used to serve static content through MKDoc plugin system
#      rather than hacking apache config file
#
# -------------------------------------------------------------------------------------
package flo::plugin::Static;
use flo::Standard;
use flo::Object;
use flo::HTTP::Date;
use lib::Exception;
use strict;
use vars qw /@ISA $MIME_TYPES/;
@ISA = qw /flo::Object/;
$MIME_TYPES = undef;


##
# $class->main;
# -------------
#   Processes the request
##
sub main
{
    my $class = shift;
    
    # if this module is not concerned, let's return ASAP
    my $config = $class->config;    
    my $http_name = $config->{'http_name'};
    my $q_http_name = quotemeta ($http_name);
    my $raw_path_info = raw_path_info();
    return unless ($raw_path_info =~ /^$q_http_name/o);
    
    # otherwise, let's process the request
    # let's compute the raw_path_info but eliminate the undesirable '..'
    $raw_path_info =~ s/^$q_http_name//;
    my @raw_path_info = split /\//, $raw_path_info;
    my @new_raw_path_info = ();
    
    foreach (@raw_path_info)
    {
	next if $_ eq '.';
	if ($_ eq '..')
	{
	    pop @new_raw_path_info if (@new_raw_path_info);
	}
	else
	{
	    push @new_raw_path_info, $_;
	}
    }
    $raw_path_info = join '/', @new_raw_path_info;

    my $file_path = $config->{disk_static_dir} . '/' . $raw_path_info;
    
    # if the file has got no extension, let's return
    # (should trigger flo::plugin::Error)
    my ($file_ext) = $file_path =~ /.*\.(.*)/;
    return unless (defined $file_ext);
    
    # if the mime types were not imported yet, let's do it
    unless (defined $MIME_TYPES)
    {
	my $mime_config = new lib::Config ('mime.types');
	foreach my $mime_type ($mime_config->keys)
	{
	    my $extentions = $mime_config->get ($mime_type);
	    my @ext = split /\s+/, $extentions;
	    foreach (@ext) { $MIME_TYPES->{$_} = $mime_type }
	}
    }
    
    # if the mime type is unkown, errr... we don't know it
    # let's send an application/octet-stream type
    my $content_type = $MIME_TYPES->{$file_ext} || 'application/octet-stream';
    
    # else, sends the proper Content-Type and the file
    open FP, "<$file_path" or return;
    my $data = join '', <FP>;
    close FP;
    
    # grab the last-modified date so that we can properly set the HTTP Headers
    # 'perl -f stat'
    # "9 mtime    last modify time in seconds since the epoch"
    my $MTIME = 9;
    my @file_stat = stat ($file_path);
    my $mtime = $file_stat[$MTIME];
    my $Last_Modified = flo::HTTP::Date::http_date ($mtime);
    
    # lets see if we can find some info on the file name
    my $info_file = $config->{disk_static_dir};
    my @path = split /\//, $raw_path_info;
    my $tmp_filename = pop (@path);
    $tmp_filename = '.' . $tmp_filename . '.nfo';
    push @path, $tmp_filename;
    $info_file = $config->{disk_static_dir} . '/' . (join '/', @path);
    
    my $save_file_name = undef;
    if (-e $info_file)
    {
	open FP, "<$info_file" or die "Cannot read-open $info_file";
	$save_file_name = <FP>;
	close FP;
	chomp ($save_file_name);
    }
    
    # spits out the content-type and the data
    if (defined $save_file_name and $save_file_name)
    {
	print "Content-Type: $content_type;name=\"$save_file_name\"\n";
	print "Last-Modified: $Last_Modified\n";
	print "Content-Length: " . length ($data) . "\n";
	print "Content-Disposition: attachment; filename=\"$save_file_name\"\r\n\r\n";
    }
    else
    {
	print "Content-Type: $content_type\n";
	print "Last-Modified: $Last_Modified\n";
	print "Content-Length: " . length ($data) . "\r\n\r\n";
    }
    
    print $data;
    return 'TERMINATE';
}


1;
