#!/usr/bin/perl

use strict;
use MIME::Types qw(by_suffix by_mediatype);
use CGI qw/:standard/;
use CGI::Carp qw(fatalsToBrowser);
use HTML::Template;
push(@INC,'/home/oc/cgi-bin/');
use lib '/home/oc/cgi-bin/';
use OC;

use vars qw /
%CONFIG
%form
%cookie
$max_dir_size
/;



sub Result {
    my ($result,$write_cookie,$rstr,$rwith)=@_;

    my $template=HTML::Template->new(
       	filename=>$CONFIG{tmpl_cvsget_file},
    );
    $template->param(
        no_panel=>1,
        title=>"Download",
        body=>$result,
    );

    if ($write_cookie>0) {
        my $cookie1=cookie(
            -name=>'cvsget',
            -value=>'download',
            -expires=>'+5y',
        );
        print header(
            -cookie=>[$cookie1],
            -type=>'text/html',
            -charset=>''
        );
    } else {
        print header(
            -type=>'text/html',
            -charset=>''
        );
    }
    if ($rstr ne '' && $rwith ne '') {
        my $html=$template->output;
        $html=~s/$rstr/$rwith/;
        print $html;
    } else {
        print $template->output;
    }
    exit;
}

sub JSDownload {
    my $dl_param='do_download=now';
    if (index($ENV{REQUEST_URI},'?')>0) {
        $dl_param='&'.$dl_param;
    } else {
        $dl_param='?'.$dl_param;
    }
    my $filename='';
    my $body=<<EOF

    <b>Contacting our website, please wait for a window to appear.</b><br>
    If download fails to begin automatically in 30 seconds, <a href="$ENV{REQUEST_URI}$dl_param">click here to download module from CVS</a>.
    Note: preparing download file of some very large CVS module can take more than a minute, please be patient.
    <p>
    If you still can't get the file, please contact webmaster.

    <p>

    $filename

    <SCRIPT LANGUAGE=Javascript>
    <!--
    function JSDownload() {
    window.location = "$ENV{REQUEST_URI}$dl_param";
    }
    -->
    </SCRIPT>

EOF
;
    Result($body,1,"<BODY","<BODY onLoad=\"JSDownload();\" ");
}

sub Check_Size {
    my ($file)=@_;
    my $du=`nice -n 19 du "$file"`;
    $du=~s!.*\n(.*)\n$!$1!s;
    $du=~s!^(\d+)[^\d]+.*$!$1!s;
    unless ($du=~m/^\d+$/) {
        Result("Requested item not found: $file");
    } else {
        unless (($du*1024)<$CONFIG{max_download_size}) {
            Result("Directory size too big ($du KB) to create tar.gz file. You will have to
            use CVS client program to get files from cvs. See <a href='/cvs.shtml'>cvs.shtml</a>.");
        } else {

        }
    }
}

sub Redirect {
    my $file=OC::Finalize_Path($_[0]);
    OC::Log("redirecting to existing file: $file");
    my $url=OC::Url($file);
    print redirect(-uri=>$url);
    exit;
}

sub Cat_File {
    my ($path,$file,$filename)=@_;
    if ($filename eq '') {
        $filename=$file;
        $filename=~s!^.*/([^/]+)$!$1!;
    }
    if (scalar(keys %cookie)<1) {
        OC::Log("no cookies - $ENV{REQUEST_URI} - requested file: $path/$file");
        Result("We are using cookies to prevent robot downloading, 
          that means you must have cookies enabled in your browser. Now click
          this link to get the file: <a href='$ENV{REQUEST_URI}'>$file</a>",1);
    }
    my ($mime_type, $encoding) = by_suffix($file);
    $mime_type="text/plain" if ($mime_type eq '');
    print "Content-type: $mime_type\nContent-Disposition: inline; filename=$filename\n\n";

    if (OC::File_Type("$path/$file")==$OC::_FILE) {
        Redirect("$path/$file");
    } else {
        Result("Cannot open file: $path/$file");
        OC::Error_Log("Cannot open file: $path/$file");
    }
}

sub Prepare_Filename {
    my ($filename,$tag)=@_;
    if ($tag ne '') {
        my $ftag=substr($tag,3);
        $filename.="-$ftag";
    }
    $filename=~s!/$!!;
    $filename=~s![/\.]!_!g;
    $filename=~s!^.*/([^/]+)$!$1!;
    $filename.=".tar.gz";
    return $filename;
}

sub Tar_Folder {
    my ($path,$file,$tag)=@_;
    my $filename=Prepare_Filename($file,$tag);
    `cd $path; nice -n 19 tar czf "$filename" "$file"`;
    Cat_File($path,$filename);
}


sub Main {
    $ENV{'PATH'}='/usr/local/bin:/usr/bin:/bin:/usr/local/bin:/usr/X11R6/bin:.';
    %CONFIG=%OC::CONFIG;
    $CONFIG{max_download_size}=300*1024*1024; # 300 MB
    %form=();
    my $query=new CGI;
    foreach ($query->param) {
	$form{$_}=$query->param($_);
    }
    %cookie=();
    foreach ($query->cookie) {
        $cookie{$_}=$query->cookie($_);
    }

    my $path='';
    my $found=0;
    my $tag="";
    my $tar=0;

    if ($form{module} ne '' && index($form{module},"..")<0 && index($form{module},"CVSROOT")<0) {
        $ENV{PATH_INFO}="/$form{module}";
        $tar=1;
    }
    if ($form{tag}=~m!^[\.A-Z0-9_-]+$!i) {
        $tag="-r $form{tag}";
    } elsif ($form{tag} ne '') {
        Result("Invalid tag: $form{tag}");
    }
    if ($form{revision}=~m!^[\.A-Z0-9_-]+$!i) {
        $tag="-r $form{revision}";
    } elsif ($form{revision} ne '') {
        Result("Invalid revision: $form{revision}");
    }

    if ($form{do_download} ne 'now') {
        JSDownload;
    }

    if ($ENV{PATH_INFO}=~m!^/projects/[A-Za-z0-9_-]+!) {
        $path=$ENV{PATH_INFO};
        $path=~s!^/!!;
        $path=~s!^projects/!cores/!;

        my $type=OC::File_Type("$CONFIG{www_folder}/$path");
        if ($type==$OC::_FILE) {
            Cat_File($CONFIG{www_folder},$path);
#        } elsif ($type==$OC::_FOLDER) {
#            Check_Size("$CONFIG{www_folder}/$path");
#            Tar_Folder($CONFIG{www_folder},$path);
        } else {
            Result("Requested item not found: "."$CONFIG{www_folder}/$path");
        }
        
    } elsif ($ENV{PATH_INFO}=~m!^/[A-Za-z0-9]+! && !($ENV{PATH_INFO}=~m/\.\./)) {
        $path=$ENV{PATH_INFO};
        $path=~s!^/cvs/!!;
        $path=~s!^/!!;
        
        my $count=0;
        my $folder="$CONFIG{cvsget_cache_folder}/";
        `mkdir -p $folder`;
        my $type=OC::File_Type("$CONFIG{cvsroot}/".$path);
	if ($type==$OC::_FILE) {
            $path=~s!,v$!!;
            if (OC::File_Type("$folder/".Prepare_Filename($path,$tag))==$OC::_FILE) {
                Redirect("$folder/".Prepare_Filename($path,$tag));
            }
            Check_Size("$CONFIG{cvsroot}/$path");
            OC::Log("Checkout ,v file: $path");
            `cd $folder; nice -n 19 cvs -d $CONFIG{cvsroot} -Q checkout $tag "$path"`;
            Cat_File($folder,$path);
        } elsif ($type==$OC::_FOLDER) {
            Check_Size("$CONFIG{cvsroot}/$path");
            if (OC::File_Type("$folder/".Prepare_Filename($path,$tag))==$OC::_FILE) {
                Redirect("$folder/".Prepare_Filename($path,$tag));
            }
            OC::Log("Checkout and tar folder: $path");
            `cd $folder; nice -n 19 cvs -d $CONFIG{cvsroot} -Q checkout $tag "$path"`;
            Tar_Folder($folder,$path,$tag);
	} else {
            $type=OC::File_Type("$CONFIG{cvsroot}/$path,v");
            if ($type==$OC::_FILE) {
                Check_Size("$CONFIG{cvsroot}/$path,v");
                if ($tar>0) {
                    my $filename=$path;
                    if ($tag ne '') {
                        my $ftag=substr($tag,3);
                        $filename.="-$ftag";
                    }
                    $filename=~s![/\.]!_!g;
                    $filename.=".tar.gz";
                    if (OC::File_Type("$folder/".Prepare_Filename($path,$tag))==$OC::_FILE) {
                        Redirect("$folder/".Prepare_Filename($path,$tag));
                    }
                    OC::Log("Checkout and tar file: $path > $filename");
                    `cd $folder; nice -n 19 cvs -d $CONFIG{cvsroot} -Q checkout $tag "$path"; nice -n 19 tar czf "$filename" *`;
                    Cat_File($folder,$filename);
                } else {
                    if (OC::File_Type("$folder/$path")==$OC::_FILE) {
                        Redirect("$folder/$path");
                    }
                    OC::Log("Checkout file: $path");
                    `cd $folder; nice -n 19 cvs -d $CONFIG{cvsroot} -Q checkout $tag "$path"`;
                    Cat_File($folder,$path);
                }
            } else {
                Result("Requested item not found");
            }            
        }

    } else {
        Result("Unknown object");
    }
    
}


Main;