#!/bin/perl -w
#
# reqfil server for XFBB 7.01+
# Author:   Stewart Wilkinson G0LGS
#

# Somewhere to create temporary files
$TempDir="/tmp/";

# Max Message Size
$MaxSize=7168;

#
# Nothing below should need changing (unless it needs fixing) :-
#

# Version Information
##VERSION##
##VERDATE##
$Version="*** REQFIL for XFBB 7.01+ (by G0LGS V${Vers} ${VDate}) ***";

# if NO Args assume script was run from command line
# so display Version information & exit with none 0 status.
if( $#ARGV < 0 ) {
   print "$Version\n";
   exit 1;
}

$Filename = $ARGV[0];

# Where is FBB Setup File
$INIT="/etc/ax25/fbb.conf";

if( defined( $ENV{FBBCONF} ) && "$ENV{FBBCONF}" != "" ){
   $INIT = $ENV{FBBCONF}
}

# Read things we need from Setup File
if(! open(CONFIG, $INIT) ) {
   print STDERR "Unable to open $INIT\n";
   exit 1;
}

while($line = <CONFIG>) {

   chomp($line);

   if( $line =~ /^\s*\#/) {
      next;

   }elsif( $line =~ /^\s*$/) {
      next;

   }else{
      $line =~ /^\s*(\S*)\s*\=\s*(.*)$/;
      $item = $1;
      $value = $2;

      if( $item =~ /^call/ ){
         $value =~ /^(\w*)\.(.*)$/;
         $BBSCALL = $1;
         $BBSHR = $2;

      }elsif( $item =~ /^qral/ ){
         $value =~ /^(\S*)$/;
         $LOC=$1;

      }elsif( $item =~ /^city/ ){
         $value =~ /^(\S*)$/;
         $QTH = $1;

      }elsif( $item =~ /^conf/ ){
         $value =~ /^(\S*)$/;
         $CONF = $1;

      }elsif( $item =~ /^fbbd/ ){
         @DIRS=split( /,/ , $value);

         $DP='A';
         foreach $D (@DIRS) {
            push( @PUBLIC, $D);
            if( ($D !~ /\*/) && ! defined(${PUB}) ){
               ${PUB} = ${D};
               ${DRV} = ${DP};
            }
            $DP++;
         }

      }elsif( $item =~ /^name/ ){
         $value =~ /^(\S*)$/;
         $NAME = $1;

      }elsif( $item =~ /^syso/ ){
         $value =~ /^(\S*)$/;
         $SYSCALL = $1;

      }elsif( $item =~ /^impo/ ){
         $value =~ /^([^\.]\S*)\.(\S*)$/;
         $MAIL = "$1.$2";
         $LOCK = "$1.lck";
 
      }

   }

}

close(CONFIG);

# REQFil Help
$ReqFilHelp="$CONF/reqfil.help";
$ReqFilErr="$CONF/reqfil.err";

if( ! open( MSG, "< ${Filename}" ) ){
   printf STDERR "Unable to Read Message\n";
   exit 1;
}

# Ok - Now Read Things we Need from The incoming Message

# Sender
chomp($Sender = <MSG>);

if( $Sender =~ /^SP\s+(\w*)\s+\<\s+(\w*)/ ){
   $To = $1;	# This should be us !
   $From = $2;
}else{
   printf STDERR "REQFIL Error Reading Sender Information\n";
   exit 1;
}

# Subject (Path/FileName [@ BBSCALL])
chomp($Subject = <MSG>);

close(MSG);
#unlink(${Filename});

# Check for Return BBS
if( $Subject =~ /^\s*(\S+)\s+\@\s+(.*)$/ ){
   $Subject = $1;
   $Dest = $2;
}

$REQFIL = ${Subject};

# change FBBDOS Drive letter to the real Unix path
if( ${REQFIL} =~ /^(\S)\:(\S*)/ ){
   ${DPATH} = ${REQFIL};

   $P = $2;
   ($D = $1) =~ tr/[a-z]/[A-Z]/;
   ${Drv} = ord($D) - 64;
 
   if( $P =~ /^\\(\S*)/ ){
      $P = $1;
   }
 
   if( $P =~ /^\/(\S*)/ ){
      $P = $1;
   }
 
   $d=1;
   foreach $Pub (@PUBLIC) {
      if( ${Drv} == ${d} ){
         if( $Pub =~ /\*/ ) {
            $NoPath = 1;
         }else{
            ${ReqFil} = ${Pub} . ${P};
         }
      }
      $d++;
   }
 
}else{
      ${ReqFil} = ${PUB} . ${REQFIL};
      ${DPATH} = ${DRV} . ":\\" . ${REQFIL};
}


# Make sure the Required Path is in '*nix' format

# translate DOS '\' chars to '/' 
${ReqFil} =~ tr /\\/\//;

# Remove any // sequences
while( ${ReqFil} =~ /(.*)\/\/(.*)/ ){
    ${ReqFil} = $1 . "/" . $2;
}

# Check for '../' sequences.
if( ${ReqFil} =~ /.*\.\.\/.*/ ){
   ${NoPath}=1;
   print DEBUG "\tInvalid Path Specified\n" if ($DEBUG);
}


# Split into Parts
$ReqFil =~ /(.*)\/([^\/]+)$/;
$ReqPath = $1;
$ReqName = $2;


print "ReqFil : ${ReqFil}\n";
print "ReqPath : ${ReqPath}\n";
print "ReqName : ${ReqName}\n";

if( "$Subject" eq "?" ){

   &StartMsg;

   print MAIL "\tREQFIL HELP\n\n";

   # Send the HELP
   if( open(HELP,"<$ReqFilHelp") ){
      print MAIL <HELP>;
      close(HELP);
   }

   &EndMsg;

}elsif( defined($NoPath) ){

   &StartMsg;

   print MAIL "\n\"$Subject\" is an Invalid Path !\n\n";
   # Add any ERROR HELP
   if( open(ERR,"<$ReqFilErr") ){
      print MAIL <ERR>;
      close(ERR);
   }

   &EndMsg;

}elsif( (! -f "${ReqFil}") || (! -r "${ReqFil}") ){

   &StartMsg;

   print MAIL "\nNo Such File \"$Subject\" !\n\n";
   # Add any ERROR HELP
   if( open(ERR,"<$ReqFilErr") ){
      print MAIL <ERR>;
      close(ERR);
   }

   &EndMsg;

# Check if Binary ????
}elsif( -B "${ReqFil}" ){
   &StartMsg;

   print MAIL "\nSorry REQFIL Cannot Process Binary File \"$Subject\", Use 7PSERV Instead.\n\n";
   # Add any ERROR HELP
   if( open(ERR,"<$ReqFilErr") ){
      print MAIL <ERR>;
      close(ERR);
   }

   &EndMsg;

}else{

   $FileSize = -s "${ReqFil}";
   if( $FileSize > $MaxSize ){
      
      if( open(REQ,"< ${ReqFil}") ){

         # Split the Source File

         # Start with New Part 
         $Part=0;
         $PSize=$MaxSize;
          
         while($Line = <REQ>){
            chop($Line);
            $PSize = $PSize + length($Line);

            if($PSize > $MaxSize){               
               $PSize = length($Line);

               if($Part > 0 ){
                  close(PART);
               }
               $Part++;

               $NPart="${TempDir}/reqfil.${$}.${Part}";
               if( ! open(PART,">$NPart") ){
                  $FileErr=1;
                  last;
               }
            }          

            print PART "$Line\n";
         }
         close(PART);
         close(REQ);

         if( defined($FileErr) ){
            print MAIL "Error - Unable to Create Temporary file.\n";
            print MAIL "\nPlease Inform the Sysop\n";
         }else{

            $MaxPart = $Part;

            $Part=1;
            while( $Part <= $MaxPart ){
               &StartMsg($Part,$MaxPart);               

               $NPart="${TempDir}/reqfil.${$}.${Part}";
               if( ! open(PART,"<$NPart") ){
                  $FileErr=1;
                  last;
               }
               print MAIL "\n\n---------- Part $Part/$MaxPart of \"$ReqName\" ----------\n\n";

               while( $B = <PART> ){
                  if( ${B} !~ /^\/ex/i ){
                     print MAIL $B;
                  }else{
                     print MAIL ";$B";
                  }
               }

               if( $Part eq $MaxPart ){
                   print MAIL "\n[Downloaded from $BBSCALL BBS]\n\n";
               }
               print MAIL "\n\n---------- End of Part $Part/$MaxPart of \"$ReqName\" ----------\n\n";
               &EndMsg($Part);

               close(PART);
               unlink($NPart);

               $Part++;
            }
         }

      } else {
         &StartMsg;

         print MAIL "Un-expected Error - Unable to Open file \"$ReqFil\"\n";
         print MAIL "\nPlease Inform the Sysop\n";

         &EndMsg;

      }

   } else {
      &StartMsg;

      if( open(REQ,"<$ReqFil") ){
         print MAIL "---------- File \"$ReqName\" ----------\n\n";
         print MAIL <REQ>;
         print MAIL "\n\n---------- End of file \"$ReqName\" ----------\n\n";
         print MAIL "\n[Downloaded from $BBSCALL BBS]\n\n";
         close(REQ);
      }else{
         print MAIL "Un-expected Error - Unable to Open file \"$ReqFil\"\n";
         print MAIL "\nPlease Inform the Sysop\n";
      }

      &EndMsg;
   }
}

exit 0;

sub StartMsg{

   if( defined($_[1]) ){
     $P =  $_[0];
     $NP =  $_[1];
   }

   if(! open(LOCK, "> ${LOCK}" ) ){
      print STDERR "ERROR: Unable to Create Message Lock\n";
      exit 1;
   }
   print LOCK "$$";

   if(! open(MAIL, ">> $MAIL")) {
      print STDERR "ERROR: Unable to Create Message\n";
      exit 1;
   }

   if( defined(${Dest}) ){
      printf MAIL "#\nSP %s \@ %s < %s\n", ${From}, ${Dest}, ${BBSCALL};
   }else{
      printf MAIL "#\nSP %s < %s\n", ${From}, ${BBSCALL};
   }

   if( ! defined($NP) ){
      print MAIL "REQFIL: $ReqName\n";
   }else{
      print MAIL "REQFIL: $ReqName ($P/$NP)\n";
   }

   # Start the Message Content.
   print MAIL "\n";

   print MAIL "$Version\n\n";

   print MAIL "File Requested: $Subject\n\n";
}

sub EndMsg{

   if( defined($_[0]) ){
     $P =  $_[0];
   }

   print MAIL "\n\n";

   if( defined($NAME) ){
      print MAIL "\n**** 73s ${NAME}";

      if( defined(${SYSCALL}) ){
         print MAIL " (${SYSCALL})";
      }
      print MAIL " Sysop ${BBSCALL}";
 
   }else{
      print MAIL "\nFrom ${BBSCALL}\n\n";
   }

   if( defined($QTH) ){
      print MAIL " $QTH";
   }

   print MAIL " ****\n\n";
   print MAIL "\/EX\n";
   close(MAIL);
 
   close(LOCK);
   unlink(${LOCK});
}
